/* ═══════════════════════════════════════════════════════════════════════════════════════════════
   AgentConnect MCP UI

   DIRECTION — a precision instrument readout, not a dashboard.

   Deliberately avoided, because they are the house style of generated interfaces: floating rounded
   cards with drop shadows, a coloured accent bar down the left of every card, evenly-weighted panels,
   emoji section markers, gradient heroes, purple.

   Used instead, because it is how real measurement equipment reads:
     · one continuous surface divided by HAIRLINES — regions, not objects
     · extreme type-scale contrast: 9px wide-tracked mono labels against 30px numerals
     · large tabular numerals in the header, the way an instrument shows its values
     · a time gutter down the trace, like a chart recorder
     · colour spent ONLY on live state and the primary action; everything else is ink
     · asymmetry — the graph is the hero and takes the space to prove it

   Palette is AgentConnect's own: #3D7BFF working accent, #F751AD for the sparkle mark (sampled from
   the real logo), #12151C ink. Light is the default, matching the product; dark is equally complete
   and shares the same accent. Every rule reads a token, so a theme swap is never a component rewrite.
   ═══════════════════════════════════════════════════════════════════════════════════════════════ */

:root {
  --bg:        #F4F6FA;
  --panel:     #FFFFFF;
  --panel-2:   #F7F9FC;
  --sunk:      #EFF2F7;
  --ink:       #12151C;
  --ink-2:     #4A5364;
  --faint:     #949CAC;
  --ghost:     #C3C9D6;
  --rule:      #E3E7EF;
  --rule-2:    #D5DAE5;

  --accent:      #2E62D6;
  --accent-2:    #3D7BFF;
  --accent-wash: #EAF1FF;
  --accent-rule: rgba(61,123,255,.30);
  --glow:        rgba(61,123,255,.30);
  --on-accent:   #FFFFFF;

  /* the logo mark's pink, sampled from public/lyriq-logo.png */
  --brand: #F751AD;

  --ok: #0F8B44;  --warn: #B3690A;  --err: #C42B2B;

  --k-trigger:  #0F8B44;
  --k-agent:    #6D5FE0;
  --k-tool:     #2E62D6;
  --k-gate:     #B3690A;
  --k-transform:#0A7C8A;
  --k-outcome:  #6B7383;
  --k-parallel: #8A5CC4;
  --k-loop:     #A0522D;

  --grid: rgba(18,21,28,.035);

  /* Washes. The base design withheld colour on purpose; these are what let state read at a
     glance instead of being decoded from a 6px dot. */
  --ok-wash:    #E7F6EE;
  --warn-wash:  #FDF3E3;
  --err-wash:   #FDECEC;
  --head:       linear-gradient(180deg, #FBFCFE, #F6F8FC);

  --sans: "Plus Jakarta Sans", ui-sans-serif, system-ui, -apple-system, Segoe UI, sans-serif;
  --mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
}

[data-theme="dark"] {
  --bg:        #080A0F;
  --panel:     #0E1219;
  --panel-2:   #12171F;
  --sunk:      #0A0D13;
  --ink:       #EDF0F6;
  --ink-2:     #99A2B4;
  --faint:     #626B7D;
  --ghost:     #39414F;
  --rule:      rgba(255,255,255,.07);
  --rule-2:    rgba(255,255,255,.12);

  --accent:      #5B8DFF;
  --accent-2:    #7BA5FF;
  --accent-wash: rgba(61,123,255,.13);
  --accent-rule: rgba(91,141,255,.32);
  --glow:        rgba(61,123,255,.45);
  --brand: #F751AD;

  --ok: #2ECC8B;  --warn: #E0A427;  --err: #F2626B;

  --k-trigger:  #2ECC8B;
  --k-agent:    #9B87F5;
  --k-tool:     #5B8DFF;
  --k-gate:     #E0A427;
  --k-transform:#22C3D6;
  --k-outcome:  #7C8698;
  --k-parallel: #C08AE8;
  --k-loop:     #D08A5A;

  --grid: rgba(255,255,255,.022);

  --ok-wash:    rgba(46,204,139,.12);
  --warn-wash:  rgba(224,164,39,.13);
  --err-wash:   rgba(242,98,107,.13);
  --head:       linear-gradient(180deg, #131922, #10151C);
}

* { box-sizing: border-box; }
html, body { height: 100%; }

body {
  margin: 0;
  font-family: var(--sans);
  color: var(--ink);
  background-color: var(--bg);
  background-image:
    linear-gradient(var(--grid) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid) 1px, transparent 1px);
  background-size: 44px 44px, 44px 44px;
  -webkit-font-smoothing: antialiased;
  display: flex; flex-direction: column; overflow: hidden;
}

.mono { font-family: var(--mono); font-variant-numeric: tabular-nums; }

/* ── header ─────────────────────────────────────────────────────────────────────────────────── */

.bar {
  flex: none;
  display: grid; grid-template-columns: auto auto 1fr; align-items: center; gap: 28px;
  padding: 0 20px; height: 74px;
  background: var(--panel);
  border-bottom: 1px solid var(--rule);
}

.brand { display: flex; align-items: center; gap: 11px; min-width: 0; }
.mark { width: 24px; height: 24px; flex: none; }
/* Brand pink, sampled from the real logo. It is the identity mark only — the working accent stays
   AgentConnect's blue, exactly as the product itself uses them. */
.mk-star { fill: var(--brand); }
.brand:hover .mk-star { animation: star-breathe 3.2s ease-in-out infinite; }
@keyframes star-breathe { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.07); } }
.mark { transform-box: fill-box; transform-origin: center; }

.brand-txt h1 {
  margin: 0; font-size: 14.5px; font-weight: 800; letter-spacing: -.024em; line-height: 1.15;
  white-space: nowrap; color: var(--ink);
}
.brand-txt h1 .sep { color: var(--ghost); font-weight: 400; margin: 0 3px; }
.brand-txt h1 em { font-style: normal; font-weight: 600; color: var(--accent); }
.brand-txt p {
  margin: 3px 0 0; font-family: var(--mono); font-size: 9.5px; letter-spacing: .10em;
  text-transform: uppercase; color: var(--faint); white-space: nowrap;
}

/* the instrument readout — the one place with big numbers */
.readout { display: flex; align-items: stretch; gap: 0; }
.ro {
  display: flex; flex-direction: column; justify-content: center; gap: 3px;
  padding: 0 20px; min-width: 96px;
  border-left: 1px solid var(--rule);
}
.ro:last-child { border-right: 1px solid var(--rule); }
.ro-k {
  font-family: var(--mono); font-size: 8.5px; letter-spacing: .16em; text-transform: uppercase;
  color: var(--faint);
}
.ro-v {
  font-family: var(--mono); font-size: 27px; font-weight: 500; line-height: 1;
  letter-spacing: -.03em; color: var(--ink); font-variant-numeric: tabular-nums;
  transition: color .2s;
}
.ro-v small { font-size: 17px; font-weight: 400; color: var(--ink-2); }
.ro-v i { font-style: normal; font-size: 13px; color: var(--faint); margin-left: 2px; }
/* Idle means these numbers are all zero, and 27px numerals shouting four zeros is the loudest
   thing on a screen where nothing has happened yet. Recede until there is something to report. */
.readout .ro-v { color: var(--ghost); }
.readout.is-live .ro-v { color: var(--accent); }
.readout.is-live { background: var(--accent-wash); }
.readout, .readout .ro-v { transition: color .25s, background .25s; }

.ro-state .ro-v {
  font-size: 12px; letter-spacing: .10em; text-transform: uppercase; font-weight: 600;
  color: var(--faint); padding-top: 8px;
}
.ro-state .ro-v.is-running { color: var(--accent); }
.ro-state .ro-v.is-done    { color: var(--ok); }
.ro-state .ro-v.is-failed  { color: var(--err); }

.lights { display: flex; align-items: center; justify-content: flex-end; gap: 7px; }

/* Not connected is not a status, it is the only available action — nothing in the app works until a
   token is pasted. So it is styled as a call to action until it succeeds, then recedes to a chip. */
.who:not(.on) {
  background: var(--accent); border-color: var(--accent); color: var(--on-accent);
  font-weight: 600; box-shadow: 0 6px 18px -10px var(--glow);
}
.who:not(.on) .who-text { color: var(--on-accent); }
.who:not(.on) .dot { background: var(--on-accent); animation: pulse 1.8s ease-in-out infinite; }
.who:not(.on):hover { background: var(--accent-2); border-color: var(--accent-2); }
.who.on { background: var(--ok-wash); border-color: color-mix(in srgb, var(--ok) 30%, transparent); }
.who.on .dot { background: var(--ok); }
.readout { margin-left: 4px; }
.light {
  display: inline-flex; align-items: center; gap: 7px; padding: 5px 10px 5px 8px;
  border: 1px solid var(--rule); border-radius: 3px; background: var(--panel-2);
  font-family: var(--mono); font-size: 10px; letter-spacing: .04em;
}
.light { border-radius: 99px; }
.light .lbl { color: var(--faint); text-transform: uppercase; }
.light .val { color: var(--ink-2); }
.light .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--ghost); flex: none; }
/* Tint the chip, not just the dot. Three 6px dots in a row is a puzzle; three coloured chips is a
   status line you read without stopping. */
.light.is-ok   { background: var(--ok-wash);   border-color: color-mix(in srgb, var(--ok) 30%, transparent); }
.light.is-warn { background: var(--warn-wash); border-color: color-mix(in srgb, var(--warn) 34%, transparent); }
.light.is-err  { background: var(--err-wash);  border-color: color-mix(in srgb, var(--err) 32%, transparent); }
.light.is-ok   .dot { background: var(--ok); }
.light.is-warn .dot { background: var(--warn); }
.light.is-err  .dot { background: var(--err); }
.light.is-ok   .val { color: var(--ok); font-weight: 600; }
.light.is-err  .val { color: var(--err); font-weight: 600; }
.light.is-live .dot { background: var(--accent); animation: pulse 1.5s ease-in-out infinite; }
@keyframes pulse { 0%,100% { box-shadow: 0 0 0 0 var(--glow); } 55% { box-shadow: 0 0 0 5px transparent; } }

.icon-btn {
  display: grid; place-items: center; width: 29px; height: 29px;
  border: 1px solid var(--rule); border-radius: 3px;
  background: var(--panel-2); color: var(--faint); cursor: pointer;
  transition: color .15s, border-color .15s;
}
.icon-btn:hover { color: var(--accent); border-color: var(--accent-rule); }

/* ── layout: asymmetric, graph dominant ─────────────────────────────────────────────────────── */

/* Two columns, not three. The graph and the trace are both horizontal things — a left-to-right
   workflow and a line-per-event log — so squeezing either into a narrow column wastes the space it
   most needs. Stacking them gives both the full width and lets the graph shrink honestly when there
   is nothing in it. */
.grid {
  flex: 1; min-height: 0;
  display: grid;
  grid-template-columns: 320px minmax(0, 1fr);
  background: var(--rule);
  gap: 1px;
}

.rail { display: grid; grid-template-rows: auto minmax(0, 1fr); gap: 1px; min-height: 0; background: var(--rule); }

/* Graph on top, trace below. The 1px gap is the page background showing through, which is what makes
   the regions read as divisions of one surface rather than as floating cards. */
.stage { display: grid; grid-template-rows: minmax(0, 1.1fr) minmax(0, 1fr); gap: 1px; min-height: 0; background: var(--rule); }

.region { display: flex; flex-direction: column; min-height: 0; background: var(--panel); }

.rhead {
  flex: none; display: flex; align-items: center; justify-content: space-between; gap: 10px;
  height: 44px; padding: 0 15px;
  background: var(--head);
  border-bottom: 1px solid var(--rule);
}
/* Sentence-case sans at a readable size. A 9.5px wide-tracked uppercase mono label is precise and
   almost unreadable; these are the signposts for the whole interface, so they read first. */
.rhead h2 {
  margin: 0; font-family: var(--sans); font-size: 13px; font-weight: 700;
  letter-spacing: -.015em; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
}
/* The measurement must never be the thing that gets clipped — it is the part that is precise. */
.rhead .tick { flex: none; white-space: nowrap; }
.tick { font-family: var(--mono); font-size: 9.5px; letter-spacing: .05em; color: var(--ghost); }
/* A shape that was described but not created must never be mistakable for one that was. */
.tick.is-sim { color: var(--warn); font-weight: 600; letter-spacing: .09em; }
.note { margin: 11px 15px 0; font-size: 11px; line-height: 1.5; color: var(--faint); }

/* ── compose ────────────────────────────────────────────────────────────────────────────────── */

#request {
  margin: 14px 15px 0; padding: 12px 13px;
  font-family: var(--sans); font-size: 13.5px; line-height: 1.6;
  color: var(--ink); background: var(--sunk);
  border: 1px solid var(--rule); border-radius: 4px;
  resize: vertical; min-height: 116px;
  transition: border-color .15s, box-shadow .15s;
}
#request::placeholder { color: var(--faint); }
#request:focus { outline: none; border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent-rule); }

/* Asking for a build with nothing written: draw the eye to the box rather than doing nothing. */
#request.nudge { animation: nudge .32s cubic-bezier(.36,.07,.19,.97) both; border-color: var(--warn); }
@keyframes nudge {
  10%, 90% { transform: translateX(-2px); }
  20%, 80% { transform: translateX(3px); }
  30%, 50%, 70% { transform: translateX(-4px); }
  40%, 60% { transform: translateX(4px); }
}

.presets { display: flex; flex-wrap: wrap; gap: 5px; padding: 11px 15px 0; }
.preset {
  font-family: var(--sans); font-size: 11.5px; font-weight: 600; letter-spacing: -.005em;
  padding: 6px 11px; border-radius: 99px; cursor: pointer;
  color: var(--accent); background: var(--accent-wash); border: 1px solid var(--accent-rule);
  transition: transform .12s, box-shadow .15s, background .15s;
}
.preset:hover { background: var(--accent); color: var(--on-accent); border-color: var(--accent); }
.preset:active { transform: translateY(1px); }

.actions { display: flex; gap: 7px; padding: 13px 15px 15px; }

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  height: 36px; padding: 0 15px;
  font-family: var(--sans); font-size: 12.5px; font-weight: 600; letter-spacing: -.005em;
  border-radius: 4px; border: 1px solid transparent; cursor: pointer;
  transition: background .15s, opacity .15s, box-shadow .15s;
}
.btn:disabled { opacity: .38; cursor: not-allowed; }
.btn.primary { flex: 1; background: var(--accent); color: var(--on-accent); box-shadow: 0 6px 18px -10px var(--glow); }
.btn.primary:hover:not(:disabled) { background: var(--accent-2); }
.btn.primary.is-running .btn-ico { animation: spin 1s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }
.btn.ghost { background: transparent; color: var(--faint); border-color: var(--rule); }
.btn.ghost:hover:not(:disabled) { color: var(--err); border-color: color-mix(in srgb, var(--err) 45%, transparent); }

.mini {
  font-family: var(--mono); font-size: 9.5px; letter-spacing: .10em; text-transform: uppercase;
  color: var(--ghost); background: none; border: 0; cursor: pointer; padding: 2px;
}
.mini:hover { color: var(--accent); }

/* ── artifacts ──────────────────────────────────────────────────────────────────────────────── */

.tabs { display: flex; gap: 0; padding: 12px 15px 0; flex: none; border-bottom: 1px solid var(--rule); }
.tab {
  font-family: var(--sans); font-size: 12.5px; font-weight: 600; letter-spacing: -.01em;
  padding: 7px 12px; cursor: pointer; position: relative; bottom: -1px;
  color: var(--faint); background: none; border: 0; border-bottom: 2px solid transparent;
  transition: color .14s;
}
/* The count is the useful part of a tab here, so give it a pill rather than making it a footnote. */
.tab b {
  display: inline-block; margin-left: 7px; padding: 1px 7px; border-radius: 99px;
  font-family: var(--mono); font-size: 10px; font-weight: 600;
  color: var(--faint); background: var(--sunk);
}
.tab:hover { color: var(--ink-2); }
.tab.is-on { color: var(--accent); border-bottom-color: var(--accent); }
.tab.is-on b { color: var(--on-accent); background: var(--accent); }

.list { flex: 1; min-height: 0; overflow-y: auto; }

.card {
  display: block; width: 100%; text-align: left; cursor: pointer;
  padding: 11px 15px; background: none;
  border: 0; border-bottom: 1px solid var(--rule); border-left: 2px solid transparent;
  transition: background .14s, border-left-color .14s;
  animation: rise .3s cubic-bezier(.2,.7,.3,1) both;
}
.card { border-left-width: 3px; }
.card:hover { background: var(--panel-2); border-left-color: var(--rule-2); }
.card.is-on { background: var(--accent-wash); border-left-color: var(--accent); }
/* Something this run created. Worth more than a 2px edge — it is the proof the build worked. */
.card.is-new { border-left-color: var(--ok); background: var(--ok-wash); }

.card .nm { font-size: 12.5px; font-weight: 600; color: var(--ink); letter-spacing: -.012em; display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.card .meta { display: flex; align-items: center; gap: 9px; margin-top: 5px; font-family: var(--mono); font-size: 9.5px; color: var(--faint); letter-spacing: .03em; }
.card .meta .new { color: var(--ok); font-weight: 600; letter-spacing: .1em; }
@keyframes rise { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }

/* ── trace: a chart recorder with a time gutter ─────────────────────────────────────────────── */

.trace .scroll { flex: 1; min-height: 0; overflow-y: auto; }

.ev {
  display: grid; grid-template-columns: 52px 1fr; gap: 11px;
  padding: 6px 15px 6px 0;
  position: relative;
  animation: slide .24s cubic-bezier(.2,.7,.3,1) both;
}
/* the recorder's rule — one continuous hairline the whole trace hangs off */
.ev::before {
  content: ""; position: absolute; left: 52px; top: 0; bottom: 0;
  border-left: 1px solid var(--rule);
}
.ev:first-child::before { top: 9px; }
@keyframes slide { from { opacity: 0; transform: translateX(-5px); } to { opacity: 1; transform: none; } }

.ev .t {
  font-family: var(--mono); font-size: 9.5px; color: var(--ghost);
  text-align: right; padding-top: 2px; font-variant-numeric: tabular-nums;
}
/* Full width now, so cap the measure — prose set to 1600px is unreadable no matter how good it is. */
.ev .body { padding-left: 13px; min-width: 0; max-width: 92ch; }

/* the tick on the rule marks a real event */
.ev .body::before {
  content: ""; position: absolute; left: 49px; top: 9px;
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--panel); border: 1.5px solid var(--ghost);
}
.ev-tool  .body::before { border-color: var(--accent); background: var(--accent); }
.ev-tool.bad .body::before { border-color: var(--err); background: var(--err); }
.ev-error .body::before { border-color: var(--err); background: var(--err); }
.ev-status .body::before { border-color: var(--ok); background: var(--panel); }

.ev-tool .nm { font-family: var(--mono); font-size: 11.5px; font-weight: 600; color: var(--ink); letter-spacing: -.01em; }
.ev-tool .ms { font-family: var(--mono); font-size: 9.5px; color: var(--ghost); margin-left: 8px; }
.ev-tool .rs { font-family: var(--mono); font-size: 10.5px; color: var(--faint); margin-top: 3px; line-height: 1.5; word-break: break-word; }
.ev-tool.bad .nm { color: var(--err); }

/* A tinted row per event type. The trace is the thing you actually read during a run, and a
   wall of uniform grey lines hides the one line that matters. */
.ev-error { background: var(--err-wash); }
.ev-warn  { background: var(--warn-wash); }
.ev-tool.bad { background: var(--err-wash); }
.ev-status .tx { border-radius: 99px; }

.ev-thought .tx { font-size: 12.5px; color: var(--ink-2); line-height: 1.55; }
.ev-status  .tx { font-family: var(--mono); font-size: 10.5px; color: var(--faint); letter-spacing: .04em; }
.ev-error   .tx { font-size: 12px; color: var(--err); line-height: 1.5; }
.ev-warn { border-left-color: var(--warn); }
.ev-warn .body::before { border-color: var(--warn); background: var(--panel); }
.ev-warn .tx { font-size: 12px; color: var(--warn); line-height: 1.5; }
.ev-out     .tx { font-family: var(--mono); font-size: 10px; color: var(--ghost); white-space: pre-wrap; word-break: break-word; line-height: 1.5; }

/* ── empty states ───────────────────────────────────────────────────────────────────────────── */

.empty {
  height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 14px; padding: 30px; text-align: center;
}
/* Was a 34px hairline, which read as a rendering artefact in a large empty panel. A soft tinted
   disc gives the space a centre and says "waiting", not "broken". */
.empty-rule {
  width: 44px; height: 44px; border-radius: 50%; background: var(--accent-wash);
  border: 1px solid var(--accent-rule); position: relative;
}
.empty-rule::after {
  content: ""; position: absolute; inset: 0; margin: auto;
  width: 10px; height: 10px; border-radius: 50%; background: var(--accent); opacity: .55;
}
.empty p {
  margin: 0; font-family: var(--sans); font-size: 13px; font-weight: 600; letter-spacing: -.012em;
  color: var(--ink-2); line-height: 1.6; text-transform: none;
}
.empty p span { display: inline-block; margin-top: 3px; font-size: 12px; font-weight: 400; color: var(--faint); letter-spacing: 0; }

/* ── graph ──────────────────────────────────────────────────────────────────────────────────── */

.canvas { min-height: 0; position: relative; }
.graph-wrap {
  flex: 1; min-height: 0; overflow: auto; padding: 40px;
  display: grid; place-items: center; position: relative;
}
/* Corner ticks — an instrument's plot frame. They give the space edges, so a small graph reads as
   correctly placed inside a measured field rather than adrift in emptiness. */
.graph-wrap::before, .graph-wrap::after {
  content: ""; position: absolute; width: 16px; height: 16px; pointer-events: none;
  border-color: var(--rule-2); border-style: solid; border-width: 0;
}
.graph-wrap::before { top: 18px; left: 18px;  border-top-width: 1px; border-left-width: 1px; }
.graph-wrap::after  { bottom: 18px; right: 18px; border-bottom-width: 1px; border-right-width: 1px; }
.canvas::before, .canvas::after {
  content: ""; position: absolute; width: 16px; height: 16px; pointer-events: none; z-index: 1;
  border-color: var(--rule-2); border-style: solid; border-width: 0;
}
.canvas::before { top: 56px; right: 18px; border-top-width: 1px; border-right-width: 1px; }
.canvas::after  { bottom: 18px; left: 18px; border-bottom-width: 1px; border-left-width: 1px; }
.graph-wrap svg { display: block; overflow: visible; max-width: 100%; height: auto; }

.gnode rect.body { fill: var(--panel); stroke: var(--rule-2); stroke-width: 1; filter: url(#nodeShadow); }
.gnode:hover rect.body { stroke: var(--accent); }
.gnode .port { fill: var(--panel); stroke: var(--rule-2); stroke-width: 1.4; }
.gnode:hover .port { stroke: var(--accent); }
.gnode .lbl  { font-family: var(--sans); font-size: 12.5px; font-weight: 600; fill: var(--ink); letter-spacing: -.012em; }
.gnode .kind { font-family: var(--mono); font-size: 8.5px; fill: var(--faint); letter-spacing: .14em; text-transform: uppercase; }
.gedge { stroke: var(--rule-2); stroke-width: 1.4; fill: none; }
.gedge-head { fill: var(--rule-2); }
.gnode .id { font-family: var(--mono); font-size: 8.5px; fill: var(--ghost); letter-spacing: .04em; }

/* While a run is live, dash the edges and march them — the one moment motion earns its place, because
   it is showing something actually moving through the graph. */
.is-running .gedge { stroke: var(--accent-rule); stroke-dasharray: 4 4; animation: flow 1.1s linear infinite; }
@keyframes flow { to { stroke-dashoffset: -16; } }
.gnode.appear { animation: pop .32s cubic-bezier(.2,.8,.3,1) both; }
@keyframes pop { from { opacity: 0; transform: translateY(7px); } to { opacity: 1; transform: none; } }

/* ── scrollbars / motion / responsive ───────────────────────────────────────────────────────── */

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--rule-2); border: 3px solid transparent; background-clip: content-box; border-radius: 99px; }
::-webkit-scrollbar-thumb:hover { background: var(--faint); background-clip: content-box; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; }
}

@media (max-width: 1180px) {
  .grid { grid-template-columns: 288px minmax(0, 1fr); }
  .readout .ro:nth-child(3) { display: none; }
}
@media (max-width: 880px) {
  body { overflow: auto; }
  .grid { grid-template-columns: 1fr; }
  .bar { grid-template-columns: 1fr auto; height: auto; padding: 12px 16px; row-gap: 12px; flex-wrap: wrap; }
  .readout { order: 3; width: 100%; }
  .ro:first-child { border-left: 0; padding-left: 0; }
  .stage { grid-template-rows: 420px 380px; }
}

/* ── not-connected helper in the rail ───────────────────────────────────────────────────────── */
.connect { padding: 18px 15px; }
.connect h3 {
  margin: 0 0 7px; font-family: var(--mono); font-size: 10px; letter-spacing: .14em;
  text-transform: uppercase; color: var(--warn);
}
.connect p { margin: 0 0 11px; font-size: 11.5px; line-height: 1.55; color: var(--ink-2); }
.connect code {
  display: block; padding: 7px 9px; margin-bottom: 12px; border-radius: 3px;
  background: var(--sunk); border: 1px solid var(--rule);
  font-size: 10px; color: var(--faint); word-break: break-all;
}
.connect ol { margin: 0; padding-left: 15px; display: flex; flex-direction: column; gap: 7px; }
.connect li { font-size: 11.5px; line-height: 1.5; color: var(--ink-2); }
.connect li::marker { font-family: var(--mono); font-size: 10px; color: var(--faint); }

/* ── rail overflow ─────────────────────────────────────────────────────────────────────────────
 * The left rail sits in a fixed 320px grid track, but a grid item's default `min-width: auto` means
 * it refuses to shrink below its content — so the request textarea, the example chips and the long
 * workflow names all pushed past the track and were clipped by the stage beside them.
 *
 * `min-width: 0` on the rail AND on its children is what actually lets the track govern the width;
 * setting it only on the rail leaves the nested grids doing the same thing one level down.
 * ──────────────────────────────────────────────────────────────────────────────────────────────*/
.rail,
.rail > *,
.rail > * > * {
  min-width: 0;
}
.rail {
  overflow: hidden;
}

/* The chip row wraps instead of running off the edge. */
.rail .presets,
.rail .actions {
  flex-wrap: wrap;
}

/* Anything holding a name or an id gets to wrap or ellipsize rather than set the rail's width. */
.rail textarea,
.rail input {
  width: 100%;
  max-width: 100%;
  box-sizing: border-box;
}
.rail .card,
.rail .card * {
  max-width: 100%;
}
.rail .card .id,
.rail .card .meta,
.rail .card .sub {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Prose in the rail wraps; a long unbroken id breaks rather than extending the column. */
.rail p,
.rail .note {
  overflow-wrap: anywhere;
}

/* ── agent prose ───────────────────────────────────────────────────────────────────────────────
 * Agent answers arrive as markdown. `.md` is the rendered form (see renderRich in app.js); every
 * other `.tx` keeps pre-wrap so that raw tool output and stack traces keep the line breaks that
 * make them readable at all.
 * ──────────────────────────────────────────────────────────────────────────────────────────────*/
.tx { white-space: pre-wrap; overflow-wrap: anywhere; }
.tx.md { white-space: normal; }

.md-p { margin: 0 0 8px; }
.md-p:last-child { margin-bottom: 0; }
.md-h { font-weight: 650; letter-spacing: -.01em; margin: 10px 0 6px; color: var(--ink); }
.md-list { margin: 0 0 8px; padding-left: 18px; }
.md-list li { margin: 2px 0; }
.md-code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: .92em;
  background: var(--chip, rgba(0,0,0,.05));
  border-radius: 4px;
  padding: 1px 4px;
}

/* A wide table scrolls in its own box — it must never widen the trace column. */
.md-tablewrap { overflow-x: auto; margin: 4px 0 10px; max-width: 100%; }
.md-table { border-collapse: collapse; font-size: 12px; min-width: 100%; }
.md-table th,
.md-table td {
  border: 1px solid var(--rule);
  padding: 5px 8px;
  text-align: left;
  vertical-align: top;
  white-space: normal;
}
.md-table th { font-weight: 650; background: var(--chip, rgba(0,0,0,.04)); position: sticky; top: 0; }
.md-table td code { white-space: nowrap; }


/* ── identity chip + connect dialog ────────────────────────────────────────────────────────────
   The chip names the person the agent will act as. It leads the header because a build that runs
   as the wrong identity looks exactly like a build that ran correctly, and there is nothing to see
   afterwards that would tell you which happened.
   ──────────────────────────────────────────────────────────────────────────────────────────────*/
.who {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 5px 11px 5px 9px; border: 1px solid var(--rule); border-radius: 999px;
  background: var(--card); color: var(--ink); font: inherit; font-size: 12px; cursor: pointer;
  max-width: 260px; transition: border-color .15s, background .15s;
}
.who:hover { border-color: var(--accent); }
.who .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--muted); flex: 0 0 auto; }
.who.on .dot { background: var(--ok, #15803d); }
.who-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.sheet {
  position: fixed; inset: 0; z-index: 60; display: grid; place-items: center;
  background: color-mix(in srgb, #0b1020 45%, transparent); backdrop-filter: blur(2px);
}
/* A class selector outranks the UA's `[hidden] { display: none }`, so without this the
   dialog is permanently on screen and `el.hidden = true` appears to do nothing. */
.sheet[hidden] { display: none; }
.sheet-card {
  width: min(460px, calc(100vw - 32px)); background: var(--card);
  border: 1px solid var(--rule); border-radius: 14px; padding: 22px;
  box-shadow: 0 24px 70px rgba(16, 24, 40, .22);
}
.sheet-card h2 { margin: 0; font-size: 17px; letter-spacing: -.01em; }
.sheet-sub { margin: 7px 0 16px; font-size: 13px; line-height: 1.6; color: var(--muted); }
.fld { display: block; margin-bottom: 12px; }
.fld > span { display: block; margin-bottom: 5px; font-size: 12px; color: var(--muted); }
.fld input {
  width: 100%; box-sizing: border-box; padding: 9px 11px; font: inherit; font-size: 13px;
  color: var(--ink); background: var(--bg); border: 1px solid var(--rule); border-radius: 9px;
}
.fld input:focus { outline: none; border-color: var(--accent); }
.chk { display: flex; gap: 9px; align-items: flex-start; font-size: 12px; line-height: 1.5; color: var(--muted); }
/* Replaces the old "remember this token" checkbox. Multi-tenant: a token is never written to disk,
   so this states the lifetime rather than offering a choice that would leak it. */
.sheet-note { margin: 0 0 14px; padding: 9px 11px; border-radius: 8px; background: var(--sunk, rgba(127,127,127,.08));
  border: 1px solid var(--line); font-size: 12px; line-height: 1.55; color: var(--muted); }
.chk input { margin-top: 2px; }
.sheet-err {
  margin: 12px 0 0; padding: 9px 11px; border-radius: 9px; font-size: 12.5px; line-height: 1.5;
  background: color-mix(in srgb, #b42318 8%, transparent); color: #b42318;
}
.sheet-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 18px; }
