/* sheet.css — bottom sheet, thread switcher, per-message menu, rail filters
   Extracted verbatim from index.html lines 564-691 (the inline <style>).
   Design TOKENS are not here: they live in /assets/shell.css, shared with the
   document pages, exactly as before. */

/* ===================== bottom sheet (replaces modals) ===================== */
.scrim{
  position:fixed;inset:0;background:rgba(0,0,0,.6);backdrop-filter:blur(3px);
  z-index:var(--z-scrim);opacity:0;pointer-events:none;transition:opacity .22s var(--ease);
}
.scrim.open{opacity:1;pointer-events:auto}
.sheet{
  position:fixed;left:50%;bottom:0;transform:translate(-50%,100%);
  width:min(560px,100%);background:var(--bg-1);
  border:1px solid var(--line);border-bottom:0;
  border-radius:var(--r4) var(--r4) 0 0;
  z-index:var(--z-sheet);padding:var(--s3) var(--s5) var(--s6);
  transition:transform .3s var(--ease);box-shadow:var(--shadow-2);
  max-height:82dvh;overflow-y:auto;
}
.sheet.open{transform:translate(-50%,0)}
.grabber{width:38px;height:4px;border-radius:var(--r-pill);background:var(--line);margin:0 auto var(--s5)}
.sheet h2{font-size:var(--t-xl);margin:0 0 var(--s2);font-weight:600;letter-spacing:-.015em}
.sheet p{color:var(--ink-2);margin:0 0 var(--s5);font-size:var(--t-sm)}
.sheet-item{
  width:100%;display:flex;align-items:center;gap:var(--s4);text-align:left;
  padding:var(--s4);border-radius:var(--r2);transition:background .16s var(--ease);
}
.sheet-item:hover{background:var(--bg-2)}
.sheet-item .ico{
  width:36px;height:36px;border-radius:var(--r2);flex:none;display:grid;place-items:center;
  background:var(--bg-3);color:var(--ink-2);
}
.sheet-item .ico svg{width:17px;height:17px;stroke:currentColor;fill:none;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round}
.sheet-item b{display:block;font-weight:500}
.sheet-item small{color:var(--ink-3);font-size:var(--t-sm)}
.sheet-item.danger b{color:var(--bad)}
.sheet-item.danger .ico{color:var(--bad);background:rgba(240,90,124,.1)}

/* preview banner */
/* A small mark, not a strip across the top. v2 is real enough now that a banner shouting
   "preview" was both wrong (the conversation IS live) and in the way. What remains true is that
   sending is not wired yet, and that belongs next to the brand, not over the whole product. */
.preview-pill{
  font-size:10px; letter-spacing:.08em; text-transform:uppercase; font-weight:600;
  padding:2px 6px; border-radius:var(--r1); flex:none;
  background:var(--accent-wash); color:var(--accent-2);
}
.app{padding-top:24px}

/* ---- thread switcher: threads hang off the COMPANION, not the rail.
   Companions are few and stable; threads are many and mostly idle, so they must
   not occupy permanent screen space on either side. */
.thread-switch{
  display:flex;align-items:center;gap:var(--s2);text-align:left;
  padding:var(--s1) var(--s2);border-radius:var(--r2);
  transition:background .16s var(--ease);min-width:0;
}
.thread-switch:hover{background:var(--bg-2)}
.thread-switch .sub b{color:var(--ink-4);font-weight:400;margin:0 2px}
.thread-switch .chev{width:16px;height:16px;stroke:var(--ink-3);fill:none;stroke-width:2;
  stroke-linecap:round;stroke-linejoin:round;flex:none;transition:transform .2s var(--ease)}
.thread-switch[aria-expanded="true"] .chev{transform:rotate(180deg)}

.thread-menu{
  position:absolute;top:calc(100% + 6px);left:var(--s4);
  width:min(340px,calc(100vw - 32px));
  background:var(--bg-1);border:1px solid var(--line);border-radius:var(--r3);
  box-shadow:var(--shadow-2);padding:var(--s2);z-index:var(--z-sheet);
  opacity:0;transform:translateY(-6px);pointer-events:none;
  transition:opacity .16s var(--ease),transform .16s var(--ease);
}
.thread-menu.open{opacity:1;transform:none;pointer-events:auto}
.tm-label{
  font-size:var(--t-xs);letter-spacing:.09em;text-transform:uppercase;
  color:var(--ink-3);padding:var(--s2) var(--s3) var(--s1);font-weight:500;
}
.tm-item{
  width:100%;display:flex;align-items:center;text-align:left;
  padding:var(--s3);border-radius:var(--r2);transition:background .16s var(--ease);
}
.tm-item:hover{background:var(--bg-2)}
.tm-item[aria-current="true"]{background:var(--accent-wash);box-shadow:inset 0 0 0 1px var(--accent-line)}
.tm-item b{display:block;font-weight:500;font-size:var(--t-md)}
.tm-item small{color:var(--ink-3);font-size:var(--t-sm)}
.tm-sep{height:1px;background:var(--line-soft);margin:var(--s2) var(--s3)}
.tm-new b{color:var(--accent-2)}
.tm-danger b{color:var(--bad)}

/* ---- per-message admin menu ----
   Reuses .thread-menu so right-click and long-press produce the same object the rest of the app
   already uses for menus — positioned by script rather than anchored to a control. */
.msg-menu{width:min(300px,calc(100vw - 16px));z-index:var(--z-toast)}
.msg-edit{margin-top:var(--s2);display:flex;flex-direction:column;gap:var(--s2)}
.msg-edit textarea{
  width:100%;padding:var(--s3);border-radius:var(--r2);
  background:var(--bg-2);border:1px solid var(--accent-line);color:var(--ink);
  font:inherit;font-size:var(--t-md);resize:vertical;
}
/* ⚠ A long-press on a phone otherwise selects the text under the finger and pops the OS copy
   bar over our own menu. Only for admins, so ordinary readers keep normal text selection. */
.thread.is-admin .msg[data-id]{-webkit-touch-callout:none}

/* ---- rail group filters ----
   The same dropdown as the thread switcher above, which is why .rail-menu carries .thread-menu
   rather than redeclaring it: one pattern, one set of open/close rules, no chance of the two
   drifting into looking like different controls. Only the anchoring differs — the rail is narrow,
   so the menu spans it instead of taking the switcher's fixed 340px. */
.rail-group{position:relative}
.rail-filter{
  width:100%; display:flex; align-items:center; gap:var(--s2);
  border-radius:var(--r2); transition:background .16s var(--ease);
}
.rail-filter:hover{background:var(--bg-2)}
.rail-filter .chev{
  width:14px; height:14px; stroke:var(--ink-3); fill:none; stroke-width:2;
  stroke-linecap:round; stroke-linejoin:round; flex:none;
  transition:transform .2s var(--ease);
}
.rail-filter[aria-expanded="true"] .chev{transform:rotate(180deg)}
/* Pushed to the right and shown only when a filter is ACTUALLY narrowing the list. A count that is
   always there is noise; a count that appears is a statement that something is being hidden. */
.rl-count{
  margin-left:auto; font-size:var(--t-xs); letter-spacing:0; text-transform:none;
  color:var(--accent-2); font-weight:500;
}
.rail-menu{left:var(--s3); right:var(--s3); width:auto; top:calc(100% + 2px)}
/* The rail lists scroll; the menu must sit above them and above the next group's heading. */
.rail-group:has(.rail-menu.open){z-index:var(--z-sheet)}

/* the drawer toggle only exists on small screens */
.menu-btn{display:none}
