/*
 * switchboard web UI: "A · Native" (issue #19). One stylesheet for index.html and login.html.
 *
 * Layout: a three-column app (sidebar 248 px, conversation, right pane 288 px that slides
 * from Members to the Inspector). Below 1101 px the pane becomes an overlay drawer; at 760 px
 * and narrower the sidebar is a left drawer and the pane is a bottom sheet (section 9).
 *
 * Security and CSP notes:
 * - The page CSP is style-src 'self', plus 'unsafe-inline' on the app page for Mermaid's
 *   drawings alone (diagram.js, DESIGN.md §33; they keep their styles in a shadow root). Everything
 *   visual lives here; the HTML carries no inline styles and the static JS never touches
 *   element.style (the static lint bans it). Widths
 *   that vary (the budget and hops meters) are classes .w0 to .w10, not inline percentages.
 * - This file loads nothing: no imported sheets, no external fonts and no image references of any
 *   kind (the lint checks). Icons are inline SVG paths coloured with currentColor.
 * - Colours come only from the tokens in section 1, redefined for dark mode, so a new
 *   component cannot drift from the approved palette.
 *
 * Sections: 1 tokens · 2 base · 3 buttons and chips · 4 app layout · 5 sidebar ·
 * 6 conversation header and bands · 7 log rows · 8 Markdown (md-*) · 9 composer and popovers ·
 * 10 right pane and members · 11 inspector · 12 sheets and panels · 13 first run ·
 * 14 login · 15 narrow widths · 16 reduced motion.
 */

/* ==== 1. Design tokens (spec 1.11) =================================================== */
:root {
  color-scheme: light dark;

  --bg: #ffffff;
  --fg: #1d1d1f;
  --side-bg: #f4f4f6;
  --side-border: #e2e2e6;
  --pane-bg: #fafafb;
  --pane-border: #e6e6ea;
  --line: #ececef;
  --muted: #6b6b73;
  --muted-2: #55555c;
  --ink-2: #3c3c43;
  --chip-bg: #f2f2f5;
  --meter-track: #dcdce1;
  --row-sel: #ececf0;
  --btn-on: #ececf0;
  --code-bg: #f0f0f3;
  --code-border: #e4e4e9;
  --code-fg: #2b2b30;
  --pre-bg: #f7f7f9;
  --tier-bg: #efeff2;
  --tier-border: #e2e2e7;
  --device-bg: #e9eef5;
  --btn-bg: #ffffff;
  --btn-border: #d6d6dc;
  --input-bg: #ffffff;
  --input-border: #d6d6dc;
  --input-shadow: 0 1px 2px rgba(0, 0, 0, .04);
  --menu-bg: #ffffff;
  --menu-border: #e2e2e6;
  --menu-shadow: 0 10px 28px rgba(0, 0, 0, .12), 0 1px 3px rgba(0, 0, 0, .06);
  --pop-shadow: 0 10px 30px rgba(20, 20, 30, .12), 0 1px 3px rgba(20, 20, 30, .08);
  --head-2-bg: #f7f7f9;
  --accent: #0a64d8;
  --accent-fg: #ffffff;
  --accent-tint: rgba(10, 100, 216, .07);
  --focus: #dbe7fb;
  --link: #0a5fcf;
  --link-hover: #084a9f;
  --mention-fg: #0b57c4;
  --mention-bg: #e7eefb;
  --green: #2e9d4e;
  --forge-gitlab: #e24329;  /* GitLab's own orange, the same in both themes (#247) */
  --busy: #d98a1c;
  --parked: #c26a00;
  --danger: #b3261e;
  --danger-bg: #fdeeed;
  --danger-solid: #b3261e;
  --amber-fg: #7a4a00;
  --amber-bg: #fff4e0;
  --amber-ink: #8a5300;
  --badge-bg: #c4271f;
  --quote-rule: #d0d0d6;
  --reply-icon: #8e8e96;
  --scroll-thumb: #c9c9cf;
  --human-bg: #ece6f7;
  --human-fg: #5a3d99;
  --h-claude-bg: #b9573a;
  --h-claude-fg: #ffffff;
  --h-opencode-bg: #2f6f73;
  --h-opencode-fg: #ffffff;
  /* the agents' icons (#62, #441, DESIGN.md §29.9): the only files this stylesheet loads, each pinned */
  --h-codex-img: url('/static/agents/codex-light.png');
  --h-codex-tile: #ffffff;
  --h-cursor-img: url('/static/agents/cursor-light.png');
  --h-devin-img: url('/static/agents/devin-light.png');
  --h-icon-ring: rgba(0, 0, 0, 0.08);
  --h-other-bg: #ececf0;
  --h-other-fg: #3c3c43;

  --text-scale: 1;
  --font: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI Variable Text", "Segoe UI", system-ui, Cantarell, "Noto Sans", Ubuntu, sans-serif;
  --mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, "Cascadia Mono", Consolas, "Liberation Mono", monospace;
  --ease: cubic-bezier(.2, .8, .2, 1);
}

:root[data-text-size="small"] { --text-scale: .9; }
:root[data-text-size="large"] { --text-scale: 1.15; }
:root[data-text-size="larger"] { --text-scale: 1.3; }

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #1c1c1f;
    --fg: #ececf0;
    --side-bg: #242427;
    --side-border: #333338;
    --pane-bg: #202023;
    --pane-border: #333338;
    --line: #2e2e33;
    --muted: #93939b;
    --muted-2: #a8a8b0;
    --ink-2: #d0d0d6;
    --chip-bg: #2a2a2e;
    --meter-track: #3d3d43;
    --row-sel: #2e2e33;
    --btn-on: #2e2e33;
    --code-bg: #2c2c31;
    --code-border: #3a3a40;
    --code-fg: #e6e6ea;
    --pre-bg: #26262a;
    --tier-bg: #2c2c31;
    --tier-border: #3a3a40;
    --device-bg: #2a3140;
    --btn-bg: #2a2a2e;
    --btn-border: #46464d;
    --input-bg: #242427;
    --input-border: #3a3a40;
    --input-shadow: none;
    --menu-bg: #2a2a2e;
    --menu-border: #3a3a40;
    --menu-shadow: 0 10px 28px rgba(0, 0, 0, .5), 0 0 0 1px rgba(0, 0, 0, .3);
    --pop-shadow: 0 10px 30px rgba(0, 0, 0, .5), 0 1px 3px rgba(0, 0, 0, .5);
    --head-2-bg: #242427;
    --accent: #2f6fd6;
    --accent-fg: #ffffff;
    --accent-tint: rgba(47, 111, 214, .16);
    --focus: rgba(47, 111, 214, .45);
    --link: #82b4ff;
    --link-hover: #a9ccff;
    --mention-fg: #9cc4ff;
    --mention-bg: #233249;
    --green: #34c759;
    --busy: #ff9f0a;
    --parked: #ff9f0a;
    --danger: #ff8f85;
    --danger-bg: #3a2020;
    --danger-solid: #c4271f;
    --amber-fg: #f5c16c;
    --amber-bg: #3a2c16;
    --amber-ink: #f0b454;
    --badge-bg: #c4271f;
    --quote-rule: #46464d;
    --reply-icon: #6e6e76;
    --scroll-thumb: #4a4a50;
    --human-bg: #342a4d;
    --human-fg: #cfbdf7;
    --h-claude-bg: #b9573a;
    --h-claude-fg: #ffffff;
    --h-opencode-bg: #2f6f73;
    --h-opencode-fg: #ffffff;
    --h-codex-img: url('/static/agents/codex-dark.png');
    --h-codex-tile: #000000;
    --h-cursor-img: url('/static/agents/cursor-dark.png');
    --h-devin-img: url('/static/agents/devin-dark.png');
    --h-icon-ring: rgba(255, 255, 255, 0.1);
    --h-other-bg: #2e2e33;
    --h-other-fg: #d0d0d6;
  }
}

:root[data-theme="dark"] {
  --bg: #1c1c1f;
  --fg: #ececf0;
  --side-bg: #242427;
  --side-border: #333338;
  --pane-bg: #202023;
  --pane-border: #333338;
  --line: #2e2e33;
  --muted: #93939b;
  --muted-2: #a8a8b0;
  --ink-2: #d0d0d6;
  --chip-bg: #2a2a2e;
  --meter-track: #3d3d43;
  --row-sel: #2e2e33;
  --btn-on: #2e2e33;
  --code-bg: #2c2c31;
  --code-border: #3a3a40;
  --code-fg: #e6e6ea;
  --pre-bg: #26262a;
  --tier-bg: #2c2c31;
  --tier-border: #3a3a40;
  --device-bg: #2a3140;
  --btn-bg: #2a2a2e;
  --btn-border: #46464d;
  --input-bg: #242427;
  --input-border: #3a3a40;
  --input-shadow: none;
  --menu-bg: #2a2a2e;
  --menu-border: #3a3a40;
  --menu-shadow: 0 10px 28px rgba(0, 0, 0, .5), 0 0 0 1px rgba(0, 0, 0, .3);
  --pop-shadow: 0 10px 30px rgba(0, 0, 0, .5), 0 1px 3px rgba(0, 0, 0, .5);
  --head-2-bg: #242427;
  --accent: #2f6fd6;
  --accent-fg: #ffffff;
  --accent-tint: rgba(47, 111, 214, .16);
  --focus: rgba(47, 111, 214, .45);
  --link: #82b4ff;
  --link-hover: #a9ccff;
  --mention-fg: #9cc4ff;
  --mention-bg: #233249;
  --green: #34c759;
  --busy: #ff9f0a;
  --parked: #ff9f0a;
  --danger: #ff8f85;
  --danger-bg: #3a2020;
  --danger-solid: #c4271f;
  --amber-fg: #f5c16c;
  --amber-bg: #3a2c16;
  --amber-ink: #f0b454;
  --badge-bg: #c4271f;
  --quote-rule: #46464d;
  --reply-icon: #6e6e76;
  --scroll-thumb: #4a4a50;
  --human-bg: #342a4d;
  --human-fg: #cfbdf7;
  --h-claude-bg: #b9573a;
  --h-claude-fg: #ffffff;
  --h-opencode-bg: #2f6f73;
  --h-opencode-fg: #ffffff;
  --h-codex-img: url('/static/agents/codex-dark.png');
  --h-codex-tile: #000000;
  --h-cursor-img: url('/static/agents/cursor-dark.png');
  --h-devin-img: url('/static/agents/devin-dark.png');
  --h-icon-ring: rgba(255, 255, 255, 0.1);
  --h-other-bg: #2e2e33;
  --h-other-fg: #d0d0d6;
  color-scheme: dark;
}

/* ==== 2. Base ======================================================================== */
*, *::before, *::after { box-sizing: border-box; }

:root[data-theme="light"] { color-scheme: light; }
html { scrollbar-width: thin; scrollbar-color: var(--scroll-thumb) transparent; }
html, body { height: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font: calc(13px * var(--text-scale))/1.45 var(--font);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

code, pre, kbd, samp { font-family: var(--mono); }
button, input, textarea, select { font: inherit; color: inherit; }
h1, h2, h3, p { margin: 0; }

.hidden { display: none !important; }

/* Visually hidden, still read by screen readers. */
.sr-only {
  position: absolute !important;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* One focus ring for every control; buttons never lose it (spec 1.10). */
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
:focus:not(:focus-visible) { outline: none; }

/* Icons: inline SVG from index.html, or app.js icon(). Stroke drawn, never filled. The
   harness fallback (no createElementNS) is an empty span of the same size. */
.ic {
  display: inline-block;
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
  vertical-align: middle;
}
span.ic { stroke: none; }
.ic-hourglass { color: var(--amber-ink); }

.muted { color: var(--muted); }
.bad { color: var(--danger); }
.fine { font-size: calc(11.5px * var(--text-scale)); color: var(--muted); line-height: 1.45; }
.fine code { font-size: calc(11px * var(--text-scale)); }
#agent-cursor-idle-limit { margin: 8px 0; }  /* Settings → Agents: set apart from Devin's note above it */

kbd, .kbd {
  font: calc(11px * var(--text-scale))/1 var(--mono);
  padding: 2px 4px;
  border: 1px solid var(--line);
  border-radius: 4px;
  background: var(--chip-bg);
  color: var(--muted-2);
}

/* The only wide/narrow switches; see section 15 for the narrow-only elements. */
@media (min-width: 761px) { .narrow-only { display: none !important; } }
@media (max-width: 760px) { .wide-only { display: none !important; } }

/* ==== 3. Buttons, chips, badges ====================================================== */
.icon-btn {
  width: 28px;
  height: 28px;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: var(--muted-2);
  cursor: pointer;
}
.icon-btn:hover { background: var(--row-sel); color: var(--fg); }

.btn,
.btn-primary,
.btn-danger,
.btn-danger-ghost {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  height: 32px;
  padding: 0 12px;
  border: 1px solid var(--btn-border);
  border-radius: 7px;
  background: var(--btn-bg);
  color: var(--fg);
  font-size: calc(13px * var(--text-scale));
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
  text-decoration: none;
  cursor: pointer;
}
.btn .ic, .btn-primary .ic, .btn-danger .ic, .btn-danger-ghost .ic { width: 14px; height: 14px; }
.btn:hover { background: var(--row-sel); }
.btn-primary { border-color: transparent; background: var(--accent); color: var(--accent-fg); }
.btn-primary:hover { background: var(--link-hover); }
.btn-danger { border-color: transparent; background: var(--danger-solid); color: #ffffff; }
.btn-danger:hover { filter: brightness(1.08); }
.btn-danger-ghost { border-color: transparent; background: transparent; color: var(--muted-2); }
.btn-danger-ghost:hover { background: var(--danger-bg); color: var(--danger); }
button:disabled, .btn:disabled, .btn-primary:disabled { opacity: .5; cursor: default; filter: none; }

.pill {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  height: 20px;
  padding: 0 8px;
  border-radius: 10px;
  background: var(--amber-bg);
  color: var(--amber-ink);
  font-size: calc(11px * var(--text-scale));
  font-weight: 500;
  white-space: nowrap;
}
.pill .ic { width: 12px; height: 12px; }

.badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: 9px;
  background: var(--chip-bg);
  color: var(--ink-2);
  font-size: calc(11px * var(--text-scale));
  font-weight: 600;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.badge.danger { background: var(--badge-bg); color: #ffffff; }

/* A plain status dot; inside an avatar it becomes the corner dot (section 10). */
.dot {
  display: inline-block;
  width: 7px;
  height: 7px;
  flex-shrink: 0;
  border-radius: 50%;
  background: var(--green);
}

/* Header chips (spec 1.6). */
.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
  height: 26px;
  padding: 0 10px;
  border-radius: 13px;
  background: var(--chip-bg);
  color: var(--ink-2);
  font-size: calc(12px * var(--text-scale));
  white-space: nowrap;
}
.chip:empty { display: none; }
.chip .ic { width: 13px; height: 13px; }
.chip-label { color: var(--muted-2); }
.chip-num { font-weight: 600; font-variant-numeric: tabular-nums; color: var(--fg); }
.chip-danger { background: var(--danger-bg); color: var(--danger); font-weight: 500; }
button.chip-danger { border: 0; cursor: pointer; }
button.chip-danger:hover { box-shadow: inset 0 0 0 1px var(--danger); }
.approvals-tip {
  position: absolute;
  top: calc(100% + 6px);
  right: 12px;
  z-index: 12;
  width: max-content;
  max-width: min(320px, calc(100vw - 24px));
  max-height: min(240px, 50vh);
  overflow: auto;
  padding: 8px 10px;
  border: 1px solid var(--menu-border);
  border-radius: 7px;
  background: var(--menu-bg);
  box-shadow: var(--menu-shadow);
  color: var(--fg);
  font-size: calc(12px * var(--text-scale));
  line-height: 1.4;
  white-space: normal;
  visibility: hidden;
  pointer-events: none;
}
.conv-head:has(#st-approvals:hover) .approvals-tip,
.conv-head:has(#st-approvals:focus) .approvals-tip { visibility: visible; }
.meter {
  display: inline-flex;
  width: 34px;
  height: 4px;
  flex-shrink: 0;
  border-radius: 2px;
  background: var(--meter-track);
  overflow: hidden;
}
.meter-fill { display: block; height: 100%; background: var(--green); }
.w0 { width: 0%; } .w1 { width: 10%; } .w2 { width: 20%; } .w3 { width: 30%; }
.w4 { width: 40%; } .w5 { width: 50%; } .w6 { width: 60%; } .w7 { width: 70%; }
.w8 { width: 80%; } .w9 { width: 90%; } .w10 { width: 100%; }
#st-budget .meter-fill.w1, #st-budget .meter-fill.w2 { background: var(--busy); }
#st-budget .meter-fill.w0 { background: var(--danger); }
#st-hops .meter-fill { background: var(--muted-2); }
#st-state.bad { background: var(--amber-bg); color: var(--amber-fg); }
#st-state.bad .dot { background: var(--amber-ink); }
/* the socket is down (#129): the chip shows the last known state, with no live colour */
#st-state.stale .dot { background: var(--muted); }
#st-hops.bad { background: var(--danger-bg); color: var(--danger); font-weight: 500; }

/* Tier and host chips (members, inspector, mentions, first run). */
.tier {
  display: inline-block;
  padding: 0 6px;
  border: 1px solid var(--tier-border);
  border-radius: 5px;
  background: var(--tier-bg);
  color: var(--ink-2);
  font: calc(11.5px * var(--text-scale))/calc(20px * var(--text-scale)) var(--mono);
  white-space: nowrap;
}
.host-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 0 7px;
  border-radius: 5px;
  background: var(--tier-bg);
  color: var(--ink-2);
  font-size: calc(11.5px * var(--text-scale));
  font-weight: 500;
  line-height: calc(22px * var(--text-scale));
  white-space: nowrap;
}
.host-chip .ic { width: 12px; height: 12px; }
.host-chip.device { background: var(--device-bg); }
.chip-held {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 0 7px;
  border-radius: 5px;
  background: var(--amber-bg);
  color: var(--amber-fg);
  font-size: calc(11.5px * var(--text-scale));
  font-weight: 500;
  line-height: calc(22px * var(--text-scale));
}
.chip-held .ic { width: 12px; height: 12px; }
.chip-quiet {
  display: inline-flex;
  align-items: center;
  padding: 0 7px;
  border-radius: 5px;
  background: var(--tier-bg);
  color: var(--ink-2);
  font-size: calc(11.5px * var(--text-scale));
  font-weight: 500;
  line-height: calc(22px * var(--text-scale));
}

/* ==== 4. App layout (spec 1.2) ======================================================= */
.app {
  position: relative;
  display: flex;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
}
.conv {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  background: var(--bg);
}
@media (min-width: 1101px) {
  .app.pane-closed .pane { display: none; }
}
.scrim { position: fixed; inset: 0; z-index: 15; background: rgba(0, 0, 0, .32); }

/* ==== 5. Sidebar ===================================================================== */
.sidebar {
  width: 248px;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  gap: 18px;
  padding: 12px 10px 10px;
  background: var(--side-bg);
  border-right: 1px solid var(--side-border);
  overflow-y: auto;
}
.brand { display: flex; align-items: center; gap: 9px; height: 32px; padding: 0 4px 0 6px; }
.brand-tile {
  width: 24px;
  height: 24px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 6px;
  background: var(--accent);
  color: #ffffff;
}
.brand-tile .ic { width: 15px; height: 15px; }
.brand-name { flex: 1; min-width: 0; font-size: calc(14px * var(--text-scale)); font-weight: 600; letter-spacing: -.01em; }

.side-section, .room-list { display: flex; flex-direction: column; gap: 2px; }
.side-label { padding: 0 10px 4px; font-size: calc(11.5px * var(--text-scale)); font-weight: 600; color: var(--muted); }
.side-spacer { flex: 1; }

.room {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  height: 30px;
  flex-shrink: 0;
  padding: 0 10px;
  border: 0;
  border-radius: 7px;
  background: transparent;
  color: var(--fg);
  font-size: calc(13px * var(--text-scale));
  text-align: left;
  cursor: pointer;
}
.room .ic { width: 14px; height: 14px; color: var(--muted); }
.room:hover { background: var(--row-sel); }
.room[aria-current="page"] { background: var(--accent); color: var(--accent-fg); font-weight: 500; }
.room[aria-current="page"] .ic { color: currentColor; }
.room[aria-current="page"] .badge { background: rgba(255, 255, 255, .22); color: #ffffff; }
.room .badge { background: var(--badge-bg); color: #ffffff; }
/* Quiet unread marker (#109): other agents talking, nothing addressed to you - a plain dot,
   not the red badge, so it doesn't read as more urgent than it is. */
.room .dot.quiet { background: var(--muted); }
.room-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.room-closed, .room-add { color: var(--muted-2); }

.side-foot {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 8px 6px 2px;
  border-top: 1px solid var(--side-border);
}
.me-settings {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  padding: 4px;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--fg);
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.me-settings:hover { background: var(--row-sel); }
.me-settings > .ic { width: 14px; height: 14px; color: var(--muted); flex-shrink: 0; }
.me-text { display: flex; flex-direction: column; flex: 1; min-width: 0; line-height: 1.25; }
.me-name { font-size: calc(13px * var(--text-scale)); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.conn { display: inline-flex; align-items: center; gap: 5px; font-size: calc(11.5px * var(--text-scale)); color: var(--muted-2); }
.conn::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--green); }
.conn.bad { color: var(--danger); }
.conn.bad::before { background: var(--danger); }
.running-release-foot { padding: 0 10px 2px; font-size: calc(11.5px * var(--text-scale)); }
.running-release-foot a {
  display: block;
  color: var(--muted-2);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ==== 6. Conversation header and bands =============================================== */
.conv-head {
  position: relative;
  height: 52px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 12px 0 20px;
  border-bottom: 1px solid var(--line);
}
.head-title { display: flex; align-items: center; gap: 6px; min-width: 0; }
.head-title:has(> h1:empty) .head-hash { visibility: hidden; }   /* no room open */
.head-hash { width: 14px; height: 14px; color: var(--muted); }
.head-title h1 {
  font-size: calc(15px * var(--text-scale));
  font-weight: 600;
  letter-spacing: -.01em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
#room-title-button { border: 0; padding: 0; background: none; color: inherit; font: inherit;
  letter-spacing: inherit; cursor: pointer; display: block; max-width: 100%; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
#room-title-button:hover { text-decoration: underline; }
#room-title-button:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 2px; }
.room-sub { margin-left: 6px; font-size: calc(12px * var(--text-scale)); color: var(--muted); white-space: nowrap; }
/* The room's name is the last thing in the header to give way: it is what you read, and since
   #316 what you click to rename. The status chips go first (they scroll, and the state chip
   keeps its place), then the member count, and only then the name. Before, the name went first
   and a 1280 px window showed "s…". The factors are this far apart so that the order is strict:
   a shared squeeze cost the member count half a pixel, which is enough for an ellipsis. The same
   order holds at every text size: the larger sizes used to cap the name at 140 px instead. */
@media (min-width: 761px) {
  .conv-head > .chips { flex-shrink: 100000; min-width: 92px; }
  .room-sub { flex-shrink: 1000; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
}
.head-spacer { flex: 1; }
.chips {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  overflow-x: auto;
  scrollbar-width: none;
}
.chips::-webkit-scrollbar { display: none; }
.head-divider { width: 1px; height: 20px; flex-shrink: 0; margin: 0 2px; background: var(--side-border); }
/* The room's buttons: part of the header's own row on a desktop; a row of their own on a phone */
.head-tools { display: contents; }
.head-btn { width: 30px; height: 30px; border-radius: 7px; color: var(--ink-2); }
#pane-toggle[aria-pressed="true"],
#focus-toggle[aria-pressed="true"] { background: var(--btn-on); }

.rooms-toggle {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  height: 44px;
  padding: 0 8px 0 4px;
  border: 0;
  background: transparent;
  color: var(--link);
  font-size: calc(15px * var(--text-scale));
  cursor: pointer;
}
.rooms-toggle .ic { width: 18px; height: 18px; stroke-width: 1.8; }
.rooms-toggle .badge { margin-left: 4px; background: var(--badge-bg); color: #ffffff; }
.members-pill {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  height: 34px;
  padding: 0 11px;
  border: 1px solid var(--meter-track);
  border-radius: 17px;
  background: var(--bg);
  color: var(--fg);
  font-size: calc(13.5px * var(--text-scale));
  font-weight: 600;
  cursor: pointer;
}
.members-pill .badge {
  position: absolute;
  top: -4px;
  right: -4px;
  min-width: 17px;
  height: 17px;
  padding: 0 4px;
  border: 2px solid var(--head-2-bg);
  font-size: calc(9.5px * var(--text-scale));
  font-weight: 700;
}

/* Bands under the header. The glyph is drawn here so app.js can replace a band's text. */
.band {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
  padding: 8px 20px;
  border-bottom: 1px solid var(--line);
  font-size: calc(12.5px * var(--text-scale));
  line-height: 1.4;
}
/* fallback glyph for a band whose text was set without an icon */
.band:not(:has(> .ic))::before {
  content: "!";
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 15px;
  height: 15px;
  border: 1.5px solid currentColor;
  border-radius: 50%;
  font-size: calc(10px * var(--text-scale));
  font-weight: 700;
  line-height: 1;
}
.band-amber { background: var(--amber-bg); color: var(--amber-fg); }
.band-danger { background: var(--danger-bg); color: var(--danger); font-weight: 500; }
.band-meeting { background: var(--chip-bg); color: var(--ink-2); flex-wrap: wrap; }
/* the text keeps room to be read: when the buttons would squeeze it, they wrap to a row of their own */
.band-meeting > span { flex: 1 1 14em; min-width: 0; }
.meeting-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-left: auto; }
.meeting-btn { height: 26px; padding: 0 10px; flex-shrink: 0; font-size: calc(12px * var(--text-scale)); }
/* the voice switch: a track and a knob drawn here; aria-checked says its state, and the bar's words repeat it */
.switch-track {
  position: relative;
  flex-shrink: 0;
  width: 24px;
  height: 14px;
  border-radius: 7px;
  background: var(--meter-track);
  transition: background 120ms;
}
.switch-knob {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: #ffffff;
  transition: transform 120ms;
}
.meeting-voice[aria-checked="true"] .switch-track { background: var(--accent); }
.meeting-voice[aria-checked="true"] .switch-knob { transform: translateX(10px); }
.band > .ic { width: 15px; height: 15px; }

/* ==== 7. Log rows (spec 1.3) ========================================================= */
.log-wrap { flex: 1; min-height: 0; position: relative; display: flex; flex-direction: column; }
.log {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 0 28px 14px 20px;
  overflow-x: hidden;
  overflow-y: auto;
  overflow-wrap: anywhere;
}
/* Top spacer: a short conversation sits at the bottom, next to the composer. */
.log::before { content: ""; flex: 1 0 0; }

.line { min-width: 0; flex-shrink: 0; }

.line.day, .day {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: calc(11.5px * var(--text-scale));
  font-weight: 600;
  color: var(--muted);
}
.day::before, .day::after { content: ""; flex: 1; height: 1px; background: var(--line); }

/* A chat message: avatar column + body column. */
.line.k-chat {
  display: grid;
  grid-template-columns: 32px minmax(0, 1fr);
  column-gap: 10px;
  row-gap: 3px;
  border-radius: 8px;
  transition: background-color 200ms;
}
.line.k-chat > .avatar { align-self: start; }
/* A transcript line (#573): smaller than a chat message, one column, a call tag.
   Two classes, so the phone's .line.k-chat columns (a 28 px avatar slot) don't win. */
.line.k-chat.k-meeting {
  grid-template-columns: minmax(0, 1fr);
  font-size: calc(12px * var(--text-scale));
  color: var(--ink-2);
}
.call-tag {
  display: inline-flex;
  align-items: center;
  height: 16px;
  padding: 0 6px;
  border-radius: 8px;
  background: var(--chip-bg);
  color: var(--muted);
  font-size: calc(10.5px * var(--text-scale));
  font-weight: 600;
  letter-spacing: .02em;
}
.nick-meeting { font-size: calc(12px * var(--text-scale)); font-weight: 600; color: var(--ink-2); }
.line.cont { margin-top: -8px; }                /* 14 px row gap becomes 6 px */

/* Selected agent (inspected) and messages that mention you: tinted bands with a bar. */
.line.sel,
.line.mention {
  margin: -4px -8px;
  padding: 4px 8px;
}
.line.sel { background: var(--accent-tint); box-shadow: inset 2px 0 0 var(--accent); }
.line.mention { background: var(--mention-bg); box-shadow: inset 2px 0 0 var(--accent); }
.line.cont.sel, .line.cont.mention { margin-top: -12px; }
/* consecutive selected rows read as one block */
.line.sel + .line.sel.cont { margin-top: -10px; border-top-left-radius: 0; border-top-right-radius: 0; }
.line.sel:has(+ .line.sel.cont) { border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
.line.flash { animation: sb-flash 1.2s ease-out; }

/* Pinned decisions (#292, DESIGN.md §48). The pin button is out of the row's grid, at its top right:
   shown on hover and focus, and always on a pinned row, which keeps clear of it. A phone has no hover. */
.line.k-chat { position: relative; }
.msg-pin {
  position: absolute;
  top: -2px;
  right: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  padding: 0;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: var(--muted);
  opacity: 0;
  cursor: pointer;
}
.msg-pin .ic { width: 14px; height: 14px; }
.line.k-chat:hover > .msg-pin, .line.k-chat:focus-within > .msg-pin, .msg-pin:focus-visible {
  opacity: 1;
  background: var(--bg);
}
.msg-pin:hover { background: var(--row-sel); color: var(--fg); }
.msg-pin[aria-pressed="true"] { opacity: 1; background: transparent; color: var(--accent); }
.msg-pin[aria-pressed="true"] .ic { fill: color-mix(in srgb, currentColor 28%, transparent); }
.line.k-chat.is-pinned { padding-right: 28px; }
/* a touch screen has no hover: the button is always there, and the text keeps clear of it */
@media (hover: none) {
  .msg-pin { opacity: .6; }
  .line.k-chat, .line.k-chat.sel, .line.k-chat.mention { padding-right: 32px; }
}
.line.k-chat.collapsible:not(.expanded) > .msg-pin { display: none; }
.pins { flex-shrink: 0; border-bottom: 1px solid var(--line); }
.pins-toggle {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  min-height: 34px;
  padding: 4px 20px;
  border: 0;
  background: transparent;
  color: var(--fg);
  font-size: calc(12.5px * var(--text-scale));
  text-align: left;
  cursor: pointer;
}
.pins-toggle:hover { background: var(--row-sel); }
.pins-toggle .ic-pin { color: var(--accent); }
.pins-count { font-weight: 600; white-space: nowrap; }
.pins-peek { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--muted-2); }
.pins-toggle .ic-chev { transition: transform 120ms; color: var(--muted); }
.pins-toggle[aria-expanded="true"] .ic-chev { transform: rotate(180deg); }
.pins-toggle[aria-expanded="true"] .pins-peek { visibility: hidden; }   /* the list says it */
.pins-list { display: flex; flex-direction: column; gap: 2px; margin: 0; padding: 0 12px 8px 20px; list-style: none; }
/* The room's claims (#545), the same strip as the pins: hidden when empty, a count, then the list. */
.claim-board { flex-shrink: 0; border-bottom: 1px solid var(--line); }
.claim-board-toggle {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  min-height: 34px;
  padding: 4px 20px;
  border: 0;
  background: transparent;
  color: var(--fg);
  font-size: calc(12.5px * var(--text-scale));
  text-align: left;
  cursor: pointer;
}
.claim-board-toggle:hover { background: var(--row-sel); }
.claim-board-toggle .ic-board { color: var(--accent); }
.claim-board-count { font-weight: 600; white-space: nowrap; }
.claim-board-peek { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--muted-2); }
.claim-board-toggle .ic-chev { transition: transform 120ms; color: var(--muted); }
.claim-board-toggle[aria-expanded="true"] .ic-chev { transform: rotate(180deg); }
.claim-board-toggle[aria-expanded="true"] .claim-board-peek { visibility: hidden; }
.claim-board-list { display: flex; flex-direction: column; gap: 2px; margin: 0; padding: 0 12px 8px 20px; list-style: none; }
.claim-board-row {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 4px 10px;
  min-width: 0;
  padding: 3px 6px;
  font-size: calc(12.5px * var(--text-scale));
}
.claim-board-key { font-weight: 600; overflow-wrap: anywhere; }
.claim-board-holder { color: var(--muted); }
.claim-board-note { flex: 1 1 120px; min-width: 0; overflow-wrap: anywhere; }
.claim-board-note .md-note { overflow-wrap: anywhere; }
.claim-board-exp { margin-left: auto; color: var(--muted-2); white-space: nowrap; }  /* right, with or without a note */
.pin-row { display: flex; align-items: center; gap: 8px; }
.pin-link {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 5px 6px;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: var(--fg);
  font-size: calc(12.5px * var(--text-scale));
  text-align: left;
  cursor: pointer;
}
.pin-link:hover { background: var(--row-sel); }
.pin-from { font-weight: 600; white-space: nowrap; }
.pin-text { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--muted-2); }
.pin-unpin { flex-shrink: 0; }
@keyframes sb-flash {
  0%, 30% { background-color: var(--focus); }
  100% { background-color: transparent; }
}

/* Focus mode (#99): chatRow builds .collapsed-line only on a message that collapses (an agent
   message not addressed to you), so the rule below hides every other direct child of the row
   in its place; a click adds .expanded, which drops out of :not(.expanded) and restores each
   child's own display (.avatar, .msg-body, .reply-to) while this one goes back to hidden. */
.line.k-chat.collapsible:not(.expanded) > :not(.collapsed-line) { display: none; }
.line.k-chat.collapsible:not(.expanded) > .collapsed-line { display: flex; }
.collapsed-line {
  display: none;
  grid-column: 1 / -1;
  align-items: center;
  gap: 7px;
  width: 100%;
  margin: 0;
  padding: 3px 6px;
  border: 0;
  border-radius: 6px;
  background: none;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.collapsed-line:hover, .collapsed-line:focus-visible { background: var(--chip-bg); }
.collapsed-sender { flex-shrink: 0; font-size: calc(12.5px * var(--text-scale)); font-weight: 600; color: var(--muted-2); }
.collapsed-snippet {
  overflow: hidden;
  min-width: 0;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: calc(12.5px * var(--text-scale));
  color: var(--muted);
}

/* Reply line above the header: gutter arrow, mini avatar, nick, first line. */
.reply-to {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: 32px auto auto minmax(0, 1fr);
  column-gap: 6px;
  align-items: center;
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  color: var(--muted-2);
  font-size: calc(12px * var(--text-scale));
  text-align: left;
  cursor: pointer;
}
.reply-gutter { display: flex; justify-content: flex-end; padding-right: 4px; color: var(--reply-icon); }
.reply-gutter .ic, .reply-to > .ic { width: 14px; height: 14px; color: var(--reply-icon); }
.reply-nick { font-weight: 600; color: var(--ink-2); white-space: nowrap; }
.reply-snippet { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.reply-to:hover .reply-snippet { color: var(--fg); }

/* Avatars: agents are rounded squares with a harness monogram, humans are circles. */
.avatar {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  flex-shrink: 0;
  border-radius: 8px;
  background: var(--h-other-bg);
  color: var(--h-other-fg);
  font-size: calc(11.5px * var(--text-scale));
  font-weight: 700;
  line-height: 1;
  user-select: none;
}
.avatar.h-claude { background: var(--h-claude-bg); color: var(--h-claude-fg); }
/* OpenCode has switchboard's own angle-brackets glyph too (#518): a neutral drawing, no company's mark. */
.avatar.h-opencode { background: var(--h-opencode-bg); color: var(--h-opencode-fg); }
.avatar.h-claude .ic, .avatar.h-opencode .ic { width: 66%; height: 66%; stroke-width: 1.6; }
/* The Inspector's avatar writes the name under the bubble, so it grows to 48 px and sits the word
   high enough to clear the status dot; white on this tile is 4.6:1. */
.avatar.lg.named {
  width: 48px; height: 48px; border-radius: 12px;
  flex-direction: column; justify-content: flex-start; gap: 2px; padding-top: 6px;
}
.avatar.named .ic { width: 24px; height: 24px; flex: none; }
.av-word { font-size: calc(9.5px * var(--text-scale)); font-weight: 700; line-height: 1; }
.avatar.h-test, .avatar.h-unknown { background: var(--h-other-bg); color: var(--h-other-fg); }
/* Codex, Cursor and Devin show their vendor's icon, unaltered; the monogram stays in the DOM, unseen.
   Claude Code has switchboard's own bubble: Anthropic allows its name in plain text, not its icon. */
.avatar.h-codex, .avatar.h-cursor, .avatar.h-devin {
  color: transparent;
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
  box-shadow: inset 0 0 0 1px var(--h-icon-ring);
}
.avatar.h-codex { background-color: var(--h-codex-tile); background-image: var(--h-codex-img); }
.avatar.h-cursor { background-color: transparent; background-image: var(--h-cursor-img); }
.avatar.h-devin { background-color: transparent; background-image: var(--h-devin-img); }
.avatar.human { border-radius: 50%; background: var(--human-bg); color: var(--human-fg); font-size: calc(12.5px * var(--text-scale)); font-weight: 600; }
.avatar.sys { background: var(--chip-bg); color: var(--muted-2); font-size: calc(15px * var(--text-scale)); font-weight: 400; }
.avatar.sm { width: 28px; height: 28px; font-size: calc(12px * var(--text-scale)); }
.avatar.lg { width: 40px; height: 40px; border-radius: 10px; font-size: calc(13px * var(--text-scale)); }
.avatar.lg.human { border-radius: 50%; }
.avatar.mini { width: 16px; height: 16px; border-radius: 4px; font-size: calc(7.5px * var(--text-scale)); font-weight: 700; }
.avatar.mini.human { border-radius: 50%; }

.msg-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.msg-head { display: flex; align-items: baseline; flex-wrap: wrap; gap: 0 7px; min-width: 0; }
.nick { font-size: calc(13px * var(--text-scale)); font-weight: 600; color: var(--fg); overflow-wrap: anywhere; min-width: 0; }
button.nick {
  padding: 0;
  border: 0;
  background: none;
  font-weight: 600;
  text-align: left;
  cursor: pointer;
}
button.nick:hover { text-decoration: underline; text-underline-offset: 2px; }
.host-tag { font-weight: 500; color: var(--muted-2); }
.flag-approvals { display: inline-flex; align-self: center; color: var(--danger); }
.flag-approvals .ic { width: 13px; height: 13px; }
.flag-unknown {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  align-self: center;
  min-width: 15px;
  height: 15px;
  padding: 0 3px;
  border-radius: 4px;
  background: var(--danger-bg);
  color: var(--danger);
  font-size: calc(10.5px * var(--text-scale));
  font-weight: 700;
  line-height: 1;
}
.approval-flag { cursor: help; }
.approval-flag::after {
  content: attr(data-tooltip);
  position: absolute;
  left: 0;
  bottom: calc(100% + 8px);
  z-index: 10;
  width: min(220px, 70vw);
  padding: 7px 9px;
  border: 1px solid var(--menu-border);
  border-radius: 7px;
  background: var(--menu-bg);
  box-shadow: var(--menu-shadow);
  color: var(--fg);
  font-size: calc(12px * var(--text-scale));
  font-weight: 400;
  line-height: 1.35;
  white-space: normal;
  visibility: hidden;
  pointer-events: none;
}
.approval-flag:hover::after, .approval-flag:focus::after, .approval-flag.tip-open::after { visibility: visible; }
.harness-name, .via, .ts { font-size: calc(11.5px * var(--text-scale)); color: var(--muted); white-space: nowrap; }
.ts { font-variant-numeric: tabular-nums; }
.msg-meta { display: inline-flex; align-items: baseline; gap: 5px; white-space: nowrap; }
.msg-number { font-size: calc(11.5px * var(--text-scale)); color: var(--muted); user-select: text; }
.msg-meta.gutter { flex-direction: column; align-items: flex-end; gap: 0; padding-top: 2px; }
.msg-meta.gutter .ts, .msg-meta.gutter .msg-number { font-size: calc(10.5px * var(--text-scale)); }
.msg-text { min-width: 0; font-size: calc(13.5px * var(--text-scale)); line-height: 1.45; }
.msg-text.md-plain { white-space: pre-wrap; }   /* fallback when md.js did not load */

/* Door, notice and local rows share the gutter layout. */
.line.k-join,
.line.k-leave,
.line.k-notice,
.line.local {
  display: grid;
  grid-template-columns: 32px minmax(0, 1fr);
  column-gap: 10px;
  align-items: start;
  font-size: calc(12.5px * var(--text-scale));
  color: var(--muted-2);
}
.line.k-join > .ic,
.line.k-leave > .ic,
.line.k-notice > .ic,
.line.local > .ic { justify-self: center; width: 14px; height: 14px; margin-top: 2px; }
.line .text { min-width: 0; }
.line .text strong { font-weight: 600; color: var(--ink-2); }
.line.k-notice.warn {
  padding: 7px 12px 7px 0;
  border-radius: 8px;
  background: var(--danger-bg);
  color: var(--danger);
  font-weight: 500;
}
.line.k-notice.warn .text strong { color: inherit; }
.line.local.error { color: var(--danger); }
.cmd-out {
  grid-column: 2;
  margin: 4px 0 0;
  padding: 8px 12px;
  border-radius: 8px;
  background: var(--pre-bg);
  color: var(--fg);
  font: calc(12px * var(--text-scale))/1.45 var(--mono);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* Empty room: a centred card over the (empty) log. */
.room-empty {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  pointer-events: none;
}
.room-empty-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  max-width: 460px;
  padding: 22px 24px;
  border: 1px solid var(--side-border);
  border-radius: 12px;
  background: var(--bg);
  text-align: center;
  pointer-events: auto;
}
.room-empty-title { font-size: calc(15px * var(--text-scale)); font-weight: 600; }
.copy-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; justify-content: center; }
.copy-row code {
  padding: 6px 10px;
  border: 1px solid var(--code-border);
  border-radius: 7px;
  background: var(--pre-bg);
  font-size: calc(13px * var(--text-scale));
  overflow-wrap: anywhere;
}

/* ==== 8. Markdown (md.js output; spec 2.3) =========================================== */
.md > * + *,
.md-quote > * + *,
.md li > * + * { margin-top: 6px; }
.md-p, .md-h, .md-pre, .md-ul, .md-ol, .md-quote, .md-hr, .md-table-wrap, .md-artifact { margin: 0; }
.md > :first-child { margin-top: 0; }
.md > :last-child { margin-bottom: 0; }

.md-h { line-height: 1.35; }
.md-h1 { font-size: calc(16px * var(--text-scale)); font-weight: 650; letter-spacing: -.01em; }
.md-h2 { font-size: calc(14.5px * var(--text-scale)); font-weight: 600; }
.md-h3 { font-size: calc(13.5px * var(--text-scale)); font-weight: 600; }
.md strong { font-weight: 600; }

.md-code {
  padding: 0 4px;
  border: 1px solid var(--code-border);
  border-radius: 4px;
  background: var(--code-bg);
  color: var(--code-fg);
  font: calc(12px * var(--text-scale))/1.4 var(--mono);
  unicode-bidi: isolate;
  overflow-wrap: anywhere;
}

.md-pre {
  max-width: 640px;
  min-width: 0;
  border: 1px solid var(--code-border);
  border-radius: 8px;
  background: var(--pre-bg);
  overflow: hidden;
}
.md-pre-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  height: 26px;
  padding: 0 4px 0 12px;
  border-bottom: 1px solid var(--line);
}
.md-lang { font-size: calc(11px * var(--text-scale)); font-weight: 500; color: var(--muted); }
.md-copy {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  height: 20px;
  padding: 0 6px;
  border: 0;
  border-radius: 5px;
  background: transparent;
  color: var(--muted-2);
  font-size: calc(11.5px * var(--text-scale));
  cursor: pointer;
}
.md-copy:hover { background: var(--row-sel); color: var(--fg); }
.md-pre-body {
  margin: 0;
  padding: 8px 12px 10px;
  overflow-x: auto;
  color: var(--fg);
  font: calc(12px * var(--text-scale))/1.5 var(--mono);
  white-space: pre;
  tab-size: 4;
  overflow-wrap: normal;
}
.md-pre-body code { font: inherit; background: none; border: 0; padding: 0; }

/* A ```mermaid block shown as its diagram (diagram.js, DESIGN.md §33). The drawing sits in the
   box's shadow root, with its own styles; containment keeps what it paints inside the box. */
.md-show-diagram { margin-left: auto; }
.md-fullscreen { display: none; }
.md-showing-diagram .md-fullscreen { display: inline-flex; }
.md-diagram, .md-diagram-error { display: none; }
.md-showing-diagram .md-diagram { display: block; }
.md-showing-diagram .md-pre-body { display: none; }
.md-diagram-failed .md-diagram-error { display: block; }
.md-diagram {
  padding: 10px 12px;
  overflow: auto;
  contain: paint;
  color: var(--fg);
}
.md-diagram:fullscreen {
  display: grid;
  place-items: center;
  box-sizing: border-box;
  width: 100vw;
  height: 100vh;
  padding: 12px;
  overflow: hidden;
  background: var(--bg);
}
.md-diagram:fullscreen::part(drawing) {
  width: 100% !important;
  height: 100% !important;
  max-width: none !important;
  max-height: none !important;
}
.md-diagram-error {
  padding: 6px 12px;
  border-bottom: 1px solid var(--line);
  color: var(--danger);
  font: calc(12px * var(--text-scale))/1.5 var(--mono);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.md-ask-fix {
  display: block;
  width: fit-content;
  height: auto;
  margin-top: 6px;
  padding: 4px 8px;
  color: var(--fg);
}
/* where Mermaid draws before the drawing moves into its box: laid out (it measures text) but
   off-screen and invisible */
.md-diagram-stage {
  position: absolute;
  top: 0;
  left: -10000px;
  width: 640px;
  visibility: hidden;
  pointer-events: none;
}

.md-ul, .md-ol { display: flex; flex-direction: column; gap: 2px; padding-left: 20px; }
.md li > .md-ul, .md li > .md-ol { margin-top: 2px; }

.md-quote {
  margin: 0;
  padding: 1px 0 1px 12px;
  border-left: 2px solid var(--quote-rule);
  color: var(--muted-2);
}

.md-hr { height: 0; border: 0; border-top: 1px solid var(--line); }

.md-table-wrap { display: block; width: max-content; max-width: 100%; overflow-x: auto; }
.md-table {
  width: auto;
  border: 1px solid var(--code-border);
  border-collapse: separate;
  border-spacing: 0;
  border-radius: 8px;
  font-size: calc(13px * var(--text-scale));
}
.md-table th, .md-table td {
  padding: 4px 12px;
  border-bottom: 1px solid var(--line);
  text-align: left;
  vertical-align: top;
}
.md-table th { background: var(--pre-bg); font-weight: 600; border-bottom-color: var(--code-border); }
.md-table th + th, .md-table td + td { border-left: 1px solid var(--code-border); }
.md-table tbody tr:last-child td { border-bottom: 0; }
.md-table thead tr:first-child th:first-child { border-top-left-radius: 7px; }
.md-table thead tr:first-child th:last-child { border-top-right-radius: 7px; }
.md-table .md-code { border: 0; background: none; padding: 0; }
.md-al-l { text-align: left !important; }
.md-al-c { text-align: center !important; }
.md-al-r { text-align: right !important; }

/* Links: always underlined (colour is not the only cue); the real address is shown next to it. */
.md-link {
  color: var(--link);
  font-weight: 500;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 2px;
}
.md-link:hover { color: var(--link-hover); text-decoration-thickness: 2px; }
.md-file {
  color: var(--link);
  font-weight: 500;
  text-decoration: underline;
  text-underline-offset: 2px;
}
.md-file:hover { color: var(--link-hover); }
.md-ext { margin-left: 2px; color: var(--link); font-size: calc(11px * var(--text-scale)); }
.md-url {
  margin-left: 8px;
  color: var(--muted);
  font: calc(12px * var(--text-scale))/1.45 var(--mono);
  word-break: break-all;
}
.md-blocked { color: var(--fg); text-decoration: none; cursor: text; }
.md-blocked-pill {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  height: 18px;
  margin-left: 6px;
  padding: 0 7px;
  border-radius: 9px;
  background: var(--code-bg);
  color: var(--muted-2);
  font-size: calc(11px * var(--text-scale));
  font-weight: 500;
  vertical-align: 1px;
  white-space: nowrap;
}
.md-blocked-pill::before { content: "\2298"; font-size: calc(11px * var(--text-scale)); }

/* An artifact line (issue #544): a file named in a message. Tokens only, so light and dark
   follow the theme, and the card wraps inside a message on a phone. */
.md-artifact {
  max-width: min(100%, 640px);
  min-width: 0;
  padding: 8px 12px 10px;
  border: 1px solid var(--code-border);
  border-radius: 8px;
  background: var(--pre-bg);
}
/* two cards in a row: apart, not one block */
.md-artifact + .md-artifact { margin-top: 6px; }
.md-artifact-name {
  color: var(--fg);
  font-weight: 600;
  overflow-wrap: anywhere;
}
.md-artifact-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 14px;
  margin-top: 2px;
  color: var(--muted);
  font: calc(12px * var(--text-scale))/1.45 var(--mono);
}
.md-artifact-k {
  margin-right: 6px;
  color: var(--muted-2);
  font-family: var(--font);
  font-size: calc(11px * var(--text-scale));
  font-weight: 600;
}
.md-artifact-where { margin-top: 6px; min-width: 0; overflow-wrap: anywhere; }
.md-artifact-path {
  display: block;
  color: var(--ink-2);
  font: calc(12px * var(--text-scale))/1.45 var(--mono);
  overflow-wrap: anywhere;
}
.md-artifact-hint {
  display: block;
  margin-top: 2px;
  color: var(--muted);
  font-size: calc(12px * var(--text-scale));
}
.md-artifact .md-url { overflow-wrap: anywhere; }
.md-mention {
  padding: 0 3px;
  border-radius: 4px;
  background: var(--mention-bg);
  color: var(--mention-fg);
  font-weight: 600;
}

/* ==== 9. Composer and popovers (spec 1.2, 1.7) ======================================= */
.composer { position: relative; flex-shrink: 0; padding: 0 20px 16px; }
.composer-box {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 9px 10px 8px 12px;
  border: 1px solid var(--input-border);
  border-radius: 10px;
  background: var(--input-bg);
  box-shadow: var(--input-shadow);
}
.composer-box:focus-within { box-shadow: 0 0 0 3px var(--focus); }
/* The mirror layer (issue #110): .input-wrap stays a plain block around #input, in normal flow,
   so #input's own sizing (rows, field-sizing, min/max-height) decides the wrap's height exactly
   as it decided composer-box's before -- no new layout mode (a grid track, a flex basis) gets a
   say, which would round its own width or height a hair differently than #input's direct math
   and so wrap the (invisible) text one character sooner or later than the mirror does. The
   mirror only needs to sit exactly over that box, which position: absolute; inset: 0 does
   without taking part in sizing it. #input stays last in source order and position: relative
   (so it paints over the mirror: a positioned box, 'auto' z-index, beats an in-flow static one
   only by coming later -- the two rules together are what keeps the caret on top). */
.input-wrap { position: relative; min-width: 0; }
#input-mirror {
  position: absolute;
  inset: 0;
  margin: 0;
  padding: 0;
  border: 0;
  overflow: hidden;
  white-space: pre-wrap;
  overflow-wrap: break-word;
  color: var(--fg);
  font-size: calc(13.5px * var(--text-scale));
  line-height: calc(20px * var(--text-scale));
  pointer-events: none; /* clicks and selection stay on #input, drawn above it */
}
/* Past 8 lines #input scrolls, and a scrollbar that takes width (Linux, Windows) would narrow its
   text but not the mirror's, so the text a person sees would wrap later than the real one and
   the caret drift off it (#110 review). Both reserve the same gutter, scrolling or not. */
#input, #input-mirror { scrollbar-gutter: stable; }
/* The same look as a sent message's .md-mention, minus the padding and bold weight: either
   would change this span's text width and so where the mirror wraps, which must stay pixel for
   pixel with #input's own (invisible) wrap -- the whole point of the mirror. */
.mention-hl { border-radius: 3px; background: var(--mention-bg); color: var(--mention-fg); }
#input {
  position: relative;
  display: block;
  width: 100%;
  min-height: 20px;
  /* 8 lines at any text size (#580): a fixed 168px held 7.3 lines at Large and 6.5 at Larger, and
     the 8th scrolled the box and hid the top of the first. No padding here, so no more to add. */
  max-height: calc(160px * var(--text-scale));
  margin: 0;
  padding: 0;
  border: 0;
  outline: none;
  resize: none;
  background: transparent;
  color: transparent; /* the mirror behind it shows the text; the caret stays visible below */
  caret-color: var(--fg);
  font-size: calc(13.5px * var(--text-scale));
  line-height: calc(20px * var(--text-scale));
  overflow-y: auto;
  field-sizing: content; /* grows with wrapped text (#130); min/max-height still clamp it */
}
/* While composing with an IME, the candidate text is #input's own (native) rendering: show it
   for real rather than leave it transparent over a mirror that hasn't caught up yet. */
#input.composing { color: var(--fg); }
#input::placeholder { color: var(--muted); }
#input:disabled { cursor: not-allowed; }
.composer-bar { display: flex; align-items: center; gap: 4px; }
.drop-target { outline: 2px dashed var(--link); outline-offset: -6px; }
.settings-files { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.settings-files input { width: 6rem; }
.composer-bar .icon-btn .ic { width: 15px; height: 15px; }
.composer-spacer { flex: 1; }
.composer-hint { margin-right: 8px; font-size: calc(11.5px * var(--text-scale)); color: var(--muted); white-space: nowrap; }
.composer-hint kbd { padding: 0; border: 0; background: none; font-size: calc(11px * var(--text-scale)); color: var(--muted-2); }
#send { height: 28px; padding: 0 12px; gap: 5px; font-size: calc(12.5px * var(--text-scale)); }
#send .ic { width: 13px; height: 13px; stroke-width: 1.8; }

/* Slash palette and @mention list: one popover shape. */
.palette {
  position: absolute;
  bottom: 100%;
  left: 20px;
  right: 20px;
  z-index: 30;
  display: flex;
  flex-direction: column;
  max-height: 320px;
  margin-bottom: 6px;
  overflow-y: auto;
  border: 1px solid var(--menu-border);
  border-radius: 11px;
  background: var(--menu-bg);
  box-shadow: var(--pop-shadow);
}
.pal-head, .pal-foot {
  position: sticky;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  padding: 8px 14px;
  background: var(--menu-bg);
  font-size: calc(12px * var(--text-scale));
  color: var(--muted);
}
.pal-head { top: 0; border-bottom: 1px solid var(--line); }
.pal-head ~ .pal-head { border-top: 1px solid var(--line); }  /* the @ popover's People head (#418) */
.pal-head > :first-child { font-size: calc(13px * var(--text-scale)); font-weight: 600; color: var(--fg); }
.pal-head > :last-child:not(:first-child):not(:nth-child(2)) { margin-left: auto; }
.pal-foot { bottom: 0; border-top: 1px solid var(--line); font-size: calc(11.5px * var(--text-scale)); }
.pal-foot .pal-tip { margin-left: auto; }
.pal-key { display: inline-flex; align-items: center; gap: 5px; }
.pal-key .ic { width: 13px; height: 13px; }
#mentions .pal-head > :last-child { margin-left: auto; }
.pal-group { display: flex; flex-direction: column; gap: 1px; padding: 4px 6px; }
.pal-group > :first-child:not(.pal-item) { padding: 6px 8px 2px; font-size: calc(11.5px * var(--text-scale)); font-weight: 600; color: var(--muted); }
.pal-item {
  display: grid;
  grid-template-columns: 76px 118px minmax(0, 1fr) auto;
  column-gap: 8px;
  row-gap: 4px;
  align-items: center;
  padding: 6px 8px;
  border-radius: 7px;
  font-size: calc(13px * var(--text-scale));
  cursor: pointer;
}
.pal-item:hover { background: var(--row-sel); }
.pal-item[aria-selected="true"] { background: var(--accent-tint); }
.pal-cmd { font: 600 calc(13px * var(--text-scale)) var(--mono); color: var(--fg); white-space: nowrap; }
.pal-item[aria-selected="true"] .pal-cmd { color: var(--link); }
.pal-args { font: calc(12.5px * var(--text-scale)) var(--mono); color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pal-desc { min-width: 0; color: var(--ink-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pal-item > .pill { grid-column: 4; }
.pal-usage {
  grid-column: 1 / -1;
  justify-self: start;
  max-width: 100%;
  padding: 3px 8px;
  border: 1px solid var(--code-border);
  border-radius: 6px;
  background: var(--menu-bg);
  font: calc(12.5px * var(--text-scale)) var(--mono);
  overflow-wrap: anywhere;
}
.pal-detail { grid-column: 1 / -1; font-size: calc(12px * var(--text-scale)); color: var(--muted-2); }

/* A mention option: avatar | name, host, status, warning | tier. */
.pal-item.mention-opt { grid-template-columns: 28px minmax(0, 1fr) auto; column-gap: 10px; row-gap: 2px; align-items: start; }
.mention-opt > .avatar { grid-column: 1; grid-row: 1 / span 3; width: 28px; height: 28px; border-radius: 7px; font-size: calc(10.5px * var(--text-scale)); }
.mention-opt > .avatar.human { border-radius: 50%; }
.mention-opt > .tier { grid-column: 3; grid-row: 1; }
.mention-opt > :not(.avatar):not(.tier) { grid-column: 2; min-width: 0; }
.mention-opt .m-warn { font-size: calc(12px * var(--text-scale)); }

/* ==== 10. Right pane and members (spec 1.2, 1.4) ===================================== */
.pane {
  width: 288px;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  background: var(--pane-bg);
  border-left: 1px solid var(--pane-border);
  overflow: hidden;
  /* clip, not just hide: focusing #insp-name mid-slide must not scroll the pane sideways */
  overflow: clip;
}
.pane-track {
  flex: 1;
  min-height: 0;
  width: 200%;
  display: flex;
  transform: translateX(0);
  transition: transform 260ms var(--ease);
}
.pane.inspecting .pane-track { transform: translateX(-50%); }
.pane-view {
  width: 50%;
  height: 100%;
  min-height: 0;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 0 12px 14px;
  overflow-y: auto;
  visibility: visible;
  transition: visibility 0s linear 0s;
}
/* hidden only after the slide ends, so it is never focusable while off screen */
.pane-view.offscreen { visibility: hidden; transition: visibility 0s linear 260ms; }
#inspector { overflow: hidden; overflow: clip; }

.pane-head {
  position: sticky;
  top: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 8px;
  height: 52px;
  flex-shrink: 0;
  margin: 0 -12px;
  padding: 0 16px;
  border-bottom: 1px solid var(--line);
  background: var(--pane-bg);
}
.pane-head h2 { font-size: calc(13px * var(--text-scale)); font-weight: 600; }
/* a focus target only (tabindex=-1: focus lands here when the last agent's row goes away) */
.pane-head h2:focus { outline: none; }
.pane-head .muted { font-size: calc(12px * var(--text-scale)); }
.insp-head { padding: 0 12px 0 8px; }
.back-btn {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  height: 30px;
  padding: 0 8px 0 4px;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: var(--fg);
  font-size: calc(13px * var(--text-scale));
  font-weight: 600;
  cursor: pointer;
}
.back-btn:hover { background: var(--row-sel); }
.back-btn .ic { width: 16px; height: 16px; stroke-width: 1.7; }
.pane-view > .group-label { margin-bottom: -8px; }
/* a private room's people (§44), the admin's list of them, and the dialog's checkbox */
.private-rooms-list { margin: 0; padding-left: 18px; display: flex; flex-direction: column; gap: 4px; font-size: calc(13px * var(--text-scale)); }
.room-people { display: flex; flex-direction: column; gap: 8px; }
.person-row { display: flex; align-items: center; gap: 8px; padding: 4px 6px; min-width: 0; }
.person-row .p-names { flex: 1; min-width: 0; }  /* the real name and @username, together (#563) */
/* a person with a page open now, and one without (#354): the dot the agents' rows use, smaller */
.p-dot { flex: 0 0 auto; width: 8px; height: 8px; margin: 0 3px; border-radius: 50%; }
.p-dot.on { background: var(--green); }
.p-dot.off { box-shadow: inset 0 0 0 1.5px var(--muted); }
.p-you { color: var(--muted-2); font-size: calc(11.5px * var(--text-scale)); }
#room-people-more { align-self: flex-start; margin-left: 6px; }
.btn-ghost-sm { height: 26px; padding: 0 10px; font-size: calc(12px * var(--text-scale)); }
.invite-btn { align-self: flex-start; margin: 2px 6px 0; }
.app-dialog .check-row { display: flex; align-items: center; gap: 8px; font-weight: 500; }
.group-label { padding: 0 6px; font-size: calc(11.5px * var(--text-scale)); font-weight: 600; color: var(--muted); }
.sheet-grip { display: block; flex-shrink: 0; align-self: center; width: 36px; height: 5px; margin-top: 7px; border-radius: 3px; background: var(--quote-rule); }

.member-list { display: flex; flex-direction: column; gap: 2px; margin: 0; padding: 0; list-style: none; }
.member {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  width: 100%;
  padding: 8px 6px;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--fg);
  text-align: left;
}
.member:not(.me) { cursor: pointer; }
.member:not(.me):hover, .member[aria-current="true"] { background: var(--row-sel); }
.m-open { display: inline-flex; align-items: center; flex-wrap: wrap; gap: 4px; padding: 0; border: 0; background: none; color: inherit; text-align: left; cursor: pointer; }
.m-open:hover .m-name { text-decoration: underline; text-underline-offset: 2px; }
.member > .avatar { margin-top: 1px; }
.m-main { display: flex; flex-direction: column; gap: 3px; flex: 1; min-width: 0; }
.m-name-line { position: relative; display: flex; align-items: center; flex-wrap: wrap; gap: 4px 6px; min-width: 0; }
.m-name { font-size: calc(13.5px * var(--text-scale)); font-weight: 600; overflow-wrap: anywhere; }
/* the part of a mention-popover row's name that matched what was typed (issue #112) */
.m-name-hit { background: var(--mention-bg); color: var(--mention-fg); border-radius: 3px; padding: 0 1px; }
.m-status { font-size: calc(12px * var(--text-scale)); color: var(--muted-2); }
.m-owner, .insp-owner { font-size: calc(12px * var(--text-scale)); color: var(--muted-2); overflow-wrap: anywhere; }
.m-owner strong, .insp-owner strong { font-weight: 600; color: var(--muted); }
.m-work { font-size: calc(12px * var(--text-scale)); overflow-wrap: anywhere; }
.m-claim-entry { font-size: calc(12px * var(--text-scale)); color: var(--accent); overflow-wrap: anywhere; }
.m-work-stale { margin-left: 7px; color: var(--muted-2); font-size: calc(11px * var(--text-scale)); }
.m-chips { display: flex; align-items: center; flex-wrap: wrap; gap: 4px 6px; font-size: calc(12px * var(--text-scale)); color: var(--muted-2); }
.m-chips .tier, .insp-chips .tier { max-width: 100%; white-space: normal; overflow-wrap: anywhere; }
.m-warn { font-size: calc(12px * var(--text-scale)); font-weight: 500; color: var(--danger); line-height: 1.35; }
.m-away { font-size: calc(12px * var(--text-scale)); font-style: italic; color: var(--muted-2); }
.m-parked {
  display: block;
  margin-top: 2px;
  padding: 7px 9px;
  border-radius: 7px;
  background: var(--amber-bg);
  color: var(--amber-fg);
  font-size: calc(12px * var(--text-scale));
  line-height: 1.35;
}
.m-parked .ic { width: 13px; height: 13px; margin-right: 5px; vertical-align: -2px; color: inherit; }
.m-parked strong { font-weight: 600; }
.m-chev { align-self: center; width: 14px; height: 14px; color: var(--muted); }
.member-empty { padding: 8px 6px; font-size: calc(12.5px * var(--text-scale)); color: var(--muted); }

/* Corner status dot on an avatar (spec 1.4 table). The 2 px ring matches the pane. */
.avatar .dot {
  position: absolute;
  right: -3px;
  bottom: -3px;
  width: 10px;
  height: 10px;
  border: 2px solid var(--pane-bg);
  background: var(--green);
}
.avatar.lg .dot { width: 13px; height: 13px; }
.dot.s-idle, .dot.s-human { background: var(--green); }
.dot.s-busy { background: var(--busy); }
.dot.s-waiting-approval { background: var(--pane-bg); box-shadow: inset 0 0 0 2px var(--busy); }
.dot.s-starting { background: var(--pane-bg); border-style: dashed; border-color: var(--muted); }
.dot.s-offline { background: var(--pane-bg); box-shadow: inset 0 0 0 1.5px var(--muted); }
.member-list.stale { opacity: 0.55; }
.dot.s-parked { background: var(--pane-bg); border-color: var(--parked); box-shadow: 0 0 0 2px var(--pane-bg); }

/* ==== 11. Inspector (spec 1.5) ======================================================= */
.insp-body {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 16px;
  margin: -14px -12px -14px;          /* the view's gap and padding move inside the scroller */
  padding: 14px 12px 14px;
  overflow-y: auto;
}
.insp-body h3, .insp-body .group-label { margin: 0; padding: 0; font-size: calc(12px * var(--text-scale)); font-weight: 600; color: var(--muted); }

.insp-id {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);  /* 40 px, or 48 for a named avatar */
  column-gap: 12px;
  row-gap: 0;
  align-items: center;
}
.insp-id > .avatar { grid-row: 1; align-self: center; }
.insp-id > :not(.avatar) { grid-column: 2; }
/* tier, host and Held chips span the pane under the avatar (InspectorStates.dc), so they rarely wrap */
.insp-id > .insp-chips { grid-column: 1 / -1; margin-top: 10px; }
.insp-id > .insp-tier-how { grid-column: 1 / -1; margin: 6px 0 0; color: var(--muted-2); font-size: calc(12px * var(--text-scale)); }
#insp-name, .insp-id h2 {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  font-size: calc(16px * var(--text-scale));
  font-weight: 600;
  letter-spacing: -.01em;
  overflow-wrap: anywhere;
}
.insp-id h2:focus { outline: none; }
.insp-id h2 .flag-approvals .ic { width: 15px; height: 15px; }
.insp-status { margin-top: 1px; font-size: calc(12.5px * var(--text-scale)); color: var(--muted-2); }
.insp-owner { margin: 1px 0 0; font-size: calc(12.5px * var(--text-scale)); }
.insp-chips { display: flex; flex-wrap: wrap; gap: 4px; }
.insp-chips .host-chip, .insp-chips .chip-held, .insp-chips .chip-quiet { padding: 0 6px; }  /* tier + host + Held + quiet fit in 264 px */
.group-label .group-count { font-weight: 400; }     /* "Delivery · last 5": the count is lighter */

.insp-attn, .insp-details, .insp-timeline { display: flex; flex-direction: column; gap: 8px; }

.note {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin: 0;
  padding: 9px 11px;
  border-radius: 8px;
  font-size: calc(12.5px * var(--text-scale));
  line-height: 1.4;
}
.note:has(> .ic) { display: grid; grid-template-columns: auto minmax(0, 1fr); column-gap: 8px; row-gap: 4px; }
.note:has(> .ic) > .ic { grid-row: 1; grid-column: 1; width: 14px; height: 14px; margin-top: 2px; }
.note:has(> .ic) > :not(.ic) { grid-column: 2; }
.note strong { font-weight: 600; }
.note > div > strong:first-child { display: block; }   /* the note's title on its own line */
.note p { margin-top: 4px; }
.note code {
  padding: 1px 5px;
  border: 1px solid var(--code-border);
  border-radius: 5px;
  background: var(--bg);
  color: var(--fg);
  font-size: calc(11.5px * var(--text-scale));
  overflow-wrap: anywhere;
}
/* Parked note (InspectorStates.dc #1): "Poke it" sits under a hairline; the command is one line
   in a box with its copy button, ellipsized when long (the title and the copy carry the full text). */
.note .poke { margin-top: 8px; padding-top: 8px; border-top: 1px solid color-mix(in srgb, currentColor 22%, transparent); }
.poke-cmd {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 6px;
  padding: 4px 4px 4px 9px;
  border: 1px solid var(--code-border);
  border-radius: 6px;
  background: var(--bg);
}
.note .poke-cmd code {
  flex: 1;
  min-width: 0;
  padding: 0;
  border: 0;
  background: none;
  font-size: calc(12px * var(--text-scale));
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.poke-cmd .copy-btn { flex-shrink: 0; color: var(--muted-2); }
.note-danger { background: var(--danger-bg); color: var(--danger); }
.note-amber { background: var(--amber-bg); color: var(--amber-fg); }
.note-muted { background: var(--chip-bg); color: var(--ink-2); }

.insp-facts {
  display: grid;
  grid-template-columns: 78px minmax(0, 1fr);
  margin: 0;
  font-size: calc(12.5px * var(--text-scale));
}
.insp-facts dt, .insp-facts dd { margin: 0; padding: 7px 0; border-bottom: 1px solid var(--line); }
.insp-facts dt { display: flex; align-items: center; color: var(--muted-2); }  /* level with a dd that holds a button */
.insp-facts dd { display: flex; align-items: center; gap: 6px; min-width: 0; }
.insp-facts dd > span:has(> .sess) { display: flex; align-items: center; gap: 6px; flex: 1; min-width: 0; }
.insp-facts > dt:nth-last-of-type(1), .insp-facts > dd:nth-last-of-type(1) { border-bottom: 0; }
.insp-facts > :not(dt):not(dd) { grid-column: 1 / -1; }
.sess { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font: calc(12px * var(--text-scale)) var(--mono); color: var(--fg); }
.copy-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  flex-shrink: 0;
  margin-left: auto;
  padding: 0;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: var(--muted-2);
  cursor: pointer;
}
.copy-btn:hover { background: var(--row-sel); color: var(--fg); }
.copy-btn .ic { width: 14px; height: 14px; }
/* a copy the browser refused (#224): the warning icon, in amber, with the text selected */
.copy-btn.copy-failed, #copy-join.copy-failed { color: var(--amber-ink); }
.queue-toggle {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--fg);
  cursor: pointer;
}
.queue-toggle .ic { width: 12px; height: 12px; transition: transform 150ms; }
.queue-toggle.open .ic, .queue-toggle[aria-expanded="true"] .ic { transform: rotate(180deg); }
.insp-queue { display: flex; flex-direction: column; gap: 3px; margin: 6px 0 0; padding: 0; list-style: none; }
.insp-queue li {
  display: grid;
  grid-template-columns: 36px auto minmax(0, 1fr);
  column-gap: 6px;
  align-items: baseline;
  padding: 5px 8px;
  border-radius: 6px;
  background: var(--chip-bg);
  font-size: calc(12px * var(--text-scale));
}
.insp-queue time { color: var(--muted); font-variant-numeric: tabular-nums; }
.q-from { font-weight: 600; white-space: nowrap; }
.q-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--muted-2); }

/* Delivery timeline: time | dot on a vertical rule | label + detail. */
.timeline { display: flex; flex-direction: column; margin: 0; padding: 0; list-style: none; }
.tl {
  display: grid;
  grid-template-columns: 36px 12px minmax(0, 1fr);
  column-gap: 8px;
  padding: 3px 0;
  font-size: calc(12px * var(--text-scale));
  line-height: 1.4;
}
.tl time { color: var(--muted); font-variant-numeric: tabular-nums; }
.tl-dot { position: relative; display: flex; justify-content: center; align-self: stretch; }
.tl-dot::before {
  content: "";
  position: absolute;
  top: -3px;
  bottom: -3px;
  left: 50%;
  width: 1px;
  margin-left: -.5px;
  background: var(--side-border);
}
.tl:first-child .tl-dot::before { top: 9px; }
.tl:last-child .tl-dot::before { bottom: calc(100% - 9px); }
.tl-dot::after {
  content: "";
  position: relative;
  z-index: 1;
  width: 9px;
  height: 9px;
  margin-top: 4px;
  border: 1.5px solid var(--muted);
  border-radius: 50%;
  background: var(--pane-bg);
}
.tl-turn .tl-dot::after { border-color: var(--accent); background: var(--accent); }
.tl-said .tl-dot::after { border-color: var(--fg); background: var(--fg); border-radius: 2px; }
.tl-steer .tl-dot::after { border: 2px solid var(--busy); }
.tl-parked .tl-dot::after { border: 2px solid var(--parked); }
.tl-other .tl-dot::after { border-color: var(--muted); }
.tl-text { min-width: 0; color: var(--muted-2); }
.tl-text strong { font-weight: 600; color: var(--fg); }
.tl-parked .tl-text strong { color: var(--amber-ink); }

.insp-actions {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  margin-top: auto;
  padding-top: 12px;
  border-top: 1px solid var(--line);
}
.insp-actions > :not(.btn) { grid-column: 1 / -1; }
.insp-actions > div:not(.menu):not(.confirm):not(.note) { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.insp-actions .btn { width: 100%; min-width: 0; height: 34px; padding: 0 10px; }
.insp-actions .btn[aria-pressed="true"] { background: var(--btn-on); }
/* "Catch up on…" carries two icons in half of 264 px: tighter gap and a smaller chevron keep the
   chevron off the border (Chosen.dc) */
.insp-actions .btn[aria-haspopup="menu"] { gap: 5px; padding: 0 8px; }
.insp-actions .btn[aria-haspopup="menu"] .ic-chev-down { width: 12px; height: 12px; }
.insp-actions .btn-danger-ghost { justify-content: flex-start; padding: 0 8px; font-weight: 500; }
.insp-actions > .fine { margin: 0; }

.menu {
  position: absolute;
  left: 0;
  right: 0;
  bottom: calc(100% + 6px);
  z-index: 5;
  display: flex;
  flex-direction: column;
  max-height: 60vh;
  padding: 5px;
  overflow-y: auto;
  border: 1px solid var(--menu-border);
  border-radius: 11px;
  background: var(--menu-bg);
  box-shadow: var(--menu-shadow);
}
.menu > :first-child:not(.menu-item) { padding: 6px 8px 4px; font-size: calc(12px * var(--text-scale)); font-weight: 600; color: var(--muted); }
.menu-item {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1px;
  width: 100%;
  padding: 6px 8px;
  border: 0;
  border-radius: 7px;
  background: transparent;
  color: var(--fg);
  font-size: calc(13px * var(--text-scale));
  text-align: left;
  cursor: pointer;
}
.menu-item:hover, .menu-item:focus-visible { background: var(--accent-tint); }
.menu-item code { font-size: calc(11px * var(--text-scale)); color: var(--muted); overflow-wrap: anywhere; }
.menu .note-danger { margin: 4px; padding: 7px 9px; font-size: calc(12px * var(--text-scale)); }

.confirm {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
  padding: 10px 12px;
  border-radius: 8px;
  background: var(--danger-bg);
  color: var(--danger);
  font-size: calc(12.5px * var(--text-scale));
}
.confirm > :not(button) { flex-basis: 100%; }
.confirm > div { display: flex; justify-content: flex-end; gap: 8px; }
.confirm .btn, .confirm .btn-danger { height: 30px; }

/* ==== 12. Sheets (Closed rooms, People, Settings) ===================================== */
.sheet {
  position: fixed;
  top: 64px;
  left: 50%;
  z-index: 40;
  display: flex;
  flex-direction: column;
  width: min(560px, calc(100vw - 32px));
  max-height: calc(100vh - 96px);
  transform: translateX(-50%);
  border: 1px solid var(--menu-border);
  border-radius: 11px;
  background: var(--menu-bg);
  box-shadow: var(--menu-shadow);
}
.sheet-head {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
  padding: 10px 10px 10px 18px;
  border-bottom: 1px solid var(--line);
}
.sheet-head h2 { flex: 1; font-size: calc(14px * var(--text-scale)); font-weight: 600; }
.sheet-body { display: flex; flex-direction: column; gap: 10px; padding: 12px 18px 18px; overflow-y: auto; }
.sheet-body > .fine { margin: 0; }
.sheet-body code { font-size: calc(12px * var(--text-scale)); }

.closed-card {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 0 0 10px;
  padding: 12px 14px;
  border: 1px solid var(--side-border);
  border-radius: 8px;
  background: var(--bg);
}
.card-head, .closed-head { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 8px; }
.card-head .ic { width: 15px; height: 15px; color: var(--muted); }
.closed-name { flex: 0 1 auto; font-size: calc(14px * var(--text-scale)); font-weight: 600; }
.card-error, .closed-result.bad { color: var(--danger); font-weight: 500; }
.closed-card .fine code { overflow-wrap: anywhere; }
.closed-delete { display: flex; flex-direction: column; gap: 6px; padding-top: 10px; border-top: 1px solid var(--line); }
.closed-card .closed-delete .cmd-block {
  display: block;
  padding: 7px 10px;
  border: 1px solid var(--code-border);
  border-radius: 6px;
  background: var(--pre-bg);
  color: var(--fg);
  font: calc(12px * var(--text-scale))/1.5 var(--mono);
  overflow-wrap: anywhere;
}
.dialog-buttons { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 0; }
.closed-card .dialog-buttons .btn:not(:disabled) { border-color: transparent; background: var(--accent); color: var(--accent-fg); }

/* ==== 13. First run (spec 1.8) ======================================================= */
/* With no open room there is nobody to list and nowhere to send: Welcome.dc shows only the steps,
   under a "Get started" title. app.js sets .no-rooms on #app. */
.app.no-rooms #pane, .app.no-rooms #composer, .app.no-rooms #pane-toggle, .app.no-rooms #buddy-toggle,
.app.no-rooms .head-divider, .app.no-rooms .head-hash, .app.no-rooms #scrim { display: none; }
.welcome {
  position: absolute;
  inset: 0;
  z-index: 3;
  overflow-y: auto;
  padding: 40px 48px 48px;
  background: var(--bg);
}
.welcome-inner {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 340px;   /* Welcome.dc: ~690 px of steps, a 340 px harness column */
  gap: 44px;
  max-width: 1080px;
  margin: 0 auto;
}
.welcome-title { font-size: calc(24px * var(--text-scale)); font-weight: 650; letter-spacing: -.02em; line-height: 1.25; }
.welcome-lead { max-width: 560px; margin-top: 6px; font-size: calc(14.5px * var(--text-scale)); color: var(--muted-2); }
.steps { display: flex; flex-direction: column; gap: 12px; margin: 22px 0 0; padding: 0; list-style: none; }
.step {
  display: grid;
  grid-template-columns: 24px minmax(0, 1fr);
  column-gap: 14px;
  padding: 16px 20px;
  border: 1px solid var(--side-border);
  border-radius: 12px;
  background: var(--bg);
}
.step-num {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--accent);
  color: #ffffff;
  font-size: calc(12px * var(--text-scale));
  font-weight: 600;
}
.step-body { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.step-title { font-size: calc(15px * var(--text-scale)); font-weight: 600; line-height: calc(24px * var(--text-scale)); }
.step-body .fine { font-size: calc(12.5px * var(--text-scale)); color: var(--muted-2); }
.step-body code { padding: 0 4px; border: 1px solid var(--code-border); border-radius: 4px; background: var(--code-bg); font-size: calc(12px * var(--text-scale)); }
.create-form { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 10px; }
.create-form label { font-size: calc(13px * var(--text-scale)); font-weight: 600; }
.input-affix {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  height: 32px;
  padding: 0 10px;
  border: 1px solid var(--input-border);
  border-radius: 7px;
  background: var(--input-bg);
}
.input-affix:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px var(--focus); }
.input-affix > span { color: var(--muted); font-weight: 600; }
.input-affix input {
  width: 160px;
  min-width: 0;
  padding: 0;
  border: 0;
  outline: none;
  background: transparent;
  color: var(--fg);
  font-size: calc(13.5px * var(--text-scale));
}
.join-box {
  padding: 12px 14px;
  border: 1px solid var(--code-border);
  border-radius: 8px;
  background: var(--pre-bg);
  overflow-x: auto;
}
.join-box code, .step-body .join-box code { padding: 0; border: 0; background: none; font-size: calc(15px * var(--text-scale)); white-space: nowrap; }

.welcome-side { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.side-title { font-size: calc(14px * var(--text-scale)); font-weight: 600; }
.welcome-side > .fine { font-size: calc(12.5px * var(--text-scale)); color: var(--muted-2); }
.harness-card {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 12px 14px;
  border: 1px solid var(--side-border);
  border-radius: 10px;
  background: var(--bg);
  font-size: calc(12.5px * var(--text-scale));
}
.harness-head { display: flex; align-items: center; gap: 8px; }
.harness-head strong { font-size: calc(13.5px * var(--text-scale)); font-weight: 600; }
.harness-head .avatar.mini { width: 22px; height: 22px; border-radius: 5px; font-size: calc(9px * var(--text-scale)); }
.harness-head .tier { margin-left: auto; border: 0; background: none; padding: 0; color: var(--muted-2); }
.harness-card ol { display: flex; flex-direction: column; gap: 4px; margin: 0; padding-left: 18px; }
.harness-card code { font-size: calc(11.5px * var(--text-scale)); }
.harness-card code.block {
  display: block;
  margin-top: 6px;
  padding: 6px 10px;
  border: 1px solid var(--code-border);
  border-radius: 6px;
  background: var(--pre-bg);
  /* wraps rather than scrolls: a clipped command (no visible scrollbar) would be copied wrong */
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* ==== 14. Login page (login.html) ==================================================== */
body.login {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100%;
  padding: 24px 16px;
  background: var(--side-bg);
}
.login-card {
  display: flex;
  flex-direction: column;
  gap: 12px;
  width: min(440px, 100%);
  padding: 22px 24px 20px;
  border: 1px solid var(--menu-border);
  border-radius: 12px;
  background: var(--bg);
  box-shadow: var(--menu-shadow);
}
.login-card .brand { padding: 0; margin-bottom: 4px; }
.login-card h1 { font-size: calc(18px * var(--text-scale)); font-weight: 650; letter-spacing: -.01em; }
.login-card p { color: var(--ink-2); }
.login-cmd {
  margin: 0;
  padding: 10px 14px;
  border: 1px solid var(--code-border);
  border-radius: 8px;
  background: var(--pre-bg);
  font: calc(14px * var(--text-scale))/1.4 var(--mono);
  overflow-x: auto;
}
.login-card .fine code {
  padding: 0 4px;
  border: 1px solid var(--code-border);
  border-radius: 4px;
  background: var(--code-bg);
}
/* the sign-in page's variants (login.html: the terminal, a passkey, the claim), spaced like the card */
.login-variant { display: flex; flex-direction: column; gap: 12px; }
.login-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 4px; }
.login-actions .btn, .login-actions .btn-primary { height: 34px; padding: 0 16px; font-size: calc(13.5px * var(--text-scale)); }
/* the passkey pages' actions span the card: one button its full width, two sharing it evenly */
.login-actions.stretch > * { flex: 1 1 0; min-width: 0; }
.login-error { margin: 0; color: var(--danger); font-weight: 500; }
.login-error:empty { display: none; }
/* the consent page (oauth.html, §49.9): who is signing in, what the agent calls itself, where it answers */
.consent-facts {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin: 0;
  padding: 10px 12px;
  border: 1px solid var(--side-border);
  border-radius: 8px;
  background: var(--side-bg);
  font-size: calc(13px * var(--text-scale));
}
.consent-facts > div { display: flex; gap: 10px; align-items: baseline; }
.consent-facts dt { flex: 0 0 9.5em; color: var(--muted); }
.consent-facts dd { margin: 0; min-width: 0; overflow-wrap: anywhere; font-weight: 600; color: var(--fg); }
.consent-confirm { display: flex; flex-direction: column; gap: 8px; }
.consent-confirm .btn { height: 34px; font-size: calc(13.5px * var(--text-scale)); }
@media (max-width: 480px) {
  .consent-facts > div { flex-direction: column; gap: 0; }
  .consent-facts dt { flex: none; }
}
/* the claim page (setup.html, §31.3): one step at a time, a name for the passkey */
.setup-step { display: flex; flex-direction: column; gap: 12px; }
.setup-step h1:focus { outline: none; }
.setup-form { display: flex; flex-direction: column; gap: 8px; }
.setup-form label, .passkey-add label, .info-add label { font-size: calc(13px * var(--text-scale)); font-weight: 600; }
.setup-form input, .passkey-add input, .info-add input {
  height: 34px;
  padding: 0 10px;
  border: 1px solid var(--input-border);
  border-radius: 7px;
  background: var(--input-bg);
  color: var(--fg);
  font-size: calc(13.5px * var(--text-scale));
}
.setup-form input:focus, .passkey-add input:focus, .info-add input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--focus); }
.passkey-add input { height: 32px; }
/* the Passkeys sheet (index.html, §31.4) */
.passkey-card {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 12px 14px;
  border: 1px solid var(--side-border);
  border-radius: 8px;
  background: var(--bg);
}
.passkey-card + .passkey-card { margin-top: 10px; }
.passkey-card > p { margin: 0; }
.passkey-head { display: flex; align-items: center; gap: 8px; }
.passkey-head .ic { width: 15px; height: 15px; color: var(--muted); flex-shrink: 0; }
.passkey-title { flex: 1; min-width: 0; font-size: calc(14px * var(--text-scale)); font-weight: 600; }
.passkey-count, .password-state { flex-shrink: 0; font-size: calc(11.5px * var(--text-scale)); color: var(--muted-2); }
.passkey-add { display: flex; flex-direction: column; gap: 6px; margin: 0; }
.passkey-row { display: flex; align-items: center; gap: 8px; }
.passkey-row input { flex: 1; min-width: 0; height: 32px; }
.passkey-row .btn-primary { flex-shrink: 0; }
.passkey-result.bad { color: var(--danger); font-weight: 500; }
.passkey-result:empty { display: none; }
/* Settings → Agents (§49.1): a person's agent tokens, one row per device, in the passkey cards */
.agent-tokens { display: flex; flex-direction: column; margin: 0; padding: 0; list-style: none; }
.agent-token { display: flex; align-items: center; gap: 8px; padding: 8px 0; border-top: 1px solid var(--side-border); }
.agent-token:first-child { border-top: 0; padding-top: 2px; }
.agent-token-main { display: flex; flex: 1; flex-direction: column; gap: 2px; min-width: 0; }
.agent-token-device { font: 600 calc(13px * var(--text-scale)) var(--mono); overflow-wrap: anywhere; }
.agent-token-meta { font-size: calc(11.5px * var(--text-scale)); color: var(--muted-2); }
.agent-token .btn { flex-shrink: 0; }
.agent-token-new { border-color: var(--accent); }
.agent-token-show { display: flex; align-items: center; gap: 8px; }
.agent-token-value {
  white-space: pre-wrap;
  flex: 1;
  min-width: 0;
  padding: 6px 8px;
  border: 1px solid var(--input-border);
  border-radius: 7px;
  background: var(--input-bg);
  font: calc(12px * var(--text-scale)) var(--mono);
  overflow-wrap: anywhere;
  user-select: all;
}
.agent-token-show .btn { flex-shrink: 0; }
.agent-connect { display: flex; flex-direction: column; gap: 8px; margin-top: 4px; padding-top: 10px; border-top: 1px solid var(--side-border); }
.agent-connect-title { margin: 0; font-size: calc(13px * var(--text-scale)); font-weight: 600; }
.agent-connect-step { display: flex; flex-direction: column; gap: 6px; }
.agent-connect-step > p { margin: 0; font-size: calc(12.5px * var(--text-scale)); color: var(--muted); }
/* Cards in the People and Settings sheets: the same as the Passkeys sheet's. */
.info-card {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 12px 14px;
  border: 1px solid var(--side-border);
  border-radius: 8px;
  background: var(--bg);
}
.info-card + .info-card { margin-top: 10px; }
.info-card:focus { outline: none; }
.info-card:focus-visible { box-shadow: 0 0 0 3px var(--focus); }
.info-card > p { margin: 0; }
.info-card .card-head { flex-wrap: nowrap; gap: 8px; }
.info-card .card-head .ic { flex-shrink: 0; }
.info-card .card-name { flex: 1; min-width: 0; overflow-wrap: anywhere; font-size: calc(14px * var(--text-scale)); font-weight: 600; }
.info-card .dialog-buttons .btn, .info-card .dialog-buttons .btn-primary { min-width: 88px; }
.info-add { display: flex; flex-direction: column; gap: 6px; margin: 0; }
.info-row { display: flex; align-items: center; gap: 8px; }
/* the username beside a person's real name (#563, §39.6); People cards use the same class */
.m-full, .person-handle { color: var(--muted); font-size: calc(12.5px * var(--text-scale)); margin-left: 6px; overflow-wrap: anywhere; }
/* Add someone (#192): first and last name side by side, the email, then the name in the rooms */
.person-names { display: flex; gap: 8px; }
.person-field { display: flex; flex: 1 1 0; min-width: 0; flex-direction: column; gap: 6px; }
@media (max-width: 420px) { .person-names { flex-direction: column; } }
.info-row input { flex: 1; min-width: 0; height: 32px; }
.info-row .btn-primary { flex-shrink: 0; }
.info-step { margin: 0; font-size: calc(12.5px * var(--text-scale)); color: var(--muted-2); }
.info-step b { color: var(--fg); font-weight: 600; }
.info-cmd {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 36px;
  padding: 4px 5px 4px 10px;
  border: 1px solid var(--code-border);
  border-radius: 6px;
  background: var(--pre-bg);
}
.sheet-body .info-cmd code {
  flex: 1;
  min-width: 0;
  padding: 0;
  border: 0;
  background: none;
  color: var(--fg);
  font: calc(12px * var(--text-scale))/1.5 var(--mono);
  overflow-wrap: anywhere;
}
.info-cmd .copy-btn { margin-left: 0; }
.info-result.bad, .email-result.bad, .name-result.bad, .names-result.bad { color: var(--danger); font-weight: 500; }
.info-result:empty { display: none; }

/* ==== 15. Narrow widths (spec 1.9) =================================================== */

/* 761–1100 px: the right pane is an overlay drawer, closed until #app has .sheet-open. */
@media (max-width: 1100px) {
  .room-sub { display: none; }
  .pane {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    z-index: 20;
    box-shadow: -8px 0 30px rgba(0, 0, 0, .14);
    transform: translateX(100%);
    visibility: hidden;
    transition: transform 260ms var(--ease), visibility 0s linear 260ms;
  }
  .app.sheet-open .pane {
    transform: none;
    visibility: visible;
    transition: transform 260ms var(--ease), visibility 0s linear 0s;
  }
  .welcome { padding: 32px 28px 40px; }
  .welcome-inner { grid-template-columns: minmax(0, 1fr); }
}

/* 760 px and narrower: sidebar drawer, two-row header, pane as a bottom sheet. */
@media (max-width: 760px) {
  .sidebar {
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    z-index: 25;
    width: min(300px, 85vw);
    padding-top: max(12px, env(safe-area-inset-top));
    box-shadow: 8px 0 30px rgba(0, 0, 0, .14);
    transform: translateX(-100%);
    visibility: hidden;
    transition: transform 260ms var(--ease), visibility 0s linear 260ms;
  }
  .app.nav-open .sidebar {
    transform: none;
    visibility: visible;
    transition: transform 260ms var(--ease), visibility 0s linear 0s;
  }
  .room { height: 40px; font-size: calc(14.5px * var(--text-scale)); }

  .conv-head {
    display: grid;
    /* The side columns are as wide as Rooms and the members pill need, and the title has the
       rest (#333). Three equal columns gave it a third of the phone, about 125 px, and cut a
       15-letter room name that would have fit. The title is centred between the two buttons,
       so it sits a few pixels off the screen's centre when they differ in width. */
    grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-areas: "nav title members" "chips chips chips" "tools tools tools";
    align-items: center;
    height: auto;
    gap: 0;
    padding: 0 8px;
    padding-top: env(safe-area-inset-top);
    border-bottom: 1px solid var(--code-border);
    background: var(--head-2-bg);
  }
  .rooms-toggle { grid-area: nav; justify-self: start; }
  .head-title {
    grid-area: title;
    width: 100%;
    overflow: hidden;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    column-gap: 1px;
    row-gap: 0;
    min-height: 52px;
    padding: 6px 0;
    line-height: 1.2;
  }
  .head-hash { width: 13px; height: 13px; flex: 0 0 auto; }
  .head-title h1 { flex: 1 1 0; min-width: 0; max-width: 100%; font-size: calc(16px * var(--text-scale)); }
  .room-sub { display: block; flex-basis: 100%; margin: 0; font-size: calc(11.5px * var(--text-scale)); color: var(--muted-2); text-align: center; }
  .members-pill { grid-area: members; justify-self: end; }
  .conv-head .head-spacer, .head-divider, #pane-toggle, #pause-toggle { display: none; }
  .chips { grid-area: chips; height: 38px; margin: 0 -8px; padding: 0 12px; white-space: nowrap; }
  .head-tools { grid-area: tools; display: flex; align-items: center; gap: 4px; padding: 0 4px 6px; }
  .chip .meter { display: none; }
  #st-approvals::after { content: attr(data-count); }

  .band { padding: 8px 14px; }
  .pins-toggle { padding: 4px 14px; }
  .pins-list { padding: 0 10px 8px 14px; }
  .claim-board-toggle { padding: 4px 14px; }
  .claim-board-list { padding: 0 10px 8px 14px; }
  .msg-pin { width: 32px; height: 32px; }
  .log { padding: 0 14px 12px; }
  .line.k-chat,
  .line.k-join,
  .line.k-leave,
  .line.k-notice,
  .line.local { grid-template-columns: 28px minmax(0, 1fr); column-gap: 8px; }
  .reply-to { grid-template-columns: 28px auto auto minmax(0, 1fr); }
  .log .avatar:not(.mini) { width: 28px; height: 28px; border-radius: 7px; font-size: calc(10.5px * var(--text-scale)); }
  .log .avatar.human:not(.mini) { border-radius: 50%; font-size: calc(12px * var(--text-scale)); }
  .md-code { font-size: calc(12.5px * var(--text-scale)); }
  .md-url { display: block; margin-left: 0; }

  /* Composer: a flex row with the textarea as the box and a round send button. */
  .composer {
    display: flex;
    align-items: flex-end;
    gap: 8px;
    padding: 8px 10px max(26px, env(safe-area-inset-bottom));
    border-top: 1px solid var(--side-border);
    background: var(--side-bg);
  }
  .composer-box { display: contents; }
  /* composer-box's own box is gone, so the chrome it drew (border, pill shape, background) moves
     to .input-wrap, now the direct flex child -- but not its padding: #input keeps the same
     padding here it always had (so field-sizing: content, in Chromium, measures the exact box
     it always measured; an #input padded by its *parent* instead rounded its grown height a
     device pixel short of its own scrollHeight at this width, enough to auto-scroll by 1px and
     hide the first line). The mirror needs that padding too, to land on the same text. */
  .input-wrap {
    flex: 1;
    min-width: 0;
    min-height: 58px;                /* two lines, as in the phone mockup */
    border: 1px solid var(--input-border);
    border-radius: 14px;
    background: var(--input-bg);
  }
  .input-wrap:focus-within { box-shadow: 0 0 0 3px var(--focus); }
  #input-mirror, #input {
    padding: 8px 12px;
    font-size: max(16px, calc(16px * var(--text-scale))); /* 16 px stops iOS zooming into the field */
    line-height: calc(20px * var(--text-scale));
  }
  /* 8 lines and the padding: max-height is border-box, so the desktop's 168px held 7.6 lines
     here, and an 8th scrolled the box and hid the top of the first. */
  #input { max-height: calc(160px * var(--text-scale) + 16px); }
  .composer-bar { flex-shrink: 0; }
  #mention-btn, #cmd-btn, .composer-spacer, .composer-hint { display: none; }
  #send { width: 40px; height: 40px; margin-bottom: 9px; padding: 0; border-radius: 50%; }
  #send .ic { width: 17px; height: 17px; }
  #send .send-label {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
  }
  .palette { left: 10px; right: 10px; }
  .pal-item { grid-template-columns: max-content minmax(0, 1fr) auto; }
  .pal-item > .pill { grid-column: 3; grid-row: 1; }
  .pal-desc { grid-column: 1 / -1; white-space: normal; }

  /* The right pane becomes a bottom sheet; #app.sheet-open shows it. */
  .pane {
    position: fixed;
    top: auto;
    left: 0;
    right: 0;
    bottom: 0;
    width: auto;
    height: min(85vh, 640px);
    max-height: 85vh;
    border-left: 0;
    border-radius: 14px 14px 0 0;
    box-shadow: 0 -8px 30px rgba(0, 0, 0, .14);
    transform: translateY(100%);
  }
  .pane-view { padding: 0 16px max(14px, env(safe-area-inset-bottom)); }
  .pane-head { height: 44px; margin: 0 -16px; padding: 0 16px; }
  .insp-head { padding: 0 12px 0 6px; }
  .back-btn { color: var(--link); font-size: calc(15px * var(--text-scale)); font-weight: 400; }
  .insp-body { margin: -14px -16px -14px; padding: 14px 16px 14px; }

  .sheet { top: max(16px, env(safe-area-inset-top)); max-height: calc(100vh - 32px); }
  .info-row, .passkey-row { flex-direction: column; align-items: stretch; }
  .info-row input, .passkey-row input { flex: 0 0 auto; height: 40px; }
  .info-row .btn-primary, .passkey-row .btn-primary { height: 40px; }

  .welcome { padding: 24px 16px 32px; }
  .welcome-title { font-size: calc(21px * var(--text-scale)); }
  .step { grid-template-columns: 24px minmax(0, 1fr); padding: 14px; column-gap: 10px; }
  .input-affix { flex: 1; }
  .input-affix input { width: 100%; }
  .join-box code, .step-body .join-box code { font-size: calc(13px * var(--text-scale)); }
}

/* ==== 16. Reduced motion ============================================================= */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    transition: none !important;
    animation: none !important;
    scroll-behavior: auto !important;
  }
}

/* ==== 14b. The three ways in (login.html, DESIGN.md §32.4) ============================= */
/* a password first; then "or" and the other two, a passkey and SSO (coming soon), full width */
.login-first {
  margin: 0;
  padding: 10px 12px;
  border: 1px solid var(--side-border);
  border-radius: 8px;
  background: var(--side-bg);
  font-size: calc(13px * var(--text-scale));
}
.login-first code, .setup-step .fine code {
  padding: 0 4px;
  border: 1px solid var(--code-border);
  border-radius: 4px;
  background: var(--code-bg);
}
.setup-form label + input + label { margin-top: 4px; }
.login-or {
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--muted);
  font-size: calc(12px * var(--text-scale));
}
.login-or::before, .login-or::after { content: ""; flex: 1 1 0; border-top: 1px solid var(--side-border); }
.login-alt { display: flex; flex-direction: column; gap: 8px; }
.login-alt .btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  height: 34px;
  padding: 0 16px;
  font-size: calc(13.5px * var(--text-scale));
}
.login-alt .btn .ic { width: 15px; height: 15px; flex: none; }
.login-alt .btn:disabled { opacity: 1; color: var(--muted); cursor: not-allowed; }
.login-alt .soon {
  padding: 1px 7px;
  border: 1px solid var(--side-border);
  border-radius: 999px;
  background: var(--side-bg);
  color: var(--muted);
  font-size: calc(11px * var(--text-scale));
  font-weight: 600;
  letter-spacing: .01em;
}

/* ==== 14c. People and passwords in the app (index.html, DESIGN.md §32) ================= */
/* the People sheet: wide, for the invite text on few lines */
#people-panel { width: min(640px, calc(100vw - 32px)); }
.person-card { min-width: 0; }
.person-card .card-head { align-items: center; flex-wrap: wrap; }
.person-card .avatar { flex: none; }
.person-card .person-chip { flex: none; }
.person-card .dialog-buttons { min-width: 0; max-width: 100%; }
.person-card .dialog-buttons .btn {
  white-space: normal; height: auto; min-height: 28px; max-width: 100%; text-align: center;
}
.person-chip { height: 22px; padding: 0 9px; border-radius: 11px; font-size: calc(11.5px * var(--text-scale)); font-weight: 600; }
.person-chip.pending { background: var(--amber-bg); color: var(--amber-fg); }
.person-chip.bad { background: var(--danger-bg); color: var(--danger); }
/* who can't sign in, having no email (#240): a note above Add someone, a name per button */
#no-email-note { margin-bottom: 10px; }
.no-email-list { display: flex; flex-wrap: wrap; gap: 6px; margin: 8px 0 0; padding: 0; list-style: none; }
.no-email-list .btn { max-width: 100%; height: auto; min-height: 26px; padding-block: 4px; white-space: normal; text-align: left; overflow-wrap: anywhere; }
.invite-card { border-color: var(--accent); }
.invite-card:focus { outline: none; }
.invite-card:focus-visible { box-shadow: 0 0 0 3px var(--focus); }
.sheet-body .invite-text code { white-space: pre-wrap; }
.invite-text { align-items: flex-start; }
.invite-text .copy-btn { margin-top: 2px; }
/* the Sign-in sheet's password form: two fields, the second with the button on its row */
#password-form label + input { margin-bottom: 4px; }
/* Confirm it's you (a password check before a change): a small modal card */
.dialog-spacer { flex: 1 1 auto; }
.confirm-dialog {
  width: min(380px, calc(100vw - 32px));
  padding: 20px 22px 18px;
  border: 1px solid var(--menu-border);
  border-radius: 12px;
  background: var(--bg);
  color: var(--fg);
  box-shadow: var(--menu-shadow);
}
.confirm-dialog::backdrop { background: rgba(0, 0, 0, .28); }
.confirm-dialog h2 { margin: 0 0 2px; font-size: calc(16px * var(--text-scale)); font-weight: 650; }
.confirm-dialog .setup-form { gap: 8px; }
.confirm-dialog .dialog-buttons { margin-top: 6px; flex-wrap: nowrap; }
.confirm-dialog .dialog-buttons .btn, .confirm-dialog .dialog-buttons .btn-primary { height: 32px; }

/* Action, notice and New room dialogs share the same native modal and page palette. */
.app-dialog {
  width: min(440px, calc(100vw - 32px));
  max-height: calc(100vh - 32px);
  padding: 0;
  border: 1px solid var(--menu-border);
  border-radius: 12px;
  background: var(--bg);
  color: var(--fg);
  box-shadow: var(--menu-shadow);
}
.app-dialog::backdrop { background: rgba(0, 0, 0, .42); }
.app-dialog-form { display: flex; flex-direction: column; gap: 12px; padding: 22px 24px 20px; }
/* a long URL or path in a title or body wraps instead of scrolling the dialog sideways (#246) */
.app-dialog h2 {
  margin: 0;
  font-size: calc(18px * var(--text-scale));
  line-height: 1.3;
  font-weight: 650;
  overflow-wrap: anywhere;
}
.app-dialog-body {
  margin: 0;
  color: var(--muted-2);
  font-size: calc(13px * var(--text-scale));
  line-height: 1.5;
  overflow-wrap: anywhere;
}
.app-dialog label { font-size: calc(12px * var(--text-scale)); font-weight: 600; }
.app-dialog input, .app-dialog select {
  height: 36px;
  padding: 0 10px;
  border: 1px solid var(--input-border);
  border-radius: 7px;
  background: var(--input-bg);
  color: var(--fg);
  font: calc(13px * var(--text-scale)) var(--font);
}
.app-dialog-error { min-height: 16px; margin: -6px 0 0; color: var(--danger); font-size: calc(12px * var(--text-scale)); }
.handoff-label { margin: 2px 0 -6px; font-size: calc(13px * var(--text-scale)); }
.handoff-summary { margin: 0; padding: 10px; border-radius: 7px; background: var(--side-bg); font: calc(12px * var(--text-scale)) / 1.5 var(--font); white-space: pre-wrap; overflow-wrap: anywhere; }
.handoff-comments { margin: 0; padding-left: 20px; font-size: calc(12px * var(--text-scale)); overflow-wrap: anywhere; }
.handoff-comments li + li { margin-top: 8px; }
.handoff-comments p { margin: 2px 0 0; }
.wake-warn, .fine.wake-warn { margin: -6px 0 0; color: var(--amber-ink); font-size: calc(12px * var(--text-scale)); }
.app-dialog-buttons { display: flex; justify-content: flex-end; gap: 8px; margin-top: 8px; }
.app-dialog .btn:disabled, .app-dialog .btn-primary:disabled, .app-dialog .btn-danger:disabled {
  opacity: .5;
  cursor: default;
}
/* The Settings sheet (#232): a fixed-size dialog with a header that never scrolls (closes
   #212's "Close scrolls away") above a desktop rail (a vertical WAI-ARIA tablist) beside the
   one scrolling panel, or a phone list with a page per group. See docs/DESIGN.md §34. */
.app-dialog-settings {
  width: min(860px, calc(100vw - 32px));
  height: min(720px, calc(100vh - 32px));
  overflow: hidden;
}
.app-dialog-form.settings-content { height: 100%; min-height: 0; padding: 0; gap: 0; }
.settings-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  flex-shrink: 0;
  padding: 14px 14px 14px 22px;
  border-bottom: 1px solid var(--line);
}
.settings-head h2 { font-size: calc(16px * var(--text-scale)); }
.settings-title-wrap { display: flex; align-items: center; gap: 2px; min-width: 0; }
.settings-back { flex-shrink: 0; }
.settings-body {
  display: grid;
  grid-template-columns: 220px 1fr;
  grid-template-rows: 1fr auto;
  flex: 1;
  min-height: 0;
}
.settings-rail {
  grid-column: 1;
  grid-row: 1;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 14px 10px;
  overflow-y: auto;
  border-right: 1px solid var(--line);
}
.settings-tab {
  display: flex;
  align-items: center;
  gap: 9px;
  height: 36px;
  flex-shrink: 0;
  padding: 0 10px;
  border: 0;
  border-radius: 7px;
  background: transparent;
  color: var(--fg);
  font: 600 calc(13px * var(--text-scale)) var(--font);
  text-align: left;
  cursor: pointer;
}
.settings-tab:hover { background: var(--row-sel); }
.settings-tab[aria-selected="true"] { background: var(--accent-tint); color: var(--link); }
.settings-foot {
  grid-column: 1;
  grid-row: 2;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
  padding: 12px 10px 16px;
  border-right: 1px solid var(--line);
}
.settings-version { margin: 0; }
.settings-panels { grid-column: 2; grid-row: 1 / span 2; min-height: 0; overflow: hidden; }
.settings-panel { display: flex; flex-direction: column; height: 100%; min-height: 0; }
.settings-panel-content { flex: 1; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 10px; padding: 20px 24px; }
.settings-savebar { display: flex; align-items: center; gap: 10px; flex-shrink: 0; border-top: 1px solid var(--line); padding: 12px 24px; }
.settings-savebar-dirty { color: var(--muted); font-size: calc(12px * var(--text-scale)); margin-right: auto; }
.settings-savebar [role="status"] { margin-right: auto; }
.settings-savebar-dirty:not(.hidden) + [role="status"] { margin-right: 0; }
.settings-savebar .btn, .settings-savebar .btn-primary { flex-shrink: 0; }
.settings-list { grid-column: 1 / span 2; grid-row: 1; overflow-y: auto; display: flex; flex-direction: column; }
.settings-row {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  min-height: 60px;
  padding: 0 20px;
  border: 0;
  border-top: 1px solid var(--line);
  background: transparent;
  color: var(--fg);
  text-align: left;
  cursor: pointer;
}
.settings-list .settings-row:first-child { border-top: 0; }
.settings-row-icon { display: inline-flex; flex-shrink: 0; color: var(--muted-2); }
.settings-row-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.settings-row-name { font-size: calc(14px * var(--text-scale)); font-weight: 600; }
.settings-row-sub {
  font-size: calc(12px * var(--text-scale));
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.settings-row > .ic:last-child { flex-shrink: 0; color: var(--muted); }
.settings-label { font-size: calc(12px * var(--text-scale)); font-weight: 600; }
.settings-theme-options { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; }
.settings-text-options { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.settings-theme-option {
  min-height: 36px;
  border: 1px solid var(--btn-border);
  border-radius: 7px;
  background: var(--btn-bg);
  color: var(--fg);
  font: 600 calc(13px * var(--text-scale)) var(--font);
  cursor: pointer;
}
.settings-theme-option[aria-pressed="true"] { border-color: var(--accent); background: var(--accent-tint); color: var(--link); }
.settings-theme-option:disabled { opacity: .6; cursor: default; }
/* Settings -> Appearance -> Agent icons (#498, DESIGN.md §29.11): the owner uploads a light and a dark
   avatar for each harness. The images come from the broker's own stylesheet (/api/agent-icons.css,
   linked after this one), which also gives each stored slot's preview its image. */
.agent-icons { display: flex; flex-direction: column; gap: 10px; margin-top: 14px; padding-top: 16px; border-top: 1px solid var(--line); }
/* the tip is placed against the heading's row, not its own button, so on a phone it can't run off the right edge */
.agent-icons-head { position: relative; display: flex; align-items: center; gap: 6px; }
.agent-icons-title { margin: 0; font-size: calc(14px * var(--text-scale)); font-weight: 600; }
.agent-icons > p { margin: 0; }
.agent-icons-body { display: flex; flex-direction: column; gap: 10px; }
.info-wrap { display: inline-flex; }
.info-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--muted-2);
  cursor: help;
}
.info-btn:hover { background: var(--row-sel); color: var(--fg); }
.info-btn .ic { width: 15px; height: 15px; }
.info-tip {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  z-index: 10;
  width: min(300px, 100%);
  padding: 8px 10px;
  border: 1px solid var(--menu-border);
  border-radius: 7px;
  background: var(--menu-bg);
  box-shadow: var(--menu-shadow);
  color: var(--fg);
  font-size: calc(12px * var(--text-scale));
  font-weight: 400;
  line-height: 1.4;
  visibility: hidden;
  pointer-events: none;
}
.info-btn:focus-visible + .info-tip, .info-wrap.tip-open .info-tip { visibility: visible; pointer-events: auto; }
@media (hover: hover) { .info-wrap:hover .info-tip { visibility: visible; pointer-events: auto; } }
.info-wrap.tip-dismissed .info-tip { visibility: hidden; }
.info-btn:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; }
.agent-icon-row { gap: 10px; }
.agent-icon-head { display: flex; align-items: center; gap: 10px; }
.agent-icon-head .avatar { flex: none; }
.agent-icon-who { display: flex; flex: 1; flex-direction: column; gap: 1px; min-width: 0; font-size: calc(14px * var(--text-scale)); }
.agent-icon-head .btn { flex: none; }
.agent-icon-slots { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.agent-icon-slot-row { display: flex; align-items: center; gap: 8px; min-width: 0; flex-wrap: wrap; }
.agent-icon-slot-text { display: flex; flex-direction: column; flex: 1; min-width: 60px; }
/* a stored slot shows its image on the surface it is for, whatever the page's theme is */
.agent-icon-slot {
  flex: none;
  width: 44px;
  height: 44px;
  border: 1px solid var(--side-border);
  border-radius: 10px;
  background-position: center;
  background-repeat: no-repeat;
  background-size: contain;
}
.agent-icon-slot.light { background-color: #ffffff; }
.agent-icon-slot.dark { background-color: #1c1c1f; }
.agent-icon-slot.empty { border-style: dashed; background-color: transparent; }
.agent-icons-error:empty, .agent-icons-status:empty { display: none; }
@media (max-width: 760px) {
  .agent-icon-slots { grid-template-columns: minmax(0, 1fr); }
}
.settings-account { display: flex; flex-direction: column; gap: 10px; }
.settings-account .passkey-card + .passkey-card { margin-top: 0; }
.rules-textarea {
  box-sizing: border-box;
  width: 100%;
  min-height: 126px;
  padding: 10px 12px;
  resize: vertical;
  border: 1px solid var(--btn-border);
  border-radius: 8px;
  background: var(--input-bg);
  color: var(--fg);
  font: 400 calc(13px * var(--text-scale)) / 1.5 var(--font);
}
.rules-textarea:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; }
.rules-count { align-self: flex-end; color: var(--muted); font-size: calc(11px * var(--text-scale)); }
@media (max-width: 760px) {
  .app-dialog {
    width: 100%;
    max-width: none;
    max-height: calc(100dvh - 24px);
    margin: auto 0 0;
    border-radius: 16px 16px 0 0;
    border-bottom: 0;
  }
  .app-dialog-form { padding: 22px 20px calc(20px + env(safe-area-inset-bottom)); }
  .app-dialog-buttons { flex-direction: column-reverse; }
  .app-dialog-buttons .btn, .app-dialog-buttons .btn-primary, .app-dialog-buttons .btn-danger { width: 100%; height: 40px; }
  .app-dialog-settings { width: 100%; height: calc(100dvh - 24px); }
  .settings-head { padding: 0 12px 0 8px; height: 52px; }
  /* a column: the list as tall as its rows (it scrolls past the sheet), then Sign out and the
     version right below it; a group's page fills the sheet instead */
  .settings-body { display: flex; flex-direction: column; min-height: 0; }
  .settings-list { flex: 0 1 auto; min-height: 0; }
  .settings-foot { flex-shrink: 0; border-right: 0; padding: 10px 16px calc(14px + env(safe-area-inset-bottom)); }
  .settings-panels { flex: 1; min-height: 0; }
  .settings-panel-content { padding: 18px 20px; }
  .settings-savebar { padding: 10px 16px calc(10px + env(safe-area-inset-bottom)); }
  .settings-panel-content > h3 { display: none; }  /* the header already names the group */
}

/* The review board (#80, DESIGN.md §37.5): shown in place of the log; the composer stays. */
#main.board-open #log, #main.board-open #room-empty { display: none; }
.board { flex: 1; min-height: 0; display: flex; flex-direction: column; gap: 12px; padding: 12px 20px 14px; overflow: auto; container: board / inline-size; }
.board-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
/* the title takes its own row when the status and Close don't fit beside it (a phone), and
   the commit wraps under the link before the repository's name is cut (#247) */
.board-title { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 8px; min-width: 0; flex: 1 1 260px; }
.board-title h2 { margin: 0; font-size: calc(15px * var(--text-scale)); }
.board-url { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
/* a recognized pull request or merge request (#247): the forge's mark, the repository (which
   may shorten) and the number (which never does) */
.board-pr {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  align-self: center;
  padding: 3px 9px 3px 7px;
  border: 1px solid var(--side-border);
  border-radius: 999px;
  color: var(--fg);
  text-decoration: none;
  font-size: calc(13px * var(--text-scale));
}
.board-pr:hover { border-color: var(--muted); }
.board-pr:hover .board-pr-repo { text-decoration: underline; }
.board-pr .mark { width: 16px; height: 16px; flex: none; fill: currentColor; }
.board-pr.forge-gitlab .mark { fill: var(--forge-gitlab); }
.board-pr-repo { overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.board-pr-num { flex: none; color: var(--muted-2); font-variant-numeric: tabular-nums; }
.board-head-sha { color: var(--muted-2); font-size: calc(12px * var(--text-scale)); }
/* Two or more open boards in a room (#445, DESIGN.md §37.14): tabs on the header's first row, one
   board on show below. A tab is the pull request's mark and short name, and the number of items
   that need a person on it, in the chip-danger colors. */
.board-tabs { display: flex; gap: 6px; flex: 1 1 100%; order: -1; min-width: 0; overflow-x: auto; padding: 2px 2px 4px; }
.board-tab {
  display: inline-flex; align-items: center; gap: 6px; flex: none; max-width: 260px; height: 30px; padding: 0 10px;
  border-radius: 15px; border: 1px solid var(--line); background: var(--bg); color: var(--fg); cursor: pointer;
  font: inherit; font-size: calc(13px * var(--text-scale));
}
.board-tab:hover { border-color: var(--input-border); }
.board-tab.selected { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); background: var(--accent-tint); }
.board-tab .mark { width: 14px; height: 14px; flex: none; fill: currentColor; }
.board-tab .mark-gitlab { fill: var(--forge-gitlab); }
.board-tab-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.board-tab-need {
  flex: none; min-width: 18px; height: 18px; padding: 0 5px; border-radius: 9px; display: inline-flex;
  align-items: center; justify-content: center; background: var(--danger-bg); color: var(--danger);
  font-size: calc(11px * var(--text-scale)); font-weight: 700; font-variant-numeric: tabular-nums;
}
.board-report { font-size: calc(12px * var(--text-scale)); color: var(--muted-2); min-width: 0; overflow-wrap: anywhere; }
.chip.chip-ok { background: var(--accent-tint); color: var(--green); }
/* The open card beside the lanes (#343). The card was a fixed 340 px: cramped on a wide window,
   and on a narrower one it left the lanes about 110 px each. Now it takes a share of the board,
   the divider between the two is dragged (or moved with the arrow keys) to trade one for the
   other, and when both can't have their smallest width the card goes under the lanes (the
   container rule below). 438px is the lanes' smallest width (420) and the divider's track with
   its two gaps (18): app.js has the same numbers. The page's script never writes a style, so
   the divider picks the width from a ladder of classes, the way a meter's fill does: dw-0 is
   340 px, each rung 24 px more, and dw-max is all the lanes can spare. */
.board-body { display: grid; grid-template-columns: minmax(0, 1fr); gap: 14px 4px; align-items: start; }
.board-body.has-detail { grid-template-columns: minmax(0, 1fr) 10px clamp(340px, var(--board-detail-w, min(45%, 560px)), calc(100% - 438px)); }
.board-divider { position: relative; align-self: stretch; min-height: 48px; border-radius: 5px; cursor: col-resize; touch-action: none; }
.board-divider::before { content: ""; position: absolute; top: 0; bottom: 0; left: 4px; width: 2px; border-radius: 1px; background: var(--line); }
.board-divider:hover::before, .board-divider:focus-visible::before, .board-resizing .board-divider::before { background: var(--accent); }
.board-divider:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
html.board-resizing { cursor: col-resize; user-select: none; -webkit-user-select: none; }
.board-body.dw-0 { --board-detail-w: 340px; } .board-body.dw-1 { --board-detail-w: 364px; } .board-body.dw-2 { --board-detail-w: 388px; } .board-body.dw-3 { --board-detail-w: 412px; }
.board-body.dw-4 { --board-detail-w: 436px; } .board-body.dw-5 { --board-detail-w: 460px; } .board-body.dw-6 { --board-detail-w: 484px; } .board-body.dw-7 { --board-detail-w: 508px; }
.board-body.dw-8 { --board-detail-w: 532px; } .board-body.dw-9 { --board-detail-w: 556px; } .board-body.dw-10 { --board-detail-w: 580px; } .board-body.dw-11 { --board-detail-w: 604px; }
.board-body.dw-12 { --board-detail-w: 628px; } .board-body.dw-13 { --board-detail-w: 652px; } .board-body.dw-14 { --board-detail-w: 676px; } .board-body.dw-15 { --board-detail-w: 700px; }
.board-body.dw-16 { --board-detail-w: 724px; } .board-body.dw-17 { --board-detail-w: 748px; } .board-body.dw-18 { --board-detail-w: 772px; } .board-body.dw-19 { --board-detail-w: 796px; }
.board-body.dw-20 { --board-detail-w: 820px; } .board-body.dw-21 { --board-detail-w: 844px; } .board-body.dw-22 { --board-detail-w: 868px; } .board-body.dw-23 { --board-detail-w: 892px; }
.board-body.dw-24 { --board-detail-w: 916px; } .board-body.dw-25 { --board-detail-w: 940px; } .board-body.dw-26 { --board-detail-w: 964px; } .board-body.dw-27 { --board-detail-w: 988px; }
.board-body.dw-28 { --board-detail-w: 1012px; } .board-body.dw-29 { --board-detail-w: 1036px; } .board-body.dw-30 { --board-detail-w: 1060px; } .board-body.dw-31 { --board-detail-w: 1084px; }
.board-body.dw-32 { --board-detail-w: 1108px; } .board-body.dw-33 { --board-detail-w: 1132px; } .board-body.dw-34 { --board-detail-w: 1156px; } .board-body.dw-35 { --board-detail-w: 1180px; }
.board-body.dw-36 { --board-detail-w: 1204px; } .board-body.dw-37 { --board-detail-w: 1228px; } .board-body.dw-38 { --board-detail-w: 1252px; } .board-body.dw-39 { --board-detail-w: 1276px; }
.board-body.dw-40 { --board-detail-w: 1300px; } .board-body.dw-41 { --board-detail-w: 1324px; } .board-body.dw-42 { --board-detail-w: 1348px; } .board-body.dw-43 { --board-detail-w: 1372px; }
.board-body.dw-44 { --board-detail-w: 1396px; } .board-body.dw-45 { --board-detail-w: 1420px; } .board-body.dw-46 { --board-detail-w: 1444px; } .board-body.dw-47 { --board-detail-w: 1468px; }
.board-body.dw-48 { --board-detail-w: 1492px; } .board-body.dw-49 { --board-detail-w: 1516px; } .board-body.dw-50 { --board-detail-w: 1540px; } .board-body.dw-51 { --board-detail-w: 1564px; }
.board-body.dw-52 { --board-detail-w: 1588px; } .board-body.dw-53 { --board-detail-w: 1612px; } .board-body.dw-54 { --board-detail-w: 1636px; } .board-body.dw-55 { --board-detail-w: 1660px; }
.board-body.dw-56 { --board-detail-w: 1684px; } .board-body.dw-57 { --board-detail-w: 1708px; } .board-body.dw-58 { --board-detail-w: 1732px; } .board-body.dw-59 { --board-detail-w: 1756px; }
.board-body.dw-60 { --board-detail-w: 1780px; }
.board-body.dw-max { --board-detail-w: 100%; }
/* three lanes in one row, never wrapped (#250): Agents working, Needs you, Settled */
.board-lanes { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; align-items: start; min-width: 0; }
.board-lane { display: flex; flex-direction: column; gap: 8px; padding: 10px; border-radius: 10px; background: var(--side-bg); border: 1px solid var(--side-border); min-width: 0; }
.board-lane.lane-you:not(.lane-clear) { background: var(--danger-bg); border-color: var(--danger); }
.board-card.dropped { opacity: .62; }
.board-card.deferred { opacity: .8; }  /* settled here, still to do in its ticket: not struck out */
.board-card.dropped .board-card-title { text-decoration: line-through; text-decoration-color: var(--muted); }
.board-lane-title { display: flex; align-items: center; gap: 6px; margin: 0; font-size: calc(12.5px * var(--text-scale)); font-weight: 600; color: var(--ink-2); }
.board-count { color: var(--muted-2); font-weight: 400; font-variant-numeric: tabular-nums; }
.board-empty { margin: 0; color: var(--muted-2); font-size: calc(12px * var(--text-scale)); }
.board-card {
  display: flex; flex-direction: column; gap: 4px; padding: 9px 10px; text-align: left; width: 100%;
  border-radius: 8px; border: 1px solid var(--line); background: var(--bg); color: var(--fg); cursor: pointer;
  font: inherit; min-width: 0; overflow-wrap: anywhere;
}
.board-card:hover { border-color: var(--input-border); }
.board-card.selected { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
/* the row wraps rather than squeezing: in a narrow lane the agent's words ("waiting for approval", #472)
   go on a second row, and the label and the words stay whole */
.board-card-top { display: flex; flex-wrap: wrap; align-items: center; gap: 2px 6px; }
.board-label { font-weight: 700; font-variant-numeric: tabular-nums; flex-shrink: 0; }
/* a confirmed fix's check (#427): the theme's success green, at the end of the card's top row */
.board-card-top .board-confirmed { margin-left: auto; color: var(--green); }
/* whose move a card waits on, and whether that agent is busy (#407): the Members dot's colors */
.board-pulse {
  display: inline-flex; align-items: center; gap: 4px; margin-left: auto; white-space: nowrap;
  font-size: calc(11px * var(--text-scale)); color: var(--muted-2);
}
.board-pulse::before {
  content: ''; width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; background: var(--green);
}
.board-pulse.s-busy::before { background: var(--busy); animation: board-pulse 1.4s ease-in-out infinite; }
.board-pulse.s-busy { color: var(--fg); font-weight: 600; }
.board-pulse.s-waiting-approval::before { background: transparent; box-shadow: inset 0 0 0 2px var(--busy); }
.board-pulse.s-waiting-approval { color: var(--amber-ink); font-weight: 600; }
.board-pulse.s-offline::before, .board-pulse.s-starting::before {
  background: transparent; box-shadow: inset 0 0 0 1.5px var(--muted);
}
.board-pulse.s-parked::before { background: transparent; box-shadow: inset 0 0 0 2px var(--parked); }
@keyframes board-pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: 0.35; transform: scale(0.7); }
}
.board-state { font-size: calc(11px * var(--text-scale)); color: var(--muted-2); }
.board-state.s-contested, .board-state.s-open { color: var(--danger); }
.board-state.s-fixed, .board-state.s-answered { color: var(--green); }
.board-card-title { font-size: calc(13px * var(--text-scale)); }
.board-card-meta { font-size: calc(11.5px * var(--text-scale)); color: var(--muted-2); }
.board-outdated { color: var(--amber-ink); font-size: calc(11.5px * var(--text-scale)); font-weight: 650; overflow-wrap: anywhere; }
.board-detail .board-outdated { margin: 0; }
/* Hand off, in the board's header (#425, DESIGN.md §37.6): an action on the whole board, so it sits
   with the title and the status, not among the items. The line says how far along the board is,
   or what is left; the button is the way. */
.board-handoff { display: flex; align-items: center; gap: 8px; min-width: 0; }
.board-handoff-note { font-size: calc(12.5px * var(--text-scale)); color: var(--muted-2); min-width: 0; max-width: 17em; overflow-wrap: anywhere; }
.board-handoff.is-ready .board-handoff-note, .board-handoff.is-done .board-handoff-note { color: var(--ink-2); }
.board-handoff .btn-primary { flex: none; }
/* the last item just settled: a halo that grows and fades once, with no sound and no movement of
   the layout. prefers-reduced-motion drops every animation (see above), and the button is lit anyway. */
.board-handoff .btn-primary.nudge { animation: board-handoff-nudge 1.8s ease-out 1; }
@keyframes board-handoff-nudge {
  0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 55%, transparent); }
  100% { box-shadow: 0 0 0 12px color-mix(in srgb, var(--accent) 0%, transparent); }
}
.board-detail { min-width: 0; container: card / inline-size; display: flex; flex-direction: column; gap: 8px; padding: 12px; border-radius: 10px; border: 1px solid var(--line); background: var(--bg); overflow-wrap: anywhere; }
.board-detail h3 { margin: 0; font-size: calc(14px * var(--text-scale)); }
.board-detail-top { display: flex; flex-direction: column; gap: 2px; }
/* a card's rows (#250): Lines and Fix, each a link to the PR or MR with the forge's mark */
.board-rows { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 6px 10px; margin: 0; align-items: baseline; }
.board-rows dt { color: var(--muted-2); font-size: calc(12px * var(--text-scale)); font-weight: 600; }
.board-rows dd { margin: 0; min-width: 0; }
.board-link { display: inline-flex; align-items: center; gap: 6px; font-size: calc(12.5px * var(--text-scale)); }
.board-link .mark { width: 14px; height: 14px; flex: none; fill: currentColor; }
.board-link.forge-gitlab .mark { fill: var(--forge-gitlab); }
/* a GitLab finding's two links (#442): its lines at the head commit, and its file in the MR diff */
.board-lines-links { display: flex; flex-wrap: wrap; gap: 4px 14px; }
/* a contested finding: both sides side by side, above the person's choice */
.board-sides { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
.board-side { padding: 8px 10px; border-radius: 8px; background: var(--side-bg); border: 1px solid var(--side-border); font-size: calc(12.5px * var(--text-scale)); min-width: 0; }
.board-side > p { margin: 0; }
.board-side > .board-side-who { margin: 0 0 4px; font-weight: 600; }
.board-side > .board-insist { margin: 6px 0 0; padding-top: 6px; border-top: 1px solid var(--side-border); font-weight: 600; }
.board-history { margin: 0; padding: 8px 0 0 18px; border-top: 1px solid var(--line); color: var(--muted-2); font-size: calc(12px * var(--text-scale)); display: flex; flex-direction: column; gap: 2px; }
.board-history strong { color: var(--fg); font-weight: 600; }
.board-history-at { margin-left: 6px; font-variant-numeric: tabular-nums; }
/* a question's agreement (#423): who is still to pick, or that the agents split; and a finding's fix options */
.board-consensus { flex: 1 1 100%; margin: 0; color: var(--muted-2); font-size: calc(12px * var(--text-scale)); }
.board-fix-options { display: flex; flex-direction: column; gap: 4px; }
.board-fix-options h4 { margin: 0; color: var(--muted-2); font-size: calc(12px * var(--text-scale)); font-weight: 600; }
.board-option-list { margin: 0; padding: 0 0 0 18px; display: flex; flex-direction: column; gap: 3px; font-size: calc(12.5px * var(--text-scale)); }
.board-answer { margin: 0; font-weight: 600; }
.board-detail-state, .board-reason { margin: 0; color: var(--muted-2); font-size: calc(12.5px * var(--text-scale)); }
.board-where { align-self: flex-start; }
.board-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: flex-end; padding-top: 4px; border-top: 1px solid var(--line); }
/* a question's options are sentences, not button labels: each takes the row and wraps inside the
   detail (a long one ran past it and was cut off) */
.board-actions button[data-option] { flex: 1 1 100%; max-width: 100%; height: auto; min-height: 32px; padding: 7px 12px; line-height: 1.3; white-space: normal; text-align: left; justify-content: flex-start; overflow-wrap: anywhere; }
.board-action-set { display: flex; flex-wrap: wrap; gap: 8px; align-items: flex-end; flex: 1 1 100%; min-width: 0; }
.board-field { display: flex; flex-direction: column; gap: 4px; font-size: calc(12px * var(--text-scale)); color: var(--muted-2); flex: 1 1 160px; }
.board-field input, .board-field select { font: inherit; color: var(--fg); background: var(--input-bg); border: 1px solid var(--input-border); border-radius: 6px; padding: 6px 8px; min-width: 0; }
/* a contested finding's two sides go one above the other in a card under 440 px: side by side
   in 340 px left each about 150 px, a few words to a line. The query measures the card inside
   its padding and border (26 px), so 440 px of card is 414 px here. */
@container card (max-width: 413px) {
  .board-sides { grid-template-columns: minmax(0, 1fr); }
}
/* under 778 px of board (340 + 18 + 420) the card and the lanes can't both have their smallest
   width: the card goes under the lanes, and there is nothing to drag. This follows the board's
   own width, so opening Members counts; it replaces a rule on the window's width (1100 px). */
@container board (max-width: 777px) {
  .board-body.has-detail { grid-template-columns: minmax(0, 1fr); }
  .board-divider { display: none; }
}
@media (max-width: 760px) {
  .board { padding: 10px 12px 12px; }
  .board-title { flex-basis: 100%; }  /* its own row; the status and Close go under it (#247) */
  /* The header stays on screen while the lanes scroll under it (#425): a person answers the last
     question in a card that is below the lanes here, and Hand off, with its highlight, is where
     they can see it. Three rows: the title; the status and Close; what is left and Hand off. */
  .board-head { position: sticky; top: -10px; z-index: 2; margin: -10px -12px 0; padding: 10px 12px 8px;
    background: var(--bg); border-bottom: 1px solid var(--line); }
  .board { scroll-padding-top: 160px; }  /* a card that takes focus by keyboard doesn't land under it */
  .board.has-tabs { scroll-padding-top: 200px; }  /* and the tabs' row is under it too (#445) */
  #board-status { order: 1; }
  #board-close { order: 2; margin-left: auto; }
  .board-handoff { order: 3; flex: 1 1 100%; justify-content: space-between; }
  .board-handoff-note { max-width: none; }
  .board-lanes { grid-template-columns: minmax(0, 1fr); }
  .board-lane.lane-you { order: -1; }  /* stacked on a phone: what needs you first */
  .board-sides { grid-template-columns: minmax(0, 1fr); }
}

/* Who someone is (#192): the admin sets each person's email on their card. */
.email-row, .name-row { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; margin: 4px 0; }
.email-row label, .name-row label { font-size: calc(12px * var(--text-scale)); color: var(--muted-2); }
.email-row input, .name-row input { flex: 1 1 200px; min-width: 0; font: inherit; color: var(--fg); background: var(--input-bg);
  border: 1px solid var(--input-border); border-radius: 6px; padding: 5px 8px; }
/* First and last name on a People card (#566): Add someone's pair, then Save. The pair takes
   the whole row (a long value must not widen the sheet: an input's min-content is its text). */
.names-row { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 6px 8px; margin: 4px 0;
  min-width: 0; max-width: 100%; }
.names-row .person-names { flex: 1 1 100%; min-width: 0; max-width: 100%; }
/* flex-basis auto, not 0: at the phone width the pair stacks, and a 0 basis plus a hidden
   overflow collapses each field to no height. The input's size attribute keeps a long value
   from widening the sheet. */
.names-row .person-field { flex: 1 1 auto; max-width: 100%; min-width: 0; }
.names-row .person-field label { font-size: calc(12px * var(--text-scale)); color: var(--muted-2); }
.names-row .person-field input { display: block; width: 100%; max-width: 100%; min-width: 0; font: inherit;
  color: var(--fg); background: var(--input-bg); border: 1px solid var(--input-border); border-radius: 6px;
  padding: 5px 8px; }
.names-row .btn { flex: none; }
