@font-face {
  font-family:'Eaves Mark'; src:url('/fonts/EavesMark.ttf') format('truetype');
  font-weight:400; font-style:normal; font-display:swap;
}
:root {
  --bg:      #f5f4f0;
  --surface: #ffffff;
  --s1:      #f8f7f4;
  --s2:      #f0efeb;
  --s3:      #e8e6e1;
  --border:  #dddbd5;
  --text:    #1a1916;
  --text2:   #6b6860;
  --text3:   #a8a69f;
  --accent:  #2a6ef5;
  --accent2: #1b55cc;
  --accent-fg:#fff;   /* text color ON accent-filled elements; dark themes with pale accents override it */
  --abg:     #eef3fe;
  --ok:      #16a34a;
  --err:     #dc2626;
  --warn:    #d97706;
  --live:    #ef4444;
  --r:       10px;   /* less-round pass (was 14px) */
  --rsm:     7px;    /* (was 9px) */
  --sh:      0 2px 8px rgba(0,0,0,.07),0 1px 3px rgba(0,0,0,.05);
  --shsm:    0 1px 2px rgba(0,0,0,.06);
  --shlg:    0 12px 32px rgba(0,0,0,.09),0 4px 12px rgba(0,0,0,.05);
}

*,*::before,*::after { margin:0; padding:0; box-sizing:border-box; }


body {
  font-family:'DM Sans',sans-serif;
  background:var(--bg); color:var(--text);
  min-height:100vh; line-height:1.55;
  -webkit-font-smoothing:antialiased;
  /* Kills the grey/blue flash Android paints over any tapped element. It fires on plain
     chrome (rails, tabs, buttons) where nothing is meant to look pressed, and our own
     :active styles already convey the press. */
  -webkit-tap-highlight-color:transparent;
}

/* ============================================================================
   SELECTION POLICY
   App chrome is NOT selectable; content is. This is a whole-app default rather than the
   ~28 scattered `user-select:none` rules that used to carry it, which is why selection
   felt arbitrary: whichever element someone remembered to mark was immune and everything
   else was fair game. Dragging across a rail or a header would smear a blue selection over
   the UI, and on touch it fights long-press.

   The opt-ins below are load-bearing, DON'T trim them: an invite code, a message, or a
   backup code that can't be selected is worse than a selectable sidebar. Anything new that
   a user might reasonably want to copy should get the `.selectable` class rather than a
   fresh one-off rule.
   ============================================================================ */
body { user-select:none; -webkit-user-select:none; }

input, textarea, select, [contenteditable], [contenteditable] *,
.chat-msg-body, .chat-msg-body *, .msg-text, .msg-text *,
.code-display, .code-display *, .code-val,
pre, code, kbd, samp,
.selectable, .selectable * {
  user-select:text; -webkit-user-select:text;
}

/* ============================================================================
   FOCUS POLICY
   A mouse click used to leave the browser's focus ring stuck on whatever was clicked (the
   stray outline that lingers on buttons). :focus-visible is the browser's own "did this
   focus come from the keyboard" answer, so pointer clicks stay clean while keyboard
   navigation keeps a real, visible ring. Do NOT collapse this into `:focus { outline:none }`
   — that silently removes keyboard navigation for anyone not using a mouse.
   ============================================================================ */
:focus:not(:focus-visible) { outline:none; }
:focus-visible { outline:2px solid var(--accent); outline-offset:2px; }

/* Universal drag-smoothing state — added to a floating object ONLY while it is being
   dragged (see dragSmoother in utils.js). Promotes a GPU layer to isolate repaints from
   the rest of the page, kills any transition (so the move can't lag/smear behind the
   pointer), and drops the costly backdrop blur (restored the instant the drag ends).
   These per-frame repaints are what make a drag feel jittery. */
.ui-dragging { will-change:transform; transition:none !important;
  backdrop-filter:none !important; -webkit-backdrop-filter:none !important; }

/* ============================================================================
   ui-v2 MOTION LAYER (anim-fx.js). Four subtle groups, each gated by a body class
   (fx-entrances / fx-cards / fx-popovers / fx-buttons) so any can be toggled off.
   Animations are driven by CSS vars that reduced-motion sets to `none`, so the whole
   layer respects prefers-reduced-motion in one place. All scoped to body.ui-v2 →
   classic UI is untouched.
   ============================================================================ */
:root {
  --fx-rise: fx-rise .3s cubic-bezier(.22,.61,.36,1) both;
  --fx-fade: fx-fade .2s ease-out both;
  --fx-item: fx-item .22s cubic-bezier(.22,.61,.36,1) both;
  --fx-pop:  fx-pop .14s cubic-bezier(.2,.7,.3,1) both;
}
@media (prefers-reduced-motion: reduce) {
  :root { --fx-rise:none; --fx-fade:none; --fx-item:none; --fx-pop:none; }
}
@keyframes fx-rise { from { opacity:0; transform:translateY(13px); } to { opacity:1; transform:none; } }
@keyframes fx-fade { from { opacity:0; } to { opacity:1; } }
@keyframes fx-item { from { opacity:0; transform:translateY(7px); } to { opacity:1; transform:none; } }
@keyframes fx-pop  { from { opacity:0; transform:scale(.96); } to { opacity:1; transform:scale(1); } }

/* 1. GENTLE VIEW ENTRANCES — opacity fade-in on navigation (.fx-in set by fxEnter).
   For HOME we fade the CONTENT wrapper (.hv-wrap / .h-feed), NOT #home-v2 itself: its
   ::before paper texture uses mix-blend-mode:overlay, and animating #home-v2's opacity
   ISOLATES that blend group, flashing the background opaque/saturated. Fade is
   opacity-ONLY (no transform) so it also never disturbs #space-v2's live media or the
   fixed mobile tab bars, and it leaves the card rise (fx-cards) as the visible motion. */
/* home gets a clearer fade+RISE (animating the content wrapper, NOT #home-v2, keeps the
   mix-blend ::before un-isolated, so no bg flash). The others stay opacity-only (fixed
   children / live media). */
body.ui-v2.fx-entrances #home-v2.fx-in .hv-wrap,
body.ui-v2.fx-entrances #home-v2.fx-in .h-feed { animation: var(--fx-rise); }
body.ui-v2.fx-entrances #space-v2.fx-in,
body.ui-v2.fx-entrances #setup-screen.fx-in,
body.ui-v2.fx-entrances #settings-v2-screen.fx-in { animation: var(--fx-fade); }
/* The You / Friends tab hubs are OPAQUE fixed overlays stacked over the home screen, so
   fading the CONTAINER would let home show through the fade on a tab switch. Fade the
   CONTENT (direct children) instead - the opaque paper bg then covers home for the whole
   entrance (same content-not-container principle as home above). */
body.ui-v2.fx-entrances #you-v2.fx-in > *,
body.ui-v2.fx-entrances #friends-v2.fx-in > * { animation: var(--fx-fade); }

/* 2. CARD & LIST FADE-IN — items stagger in, but ONLY inside a freshly-entered (.fx-in)
   container, so the 1.5s members poll / 25s home poll don't re-animate. */
body.ui-v2.fx-cards #home-v2.fx-in .workrow .space,
body.ui-v2.fx-cards #home-v2.fx-in .h-space,
body.ui-v2.fx-cards #home-v2.fx-in .fr,
body.ui-v2.fx-cards #space-v2.fx-in .mrow {
  /* longhands (NOT the `animation` shorthand) so the base never resets animation-delay,
     letting the lower-specificity nth-child stagger below take effect */
  animation-name: fx-item; animation-duration: .22s;
  animation-timing-function: cubic-bezier(.22,.61,.36,1); animation-fill-mode: both;
}
@media (prefers-reduced-motion: reduce) {
  body.ui-v2.fx-cards #home-v2.fx-in .workrow .space,
  body.ui-v2.fx-cards #home-v2.fx-in .h-space,
  body.ui-v2.fx-cards #home-v2.fx-in .fr,
  body.ui-v2.fx-cards #space-v2.fx-in .mrow { animation-name: none; }
}
body.ui-v2.fx-cards .fx-in :is(.space,.h-space,.fr,.mrow):nth-child(2) { animation-delay:.035s; }
body.ui-v2.fx-cards .fx-in :is(.space,.h-space,.fr,.mrow):nth-child(3) { animation-delay:.07s; }
body.ui-v2.fx-cards .fx-in :is(.space,.h-space,.fr,.mrow):nth-child(4) { animation-delay:.105s; }
body.ui-v2.fx-cards .fx-in :is(.space,.h-space,.fr,.mrow):nth-child(5) { animation-delay:.14s; }
body.ui-v2.fx-cards .fx-in :is(.space,.h-space,.fr,.mrow):nth-child(6) { animation-delay:.175s; }
body.ui-v2.fx-cards .fx-in :is(.space,.h-space,.fr,.mrow):nth-child(n+7) { animation-delay:.21s; }

/* 3. POPOVER / MENU / MODAL EASE-IN — scale + fade from instant-appear. */
body.ui-v2.fx-popovers .spv2-more-menu,
body.ui-v2.fx-popovers .spv2-srvmenu,
body.ui-v2.fx-popovers .spv2-notifs,
body.ui-v2.fx-popovers .spv2-notifs-wrap,
body.ui-v2.fx-popovers .profile-card,
body.ui-v2.fx-popovers .ep-panel,
body.ui-v2.fx-popovers .gp-panel { animation: var(--fx-pop); }

/* 4. BUTTON MICRO-INTERACTIONS — a subtle press scale; bg/color/border keep their easing. */
body.ui-v2.fx-buttons :is(button,.tbtn,.tb-btn,.cdock-btn,.h-tab,.tray-act,.spv2-more-item,.set-item) {
  transition: transform .09s ease, background-color .15s ease, color .15s ease, border-color .15s ease;
}
body.ui-v2.fx-buttons :is(button,.tbtn,.tb-btn,.cdock-btn,.h-tab,.tray-act,.spv2-more-item,.set-item):active {
  transform: scale(.95);
}
@media (prefers-reduced-motion: reduce) {
  body.ui-v2.fx-buttons :is(button,.tbtn,.tb-btn,.cdock-btn,.h-tab,.tray-act,.spv2-more-item,.set-item):active { transform: none; }
}
/* Manual "Reduce motion" toggle (Settings → Appearance) — an explicit user override that mirrors
   the prefers-reduced-motion blocks above, so it kills the motion layer regardless of the OS pref.
   The --fx-* vars set on body cascade to the fx-* rules (body descendants), same as :root. */
body.reduce-motion { --fx-rise:none; --fx-fade:none; --fx-item:none; --fx-pop:none; }
body.reduce-motion.ui-v2.fx-cards #home-v2.fx-in .workrow .space,
body.reduce-motion.ui-v2.fx-cards #home-v2.fx-in .h-space,
body.reduce-motion.ui-v2.fx-cards #home-v2.fx-in .fr,
body.reduce-motion.ui-v2.fx-cards #space-v2.fx-in .mrow { animation-name: none; }
body.reduce-motion.ui-v2.fx-buttons :is(button,.tbtn,.tb-btn,.cdock-btn,.h-tab,.tray-act,.spv2-more-item,.set-item):active { transform: none; }

/* HEADER */
header {
  position:sticky; top:0; z-index:100;
  background:color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter:blur(18px);
  -webkit-backdrop-filter:blur(18px);
  border-bottom:1px solid var(--border);
  height:58px;
  display:flex; align-items:center; justify-content:center;
  padding:0 28px;
}
.logo {
  display:flex; align-items:center; gap:10px;
  font-weight:700; font-size:17px; letter-spacing:-.3px;
  text-decoration:none; color:var(--text);
  position:absolute; left:28px;
}
.logo-mark {
  width:30px; height:30px; background:var(--text);
  border-radius:8px;
  display:flex; align-items:center; justify-content:center; flex-shrink:0;
}
.logo-flow {
  font-family:'Caveat',cursive; font-size:24px; font-weight:700;
  margin-left:-2px; letter-spacing:0;
  position:relative; top:-3px;
}
.header-nav {
  display:flex; gap:8px;
}
.header-btn {
  border:none; cursor:pointer;
  padding:8px 16px; border-radius:8px;
  font-family:'DM Sans',sans-serif; font-size:13px; font-weight:600;
  color:var(--text2); background:none;
  transition:all .15s;
}
.header-btn:hover {
  color:var(--text); background:rgba(0,0,0,.05);
}
.settings-btn {
  position:absolute; right:28px; top:0; height:100%;
  border:none; cursor:pointer; background:none;
  padding:0 8px; color:var(--text2); transition:all .15s;
  display:flex; align-items:center; justify-content:center;
}
.settings-btn:hover { color:var(--text); }
.hamburger-btn {
  position:absolute; left:16px; top:0; height:100%;
  border:none; cursor:pointer; background:none;
  padding:0 8px; color:var(--text2); transition:all .15s;
  display:flex; align-items:center; justify-content:center;
}
.hamburger-btn:hover { color:var(--text); }

/* MOBILE SIDEBAR */
.mobile-sidebar {
  position:fixed; left:0; top:0; bottom:0; z-index:150;
  display:flex; flex-direction:column; width:100%;
  pointer-events:none;
}
.mobile-sidebar.open { pointer-events:auto; }
.mobile-sidebar-overlay {
  position:absolute; inset:0; background:rgba(0,0,0,0);
  transition:background .25s ease; pointer-events:none;
}
.mobile-sidebar.open .mobile-sidebar-overlay {
  background:rgba(0,0,0,.4); pointer-events:auto;
}
.mobile-sidebar-content {
  position:absolute; left:0; top:0; bottom:0; width:280px;
  background:var(--surface); border-right:1px solid var(--border);
  box-shadow:var(--sh); transform:translateX(-100%);
  transition:transform .25s cubic-bezier(0.16, 1, 0.3, 1);
  display:flex; flex-direction:column; padding:20px;
  z-index:10;
}
.mobile-sidebar.open .mobile-sidebar-content {
  transform:translateX(0);
}
.sidebar-logo {
  display:flex; align-items:center; gap:12px;
  text-decoration:none; color:var(--text);
  margin-bottom:32px; margin-top:4px;
}
.sidebar-logo .logo-mark {
  flex-shrink:0;
}
.sidebar-logo-text {
  display:flex; align-items:baseline; gap:4px;
  font-weight:700; font-size:15px; letter-spacing:-.3px;
}
.sidebar-settings-btn {
  display:flex; align-items:center; gap:10px;
  border:none; cursor:pointer; background:none;
  padding:12px 14px; border-radius:8px;
  font-family:'DM Sans',sans-serif; font-size:14px; font-weight:500;
  color:var(--text2); transition:all .15s;
  width:100%;
  justify-content:flex-start;
}
.sidebar-settings-btn:hover {
  color:var(--text); background:var(--s2);
}

/* SETTINGS SCREEN */
#settings-screen {
  position:fixed; inset:0; z-index:200;
  background:var(--bg); overflow-y:auto;
  display:flex; flex-direction:column;
}
.settings-page-topbar {
  flex-shrink:0; height:56px;
  display:flex; align-items:center; padding:0 16px;
  background:var(--bg); border-bottom:1px solid var(--border);
  position:relative; top:0; z-index:10;
}
.settings-page-title {
  font-size:16px; font-weight:700; margin:0;
  position:absolute; left:50%; transform:translateX(-50%);
}
.settings-page-body {
  padding:32px 24px 80px; max-width:560px; margin:0 auto; width:100%;
}
.settings-page-card {
  background:var(--surface); border:1px solid var(--border);
  border-radius:var(--r); box-shadow:var(--sh); overflow:hidden;
  padding:24px;
}
.settings-row {
  margin-bottom:24px;
}
.settings-label {
  font-size:11px; font-weight:600; text-transform:uppercase; letter-spacing:.7px;
  color:var(--text3); margin-bottom:12px;
}
.settings-options {
  display:flex; gap:12px;
}
.mute-key-display {
  display:inline-flex; align-items:center; justify-content:center;
  min-width:80px; padding:5px 14px;
  background:var(--s2); border:1px solid var(--border); border-radius:7px;
  font-family:'DM Mono',monospace; font-size:13px; color:var(--text);
  cursor:pointer; user-select:none; transition:background .12s;
}
.mute-key-display:hover { background:var(--s3); }
.mute-key-display.listening { border-color:var(--accent); background:var(--abg); color:var(--accent); }
.theme-option {
  flex:1; display:flex; align-items:center; gap:8px;
  padding:10px 14px; border:1px solid var(--border);
  border-radius:8px; cursor:pointer; font-size:13px;
  transition:all .15s;
}
.theme-option:hover {
  background:var(--s2); border-color:var(--accent);
}
.theme-option input[type="radio"] {
  cursor:pointer;
}
.theme-option input[type="radio"]:checked + span {
  color:var(--accent); font-weight:600;
}

.status-pill {
  position:fixed; bottom:24px; right:24px; z-index:50;
  /* Hidden except on quickshare surfaces — body.qs-active is mirrored from
     setup/sharing/viewer screen visibility by an observer in boot.js. The pill
     only ever reflects quickshare streaming state (screenshare.js setStatus). */
  display:none; align-items:center; gap:7px;
  font-size:13px; font-weight:500; color:var(--text2);
  background:var(--surface); border:1px solid var(--border);
  border-radius:9px; padding:5px 14px; box-shadow:var(--shsm);
}
body.qs-active .status-pill { display:flex; }
.sdot {
  width:7px; height:7px; border-radius:50%;
  background:var(--text3); transition:background .3s; flex-shrink:0;
}
.sdot.live { background:var(--live); }
.sdot.ok   { background:var(--ok); }
.sdot.wait { background:var(--warn); }
.sdot.bad  { background:var(--err); }
@keyframes blink { 0%,100%{opacity:1} 50%{opacity:.3} }

/* MAIN */
/* Vertical padding lives on the screens INSIDE main (auth/setup/files/sharing),
   not on main itself — when all of them are hidden an empty main otherwise
   still occupies 124px and pushes the home/moderation screens (which sit after
   it in the DOM) down a dead band. */
main { max-width:980px; margin:0 auto; padding:0 24px; }

/* TABS */
.tab-row {
  display:flex; gap:4px;
  background:var(--surface); border:1px solid var(--border);
  border-radius:9px; padding:4px;
  max-width:520px; margin:0 auto 32px;
  box-shadow:var(--shsm);
}
.tab-btn {
  flex:1; border:none; cursor:pointer;
  padding:10px 16px; border-radius:9px;
  font-family:'DM Sans',sans-serif; font-size:14px; font-weight:600;
  color:var(--text2); background:none;
  display:flex; align-items:center; justify-content:center; gap:7px;
  transition:all .18s;
}
.tab-btn.active { background:var(--text); color:var(--bg,#fff); box-shadow:0 2px 8px rgba(0,0,0,.18); }
.tab-pane { display:none; }
.tab-pane.active { display:block; }

/* HERO */
.hero { text-align:center; max-width:520px; margin:0 auto 32px; }
.hero-badge {
  display:inline-flex; align-items:center; gap:6px;
  font-size:11.5px; font-weight:600; letter-spacing:.6px; text-transform:uppercase;
  color:var(--accent); background:var(--abg); border:1px solid rgba(42,110,245,.18);
  border-radius:9px; padding:4px 12px; margin-bottom:18px;
}
.hero h1 { font-size:40px; font-weight:700; letter-spacing:-1.5px; line-height:1.1; margin-bottom:12px; }
.hero p  { font-size:15.5px; color:var(--text2); line-height:1.65; }

/* SETTINGS CARD */
.settings-card {
  max-width:520px; margin:0 auto 18px;
  background:var(--surface); border:1px solid var(--border);
  border-radius:var(--r); box-shadow:var(--sh); overflow:hidden;
}
.setting-row {
  display:grid; grid-template-columns:1fr 1fr;
  border-bottom:1px solid var(--border);
}
.setting-row:last-child { border-bottom:none; }
.setting-cell { padding:18px 20px; border-right:1px solid var(--border); }
.setting-cell:last-child { border-right:none; }
.setting-cell.full { grid-column:1/-1; border-right:none; }
.slbl { font-size:11px; font-weight:600; text-transform:uppercase; letter-spacing:.7px; color:var(--text3); margin-bottom:10px; }

/* SELECT */
.sel-wrap { position:relative; }
.sel-wrap select {
  width:100%; background:var(--s2); border:1px solid var(--border);
  border-radius:var(--rsm); padding:9px 32px 9px 12px;
  font-family:'DM Sans',sans-serif; font-size:14px; font-weight:500;
  color:var(--text); cursor:pointer; outline:none; appearance:none;
}
.sel-wrap select:focus { border-color:var(--accent); box-shadow:0 0 0 3px rgba(42,110,245,.12); }
.sel-wrap::after {
  content:''; position:absolute; right:11px; top:50%;
  transform:translateY(-50%);
  border:5px solid transparent; border-top-color:var(--text2); border-bottom:none;
  pointer-events:none;
}

/* SEG CONTROL */
.seg { display:flex; background:var(--s2); border:1px solid var(--border); border-radius:var(--rsm); overflow:hidden; }
.seg-btn {
  flex:1; border:none; cursor:pointer; padding:9px 8px;
  font-family:'DM Sans',sans-serif; font-size:14px; font-weight:500;
  color:var(--text2); background:none; transition:all .15s;
}
.seg-btn.on { background:var(--accent); color:var(--accent-fg,#fff); }

/* CHECKBOX */
.chk-row { display:flex; align-items:flex-start; gap:9px; margin-bottom:10px; cursor:pointer; }
.chk-row:last-child { margin-bottom:0; }
.chk-row input[type=checkbox] { width:17px; height:17px; margin-top:2px; accent-color:var(--accent); cursor:pointer; flex-shrink:0; }
.chk-row label { font-size:14px; font-weight:500; cursor:pointer; }
.chk-row .sub  { font-size:12px; color:var(--text3); margin-top:1px; }

/* TIP */
.tip {
  display:flex; gap:9px; align-items:flex-start;
  background:var(--abg); border:1px solid rgba(42,110,245,.18);
  border-radius:var(--rsm); padding:11px 15px;
  font-size:13px; color:#2952b3; line-height:1.5;
  max-width:520px; margin:0 auto 22px;
}
.tip svg { flex-shrink:0; margin-top:1px; }
.tip.warn-tip { background:#fffbeb; border-color:rgba(217,119,6,.25); color:#92400e; }

/* BUTTONS */
.btn {
  display:inline-flex; align-items:center; justify-content:center; gap:7px;
  padding:10px 20px; border-radius:var(--rsm);
  font-family:'DM Sans',sans-serif; font-size:14px; font-weight:600;
  cursor:pointer; border:none; transition:all .15s;
  white-space:nowrap; text-decoration:none;
}
.btn-primary { background:var(--accent); color:var(--accent-fg,#fff); box-shadow:0 2px 10px rgba(42,110,245,.35); }
.btn-primary:hover  { background:var(--accent2); transform:translateY(-1px); box-shadow:0 4px 16px rgba(42,110,245,.4); }
.btn-primary:active { transform:translateY(0); }
.btn-primary:disabled { background:#a5b4fc; box-shadow:none; cursor:not-allowed; transform:none; }
.btn-xl { width:100%; max-width:520px; padding:15px 28px; font-size:16px; border-radius:var(--r); display:flex; margin:0 auto; }
.btn-outline { background:var(--surface); border:1px solid var(--border); color:var(--text); box-shadow:var(--shsm); }
.btn-secondary { background:var(--s2); color:var(--text); border:1px solid var(--border); }
.btn-outline:hover { background:var(--s2); }
.btn-danger { background:#fef2f2; color:var(--err); border:1px solid #fecaca; }
.btn-danger:hover { background:#fee2e2; }
.btn-ghost { background:none; color:var(--text2); border:none; }
.btn-ghost:hover { background:var(--s2); color:var(--text); }
.btn-icon { padding:8px 10px; }
.btn-outline.mic-off { background:#fef2f2; border-color:#fecaca; color:var(--err); }
.btn-outline.mic-off:hover { background:#fee2e2; }

/* JOIN PANE */
.join-card {
  max-width:520px; margin:0 auto;
  background:var(--surface); border:1px solid var(--border);
  border-radius:var(--r); box-shadow:var(--sh); padding:28px;
}
.join-hero { text-align:center; margin-bottom:28px; }
.join-icon {
  width:60px; height:60px; background:var(--s2);
  border:1px solid var(--border); border-radius:8px;
  display:flex; align-items:center; justify-content:center; margin:0 auto 16px;
}
.join-hero h2 { font-size:22px; font-weight:700; letter-spacing:-.4px; margin-bottom:8px; }
.join-hero p  { font-size:14px; color:var(--text2); }
.join-label { font-size:12px; font-weight:600; letter-spacing:.5px; text-transform:uppercase; color:var(--text3); margin-bottom:8px; }
.join-input-row { display:flex; gap:8px; margin-bottom:14px; }
.join-input {
  flex:1; min-width:0;
  background:var(--s2); border:1px solid var(--border);
  border-radius:var(--rsm); padding:11px 14px;
  font-family:'DM Mono',monospace; font-size:13px;
  color:var(--text); outline:none;
  transition:border-color .15s,box-shadow .15s;
}
.join-input:focus { border-color:var(--accent); box-shadow:0 0 0 3px rgba(42,110,245,.12); }
.join-input::placeholder { color:var(--text3); font-family:'DM Sans',sans-serif; font-size:13px; }
.join-input.shake { animation:shk .4s ease; }
.join-divider { display:flex; align-items:center; gap:12px; color:var(--text3); font-size:12px; margin:16px 0; }
.join-divider::before,.join-divider::after { content:''; flex:1; height:1px; background:var(--border); }

/* CARD */
.card { background:var(--surface); border:1px solid var(--border); border-radius:var(--r); box-shadow:var(--sh); }
.card-head { display:flex; align-items:center; justify-content:space-between; padding:16px 22px; border-bottom:1px solid var(--border); }
.card-title { font-size:14px; font-weight:600; letter-spacing:-.2px; display:flex; align-items:center; gap:8px; color:var(--text); }
.card-title svg { color:var(--accent); }
.card-body { padding:20px 22px; }

/* SHARING SCREEN */
#sharing-screen { display:none; padding-top:44px; padding-bottom:80px; }
/* Hidden until boot routing picks a screen — without this the quickshare page
   paints during the /api/me round trip on every load. switchToSetupScreen()
   shows it explicitly on the /quickshare and ?host= paths. */
#setup-screen { display:none; padding-top:44px; padding-bottom:80px; }
.share-layout { display:grid; grid-template-columns:1fr 318px; gap:20px; align-items:start; }

/* PREVIEW */
.preview-wrap {
  background:#0d0d0d; border-radius:var(--r); overflow:hidden;
  aspect-ratio:16/9; position:relative;
  border:1px solid #222; box-shadow:var(--shlg);
}
#preview-video { width:100%; height:100%; object-fit:contain; display:block; }
.preview-badges { position:absolute; bottom:12px; left:12px; display:flex; gap:7px; }
.badge {
  display:inline-flex; align-items:center; gap:5px;
  background:rgba(0,0,0,.58); backdrop-filter:blur(10px);
  color:#fff; font-size:12px; font-weight:600;
  padding:4px 10px; border-radius:6px; border:1px solid rgba(255,255,255,.1);
}
.live-pip { width:7px; height:7px; border-radius:50%; background:var(--live); }
.preview-actions { display:flex; gap:10px; margin-top:14px; flex-wrap:wrap; }

/* SIDEBAR */
.sidebar { display:flex; flex-direction:column; gap:16px; }
.link-wrap { display:flex; gap:8px; margin-top:12px; }
.link-input {
  flex:1; min-width:0; background:var(--s2); border:1px solid var(--border);
  border-radius:var(--rsm); padding:9px 12px;
  font-family:'DM Mono',monospace; font-size:11.5px; color:var(--text); outline:none;
}

/* CODE DISPLAY */
.code-display { background:var(--s2); border:1px solid var(--border); border-radius:var(--rsm); padding:14px; margin-top:14px; text-align:center; }
.code-display .code-lbl { font-size:11px; font-weight:600; text-transform:uppercase; letter-spacing:.6px; color:var(--text3); margin-bottom:6px; }
.code-display .code-val { font-family:'DM Mono',monospace; font-size:15px; font-weight:500; color:var(--text); letter-spacing:1px; word-break:break-all; }

/* QR */
#qr-container { display:none; justify-content:center; margin-top:16px; padding-top:16px; border-top:1px solid var(--border); }
#qr-container canvas { border-radius:8px; display:block; }

/* STATS */
.stats-grid { display:grid; grid-template-columns:1fr 1fr; gap:10px; }
.stat-box { background:var(--s2); border:1px solid var(--border); border-radius:var(--rsm); padding:12px 14px; }
.stat-lbl { font-size:11px; font-weight:600; text-transform:uppercase; letter-spacing:.6px; color:var(--text3); margin-bottom:4px; }
.stat-val { font-size:18px; font-weight:700; letter-spacing:-.5px; color:var(--text); }
.stat-val.sm { font-size:13px; font-weight:600; }
.viewers-chip {
  display:inline-flex; align-items:center; gap:5px;
  font-size:12px; font-weight:600; color:var(--accent);
  background:var(--abg); border:1px solid rgba(42,110,245,.2);
  border-radius:9px; padding:3px 10px;
}

/* VOICE CARD — host sidebar */
.voice-participant-row {
  display:flex; align-items:center; gap:8px;
  padding:10px 0; border-bottom:1px solid var(--border);
}
.voice-participant-row:last-child { border-bottom:none; }
.voice-p-name {
  flex:1; font-size:13px; font-weight:500; color:var(--text);
  min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.voice-p-btn {
  background:none; border:1px solid var(--border); border-radius:6px;
  color:var(--text2); padding:4px 7px; cursor:pointer; flex-shrink:0;
  transition:all .15s; display:inline-flex; align-items:center;
}
.voice-p-btn:hover { background:var(--s2); }
.voice-p-btn.muted { color:var(--err); border-color:#fecaca; background:#fef2f2; }
input[type=range].h-vol {
  -webkit-appearance:none; width:64px; height:3px; border-radius:2px;
  background:var(--s3); outline:none; cursor:pointer; flex-shrink:0;
}
input[type=range].h-vol::-webkit-slider-thumb {
  -webkit-appearance:none; width:12px; height:12px; border-radius:50%;
  background:var(--text); cursor:pointer;
}
input[type=range].h-vol::-moz-range-thumb { width:12px; height:12px; border-radius:50%; background:var(--text); cursor:pointer; border:none; }
.voice-empty { font-size:13px; color:var(--text3); text-align:center; padding:12px 0; }
.voice-own-row {
  display:flex; align-items:center; justify-content:space-between;
  padding-top:12px; margin-top:8px; border-top:1px solid var(--border);
}
.voice-own-lbl { font-size:12px; font-weight:600; color:var(--text3); text-transform:uppercase; letter-spacing:.5px; }

/* VIEWER SCREEN */
#viewer-screen { display:none; position:fixed; inset:0; background:#050505; z-index:50; }
#viewer-video  { width:100%; height:100%; object-fit:contain; display:block; }

.v-overlay {
  position:absolute; inset:0; display:flex; flex-direction:column;
  align-items:center; justify-content:center;
  background:rgba(5,5,5,.92); color:#fff; z-index:10;
  transition:opacity .4s; padding:24px; text-align:center;
}
.v-overlay.gone { opacity:0; pointer-events:none; }
.spinner {
  width:44px; height:44px;
  border:3px solid rgba(255,255,255,.15); border-top-color:rgba(255,255,255,.8);
  border-radius:50%; animation:spin .7s linear infinite; margin-bottom:22px;
}
@keyframes spin { to { transform:rotate(360deg); } }
.v-overlay h2 { font-size:22px; font-weight:700; margin-bottom:8px; cursor:pointer; user-select:none; }
.v-overlay p  { font-size:14px; color:rgba(255,255,255,.5); max-width:320px; cursor:pointer; user-select:none; }
.v-back {
  margin-top:24px; display:inline-flex; align-items:center; gap:6px;
  background:rgba(255,255,255,.1); border:1px solid rgba(255,255,255,.2);
  color:#fff; border-radius:8px; padding:10px 20px;
  font-family:'DM Sans',sans-serif; font-size:14px; font-weight:500;
  cursor:pointer; transition:background .15s; text-decoration:none;
}
.v-back:hover { background:rgba(255,255,255,.18); }

.v-topbar {
  position:absolute; top:0; left:0; right:0; display:flex; align-items:center; gap:10px;
  padding:16px 24px; padding-top:calc(16px + env(safe-area-inset-top,0px)); background:linear-gradient(rgba(0,0,0,.55),transparent);
  opacity:0; transition:opacity .3s; z-index:20;
}
#viewer-screen.ui-visible .v-topbar { opacity:1; }
.v-logo { display:flex; align-items:center; gap:8px; font-size:15px; font-weight:700; color:#fff; }

.v-controls {
  position:absolute; bottom:0; left:0; right:0;
  padding:20px 24px 24px; background:linear-gradient(transparent,rgba(0,0,0,.72));
  display:flex; align-items:center; gap:10px; flex-wrap:wrap;
  opacity:0; transition:opacity .3s; z-index:20;
}
#viewer-screen.ui-visible .v-controls { opacity:1; }
#viewer-screen.ui-hidden { cursor:none; }

.v-btn {
  display:inline-flex; align-items:center; gap:6px;
  background:rgba(255,255,255,.12); backdrop-filter:blur(12px); -webkit-backdrop-filter:blur(12px);
  border:1px solid rgba(255,255,255,.18); color:#fff; border-radius:8px; padding:8px 14px;
  font-family:'DM Sans',sans-serif; font-size:13px; font-weight:500; cursor:pointer;
  transition:background .15s;
}
.v-btn:hover { background:rgba(255,255,255,.22); }
.v-btn.icon  { padding:8px 10px; }
.v-btn.mic-off { background:rgba(239,68,68,.22); border-color:rgba(239,68,68,.45); }
.v-btn.mic-off:hover { background:rgba(239,68,68,.35); }
.v-sep   { width:1px; height:22px; background:rgba(255,255,255,.2); }
.v-space { flex:1; }
.v-info  { font-size:12px; font-family:'DM Mono',monospace; color:rgba(255,255,255,.4); }

input[type=range].vol { -webkit-appearance:none; width:80px; height:3px; border-radius:2px; background:rgba(255,255,255,.3); outline:none; cursor:pointer; }
input[type=range].vol::-webkit-slider-thumb { -webkit-appearance:none; width:14px; height:14px; border-radius:50%; background:#fff; cursor:pointer; }
input[type=range].vol::-moz-range-thumb { width:14px; height:14px; border-radius:50%; background:#fff; cursor:pointer; border:none; }
.vol-pct { font-size:11px; font-family:'DM Mono',monospace; min-width:32px; text-align:right; color:var(--text2); }
input[type=range].v-vol + .vol-pct, input[type=range].vol + .vol-pct { color:rgba(255,255,255,.55); }

/* VOICE PANEL — viewer */
.v-voice-panel {
  position:absolute; left:0; top:0; bottom:0; width:268px;
  background:rgba(5,5,5,.88); backdrop-filter:blur(16px); -webkit-backdrop-filter:blur(16px);
  border-right:1px solid rgba(255,255,255,.1);
  display:flex; flex-direction:column;
  transform:translateX(-100%); transition:transform .25s ease;
  z-index:25;
}
.v-voice-panel.open { transform:translateX(0); }
.v-voice-head {
  display:flex; align-items:center; justify-content:space-between;
  padding:14px 16px; border-bottom:1px solid rgba(255,255,255,.1);
  font-size:14px; font-weight:600; color:#fff; flex-shrink:0;
}
.v-voice-close {
  background:none; border:none; cursor:pointer;
  color:rgba(255,255,255,.45); font-size:20px; line-height:1; padding:2px 4px;
}
.v-voice-close:hover { color:#fff; }
.v-voice-list {
  flex:1; overflow-y:auto; padding:10px 12px;
  display:flex; flex-direction:column; gap:6px;
}
.v-voice-list::-webkit-scrollbar { width:3px; }
.v-voice-list::-webkit-scrollbar-thumb { background:rgba(255,255,255,.18); border-radius:2px; }
.v-voice-empty { font-size:13px; color:rgba(255,255,255,.28); text-align:center; padding:24px 0; }
.v-participant {
  display:flex; align-items:center; gap:8px;
  padding:8px 10px; border-radius:8px;
  background:rgba(255,255,255,.07); border:1px solid rgba(255,255,255,.1);
}
.v-p-name {
  flex:1; font-size:13px; color:#fff; font-weight:500;
  min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.v-p-btn {
  background:none; border:1px solid rgba(255,255,255,.2); border-radius:6px;
  color:rgba(255,255,255,.65); padding:4px 7px; cursor:pointer; flex-shrink:0;
  transition:all .15s; display:inline-flex; align-items:center;
}
.v-p-btn:hover { background:rgba(255,255,255,.1); color:#fff; }
.v-p-btn.muted { color:rgba(239,68,68,.9); border-color:rgba(239,68,68,.5); background:rgba(239,68,68,.12); }
input[type=range].v-vol {
  -webkit-appearance:none; width:54px; height:3px; border-radius:2px;
  background:rgba(255,255,255,.3); outline:none; cursor:pointer; flex-shrink:0;
}
input[type=range].v-vol::-webkit-slider-thumb {
  -webkit-appearance:none; width:12px; height:12px; border-radius:50%; background:#fff; cursor:pointer;
}
input[type=range].v-vol::-moz-range-thumb { width:12px; height:12px; border-radius:50%; background:#fff; cursor:pointer; border:none; }
.v-voice-footer {
  padding:12px; border-top:1px solid rgba(255,255,255,.1); flex-shrink:0;
}

/* TOAST */
#toast {
  position:fixed; bottom:28px; left:50%;
  transform:translateX(-50%) translateY(80px);
  background:var(--text); color:var(--bg,#fff);
  padding:11px 22px; border-radius:10px;
  font-size:14px; font-weight:500;
  z-index:9999; transition:transform .3s cubic-bezier(.34,1.56,.64,1), opacity .25s ease;
  white-space:nowrap;
  box-shadow:0 8px 24px rgba(0,0,0,.25);
  cursor:pointer; user-select:none;
  /* Hide via opacity too, not just the 80px slide: `bottom` is raised while the
     chat input is visible (rule below), and a fixed translateY can't push the pill
     off-screen from a raised anchor, so the slide alone would leave it stuck visible. */
  opacity:0; pointer-events:none;
}
#toast.up { transform:translateX(-50%) translateY(0); opacity:1; pointer-events:auto; }
/* While the chat compose box is visible, joining/leaving a call (or any other
   in-chat action) commonly fires a toast (e.g. "Joining without mic") right at
   the moment the input area is on screen. At the default bottom:28px it lands
   directly on top of the textarea for its ~3s duration — the box itself never
   resizes, but a toast pill covering its upper half reads exactly like a
   "squished" input. Lift it above the compose box using the same live-measured
   height var the input's own scroll padding uses. */
body.chat-input-visible #toast { bottom: calc(var(--chat-bottom-h, 60px) + 20px); }

@keyframes shk { 0%,100%{transform:translateX(0)} 20%,60%{transform:translateX(-5px)} 40%,80%{transform:translateX(5px)} }

/* CHAT — broadcaster sidebar */
.chat-msgs {
  height:220px; overflow-y:auto; padding:12px 16px;
  display:flex; flex-direction:column; gap:8px;
}
.chat-msgs::-webkit-scrollbar { width:4px; }
.chat-msgs::-webkit-scrollbar-thumb { background:var(--border); border-radius:2px; }
.chat-msg { display:flex; flex-direction:column; gap:2px; max-width:86%; }
.chat-msg.self { align-self:flex-end; align-items:flex-end; }
.chat-msg .who { font-size:11px; font-weight:600; color:var(--text3); }
.chat-msg.self .who { color:var(--accent); }
.chat-msg .txt {
  background:var(--s2); border:1px solid var(--border);
  border-radius:10px; padding:6px 10px;
  font-size:13px; line-height:1.4; word-break:break-word;
}
.chat-msg.self .txt { background:var(--abg); border-color:rgba(42,110,245,.22); }
.chat-empty { font-size:13px; color:var(--text3); text-align:center; padding:24px 0; }
.chat-input-row {
  display:flex; gap:8px; padding:10px 12px;
  border-top:1px solid var(--border);
}
.chat-input-row .join-input { font-family:'DM Sans',sans-serif; font-size:13px; }

/* CHAT — viewer slide-in panel */
.v-chat-panel {
  position:absolute; right:0; top:0; bottom:0; width:280px;
  background:rgba(5,5,5,.85); backdrop-filter:blur(16px); -webkit-backdrop-filter:blur(16px);
  border-left:1px solid rgba(255,255,255,.1);
  display:flex; flex-direction:column;
  transform:translateX(100%); transition:transform .25s ease;
  z-index:25;
}
.v-chat-panel.open { transform:translateX(0); }
.v-chat-head {
  display:flex; align-items:center; justify-content:space-between;
  padding:14px 16px; border-bottom:1px solid rgba(255,255,255,.1);
  font-size:14px; font-weight:600; color:#fff; flex-shrink:0;
}
.v-chat-close {
  background:none; border:none; cursor:pointer;
  color:rgba(255,255,255,.45); font-size:20px; line-height:1; padding:2px 4px;
}
.v-chat-close:hover { color:#fff; }
.v-chat-msgs {
  flex:1; overflow-y:auto; padding:12px;
  display:flex; flex-direction:column; gap:8px;
}
.v-chat-msgs::-webkit-scrollbar { width:3px; }
.v-chat-msgs::-webkit-scrollbar-thumb { background:rgba(255,255,255,.18); border-radius:2px; }
.v-chat-msg { display:flex; flex-direction:column; gap:2px; max-width:90%; }
.v-chat-msg.self { align-self:flex-end; align-items:flex-end; }
.v-chat-msg .who { font-size:11px; font-weight:600; color:rgba(255,255,255,.38); }
.v-chat-msg.self .who { color:rgba(110,170,255,.9); }
.v-chat-msg .txt {
  background:rgba(255,255,255,.1); border:1px solid rgba(255,255,255,.12);
  border-radius:10px; padding:6px 10px;
  font-size:13px; color:#fff; line-height:1.4; word-break:break-word;
}
.v-chat-msg.self .txt { background:rgba(42,110,245,.38); border-color:rgba(42,110,245,.45); }
.v-chat-empty { font-size:13px; color:rgba(255,255,255,.28); text-align:center; padding:24px 0; }
.v-chat-input-row {
  display:flex; gap:8px; padding:10px 12px; flex-shrink:0;
  border-top:1px solid rgba(255,255,255,.1);
}
.v-chat-input {
  flex:1; min-width:0; background:rgba(255,255,255,.1); border:1px solid rgba(255,255,255,.18);
  border-radius:8px; padding:8px 12px; color:#fff;
  font-size:13px; font-family:'DM Sans',sans-serif; outline:none;
}
.v-chat-input:focus { border-color:rgba(42,110,245,.65); }
.v-chat-input::placeholder { color:rgba(255,255,255,.3); }
.v-chat-send {
  background:rgba(42,110,245,.75); border:none; border-radius:8px;
  color:#fff; font-size:13px; padding:8px 12px; cursor:pointer;
  font-family:'DM Sans',sans-serif; font-weight:500; white-space:nowrap;
}
.v-chat-send:hover { background:rgba(42,110,245,.95); }
.unread-badge {
  display:inline-flex; align-items:center; justify-content:center;
  min-width:18px; height:18px; border-radius:9px;
  background:var(--live); font-size:11px; font-weight:700; color:#fff; padding:0 4px;
}

/* SETUP LOGIN BUTTON */
.setup-login-btn {
  position:fixed; bottom:24px; left:24px;
  display:flex; align-items:center; gap:6px;
  border:1px solid var(--border); background:var(--surface);
  padding:8px 12px; border-radius:8px;
  font-family:'DM Sans',sans-serif; font-size:12px; font-weight:500;
  color:var(--text2); cursor:pointer;
  transition:all .15s; box-shadow:var(--shsm);
  z-index:50;
}
.setup-login-btn:hover {
  color:var(--text); background:var(--s2);
  border-color:var(--accent); box-shadow:0 2px 8px rgba(42,110,245,.12);
}

/* AUTH SCREEN */
.invite-banner { display:flex; align-items:center; gap:13px; width:min(560px, calc(100% - 32px));
  margin:26px auto -14px; padding:14px 18px; background:var(--surface);
  border:1px solid var(--border); border-radius:12px; box-shadow:var(--shlg); position:relative; z-index:1; }
.ib-icon { width:44px; height:44px; border-radius:10px; background-color:var(--s3); display:grid; place-items:center;
  font-weight:800; font-size:19px; color:var(--text); background-size:cover; background-position:center; flex-shrink:0; }
.ib-title { font-size:15px; color:var(--text2); }
.ib-title b { color:var(--text); }
.ib-sub { font-size:12.5px; color:var(--text3); margin-top:3px; }
#auth-screen { display:none; padding-top:44px; padding-bottom:80px;
  /* soft warm depth so the form isn't a lone card in a flat void */
  background:radial-gradient(1100px 560px at 28% 24%, rgba(221,148,48,.12), transparent 62%); }
.auth-container {
  display:flex; align-items:center; justify-content:center; gap:56px;
  min-height:calc(100vh - 58px);
  padding:32px 24px;
}
/* Desktop-only welcome panel beside the form (real product voice, hand-made feel).
   Hidden on narrow screens, where the card stands alone exactly as before. */
.auth-welcome { display:none; max-width:380px; }
@media (min-width:920px){ .auth-welcome { display:block; } .auth-header { display:none; } }
/* Mobile: the pitch list rides BELOW the card (same DOM as the desktop panel,
   just reordered) - wordmark + headline stay hidden since the card header
   already carries them on small screens */
@media (max-width:919.9px){
  .auth-container { flex-direction:column; gap:0; }
  .auth-welcome { display:block; order:2; margin:26px auto 0; padding:0 6px; }
  .auth-welcome-mark, .auth-welcome-h { display:none; }
}
.auth-welcome-mark { font-weight:800; font-size:20px; letter-spacing:-.4px; color:var(--text); margin-bottom:28px; }
.auth-welcome-h { font-family:'Eaves Mark',cursive; font-size:32px; line-height:1.2; font-weight:400; letter-spacing:0; color:var(--text); margin:0 0 16px; }
.awl-items { list-style:none; margin:0 0 18px; padding:0; display:flex; flex-direction:column; gap:12px; }
.awl-items li { display:flex; gap:11px; align-items:flex-start; font-size:15px; line-height:1.45; color:var(--text2); font-weight:500; max-width:38ch; }
.awl-items li svg { width:17px; height:17px; flex-shrink:0; margin-top:2px; color:var(--accent); }
.awl-click { cursor:pointer; }
.awl-click:hover span { text-decoration:underline; text-underline-offset:3px; }
.awl-sweep { font-size:13px; line-height:1.55; color:var(--text3); margin:0; max-width:33ch; }
.auth-card {
  background:var(--surface); border:1px solid var(--border);
  border-radius:8px; width:100%; max-width:420px;
  padding:40px 32px; box-shadow:var(--shlg);
}
.auth-header {
  text-align:center; margin-bottom:36px;
}
.auth-header h1 {
  font-size:19px; font-weight:800; margin-bottom:20px;
  letter-spacing:-.3px; color:var(--text2);
}
.auth-header p {
  font-family:'Eaves Mark',cursive; font-size:19px; color:var(--text);
}
.auth-tabs {
  display:flex; gap:8px; margin-bottom:28px;
  background:var(--s2); border-radius:10px; padding:4px;
}
.auth-tab {
  flex:1; border:none; background:none; cursor:pointer;
  padding:10px 16px; border-radius:8px;
  font-weight:600; font-size:14px; color:var(--text2);
  transition:all .18s;
}
.auth-tab.active {
  background:var(--surface); color:var(--text);
  border:1px solid var(--border); box-shadow:0 1px 3px rgba(0,0,0,.05);
}
.auth-pane { display:none; }
.auth-pane.active { display:block; }
.auth-form {
  display:flex; flex-direction:column; gap:16px;
}
.form-group {
  display:flex; flex-direction:column; gap:6px;
}
.form-group label {
  font-size:13px; font-weight:600; color:var(--text);
}
.form-group input, #temp-username {
  padding:10px 14px; border:1px solid var(--border);
  border-radius:9px; font-family:'DM Sans',sans-serif;
  font-size:14px; transition:border .18s;
}
.form-group input:focus, #temp-username:focus {
  outline:none; border-color:var(--accent);
  box-shadow:0 0 0 3px rgba(42,110,245,.1);
}
.auth-link {
  text-align:center; font-size:12px; color:var(--text2);
  margin-top:4px;
}
.auth-link a {
  color:var(--accent); text-decoration:none;
}
.auth-link a:hover { text-decoration:underline; }

/* Password-strength nudge under the register password field. */
.auth-pw-hint {
  font-size:12px; line-height:1.3; margin-top:6px; min-height:15px;
  color:var(--text3, #888); transition:color .15s;
}
.auth-pw-hint.weak   { color:#e74c3c; }
.auth-pw-hint.warn   { color:#e67e22; }
.auth-pw-hint.okay   { color:#c9a227; }
.auth-pw-hint.strong { color:#2ecc71; }

/* Required ToS/Privacy checkbox on the register form */
.auth-tos-check label {
  display:flex; align-items:flex-start; gap:8px;
  font-size:12.5px; line-height:1.4; color:var(--text2);
  cursor:pointer;
}
.auth-tos-check input[type="checkbox"] {
  margin-top:2px; flex-shrink:0;
}
.auth-tos-check a { color:var(--accent); }
.auth-tos-check a:hover { text-decoration:underline; }

/* Persistent Terms/Privacy footer, visible under login, register, and guest */
.auth-legal-footer {
  text-align:center; font-size:11px; color:var(--text3, #888);
  margin-top:18px;
}
.auth-legal-footer a { color:var(--text3, #888); text-decoration:underline; }
.auth-legal-footer a:hover { color:var(--accent); }
.auth-legal-footer a { cursor:pointer; }

/* Guest (temporary account) sign-in section */
.auth-guest { margin-top:18px; }
.auth-guest-divider {
  display:flex; align-items:center; text-align:center;
  color:var(--text3, #888); font-size:12px; margin:4px 0 14px;
}
.auth-guest-divider::before, .auth-guest-divider::after { content:''; flex:1; height:1px; background:var(--border); }
.auth-guest-divider span { padding:0 10px; }

/* Guest countdown — faint watermark, bottom-right, app-wide while signed in as a
   guest. Stays out of the way; brightens on hover. Still clickable (-> upgrade). */
#temp-account-banner {
  position:fixed; bottom:10px; right:12px; z-index:9000;
  background:var(--accent); color:var(--accent-fg,#fff); font-size:11px; font-weight:600;
  padding:6px 11px; border-radius:999px; cursor:pointer;
  box-shadow:0 2px 10px rgba(0,0,0,.2); user-select:none;
  opacity:.5; transition:opacity .15s;
}
#temp-account-banner:hover { opacity:1; }

/* Upgrade (guest -> full account) modal */
.upgrade-modal-overlay {
  position:fixed; inset:0; z-index:10002; background:rgba(0,0,0,.5);
  display:flex; align-items:center; justify-content:center; padding:16px;
}
.upgrade-modal-card {
  background:var(--surface); border:1px solid var(--border); border-radius:9px;
  padding:22px; width:100%; max-width:380px; box-shadow:0 10px 40px rgba(0,0,0,.35);
}
.upgrade-modal-card h2 { margin:0 0 6px; font-size:19px; }
.upgrade-modal-sub { margin:0 0 16px; font-size:13px; color:var(--text2); line-height:1.4; }
.guest-welcome-list { margin:0 0 18px; padding-left:20px; font-size:13px; color:var(--text2); line-height:1.5; }
.guest-welcome-list li { margin-bottom:9px; }
.guest-welcome-list strong { color:var(--text); }
#guest-welcome-ok:disabled { opacity:.55; cursor:default; }

/* First-run "how Eaves works" disclosure. Reuses .upgrade-modal-overlay/-card and the
   6-second forced-read countdown from the guest explainer above; only the extra width
   (four items instead of a paragraph) and the footer link are new. */
.intro-modal-card { max-width:460px; }
.intro-list { margin:0 0 16px; padding:0; list-style:none; font-size:13px; color:var(--text2); line-height:1.5; }
.intro-list li { margin-bottom:12px; padding-left:26px; position:relative; }
.intro-list li svg { position:absolute; left:0; top:1px; width:16px; height:16px; color:var(--text3); }
.intro-list b { display:block; color:var(--text); font-weight:600; margin-bottom:1px; }
.intro-modal-foot { margin:0 0 14px; font-size:12px; color:var(--text3); line-height:1.45; }
.intro-modal-foot a { color:var(--accent); cursor:pointer; text-decoration:underline; }
#intro-modal-ok:disabled { opacity:.55; cursor:default; }

/* HOME SCREEN */
#home-screen {
  display:none; padding:40px 20px 80px;
}
#home-screen > * {
  max-width:1100px; margin-left:auto; margin-right:auto;
}
.home-header {
  text-align:center; margin-bottom:32px;
}
.home-header h1 {
  font-size:28px; font-weight:700; margin-bottom:6px;
}
.home-header p {
  font-size:14px; color:var(--text2);
}
.home-tabs {
  display:flex; gap:4px;
  background:var(--surface); border:1px solid var(--border);
  border-radius:9px; padding:4px;
  max-width:520px; margin:0 auto 32px;
  box-shadow:var(--shsm);
}
.home-tab {
  flex:1; border:none; cursor:pointer;
  padding:10px 16px; border-radius:9px;
  font-family:'DM Sans',sans-serif; font-size:14px; font-weight:600;
  color:var(--text2); background:none;
  display:flex; align-items:center; justify-content:center; gap:7px;
  transition:all .18s;
}
.home-tab.active {
  background:var(--text); color:#fff;
  box-shadow:0 2px 8px rgba(0,0,0,.18);
}
/* Needs the #home-screen prefix to outrank `#home-screen > * { max-width:1100px }`
   — without it the .home-tabs 520px cap silently loses and the bar spans the
   full dashboard width. */
#home-screen > .home-tabs { max-width:520px; }
.home-pane { display:none; }
.home-pane.active { display:block; }

/* Store — its own full-screen page (overlay). Sits BELOW the billing page
   (z-index 210) so "Get credits" stacks on top, ABOVE settings (200). */
#store-screen {
  position:fixed; inset:0; z-index:205;
  background:var(--bg); overflow-y:auto;
  display:flex; flex-direction:column;
}
.store-page { width:100%; max-width:1120px; margin:0 auto; padding:28px 24px 80px; }

.store-head { display:flex; align-items:flex-start; justify-content:space-between; gap:16px; flex-wrap:wrap; margin-bottom:22px; }
.store-head h2 { font-size:24px; font-weight:700; margin-bottom:4px; }
.store-sub { font-size:13px; color:var(--text2); line-height:1.5; max-width:460px; }
.store-bal { display:flex; align-items:center; gap:12px; flex-wrap:wrap; }
.store-bal-amt { display:inline-flex; align-items:center; gap:6px; font:800 18px 'DM Sans',sans-serif; font-variant-numeric:tabular-nums;
  background:var(--s2); border:1px solid var(--border); border-radius:8px; padding:7px 14px; }
.store-bal-coin { font-size:18px; line-height:1; }
.store-empty { text-align:center; color:var(--text2); font-size:14px; padding:44px 0; }
.sub-cosmetic-owned { font-size:11px; color:var(--text2); margin-bottom:7px; }

.empty-state {
  text-align:center; padding:60px 32px;
  background:var(--surface); border:1px solid var(--border);
  border-radius:10px; max-width:420px; margin:0 auto;
}
.empty-state svg {
  opacity:.4; margin-bottom:16px;
}
.empty-state h2 {
  font-size:18px; font-weight:700; margin-bottom:8px;
}
.empty-state p {
  font-size:14px; color:var(--text2); margin-bottom:24px;
}

.servers-list {
  display:flex; flex-direction:column;
  background:var(--surface); border:1px solid var(--border);
  border-radius:9px; max-width:600px; margin:0 auto;
  overflow:hidden;
}
/* With no rows these bordered cards collapse to a stray 1px gray line
   (during the fetch and for users with zero servers/friends) — hide until
   a render puts content in. */
.servers-list:empty, .friends-list:empty { display:none; }

.friends-container { max-width:600px; margin:0 auto; }
.friends-header {
  display:flex; align-items:center; justify-content:space-between;
  margin-bottom:20px;
}
.friends-header h2 {
  font-size:18px; font-weight:700;
}
.friends-list {
  display:flex; flex-direction:column;
  background:var(--surface); border:1px solid var(--border);
  border-radius:9px;
}

.friend-row {
  display:flex; align-items:center; justify-content:space-between;
  padding:12px 16px; border-bottom:1px solid var(--border);
}
.friend-row:last-child { border-bottom:none; }
/* Long usernames must truncate, not widen the row — a ~38-char name otherwise
   forces horizontal page scroll on narrow phones. min-width:0 lets the flex
   child shrink below its content (same trap as the flex-scroll min-height). */
.friend-row > div:first-child { flex:1; min-width:0; }
.friend-row .user-avatar { flex-shrink:0; }
.friend-name { font-size:14px; font-weight:500; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }

/* DARK MODE */
body.dark {
  --bg:      #1a1916;
  --surface: #242220;
  --s1:      #2a2825;
  --s2:      #2c2a27;
  --s3:      #343230;
  --border:  #3d3b37;
  --text:    #f5f4f0;
  --text2:   #a8a69f;
  --text3:   #6b6860;
  --abg:     #1a2a4a;
}

body.dark header {
  background:color-mix(in srgb, #1a1916 88%, transparent);
}

body.dark .logo-mark {
  background:var(--text3);
}

body.dark .tab-btn,
body.dark .home-tab {
  color:var(--text3);
}

/* ============================================================
   UI v2 — "Warm Loft" opt-in re-skin. Toggle: Settings -> New look
   (adds body.ui-v2; default OFF, so this never affects anyone who
   hasn't opted in). Token-driven: it re-skins the app from the same
   CSS variables the components already use. Warm light + a warm dark
   variant for users who also have dark mode on.
   ============================================================ */
body.ui-v2 {
  /* WARMTH DIALED DOWN 2026-06-27: neutrals pulled toward warm-greige (much less
     cream/yellow), keeping the rust/honey accent family as the warm anchor. To
     restore the original Warm Loft, swap these back:
       --bg #f2e4cb; --surface #fdf6e7; --s1 #f8efdc; --s2 #f0e6d1; --s3 #ecdcbf;
       --border #e7d8bd; --text #2c2014; --text2 #6e6049; --text3 #a5947a;
       --abg #f3e8d2; --div rgba(120,94,54,.42);
       --paper #f2e4cb; --card #fdf6e7; --card2 #f8efdc; --ink #2c2014; --ink2 #6e6049; --ink3 #a5947a;
       --line #e7d8bd; --line2 #f0e6d1 */
  --bg:      #ece7df;
  --surface: #faf8f3;
  --s1:      #f4f1ea;
  --s2:      #ebe7df;
  --s3:      #e3ded3;
  --border:  #ddd7cc;
  --text:    #29251f;
  --text2:   #615b51;
  --text3:   #9a9389;
  --accent:  #bd6a39;
  --accent2: #a4542b;
  --accent-fg:#fff;
  --abg:     #efe9e0;
  --live:    #c75f3e;
  --div:     rgba(110,100,86,.40);   /* mock --div: the darker structural divider (header/sidebar/section), distinct from the lighter --border/--line */
  /* mock (warm3.css) palette names, aliased so ported mock CSS resolves VERBATIM.
     Zero classic CSS references these names, so they only affect ported ui-v2 surfaces. */
  --paper:#ece7df; --card:#faf8f3; --card2:#f4f1ea; --ink:#29251f; --ink2:#615b51; --ink3:#9a9389;
  --line:#ddd7cc; --line2:#ebe7df; --honey:#dd9430; --clay:#c75f3e; --olive:#7f8b3c; --plum:#9c5e78; --rust:#bd6a39; --teal:#3f8276;
  --f:'DM Sans',system-ui,-apple-system,sans-serif; --disp:'Hanken Grotesk','DM Sans',system-ui,sans-serif;
  /* in-call "stage" tokens (space.css :root) — warm-DARK, constant in both light + dark modes
     (the call stage is intentionally dark regardless of the app theme). */
  --stage:#271d12; --stage2:#211a10; --tile:#33271a; --tile2:#2c2114; --tline:rgba(246,193,99,.11);
  --cream:#efe2c8; --cream2:#c3b193; --cream3:#8f8068;
  /* stage accent literals, tokenized 2026-07-11 so dark can repaint the stage (light keeps the warm stage) */
  --st-rgb:246,193,99; --st-act-rgb:221,148,48; --st-hot:#f3c074;
  --st-glass-rgb:33,25,15; --st-ink-rgb:28,21,12; --st-pop-rgb:35,26,15;
  --st-wash:#34271640; --st-editor:#2c2014;
  --st-dock-bg:linear-gradient(180deg,#2d2215,#241a0f); --st-dock-bg2:#241a0f;
  --st-tile-act:linear-gradient(150deg,#3a2c18,#2c2114);
  --r:       10px;   /* less-round pass 2026-06-27 (was 16px) */
  --rsm:     7px;    /* (was 11px) */
}
body.ui-v2.dark {
  /* FOREST — deep pine + mint-ivory, the new dark identity (2026-07-11 velvet session).
     Accent rule: the accent is the wall hue pushed to its lightest tint, never a foreign
     neutral; --accent-fg carries the dark ink used ON accent fills.
     Previous neutral warm-dark, restore by swapping back:
       --bg #201d18; --surface #2a2620; --s1 #2f2b24; --s2 #332f27; --s3 #3a352c;
       --border #3a352c; --text #f1ede5; --text2 #b8b1a4; --text3 #88827a;
       --accent #dd9430; --accent2 #f0c46a; --abg #332f27; --div rgba(235,232,226,.13);
       --paper #201d18; --card #2a2620; --card2 #2f2b24; --ink #f1ede5; --ink2 #b8b1a4; --ink3 #88827a;
       --line #3a352c; --line2 #332f27; --rust #f0c46a */
  --bg:      #1d2921;
  --surface: #24352a;
  --s1:      #293a2e;
  --s2:      #2d3f33;
  --s3:      #334939;
  --border:  #3b5745;
  --text:    #dee6da;
  --text2:   #adc2af;
  --text3:   #7d937f;
  --accent:  #dde7d3;
  --accent2: #eaf1e1;
  --accent-fg:#16221b;
  --abg:     #213127;
  --live:    #c75f3e;
  --div:     rgba(230,242,230,.15);
  --paper:#1d2921; --card:#24352a; --card2:#293a2e; --ink:#dee6da; --ink2:#adc2af; --ink3:#7d937f;
  --line:#3b5745; --line2:#2d3f33; --honey:#dde7d3; --clay:#c96a52; --olive:#7f8b3c; --plum:#9c5e78; --teal:#3f8276; --rust:#dde7d3;
  /* pine stage: dark users get a forest call room; light users keep the warm stage */
  --stage:#19241d; --stage2:#16201a; --tile:#263629; --tile2:#203025; --tline:rgba(190,222,196,.11);
  --cream:#dfe8db; --cream2:#aac0ad; --cream3:#7e937f;
  --st-rgb:190,222,196; --st-act-rgb:190,222,196; --st-hot:#d0e0cc;
  --st-glass-rgb:18,28,22; --st-ink-rgb:14,22,17; --st-pop-rgb:16,26,20;
  --st-wash:#16241c40; --st-editor:#14211a;
  --st-dock-bg:linear-gradient(180deg,#1c2b21,#141f18); --st-dock-bg2:#141f18;
  --st-tile-act:linear-gradient(150deg,#223328,#1a2820);
  --f:'DM Sans',system-ui,-apple-system,sans-serif; --disp:'Hanken Grotesk','DM Sans',system-ui,sans-serif;
}
/* Forest ambience: a faint fixed light wash (kept ultra-low alpha; sits above opaque
   screen fills, which is deliberate — behind them it would be invisible). */
body.ui-v2.dark::after {
  content:""; position:fixed; inset:0; pointer-events:none; z-index:9999;
  background:
    radial-gradient(1000px 540px at 18% -6%, rgba(210,225,205,.05), transparent 60%),
    radial-gradient(1100px 640px at 90% 110%, rgba(88,150,108,.06), transparent 58%);
}
body.ui-v2.dark #home-v2 .hero:not(.live) { background:linear-gradient(165deg,#23352a 0%,#1b2a21 100%); border-color:#3a5641; }
body.ui-v2.dark #auth-screen { background:radial-gradient(1100px 560px at 28% 24%, rgba(140,180,150,.09), transparent 62%); }
body.ui-v2.dark #auth-screen input { background:var(--s1); color:var(--text); }
body.ui-v2.dark #auth-screen input::placeholder { color:var(--text3); }
/* Sibling theme: VELVET — soft burgundy + rose-ivory. Same structure as forest, one hue
   apart. No settings UI yet: enable with body.theme-velvet alongside .ui-v2.dark. */
body.ui-v2.dark.theme-velvet {
  --bg:#2b161a; --surface:#3e2126; --s1:#43242a; --s2:#49282e; --s3:#522d33;
  --border:#5e343a; --text:#eddcd7; --text2:#c4a09d; --text3:#94706f;
  --accent:#efdcd4; --accent2:#f8ece6; --accent-fg:#3d1418; --abg:#49282e;
  --live:#e07a50; --div:rgba(238,220,214,.15);
  --paper:#2b161a; --card:#3e2126; --card2:#43242a; --ink:#eddcd7; --ink2:#c4a09d; --ink3:#94706f;
  --line:#5e343a; --line2:#49282e; --honey:#efdcd4; --clay:#e07a50; --rust:#efdcd4;
}
body.ui-v2.dark.theme-velvet::after {
  background:
    radial-gradient(1000px 540px at 18% -6%, rgba(240,220,196,.05), transparent 60%),
    radial-gradient(1100px 640px at 90% 110%, rgba(214,74,74,.07), transparent 58%);
}
body.ui-v2.dark.theme-velvet #home-v2 .hero:not(.live) { background:linear-gradient(165deg,#442329 0%,#351a1f 100%); border-color:#653840; }
body.ui-v2.dark.theme-velvet #auth-screen { background:radial-gradient(1100px 560px at 28% 24%, rgba(214,74,74,.10), transparent 62%); }
/* Cross-rule light-text-on-accent cases the token migration could not reach in-place */
.band-pkey-white.band-key-active .band-pkey-label { color:var(--accent-fg,#fff); }
.spv2-search .ssch-av-i { color:var(--accent-fg,#fff); }
/* Dark themes: light-tinted chips + hardcoded slabs that never had dark variants */
body.ui-v2.dark .fr-btn.no, body.ui-v2.dark #hv-header .fr-act .mini.no { background:#33231e; color:#e09a82; }
body.ui-v2.dark .vchip-warn { background:#33231e; color:#e09a82; }
body.ui-v2.dark #home-v2 .addspace:hover { background:var(--s2); color:var(--text); }
body.ui-v2.dark .band-banner-join { background:var(--accent); color:var(--accent-fg,#fff); }
body.ui-v2.dark #spe-insp .imgbtn { background:var(--s2); }
body.ui-v2.dark #spe-insp input[type=range].rng { background:var(--s3); }
body.ui-v2.dark .btn-primary { box-shadow:0 2px 10px rgba(0,0,0,.4); }
body.ui-v2.dark .btn-primary:hover { box-shadow:0 4px 16px rgba(0,0,0,.5); }
/* Dark forest: screenshot-sweep round 2 (specificity + leftover Warm Loft orange) */
body.dark .tab-btn.active { color:var(--bg,#fff); }
body.ui-v2.dark .form-group input, body.ui-v2.dark #temp-username { background:var(--s1); color:var(--text); }
body.ui-v2.dark .form-group input::placeholder, body.ui-v2.dark #temp-username::placeholder { color:var(--text3); }
body.ui-v2.dark #settings-v2-screen .prof-banner { background:linear-gradient(120deg,#35503c,#213127); background-size:cover; background-position:center; }
body.ui-v2.dark #store-v2 .cr-bal { background:linear-gradient(135deg,#1e2d24,#16241c); color:var(--text); border-color:var(--border); }
body.ui-v2.dark #store-v2 .cr-bal .ci { background:rgba(230,242,230,.12); color:var(--accent); }
body.ui-v2.dark #store-v2 .cr-bal .cn span { color:var(--text2); }
body.ui-v2.dark #store-v2 .cr-bal .gift { border-color:rgba(230,242,230,.25); color:var(--accent); }
body.ui-v2.dark #home-v2 .hero.live { background:linear-gradient(135deg,#1e2f25,#16241c); color:var(--text); border-color:var(--border); }
body.ui-v2.dark #home-v2 .hero.live .lab { color:var(--accent2); }
body.ui-v2.dark #settings-v2-screen .plan { background:linear-gradient(135deg,#1e2d24,#16241c); color:var(--text); border-color:var(--border); }
body.ui-v2.dark #settings-v2-screen .plan .pm { color:var(--text2); }
body.ui-v2.dark #settings-v2-screen .plan .pr button { color:var(--accent); }
body.ui-v2.dark #settings-v2-screen .plan .pt .bdg { color:#16221b; }
/* headings take the display face in the new look */
body.ui-v2 #home-username,
body.ui-v2 .home-header h1,
body.ui-v2 .home-header h2,
body.ui-v2 .settings-title,
body.ui-v2 .logo-text {
  font-family:'Hanken Grotesk','DM Sans',system-ui,sans-serif;
  font-weight:800;
  letter-spacing:-.015em;
}

/* The redesigned Home (#home-v2). Rendered by js/home-v2.js. Hidden unless
   ui-v2 is on, at which point it replaces the classic home header/tabs/panes. */
#home-v2 { display:none; }
body.ui-v2 #home-screen > .home-header,
body.ui-v2 #home-screen > .home-tabs,
body.ui-v2 #home-screen > .home-pane { display:none !important; }
body.ui-v2 #home-v2 { display:block; }
/* #home-v2 is the sole source of its own padding/width; cancel the inherited
   #home-screen box so they don't stack (doubled gutters / nested max-width). */
body.ui-v2 #home-screen { padding:0; }
body.ui-v2 #home-v2 { max-width:none; margin:0; width:100%; }
/* ---- home content: ported VERBATIM from warm3.css, scoped under #home-v2 ----
   Mock class names kept (.greet/.hero/.space/.qs/...); values byte-for-byte from
   the mock. .hv-wrap is the one namespaced container (mock `.wrap` is too generic). */
body.ui-v2 #home-v2 { font-family:var(--f); color:var(--ink); }
#home-v2 .hv-wrap { max-width:1100px; margin:0 auto; padding:0 30px 40px; }
/* greeting */
#home-v2 .greet { margin:20px 2px 6px; position:relative; }   /* positioning anchor for the splash-warp canvas (splash-warp.js) */
/* touch-action:none is load-bearing, not decorative: on a real touchscreen the OS
   decides scroll-vs-custom-gesture the instant a finger moves, based on CSS set
   BEFORE the drag starts - it doesn't wait for JS. Setting this only on the
   dynamically-created warp canvas (which doesn't exist until well after the drag
   has already begun) was too late; the page could already be scrolling by then. */
#home-v2 .greet h1 { font-family:var(--disp); font-weight:700; font-size:32px; letter-spacing:-.025em; line-height:1.05; cursor:pointer; touch-action:none; user-select:none; }
#home-v2 .greet .status { margin-top:9px; font-size:14.5px; color:var(--ink2); display:inline-flex; align-items:center; gap:9px; }
#home-v2 .greet .status .d { width:8px; height:8px; border-radius:50%; background:var(--olive); }
#home-v2 .greet .status b { color:var(--ink); font-weight:700; }
#home-v2 .greet .status.quiet .d { background:var(--ink3); }
#home-v2 .greet .util { display:inline-flex; gap:8px; margin-left:14px; }
#home-v2 .greet .util a { color:var(--rust); font-weight:700; font-size:13px; cursor:pointer; }
/* hero (no glows) */
#home-v2 .hero { position:relative; border-radius:9px; padding:22px 24px; margin:16px 0 6px; overflow:hidden; border:1px solid var(--line); }
#home-v2 .hero.live { background:linear-gradient(135deg,#2f2415,#3a2c18); color:#f6ecd8; border-color:#43331c; }
#home-v2 .hero.live::before { content:""; position:absolute; left:0; top:0; bottom:0; width:5px; background:var(--clay); }
#home-v2 .hero .lab { position:relative; font-size:11.5px; font-weight:800; letter-spacing:.12em; text-transform:uppercase; display:flex; align-items:center; gap:8px; color:var(--honey); }
#home-v2 .hero.live .lab { color:#f0c46a; }
#home-v2 .hero .lab i { width:7px; height:7px; border-radius:50%; background:var(--clay); }
@keyframes hv-pp { 50% { opacity:.4; } }
#home-v2 .hero h2 { position:relative; font-family:var(--disp); font-weight:800; font-size:23px; letter-spacing:-.02em; margin:11px 0 4px; }
#home-v2 .ld { display:inline-block; width:8px; height:8px; border-radius:50%; background:var(--clay); margin-right:10px; vertical-align:middle; }
#home-v2 .hero .sub { position:relative; font-size:14px; opacity:.92; }
#home-v2 .hero .row2 { position:relative; display:flex; align-items:center; gap:14px; margin-top:16px; flex-wrap:wrap; }
#home-v2 .hero .avs { display:flex; }
#home-v2 .hero .avs span { width:38px; height:38px; border-radius:50%; border:3px solid #3a2c18; margin-left:-11px; display:grid; place-items:center; font-weight:700; font-size:14px; color:#fff; }
#home-v2 .hero .avs span:first-child { margin-left:0; }
#home-v2 .btn-primary { border:none; background:var(--honey); color:#3a2410; font-family:var(--f); font-weight:800; font-size:14.5px; padding:12px 22px; border-radius:9px; cursor:pointer; box-shadow:0 8px 18px -9px rgba(189,106,57,.55); }
#home-v2 .btn-primary:hover { filter:brightness(1.06); }
#home-v2 .hero .go { margin-left:auto; }
#home-v2 .hero.calm, #home-v2 .hero.welcome { background:linear-gradient(150deg,var(--card),var(--card2)); color:var(--ink); }
#home-v2 .hero.calm .lab { color:var(--clay); }
#home-v2 .hero.calm .lab i { background:var(--ink3); animation:none; }
#home-v2 .hero.calm h2, #home-v2 .hero.welcome h2 { color:var(--ink); }
#home-v2 .hero.calm .sub, #home-v2 .hero.welcome .sub { color:var(--ink2); max-width:480px; }
#home-v2 .hero .acts { position:relative; display:flex; gap:10px; margin-top:16px; flex-wrap:wrap; }
#home-v2 .btn-soft { border:1px solid var(--line); background:var(--card); color:var(--ink); font-family:var(--f); font-weight:700; font-size:14px; padding:11px 17px; border-radius:9px; cursor:pointer; }
#home-v2 .btn-soft:hover { border-color:var(--honey); color:var(--rust); }
#home-v2 .hero.welcome { display:grid; grid-template-columns:minmax(0,1fr) 220px; gap:28px; align-items:center; padding:26px 30px; }
#home-v2 .hero.welcome .lab { color:var(--honey); }
#home-v2 .welcome-main h2 { font-size:28px; margin:11px 0 7px; max-width:none; }
#home-v2 .welcome-main .acts { margin-top:18px; }
#home-v2 .welcome-alt { margin-top:15px; font-size:13px; color:var(--ink2); }
#home-v2 .welcome-alt a { color:var(--rust); font-weight:700; text-decoration:none; cursor:pointer; }
#home-v2 .welcome-art { width:220px; }
#home-v2 .welcome-art svg { width:100%; height:auto; display:block; }
/* two-column work row: spaces | divider | quick share */
#home-v2 .workrow { display:grid; grid-template-columns:minmax(0,1fr) 1px 300px; gap:26px; align-items:stretch; margin-top:8px; }
#home-v2 .div-v { background:var(--div); }
#home-v2 .sec { display:flex; align-items:center; gap:12px; margin:0 2px 14px; }
#home-v2 .sec h3 { font-family:var(--disp); font-weight:800; font-size:18px; letter-spacing:-.01em; }
#home-v2 .sec .ct { font-size:12px; color:var(--ink3); font-weight:700; background:var(--s3,#e3ded3); padding:3px 9px; border-radius:999px; }
#home-v2 .sec .rule { flex:1; height:1px; background:linear-gradient(90deg,var(--line),transparent); }
#home-v2 .spaces-scroll { max-height:432px; overflow-y:auto; overflow-x:hidden; padding-right:10px; scrollbar-width:thin; scrollbar-color:var(--rust) rgba(120,94,54,.14); }
#home-v2 .spaces-scroll::-webkit-scrollbar { width:9px; }
#home-v2 .spaces-scroll::-webkit-scrollbar-track { background:rgba(120,94,54,.10); border-radius:99px; margin:2px 0; }
#home-v2 .spaces-scroll::-webkit-scrollbar-thumb { background:linear-gradient(var(--honey),var(--rust)); border-radius:99px; border:2px solid transparent; background-clip:padding-box; }
#home-v2 .spaces-scroll::-webkit-scrollbar-thumb:hover { filter:brightness(1.07); }
#home-v2 .grid { display:grid; grid-template-columns:1fr 1fr; gap:13px; }
/* min-height:104px matches the mock/add-card so all cards are the same (taller) size; we
   center the icon+name vertically since our cards lack the mock's desc/avatar rows that would
   otherwise fill the height (top-align + revisit once that content exists — MOCK_REBUILD_GAPS.md). */
#home-v2 .space { position:relative; min-width:0; min-height:104px; display:flex; flex-direction:column; justify-content:center; background:var(--card); border:1px solid var(--line); border-radius:10px; padding:13px; box-shadow:0 12px 24px -22px rgba(80,50,15,.5); transition:transform .12s; cursor:pointer; overflow:hidden; }
#home-v2 .space::before { content:""; position:absolute; inset:0; background:var(--tint); opacity:.07; pointer-events:none; }
#home-v2 .space:hover { transform:translateY(-2px); }
#home-v2 .space .top { position:relative; display:flex; align-items:center; gap:11px; min-width:0; }
#home-v2 .space .top > div { min-width:0; }
#home-v2 .space .ic { width:42px; height:42px; border-radius:9px; background:var(--c2); display:grid; place-items:center; font-size:18px; font-weight:800; color:#fff; flex:none; background-size:cover; background-position:center; }
#home-v2 .space .ic-wrap { position:relative; flex:none; }
#home-v2 .space .sp-unread { position:absolute; top:-5px; right:-5px; min-width:18px; height:18px; padding:0 4px; border-radius:99px;
  background:var(--clay); color:#fff; font-size:10px; font-weight:800; display:flex; align-items:center; justify-content:center; border:2px solid var(--card); }
/* single-line name (ellipsis) so every card is the SAME height — without the mock's
   desc/presence rows to equalize them, a wrapping 2-line name would make a card taller. */
#home-v2 .space h4 { font-family:var(--disp); font-weight:800; font-size:15px; letter-spacing:-.01em; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
#home-v2 .space .meta { font-size:12px; color:var(--ink2); margin-top:2px; display:flex; align-items:center; gap:6px; }
/* optional space tagline on the card (single-line ellipsis so cards stay the same height) */
#home-v2 .space .sp-desc, #home-v2 .h-space .sp-desc { font-size:12px; color:var(--ink2); margin:2px 0 0; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
#home-v2 .space .dot { width:7px; height:7px; border-radius:50%; background:var(--olive); }
#home-v2 .space .dot.idle { background:var(--ink3); }
/* live-call badge (top-right of the space card) — ported from warm3.css .space .live */
#home-v2 .space .live { position:absolute; top:0; right:0; border-radius:0 0 0 10px; padding:5px 10px 5px 11px;
  font-size:10px; font-weight:800; letter-spacing:.06em; text-transform:uppercase; color:#fff; background:var(--clay);
  display:flex; align-items:center; gap:5px; z-index:2; }
#home-v2 .space .live i { width:6px; height:6px; border-radius:50%; background:#ffd9c8; }
@keyframes hv-pp { 50% { opacity:.4; } }
#home-v2 .space .desc { position:relative; margin-top:9px; font-size:12px; color:var(--ink2); line-height:1.42; display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden; }
#home-v2 .space .live { position:absolute; top:0; right:0; border-radius:0 0 0 10px; padding:5px 10px 5px 11px; font-size:10px; font-weight:800; letter-spacing:.06em; text-transform:uppercase; color:#fff; background:var(--clay); display:flex; align-items:center; gap:5px; z-index:2; }
#home-v2 .space .live i { width:6px; height:6px; border-radius:50%; background:#ffd9c8; }
#home-v2 .space .av { position:relative; display:flex; margin-top:11px; align-items:center; }
#home-v2 .space .av span { width:24px; height:24px; border-radius:50%; border:2px solid var(--card); margin-left:-8px; font-size:10px; display:grid; place-items:center; color:#fff; font-weight:700; }
#home-v2 .space .av span:first-child { margin-left:0; }
#home-v2 .space .av .n { margin-left:9px; font-size:11.5px; color:var(--ink3); font-weight:600; }
#home-v2 .addspace { border:1.5px dashed var(--border,#ddd7cc); border-radius:10px; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:3px; color:var(--ink2); font-weight:700; font-size:13.5px; min-height:104px; cursor:pointer; text-align:center; }
#home-v2 .addspace span { font-size:20px; }
#home-v2 .addspace:hover { border-color:var(--honey); color:var(--rust); background:#faf2e2; }
/* quick share column */
#home-v2 .qs { background:var(--card); border:1px solid var(--line); border-radius:8px; padding:18px; box-shadow:0 12px 26px -22px rgba(80,50,15,.5); }
#home-v2 .qs .qi { width:46px; height:46px; border-radius:9px; background:linear-gradient(150deg,var(--honey),var(--rust)); display:grid; place-items:center; font-size:22px; margin-bottom:12px; }
#home-v2 .qs h4 { font-family:var(--disp); font-weight:800; font-size:17px; margin-bottom:5px; }
#home-v2 .qs p { font-size:12.5px; color:var(--ink2); line-height:1.5; margin-bottom:14px; }
#home-v2 .qs .btn-primary { width:100%; text-align:center; }
#home-v2 .qs .recent { margin-top:16px; border-top:1px solid var(--line2); padding-top:13px; }
#home-v2 .qs .recent h6 { font-size:11px; text-transform:uppercase; letter-spacing:.08em; color:var(--ink3); font-weight:700; margin-bottom:9px; }
#home-v2 .qs .ritem { display:flex; align-items:center; gap:10px; padding:6px 0; font-size:13px; }
#home-v2 .qs .ritem .ri { width:30px; height:30px; border-radius:9px; background:var(--card2); display:grid; place-items:center; font-size:15px; flex:none; }
#home-v2 .qs .ritem .rn { font-weight:700; }
#home-v2 .qs .ritem .rt { font-size:11.5px; color:var(--ink3); }
/* empty + foot */
#home-v2 .empty { border:1.5px dashed var(--border,#ddd7cc); border-radius:9px; padding:38px 24px; text-align:center; background:linear-gradient(180deg,var(--card),var(--card2)); }
#home-v2 .empty .ei { font-size:40px; margin-bottom:12px; }
#home-v2 .empty h3 { font-family:var(--disp); font-weight:800; font-size:20px; margin-bottom:6px; }
#home-v2 .empty p { color:var(--ink2); font-size:14px; max-width:420px; margin:0 auto 18px; line-height:1.5; }
#home-v2 .empty .erow { display:flex; gap:10px; justify-content:center; flex-wrap:wrap; }
@media (max-width:820px){
  #home-v2 .workrow { grid-template-columns:1fr; }
  #home-v2 .div-v { display:none; }
  #home-v2 .hero.welcome { grid-template-columns:1fr; }
  #home-v2 .welcome-art { display:none; }
  #home-v2 .grid { grid-template-columns:1fr; }
}

/* ===== MOBILE HOME (warm3-home-mobile.html + mobile.css, ported scoped) =====
   Same breakpoint as the Space mobile reflow. The desktop #hv-header becomes the
   mock's compact app bar; #home-v2 renders the mobile feed + a fixed bottom tab
   bar (built by home-v2.js renderHomeV2Mobile). Fake phone frame / status bar /
   home indicator are dropped (real app chrome). */
@media (max-width:700px), (pointer:coarse) and (max-width:950px){
  /* --- feed (app-bar #hv-header rules live AFTER the desktop header CSS below,
     so they win on source order) --- */
  body.ui-v2 #home-v2 { padding:0; }
  /* Keep the browser's pull-to-refresh from hijacking downward pulls at the top:
     it fights the h-eaves easter egg, and an accidental PTR reload of the SPA
     would drop a live call. ui-v2 mobile only. The viewport reads this off the
     ROOT element (spec; body doesn't propagate it), hence the :has() rule; the
     body rule is a belt-and-suspenders for engines that still honor body. */
  html:has(body.ui-v2) { overscroll-behavior-y:contain; }
  body.ui-v2 { overscroll-behavior-y:contain; }
  /* "under the eaves" pull-down easter egg strip (rendered by renderHomeV2Mobile;
     home-v2.js inflates it with sustained fast pulling at scroll-top and drives
     every frame via rAF, no CSS transition). Two sliders: the strip edge moves
     1:1 with pressure, the text (.t) trails at 0.6x via translateY, starting
     tucked out of sight above (-15px). */
  #home-v2 .h-eaves { position:relative; height:0; overflow:hidden; }
  #home-v2 .h-eaves .t { position:absolute; top:0; left:0; right:0; text-align:center;
    color:var(--ink3); font-size:12px; letter-spacing:.03em; line-height:1.3;
    transform:translateY(-37px); will-change:transform; }
  /* position+z-index (not just padding) matters here: #home-v2::before (the paper
     texture) is position:absolute z-index:0, and in dark mode it's opacity:1/fully
     opaque (crumple-dark-baked.png IS the final composited pixels, see the ::before
     rule). Desktop's content wrapper (.hv-wrap) already has position:relative;z-index:1
     to paint above that; .h-feed never did, so on mobile the opaque texture painted
     OVER the whole feed (greet/hero/friends card all visually covered, though the DOM/
     computed styles looked completely normal - only screen-space paint order was wrong).
     This was the real cause of the "home page mostly disappearing" mobile report. */
  #home-v2 .h-feed { padding:17px 15px 90px; position:relative; z-index:1; }   /* bottom pad clears the fixed tab bar */
  #home-v2 .h-greet { position:relative; }   /* positioning anchor for the splash-warp canvas (splash-warp.js) */
  #home-v2 .h-greet h1 { font-family:var(--disp); font-weight:700; font-size:25px; letter-spacing:-.02em; line-height:1.05; color:var(--ink); cursor:pointer; touch-action:none; user-select:none; }
  #home-v2 .h-greet .st { margin-top:7px; font-size:13.5px; color:var(--ink2); display:flex; align-items:center; gap:8px; flex-wrap:wrap; }
  #home-v2 .h-greet .st .d { width:8px; height:8px; border-radius:50%; background:var(--olive); flex:none; }
  #home-v2 .h-greet .st.quiet .d { background:var(--ink3); }
  #home-v2 .h-greet .util { display:inline-flex; gap:10px; }
  #home-v2 .h-greet .util a { color:var(--rust); font-weight:700; cursor:pointer; }

  #home-v2 .h-friends { display:flex; align-items:center; gap:11px; margin-top:15px; padding:11px 13px; background:var(--card); border:1px solid var(--line); border-radius:10px; cursor:pointer; }
  #home-v2 .h-friends .avs { display:flex; }
  #home-v2 .h-friends .avs span { width:30px; height:30px; border-radius:50%; border:2px solid var(--card); margin-left:-9px; display:grid; place-items:center; color:#fff; font-weight:700; font-size:11px; background-size:cover; background-position:center; }
  #home-v2 .h-friends .avs span:first-child { margin-left:0; }
  #home-v2 .h-friends .ft { font-size:13.5px; font-weight:800; color:var(--ink); min-width:0; }
  #home-v2 .h-friends .ft small { display:block; font-size:11.5px; color:var(--ink2); font-weight:600; margin-top:1px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
  #home-v2 .h-friends .go { margin-left:auto; color:var(--ink3); flex:none; }

  #home-v2 .h-sec { display:flex; align-items:center; gap:10px; margin:20px 2px 13px; }
  #home-v2 .h-sec h3 { font-family:var(--disp); font-weight:800; font-size:17px; color:var(--ink); }
  #home-v2 .h-sec .ct { font-size:11px; color:var(--ink3); font-weight:700; background:var(--s3,#e3ded3); padding:3px 9px; border-radius:999px; }
  #home-v2 .h-sec .rule { flex:1; height:1px; background:linear-gradient(90deg,var(--line),transparent); }

  #home-v2 .h-space { position:relative; display:flex; align-items:center; gap:12px; background:var(--card); border:1px solid var(--line); border-radius:10px; padding:13px; margin-bottom:11px; overflow:hidden; box-shadow:0 12px 24px -22px rgba(80,50,15,.5); cursor:pointer; }
  #home-v2 .h-space::before { content:""; position:absolute; inset:0; background:var(--tint); opacity:.06; pointer-events:none; }
  #home-v2 .h-space .ic { width:46px; height:46px; border-radius:9px; background:var(--c2); display:grid; place-items:center; color:#fff; font-weight:800; font-size:19px; font-family:var(--disp); flex:none; position:relative; background-size:cover; background-position:center; }
  #home-v2 .h-space .info { flex:1; min-width:0; position:relative; }
  #home-v2 .h-space h4 { font-family:var(--disp); font-weight:800; font-size:15px; color:var(--ink); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
  /* mobile space-card presence (call badge / online count / avatar stack / unread) — mirrors desktop spaceCard */
  #home-v2 .h-space .ic-wrap { position:relative; flex:none; }
  #home-v2 .h-space .sp-unread { position:absolute; top:-5px; right:-5px; min-width:18px; height:18px; padding:0 5px; border-radius:99px; background:var(--clay); color:#fff; font-size:10px; font-weight:800; display:flex; align-items:center; justify-content:center; border:2px solid var(--card); }
  #home-v2 .h-space .h-meta { display:flex; align-items:center; gap:8px; margin-top:3px; font-size:11.5px; color:var(--ink2); font-weight:600; }
  #home-v2 .h-space .h-meta .live { display:inline-flex; align-items:center; gap:4px; padding:2px 7px; border-radius:99px; background:var(--clay); color:#fff; font-size:9.5px; font-weight:800; letter-spacing:.05em; text-transform:uppercase; }
  #home-v2 .h-space .h-meta .live i { width:5px; height:5px; border-radius:50%; background:#ffd9c8; }
  #home-v2 .h-space .h-meta .on { display:inline-flex; align-items:center; gap:5px; }
  #home-v2 .h-space .h-meta .on .dot { width:6px; height:6px; border-radius:50%; background:var(--olive); }
  #home-v2 .h-space .av { display:flex; align-items:center; flex:none; }
  #home-v2 .h-space .av span { width:24px; height:24px; border-radius:50%; border:2px solid var(--card); margin-left:-8px; display:grid; place-items:center; color:#fff; font-weight:700; font-size:10px; background-size:cover; background-position:center; }
  #home-v2 .h-space .av span:first-child { margin-left:0; }
  #home-v2 .h-space .av .n { margin-left:7px; font-size:11px; color:var(--ink3); font-weight:700; }

  #home-v2 .h-addspace { border:1.5px dashed var(--border,#ddd7cc); border-radius:10px; display:flex; align-items:center; justify-content:center; gap:8px; color:var(--ink2); font-weight:700; font-size:13.5px; padding:15px; cursor:pointer; }
  #home-v2 .h-addspace span { font-size:18px; }
  #home-v2 .h-addspace:active { border-color:var(--honey); color:var(--rust); }

  #home-v2 .h-qs { background:var(--card); border:1px solid var(--line); border-radius:8px; padding:16px; box-shadow:0 12px 24px -22px rgba(80,50,15,.5); }
  #home-v2 .h-qs p { font-size:12.5px; color:var(--ink2); line-height:1.5; margin-bottom:13px; }
  #home-v2 .h-qs .btn { width:100%; border:none; background:var(--honey); color:#3a2410; font-family:var(--f); font-weight:800; font-size:14px; padding:12px; border-radius:9px; cursor:pointer; }

  #home-v2 .h-welcome { background:linear-gradient(150deg,var(--card),var(--card2)); border:1px solid var(--line); border-radius:9px; padding:20px; margin-top:15px; }
  #home-v2 .h-welcome h2 { font-family:var(--disp); font-weight:800; font-size:21px; color:var(--ink); margin-bottom:8px; }
  #home-v2 .h-welcome p { font-size:13px; color:var(--ink2); line-height:1.5; margin-bottom:15px; }
  #home-v2 .h-welcome .btn { width:100%; border:none; background:var(--honey); color:#3a2410; font-family:var(--f); font-weight:800; font-size:14px; padding:12px; border-radius:9px; cursor:pointer; margin-bottom:9px; }
  #home-v2 .h-welcome .btn.soft { background:var(--card); color:var(--ink); border:1px solid var(--line); margin-bottom:0; }

  /* --- fixed bottom tab bar (home feed + the Quick Share / setup screen) --- */
  #home-v2 .h-tabs, body.ui-v2 #setup-screen .h-tabs { position:fixed; left:0; right:0; bottom:0; z-index:40; display:flex;
    border-top:1px solid var(--div); background:var(--paper); padding:8px 6px calc(4px + env(safe-area-inset-bottom)); }
  #home-v2 .h-tab, body.ui-v2 #setup-screen .h-tab { flex:1; display:flex; flex-direction:column; align-items:center; gap:4px; color:var(--ink3); font-size:10.5px; font-weight:700; cursor:pointer; }
  #home-v2 .h-tab.on, body.ui-v2 #setup-screen .h-tab.on { color:var(--rust); }
  #home-v2 .h-tab svg, body.ui-v2 #setup-screen .h-tab svg { display:block; }
  #home-v2 .h-tabav, body.ui-v2 #setup-screen .h-tabav { width:22px; height:22px; border-radius:50%; background:var(--plum); color:#fff; display:grid; place-items:center; font-weight:800; font-size:10px; font-family:var(--disp); background-size:cover; background-position:center; }
  /* the Quick Share screen body-scrolls; pad the bottom so content clears the fixed bar */
  body.ui-v2 #setup-screen { padding-bottom:calc(76px + env(safe-area-inset-bottom)); }
}

/* ===== MOBILE "You" hub (warm3-you-mobile.html), scoped under #you-v2 — the dedicated
   mobile settings tab. A fixed overlay shown ONLY on mobile (home-v2.js showYouHub sets
   display:flex; default display:none keeps it off desktop). z 205 < settings-v2's 212, so
   opening a row's panel covers the hub and closing it reveals the hub again. ===== */
#you-v2 { display:none; position:fixed; inset:0; z-index:205; flex-direction:column;
  background:var(--paper); font-family:var(--f); color:var(--ink); }
#you-v2 .you-top { height:calc(52px + env(safe-area-inset-top,0px)); padding-top:env(safe-area-inset-top,0px); flex:none; display:grid; place-items:center; border-bottom:1px solid var(--div); }
#you-v2 .you-top .t { font-family:var(--disp); font-weight:800; font-size:17px; color:var(--ink); }
#you-v2 .you-scroll { flex:1; min-height:0; overflow-y:auto; padding:16px 14px 14px; scrollbar-width:none; }
#you-v2 .you-scroll::-webkit-scrollbar { display:none; }
#you-v2 .you-hd { display:flex; align-items:center; gap:13px; background:var(--card); border:1px solid var(--line); border-radius:8px; padding:14px; margin-bottom:18px; cursor:pointer; }
#you-v2 .you-hd .av { width:54px; height:54px; border-radius:50%; background:var(--plum); color:#fff; display:grid; place-items:center; font-weight:800; font-size:21px; font-family:var(--disp); flex:none; background-size:cover; background-position:center; }
#you-v2 .you-hd .who { min-width:0; }
#you-v2 .you-hd .nm { font-family:var(--disp); font-weight:800; font-size:17px; color:var(--ink); display:flex; align-items:center; gap:8px; }
#you-v2 .you-hd .bdg { font-size:9.5px; font-weight:800; text-transform:uppercase; letter-spacing:.04em; color:#3a2410; background:var(--honey); padding:2px 6px; border-radius:6px; }
#you-v2 .you-hd .un { font-size:12.5px; color:var(--ink3); font-weight:600; margin-top:3px; }
#you-v2 .you-hd .go { margin-left:auto; color:var(--ink3); flex:none; }
#you-v2 .you-glab { font-size:11px; text-transform:uppercase; letter-spacing:.08em; color:var(--ink3); font-weight:800; padding:0 6px 8px; }
#you-v2 .you-card { background:var(--card); border:1px solid var(--line); border-radius:10px; overflow:hidden; margin-bottom:18px; }
#you-v2 .you-row { display:flex; align-items:center; gap:13px; padding:13px 14px; cursor:pointer; border-top:1px solid var(--line2); }
#you-v2 .you-row:first-child { border-top:none; }
#you-v2 .you-row .ic { color:var(--ink3); flex:none; display:grid; place-items:center; width:20px; }
#you-v2 .you-row .lb { flex:1; font-weight:700; font-size:14.5px; color:var(--ink); }
#you-v2 .you-row .vl { font-size:12.5px; color:var(--ink3); font-weight:700; }
#you-v2 .you-row .ch { color:var(--ink3); flex:none; display:flex; }
#you-v2 .you-row.danger .lb { color:var(--clay); }
#you-v2 .you-row.danger .ic { color:var(--clay); }
/* the hub's bottom tabs (a flex child, not fixed — the hub is its own flex column) */
#you-v2 .h-tabs { flex:none; display:flex; border-top:1px solid var(--div); background:var(--paper); padding:8px 6px calc(4px + env(safe-area-inset-bottom)); }
#you-v2 .h-tab { flex:1; display:flex; flex-direction:column; align-items:center; gap:4px; color:var(--ink3); font-size:10.5px; font-weight:700; cursor:pointer; }
#you-v2 .h-tab.on { color:var(--rust); }
#you-v2 .h-tab svg { display:block; }
#you-v2 .h-tabav { width:22px; height:22px; border-radius:50%; background:var(--plum); color:#fff; display:grid; place-items:center; font-weight:800; font-size:10px; font-family:var(--disp); background-size:cover; background-position:center; }

/* ===== "Friends" — designed fresh in the locked language (tokens.html), modeled on the
   You hub. MOBILE = a fixed full-screen overlay (#friends-v2). DESKTOP = its own nav tab,
   rendered as a centered page inside the warm home (#home-v2 .fr-page). The CARD/ROW
   content rules below are shared by both; the overlay + mobile-only rules stay #friends-v2. */
#friends-v2 { display:none; position:fixed; inset:0; z-index:205; flex-direction:column;
  background:var(--paper); font-family:var(--f); color:var(--ink); }
#friends-v2 .fr-top { height:calc(52px + env(safe-area-inset-top,0px)); padding-top:env(safe-area-inset-top,0px); flex:none; display:grid; place-items:center; border-bottom:1px solid var(--div); }
#friends-v2 .fr-top .t { font-family:var(--disp); font-weight:800; font-size:17px; color:var(--ink); }
#friends-v2 .fr-scroll { flex:1; min-height:0; overflow-y:auto; padding:16px 14px 14px; scrollbar-width:none; }
#friends-v2 .fr-scroll::-webkit-scrollbar { display:none; }
/* desktop tab page */
#home-v2 .fr-page { max-width:680px; margin:0 auto; padding:6px 0 40px; }
#home-v2 .fr-h1 { font-family:var(--disp); font-weight:800; font-size:28px; letter-spacing:-.025em; color:var(--ink); margin:16px 2px 20px; }
/* shared content (mobile overlay + desktop page) */
#friends-v2 .fr-add, #home-v2 .fr-add { display:flex; gap:9px; margin-bottom:18px; }
#friends-v2 .fr-input, #home-v2 .fr-input { flex:1; min-width:0; border:1px solid var(--line); background:var(--card); color:var(--ink); font-family:var(--f); font-size:14px; padding:11px 13px; border-radius:9px; outline:none; }
#friends-v2 .fr-input:focus, #home-v2 .fr-input:focus { border-color:var(--honey); box-shadow:0 0 0 3px rgba(var(--st-act-rgb),.18); }
#friends-v2 .fr-addbtn, #home-v2 .fr-addbtn { border:none; background:var(--honey); color:#3a2410; font-family:var(--f); font-weight:800; font-size:14px; padding:0 18px; border-radius:9px; cursor:pointer; flex:none; }
#friends-v2 .fr-glab, #home-v2 .fr-glab { font-size:11px; text-transform:uppercase; letter-spacing:.08em; color:var(--ink3); font-weight:800; padding:0 6px 8px; display:flex; align-items:center; gap:8px; }
#friends-v2 .fr-ct, #home-v2 .fr-ct { font-size:11px; color:var(--ink3); font-weight:700; background:var(--s3,#e3ded3); padding:2px 8px; border-radius:999px; }
#friends-v2 .fr-card, #home-v2 .fr-card { background:var(--card); border:1px solid var(--line); border-radius:10px; overflow:hidden; margin-bottom:18px; }
#friends-v2 .fr-row, #home-v2 .fr-row { display:flex; align-items:center; gap:12px; padding:11px 13px; border-top:1px solid var(--line2); }
#friends-v2 .fr-row:first-child, #home-v2 .fr-row:first-child { border-top:none; }
#friends-v2 .fr-id, #home-v2 .fr-id { display:flex; align-items:center; gap:11px; flex:1; min-width:0; cursor:pointer; }
#friends-v2 .fr-av, #home-v2 .fr-av { width:38px; height:38px; border-radius:50%; flex:none; display:grid; place-items:center; color:#fff; font-weight:700; font-size:14px; font-family:var(--disp); background-size:cover; background-position:center; }
#friends-v2 .fr-name, #home-v2 .fr-name { font-weight:700; font-size:14.5px; color:var(--ink); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
#friends-v2 .fr-act, #home-v2 .fr-act { display:flex; gap:6px; flex:none; }
#friends-v2 .fr-btn, #home-v2 .fr-btn { border:none; font-family:var(--f); font-weight:700; font-size:12.5px; padding:7px 12px; border-radius:9px; cursor:pointer; }
#friends-v2 .fr-btn.ok, #home-v2 .fr-btn.ok { background:#e9edd6; color:#5a6a26; }
#friends-v2 .fr-btn.no, #home-v2 .fr-btn.no { background:#f3e2da; color:var(--rust); }
#friends-v2 .fr-btn.ghost, #home-v2 .fr-btn.ghost { background:var(--card2); color:var(--ink2); }
#home-v2 .fr-row:hover .fr-btn.ghost { background:var(--s3,#e3ded3); }
#friends-v2 .fr-pending, #home-v2 .fr-pending { font-size:12px; color:var(--ink3); font-weight:700; flex:none; }
#friends-v2 .fr-empty, #home-v2 .fr-empty { color:var(--ink2); font-size:13.5px; padding:16px 6px 6px; }
#friends-v2 .h-tabs { flex:none; display:flex; border-top:1px solid var(--div); background:var(--paper); padding:8px 6px calc(4px + env(safe-area-inset-bottom)); }
#friends-v2 .h-tab { flex:1; display:flex; flex-direction:column; align-items:center; gap:4px; color:var(--ink3); font-size:10.5px; font-weight:700; cursor:pointer; }
#friends-v2 .h-tab.on { color:var(--rust); }
#friends-v2 .h-tab svg { display:block; }
#friends-v2 .h-tabav { width:22px; height:22px; border-radius:50%; background:var(--plum); color:#fff; display:grid; place-items:center; font-weight:800; font-size:10px; font-family:var(--disp); background-size:cover; background-position:center; }

/* ---- header: ported VERBATIM from warm3.css `header`/.brand/nav/.chip/.iconbtn/.fdd,
   scoped under #hv-header. Non-sticky, 1100px-centered like the mock (header lives
   inside .wrap there). Replaces the classic #app-header under ui-v2. ---- */
#hv-header { display:none; }
body.ui-v2 #app-header { display:none; }
/* Logged out, the ui-v2 app bar's nav routes into account-only screens, so hide the
   whole bar until authed (.app-authed is toggled in boot.js from state.isLoggedIn). The
   auth and landing screens carry their own branding. The :not() bumps specificity above
   the display:flex rule below, so source order does not matter. */
body.ui-v2:not(.app-authed) #hv-header { display:none; }
/* NOTE: classic CSS has a bare `header { height:58px; background:...; backdrop-filter:...;
   justify-content:center; position:sticky }` rule that leaks into #hv-header (a <header>).
   We must override ALL of it: height:auto (else the 39px chip is clamped into 58px),
   transparent bg (mock header sits on the paper), justify-content:flex-start, non-sticky. */
body.ui-v2 #hv-header { display:flex; align-items:center; justify-content:flex-start; gap:18px; max-width:1100px; margin:0 auto; padding:18px 30px 16px; height:auto; background:transparent; backdrop-filter:none; -webkit-backdrop-filter:none; border-bottom:none; position:relative; font-family:var(--f); }
/* divider inset to the 30px gutter so it spans the CONTENT width (1040), like the mock
   header nested inside .wrap — not the full padded box. */
body.ui-v2 #hv-header::after { content:""; position:absolute; left:30px; right:30px; bottom:0; height:1px; background:var(--div); }
#hv-header .brand { display:flex; align-items:center; gap:10px; font-family:var(--disp); font-weight:800; font-size:21px; letter-spacing:-.02em; color:var(--ink); text-decoration:none; cursor:pointer; }
#hv-header .brand svg { display:block; }
#hv-header nav { display:flex; gap:2px; margin-left:6px; }
#hv-header nav a { font-size:14.5px; color:var(--ink2); text-decoration:none; padding:8px 13px; border-radius:10px; font-weight:600; cursor:pointer; }
#hv-header nav a.on { color:var(--ink); background:var(--s3,#e3ded3); }
#hv-header nav a:not(.on):hover { color:var(--ink); background:var(--s3,#e3ded3); }
#hv-header .spacer { flex:1; }
#hv-header .chip { display:inline-flex; align-items:center; gap:7px; border:1px solid var(--line); background:var(--card); padding:8px 13px; border-radius:999px; font-size:13.5px; font-weight:700; cursor:pointer; color:var(--ink); }
#hv-header .chip .coin { color:var(--honey); }
#hv-header .iconbtn { position:relative; width:38px; height:38px; border-radius:8px; border:1px solid var(--line); background:var(--card); display:grid; place-items:center; cursor:pointer; color:var(--ink2); }
#hv-header .iconbtn:hover { color:var(--ink); border-color:var(--text3,#9a9389); }
#hv-header .iconbtn .nbadge { position:absolute; top:-3px; right:-3px; min-width:9px; height:9px; border-radius:50%; background:var(--clay); border:2px solid var(--paper); }
/* mobile-only account avatar (mock .h-av) — hidden on desktop; shown in the mobile app-bar block below */
#hv-header .hv-av { display:none; width:37px; height:37px; border-radius:50%; border:none; cursor:pointer;
  background:var(--plum); color:#fff; place-items:center; font-family:var(--disp); font-weight:800; font-size:13.5px;
  background-size:cover; background-position:center; flex:none; }
/* friends dropdown */
#hv-header .fdd { position:relative; }
#hv-header .fdd .trig { display:inline-flex; align-items:center; gap:9px; border:1px solid var(--line); background:var(--card); padding:5px 11px 5px 7px; border-radius:999px; cursor:pointer; font-weight:700; font-size:13px; color:var(--ink); }
#hv-header .fdd .av { display:flex; }
#hv-header .fdd .av span { width:26px; height:26px; border-radius:50%; border:2px solid var(--card); margin-left:-9px; display:grid; place-items:center; color:#fff; font-weight:700; font-size:11px; background-size:cover; background-position:center; }
#hv-header .fdd .av span:first-child { margin-left:0; }
#hv-header .fdd .cnt b { color:var(--olive); }
#hv-header .fdd .panel { position:absolute; top:46px; right:0; width:280px; max-width:84vw; background:var(--card); border:1px solid var(--line); border-radius:10px; box-shadow:0 24px 50px -22px rgba(70,45,15,.55); padding:8px; z-index:20; display:none; }
#hv-header .fdd .panel.open { display:block; }
#hv-header .fdd .panel h5 { font-size:11.5px; text-transform:uppercase; letter-spacing:.08em; color:var(--ink3); font-weight:700; padding:8px 10px 6px; }
#hv-header .fr { display:flex; align-items:center; gap:11px; padding:8px 10px; border-radius:8px; cursor:pointer; }
#hv-header .fr:hover { background:var(--card2); }
#hv-header .fr .fa { width:33px; height:33px; border-radius:50%; display:grid; place-items:center; color:#fff; font-weight:700; font-size:12.5px; flex:none; position:relative; background-size:cover; background-position:center; }
#hv-header .fr .fa::after { content:""; position:absolute; right:-1px; bottom:-1px; width:10px; height:10px; border-radius:50%; border:2.5px solid var(--card); background:var(--ink3); }
#hv-header .fr.on .fa::after { background:var(--olive); }
#hv-header .fr.lv .fa::after { background:var(--clay); }
#hv-header .fr .fn { font-weight:700; font-size:14px; }
#hv-header .fr .fs { font-size:12px; color:var(--ink2); }
#hv-header .fr .pres { margin-left:auto; font-size:11.5px; font-weight:700; color:var(--olive); }
#hv-header .fr .pres.lv { color:var(--clay); }
#hv-header .fr-act { display:flex; gap:5px; margin-left:auto; flex:none; }
#hv-header .fr-act .mini { border:none; font-family:var(--f); font-weight:700; font-size:12px; padding:5px 9px; border-radius:8px; cursor:pointer; }
#hv-header .fr-act .mini.ok { background:#e9edd6; color:#5a6a26; }
#hv-header .fr-act .mini.no { background:#f3e2da; color:var(--rust); }
/* add-friend input row (mock showed only a button; the app keeps an inline add) */
#hv-header .addrow { display:flex; gap:8px; margin-top:6px; padding:0 2px 2px; }
#hv-header .addrow input { flex:1; min-width:0; border:1px solid var(--line); background:var(--card2); border-radius:10px; padding:9px 11px; font-family:var(--f); font-size:13px; color:var(--ink); }
#hv-header .addrow .addbtn { border:none; background:var(--card2); color:var(--ink); font-family:var(--f); font-weight:700; font-size:13px; padding:9px 13px; border-radius:10px; cursor:pointer; }
#hv-header .panel-empty { font-size:13px; color:var(--ink2); padding:10px; }
@media (max-width:600px){ body.ui-v2 #hv-header { padding:14px 16px; gap:10px; } body.ui-v2 #hv-header::after { left:16px; right:16px; } #hv-header nav { display:none; } }

/* MOBILE-HOME app bar: restyle the global #hv-header into the mock .h-bar. Placed
   AFTER the desktop #hv-header rules above so these win on source order (and the
   body.ui-v2 prefix keeps specificity >= the desktop rules). Same breakpoint as the
   feed/tabs block earlier. */
@media (max-width:700px), (pointer:coarse) and (max-width:950px){
  body.ui-v2 #hv-header { position:sticky; top:0; z-index:40; max-width:none; margin:0;
    height:calc(54px + env(safe-area-inset-top,0px)); padding:env(safe-area-inset-top,0px) 15px 0; gap:9px; background:var(--paper); border-bottom:1px solid var(--div); }
  body.ui-v2 #hv-header::after { display:none; }              /* sticky border-bottom replaces the inset divider */
  body.ui-v2 #hv-header nav { display:none; }                 /* Home/Quick Share -> bottom tabs */
  body.ui-v2 #hv-header .fdd .trig { display:none; }          /* friends -> bottom tab + feed card */
  body.ui-v2 #hv-header .iconbtn[title="Settings"] { display:none; }   /* settings -> the You tab */
  body.ui-v2 #hv-header .brand { font-size:18.5px; }
  body.ui-v2 #hv-header .chip { padding:7px 11px; font-size:12.5px; }
  body.ui-v2 #hv-header .iconbtn { width:37px; height:37px; }
  body.ui-v2 #hv-header .hv-av { display:grid; }   /* mock app bar shows the account avatar (top-right) */
  /* friends dropdown -> a bottom sheet above the tab bar */
  body.ui-v2 #hv-header .fdd .panel { position:fixed; top:auto; left:12px; right:12px; bottom:74px;
    width:auto; max-width:none; max-height:60vh; overflow-y:auto; z-index:45; }
}

/* ===== ui-v2 Store (#store-v2) — ported from warm3-store.html / store.css ===== */
#store-v2 { position:fixed; inset:0; z-index:215; background:var(--bg); overflow-y:auto; flex-direction:column; font-family:'DM Sans',sans-serif; color:var(--text); }
#store-v2 .sv2-top { height:calc(56px + env(safe-area-inset-top,0px)); flex:none; display:flex; align-items:center; gap:13px; padding:0 18px; padding-top:env(safe-area-inset-top,0px); border-bottom:1px solid var(--border); position:sticky; top:0; background:color-mix(in srgb, var(--bg) 92%, transparent); backdrop-filter:blur(12px); z-index:2; }
#store-v2 .sv2-back { display:inline-flex; align-items:center; gap:6px; color:var(--text2); font-weight:700; font-size:13.5px; cursor:pointer; padding:7px 10px; border-radius:9px; }
#store-v2 .sv2-back:hover { background:var(--s2); color:var(--text); }
#store-v2 .sv2-ttl { font-family:'Hanken Grotesk','DM Sans',sans-serif; font-weight:800; font-size:16px; }
#store-v2 .sv2-wrap { max-width:1060px; width:100%; margin:0 auto; padding:8px 30px 50px; }
#store-v2 .sv2-tabs { display:flex; gap:4px; margin:18px 2px 0; }
#store-v2 .sv2-tabs a { font-size:14.5px; color:var(--text2); font-weight:700; padding:9px 16px; border-radius:8px; cursor:pointer; }
#store-v2 .sv2-tabs a.on { background:var(--s3,#e3ded3); color:var(--text); }
#store-v2 .store-head { margin:24px 2px 6px; display:flex; align-items:flex-end; justify-content:space-between; gap:22px; flex-wrap:wrap; }
#store-v2 .store-head h1 { font-family:'Hanken Grotesk','DM Sans',sans-serif; font-weight:800; font-size:30px; letter-spacing:-.025em; line-height:1.04; }
#store-v2 .store-head .sub { margin-top:9px; font-size:14.5px; color:var(--text2); max-width:540px; line-height:1.5; }
#store-v2 .bill-seg { display:flex; background:var(--s3,#e3ded3); border-radius:9px; padding:4px; }
#store-v2 .bill-seg button { border:none; background:transparent; font-family:inherit; font-weight:800; font-size:13.5px; color:var(--text2); padding:9px 15px; border-radius:9px; cursor:pointer; display:flex; align-items:center; gap:9px; }
#store-v2 .bill-seg button.on { background:var(--surface); color:var(--text); box-shadow:0 1px 3px rgba(80,50,15,.18); }
#store-v2 .bill-seg .save { font-size:11px; font-weight:800; color:#7f8b3c; background:#e9edd6; padding:2px 8px; border-radius:99px; }
#store-v2 .tiers { display:grid; grid-template-columns:1fr 1fr 1fr; gap:18px; margin-top:30px; align-items:start; }
#store-v2 .tier { position:relative; background:var(--surface); border:1px solid var(--border); border-radius:9px; padding:22px 21px; box-shadow:0 14px 30px -24px rgba(80,50,15,.5); }
#store-v2 .tier.pop { border:2px solid var(--accent); box-shadow:0 24px 46px -22px rgba(189,106,57,.42); transform:translateY(-10px); }
#store-v2 .tier .badge { position:absolute; top:-12px; left:22px; background:var(--accent); color:var(--accent-fg,#fff); font-size:11px; font-weight:800; letter-spacing:.04em; text-transform:uppercase; padding:5px 12px; border-radius:99px; }
#store-v2 .tier .tname { font-family:'Hanken Grotesk','DM Sans',sans-serif; font-weight:800; font-size:18px; }
#store-v2 .tier .for { font-size:12px; color:var(--text3); font-weight:700; margin-top:3px; }
#store-v2 .tier .price { display:flex; align-items:baseline; gap:5px; margin:15px 0 2px; }
#store-v2 .tier .price b { font-family:'Hanken Grotesk','DM Sans',sans-serif; font-weight:800; font-size:34px; letter-spacing:-.02em; }
#store-v2 .tier .price .per { font-size:13px; color:var(--text2); font-weight:700; }
#store-v2 .tier .yr { font-size:12px; color:var(--text3); font-weight:600; min-height:15px; }
#store-v2 .tier ul { list-style:none; margin:17px 0 19px; display:flex; flex-direction:column; gap:11px; }
#store-v2 .tier li { display:flex; gap:9px; font-size:13px; line-height:1.4; }
#store-v2 .tier li svg { color:#7f8b3c; flex:none; margin-top:1px; }
#store-v2 .tier.soon { background:var(--s1); border-style:dashed; }
#store-v2 .tier.soon .price b { font-size:23px; color:var(--text2); }
#store-v2 .tier.soon li svg { color:var(--text3); }
#store-v2 .sv2-btn { border:none; font-family:inherit; font-weight:800; font-size:14.5px; padding:12px 22px; border-radius:9px; cursor:pointer; }
#store-v2 .sv2-btn.primary { background:var(--accent); color:var(--accent-fg,#fff); }
#store-v2 .sv2-btn.primary:hover { filter:brightness(1.06); }
#store-v2 .sv2-btn.soft { border:1px solid var(--border); background:var(--surface); color:var(--text); font-weight:700; }
#store-v2 .sv2-btn.soft:hover { border-color:var(--accent); }
#store-v2 .sv2-btn.cta { width:100%; text-align:center; }
#store-v2 .sv2-btn[disabled] { opacity:.55; cursor:default; }
#store-v2 .store-foot { margin-top:24px; text-align:center; font-size:13px; color:var(--text2); }
#store-v2 .store-foot a { color:var(--accent); font-weight:700; cursor:pointer; }
#store-v2 .cr-bal { display:flex; align-items:center; gap:14px; background:linear-gradient(135deg,#2f2415,#3a2c18); color:#f6ecd8; border:1px solid #43331c; border-radius:8px; padding:18px 22px; margin-top:26px; }
#store-v2 .cr-bal .ci { width:46px; height:46px; border-radius:9px; background:rgba(var(--st-rgb),.16); display:grid; place-items:center; color:#f6c163; flex:none; }
#store-v2 .cr-bal .cn b { font-family:'Hanken Grotesk','DM Sans',sans-serif; font-weight:800; font-size:24px; display:block; line-height:1; }
#store-v2 .cr-bal .cn span { font-size:12.5px; color:#c3b193; font-weight:600; }
#store-v2 .cr-bal .gift { margin-left:auto; border:1px solid rgba(var(--st-rgb),.25); background:rgba(255,255,255,.04); color:#f0c46a; font-family:inherit; font-weight:700; font-size:13px; padding:10px 15px; border-radius:8px; cursor:pointer; }
#store-v2 .packs { display:grid; grid-template-columns:1fr 1fr 1fr; gap:16px; margin-top:18px; align-items:stretch; }
#store-v2 .pack { position:relative; background:var(--surface); border:1px solid var(--border); border-radius:8px; padding:20px; text-align:center; box-shadow:0 14px 30px -24px rgba(80,50,15,.5); }
#store-v2 .pack.best { border:2px solid var(--accent); box-shadow:0 22px 44px -22px rgba(189,106,57,.42); }
#store-v2 .pack .bdg { position:absolute; top:-11px; left:50%; transform:translateX(-50%); background:var(--accent); color:var(--accent-fg,#fff); font-size:10.5px; font-weight:800; text-transform:uppercase; letter-spacing:.04em; padding:4px 11px; border-radius:99px; }
#store-v2 .pack .amt { font-family:'Hanken Grotesk','DM Sans',sans-serif; font-weight:800; font-size:26px; }
#store-v2 .pack .amt small { font-size:13px; color:var(--text2); font-weight:700; }
#store-v2 .pack .cost { font-size:13.5px; color:var(--text2); font-weight:700; margin-top:9px; }
#store-v2 .cr-note { margin-top:14px; font-size:12.5px; color:var(--text3); text-align:center; }
#store-v2 .spend { margin-top:14px; display:grid; grid-template-columns:1fr 1fr; gap:14px; }
#store-v2 .spend .si { background:var(--surface); border:1px solid var(--border); border-radius:10px; padding:16px; display:flex; align-items:center; gap:13px; }
#store-v2 .spend .si .ig { width:42px; height:42px; border-radius:9px; display:grid; place-items:center; color:#fff; flex:none; }
#store-v2 .spend .si h4 { font-weight:800; font-size:14px; }
#store-v2 .spend .si p { font-size:12px; color:var(--text2); margin-top:2px; }
#store-v2 .spend .si .pc { margin-left:auto; font-weight:800; color:var(--accent); font-size:13.5px; white-space:nowrap; }
#store-v2 .earn { margin-top:22px; border-top:1px solid var(--border); padding-top:18px; display:flex; align-items:center; gap:13px; }
#store-v2 .earn .ei { width:40px; height:40px; border-radius:8px; background:var(--s1); display:grid; place-items:center; color:var(--text2); flex:none; }
#store-v2 .earn .et { font-size:13px; color:var(--text2); }
#store-v2 .earn .et b { color:var(--text); font-weight:800; }
#store-v2 .earn .eb { margin-left:auto; border:1px solid var(--border); background:var(--surface); color:var(--text); font-family:inherit; font-weight:700; font-size:13px; padding:9px 14px; border-radius:8px; cursor:pointer; }
@media (max-width:780px){ #store-v2 .tiers, #store-v2 .packs, #store-v2 .spend { grid-template-columns:1fr; } #store-v2 .tier.pop { transform:none; } #store-v2 .sv2-wrap { padding:8px 16px 40px; } }

/* ===== ui-v2 Settings (#settings-v2-screen) — ported from warm3-settings.html ===== */
#settings-v2-screen { position:fixed; inset:0; z-index:212; background:var(--bg); color:var(--text); flex-direction:column; font-family:'DM Sans',sans-serif; }
#settings-v2-screen .sv2s-top { height:56px; flex:none; display:flex; align-items:center; gap:13px; padding:0 18px; border-bottom:1px solid var(--border); }
#settings-v2-screen .sv2s-back { display:inline-flex; align-items:center; gap:6px; color:var(--text2); font-weight:700; font-size:13.5px; cursor:pointer; padding:7px 10px; border-radius:9px; }
#settings-v2-screen .sv2s-back:hover { background:var(--s2); color:var(--text); }
#settings-v2-screen .sv2s-ttl { font-family:'Hanken Grotesk','DM Sans',sans-serif; font-weight:800; font-size:18px; }
#settings-v2-screen .sv2s-body { flex:1; display:flex; min-height:0; }
#settings-v2-screen .sv2s-side { width:248px; flex:none; border-right:1px solid var(--border); overflow-y:auto; padding:14px 12px; }
#settings-v2-screen .sv2s-me { display:flex; align-items:center; gap:11px; padding:11px; background:var(--surface); border:1px solid var(--border); border-radius:10px; margin-bottom:14px; }
#settings-v2-screen .sv2s-me .nm { font-weight:800; font-size:14.5px; display:flex; align-items:center; gap:7px; }
#settings-v2-screen .sv2s-me .bdg { font-size:9.5px; font-weight:800; text-transform:uppercase; letter-spacing:.04em; color:var(--accent-fg,#fff); background:var(--accent); padding:2px 6px; border-radius:6px; }
#settings-v2-screen .sv2s-me .un { font-size:12px; color:var(--text3); font-weight:600; margin-top:2px; }
#settings-v2-screen .sv2s-me .user-avatar, #settings-v2-screen .sv2s-me img, #settings-v2-screen .sv2s-me .av-wrap { width:42px !important; height:42px !important; border-radius:50%; flex:none; font-size:17px; }
#settings-v2-screen .sv2s-grp { font-size:11px; text-transform:uppercase; letter-spacing:.08em; color:var(--text3); font-weight:800; padding:14px 10px 6px; }
#settings-v2-screen .sv2s-grp:first-of-type { padding-top:4px; }
#settings-v2-screen .sv2s-item { display:flex; align-items:center; gap:11px; padding:9px 11px; border-radius:10px; cursor:pointer; color:var(--text2); font-weight:700; font-size:14px; }
#settings-v2-screen .sv2s-item:hover { background:var(--s2); color:var(--text); }
#settings-v2-screen .sv2s-item.on { background:color-mix(in srgb, var(--accent) 16%, var(--surface)); color:var(--text); }
#settings-v2-screen .sv2s-item svg { color:var(--text3); flex:none; }
#settings-v2-screen .sv2s-item.on svg { color:var(--accent); }
#settings-v2-screen .sv2s-content { flex:1; overflow-y:auto; padding:30px 40px 60px; }
#settings-v2-screen .sv2s-panel { display:none; max-width:680px; }
#settings-v2-screen .sv2s-panel.on { display:block; }
#settings-v2-screen .sv2s-panel h2 { font-family:'Hanken Grotesk','DM Sans',sans-serif; font-weight:800; font-size:25px; margin-bottom:16px; letter-spacing:-.02em; }
#settings-v2-screen .sv2s-rows .settings-row { display:flex; gap:18px; padding:18px 0; border-top:1px solid var(--s3); align-items:flex-start; }
#settings-v2-screen .sv2s-rows > .settings-row:first-child { border-top:none; }
#settings-v2-screen .sv2s-rows .settings-label { width:150px; flex:none; font-weight:800; font-size:14px; color:var(--text); }
#settings-v2-screen .sv2s-rows .settings-page-card { background:transparent; border:none; padding:0; box-shadow:none; }
/* --- skin the relocated classic controls to match the mock's warm forms --- */
#settings-v2-screen .sv2s-rows .settings-label { width:160px; font-size:13px; }
#settings-v2-screen .sv2s-rows .sub { color:var(--text2); font-size:12px; line-height:1.5; }
#settings-v2-screen .sv2s-rows input[type=text],
#settings-v2-screen .sv2s-rows textarea,
#settings-v2-screen .sv2s-rows select {
  border:1px solid var(--border) !important; background:var(--surface) !important; color:var(--text) !important;
  border-radius:10px !important; padding:10px 12px !important; font-family:'DM Sans',sans-serif !important; font-size:13.5px !important;
}
#settings-v2-screen .sv2s-rows input[type=text]:focus,
#settings-v2-screen .sv2s-rows textarea:focus,
#settings-v2-screen .sv2s-rows select:focus { outline:none; border-color:var(--accent) !important; }
/* buttons -> soft warm buttons (override their inline styles) */
#settings-v2-screen .sv2s-rows button {
  border:1px solid var(--border) !important; background:var(--surface) !important; color:var(--text) !important;
  border-radius:10px !important; padding:9px 15px !important; font-weight:700 !important; font-size:13px !important;
  font-family:'DM Sans',sans-serif !important; cursor:pointer;
}
#settings-v2-screen .sv2s-rows button:hover { border-color:var(--accent) !important; color:var(--accent) !important; }
/* the red Delete Account button stays a danger button */
#settings-v2-screen .sv2s-rows button[onclick*="deleteAccount"] { border-color:#d98b6e !important; color:var(--clay,#c75f3e) !important; background:transparent !important; }
/* checkboxes -> warm toggle switches */
#settings-v2-screen .sv2s-rows input[type=checkbox] {
  appearance:none; -webkit-appearance:none; width:42px; height:24px; border-radius:99px; background:var(--border,#ddd7cc);
  position:relative; cursor:pointer; flex:none; border:none !important; transition:background .15s; margin-top:2px;
}
#settings-v2-screen .sv2s-rows input[type=checkbox]:checked { background:#7f8b3c; }
#settings-v2-screen .sv2s-rows input[type=checkbox]::after { content:""; position:absolute; top:2px; left:2px; width:20px; height:20px; border-radius:50%; background:#fff; transition:left .15s; box-shadow:0 1px 2px rgba(0,0,0,.25); }
#settings-v2-screen .sv2s-rows input[type=checkbox]:checked::after { left:20px; }
/* theme radios -> warm pills */
#settings-v2-screen .sv2s-rows .theme-option { border:1px solid var(--border) !important; background:var(--surface) !important; border-radius:10px; padding:9px 14px; }
#settings-v2-screen .sv2s-rows .theme-option input[type=radio] { width:auto; }
#settings-v2-screen .sv2s-rows .settings-options { display:flex; gap:8px; }
/* avatar/banner previews + mute-key chip: warm rounding */
#settings-v2-screen .sv2s-rows #settings-avatar-preview { background:var(--s2) !important; }
#settings-v2-screen .sv2s-rows .mute-key-display { border:1px solid var(--border); background:var(--surface); border-radius:8px; padding:7px 13px; font-weight:800; cursor:pointer; }
/* pin-usage bar warm */
#settings-v2-screen .sv2s-rows #pin-usage-bar { background:var(--accent) !important; }
/* --- Profile banner-hero (reuses the real avatar/banner/bio elements) --- */
/* banner-hero values copied verbatim from the mock (.prof-banner in settings.css):
   gradient is literal honey->rust hex, NOT var(--accent) (which is clay in ui-v2 and
   collapsed the gradient into a flat band). */
#settings-v2-screen .sv2p-hero { position:relative; margin:6px 0 44px; }
#settings-v2-screen .sv2p-banner { position:relative; height:118px; border-radius:8px; overflow:hidden; background:linear-gradient(120deg,#c98a2e,#bd6a39); }
#settings-v2-screen .sv2p-banner #settings-banner-preview { width:100% !important; height:100% !important; border:none !important; border-radius:0 !important; background-color:transparent !important; background-size:cover !important; background-position:center !important; cursor:pointer; }
#settings-v2-screen .sv2p-bhint { position:absolute; top:11px; right:11px; background:rgba(var(--st-ink-rgb),.55); -webkit-backdrop-filter:blur(5px); backdrop-filter:blur(5px); color:#fff; font-size:12px; font-weight:700; padding:8px 12px; border-radius:10px; pointer-events:none; }
#settings-v2-screen .sv2p-av { position:absolute; left:22px; bottom:-30px; width:84px; height:84px; }
#settings-v2-screen .sv2p-av #settings-avatar-preview { width:84px !important; height:84px !important; font-size:30px !important; border-radius:50% !important; border:4px solid var(--bg) !important; box-sizing:border-box; cursor:pointer; }
#settings-v2-screen .sv2p-cam { position:absolute; right:-2px; bottom:-2px; width:28px; height:28px; border-radius:50%; background:var(--surface); border:2px solid var(--bg); display:grid; place-items:center; color:var(--text2); pointer-events:none; }
#settings-v2-screen .sv2p-bioblock { max-width:480px; }
#settings-v2-screen .sv2p-flabel { display:block; font-weight:800; font-size:13px; color:var(--text); margin-bottom:8px; }
#settings-v2-screen .sv2p-bioblock #settings-bio-input { width:100% !important; }
#settings-v2-screen .sv2p-save { margin-top:8px !important; }
@media (max-width:820px){ #settings-v2-screen .sv2s-body { flex-direction:column; } #settings-v2-screen .sv2s-side { width:auto; border-right:none; border-bottom:1px solid var(--border); display:flex; overflow-x:auto; gap:6px; padding:10px; } #settings-v2-screen .sv2s-me { display:none; } #settings-v2-screen .sv2s-item { white-space:nowrap; } #settings-v2-screen .sv2s-content { padding:20px; } #settings-v2-screen .sv2s-rows .settings-row { flex-direction:column; gap:8px; } #settings-v2-screen .sv2s-rows .settings-label { width:auto; } }

/* ============================================================
   ui-v2 Settings v2 — FULL rebuild, ported VERBATIM from settings.css /
   warm3-settings.html (mock classes), scoped under #settings-v2-screen .set-app.
   Renders all 13 sections; wired controls bridge to the existing handlers.
   (The #settings-v2-screen .sv2s- and .sv2p- rules above are now UNUSED; the old
   relocate-the-controls approach was dropped. Clean them up later. NOTE: never
   put an asterisk followed by a slash inside a comment, even when naming a
   wildcard like ".sv2s-STAR/": it terminates the comment early and the parser
   eats the NEXT rule as garbage; that silently killed .set-app for weeks.)
   ============================================================ */
#settings-v2-screen .set-app { position:absolute; inset:0; display:flex; flex-direction:column; background:var(--paper); font-family:var(--f); color:var(--ink); }
#settings-v2-screen .set-top { height:calc(58px + env(safe-area-inset-top,0px)); flex:none; display:flex; align-items:center; gap:13px; padding:0 20px; padding-top:env(safe-area-inset-top,0px); border-bottom:1px solid var(--div); }
#settings-v2-screen .set-top .bk { width:36px; height:36px; border-radius:10px; display:grid; place-items:center; color:var(--ink2); cursor:pointer; }
#settings-v2-screen .set-top .bk:hover { background:var(--s3,#e3ded3); color:var(--ink); }
#settings-v2-screen .set-top .ttl { font-family:var(--disp); font-weight:800; font-size:18px; letter-spacing:-.01em; }
#settings-v2-screen .set-top .esc { margin-left:auto; font-size:12px; color:var(--ink3); font-weight:700; border:1px solid var(--line); border-radius:8px; padding:6px 10px; cursor:pointer; }
#settings-v2-screen .set-body { flex:1; display:flex; min-height:0; }
#settings-v2-screen .set-side { width:252px; flex:none; border-right:1px solid var(--div); overflow-y:auto; padding:14px 12px 24px; scrollbar-width:thin; scrollbar-color:var(--rust) transparent; }
#settings-v2-screen .set-side::-webkit-scrollbar { width:8px; }
#settings-v2-screen .set-side::-webkit-scrollbar-thumb { background:linear-gradient(var(--honey),var(--rust)); border-radius:99px; border:2px solid transparent; background-clip:padding-box; }
#settings-v2-screen .set-me { display:flex; align-items:center; gap:11px; padding:11px; background:var(--card); border:1px solid var(--line); border-radius:10px; margin-bottom:14px; overflow:hidden; }
#settings-v2-screen .set-me .av { width:42px; height:42px; border-radius:50%; background:var(--plum); color:#fff; display:grid; place-items:center; font-weight:800; font-size:15px; font-family:var(--disp); flex:none; background-size:cover; background-position:center; }
#settings-v2-screen .set-me .set-me-id { min-width:0; flex:1; }
#settings-v2-screen .set-me .nm { font-weight:800; font-size:14.5px; color:var(--ink); display:flex; align-items:center; gap:7px; min-width:0; }
#settings-v2-screen .set-me .nm .nm-text { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; min-width:0; }
#settings-v2-screen .set-me .bdg { font-size:9.5px; font-weight:800; text-transform:uppercase; letter-spacing:.04em; color:#3a2410; background:var(--honey); padding:2px 6px; border-radius:6px; flex-shrink:0; }
#settings-v2-screen .set-me .un { font-size:12px; color:var(--ink3); font-weight:600; margin-top:2px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
#settings-v2-screen .set-grp { margin-bottom:14px; }
#settings-v2-screen .set-grp h6 { font-size:11px; text-transform:uppercase; letter-spacing:.08em; color:var(--ink3); font-weight:800; padding:0 10px 6px; }
/* the tagline, tucked at the very bottom of the sidebar (quiet on purpose) */
#settings-v2-screen .set-foot { color:var(--ink3); opacity:.6; font-size:10.5px; line-height:1.4; padding:14px 10px 2px; }
#settings-v2-screen .set-item { display:flex; align-items:center; gap:11px; padding:9px 11px; border-radius:10px; cursor:pointer; color:var(--ink2); font-weight:700; font-size:14px; }
#settings-v2-screen .set-item:hover { background:var(--s3,#e3ded3); color:var(--ink); }
#settings-v2-screen .set-item.on { background:var(--s3,#e3ded3); color:var(--ink); }
#settings-v2-screen .set-item svg { color:var(--ink3); flex:none; }
#settings-v2-screen .set-item.on svg { color:var(--rust); }
#settings-v2-screen .set-item.danger { color:var(--clay); }
#settings-v2-screen .set-item.danger svg { color:var(--clay); }
#settings-v2-screen .set-content { flex:1; overflow-y:auto; padding:32px 44px 60px; scrollbar-width:thin; scrollbar-color:var(--rust) transparent; }
#settings-v2-screen .set-content::-webkit-scrollbar { width:9px; }
#settings-v2-screen .set-content::-webkit-scrollbar-thumb { background:linear-gradient(var(--honey),var(--rust)); border-radius:99px; border:2px solid transparent; background-clip:padding-box; }
#settings-v2-screen .set-panel { display:none; max-width:660px; }
#settings-v2-screen #p-profile.set-panel { max-width:400px; margin-left:auto; margin-right:auto; }
#settings-v2-screen .set-panel.on { display:block; }
#settings-v2-screen .set-panel h2 { font-family:var(--disp); font-weight:800; font-size:25px; letter-spacing:-.02em; margin-bottom:5px; }
#settings-v2-screen .set-panel .pdesc { font-size:14px; color:var(--ink2); margin-bottom:8px; line-height:1.5; }
#settings-v2-screen .srow { display:flex; align-items:center; gap:18px; padding:17px 0; border-top:1px solid var(--line2); }
#settings-v2-screen .srow:first-of-type { border-top:none; }
#settings-v2-screen .srow .sl { flex:1; min-width:0; }
#settings-v2-screen .srow .sl h4 { font-weight:800; font-size:14.5px; color:var(--ink); }
#settings-v2-screen .srow .sl p { font-size:12.5px; color:var(--ink2); margin-top:3px; line-height:1.45; }
#settings-v2-screen .srow .sc { flex:none; }
#settings-v2-screen .sect-h { font-family:var(--disp); font-weight:800; font-size:15px; color:var(--ink2); margin:26px 0 2px; text-transform:none; }
#settings-v2-screen .tg { width:46px; height:26px; border-radius:99px; background:var(--border,#ddd7cc); position:relative; cursor:pointer; flex:none; }
#settings-v2-screen .tg.on { background:var(--olive); }
#settings-v2-screen .tg::after { content:""; position:absolute; top:2.5px; left:2.5px; width:21px; height:21px; border-radius:50%; background:#fff; transition:left .15s; box-shadow:0 1px 2px rgba(0,0,0,.25); }
#settings-v2-screen .tg.on::after { left:22.5px; }
#settings-v2-screen .ssel { font-family:var(--f); font-weight:700; font-size:13.5px; border:1px solid var(--line); background:var(--card); border-radius:10px; padding:10px 34px 10px 13px; color:var(--ink); cursor:pointer; min-width:200px; -webkit-appearance:none; appearance:none; background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%236e6049' stroke-width='2'%3E%3Cpath d='M2 4l4 4 4-4'/%3E%3C/svg%3E"); background-repeat:no-repeat; background-position:right 12px center; }
#settings-v2-screen .sin { font-family:var(--f); font-weight:600; font-size:13.5px; border:1px solid var(--line); background:var(--card); border-radius:10px; padding:11px 13px; color:var(--ink); width:100%; }
#settings-v2-screen .stext { font-family:var(--f); font-weight:500; font-size:13.5px; border:1px solid var(--line); background:var(--card); border-radius:10px; padding:11px 13px; color:var(--ink); width:100%; resize:none; line-height:1.5; }
#settings-v2-screen .fld { margin-bottom:16px; }
#settings-v2-screen #p-profile .fld { max-width:354px; }
#settings-v2-screen .fld label { display:block; font-size:12.5px; color:var(--ink2); font-weight:800; margin-bottom:7px; }
#settings-v2-screen .srng { -webkit-appearance:none; appearance:none; width:230px; height:6px; border-radius:99px; background:#e2d2b4; outline:none; }
#settings-v2-screen .srng::-webkit-slider-thumb { -webkit-appearance:none; width:19px; height:19px; border-radius:50%; background:var(--honey); border:3px solid var(--paper); box-shadow:0 1px 4px rgba(80,50,15,.45); cursor:pointer; }
/* Small reset-to-default icon next to a slider (sliders have no "click again to
   undo" affordance the way a toggle does). Sits flush against the slider in the
   source HTML (string concatenation, no whitespace), hence the margin-left. */
#settings-v2-screen .sv2-reset-mini {
  margin-left:10px; width:26px; height:26px; border-radius:8px; border:1px solid var(--line);
  background:var(--card); color:var(--ink2); display:inline-flex; align-items:center; justify-content:center;
  cursor:pointer; vertical-align:middle; flex:none;
}
#settings-v2-screen .sv2-reset-mini:hover { color:var(--ink); background:var(--card2); }
/* Section/global "Restore to default" rows read as a utility action, not a
   preference — a touch more separation + a muted label keeps it visually
   distinct from the toggles/sliders above it. */
#settings-v2-screen .sv2-reset-row { margin-top:6px; }
#settings-v2-screen .sv2-reset-row .sl h4 { color:var(--ink2); font-size:13.5px; }
#settings-v2-screen .seg2 { display:inline-flex; background:var(--s3,#e3ded3); border-radius:10px; padding:3px; }
#settings-v2-screen .seg2 button { border:none; background:transparent; font-family:var(--f); font-weight:700; font-size:13px; color:var(--ink2); padding:8px 15px; border-radius:8px; cursor:pointer; }
#settings-v2-screen .seg2 button.on { background:var(--card); color:var(--ink); box-shadow:0 1px 3px rgba(80,50,15,.18); }
#settings-v2-screen .swatches { display:flex; gap:9px; }
#settings-v2-screen .swatches i { width:28px; height:28px; border-radius:50%; cursor:pointer; border:2px solid transparent; }
#settings-v2-screen .swatches i.on { border-color:var(--ink); box-shadow:0 0 0 2px var(--paper) inset; }
#settings-v2-screen .swatches i.sw-reset { background:var(--paper,#f0e6d1); color:var(--ink3,#998); display:grid; place-items:center; font-size:12px; font-weight:800; border:2px solid var(--line,#e5ddcf); }
#settings-v2-screen .prof-banner { max-width:354px; aspect-ratio:3/1; border-radius:8px; background:linear-gradient(120deg,#c98a2e,#bd6a39); position:relative; margin:6px 0 44px; background-size:cover; background-position:center; }
#settings-v2-screen .prof-banner .chg { position:absolute; top:11px; right:11px; border:none; background:rgba(var(--st-ink-rgb),.55); -webkit-backdrop-filter:blur(5px); backdrop-filter:blur(5px); color:#fff; font-family:var(--f); font-weight:700; font-size:12px; padding:8px 12px; border-radius:10px; cursor:pointer; }
#settings-v2-screen .prof-banner .pa { position:absolute; left:22px; bottom:-30px; width:84px; height:84px; border-radius:50%; background:var(--plum); border:4px solid var(--paper); display:grid; place-items:center; color:#fff; font-weight:800; font-size:30px; font-family:var(--disp); background-size:cover; background-position:center; cursor:pointer; }
#settings-v2-screen .prof-banner .pa .cam { position:absolute; right:-2px; bottom:-2px; width:28px; height:28px; border-radius:50%; background:var(--card); border:2px solid var(--paper); display:grid; place-items:center; color:var(--ink2); cursor:pointer; }
#settings-v2-screen .plan { background:linear-gradient(135deg,#2f2415,#3a2c18); color:#f6ecd8; border:1px solid #43331c; border-radius:8px; padding:20px 22px; margin:6px 0 18px; }
#settings-v2-screen .plan .pt { display:flex; align-items:center; gap:10px; }
#settings-v2-screen .plan .pt b { font-family:var(--disp); font-weight:800; font-size:19px; }
#settings-v2-screen .plan .pt .bdg { font-size:10px; font-weight:800; text-transform:uppercase; letter-spacing:.04em; color:#3a2410; background:var(--honey); padding:3px 8px; border-radius:6px; }
#settings-v2-screen .plan .pm { font-size:13px; color:#c3b193; margin-top:7px; }
#settings-v2-screen .plan .pr { display:flex; gap:10px; margin-top:16px; flex-wrap:wrap; }
#settings-v2-screen .plan .pr button { border:1px solid rgba(var(--st-rgb),.25); background:rgba(255,255,255,.05); color:#f0c46a; font-family:var(--f); font-weight:700; font-size:13px; padding:10px 15px; border-radius:8px; cursor:pointer; }
#settings-v2-screen .plan .pr button.warnb { color:#eda486; border-color:rgba(199,95,62,.3); }
#settings-v2-screen .mini { font-size:13px; color:var(--ink2); display:flex; align-items:center; gap:9px; padding:13px 0; border-top:1px solid var(--line2); }
#settings-v2-screen .mini svg { color:var(--ink3); }
#settings-v2-screen .mini .mr { margin-left:auto; color:var(--rust); font-weight:700; }
#settings-v2-screen .newlook { background:linear-gradient(150deg,var(--card),var(--card2)); border:1.5px solid var(--honey); border-radius:10px; padding:17px 18px; display:flex; align-items:center; gap:16px; margin:6px 0 8px; }
#settings-v2-screen .newlook .ni { width:44px; height:44px; border-radius:9px; background:var(--honey); display:grid; place-items:center; color:#3a2410; flex:none; }
#settings-v2-screen .newlook h4 { font-weight:800; font-size:15px; color:var(--ink); display:flex; align-items:center; gap:8px; }
#settings-v2-screen .newlook h4 .new { font-size:9.5px; font-weight:800; text-transform:uppercase; letter-spacing:.04em; color:#fff; background:var(--clay); padding:2px 6px; border-radius:6px; }
#settings-v2-screen .newlook p { font-size:12.5px; color:var(--ink2); margin-top:3px; line-height:1.45; }
#settings-v2-screen .vchip { font-size:10px; font-weight:800; text-transform:uppercase; letter-spacing:.04em; color:var(--olive); background:#e9edd6; padding:2px 7px; border-radius:6px; margin-left:6px; }
#settings-v2-screen .vchip-warn { color:var(--rust,#c75f3e); background:#f5e2d8; }
#settings-v2-screen .keycap { font-family:var(--f); font-weight:800; font-size:12.5px; color:var(--ink); background:var(--card); border:1px solid var(--line); border-bottom-width:2px; border-radius:8px; padding:7px 13px; cursor:pointer; }
#settings-v2-screen .cpick { display:flex; align-items:center; gap:8px; }
#settings-v2-screen .cpick i { width:26px; height:26px; border-radius:50%; cursor:pointer; border:2px solid transparent; }
#settings-v2-screen .cpick i.on { border-color:var(--ink); box-shadow:0 0 0 2px var(--paper) inset; }
#settings-v2-screen .usage { margin:4px 0 2px; }
#settings-v2-screen .usage .bar { height:9px; border-radius:99px; background:#e7d8bd; overflow:hidden; }
#settings-v2-screen .usage .bar i { display:block; height:100%; border-radius:99px; background:linear-gradient(90deg,var(--honey),var(--rust)); }
#settings-v2-screen .usage .lb { display:flex; justify-content:space-between; font-size:12px; color:var(--ink2); font-weight:700; margin-top:8px; }
#settings-v2-screen .folderbtn { display:flex; align-items:center; gap:10px; border:1px solid var(--line); background:var(--card); border-radius:8px; padding:11px 13px; width:100%; cursor:pointer; font-family:var(--f); font-weight:700; font-size:13.5px; color:var(--ink); }
#settings-v2-screen .folderbtn svg { color:var(--ink3); }
#settings-v2-screen .folderbtn .pth { margin-left:auto; font-size:12px; color:var(--ink3); font-weight:600; }
#settings-v2-screen .btn-primary { border:none; background:var(--honey); color:#3a2410; font-family:var(--f); font-weight:800; font-size:14.5px; padding:12px 22px; border-radius:9px; cursor:pointer; box-shadow:0 8px 18px -9px rgba(189,106,57,.55); }
#settings-v2-screen .btn-primary:hover { filter:brightness(1.06); }
#settings-v2-screen .btn-soft { border:1px solid var(--line); background:var(--card); color:var(--ink); font-family:var(--f); font-weight:700; font-size:14px; padding:11px 17px; border-radius:9px; cursor:pointer; }
#settings-v2-screen .btn-soft:hover { border-color:var(--honey); color:var(--rust); }
#settings-v2-screen .delacct { border:1px solid #e3b9ab; background:transparent; color:var(--clay); font-family:var(--f); font-weight:800; font-size:13.5px; padding:11px 18px; border-radius:8px; cursor:pointer; }
@media (max-width:760px){
  #settings-v2-screen .set-body { flex-direction:column; }
  #settings-v2-screen .set-side { width:auto; border-right:none; border-bottom:1px solid var(--div); display:flex; overflow-x:auto; gap:6px; padding:10px; }
  #settings-v2-screen .set-me { display:none; }
  #settings-v2-screen .set-grp { display:flex; gap:6px; margin:0; }
  #settings-v2-screen .set-grp h6 { display:none; }
  #settings-v2-screen .set-foot { display:none; }   /* no room in the horizontal chip strip */
  #settings-v2-screen .set-item { white-space:nowrap; }
  /* min-height:0 lets the flex:1 content actually shrink + scroll inside the fixed
     screen; scrollbar hidden (the thin rust bar reads as ugly on a phone). */
  #settings-v2-screen .set-content { padding:22px; min-height:0; scrollbar-width:none; }
  #settings-v2-screen .set-content::-webkit-scrollbar { display:none; }
  #settings-v2-screen .set-panel { max-width:none; }
}
/* Drilled in from the mobile "You" hub: drop the horizontal category chip-strip so it
   reads as a single settings page (back returns to the hub). you-drill is set only on
   mobile (home-v2.js youOpenPanel), so this never affects desktop. */
body.you-drill #settings-v2-screen .set-side { display:none; }
/* min-height (not position:fixed on the texture below) is what makes the paper layer
   reach the bottom of a short page: Android WebView (the mobile APK - a bare WebView
   shell, see technical_react_native_app.md) has real, reproducible bugs with
   full-viewport position:fixed elements - large parts of the page silently failing to
   composite/paint, not fixed by a reload. Forcing #home-v2's own box to be at least
   one viewport tall means the ::before below can stay position:absolute (normal flow,
   no WebView risk) and still reach the bottom on a sparse/new account. */
#home-v2 { position:relative; min-height:100vh; min-height:100dvh; }
#home-v2::before { content:""; position:absolute; inset:0; pointer-events:none; z-index:0;
  background-image:url("/crumple.png"); background-size:cover; background-position:center;
  mix-blend-mode:overlay; opacity:.075; }
/* Dark forest bg: mix-blend-mode:overlay crushes to ~2 representable 8-bit levels against
   a near-black backdrop (verified - the raw texture's contrast survives an alpha this low
   as a single hard-edged contour, not grain). Pre-baked crumple-dark-baked.png already IS
   the exact composited result (forest --bg + the same .075 intensity) with real
   Floyd-Steinberg error-diffusion dithering applied at generation time, so it's shown as-is
   (normal blend, opacity 1) with no further lossy blend math at render time. Light theme
   is untouched/unaffected - still the original texture + overlay above. */
body.ui-v2.dark #home-v2::before { background-image:url("/crumple-dark-baked.png"); mix-blend-mode:normal; opacity:1; }
#home-v2 .hv-wrap { position:relative; z-index:1; }
/* (old .hv-space/.hv-spaces/.hv-fdd polish rules removed — the rebuilt home uses the
   mock class names .space/.spaces-scroll, styled verbatim above; friends moved to #hv-header.) */

/* CREATE SERVER SCREEN */
#create-server-screen { display:none; }

.create-server-container {
  display:flex; align-items:flex-start; justify-content:center;
  min-height:calc(100vh - 58px);
  padding:32px 24px 80px;
}

.create-server-card {
  background:var(--surface); border:1px solid var(--border);
  border-radius:8px; width:100%; max-width:480px;
  padding:40px 32px; box-shadow:var(--shlg);
}

.create-server-header {
  margin-bottom:32px;
}

.create-server-header h1 {
  font-size:24px; font-weight:700; letter-spacing:-.4px;
  margin-bottom:6px; margin-top:16px;
}

.create-server-header p {
  font-size:14px; color:var(--text2);
}

.back-btn {
  display:inline-flex; align-items:center; gap:6px;
  border:none; background:none; cursor:pointer;
  font-family:'DM Sans',sans-serif; font-size:13px;
  color:var(--text2); padding:0;
  transition:color .15s;
}
.back-btn:hover { color:var(--text); }

.create-server-form {
  display:flex; flex-direction:column; align-items:center; gap:20px;
}

.server-icon-upload {
  width:100px; height:100px; border-radius:22px;
  background:var(--s2); border:2px dashed var(--border);
  display:flex; align-items:center; justify-content:center;
  cursor:pointer; overflow:hidden; flex-shrink:0;
  transition:border-color .15s, background .15s;
}
.server-icon-upload:hover {
  border-color:var(--accent); background:var(--abg);
}

.server-icon-placeholder {
  display:flex; flex-direction:column; align-items:center; gap:6px;
  color:var(--text3); font-size:12px; font-weight:500;
}

.server-icon-preview {
  width:100%; height:100%; object-fit:cover; display:block;
}

.icon-hint {
  font-size:12px; color:var(--text3); text-align:center; margin-top:-10px;
}

.create-server-form .form-group {
  width:100%;
}

/* SERVER SCREEN */
#create-server-screen,
#server-screen {
  position:fixed; inset:0; z-index:200;
  background:var(--bg); overflow:hidden;
  flex-direction:column;
}

#server-screen {
  display:none; height:100vh; width:100%; overflow:hidden;
}

.server-page-topbar {
  flex-shrink:0; height:56px; z-index:50;
  background:var(--bg); border-bottom:1px solid var(--border);
  display:flex; align-items:center; padding:0 16px;
}

.server-page-topbar .back-btn { flex-shrink:0; }

.server-page-identity {
  flex:1; display:flex; align-items:center; justify-content:center; gap:10px;
}

.server-page-title {
  font-size:16px; font-weight:700; margin:0;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}

.members-toggle-btn {
  border:none; cursor:pointer; background:none; padding:8px;
  color:var(--text2); transition:color .15s;
  display:flex; align-items:center; justify-content:center;
}
.members-toggle-btn:hover { color:var(--text); }

.server-page-layout {
  display:flex; flex:1; width:100%; overflow:hidden;
}

.server-page-main {
  flex:1; overflow-y:auto; padding:32px 24px 80px;
}

.server-page-container {
  display:flex; flex-direction:column;
}


.server-page-icon {
  width:36px; height:36px; border-radius:8px;
  background:var(--s2); border:1px solid var(--border);
  display:flex; align-items:center; justify-content:center;
  overflow:hidden; flex-shrink:0;
  font-size:15px; font-weight:700; color:var(--text2);
}
.server-page-icon--initials {
  background:var(--abg); color:var(--accent);
}
.server-page-icon-img {
  width:100%; height:100%; object-fit:cover; display:block;
}

.server-page-identity h2 {
  font-size:20px; font-weight:700; letter-spacing:-.3px;
  margin-bottom:4px; margin:0;
}
.server-page-meta {
  font-size:13px; color:var(--text2); margin:0;
}

.server-page-body {
  display:flex; flex-direction:column; gap:24px;
}

.server-members-panel {
  width:300px; flex-shrink:0; border-left:1px solid var(--border);
  background:var(--surface); overflow-y:auto;
  transition:transform .3s ease, width .3s ease;
}
.server-members-panel .server-section {
  margin:0; border-radius:0; box-shadow:none; border:none;
  border-bottom:1px solid var(--border);
  /* Transparent so a themed/per-element members-panel background shows behind
     the member list. The panel itself paints var(--surface) by default, so the
     unthemed look is unchanged. Without this, the section's own opaque surface
     covered the panel background in the members region (but not the footer). */
  background:transparent;
}
.server-members-panel .server-section-title {
  padding:16px 16px 12px;
  border-bottom:1px solid var(--border);
}
.server-members-panel .server-members-list {
  padding:0;
}
.server-members-panel .server-member-row {
  padding:12px 16px;
}
.server-members-panel.collapsed {
  width:0; border-left:none; overflow:hidden;
}

.server-section {
  background:var(--surface); border:1px solid var(--border);
  border-radius:var(--r); box-shadow:var(--sh); overflow:hidden;
}

.server-section-title {
  font-size:11px; font-weight:600; text-transform:uppercase;
  letter-spacing:.7px; color:var(--text3);
  padding:14px 20px; border-bottom:1px solid var(--border);
}

.server-members-list {
  padding:8px 0;
}

.server-member-row {
  display:flex; align-items:center; gap:12px;
  padding:10px 20px;
  transition:background .12s;
}
.server-member-row:hover { background:var(--s2); }

.server-member-avatar {
  position:relative;
  width:34px; height:34px; border-radius:50%;
  background:var(--abg); color:var(--accent);
  display:flex; align-items:center; justify-content:center;
  font-size:14px; font-weight:700; flex-shrink:0;
  /* overflow visible so a real-art frame overlay can extend past the circle; the
     avatar img + the background circle both clip themselves via border-radius. */
  overflow:visible;
}
.server-member-avatar img:not(.av-frame-img) { width:100%; height:100%; object-fit:cover; border-radius:50%; }
.user-avatar {
  border-radius:50%; background:var(--abg); color:var(--accent);
  display:flex; align-items:center; justify-content:center;
  font-weight:700; flex-shrink:0; overflow:hidden;
}
.user-avatar img { width:100%; height:100%; object-fit:cover; border-radius:50%; }

.server-member-name {
  flex:1; font-size:14px; font-weight:500; color:var(--text);
}

.server-member-badge {
  font-size:11px; font-weight:600; text-transform:uppercase;
  letter-spacing:.5px; color:var(--accent);
  background:var(--abg); border:1px solid rgba(42,110,245,.2);
  border-radius:6px; padding:2px 7px;
}

.server-members-empty {
  font-size:13px; color:var(--text3);
  text-align:center; padding:24px;
}

.server-card {
  display:flex; align-items:center; gap:14px;
  padding:14px 16px; cursor:pointer;
  border-bottom:1px solid var(--border);
  transition:background .15s;
}
.server-card:last-child { border-bottom:none; }
.server-card:hover { background:var(--s2); }

.server-card-icon {
  width:48px; height:48px; border-radius:9px;
  background:var(--s2); border:1px solid var(--border);
  display:flex; align-items:center; justify-content:center;
  overflow:hidden; flex-shrink:0;
}

.server-card-icon-img {
  width:100%; height:100%; object-fit:cover; display:block;
}

.server-card-icon-placeholder {
  font-size:20px; font-weight:700; color:var(--accent);
}

.server-card-info {
  min-width:0;
}

.server-card-name {
  font-size:15px; font-weight:600; color:var(--text);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}

.servers-actions {
  display:flex; justify-content:space-between; margin-top:16px;
  max-width:600px; margin-left:auto; margin-right:auto;
}

@media(max-width:1000px){
  .server-members-panel { width:100%; border-left:none; border-top:1px solid var(--border); margin-top:0; padding:0; }
  .server-members-panel.collapsed { display:none; }
}

/* INVITE MODAL */
#invite-modal {
  position:fixed; inset:0; z-index:300;
  display:none; align-items:center; justify-content:center;
}
#invite-modal[style*="display: flex"] {
  display:flex;
}
.invite-modal-overlay {
  position:absolute; inset:0;
  background:rgba(0,0,0,.45); backdrop-filter:blur(6px); -webkit-backdrop-filter:blur(6px);
  cursor:pointer;
}
.invite-modal-card {
  position:relative; z-index:1;
  background:var(--surface); border:1px solid var(--border);
  border-radius:8px; box-shadow:var(--shlg);
  width:100%; max-width:420px; max-height:80vh;
  display:flex; flex-direction:column;
  margin:24px;
}
.invite-modal-header {
  display:flex; align-items:center; justify-content:space-between;
  padding:18px 20px; border-bottom:1px solid var(--border); flex-shrink:0;
}
.invite-modal-header h2 { font-size:16px; font-weight:700; margin:0; }
.invite-modal-close {
  background:none; border:none; cursor:pointer; font-size:22px;
  color:var(--text3); line-height:1; padding:2px 6px; transition:color .15s;
}
.invite-modal-close:hover { color:var(--text); }
#invite-modal-body {
  overflow-y:auto; padding:12px;
  display:flex; flex-direction:column; gap:6px;
}
.invite-friend-row {
  display:flex; align-items:center; justify-content:space-between;
  padding:10px 12px; border-radius:9px; transition:background .15s;
}
.invite-friend-row:hover { background:var(--s2); }
.invite-friend-name {
  font-size:14px; font-weight:500; flex:1; min-width:0;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.invite-confirm-box {
  padding:20px; text-align:center;
  display:flex; flex-direction:column; gap:12px;
}
.invite-confirm-box p { font-size:14px; color:var(--text2); line-height:1.5; }
.invite-confirm-box strong { color:var(--text); }
.invite-confirm-actions { display:flex; gap:8px; justify-content:center; }

.server-invite-footer {
  padding:12px; border-top:1px solid var(--border);
}

/* NOTIFICATION BELL */
/* Credits live next to Quick Share in the header-nav on desktop, and in the
   hamburger menu on mobile. js/store.js shows the desktop button only on the home
   screen (via a #home-screen MutationObserver) so it never appears in a server or
   call, where header-nav is still visible. */
.credit-nav-btn { display:inline-flex; align-items:center; gap:5px; font-variant-numeric:tabular-nums; }
.credit-nav-btn .credit-coin { font-size:15px; line-height:1; }

.notif-bell-btn {
  position:fixed; top:11px; right:68px; z-index:200;
  border-radius:10px; width:38px; height:38px;
  display:flex; align-items:center; justify-content:center;
  cursor:pointer; color:var(--text2); transition:all .15s;
  background:var(--surface); border:1px solid var(--border);
}
.notif-bell-btn:hover { color:var(--text); background:var(--s2); }
.notif-badge {
  position:absolute; top:-5px; right:-5px;
  background:#e53e3e; color:#fff; font-size:10px; font-weight:700;
  border-radius:99px; min-width:16px; height:16px;
  display:flex; align-items:center; justify-content:center;
  padding:0 3px;
}

#notif-panel {
  position:fixed; top:55px; right:28px; z-index:250;
  background:var(--surface); border:1px solid var(--border);
  border-radius:10px; box-shadow:var(--shlg);
  width:300px; max-height:400px; overflow-y:auto;
  display:none;
}
#notif-panel[style*="display: block"] {
  display:block;
}
.notif-invite-row {
  padding:12px 14px; border-bottom:1px solid var(--border);
  display:flex; flex-direction:column; gap:6px;
}
.notif-invite-row:last-child { border-bottom:none; }
.notif-invite-title { font-size:13px; font-weight:600; }
.notif-invite-sub { font-size:12px; color:var(--text3); }
.notif-invite-actions { display:flex; gap:6px; margin-top:2px; }

/* OVERRIDE: server-page-main for chat layout */
.server-page-main { padding:0; overflow:hidden; }

/* CHANNEL BAR */
.server-channel-bar {
  width:220px; flex-shrink:0;
  background:var(--s2); border-right:1px solid var(--border);
  overflow-y:auto; display:flex; flex-direction:column;
}
.channel-bar-server-name {
  display:flex; align-items:center; gap:4px;
  font-size:14px; font-weight:700; padding:16px 14px 12px;
  border-bottom:1px solid var(--border);
  overflow:hidden;
}
.channel-section { padding:8px 0; }
.channel-section-header {
  display:flex; align-items:center; justify-content:space-between;
  padding:6px 8px 4px 14px; font-size:11px; font-weight:600;
  text-transform:uppercase; letter-spacing:.6px; color:var(--text3);
}
.channel-section-header--disabled { opacity:.5; }
.channel-section-header .channel-add-btn {
  background:none; border:none; cursor:pointer; color:var(--text3);
  padding:2px 6px; border-radius:4px; font-size:18px; line-height:1;
  transition:color .12s;
}
.channel-section-header .channel-add-btn:hover { color:var(--text); }
.channel-list { display:flex; flex-direction:column; }
.channel-item {
  display:flex; align-items:center; gap:6px;
  padding:6px 8px 6px 12px; cursor:pointer;
  border-radius:6px; margin:1px 6px;
  font-size:14px; color:var(--text2);
  transition:background .12s, color .12s; user-select:none;
}
.channel-item:hover { background:var(--s3); color:var(--text); }
.channel-item.active { background:var(--border); color:var(--text); font-weight:600; }
.channel-item-hash { font-size:16px; color:var(--text3); flex-shrink:0; }
.channel-item.active .channel-item-hash { color:var(--text2); }
.voice-channel-item {
  display:flex; align-items:center; gap:8px;
  padding:6px 8px 6px 12px; cursor:pointer;
  border-radius:6px; margin:1px 6px;
  font-size:14px; color:var(--text2);
  transition:background .12s, color .12s; user-select:none;
}
.voice-channel-item:hover { background:var(--s3); color:var(--text); }
.voice-channel-item.active { background:var(--border); color:var(--text); font-weight:600; }
.voice-channel-icon { font-size:14px; flex-shrink:0; }
.channel-category-label {
  font-size:11px; font-weight:600; text-transform:uppercase;
  letter-spacing:.6px; color:var(--text3);
  padding:10px 14px 2px; user-select:none;
}
.channel-coming-soon { font-size:12px; color:var(--text3); padding:4px 14px 8px; font-style:italic; }
.channel-bar-toggle-btn {
  display:none; position:fixed; top:66px; left:8px; z-index:85;
  background:var(--surface); border:1px solid var(--border);
  border-radius:8px; padding:8px; cursor:pointer; color:var(--text2);
  box-shadow:var(--shsm); transition:all .15s;
}
.channel-bar-toggle-btn:hover { background:var(--s2); color:var(--text); }
/* Inline hamburger that sits inside .server-page-topbar (right of back).
   Same look as .back-btn since it lives in the same row. Hidden on
   desktop; shown only inside the mobile-mode media query below. */
.channel-bar-toggle-btn-inline { display:none; }

/* VOICE CONTROL PANEL
   Capped at half the channel-column height (`(100vh - 56) / 2`) so the
   channels list above stays browsable. The 8 action buttons inside
   .voice-control-footer get their own scroll viewport. Desktop and
   mobile share the same shape; mobile-specific tweaks (slide-out,
   chat-input-h subtraction when the typing bar is fixed at the bottom)
   are in the @media block further down. */
.voice-control-panel {
  position:fixed; bottom:0; left:0; width:220px;
  background:var(--s3); border-top:1px solid var(--border);
  border-right:1px solid var(--border);
  display:flex; flex-direction:column; z-index:50;
  transition:transform .25s cubic-bezier(0.16,1,0.3,1);
  max-height:calc((100vh - 56px) / 2);
  overflow:hidden; /* internal flex layout owns scrolling */
}
.voice-control-header {
  display:flex; align-items:center; justify-content:space-between;
  padding:12px; gap:8px; border-bottom:1px solid var(--border);
}
.voice-control-title {
  display:flex; align-items:center; gap:8px;
  font-size:13px; font-weight:600; color:var(--accent);
  flex:1; min-width:0;
}
.voice-control-title span {
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.voice-control-close {
  background:none; border:none; cursor:pointer; color:var(--text3);
  font-size:20px; line-height:1; padding:0; width:24px; height:24px;
  display:flex; align-items:center; justify-content:center;
  border-radius:4px; transition:all .12s;
}
.voice-control-close:hover { background:var(--s2); color:var(--text); }
.voice-control-members {
  /* Capped to 30% of the active-section so a long participant list
     doesn't push the action buttons (mic/share/cam/etc.) off-screen.
     Members above the cap scroll within this box. */
  flex: 0 1 auto;
  max-height: 30%;
  overflow-y:auto; padding:8px;
  font-size:12px; color:var(--text2);
}
.voice-avatar-wrap {
  position:relative; border-radius:50%; flex-shrink:0;
}
.voice-avatar-wrap::after {
  content:''; position:absolute; inset:0; border-radius:50%;
  border:2px solid var(--accent); opacity:0; pointer-events:none;
  transition:opacity .1s;
}
.voice-avatar-wrap.speaking::after { opacity:1; }
.voice-control-member {
  padding:6px 8px; border-radius:4px; margin-bottom:4px;
  background:var(--s2); display:flex; align-items:center; gap:6px;
}
.voice-control-member-dot {
  width:6px; height:6px; border-radius:50%;
  background:var(--ok); flex-shrink:0;
}
.voice-control-footer {
  /* Scrollable button list (mic / share / camera / call view / youtube
     / band / drawing / cursor). flex:1 1 auto + min-height:0 lets it
     shrink below content size; without min-height:0 the parent's
     overflow:hidden would clip the bottom buttons. */
  padding:8px; border-top:1px solid var(--border);
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
}

/* Hide the scroll bars on the voice control panel + members/activity panel
   while keeping wheel/touch scrolling. scrollbar-width:none covers Firefox;
   ::-webkit-scrollbar covers Chromium / Safari / Electron. */
.voice-control-members,
.voice-control-footer,
.server-members-panel {
  scrollbar-width: none;
}
.voice-control-members::-webkit-scrollbar,
.voice-control-footer::-webkit-scrollbar,
.server-members-panel::-webkit-scrollbar {
  display: none;
  width: 0; height: 0;
}
.voice-control-footer .btn.sharing {
  background:var(--accent); color:var(--accent-fg,#fff); border-color:var(--accent);
}

/* ── CALL GRID ── */
#voice-call-grid {
  display:none; flex:1; flex-direction:column;
  background:#111; position:relative; overflow:hidden; min-height:0;
}
#voice-call-grid.call-grid-floating {
  position:fixed;
  width:480px; height:320px;
  min-width:260px; min-height:160px;
  z-index:850; border-radius:9px; border:1px solid var(--border);
  box-shadow:0 8px 40px rgba(0,0,0,.5);
}
/* Resize handles — visible only when floating */
.cg-rh { position:absolute; z-index:20; display:none; }
#voice-call-grid.call-grid-floating .cg-rh { display:block; }
.cg-rh[data-dir="nw"] { top:0; left:0;    width:16px; height:16px; cursor:nw-resize; }
.cg-rh[data-dir="ne"] { top:0; right:0;   width:16px; height:16px; cursor:ne-resize; }
.cg-rh[data-dir="sw"] { bottom:0; left:0;  width:16px; height:16px; cursor:sw-resize; }
.cg-rh[data-dir="se"] { bottom:0; right:0; width:16px; height:16px; cursor:se-resize; }
.cg-rh[data-dir="s"]  { bottom:0; left:16px; right:16px; height:6px; cursor:s-resize; }
.cg-rh[data-dir="e"]  { right:0; top:16px; bottom:16px; width:6px; cursor:e-resize; }
.cg-rh[data-dir="w"]  { left:0;  top:16px; bottom:16px; width:6px; cursor:w-resize; }
.call-grid-header {
  display:flex; align-items:center; padding:6px 10px;
  background:rgba(0,0,0,.4); border-bottom:1px solid rgba(255,255,255,.06);
  cursor:move; user-select:none; flex-shrink:0;
}
.call-grid-header-title { flex:1; font-size:12px; font-weight:600; color:rgba(255,255,255,.7); letter-spacing:.3px; }
.call-grid-header-btns { display:flex; gap:4px; }
.call-grid-hbtn {
  background:none; border:none; color:rgba(255,255,255,.5); cursor:pointer;
  padding:4px; border-radius:4px; display:flex; align-items:center; justify-content:center;
}
.call-grid-hbtn:hover { background:rgba(255,255,255,.1); color:#fff; }
.call-grid-hbtn.sharing { color:#57f287; }

.call-grid-inner {
  flex:1; display:grid; gap:4px; padding:4px;
  min-height:0; overflow:hidden; grid-auto-rows:1fr;
}
.call-grid-inner.call-grid-focused {
  display:flex; flex-direction:row; gap:4px;
}
.call-grid-main { flex:1; min-width:0; }
.call-grid-main .call-tile { width:100%; height:100%; }
.call-grid-sidebar {
  width:150px; flex-shrink:0; display:flex; flex-direction:column;
  gap:4px; overflow-y:auto;
}
.call-grid-sidebar .call-tile { flex-shrink:0; width:100%; aspect-ratio:16/9; }

.call-tile {
  position:relative; background:#1a1a1a; border-radius:8px; overflow:hidden;
  display:flex; align-items:center; justify-content:center; cursor:pointer;
  min-height:0;
}
.call-tile-video { width:100%; height:100%; object-fit:contain; display:block; }
.call-tile-mirror { transform:scaleX(-1); }

/* Avatar (audio-only) tile */
.call-tile-avatar-bg {
  width:100%; height:100%; display:flex;
  align-items:center; justify-content:center;
}
.call-tile-avatar-img {
  width:64px; height:64px; border-radius:50%; object-fit:cover;
  box-shadow:0 2px 12px rgba(0,0,0,.4);
}
.call-tile-avatar-initial {
  width:64px; height:64px; border-radius:50%;
  background:rgba(255,255,255,.15); color:#fff;
  display:flex; align-items:center; justify-content:center;
  font-size:28px; font-weight:700;
}

/* Tile overlay (shown on hover) */
.call-tile-overlay {
  position:absolute; inset:0; display:flex;
  flex-direction:column; justify-content:space-between;
  padding:6px 8px; opacity:0; transition:opacity .15s;
  background:linear-gradient(to bottom, rgba(0,0,0,.5) 0%, transparent 40%, transparent 60%, rgba(0,0,0,.6) 100%);
  pointer-events:none;
}
.call-tile:hover .call-tile-overlay { opacity:1; pointer-events:all; }
.call-tile-label {
  font-size:12px; font-weight:600; color:#fff;
  display:flex; align-items:center; gap:5px; align-self:flex-end;
}
.call-tile-controls { display:flex; gap:4px; justify-content:flex-end; align-self:flex-start; }
.call-tile-btn {
  background:rgba(0,0,0,.55); border:none; color:#fff;
  width:26px; height:26px; border-radius:6px; cursor:pointer;
  display:flex; align-items:center; justify-content:center; font-size:14px;
}
.call-tile-btn:hover { background:rgba(255,255,255,.2); }
.call-tile-report-btn:hover { background:rgba(220,60,60,.85); }
/* A stream this user reported: blurred locally (not killed for everyone). */
.call-tile-reported .call-tile-video { filter:blur(30px) brightness(.45); }
.call-tile-reported-cover {
  position:absolute; inset:0; z-index:6;
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  gap:10px; text-align:center; padding:14px;
  background:rgba(0,0,0,.55); color:#fff;
}
.call-tile-reported-cover .ctr-msg { font-size:13px; font-weight:600; }
.call-tile-reported-cover .ctr-show {
  background:rgba(255,255,255,.15); border:1px solid rgba(255,255,255,.35); color:#fff;
  border-radius:6px; padding:4px 12px; font-size:12px; cursor:pointer;
}
.call-tile-reported-cover .ctr-show:hover { background:rgba(255,255,255,.28); }
.call-tile-badge {
  font-size:9px; font-weight:700; padding:1px 5px; border-radius:3px;
  letter-spacing:.3px;
}
.call-tile-badge-cam    { background:#5865f2; color:#fff; }
.call-tile-badge-screen { background:#ed4245; color:#fff; }
.call-tile-badge-activity { background:#3ba55d; color:#fff; }
/* muted (mic off) badge — top-left, always shown while muted (not gated on hover). */
.call-tile-mute { display:none; position:absolute; left:7px; top:7px; z-index:3;
  width:23px; height:23px; border-radius:7px; align-items:center; justify-content:center;
  color:#fff; background:rgba(237,66,69,.92); box-shadow:0 2px 8px rgba(0,0,0,.4); pointer-events:none; }
.call-tile-muted .call-tile-mute { display:flex; }

/* Game activity tile: the iframe fills the tile. */
.call-tile-activity { width:100%; height:100%; border:0; display:block; background:#000; }
/* Never let the hover overlay swallow board clicks on a game tile; only the
   control buttons stay clickable (the rest passes through to the iframe). */
.call-tile-is-activity .call-tile-overlay,
.call-tile-is-activity:hover .call-tile-overlay { pointer-events:none !important; }
.call-tile-is-activity .call-tile-controls,
.call-tile-is-activity .call-tile-btn { pointer-events:auto; }

/* Game picker modal */
.ss-game-modal-overlay {
  position:fixed; inset:0; background:rgba(0,0,0,.55); z-index:4000;
  display:flex; align-items:center; justify-content:center;
}
.ss-game-modal {
  position:relative; background:#2b2d31; color:#e9eaed;
  border-radius:9px; padding:20px 22px; min-width:min(280px, 100vw - 16px); max-width:min(540px, 92vw);
  box-shadow:0 12px 40px rgba(0,0,0,.5);
}
/* The game-list modal gets an explicit responsive width so the 100%-wide grid
   fills it (and reaches 2 columns on desktop); the small confirm / in-progress
   modals stay content-sized. */
.ss-game-modal:has(.ss-game-list) { width:min(540px, 92vw); }
.ss-game-modal-title { font-size:16px; font-weight:700; margin-bottom:4px; }
.ss-game-modal-sub   { font-size:13px; opacity:.75; margin-bottom:14px; }
.ss-game-modal-close {
  position:absolute; top:6px; right:8px; width:36px; height:36px;
  display:flex; align-items:center; justify-content:center; line-height:1;
  background:none; border:none; border-radius:8px;
  color:inherit; font-size:16px; cursor:pointer; opacity:.6;
}
.ss-game-modal-close:hover { opacity:1; background:rgba(255,255,255,.08); }
/* Game picker: a responsive 2-up grid of photo tiles. Each card is a background
   photo (drop-in /games/tiles/<id>.jpg) with the title overlaid on a dark scrim;
   until a photo exists, a tinted gradient + the game's emoji is the placeholder. */
.ss-game-list {
  width:100%; display:grid; gap:10px; margin-top:14px;
  grid-template-columns:repeat(auto-fill, minmax(200px, 1fr));
  max-height:64vh; overflow-y:auto; overflow-x:hidden; padding:2px;
}
.ss-game-card {
  /* min-height is a collapse-guard: all of this card's content is position:absolute,
     so its height relies ENTIRELY on aspect-ratio. Where aspect-ratio isn't honored
     in this grid (a Safari/grid quirk), the cards would collapse to ~0 and look
     "squished together". 120px sits below the normal computed height (>=125px), so
     it only rescues the broken case and never alters the working layout. */
  position:relative; overflow:hidden; aspect-ratio:16/10; min-height:120px;
  border:1px solid rgba(255,255,255,.10); border-radius:9px; padding:0; margin:0;
  text-align:left; cursor:pointer; color:#fff;
  background:var(--tint, #5865f2);   /* solid fallback if color-mix is unsupported */
  background:linear-gradient(150deg, var(--tint, #5865f2), color-mix(in srgb, var(--tint, #5865f2) 42%, #000));
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.07), inset 0 -44px 56px -24px rgba(0,0,0,.55);
  transition:transform .14s ease, box-shadow .14s ease;
}
.ss-game-card:hover { transform:translateY(-2px); box-shadow:0 12px 26px -10px rgba(0,0,0,.65), inset 0 0 0 1px rgba(255,255,255,.14), inset 0 -44px 56px -24px rgba(0,0,0,.55); }
/* placeholder emoji watermark (sits behind the photo; shown when no photo) */
.ss-game-tile-glyph { position:absolute; top:8px; right:12px; font-size:46px; line-height:1; opacity:.32; filter:drop-shadow(0 2px 4px rgba(0,0,0,.4)); }
.ss-game-tile-img { position:absolute; inset:0; width:100%; height:100%; object-fit:cover; image-rendering:auto; opacity:0; transition:opacity .25s ease, filter .35s ease;
  filter:blur(3px); transform:scale(1.06);   /* base blur; scale so the blurred edges are clipped (no feathered rim) */ }
.ss-game-tile-img.is-loaded { opacity:1; }
.ss-game-card:hover .ss-game-tile-img.is-loaded { filter:blur(0); }   /* hover: smoothly unblur to show the real photo */
/* Progressive blur: a stronger-blurred copy of the photo, shown only near the top
   + bottom edges and fading out by the centre (mask), over the 3px base. */
.ss-game-tile-edge { position:absolute; inset:0; background-size:cover; background-position:center;
  filter:blur(8px); transform:scale(1.1); opacity:0; transition:opacity .25s ease; pointer-events:none;
  -webkit-mask-image:linear-gradient(to bottom, #000 0%, rgba(0,0,0,0) 42%, rgba(0,0,0,0) 58%, #000 100%);
          mask-image:linear-gradient(to bottom, #000 0%, rgba(0,0,0,0) 42%, rgba(0,0,0,0) 58%, #000 100%); }
.ss-game-tile-edge.is-loaded { opacity:1; }
.ss-game-card:hover .ss-game-tile-edge.is-loaded { opacity:0; }   /* hover: drop the extra edge blur along with the base image's */
/* readability scrim: darkens the lower portion so the title pops on any photo */
.ss-game-tile-scrim { position:absolute; inset:0; pointer-events:none;
  background:linear-gradient(to top, rgba(0,0,0,.84) 0%, rgba(0,0,0,.45) 30%, rgba(0,0,0,0) 58%),
             linear-gradient(to bottom, rgba(0,0,0,.84) 0%, rgba(0,0,0,.45) 30%, rgba(0,0,0,0) 58%); }
.ss-game-card-text { position:absolute; left:13px; right:13px; bottom:11px; }
.ss-game-card-name { font-weight:700; font-size:15px; text-shadow:0 1px 3px rgba(0,0,0,.75); }
.ss-game-card-meta { font-size:11.5px; margin-top:2px; line-height:1.35; opacity:.94; text-shadow:0 1px 3px rgba(0,0,0,.8); }
/* Paid-game status badge (Phase 2 unlocks) — top-right corner, readable on photos. */
.ss-game-card-lock, .ss-game-card-owned {
  position:absolute; top:9px; left:9px; font-size:11px; font-weight:700; padding:3px 9px;
  border-radius:999px; white-space:nowrap; backdrop-filter:blur(3px);
}
.ss-game-card-lock  { color:#cfe0ff; background:rgba(20,30,60,.6); border:1px solid rgba(120,150,220,.5); }
.ss-game-card-owned { color:#c9ffd8; background:rgba(15,45,25,.6); border:1px solid rgba(87,242,135,.45); }

/* Speaking ring */
.call-tile-speaking-ring {
  position:absolute; inset:0; border-radius:8px;
  border:3px solid transparent; pointer-events:none; transition:border-color .1s;
}
.call-tile-speaking-ring.speaking { border-color:#57f287; }

/* Per-stream volume row, anchored bottom-right of the tile overlay */
.call-tile-vol-row {
  position:absolute; bottom:6px; right:8px;
  display:flex; align-items:center; gap:6px;
  background:rgba(0,0,0,.55); border-radius:6px;
  padding:4px 8px;
  pointer-events:all;
}
.call-tile-vol-icon {
  display:inline-flex; align-items:center; color:rgba(255,255,255,.85);
}
input[type=range].call-tile-vol-range {
  -webkit-appearance:none;
  width:80px; height:3px; border-radius:2px;
  background:rgba(255,255,255,.3); outline:none; cursor:pointer; flex-shrink:0;
}
input[type=range].call-tile-vol-range::-webkit-slider-thumb {
  -webkit-appearance:none; width:13px; height:13px; border-radius:50%;
  background:#fff; cursor:pointer;
}
input[type=range].call-tile-vol-range::-moz-range-thumb {
  width:13px; height:13px; border-radius:50%; background:#fff; cursor:pointer; border:none;
}
.call-tile-vol-pct {
  font-size:11px; font-family:'DM Mono',monospace;
  min-width:36px; text-align:right; color:rgba(255,255,255,.7);
}

/* In-app fullscreen — fills viewport, app chrome covered, escape/button to exit */
.call-tile.call-tile-expanded {
  position:fixed; inset:0;
  width:100vw; height:100vh;   /* inset:0 already fits it; kept for clarity */
  z-index:9000; border-radius:0;
  background:#000;
  cursor:default;
}
.call-tile.call-tile-expanded .call-tile-video {
  width:100%; height:100%;
}
.call-tile.call-tile-expanded .call-tile-speaking-ring { border-radius:0; }
/* A fullscreened game activity should NOT show the video-darkening overlay gradient
   (it reads as black/gray bands over the game's own UI). The controls keep their own
   backgrounds, so they stay usable. */
.call-tile-is-activity.call-tile-expanded .call-tile-overlay { background:none; }

#voice-active-section {
  flex-direction:column; flex:1; min-height:0; overflow:hidden;
  border-bottom:1px solid var(--border);
}
.voice-user-bar {
  display:flex; align-items:center; gap:6px;
  padding:8px 10px; flex-shrink:0;
}
.voice-user-bar-avatar {
  width:28px; height:28px; border-radius:50%; background:var(--accent);
  flex-shrink:0; display:flex; align-items:center; justify-content:center;
  font-size:12px; font-weight:600; color:var(--accent-fg,#fff);
  background-size:cover; background-position:center;
}
.voice-user-bar-name {
  flex:1; font-size:13px; font-weight:500; color:var(--text);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.voice-user-bar-btn {
  background:none; border:none; cursor:pointer; color:var(--text3);
  padding:4px; border-radius:4px; display:flex; align-items:center;
  justify-content:center; transition:color .12s, background .12s;
  flex-shrink:0;
}
.voice-user-bar-btn:hover { background:var(--s2); color:var(--text); }
.voice-user-bar-btn.muted { color:var(--danger, #e05252); }

/* CHAT AREA */
.server-chat-area { display:flex; flex-direction:column; height:100%; overflow:hidden; }
.chat-no-channel { flex:1; display:flex; align-items:center; justify-content:center; color:var(--text3); font-size:14px; }
.chat-view { display:flex; flex-direction:column; height:100%; overflow:hidden; }
.chat-channel-header {
  /* Floats over the top of the message scroll area (which fills the whole
     chat-view) so a themed translucent / backdrop-blurred header reveals the
     messages scrolling behind it. Reset to in-flow on mobile. */
  position:absolute; top:0; left:0; right:0; z-index:6;
  flex-shrink:0; display:flex; align-items:center; gap:6px;
  padding:12px 20px; border-bottom:1px solid var(--border);
  font-size:15px; font-weight:600; background:var(--surface);
}
.chat-channel-hash { font-size:18px; color:var(--text3); font-weight:400; }
.chat-messages {
  /* Desktop: the scroll area's box stops exactly at the header on top and the
     input bar on the bottom (top:var(--chat-header-h) / bottom:var(--chat-bottom-h))
     instead of running the full chat-view height behind them. A position:absolute
     box's native scrollbar always spans its own full height regardless of
     padding — running this box full-height with padding to reserve the header/
     input bands (the old approach) let the scrollbar visibly dip behind/through
     both of them. Ending the box at each bar's real edge instead means the
     scrollbar (and the box) simply stop there — no dip, on either side,
     regardless of either bar's opacity/theme.
     Heights come from --chat-header-h / --chat-bottom-h (published by the
     ResizeObservers in boot.js); the fallbacks match the default bar sizes.
     Mobile resets this back to a flex child (min-height:0) — see the media
     query below. */
  position:absolute; top:var(--chat-header-h, 49px); left:0; right:0; bottom:var(--chat-bottom-h, 60px); z-index:1;
  overflow-y:auto;
  padding: 8px 10px;
  display:flex; flex-direction:column; gap: var(--srv-msg-spacing, 2px);
  /* Server-theme background image lives here. Dim overlay is the first layer so it
     darkens the image without affecting message bubble colors. Both vars fall back
     to no-effect defaults so unthemed servers render exactly as before. */
  background-image:
    linear-gradient(rgba(0,0,0, var(--srv-bg-dim-alpha, 0)), rgba(0,0,0, var(--srv-bg-dim-alpha, 0))),
    var(--srv-chat-bg-image, none);
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}
.chat-msg {
  display:flex; flex-direction:row; gap:10px; padding:6px 10px; align-items:flex-start;
  background: var(--srv-msg-bg, var(--s2));
  border-radius: var(--srv-msg-radius, 8px);
  /* layout+style containment only — NOT paint: paint containment clips the
     3-dot message menu (position:absolute, can extend past the bubble), which
     becomes very visible with narrow fit-to-content bubbles. */
  contain:layout style;
}
.chat-msg:hover { background:var(--s3); }
body.has-server-theme .chat-msg:hover { background: var(--srv-msg-bg, var(--s3)); filter: brightness(1.08); }
.chat-msg-avatar { flex-shrink:0; }
.chat-msg-body { display:flex; flex-direction:column; gap:2px; flex:1; min-width:0; }

/* Message bubble width. DEFAULT: full-width rows that fill to the edges. Owners
   can switch to fit-to-content chips (left-aligned, capped) via the "Fit bubble
   width to message" toggle (on → body.srv-msg-fitcontent). Scoped to
   .chat-messages so the standalone screenshare chat (.chat-msgs) is untouched. */
.chat-messages .chat-msg { align-self: stretch; }
.chat-messages .chat-msg .chat-msg-body { flex: 1 1 auto; }
body.srv-msg-fitcontent .chat-messages .chat-msg {
  /* Stretch close to the right wall before capping, so wide attachments have
     room; media inside is bounded to the bubble (below) and shrinks once the
     bubble can't stretch further. */
  align-self: flex-start; width: fit-content; max-width: min(94%, 680px);
}
body.srv-msg-fitcontent .chat-messages .chat-msg .chat-msg-body { flex: 0 1 auto; }
/* Keep wide media within the (capped) fit-content bubble on narrow screens —
   preserve each pixel cap but also bound to the bubble width. Harmless in
   full-width mode (min() picks the pixel cap there). */
.chat-messages .chat-msg .link-preview         { max-width: min(480px, 100%); }
.chat-messages .chat-msg .link-preview-yt iframe { max-width: min(480px, 100%); }
.chat-messages .chat-msg .chat-file-img        { max-width: min(300px, 100%); }
.chat-messages .chat-msg .chat-msg-file-r2     { max-width: min(380px, 100%); }
.chat-msg-header { display:flex; align-items:baseline; gap:8px; margin-bottom:1px; position:relative; z-index:10; }
.chat-msg-author { font-size:13px; font-weight:600; color:var(--text); }
.chat-msg-time { font-size:11px; color:var(--text3); }
.msg-menu-wrap { position:relative; margin-left:auto; }
.msg-menu-btn { display:none; background:none; border:none; color:var(--text3); cursor:pointer; padding:2px 6px; border-radius:4px; font-size:15px; line-height:1; letter-spacing:1px; }
.msg-menu-btn:hover { background:var(--s2); color:var(--text2); }
.chat-msg:hover .msg-menu-btn { display:inline-block; }
.msg-menu { display:none; position:absolute; right:0; top:calc(100% + 2px); background:var(--s1); border:1px solid var(--border); border-radius:8px; padding:4px; min-width:150px; z-index:9999; box-shadow:0 4px 16px rgba(0,0,0,0.35); }
.msg-menu.open { display:block; }
.msg-menu-item { display:flex; align-items:center; gap:8px; width:100%; background:none; border:none; color:var(--text2); font-size:13px; padding:7px 10px; border-radius:5px; cursor:pointer; text-align:left; white-space:nowrap; }
.msg-menu-item:hover { background:var(--s2); }
.msg-menu-item-danger { color:#f04747; }
.msg-menu-item-danger:hover { background:rgba(240,71,71,0.1); color:#f04747; }
.msg-emoji-picker { display:none; position:absolute; right:0; top:calc(100% + 2px); background:var(--s1); border:1px solid var(--border); border-radius:10px; padding:6px 8px; z-index:200; box-shadow:0 4px 16px rgba(0,0,0,0.35); }
.msg-emoji-picker.open { display:flex; gap:2px; }
.msg-emoji-btn { background:none; border:none; cursor:pointer; font-size:22px; padding:4px 5px; border-radius:6px; line-height:1; }
.msg-emoji-btn:hover { background:var(--s2); }
.msg-reactions { display:flex; flex-wrap:wrap; gap:4px; margin-top:4px; }
.reaction-chip { display:inline-flex; align-items:center; gap:4px; background:var(--s2); border:1px solid var(--border); border-radius:9px; padding:3px 9px; font-size:13px; cursor:pointer; line-height:1; }
.reaction-chip.by-me { border-color:var(--accent); background:rgba(42,110,245,0.12); }
.reaction-chip:hover { filter:brightness(1.15); }
.chat-msg-content {
  font-size:calc(14px * var(--txtscale, 1));   /* --txtscale: Accessibility > Text size */
  color: var(--srv-msg-text, var(--text2));
  line-height:1.5; word-break:break-word;
  font-family: var(--srv-msg-font, inherit);
  white-space:pre-wrap;   /* Shift+Enter newlines render as real line breaks */
}
.chat-msg-content.emoji-only { font-size:calc(40px * var(--txtscale, 1)); line-height:1.2; }
/* E2E Phase 3: placeholder shown for an encrypted message we can't (yet) decrypt —
   waiting for the channel key, E2E off, no identity, or a failed verification. Reads
   as a muted system note, never a real message. */
.chat-msg-content.e2e-placeholder { color: var(--text3); font-style: italic; opacity: .85; }
.chat-msg-content.e2e-badkey { color: var(--danger, #e05260); font-style: normal; }
.chat-msg.chat-msg-failed { opacity: .6; }
.chat-msg.chat-msg-failed .chat-msg-time { color: var(--danger, #e05260); }
/* The "this message is encrypted" lock — only rendered on cryptographically-verified
   (decrypted) messages. Small + muted so it reads as a quiet "verified" mark. */
.msg-e2e-lock { margin-left: 6px; font-size: 11px; opacity: .6; vertical-align: middle; }
.msg-e2e-lock img.emoji { width: 12px; height: 12px; vertical-align: -1px; }
/* Retention countdown chip. Deliberately quiet: tiny, dim, coarse units, no
   ticking clock. The final 24h shifts to a soft amber, never red. */
.msg-ttl { font-size:10px; color:var(--text3); opacity:.55; white-space:nowrap; flex-shrink:0; }
.msg-ttl-soon { color:#d8a657; opacity:.8; }
.msg-pinned-chip { font-size:10px; color:var(--text3); opacity:.75; white-space:nowrap; flex-shrink:0; }
.msg-pinned-chip img.emoji { width:11px; height:11px; vertical-align:-1px; }
/* Gentle fade for rows the retention sweep just removed (messages-expired SSE). */
.msg-expired-fade { opacity:0; transition:opacity .65s ease; pointer-events:none; }
/* Timed-out note (type='expired'): a quiet marker where a message used to be.
   Whole row dimmed, content italic and muted; transitions softly when a live
   row converts in place. */
.chat-msg-tombstone { transition:opacity .65s ease; }
.chat-msg-tombstone .chat-msg-avatar { opacity:.45; }
.chat-msg-tombstone .chat-msg-author { color:var(--text3); }

/* Consecutive same-author messages within a minute: the avatar keeps its
   space (visibility, not display) so the body column doesn't shift, but the
   repeated name/picture goes away. Time/chips/lock/menu stay in the header. */
.chat-msg-grouped .chat-msg-avatar { visibility:hidden; }
.chat-msg-grouped .chat-msg-author { display:none; }
.msg-tombstone { color:var(--text3); font-style:italic; opacity:.75; font-size:13px; }
/* Pinned text-message cards on the pin board. */
.pin-card-msg-snippet { font-size:12px; color:var(--text); line-height:1.45; word-break:break-word;
  display:-webkit-box; -webkit-line-clamp:4; -webkit-box-orient:vertical; overflow:hidden; }
/* Member "set up encryption" banner — auto-appears in an encrypted channel when the
   member has no keys yet; the password prompt only opens on the explicit button click. */
.e2e-setup-banner { display: none; align-items: center; gap: 12px; justify-content: space-between;
  margin: 8px 12px; padding: 10px 14px; border-radius: 8px; background: var(--s2, #2b2d31);
  border: 1px solid var(--accent, #5865f2); font-size: 14px; color: var(--text2, #dbdee1); flex-wrap: wrap; }
.e2e-setup-banner .e2e-setup-btn { flex: 0 0 auto; padding: 8px 14px; border: 0; border-radius: 6px;
  background: var(--accent, #5865f2); color:var(--accent-fg,#fff); font-size: 14px; font-weight: 600; cursor: pointer; }
.e2e-setup-banner .e2e-setup-btn:hover { filter: brightness(1.08); }
/* Recovery-backup nudge reuses the setup banner; "Later" reads quieter than the primary. */
.e2e-setup-banner .e2e-nudge-later { background: transparent; color: var(--text2); border: 1px solid var(--border, var(--line)); }
/* When the owner enables "Apply font to whole UI", force the themed font on
   the whole server view. The `* !important` is needed because lots of rules
   declare font-family explicitly (DM Sans, etc.) and wouldn't otherwise
   inherit. Scoped to #server-screen so it doesn't touch the settings chrome.
   (Affects text rendering only — SVG/emoji icons are unaffected.) */
body.srv-whole-ui-font { font-family: var(--srv-ui-font, inherit); }
body.srv-whole-ui-font #server-screen,
body.srv-whole-ui-font #server-screen * { font-family: var(--srv-ui-font, inherit) !important; }
.chat-link { color:var(--accent); text-decoration:none; }
.chat-link:hover { text-decoration:underline; }
.link-preview {
  margin-top:8px; max-width:480px;
  border-left:3px solid var(--accent);
  background: var(--srv-card-bg, var(--s3));
  border-radius:0 6px 6px 0; padding:10px 12px;
  /* Explicit color so the link-preview doesn't inherit a themed message text
     color into surfaces that have their own light/dark card background. */
  color: var(--srv-card-text, var(--text));
}
.link-preview-yt { border-left:none; background:none; padding:0; margin-top:8px; }
.link-preview-yt iframe { width:100%; max-width:480px; height:270px; border-radius:8px; display:block; }
.link-preview-site { font-size:11px; font-weight:700; color:var(--accent); text-transform:uppercase; letter-spacing:.5px; margin-bottom:4px; }
.link-preview-title a { font-size:14px; font-weight:600; color:var(--text); text-decoration:none; }
.link-preview-title a:hover { text-decoration:underline; }
.link-preview-desc { font-size:12px; color:var(--text2); line-height:1.4; margin-top:4px; }
.link-preview-img { max-width:100%; max-height:180px; border-radius:4px; object-fit:cover; display:block; margin-top:8px; }
.msg-edited-label { font-size:11px; color:var(--text3); }
/* Height is driven by JS (fitEditBox sizes it to the content) so entering edit
   mode keeps the message's footprint instead of jumping to a fixed-height box.
   overflow-y:auto (not hidden): a width change mid-edit (window resize, panel
   toggle) reflows the wrap without re-firing fitEditBox — scroll, don't clip. */
.msg-edit-input { width:100%; background:var(--s3); border:1px solid var(--border); border-radius:6px; color:var(--text); font-family:'DM Sans',sans-serif; font-size:14px; line-height:1.5; padding:4px 8px; resize:none; overflow-y:auto; outline:none; margin-top:2px; }
.msg-edit-input:focus { border-color:var(--accent); }
.msg-edit-actions { display:flex; gap:6px; margin-top:6px; }
.msg-edit-save { background:var(--accent); color:var(--accent-fg,#fff); border:none; border-radius:5px; padding:4px 12px; font-size:12px; font-weight:600; cursor:pointer; font-family:'DM Sans',sans-serif; }
.msg-edit-save:hover { background:var(--accent2); }
.msg-edit-cancel { background:none; color:var(--text3); border:none; border-radius:5px; padding:4px 10px; font-size:12px; cursor:pointer; font-family:'DM Sans',sans-serif; }
.msg-edit-cancel:hover { color:var(--text); background:var(--s3); }
.chat-msgs-empty { color:var(--text3); font-size:13px; text-align:center; padding:32px 0; }
.chat-older-sentinel { width:100%; min-height:1px; flex-shrink:0; }
.chat-load-older-spinner { padding:8px 10px; font-size:12px; color:var(--text3); text-align:center; }
.chat-loading-initial { padding:24px 10px; font-size:13px; color:var(--text3); text-align:center; }
/* bottom tracks --chat-bottom-h (the same live-measured var .chat-messages' padding
   uses) instead of a fixed offset, so the button rides up/down with the input box
   as it grows/shrinks (multi-line messages, reply/attachment bars) instead of
   staying pinned at a height that assumes a single-line input. */
.chat-jump-latest { position:absolute; bottom:calc(var(--chat-bottom-h, 60px) + 12px); right:16px; z-index:20; display:none; align-items:center; gap:6px; background:var(--accent); color:var(--accent-fg,#fff); border:none; border-radius:9px; padding:6px 14px; font-size:13px; font-weight:600; cursor:pointer; box-shadow:0 2px 8px rgba(0,0,0,0.3); }
.chat-jump-latest:hover { filter:brightness(1.1); }
.chat-msg-optimistic { opacity:0.6; }
.reply-preview-bar {
  flex-shrink:0; display:flex; align-items:flex-start; gap:8px;
  padding:6px 16px; background:var(--s2); border-top:1px solid var(--border);
  font-size:12px; color:var(--text3); max-height:120px; overflow-y:auto;
}
.reply-preview-bar .rp-chips { flex:1; display:flex; flex-direction:column; gap:4px; min-width:0; }
.reply-preview-bar .rp-chip {
  display:flex; align-items:center; gap:6px; max-width:100%;
  background:var(--s3); border:1px solid var(--border); border-left:3px solid var(--accent);
  border-radius:6px; padding:3px 4px 3px 8px; cursor:pointer; transition:background .12s;
}
.reply-preview-bar .rp-chip:hover { background:var(--s1, var(--surface)); }
.reply-preview-bar .rp-chip-name { color:var(--accent); font-weight:600; flex-shrink:0; }
.reply-preview-bar .rp-chip-text { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.reply-preview-bar .rp-chip-x {
  flex-shrink:0; background:none; border:none; color:var(--text3); cursor:pointer;
  font-size:15px; line-height:1; padding:0 4px; border-radius:4px; transition:color .12s, background .12s;
}
.reply-preview-bar .rp-chip-x:hover { color:var(--text); background:var(--s2); }
.reply-preview-bar .rp-cancel {
  flex-shrink:0; background:none; border:none; color:var(--text3); cursor:pointer;
  font-size:18px; line-height:1; padding:0 2px;
}
.reply-preview-bar .rp-cancel:hover { color:var(--text); }
.reply-ico { vertical-align:-1px; flex-shrink:0; }
.msg-reply-author .reply-ico, .msg-menu-item .reply-ico { margin-right:3px; }
.attachment-preview-bar {
  flex-shrink:0; display:flex; align-items:flex-start;
  padding:8px 16px; background:var(--s2); border-top:1px solid var(--border);
  max-height:160px; overflow-y:auto;
}
.ap-list {
  flex:1; display:flex; flex-wrap:wrap; gap:8px;
}
.ap-chip {
  display:flex; align-items:center; gap:8px;
  background:var(--s3); border:1px solid var(--border);
  padding:6px 4px 6px 6px; border-radius:8px;
  max-width:280px;
}
.ap-chip .ap-thumb-wrap {
  position:relative; width:44px; height:44px; flex-shrink:0;
}
.ap-chip .ap-thumb {
  width:44px; height:44px; object-fit:cover; border-radius:5px;
  background:var(--s2); display:block; cursor:zoom-in;
  transition:filter .12s;
}
.ap-chip .ap-thumb:hover { filter:brightness(1.1); }
.ap-chip .ap-icon {
  width:44px; height:44px; border-radius:5px; background:var(--s2);
  display:flex; align-items:center; justify-content:center;
  font-size:22px;
}
.ap-chip .ap-p2p-badge {
  position:absolute; bottom:-3px; right:-3px;
  background:var(--accent); color:var(--accent-fg,#fff);
  font-size:9px; font-weight:700; letter-spacing:.3px;
  padding:1px 4px; border-radius:3px; line-height:1;
  border:1px solid var(--s3); pointer-events:none;
  box-shadow:0 1px 2px rgba(0,0,0,.3);
}
.ap-chip .ap-info {
  flex:1; min-width:0; display:flex; flex-direction:column; gap:2px; max-width:170px;
}
.ap-chip .ap-name {
  color:var(--text); font-size:12px; font-weight:500;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.ap-chip .ap-size { font-size:11px; color:var(--text3); }
.ap-chip .ap-cancel {
  flex-shrink:0; background:none; border:none; color:var(--text3); cursor:pointer;
  font-size:18px; line-height:1; padding:2px 6px; border-radius:4px;
  transition:background .12s, color .12s;
}
.ap-chip .ap-cancel:hover { color:var(--text); background:var(--s2); }
.msg-reply-quote {
  display:flex; align-items:center; gap:8px; margin-bottom:3px;
  background:var(--s3); border-left:3px solid var(--accent);
  border-radius:4px; padding:3px 8px; max-width:100%; cursor:pointer;
  transition:background .12s;
}
.msg-reply-quote:hover { background:var(--s1, var(--surface)); }
.msg-reply-author { font-size:11px; font-weight:600; color:var(--accent); flex-shrink:0; display:inline-flex; align-items:center; }
.msg-reply-content { font-size:12px; color:var(--text3); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
/* Floats over the bottom of the message scroll area (reply preview +
   attachment preview + input). Its measured height feeds --chat-bottom-h so
   the messages reserve space for it. Mobile: display:contents (below) so the
   children behave exactly as before (input becomes position:fixed). */
.chat-bottom-bar {
  position:absolute; left:0; right:0; bottom:0; z-index:6;
  display:flex; flex-direction:column;
}
/* "X is typing" line — sits just above the input, animated dots */
.chat-typing { display:none; align-items:center; gap:8px; padding:3px 18px 5px; font-size:12.5px; font-weight:600; color:var(--text2);
  background:var(--bg); pointer-events:none; }
.chat-typing .td { display:inline-flex; gap:3px; }
.chat-typing .td i { width:5px; height:5px; border-radius:50%; background:var(--text3); animation:chat-typing-bounce 1.25s infinite ease-in-out; }
.chat-typing .td i:nth-child(2){ animation-delay:.18s; }
.chat-typing .td i:nth-child(3){ animation-delay:.36s; }
@keyframes chat-typing-bounce { 0%,70%,100%{ transform:translateY(0); opacity:.45; } 35%{ transform:translateY(-3px); opacity:1; } }
.chat-input-area {
  /* flex-end (was center): the textarea grows upward as you type, so the
     attach/send buttons anchor to the bottom row like every chat app. */
  flex-shrink:0; display:flex; align-items:flex-end; gap:8px;
  padding:12px 16px; border-top:1px solid var(--border); background:var(--surface);
  min-height:50px;
  /* One height for the whole row. The input is 14px text at 1.45 line-height
     plus 9px padding each side plus its 1px border = 40px on a single line, so
     the +, mic and send buttons take the same 40px and stop looking like three
     different sizes next to it. Driving all four from one value is the point:
     they were each sized independently before and none of them agreed. */
  --chat-ctl-h:40px;
  /* .chat-messages now bottom-insets to var(--chat-bottom-h) (this bar's own
     measured height) instead of running full-height behind it, so there's no
     more overlap to stack above — but this bar still floats over the top of
     .chat-view like the header does, so keep its own stacking context. */
  position:relative; z-index:2;
}
.chat-input {
  /* min-width:0 lets the input shrink below its intrinsic min-width so the
     fixed-size buttons (attach/emoji/send, all flex-shrink:0) always fit the
     row — without it a tight width pushes the send button off the right edge.
     It's a textarea now (Shift+Enter = new line): JS auto-grows it to the text
     (syncChatInputHeight); past max-height it scrolls internally. */
  flex:1; min-width:0; border:1px solid var(--border); border-radius:9px;
  padding:9px 14px; font-size:14px; background:var(--s2); color:var(--text); outline:none;
  /* Pins the single-line height to exactly the buttons' height. min-height also
     beats the inline height syncChatInputHeight sets, so a 1px rounding
     difference in scrollHeight can't knock the row out of alignment. */
  min-height:var(--chat-ctl-h,40px);
  transition:border-color .15s, background .15s;
  resize:none; line-height:1.45; max-height:172px; overflow-y:auto; display:block;
  /* The default browser scrollbar (~15-17px) only appears once a message grows
     past max-height, but eats into the same content width the text wraps at —
     so long messages visibly wrap well short of the box's right edge the moment
     scrolling kicks in. A slim scrollbar keeps that gap small and unnoticeable. */
  scrollbar-width:thin;
}
.chat-input::-webkit-scrollbar { width:6px; }
.chat-input::-webkit-scrollbar-thumb { background:var(--border); border-radius:3px; }
.chat-input:focus { border-color:var(--accent); background:var(--surface); }
.chat-send-btn {
  background:var(--accent); color:var(--accent-fg,#fff); border:none; border-radius:9px;
  /* Square, same as the + and mic, instead of a padding-derived size that
     landed a few px shorter than both of them. */
  width:var(--chat-ctl-h,40px); height:var(--chat-ctl-h,40px); padding:0;
  cursor:pointer; display:flex; align-items:center; justify-content:center;
  transition:background .15s; flex-shrink:0;
}
/* The markup asks for 15px, which read small beside the 17px mic once the
   buttons matched in size. */
.chat-send-btn svg { width:17px; height:17px; }
.chat-send-btn:hover { background:var(--accent2); }

/* CONTEXT MENU */
.channel-ctx-menu {
  position:fixed; z-index:500;
  background:var(--surface); border:1px solid var(--border);
  border-radius:10px; box-shadow:var(--shlg); padding:4px; min-width:160px;
}
.ctx-menu-item {
  display:block; width:100%; text-align:left; background:none; border:none;
  padding:9px 14px; font-family:'DM Sans',sans-serif; font-size:13px;
  color:var(--text); cursor:pointer; border-radius:7px; transition:background .12s;
}
.ctx-menu-item:hover { background:var(--s2); }

/* MOBILE OVERRIDE
   Triggers: viewport ≤700px (narrow desktop or phone portrait), OR a
   touch device with viewport ≤950px (catches phone landscape ~932px
   that wouldn't otherwise hit the 700px breakpoint). The touch-and-
   wider clause keeps mouse-driven narrow-desktop windows on the desktop
   layout. */
@media (max-width: 700px), (pointer: coarse) and (max-width: 950px) {
  .server-channel-bar {
    position:fixed; top:56px; left:0; bottom:0; z-index:80;
    width:220px; transform:translateX(-100%);
    transition:transform .25s cubic-bezier(0.16,1,0.3,1);
    box-shadow:var(--shlg);
    overflow-y:auto;
  }
  .server-channel-bar.open { transform:translateX(0); }
  .voice-control-panel {
    /* Mobile slide-out: hidden off-screen by default, .open class
       brings it in. max-height + overflow + flex layout are inherited
       from the base rule above. z-index bumped over chat-input. */
    position:fixed; bottom:0; left:0;
    width:220px;
    transform:translateX(-100%);
    z-index:110;
  }
  .voice-control-panel.open { transform:translateX(0); }
  /* body.chat-input-visible is toggled by the MutationObserver in
     boot.js (setupChatInputVisibilityObserver) whenever #chat-view's
     inline display flips. --chat-input-h is the actual rendered height
     of the typing bar (published by a ResizeObserver in the same
     setup). Anchoring `bottom` to that value makes the channel + voice
     panels' bottoms TOUCH the top of the typing bar exactly, including
     when the input grows (emoji picker, attached files) or shrinks
     (rotation, safe-area changes). 60 px fallback matches the
     .chat-input-area max-height in case the JS hasn't measured yet. */
  body.chat-input-visible .server-channel-bar {
    bottom: var(--chat-input-h, 60px);
  }
  body.chat-input-visible .voice-control-panel {
    bottom: var(--chat-input-h, 60px);
    max-height: calc((100vh - 56px - var(--chat-input-h, 60px)) / 2);
  }
  /* The free-floating channel-bar-toggle-btn is replaced by the inline
     hamburger inside .server-page-topbar — keep it hidden so we don't
     show two hamburgers on mobile. */
  .channel-bar-toggle-btn { display:none !important; }
  .channel-bar-toggle-btn-inline { display:flex !important; }
  .channel-bar-overlay {
    display:block !important; position:fixed; inset:0; z-index:79;
    background:rgba(0,0,0,.3);
  }

  /* Ensure chat layout works on mobile */
  .server-page-layout { flex-direction:column; }
  .server-page-main {
    flex:1; padding:0; overflow:hidden;
    height:calc(100vh - 56px);
  }
  .server-chat-area {
    display:flex; flex-direction:column; height:100%;
  }
  .chat-view {
    display:flex; flex-direction:column; height:100%;
  }
  /* Behind-bars layout applies on mobile too (header + bottom bar float, the
     messages fill the view behind them so a translucent/blurred bar reveals
     the chat). The header + messages keep their desktop absolute rules; we
     only adapt the bottom bar. The bottom bar is position:fixed (not absolute)
     so it survives the soft keyboard exactly as the input did before, and it
     carries reply/attachment previews + the input together. */
  .chat-bottom-bar {
    /* Fixed (not absolute) so it survives the soft keyboard like the input did
       before. Transparent so a themed translucent/blurred input reveals the
       messages behind it — the input-area paints its own background and covers
       the safe-area zone itself. */
    position:fixed; bottom:0; left:0; right:0; z-index:100;
  }
  .chat-messages {
    /* keep the base rule's top:var(--chat-header-h)/bottom:var(--chat-bottom-h)
       inset (so the scroll region — and its scrollbar — still stops at each
       bar's real edge instead of running full height) — just adjust padding
       for a touch wider side gutters. Do NOT re-add --chat-header-h here, the
       box's own `top` already accounts for it. */
    padding: 8px 12px;
  }
  .chat-input-area {
    /* Equal space above and below the controls in the usable area; the
       safe-area inset extends the input's own background below the home
       indicator (so there's no transparent strip and no clipped buttons). */
    padding: 10px 12px calc(10px + env(safe-area-inset-bottom));
    max-height:none;
  }
  .chat-input { font-size:14px; }
  .chat-jump-latest { bottom:calc(var(--chat-bottom-h, 66px) + 12px); }
  .server-members-panel {
    position:fixed; top:56px; right:0; bottom:0; z-index:80;
    width:260px; height:calc(100vh - 56px);
    transform:translateX(100%);
    transition:transform .25s cubic-bezier(0.16,1,0.3,1);
    border-left:1px solid var(--border); border-top:none;
    overflow-y:auto;
  }
  .server-members-panel:not(.collapsed) {
    transform:translateX(0);
  }
}

/* Mobile header / page-padding overrides — same wider trigger as the
   sidebar overrides above so phone landscape gets the compact header
   instead of the desktop one. */
@media (max-width: 700px), (pointer: coarse) and (max-width: 950px) {
  .share-layout { grid-template-columns:1fr; }
  .setting-row  { grid-template-columns:1fr; }
  .hero h1      { font-size:30px; }
  header        { padding:0 16px; }
  /* Same empty-main collapse as the base rule: vertical padding lives on the
     screens inside main so a hidden-everything main takes no height. The
     files screen's mobile values live next to its base rule (cascade order). */
  main          { padding:0 16px; }
  #auth-screen, #setup-screen, #sharing-screen { padding-top:28px; padding-bottom:60px; }
  .server-page-topbar { padding:0 12px; }
  .server-page-title { font-size:14px; }

  /* Mobile header layout */
  .hamburger-btn { display:flex !important; }
  .logo { display:none; }
  .settings-btn { display:none; }
  .notif-bell-btn { right:16px; }
  /* Mobile uses the hamburger's Store item instead of the header-nav credits button. */
  .credit-nav-btn { display:none !important; }
  #notif-panel { right:16px; }
}

/* File Sharing Styles */
/* EMOJI BUTTON + PICKER */
.chat-emoji-btn {
  display: flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; flex-shrink: 0;
  border: 1px solid var(--border); border-radius: 6px;
  background: var(--bg); color: var(--text2); cursor: pointer;
  transition: all 0.15s ease;
}
.chat-emoji-btn:hover { color: var(--accent); border-color: var(--accent); background: var(--abg); }
.chat-emoji-btn.active { color: var(--accent); border-color: var(--accent); background: var(--abg); }

/* EMOJI PICKER (js/emoji-picker.js) — native-DOM. Generic vars => Warm Loft under
   body.ui-v2, neutral under classic, and tracks server themes for free. */
#emoji-picker-wrap { width: 348px; max-width: 94vw; }
.ep-panel {
  display: flex; flex-direction: column;
  width: 100%; height: 408px; max-height: min(70vh, 460px);
  background: var(--surface); border: 1px solid var(--border);
  border-radius:10px; box-shadow: 0 14px 40px rgba(0,0,0,.20);
  overflow: hidden; color: var(--text);
  font-family: 'DM Sans', system-ui, -apple-system, sans-serif;
}
.ep-panel img.emoji { margin: 0; width: 24px; height: 24px; vertical-align: middle; }
.ep-top { display: flex; align-items: center; gap: 8px; padding: 10px 10px 8px; }
.ep-search { flex: 1; min-width: 0; display: flex; align-items: center; gap: 7px; height: 34px;
  padding: 0 10px; background: var(--bg); border: 1px solid var(--border); border-radius: 10px; }
.ep-search svg { color: var(--text2); flex: none; }
.ep-search input { flex: 1; min-width: 0; border: none; background: none; outline: none;
  font: inherit; font-size: 13.5px; color: var(--text); }
.ep-search input::placeholder { color: var(--text3, var(--text2)); }
.ep-tone { width: 34px; height: 34px; flex: none; display: grid; place-items: center;
  background: var(--bg); border: 1px solid var(--border); border-radius: 10px; cursor: pointer; }
.ep-tone .dot { width: 16px; height: 16px; border-radius: 50%; box-shadow: inset 0 0 0 1px rgba(0,0,0,.18); }
.ep-tonepop { position: absolute; top: 46px; right: 10px; z-index: 6; display: flex; gap: 5px;
  padding: 6px; background: var(--surface); border: 1px solid var(--border);
  border-radius: 10px; box-shadow: 0 8px 22px rgba(0,0,0,.18); }
.ep-tonepop[hidden] { display: none; }
.ep-tonepop button { width: 24px; height: 24px; padding: 0; border-radius: 50%;
  border: 2px solid transparent; cursor: pointer; box-shadow: inset 0 0 0 1px rgba(0,0,0,.18); }
.ep-tonepop button.on { border-color: var(--accent); }
.ep-tabs { display: flex; align-items: center; gap: 2px; padding: 2px 8px 6px;
  border-bottom: 1px solid var(--border); }
.ep-tab { flex: 1; height: 30px; display: grid; place-items: center; padding: 0;
  border: none; background: none; border-radius: 8px; cursor: pointer; opacity: .55;
  color: var(--text2); transition: opacity .12s, background .12s; }
.ep-tab:hover { opacity: .85; }
.ep-tab.on { opacity: 1; background: var(--s2); }
.ep-panel .ep-tab img.emoji { width: 18px; height: 18px; }
.ep-scroll { flex: 1; overflow-y: auto; overflow-x: hidden; padding: 0 8px 10px; scrollbar-width: thin; }
.ep-scroll::-webkit-scrollbar { width: 9px; }
.ep-scroll::-webkit-scrollbar-thumb { background: var(--border); border-radius: 6px; border: 2px solid var(--surface); }
.ep-h { position: sticky; top: 0; z-index: 1; padding: 9px 4px 5px;
  background: var(--surface); color: var(--text2);
  font-size: 11px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; }
.ep-grid { display: grid; grid-template-columns: repeat(8, 1fr); }
.ep-em { aspect-ratio: 1 / 1; display: grid; place-items: center; padding: 0;
  border: none; background: none; border-radius: 8px; cursor: pointer;
  font-size: 22px; line-height: 1; }
.ep-em:hover { background: var(--s2); }
.ep-empty { padding: 34px 10px; text-align: center; color: var(--text2); font-size: 13px; }
body.ui-v2 .ep-panel { border-radius:8px; }

/* GIF PICKER (js/gif-picker.js) — same real-DOM popover-attach pattern + generic
   vars as the emoji picker above, just a search bar + a thumbnail grid.
   Positioning lives here (not inline in index.html, unlike #emoji-picker-wrap)
   specifically so the mobile media query below can cleanly override it into a
   bottom sheet instead of fighting inline-style specificity with !important. */
#gif-picker-wrap { position: absolute; bottom: calc(100% + 8px); right: 0; z-index: 300; width: 420px; max-width: 94vw; }
.gp-panel {
  display: flex; flex-direction: column;
  width: 100%; height: 480px; max-height: min(75vh, 520px);
  background: var(--surface); border: 1px solid var(--border);
  border-radius:10px; box-shadow: 0 14px 40px rgba(0,0,0,.20);
  overflow: hidden; color: var(--text);
  font-family: 'DM Sans', system-ui, -apple-system, sans-serif;
}
.gp-top { display: flex; align-items: center; gap: 7px; height: 34px; margin: 10px 10px 8px; flex: none;
  padding: 0 10px; background: var(--bg); border: 1px solid var(--border); border-radius: 10px; }
.gp-top svg { color: var(--text2); flex: none; }
.gp-top input { flex: 1; min-width: 0; border: none; background: none; outline: none;
  font: inherit; font-size: 13.5px; color: var(--text); }
.gp-top input::placeholder { color: var(--text3, var(--text2)); }
/* grid-auto-rows is a FIXED px height, not aspect-ratio on .gp-item — letting the
   row height come from aspect-ratio (which itself depends on the auto-computed
   column width) sent Chrome's grid track sizing into a bad state where rows
   overlapped by ~50px instead of stacking (verified via getBoundingClientRect,
   not a guess). A fixed row height sidesteps that entirely; object-fit:cover
   below still crops every GIF (whatever its real aspect ratio) to fill it. */
.gp-grid { flex: 1; min-height: 0; overflow-y: auto; padding: 0 10px 10px;
  display: grid; grid-template-columns: 1fr 1fr; grid-auto-rows: 140px; gap: 6px; align-content: start; }
.gp-item { position: relative; border: none; padding: 0; background: var(--bg); border-radius: 8px; overflow: hidden; cursor: pointer; }
/* Fades in once ITS OWN image finishes loading (each thumbnail is a separate
   network request) — the gray .gp-item background + spinner show instantly in
   the meantime, so the grid never looks empty while things trickle in. */
.gp-item img { width: 100%; height: 100%; object-fit: cover; display: block; position: relative; z-index: 1;
  opacity: 0; transition: opacity .2s ease; }
.gp-item img.gp-loaded { opacity: 1; }
.gp-item img.gp-loaded + .gp-item-spin { display: none; }
.gp-item-spin { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; }
.gp-item-spin::after { content: ''; width: 18px; height: 18px; border-radius: 50%;
  border: 2px solid var(--border); border-top-color: var(--text2); animation: gp-spin .7s linear infinite; }
@keyframes gp-spin { to { transform: rotate(360deg); } }
.gp-item:hover { outline: 2px solid var(--accent); outline-offset: -2px; }
.gp-item.gp-skel { cursor: default; }
.gp-item.gp-skel:hover { outline: none; }
.gp-status { grid-column: 1 / -1; text-align: center; padding: 30px 10px; font-size: 13px; color: var(--text3, var(--text2)); }
.gp-attribution { flex: none; text-align: center; padding: 6px 10px 10px; font-size: 10.5px; color: var(--text3, var(--text2)); }
body.ui-v2 .gp-panel { border-radius:8px; }
body.ui-v2 .ep-h { font-family: var(--disp); letter-spacing: .03em; }

/* GIF PICKER — mobile: a floating 420px popover doesn't fit a phone screen (it'd
   either overflow or need to shrink to a cramped sliver). Becomes a bottom sheet
   instead — full width, anchored to the screen edge, taller for comfortable
   thumb scrolling, 3 columns since the extra width supports it. Same breakpoint
   used app-wide for touch/narrow layouts. Only #gif-picker-wrap's POSITION needs
   overriding (it's a real CSS rule, not inline, specifically so this doesn't need
   !important); .gp-panel/.gp-grid are restyled directly. */
@media (max-width:700px), (pointer:coarse) and (max-width:950px){
  #gif-picker-wrap { position: fixed; left: 0; right: 0; bottom: 0; top: auto; width: auto; max-width: none; z-index: 400; }
  .gp-panel {
    width: 100%; height: 62vh; max-height: 62vh;
    border-radius: 16px 16px 0 0;
    box-shadow: 0 -8px 30px rgba(0,0,0,.25);
    padding-bottom: env(safe-area-inset-bottom, 0px);
  }
  .gp-top { margin: 12px 12px 8px; height: 40px; }
  .gp-grid { grid-template-columns: 1fr 1fr 1fr; grid-auto-rows: 110px; padding: 0 12px 12px; }
}

img.emoji {
  height: 1em; width: 1em;
  margin: 0 .05em 0 .1em;
  vertical-align: -0.1em;
}

.chat-attach-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--chat-ctl-h,40px);
  height: var(--chat-ctl-h,40px);
  flex-shrink: 0;   /* without this the "+" squashes to a tall skinny sliver */
  border: 1px solid var(--border);
  border-radius: 9px;   /* matches the input and the send button */
  background: var(--bg);
  color: var(--text2);
  cursor: pointer;
  font-size: 20px;
  font-weight: bold;
  transition: all 0.15s ease;
}

.chat-attach-btn:hover,
.chat-attach-btn.active {
  color: var(--accent);
  border-color: var(--accent);
  background: var(--abg);
}

/* "+" attach menu popover (Photo or file / Emoji), anchored above the + button. */
.chat-plus-menu {
  position: absolute; bottom: calc(100% + 8px); left: 0; z-index: 300;
  min-width: 178px; padding: 6px;
  background: var(--surface); border: 1px solid var(--border); border-radius: 10px;
  box-shadow: 0 16px 40px -18px rgba(40,25,8,.55);
  display: flex; flex-direction: column; gap: 2px;
}
.chat-plus-menu button {
  display: flex; align-items: center; gap: 10px;
  width: 100%; text-align: left;
  border: none; background: transparent; cursor: pointer;
  font-family: 'DM Sans', sans-serif; font-size: 14px; font-weight: 600;
  color: var(--text); padding: 9px 11px; border-radius: 8px;
}
.chat-plus-menu button svg { color: var(--text2); flex: none; }
.chat-plus-menu button:hover { background: var(--abg); color: var(--accent); }
.chat-plus-menu button:hover svg { color: var(--accent); }

.chat-msg-file {
  display: flex;
  align-items: center;
  gap: 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 12px;
  background: var(--srv-card-bg, var(--s2));
  color: var(--srv-card-text, var(--text));
  margin-top: 4px;
  max-width: 380px;
}

.file-name {
  font-weight: 500;
  color: var(--text1);
  word-break: break-word;
  max-width: 300px;
}

.file-size {
  color: var(--text2);
  font-size: 12px;
  margin-top: 2px;
}

.settings-disclosure > summary {
  cursor: pointer;
  user-select: none;
  font-size: 12px;
  color: var(--text2);
  padding: 4px 0;
  list-style: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.settings-disclosure > summary::-webkit-details-marker { display: none; }
.settings-disclosure > summary::before {
  content: '';
  width: 0; height: 0;
  border-left: 5px solid currentColor;
  border-top: 4px solid transparent;
  border-bottom: 4px solid transparent;
  transition: transform .15s ease;
}
.settings-disclosure[open] > summary::before { transform: rotate(90deg); }
.settings-disclosure > summary:hover { color: var(--text); }
.settings-disclosure[open] > summary { color: var(--text); margin-bottom: 4px; }

.file-download-btn {
  padding: 6px 12px;
  border: 1px solid var(--accent);
  border-radius: 4px;
  background: var(--accent);
  color:var(--accent-fg,#fff);
  cursor: pointer;
  font-size: 12px;
  font-weight: 500;
  transition: all 0.15s ease;
  white-space: nowrap;
  flex-shrink: 0;
}

.file-download-btn:hover {
  background: var(--accent2);
  border-color: var(--accent2);
}

#download-panel.dragging {
  cursor:grabbing;
  opacity:.95;
}


/* SOUNDBOARD */
.soundboard-popup {
  position: fixed;
  left: 230px;
  bottom: 16px;
  width: 280px;
  max-height: 60vh;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: 0 8px 32px rgba(0,0,0,.35);
  z-index: 1100;
  flex-direction: column;
  overflow: hidden;
}
.soundboard-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 10px 12px;
  border-bottom: 1px solid var(--border);
}
.soundboard-title {
  font-size: 13px; font-weight: 600; color: var(--text);
}
.soundboard-close {
  background: none; border: none; color: var(--text2);
  cursor: pointer; font-size: 14px; line-height: 1; padding: 2px 6px;
  border-radius: 4px;
}
.soundboard-close:hover { background: var(--s2); color: var(--text); }
.soundboard-toolbar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 8px;
  padding: 8px 12px;
  border-bottom: 1px solid var(--border);
}
.soundboard-upload-btn {
  padding: 6px 12px;
  border-radius: 6px;
  border: 1px solid var(--accent);
  background: var(--accent);
  color:var(--accent-fg,#fff);
  font-size: 12px;
  font-weight: 500;
  cursor: pointer;
}
.soundboard-upload-btn:hover { filter: brightness(1.1); }
.soundboard-upload-btn:disabled { opacity: 0.6; cursor: not-allowed; }
.soundboard-toolbar-note {
  font-size: 11px;
  color: var(--text3);
}
.soundboard-list {
  flex: 1; min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 10px;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  align-content: start;
  scrollbar-width: none;
}
.soundboard-list::-webkit-scrollbar { display: none; width: 0; height: 0; }
.soundboard-empty {
  grid-column: 1 / -1;
  color: var(--text3);
  font-size: 12px;
  text-align: center;
  padding: 24px 8px;
}
.soundboard-sound-cell {
  position: relative;
  min-width: 0;
}
.soundboard-sound {
  width: 100%;
  min-width: 0;
  max-width: 100%;
  padding: 10px 24px 10px 8px;
  border-radius: 6px;
  border: 1px solid var(--border);
  background: var(--bg);
  color: var(--text);
  font-size: 12px;
  cursor: pointer;
  text-align: center;
  overflow: hidden;
  box-sizing: border-box;
}
.soundboard-sound:hover { background: var(--s2); border-color: var(--accent); }
.soundboard-sound:active { transform: translateY(1px); }
.soundboard-sound-name {
  display: block;
  text-overflow: ellipsis;
  white-space: nowrap;
  overflow: hidden;
}
.soundboard-sound-gear {
  position: absolute;
  top: 4px; right: 4px;
  width: 20px; height: 20px;
  padding: 0;
  border: none;
  background: transparent;
  color: var(--text3);
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  border-radius: 4px;
  opacity: 0.7;
}
.soundboard-sound-gear:hover {
  background: rgba(0,0,0,0.18);
  color: var(--text);
  opacity: 1;
}

/* PER-ITEM MENU */
.soundboard-item-menu {
  position: fixed;
  width: 240px;
  padding: 10px 12px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 6px 24px rgba(0,0,0,0.35);
  z-index: 1101;
  display: none;
  flex-direction: column;
  gap: 8px;
  box-sizing: border-box;
}
.soundboard-item-menu-title {
  font-size: 12px;
  font-weight: 600;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin-bottom: 2px;
}
.soundboard-item-menu-row {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  min-width: 0;
}
.soundboard-item-menu-label {
  color: var(--text2);
  flex-shrink: 0;
}
.soundboard-item-vol-slider {
  flex: 1 1 0;
  min-width: 0;
  accent-color: var(--accent);
}
.soundboard-item-vol-pct {
  color: var(--text2);
  font-variant-numeric: tabular-nums;
  min-width: 40px;
  text-align: right;
  flex-shrink: 0;
}
.soundboard-item-remove-btn {
  padding: 6px 10px;
  border: 1px solid #c0392b;
  border-radius: 6px;
  background: transparent;
  color: #e74c3c;
  font-size: 12px;
  cursor: pointer;
  margin-top: 2px;
}
.soundboard-item-remove-btn:hover { background: rgba(231,76,60,0.12); }
.soundboard-item-remove-btn:disabled { opacity: 0.6; cursor: not-allowed; }

/* SOUNDBOARD VIEWS (sounds <-> shortcut keys) */
.soundboard-view {
  flex: 1; min-height: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.soundboard-header-actions {
  display: flex; align-items: center; gap: 2px;
}
.soundboard-back-btn,
.soundboard-keys-btn {
  background: none; border: none; color: var(--text2);
  cursor: pointer; padding: 4px 6px; border-radius: 4px;
  display: flex; align-items: center; justify-content: center;
}
.soundboard-back-btn:hover,
.soundboard-keys-btn:hover { background: var(--s2); color: var(--text); }

/* SHORTCUT KEYS VIEW */
.soundboard-keys-view { padding: 0; }
.soundboard-keys-note {
  padding: 8px 12px;
  font-size: 11px;
  color: var(--text3);
  border-bottom: 1px solid var(--border);
  line-height: 1.4;
}
.soundboard-keys-note code {
  font-family: 'DM Mono', ui-monospace, monospace;
  font-size: 10.5px;
  background: var(--s2);
  padding: 1px 5px;
  border-radius: 3px;
  color: var(--text2);
}
.soundboard-keys-list {
  flex: 1; min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 8px 10px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  scrollbar-width: none;
}
.soundboard-keys-list::-webkit-scrollbar { display: none; width: 0; height: 0; }
.soundboard-key-row {
  display: flex; align-items: center; gap: 6px;
  padding: 4px 0;
  min-width: 0;
}
.soundboard-key-name {
  flex: 1; min-width: 0;
  font-size: 12px;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.soundboard-key-binding {
  padding: 4px 10px;
  border: 1px solid var(--border);
  border-radius: 5px;
  background: var(--bg);
  color: var(--text2);
  font-size: 11px;
  font-family: 'DM Mono', ui-monospace, monospace;
  cursor: pointer;
  white-space: nowrap;
  min-width: 90px;
  text-align: center;
  flex-shrink: 0;
}
.soundboard-key-binding:hover { border-color: var(--accent); color: var(--text); }
.soundboard-key-binding.set { color: var(--text); border-color: var(--accent); }
.soundboard-key-binding.capturing { color: var(--accent); border-color: var(--accent); background: var(--s2); }
.soundboard-key-clear {
  width: 22px; height: 22px; padding: 0;
  background: transparent; border: none;
  color: var(--text3); cursor: pointer;
  font-size: 14px; line-height: 1;
  border-radius: 4px;
  flex-shrink: 0;
}
.soundboard-key-clear:hover { background: rgba(0,0,0,0.18); color: var(--text); }
.soundboard-key-clear-placeholder { width: 22px; flex-shrink: 0; }

/* Wayland portal mode: single bulk-bind button at the top of the keys view */
.soundboard-portal-bind-btn {
  margin: 8px 10px 4px;
  padding: 8px 12px;
  border: 1px solid var(--accent);
  border-radius: 6px;
  background: var(--accent);
  color:var(--accent-fg,#fff);
  font-size: 12px;
  font-weight: 500;
  cursor: pointer;
}
.soundboard-portal-bind-btn:hover { filter: brightness(1.1); }
.soundboard-portal-bind-btn:disabled { opacity: 0.6; cursor: not-allowed; }
@media (max-width: 700px) {
  .soundboard-popup { left: 16px; right: 16px; width: auto; bottom: 80px; }
}

/* IMAGE CROPPER */
#cropper-overlay {
  position:fixed; inset:0; z-index:1200;
  background:rgba(0,0,0,.7);
  display:flex; align-items:center; justify-content:center;
  padding:16px;
}
.cropper-modal {
  background:var(--surface); border:1px solid var(--border);
  border-radius:10px; padding:18px;
  display:flex; flex-direction:column; gap:14px;
  max-width:95vw; max-height:95vh;
  box-shadow:0 12px 48px rgba(0,0,0,.4);
}
.cropper-header {
  display:flex; align-items:center; justify-content:space-between;
}
.cropper-title {
  font-size:15px; font-weight:600; color:var(--text);
}
.cropper-close {
  background:none; border:none; color:var(--text2);
  font-size:18px; cursor:pointer; padding:4px 8px;
  border-radius:6px; line-height:1;
}
.cropper-close:hover { background:var(--s2); color:var(--text); }
.cropper-surface {
  position:relative; background:#000;
  border-radius:8px; overflow:hidden;
  touch-action:none; user-select:none;
  cursor:grab;
}
.cropper-surface:active { cursor:grabbing; }
.cropper-surface canvas {
  display:block; width:100%; height:100%;
}
.cropper-frame {
  position:absolute; top:50%; left:50%;
  transform:translate(-50%, -50%);
  pointer-events:none;
  border:2px solid #fff;
  box-shadow:0 0 0 9999px rgba(0,0,0,.55);
}
.cropper-frame.circle { border-radius:50%; }
.cropper-controls {
  display:flex; align-items:center; gap:12px;
}
.cropper-zoom-label {
  font-size:12px; color:var(--text2); flex-shrink:0;
}
.cropper-zoom-slider {
  flex:1; accent-color:var(--accent);
}
.cropper-actions {
  display:flex; gap:8px; justify-content:flex-end;
}
.cropper-btn {
  padding:8px 16px; border-radius:8px;
  font-size:13px; font-weight:500; cursor:pointer;
  border:1px solid var(--border);
}
.cropper-btn-secondary {
  background:var(--bg); color:var(--text);
}
.cropper-btn-secondary:hover { background:var(--s2); }
.cropper-btn-primary {
  background:var(--accent); color:var(--accent-fg,#fff); border-color:var(--accent);
}
.cropper-btn-primary:hover { filter:brightness(1.1); }
.cropper-btn-primary:disabled {
  opacity:.6; cursor:not-allowed;
}

/* PROFILE CARD */
#profile-card-overlay {
  position:fixed; inset:0; z-index:500;
  background:rgba(0,0,0,.55);
  display:flex; align-items:center; justify-content:center;
}
.profile-card {
  position:relative;
  width:340px; border-radius:8px;
  background:var(--surface); border:1px solid var(--border);
  box-shadow:0 8px 40px rgba(0,0,0,.28);
  overflow:hidden;
}
.profile-card-close {
  position:absolute; top:10px; right:12px; z-index:2;
  background:rgba(0,0,0,.45); border:none; color:#fff;
  width:28px; height:28px; border-radius:50%;
  font-size:13px; cursor:pointer; display:flex; align-items:center; justify-content:center;
  transition:background .15s;
}
.profile-card-close:hover { background:rgba(0,0,0,.7); }
.profile-card-banner {
  width:100%; height:110px;
  background:linear-gradient(135deg, var(--accent) 0%, #7c5cbf 100%);
  background-size:cover; background-position:center;
}
.profile-card-avatar-wrap {
  position:relative; margin:-28px 0 0 20px;
  width:56px; height:56px;
}
.profile-card-avatar-wrap .user-avatar,
.profile-card-avatar-wrap img:not(.av-frame-img) {   /* NOT the cosmetic frame overlay */
  width:56px; height:56px; font-size:22px;
  border-radius:50%; object-fit:cover;
}
/* The lift-off-the-banner ring only for a FRAMELESS avatar (a direct child).
   When a cosmetic frame is equipped the avatar sits inside .av-wrap, so it gets
   no ring and the frame is the only decoration. */
.profile-card-avatar-wrap > .user-avatar,
.profile-card-avatar-wrap > img:not(.av-frame-img) {
  border:3px solid var(--surface);
}
.profile-card-body {
  padding:8px 20px 20px;
}
.profile-card-username {
  font-size:17px; font-weight:700; color:var(--text);
  margin-bottom:4px;
}
.pc-pronouns { font-size:12px; font-weight:600; color:var(--text-muted,#888); }
.pc-status { font-size:13px; font-style:italic; color:var(--text,#222); margin-bottom:6px; }
.profile-card-bio {
  font-size:13px; color:var(--text2); margin-bottom:14px;
  min-height:0; line-height:1.5;
}
.profile-card-actions { display:flex; gap:8px; flex-wrap:wrap; margin-top:16px; }

/* CAMERA SETUP MODAL */
#cam-setup-overlay {
  position:fixed; inset:0; z-index:500;
  background:rgba(0,0,0,.55);
  display:flex; align-items:center; justify-content:center;
}
.cam-res-grid {
  display:grid; grid-template-columns:repeat(3,1fr); gap:6px; margin-bottom:4px;
}
.cam-res-tile {
  background:var(--s2); border:2px solid var(--border); border-radius:8px;
  padding:10px 4px; cursor:pointer; display:flex; flex-direction:column;
  align-items:center; gap:3px; transition:border-color .15s;
}
.cam-res-tile:hover { border-color:var(--accent); }
.cam-res-tile.cam-res-selected { border-color:var(--accent); background:var(--s3); }
.cam-res-tile.cam-res-selected .cam-res-name { color:var(--accent); }
.cam-res-name { font-size:13px; font-weight:600; color:var(--text); display:flex; align-items:center; gap:4px; }
.cam-res-sub  { font-size:10px; color:var(--text3); }
.cam-res-max  { font-size:9px; background:var(--accent); color:var(--accent-fg,#fff); border-radius:3px; padding:1px 4px; font-weight:700; }

/* CAMERA SELF-PREVIEW */
#voice-cam-self-preview {
  position:fixed; bottom:80px; right:16px; z-index:800;
  border-radius:10px; overflow:hidden;
  box-shadow:0 4px 20px rgba(0,0,0,.45);
  border:2px solid var(--accent);
  cursor:move; user-select:none;
}
#voice-cam-self-preview video {
  width:192px; height:108px; display:block;
  object-fit:cover; transform:scaleX(-1);
}
.cam-self-close {
  position:absolute; top:5px; right:5px;
  background:rgba(0,0,0,.65); border:none; color:#fff;
  width:22px; height:22px; border-radius:50%;
  cursor:pointer; font-size:17px; line-height:1;
  display:flex; align-items:center; justify-content:center;
}
.cam-self-label {
  position:absolute; bottom:5px; left:7px;
  font-size:10px; color:rgba(255,255,255,.8);
  font-weight:700; letter-spacing:.5px; pointer-events:none;
}

/* SCREEN SHARE SETUP MODAL */
#ss-setup-overlay {
  position:fixed; inset:0; z-index:500;
  background:rgba(0,0,0,.55);
  display:flex; align-items:center; justify-content:center;
}
.ss-setup-modal {
  width:340px; border-radius:9px;
  background:var(--surface); border:1px solid var(--border);
  box-shadow:0 8px 40px rgba(0,0,0,.28);
  padding:20px;
}
.ss-setup-title { font-size:15px; font-weight:600; margin-bottom:14px; }
.ssq-gear-btn {
  background:none; border:1px solid var(--border); border-radius:6px;
  width:36px; height:36px; display:flex; align-items:center; justify-content:center;
  cursor:pointer; color:var(--text2); flex-shrink:0;
  transition:background .15s, color .15s, border-color .15s;
}
.ssq-gear-btn:hover { background:var(--s2); color:var(--text); border-color:var(--accent); }

/* SHARE QUALITY SETTINGS POPUP */
#ss-quality-overlay {
  position:fixed; inset:0; z-index:10000;
  background:rgba(0,0,0,.6);
  display:flex; align-items:center; justify-content:center;
}
.ssq-modal {
  width:440px; max-width:95vw; max-height:88vh;
  border-radius:9px;
  background:var(--surface); border:1px solid var(--border);
  box-shadow:0 12px 48px rgba(0,0,0,.42);
  display:flex; flex-direction:column;
  overflow:hidden;
}
.ssq-header {
  display:flex; align-items:center; justify-content:space-between;
  padding:14px 16px; border-bottom:1px solid var(--border);
}
.ssq-title { font-size:15px; font-weight:600; color:var(--text); }
.ssq-close {
  background:none; border:none; cursor:pointer; color:var(--text2);
  font-size:16px; line-height:1; padding:4px 6px; border-radius:4px;
}
.ssq-close:hover { background:var(--s2); color:var(--text); }
.ssq-body { padding:14px 16px; overflow-y:auto; }
.ssq-section { margin-bottom:16px; }
.ssq-section:last-child { margin-bottom:0; }
.ssq-label {
  display:block; font-size:12px; font-weight:600;
  color:var(--text); margin-bottom:6px;
  letter-spacing:.3px; text-transform:uppercase;
}
.ssq-select, .ssq-num {
  background:var(--bg); border:1px solid var(--border);
  border-radius:6px; padding:8px 10px;
  color:var(--text); font-size:13px; font-family:inherit;
  outline:none;
}
.ssq-select { width:100%; }
.ssq-select:focus, .ssq-num:focus { border-color:var(--accent); }
.ssq-custom-row {
  display:flex; align-items:center; gap:8px; margin-top:8px;
}
.ssq-custom-row .ssq-num { flex:1; min-width:0; width:auto; }
.ssq-x { color:var(--text2); font-size:13px; }
.ssq-unit { color:var(--text2); font-size:12px; }
.ssq-bitrate-row { display:flex; align-items:center; gap:10px; }
.ssq-bitrate-row .ssq-num { flex:1; min-width:0; width:auto; }
.ssq-inline-chk {
  display:flex; align-items:center; gap:6px;
  font-size:13px; color:var(--text); cursor:pointer; user-select:none;
}
.ssq-inline-chk input { cursor:pointer; }
.ssq-hint {
  font-size:11px; color:var(--text2); margin-top:6px; line-height:1.45;
}
.ssq-toggle-row {
  display:flex; align-items:flex-start; gap:10px;
  cursor:pointer;
}
.ssq-toggle-row input { margin-top:3px; cursor:pointer; flex-shrink:0; }
.ssq-toggle-title { font-size:13px; color:var(--text); font-weight:500; }
.ssq-note {
  font-size:11px; color:var(--text2); font-style:italic;
  padding:10px 12px; background:var(--bg); border-radius:6px;
  border-left:3px solid var(--accent);
  line-height:1.5;
}
.ssq-footer {
  display:flex; gap:8px; padding:12px 16px;
  border-top:1px solid var(--border);
  justify-content:space-between;
}
.ssq-footer .btn { padding:8px 14px; }

/* ── PIN BOARD ── */
.chat-view { position:relative; }
/* Drag-and-drop attach overlay (chat.js builds it lazily on the first file drag).
   pointer-events:none so drops fall through to the chat and bubble to the
   #chat-view listeners without the overlay churning enter/leave events. */
#chat-drop-overlay { position:absolute; inset:0; z-index:40; display:none; align-items:center; justify-content:center;
  background:rgba(20,15,8,.42); backdrop-filter:blur(2px); -webkit-backdrop-filter:blur(2px); pointer-events:none; }
#chat-drop-overlay .cdo-box { display:flex; flex-direction:column; align-items:center; gap:10px;
  padding:26px 38px; border:2px dashed var(--accent); border-radius:14px;
  background:var(--surface); color:var(--text); font-weight:600; font-size:15px;
  box-shadow:0 12px 40px -12px rgba(0,0,0,.5); }
/* While a file drag is live, embedded previews (YouTube iframes etc.) must not
   swallow the drop into their own cross-origin document. */
body.file-dragging .chat-messages iframe { pointer-events:none; }
.chat-pin-toggle { margin-left:auto; display:flex; align-items:center; gap:5px; background:none; border:1px solid var(--border); border-radius:6px; color:var(--text2); font-size:12px; padding:4px 10px; cursor:pointer; }
.chat-pin-toggle:hover { background:var(--s2); }
.pin-board { position:absolute; top:48px; right:0; width:260px; height:calc(100% - 48px); background:var(--surface); border-left:1px solid var(--border); display:flex; flex-direction:column; z-index:10; box-shadow:-4px 0 16px rgba(0,0,0,0.12);
  /* slide in/out smoothly: it's an absolute overlay so transform is pure GPU (no reflow). Toggled by .pin-open. */
  transform:translateX(100%); opacity:0; pointer-events:none; will-change:transform; transition:transform .26s cubic-bezier(.16,1,.3,1), opacity .2s ease; }
.pin-board.pin-open { transform:translateX(0); opacity:1; pointer-events:auto; }
@media (prefers-reduced-motion: reduce){ .pin-board { transition:none; } }
.pin-board-header { display:flex; align-items:center; justify-content:space-between; padding:12px 14px; border-bottom:1px solid var(--border); font-size:13px; font-weight:600; color:var(--text); flex-shrink:0; }
.pin-board-body { overflow-y:auto; padding:10px; display:flex; flex-direction:column; gap:10px; flex:1;
  scrollbar-width:thin; scrollbar-color:var(--rust, var(--accent)) transparent; }
/* warm gradient scrollbar (matches the members panel); --honey/--rust fall back to the
   classic accent so it looks right with New look OFF too. */
.pin-board-body::-webkit-scrollbar { width:8px; }
.pin-board-body::-webkit-scrollbar-track { background:transparent; }
.pin-board-body::-webkit-scrollbar-thumb { background:linear-gradient(var(--honey, var(--accent)), var(--rust, var(--accent2)));
  border-radius:99px; border:2px solid transparent; background-clip:padding-box; }
.pin-board-body:hover::-webkit-scrollbar-thumb { filter:brightness(1.08); }
.pin-card { background:var(--bg); border:1px solid var(--border); border-radius:8px; padding:10px; }
.pin-card-p2p { opacity:0.6; }
.pin-card-frozen { border-color:rgba(199,154,58,.45); }
.pin-card-btn { font-size:11px; padding:4px 8px; border:1px solid var(--border); border-radius:4px; background:var(--bg); color:var(--text2); cursor:pointer; }
.pin-card-btn:hover { background:var(--s2); }
.pin-card-btn.pinned { background:var(--abg); border-color:var(--accent); color:var(--accent); }

/* ── EXPIRY BANNER ── */
.expiry-banner { display:flex; align-items:center; gap:10px; background:#3d1f00; border-bottom:1px solid #7a3e00; padding:8px 16px; flex-shrink:0;
  /* Float just below the absolute header (desktop). Reset to in-flow on mobile. */
  position:absolute; top:var(--chat-header-h, 49px); left:0; right:0; z-index:6; }
.expiry-banner-btn { font-size:12px; padding:4px 10px; border:1px solid #f0a030; border-radius:4px; background:transparent; color:#f0a030; cursor:pointer; white-space:nowrap; }
.expiry-banner-btn:hover { background:#7a3e00; }

/* Per-file list, so "Download All / Re-pin All" isn't the only choice. A
   floating panel BELOW the banner rather than growing the banner's own box —
   the banner is position:absolute at the same top offset as --chat-header-h
   with no height reserved for it, so letting it grow would push it over the
   message list without shifting anything to make room. */
.expiry-file-list {
  position:absolute; top:calc(var(--chat-header-h, 49px) + 37px); left:0; right:0; z-index:6;
  max-height:240px; overflow-y:auto;
  background:#2a1500; border-bottom:1px solid #7a3e00;
}
.expiry-file-row { display:flex; align-items:center; gap:10px; padding:7px 16px; font-size:12.5px; border-top:1px solid rgba(240,160,48,.15); }
.expiry-file-row:first-child { border-top:none; }
.expiry-file-name { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; color:#e8d5b8; }
.expiry-file-when { color:#c99a5c; flex-shrink:0; }
.expiry-file-row .expiry-banner-btn { padding:2px 8px; font-size:11px; }

/* ── IMAGE LIGHTBOX ── */
/* touch-action:none hands every touch gesture to the pinch/pan handlers in files.js.
   Without it the browser claims them first and the image can't be panned while zoomed.
   Safe to swallow here because the overlay is a fullscreen viewer with nothing to scroll,
   and it holds regardless of the "Pinch to zoom" Appearance setting, which otherwise
   re-enables page zoom and would fight the lightbox for the same two fingers. */
#img-lightbox { display:none; position:fixed; inset:0; z-index:9999; background:rgba(0,0,0,0.85); backdrop-filter:blur(8px); align-items:center; justify-content:center; cursor:zoom-in; touch-action:none; }
#img-lightbox.open { display:flex; }
#img-lightbox.zoomed { cursor:grab; }
#img-lightbox.zoomed.dragging { cursor:grabbing; }
#img-lightbox img, #img-lightbox video { max-width:90vw; max-height:90vh; object-fit:contain; border-radius:6px; box-shadow:0 8px 40px rgba(0,0,0,0.7); user-select:none; transition:transform 0.15s ease; transform-origin:center center; }
/* One lightbox, two modes: whichever element isn't in use is fully out of the way so it can't
   catch pointer events or hold a decoded frame. */
#img-lightbox video { display:none; }
#img-lightbox.video img { display:none; }
#img-lightbox.video video { display:block; }
/* Copying a video frame to the clipboard is a different feature from copying an image, so the
   button is hidden in video mode rather than silently doing the wrong thing. */
#img-lightbox.video #img-lightbox-copy { display:none; }
/* A zoomed video has its native controls removed (they'd scale with the transform), so the
   grab cursor is the honest affordance there too. */
#img-lightbox.video.zoomed { cursor:grab; }

/* Zoom affordance on a chat video. Always visible rather than hover-only: on a phone there's
   no hover, and the phone is exactly where this matters. */
.video-expand-btn {
  position:absolute; top:8px; right:8px; z-index:2;
  width:32px; height:32px; padding:0; display:flex; align-items:center; justify-content:center;
  border:none; border-radius:8px; cursor:pointer;
  background:rgba(0,0,0,0.55); color:#fff;
  backdrop-filter:blur(4px);
  opacity:0.75; transition:opacity 0.15s ease, background 0.15s ease;
}
.video-expand-btn:hover { opacity:1; background:rgba(0,0,0,0.75); }
/* Touch needs a 44px target (32 is fine for a cursor but is a fat-finger risk next to the
   video's own controls). Grow the button on coarse pointers rather than everywhere, so the
   desktop chrome stays unobtrusive. */
@media (pointer: coarse) {
  .video-expand-btn { width:44px; height:44px; opacity:0.85; }
}
#img-lightbox-controls { position:fixed; top:calc(18px + env(safe-area-inset-top,0px)); right:22px; z-index:10000; display:flex; flex-direction:column; gap:14px; align-items:center; }
.lightbox-btn { width:28px; height:28px; font-size:28px; color:#fff; background:none; border:none; cursor:pointer; opacity:0.7; line-height:1; padding:0; display:flex; align-items:center; justify-content:center; }
.lightbox-btn:hover { opacity:1; }
.lightbox-btn svg { display:block; }

/* ── INLINE FILE MEDIA ── */
.chat-file-img { max-width:300px; max-height:220px; border-radius:8px; display:block; margin-top:6px; cursor:pointer; object-fit:contain; background:var(--s2); }
/* E2E images sit on a 1px placeholder until fetched + decrypted; give the
   pending card a real box so the blur + scanning overlay have room. The class
   drops on reveal, so the decrypted image sizes naturally. */
.chat-file-img.moderation-pending[data-e2e-file] { min-width:220px; min-height:140px; }
.video-preview-wrap {
  position:relative; display:inline-block; margin-top:6px;
  max-width:min(480px, 100%);
  border-radius:10px; overflow:hidden; background:#000;
}
.video-preview {
  display:block; width:100%; height:auto;
  max-width:480px; max-height:360px;
  border-radius:10px; background:#000;
}
/* Codec-failure fallback shown by handleVideoError(). Flex column so the
 * icon + message + download button stack nicely inside the same wrapper. */
.video-err {
  flex-direction:column; align-items:center; justify-content:center;
  gap:6px; padding:24px 18px;
  background:var(--s1); border:1px solid var(--border); border-radius:10px;
  min-width:280px; max-width:420px;
  color:var(--text2);
}
.video-err-icon { font-size:28px; line-height:1; }
.video-err-msg { font-weight:700; font-size:14.5px; color:var(--text); }
.video-err-sub { font-size:12.5px; text-align:center; line-height:1.45; margin-bottom:6px; }
.video-err-dl {
  padding:8px 16px; border-radius:8px;
  background:var(--accent); color:var(--accent-fg,#fff); border:none;
  font:600 13px 'DM Sans',sans-serif; cursor:pointer;
}
.video-err-dl:hover { transform:translateY(-1px); box-shadow:0 2px 8px rgba(42,110,245,.3); }
.chat-msg-file-r2 {
  display:flex; align-items:center; gap:10px;
  background: var(--srv-card-bg, var(--s2));
  color: var(--srv-card-text, var(--text));
  border:1px solid var(--border); border-radius:8px; padding:10px 12px; margin-top:4px; max-width:380px;
}

/* Inline audio message (Studio shares, voice notes, uploaded music) */
.chat-file-audio {
  background: var(--srv-card-bg, var(--s2));
  color: var(--srv-card-text, var(--text));
  border:1px solid var(--border); border-radius:8px;
  padding:8px 10px 10px; margin-top:4px;
  width:min(420px, 100%); box-sizing:border-box;
}
.chat-file-audio-head { display:flex; align-items:center; gap:8px; padding-bottom:6px; }
.chat-file-audio-name {
  flex:1; min-width:0; font-size:13px; font-weight:600;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.chat-file-audio-size { font-size:11.5px; color:var(--text3); flex:0 0 auto; }
.chat-file-audio audio { width:100%; display:block; height:36px; }

/* ── PIN BUTTON ON MESSAGES ── */
/* width:fit-content pins the wrap (and so the stretched pin button below) to the
   media's own rendered width. Without it, an inline-flex box with no explicit
   width can resolve its auto width against the full message row for some aspect
   ratios (very flat/short or very tall/narrow images, where the <img>'s clamped
   render size isn't known ahead of layout) — the button then spans the whole
   message instead of just the image. */
.media-pin-wrap { display:inline-flex; flex-direction:column; align-items:stretch; align-self:flex-start; width:fit-content; max-width:100%; }
.msg-pin-btn { font-size:11px; padding:3px 7px; border:1px solid var(--border); border-radius:4px; background:none; color:var(--text3); cursor:pointer; margin-top:4px; }
.msg-pin-btn:hover { background:var(--s2); color:var(--text2); }
.msg-pin-btn.pinned { color:var(--accent); border-color:var(--accent); }

/* ── SYSTEM MESSAGE ── */
.chat-msg-system { text-align:center; color:var(--text3); font-size:12px; font-style:italic; padding:6px 20px; }
.chat-msg-system span { background:var(--s2); padding:3px 10px; border-radius:10px; }

/* ── MESSAGE HIGHLIGHT ── */
@keyframes msg-highlight { 0%,100%{background:transparent} 30%{background:rgba(42,110,245,0.15)} }
.msg-highlight { animation:msg-highlight 2s ease; }

/* ── YOUTUBE SYNC PANEL ── */
.yt-panel {
  position:fixed; bottom:0; right:20px; width:340px;
  background:var(--surface); border:1px solid var(--border);
  border-radius:10px 10px 0 0; box-shadow:0 -4px 24px rgba(0,0,0,0.25);
  z-index:200; display:flex; flex-direction:column; overflow:hidden;
  max-height:90vh;
}
.yt-panel-header {
  display:flex; align-items:center; justify-content:space-between;
  padding:10px 12px; background:var(--s3); cursor:grab;
  border-bottom:1px solid var(--border); flex-shrink:0; user-select:none;
}
.yt-panel-header:active { cursor:grabbing; }
.yt-panel-title {
  display:flex; align-items:center; gap:8px;
  font-size:13px; font-weight:600; color:var(--text);
}
.yt-panel-actions { display:flex; align-items:center; gap:2px; }
.yt-panel-btn {
  background:none; border:none; color:var(--text3); cursor:pointer;
  padding:3px 6px; border-radius:4px; display:flex; align-items:center; justify-content:center; line-height:1;
}
.yt-panel-btn:hover { background:var(--s2); color:var(--text); }
.yt-player-section { flex-shrink:0; }
.yt-player-wrap {
  position:relative; width:100%; aspect-ratio:16/9; background:#000; overflow:hidden;
}
.yt-player-wrap > div { width:100%; height:100%; }
.yt-player-wrap iframe { width:100% !important; height:100% !important; border:none; }
.yt-player-placeholder {
  position:absolute; inset:0; display:flex; flex-direction:column;
  align-items:center; justify-content:center; gap:8px; background:var(--s2);
}
.yt-controls { padding:7px 10px; border-bottom:1px solid var(--border); flex-shrink:0; }
.yt-controls-row { display:flex; align-items:center; gap:5px; }
.yt-ctrl-btn {
  background:none; border:none; color:var(--text2); cursor:pointer;
  padding:4px; border-radius:4px; display:flex; align-items:center; flex-shrink:0;
}
.yt-ctrl-btn:hover { color:var(--text); background:var(--s2); }
.yt-seek { flex:1; height:4px; cursor:pointer; accent-color:var(--accent); min-width:0; }
.yt-time { font-size:11px; color:var(--text3); font-family:'DM Mono',monospace; white-space:nowrap; flex-shrink:0; }
.yt-vol-row { display:flex; align-items:center; gap:6px; margin-top:5px; }
.yt-clarity-btn { flex-shrink:0; font-size:10px; padding:3px 7px; border-radius:6px; border:1px solid var(--border2);
  background:transparent; color:var(--text3); cursor:pointer; }
.yt-clarity-btn:hover { border-color:var(--text3); color:var(--text2); }
.yt-clarity-btn.on { background:var(--accent); border-color:var(--accent); color:#fff; }
.yt-clarity-btn.busy { opacity:.6; cursor:wait; }
.yt-now-playing-row { display:flex; align-items:center; gap:4px; margin-top:4px; }
.yt-add-pl-btn { background:none; border:none; color:var(--text3); cursor:pointer; padding:2px 3px; border-radius:3px; line-height:1; flex-shrink:0; display:flex; align-items:center; }
.yt-add-pl-btn:hover { color:var(--accent); background:var(--s2); }
.yt-result-btns { display:flex; align-items:center; gap:4px; flex-shrink:0; }
.yt-result-pl-btn { width:22px; height:22px; display:flex; align-items:center; justify-content:center; border-radius:4px; color:var(--text3); cursor:pointer; flex-shrink:0; }
.yt-result-pl-btn:hover { color:var(--accent); background:var(--s3); }
.yt-add-pl-menu { position:absolute; z-index:100; background:var(--s2); border:1px solid var(--s3); border-radius:6px; min-width:160px; max-width:220px; box-shadow:0 4px 12px rgba(0,0,0,.3); overflow:hidden; }
.yt-add-pl-menu-item { padding:7px 12px; font-size:12px; color:var(--text); cursor:pointer; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.yt-add-pl-menu-item:hover { background:var(--s3); }
.yt-add-pl-menu-empty { padding:8px 12px; font-size:12px; color:var(--text3); font-style:italic; }
.yt-now-playing-title {
  font-size:11px; color:var(--text2); flex:1; min-width:0;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.yt-queue-section { flex:1; overflow-y:auto; min-height:0; display:flex; flex-direction:column; }
.yt-section-label {
  font-size:11px; font-weight:600; color:var(--text3); text-transform:uppercase;
  letter-spacing:.5px; padding:0 12px 5px; flex-shrink:0;
}
.yt-queue-list { display:flex; flex-direction:column; flex-shrink:0; }
.yt-queue-item {
  display:flex; align-items:center; gap:8px; padding:6px 12px; position:relative;
}
.yt-queue-item:hover { background:var(--s2); }
.yt-queue-num { font-size:11px; color:var(--text3); width:16px; text-align:right; flex-shrink:0; font-family:'DM Mono',monospace; }
.yt-queue-info { flex:1; min-width:0; }
.yt-queue-item-title { font-size:12px; color:var(--text); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.yt-queue-item-by { font-size:11px; color:var(--text3); }
.yt-queue-remove {
  background:none; border:none; color:var(--text3); cursor:pointer;
  font-size:16px; padding:0 4px; line-height:1; border-radius:3px; display:none; flex-shrink:0;
}
.yt-queue-item:hover .yt-queue-remove.visible { display:block; }
.yt-queue-remove:hover { color:var(--err); }
.yt-queue-empty { font-size:12px; color:var(--text3); padding:4px 12px 8px; font-style:italic; }
.yt-tabs { display:flex; border-bottom:1px solid var(--s3); flex-shrink:0; }
.yt-tab { flex:1; background:none; border:none; border-bottom:2px solid transparent; padding:7px 0; font-size:12px; font-weight:500; color:var(--text3); cursor:pointer; transition:color .15s,border-color .15s; }
.yt-tab:hover { color:var(--text); }
.yt-tab.yt-tab-active { color:var(--accent); border-bottom-color:var(--accent); }
#yt-queue-pane { display:flex; flex-direction:column; flex:1; overflow-y:auto; min-height:0; padding:8px 0 0; }
.yt-save-queue-row { padding:4px 12px 10px; flex-shrink:0; }
.yt-save-queue-btn { width:100%; background:none; border:1px solid var(--s3); color:var(--text3); border-radius:5px; padding:5px; font-size:11px; cursor:pointer; }
.yt-save-queue-btn:hover { background:var(--s2); color:var(--text); }
.yt-pl-header-row { display:flex; align-items:center; justify-content:space-between; padding:6px 12px 4px; flex-shrink:0; }
.yt-pl-new-btn { background:none; border:none; color:var(--accent); font-size:12px; cursor:pointer; padding:2px 4px; border-radius:3px; }
.yt-pl-new-btn:hover { background:var(--s2); }
.yt-pl-list { display:flex; flex-direction:column; flex-shrink:0; padding:0 8px; }
.yt-pl-empty { font-size:12px; color:var(--text3); padding:4px 4px 8px; font-style:italic; }
.yt-pl-row { border-radius:6px; margin-bottom:4px; background:var(--s1); overflow:hidden; }
.yt-pl-row-open { background:var(--s2); }
.yt-pl-row-header { display:flex; align-items:center; gap:6px; padding:7px 8px; }
.yt-pl-row-info { flex:1; min-width:0; }
.yt-pl-row-name { font-size:12px; color:var(--text); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-weight:500; }
.yt-pl-row-meta { font-size:11px; color:var(--text3); }
.yt-pl-row-actions { display:flex; gap:4px; flex-shrink:0; }
.yt-pl-btn { background:none; border:1px solid var(--s3); border-radius:4px; color:var(--text2); font-size:11px; padding:2px 6px; cursor:pointer; white-space:nowrap; }
.yt-pl-btn:hover { background:var(--s3); color:var(--text); }
.yt-pl-btn-del:hover { border-color:var(--err); color:var(--err); }
.yt-pl-items { border-top:1px solid var(--s3); }
.yt-pl-item { display:flex; align-items:center; padding:5px 8px; gap:6px; }
.yt-pl-item:hover { background:var(--s3); }
.yt-pl-item-title { flex:1; font-size:11px; color:var(--text2); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.yt-pl-item-remove { background:none; border:none; color:var(--text3); cursor:pointer; font-size:14px; padding:0 2px; line-height:1; flex-shrink:0; opacity:0; }
.yt-pl-item:hover .yt-pl-item-remove { opacity:1; }
.yt-pl-item-remove:hover { color:var(--err); }
.yt-search-area { padding:8px 12px 10px; flex-shrink:0; }
.yt-search-row { display:flex; gap:6px; margin-bottom:6px; }
.yt-search-input {
  flex:1; padding:6px 10px; border:1px solid var(--border); border-radius:6px;
  background:var(--bg); color:var(--text); font-family:'DM Sans',sans-serif;
  font-size:13px; outline:none;
}
.yt-search-input:focus { border-color:var(--accent); }
.yt-search-btn {
  padding:6px 10px; border:1px solid var(--border); border-radius:6px;
  background:var(--accent); color:var(--accent-fg,#fff); cursor:pointer; display:flex;
  align-items:center; justify-content:center; flex-shrink:0;
}
.yt-search-btn:hover { opacity:.85; }
.yt-search-btn:disabled { opacity:.5; cursor:default; }
.yt-search-results {
  max-height:200px; overflow-y:auto; border:1px solid var(--border);
  border-radius:6px; background:var(--surface);
}
.yt-result-item {
  display:flex; align-items:center; gap:8px; padding:7px 10px;
  cursor:pointer; border-bottom:1px solid var(--border);
}
.yt-result-item:last-child { border-bottom:none; }
.yt-result-item:hover { background:var(--s2); }
.yt-result-thumb { width:60px; height:34px; object-fit:cover; border-radius:3px; flex-shrink:0; background:var(--s2); }
.yt-result-info { flex:1; min-width:0; }
.yt-result-title { font-size:12px; color:var(--text); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.yt-result-channel { font-size:11px; color:var(--text3); }
.yt-result-add { font-size:20px; color:var(--accent); padding:0 4px; flex-shrink:0; font-weight:700; line-height:1; }
.yt-resize-handle {
  position:absolute; bottom:0; right:0; width:16px; height:16px; cursor:se-resize;
}
.yt-resize-handle::after {
  content:''; position:absolute; bottom:3px; right:3px;
  width:9px; height:9px; border-right:2px solid var(--border); border-bottom:2px solid var(--border);
}
.yt-channel-np {
  display:flex; align-items:center; gap:5px; padding:2px 8px 4px 24px;
  font-size:11px; color:var(--accent); cursor:pointer; overflow:hidden;
}
.yt-channel-np:hover { opacity:.8; }
.yt-channel-np-title { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; flex:1; }


/* ── ELECTRON SOURCE PICKER ── */
#electron-source-picker { display:none; position:fixed; inset:0; z-index:9999; align-items:center; justify-content:center; }
#electron-source-picker.esp-visible { display:flex; }
.esp-backdrop { position:absolute; inset:0; background:rgba(0,0,0,.55); }
.esp-modal { position:relative; background:var(--surface); border-radius:9px; width:680px; max-width:95vw; max-height:80vh; display:flex; flex-direction:column; box-shadow:0 8px 40px rgba(0,0,0,.28); overflow:hidden; }
.esp-header { display:flex; align-items:center; justify-content:space-between; padding:16px 18px 12px; border-bottom:1px solid var(--border); flex-shrink:0; }
.esp-title { font-size:15px; font-weight:600; color:var(--text); }
.esp-close { background:none; border:none; cursor:pointer; color:var(--text-muted); font-size:18px; line-height:1; padding:2px 4px; border-radius:4px; }
.esp-close:hover { background:var(--s2); }
.esp-grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(180px,1fr)); gap:10px; padding:14px; overflow-y:auto; }
.esp-item { background:var(--s2); border:2px solid transparent; border-radius:8px; cursor:pointer; padding:8px; display:flex; flex-direction:column; align-items:center; gap:6px; transition:border-color .15s,background .15s; }
.esp-item:hover { background:var(--s3); border-color:var(--accent); }
.esp-item img { width:100%; aspect-ratio:16/9; object-fit:cover; border-radius:4px; background:#000; }
.esp-item span { font-size:11px; color:var(--text); text-align:center; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; width:100%; }
.esp-item.esp-selected { border-color:var(--accent); background:var(--s3); }
.esp-options { display:flex; gap:16px; padding:10px 14px; border-top:1px solid var(--border); flex-shrink:0; }
.esp-chk-row { display:flex; align-items:center; gap:6px; font-size:13px; color:var(--text); cursor:pointer; user-select:none; }
.esp-chk-row input { cursor:pointer; }
.esp-footer { display:flex; gap:8px; padding:12px 14px; border-top:1px solid var(--border); flex-shrink:0; align-items:center; }
.esp-share-btn:disabled { opacity:.45; cursor:not-allowed; }

/* ── SHARED CURSORS ── */
#cursor-layer { font-family:'DM Sans', sans-serif; }
.remote-cursor {
  position:absolute; top:0; left:0;
  transform: translate(0,0);
  transition: transform 60ms linear;
  will-change: transform;
  pointer-events:none;
  filter: drop-shadow(0 1px 2px rgba(0,0,0,.35));
}
.remote-cursor .rc-arrow { display:block; }
.remote-cursor .rc-name {
  display:inline-block;
  margin-left:14px;
  margin-top:-2px;
  padding:2px 6px;
  font-size:10px;
  font-weight:600;
  color:#fff;
  border-radius:4px;
  white-space:nowrap;
  text-shadow: 0 1px 1px rgba(0,0,0,.4);
  line-height:1.2;
}
.rc-pulse {
  position:absolute;
  width:14px; height:14px;
  border-radius:50%;
  transform: translate(-50%,-50%) scale(0.3);
  opacity:0.7;
  pointer-events:none;
  animation: rcPulse 700ms ease-out forwards;
}
@keyframes rcPulse {
  0%   { transform: translate(-50%,-50%) scale(0.3); opacity:0.7; }
  100% { transform: translate(-50%,-50%) scale(3.5); opacity:0;   }
}

/* Synced-popout toggle button */
.popout-sync-btn {
  background:none; border:none; padding:4px 6px; margin:0 2px;
  cursor:pointer; color:var(--text3); border-radius:4px;
  display:inline-flex; align-items:center; justify-content:center;
  line-height:0;
}
.popout-sync-btn:hover { background:var(--s2); color:var(--text); }
.popout-sync-btn.active { color:#43b581; background:rgba(67,181,129,.15); }

/* ── SYNCED POPOUT: peer-grab lock ── */
.popout-drag-lock .yt-panel-header,
.popout-drag-lock .call-grid-header {
  opacity:0.55;
  cursor:not-allowed;
  filter: grayscale(0.6);
}
/* Re-enable interactive controls inside the header so close/popout etc still click */
.popout-drag-lock .yt-panel-actions,
.popout-drag-lock .call-grid-header-btns,
.popout-drag-lock .yt-panel-actions *,
.popout-drag-lock .call-grid-header-btns * {
  opacity:1;
  cursor:pointer;
  filter:none;
}
/* Hide resize handles while a peer is holding the lock */
.popout-drag-lock .cg-rh,
.popout-drag-lock #yt-resize-handle {
  pointer-events:none;
  opacity:0;
}

/* ── SERVER VIEW SYNC ── */
.server-sync-btn {
  background:none; border:none; padding:2px 4px; margin:0 2px;
  cursor:pointer; color:var(--text3); border-radius:4px;
  flex-shrink:0;
  display:inline-flex; align-items:center; justify-content:center;
  line-height:0;
}
.server-sync-btn:hover { background:var(--s2); color:var(--text); }
.server-sync-btn.active { color:#43b581; background:rgba(67,181,129,.15); }

/* Per-viewer "custom design / plain look" toggle (sidebar server-name row). */
.server-theme-toggle-btn {
  position:relative;
  background:none; border:none; padding:2px 4px; margin:0 2px;
  cursor:pointer; color:var(--accent); border-radius:4px;
  flex-shrink:0; display:inline-flex; align-items:center; justify-content:center;
  line-height:0;
}
.server-theme-toggle-btn:hover { background:var(--s2); }
/* Opted out → plain look: dim the palette + strike it to read as "off". */
.server-theme-toggle-btn.off { color:var(--text3); }
.server-theme-toggle-btn.off::after {
  content:''; position:absolute; top:50%; left:50%;
  width:18px; height:2px; margin:-1px 0 0 -9px;
  background:var(--text3); transform:rotate(-45deg); border-radius:2px;
}

.follow-peer-badge {
  position:absolute;
  top:46px;
  left:50%;
  transform:translateX(-50%);
  z-index:50;
  display:none;
  align-items:center;
  gap:4px;
  background:var(--accent);
  color:var(--accent-fg,#fff);
  padding:6px 12px;
  border-radius:6px;
  font-size:12px;
  cursor:pointer;
  box-shadow:0 4px 14px rgba(0,0,0,0.25);
  user-select:none;
}
.follow-peer-badge:hover { filter:brightness(1.1); }


/* ─── SERVER SETTINGS SCREEN ─────────────────────────────────────────── */
.server-settings-screen {
  position: fixed; inset: 0; z-index: 200;
  display: flex; flex-direction: column;
  background: var(--bg); color: var(--text);
}
.server-settings-screen .ss-topbar {
  display: flex; align-items: center; gap: 14px;
  padding: 14px 22px;
  border-bottom: 1px solid var(--border);
  background: var(--surface);
  flex-shrink: 0;
}
.server-settings-screen .ss-topbar h1 {
  font-size: 17px; font-weight: 600; margin: 0;
  font-family: "DM Sans", sans-serif;
}
.server-settings-screen .ss-body {
  flex: 1; display: flex; min-height: 0; overflow: hidden;
}
.server-settings-screen .ss-sidebar {
  width: 220px; flex-shrink: 0;
  border-right: 1px solid var(--border);
  padding: 18px 12px; overflow-y: auto;
  background: var(--surface);
}
.server-settings-screen .ss-tab {
  display: block; width: 100%; text-align: left;
  padding: 8px 12px; margin-bottom: 2px;
  border: none; background: none; cursor: pointer;
  border-radius: 5px; font-size: 13px;
  color: var(--text2); font-family: inherit;
}
.server-settings-screen .ss-tab:hover { background: var(--s2); color: var(--text); }
.server-settings-screen .ss-tab.active { background: var(--accent); color:var(--accent-fg,#fff); }
.server-settings-screen .ss-content {
  flex: 1; overflow-y: auto;
  padding: 26px 36px;
  max-width: 920px;
}
.server-settings-screen h2 {
  font-size: 18px; font-weight: 600; margin: 0 0 16px;
  font-family: "DM Sans", sans-serif;
}
.server-settings-screen h3 {
  font-size: 14px; font-weight: 600; margin: 14px 0 10px;
  text-transform: uppercase; letter-spacing: .5px;
  color: var(--text2);
}
.server-settings-screen .ss-card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 10px; padding: 16px;
  margin-bottom: 14px;
}
.server-settings-screen .ss-row {
  display: flex; align-items: center; gap: 14px;
  padding: 10px 0;
  border-bottom: 1px solid var(--border);
}
.server-settings-screen .ss-row:last-child { border-bottom: none; }
.server-settings-screen .ss-label {
  width: 160px; flex-shrink: 0;
  font-size: 13px; color: var(--text2); font-weight: 500;
}
.server-settings-screen .ss-sub {
  font-size: 12px; color: var(--text3); margin-top: 4px;
}
.server-settings-screen .ss-input {
  padding: 7px 10px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg);
  color: var(--text);
  font-family: "DM Sans", sans-serif;
  font-size: 13px;
  flex: 1;
}
.server-settings-screen .ss-input-tight { padding: 5px 8px; flex: 1 1 auto; min-width: 0; }
.ss-btn {
  padding: 7px 14px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg);
  color: var(--text);
  cursor: pointer;
  font-size: 13px; font-family: inherit;
}
.ss-btn:hover { background: var(--s2); }
.ss-btn-primary { background: var(--accent); color:var(--accent-fg,#fff); border-color:var(--accent); }
.ss-btn-primary:hover { filter: brightness(1.1); }
.ss-btn-danger {
  background: transparent; color: #f04747; border-color: #f04747;
}
.ss-btn-danger:hover { background: rgba(240,71,71,.08); }
.server-settings-screen .ss-mini {
  padding: 4px 8px;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--bg);
  color: var(--text);
  cursor: pointer; font-size: 11px;
}
.server-settings-screen .ss-mini:hover { background: var(--s2); }
.server-settings-screen .ss-mini-danger { color: #f04747; border-color: #f04747; }
.server-settings-screen .ss-mini-danger:hover { background: rgba(240,71,71,.08); }
.server-settings-screen .ss-icon-preview {
  width: 72px; height: 72px;
  border-radius:10px;
  background: var(--accent);
  display: flex; align-items: center; justify-content: center;
  color:var(--accent-fg,#fff); font-size: 30px; font-weight: 600;
  overflow: hidden; flex-shrink: 0;
}
.server-settings-screen .ss-icon-preview img {
  width: 100%; height: 100%; object-fit: cover;
}
.server-settings-screen .ss-ch-row {
  display: flex; align-items: center; gap: 6px;
  padding: 6px 0;
  border-bottom: 1px dashed var(--border);
}
.server-settings-screen .ss-ch-row:last-child { border-bottom: none; }
.server-settings-screen .ss-ch-hash {
  color: var(--text3); font-weight: 600; width: 14px; flex-shrink: 0;
}
.server-settings-screen .ss-role-row {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 0;
  border-bottom: 1px dashed var(--border);
}
.server-settings-screen .ss-role-row:last-child { border-bottom: none; }
.server-settings-screen .ss-role-perms {
  display: flex; gap: 10px; flex-wrap: wrap; align-items: center;
  font-size: 12px; color: var(--text-secondary, #888); margin-left: auto;
}
.server-settings-screen .ss-role-perm {
  display: inline-flex; align-items: center; gap: 4px;
  cursor: pointer; white-space: nowrap;
}
.server-settings-screen .ss-role-color {
  width: 28px; height: 28px;
  border: 1px solid var(--border);
  border-radius: 6px;
  cursor: pointer; padding: 1px;
  background: var(--bg);
}
.server-settings-screen .ss-role-chip {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 2px 8px; border-radius: 10px;
  font-size: 11px; font-weight: 600; color: #fff;
  text-shadow: 0 1px 1px rgba(0,0,0,.4);
}
.server-settings-screen .ss-chip-rm {
  background: none; border: none; color: #fff; cursor: pointer;
  font-size: 12px; line-height: 1; padding: 0; opacity: .8;
}
.server-settings-screen .ss-chip-rm:hover { opacity: 1; }
.server-settings-screen .ss-perm-grid {
  display: flex; flex-direction: column; gap: 4px;
}
.server-settings-screen .ss-perm-row {
  display: grid; grid-template-columns: 1fr 80px 80px;
  align-items: center; gap: 8px; padding: 6px 0;
  border-bottom: 1px dashed var(--border);
}
.server-settings-screen .ss-perm-row:last-child { border-bottom: none; }
.server-settings-screen .ss-perm-head {
  font-size: 11px; color: var(--text3);
  text-transform: uppercase; letter-spacing: .5px;
}
.server-settings-screen .ss-perm-header {
  font-size: 14px; margin-bottom: 8px;
}
.server-settings-screen .ss-member-row {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 8px 0;
  border-bottom: 1px dashed var(--border);
}
.server-settings-screen .ss-member-row:last-child { border-bottom: none; }
.server-settings-screen .ss-member-name {
  font-weight: 500; min-width: 100px;
}
.server-settings-screen .ss-member-roles {
  display: flex; flex-wrap: wrap; gap: 4px; flex: 1; min-width: 100px;
}
.server-settings-screen .ss-badge {
  background: var(--accent); color:var(--accent-fg,#fff);
  font-size: 10px; padding: 2px 7px;
  border-radius: 10px; font-weight: 600;
}
.server-settings-screen .ss-invite-row,
.server-settings-screen .ss-pin-row,
.server-settings-screen .ss-audit-row {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 0;
  border-bottom: 1px dashed var(--border);
  font-size: 13px;
}
.server-settings-screen .ss-invite-row:last-child,
.server-settings-screen .ss-pin-row:last-child,
.server-settings-screen .ss-audit-row:last-child { border-bottom: none; }
.server-settings-screen .ss-pin-name {
  color: var(--accent); text-decoration: none; font-weight: 500;
}
.server-settings-screen .ss-pin-name:hover { text-decoration: underline; }
.server-settings-screen .ss-audit-when {
  color: var(--text3); font-size: 11px; min-width: 140px;
  font-family: "DM Mono", monospace;
}
.server-settings-screen .ss-audit-who {
  font-weight: 500; min-width: 100px;
}
.server-settings-screen .ss-audit-action {
  color: var(--text2); font-family: "DM Mono", monospace;
  font-size: 12px; min-width: 180px;
}
.server-settings-screen .ss-audit-target {
  color: var(--text3); font-size: 12px;
}
.server-settings-screen .ss-danger-card {
  border-color: rgba(240,71,71,.4);
}
.server-settings-screen .ss-danger-card h3 {
  color: #f04747; margin-top: 0;
}
@media (max-width: 700px) {
  .server-settings-screen .ss-body { flex-direction: column; }
  .server-settings-screen .ss-sidebar { width: 100%; max-height: 140px; border-right: none; border-bottom: 1px solid var(--border); display: flex; gap: 6px; overflow-x: auto; }
  .server-settings-screen .ss-tab { flex-shrink: 0; }
  .server-settings-screen .ss-content { padding: 18px; }
  .server-settings-screen .ss-row { flex-direction: column; align-items: flex-start; }
  .server-settings-screen .ss-label { width: 100%; }
}


.server-member-roles-inline {
  display: inline-flex; flex-wrap: wrap; gap: 3px;
  margin-left: 4px;
}
.server-member-role-chip {
  font-size: 9px; padding: 1px 6px;
  border-radius: 9px; color: #fff; font-weight: 600;
  text-shadow: 0 1px 1px rgba(0,0,0,.3);
  white-space: nowrap;
}


/* ─── SERVER-SETTINGS INLINE MODAL ─── */
.ss-modal-overlay {
  position: fixed; inset: 0;
  background: rgba(0,0,0,0.55);
  z-index: 10001;
  display: flex; align-items: center; justify-content: center;
}
.ss-modal {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 22px;
  width: min(420px, 90vw);
  box-shadow: 0 8px 28px rgba(0,0,0,0.4);
  font-family: "DM Sans", sans-serif;
}
.ss-modal-title {
  font-size: 16px; font-weight: 600;
  color: var(--text); margin-bottom: 8px;
}
.ss-modal-msg {
  font-size: 13px; color: var(--text2);
  margin-bottom: 14px; line-height: 1.5;
  white-space: pre-wrap;
}
.ss-modal input[type="text"] {
  width: 100%;
  padding: 9px 12px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface);
  color: var(--text);
  font-family: inherit; font-size: 14px;
  box-sizing: border-box;
}
.ss-modal-actions {
  display: flex; justify-content: flex-end; gap: 8px;
  margin-top: 14px;
}


/* ─── CHANNEL READ-ONLY (no can_send) ─── */
.chat-input-area.chat-input-locked {
  opacity: 0.55;
  pointer-events: none;
  filter: grayscale(0.5);
}
.chat-input-area.chat-input-locked .chat-input,
.chat-input-area.chat-input-locked .chat-attach-btn,
.chat-input-area.chat-input-locked .chat-emoji-btn,
.chat-input-area.chat-input-locked .chat-send-btn {
  cursor: not-allowed;
}
.chat-input-area.chat-input-locked .chat-input {
  background: var(--s2);
  color: var(--text3);
}
.chat-input-lock-msg {
  display: flex; align-items: center; justify-content: center;
  gap: 8px;
  padding: 10px 14px;
  margin: 0 14px 6px;
  background: var(--s2);
  border: 1px dashed var(--border);
  border-radius: 8px;
  font-size: 12px;
  color: var(--text3);
  font-style: italic;
  user-select: none;
}
.chat-input-lock-msg::before {
  content: "🔒";
  font-style: normal;
  font-size: 13px;
}


/* ─── PROFILE CARD ROLES ─── */
.profile-card-roles {
  margin: 10px 16px 0;
  padding-top: 10px;
  border-top: 1px solid var(--border);
}
.profile-card-roles-label {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--text3);
  margin-bottom: 6px;
}
.profile-card-roles-chips {
  display: flex; flex-wrap: wrap; gap: 4px;
}
.profile-card-role-chip {
  display: inline-flex; align-items: center;
  padding: 2px 9px;
  border-radius: 10px;
  font-size: 11px;
  font-weight: 600;
  color: #fff;
  text-shadow: 0 1px 1px rgba(0,0,0,0.3);
  white-space: nowrap;
}

/* ── BAND ── */

/* Band setup modal — instrument picker */
#band-setup-overlay {
  position:fixed; inset:0; z-index:600;
  background:rgba(0,0,0,.55);
  display:flex; align-items:center; justify-content:center;
}
.band-setup-modal {
  width:520px; max-width:95vw; max-height:88vh;
  border-radius:9px;
  background:var(--surface); border:1px solid var(--border);
  box-shadow:0 8px 40px rgba(0,0,0,.32);
  padding:22px;
  display:flex; flex-direction:column;
}
.band-setup-title { font-size:16px; font-weight:600; margin-bottom:6px; }
.band-setup-sub   { font-size:12px; color:var(--text3); margin-bottom:14px; }
.band-builtin-title,
.band-custom-title {
  font-size:11px; text-transform:uppercase; letter-spacing:0.06em;
  color:var(--text2); font-weight:600;
}
.band-custom-section {
  display:flex; flex-direction:column; gap:8px; margin-bottom:14px;
}
.band-custom-section-header {
  display:flex; align-items:center; justify-content:space-between; gap:8px;
}
.band-custom-upload-btn { font-size:12px; padding:5px 10px; }
.band-custom-list {
  display:grid; grid-template-columns:repeat(auto-fill, minmax(108px, 1fr)); gap:8px;
  min-height:24px;
}
.band-custom-empty {
  font-size:12px; color:var(--text3); padding:6px 0; grid-column:1/-1;
}
.band-custom-tile {
  position:relative;
  background:var(--s2); border:2px solid var(--border); border-radius:10px;
  padding:14px 6px; cursor:pointer;
  display:flex; flex-direction:column; align-items:center; gap:6px;
  transition:border-color .15s, transform .1s;
}
.band-custom-tile:hover:not(:disabled) { border-color:var(--accent); transform:translateY(-1px); }
.band-custom-tile:disabled { opacity:0.5; cursor:wait; }
.band-custom-tile.loading { border-color:var(--accent); background:var(--s3); }
.band-custom-tile-emoji { font-size:24px; line-height:1; }
.band-custom-tile-name {
  font-size:12px; color:var(--text); font-weight:500; text-align:center;
  width:100%;
  overflow:hidden; text-overflow:ellipsis;
  display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical;
}
.band-custom-tile-delete {
  position:absolute; top:4px; right:4px;
  width:18px; height:18px;
  background:var(--s3); border:1px solid var(--border); border-radius:50%;
  cursor:pointer; padding:0; line-height:1;
  font-size:11px; color:var(--text2);
  display:flex; align-items:center; justify-content:center;
}
.band-custom-tile-delete:hover { background:#d11; color:#fff; border-color:#d11; }
.band-builtin-title { margin-bottom:6px; }

.band-instrument-grid {
  display:grid; grid-template-columns:repeat(4, 1fr); gap:8px;
}
.band-inst-tile {
  background:var(--s2); border:2px solid var(--border); border-radius:10px;
  padding:14px 6px; cursor:pointer;
  display:flex; flex-direction:column; align-items:center; gap:6px;
  transition:border-color .15s, transform .1s;
}
.band-inst-tile:hover:not(:disabled){ border-color:var(--accent); transform:translateY(-1px); }
.band-inst-tile:disabled { opacity:0.5; cursor:wait; }
.band-inst-tile.loading { border-color:var(--accent); background:var(--s3); }
.band-inst-emoji { font-size:24px; line-height:1; }
.band-inst-label { font-size:12px; color:var(--text); font-weight:500; }

/* Per-member floating panel — uniform layout for self and remote.
 *
 * Two modes:
 *   default (no body class)   — width:560px fixed. Predictable size everywhere.
 *   body.band-scaled-panels   — width clamps to 35vw between 320px and 720px.
 *     Combined with the normalized panel position + cursor coordinates, this
 *     makes cursor positions land on the same key on every screen, regardless
 *     of viewport size. Synced + persisted band-wide via mesh.
 */
.band-mpanel {
  z-index:700;
  width:560px; max-width:95vw;
  background:var(--surface); border:1px solid var(--border);
  border-radius:9px;
  box-shadow:0 8px 40px rgba(0,0,0,.42);
  display:flex; flex-direction:column;
  overflow:hidden;
  user-select:none;
}
/* In scaled mode, each client transforms the panel by --band-scale (set in
 * band.js based on the local viewport relative to a 1920x1080 reference).
 * Layout dimensions stay in fixed px so child elements scale uniformly with
 * the parent. transform-origin:top-left means style.left/top still equal the
 * visual top-left, so position math (drag, broadcasts) is unchanged. */
body.band-scaled-panels .band-mpanel {
  transform: scale(var(--band-scale, 1));
  transform-origin: top left;
}
.band-mpanel-self {
  border-color:var(--accent);
  box-shadow:0 8px 40px rgba(88,101,242,.32);
}
.band-mpanel-header {
  display:flex; align-items:center; justify-content:space-between;
  padding:8px 12px;
  background:var(--s2); border-bottom:1px solid var(--border);
  cursor:move; gap:8px;
}
.band-mpanel-self .band-mpanel-header { background:var(--accent); color:var(--accent-fg,#fff); }
.band-mpanel-self .band-mpanel-name,
.band-mpanel-self .band-mpanel-emoji { color:#fff; }
.band-mpanel-title {
  display:flex; align-items:center; gap:8px;
  flex:0 1 auto; min-width:0;
  font-size:13px; font-weight:600; color:var(--text);
}
/* Center slot — empty (no border) on remote/non-sf2 panels, expands to take
   the spare row width when filled with the preset picker on a self+sf2 panel. */
.band-mpanel-preset {
  flex:0 1 auto; min-width:0;
  display:flex; align-items:center; justify-content:center;
}
.band-mpanel-preset[data-empty="1"] { flex:1 1 auto; }
.band-mpanel-preset:not([data-empty="1"]) { flex:1 1 0; margin:0 4px; }
.band-mpanel-preset-btn {
  display:flex; align-items:center; gap:6px;
  width:100%; min-width:0;
  background:rgba(255,255,255,.18); border:1px solid rgba(255,255,255,.22);
  color:#fff; font-size:12px; font-weight:500;
  padding:4px 8px; border-radius:6px; cursor:pointer;
  transition:background .12s;
}
.band-mpanel:not(.band-mpanel-self) .band-mpanel-preset-btn {
  background:var(--s3); border-color:var(--border); color:var(--text);
}
.band-mpanel-preset-btn:hover { background:rgba(255,255,255,.32); }
.band-mpanel:not(.band-mpanel-self) .band-mpanel-preset-btn:hover { background:var(--s2); }
/* Read-only variant on remote panels — looks the same but not clickable. */
.band-mpanel-preset-readonly { cursor:default; }
.band-mpanel-preset-readonly:hover { background:var(--s3); }
.band-mpanel-self .band-mpanel-preset-readonly:hover { background:rgba(255,255,255,.18); }
.band-mpanel-preset-name {
  flex:1 1 0; min-width:0;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  text-align:left;
}
.band-mpanel-preset-caret { font-size:11px; opacity:0.85; flex-shrink:0; }
.band-mpanel-avatar { width:22px; height:22px; flex-shrink:0; }
.band-mpanel-avatar .voice-avatar-wrap { width:22px; height:22px; }
.band-mpanel-name {
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.band-mpanel-emoji { font-size:16px; line-height:1; flex-shrink:0; }
.band-mpanel-actions { display:flex; align-items:center; gap:6px; flex-shrink:0; }
.band-octave-label, .band-mpanel-octave {
  font-size:10px; padding:3px 7px; border-radius:5px;
  background:rgba(255,255,255,.18); color:#fff;
  font-family:ui-monospace, monospace;
}
.band-mpanel:not(.band-mpanel-self) .band-octave-label,
.band-mpanel:not(.band-mpanel-self) .band-mpanel-octave {
  background:var(--s3); color:var(--text3);
}
.band-mpanel-btn {
  background:rgba(255,255,255,.15); border:none; cursor:pointer;
  color:#fff; font-size:14px; line-height:1;
  width:24px; height:24px; border-radius:5px;
  display:flex; align-items:center; justify-content:center;
}
.band-mpanel:not(.band-mpanel-self) .band-mpanel-btn {
  background:var(--s3); color:var(--text2);
}
.band-mpanel-btn:hover { background:rgba(255,255,255,.32); }
.band-mpanel:not(.band-mpanel-self) .band-mpanel-btn:hover { background:var(--s2); color:var(--text); }
.band-mpanel-close { font-size:16px; }

/* Sync chain button — active state means position-sync is ON for this panel */
.band-mpanel-sync-btn.active { background:rgba(255,255,255,.45); color:#fff; }
.band-mpanel:not(.band-mpanel-self) .band-mpanel-sync-btn.active { background:var(--accent); color:var(--accent-fg,#fff); }
.band-mpanel:not(.band-mpanel-self) .band-mpanel-sync-btn.active:hover { background:var(--accent); opacity:0.85; }

.band-mpanel-body {
  padding:10px 12px;
  background:var(--surface);
}
.band-mpanel-vol {
  display:flex; align-items:center; gap:8px;
  padding:6px 12px 10px;
  background:var(--s1); border-top:1px solid var(--border);
}
.band-mpanel-vol-icon { font-size:14px; }
.band-mpanel-vol-slider { flex:1; }
.band-mpanel-vol-pct {
  font-size:11px; color:var(--text3);
  font-family:ui-monospace, monospace;
  min-width:36px; text-align:right;
}

/* Band Menu master panel — z below member panels so dragged panels are
 * always in front of it (otherwise it visually blocks the bottom-right
 * corner of the viewport on smaller screens). */
.band-menu-panel {
  z-index:650;
  width:280px;
  background:var(--surface); border:1px solid var(--border);
  border-radius:9px;
  box-shadow:0 8px 40px rgba(0,0,0,.42);
  display:flex; flex-direction:column;
  overflow:hidden;
  user-select:none;
}
.band-menu-header {
  display:flex; align-items:center; justify-content:space-between;
  padding:8px 12px;
  background:var(--s2); border-bottom:1px solid var(--border);
  cursor:move; gap:6px;
}
.band-menu-title { font-size:13px; font-weight:600; color:var(--text); }
.band-menu-actions { display:flex; gap:4px; }
.band-menu-btn {
  background:var(--s3); border:none; cursor:pointer;
  color:var(--text2); font-size:11px; padding:3px 8px;
  border-radius:4px;
}
.band-menu-btn:hover { background:var(--accent); color:var(--accent-fg,#fff); }
.band-menu-section { padding:8px 12px; border-bottom:1px solid var(--border); }
.band-menu-section:last-child { border-bottom:none; }
.band-menu-section-label {
  font-size:10px; color:var(--text3);
  text-transform:uppercase; letter-spacing:.5px;
  margin-bottom:6px;
}
.band-menu-members { display:flex; flex-direction:column; gap:4px; }
.band-menu-member {
  display:flex; align-items:center; gap:8px;
  padding:4px 6px; border-radius:6px;
  font-size:12px; color:var(--text);
}
.band-menu-member:hover { background:var(--s2); }
.band-menu-member-avatar { width:20px; height:20px; flex-shrink:0; }
.band-menu-member-avatar .voice-avatar-wrap { width:20px; height:20px; }
.band-menu-member-name { flex:1; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.band-menu-member-emoji { font-size:14px; line-height:1; }
.band-menu-you { color:var(--text3); font-size:10px; }

.band-menu-hidden { display:flex; flex-wrap:wrap; gap:4px; }
.band-menu-hidden-chip {
  display:flex; align-items:center; gap:4px;
  padding:4px 8px;
  background:var(--s3); border:1px solid var(--border);
  border-radius:10px;
  cursor:pointer;
  font-size:11px; color:var(--text);
}
.band-menu-hidden-chip:hover { background:var(--accent); color:var(--accent-fg,#fff); border-color:var(--accent); }

.band-menu-master {
  display:flex; align-items:center; gap:8px;
}
.band-menu-master input[type="range"] { flex:1; }
.band-menu-master span {
  font-size:11px; color:var(--text3);
  font-family:ui-monospace, monospace;
  min-width:36px; text-align:right;
}

.band-menu-toggle {
  display:flex; align-items:center; gap:8px;
  cursor:pointer; font-size:12px; color:var(--text);
}
.band-menu-toggle input[type="checkbox"] { cursor:pointer; }
.band-menu-toggle-label { font-weight:500; }
.band-menu-toggle-sub {
  margin-top:4px; padding-left:22px;
  font-size:10px; color:var(--text3); line-height:1.35;
}

.band-menu-footer { padding:10px 12px; }

/* Post-recording modal — preview + per-file Save buttons */
.band-rec-overlay {
  position:fixed; inset:0;
  z-index:1100;
  background:rgba(0,0,0,.55);
  display:flex; align-items:center; justify-content:center;
  padding:20px;
  animation:bandRecFade .15s ease;
}
@keyframes bandRecFade {
  from { opacity:0; }
  to   { opacity:1; }
}
.band-rec-modal {
  background:var(--surface);
  border:1px solid var(--border);
  border-radius:9px;
  padding:22px;
  max-width:540px; width:100%;
  box-shadow:0 16px 48px rgba(0,0,0,.4);
  display:flex; flex-direction:column;
}
.band-rec-title {
  font-size:18px; font-weight:700;
  color:var(--text);
  margin-bottom:4px;
}
.band-rec-sub {
  font-size:11px; color:var(--text3);
  font-family:monospace;
  margin-bottom:14px;
  word-break:break-all;
}
.band-rec-preview {
  width:100%;
  margin-bottom:14px;
  border-radius:8px;
}
.band-rec-list {
  display:flex; flex-direction:column;
  gap:8px;
  margin-bottom:14px;
}
.band-rec-row {
  display:flex; align-items:center; gap:12px;
  padding:10px 12px;
  background:var(--s2);
  border:1px solid var(--border);
  border-radius:8px;
}
.band-rec-row-info { flex:1; min-width:0; }
.band-rec-row-label { font-size:13px; font-weight:600; color:var(--text); }
.band-rec-row-desc  { font-size:11px; color:var(--text3); margin-top:2px; }
.band-rec-row-meta {
  display:flex; align-items:center; gap:10px;
  flex-shrink:0;
}
.band-rec-row-size {
  font-size:11px; color:var(--text3);
  font-variant-numeric:tabular-nums;
  min-width:50px; text-align:right;
}
.band-rec-row-save {
  padding:6px 14px;
  font-size:12px;
  min-width:64px;
  display:inline-flex; align-items:center; justify-content:center;
}
.band-rec-row-save:disabled { opacity:.55; cursor:default; }
/* After the file has been saved at least once, the button stays clickable
 * so the user can re-trigger the save (e.g. they meant to put it elsewhere,
 * the download was blocked, etc) without losing the recording. The icon
 * communicates "still available, click to re-download". */
.band-rec-row-save.saved {
  min-width:0;
  padding:6px 10px;
  background:var(--accent);
  color:var(--accent-fg,#fff);
}
.band-rec-row-save.saved:hover {
  background:var(--accent2);
  transform:translateY(-1px);
}
.band-rec-row-save.saved svg {
  display:block;
}
.band-rec-footer {
  display:flex; justify-content:flex-end;
  gap:8px;
}
.band-rec-footer .band-rec-discard-armed {
  background:#fee2e2;
  border-color:#fca5a5;
  color:#b91c1c;
}
.band-rec-footer .band-rec-discard-armed:hover {
  background:#fecaca;
}

/* Record button in Band Menu */
.band-record-section { padding-top:10px; }
.band-record-btn {
  width:100%;
  display:flex; align-items:center; justify-content:center; gap:8px;
  padding:8px 12px;
  background:var(--s2); color:var(--text);
  border:1px solid var(--border); border-radius:6px;
  font-size:13px; font-weight:600;
  cursor:pointer;
  transition:background .12s, color .12s, border-color .12s;
}
.band-record-btn:hover { background:var(--s3); }
.band-record-btn.active {
  background:#eb4747; color:#fff; border-color:#eb4747;
}
.band-record-btn.active:hover { background:#d63838; border-color:#d63838; }
.band-record-dot {
  width:10px; height:10px; border-radius:50%;
  background:#eb4747; flex-shrink:0;
}
.band-record-btn.active .band-record-dot {
  background:#fff;
}
.band-record-dot.pulsing { animation:bandRecPulse 1.1s ease-in-out infinite; }
@keyframes bandRecPulse {
  0%, 100% { opacity:1; transform:scale(1); }
  50%      { opacity:.5; transform:scale(.85); }
}

/* Metronome section in Band Menu */
.band-metro-toprow {
  display:flex; align-items:center; gap:10px;
  margin-bottom:6px;
}
.band-metro-on-toggle { flex:1; margin:0; }
.band-metro-pulse {
  width:14px; height:14px; border-radius:50%;
  background:var(--s3); border:1px solid var(--border);
  flex-shrink:0;
  transition:background 80ms ease, transform 80ms ease, box-shadow 80ms ease;
}
.band-metro-pulse.beat {
  background:var(--accent);
  transform:scale(1.15);
}
.band-metro-pulse.downbeat {
  background:#fff;
  border-color:var(--accent);
  transform:scale(1.35);
  box-shadow:0 0 0 3px rgba(88,101,242,.35);
}
body.dark .band-metro-pulse.downbeat { background:#fff; }
.band-metro-row {
  display:flex; align-items:center; gap:8px;
  margin:6px 0;
  font-size:12px; color:var(--text2);
}
.band-metro-side-label {
  flex:0 0 64px;
  font-size:11px; font-weight:500;
  color:var(--text2);
}
.band-metro-slider { flex:1; min-width:0; }   /* range inputs default to min-width:auto, which refuses to shrink under flex:1 and pushes the tempo number past the panel's overflow:hidden edge */
.band-metro-num {
  flex:0 0 36px;
  text-align:right;
  font-variant-numeric:tabular-nums;
  font-weight:600;
  color:var(--text);
}
.band-metro-unit {
  flex:0 0 auto;
  font-size:10px; color:var(--text3);
}

/* Band banner — shown to voice members when a band is active but they aren't in it */
.band-banner {
  position:fixed; top:16px; left:50%;
  transform:translateX(-50%);
  z-index:800;
  background:var(--accent); color:var(--accent-fg,#fff);
  padding:8px 14px 8px 16px; border-radius:24px;
  display:flex; align-items:center; gap:12px;
  box-shadow:0 6px 20px rgba(0,0,0,.32);
  font-size:13px;
  animation:bandBannerIn .25s ease;
}
@keyframes bandBannerIn {
  from { opacity:0; transform:translateX(-50%) translateY(-6px); }
  to   { opacity:1; transform:translateX(-50%) translateY(0); }
}
.band-banner-emoji { font-size:18px; line-height:1; }
.band-banner-text { white-space:nowrap; }
.band-banner-text b { font-weight:700; }
.band-banner-join {
  background:#fff; color:var(--accent);
  border:none; cursor:pointer;
  padding:4px 12px; border-radius:10px;
  font-size:12px; font-weight:600;
}
.band-banner-join:hover { background:rgba(255,255,255,.85); }

/* Piano keyboard */
.band-piano {
  position:relative; width:100%; height:140px;
  background:var(--s3); border-radius:6px;
  user-select:none;
}
/* (No piano-specific rule needed in scaled mode — the parent panel's
 * transform:scale uniformly resizes every child including the piano.) */
.band-piano-readonly .band-pkey { cursor:default; pointer-events:none; }
.band-pkey {
  position:absolute; top:0; bottom:0;
  cursor:pointer;
  display:flex; align-items:flex-end; justify-content:center;
  padding-bottom:6px;
  transition:background .04s, box-shadow .04s;
}
.band-pkey-white {
  background:#fafafa;
  border:1px solid #b8b8b8; border-radius:0 0 4px 4px;
  z-index:1;
}
.band-pkey-white + .band-pkey-white { border-left:none; }
.band-pkey-white:hover { background:#ececec; }
.band-pkey-white.band-key-active { background:var(--accent); border-color:var(--accent); }
.band-pkey-white.band-key-active .band-pkey-label { color:#fff; }
.band-pkey-black {
  top:0; height:62%;
  background:#222; border:1px solid #000; border-radius:0 0 3px 3px;
  z-index:2;
}
.band-pkey-black:hover { background:#3a3a3a; }
.band-pkey-black.band-key-active { background:var(--accent); border-color:var(--accent); }
.band-pkey-label {
  font-size:9px; color:#888; pointer-events:none;
  font-family:ui-monospace, monospace;
}
body.band-no-labels .band-pkey-label { display:none; }

/* Per-user keyboard settings popup — anchored to the gear button on a
   self panel. NOT synced; affects only the local user's typing input. */
.band-settings-popup {
  background:var(--surface); border:1px solid var(--border); border-radius:10px;
  box-shadow:0 8px 32px rgba(0,0,0,.32);
  padding:12px; z-index:1102;
  display:flex; flex-direction:column; gap:12px;
  font-size:13px; color:var(--text);
}
.band-settings-section { display:flex; flex-direction:column; gap:6px; }
.band-settings-label {
  font-size:11px; text-transform:uppercase; letter-spacing:0.04em;
  color:var(--text2); font-weight:600;
}
.band-settings-select {
  background:var(--s2); border:1px solid var(--border); color:var(--text);
  padding:6px 8px; border-radius:6px; font-size:13px;
}
.band-settings-hint {
  font-size:11px; color:var(--text3); line-height:1.4;
}
.band-settings-hint kbd {
  display:inline-block; background:var(--s3); border:1px solid var(--border);
  border-radius:4px; padding:1px 5px; font-family:ui-monospace, monospace;
  font-size:10px; color:var(--text);
}
.band-settings-toggle {
  display:flex; align-items:center; gap:8px; cursor:pointer; font-size:13px;
}
.band-settings-toggle input { width:16px; height:16px; cursor:pointer; }
.band-settings-panic-btn { width:100%; }

/* FX button & popup — reuses .band-settings-popup for outer styling */
.band-mpanel-fx-btn .band-mpanel-fx-label {
  font-size:10px; font-weight:700; letter-spacing:0.04em;
  font-family:ui-monospace, monospace; line-height:1;
}
.band-fx-header {
  font-size:11px; text-transform:uppercase; letter-spacing:0.06em;
  color:var(--text2); font-weight:600; text-align:center;
  border-bottom:1px solid var(--border); padding-bottom:8px; margin-bottom:-4px;
}
.band-fx-row { display:flex; align-items:baseline; justify-content:space-between; gap:8px; }
.band-fx-pct {
  font-size:11px; color:var(--text2);
  font-family:ui-monospace, monospace;
}
.band-fx-slider { width:100%; margin:0; }

/* SF2 preset picker popup — anchored to the header preset button. */
.band-preset-popup .band-fx-header { padding-bottom:6px; margin-bottom:0; }
.band-preset-search {
  width:100%;
  background:var(--s2); border:1px solid var(--border); color:var(--text);
  padding:6px 10px; border-radius:6px; font-size:13px;
}
.band-preset-list {
  display:flex; flex-direction:column; gap:2px;
  max-height:340px; overflow-y:auto;
  margin:0 -4px; padding:0 4px;
}
.band-preset-row {
  display:flex; align-items:center; gap:8px;
  width:100%; text-align:left;
  padding:5px 8px; border-radius:6px;
  background:transparent; border:1px solid transparent; cursor:pointer;
  font-size:12px; color:var(--text);
}
.band-preset-row:hover { background:var(--s2); }
.band-preset-row-active { background:var(--s2); border-color:var(--accent); }
.band-preset-row-num {
  font-family:ui-monospace, monospace; font-size:10px; color:var(--text3);
  min-width:42px; flex-shrink:0;
}
.band-preset-row-name {
  flex:1 1 0; min-width:0;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.band-preset-drum {
  font-size:9px; padding:1px 5px; border-radius:3px;
  background:#d11; color:#fff;
  text-transform:uppercase; letter-spacing:0.04em; font-weight:700;
  flex-shrink:0;
}

/* Drum pads */
.band-pads {
  display:grid; grid-template-columns:repeat(4, 1fr); gap:8px;
}
.band-pad {
  aspect-ratio:1.4 / 1;
  background:var(--s3); border:2px solid var(--border); border-radius:10px;
  cursor:pointer;
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  gap:4px; transition:transform .05s, background .05s, border-color .05s;
  color:var(--text);
}
.band-pad:hover { border-color:var(--accent); }
.band-pad:active,
.band-pad.band-key-active { background:var(--accent); border-color:var(--accent); color:var(--accent-fg,#fff); transform:scale(0.97); }
.band-pad-label { font-size:13px; font-weight:600; }
.band-pad-key {
  font-size:10px; opacity:0.7; font-family:ui-monospace, monospace;
}
.band-pads-readonly .band-pad { cursor:default; opacity:0.85; }
.band-pads-readonly .band-pad:hover { border-color:var(--border); }
.band-pads-readonly .band-pad:active { transform:none; background:var(--s3); color:var(--text); }

/* ── DRAWING ACTIVITY ── */
.draw-app {
  flex:1; min-height:0; min-width:0; background:var(--bg);
  display:flex; flex-direction:column; overflow:hidden;
  position:relative;
}
/* Native fullscreen (kept as a harmless fallback if the OS API is ever used). */
.draw-app:fullscreen, .draw-app:-webkit-full-screen { width:100%; height:100%; background:var(--bg); }
/* The topbar fullscreen button now maximizes via this body class (CSS, like the
   games/streams) instead of the flaky OS Fullscreen API: lift #draw-app out to
   fill the whole window, over the app chrome. Cleared on close (ui.js). */
body.draw-fs { overflow:hidden; }   /* no scrollbar gutter behind the maximized drawing */
body.draw-fs #draw-app {
  position:fixed; inset:0; z-index:9999;
  width:auto; height:auto; max-width:none; max-height:none;
}
/* Split view: drawing takes the full stage by default, even in chat mode. Clicking
   a chat channel FULLY switches to that channel instead (the drawing session stays
   alive in the background, just off-screen — spv2NotifyChannelClicked/
   spv2ShowDrawStage in space-v2.js). This split/compact-strip view is a SEPARATE,
   explicit opt-in: a "side chat" button on the drawing toolbar itself
   (drawToggleSideChat, draw/ui.js) toggles body.draw-split to peek at chat
   alongside the still-visible drawing. draw-fs still wins if both are set
   (position:fixed above takes the panel out of flow). */
body.draw-open.draw-split:not(.draw-fs) #space-v2.smode-chat #draw-app {
  flex:0 0 clamp(180px, 36vh, 420px);
  order:-1;   /* the slot appends #chat-view before #draw-app; draw goes on top */
}
.draw-topbar {
  display:flex; align-items:center; justify-content:space-between;
  padding:6px 10px; background:var(--surface); border-bottom:1px solid var(--border);
  flex-shrink:0; min-height:42px; gap:12px;
}
.draw-topbar-section { display:flex; align-items:center; gap:6px; }
.draw-tb-btn {
  background:none; border:1px solid transparent; color:var(--text);
  padding:5px 9px; border-radius:6px; cursor:pointer; font-size:12px; line-height:1;
  display:inline-flex; align-items:center; justify-content:center; gap:4px;
}
.draw-tb-btn:hover { background:var(--s2); border-color:var(--border); }
.draw-tb-btn:disabled { opacity:.4; cursor:not-allowed; }
.draw-tb-btn-danger { color:var(--err); }
.draw-tb-btn-danger:hover { background:#fef2f2; border-color:#fecaca; }
.draw-tb-btn.active { background:var(--abg); border-color:var(--accent); color:var(--accent); }
.draw-tb-sep { width:1px; height:20px; background:var(--border); margin:0 4px; }
.draw-tb-zoom { font-size:11px; color:var(--text2); min-width:38px; text-align:center; font-variant-numeric:tabular-nums; }
.draw-tb-title { font-size:13px; font-weight:600; margin-left:8px; max-width:200px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.draw-tb-saved { font-size:10px; color:var(--text3); font-style:italic; margin-left:6px; }

.draw-body { flex:1; display:flex; min-height:0; }

.draw-tools {
  /* 106px (was 84px): the editable number inputs need room beside their labels;
     at 84px "Hardness"+input overflowed the column (toolbar shoved, inputs
     clipped). Mobile @media overrides this back to 44px (popover panel). */
  width:106px; flex-shrink:0; background:var(--surface); border-right:1px solid var(--border);
  padding:8px 6px; overflow-y:auto; display:flex; flex-direction:column; gap:6px;
}
.draw-tool-grid { display:grid; grid-template-columns:1fr 1fr; gap:4px; }
.draw-tool-btn {
  aspect-ratio:1; background:var(--s2); border:1px solid var(--border); border-radius:6px;
  cursor:pointer; display:flex; align-items:center; justify-content:center; color:var(--text);
  padding:0; transition:background .08s, border-color .08s;
}
.draw-tool-btn:hover { background:var(--s3); }
.draw-tool-btn.active { background:var(--accent); border-color:var(--accent2); color:var(--accent-fg,#fff); }
.draw-tool-btn svg { width:18px; height:18px; }

.draw-tools-sep { height:1px; background:var(--border); margin:4px 0; }

.draw-color-swatch {
  width:100%; aspect-ratio:1; padding:4px; background:var(--s2); border:1px solid var(--border); border-radius:8px; cursor:pointer;
  position:relative;
}
.draw-color-swatch:hover { border-color:var(--accent); }
.draw-color-swatch-inner {
  display:block; width:100%; height:100%; border-radius:5px;
  background:#000; box-shadow:inset 0 0 0 1px rgba(0,0,0,.15);
}
/* Checkerboard for transparent alpha */
.draw-color-swatch-inner.alpha {
  background-image:
    linear-gradient(45deg, #ddd 25%, transparent 25%),
    linear-gradient(-45deg, #ddd 25%, transparent 25%),
    linear-gradient(45deg, transparent 75%, #ddd 75%),
    linear-gradient(-45deg, transparent 75%, #ddd 75%);
  background-size:8px 8px;
  background-position:0 0, 0 4px, 4px -4px, -4px 0;
}

.draw-brush-props { display:flex; flex-direction:column; gap:10px; }
.draw-brush-prop { display:flex; flex-direction:column; gap:4px; padding:0 2px; box-sizing:border-box; }
.draw-brush-prop label { font-size:10px; color:var(--text2); display:flex; justify-content:space-between; align-items:center; gap:3px; min-width:0; }
.draw-brush-prop label span { color:var(--text3); font-variant-numeric:tabular-nums; }
.draw-brush-prop input[type=range] { width:100%; }
/* Editable value inputs (type a brush value directly; Size can be typed past
   the slider's 200 up to 500). Small right-aligned mono chip, spinner arrows
   hidden. */
.draw-prop-val { display:inline-flex; align-items:center; gap:1px; flex-shrink:0; }
.draw-prop-num {
  width:32px; padding:1px 2px; text-align:right; box-sizing:border-box;
  background:var(--s2); border:1px solid var(--border); border-radius:5px;
  color:var(--text); font-family:'DM Mono', monospace; font-size:11px;
  font-variant-numeric:tabular-nums; appearance:textfield; -moz-appearance:textfield;
}
.draw-prop-num::-webkit-outer-spin-button,
.draw-prop-num::-webkit-inner-spin-button { -webkit-appearance:none; margin:0; }
.draw-prop-num:focus { outline:none; border-color:var(--accent); }
.draw-prop-suffix { color:var(--text3); font-size:9px; }
/* Warm-themed range sliders for the drawing panel (brush props + layer opacity),
   replacing the default OS blue sliders that clashed with the cream/terracotta theme. */
.draw-brush-prop input[type=range],
.draw-layer-meta input[type=range] {
  -webkit-appearance:none; appearance:none; height:4px; border-radius:3px;
  background:var(--s3); outline:none; cursor:pointer; margin:2px 0;
}
.draw-brush-prop input[type=range]::-webkit-slider-thumb,
.draw-layer-meta input[type=range]::-webkit-slider-thumb {
  -webkit-appearance:none; appearance:none; width:13px; height:13px; border-radius:50%;
  background:var(--accent); border:2px solid var(--surface); box-shadow:0 1px 2px rgba(0,0,0,.28); cursor:pointer;
}
.draw-brush-prop input[type=range]::-moz-range-thumb,
.draw-layer-meta input[type=range]::-moz-range-thumb {
  width:13px; height:13px; border-radius:50%; background:var(--accent);
  border:2px solid var(--surface); box-shadow:0 1px 2px rgba(0,0,0,.28); cursor:pointer;
}
.draw-brush-prop input[type=range]:hover::-webkit-slider-thumb,
.draw-layer-meta input[type=range]:hover::-webkit-slider-thumb { background:var(--accent2, var(--accent)); }
.draw-brush-prop input[type=range]:hover::-moz-range-thumb,
.draw-layer-meta input[type=range]:hover::-moz-range-thumb { background:var(--accent2, var(--accent)); }
.draw-brush-prop-row { flex-direction:row; align-items:center; justify-content:space-between; gap:4px; }
.draw-brush-prop-row label { color:var(--text2); }
.draw-brush-prop-row select { background:var(--bg); color:var(--text); border:1px solid var(--border); border-radius:4px; padding:2px 4px; font-size:11px; max-width:60px; }

.draw-viewport {
  /* touch-action:none so browser pinch-zoom and swipe gestures don't fight
     our multi-touch handler in input.js (pinch-to-zoom + 2-finger pan). */
  flex:1; min-width:0; position:relative; background:#3a3a3a; overflow:hidden;
  touch-action:none;
  background-image:
    linear-gradient(45deg, #444 25%, transparent 25%),
    linear-gradient(-45deg, #444 25%, transparent 25%),
    linear-gradient(45deg, transparent 75%, #444 75%),
    linear-gradient(-45deg, transparent 75%, #444 75%);
  background-size:24px 24px;
  background-position:0 0, 0 12px, 12px -12px, -12px 0;
}
.draw-canvas-stage {
  position:absolute; inset:0;
  user-select:none; touch-action:none;
  /* No flex centering here — fitToViewport's panX/panY already center the
     canvas. Adding flex-center would double-position the wrap, causing
     cursor + stroke rendering to disagree with the visual position. */
}
.draw-canvas-wrap {
  position:relative;
  box-shadow:0 8px 40px rgba(0,0,0,.4);
  transform-origin: 0 0;
  touch-action: none;
  background:#fff;
}
.draw-display-canvas {
  display:block; image-rendering:auto;
  background:transparent; cursor:crosshair;
}
.draw-cursor-layer {
  position:absolute; inset:0; pointer-events:none; overflow:visible;
}
.draw-selection-svg {
  position:absolute; inset:0; pointer-events:none; overflow:visible;
  /* Width/height set inline to canvas pixel dims so polygon points map 1:1 */
}
/* 2-row chips: "New" full-width on top (the default), Add/Sub side by side
   below. Three text buttons can't breathe in one row at the ~68px column width,
   so the modifiers drop to their own row where each gets comfortable room. */
.draw-lasso-modes { display:grid; grid-template-columns:1fr 1fr; gap:4px; width:100%; }
.draw-lasso-modes button {
  text-align:center;
  background:var(--surface); color:var(--text2);
  border:1px solid var(--border); border-radius:5px;
  padding:5px 0; font-size:11px; cursor:pointer; line-height:1;
}
.draw-lasso-modes .draw-lasso-new { grid-column:1 / -1; }
.draw-lasso-modes button:hover { background:var(--s2); color:var(--text); }
.draw-lasso-modes button.active { background:var(--accent); color:var(--accent-fg,#fff); border-color:var(--accent); }

.draw-selection-svg .draw-ants-bg {
  stroke:#000; stroke-width:2; vector-effect:non-scaling-stroke;
}
.draw-selection-svg .draw-ants-fg {
  stroke:#fff; stroke-width:2; stroke-dasharray:6 4;
  vector-effect:non-scaling-stroke;
  animation:draw-ants 0.6s linear infinite;
}
@keyframes draw-ants {
  to { stroke-dashoffset:-10; }
}
/* Resize handles for the move tool. Width/height are set inline in canvas
   pixels (HANDLE_SIZE_PX / zoom); vector-effect keeps the stroke at a
   fixed 1.5px on screen so the squares stay readable at any zoom. */
.draw-selection-svg .draw-resize-handle {
  fill:#fff; stroke:#000; stroke-width:1.5;
  vector-effect:non-scaling-stroke;
  pointer-events:none;
}

/* Desktop / mobile visibility helpers. The mobile media query at the
   bottom of the file flips these. Mobile = touch device (pointer:coarse)
   AND viewport width ≤ 950 px (so phone landscape qualifies but iPad
   landscape stays on the desktop layout). */
.draw-tb-mobile-only { display:none; }
.draw-rp-tab-icon { display:none; }
.draw-tools-gear { display:none; }
/* The side-chat peek only means anything against the ui-v2 Space stage (call/
   chat/drawing sharing one slot) — classic's drawing view has no such split
   concept, so hide the toggle there rather than have it silently no-op. */
body:not(.ui-v2) #draw-tb-sidechat { display:none; }

/* The mobile-only "more" menu and the brush-props popover, positioned
   absolutely over the canvas. Visibility is opened in JS by toggling
   display. */
.draw-more-menu {
  position:absolute;
  background:var(--surface);
  border:1px solid var(--border); border-radius:8px;
  box-shadow:0 6px 20px rgba(0,0,0,.3);
  padding:4px;
  z-index:50;
  min-width:140px;
  display:flex; flex-direction:column;
}
.draw-more-item {
  background:none; border:none; color:var(--text); cursor:pointer;
  padding:8px 10px; font-size:12px; text-align:left; border-radius:4px;
}
.draw-more-item:hover { background:var(--s2); }
.draw-more-item-danger { color:var(--err); }
.draw-more-item-danger:hover { background:#fef2f2; }

.draw-brush-props-popover {
  position:absolute; left:50px; bottom:8px;
  background:var(--surface); border:1px solid var(--border);
  border-radius:8px; padding:10px;
  box-shadow:0 6px 20px rgba(0,0,0,.3);
  z-index:50;
  display:flex; flex-direction:column; gap:6px;
  min-width:180px;
}
.draw-local-cursor {
  position:absolute; left:0; top:0;
  width:24px; height:24px;
  pointer-events:none; display:none;
  /* Inverts whatever's underneath via difference blend; opacity 0.7 mutes
     the inversion so it reads as "darker inverse" rather than full-bright. */
  mix-blend-mode:difference;
  opacity:0.7;
  z-index:1;
}
.draw-local-cursor svg { width:100%; height:100%; display:block; }
.draw-app.cursor-active .draw-display-canvas { cursor:none; }
.draw-remote-cursor {
  /* Width/height 0 — this is just the anchor point. Children position
     themselves relative to it. */
  position:absolute; pointer-events:none; width:0; height:0;
  top:0; left:0;
  /* Match regular cursors.js smoothing — 30Hz broadcasts at 60ms transition
     glides between positions instead of jumping. */
  transition: transform 60ms linear;
  will-change: transform;
}
.draw-remote-cursor-ring {
  position:absolute; left:0; top:0;
  transform:translate(-50%, -50%);
  border-radius:50%; border:2px solid currentColor;
  box-shadow:0 0 0 1px rgba(0,0,0,.4);
}
.draw-remote-cursor-name {
  position:absolute; left:0;
  /* top set in JS to (ring radius + 4px) so the chip sits below the ring */
  transform:translateX(-50%);
  font-size:10px; padding:1px 5px; border-radius:3px; color:#fff;
  white-space:nowrap; box-shadow:0 1px 4px rgba(0,0,0,.4); font-weight:600;
}

.draw-empty-state {
  position:absolute; inset:0; display:flex; flex-direction:column;
  align-items:center; justify-content:center; gap:12px; color:var(--text2);
  background:#3a3a3a; pointer-events:auto;
}
.draw-empty-state h3 { color:#ddd; font-size:18px; margin:0; }
.draw-empty-state p { color:#999; font-size:13px; margin:0; max-width:300px; text-align:center; }
.draw-empty-actions { display:flex; gap:8px; margin-top:8px; }

/* Loading overlay shown while crash-recovery replays un-baked effect ops on
   reopen. The PNG snapshot is already painted underneath; this is a light,
   dismissable scrim so the art stays visible while the last few effects fill
   in. Only appears if recovery is slow enough to notice (delayed-show in
   ui.js). Reuses the @keyframes spin from the voice overlay spinner. */
.draw-loading {
  position:absolute; inset:0; z-index:30;
  display:flex; align-items:center; justify-content:center;
  background:rgba(20,18,16,.28);
  opacity:0; pointer-events:none;
  transition:opacity .18s ease;
}
.draw-loading.draw-loading-on { opacity:1; pointer-events:auto; }
.draw-loading-card {
  display:flex; flex-direction:column; align-items:center; gap:12px;
  padding:20px 26px; border-radius:14px;
  background:#2b2724; color:#f3ede4;
  box-shadow:0 8px 28px rgba(0,0,0,.32);
}
.draw-loading-spinner {
  width:34px; height:34px;
  border:3px solid rgba(255,255,255,.16);
  border-top-color:var(--accent, #d08a5e);
  border-radius:50%;
  animation:spin .7s linear infinite;
}
.draw-loading-label { font-size:13px; font-weight:600; letter-spacing:.01em; }

.draw-rightpanel {
  width:240px; flex-shrink:0; background:var(--surface); border-left:1px solid var(--border);
  display:flex; flex-direction:column; min-height:0;
}
.draw-rp-tabs { display:flex; border-bottom:1px solid var(--border); flex-shrink:0; }
.draw-rp-tab {
  flex:1; padding:8px 4px; background:none; border:none; cursor:pointer; font-size:11px;
  color:var(--text2); border-bottom:2px solid transparent;
}
.draw-rp-tab:hover { background:var(--s2); }
.draw-rp-tab-active { color:var(--accent); border-bottom-color:var(--accent); font-weight:600; }
.draw-rp-pane {
  /* Flex column with pinned buttons top and bottom, the layer list
     scrolls internally between them. overflow:hidden on the pane so
     it doesn't double-scroll with the layer list. */
  flex:1; overflow:hidden; padding:8px; min-height:0;
  display:flex; flex-direction:column; gap:6px;
}
.draw-rp-pane > .draw-layer-list {
  flex:1 1 auto; min-height:0; overflow-y:auto;
}
.draw-rp-add-btn {
  background:var(--s2); border:1px dashed var(--border); border-radius:6px; padding:6px;
  cursor:pointer; color:var(--text2); font-size:11px; flex-shrink:0;
}
.draw-rp-add-btn:hover { background:var(--abg); color:var(--accent); border-color:var(--accent); }

.draw-layer-list { display:flex; flex-direction:column-reverse; gap:4px; }
.draw-layer-item {
  display:flex; align-items:center; gap:6px; padding:5px 6px;
  background:var(--s2); border:1px solid var(--border); border-radius:6px;
  cursor:pointer; font-size:12px;
  position:relative;
}
.draw-layer-item:hover { background:var(--s3); }
.draw-layer-item.active { background:var(--abg); border-color:var(--accent); }
.draw-layer-item.dragging { opacity:.4; }
.draw-layer-item.drag-over-top::before,
.draw-layer-item.drag-over-bottom::after {
  content:''; position:absolute; left:0; right:0; height:2px;
  background:var(--accent); border-radius:1px; pointer-events:none;
  box-shadow:0 0 4px var(--accent);
}
.draw-layer-item.drag-over-top::before { top:-2px; }
.draw-layer-item.drag-over-bottom::after { bottom:-2px; }
.draw-layer-thumb {
  width:36px; height:24px; flex-shrink:0; background:#fff;
  background-image:
    linear-gradient(45deg, #ddd 25%, transparent 25%),
    linear-gradient(-45deg, #ddd 25%, transparent 25%),
    linear-gradient(45deg, transparent 75%, #ddd 75%),
    linear-gradient(-45deg, transparent 75%, #ddd 75%);
  background-size:6px 6px;
  background-position:0 0, 0 3px, 3px -3px, -3px 0;
  border:1px solid var(--border); border-radius:3px; overflow:hidden;
  display:block; position:relative;
}
.draw-layer-thumb canvas { width:100%; height:100%; display:block; }
.draw-layer-name {
  flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
  background:none; border:none; padding:0; font:inherit; color:inherit; outline:none;
}
.draw-layer-name:focus { background:var(--bg); border-radius:3px; padding:0 3px; }
.draw-layer-icon-btn {
  background:none; border:none; padding:2px; cursor:pointer; color:var(--text3); border-radius:3px;
  display:inline-flex; align-items:center; justify-content:center;
}
.draw-layer-icon-btn:hover { color:var(--text); background:var(--bg); }
.draw-layer-icon-btn.off { opacity:.35; }
.draw-layer-controls { display:flex; align-items:center; gap:2px; flex-shrink:0; }
.draw-layer-meta { display:flex; align-items:center; gap:4px; padding:0 6px 5px; font-size:10px; color:var(--text3); }
.draw-layer-meta input[type=range] { flex:1; }

.draw-list { display:flex; flex-direction:column; gap:5px; }
.draw-list-item {
  background:var(--s2); border:1px solid var(--border); border-radius:6px;
  padding:6px 26px 6px 8px; cursor:pointer; display:flex; flex-direction:column; gap:2px;
  position:relative;
}
.draw-list-item:hover { background:var(--s3); border-color:var(--accent); }
.draw-list-item.current { background:var(--abg); border-color:var(--accent); }
/* Dedicated drag handle, not the whole row — a full-row touch-drag would
   fight with the list's own vertical scroll gesture. touch-action:none is
   load-bearing: without it the browser can intercept the gesture as a page
   scroll before JS ever sees the pointermove. */
.draw-list-handle {
  position:absolute; top:0; bottom:0; right:0; width:22px;
  display:flex; align-items:center; justify-content:center;
  color:var(--text3); cursor:grab; touch-action:none;
}
.draw-list-handle:hover { color:var(--text); }
.draw-list-handle:active { cursor:grabbing; }
.draw-list-name {
  font-size:12px; font-weight:600; color:var(--text); cursor:text;
  background:none; border:none; padding:0; font-family:inherit; width:100%; outline:none;
}
.draw-list-name:focus { background:var(--bg); border-radius:3px; padding:0 3px; }
.draw-list-meta { font-size:10px; color:var(--text3); display:flex; align-items:center; gap:6px; }
.draw-list-pin { color:var(--accent); cursor:pointer; padding:0; background:none; border:none; }
.draw-list-empty { font-size:11px; color:var(--text3); padding:14px 4px; text-align:center; font-style:italic; }
.draw-list-group-head {
  display:flex; align-items:center; gap:6px; padding:5px 4px 2px; margin-top:4px;
  font-size:11px; font-weight:700; color:var(--text2); cursor:pointer; user-select:none;
  position:relative; border-radius:4px;
}
.draw-list-group-head:first-child { margin-top:0; }
.draw-list-group-caret { color:var(--text3); width:10px; flex:none; }
.draw-list-group-count { color:var(--text3); font-weight:400; }
.draw-list-group-name:hover { color:var(--accent); text-decoration:underline; }

/* Drag-to-sort + drag-to-group (mirrors .draw-layer-item's top/bottom pattern,
   plus a "middle" zone that means "drop here to join/create a group" instead
   of reordering). */
.draw-list-item.dragging { opacity:.4; }
.draw-list-item.drag-over-top::before,
.draw-list-item.drag-over-bottom::after {
  content:''; position:absolute; left:0; right:0; height:2px;
  background:var(--accent); border-radius:1px; pointer-events:none;
  box-shadow:0 0 4px var(--accent);
}
.draw-list-item.drag-over-top::before { top:-3px; }
.draw-list-item.drag-over-bottom::after { bottom:-3px; }
.draw-list-item.drag-over-group,
.draw-list-group-head.drag-over-group {
  background:var(--abg); border-color:var(--accent); outline:2px dashed var(--accent); outline-offset:-2px;
}

.draw-people-list { display:flex; flex-direction:column; gap:4px; }
.draw-people-item { display:flex; align-items:center; gap:6px; padding:4px; font-size:12px; }
.draw-people-color { width:10px; height:10px; border-radius:50%; flex-shrink:0; }
.draw-people-name { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.draw-people-tool { font-size:10px; color:var(--text3); }

.draw-vote-banner {
  position:absolute; left:0; right:0; top:0; padding:8px 14px;
  background:#fff8e1; border-bottom:1px solid #f0c674; color:#7b5d00;
  display:flex; align-items:center; gap:10px; font-size:12px; z-index:10;
  box-shadow:0 2px 6px rgba(0,0,0,.08);
}
.draw-undo-banner {
  position:absolute; left:50%; top:50px; transform:translateX(-50%);
  background:#1a1916; color:#f5f4f0; padding:8px 14px; border-radius:6px;
  font-size:12px; z-index:55; display:flex; align-items:center; gap:10px;
  box-shadow:0 4px 14px rgba(0,0,0,.4);
  animation:draw-undo-slide-in .15s ease-out;
}
.draw-undo-banner .undo-btn {
  padding:3px 10px; background:var(--accent); color:var(--accent-fg,#fff);
  border:0; border-radius:4px; cursor:pointer; font-size:11px; font-weight:600;
}
.draw-undo-banner .undo-btn:hover { background:var(--accent2); }
.draw-undo-banner .dismiss-btn {
  padding:0 4px; background:none; color:#aaa; border:0;
  cursor:pointer; font-size:14px; line-height:1;
}
.draw-undo-banner .dismiss-btn:hover { color:#fff; }
@keyframes draw-undo-slide-in {
  from { opacity:0; transform:translate(-50%, -8px); }
  to   { opacity:1; transform:translate(-50%, 0); }
}
.draw-vote-banner .draw-vote-text { flex:1; }
.draw-vote-banner button { padding:4px 10px; border-radius:4px; cursor:pointer; font-size:11px; border:1px solid transparent; }
.draw-vote-banner .draw-vote-yes { background:var(--ok); color:#fff; border-color:#15803d; }
.draw-vote-banner .draw-vote-no { background:var(--err); color:#fff; border-color:#b91c1c; }

.draw-modal {
  position:fixed; inset:0; background:rgba(0,0,0,.55); z-index:9000;
  display:flex; align-items:center; justify-content:center;
}
.draw-modal-card {
  background:var(--surface); border-radius:var(--r); padding:18px; width:340px; max-width:95vw;
  display:flex; flex-direction:column; gap:10px; box-shadow:var(--shlg);
}
.draw-modal-card h3 { font-size:16px; margin:0 0 4px; }
.draw-modal-card label { font-size:11px; color:var(--text2); display:flex; flex-direction:column; gap:3px; }
.draw-modal-card input, .draw-modal-card select {
  background:var(--bg); border:1px solid var(--border); border-radius:5px; padding:6px 8px; font-size:13px; color:var(--text);
}
.draw-new-custom { display:flex; gap:8px; }
.draw-new-custom label { flex:1; }
.draw-modal-actions { display:flex; gap:8px; justify-content:flex-end; margin-top:6px; }

.draw-picker {
  position:fixed; z-index:9100; background:var(--surface); border:1px solid var(--border);
  border-radius:8px; box-shadow:var(--shlg); padding:0;
}
.draw-picker-card {
  display:grid; grid-template-columns: 200px 20px 20px; grid-template-rows: 160px auto auto;
  gap:8px; padding:10px;
}
.draw-picker-sv-wrap { position:relative; grid-column:1; grid-row:1; }
.draw-picker-h-wrap  { position:relative; grid-column:2; grid-row:1; }
.draw-picker-a-wrap  { position:relative; grid-column:3; grid-row:1; }
.draw-picker-sv-wrap canvas, .draw-picker-h-wrap canvas, .draw-picker-a-wrap canvas {
  display:block; border-radius:4px; cursor:crosshair;
}
.draw-picker-sv-cursor { position:absolute; width:10px; height:10px; border:2px solid #fff; border-radius:50%; box-shadow:0 0 0 1px #000; pointer-events:none; transform:translate(-50%,-50%); }
.draw-picker-h-cursor, .draw-picker-a-cursor {
  position:absolute; left:0; right:0; height:0; border-top:2px solid #fff; box-shadow:0 0 0 1px #000; pointer-events:none;
}
.draw-picker-fields { grid-column:1 / -1; grid-row:2; display:grid; grid-template-columns:repeat(5, 1fr); gap:4px; }
.draw-picker-fields label { font-size:10px; color:var(--text3); display:flex; flex-direction:column; gap:2px; }
.draw-picker-fields input { background:var(--bg); border:1px solid var(--border); border-radius:3px; padding:3px 4px; font-size:11px; min-width:0; width:100%; }
.draw-picker-recents { grid-column:1 / -1; grid-row:3; display:grid; grid-template-columns:repeat(8, 1fr); gap:3px; }
.draw-picker-recent {
  width:100%; aspect-ratio:1; border:1px solid var(--border); border-radius:3px; cursor:pointer; padding:0;
}
.draw-picker-recent:hover { border-color:var(--accent); transform:scale(1.08); }

/* Toast for "Saved 3s ago" indicator inside drawing UI */
.draw-tb-saved.saving { color:var(--accent); }
.draw-tb-saved.error { color:var(--err); }

/* Dark mode */
body.dark .draw-viewport {
  background-image:
    linear-gradient(45deg, #2a2a2a 25%, transparent 25%),
    linear-gradient(-45deg, #2a2a2a 25%, transparent 25%),
    linear-gradient(45deg, transparent 75%, #2a2a2a 75%),
    linear-gradient(-45deg, transparent 75%, #2a2a2a 75%);
}
body.dark .draw-empty-state h3 { color:var(--text); }
body.dark .draw-empty-state p { color:var(--text2); }

/* ─────────────────────────────────────────────────────────────────
   Drawing app — mobile layout
   ─────────────────────────────────────────────────────────────────
   Triggered on touch devices with a viewport width ≤ 950 px. Catches
   phones in both portrait and landscape (Pro Max landscape ≈ 932 px)
   without grabbing iPad landscape (1180 +). Uses orientation overrides
   inside for landscape-specific tweaks (extra-tight top bar, etc).

   Goal: maximum canvas room. Always-visible 44 px left rail + 56 px
   right rail. Brush props live in a popover (gear button). Hidden top-
   bar buttons collapse into a ⋯ menu. Layer add/import collapse into a
   "+" popover. Multi-touch (2-finger) pans and pinches the viewport.
   ───────────────────────────────────────────────────────────────── */
@media (pointer: coarse) and (max-width: 950px){
  .draw-tb-mobile-only { display:inline-flex !important; }
  .draw-tb-desktop-only { display:none !important; }

  .draw-topbar {
    padding:4px 6px; min-height:34px; gap:4px;
  }
  .draw-tb-btn { padding:6px 7px; font-size:12px; }
  .draw-tb-zoom { display:none; }
  .draw-tb-sep { margin:0 2px; }
  .draw-tb-title {
    font-size:11px; max-width:32vw;
    /* On very narrow screens (<420px) drop the title entirely so the
       undo/redo + close buttons fit comfortably. */
  }
  .draw-tb-saved { display:none; }

  .draw-tools {
    width:44px; padding:5px 4px; gap:4px;
  }
  .draw-tool-grid { grid-template-columns:1fr; gap:3px; }
  .draw-tool-btn svg { width:16px; height:16px; }

  /* Brush-props block lives in a popover anchored to the gear button. */
  .draw-brush-props { display:none; }
  .draw-brush-props.draw-brush-props-popover-open {
    /* Class added by JS to convert the inline block into a popover. */
    display:flex;
    position:absolute; left:50px; bottom:12px;
    background:var(--surface); border:1px solid var(--border);
    border-radius:8px; padding:10px;
    box-shadow:0 6px 20px rgba(0,0,0,.3);
    z-index:50;
    flex-direction:column; gap:8px;
    min-width:180px; max-width:240px;
  }
  .draw-tools-gear {
    display:flex !important;
    align-items:center; justify-content:center;
    aspect-ratio:1; width:100%; padding:0;
    background:var(--s2); border:1px solid var(--border); border-radius:6px;
    color:var(--text); cursor:pointer;
    margin-top:auto; /* push to the bottom of the rail */
  }
  .draw-tools-gear.active { background:var(--accent); border-color:var(--accent2); color:var(--accent-fg,#fff); }

  .draw-rightpanel { width:60px; }
  .draw-rp-tabs { padding:0; }
  .draw-rp-tab { padding:6px 0; }
  .draw-rp-tab-text { display:none; }
  .draw-rp-tab-icon { display:inline-block; }
  .draw-rp-pane { padding:5px 4px; gap:4px; }
  .draw-rp-add-btn { font-size:10px; padding:5px; }

  /* Layer items: thumbnail + visibility-only on mobile (no name input,
     no opacity slider — those live in a long-press menu). The actual
     thumbnail keeps its aspect ratio. */
  .draw-layer-item {
    flex-direction:column; padding:3px;
    align-items:stretch; gap:2px;
  }
  .draw-layer-item .draw-layer-thumb { width:100%; }
  .draw-layer-item .draw-layer-name,
  .draw-layer-item .draw-layer-opacity-slider,
  .draw-layer-item .draw-layer-blend-select {
    display:none;
  }

  /* Resize handles: bigger on touch so fingers can grab them. */
  .draw-selection-svg .draw-resize-handle { stroke-width:2; }

  /* Landscape-specific tweaks: top bar even shorter, hide title text. */
  @media (orientation: landscape) and (max-height: 500px){
    .draw-topbar { min-height:30px; padding:2px 4px; }
    .draw-tb-btn { padding:4px 6px; }
    .draw-tb-title { display:none; }
  }
}

/* ── Colorblind correction filters (Settings > Accessibility > Color filter) ──
   Filter defs are injected at runtime by boot.js applyColorFilter (type x
   strength matrix), which also sets these html classes from localStorage.
   Applied to the ROOT element on purpose: a filter on body would re-anchor
   every position:fixed panel (a filtered ancestor turns fixed into absolute),
   but the root is exempt. .cb-media scopes it to media elements instead;
   .moderation-pending is excluded there so the NSFW-scan blur can't be
   overridden (the reported-stream blur already wins on its ID specificity). */
html.cb-prot:not(.cb-media) { filter:url(#cbf-prot); }
html.cb-deut:not(.cb-media) { filter:url(#cbf-deut); }
html.cb-trit:not(.cb-media) { filter:url(#cbf-trit); }
html.cb-achr:not(.cb-media) { filter:url(#cbf-achr); }
html.cb-media.cb-prot :is(img,video,canvas,iframe):not(.moderation-pending) { filter:url(#cbf-prot); }
html.cb-media.cb-deut :is(img,video,canvas,iframe):not(.moderation-pending) { filter:url(#cbf-deut); }
html.cb-media.cb-trit :is(img,video,canvas,iframe):not(.moderation-pending) { filter:url(#cbf-trit); }
html.cb-media.cb-achr :is(img,video,canvas,iframe):not(.moderation-pending) { filter:url(#cbf-achr); }

/* ── Accessibility toggles (Settings > Accessibility; boot.js applyA11yPrefs
      sets these html classes + the --txtscale var from localStorage) ── */
/* underline links: never rely on color alone */
html.a11y-underline a { text-decoration:underline !important; }
/* bold text: raises the BASELINE weight; explicitly weighted UI (600/700/800
   headings, buttons) keeps its own values since inheritance doesn't override */
html.a11y-bold body { font-weight:600; }
html.a11y-bold .chat-msg-content { font-weight:600; }
/* reduced transparency: kill the frosted-glass blurs (translucent surfaces are
   mostly near-opaque already; the blur is what reads as "transparency") */
html.a11y-solid *, html.a11y-solid *::before, html.a11y-solid *::after {
  backdrop-filter:none !important; -webkit-backdrop-filter:none !important; }
html.a11y-solid .badge { background:rgba(0,0,0,.85); }
/* high contrast: strengthen the secondary-text + border tokens (ui-v2 both themes).
   Token overrides, NOT a filter: a contrast() filter on html would collide with
   the colorblind filter (one filter property, last wins). */
html.a11y-contrast body.ui-v2 { --ink2:#4a3e2c; --ink3:#75643f; --line:#c9b48b; --line2:#d6c5a0; --div:rgba(80,68,50,.62); }
html.a11y-contrast body.ui-v2.dark { --ink2:#ddcdae; --ink3:#b4a382; --div:rgba(246,220,180,.30); }
/* dyslexia-friendly font: Atkinson Hyperlegible sitewide (boot.js lazy-loads the
   face). By default server-themed text keeps its custom font; the "Override
   server fonts" toggle (html.a11y-dysfont-srv) beats those too. The exemption
   rules out-specificity the base; the -srv rule out-specificities the server
   theme's `body.srv-whole-ui-font #server-screen *` ID rule (tie + later wins). */
html.a11y-dysfont body, html.a11y-dysfont body * { font-family:'Atkinson Hyperlegible',sans-serif !important; }
html.a11y-dysfont:not(.a11y-dysfont-srv) .chat-msg-content { font-family:var(--srv-msg-font, inherit) !important; }
html.a11y-dysfont:not(.a11y-dysfont-srv) body.srv-whole-ui-font #server-screen,
html.a11y-dysfont:not(.a11y-dysfont-srv) body.srv-whole-ui-font #server-screen * { font-family:var(--srv-ui-font, inherit) !important; }
html.a11y-dysfont.a11y-dysfont-srv body #server-screen * { font-family:'Atkinson Hyperlegible',sans-serif !important; }
/* OpenDyslexic variant (.a11y-dysfont-od): same cascade, stronger face. The
   server-font exemption above still wins on specificity for both faces. */
html.a11y-dysfont.a11y-dysfont-od body, html.a11y-dysfont.a11y-dysfont-od body * { font-family:'OpenDyslexic',sans-serif !important; }
html.a11y-dysfont.a11y-dysfont-od.a11y-dysfont-srv body #server-screen * { font-family:'OpenDyslexic',sans-serif !important; }
/* GIF autoplay off: an opaque tap-to-play cover over the (still moderated) GIF */
.media-pin-wrap.gif-hold { position:relative; }
.media-pin-wrap.gif-hold .gif-cover { position:absolute; inset:0; z-index:3; cursor:pointer;
  border:1px solid var(--border, rgba(255,255,255,.14)); border-radius:10px;
  background:var(--s2, #26262b); color:var(--text2, #b9bdc7);
  font-family:inherit; font-weight:800; font-size:13px; letter-spacing:.04em; }
.media-pin-wrap.gif-hold .gif-cover:hover { color:var(--text, #e8eaef); }
/* auto-dim (flash-guard.js): videos carry an inline brightness() the JS manages;
   images get a body.dark-scoped filter so flipping to light auto-restores them */
.autodim-media { transition:filter .3s ease; }
/* images: the dim is meant to be SEEN arriving - first verdict paints a frame at
   full brightness then glides down (.25s: fast, but visible) */
body.dark img.autodim-img { filter:brightness(var(--adim,1)); transition:filter .25s ease-out; }
/* flash-guard cover (Accessibility > Flash protection; js/flash-guard.js): the
   opaque shield dropped over a video the moment strobing is detected */
.flash-guard-cover { position:absolute; inset:0; z-index:6; display:flex; flex-direction:column;
  align-items:center; justify-content:center; gap:6px; text-align:center; padding:14px;
  background:#151009; border-radius:inherit; }
.flash-guard-cover .fg-t { font-weight:800; font-size:14px; color:#f2e6cf; }
.flash-guard-cover .fg-s { font-size:12px; color:#b7a98d; }
.flash-guard-cover .fg-btns { margin-top:6px; display:flex; gap:7px; flex-wrap:wrap; justify-content:center; }
.flash-guard-cover .fg-btn { border:1px solid rgba(var(--st-rgb),.35); background:transparent;
  color:#e9d9b7; font-family:inherit; font-weight:700; font-size:12.5px; padding:7px 14px; border-radius:8px; cursor:pointer; }
.flash-guard-cover .fg-btn:hover { background:rgba(255,255,255,.07); }

/* ── Content moderation UI ── */
/* Applied to images/videos awaiting receiver-side ViT scan. Removed once
   the scanner returns 'safe'. If 'flagged', the element is replaced with
   a .moderation-flagged-card via JS. */
.moderation-pending {
  filter: blur(24px);
  pointer-events: none;
  transition: filter 200ms ease;
}
.moderation-revealed {
  filter: none;
  pointer-events: auto;
}
.moderation-flagged-card {
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  gap:10px;
  min-height:140px; max-width:380px;
  padding:20px 24px;
  background:var(--s2);
  border:1px solid var(--border);
  border-radius:var(--rsm);
  color:var(--text2);
  font-size:13px;
}
.moderation-flagged-card .mod-icon {
  width:28px; height:28px;
  display:inline-flex; align-items:center; justify-content:center;
  background:var(--s3); border-radius:50%;
  font-size:16px;
}
.moderation-flagged-card .mod-label {
  font-weight:500; color:var(--text);
}
.moderation-flagged-card .mod-sub {
  font-size:11px; color:var(--text3); text-align:center;
}
.moderation-flagged-card .mod-view-btn {
  margin-top:4px;
  padding:6px 14px;
  background:var(--surface);
  border:1px solid var(--border);
  border-radius:var(--rsm);
  color:var(--text);
  cursor:pointer;
  font-size:12px;
}
.moderation-flagged-card .mod-view-btn:hover {
  background:var(--s3);
}

/* "Scanning..." overlay shown over blurred media while the local ViT
   classifier is actively working on it. The anchor (img/video parent
   or wrapper) gets position:relative via JS; this overlay positions
   absolutely at its center. */
.moderation-scanning-overlay {
  position:absolute;
  top:50%; left:50%;
  transform:translate(-50%, -50%);
  background:rgba(0, 0, 0, .65);
  color:#fff;
  padding:6px 12px;
  border-radius:var(--rsm);
  font-size:12px;
  font-weight:500;
  pointer-events:none;
  white-space:nowrap;
  z-index:1;
  letter-spacing:.2px;
}
.moderation-scanning-overlay::after {
  content:'';
  display:inline-block;
  min-width:1.5em;
  text-align:left;
  margin-left:2px;
  animation:mod-scan-dots 1.6s infinite steps(1);
}
@keyframes mod-scan-dots {
  0%   { content:''; }
  25%  { content:'.'; }
  50%  { content:'..'; }
  75%  { content:'...'; }
}

/* ─────────── QUICKSHARE SUB-NAV + FILES SCREEN ─────────── */
.qs-subnav {
  display:flex; gap:6px;
  max-width:520px; margin:0 auto 22px;
  justify-content:center;
}
.qs-pill {
  display:inline-flex; align-items:center; gap:6px;
  padding:7px 14px; border-radius:999px;
  background:var(--surface); border:1px solid var(--border);
  color:var(--text2); font:600 12.5px 'DM Sans',sans-serif;
  cursor:pointer; transition:all .16s;
}
.qs-pill:hover { color:var(--text); border-color:var(--text3); }
.qs-pill.active { background:var(--text); color:#fff; border-color:var(--text); }
body.dark .qs-pill { background:var(--s1); border-color:var(--border); }
body.dark .qs-pill.active { background:var(--accent); border-color:var(--accent); color:var(--accent-fg,#fff); }

/* 68/160 = the old 24/80 plus the 44/80 this screen used to inherit from
   main's padding — keeps the rendered geometry identical. Mobile mirrors the
   compact main padding (24/80 + 28/60). */
#quickshare-files-screen { padding:68px 20px 160px; max-width:880px; margin:0 auto; }
@media (max-width: 700px), (pointer: coarse) and (max-width: 950px) {
  #quickshare-files-screen { padding:52px 20px 140px; }
}
.qf-header {
  display:flex; justify-content:space-between; align-items:flex-start; gap:20px;
  margin-bottom:28px; flex-wrap:wrap;
}
.qf-header h1 { font-size:28px; font-weight:700; letter-spacing:-.8px; margin:0 0 6px; }
.qf-sub { font-size:14px; color:var(--text2); line-height:1.55; max-width:560px; margin:0; }

.qf-create-row { display:flex; gap:8px; flex-shrink:0; flex-wrap:wrap; }
.qf-create-btn {
  display:inline-flex; align-items:center; gap:7px;
  padding:10px 16px; border-radius:10px;
  background:var(--accent); color:var(--accent-fg,#fff); border:none;
  font:600 13.5px 'DM Sans',sans-serif; cursor:pointer;
  box-shadow:0 2px 8px rgba(42,110,245,.25); transition:all .16s;
  flex-shrink:0;
}
.qf-create-btn:hover { transform:translateY(-1px); box-shadow:0 4px 14px rgba(42,110,245,.32); }
.qf-create-btn-folder { background:var(--surface); color:var(--text); border:1px solid var(--border); box-shadow:var(--shsm); }
.qf-create-btn-folder:hover { background:var(--s1); box-shadow:var(--sh); }

.qf-list { display:flex; flex-direction:column; gap:10px; }
.qf-item {
  display:grid; grid-template-columns:auto 1fr auto auto auto;
  gap:14px; align-items:center;
  padding:14px 16px;
  background:var(--surface); border:1px solid var(--border); border-radius:9px;
  box-shadow:var(--shsm);
}
.qf-item-icon {
  width:38px; height:38px; border-radius:9px;
  background:var(--abg); color:var(--accent);
  display:flex; align-items:center; justify-content:center; flex-shrink:0;
}
.qf-item-main { min-width:0; }
.qf-item-name { font-weight:600; font-size:14px; color:var(--text); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.qf-item-meta { font-size:12px; color:var(--text2); margin-top:2px; }
.qf-item-stat {
  display:flex; flex-direction:column; align-items:center; gap:2px;
  padding:0 12px;
}
.qf-item-stat-num { font-weight:700; font-size:15px; color:var(--text); }
.qf-item-stat-label { font-size:10.5px; text-transform:uppercase; letter-spacing:.5px; color:var(--text2); }
.qf-item-copy {
  padding:7px 12px; border-radius:8px;
  background:var(--s1); border:1px solid var(--border); color:var(--text2);
  font:600 12px 'DM Sans',sans-serif; cursor:pointer;
  display:inline-flex; align-items:center; gap:6px;
  transition:all .16s;
}
.qf-item-copy:hover { color:var(--text); border-color:var(--text3); }
.qf-item-copy.copied { background:#1f9d55; color:#fff; border-color:#1f9d55; }

.qf-item-menu-wrap { position:relative; }
.qf-item-menu-btn {
  background:none; border:none; color:var(--text3);
  cursor:pointer; padding:6px 8px; border-radius:6px;
  font-size:17px; line-height:1; letter-spacing:1.5px;
}
.qf-item-menu-btn:hover { background:var(--s2); color:var(--text2); }
.qf-item-menu {
  display:none; position:absolute; right:0; top:calc(100% + 4px);
  background:var(--s1); border:1px solid var(--border); border-radius:8px;
  padding:4px; min-width:160px; z-index:9999;
  box-shadow:0 4px 16px rgba(0,0,0,.25);
}
.qf-item-menu.open { display:block; }
.qf-item-menu-item {
  display:flex; align-items:center; gap:8px; width:100%;
  background:none; border:none; color:var(--text2);
  font:500 13px 'DM Sans',sans-serif;
  padding:8px 10px; border-radius:5px; cursor:pointer;
  text-align:left; white-space:nowrap;
}
.qf-item-menu-item:hover { background:var(--s2); }
.qf-item-menu-item.danger { color:#f04747; }
.qf-item-menu-item.danger:hover { background:rgba(240,71,71,.1); }

.qf-empty {
  text-align:center; padding:60px 20px; color:var(--text2); font-size:14px;
  border:2px dashed var(--border); border-radius:10px;
}
.qf-loggedout { padding:40px 0; }
.qf-loggedout-card {
  max-width:440px; margin:0 auto; padding:36px 28px;
  background:var(--surface); border:1px solid var(--border); border-radius:10px;
  text-align:center; color:var(--text2);
}
.qf-loggedout-card h2 { font-size:20px; color:var(--text); margin:0 0 8px; }
.qf-loggedout-card p { font-size:13.5px; line-height:1.6; margin:0 0 20px; }

/* RECEIVER */
.qf-receive { padding:40px 0; }
.qf-receive-card {
  max-width:480px; margin:0 auto; padding:32px 28px;
  background:var(--surface); border:1px solid var(--border); border-radius:8px;
  box-shadow:var(--sh);
}
.qf-receive-header { display:flex; align-items:center; gap:14px; margin-bottom:24px; color:var(--accent); }
.qf-receive-from { font-weight:700; font-size:17px; color:var(--text); }
.qf-receive-sub { font-size:12.5px; color:var(--text2); margin-top:1px; }
.qf-receive-file {
  padding:18px 16px; background:var(--abg); border-radius:9px;
  margin-bottom:18px;
}
.qf-receive-filename { font-weight:600; font-size:15px; color:var(--text); word-break:break-all; }
.qf-receive-meta { font-size:12.5px; color:var(--text2); margin-top:4px; }
.qf-receive-status {
  font-size:13px; color:var(--text2); text-align:center; margin-bottom:14px;
  display:flex; align-items:center; justify-content:center; gap:8px;
}
.qf-receive-status .qf-dot { width:8px; height:8px; border-radius:50%; background:var(--text3); }
.qf-receive-status.online .qf-dot { background:#1f9d55; box-shadow:0 0 0 3px rgba(31,157,85,.18); }
.qf-receive-btn {
  width:100%; padding:13px; border-radius:8px;
  background:var(--accent); color:var(--accent-fg,#fff); border:none;
  font:700 14.5px 'DM Sans',sans-serif; cursor:pointer;
  transition:all .16s;
}
.qf-receive-btn:hover:not(:disabled) { transform:translateY(-1px); box-shadow:0 4px 14px rgba(42,110,245,.32); }
.qf-receive-btn:disabled { opacity:.45; cursor:not-allowed; }
.qf-receive-footer { text-align:center; margin-top:16px; }
.qf-receive-footer p { font-size:11.5px; color:var(--text2); margin:0; }

/* LINK MODAL */
.qf-modal { position:fixed; inset:0; z-index:10000; display:flex; align-items:center; justify-content:center; }
.qf-modal-backdrop { position:absolute; inset:0; background:rgba(0,0,0,.55); }
.qf-modal-card {
  position:relative; background:var(--surface); border:1px solid var(--border);
  border-radius:8px; padding:28px; max-width:480px; width:calc(100% - 32px);
  box-shadow:0 14px 50px rgba(0,0,0,.32);
}
.qf-modal-card h2 { font-size:20px; margin:0 0 6px; }
.qf-modal-sub { font-size:13px; color:var(--text2); line-height:1.55; margin:0 0 18px; }
.qf-modal-link-row { display:flex; gap:8px; margin-bottom:18px; }
.qf-modal-link-row input {
  flex:1; padding:10px 12px; border-radius:9px;
  background:var(--s1); border:1px solid var(--border); color:var(--text);
  font:500 13px 'DM Mono',monospace;
}
.qf-modal-link-row button {
  padding:10px 16px; border-radius:9px;
  background:var(--accent); color:var(--accent-fg,#fff); border:none;
  font:600 13px 'DM Sans',sans-serif; cursor:pointer;
  min-width:80px;
}
.qf-modal-link-row button.copied { background:#1f9d55; }
.qf-modal-foot { display:flex; justify-content:flex-end; }
.qf-modal-done {
  padding:9px 18px; border-radius:9px;
  background:none; border:1px solid var(--border); color:var(--text2);
  font:600 13px 'DM Sans',sans-serif; cursor:pointer;
}
.qf-modal-done:hover { color:var(--text); border-color:var(--text3); }

@media (max-width: 600px) {
  .qf-header { flex-direction:column; align-items:stretch; }
  .qf-item { grid-template-columns:auto 1fr auto; }
  .qf-item-stat { display:none; }
}

/* MODE PICKER MODAL */
.qf-mode-card { max-width:520px; }
.qf-mode-opt {
  display:flex; gap:12px; padding:14px 14px;
  background:var(--s1); border:1px solid var(--border); border-radius:8px;
  margin-bottom:10px; cursor:pointer;
  transition:all .14s;
}
.qf-mode-opt:hover { border-color:var(--text3); }
.qf-mode-opt input[type=radio] { margin-top:3px; accent-color:var(--accent); flex-shrink:0; }
.qf-mode-opt-body { flex:1; }
.qf-mode-opt-head { display:flex; align-items:center; gap:8px; margin-bottom:3px; }
.qf-mode-opt-title { font-weight:600; font-size:14px; color:var(--text); }
.qf-mode-opt-desc { font-size:12.5px; color:var(--text2); line-height:1.5; }
.qf-mode-badge {
  font-size:10.5px; font-weight:700; letter-spacing:.5px; text-transform:uppercase;
  color:var(--accent); background:var(--abg); padding:2px 8px; border-radius:999px;
}
.qf-mode-opt-recommended {
  border:1.5px solid var(--accent);
  background:linear-gradient(0deg, var(--abg) 0%, var(--surface) 100%);
}
.qf-mode-opt-recommended:hover { border-color:var(--accent); }
.qf-modal-primary {
  padding:9px 18px; border-radius:9px;
  background:var(--accent); color:var(--accent-fg,#fff); border:none;
  font:700 13px 'DM Sans',sans-serif; cursor:pointer; margin-left:8px;
}
.qf-modal-primary:hover { transform:translateY(-1px); box-shadow:0 3px 10px rgba(42,110,245,.3); }
.qf-modal-primary:disabled { opacity:.5; cursor:wait; transform:none; box-shadow:none; }

/* BUNDLE RECEIVE — file list inside the receiver card */
.qf-bundle-actions { display:flex; flex-direction:column; gap:8px; }
.qf-bundle-files {
  display:flex; flex-direction:column; gap:6px;
  max-height:280px; overflow-y:auto;
  padding:6px; background:var(--s1); border:1px solid var(--border); border-radius:10px;
}
.qf-bundle-file-row {
  display:grid; grid-template-columns:1fr auto auto;
  gap:10px; align-items:center;
  padding:8px 10px; border-radius:7px;
  font-size:12.5px;
}
.qf-bundle-file-row:hover { background:var(--s2); }
.qf-bundle-file-name { color:var(--text); word-break:break-all; min-width:0; }
.qf-bundle-file-size { color:var(--text2); font-size:11.5px; white-space:nowrap; }
.qf-bundle-file-btn {
  padding:4px 10px; border-radius:6px;
  background:var(--surface); border:1px solid var(--border); color:var(--text2);
  font:600 11.5px 'DM Sans',sans-serif; cursor:pointer;
}
.qf-bundle-file-btn:hover:not(:disabled) { color:var(--accent); border-color:var(--accent); }
.qf-bundle-file-btn:disabled { opacity:.4; cursor:not-allowed; }

/* Create-link modal needs a primary action button that aligns with the new
 * mode-picker primary. The existing .qf-modal-done is the secondary/cancel. */
#qf-link-modal .qf-modal-foot { gap:8px; }

/* BOOST — pre-send clock-icon button on staging chips + the boost modal */
.ap-boost {
  background:none; border:1px solid var(--border); color:var(--text2);
  cursor:pointer; padding:5px 7px; border-radius:6px;
  display:inline-flex; align-items:center; justify-content:center;
  margin-right:4px; transition:all .14s;
}
.ap-boost:hover { color:var(--accent); border-color:var(--accent); }
.ap-boost.active { color:var(--accent); border-color:var(--accent); background:var(--abg); }
.ap-boost-badge {
  position:absolute; bottom:-4px; right:-4px;
  font-size:9.5px; font-weight:700; letter-spacing:.3px;
  color:var(--accent-fg,#fff); background:var(--accent);
  padding:1px 6px; border-radius:8px;
  white-space:nowrap;
}
.boost-dur-btn.selected {
  border-color:var(--accent); background:var(--abg); color:var(--accent);
}
.boost-file-row {
  display:flex; justify-content:space-between; align-items:center;
  padding:10px 12px; background:var(--s1); border-radius:8px;
  margin-bottom:14px; font-size:13px;
}
.boost-file-name { font-weight:600; color:var(--text); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; max-width:75%; }
.boost-file-size { color:var(--text2); font-size:12.5px; white-space:nowrap; }
.boost-durations {
  display:grid; grid-template-columns:repeat(2, 1fr); gap:8px; margin-bottom:18px;
}
.boost-dur-btn {
  display:flex; flex-direction:column; align-items:flex-start; gap:2px;
  padding:11px 13px; border-radius:9px;
  background:var(--s1); border:1px solid var(--border); color:var(--text);
  font:600 13px 'DM Sans',sans-serif; cursor:pointer; text-align:left;
  transition:all .14s;
}
.boost-dur-btn:hover:not(:disabled) { border-color:var(--accent); background:var(--abg); }
.boost-dur-btn:disabled { opacity:.38; cursor:not-allowed; }
.boost-dur-max { font-size:11px; font-weight:500; color:var(--text2); text-transform:none; letter-spacing:0; }
.boost-dur-btn.busy { opacity:.7; cursor:wait; }
.boost-dur-btn.busy::after {
  content:'…'; margin-left:6px; color:var(--accent);
}

/* ──────────────────────────────────────────────────────────────
   Server appearance (per-server theming) — see js/server-theme.js
   ──────────────────────────────────────────────────────────── */

/* Extend the chat background to fill the whole server view: sidebar,
   members panel, and chat input float on top with backdrop blur. */
body.has-server-theme.srv-bg-extend .server-page-layout {
  background-image:
    linear-gradient(rgba(0,0,0, var(--srv-bg-dim-alpha, 0)), rgba(0,0,0, var(--srv-bg-dim-alpha, 0))),
    var(--srv-chat-bg-image, none);
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}
body.has-server-theme.srv-bg-extend .chat-messages { background-image: none; }
body.has-server-theme.srv-bg-extend .server-channel-bar,
body.has-server-theme.srv-bg-extend .server-members-panel,
body.has-server-theme.srv-bg-extend .chat-input-area {
  background: color-mix(in srgb, var(--bg) 65%, transparent);
  backdrop-filter: blur(var(--srv-extend-blur, 0));
  -webkit-backdrop-filter: blur(var(--srv-extend-blur, 0));
}
/* ── Appearance tab: 2-column grid, controls + sandboxed preview ── */
.ss-appearance {
  display: grid;
  grid-template-columns: minmax(280px, 360px) 1fr;
  gap: 24px; align-items: start;
}
.ss-appearance-controls { display: flex; flex-direction: column; gap: 0; min-width: 0; }
.ss-appearance-row {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 0; border-bottom: 1px solid var(--border);
}
.ss-appearance-row:last-of-type { border-bottom: none; }
/* When a control's precedence switch is showing, drop the row's divider so
   the switch reads as belonging to the control above it, not the row below. */
.ss-appearance-row:has(+ .ss-ws-force:not([hidden])) { border-bottom: none; }
.ss-appearance-row > label {
  flex: 1; font-size: 13px; color: var(--text2); font-weight: 500;
}
.ss-appearance-row input[type="color"] {
  width: 36px; height: 28px; padding: 0;
  border: 1px solid var(--border); border-radius: 6px; cursor: pointer;
  background: transparent;
}
.ss-appearance-row input[type="range"] { width: 130px; }
.ss-appearance-row select {
  font-size: 13px; padding: 5px 8px; border-radius: 6px;
  border: 1px solid var(--border); background: var(--bg); color: var(--text);
  max-width: 160px;
}
.ss-appearance-row input[type="checkbox"] { width: 16px; height: 16px; cursor: pointer; }
.ss-appearance-row .ss-bg-thumb {
  width: 48px; height: 28px; border-radius: 6px;
  background-size: cover; background-position: center;
  border: 1px solid var(--border);
}
.ss-appearance-row .ss-bg-thumb.empty { background: repeating-linear-gradient(45deg, var(--s2) 0 4px, var(--s3) 4px 8px); }
.ss-appearance-reset {
  background: none; border: none; cursor: pointer;
  color: var(--text3); font-size: 14px; padding: 2px 6px;
  border-radius: 4px; line-height: 1;
}
.ss-appearance-reset:hover { color: var(--text); background: var(--s2); }
.ss-appearance-reset[aria-hidden="true"] { visibility: hidden; }

/* Whole-server precedence switch — shown beneath a governing control when a
   per-element tweak conflicts with it. On = whole-server value wins. */
.ss-ws-force {
  display: flex; align-items: center; gap: 8px;
  margin: -4px 0 6px; padding: 5px 10px;
  border-left: 2px solid var(--accent);
  background: color-mix(in srgb, var(--accent) 9%, transparent);
  border-radius: 0 6px 6px 0;
}
.ss-ws-force[hidden] { display: none; }
.ss-ws-force-text { font-size: 12px; color: var(--text2); }
/* The toggle itself. Pure CSS, driven by the hidden checkbox's :checked. */
.ss-switch { position: relative; display: inline-flex; flex-shrink: 0; cursor: pointer; }
.ss-switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.ss-switch-track {
  width: 32px; height: 18px; border-radius: 9px;
  background: var(--s3); transition: background 0.15s;
}
.ss-switch-track::after {
  content: ''; position: absolute; top: 2px; left: 2px;
  width: 14px; height: 14px; border-radius: 50%;
  background: #fff; box-shadow: 0 1px 2px rgba(0,0,0,0.3);
  transition: transform 0.15s;
}
.ss-switch input:checked + .ss-switch-track { background: var(--accent); }
.ss-switch input:checked + .ss-switch-track::after { transform: translateX(14px); }
.ss-switch input:focus-visible + .ss-switch-track { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Preset starter-theme cards (top of the appearance controls). */
.ss-presets-label {
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.05em;
  color: var(--text3); font-weight: 700; margin: 2px 0 6px;
}
.ss-presets { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 12px; }
.ss-preset {
  display: flex; flex-direction: column; align-items: flex-start; gap: 6px;
  flex: 1 1 92px; min-width: 88px;
  padding: 8px 9px; border: 1px solid var(--border); border-radius: 8px;
  background: var(--bg); cursor: pointer; text-align: left;
  transition: border-color 0.12s, transform 0.12s;
}
.ss-preset:hover { border-color: var(--accent); transform: translateY(-1px); }
.ss-preset-dots { display: flex; gap: 3px; }
.ss-preset-dot {
  width: 14px; height: 14px; border-radius: 50%;
  border: 1px solid rgba(0,0,0,0.15);
}
.ss-preset-name { font-size: 12px; font-weight: 600; color: var(--text); }

/* Saved-themes library + export/import (below the presets). */
.ss-theme-library { margin: 4px 0 14px; }
.ss-saved-list { display: flex; flex-direction: column; gap: 5px; margin-bottom: 8px; }
.ss-saved-empty { font-size: 12px; color: var(--text3); line-height: 1.4; padding: 2px 0; }
.ss-saved-theme { display: flex; gap: 6px; align-items: stretch; }
.ss-saved-theme-apply {
  flex: 1; text-align: left; padding: 7px 10px; cursor: pointer;
  background: var(--bg); border: 1px solid var(--border); border-radius: 7px;
  color: var(--text); font-size: 13px; font-weight: 500;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  transition: border-color 0.12s, background 0.12s;
}
.ss-saved-theme-apply:hover { border-color: var(--accent); background: var(--s1); }
.ss-saved-theme-del {
  flex-shrink: 0; width: 30px; cursor: pointer;
  background: var(--bg); border: 1px solid var(--border); border-radius: 7px;
  color: var(--text3); font-size: 13px; line-height: 1;
}
.ss-saved-theme-del:hover { color: #e0483d; border-color: #e0483d; }
.ss-theme-lib-actions { display: flex; flex-wrap: wrap; gap: 6px; }
.ss-theme-lib-actions .ss-btn { flex: 1 1 auto; }

/* Sub-section label inside the element side panel (e.g. "Hover & pressed"). */
.ss-elt-section {
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.05em;
  color: var(--text3); font-weight: 700; margin: 10px 0 2px;
  border-top: 1px solid var(--border); padding-top: 8px;
}
.ss-contrast-warn {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 11px; color: #b45309;
  background: rgba(252, 211, 77, 0.22);
  padding: 2px 7px; border-radius: 4px;
}
.ss-appearance-save-row {
  display: flex; gap: 10px; align-items: center;
  padding-top: 14px; margin-top: 8px;
  border-top: 1px solid var(--border);
}
.ss-appearance-save-row .ss-appearance-msg { font-size: 12px; color: var(--text3); }
.ss-appearance-preview-wrap {
  position: sticky; top: 16px;
  border: 1px solid var(--border); border-radius: 10px;
  background: var(--bg); overflow: hidden;
  min-height: 460px;
  display: flex; flex-direction: column;
}
.ss-appearance-preview-label {
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.05em;
  color: var(--text3); padding: 8px 12px; background: var(--s2);
  border-bottom: 1px solid var(--border);
}
.ss-appearance-preview {
  flex: 1;
  background-image:
    linear-gradient(rgba(0,0,0, var(--srv-bg-dim-alpha, 0)), rgba(0,0,0, var(--srv-bg-dim-alpha, 0))),
    var(--srv-chat-bg-image, none);
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  padding: 12px;
  display: flex; flex-direction: column; gap: 6px;
  font-family: var(--srv-ui-font, inherit);
}
.ss-preview-channel-header {
  font-size: 14px; font-weight: 600;
  color: var(--text); padding: 4px 6px 8px;
  border-bottom: 1px solid var(--border);
}
.ss-preview-msg {
  display: flex; gap: 10px; padding: 6px 10px;
  background: var(--srv-msg-bg, var(--s2));
  border-radius: var(--srv-msg-radius, 8px);
}
.ss-preview-msg-avatar {
  width: 32px; height: 32px; border-radius: 50%;
  background: var(--accent); color:var(--accent-fg,#fff);
  font-size: 13px; font-weight: 600;
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.ss-preview-msg-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.ss-preview-msg-header { display: flex; gap: 8px; align-items: baseline; }
.ss-preview-msg-author { font-size: 13px; font-weight: 600; color: var(--text); }
.ss-preview-msg-time { font-size: 11px; color: var(--text3); }
.ss-preview-msg-content {
  font-size: 14px;
  color: var(--srv-msg-text, var(--text2));
  line-height: 1.4;
  font-family: var(--srv-msg-font, inherit);
}
.ss-preview-msg-content.emoji-only { font-size: 36px; line-height: 1.2; }
.ss-preview-msg-content .mention {
  color: var(--accent); background: rgba(42,110,245,0.18);
  padding: 0 4px; border-radius: 4px;
}
.ss-preview-link-card {
  margin-top: 4px; border-left: 3px solid var(--accent);
  background: var(--srv-card-bg, var(--s3)); padding: 6px 10px;
  font-size: 12px;
  color: var(--srv-card-text, var(--text));
  border-radius: 0 4px 4px 0;
}
.ss-preview-link-card-title { font-weight: 600; color: var(--srv-card-text, var(--text)); margin-bottom: 2px; }
.ss-preview-file-card {
  margin-top: 4px; display: flex; gap: 8px; align-items: center;
  background: var(--srv-card-bg, var(--s2)); border: 1px solid var(--border);
  color: var(--srv-card-text, var(--text));
  border-radius: 6px; padding: 6px 10px; font-size: 12px;
  max-width: 280px;
}
.ss-preview-input-row {
  margin-top: auto; padding: 6px 10px;
  background: var(--s2); border: 1px solid var(--border);
  border-radius: 8px; color: var(--text3); font-size: 13px;
}
@media (max-width: 900px) {
  .ss-appearance { grid-template-columns: 1fr; }
  .ss-appearance-preview-wrap { position: static; }
}

/* ── Phase 2: iframe preview-mode + click-to-pick ────────────────────── */

/* Hide cross-section chrome that isn't part of the server view itself.
   Keep .server-page-topbar + #voice-control-panel so the preview shows
   the full server experience (server name + gear + members icons up top,
   user bar with mute/account-settings down at the bottom-left). */
body.srv-preview-mode > header,
body.srv-preview-mode #header-nav,
body.srv-preview-mode #mobile-sidebar,
body.srv-preview-mode .status-pill,
body.srv-preview-mode .channel-bar-toggle-btn,
body.srv-preview-mode #notif-panel,
body.srv-preview-mode .quickshare-files-screen {
  display: none !important;
}
body.srv-preview-mode #server-screen {
  /* Drop the fixed positioning so the iframe height controls the layout.
     Use 100vh (not 100%): inside the iframe the <body>/<html> heights are
     auto, so height:100% would collapse to content height — breaking the
     definite-height chain that .chat-messages (flex:1; min-height:0) needs
     to scroll. 100vh is the iframe's own viewport height, which is definite. */
  position: static !important;
  height: 100vh !important;
}
body.srv-preview-mode {
  overflow: hidden;
}
/* Disable interactions on controls that would do something inappropriate
   in a read-only preview (open modals, dial voice, send messages). They
   stay visible so the rendered layout matches reality — owners need to see
   exactly what their members will see. */
body.srv-preview-mode #server-settings-btn,
body.srv-preview-mode #members-toggle-btn,
body.srv-preview-mode .server-page-topbar .back-btn,
body.srv-preview-mode .channel-bar-toggle-btn-inline,
body.srv-preview-mode #voice-control-panel button,
body.srv-preview-mode .chat-input-area {
  pointer-events: none !important;
}
/* Keep chat input visible (not dimmed) — owners need to see the bar as it
   actually looks. Just block interaction. */
body.srv-preview-mode .chat-input-area {
  filter: grayscale(0.15);
}
/* ...except while picking an element to theme: every element in the server
   view is a potential target, so pick mode must be able to hover/click all of
   them — including controls the preview otherwise makes inert (top-bar
   buttons, voice-panel buttons, the chat input). The capture-phase pick
   listener swallows the click (preventDefault + stopPropagation), so
   re-enabling pointer events can't trigger any real action. Wins over the
   narrow inert rules above on specificity (carries an id + two classes). */
body.srv-preview-mode.srv-pick-mode #server-screen,
body.srv-preview-mode.srv-pick-mode #server-screen * {
  pointer-events: auto !important;
}

/* Pick-mode visuals inside the iframe. Capture-phase listeners in
   server-theme.js track the hovered themable target and put this class
   on it. */
body.srv-pick-mode, body.srv-pick-mode * { cursor: crosshair !important; }
.srv-pick-hover {
  outline: 2px solid var(--accent) !important;
  outline-offset: -2px;
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 25%, transparent) !important;
}

/* Side panel that appears in the controls column when an element is
   selected inside the iframe. */
.ss-elt-panel {
  margin-top: 12px;
  border: 1px solid var(--accent);
  border-radius: 8px;
  padding: 10px 12px;
  background: color-mix(in srgb, var(--accent) 6%, var(--bg));
}
.ss-elt-panel-head {
  display: flex; align-items: center;
  margin-bottom: 6px;
}
.ss-elt-panel-title {
  flex: 1; font-size: 13px; font-weight: 600;
  color: var(--text);
}
.ss-elt-panel-foot {
  margin-top: 8px; display: flex; justify-content: flex-end;
}
.ss-elt-forced-note {
  font-size: 11.5px; line-height: 1.4; color: var(--text2);
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  border-left: 2px solid var(--accent);
  padding: 6px 9px; border-radius: 0 6px 6px 0; margin-bottom: 8px;
}
/* Slider value shown muted while it's the element's inherited default (unset).
   _ssEltSet removes this class on edit, so an active override reads at full
   strength — the visual cue for "this is your value" vs "this is inherited". */
.ss-elt-val-default { color: var(--text3); opacity: 0.65; }
.ss-elt-image {
  padding: 8px 0; border-top: 1px solid var(--border);
  margin-top: 4px;
}
.ss-elt-image-label {
  font-size: 12px; color: var(--text2); font-weight: 500;
  margin-bottom: 6px;
}
.ss-elt-image-opt {
  display: flex; align-items: center; gap: 6px;
  font-size: 13px; color: var(--text2); padding: 3px 0;
  cursor: pointer;
}
.ss-elt-image-opt input { cursor: pointer; }
.ss-elt-image-row {
  display: flex; align-items: center; gap: 8px;
  margin-top: 6px;
}
/* Element side-panel rows can carry more controls than the basic tab (e.g.
   the compound Border = width slider + value + color). Narrow the sliders so
   a row fits the ~330px toolbar without overflowing horizontally. */
.ss-elt-panel .ss-appearance-row input[type="range"] { width: 84px; }
.ss-elt-panel .ss-appearance-row { gap: 8px; }
.ss-elt-panel .ss-appearance-row select { max-width: 150px; }

/* ── Phase 2 v2: full-page Advanced overlay ──────────────────────────── */

/* When the owner opens the Advanced editor, the Settings screen is hidden
   behind the overlay. The overlay covers the entire viewport. */
body.ss-adv-fullscreen #server-settings-screen { display: none !important; }

.ss-advanced-screen {
  position: fixed; inset: 0; z-index: 250;
  background: var(--bg);
}
/* Iframe wrapper takes everything left of the 360px toolbar. When the host
   window is narrow, the iframe (pinned to its 1100px min-width) overflows
   the wrapper; overflow-x:auto gives horizontal scrolling there. The
   toolbar stays pinned to the viewport's right edge so it's always
   reachable regardless of how narrow the host gets. (Keep `right` here in
   sync with .ss-advanced-toolbar width.) */
.ss-advanced-iframe-wrap {
  position: absolute;
  left: 0; top: 0; bottom: 0;
  right: 360px;
  overflow-x: auto;
  overflow-y: hidden;
}
.ss-advanced-iframe-wrap iframe#ss-advanced-iframe {
  /* Stay above ALL the responsive breakpoints inside the SPA — 700 (channel
     bar + voice panel slide-out), 900 (a11y), 1000 (members-panel goes
     100% width and collapses the chat). 1100 clears them all. */
  min-width: 1100px;
  width: 100%;
  height: 100%;
  border: 0;
  background: var(--bg);
  display: block;
}
.ss-advanced-toolbar {
  position: absolute;
  right: 0; top: 0; bottom: 0;
  width: 360px;
  border-left: 1px solid var(--border);
  background: var(--surface);
  display: flex; flex-direction: column;
  overflow-y: auto;
  padding: 14px 14px 0;
  gap: 8px;
}
.ss-advanced-toolbar-divider {
  height: 1px; background: var(--border);
  margin: 4px -14px;
}
.ss-advanced-toolbar .ss-btn { width: 100%; text-align: left; }
/* ...but buttons that sit INSIDE a control row (the bg Upload/Remove, the
   element-image Upload) must stay compact + inline, not full-width. */
.ss-advanced-toolbar .ss-appearance-row .ss-btn,
.ss-advanced-toolbar .ss-elt-image-row .ss-btn {
  width: auto; text-align: center;
}
.ss-advanced-toolbar .ss-elt-panel { margin-top: 0; }
/* Section headers in the toolbar ("Whole server" / "Selected element"). */
.ss-adv-section-label {
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.05em;
  font-weight: 700; color: var(--text3); margin-top: 2px;
}
/* Clear-all-overrides button: full-width (direct toolbar child) but visually
   secondary, and centered text reads better than the default left-align. */
.ss-adv-clear-btn { text-align: center !important; font-size: 12px; }
.ss-adv-clear-btn:disabled { opacity: 0.5; cursor: default; }
.ss-advanced-toolbar-foot {
  margin-top: auto;
  position: sticky; bottom: 0;
  padding: 12px 0 14px;
  background: linear-gradient(to bottom, transparent, var(--surface) 12px);
}
.ss-advanced-toolbar-foot .ss-btn { margin-bottom: 6px; }
.ss-advanced-toolbar-foot .ss-appearance-msg {
  display: block; text-align: center;
  font-size: 12px; color: var(--text3);
  margin-top: 4px;
}
.ss-advanced-back {
  display: flex; align-items: center; gap: 6px;
}
.ss-advanced-open-btn {
  /* Capped width: the desktop Appearance tab places this directly in the
     full-width settings content, so an uncapped width:100% would stretch the
     whole pane. max-width keeps it a sensibly-sized CTA. */
  width: 100%; max-width: 340px; margin-top: 10px;
  background: var(--accent); color:var(--accent-fg,#fff); border-color: var(--accent);
  padding: 10px 14px; font-size: 14px; font-weight: 600;
}
.ss-advanced-open-btn:hover { filter: brightness(1.1); }
.ss-advanced-mobile-note {
  margin-top: 10px;
  padding: 10px 12px;
  border: 1px dashed var(--border);
  border-radius: 8px;
  font-size: 12px; color: var(--text2);
  text-align: center;
}
@media (max-width: 900px) {
  .ss-advanced-toolbar { width: 260px; padding: 10px 10px 0; }
}

/* ── Platform-admin moderation review screen ── */
#moderation-screen { position: fixed; inset: 0; z-index: 200; background: var(--bg); overflow-y: auto; display: flex; padding-top: env(safe-area-inset-top, 0px); }
.mod-screen-inner { max-width: 900px; margin: 0 auto; padding: 20px 16px 60px; width: 100%; }
.mod-screen-header { display: flex; align-items: center; gap: 12px; margin-bottom: 6px; }
.mod-screen-header h1 { font-size: 22px; margin: 0; }
.mod-count { opacity: .7; font-size: 13px; }
.mod-screen-header .btn:last-child { margin-left: auto; }
.mod-screen-sub { opacity: .65; font-size: 13px; margin: 0 0 18px; }
.mod-list { display: flex; flex-direction: column; gap: 12px; }
.mod-card { background: var(--surface); border: 1px solid var(--border); border-radius: 10px; padding: 14px; }
.mod-card-head { display: flex; align-items: center; gap: 8px; margin-bottom: 4px; }
.mod-badge { font-size: 11px; padding: 2px 8px; border-radius: 999px; text-transform: uppercase; letter-spacing: .04em; color: #fff; }
.mod-badge-q { background: #b8860b; }
.mod-badge-csam { background: var(--danger, #c0392b); }
.mod-badge-urgent { background: var(--danger, #c0392b); }
.mod-card-urgent { border-color: var(--danger, #c0392b); box-shadow: 0 0 0 1px var(--danger, #c0392b); }
.mod-meta { font-size: 12px; opacity: .7; margin-bottom: 8px; }
.mod-view { margin: 8px 0; }
.mod-img { max-width: 280px; max-height: 280px; border-radius: 8px; border: 1px solid var(--border); display: block; }
.mod-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.mod-act { font-size: 13px; padding: 6px 12px; }
.btn.mod-danger { border-color: var(--danger, #c0392b); color: var(--danger, #c0392b); }
.mod-confirm { background: var(--danger, #c0392b) !important; color: #fff !important; border-color: var(--danger, #c0392b) !important; }
.mod-note { font-size: 12px; opacity: .7; }


/* ── CLIENT PORTALS (js/portal.js renders into #portal-screen) ─────────── */
#portal-screen { position: fixed; inset: 0; z-index: 200; background: var(--bg); overflow-y: auto; display: none; flex-direction: column; padding-top: env(safe-area-inset-top, 0px); }
.pt-wrap { width: 100%; max-width: 880px; margin: 0 auto; padding: 24px 20px 80px; }
.pt-loading { text-align: center; color: var(--text2); padding: 48px 0; font-size: 14px; }
.pt-header { display: flex; align-items: center; gap: 12px; margin-bottom: 6px; flex-wrap: wrap; }
.pt-header h1 { font-size: 22px; font-weight: 700; margin: 0; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.pt-sub { color: var(--text2); font-size: 13px; margin: 0 0 18px; line-height: 1.55; }
.pt-sect { font-size: 13px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--text3); margin: 22px 0 10px; }
.pt-list { display: flex; flex-direction: column; gap: 10px; }
.pt-card { display: flex; align-items: center; gap: 12px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--r); padding: 14px 16px; box-shadow: var(--shsm); }
.pt-row-click { cursor: pointer; transition: background .12s; }
.pt-row-click:hover { background: var(--s1); }
.pt-card-main { flex: 1; min-width: 0; }
.pt-card-title { font-weight: 600; font-size: 14px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pt-card-sub { font-size: 12px; color: var(--text2); margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pt-chevron { color: var(--text3); font-size: 20px; }
.pt-logo { border-radius: 10px; object-fit: cover; flex-shrink: 0; }
.pt-logo-letter { display: inline-flex; align-items: center; justify-content: center; background: var(--abg); color: var(--accent); font-weight: 700; }
.pt-badge { font-size: 11px; font-weight: 600; padding: 3px 9px; border-radius: 999px; background: var(--abg); color: var(--accent); white-space: nowrap; }
.pt-badge-ok { background: #dcfce7; color: #15803d; }
.pt-badge-mute { background: var(--s2); color: var(--text3); }
body.dark .pt-badge-ok { background: #14331f; color: #4ade80; }
.pt-tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--border); margin: 14px 0 16px; }
.pt-tab { background: none; border: none; padding: 9px 14px; font: 600 13px 'DM Sans', sans-serif; color: var(--text2); cursor: pointer; border-bottom: 2px solid transparent; margin-bottom: -1px; }
.pt-tab.active { color: var(--accent); border-bottom-color: var(--accent); }
.pt-tab-body { min-height: 120px; }
.pt-row-end { display: flex; justify-content: flex-end; margin-bottom: 12px; }
.pt-invite-bar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; background: var(--abg); border: 1px solid var(--border); border-radius: var(--rsm); padding: 10px 12px; font-size: 12px; margin-bottom: 12px; }
.pt-invite-bar code { background: var(--surface); border: 1px solid var(--border); border-radius: 6px; padding: 4px 8px; font-size: 11px; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; min-width: 120px; }
.pt-delivery { background: var(--surface); border: 1px solid var(--border); border-radius: var(--r); padding: 14px 16px; box-shadow: var(--shsm); }
.pt-delivery-head { display: flex; align-items: flex-start; gap: 10px; justify-content: space-between; }
.pt-delivery-actions { display: flex; gap: 6px; flex-shrink: 0; }
.pt-delivery-note { font-size: 13px; color: var(--text2); margin-top: 6px; line-height: 1.5; white-space: pre-wrap; }
.pt-files { display: flex; flex-direction: column; gap: 6px; margin-top: 10px; }
.pt-file { display: flex; align-items: center; gap: 10px; background: var(--s1); border-radius: var(--rsm); padding: 8px 12px; }
.pt-file-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.pt-file-name { font-size: 13px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pt-file-meta { font-size: 11px; color: var(--text3); }
.pt-mini { font-size: 12px !important; padding: 5px 10px !important; }
.pt-upload-progress { display: flex; align-items: center; gap: 10px; margin-top: 10px; }
.pt-up-bar { flex: 1; height: 6px; background: var(--s2); border-radius: 3px; overflow: hidden; }
.pt-up-fill { height: 100%; width: 0%; background: var(--accent); transition: width .25s; border-radius: 3px; }
.pt-up-label { font-size: 11px; color: var(--text2); white-space: nowrap; }
.pt-field { margin-bottom: 14px; }
.pt-field label { display: block; font-size: 12px; font-weight: 600; color: var(--text2); margin-bottom: 5px; }
.pt-field input, .pt-field textarea { width: 100%; padding: 10px 12px; background: var(--s1); border: 1px solid var(--border); border-radius: var(--rsm); font: 500 14px 'DM Sans', sans-serif; color: var(--text); box-sizing: border-box; }
.pt-field input[type=color] { padding: 4px; height: 38px; width: 64px; cursor: pointer; }
.pt-field input:disabled { opacity: .55; }
.pt-hint { font-size: 11px; color: var(--text3); margin-top: 4px; }
.pt-logo-row { display: flex; align-items: center; gap: 12px; }
.pt-settings { max-width: 460px; }
.pt-activity-row { display: flex; justify-content: space-between; gap: 12px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--rsm); padding: 10px 14px; font-size: 13px; }
.pt-act-main { min-width: 0; }
.pt-act-main em { color: var(--text2); font-style: normal; }
.pt-act-meta { color: var(--text3); font-size: 11px; white-space: nowrap; }
.pt-brandbar { display: flex; align-items: center; gap: 14px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--r); padding: 16px 18px; margin-bottom: 16px; box-shadow: var(--shsm); }
.pt-brand-names { flex: 1; min-width: 0; }
.pt-brand-portal { font-weight: 700; font-size: 17px; }
.pt-brand-booth { font-size: 13px; color: var(--text2); }
.pt-powered { text-align: center; color: var(--text3); font-size: 11px; margin-top: 28px; }
.pt-claim-wrap { min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 24px 16px; }
.pt-claim-card { background: var(--surface); border: 1px solid var(--border); border-radius:8px; box-shadow: var(--shlg); padding: 32px 28px; width: 100%; max-width: 420px; text-align: center; }
.pt-claim-brand { display: flex; justify-content: center; margin-bottom: 14px; }
.pt-claim-card h2 { margin: 0 0 8px; font-size: 20px; }
.pt-claim-sub { color: var(--text2); font-size: 13px; line-height: 1.55; margin: 0 0 18px; }
.pt-claim-as { font-size: 13px; color: var(--text2); margin-bottom: 12px; }
.pt-claim-card .pt-field { text-align: left; }
.pt-claim-card .btn-xl { margin-top: 4px; }
.pt-claim-toggle { display: flex; gap: 4px; justify-content: center; margin-bottom: 16px; border-bottom: 1px solid var(--border); }
.pt-modal { position: fixed; inset: 0; z-index: 10000; display: flex; align-items: center; justify-content: center; padding: 16px; }
.pt-modal-backdrop { position: absolute; inset: 0; background: rgba(0,0,0,.55); }
.pt-modal-card { position: relative; background: var(--surface); border: 1px solid var(--border); border-radius:8px; padding: 24px; width: 100%; max-width: 440px; max-height: 85vh; overflow-y: auto; box-shadow: var(--shlg); }
.pt-modal-card h3 { margin: 0 0 16px; font-size: 17px; }
.pt-modal-actions { display: flex; gap: 8px; justify-content: flex-end; margin-top: 18px; flex-wrap: wrap; }
/* Home-header hamburger (portals entry) */
.home-header { position: relative; }
.home-menu-btn { position: absolute; top: 0; right: 0; background: var(--surface); border: 1px solid var(--border); border-radius: var(--rsm); padding: 8px 10px; cursor: pointer; color: var(--text2); box-shadow: var(--shsm); transition: background .12s; }
.home-menu-btn:hover { background: var(--s2); color: var(--text); }
.home-menu { position: absolute; top: 42px; right: 0; background: var(--surface); border: 1px solid var(--border); border-radius: var(--rsm); box-shadow: var(--shlg); padding: 6px; z-index: 60; min-width: 180px; }
.home-menu-item { display: flex; align-items: center; gap: 9px; width: 100%; background: none; border: none; padding: 10px 12px; font: 600 13px 'DM Sans', sans-serif; color: var(--text); cursor: pointer; border-radius: 7px; text-align: left; }
.home-menu-item:hover { background: var(--s2); }
@media (max-width: 600px) {
  .pt-header h1 { font-size: 18px; }
  .pt-activity-row { flex-direction: column; gap: 4px; }
  .pt-act-meta { white-space: normal; }
  .pt-delivery-head { flex-direction: column; }
  .pt-file { flex-wrap: wrap; }
}
.pt-danger-zone { margin-top: 28px; padding-top: 18px; border-top: 1px solid var(--border); display: flex; flex-direction: column; gap: 10px; align-items: flex-start; }

/* ── Portal Phase 2: messages, calendar, tokens ─────────────────────────── */
.pt-unread-dot { display: inline-flex; align-items: center; justify-content: center; min-width: 17px; height: 17px; padding: 0 5px; margin-left: 5px; background: var(--accent); color:var(--accent-fg,#fff); border-radius: 999px; font-size: 11px; font-weight: 700; vertical-align: middle; }
/* Chat */
.pt-chat { display: flex; flex-direction: column; height: min(60vh, 540px); background: var(--surface); border: 1px solid var(--border); border-radius: var(--r); overflow: hidden; }
.pt-chat-scroll { flex: 1; overflow-y: auto; padding: 16px; display: flex; flex-direction: column; gap: 8px; min-height: 0; }
.pt-chat-empty { margin: auto; color: var(--text3); font-size: 13px; }
.pt-msg { position: relative; max-width: 78%; padding: 9px 13px; border-radius:10px; font-size: 14px; line-height: 1.45; word-wrap: break-word; }
.pt-msg-them { align-self: flex-start; background: var(--s2); border-bottom-left-radius: 4px; }
.pt-msg-mine { align-self: flex-end; background: var(--accent); color:var(--accent-fg,#fff); border-bottom-right-radius: 4px; }
.pt-msg-who { font-size: 11px; font-weight: 700; color: var(--text2); margin-bottom: 3px; }
.pt-msg-text { white-space: pre-wrap; }
.pt-msg-mine .pt-msg-text { color:var(--accent-fg,#fff); }
.pt-msg audio { display: block; max-width: 240px; margin: 2px 0; }
.pt-msg-file { color: inherit; text-decoration: underline; font-size: 13px; }
.pt-msg-del { position: absolute; top: -7px; right: -7px; width: 18px; height: 18px; border-radius: 50%; border: none; background: var(--err); color: #fff; font-size: 12px; line-height: 1; cursor: pointer; display: none; }
.pt-msg-mine:hover .pt-msg-del { display: block; }
.pt-composer { display: flex; align-items: flex-end; gap: 8px; padding: 10px; border-top: 1px solid var(--border); background: var(--surface); }
.pt-msg-input { flex: 1; resize: none; max-height: 120px; padding: 9px 12px; background: var(--s1); border: 1px solid var(--border); border-radius: 10px; font: 500 14px 'DM Sans', sans-serif; color: var(--text); }
.pt-mic-btn { flex-shrink: 0; width: 38px; height: 38px; border-radius: 50%; border: 1px solid var(--border); background: var(--surface); cursor: pointer; font-size: 16px; }
.pt-mic-btn.recording { background: var(--err); border-color: var(--err); animation: pt-pulse 1s infinite; }
@keyframes pt-pulse { 0%,100% { opacity: 1; } 50% { opacity: .55; } }
.pt-send-btn { flex-shrink: 0; }
/* Calendar */
.pt-cal-list { display: flex; flex-direction: column; gap: 8px; }
.pt-cal-entry { display: flex; align-items: center; gap: 14px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--rsm); padding: 12px 14px; box-shadow: var(--shsm); }
.pt-cal-entry.done { opacity: .72; }
.pt-cal-date { flex-shrink: 0; width: 92px; font-size: 12px; font-weight: 700; color: var(--accent); }
.pt-cal-entry.done .pt-cal-date { color: var(--ok); }
.pt-cal-main { flex: 1; min-width: 0; }
.pt-cal-title { font-weight: 600; font-size: 14px; }
.pt-cal-notes { font-size: 12px; color: var(--text2); margin-top: 2px; white-space: pre-wrap; }
.pt-cal-actions { display: flex; gap: 4px; flex-shrink: 0; }
.pt-select { width: 100%; padding: 10px 12px; background: var(--s1); border: 1px solid var(--border); border-radius: var(--rsm); font: 500 14px 'DM Sans', sans-serif; color: var(--text); }
/* Tokens */
.pt-token-section { margin-top: 26px; padding-top: 18px; border-top: 1px solid var(--border); }
.pt-token-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; background: var(--s1); border: 1px solid var(--border); border-radius: var(--rsm); padding: 10px 12px; margin-bottom: 8px; }
.pt-token-row code { font-size: 12px; }
.pt-token-label { font-size: 12px; color: var(--text2); margin-left: 6px; }
.pt-token-reveal { background: var(--s2); border: 1px solid var(--border); border-radius: var(--rsm); padding: 12px; margin: 12px 0; word-break: break-all; }
.pt-token-reveal code { font-size: 13px; font-family: 'DM Mono', monospace; }

/* ── Portal custom CSS editor + assets ──────────────────────────────────── */
.pt-css-section { margin-top: 26px; padding-top: 18px; border-top: 1px solid var(--border); }
.pt-subsect { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .03em; color: var(--text3); margin: 16px 0 8px; }
.pt-css-editor { width: 100%; min-height: 240px; padding: 12px 14px; background: #1a1916; color: #e8e6e1; border: 1px solid var(--border); border-radius: var(--rsm); font: 13px/1.5 'DM Mono', ui-monospace, monospace; resize: vertical; box-sizing: border-box; white-space: pre; tab-size: 2; }
.pt-asset-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; background: var(--s1); border: 1px solid var(--border); border-radius: var(--rsm); padding: 9px 12px; margin-bottom: 6px; }
.pt-asset-main { min-width: 0; flex: 1; }
.pt-asset-name { font-size: 13px; font-weight: 600; display: block; }
.pt-asset-url { display: block; font-size: 11px; color: var(--text2); margin-top: 3px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; cursor: pointer; font-family: 'DM Mono', monospace; }
.pt-asset-url:hover { color: var(--accent); }

/* ── Portal theme editor ────────────────────────────────────────────────── */
.pt-theme-section { margin-top: 26px; padding-top: 18px; border-top: 1px solid var(--border); }
.pt-theme-preview { background: var(--bg); border: 1px solid var(--border); border-radius: var(--r); padding: 16px; display: flex; flex-direction: column; gap: 10px; cursor: pointer; }
.pt-theme-preview [data-pt-target] { cursor: pointer; }
.pt-theme-preview .pt-brandbar { margin-bottom: 0; }
.pt-theme-preview .pt-tabs { margin: 0; }
.pt-th-chat { display: flex; flex-direction: column; gap: 6px; }
.pt-th-chat .pt-msg { max-width: 70%; }
.pt-th-hint { text-align: center; font-size: 11px; color: var(--text3); padding-top: 4px; }
.pt-th-presets { display: flex; gap: 8px; flex-wrap: wrap; margin: 14px 0; }
.pt-th-preset { display: inline-flex; align-items: center; gap: 7px; padding: 6px 11px; background: var(--surface); border: 1px solid var(--border); border-radius: 999px; font: 600 12px 'DM Sans', sans-serif; color: var(--text); cursor: pointer; }
.pt-th-preset:hover { background: var(--s2); }
.pt-th-sw { display: inline-flex; }
.pt-th-sw span { width: 12px; height: 12px; border-radius: 3px; display: inline-block; margin-left: -3px; border: 1px solid rgba(0,0,0,.1); }
.pt-th-sw span:first-child { margin-left: 0; }
.pt-th-controls { margin-top: 8px; }
.pt-th-row { display: flex; align-items: center; gap: 10px; padding: 6px 0; }
.pt-th-row label { flex: 1; font-size: 13px; color: var(--text2); }
.pt-th-row input[type=color] { width: 44px; height: 30px; padding: 2px; border: 1px solid var(--border); border-radius: 7px; cursor: pointer; background: var(--surface); }
.pt-th-row input[type=range] { width: 130px; }
.pt-th-row select { min-width: 130px; padding: 7px 10px; background: var(--s1); border: 1px solid var(--border); border-radius: var(--rsm); font: 500 13px 'DM Sans', sans-serif; color: var(--text); }
.pt-th-val { font-size: 12px; color: var(--text2); min-width: 40px; text-align: right; }
.pt-th-reset { background: none; border: none; color: var(--text3); cursor: pointer; font-size: 14px; padding: 2px 6px; border-radius: 5px; }
.pt-th-reset:hover { background: var(--s2); color: var(--text); }
.pt-th-reset.off { opacity: .3; }

/* ───────────────────────── SUBSCRIPTION PAGE ───────────────────────── */
#subscription-screen {
  position: fixed; inset: 0; z-index: 210;
  background: var(--bg); overflow-y: auto;
  display: flex; flex-direction: column;
}
.sub-page { width: 100%; max-width: 1120px; margin: 0 auto; padding: 28px 24px 80px; }

/* Hero */
.sub-hero { text-align: center; max-width: 600px; margin: 14px auto 30px; }
.sub-hero-glyph {
  width: 52px; height: 52px; margin: 0 auto 16px;
  display: flex; align-items: center; justify-content: center;
  font-size: 24px; border-radius: 50%;
  background: var(--abg); color: var(--accent);
  box-shadow: 0 4px 14px rgba(42,110,245,.18);
}
.sub-hero h2 { font-size: 30px; font-weight: 800; letter-spacing: -.02em; margin: 0 0 10px; }
.sub-hero p { font-size: 15px; color: var(--text2); line-height: 1.6; margin: 0 0 18px; }
.sub-status {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 7px 16px; border-radius: 999px;
  background: var(--surface); border: 1px solid var(--border); box-shadow: var(--shsm);
  font-size: 13px; font-weight: 600; color: var(--text2);
}
.sub-status.is-supporter { background: var(--abg); border-color: rgba(42,110,245,.25); color: var(--accent2); }

/* Monthly / Annual toggle */
.sub-toggle {
  display: inline-flex; gap: 4px; margin: 0 auto 28px;
  padding: 4px; border-radius: 999px;
  background: var(--s2); border: 1px solid var(--border);
  position: relative; left: 50%; transform: translateX(-50%);
}
.sub-toggle-btn {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 9px 20px; border: none; border-radius: 999px;
  background: none; cursor: pointer;
  font: 600 14px 'DM Sans', sans-serif; color: var(--text2);
  transition: all .18s;
}
.sub-toggle-btn:hover { color: var(--text); }
.sub-toggle-btn.active { background: var(--surface); color: var(--text); box-shadow: var(--shsm); }
.sub-save {
  font-size: 11px; font-weight: 700; padding: 2px 8px; border-radius: 999px;
  background: var(--ok); color: #fff; letter-spacing: .01em;
}

/* Tier grid */
.sub-tiers { display: grid; grid-template-columns: repeat(4, 1fr); gap: 18px; align-items: stretch; }
.sub-tier {
  display: flex; flex-direction: column;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r); box-shadow: var(--sh);
  padding: 24px 22px; position: relative;
  transition: transform .2s, box-shadow .2s;
}
.sub-tier:hover { transform: translateY(-4px); box-shadow: var(--shlg); }
.sub-tier.featured { border: 2px solid var(--accent); box-shadow: var(--shlg); transform: translateY(-6px); }
.sub-tier.featured:hover { transform: translateY(-10px); }
.sub-tier-badge {
  position: absolute; top: -11px; left: 50%; transform: translateX(-50%);
  padding: 4px 13px; border-radius: 999px; white-space: nowrap;
  background: var(--accent); color:var(--accent-fg,#fff); font-size: 11px; font-weight: 700; letter-spacing: .02em;
  box-shadow: 0 3px 10px rgba(42,110,245,.4);
}
.sub-tier-name { font-size: 17px; font-weight: 700; margin-bottom: 4px; }
.sub-tier-tagline { font-size: 12.5px; color: var(--text3); min-height: 30px; line-height: 1.4; margin-bottom: 14px; }
.sub-tier-price { display: flex; align-items: baseline; gap: 3px; margin-bottom: 2px; }
.sub-tier-price .amt { font-size: 34px; font-weight: 800; letter-spacing: -.03em; }
.sub-tier-price .per { font-size: 14px; font-weight: 600; color: var(--text2); }
.sub-tier-price-sub { font-size: 12px; color: var(--text3); min-height: 16px; margin-bottom: 18px; }
.sub-tier-cta { width: 100%; margin-bottom: 18px; }
.sub-tier-cta:disabled, .sub-tier-cta.is-soon {
  background: var(--s2); color: var(--text3); border: 1px solid var(--border);
  box-shadow: none; cursor: default; transform: none;
}
/* Secondary "Manage subscription" button sits just under the "Current plan" pill. */
.sub-tier-manage { margin-top: -10px; }
.sub-tier-perks { display: flex; flex-direction: column; gap: 9px; margin-top: auto; }
.sub-perk { display: flex; align-items: flex-start; gap: 9px; font-size: 13px; color: var(--text); line-height: 1.4; }
.sub-perk svg { flex-shrink: 0; margin-top: 2px; color: var(--accent); }
.sub-perk.muted { color: var(--text3); }
.sub-perk.muted svg { color: var(--text3); }
.sub-perk-head { font-size: 12px; font-weight: 700; color: var(--text2); text-transform: uppercase; letter-spacing: .04em; margin-bottom: 1px; }

/* Credits */
.sub-credits-section {
  max-width: 720px; margin: 40px auto 0;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r); box-shadow: var(--sh); padding: 26px 26px 22px;
}
.sub-section-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 4px; }
.sub-section-head h3 { font-size: 19px; font-weight: 700; }
.sub-credits-balance {
  font-size: 13px; font-weight: 700; color: var(--accent2);
  background: var(--abg); border: 1px solid rgba(42,110,245,.2);
  padding: 5px 13px; border-radius: 999px;
}
.sub-section-sub { font-size: 13px; color: var(--text2); line-height: 1.5; margin-bottom: 18px; }
.sub-packs { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
/* Credit history ("Recent activity") on the subscription page. */
.sub-history-section {
  max-width: 720px; margin: 18px auto 0;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r); box-shadow: var(--sh); padding: 22px 26px;
}
.sub-history-list { display: flex; flex-direction: column; margin-top: 8px; }
.sub-history-row { display: flex; align-items: center; justify-content: space-between; padding: 9px 0; border-bottom: 1px solid var(--border); }
.sub-history-row:last-child { border-bottom: none; }
.sub-history-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.sub-history-label { font-size: 13px; font-weight: 600; color: var(--text); }
.sub-history-when { font-size: 11px; color: var(--text3); }
.sub-history-amt { font-size: 14px; font-weight: 700; flex-shrink: 0; margin-left: 12px; }
.sub-history-amt.pos { color: var(--accent2); }
.sub-history-amt.neg { color: var(--text2); }
/* Go-live readiness panel (admin only). */
.sub-preflight-section {
  max-width: 720px; margin: 18px auto 0;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r); box-shadow: var(--sh); padding: 22px 26px;
}
.sub-preflight-out { margin-top: 14px; }
.sub-pf-head { font-size: 13px; font-weight: 700; margin-bottom: 8px; color: var(--text); }
.sub-pf-head.ok { color: #3ba55d; }
.sub-pf-row { display: flex; align-items: baseline; gap: 8px; padding: 6px 0; border-bottom: 1px solid var(--border); font-size: 12px; }
.sub-pf-row:last-child { border-bottom: none; }
.sub-pf-dot { flex-shrink: 0; }
.sub-pf-label { font-weight: 600; color: var(--text); flex-shrink: 0; }
.sub-pf-detail { color: var(--text2); min-width: 0; }
/* Cosmetic avatar frames (placeholder CSS rings; box-shadow = no layout impact).
   Replace any of these with a real PNG overlay later by giving the catalog item
   an `asset` and rendering it — zero change needed to the call sites. */
.av-wrap { position: relative; display: inline-flex; align-items: center; justify-content: center; border-radius: 50%; flex-shrink: 0; vertical-align: middle; }
/* Real-art overlay (a PNG frame around the avatar). Larger than the avatar so it
   frames it; never intercepts clicks. Present only when the art file exists. */
.av-frame-img { position: absolute; left: -16%; top: -16%; width: 132%; height: 132%; object-fit: contain; pointer-events: none; }
/* When real art loads, drop the CSS placeholder ring so they don't double up. */
.av-wrap.has-art, .server-member-avatar.has-art { box-shadow: none; }
.av-frame-aurora  { box-shadow: 0 0 0 2px var(--accent), 0 0 7px 1px var(--accent); }
.av-frame-gold    { box-shadow: 0 0 0 2px #f5c84b, 0 0 5px rgba(245,200,75,.55); }
.av-frame-emerald { box-shadow: 0 0 0 2px #3ba55d, 0 0 5px rgba(59,165,93,.55); }
.av-frame-rose    { box-shadow: 0 0 0 2px #eb459e, 0 0 5px rgba(235,69,158,.55); }
.av-frame-frost   { box-shadow: 0 0 0 2px #5fd0e0, 0 0 7px 1px rgba(95,208,224,.6); }
.av-frame-dusk    { box-shadow: 0 0 0 2px #9b59b6, 0 0 5px rgba(155,89,182,.55); }
/* Cosmetics shop (subscription page). */
.sub-cosmetics-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 12px; margin-top: 14px; }
.sub-cosmetic { background: var(--s2); border: 1px solid var(--border); border-radius: 10px; padding: 14px 10px; text-align: center; }
.sub-cosmetic.equipped { border-color: var(--accent); }
.sub-cosmetic-preview { margin: 0 auto 9px; }
.sub-cosmetic-name { font-size: 13px; font-weight: 600; margin-bottom: 7px; }
.sub-cosmetic-btn { width: 100%; font-size: 12px; padding: 6px 8px; }
/* Cosmetic Studio (creator tool in Settings). */
.cs-build { display: flex; gap: 20px; flex-wrap: wrap; align-items: flex-start; }
.cs-preview { position: relative; width: 64px; height: 64px; display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; }
.cs-fields { flex: 1; min-width: 220px; display: flex; flex-direction: column; gap: 4px; }
.cs-l { font-size: 12px; font-weight: 600; color: var(--text2); margin-top: 8px; }
.cs-v { color: var(--text3); font-weight: 400; }
.cs-fields input[type=text], .cs-fields input[type=number] { padding: 7px 9px; border-radius: 6px; border: 1px solid var(--border); background: var(--bg); color: var(--text); font-size: 13px; }
.cs-fields input[type=range] { width: 100%; }
.cs-item { display: flex; align-items: center; gap: 12px; padding: 9px 0; border-bottom: 1px solid var(--border); }
.cs-item:last-child { border-bottom: none; }
.cs-item-prev { position: relative; width: 44px; height: 44px; display: inline-flex; flex-shrink: 0; }
.cs-item-meta { flex: 1; min-width: 0; }
.cs-item-name { font-weight: 600; font-size: 13px; color: var(--text); }
.cs-item-actions { display: flex; gap: 6px; align-items: center; flex-shrink: 0; }
.cs-live { color: #3ba55d; font-size: 12px; font-weight: 600; }
.cs-admin { margin-top: 20px; border-top: 1px solid var(--border); padding-top: 14px; }
.cs-anim { font-size: 11px; color: var(--accent2); font-weight: 600; }
.sub-cosmetic-anim { font-size: 11px; color: var(--accent2); font-weight: 600; margin-bottom: 7px; }
.sub-pack {
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  padding: 18px 14px; border-radius: var(--rsm);
  background: var(--s1); border: 1.5px solid var(--border); cursor: pointer;
  transition: all .15s; font-family: 'DM Sans', sans-serif;
}
.sub-pack:hover { border-color: var(--accent); background: var(--surface); transform: translateY(-2px); box-shadow: var(--shsm); }
.sub-pack.popular { border-color: var(--accent); }
.sub-pack-price { font-size: 22px; font-weight: 800; letter-spacing: -.02em; color: var(--text); }
.sub-pack-credits { font-size: 12.5px; font-weight: 600; color: var(--text2); }
.sub-pack-tag { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--accent); margin-top: 2px; min-height: 13px; }
.sub-gift-link {
  display: block; margin: 18px auto 0; padding: 9px 16px;
  background: none; border: none; cursor: pointer;
  font: 600 13.5px 'DM Sans', sans-serif; color: var(--text2);
  border-radius: var(--rsm); transition: all .15s;
}
.sub-gift-link:hover { background: var(--s2); color: var(--text); }

/* Fine print */
.sub-fineprint {
  display: flex; align-items: center; justify-content: center; flex-wrap: wrap; gap: 8px;
  margin: 34px auto 0; font-size: 12px; color: var(--text3);
}
.sub-fineprint .sub-dot { opacity: .5; }

/* Responsive */
@media (max-width: 1000px) { .sub-tiers { grid-template-columns: repeat(2, 1fr); } .sub-tier.featured { transform: none; } .sub-tier.featured:hover { transform: translateY(-4px); } }
@media (max-width: 560px) {
  .sub-page { padding: 20px 14px 70px; }
  .sub-hero h2 { font-size: 25px; }
  .sub-tiers { grid-template-columns: 1fr; }
  .sub-packs { grid-template-columns: 1fr; }
  .sub-toggle-btn { padding: 9px 16px; }
}

/* Supporter badge (the heart next to a subscriber's name) */
.supporter-badge { display: inline-flex; align-items: center; vertical-align: middle; margin-left: 5px; color: var(--accent); flex-shrink: 0; }

/* ============================================================
   ui-v2 In-call / Space (#space-v2) — ported VERBATIM from
   design-mockups/eaves-ui/space.css (warm3-space.html), every selector
   scoped under #space-v2 (id specificity, collision-proof vs classic).
   Paper chrome (topbar/rail/members) wrapping a warm-DARK stage where the
   live call lives. The stage body hosts the REPARENTED classic
   .server-chat-area (call grid + chat + draw + empty), restyled warm.
   Stage tokens (--stage/--tile/--cream...) live in the body.ui-v2 block.
   The Wave-5 edit-mode block (.editbar/.insp/.sel...) is intentionally NOT
   ported here.  ============================================================ */
@keyframes spv2-pp { 50% { opacity:.4; } }

body.ui-v2.space-open.space-onscreen { overflow:hidden; }   /* only lock body scroll while the Space is actually on screen (not on home/quickshare with a persistent call) */

/* (box-sizing/margins are already reset globally at the top of this file, so the only
   "reset" worth adding here is a typography baseline so classic body font-size/line-height
   can't leak in and shift the mock's spacing.) */
#space-v2 { position:fixed; inset:0; display:none; flex-direction:column; z-index:30; overflow:hidden;
  background:var(--paper); font-family:var(--f); color:var(--ink); font-size:14px; line-height:1.45;
  -webkit-font-smoothing:antialiased; -moz-osx-font-smoothing:grayscale; }
body.ui-v2.space-open #space-v2 { display:flex; }
/* When the warm Space owns the screen, HIDE the classic in-call chrome rather than
   relying on z-index to cover it (the classic header + voice bar are z-index:50 and
   would paint over #space-v2's z-index:30). They stay in the DOM — display:none does
   not stop their JS timers — so the 1.5s member poll + heartbeat keep feeding state.
   Scoped to body.ui-v2.space-open, so classic (New look off) is untouched. */
body.ui-v2.space-open .server-page-topbar,
body.ui-v2.space-open #server-channel-bar,
body.ui-v2.space-open #server-members-panel,
body.ui-v2.space-open #voice-control-panel,
body.ui-v2.space-open #channel-bar-toggle-btn { display:none !important; }

/* ── top bar ───────────────────────────────────────────────── */
#space-v2 .topbar { height:56px; flex:none; display:flex; align-items:center; gap:14px;
  padding:0 16px; border-bottom:1px solid var(--div); background:var(--paper); position:relative; z-index:3; }
#space-v2 .tb-back { width:34px; height:34px; border-radius:10px; display:grid; place-items:center;
  color:var(--ink2); cursor:pointer; border:1px solid transparent; }
#space-v2 .tb-back:hover { background:var(--s3,#e3ded3); color:var(--ink); }
#space-v2 .tb-id { display:flex; align-items:center; gap:11px; cursor:pointer; border-radius:10px; padding:4px 8px; margin-left:-8px; }
#space-v2 .tb-id:hover { background:var(--s3,#e3ded3); }
#space-v2 .tb-id.open { background:var(--s3,#e3ded3); }
#space-v2 .tb-id .tb-chev { display:inline-flex; vertical-align:-2px; color:var(--ink3); transition:transform .15s; }
#space-v2 .tb-id.open .tb-chev { transform:rotate(180deg); }
#space-v2 .tb-id .mono { width:34px; height:34px; border-radius:8px; background:var(--honey); color:var(--accent-fg,#fff);
  display:grid; place-items:center; font-weight:800; font-size:15px; font-family:var(--disp); background-size:cover; background-position:center; }
#space-v2 .tb-id .nm { font-family:var(--disp); font-weight:800; font-size:16.5px; letter-spacing:-.01em; line-height:1; }
#space-v2 .tb-id .sub { font-size:11.5px; color:var(--ink3); font-weight:600; margin-top:3px; display:flex; align-items:center; gap:5px; }
#space-v2 .tb-id .sub .lv { width:6px; height:6px; border-radius:50%; background:var(--clay); display:inline-block; }
#space-v2 .tb-spacer { flex:1; }
#space-v2 .tb-btn { position:relative; width:38px; height:38px; border-radius:8px; border:1px solid var(--line);
  background:var(--card); display:grid; place-items:center; cursor:pointer; color:var(--ink2); }
#space-v2 .tb-btn:hover { color:var(--ink); border-color:var(--text3,#9a9389); }
#space-v2 .tb-btn.on { background:var(--s3,#e3ded3); border-color:var(--border,#ddd7cc); color:var(--ink); }
#space-v2 .tb-btn .nb { position:absolute; top:-3px; right:-3px; min-width:9px; height:9px; border-radius:50%;
  background:var(--clay); border:2px solid var(--paper); }
#space-v2 .tb-pill { display:inline-flex; align-items:center; gap:7px; border:1px solid var(--line); background:var(--card);
  padding:8px 14px; border-radius:999px; font-size:13px; font-weight:700; cursor:pointer; color:var(--ink); }
#space-v2 .tb-pill:hover { border-color:var(--text3,#9a9389); }

/* ── 3-column body ─────────────────────────────────────────── */
#space-v2 .layout { flex:1; display:flex; min-height:0; }

/* left channel rail.
   Layout props read Wave-5 customization vars with today's values as fallbacks,
   so an unthemed/empty theme renders byte-identically. dock=order, width=width,
   visible=display, float=position:absolute + left/top/z (all var-driven). */
#space-v2 .rail { width:var(--space-rail-w,236px); flex:none; background:var(--paper); border-right:1px solid var(--div);
  display:var(--space-rail-disp,flex); flex-direction:column; min-height:0; position:var(--space-rail-pos,relative);
  order:var(--space-rail-order,0); left:var(--space-rail-x,auto); top:var(--space-rail-y,auto); z-index:var(--space-rail-z,auto); }
/* drawer header — hidden on desktop (the topbar already shows the server); shown on mobile (rail is a full-cover drawer there) */
#space-v2 .rail-head { display:none; align-items:center; gap:11px; flex:none; padding:14px 14px 12px; padding-top:calc(14px + env(safe-area-inset-top,0px)); border-bottom:1px solid var(--div); }
#space-v2 .rail-head .mono { width:36px; height:36px; border-radius:8px; display:grid; place-items:center; color:#fff; font-weight:800; font-size:14px; background-size:cover; background-position:center; flex:none; }
#space-v2 .rail-head .rh-nm { font-family:var(--disp); font-weight:800; font-size:17px; letter-spacing:-.01em; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; min-width:0; }
#space-v2 .rail-scroll { flex:1; overflow-y:auto; padding:14px 10px 8px; scrollbar-width:thin; scrollbar-color:var(--rust) transparent; }
#space-v2 .rail-scroll::-webkit-scrollbar { width:8px; }
#space-v2 .rail-scroll::-webkit-scrollbar-thumb { background:linear-gradient(var(--honey),var(--rust)); border-radius:99px; border:2px solid transparent; background-clip:padding-box; }
#space-v2 .chgrp { margin-bottom:14px; }
#space-v2 .chgrp h6 { font-size:11px; text-transform:uppercase; letter-spacing:.09em; color:var(--ink3); font-weight:800;
  padding:0 8px 7px; display:flex; align-items:center; justify-content:space-between; }
#space-v2 .chgrp h6 .plus { cursor:pointer; color:var(--ink3); display:grid; place-items:center; padding:2px; border-radius:5px; }
#space-v2 .chgrp h6 .plus:hover { color:var(--rust); }
#space-v2 .ch { display:flex; align-items:center; gap:9px; padding:8px 9px; border-radius:9px; cursor:pointer;
  color:var(--ink2); font-weight:600; font-size:14px; }
#space-v2 .ch:hover { background:var(--s3,#e3ded3); color:var(--ink); }
#space-v2 .ch.on { background:var(--s3,#e3ded3); color:var(--ink); font-weight:700; }
#space-v2 .ch svg { color:var(--ink3); flex:none; }
#space-v2 .ch.on svg { color:var(--rust); }
#space-v2 .ch .ct { margin-left:auto; font-size:11px; color:var(--ink3); font-weight:700; }
/* unread: bolden the channel + a clay count pill */
#space-v2 .ch.has-unread { color:var(--ink); font-weight:700; }
#space-v2 .ch.has-unread svg { color:var(--ink2); }
#space-v2 .ch .ch-unread { margin-left:auto; background:var(--clay); color:#fff; font-size:10.5px; font-weight:800;
  min-width:18px; height:18px; padding:0 5px; border-radius:99px; display:inline-flex; align-items:center; justify-content:center; flex:none; }
#space-v2 .vc { border-radius:8px; overflow:hidden; }
/* Same bug class as the mebar fix: a hardcoded light-cream hex that never
   flipped with dark mode, so the voice channel you're currently in (+ its
   occupant rows, which have no background of their own except on hover) sat
   as a stark tan/off-white rectangle against the rest of the theme-dark rail.
   var(--card2) matches the warm surface shade used elsewhere in the rail. */
#space-v2 .vc.live { background:var(--card2); }
#space-v2 .vc-occ { padding:2px 8px 8px 14px; }
/* who's in a call you haven't joined yet — an overlapping avatar stack, like the
   home space card's .av row. Clicking it joins (same target as the channel name). */
#space-v2 .vc-faces { display:flex; align-items:center; padding:0 10px 8px 31px; margin-top:-2px; cursor:pointer; min-height:22px; }
#space-v2 .vc-faces span { width:22px; height:22px; border-radius:50%; border:2px solid var(--paper); margin-left:-8px;
  font-size:9.5px; display:grid; place-items:center; color:#fff; font-weight:700; background-size:cover; background-position:center; flex:none; }
#space-v2 .vc-faces span:first-child { margin-left:0; }
#space-v2 .vc-faces .n { border:none; width:auto; height:auto; margin-left:8px; font-size:11px; color:var(--ink3); font-weight:700; background:none; }
#space-v2 .occ { display:flex; align-items:center; gap:8px; padding:5px 6px; border-radius:8px; font-size:13px; color:var(--ink); font-weight:600; }
#space-v2 .occ:hover { background:var(--s3,#e3ded3); }
#space-v2 .occ .oa { width:24px; height:24px; border-radius:50%; display:grid; place-items:center; color:#fff; font-weight:700; font-size:10.5px; flex:none; position:relative; background-size:cover; background-position:center; }
#space-v2 .occ.speaking .oa { box-shadow:0 0 0 2px var(--paper),0 0 0 4px var(--olive); }
#space-v2 .occ .ona { flex:1; min-width:0; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
#space-v2 .occ .ost { display:flex; gap:5px; color:var(--ink3); }
#space-v2 .occ .ost .sh { color:var(--olive); }
#space-v2 .occ .ost .mu { color:var(--clay); }
#space-v2 .occ .ost .act { color:var(--rust); }

/* the "me" identity bar pinned bottom-left */
/* background was a hardcoded light-cream hex that never changed under dark mode
   (body.ui-v2.dark), while .mn's text color inherits the theme-aware --ink —
   so in dark mode the username flipped to light text over a background that
   stayed just as light, becoming unreadable. var(--card2) is the same warm
   palette the rest of the rail draws from, and correctly flips with --ink. */
#space-v2 .mebar { flex:none; border-top:1px solid var(--div); background:var(--card2); display:flex; align-items:center; gap:9px; padding:9px 10px; }
#space-v2 .mebar .ma { width:34px; height:34px; border-radius:50%; background:var(--plum); color:#fff; display:grid; place-items:center; font-weight:800; font-size:13px; flex:none; background-size:cover; background-position:center; }
#space-v2 .mebar .me-id { flex:1; min-width:0; }   /* push the buttons right + let the name truncate */
#space-v2 .mebar .mn { font-weight:700; font-size:13.5px; line-height:1.15; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
#space-v2 .mebar .ms { font-size:11px; color:var(--olive); font-weight:700; }
#space-v2 .mebar .mb { width:32px; height:32px; border-radius:9px; display:grid; place-items:center; color:var(--ink2); cursor:pointer; flex:none; }
#space-v2 .mebar .mb:hover { background:var(--card); color:var(--ink); }
#space-v2 .mebar .mb.muted { color:var(--clay); }                          /* pre-join / in-call muted */
#space-v2 .mebar .mb.muted:hover { color:var(--clay); background:var(--card); }
#space-v2 .mebar .mb.deafened { color:var(--clay); }                       /* self-deafened */
#space-v2 .mebar .mb.deafened:hover { color:var(--clay); background:var(--card); }
/* warm custom scrollbar for the in-Space chat (matches the members panel) */
#space-v2 .chat-messages { scrollbar-width:thin; scrollbar-color:var(--rust) transparent; }
#space-v2 .chat-messages::-webkit-scrollbar { width:9px; }
#space-v2 .chat-messages::-webkit-scrollbar-track { background:transparent; }
#space-v2 .chat-messages::-webkit-scrollbar-thumb { background:linear-gradient(var(--honey),var(--rust)); border-radius:99px; border:2px solid transparent; background-clip:padding-box; }

/* ── center stage ──────────────────────────────────────────────
   The warm-DARK "stage" backdrop + dark header + floating tray belong ONLY to the
   live call grid (mode-call, marked by #space-v2.smode-call). A text channel's chat
   and the empty state render on PAPER like the rest of the app — so the call grid
   and the chat are clearly separate surfaces, never a morphing box. */
/* neutralize the bare `main { max-width:980px; margin:0 auto; padding:0 24px }` element
   rule (index.html:224 era) that leaks into <main class="stage"> and capped the stage
   to 980px on wide screens — that was the "call + chat don't fill the area" bug. */
#space-v2 .stage { flex:1; min-width:0; min-height:0; position:relative; display:flex; flex-direction:column;
  max-width:none; margin:0; padding:0; order:var(--space-stage-order,1); }
/* belt-and-suspenders: bare element rules (main/aside/header) must not leak into the
   Space's structural elements. */
#space-v2 main, #space-v2 aside, #space-v2 header { max-width:none; margin:0; }
#space-v2.smode-call .stage { background:radial-gradient(120% 90% at 50% -10%, var(--st-wash), transparent 60%), var(--stage); }
#space-v2 .stage-head { flex:none; display:flex; align-items:center; gap:12px; padding:13px 18px; color:var(--cream); }
#space-v2:not(.smode-call) .stage-head { display:none; }   /* chat shows its OWN (paper) header; the dark stage-head is call-only */
#space-v2 .stage-head .sh-t { font-family:var(--disp); font-weight:700; font-size:15px; letter-spacing:-.01em; display:flex; align-items:center; gap:9px; white-space:nowrap; }
#space-v2 .stage-head .sh-spacer { flex:1; }
#space-v2 .sh-btn { display:inline-flex; align-items:center; gap:7px; height:34px; padding:0 12px; border-radius:10px;
  border:1px solid rgba(var(--st-rgb),.16); background:rgba(255,255,255,.03); color:var(--cream2); cursor:pointer;
  font-family:var(--f); font-weight:700; font-size:12.5px; white-space:nowrap; flex:none; }
#space-v2 .sh-btn:hover { color:var(--cream); background:rgba(255,255,255,.07); }
#space-v2 .sh-btn.on { background:rgba(var(--st-act-rgb),.18); border-color:rgba(var(--st-act-rgb),.4); color:var(--st-hot); }

/* stage body hosts the reparented classic .server-chat-area (call grid / chat / draw / empty) */
#space-v2 .stage-body { flex:1; min-height:0; display:flex; flex-direction:column; padding:2px 18px 18px; position:relative; }
#space-v2 .stage-slot { flex:1; min-height:0; display:flex; flex-direction:column; }

/* floating control tray (offset_x/y nudge it via the Wave-5 editor) */
#space-v2 .tray { position:absolute; left:50%; bottom:18px; transform:translateX(-50%) translate(var(--space-tray-x,0px),var(--space-tray-y,0px)); display:flex; align-items:center; gap:6px;
  background:rgba(var(--st-glass-rgb),.82); backdrop-filter:blur(14px); -webkit-backdrop-filter:blur(14px); border:1px solid rgba(var(--st-rgb),.16);
  border-radius:8px; padding:8px; box-shadow:0 24px 50px -22px rgba(0,0,0,.7); z-index:5; }
#space-v2 .tbtn { width:44px; height:44px; border-radius:9px; display:grid; place-items:center; cursor:pointer;
  color:var(--cream2); background:transparent; border:1px solid rgba(var(--st-rgb),.24); position:relative; transition:border-color .14s ease, background-color .14s ease; }
#space-v2 .tbtn:hover { background:rgba(255,255,255,.07); color:var(--cream); border-color:rgba(var(--st-rgb),.45); }
#space-v2 .tbtn.on { background:var(--olive); color:#fff; border-color:rgba(255,255,255,.22); }
/* Which panel is currently open, on the tray button that opens it. Keyed off
   existing body classes (draw/ui.js, band.js, youtube.js, activities.js) rather
   than tracked separately in JS, so it can never drift out of sync with the
   actual state. Games' button opens a picker modal rather than toggling a
   panel directly, but body.game-active (activities.js _syncPanelLabel, the one
   shared hook already called after every activeActivity change) reflects
   whether a game is actually running on the stage, which is the real analog.
   Drawing is the one exception: body.draw-open means "a session is alive,"
   which stays true even while hidden behind a text channel you clicked over
   to (see technical_drawing_overview.md) — body.draw-shown (space-v2.js
   applyStageMode) is the derived "currently ON SCREEN" flag this button
   actually needs, so the icon doesn't stay lit after you've switched away. */
body.draw-shown #space-v2 .tray .tbtn[data-panel="draw"],
body.band-open #space-v2 .tray .tbtn[data-panel="band"],
body.studio-open #space-v2 .tray .tbtn[data-panel="band"],
body.yt-panel-open #space-v2 .tray .tbtn[data-panel="watch"],
body.soundboard-open #space-v2 .tray .tbtn[data-panel="soundboard"],
body.game-active #space-v2 .tray .tbtn[data-panel="games"] { background:var(--olive); color:#fff; border-color:rgba(255,255,255,.22); }
#space-v2 .tbtn.warn { background:rgba(199,95,62,.16); color:#ed9a7e; border-color:rgba(237,154,126,.4); }
#space-v2 .tbtn.act { background:var(--honey); color:#3a2410; border-color:rgba(58,36,16,.22); }
#space-v2 .tray-div { width:1px; height:26px; background:rgba(var(--st-rgb),.16); margin:0 3px; }
#space-v2 .tleave { display:inline-flex; align-items:center; gap:8px; height:44px; padding:0 18px; border-radius:9px; border:1px solid rgba(255,255,255,.18);
  background:var(--clay); color:#fff; font-family:var(--f); font-weight:800; font-size:13.5px; cursor:pointer; }
#space-v2 .tleave:hover { filter:brightness(1.07); }
/* DESKTOP shows every control directly, so the "More" overflow button is mobile-only */
#space-v2 .tray .tray-more { display:none; }
/* Width-driven fold, applied by fitTray() in space-v2.js. Same shape as the
   phone breakpoint's fold further down, but keyed on whether the tray actually
   fits the stage rather than on a viewport size — the rail and members panel
   eat into the stage, so the full tray overflows well before phone widths. */
#space-v2 .tray.tray-compact .tray-act,
#space-v2 .tray.tray-compact .tray-div { display:none; }
#space-v2 .tray.tray-compact .tray-more { display:grid; }
/* Still too wide: hang-up icon only. font-size:0 drops the "Leave" text and
   leaves the SVG, matching what the phone rule does to .tleave. */
#space-v2 .tray.tray-tiny .tleave { padding:0 14px; gap:0; font-size:0; }
/* "Back to the call" pill — leads the tray while reading chat; hidden when already
   in the call view (you don't need it there). */
#space-v2 .tray .spv2-tocall { width:auto; height:44px; padding:0 15px; display:inline-flex; align-items:center; gap:7px;
  background:var(--honey); color:#3a2410; font-family:var(--f); font-weight:800; font-size:13px; }
#space-v2 .tray .spv2-tocall:hover { background:var(--honey); filter:brightness(1.07); color:#3a2410; }
body.ui-v2 #space-v2.smode-call .tray .spv2-tocall,
body.ui-v2 #space-v2.smode-call .tray .spv2-tocall-div { display:none; }

/* ── right members panel (layout vars: dock/width/visible/float, see .rail) ── */
#space-v2 .members { width:var(--space-members-w,256px); flex:none; background:var(--paper); border-left:1px solid var(--div);
  display:var(--space-members-disp,flex); flex-direction:column; min-height:0; position:var(--space-members-pos,static);
  order:var(--space-members-order,2); left:var(--space-members-x,auto); top:var(--space-members-y,auto); z-index:var(--space-members-z,auto); }
#space-v2 .members .mscroll { flex:1; overflow-y:auto; padding:16px 12px; scrollbar-width:thin; scrollbar-color:var(--rust) transparent; }
#space-v2 .members .mscroll::-webkit-scrollbar { width:8px; }
#space-v2 .members .mscroll::-webkit-scrollbar-thumb { background:linear-gradient(var(--honey),var(--rust)); border-radius:99px; border:2px solid transparent; background-clip:padding-box; }
/* Desktop: smoothly collapse/expand the members column (spv2-mhide on the HOST so the
   state survives the roster re-render). The VISIBLE motion is a GPU transform on the
   inner list (its own compositor layer via will-change) so it stays buttery even while
   video decodes; the panel box width animates underneath so the stage reclaims the
   space, and overflow:hidden clips the list as it slides out. */
#space-v2 .members { overflow:hidden; transition:width .3s cubic-bezier(.33,1,.68,1), opacity .24s ease; }
#space-v2 .members .mscroll { min-width:var(--space-members-w,256px); box-sizing:border-box;
  will-change:transform; transition:transform .3s cubic-bezier(.33,1,.68,1); }
#space-v2.spv2-mhide .members { width:0; opacity:0; border-left-width:0; pointer-events:none; }
#space-v2.spv2-mhide .members .mscroll { transform:translateX(100%); }
@media (prefers-reduced-motion: reduce){ #space-v2 .members, #space-v2 .members .mscroll { transition:none; } }
#space-v2 .mgrp { margin-bottom:16px; }
#space-v2 .mgrp h6 { font-size:11px; text-transform:uppercase; letter-spacing:.09em; color:var(--ink3); font-weight:800; padding:0 8px 9px; }
#space-v2 .mrow { display:flex; align-items:center; gap:11px; padding:7px 8px; border-radius:10px; cursor:pointer; }
#space-v2 .mrow:hover { background:var(--s3,#e3ded3); }
#space-v2 .mrow .ma { width:34px; height:34px; border-radius:50%; display:grid; place-items:center; color:#fff; font-weight:700; font-size:13px; flex:none; position:relative; background-size:cover; background-position:center; }
#space-v2 .mrow .ma::after { content:""; position:absolute; right:-1px; bottom:-1px; width:11px; height:11px; border-radius:50%; border:2.5px solid var(--paper); background:var(--ink3); }
#space-v2 .mrow.on .ma::after { background:var(--olive); }
#space-v2 .mrow.call .ma::after { background:var(--clay); }
#space-v2 .mrow.idle .ma::after { background:var(--honey); }   /* idle = amber dot (Discord-style) */
#space-v2 .mrow .mn { font-weight:700; font-size:14px; line-height:1.15; display:flex; align-items:center; gap:6px; }
#space-v2 .mrow .crown { color:var(--honey); }
#space-v2 .mrow .mst { font-size:11.5px; color:var(--ink2); }
#space-v2 .mrow.off { opacity:.55; }
/* trailing in-call status icon (muted mic / sharing) on the right of the row */
#space-v2 .mrow .mrow-st { margin-left:auto; display:flex; align-items:center; flex:none; }
#space-v2 .mrow .mrow-st.mut { color:var(--clay); }
#space-v2 .mrow .mrow-st.shr { color:var(--olive); }
/* .act can hold more than one icon at once (YouTube + Studio together) -
   gap between them, same 6px separation from whatever sits before it. */
#space-v2 .mrow .mrow-st.act { color:var(--rust); margin-left:6px; }

/* the floating tray + its bottom-padding clearance + the stage padding belong to
   the call grid only (mode-call). chat/empty fill the stage edge-to-edge on paper. */
#space-v2 .tray { display:none; }
body.ui-v2 #space-v2.smode-call .tray { display:flex; }
#space-v2:not(.smode-call) .stage-body { padding:0; }
body.ui-v2 #space-v2.smode-call .stage-body { padding-bottom:92px; }

/* ===== stage content: ONE section, three mutually-exclusive modes =====
   The stage slot holds the FRESH call view (#spv2-call, built from the mock),
   the reparented #chat-view, and an empty placeholder (#spv2-empty). One class on
   the slot (mode-call / mode-chat / mode-empty) shows exactly one — so chat and
   the call live in the SAME element/section/layer and can never split. The call
   view is shown ONLY in mode-call (set only while in a voice call). */
/* The three stage surfaces all fill the slot. VISIBILITY:
   - #spv2-call + #spv2-empty are gated by the slot's MODE CLASS (.mode-call / .mode-empty)
     so an audio-only call (which adds .spv2-grid) can't leak past the hide — that was
     the "both half-size" bug: display:grid !important on .spv2-grid beat the hide, so
     the call grid showed in the top half while chat showed in the bottom half.
   - #chat-view is gated by inline display in applyStageMode() (chat.js sets #chat-view's
     inline display, which a CSS class can't beat). */
body.ui-v2 #space-v2 #spv2-call,
body.ui-v2 #space-v2 #spv2-empty,
body.ui-v2 #space-v2 #chat-view { flex:1; min-height:0; }
body.ui-v2 #space-v2 .stage-slot.mode-call > #spv2-call { display:flex; }
body.ui-v2 #space-v2 .stage-slot.mode-call > #spv2-call.spv2-grid { display:grid; }
body.ui-v2 #space-v2 .stage-slot:not(.mode-call) > #spv2-call { display:none; }
body.ui-v2 #space-v2 .stage-slot.mode-empty > #spv2-empty { display:flex; }
body.ui-v2 #space-v2 .stage-slot:not(.mode-empty) > #spv2-empty { display:none; }

/* --- fresh call view, ported from the mock (.spot spotlight + .film filmstrip) --- */
#space-v2 #spv2-call { gap:12px; }
#space-v2 #spv2-call:not(.spv2-grid) { flex-direction:row; }
#space-v2 #spv2-call.spv2-grid { grid-auto-rows:1fr; }
#space-v2 .spot { flex:1; min-width:0; border-radius:8px; overflow:hidden; position:relative;
  background:var(--tile); border:1px solid var(--tline); box-shadow:0 20px 50px -28px #000; }
#space-v2 .film { width:188px; flex:none; display:flex; flex-direction:column; gap:12px; overflow-y:auto; }
#space-v2 .ftile { flex:none; aspect-ratio:16/11; border-radius:9px; position:relative; overflow:hidden;
  background:var(--tile2); border:1px solid var(--tline); cursor:pointer; }
#space-v2 #spv2-call.spv2-grid .ftile { aspect-ratio:auto; }
#space-v2 .spot > .ftile { position:absolute; inset:0; aspect-ratio:auto; border:none; border-radius:8px; }
/* speaking ring drawn INSIDE the tile via an ::after over the video, so it hugs the
   rounded tile exactly and is never clipped. An OUTER box-shadow got cut off by the
   .spot (overflow:hidden) on the spotlight and by the .film scroll box on the small
   tiles — the "doesn't fit the little window" bug. inset + border-radius:inherit fits
   every size (13px film tile, 16px spotlight, 0 when full-bleed). */
#space-v2 .ftile.speaking::after { content:''; position:absolute; inset:0; border-radius:inherit;
  box-shadow:inset 0 0 0 2px var(--olive); pointer-events:none; z-index:6; }
#space-v2 .cam { position:absolute; inset:0; display:grid; place-items:center;
  background:radial-gradient(80% 80% at 50% 35%, var(--cf1,#c98a4e), var(--cf2,#6e4a22)); }
#space-v2 .cam .big { width:52px; height:52px; border-radius:50%; background:rgba(255,255,255,.16);
  display:grid; place-items:center; color:#fff; font-weight:800; font-size:20px; font-family:var(--disp);
  background-size:cover; background-position:center; }
#space-v2 .spot .cam .big, #space-v2 #spv2-call.spv2-grid .cam .big { width:72px; height:72px; font-size:28px; }
/* always show the whole stream (camera or screen share) scaled to fit the tile on
   every side, never cropped; letterbox gaps fall back to --tile2. */
#space-v2 .spv-video { position:absolute; inset:0; width:100%; height:100%; object-fit:contain; display:block; background:var(--tile2); }
#space-v2 .spv-mirror { transform:scaleX(-1); }
#space-v2 .spv-activity { position:absolute; inset:0; width:100%; height:100%; border:0; display:block; background:#000; }
/* click-shield over a SMALL (not spotlit) game tile so it can be focused/enlarged;
   removed once the tile is the spotlight, so the big game iframe is fully interactive */
#space-v2 .ftile.act .spv-act-shield { position:absolute; inset:0; z-index:4; cursor:pointer; }
#space-v2 .ftile.act.is-spot .spv-act-shield { display:none; }
/* in-app "fullscreen" (maximize) — the fs button expands the spotlight to FULL-BLEED:
   over the topbar, to the very bottom edge, with rail/members/stage-head/filmstrip hidden.
   The control tray becomes a popup toggled by a small bottom-left button. Exit via the
   spotlight's compress button or Escape. Reliable CSS, unlike the OS Fullscreen API. */
#space-v2.spv2-maxed .rail,
#space-v2.spv2-maxed .members,
#space-v2.spv2-maxed .stage-head,
#space-v2.spv2-maxed .topbar { display:none; }
body.ui-v2 #space-v2.spv2-maxed .stage-body { padding:0; }   /* beat the smode-call padding-bottom */
#space-v2.spv2-maxed .spot,
#space-v2.spv2-maxed .spot > .ftile { border-radius:0; border:none; box-shadow:none; }   /* no bevel when full-bleed (the inner tile keeps 16px rounding otherwise) */
#space-v2.spv2-maxed .tile-tag { top:16px; bottom:auto; left:16px; }   /* move the "X is sharing" tag clear of the bottom-left controls button */
/* tray = popup: hidden by default in maxed, anchored bottom-left, shown when controls-open */
body.ui-v2 #space-v2.spv2-maxed .tray { display:none; left:16px; bottom:66px; transform:none; }
body.ui-v2 #space-v2.spv2-maxed.spv2-controls-open .tray { display:flex; }
/* the bottom-left "controls" toggle button (only visible while maxed) */
#space-v2 .spv2-maxbar { display:none; }
#space-v2.spv2-maxed .spv2-maxbar { display:grid; place-items:center; position:absolute; left:16px; bottom:16px; z-index:6;
  width:42px; height:42px; border-radius:9px; cursor:pointer; color:var(--cream2);
  background:rgba(var(--st-glass-rgb),.82); -webkit-backdrop-filter:blur(14px); backdrop-filter:blur(14px);
  border:1px solid rgba(var(--st-rgb),.16); box-shadow:0 14px 32px -14px rgba(0,0,0,.65); }
#space-v2.spv2-maxed .spv2-maxbar:hover { color:var(--cream); background:rgba(45,34,18,.9); }
#space-v2.spv2-maxed.spv2-controls-open .spv2-maxbar { color:var(--st-hot); border-color:rgba(var(--st-act-rgb),.4); background:rgba(var(--st-act-rgb),.18); }
#space-v2 .ftile.act { background:var(--st-tile-act); }
#space-v2 .ftile .nm { position:absolute; left:9px; bottom:8px; font-size:11.5px; font-weight:700;
  color:var(--cream); text-shadow:0 1px 4px rgba(0,0,0,.5); display:flex; align-items:center; gap:5px; z-index:2; }
#space-v2 .is-spot .nm { display:none; }   /* mock: the spotlight shows only the "X is sharing" tag, no name */
#space-v2 .nm .gmu { color:var(--clay); display:inline-flex; }
#space-v2 .nm .gsh { color:var(--olive); display:inline-flex; }
/* Corner badge cluster: mute + one chip per activity type, ALL sized/built
   the exact same way (same width/height/radius/background/blur/shadow) and
   toggled the exact same way (display:none, a class on the tile flips ONE
   chip to display:grid) - no shared multi-icon container, no chip that
   changes its own content. They're flex siblings in one positioned parent
   so however many show up at once get spaced by real layout instead of a
   guessed pixel offset between separately-positioned chips (that guess is
   what read as merged/too-close before). */
#space-v2 .ftile .tile-badges { position:absolute; left:8px; top:8px; z-index:5; display:flex; gap:6px; }
#space-v2 .ftile .tile-mute,
#space-v2 .ftile .tile-act { display:none; width:23px; height:23px; border-radius:8px; place-items:center;
  background:rgba(var(--st-ink-rgb),.72); -webkit-backdrop-filter:blur(6px); backdrop-filter:blur(6px);
  box-shadow:0 2px 9px -2px rgba(0,0,0,.5); }
#space-v2 .ftile .tile-mute { color:var(--clay); }
#space-v2 .ftile .tile-act { color:var(--rust); }
#space-v2 .ftile.is-muted .tile-mute { display:grid; }
#space-v2 .ftile.has-studio .tile-act-studio { display:grid; }
#space-v2 .ftile.has-drawing .tile-act-drawing { display:grid; }
#space-v2 .ftile.has-youtube .tile-act-youtube { display:grid; }
/* Report-stream button on remote camera/screen tiles. Matches .tile-fs (same
   size/shape/reveal); on the spotlight it sits to the LEFT of the fullscreen
   button so the two don't stack. */
#space-v2 .ftile .spv-report-btn,
#space-v2 .ftile .spv-vol-btn {
  position:absolute; top:12px; right:12px; width:32px; height:32px; border-radius:9px;
  display:grid; place-items:center; border:none; cursor:pointer; z-index:3;
  background:rgba(var(--st-ink-rgb),.6); color:var(--cream2);
  opacity:0; transition:opacity .15s, color .15s, background .15s;
}
#space-v2 .ftile:hover .spv-report-btn,
#space-v2 .spot:hover .spv-report-btn,
#space-v2 .ftile:hover .spv-vol-btn,
#space-v2 .spot:hover .spv-vol-btn { opacity:1; }
#space-v2 .spot .spv-report-btn { right:52px; }   /* clear the fullscreen button on the spotlight */
#space-v2 .spv-report-btn:hover { color:#fff; background:rgba(200,55,55,.85); }
/* Stream volume sits one slot further in than report, so the row reads
   fullscreen / report / volume from the corner inwards and nothing stacks. */
#space-v2 .ftile .spv-vol-btn { right:52px; }
#space-v2 .spot  .spv-vol-btn { right:92px; }
#space-v2 .spv-vol-btn:hover { color:var(--cream); background:rgba(var(--st-ink-rgb),.85); }
@media (hover:none){ #space-v2 .ftile .spv-report-btn,
                     #space-v2 .ftile .spv-vol-btn { opacity:.85; } }   /* touch: no hover, keep it reachable */
#space-v2 .ftile.spv-reported .spv-video { filter:blur(30px) brightness(.45); }
#space-v2 .ftile .spv-reported-cover {
  position:absolute; inset:0; z-index:6; border-radius:inherit;
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  gap:10px; text-align:center; padding:14px; background:rgba(var(--st-ink-rgb),.62); color:var(--cream,#fff);
}
#space-v2 .ftile .spv-reported-cover .src-msg { font-size:12.5px; font-weight:700; }
#space-v2 .ftile .spv-reported-cover .src-show {
  background:rgba(255,255,255,.16); border:1px solid rgba(255,255,255,.35); color:var(--cream,#fff);
  border-radius:8px; padding:5px 13px; font-size:12px; cursor:pointer;
}
#space-v2 .ftile .spv-reported-cover .src-show:hover { background:rgba(255,255,255,.28); }
#space-v2 .tile-tag { position:absolute; left:12px; bottom:12px; display:flex; align-items:center; gap:7px;
  background:rgba(var(--st-ink-rgb),.72); backdrop-filter:blur(6px); -webkit-backdrop-filter:blur(6px); color:var(--cream);
  padding:6px 11px; border-radius:10px; font-size:12px; font-weight:700; z-index:3; }
#space-v2 .tile-tag .lv { width:6px; height:6px; border-radius:50%; background:var(--clay); }
#space-v2 .tile-fs { position:absolute; right:12px; top:12px; width:32px; height:32px; border-radius:9px; display:grid; place-items:center;
  background:rgba(var(--st-ink-rgb),.6); color:var(--cream2); cursor:pointer; opacity:0; transition:opacity .15s; z-index:3; border:none; }
#space-v2 .spot:hover .tile-fs { opacity:1; }
#space-v2 .tile-fs:hover { color:var(--cream); }

/* --- Pop out: the live call as a draggable picture-in-picture (desktop) ---
   Kept INSIDE #space-v2 (position:fixed) so every #space-v2 .spot/.film/.ftile
   rule still styles the moved call node — #spv2-call is MOVED here, not rebuilt.
   renderSpaceV2() reattaches this node across chrome rebuilds so media survives. */
#space-v2 #spv2-float { position:fixed; right:24px; bottom:24px; z-index:64;
  width:min(460px,40vw); height:min(300px,42vh); display:flex; flex-direction:column; overflow:hidden;
  background:var(--stage); border:1px solid var(--tline); border-radius:8px;
  box-shadow:0 28px 64px -20px rgba(15,9,3,.7), 0 0 0 1px rgba(0,0,0,.25); }
#space-v2 #spv2-float .spv2-float-head { flex:none; display:flex; align-items:center; gap:8px;
  height:38px; padding:0 8px 0 13px; background:rgba(255,255,255,.04); border-bottom:1px solid var(--tline);
  cursor:grab; user-select:none; touch-action:none; }
#space-v2 #spv2-float .spv2-float-head:active { cursor:grabbing; }
#space-v2 #spv2-float .spv2-float-t { flex:1; min-width:0; display:inline-flex; align-items:center; gap:7px;
  font-family:var(--disp); font-weight:700; font-size:12.5px; color:var(--cream);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
#space-v2 #spv2-float .spv2-float-t .lv { width:7px; height:7px; border-radius:50%; background:var(--clay);
  flex:none; }
#space-v2 #spv2-float .spv2-float-dock { flex:none; display:grid; place-items:center; width:28px; height:28px;
  border-radius:8px; border:1px solid var(--tline); background:rgba(255,255,255,.04); color:var(--cream2); cursor:pointer; }
#space-v2 #spv2-float .spv2-float-dock:hover { color:var(--cream); background:rgba(255,255,255,.09); }
#space-v2 #spv2-float .spv2-float-body { flex:1; min-height:0; min-width:0; display:flex; padding:10px; }
/* the moved call node: show it regardless of the slot mode-class (it's no longer a slot child) */
#space-v2 #spv2-float #spv2-call { display:flex; }
#space-v2 #spv2-float #spv2-call.spv2-grid { display:grid; }
#space-v2 #spv2-float .film { width:118px; gap:9px; }   /* compact filmstrip for the small PiP */

/* ============================================================
   ui-v2 — the floating CALL DOCK (ported 1:1 from the mock
   design-mockups/eaves-ui/calldock.css). A persistent call HUD that follows you
   when you're in a call but away from that call's Space. Warm-dark, draggable.
   z-index 9000: above full-screen content (store/settings ~215), below modals (9999+).
   Positioning is owned entirely by call-dock.js (JS) so drag + re-render don't fight.
   ============================================================ */
/* min() so a window narrower than the dock shrinks it instead of letting it hang
   off the edge. The JS clamp keeps it in view, but with a hard 300px it had
   nowhere to go once the viewport was under ~312px. */
#call-dock { position:fixed; width:min(300px, calc(100vw - 12px)); z-index:9000;
  background:var(--st-dock-bg);
  border:1px solid var(--tline); border-radius:9px; overflow:hidden;
  box-shadow:0 30px 70px -24px rgba(10,6,2,.82), 0 0 0 1px rgba(0,0,0,.28);
  font-family:var(--f); color:var(--cream); -webkit-font-smoothing:antialiased; user-select:none; }
#call-dock .cdock-grip { display:flex; align-items:center; gap:10px; padding:11px 9px 11px 13px;
  cursor:grab; border-bottom:1px solid var(--tline); touch-action:none; }
#call-dock .cdock-grip:active { cursor:grabbing; }
#call-dock .cdock-live { position:relative; width:9px; height:9px; flex:none; border-radius:50%; background:var(--olive); }
#call-dock .cdock-live::after { display:none; }   /* dropped the pulsing ripple ring (read as an AI tell) */
@keyframes cd-pulse { 0%{ transform:scale(.7); opacity:.6 } 100%{ transform:scale(1.5); opacity:0 } }
#call-dock .cdock-id { flex:1; min-width:0; }
#call-dock .cdock-ch { font-family:var(--disp); font-weight:800; font-size:13.5px; letter-spacing:-.01em; line-height:1.15;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
#call-dock .cdock-srv { font-size:11px; color:var(--cream3); font-weight:600; margin-top:2px;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
#call-dock .cdock-gbtn { width:28px; height:28px; flex:none; border-radius:8px; display:grid; place-items:center;
  border:none; background:transparent; color:var(--cream2); cursor:pointer; }
#call-dock .cdock-gbtn:hover { background:rgba(255,255,255,.08); color:var(--cream); }
#call-dock .cdock-people { display:flex; align-items:center; gap:9px; padding:13px 13px 11px; cursor:pointer; }
#call-dock .cdock-people:hover .cdock-av { filter:brightness(1.05); }
#call-dock .cdock-av { position:relative; width:34px; height:34px; flex:none; border-radius:50%;
  display:grid; place-items:center; color:#fff; font-weight:800; font-size:14px; font-family:var(--disp);
  background-size:cover; background-position:center; }
#call-dock .cdock-av.speaking { box-shadow:0 0 0 2px var(--st-dock-bg2), 0 0 0 4px var(--olive); }
#call-dock .cdock-av .badge { position:absolute; right:-3px; bottom:-3px; width:16px; height:16px; padding:0; gap:0; border-radius:50%;
  display:grid; place-items:center; border:2.5px solid var(--st-dock-bg2); }
#call-dock .cdock-av .badge svg { display:block; }
#call-dock .cdock-av .badge.mu { background:var(--clay); color:#fff; }
#call-dock .cdock-av .badge.sh { background:var(--olive); color:#fff; }
#call-dock .cdock-more { width:34px; height:34px; flex:none; border-radius:50%; display:grid; place-items:center;
  background:rgba(255,255,255,.06); color:var(--cream2); font-weight:800; font-size:12px; }
#call-dock .cdock-controls { display:flex; align-items:center; gap:7px; padding:0 13px 13px; }
/* flex:none is load-bearing, not tidying. Without it these shrink, so the row
   silently squeezed four 43px buttons into the space for about three and a half
   (it needs ~324px inside a 300px dock) and they stopped being square. It also
   makes the overflow test in fitControls() meaningful: shrinkable items never
   overflow, so scrollWidth would always equal clientWidth and the row would
   never fold. */
#call-dock .cdock-btn { width:43px; height:43px; flex:none; border-radius:9px; display:grid; place-items:center; cursor:pointer;
  border:none; background:rgba(255,255,255,.05); color:var(--cream2); transition:background .12s, color .12s; }
#call-dock .cdock-btn:hover { background:rgba(255,255,255,.1); color:var(--cream); }
#call-dock .cdock-btn.on { background:var(--olive); color:#fff; }
#call-dock .cdock-btn.warn { background:rgba(199,95,62,.2); color:#ed9a7e; }
#call-dock .cdock-btn.act { background:var(--honey); color:#3a2410; }
#call-dock .cdock-spacer { flex:1; }
#call-dock .cdock-leave { display:inline-flex; align-items:center; gap:7px; height:43px; flex:none; padding:0 15px; border-radius:9px;
  border:none; background:var(--clay); color:#fff; font-family:var(--f); font-weight:800; font-size:13px; cursor:pointer; }
#call-dock .cdock-leave:hover { filter:brightness(1.07); }

/* ── overflow (⋯): two tiers, both driven by a real fit measurement in
   fitControls(), not a guessed breakpoint. cd-narrow folds camera + share into
   the menu; cd-tiny additionally drops the Leave label. Mic, deafen and Leave
   itself never leave the row. ── */
#call-dock .cd-morebtn { display:none; }
#call-dock.cd-narrow .cd-morebtn { display:grid; }
#call-dock.cd-narrow .cdock-controls .cd-opt { display:none; }
#call-dock.cd-tiny .cdock-leave { padding:0 13px; }
#call-dock.cd-tiny .cd-leave-label { display:none; }
#call-dock .cdock-more-menu { display:none; }
#call-dock.cd-more-open .cdock-more-menu { display:flex; flex-direction:column; gap:2px; padding:0 13px 13px; }
#call-dock .cdock-more-menu button { display:flex; align-items:center; gap:10px; width:100%;
  padding:9px 10px; border:none; border-radius:8px; cursor:pointer; text-align:left;
  background:rgba(255,255,255,.05); color:var(--cream2);
  font-family:var(--f); font-weight:700; font-size:13px; }
#call-dock .cdock-more-menu button:hover { background:rgba(255,255,255,.1); color:var(--cream); }
#call-dock .cdock-more-menu button svg { flex:none; }

/* minimized: a compact one-row pill */
#call-dock.mini { width:auto; max-width:min(300px, calc(100vw - 12px)); }
#call-dock .cdock-pill { display:flex; align-items:center; gap:8px; padding:8px 8px 8px 7px; cursor:grab; touch-action:none; }
#call-dock .cdock-pill:active { cursor:grabbing; }
#call-dock .cdock-drag { flex:none; display:grid; place-items:center; color:var(--cream3); cursor:grab; touch-action:none; padding:2px 1px; }
#call-dock .cdock-drag:active { cursor:grabbing; }
#call-dock .cdock-pill .cdock-open { display:flex; align-items:center; gap:9px; min-width:0; cursor:pointer; flex:1; }
/* Without min-width:0 here, this flex item's default min-width is its nowrap
   channel-name text's full intrinsic width — .cdock-ch's own text-overflow:ellipsis
   (above) never gets a chance to engage, so a long channel/server name overflows
   straight across the Expand/mic/deafen/leave buttons in the minimized pill
   (mirrors the same min-width:0 the expanded view's .cdock-id already has). */
#call-dock .cdock-pill-id { min-width:0; }
#call-dock .cdock-pill .cdock-ch { font-size:13px; }
#call-dock .cdock-pill .cdock-n { font-size:11px; font-weight:700; color:var(--cream3); margin-top:1px;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
#call-dock .cdock-pill .cdock-btn { width:38px; height:38px; }
#call-dock .cdock-pill .cdock-leave { height:38px; width:38px; padding:0; justify-content:center; }

/* the call tray's "More" (⋯) overflow menu — appended to <body>, opens from the tray */
body.ui-v2 .spv2-more-menu { position:fixed; z-index:9500; min-width:196px; padding:6px;
  background:rgba(var(--st-pop-rgb),.97); -webkit-backdrop-filter:blur(16px); backdrop-filter:blur(16px);
  border:1px solid rgba(var(--st-rgb),.18); border-radius:10px;
  box-shadow:0 26px 56px -20px rgba(0,0,0,.72), 0 0 0 1px rgba(0,0,0,.25);
  display:flex; flex-direction:column; gap:1px; font-family:var(--f); }
body.ui-v2 .spv2-more-item { display:flex; align-items:center; gap:11px; padding:9px 11px; border-radius:9px;
  border:none; background:transparent; color:var(--cream2); cursor:pointer; font-family:var(--f);
  font-weight:600; font-size:13px; text-align:left; width:100%; }
body.ui-v2 .spv2-more-item:hover { background:rgba(255,255,255,.07); color:var(--cream); }
/* I.cursor (space-v2.js) carries an inline transform:translate() optical nudge
   tuned for its OTHER use (the round 44px call-tray .tbtn) — cancel it here so
   the "Share cursor" row's icon doesn't sit ~1.5px off from its siblings in
   this flex icon+label row, which was never the context that nudge was for. */
body.ui-v2 .spv2-more-item svg { flex:none; opacity:.9; transform:none !important; }
body.ui-v2 .spv2-more-div { height:1px; margin:5px 8px; background:rgba(var(--st-rgb),.14); }
/* in-call Microphone & audio popover (a wider .spv2-more-menu variant with selects + a slider) */
body.ui-v2 .spv2-mic-menu { min-width:248px; gap:0; padding:10px 12px 12px; }
body.ui-v2 .spv2-mic-menu .spv2-mic-h { font-size:11px; font-weight:800; letter-spacing:.04em; text-transform:uppercase; color:var(--cream2); opacity:.7; margin:10px 2px 5px; }
body.ui-v2 .spv2-mic-menu .spv2-mic-h:first-child { margin-top:0; }
body.ui-v2 .spv2-mic-sel { width:100%; box-sizing:border-box; padding:8px 10px; border-radius:9px; border:1px solid rgba(var(--st-rgb),.2);
  background:rgba(0,0,0,.28); color:var(--cream); font-family:var(--f); font-size:13px; font-weight:600; }
body.ui-v2 .spv2-mic-sel:focus { outline:none; border-color:var(--honey); }
body.ui-v2 .spv2-mic-rng { width:100%; margin:4px 0 0; accent-color:var(--honey); }
/* Input mode segment (Voice / Push to talk) + the key-capture button below
   it - same visual language as the sel/rng controls above, scoped to this
   popup since #settings-v2-screen .seg2/.keycap aren't in the DOM here. */
body.ui-v2 .spv2-mic-seg { display:flex; background:rgba(0,0,0,.28); border-radius:9px; padding:3px; }
body.ui-v2 .spv2-mic-seg button { flex:1; border:none; background:transparent; font-family:var(--f); font-weight:700;
  font-size:12px; color:var(--cream2); padding:6px 8px; border-radius:7px; cursor:pointer; }
body.ui-v2 .spv2-mic-seg button.on { background:rgba(255,255,255,.14); color:var(--cream); }
body.ui-v2 .spv2-mic-key { width:100%; box-sizing:border-box; margin-top:6px; padding:7px 10px; border-radius:9px;
  border:1px solid rgba(var(--st-rgb),.2); background:rgba(0,0,0,.28); color:var(--cream);
  font-family:var(--f); font-weight:800; font-size:12.5px; cursor:pointer; }
body.ui-v2 .spv2-mic-key.listening { border-color:var(--honey); color:var(--honey); }

/* server menu (off the topbar server name) — a warm PAPER popover (the desktop topbar is paper) */
body.ui-v2 .spv2-srvmenu { position:fixed; z-index:9500; min-width:214px; padding:6px;
  background:var(--card); border:1px solid var(--line); border-radius:10px;
  box-shadow:0 22px 48px -18px rgba(80,50,15,.42), 0 0 0 1px rgba(80,50,15,.05);
  display:flex; flex-direction:column; gap:1px; font-family:var(--f); }
body.ui-v2 .spv2-srvmenu-item { display:flex; align-items:center; gap:11px; padding:9px 11px; border-radius:9px;
  border:none; background:transparent; color:var(--ink); cursor:pointer; font-family:var(--f);
  font-weight:600; font-size:13px; text-align:left; width:100%; }
body.ui-v2 .spv2-srvmenu-item:hover { background:var(--s3,#e3ded3); }
body.ui-v2 .spv2-srvmenu-item svg { flex:none; color:var(--ink2); }
/* "Invite people" and "Notifications: ..." are always items 1 and 2 (pushed
   unconditionally before any conditional items) — their icons sat visibly
   off-center against the others in the shared gap/padding. */
body.ui-v2 .spv2-srvmenu-item:nth-child(1) svg { position:relative; left:2px; }
body.ui-v2 .spv2-srvmenu-item:nth-child(2) svg { position:relative; left:-1px; }
body.ui-v2 .spv2-srvmenu-item.danger { color:var(--clay); }
body.ui-v2 .spv2-srvmenu-item.danger svg { color:var(--clay); }
body.ui-v2 .spv2-srvmenu-div { height:1px; margin:5px 8px; background:var(--line); }

/* notification inbox (off the topbar bell) — a warm PAPER popover. The inner
   .notif-invite-* rows are reused from the classic panel; their var(--border)/
   var(--text2/3) tokens are already redefined warm under body.ui-v2, so they
   inherit the warm palette with no per-row overrides. */
body.ui-v2 .spv2-notifs { position:fixed; z-index:9500; width:320px; max-width:calc(100vw - 16px); max-height:min(70vh,460px); overflow-y:auto;
  background:var(--card); border:1px solid var(--line); border-radius:10px;
  box-shadow:0 22px 48px -18px rgba(80,50,15,.42), 0 0 0 1px rgba(80,50,15,.05);
  font-family:var(--f); }
body.ui-v2 .spv2-notifs-head { position:sticky; top:0; z-index:1; padding:11px 14px 9px;
  font-family:var(--disp); font-weight:800; font-size:14px; color:var(--ink);
  background:var(--card); border-bottom:1px solid var(--line);
  display:flex; align-items:center; justify-content:space-between; }
body.ui-v2 .spv2-notifs-clear { font-family:var(--f); font-weight:700; font-size:11.5px; color:var(--rust);
  background:none; border:none; cursor:pointer; padding:2px 4px; }
body.ui-v2 .spv2-notifs-clear:hover { text-decoration:underline; }
body.ui-v2 .spv2-notifs-empty { padding:30px 16px; text-align:center; color:var(--ink3); font-size:13px; }
/* --- ui-v2 in-call / space message search popover (warm paper) --- */
body.ui-v2 .spv2-search { position:fixed; z-index:9500; width:400px; max-width:calc(100vw - 16px);
  max-height:min(72vh,520px); display:flex; flex-direction:column; overflow:hidden;
  background:var(--card); border:1px solid var(--line); border-radius:10px;
  box-shadow:0 22px 48px -18px rgba(80,50,15,.42), 0 0 0 1px rgba(80,50,15,.05);
  font-family:var(--f); }
body.ui-v2 .spv2-search-head { display:flex; align-items:center; gap:8px; padding:10px 12px;
  border-bottom:1px solid var(--line); background:var(--card); flex:none; }
body.ui-v2 .spv2-search-head .ssch-ico { display:grid; place-items:center; color:var(--ink3); flex:none; }
body.ui-v2 .spv2-search .ssch-input { flex:1; min-width:0; border:none; background:none; outline:none;
  font-family:var(--f); font-size:14px; color:var(--ink); padding:2px 0; }
body.ui-v2 .spv2-search .ssch-input::placeholder { color:var(--ink3); }
body.ui-v2 .spv2-search .ssch-close { flex:none; display:grid; place-items:center; width:26px; height:26px;
  border:none; background:none; border-radius:8px; color:var(--ink3); cursor:pointer; }
body.ui-v2 .spv2-search .ssch-close:hover { background:var(--card2); color:var(--ink); }
/* which on-device engine is searching encrypted channels: muted "Standard" vs accent "Cool Search" */
body.ui-v2 .spv2-search .ssch-eng { flex:none; align-items:center; font-size:10px; font-weight:800; letter-spacing:.03em;
  text-transform:uppercase; padding:3px 8px; border-radius:999px; white-space:nowrap; cursor:default;
  background:var(--card2); color:var(--ink3); border:1px solid var(--line); }
body.ui-v2 .spv2-search .ssch-eng.cool { background:var(--accent); color:var(--accent-fg,#fff); border-color:transparent; }
/* from:/in: autocomplete dropdown (sits between the input row and the results) */
body.ui-v2 .spv2-search .ssch-ac { flex:none; max-height:230px; overflow-y:auto; border-bottom:1px solid var(--line); padding:5px; }
body.ui-v2 .spv2-search .ssch-ac-item { display:flex; align-items:center; gap:6px; padding:7px 9px; border-radius:8px; cursor:pointer; font-size:13px; color:var(--ink); }
body.ui-v2 .spv2-search .ssch-ac-item:hover { background:var(--card2); }
body.ui-v2 .spv2-search .ssch-ac-pfx { color:var(--accent); font-weight:800; }
body.ui-v2 .spv2-search-body { overflow-y:auto; padding:6px; flex:1; }
body.ui-v2 .spv2-search-body.ssch-loading { opacity:.55; }
body.ui-v2 .spv2-search .ssch-hint,
body.ui-v2 .spv2-search .ssch-empty { padding:26px 16px; text-align:center; color:var(--ink3); font-size:13px; }
body.ui-v2 .spv2-search .ssch-ops { margin-top:10px; font-size:11.5px; line-height:1.7; color:var(--ink3); }
body.ui-v2 .spv2-search .ssch-ops b { font-family:var(--mono,ui-monospace,monospace); font-weight:700; color:var(--ink2); }
body.ui-v2 .spv2-search .ssch-encnote,
body.ui-v2 .spv2-search .ssch-more { padding:8px 12px 4px; text-align:center; color:var(--ink3); font-size:11.5px; }
body.ui-v2 .spv2-search .ssch-res { display:flex; gap:10px; padding:9px 10px; border-radius:10px; cursor:pointer; align-items:flex-start; }
body.ui-v2 .spv2-search .ssch-res:hover,
body.ui-v2 .spv2-search .ssch-res.nav-sel { background:var(--card2); }
body.ui-v2 .spv2-search .ssch-ac-item.nav-sel { background:var(--card2); }
/* author + channel in a result are clickable to refine (from: / in:) */
body.ui-v2 .spv2-search .ssch-user, body.ui-v2 .spv2-search .ssch-ch { cursor:pointer; }
body.ui-v2 .spv2-search .ssch-user:hover, body.ui-v2 .spv2-search .ssch-ch:hover { text-decoration:underline; }
body.ui-v2 .spv2-search .ssch-av { flex:none; width:32px; height:32px; border-radius:50%; background-size:cover; background-position:center;
  background-color:var(--card2); display:grid; place-items:center; font-weight:800; font-size:13px; color:#fff; }
body.ui-v2 .spv2-search .ssch-av-i { background:var(--accent); }
body.ui-v2 .spv2-search .ssch-main { flex:1; min-width:0; }
body.ui-v2 .spv2-search .ssch-meta { display:flex; align-items:baseline; gap:7px; flex-wrap:wrap; line-height:1.3; }
body.ui-v2 .spv2-search .ssch-user { font-weight:700; font-size:13px; color:var(--ink); }
body.ui-v2 .spv2-search .ssch-ch { font-size:11.5px; color:var(--accent); font-weight:600; }
body.ui-v2 .spv2-search .ssch-time { font-size:11px; color:var(--ink3); }
body.ui-v2 .spv2-search .ssch-lock { display:inline-flex; align-items:center; color:var(--accent); opacity:.85; }
body.ui-v2 .spv2-search .ssch-srv { font-size:11px; color:var(--ink3); font-weight:600; }
body.ui-v2 .spv2-search .ssch-srv::before { content:"in "; font-weight:400; opacity:.7; }
/* scope toggle: This server / All servers (global search) */
body.ui-v2 .spv2-search .ssch-scope { display:flex; gap:4px; padding:6px 10px; border-bottom:1px solid var(--line); flex:none; }
body.ui-v2 .spv2-search .ssch-scope button { flex:1; font-family:var(--f); font-size:12px; font-weight:700; padding:6px 8px;
  border-radius:8px; border:1px solid transparent; background:none; color:var(--ink3); cursor:pointer; }
body.ui-v2 .spv2-search .ssch-scope button.on { background:var(--card2); color:var(--ink); border-color:var(--line); }
body.ui-v2 .spv2-search .ssch-snip { font-size:12.5px; color:var(--ink2); line-height:1.45; margin-top:2px;
  display:-webkit-box; -webkit-line-clamp:3; -webkit-box-orient:vertical; overflow:hidden; word-break:break-word; }
body.ui-v2 .spv2-search .ssch-snip mark { background:rgba(201,138,46,.28); color:var(--ink); border-radius:3px; padding:0 1px; }
body.ui-v2 .spv2-search .ssch-reply { font-size:11.5px; color:var(--ink3); line-height:1.4; margin-top:2px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
body.ui-v2 .spv2-search .ssch-reply-user { font-weight:700; color:var(--ink2); }
body.ui-v2 .spv2-search .ssch-reactions { display:flex; flex-wrap:wrap; gap:4px; margin-top:4px; }
body.ui-v2 .spv2-search .ssch-reaction-chip { font-size:11px; padding:1px 6px; border-radius:8px; background:var(--card2); border:1px solid var(--line); color:var(--ink2); }
/* mobile: full-width sheet TOP-anchored under the topbar (the JS sets `top` just below it), so
   the input stays above the on-screen keyboard and the results scroll beneath it. Bottom-anchoring
   would put the input/results behind the keyboard. Honors the home-bar safe area. */
@media (max-width:700px), (pointer:coarse) and (max-width:950px){
  body.ui-v2 .spv2-search { left:8px !important; right:8px; width:auto; max-width:none;
    bottom:calc(10px + env(safe-area-inset-bottom, 0px)); max-height:none; }
  /* the engine chip can't change on mobile (Cool Search is desktop-only) -> drop it to free head room */
  body.ui-v2 .spv2-search .ssch-eng { display:none !important; }
}

/* classic panel clear row */
.notif-clear-row { display:flex; justify-content:flex-end; padding:6px 10px; border-bottom:1px solid var(--border); }
.notif-clear-row button { font-size:11.5px; font-weight:600; color:var(--text2); background:none; border:none; cursor:pointer; padding:2px 6px; }
.notif-clear-row button:hover { color:var(--text); text-decoration:underline; }

/* --- empty stage ("pick a channel" / "you're in the lobby") — on PAPER --- */
#space-v2 #spv2-empty { flex-direction:column; align-items:center; justify-content:center; gap:12px; color:var(--ink3); text-align:center; padding:24px; }
#space-v2 #spv2-empty .ee-ic { width:56px; height:56px; border-radius:8px; background:var(--card2); border:1px solid var(--line); display:grid; place-items:center; color:var(--ink2); }
#space-v2 #spv2-empty h3 { font-family:var(--disp); font-weight:800; font-size:17px; color:var(--ink); margin:0; }
#space-v2 #spv2-empty p { font-size:13px; color:var(--ink2); margin:0; max-width:340px; line-height:1.5; }

/* The chat (text channels) is a NORMAL warm chat: it inherits the classic chat
   styling + the ui-v2 warm-paper tokens, so we deliberately do NOT skin it dark
   here. It reads as a chat, not the dark call box — the call grid and the chat are
   clearly separate surfaces. (Only the call grid keeps the dark stage.) */
/* make #chat-view the positioning context so its absolute channel-header spans the
   FULL chat width (edge to edge), not whatever ancestor it would otherwise resolve to. */
body.ui-v2 #space-v2 #chat-view { position:relative; }
/* the classic chat caps each message row at max-width:86% (readability column); the
   warm full-width chat fills the area instead, so a sparse channel doesn't read as a
   narrow inset column. Comfortable side gutters via the message-list padding. */
body.ui-v2 #space-v2 .chat-messages .chat-msg { max-width:100%; }
body.ui-v2 #space-v2 .chat-messages { padding-left:18px; padding-right:18px; }
/* Call controls while reading chat (in a call): keep the tray, but pin it to the TOP
   right under the channel header so the message area below stays clear to read. */
body.ui-v2.in-call #space-v2.smode-chat .tray { display:flex; top:60px; bottom:auto; z-index:200;
  /* compose the user's drag offset (--tray-ux/uy, set by the grip) ONLY in chat mode,
     on top of the centering + the owner's design offset; call mode keeps the base transform.
     z-index:200 keeps the draggable bar above all chat/call/float content (still below the
     z:9500 menus so its own popovers work). */
  transform:translateX(-50%) translate(var(--space-tray-x,0px),var(--space-tray-y,0px)) translate(var(--tray-ux,0px),var(--tray-uy,0px)); }
/* while actively dragging: own GPU layer + drop the costly backdrop blur so the move is smooth */
#space-v2 .tray.tray-dragging { will-change:transform; transition:none;
  backdrop-filter:none; -webkit-backdrop-filter:none; background:rgba(var(--st-ink-rgb),.94); }
/* drag grip — only while the bar floats over chat (hidden in call mode + mobile) */
#space-v2 .tray-grip { display:none; width:22px; height:44px; flex:none; align-items:center; justify-content:center;
  color:var(--cream3); cursor:grab; touch-action:none; border-radius:9px; margin-right:1px; }
#space-v2 .tray-grip:hover { color:var(--cream2); background:rgba(255,255,255,.06); }
#space-v2 .tray-grip.grabbing { cursor:grabbing; color:var(--cream); }
body.ui-v2.in-call #space-v2.smode-chat .tray .tray-grip { display:grid; }
/* Extra clearance so the floating tray (top:60px, own height ~60px) doesn't sit
   on top of the first message. .chat-messages' own box already starts BELOW the
   header (top:var(--chat-header-h) on the base rule) — this is purely additional
   in-box padding for the tray, not a 2nd header reservation, so it does NOT
   include --chat-header-h itself (that would double-count it). */
body.ui-v2.in-call #space-v2.smode-chat .chat-messages { padding-top:64px; }

/* the mobile-only bits are hidden on desktop */
#space-v2 .tb-ham { display:none; }
#space-v2 .spv2-seg { display:none; }
#space-v2 .spv2-scrim { display:none; }

/* ============================================================
   ui-v2 Space — MOBILE reflow (from warm3-space-mobile.html + mobile.css).
   Single column: app bar + Call/Chat segment + full-bleed stage + bottom tray.
   The channel rail + members panel become slide-in DRAWERS. Fake status bar /
   home indicator dropped; safe-area insets used instead.
   ============================================================ */
@media (max-width:700px), (pointer:coarse) and (max-width:950px){
  /* ---- app bar ---- */
  /* back-to-home + channels hamburger both show on mobile (back was the gap — no way home) */
  #space-v2 .tb-ham, #space-v2 .tb-back { display:grid; place-items:center; width:38px; height:38px; border-radius:8px; cursor:pointer; flex:none; }
  #space-v2 .tb-pill,
  #space-v2 .tb-btn[title="Notifications"], #space-v2 .tb-btn[title="Settings"] { display:none; }   /* Search stays visible on mobile (its only entry point) */
  /* stage-head Grid/Chat/Pop-out give way to the Call/Chat segment + tray on phones; pop-out is desktop-only */
  #space-v2 .stage-head .sh-btn { display:none; }
  #space-v2 #spv2-float { display:none; }
  #space-v2 .topbar { gap:10px; padding:0 12px; padding-top:env(safe-area-inset-top,0px); height:calc(54px + env(safe-area-inset-top,0px)); }
  #space-v2 .tb-id { flex:1; min-width:0; justify-content:flex-start; gap:9px; }
  #space-v2 .tb-spacer { display:none; }   /* let the title span all the way to near the members button */
  #space-v2 .tb-id .mono { display:grid; width:30px; height:30px; flex:none; }   /* show the server icon */
  #space-v2 .tb-id > div { width:auto; min-width:0; text-align:left; }
  #space-v2 .tb-id .nm { white-space:nowrap; overflow:hidden; text-overflow:ellipsis; font-size:15.5px; }   /* one line, ellipsis — don't grow the bar vertically */
  #space-v2 .tb-id .sub { justify-content:flex-start; white-space:nowrap; overflow:hidden; font-size:11px; margin-top:1px; }
  #space-v2 .rail-head { display:flex; }   /* server name above the channel list in the drawer */
  /* the app bar follows the surface: dark over the call, paper over chat */
  #space-v2.smode-call .topbar { background:var(--stage); border-bottom-color:var(--tline); }
  #space-v2.smode-call .topbar .tb-ham, #space-v2.smode-call .topbar .tb-back, #space-v2.smode-call .topbar .tb-btn { color:var(--cream2); }
  #space-v2.smode-call .tb-id .nm { color:var(--cream); }
  #space-v2.smode-call .tb-id .sub { color:var(--cream3); }

  /* ---- Call/Chat segment (only while in a call) ---- */
  body.ui-v2.in-call #space-v2 .spv2-seg { display:flex; flex:none; margin:6px 12px 2px; border-radius:9px; padding:3px; gap:3px; }
  #space-v2 .spv2-seg button { flex:1; border:none; background:transparent; font-family:var(--f); font-weight:700; font-size:13px; padding:8px; border-radius:9px; cursor:pointer; display:inline-flex; align-items:center; justify-content:center; gap:7px; }
  #space-v2.smode-call .spv2-seg { background:rgba(255,255,255,.06); }
  #space-v2.smode-call .spv2-seg button { color:var(--cream2); }
  #space-v2.smode-call .spv2-seg .seg-call { background:rgba(var(--st-rgb),.16); color:var(--st-hot); }
  #space-v2:not(.smode-call) .spv2-seg { background:var(--s3); margin-top:8px; }
  #space-v2:not(.smode-call) .spv2-seg button { color:var(--ink2); }
  #space-v2:not(.smode-call) .spv2-seg .seg-chat { background:var(--card); color:var(--ink); box-shadow:0 1px 3px rgba(80,50,15,.18); }

  /* ---- rail + members become slide-in drawers ---- */
  #space-v2 .rail, #space-v2 .members {
    position:fixed; top:0; bottom:0; z-index:60; width:min(84vw, 300px);
    transition:transform .25s cubic-bezier(.16,1,.3,1); box-shadow:0 0 60px -8px rgba(40,25,8,.5);
    padding-top:env(safe-area-inset-top,0px); }
  #space-v2 .rail { left:0; transform:translateX(-100%); }
  #space-v2 .members { right:0; transform:translateX(100%); width:min(78vw, 280px); transition:transform .25s cubic-bezier(.16,1,.3,1); }
  #space-v2.spv2-railopen .rail { transform:translateX(0); }
  #space-v2.spv2-membersopen .members { transform:translateX(0); }
  #space-v2.spv2-mhide .members { width:min(78vw, 280px); opacity:1; }   /* desktop collapse is irrelevant on the mobile drawer */
  #space-v2 .spv2-scrim { display:block; position:fixed; inset:0; z-index:55; background:rgba(20,12,4,.5); opacity:0; pointer-events:none; transition:opacity .2s; }
  #space-v2.spv2-scrimon .spv2-scrim { opacity:1; pointer-events:auto; }

  /* ---- stage fills the column (rail/members are out of flow) ---- */
  #space-v2 .stage-body { padding:0 12px 0; }
  body.ui-v2 #space-v2.smode-call .stage-body { padding:0 12px 0; }
  /* call view: spotlight on top, filmstrip a horizontal swipe strip below
     (body.ui-v2 prefix so it beats the desktop body.ui-v2 ...#spv2-call row rule) */
  body.ui-v2 #space-v2 #spv2-call:not(.spv2-grid) { flex-direction:column; gap:10px; }
  #space-v2 .spot { border-radius:8px; min-height:0; }
  /* keep the people button readable on the dark call app bar */
  #space-v2.smode-call .topbar .tb-btn.on { background:rgba(255,255,255,.08); border-color:var(--tline); color:var(--cream); }
  #space-v2 .film { width:auto; flex-direction:row; gap:9px; overflow-x:auto; overflow-y:hidden; padding-bottom:2px; scrollbar-width:none; }
  #space-v2 .film::-webkit-scrollbar { display:none; }
  #space-v2 .film .ftile { width:98px; height:74px; aspect-ratio:auto; flex:none; }
  #space-v2 .film .cam .big { width:40px; height:40px; font-size:16px; }
  #space-v2 #spv2-call.spv2-grid { grid-template-columns:repeat(2,1fr) !important; }
  #space-v2 #spv2-call.spv2-grid[data-n="1"], #space-v2 #spv2-call.spv2-grid[data-n="2"] { grid-template-columns:1fr !important; }   /* 1-2 people stack top/bottom (grid-auto-rows:1fr halves the height) */

  /* ---- tray = bottom bar; only in the call view (use the segment to reach it from chat) ---- */
  body.ui-v2 #space-v2.smode-call .tray { display:flex; left:12px; right:12px; bottom:calc(10px + env(safe-area-inset-bottom,0px)); top:auto; transform:none; gap:6px; padding:9px; border-radius:9px; }
  body.ui-v2.in-call #space-v2.smode-chat .tray { display:none; }   /* mobile chat: no floating tray; tap Call in the segment */
  body.ui-v2.in-call #space-v2.smode-chat .chat-messages { padding-top:8px; }   /* no top tray to clear on mobile — box's own top:var(--chat-header-h) already clears the header itself */
  #space-v2 .tray .tbtn { flex:1; height:48px; width:auto; }
  #space-v2 .tray .tray-act, #space-v2 .tray .tray-div { display:none; }   /* games/youtube/draw/band/cursor -> the More menu on phones */
  #space-v2 .tray .tray-more { display:grid; }                            /* ...and show the More button instead */
  #space-v2 .tleave { flex:none; width:52px; padding:0; gap:0; font-size:0; justify-content:center; }   /* hang-up icon only (font-size:0 hides the "Leave" text, the SVG stays) */
  body.ui-v2 #space-v2.smode-call .stage-body { padding-bottom:78px; }   /* clear the bottom tray */

  /* ---- chat on mobile fills the stage; bottom-safe-area for the input ---- */
  #space-v2 .chat-input-area { padding-bottom:calc(12px + env(safe-area-inset-bottom,0px)); }
}

/* ============================================================
   Wave 5 — in-call Space customization editor (space-edit-v2.js).
   Ported from design-mockups/eaves-ui/space.css (edit mode), with the generic
   class names SCOPED under #spe-bar / #spe-insp so they can't collide with the
   rest of the app. Present only while body.space-editing (owner-only, ui-v2). */
/* shrink the live Space to make room for the editbar (top) + inspector (right) */
body.space-editing #space-v2 { top:56px; right:300px; }
body.space-editing #space-v2 .topbar { display:none; }
body.space-editing #space-v2 * { cursor:default; }
/* preview-as-member: hide the editor chrome + outlines and give back the full stage */
body.space-editing.spe-preview #space-v2 { right:0; }
body.spe-preview #spe-insp { display:none; }
body.spe-preview .spe-sel { outline:none; box-shadow:none; }
body.spe-preview .spe-hint { outline:none; }
body.spe-preview #spe-tag, body.spe-preview #spe-wresize { display:none; }

/* dark edit bar (replaces the Space top bar) */
#spe-bar { position:fixed; top:0; left:0; right:0; height:56px; z-index:36; display:flex; align-items:center; gap:12px; padding:0 16px;
  background:var(--st-editor); color:var(--cream); font-family:var(--f); }
#spe-bar .eb-x { width:34px; height:34px; border-radius:9px; display:grid; place-items:center; flex:none; cursor:pointer;
  border:1px solid rgba(var(--st-rgb),.2); background:rgba(255,255,255,.04); color:var(--cream2); }
#spe-bar .eb-x:hover { color:var(--cream); background:rgba(255,255,255,.08); }
#spe-bar .eb-t { font-family:var(--disp); font-weight:800; font-size:15px; display:flex; align-items:center; gap:9px; }
#spe-bar .eb-t .dot { width:8px; height:8px; border-radius:50%; background:var(--honey); }
#spe-bar .eb-t small { font-weight:600; font-size:12px; color:var(--cream3); margin-left:2px; }
#spe-bar .eb-sp { flex:1; }
#spe-bar .eb-pill { height:36px; padding:0 13px; border-radius:10px; border:1px solid rgba(var(--st-rgb),.2); background:rgba(255,255,255,.04);
  color:var(--cream2); font-family:var(--f); font-weight:700; font-size:13px; cursor:pointer; display:inline-flex; align-items:center; gap:7px; }
#spe-bar .eb-pill:hover { color:var(--cream); background:rgba(255,255,255,.08); }
#spe-bar .eb-pill.on { background:var(--honey); color:#3a2410; border-color:transparent; }
#spe-bar .eb-pill.on:hover { background:var(--honey); filter:brightness(1.05); color:#3a2410; }
#spe-bar .eb-save { height:36px; padding:0 18px; border-radius:10px; border:none; background:var(--honey); color:#3a2410;
  font-family:var(--f); font-weight:800; font-size:13.5px; cursor:pointer; }
#spe-bar .eb-save:hover { filter:brightness(1.06); }
#spe-bar .eb-save[disabled] { opacity:.5; cursor:default; filter:none; }

/* on-canvas selection + hover hints — GLOBAL (so they also reach the floating
   activity panels: YouTube #yt-panel, Band .band-mpanel). No position:relative
   override, so already-positioned panels aren't disturbed; the tag is a separate
   fixed element placed at the picked element's corner. */
body.space-editing .spe-sel { outline:2px solid var(--honey); outline-offset:-2px; box-shadow:inset 0 0 0 4px rgba(var(--st-act-rgb),.16); }
body.space-editing .spe-hint { outline:1.5px dashed rgba(var(--st-act-rgb),.4); outline-offset:-3px; }
#spe-tag { position:fixed; z-index:35; background:var(--honey); color:#3a2410; font-size:11px; font-weight:800; font-family:var(--f);
  padding:5px 10px; border-radius:9px; display:flex; align-items:center; gap:7px; box-shadow:0 6px 14px -5px rgba(80,50,15,.55); pointer-events:none; }
#spe-wresize { position:fixed; z-index:35; width:9px; height:54px; border-radius:99px; background:var(--honey); box-shadow:0 0 0 3px rgba(var(--st-act-rgb),.22); cursor:ew-resize; touch-action:none; }

/* ---- Wave 5 stage 4b: Desktop|Phone axis toggle (a separate phone look) ---- */
/* desktop editbar segment (dark bar) */
#spe-bar .spe-axis { display:flex; gap:2px; flex:none; background:rgba(255,255,255,.05); border:1px solid rgba(var(--st-rgb),.2); border-radius:10px; padding:3px; }
#spe-bar .spe-axis button { height:30px; padding:0 13px; border:none; background:transparent; color:var(--cream2); font-family:var(--f); font-weight:700; font-size:12.5px; border-radius:8px; cursor:pointer; }
#spe-bar .spe-axis button:hover { color:var(--cream); }
#spe-bar .spe-axis button.on { background:var(--honey); color:#3a2410; }
/* phone axis = a distinct (cool) selection colour so it's obvious you're editing the phone look */
body.spe-axis-mobile.space-editing .spe-sel { outline-color:#5b9bd5; box-shadow:inset 0 0 0 4px rgba(91,155,213,.16); }
body.spe-axis-mobile.space-editing #spe-tag { background:#5b9bd5; color:#fff; }
/* inheritance banner inside the inspector */
#spe-insp .spe-axis-note { flex:none; font-size:11.5px; color:#2f567a; background:#e7f0f8; padding:8px 15px; display:flex; align-items:center; gap:8px; border-bottom:1px solid #cfe0ef; }
#spe-insp .spe-axis-note svg { color:#5b9bd5; flex:none; }
#spe-insp .insp-tip.mini { border-bottom:none; padding:8px 12px; border-radius:9px; margin-top:8px; font-size:11px; }

/* ---- Wave 5 stage 4b: phone-frame preview (DESKTOP screens only) ----
   When editing the Phone axis on a desktop screen, show the LIVE Space (your real
   session + call) inside a phone-shaped device frame at true phone width. The real
   mobile @media is window-width-driven so it can't fire for a panel in a desktop
   window; instead we make #space-v2 a CSS CONTAINER in the frame and add a
   frame-scoped @container COPY of the real mobile rules below. The @media block
   (real phones) is left 100% untouched, so phones cannot regress. The @container
   copy must stay in sync with the @media block at ~L7054. */
body.spe-phone-preview::before { content:""; position:fixed; top:56px; left:0; right:300px; bottom:0; z-index:32;
  background:radial-gradient(120% 120% at 50% 0, #2a2014, #140f08); }
/* the device frame (2 body classes so it beats the member-preview right:0 rule). The
   container-name makes the @container rules below resolve ONLY here. */
body.spe-phone-preview.space-editing #space-v2 {
  top:calc(56px + (100vh - 56px)/2); left:calc((100vw - 300px)/2); transform:translate(-50%,-50%);
  right:auto; bottom:auto; width:390px; height:min(844px, calc(100vh - 120px)); z-index:33;
  container:spv2frame / inline-size;
  border:13px solid #14100b; border-radius:40px; overflow:hidden;
  box-shadow:0 40px 90px -25px rgba(0,0,0,.75), 0 0 0 2px #000, inset 0 0 0 2px rgba(255,255,255,.05); }
/* home indicator */
body.spe-phone-preview #space-v2::after { content:""; position:absolute; bottom:7px; left:50%; transform:translateX(-50%);
  width:120px; height:5px; border-radius:99px; background:rgba(255,255,255,.45); z-index:9; pointer-events:none; }
/* the app bar is hidden while editing on desktop — show it in the frame (real phones show it) */
body.spe-phone-preview #space-v2 .topbar { display:flex; }

/* === @container COPY of the real mobile reflow (sync with the @media block ~L7054). === */
/* Only resolves inside the phone frame (the only place #space-v2 is named spv2frame). */
@container spv2frame (max-width:700px){
  #space-v2 .tb-ham, #space-v2 .tb-back { display:grid; place-items:center; width:38px; height:38px; border-radius:8px; cursor:pointer; flex:none; }
  #space-v2 .tb-pill,
  #space-v2 .tb-btn[title="Notifications"], #space-v2 .tb-btn[title="Settings"] { display:none; }   /* Search stays visible on mobile (its only entry point) */
  #space-v2 .stage-head .sh-btn { display:none; }
  #space-v2 #spv2-float { display:none; }
  #space-v2 .topbar { gap:10px; padding:0 12px; padding-top:env(safe-area-inset-top,0px); height:calc(54px + env(safe-area-inset-top,0px)); }
  #space-v2 .tb-id { flex:1; min-width:0; justify-content:flex-start; gap:9px; }
  #space-v2 .tb-spacer { display:none; }   /* let the title span all the way to near the members button */
  #space-v2 .tb-id .mono { display:grid; width:30px; height:30px; flex:none; }   /* show the server icon */
  #space-v2 .tb-id > div { width:auto; min-width:0; text-align:left; }
  #space-v2 .tb-id .nm { white-space:nowrap; overflow:hidden; text-overflow:ellipsis; font-size:15.5px; }   /* one line, ellipsis — don't grow the bar vertically */
  #space-v2 .tb-id .sub { justify-content:flex-start; white-space:nowrap; overflow:hidden; font-size:11px; margin-top:1px; }
  #space-v2 .rail-head { display:flex; }   /* server name above the channel list in the drawer */
  #space-v2.smode-call .topbar { background:var(--stage); border-bottom-color:var(--tline); }
  #space-v2.smode-call .topbar .tb-ham, #space-v2.smode-call .topbar .tb-back, #space-v2.smode-call .topbar .tb-btn { color:var(--cream2); }
  #space-v2.smode-call .tb-id .nm { color:var(--cream); }
  #space-v2.smode-call .tb-id .sub { color:var(--cream3); }
  body.ui-v2.in-call #space-v2 .spv2-seg { display:flex; flex:none; margin:6px 12px 2px; border-radius:9px; padding:3px; gap:3px; }
  #space-v2 .spv2-seg button { flex:1; border:none; background:transparent; font-family:var(--f); font-weight:700; font-size:13px; padding:8px; border-radius:9px; cursor:pointer; display:inline-flex; align-items:center; justify-content:center; gap:7px; }
  #space-v2.smode-call .spv2-seg { background:rgba(255,255,255,.06); }
  #space-v2.smode-call .spv2-seg button { color:var(--cream2); }
  #space-v2.smode-call .spv2-seg .seg-call { background:rgba(var(--st-rgb),.16); color:var(--st-hot); }
  #space-v2:not(.smode-call) .spv2-seg { background:var(--s3); margin-top:8px; }
  #space-v2:not(.smode-call) .spv2-seg button { color:var(--ink2); }
  #space-v2:not(.smode-call) .spv2-seg .seg-chat { background:var(--card); color:var(--ink); box-shadow:0 1px 3px rgba(80,50,15,.18); }
  #space-v2 .rail, #space-v2 .members {
    position:fixed; top:0; bottom:0; z-index:60; width:min(84cqw, 300px);
    transition:transform .25s cubic-bezier(.16,1,.3,1); box-shadow:0 0 60px -8px rgba(40,25,8,.5);
    padding-top:env(safe-area-inset-top,0px); }
  #space-v2 .rail { left:0; transform:translateX(-100%); }
  #space-v2 .members { right:0; transform:translateX(100%); width:min(78cqw, 280px); }
  #space-v2.spv2-railopen .rail { transform:translateX(0); }
  #space-v2.spv2-membersopen .members { transform:translateX(0); }
  #space-v2.spv2-mhide .members { width:min(78cqw, 280px); opacity:1; }   /* desktop collapse is irrelevant on the mobile drawer */
  #space-v2 .spv2-scrim { display:block; position:fixed; inset:0; z-index:55; background:rgba(20,12,4,.5); opacity:0; pointer-events:none; transition:opacity .2s; }
  #space-v2.spv2-scrimon .spv2-scrim { opacity:1; pointer-events:auto; }
  #space-v2 .stage-body { padding:0 12px 0; }
  body.ui-v2 #space-v2.smode-call .stage-body { padding:0 12px 0; }
  body.ui-v2 #space-v2 #spv2-call:not(.spv2-grid) { flex-direction:column; gap:10px; }
  #space-v2 .spot { border-radius:8px; min-height:0; }
  #space-v2.smode-call .topbar .tb-btn.on { background:rgba(255,255,255,.08); border-color:var(--tline); color:var(--cream); }
  #space-v2 .film { width:auto; flex-direction:row; gap:9px; overflow-x:auto; overflow-y:hidden; padding-bottom:2px; scrollbar-width:none; }
  #space-v2 .film::-webkit-scrollbar { display:none; }
  #space-v2 .film .ftile { width:98px; height:74px; aspect-ratio:auto; flex:none; }
  #space-v2 .film .cam .big { width:40px; height:40px; font-size:16px; }
  #space-v2 #spv2-call.spv2-grid { grid-template-columns:repeat(2,1fr) !important; }
  #space-v2 #spv2-call.spv2-grid[data-n="1"], #space-v2 #spv2-call.spv2-grid[data-n="2"] { grid-template-columns:1fr !important; }   /* 1-2 people stack top/bottom (grid-auto-rows:1fr halves the height) */
  body.ui-v2 #space-v2.smode-call .tray { display:flex; left:12px; right:12px; bottom:calc(10px + env(safe-area-inset-bottom,0px)); top:auto; transform:none; gap:6px; padding:9px; border-radius:9px; }
  body.ui-v2.in-call #space-v2.smode-chat .tray { display:none; }
  body.ui-v2.in-call #space-v2.smode-chat .chat-messages { padding-top:8px; }   /* no top tray to clear on mobile — box's own top:var(--chat-header-h) already clears the header itself */
  #space-v2 .tray .tbtn { flex:1; height:48px; width:auto; }
  #space-v2 .tray .tray-act, #space-v2 .tray .tray-div { display:none; }
  #space-v2 .tray .tray-more { display:grid; }
  #space-v2 .tleave { flex:none; width:52px; padding:0; gap:0; font-size:0; justify-content:center; }   /* hang-up icon only (font-size:0 hides the "Leave" text, the SVG stays) */
  body.ui-v2 #space-v2.smode-call .stage-body { padding-bottom:78px; }
  #space-v2 .chat-input-area { padding-bottom:calc(12px + env(safe-area-inset-bottom,0px)); }
}
/* the View segment inside the inspector */
#spe-insp .spe-pfview { display:flex; gap:3px; margin:0 0 4px; background:var(--s3,#e3ded3); border-radius:10px; padding:3px; }
#spe-insp .spe-pfview button { flex:1; border:none; background:transparent; font-family:var(--f); font-weight:700; font-size:11.5px; color:var(--ink2); padding:7px 4px; border-radius:8px; cursor:pointer; }
#spe-insp .spe-pfview button.on { background:var(--card); color:var(--ink); box-shadow:0 1px 3px rgba(80,50,15,.18); }

/* inspector */
#spe-insp { position:fixed; top:56px; right:0; bottom:0; width:300px; z-index:36; background:var(--paper); border-left:1px solid var(--div);
  display:flex; flex-direction:column; min-height:0; font-family:var(--f); }
#spe-insp .insp-head { flex:none; padding:14px 15px; border-bottom:1px solid var(--div); display:flex; align-items:center; gap:11px; }
#spe-insp .insp-head .ico { width:40px; height:40px; border-radius:9px; background:var(--card); border:1px solid var(--line); display:grid; place-items:center; color:var(--rust); flex:none; }
#spe-insp .insp-head .nm { font-family:var(--disp); font-weight:800; font-size:15.5px; line-height:1.1; color:var(--ink); }
#spe-insp .insp-head .kd { font-size:11px; color:var(--ink3); font-weight:700; margin-top:3px; }
#spe-insp .insp-head .tgt { margin-left:auto; flex:none; display:inline-flex; align-items:center; gap:5px; border:1px solid var(--line); background:var(--card);
  border-radius:9px; padding:8px 9px; color:var(--ink2); cursor:pointer; }
#spe-insp .insp-head .tgt:hover { border-color:var(--text3,#9a9389); color:var(--ink); }
/* Same hardcoded-light-cream bug as .vc.live / .mebar above — never flipped with dark mode. */
#spe-insp .insp-tip { flex:none; font-size:11.5px; color:var(--ink2); background:var(--card2); padding:8px 15px; display:flex; align-items:center; gap:8px; border-bottom:1px solid var(--line2); }
#spe-insp .insp-tip svg { color:var(--honey); flex:none; }
#spe-insp .insp-scroll { flex:1; overflow-y:auto; min-height:0; scrollbar-width:thin; scrollbar-color:var(--rust) transparent; }
#spe-insp .insp-scroll::-webkit-scrollbar { width:8px; }
#spe-insp .insp-scroll::-webkit-scrollbar-thumb { background:linear-gradient(var(--honey),var(--rust)); border-radius:99px; border:2px solid transparent; background-clip:padding-box; }
#spe-insp .insp-foot { flex:none; padding:11px 15px; border-top:1px solid var(--div); display:flex; gap:9px; }
#spe-insp .isec { padding:14px 15px; border-bottom:1px solid var(--line2); }
#spe-insp .isec-h { display:flex; align-items:center; justify-content:space-between; margin-bottom:12px; }
#spe-insp .isec-h .t { font-size:11.5px; text-transform:uppercase; letter-spacing:.07em; font-weight:800; color:var(--ink2); display:flex; align-items:center; gap:7px; }
#spe-insp .isec-h .rst { font-size:11px; color:var(--ink3); font-weight:700; cursor:pointer; }
#spe-insp .isec-h .rst:hover { color:var(--rust); }
#spe-insp .field { margin-bottom:12px; }
#spe-insp .field:last-child { margin-bottom:0; }
#spe-insp .field > label { display:block; font-size:12px; color:var(--ink2); font-weight:700; margin-bottom:7px; }
#spe-insp .slrow { display:flex; align-items:center; gap:12px; }
#spe-insp .slrow .val { font-size:12px; font-weight:700; color:var(--ink); min-width:42px; text-align:right; font-variant-numeric:tabular-nums; }
#spe-insp .slrow .val.spe-unset, #spe-insp .hex.spe-unset { color:var(--ink3); }
#spe-insp input[type=range].rng { -webkit-appearance:none; appearance:none; flex:1; height:5px; border-radius:99px; background:#e2d2b4; outline:none; }
#spe-insp input[type=range].rng::-webkit-slider-thumb { -webkit-appearance:none; width:17px; height:17px; border-radius:50%; background:var(--honey); border:2.5px solid var(--paper); box-shadow:0 1px 4px rgba(80,50,15,.45); cursor:pointer; }
#spe-insp input[type=range].rng::-moz-range-thumb { width:17px; height:17px; border-radius:50%; background:var(--honey); border:2.5px solid var(--paper); cursor:pointer; }
#spe-insp .crow { display:flex; align-items:center; gap:10px; }
#spe-insp .sw-color { width:32px; height:32px; border-radius:9px; border:1px solid rgba(0,0,0,.12); flex:none; cursor:pointer; }
#spe-insp .hex { flex:1; font-family:var(--f); font-weight:700; font-size:13px; border:1px solid var(--line); background:var(--card); border-radius:9px; padding:8px 11px; color:var(--ink); }
#spe-insp .isel { width:100%; font-family:var(--f); font-weight:700; font-size:13px; border:1px solid var(--line); background:var(--card); border-radius:9px; padding:9px 11px; color:var(--ink); cursor:pointer;
  -webkit-appearance:none; appearance:none; background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%236e6049' stroke-width='2'%3E%3Cpath d='M2 4l4 4 4-4'/%3E%3C/svg%3E"); background-repeat:no-repeat; background-position:right 11px center; }
#spe-insp .imgbtn { width:100%; border:1.5px dashed var(--border,#ddd7cc); border-radius:8px; padding:13px; color:var(--ink2); font-family:var(--f); font-weight:700; font-size:13px;
  background:#faf2e2; cursor:pointer; display:flex; align-items:center; justify-content:center; gap:8px; }
#spe-insp .imgbtn:hover { border-color:var(--honey); color:var(--rust); }
#spe-insp .ifoot-btn { flex:1; border:1px solid var(--line); background:var(--card); color:var(--ink); font-family:var(--f); font-weight:700; font-size:13px; padding:10px; border-radius:10px; cursor:pointer; }
#spe-insp .ifoot-btn:hover { border-color:var(--text3,#9a9389); }
#spe-insp .ifoot-btn.warn { color:var(--clay); }
/* Arrange-section controls (segmented dock, offset numbers, visible toggle) */
#spe-insp .seg { display:flex; background:var(--s3,#e3ded3); border-radius:10px; padding:3px; gap:3px; }
#spe-insp .seg button { flex:1; border:none; background:transparent; font-family:var(--f); font-weight:700; font-size:12.5px; color:var(--ink2); padding:7px 4px; border-radius:8px; cursor:pointer; }
#spe-insp .seg button.on { background:var(--card); color:var(--ink); box-shadow:0 1px 3px rgba(80,50,15,.18); }
#spe-insp .numin { width:100%; font-family:var(--f); font-weight:700; font-size:13px; border:1px solid var(--line); background:var(--card); border-radius:9px; padding:8px 11px; color:var(--ink); }
#spe-insp .row2c { display:flex; gap:9px; }
#spe-insp .row2c .field { flex:1; margin-bottom:0; }
#spe-insp .togrow { display:flex; align-items:center; justify-content:space-between; }
#spe-insp .togrow span { font-size:12.5px; font-weight:700; color:var(--ink); }
#spe-insp .sw { width:40px; height:23px; border-radius:99px; background:var(--border,#ddd7cc); position:relative; cursor:pointer; flex:none; }
#spe-insp .sw.on { background:var(--olive); }
#spe-insp .sw::after { content:""; position:absolute; top:2.5px; left:2.5px; width:18px; height:18px; border-radius:50%; background:#fff; transition:left .15s; box-shadow:0 1px 2px rgba(0,0,0,.2); }
#spe-insp .sw.on::after { left:19.5px; }
/* ── Space editor on mobile: the inspector becomes a bottom sheet, the editbar a
   compact scrolling top bar, and the live Space sits between them. (The mock-exact
   me-sheet with Style/Arrange tabs + the Shared/phone override axis is a later stage.) */
@media (max-width:700px), (pointer:coarse) and (max-width:950px) {
  /* MOBILE = a floating draggable toolbar over the FULL-SIZE Space (no inset, no
     top-bar replacing the banner). The ▲ pops the properties panel above it. */
  body.space-editing #space-v2 { top:0; right:0; bottom:0; }
  body.space-editing #space-v2 .topbar { display:flex; }   /* banner stays (unlike desktop) */
  /* floating frosted toolbar */
  #spe-bar.spe-float { position:fixed; left:50%; bottom:max(20px,env(safe-area-inset-bottom,0px)); transform:translateX(-50%); top:auto; right:auto; width:auto; height:auto;
    display:flex; align-items:center; gap:5px; padding:6px 7px; border-radius:8px; font-family:var(--f);
    background:rgba(250,247,242,.8); -webkit-backdrop-filter:blur(14px) saturate(1.4); backdrop-filter:blur(14px) saturate(1.4);
    border:1px solid rgba(120,94,54,.16); box-shadow:0 12px 34px -10px rgba(0,0,0,.34); color:var(--ink); z-index:42; }
  #spe-bar.spe-float.dragging { transform:none; transition:none; }
  #spe-bar.spe-float .fb-grip { width:24px; height:40px; display:grid; place-items:center; color:var(--ink3); cursor:grab; touch-action:none; }
  #spe-bar.spe-float .fb-arrow { width:40px; height:40px; border-radius:9px; display:grid; place-items:center; border:none; background:rgba(120,94,54,.1); color:var(--ink); cursor:pointer; }
  #spe-bar.spe-float .fb-arrow.has-sel { background:var(--honey); color:#3a2410; }
  #spe-bar.spe-float .fb-arrow svg { transition:transform .18s; }
  body.spe-props-open #spe-bar.spe-float .fb-arrow svg { transform:rotate(180deg); }
  #spe-bar.spe-float .eb-save { height:40px; border-radius:9px; padding:0 16px; font-size:13.5px; }
  #spe-bar.spe-float .eb-x { width:40px; height:40px; border-radius:9px; background:transparent; border:none; color:var(--ink2); cursor:pointer; display:grid; place-items:center; }
  #spe-bar.spe-float .fb-eye { width:40px; height:40px; border-radius:9px; display:grid; place-items:center; border:none; background:rgba(120,94,54,.1); color:var(--ink); cursor:pointer; }
  #spe-bar.spe-float .fb-eye.on { background:var(--honey); color:#3a2410; }
  /* preview-as-member: hide the panel + outlines (the toolbar stays so the eye can toggle back) */
  body.spe-preview #spe-insp { display:none; }
  /* floating properties panel (the warm inspector) above the toolbar */
  #spe-insp { position:fixed; left:9px; right:9px; bottom:84px; top:auto; width:auto; height:auto; max-height:62vh; z-index:41;
    border-radius:9px; border:1px solid var(--div); box-shadow:0 22px 52px -16px rgba(0,0,0,.44); display:none; }
  body.spe-props-open #spe-insp { display:flex; }
  #spe-insp::before { content:""; flex:none; width:42px; height:5px; border-radius:99px; background:var(--border,#ddd7cc); margin:8px auto 0; }
  #spe-insp .insp-head { border-radius:20px 20px 0 0; padding:9px 15px 12px; cursor:grab; touch-action:none; }
  #spe-insp .insp-head .tgt { touch-action:auto; }
  /* bottom grip: drag to resize the panel height */
  #spe-insp .spe-resize { flex:none; height:18px; display:flex; align-items:center; justify-content:center; cursor:ns-resize; touch-action:none; }
  #spe-insp .spe-resize::before { content:""; width:42px; height:5px; border-radius:99px; background:var(--border,#ddd7cc); }
  #spe-insp .insp-head .nm { font-size:16px; }
  /* the panel axis toggle: Desktop | Phone (light segmented control) */
  #spe-insp .insp-mob-axis { padding:10px 14px 0; }
  #spe-insp .spe-axis { display:flex; gap:3px; background:var(--s3,#e3ded3); border-radius:10px; padding:3px; }
  #spe-insp .spe-axis button { flex:1; border:none; background:transparent; font-family:var(--f); font-weight:700; font-size:12.5px; color:var(--ink2); padding:9px 4px; border-radius:8px; cursor:pointer; }
  #spe-insp .spe-axis button.on { background:var(--card); color:var(--ink); box-shadow:0 1px 3px rgba(80,50,15,.18); }
  /* the panel action row: Advanced / Reset all */
  #spe-insp .insp-mob-actions { display:flex; gap:7px; padding:8px 14px 2px; }
  #spe-insp .insp-mob-actions .ima-btn { flex:1; display:inline-flex; align-items:center; justify-content:center; gap:6px;
    border:1px solid var(--line); background:var(--card); color:var(--ink2); border-radius:10px; padding:9px 4px; font-family:var(--f); font-weight:700; font-size:12px; cursor:pointer; }
  #spe-insp .insp-mob-actions .ima-btn.on { background:var(--honey); color:#3a2410; border-color:transparent; }
  /* touch-friendly controls */
  #spe-insp .isec { padding:14px 15px; }
  #spe-insp input[type=range].rng { height:6px; }
  #spe-insp input[type=range].rng::-webkit-slider-thumb { width:22px; height:22px; }
  #spe-insp input[type=range].rng::-moz-range-thumb { width:22px; height:22px; }
  #spe-insp .sw-color { width:38px; height:38px; }
  #spe-insp .hex, #spe-insp .numin, #spe-insp .isel { padding:11px 13px; font-size:14px; }
  #spe-insp .seg button { padding:10px 4px; font-size:13px; }
  #spe-insp .sw { width:46px; height:26px; }
  #spe-insp .sw::after { width:21px; height:21px; }
  #spe-insp .sw.on::after { left:22px; }
  #spe-insp .insp-foot .ifoot-btn { padding:13px; font-size:14px; }
}

/* Blocked-users manager modal (settings → Privacy & Safety). Appended to <body>, so it
   styles its own buttons rather than relying on the screen-scoped .btn-soft. */
.bm-overlay { position:fixed; inset:0; z-index:9600; background:rgba(20,14,6,.5); display:flex; align-items:center; justify-content:center; padding:20px; }
.bm-box { width:100%; max-width:420px; max-height:78vh; display:flex; flex-direction:column; background:var(--card,#fff); color:var(--ink,#222); border:1px solid var(--line,#e5ddcf); border-radius:8px; box-shadow:0 24px 60px -20px rgba(0,0,0,.5); overflow:hidden; font-family:var(--f,inherit); }
.bm-head { display:flex; align-items:center; justify-content:space-between; padding:15px 18px; border-bottom:1px solid var(--line,#e5ddcf); }
.bm-head h3 { font-size:16px; font-weight:800; margin:0; font-family:var(--disp,inherit); }
.bm-x { background:none; border:none; font-size:24px; line-height:1; color:var(--ink3,#998); cursor:pointer; padding:0 4px; }
.bm-list { overflow-y:auto; padding:8px 10px 12px; }
.bm-row { display:flex; align-items:center; gap:11px; padding:8px; border-radius:10px; }
.bm-row:hover { background:var(--paper,rgba(0,0,0,.04)); }
.bm-av { width:34px; height:34px; border-radius:50%; flex:none; display:grid; place-items:center; color:#fff; font-weight:700; font-size:13px; background-color:var(--plum,#9c5e78); background-size:cover; background-position:center; }
.bm-name { flex:1; min-width:0; font-weight:600; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.bm-row button { flex:none; border:1px solid var(--line,#e5ddcf); background:var(--card,#fff); color:var(--ink,#222); font-weight:700; font-size:12.5px; padding:6px 12px; border-radius:9px; cursor:pointer; }
.bm-row button:hover { border-color:var(--rust,#c75f3e); color:var(--rust,#c75f3e); }
.bm-empty { padding:26px 12px; text-align:center; color:var(--ink3,#998); font-size:13.5px; }

/* Change-password modal fields (Account panel; reuses the .bm-overlay/.bm-box shell) */
.pwm-box { max-width:380px; }
.pwm-body { padding:16px 18px 18px; display:flex; flex-direction:column; }
.pwm-body label { font-size:12px; font-weight:700; color:var(--ink2,#555); margin:11px 0 5px; }
.pwm-body label:first-child { margin-top:0; }
.pwm-in { width:100%; box-sizing:border-box; padding:10px 12px; border:1px solid var(--line,#ddd); border-radius:10px; background:var(--paper,#fff); color:var(--ink,#222); font-size:14px; font-family:var(--f,inherit); }
.pwm-in:focus { outline:none; border-color:var(--honey,#c98a2e); }
.pwm-err { color:var(--rust,#c75f3e); font-size:12.5px; min-height:16px; margin:9px 0 2px; }
.pwm-submit { margin-top:6px; border:none; background:var(--honey,#c98a2e); color:#3a2410; font-family:var(--f,inherit); font-weight:800; font-size:14px; padding:11px; border-radius:8px; cursor:pointer; }
.pwm-submit:disabled { opacity:.6; cursor:default; }

/* Two-factor modals (login step-2 + Account setup/disable/regenerate; reuse .bm-overlay/.pwm-*) */
.tfa-sub { font-size:13px; color:var(--ink2,#555); line-height:1.5; margin:0 0 12px; }
.tfa-alt { margin-top:12px; background:none; border:none; color:var(--honey,#c98a2e); font-family:var(--f,inherit); font-weight:700; font-size:12.5px; cursor:pointer; padding:4px; align-self:center; }
.tfa-alt:hover { text-decoration:underline; }
.tfa-qr { display:flex; justify-content:center; margin:6px 0 12px; }
.tfa-qr img, .tfa-qr canvas { border-radius:10px; border:1px solid var(--line,#e5ddcf); background:#fff; padding:8px; }
.tfa-secret { font-size:12.5px; color:var(--ink2,#555); text-align:center; line-height:1.6; margin-bottom:12px; }
.tfa-secret code { display:inline-block; margin-top:3px; font-family:var(--mono,ui-monospace,monospace); font-size:13px; font-weight:700; letter-spacing:1px; color:var(--ink,#222); background:var(--paper,rgba(0,0,0,.05)); padding:3px 8px; border-radius:7px; word-break:break-all; }
.tfa-codes { display:grid; grid-template-columns:1fr 1fr; gap:7px 12px; margin:4px 0 12px; padding:14px; background:var(--paper,rgba(0,0,0,.04)); border:1px solid var(--line,#e5ddcf); border-radius:8px; }
.tfa-codes code { font-family:var(--mono,ui-monospace,monospace); font-size:14px; font-weight:700; letter-spacing:1px; color:var(--ink,#222); text-align:center; }
.tfa-codes-actions { display:flex; gap:8px; margin-bottom:12px; }
.tfa-codes-actions .btn-soft { flex:1; }
.sv2-link { color:var(--honey,#c98a2e); font-weight:700; cursor:pointer; }
.sv2-link:hover { text-decoration:underline; }
/* 2FA method picker (authenticator app vs email codes) */
.tfa-method { display:block; width:100%; text-align:left; margin-top:10px; padding:13px 14px; border:1px solid var(--line,#e5ddcf); border-radius:9px; background:var(--paper,#fff); color:var(--ink,#222); font-family:var(--f,inherit); cursor:pointer; }
.tfa-method:hover { border-color:var(--honey,#c98a2e); background:var(--card,#fff); }
.tfa-method b { display:block; font-size:14px; font-weight:800; }
.tfa-method span { display:block; font-size:12.5px; color:var(--ink2,#555); margin-top:2px; line-height:1.45; }

/* ── User reports: report modal + selectable span picker (report.js) ── */
.rep-overlay{position:fixed;inset:0;z-index:4000;background:rgba(30,24,16,.5);display:flex;align-items:center;justify-content:center;padding:20px}
.rep-modal{background:var(--s1,#fffdf7);color:var(--text,#2a2620);border:1px solid var(--line,#e7ddc9);border-radius:10px;box-shadow:0 18px 50px rgba(40,30,15,.28);width:min(520px,94vw);max-height:86vh;overflow:auto;padding:18px}
.rep-head{font-size:17px;font-weight:700;margin-bottom:4px}
.rep-sub{font-size:12.5px;color:var(--text3,#8a8276);margin-bottom:12px;line-height:1.4}
.rep-field{margin:10px 0}
.rep-field label{display:block;font-size:12px;color:var(--text3,#8a8276);margin-bottom:4px}
.rep-field .sin,.rep-field .stext{width:100%;box-sizing:border-box}
.rep-msglist{max-height:34vh;overflow:auto;border:1px solid var(--line,#e7ddc9);border-radius:10px;padding:4px;background:var(--s2,#faf6ec)}
.rep-msg{display:flex;gap:7px;padding:5px 8px;border-radius:7px;cursor:pointer;font-size:13px;line-height:1.35;border-left:2px solid transparent}
.rep-msg:hover{background:rgba(80,76,68,.06)}
.rep-msg.sel{background:rgba(110,104,92,.16)}
.rep-msg.anchor{border-left-color:var(--accent,#c8923b)}
.rep-msg-a{font-weight:600;flex:none;max-width:30%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rep-msg-t{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--text2,#5b5347)}
.rep-counter{font-size:11.5px;color:var(--text3,#8a8276);margin:8px 0 2px}
.rep-actions{display:flex;justify-content:flex-end;gap:8px;margin-top:14px}
/* moderation review: tabs + user-report cards */
.mod-tabs{display:flex;gap:6px;margin:6px 0 12px}
.mod-tab{background:none;border:1px solid var(--line,#e7ddc9);color:var(--text3,#8a8276);padding:6px 14px;border-radius:999px;cursor:pointer;font-size:13px}
.mod-tab.active{background:var(--accent,#c8923b);border-color:var(--accent,#c8923b);color:var(--accent-fg,#fff)}
.rep-note{font-style:italic;color:var(--text2,#5b5347);font-size:13px;margin:6px 0;padding-left:10px;border-left:3px solid var(--line,#e7ddc9)}
.rep-transcript{margin:8px 0;border:1px solid var(--line,#e7ddc9);border-radius:8px;background:var(--s2,#faf6ec);max-height:240px;overflow:auto}
.rep-tx-row{padding:4px 10px;font-size:13px;line-height:1.4;border-bottom:1px solid rgba(150,120,60,.08)}
.rep-tx-row:last-child{border-bottom:none}
.rep-tx-a{font-weight:600;margin-right:5px}
.rep-chk{display:flex;gap:8px;align-items:flex-start;font-size:13px;color:var(--text,#2a2620);margin:8px 0;cursor:pointer;line-height:1.4}
.rep-chk input{margin-top:2px;flex:none}

/* Settings -> Feedback (suggestions + bug reports) */
.fb-anon{display:flex;align-items:center;gap:7px;font-size:13px;color:var(--text2,#6e6049);margin:8px 0 10px;cursor:pointer}
.fb-anon input{flex:none}
.fb-send{margin-top:2px}
.fb-mine{margin-top:8px}
.fb-mine-h{font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:.5px;color:var(--text3,#a5947a);margin:6px 0 8px}
.fb-item{border:1px solid var(--border,#e7d8bd);border-radius:10px;padding:10px 12px;margin-bottom:8px;background:var(--surface,#fdf6e7)}
.fb-item-top{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:4px}
.fb-type{font-size:12px;font-weight:600;color:var(--text2,#6e6049)}
.fb-body{font-size:13px;line-height:1.45;color:var(--text,#2c2014);white-space:pre-wrap;word-break:break-word}
.fb-resp{margin-top:7px;padding:7px 10px;border-left:3px solid var(--accent,#bd6a39);background:rgba(189,106,57,.07);border-radius:0 8px 8px 0;font-size:13px;line-height:1.45;color:var(--text2,#6e6049)}
.fb-badge{font-size:11px;font-weight:600;padding:2px 9px;border-radius:999px;white-space:nowrap}
.fb-open{color:var(--text2,#6e6049);background:rgba(150,120,60,.12)}
.fb-reviewed{color:#3f6f8c;background:rgba(63,111,140,.14)}
.fb-resolved{color:#3b7a4a;background:rgba(59,122,74,.16)}

/* Settings -> What's new (changelog) */
.cl-list{margin-top:4px}
.cl-item{padding:12px 0;border-bottom:1px solid var(--line2,#f0e6d1)}
.cl-item:last-child{border-bottom:none}
.cl-top{display:flex;align-items:center;gap:8px;margin-bottom:5px;flex-wrap:wrap}
.cl-title{font-weight:700;font-size:14.5px;color:var(--text,#2c2014)}
.cl-date{font-size:11.5px;color:var(--text3,#a5947a);margin-left:auto}
.cl-body{font-size:13px;line-height:1.5;color:var(--text2,#6e6049);white-space:pre-wrap;word-break:break-word}
.cl-tag{font-size:10.5px;font-weight:700;letter-spacing:.3px;text-transform:uppercase;padding:2px 8px;border-radius:999px}
.cl-new{color:#3b7a4a;background:rgba(59,122,74,.15)}
.cl-improved{color:#3f6f8c;background:rgba(63,111,140,.14)}
.cl-fixed{color:var(--rust,#bd6a39);background:rgba(189,106,57,.13)}
/* admin changelog composer */
.clc-form{display:flex;flex-direction:column;gap:8px;margin:0 0 16px;padding:12px;border:1px solid var(--border,#e7d8bd);border-radius:10px;background:var(--surface,#fdf6e7)}
.clc-form input,.clc-form textarea,.clc-form select{font:inherit;padding:7px 9px;border:1px solid var(--border,#e7d8bd);border-radius:7px;background:var(--bg,#f2e4cb);color:var(--text,#2c2014)}
.clc-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}

/* ═══════════ STUDIO (mini DAW) ═══════════
   Classic dark DAW look on purpose (user decision 2026-07-03): neutral dark
   grays, flat panels, colored clips. Deliberately NOT the warm Eaves palette.
   Everything scoped under .daw- / .band-mode- / tile hook classes. */

/* Band setup: mode pick step */
.band-mode-cards{ display:flex; gap:12px; margin-top:14px; }
.band-mode-card{
  flex:1; display:flex; flex-direction:column; align-items:center; gap:6px;
  padding:18px 12px; border-radius:10px; cursor:pointer;
  /* Theme-neutral tint: the band modal is light in ui-v2 and dark in classic,
     so the cards shade whatever surface they sit on instead of hardcoding one. */
  background:rgba(128,118,100,.10); border:1px solid rgba(128,118,100,.42);
  color:inherit; transition:border-color .12s, transform .12s;
}
.band-mode-card:hover{ border-color:#e0a458; transform:translateY(-1px); }
.band-mode-ico{ display:inline-flex; }
.band-mode-ico svg{ width:32px; height:32px; }
.band-mode-name{ font-weight:700; font-size:15px; }
.band-mode-desc{ font-size:11.5px; opacity:.65; text-align:center; }

/* Tile plumbing */
.call-tile-is-studio{ background:#141517; }
.call-tile-is-studio .call-tile-overlay{ pointer-events:none; }
.call-tile-is-studio .call-tile-controls{ pointer-events:auto; }
.spv-studio-tile{ background:#141517; }
.spv-studio-tile .daw-root{ position:absolute; inset:0; }

/* Root layout */
.daw-root{
  position:absolute; inset:0; display:flex; flex-direction:column;
  background:#141517; color:#c9cacd; font-size:12px; overflow:hidden;
  font-family:system-ui, sans-serif; border-radius:inherit;
  --daw-accent:#e0a458; --daw-line:#2c2d31; --daw-panel:#1b1c1f;
}
.call-tile .daw-root{ position:absolute; inset:0; }
.daw-root canvas{ display:block; }
.daw-root button{ font-family:inherit; }

/* Transport bar */
.daw-top{
  display:flex; align-items:center; gap:8px; padding:4px 8px; flex:0 0 auto;
  background:#101113; border-bottom:1px solid var(--daw-line); min-height:34px;
  flex-wrap:wrap;
}
.daw-title{
  font-weight:700; font-size:12.5px; color:#e4e5e7; cursor:pointer;
  max-width:180px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.daw-title:hover{ color:var(--daw-accent); }
.daw-dirty{ color:var(--daw-accent); font-weight:700; }
.daw-transport{ display:flex; align-items:center; gap:4px; margin:0 auto; }
.daw-tbtn{
  background:#1e1f23; border:1px solid var(--daw-line); color:#c9cacd;
  border-radius:4px; min-width:26px; height:24px; cursor:pointer; font-size:11px;
  display:inline-flex; align-items:center; justify-content:center; padding:0 5px;
}
.daw-tbtn:hover{ border-color:#4a4b50; }
.daw-tbtn.on{ background:var(--daw-accent); color:#141517; border-color:var(--daw-accent); }
.daw-play{ font-size:12px; }
.daw-rec{ color:#d9534f; }
.daw-rec.on{ background:#d9534f; color:#fff; border-color:#d9534f; animation:daw-rec-pulse 1.2s ease-in-out infinite; }
@keyframes daw-rec-pulse{ 0%,100%{ opacity:1; } 50%{ opacity:.55; } }
.daw-sync-btn.off{ background:#3a2c2c; border-color:#5a3c3c; color:#d9a0a0; }
.daw-pos{
  font-family:ui-monospace, monospace; font-size:12px; color:#e4e5e7;
  background:#0c0d0f; border:1px solid var(--daw-line); border-radius:4px;
  padding:2px 8px; min-width:44px; text-align:center;
}
.daw-tempo-wrap{ display:inline-flex; align-items:center; gap:2px; font-size:11px; color:#9a9b9e; }
.daw-tempo{
  width:44px; background:#0c0d0f; border:1px solid var(--daw-line); color:#e4e5e7;
  border-radius:4px; padding:2px 4px; font-family:ui-monospace, monospace; font-size:11px;
}
.daw-topright{ display:flex; gap:6px; align-items:center; }

/* Buttons */
.daw-btn{
  background:#1e1f23; border:1px solid var(--daw-line); color:#c9cacd;
  border-radius:4px; padding:3px 10px; cursor:pointer; font-size:11.5px;
}
.daw-btn:hover{ border-color:#4a4b50; }
.daw-btn-accent{ background:var(--daw-accent); color:#141517; border-color:var(--daw-accent); font-weight:600; }
.daw-btn-accent:hover{ filter:brightness(1.08); }
.daw-btn-ghost{ background:transparent; }
.daw-save-btn.saving{ opacity:.5; pointer-events:none; }

/* Main area */
.daw-main{ display:flex; flex:1 1 55%; min-height:0; border-bottom:1px solid var(--daw-line); }
.daw-tracks{
  flex:0 0 190px; overflow-y:auto; background:var(--daw-panel);
  border-right:1px solid var(--daw-line); padding-top:22px;
  scrollbar-width:thin; scrollbar-color:#3a3b3e transparent;
}
/* Same reasoning as .daw-tl-wrap right next to it: real drag/mute/solo/arm
   controls, never should grab the window. */
body.has-win-chrome .daw-tracks{ -webkit-app-region:no-drag; }
.daw-tracks::-webkit-scrollbar{ width:8px; }
.daw-tracks::-webkit-scrollbar-track{ background:transparent; }
.daw-tracks::-webkit-scrollbar-thumb{ background:#3a3b3e; border-radius:99px; border:2px solid transparent; background-clip:padding-box; }
.daw-tracks::-webkit-scrollbar-thumb:hover{ background:#4a4b4f; background-clip:padding-box; }
.daw-trk{
  display:flex; align-items:center; gap:4px; flex-wrap:wrap;
  height:44px; padding:2px 4px; border-bottom:1px solid #232428;
  cursor:pointer; position:relative; overflow:hidden;
}
.daw-trk.sel{ background:#232427; }
.daw-trk-sub{
  display:flex; align-items:center; padding:0 8px; box-sizing:border-box;
  font-size:9.5px; color:#9a9b9e; background:#101113;
  border-bottom:1px solid #232428; overflow:hidden; white-space:nowrap;
}
.daw-auto-row{ display:flex; align-items:center; }
.daw-auto-row .daw-menu-item{ flex:1; }
.daw-auto-row.on .daw-menu-item{ color:#e4e5e7; }
.daw-auto-trash{
  background:transparent; border:none; color:#9a9b9e; cursor:pointer;
  padding:4px 8px; flex:0 0 auto;
}
.daw-auto-trash svg{ width:13px; height:13px; display:block; }
.daw-auto-trash:hover{ color:#d9534f; }
.daw-trk-color{ width:3px; align-self:stretch; border-radius:2px; flex:0 0 auto; }
.daw-trk-icon{ font-size:13px; flex:0 0 auto; cursor:pointer; }
.daw-trk-name{
  flex:1 1 auto; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
  font-size:11.5px; color:#e4e5e7;
}
.daw-trk-btns{ display:flex; gap:2px; flex:0 0 auto; }
.daw-trk-b{
  background:#141517; border:1px solid var(--daw-line); color:#9a9b9e;
  border-radius:3px; font-size:9px; width:18px; height:16px; cursor:pointer; padding:0;
  display:inline-flex; align-items:center; justify-content:center;
}
.daw-trk-b.on{ background:var(--daw-accent); color:#141517; border-color:var(--daw-accent); }
.daw-trk-arm.on{ background:#d9534f; border-color:#d9534f; color:#fff; }
.daw-trk-vol{
  width:100%; height:10px; margin:0; accent-color:var(--daw-accent);
  flex:1 0 100%;
}
.daw-trk-add{ display:flex; gap:6px; padding:8px 6px; }
.daw-trk-add .daw-btn{ flex:1; font-size:10.5px; padding:4px 4px; }

.daw-tl-wrap{ flex:1; position:relative; min-width:0; overflow:hidden; }
/* Explicit no-drag, not just "not a bar": the canvas has its own drag
   gestures (seek, clip move, loop-region, pan) and had NO app-region
   declared at all, so nothing ever subtracted it back out of whatever a
   surrounding bar declares - only an EXPLICIT no-drag does that, an
   unmarked element does not. Harmless outside Electron/fullscreen (no
   ancestor ever declares drag there to begin with). */
body.has-win-chrome .daw-tl-wrap{ -webkit-app-region:no-drag; }
.daw-tl{ position:absolute; inset:0; cursor:default; }

/* Bottom: tabs + roll/keys */
.daw-bottom{ flex:1 1 45%; min-height:0; display:flex; flex-direction:column; }
.daw-tabs{
  display:flex; align-items:center; gap:4px; padding:2px 8px; flex:0 0 24px;
  background:#101113; border-bottom:1px solid var(--daw-line);
}
.daw-tab{
  background:transparent; border:none; color:#9a9b9e; font-size:11px;
  padding:3px 8px; cursor:pointer; border-radius:3px;
}
.daw-tab.on{ background:#232427; color:#e4e5e7; }
.daw-tab-hint{ font-size:10px; color:#6a6b6e; margin-left:8px; flex:1; overflow:hidden; white-space:nowrap; text-overflow:ellipsis; }
.daw-snap-wrap{ font-size:10px; color:#9a9b9e; display:inline-flex; gap:4px; align-items:center; }
.daw-snap{
  background:#0c0d0f; color:#c9cacd; border:1px solid var(--daw-line);
  border-radius:3px; font-size:10px; padding:1px 2px;
}
.daw-roll-wrap{ flex:1; position:relative; min-height:0; overflow:hidden; }
.daw-roll{ position:absolute; inset:0; }
.daw-keys-wrap{ flex:1; min-height:0; overflow:auto; display:none; }
.daw-steps-wrap{ flex:1; min-height:0; overflow:auto; display:none; }
.daw-fx-wrap{ flex:1; min-height:0; overflow:auto; display:none; }
.daw-inst-wrap{ flex:1; min-height:0; overflow:auto; display:none; }

/* FX rack */
.daw-fxrack{ padding:6px 10px 10px; }
.daw-fxrack-head{ display:flex; align-items:center; gap:10px; padding-bottom:6px; }
.daw-fxrack-pan{ display:flex; align-items:center; gap:6px; font-size:11px; color:#c9cacd; flex:none; }
.daw-fxrack-pan input{ width:80px; accent-color:#e0a458; }
.daw-fxrack-trk{ font-size:11px; color:#9a9b9e; margin-right:auto; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.daw-fx-cards{ display:flex; flex-wrap:wrap; gap:8px; align-items:flex-start; }
.daw-fx-card{
  background:#1b1c1f; border:1px solid var(--daw-line); border-radius:5px;
  padding:6px 8px 8px; width:210px; box-sizing:border-box;
}
.daw-fx-card-head{
  display:flex; align-items:center; font-size:11.5px; color:#e4e5e7;
  padding-bottom:4px; gap:4px;
}
.daw-fx-card-btns{ margin-left:auto; display:inline-flex; gap:2px; align-items:center; }
.daw-fx-card .daw-fx-row{ padding:3px 0; }
.daw-adsr-graph{
  display:block; width:100%; height:46px; margin:2px 0 4px;
  background:#161718; border:1px solid var(--daw-line); border-radius:4px;
}
.daw-fx-val{ font-family:ui-monospace, monospace; font-size:9.5px; color:#9a9b9e; min-width:34px; text-align:right; }
.daw-tap-btn, .daw-vel-toggle, .daw-sel-toggle{ font-size:9px; letter-spacing:.5px; text-transform:uppercase; }

/* Step sequencer */
.daw-steps{ display:flex; flex-direction:column; height:100%; padding:4px 8px 8px; box-sizing:border-box; }
.daw-steps-head{ display:flex; align-items:center; gap:8px; padding:2px 0 6px; flex:0 0 auto; }
.daw-steps-trk{ font-size:11px; color:#9a9b9e; margin-right:auto; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; max-width:40%; }
.daw-steps-bar{ font-size:11px; color:#c9cacd; min-width:74px; text-align:center; font-variant-numeric:tabular-nums; }
.daw-steps-follow.on{ background:#233123; color:#9ac07a; border-color:#3a4f3a; }
.daw-steps-grid{ display:grid; gap:3px; flex:1; min-height:0; align-content:stretch; }
.daw-steps-lbl{
  font-size:11px; color:#9a9b9e; align-self:center; padding-right:6px; text-align:right;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.daw-steps-cell{
  border:1px solid var(--daw-line); border-radius:3px; background:#212327; cursor:pointer;
  min-height:22px; padding:0; touch-action:manipulation;
}
.daw-steps-cell.beat{ border-left:2px solid #4a4d54; }
.daw-steps-cell:hover{ background:#2b2d32; }
.daw-steps-cell.on{ background:var(--daw-accent); border-color:#ecc088; }
.daw-steps-cell.on:hover{ background:#e8b06c; }
.daw-steps-cell.ph{ box-shadow:inset 0 0 0 1px #7fb4e0; }
.daw-steps-cell.on.ph{ box-shadow:inset 0 0 0 2px #eef2f6; }
.daw-narrow .daw-steps-lbl{ font-size:10px; }
.daw-narrow .daw-steps-cell{ min-height:16px; }
.daw-narrow .daw-steps-grid{ gap:2px; }

/* On-screen keys */
.daw-kb{ display:flex; flex-direction:column; height:100%; }
.daw-kb-octave-ctl{ display:flex; align-items:center; gap:8px; padding:4px 8px; }
.daw-kb-oct{ font-family:ui-monospace, monospace; font-size:11px; }
.daw-kb-keys{ flex:1; display:flex; padding:0 8px 8px; min-height:70px; }
.daw-kb-white{
  flex:1; background:#dcdcde; border:1px solid #2a2b2e; border-radius:0 0 4px 4px;
  position:relative; cursor:pointer; min-width:14px;
}
/* Scroll keys: "Visible" is a zoom level. The inner strip is a percentage
   of this container's real width (set inline per-render), so whatever
   space the panel actually has, exactly that many octaves fill it edge to
   edge - the rest of the full range sits off to the side and scrolls in,
   instead of every key just shrinking to cram more octaves into the same
   width. */
.daw-kb-keys.scroll-mode{ overflow-x:auto; overflow-y:hidden; align-items:stretch; }
/* Same bar as the rest of the Studio (.daw-tracks / .daw-menu), not hidden. */
.daw-kb-keys.scroll-mode::-webkit-scrollbar{ height:8px; }
.daw-kb-keys.scroll-mode::-webkit-scrollbar-track{ background:transparent; }
.daw-kb-keys.scroll-mode::-webkit-scrollbar-thumb{ background:#3a3b3e; border-radius:99px; border:2px solid transparent; background-clip:padding-box; }
.daw-kb-keys.scroll-mode::-webkit-scrollbar-thumb:hover{ background:#4a4b4f; background-clip:padding-box; }
/* No explicit height here on purpose: percentage heights on a flex item
   nested inside another flex item are fragile (depend on the outer's own
   height being "definite" all the way up the ancestor chain, which a
   flex:1 + min-height combo doesn't reliably give). align-items:stretch on
   the ROW container above is a direct flex mechanism, not a percentage
   calculation, so it reliably fills the real available height instead of
   the inner strip (and every key inside it) collapsing to its own tiny
   content height and leaving a gap below. */
.daw-kb-keys-inner{ display:flex; flex:none; }
.daw-kb-keys-inner .daw-kb-white{ flex:1; min-width:0; }
/* Keys tab settings: Layout/Visible/labels/scroll tucked behind a gear
   button instead of cluttering the bar above the keyboard. */
.daw-kb-settings-wrap{ position:relative; }
.daw-kb-settings-btn svg{ width:14px; height:14px; }
.daw-kb-settings-pop{
  /* Anchored by its LEFT edge: the gear button sits near the start of the
     toolbar, so right:0 (opening leftward) used to shoot the popover back
     over the octave buttons instead of into the empty space to the right. */
  display:none; position:absolute; top:100%; left:0; margin-top:4px;
  flex-direction:column; gap:8px; z-index:20;
  background:#1b1c1f; border:1px solid #2c2d31; border-radius:6px;
  padding:8px 10px; min-width:170px; box-shadow:0 8px 24px rgba(0,0,0,.5);
}
.daw-kb-settings-pop.open{ display:flex; }
.daw-kb-settings-pop .daw-snap-wrap{ justify-content:space-between; }
/* Remote (friend) key highlight: their identity color rides in on --rkey
   (cursor color, or a stable palette pick). Defined BEFORE .down so your own
   press wins when both hold the same key. */
.daw-kb-white.rdown{ background:var(--rkey, #7aa2c9); }
.daw-kb-black.rdown{ background:var(--rkey, #7aa2c9); }
.daw-pad.rdown{ background:var(--rkey, #7aa2c9); color:#141517; }
.daw-kb-white.down{ background:var(--daw-accent); }
.daw-kb-black{
  position:absolute; top:0; right:-27%; width:54%; height:58%;
  background:#232427; border:1px solid #0c0d0f; border-radius:0 0 3px 3px;
  z-index:2; cursor:pointer;
}
.daw-kb-black.down{ background:var(--daw-accent); }
.daw-pads{ display:grid; grid-template-columns:repeat(4, 1fr); gap:8px; padding:12px; height:100%; box-sizing:border-box; }
.daw-pad{
  background:#1e1f23; border:1px solid var(--daw-line); color:#c9cacd; border-radius:6px;
  cursor:pointer; font-size:11px; display:flex; flex-direction:column; gap:4px;
  align-items:center; justify-content:center; user-select:none; touch-action:none;
}
.daw-pad:active{ background:var(--daw-accent); color:#141517; }
.daw-pad.down{ background:var(--daw-accent); color:#141517; }
.daw-pad-key{ font-family:ui-monospace, monospace; font-size:14px; font-weight:700; }

/* Modals + menus (Studio-scoped, dark) */
.daw-modal-overlay{
  /* Above the fs host (4500) and the classic expanded tile (9000), below the
     ss confirm stack (9100) which opens on top of these, and toasts (9999).
     At the old 3000 every Studio dialog opened INVISIBLY under fullscreen. */
  position:fixed; inset:0; z-index:9050; background:rgba(0,0,0,.55);
  display:flex; align-items:center; justify-content:center;
  /* Modals are appended straight to <body> (document.body.appendChild), never
     nested inside .daw-root — so --daw-accent (only defined there) was unresolved
     for any button in here that reads it (.daw-btn-accent), leaving its background
     transparent and just the button's own near-black text visible: the "New song"
     black-on-black button. Re-declare it at this scope too. */
  --daw-accent:#e0a458;
}
.daw-modal{
  background:#1b1c1f; color:#c9cacd; border:1px solid #2c2d31; border-radius:8px;
  padding:18px; width:min(440px, 92vw); max-height:80vh; overflow-y:auto;
  font-size:12.5px;
}
.daw-modal-title{ font-size:15px; font-weight:700; color:#e4e5e7; margin-bottom:4px; }
.daw-modal-sub{ font-size:11.5px; color:#9a9b9e; margin-bottom:10px; }
.daw-modal-row{ display:flex; gap:8px; margin-top:14px; }
.daw-modal-row .daw-btn{ flex:1; padding:7px 10px; }
/* Both #1e1f23 (Import) and transparent (Cancel/ghost) sat too close to the
   modal's own #1b1c1f background to read as buttons. Brighten both, and give
   ghost the same visible box Import already has instead of true transparency. */
.daw-modal .daw-btn{ background:#28292e; border-color:#3d3e44; }
.daw-modal .daw-btn:hover{ border-color:#57585e; }
.daw-modal .daw-btn-ghost{ background:#28292e; }
.daw-input{
  width:100%; box-sizing:border-box; background:#0c0d0f; color:#e4e5e7;
  border:1px solid #2c2d31; border-radius:5px; padding:7px 9px; font-size:12.5px;
}
.daw-radio{ display:block; padding:6px 2px; font-size:12px; cursor:pointer; }
.daw-radio input{ margin-right:7px; accent-color:#e0a458; }
.daw-proj-list{ max-height:280px; overflow-y:auto; margin:6px 0; }
.daw-proj-row{
  padding:8px 10px; border:1px solid #2c2d31; border-radius:6px; margin-bottom:6px;
  cursor:pointer; background:#1e1f23;
}
.daw-proj-row:hover{ border-color:#e0a458; }
.daw-proj-name{ font-weight:600; color:#e4e5e7; font-size:12.5px; }
.daw-proj-lock{ font-weight:400; font-size:10px; color:#d9a0a0; margin-left:6px; }
.daw-proj-meta{ font-size:10.5px; color:#8a8b8e; margin-top:2px; }
.daw-proj-empty{ padding:14px 8px; color:#8a8b8e; font-size:11.5px; text-align:center; }
.daw-share-list{ max-height:220px; overflow-y:auto; }
.daw-menu{
  position:fixed; z-index:9060; background:#1b1c1f; border:1px solid #2c2d31;
  border-radius:6px; padding:4px; min-width:230px; box-shadow:0 8px 24px rgba(0,0,0,.5);
  max-height:340px; overflow-y:auto; scrollbar-width:thin; scrollbar-color:#3a3b3e transparent;
}
.daw-menu::-webkit-scrollbar{ width:8px; }
.daw-menu::-webkit-scrollbar-track{ background:transparent; }
.daw-menu::-webkit-scrollbar-thumb{ background:#3a3b3e; border-radius:99px; border:2px solid transparent; background-clip:padding-box; }
.daw-menu::-webkit-scrollbar-thumb:hover{ background:#4a4b4f; background-clip:padding-box; }
.daw-menu-item{
  display:block; width:100%; text-align:left; background:transparent; border:none;
  color:#c9cacd; font-size:12px; padding:7px 10px; cursor:pointer; border-radius:4px;
}
.daw-menu-item:hover{ background:#26272b; }
.daw-menu-section{
  font-size:9.5px; letter-spacing:.5px; text-transform:uppercase; color:#7a7b7e;
  padding:8px 10px 3px; margin-top:4px; border-top:1px solid var(--daw-line);
}
.daw-menu-section:first-child{ margin-top:0; padding-top:4px; border-top:none; }
.daw-fx-row{ display:flex; align-items:center; gap:8px; padding:6px 10px; font-size:11.5px; color:#c9cacd; }
.daw-fx-row input{ flex:1; min-width:0; accent-color:#e0a458; }
.daw-fx-row select{ flex:1; min-width:0; background:#232427; color:#c9cacd; border:1px solid var(--daw-line); border-radius:5px; padding:3px 6px; font-size:11.5px; }
.daw-preset-search{ width:100%; margin:8px 0 6px; box-sizing:border-box; }
.daw-preset-list{ max-height:300px; overflow:auto; display:flex; flex-direction:column; gap:2px; }
.daw-preset-row{
  display:flex; align-items:center; gap:8px; text-align:left; padding:5px 8px;
  background:#1e1f23; border:1px solid var(--daw-line); border-radius:4px;
  color:#c9cacd; font-size:11.5px; cursor:pointer;
}
.daw-preset-row:hover{ background:#26272c; }
.daw-preset-row.on{ border-color:var(--daw-accent); color:#e4e5e7; }
.daw-preset-num{ font-family:ui-monospace, monospace; font-size:10px; color:#9a9b9e; min-width:36px; }
.daw-preset-name{ flex:1; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.daw-preset-drum{ font-size:9px; color:#d9a441; border:1px solid #5a4a2a; border-radius:3px; padding:0 4px; }
.daw-clip-num{ display:inline-flex; align-items:center; gap:4px; margin-left:auto; }
.daw-clip-num input{
  width:64px; flex:0 0 auto; background:#0c0d0f; color:#e4e5e7;
  border:1px solid var(--daw-line); border-radius:3px; font-size:11px; padding:2px 4px;
}
.daw-inst-grid{ display:grid; grid-template-columns:repeat(3, 1fr); gap:6px; margin:8px 0; }
.daw-inst{
  background:#1e1f23; border:1px solid #2c2d31; color:#c9cacd; border-radius:6px;
  padding:9px 4px; cursor:pointer; font-size:11px; display:flex; flex-direction:column;
  gap:4px; align-items:center;
}
.daw-inst-ico{ display:inline-flex; }
.daw-inst-ico svg{ width:18px; height:18px; }
.daw-inst:hover{ border-color:#e0a458; }
.daw-arm-dot{ width:7px; height:7px; border-radius:50%; background:currentColor; display:inline-block; }
.daw-del-x{ position:relative; width:8px; height:8px; display:inline-block; }
.daw-del-x::before, .daw-del-x::after{
  content:''; position:absolute; left:3.2px; top:0; width:1.6px; height:8px; background:currentColor;
}
.daw-del-x::before{ transform:rotate(45deg); }
.daw-del-x::after{ transform:rotate(-45deg); }
.daw-chev{
  width:7px; height:7px; display:inline-block;
  border-right:1.6px solid currentColor; border-bottom:1.6px solid currentColor;
  transform:rotate(45deg) translate(-1px,-1px);
}
.daw-chev-up{ transform:rotate(-135deg) translate(-1px,-1px); }
.daw-trk-icon svg{ width:13px; height:13px; display:block; }
.daw-custom-list .daw-inst{ flex-direction:row; justify-content:flex-start; width:100%; margin-bottom:4px; }

/* Cramped tiles: hide the editors, keep transport + tracks readable */
.daw-root.daw-mini .daw-bottom{ display:none; }
.daw-root.daw-mini .daw-tracks{ flex-basis:120px; }

/* Studio keys tab: layout controls, key labels, record */
.daw-kb-octave-ctl{ flex-wrap:wrap; }
.daw-kb-rec{
  background:#1e1f23; border:1px solid #d9534f; color:#d9534f;
  border-radius:4px; padding:3px 12px; cursor:pointer; font-size:11.5px; font-weight:600;
}
.daw-kb-rec.on{ background:#d9534f; color:#fff; animation:daw-rec-pulse 1.2s ease-in-out infinite; }
.daw-kb-target{ font-size:10.5px; color:#8a8b8e; }
.daw-kb-lbl{
  position:absolute; bottom:13px; left:50%; transform:translateX(-50%);
  font-family:ui-monospace, monospace; font-size:9px; color:#3a3b40; pointer-events:none;
}
.daw-kb-black .daw-kb-lbl, .daw-kb-lbl-b{ color:#9a9b9e; }
.daw-kb-white{ position:relative; }
/* Same bottom-anchored spot as .daw-kb-lbl, stacked below it when both are on. */
.daw-kb-note{
  position:absolute; bottom:3px; left:50%; transform:translateX(-50%);
  font-family:ui-monospace, monospace; font-size:8.5px; color:#7a7b80; pointer-events:none;
}
.daw-kb-black .daw-kb-note, .daw-kb-note-b{ color:#b6b7ba; }

/* Studio phone layout (.daw-narrow set by the tile's ResizeObserver under
   640px width; a fullscreen phone tile shows the FULL editor, compacted). */
.daw-narrow .daw-top{ gap:4px; padding:3px 5px; }
.daw-narrow .daw-title{ max-width:90px; font-size:11.5px; }
.daw-narrow .daw-peers{ display:none; }
.daw-narrow .daw-transport{ gap:3px; }
.daw-narrow .daw-tbtn{ min-width:30px; height:28px; }
.daw-narrow .daw-pos{ font-size:10.5px; min-width:0; padding:2px 4px; }
.daw-narrow .daw-tempo-wrap{ font-size:10px; }
.daw-narrow .daw-tempo{ width:34px; }
.daw-narrow .daw-btn{ padding:4px 8px; }
.daw-narrow .daw-tracks{ flex:0 0 128px; }
.daw-narrow .daw-trk-name{ font-size:10.5px; }
.daw-narrow .daw-trk-b{ width:20px; height:18px; }
.daw-narrow .daw-tab-hint{ display:none; }
.daw-narrow .daw-tabs .daw-tbtn{ min-width:26px; height:22px; }
.daw-narrow .daw-kb-target{ display:none; }
.daw-narrow .daw-main{ flex:1 1 50%; }
.daw-narrow .daw-bottom{ flex:1 1 50%; }

/* Studio: song delete in the project browser + time signature select */
.daw-proj-row{ position:relative; }
.daw-proj-delbtn{
  position:absolute; top:8px; right:8px; width:22px; height:22px;
  background:transparent; border:1px solid transparent; border-radius:4px;
  color:#8a8b8e; cursor:pointer; display:inline-flex; align-items:center; justify-content:center;
}
.daw-proj-delbtn:hover{ color:#d9534f; border-color:#d9534f; }
.daw-tsig{ height:22px; }

/* Studio true fullscreen overlay: dynamic viewport (100dvh beats the mobile
   URL bar) + notch/gesture-bar safe areas. The root is a FLEX child here, not
   absolute: an absolute inset:0 child would span the padding box and sit
   under the notch, defeating the safe-area padding. */
.daw-fs-host{
  position:fixed; inset:0; z-index:4500; background:#141517;
  height:100vh; height:100dvh; width:100vw; box-sizing:border-box;
  padding-top:env(safe-area-inset-top); padding-bottom:env(safe-area-inset-bottom);
  padding-left:env(safe-area-inset-left); padding-right:env(safe-area-inset-right);
  display:flex;
}
.daw-fs-host .daw-root{ position:relative; inset:auto; flex:1; min-width:0; min-height:0; border-radius:0; }
/* Exit-fullscreen button: only exists while the fs host holds the root
   (Escape works on desktop; phones need something tappable). */
.daw-unfs-btn{ display:none; }
.daw-unfs-btn svg{ width:12px; height:12px; display:block; }
.daw-root.daw-isfs .daw-unfs-btn{ display:inline-flex; align-items:center; justify-content:center; }


/* Voice message recording pill (chat composer). Sits above the input row while
   recording; removed entirely when idle so it never affects normal layout. */
.voice-rec-pill{
  position:absolute; left:8px; bottom:calc(100% + 6px); z-index:5;
  display:flex; align-items:center; gap:8px;
  padding:5px 8px 5px 10px; border-radius:999px;
  background:var(--panel,#2b2b2b); border:1px solid var(--border,#3a3a3a);
  box-shadow:0 4px 14px rgba(0,0,0,.25); font-size:13px;
}
.voice-rec-pill .vrp-dot{
  width:8px; height:8px; border-radius:50%; background:#e5484d;
  animation:vrpPulse 1.1s ease-in-out infinite;
}
.voice-rec-pill .vrp-time{ font-variant-numeric:tabular-nums; opacity:.9; }
.voice-rec-pill .vrp-cancel{
  background:none; border:none; cursor:pointer; padding:0 2px;
  color:inherit; opacity:.6; font-size:13px; line-height:1;
}
.voice-rec-pill .vrp-cancel:hover{ opacity:1; }
#chat-mic-btn.recording{ color:#e5484d; }
@keyframes vrpPulse{ 0%,100%{ opacity:1 } 50%{ opacity:.25 } }
/* App's own toggle (body.reduce-motion), matching how every other effect
   here is gated, plus the OS preference. */
body.reduce-motion .voice-rec-pill .vrp-dot{ animation:none; }
@media (prefers-reduced-motion: reduce){ .voice-rec-pill .vrp-dot{ animation:none } }

/* ── DESKTOP WINDOW CONTROLS (frameless Electron, NO title bar) ──
   The buttons float in the top-right corner and the app keeps the whole
   viewport — no strip, no wrapper, no per-screen offsets. Injected by
   js/window-chrome.js only inside Electron, so the browser build never sees
   any of this. */

/* Invisible drag lane along the very top edge: the window stays movable on
   every screen, including ones with no header, without a visible bar. Thin
   enough not to steal clicks from anything real, and it sits BELOW the buttons
   in z-order so it can span the full width. */
body.has-win-chrome #win-drag-lane{
  position:fixed; top:0; left:0; right:0; height:8px;
  z-index:2147482999;
  -webkit-app-region:drag;
}

body.has-win-chrome #win-chrome{
  position:fixed; top:0; right:0; z-index:2147483000;
  display:flex; align-items:stretch; height:var(--wc-h);
  /* Above modals too (they append to <body>), so the window can always be
     closed even with one open. */
}
/* CRITICAL: buttons must opt OUT of the drag region or they stop responding —
   a drag region swallows clicks. Anything interactive added here needs it. */
body.has-win-chrome #win-chrome .wc-btn{
  -webkit-app-region:no-drag;
  width:42px; border:none; background:none; cursor:default;
  color:var(--text,#e8e3da); opacity:.55;
  display:flex; align-items:center; justify-content:center;
  transition:background .12s ease, opacity .12s ease;
}
body.has-win-chrome #win-chrome .wc-btn:hover{ background:rgba(128,128,128,.18); opacity:1; }
body.has-win-chrome #win-chrome .wc-btn:active{ background:rgba(128,128,128,.28); }
body.has-win-chrome #win-chrome .wc-close:hover{ background:#c4342f; color:#fff; opacity:1; }
body.has-win-chrome #win-chrome .wc-close:active{ background:#a82b27; }

/* Space reserved so nothing lands underneath the buttons. This is a handful of
   BARS that reach the right edge, not a per-screen list — a new screen inherits
   correct behaviour as long as it uses one of these bars. */
/* --wc-inset = width of the whole cluster (3 x 42px), --wc-h = its height. Both
   are read back by the rules below, so the cluster's size and the space reserved
   for it can never drift apart. */
body.has-win-chrome{ --wc-inset:126px; --wc-h:30px; }
/* ⚠️ EVERY selector below must match real markup. A made-up one is a SILENT
   no-op: `.spv2-topbar` was in this list at first and exists nowhere in the
   repo, so the ui-v2 server page shipped with the buttons sitting on its top
   bar. Grep each class in public/js + index.html before adding it here. */
body.has-win-chrome :is(
  #app-header,                    /* classic header */
  .server-page-topbar,            /* classic server page */
  .settings-page-topbar,          /* classic settings screens */
  #space-v2 .topbar,              /* ui-v2 server page */
  #settings-v2-screen .set-top,   /* ui-v2 settings ("Esc to close" is right-aligned) */
  #store-v2 .sv2-top,             /* ui-v2 store */
  #spe-bar,                       /* space editor (Save is right-aligned) */
  .daw-fs-host .daw-top           /* Studio fullscreen: the only bar at y=0 there, same gap as every other one below */
){
  padding-right:var(--wc-inset);
  /* ...and the same bars ARE the drag handle. A 8px lane is all you get on a
     screen with no bar; where there IS one, the whole bar grabs the window,
     which is what a title bar gives you for free. */
  -webkit-app-region:drag;
}

/* Everything interactive inside those bars opts back out, or it silently stops
   responding — a drag region is consumed by the window manager and the click
   never reaches the renderer. Matching by ROLE (button / link / anything with a
   handler attribute) rather than by class, so a control added to one of these
   bars later is covered without anyone remembering this rule exists.
   Deliberately scoped to the bars instead of the whole document: Electron
   recomputes the region and IPCs it on layout changes, and a no-drag rule over
   every button in a chat app would make that list enormous. */
body.has-win-chrome :is(
  #app-header, .server-page-topbar, .settings-page-topbar, #hv-header,
  #space-v2 .topbar, #settings-v2-screen .set-top, #store-v2 .sv2-top, #spe-bar,
  .daw-fs-host .daw-top
) :is(a, button, input, select, textarea, label, summary,
      [onclick], [data-act], [role="button"], [contenteditable], [tabindex]){
  -webkit-app-region:no-drag;
}

/* Overlays that FLOAT OVER those bars have to opt out as a whole, or the bar's
   drag region shows through them. An element with no app-region is not collected
   at all, so it does not subtract — only an explicit no-drag does. Left
   unmarked, pressing #call-dock while it sat over a bar started a native WINDOW
   drag instead of moving the dock: the OS took the gesture, pointercancel fired,
   and the dock stopped following the cursor. That is the "it jumps back when you
   drag it in certain places", and the places were the bars.
   All of these sit after every bar in DOM order, which is what makes the
   subtraction land — Electron composes the region in document order, last wins.
   Anything new that floats above a bar belongs in this list. */
body.has-win-chrome :is(
  #call-dock,               /* draggable itself, so the conflict is total */
  .channel-ctx-menu,        /* both the channel menu and the per-peer volume menu */
  #notif-panel,
  #img-lightbox-controls,
  #spv2-float
){
  -webkit-app-region:no-drag;
}

/* Corner-anchored controls need pushing directly: padding can't reach them.
   A position:fixed element ignores its ancestor's padding outright, and an
   absolutely positioned one resolves `right` against the padding BOX, which
   padding never changes — so both of the classic header's right-hand buttons
   sat underneath the window controls and swallowed their own clicks.
   translateX rather than a new `right` value, so whatever base offset each one
   already has (including the mobile overrides further down) still holds. */
body.has-win-chrome #notif-bell-btn,
body.has-win-chrome #settings-btn{
  transform:translateX(calc(-1 * var(--wc-inset)));
}

/* A stream taken FULL-BLEED is the one case with no bar to reserve space in: it
   hides the top bar and runs to the window edges, so the tile's own controls
   land in the same corner as the window buttons. Push them DOWN past the cluster
   rather than left, so the control stays in the corner people reach for. Scoped
   to the full-bleed state only — a tile in the normal grid sits under a bar and
   has nothing to clear. Both UIs do this, by different mechanisms: ui-v2's are
   absolutely positioned so they need `top`, the classic overlay lays its
   controls out in flow so padding is what moves them. */
body.has-win-chrome #space-v2.spv2-maxed .tile-fs,
body.has-win-chrome #space-v2.spv2-maxed .spv-report-btn,
body.has-win-chrome #space-v2.spv2-maxed .spv-vol-btn{
  top:calc(12px + var(--wc-h));
}
body.has-win-chrome .call-tile.call-tile-expanded .call-tile-overlay{
  padding-top:calc(6px + var(--wc-h));   /* moves the top-right label; the controls are bottom-left and stay put */
}
/* Same situation, other full-bleed overlays. #img-lightbox-controls is
   corner-anchored so it moves down. .daw-fs-host .daw-top used to get its
   OWN one-off padding-right rule here (daw-topright, the child that's flush
   against the right edge) instead of being a real bar in the list above -
   which reserved the inset but never made the bar's own buttons no-drag,
   so the always-on #win-drag-lane silently ate clicks on anything sitting
   in the window's top few pixels. It's a real bar now (see the list above),
   which reserves the SAME space one level up (.daw-top, not .daw-topright -
   doing both would double the reservation) and gets the no-drag treatment
   that actually matters here. */
body.has-win-chrome #img-lightbox-controls{
  top:calc(18px + var(--wc-h) + env(safe-area-inset-top,0px));
}

/* #hv-header is max-width:1100px and centred, so on a wide window the centring
   gutter ALREADY clears the buttons; reserving the full inset there would leave
   its icons floating ~126px short of the header's own divider rule. Taper the
   reservation by whatever gutter the centring provides, down to the base 30px.
   `100%` (the header's containing block) rather than 100vw on purpose: 100vw
   counts the scrollbar but the buttons are pinned to the layout viewport, and
   that half-scrollbar of drift is enough to put an icon back under them.
   (30px and 1100px come from the #hv-header rule in the ui-v2 section above —
   keep them in step.) */
body.has-win-chrome #hv-header{
  padding-right:clamp(30px, calc(var(--wc-inset) - (100% - 1100px) / 2), var(--wc-inset));
  /* Split out of the bar list above only for that taper — it is still a bar, so
     it still grabs the window. Its interactive children are in the no-drag rule
     with everyone else's. */
  -webkit-app-region:drag;
}
