/* Palette carried over from the previous UI deliberately -- this is a rebuild of the same
   product, not a different one. Light is the default; dark via [data-theme="dark"]. */
:root{
  --bg:#fbfcfd; --bg2:#fff; --bg3:#f2f4f7; --line:#dfe3ea;
  --fg:#131722; --fg2:#5b6472; --fg3:#8b94a3;
  --acc:#3b6fd4; --ok:#2f9e63; --warn:#b8801f; --err:#c8453a; --run:#3b6fd4;
  --mono:ui-monospace,SFMono-Regular,"SF Mono",Menlo,monospace;
  --sans:-apple-system,BlinkMacSystemFont,"Segoe UI",Inter,system-ui,sans-serif;
}
html[data-theme="dark"]{
  --bg:#0e1014; --bg2:#15181f; --bg3:#1c2029; --line:#272c38;
  --fg:#e6e9ef; --fg2:#9aa3b2; --fg3:#6b7484;
  --acc:#5b8cff; --ok:#3fbf7f; --warn:#e0a33e; --err:#e0574a; --run:#5b8cff;
}
*{box-sizing:border-box}

/* A class rule that sets `display` outranks the UA stylesheet's [hidden]{display:none}. That
   has bitten four times here -- an invisible backdrop swallowing clicks, a stale filter note,
   the whole signed-in shell rendering to logged-out visitors, and again in the rebuild. Every
   selector below that sets `display` carries an explicit [hidden] override. */
[hidden]{display:none !important}

body{background:var(--bg);color:var(--fg);font-family:var(--sans);font-size:14px;margin:0;
  height:100vh;display:grid;grid-template-columns:210px 1fr}
body:has(#login:not([hidden])){display:grid;grid-template-columns:1fr;place-items:center}

.muted{color:var(--fg2)}
.pad{padding:0 20px}
code{font-family:var(--mono);font-size:12.5px}

/* login
   One card. It used to be two, and #login was a grid whose two card children became two tracks
   with the leftover viewport height dumped between them -- the gap in the screenshot was not
   spacing anybody chose, it was an empty grid row. A single centred card has no leftover to
   distribute. */
#login{display:grid;place-items:center;min-height:100vh;width:100%;padding:24px}
#login[hidden]{display:none !important}
.login-card{background:var(--bg2);border:1px solid var(--line);border-radius:12px;padding:28px;
  width:340px;max-width:100%;display:grid;gap:10px}
.login-card[hidden]{display:none !important}
.login-logo{font-size:26px;color:var(--acc);line-height:1}
.login-card h1{margin:0;font-size:18px}
/* The subtitle belongs to the heading, so it sits tight under it and the 10px gap goes to the
   things you actually act on. */
.login-sub{margin:-6px 0 6px}
#loginErr,#walletErr{color:var(--err);font-size:13px}
/* Empty is EMPTY. These reserved 18px whether or not anything had gone wrong, which put a
   permanent dead band under each button and was half of why the card looked padded out. */
#loginErr:empty,#walletErr:empty{display:none}
/* The two blocks are one decision, so they inherit the card's rhythm rather than setting their
   own. */
#walletCard,#loginForm{display:grid;gap:10px}
.login-card .hint{margin:0}
/* A login button is the page's one action, so it gets the width and a little more height
   than the toolbar buttons this class otherwise styles. */
.btn.wide{width:100%;padding:9px 13px}
/* A rule with the word in it, not a lone "or" floating in its own paragraph. */
.login-or{display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:10px;
  margin:4px 0 0;color:var(--fg3);font-size:12px}
.login-or::before,.login-or::after{content:"";height:1px;background:var(--line)}

/* shell */
#app{display:contents}
#app[hidden]{display:none !important}
.sidebar{background:var(--bg2);border-right:1px solid var(--line);padding:14px 10px;
  display:flex;flex-direction:column;gap:14px;overflow-y:auto}
.brand{display:flex;gap:10px;align-items:center;padding:0 4px}
.logo{font-size:20px;color:var(--acc)}
.brand-name{font-weight:600;font-size:13.5px;line-height:1.2}
.brand-org{font-size:11px;color:var(--fg3)}
nav{display:flex;flex-direction:column;gap:2px;flex:1}
.nav{display:flex;gap:10px;align-items:center;padding:8px 10px;border:0;border-radius:7px;
  background:none;color:var(--fg2);font:inherit;cursor:pointer;text-align:left}
.nav span{opacity:.65;font-size:12px;width:14px}
.nav:hover{background:var(--bg3);color:var(--fg)}
.nav.active{background:var(--bg3);color:var(--fg);font-weight:550}
.nav.active span{opacity:1;color:var(--acc)}
.sidebar-foot{border-top:1px solid var(--line);padding:12px 4px 2px;font-size:11px;line-height:1.7}
.foot-actions{display:flex;gap:10px;margin-top:6px}

main{overflow:hidden;display:flex;flex-direction:column;min-height:0}
.view{display:flex;flex-direction:column;min-height:0;flex:1;overflow:hidden}
.view[hidden]{display:none !important}
.vh{display:flex;align-items:center;gap:12px;padding:16px 20px 10px}
.vh h1{margin:0;font-size:15px}
.vh .btn{margin-left:auto}
.vh .muted{margin-left:auto;font-family:var(--mono);font-size:11.5px}

/* buttons + inputs */
.btn{font:inherit;cursor:pointer;border:1px solid var(--line);background:var(--bg3);
  color:var(--fg);border-radius:7px;padding:7px 13px}
.btn:hover{border-color:var(--acc)}
.btn.primary{background:var(--acc);border-color:var(--acc);color:#fff;font-weight:600}
.btn.small{padding:4px 9px;font-size:12.5px}
.link{background:none;border:0;color:var(--fg2);cursor:pointer;font:inherit;padding:0;
  text-decoration:underline}
.link:hover{color:var(--fg)}
input,textarea,select{font:inherit;background:var(--bg);color:var(--fg);border:1px solid var(--line);
  border-radius:7px;padding:7px 10px;width:100%}
textarea{font-family:var(--mono);font-size:13px;resize:vertical}

/* stats strip */
.stats{display:flex;gap:10px;padding:0 20px 12px;flex-wrap:wrap}
.stat{background:var(--bg2);border:1px solid var(--line);border-radius:9px;padding:9px 14px;min-width:104px}
.stat b{display:block;font-size:19px;line-height:1.3}
.stat span{font-size:11px;color:var(--fg2)}
.stat.warn b{color:var(--warn)}
.stat.bad b{color:var(--err)}

/* filters */
.filters{display:flex;gap:8px;padding:0 20px 12px;align-items:center}
.filters input{max-width:260px}
.filters select{max-width:150px}

/* split list/detail */
.split{display:grid;grid-template-columns:320px 1fr;flex:1;min-height:0;
  border-top:1px solid var(--line)}
.list{border-right:1px solid var(--line);overflow-y:auto;padding:10px;display:flex;
  flex-direction:column;gap:7px;background:var(--bg2)}
.item{border:1px solid var(--line);border-radius:8px;padding:9px 11px;cursor:pointer;
  background:var(--bg);display:grid;gap:5px}
.item:hover{border-color:var(--acc)}
.item.sel{border-color:var(--acc);background:var(--bg3)}
.item .t{font-weight:600;font-size:13px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.meta{display:flex;gap:6px;align-items:center;color:var(--fg2);font-size:11px;flex-wrap:wrap}
.badge{border-radius:4px;padding:1px 7px;font-size:11px;font-weight:600;background:var(--bg3);
  border:1px solid var(--line)}
.badge.sre{color:#79c0ff}.badge.reviewer{color:#d2a8ff}.badge.devops{color:#ffa657}
.st{font-weight:600}
.st.running{color:var(--run)}.st.idle{color:var(--ok)}
.st.needs_approval{color:var(--warn)}.st.failed{color:var(--err)}
.st.stopped{color:var(--fg3)}

.detail[hidden]{display:none !important}
.empty{color:var(--fg2);display:grid;place-items:center;height:55vh}
.detail h2{margin:0 0 6px;font-size:17px}

/* trace */
.trace{display:flex;flex-direction:column;gap:7px;margin:16px 0}
.ev{border:1px solid var(--line);border-radius:8px;padding:9px 11px;background:var(--bg2)}
.ev.tool{border-left:3px solid var(--acc)}
.ev.denied{border-left:3px solid var(--warn)}
.ev.error{border-left:3px solid var(--err)}
.ev.turn{border-left:3px solid var(--fg3);background:var(--bg3)}
.ev .k{font-size:10.5px;text-transform:uppercase;letter-spacing:.05em;color:var(--fg3)}
.ev pre{margin:5px 0 0;font-family:var(--mono);font-size:12.5px;white-space:pre-wrap;
  word-break:break-word}
.ev .why{color:var(--warn);font-size:12.5px;margin-top:5px}
.answer{background:var(--bg2);border:1px solid var(--line);border-left:3px solid var(--ok);
  border-radius:8px;padding:15px 17px;margin-top:14px}
.answer pre{white-space:pre-wrap;font-family:inherit;margin:0;line-height:1.6}
.approval{background:var(--bg2);border:1px solid var(--warn);border-radius:8px;padding:13px 15px;
  margin:11px 0;display:grid;gap:9px}
.handoff{background:var(--bg2);border:1px solid var(--acc);border-radius:8px;padding:13px 15px;
  margin:11px 0;display:grid;gap:9px}
.handoff .prose p:first-child{margin-top:0}
.handoff .prose p:last-child{margin-bottom:0}
/* A blocked command on a finished session is a record, not a pending decision. Amber says
   "act on me"; this one has nothing to act on. */
/* Command output: folded, and it says how much there is before you open it. */
details.out{margin:3px 0 8px}
details.out>summary{cursor:pointer;color:var(--fg3);font-size:11px;letter-spacing:.03em;
  padding:1px 0;user-select:none}
details.out>summary:hover{color:var(--fg2)}
details.out.bad>summary{color:var(--err)}
details.out pre{color:var(--fg2);border-left:2px solid var(--line);padding:7px 11px;margin:5px 0 0;
  overflow-x:auto;max-height:320px;white-space:pre-wrap}
details.out.bad pre{border-left-color:var(--err)}

/* Reasoning reads as prose, not as a toggle: it is why a command was chosen, and it is the part
   of a trace worth reading. Set apart from the agent's own answer, never hidden from it. */
.ev.prose.think{color:var(--fg2);border-left:2px solid var(--line);padding-left:13px}

.approval.spent{border-color:var(--line)}
.approval code{background:var(--bg);padding:3px 7px;border-radius:4px;display:block;overflow-x:auto}
.acts{display:flex;gap:8px}
.reply{display:flex;gap:8px;margin-top:18px;position:sticky;bottom:0;background:var(--bg);padding:10px 0}
.spin{display:inline-block;width:10px;height:10px;border:2px solid var(--line);
  border-top-color:var(--acc);border-radius:50%;animation:s .8s linear infinite}
@keyframes s{to{transform:rotate(360deg)}}

/* cards */
.cards{padding:14px 20px;display:grid;gap:12px;overflow-y:auto;
  grid-template-columns:repeat(auto-fill,minmax(320px,1fr))}
.card{background:var(--bg2);border:1px solid var(--line);border-radius:10px;padding:15px 17px}
.card h3{margin:0 0 5px;font-size:14.5px;display:flex;align-items:center;gap:8px}
.card p{margin:0 0 9px;color:var(--fg2);font-size:13px}
.tools{display:flex;gap:5px;flex-wrap:wrap}
.tools span{font-family:var(--mono);font-size:11px;background:var(--bg3);border:1px solid var(--line);
  border-radius:4px;padding:2px 7px}
.ok{color:var(--ok)}.bad{color:var(--err)}

/* ask */
.ask-wrap{padding:0 20px;display:grid;gap:11px;max-width:820px}
.rolepick{display:grid;gap:8px;grid-template-columns:repeat(auto-fit,minmax(150px,1fr))}
.rolepick .r{border:1px solid var(--line);border-radius:8px;padding:9px 11px;cursor:pointer;
  background:var(--bg2)}
.rolepick .r.sel{border-color:var(--acc);background:var(--bg3)}
.rolepick .r b{display:block;font-size:13px}
.rolepick .r span{color:var(--fg2);font-size:11.5px}
label.row{display:flex;align-items:center;gap:8px}
label.row input{width:auto}

/* role editor + knowledge viewer */
.editor{width:100%;min-height:60vh;font-family:var(--mono);font-size:12.5px}
.doc{white-space:pre-wrap;font-family:var(--mono);font-size:12.5px;line-height:1.6}
.editbar{display:flex;gap:8px;align-items:center;margin:10px 0}
.saved{color:var(--ok);font-size:12.5px}

/* dialog */
dialog{background:var(--bg2);color:var(--fg);border:1px solid var(--line);border-radius:12px;
  padding:0;width:min(620px,92vw)}
dialog::backdrop{background:#000a}
dialog form{padding:20px;display:grid;gap:9px}
dialog h2{margin:0;font-size:17px}
dialog label{font-size:12px;color:var(--fg2);margin-top:5px}
dialog menu{display:flex;justify-content:flex-end;gap:8px;padding:0;margin:12px 0 0}

/* ── ported verbatim from the previous UI ──────────────────────────────────────
   These screens worked. The rebuild changed the data model underneath them, not
   the way they look, so the styles come across unchanged rather than reinvented. */
.topbar{display:flex;justify-content:space-between;align-items:center;gap:16px;
        padding:9px 18px;border-bottom:1px solid var(--line);flex-shrink:0}
.actions{display:flex;gap:8px;align-items:center}
.overview{padding:18px 22px 0;flex-shrink:0}
.overview.collapsed{display:none}   /* the whole thing, cards included: hiding only the chart
                                       still left half the window to a strip nobody asked for */
.ov-toggle{border:0;background:transparent;color:var(--fg3);font:inherit;font-size:11px;
           cursor:pointer;padding:2px 6px;border-radius:5px}
.ov-toggle:hover{background:var(--bg3);color:var(--fg)}
.stat-row{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:11px;
          margin-bottom:14px}
.stat-label{font-size:10px;text-transform:uppercase;letter-spacing:.07em;color:var(--fg3);
            font-weight:600}
.stat-value{font-size:22px;font-weight:650;margin-top:5px;font-variant-numeric:tabular-nums}
.stat-sub{font-size:11px;color:var(--fg3);margin-top:2px}
.stat-value.ok{color:var(--ok)}.stat-value.warn{color:var(--warn)}.stat-value.bad{color:var(--err)}
.chart-card{background:var(--bg2);border:1px solid var(--line);border-radius:10px;padding:14px 16px}
.chart-head{display:flex;justify-content:space-between;align-items:center;gap:12px;
            flex-wrap:wrap;margin-bottom:10px}
.chart-title{font-size:11px;text-transform:uppercase;letter-spacing:.07em;color:var(--fg3);
             font-weight:600}
.chart-controls{display:flex;gap:8px}
.seg{display:flex;border:1px solid var(--line);border-radius:7px;overflow:hidden}
.seg button{border:0;background:transparent;color:var(--fg3);font:inherit;font-size:11px;
            padding:4px 10px;cursor:pointer}
.seg button+button{border-left:1px solid var(--line)}
.seg button:hover{color:var(--fg)}
.seg button.on{background:var(--bg3);color:var(--fg);font-weight:550}
.chart-legend{display:flex;gap:12px;flex-wrap:wrap;margin-top:6px;font-size:10.5px;color:var(--fg2)}
.chart-legend span{display:flex;align-items:center;gap:6px}
.chart-legend i{width:10px;height:2px;border-radius:2px;display:inline-block}
.chart-empty{color:var(--fg3);font-size:12.5px;padding:26px 0;text-align:center}
svg .grid{stroke:var(--line);stroke-width:1}
svg .axis{fill:var(--fg3);font-size:9.5px;font-family:var(--mono)}
svg .ln{fill:none;stroke-width:2;stroke-linejoin:round;stroke-linecap:round}
svg .pt{stroke:var(--bg2);stroke-width:1.5}
svg .hit{cursor:pointer}
.btn.danger{color:var(--err);border-color:transparent}
.btn.danger:hover{border-color:var(--err)}
.pill{padding:2px 7px;border-radius:20px;font-size:10.5px;background:var(--bg);
      border:1px solid var(--line);color:var(--fg2);font-family:var(--mono)}

/* visibility: who else can see this session. Private is the exception and should look like it. */
.pill.vis-private{border-color:var(--warn);color:var(--warn)}
.pill.vis-org{border-color:var(--ok);color:var(--ok)}
.pill.vis-channel{border-color:var(--acc);color:var(--acc)}

.sched-card{background:var(--bg2);border:1px solid var(--line);border-radius:10px;
            padding:15px 17px;margin-bottom:12px;display:grid;
            grid-template-columns:1fr auto;gap:10px 18px;align-items:start}
.sched-main{min-width:0}
.sched-side{display:flex;flex-direction:column;align-items:flex-end;gap:9px}
.sched-name{font-size:14px;font-weight:600}
.sched-badges{display:flex;gap:7px;align-items:center;flex-wrap:wrap;justify-content:flex-end}
.sched-meta{display:flex;gap:7px;flex-wrap:wrap;margin-top:9px}
.sched-prompt{font-size:12.5px;color:var(--fg2);margin-top:11px;line-height:1.6;
              white-space:pre-wrap;border-left:2px solid var(--line);padding-left:11px}
.sched-prompt-wrap{margin-top:7px}
.sched-prompt-wrap summary{cursor:pointer;color:var(--fg2);font-size:12px;line-height:1.55;
                           user-select:none}
.sched-prompt-wrap summary:hover{color:var(--fg)}
.sched-prompt-full{margin-top:8px;white-space:pre-wrap}
.sched-actions{display:flex;gap:6px;flex-wrap:wrap;justify-content:flex-end}
.sched-off{opacity:.6}
.sched-off .sched-name{text-decoration:line-through;text-decoration-color:var(--fg3)}
.sw{position:relative;width:34px;height:19px;flex-shrink:0;border:0;padding:0;cursor:pointer;
    border-radius:20px;background:var(--line);transition:.18s}
.sw.on{background:var(--ok)}
.sw:after{content:"";position:absolute;top:2px;left:2px;width:15px;height:15px;border-radius:50%;
          background:#fff;transition:.18s}
.sw.on:after{transform:translateX(15px)}
.cron-modes{display:flex;gap:5px;flex-wrap:wrap;margin-bottom:10px}
.cron-modes button{border:1px solid var(--line);background:var(--bg);color:var(--fg3);
                   border-radius:7px;padding:5px 10px;font:inherit;font-size:11.5px;cursor:pointer}
.cron-modes button.on{background:var(--bg3);color:var(--fg);border-color:var(--acc);font-weight:550}
.cron-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap;font-size:12.5px;color:var(--fg2)}
.cron-row input,.cron-row select{width:auto;min-width:70px}
.cron-next{margin-top:9px;font-size:11.5px;color:var(--fg3);font-family:var(--mono);line-height:1.7}
.dow{display:flex;gap:4px}
.dow button{border:1px solid var(--line);background:var(--bg);color:var(--fg3);border-radius:6px;
            width:34px;padding:5px 0;font:inherit;font-size:11px;cursor:pointer}
.dow button.on{background:var(--acc);color:#fff;border-color:var(--acc)}
.field{margin-bottom:13px}
.field label{display:block;font-size:11px;color:var(--fg2);margin-bottom:5px}
.field input,.field select,.field textarea{width:100%}
.field textarea{min-height:110px;font-family:var(--mono);font-size:12px}
.pad{padding:16px 22px;overflow-y:auto}


/* ── layout corrections ────────────────────────────────────────────────────────
   (2) the view header was 16px top and bottom plus an 18px title -- ~50px of chrome
   above every screen. (3) the overview sat outside the scroll area, so on a laptop the
   list and detail were squeezed into a third of the window while charts nobody was
   reading held the rest. (5) the reply box was sticky INSIDE the scrolling pane, so
   content ran underneath it and text appeared both above and below. */
.topbar h1{font-size:15px;margin:0;font-weight:650}
.overview{padding:9px 18px 12px}
.stat-row{gap:8px;margin-bottom:9px;grid-template-columns:repeat(auto-fit,minmax(128px,1fr))}
.stat{padding:7px 11px;border-radius:8px}
.stat-value{font-size:17px;margin-top:2px}
.stat-label{font-size:9.5px}
.stat-sub{font-size:10px}
.chart-card{padding:9px 12px}
.chart-head{margin-bottom:6px}
.filters{padding:9px 18px;border-top:1px solid var(--line);margin:0}

/* the working area owns the remaining height, and never less than half the window */
/* The working area gets the height, not the dashboard above it. Charts are context;
   the list and the trace are the job. */
.split{flex:1;min-height:min(58vh,560px)}

/* detail: one scrolling region, one pinned footer
   `min-height:0` is load-bearing, not tidying. `.detail` is a GRID ITEM of `.split`, and a grid
   item's default `min-height:auto` refuses to shrink a flex container below its content's
   min-content height. So the scroll pane plus the reply bar sized this box, it overflowed the grid
   row, and the composer sat half below the bottom of the window -- a clipped input and a
   half-drawn Send button. `overflow:hidden` cannot rescue it: the box itself is taller than the
   row, so there is nothing left to clip against. Same reason on `.detail-scroll`, which is a flex
   item with the same default. */
.detail{padding:0;display:flex;flex-direction:column;overflow:hidden;min-height:0}
.detail-scroll{flex:1;overflow-y:auto;padding:16px 20px;min-height:0}
.reply{position:static;margin:0;padding:10px 20px;border-top:1px solid var(--line);
  background:var(--bg2);flex-shrink:0}

/* When the clipboard is unavailable the button shows the URL instead, which is long -- let it
   wrap and shrink rather than stretching the header row off the side. */
.btn.small.copy-failed{font-family:var(--mono);font-size:11px;white-space:normal;
  word-break:break-all;text-align:left;max-width:100%}

/* (4) consecutive tool calls collapse into one line you can open */
.tools-group{border:1px solid var(--line);border-radius:8px;background:var(--bg2);
  border-left:3px solid var(--acc)}
.tools-group>summary{cursor:pointer;padding:7px 11px;font-size:12px;color:var(--fg2);
  user-select:none;list-style:none;display:flex;gap:8px;align-items:center}
.tools-group>summary::-webkit-details-marker{display:none}
.tools-group>summary:hover{color:var(--fg)}
.tools-group>summary .caret{color:var(--fg3);font-size:10px}
.tools-group[open]>summary{border-bottom:1px solid var(--line)}
.tools-group .inner{padding:7px 11px;display:flex;flex-direction:column;gap:6px}
.tools-group .inner pre{margin:0;font-family:var(--mono);font-size:12px;white-space:pre-wrap;
  word-break:break-word;color:var(--fg2)}
.tools-group .last{font-family:var(--mono);font-size:11.5px;color:var(--fg3);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1}

/* (6) modal breathing room */
dialog{width:min(680px,94vw)}
#modalBody{padding:20px 22px 18px}
#modalBody h2{margin:0 0 14px;font-size:16px}
.field{margin-bottom:15px}
.modal-actions{margin-top:18px;padding-top:14px;border-top:1px solid var(--line)}
.cron-modes{margin-bottom:9px}
.cron-next{margin-top:10px;padding:8px 10px;background:var(--bg3);border-radius:7px}

/* (7) the agent editor edits every field, not just the prompt */
.agent-form{display:grid;gap:13px;max-width:760px}
.agent-form .row2{display:grid;grid-template-columns:1fr 1fr;gap:13px}
.toolbox{display:flex;gap:6px;flex-wrap:wrap}
.toolbox label{display:flex;align-items:center;gap:5px;border:1px solid var(--line);
  border-radius:7px;padding:4px 9px;font-size:12px;cursor:pointer;background:var(--bg2)}
.toolbox label.on{border-color:var(--acc);background:var(--bg3)}
.toolbox input{width:auto}
.editor{min-height:38vh}


/* the agent writes markdown; render it like prose, not like a log line */
.prose{font-size:13.5px;line-height:1.62}
.prose p{margin:0 0 8px}
.prose p:last-child{margin-bottom:0}
.prose h4{margin:12px 0 6px;font-size:13px;font-weight:650;color:var(--fg)}
.prose h4:first-child{margin-top:0}
.prose ul,.prose ol{margin:0 0 8px;padding-left:20px}
.prose li{margin:2px 0}
.prose code{font-family:var(--mono);font-size:12.2px;background:var(--bg3);
  border:1px solid var(--line);border-radius:4px;padding:1px 5px}
.prose pre.code{font-family:var(--mono);font-size:12px;background:var(--bg3);
  border:1px solid var(--line);border-radius:7px;padding:9px 11px;overflow-x:auto;
  margin:8px 0;white-space:pre;line-height:1.5}
.prose pre.code code{background:none;border:0;padding:0}
.prose b{font-weight:650;color:var(--fg)}
.answer.prose{padding:15px 17px}


/* a message typed while the agent is still working */
.ev.queued{border-left:3px solid var(--warn);background:var(--bg3)}
.queued-note{font-size:11.5px;color:var(--warn);padding:6px 20px 0}
.reply.busy input{opacity:.85}

/* the composer: the way in, on the screen rather than behind a button */
.composer{max-width:760px;display:grid;gap:12px;padding:8px 0}
.composer h2{margin:0;font-size:16px}
.composer textarea{min-height:120px}
.crow{display:flex;align-items:center;gap:14px}
.crow .btn{margin-left:auto}
.composer .rolepick .r{padding:8px 11px}

/* the agent writes markdown tables constantly; they arrived as literal pipes */
.prose table{border-collapse:collapse;margin:10px 0;font-size:12.5px;display:block;
  overflow-x:auto;max-width:100%}
.prose th,.prose td{border:1px solid var(--line);padding:5px 9px;text-align:left;
  vertical-align:top}
.prose th{background:var(--bg3);font-weight:600;white-space:nowrap}
.prose tbody tr:nth-child(even){background:var(--bg2)}


/* a failure the user can actually see */
.banner{position:fixed;top:0;left:0;right:0;z-index:50;background:var(--err);color:#fff;
  padding:9px 16px;font-size:13px;display:flex;align-items:center;gap:12px;
  box-shadow:0 1px 6px #0004}
.banner[hidden]{display:none !important}
.banner .link{color:#fff;margin-left:auto;opacity:.85}
.banner .link:hover{color:#fff;opacity:1}

/* Good news, bottom right, gone in seven seconds.
   It used to be the error strip in green: full width, pinned to the top over the toolbar so the
   buttons underneath could not be clicked, and staying until somebody pressed dismiss. A
   confirmation that has to be dismissed is a confirmation charging rent. */
#toasts{position:fixed;right:18px;bottom:18px;z-index:60;display:flex;flex-direction:column;
  gap:8px;align-items:flex-end;pointer-events:none}
.toast{
  pointer-events:auto;cursor:pointer;max-width:min(460px,60vw);
  background:var(--ok);color:#fff;font-size:13px;line-height:1.5;
  padding:10px 14px;border-radius:9px;box-shadow:0 4px 16px rgba(25,19,37,.22);
  animation:toast-in .18s ease-out}
.toast.out{opacity:0;transform:translateY(6px);transition:opacity .2s,transform .2s}
@keyframes toast-in{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}

/* what a session cost */
.usage{display:flex;gap:12px;flex-wrap:wrap;font-family:var(--mono);font-size:11px;
  color:var(--fg3);margin-top:8px}
.usage b{color:var(--fg2);font-weight:600}

/* Artifacts an agent produced. A list, not cards: the question is "which edition", so the
   titles must line up and scan vertically. */
.artifacts-h { margin: 22px 0 8px; font-size: 13px; letter-spacing: .04em; text-transform: uppercase; opacity: .65; }
.artifacts { display: flex; flex-direction: column; gap: 2px; }
.artifacts.muted { padding: 8px 0; }
a.artifact {
  display: flex; justify-content: space-between; align-items: baseline; gap: 12px;
  padding: 8px 10px; border-radius: 6px; text-decoration: none; color: inherit;
  border: 1px solid transparent;
}
a.artifact:hover { background: rgba(127, 127, 127, .10); border-color: rgba(127, 127, 127, .22); }
.artifact-title { font-weight: 500; }
.artifact-meta { font-size: 12px; opacity: .6; white-space: nowrap; }

/* In a session the artifact list sits above the answer, so it reads as part of the result
   rather than as an appendix to it. */
.session-artifacts { margin: 10px 0 4px; }
.session-artifacts a.artifact { border-color: rgba(127, 127, 127, .22); }

/* ── authoring ─────────────────────────────────────────────────────────────── */
/* A draft has to look unfinished at a glance. The list mixes drafts with the agents the team
   actually depends on, and the difference between them is who gets routed to them. */
.pill.draft{background:color-mix(in srgb,var(--warn) 18%,transparent);
  border-color:var(--warn);color:var(--warn)}
.notice{border:1px solid var(--warn);border-radius:8px;padding:11px 13px;margin:12px 0;
  background:color-mix(in srgb,var(--warn) 8%,transparent);line-height:1.6}
.notice .editbar{margin-top:10px}
/* The one line an agent sees when choosing a skill, and the one a router matches. Both are
   fields people leave blank because nothing tells them what they are for. */
.hint{display:block;color:var(--fg2);font-size:11.5px;margin-top:4px;line-height:1.5}
.history{margin-top:14px;border-top:1px solid var(--line);padding-top:10px}
.history summary{cursor:pointer;color:var(--fg2);font-size:12px}
.hrow{display:flex;justify-content:space-between;align-items:center;gap:12px;
  padding:5px 0;font-size:12px;color:var(--fg2);border-bottom:1px solid var(--line)}
.hrow:last-child{border-bottom:0}

/* connections
   A connector card has to answer one question at a glance: is this MINE, the company's, or
   neither. Colour does that -- green for connected, muted for the deployment's own credential,
   amber for something an operator has to do first -- so the state is legible before the label
   is read. */
.pad-h{padding:14px 20px 0;margin:0;font-size:15px}
.conn{background:var(--bg2);border:1px solid var(--line);border-radius:10px;padding:14px 16px;
  display:grid;gap:8px 12px;grid-template-columns:auto 1fr auto;align-items:start}
/* The operator instruction spans the whole row, tile included, or it starts halfway across. */
.conn .setup{grid-column:1/-1}
.conn.connected{border-left:3px solid var(--ok)}
.conn.workspace{border-left:3px solid var(--fg2)}
.conn.unavailable{border-left:3px solid var(--warn)}
.conn h3{margin:0;font-size:14.5px;display:flex;align-items:center;gap:8px}
.conn p{margin:4px 0 0;color:var(--fg2);font-size:13px;line-height:1.55}
.conn .who{font-family:var(--mono);font-size:11px;border:1px solid var(--line);border-radius:4px;
  padding:1px 6px;color:var(--fg2)}
.conn .acts{display:flex;gap:7px;align-items:center}
/* An operator instruction carries a redirect URI and two variable names -- all three get
   pasted into a console, so they have to be selectable and unwrapped rather than prose. */
.conn .setup{grid-column:1/-1;font-family:var(--mono);font-size:11.5px;color:var(--warn);
  background:var(--bg3);border:1px solid var(--line);border-radius:6px;padding:8px 10px;
  overflow-x:auto;white-space:pre-wrap;word-break:break-all;line-height:1.6}

/* An account an agent asks for but nobody has connected. Said in the picker rather than left
   for runtime: a ticked Gmail with no connection gives an agent that correctly reports it could
   not look, which reads as a broken agent unless the form warned first. */
.conn-pick .unconn{color:var(--warn);font-size:11px;font-family:var(--mono)}
.notice ul{margin:6px 0 0;padding-left:18px}
.notice li{margin:2px 0}
/* Whose account a connector uses. Said on the checkbox and on the card, because "the company's
   Notion" and "your Notion" answer different questions and the difference is invisible
   otherwise -- an author ticking a box cannot tell which one the agent will read. */
.whose{color:var(--fg2);font-size:11px;font-weight:400;font-family:var(--mono)}
.conn h3 .whose{margin-left:2px}
/* A personal agent, in the list. Not a warning — a fact about whose it is, and the reason
   nobody else can see the row at all. */
.pill.mine{border-color:var(--acc);color:var(--acc)}

/* "Your wallet is not on the list" -- the one refusal a person cannot retry their way out of,
   so it reads as an instruction with the address to hand rather than as a red error line. */
#walletErr{color:var(--err);font-size:13px;margin-top:8px;line-height:1.5}
#walletErr .walletAddr{display:flex;gap:6px;align-items:center;margin-top:8px}
#walletErr code{
  flex:1;min-width:0;overflow-x:auto;white-space:nowrap;
  font-family:var(--mono);font-size:11px;color:var(--fg2);
  background:var(--bg3);border:1px solid var(--line);border-radius:6px;padding:6px 8px;
}
#walletErr button{
  font:inherit;font-size:12px;cursor:pointer;padding:6px 10px;
  color:var(--fg2);background:var(--bg2);border:1px solid var(--line);border-radius:6px;
}

/* A connector's face: a brand-coloured monogram rather than a logo file. See `brand()` in
   app.js for why — no network, no trademark redrawn slightly wrong, and a connector added
   tomorrow gets a colour without anyone editing a map. */
.tile{
  display:inline-grid;place-items:center;flex-shrink:0;
  width:30px;height:30px;border-radius:7px;
  color:#fff;font-size:12px;font-weight:700;letter-spacing:-0.02em;
  font-family:var(--sans);
  box-shadow:inset 0 0 0 1px rgba(0,0,0,.08);
}
.card h3 .tile{width:22px;height:22px;font-size:10px;border-radius:5px;vertical-align:-6px}

/* Three chips that choose what the list shows. In the topbar, so the heading and the filter
   read as one control rather than the filter looking like part of the first section. */
.segmented{display:flex;gap:2px;margin-left:auto;background:var(--bg3);border:1px solid var(--line);
  border-radius:8px;padding:2px}
.segmented .seg{font:inherit;font-size:12px;cursor:pointer;padding:4px 11px;border:0;border-radius:6px;
  background:none;color:var(--fg2)}
.segmented .seg:hover{color:var(--fg)}
.segmented .seg.on{background:var(--bg2);color:var(--fg);box-shadow:0 1px 2px rgba(0,0,0,.06)}

/* WHOSE agent, on the list. A flat list of names says nothing about who to ask when one
   misbehaves, or who has already built the thing you are about to build. */
.list .group{position:sticky;top:0;z-index:1;background:var(--bg);
  padding:10px 14px 5px;font-size:11px;font-weight:600;letter-spacing:.03em;
  text-transform:uppercase;color:var(--fg3);border-bottom:1px solid var(--line)}
.list .item .by{margin-top:3px;font-size:11px;color:var(--fg3)}
.list .item.locked{opacity:.72}
.pill.locked{background:var(--bg3);color:var(--fg2);border:1px solid var(--line)}
.detail .meta .by{font-size:11.5px;color:var(--fg3)}

/* Search, beside the filter chips. With thirty-odd connectors, scanning is no longer the way
   anyone finds one. */
.topbar .search{
  margin-left:auto;font:inherit;font-size:13px;width:min(260px,34vw);
  padding:6px 10px;border:1px solid var(--line);border-radius:8px;
  background:var(--bg2);color:var(--fg);
}
.topbar .search:focus{outline:none;border-color:var(--acc)}
.topbar .search::placeholder{color:var(--fg3)}
/* The segmented control sits next to it rather than pushing off the right edge. */
.topbar .search + .segmented{margin-left:8px}

/* Connected: a tick, not a word. Three labels saying overlapping things is what "Connected /
   yours / yours only" had become; this is the one a person scans for. */
.conn .tick{
  display:inline-grid;place-items:center;width:16px;height:16px;border-radius:50%;
  background:var(--ok);color:#fff;font-size:10px;line-height:1;flex-shrink:0;
}
.conn .tick.shared{background:var(--fg2)}

/* The connectors view scrolls as one column. Its sections are headings and lists in a single
   flow, so scrolling them separately made the page feel like two panes that happened to be
   stacked — and with thirty-four connectors it clipped the list outright. */
#view-health .scroll{flex:1;min-height:0;overflow-y:auto;padding-bottom:24px}
/* An intro line is one line. `.pad` gives it a scroll container's padding, which above a grid
   that has its own reads as a gap somebody forgot to close. */
.muted.pad.tight{padding:12px 20px 2px;margin:0}
/* Two segmented controls in one bar. The scope tabs sit next to the title and STAY there —
   `margin-right:auto` rather than letting the search push them, or they slide across the bar
   when the search is hidden on the Workspace tab and the thing you just clicked has moved. */
#connScope{margin-left:16px;margin-right:auto}
#view-health .scroll .cards{overflow:visible}

/* What a connected account may do. Collapsed by default, because the answer is almost always
   "all of it" — and reads/writes are separate groups with a header checkbox each, so "no
   writes", the case anyone actually wants, is one click rather than eleven. */
.conn .tools{grid-column:1/-1;margin-top:10px;padding-top:10px;border-top:1px solid var(--line)}
.conn .thead{display:flex;align-items:center;gap:10px;font-size:12px;font-weight:600;
  color:var(--fg2);margin-bottom:6px}
.conn .thead .link{font-weight:400}
.conn .tlist{display:flex;flex-wrap:wrap;gap:2px 14px;margin:6px 0 10px}
.conn .titem{display:inline-flex;align-items:center;gap:6px;font-size:12px}
.conn .titem code{font-family:var(--mono);font-size:11px;color:var(--fg2)}
/* A tag only where the SERVER said so. No tag means we do not know, which is different from
   "write" and must not look the same. */
.conn .tkind{font-size:9.5px;text-transform:uppercase;letter-spacing:.04em;
  padding:1px 5px;border-radius:4px;background:var(--bg3);color:var(--fg3)}
.conn .tkind.read{color:var(--ok)}
.conn .tkind.write{color:var(--warn)}
.conn .small{font-size:11.5px;line-height:1.5;margin:4px 0 8px}
.conn .tacts{display:flex;justify-content:flex-end}

/* The "+ N more nobody has connected yet" expander in the agent form. */
.conn-pick .more{width:100%;margin-top:6px}
.conn-pick .rest{display:contents}
.conn-pick .rest[hidden]{display:none}

/* A field that is wrong SAYS SO WHERE IT IS. The message used to be prose in a bar at the top
   of the window — behind the modal, unreadable — with nothing to say which box it meant. */
.field input.bad,.field select.bad,.field textarea.bad{
  border-color:var(--err);box-shadow:0 0 0 2px color-mix(in srgb,var(--err) 18%,transparent)}
/* Above the buttons, not below them: an error under the footer is off the bottom of a scrolled
   modal at the moment somebody presses Create. */
#modalBody .err{color:var(--err);font-size:12.5px;line-height:1.5;margin:2px 0 0;min-height:0}
#modalBody .err:empty{display:none}

/* The derived variable names, in the custom-connector form. Monospace and selectable: they get
   typed into the `howto` right below, and into a curl somebody tries by hand. */
.vars{display:flex;flex-wrap:wrap;gap:6px}
.vars code{font-family:var(--mono);font-size:11.5px;color:var(--fg2);
  background:var(--bg3);border:1px solid var(--line);border-radius:5px;padding:3px 7px}

/* Connectors in the agent form, grouped by whose account rather than labelled per row. */
.conn-pick .cgroup{width:100%;display:flex;flex-wrap:wrap;gap:6px;margin-bottom:8px}
.conn-pick .chead{width:100%;font-size:11px;font-weight:600;letter-spacing:.03em;
  text-transform:uppercase;color:var(--fg3);margin:2px 0 2px}
.conn-pick .chead .muted{text-transform:none;letter-spacing:0;font-weight:400}

/* WHICH SKILLS AN AGENT MAY REACH. Collapsed behind one checkbox, because the answer is
   usually "all of them" and the list is long — and the description is the reason to show
   them at all: it is what the model matches on when it decides to reach for one. */
.skillbox{border:1px solid var(--line);border-radius:8px;padding:10px 12px;background:var(--bg2)}
.skillbox .thead{display:flex;align-items:center;gap:8px;font-size:12.5px;color:var(--fg);margin:0}
.skillbox .picked{margin-top:10px;padding-top:8px;border-top:1px solid var(--line);
  max-height:240px;overflow-y:auto}
.skillbox .sgroup{margin-bottom:10px}
.skillbox .chead{font-size:10.5px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;
  color:var(--fg3);margin:0 0 4px}
.skillbox .sitem{display:flex;align-items:flex-start;gap:7px;margin:0 0 5px;font-size:12px;
  line-height:1.45;cursor:pointer}
.skillbox .sitem code{font-family:var(--mono);font-size:11.5px;color:var(--fg)}
.skillbox .sitem .muted{display:block;font-size:11px}

/* Variables on a custom connector: name, value, remove — and a + button. Whatever the thing
   needs, rather than a url/username/password schema that fits one system and not the next. */
.varlist{display:flex;flex-direction:column;gap:6px;margin-bottom:7px}
.varrow{display:grid;grid-template-columns:1fr 1fr auto;gap:6px;align-items:center}
.varrow .vname{font-family:var(--mono);font-size:12px}
.varrow input[readonly]{background:var(--bg3);color:var(--fg2)}
.varrow .link{font-size:11.5px}
