:root {
  --bg: #0e0f13;
  --panel: #15171d;
  --panel-2: #1c1f27;
  --border: #262a33;
  --text: #e7e9ee;
  --muted: #8b919e;
  --accent: #ff7a45;
  --accent-2: #c061ff;
  --link: #7cc7ff;
  --ok: #38d39f;
  --warn: #ffc857;
  --err: #ff5d6c;
  --font-sans: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont,
               "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --scrollbar-track: rgba(255,255,255,0.035);
  --scrollbar-thumb: #343a46;
  --scrollbar-thumb-hover: #465061;
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; height: 100%; }
body {
  font-family: var(--font-sans);
  background: var(--bg);
  color: var(--text);
}
button, input, select, textarea { font-family: inherit; }
a { color: var(--link); text-decoration: none; }
a:hover { text-decoration: underline; }
code, pre { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
.muted { color: var(--muted); }

* {
  scrollbar-width: thin;
  scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track);
}

*::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}

*::-webkit-scrollbar-track {
  background: var(--scrollbar-track);
}

*::-webkit-scrollbar-thumb {
  background: var(--scrollbar-thumb);
  border: 3px solid transparent;
  border-radius: 999px;
  background-clip: padding-box;
}

*::-webkit-scrollbar-thumb:hover {
  background: var(--scrollbar-thumb-hover);
  background-clip: padding-box;
}

*::-webkit-scrollbar-corner {
  background: transparent;
}

/* Navigation */
.topnav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.75rem 1.25rem;
  background: var(--panel);
  border-bottom: 1px solid var(--border);
}
.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-weight: 600;
  color: var(--text);
}
.brand .dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--accent);
  display: inline-block;
}
.navlinks { display: flex; align-items: center; gap: 1rem; }
.navlinks a { color: var(--text); }
.navlinks .me { color: var(--muted); font-size: 0.9rem; }

.nav-left, .nav-right { display: flex; align-items: center; gap: 0.75rem; }
.nav-right a { color: var(--text); }

/* Hamburger button */
.nav-toggle {
  display: inline-grid;
  place-items: center;
  width: 36px;
  height: 36px;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text);
  cursor: pointer;
  transition: background-color 120ms ease, border-color 120ms ease;
}
.nav-toggle:hover { background: rgba(255,255,255,0.04); border-color: #3a3f4b; }
.nav-toggle[aria-expanded="true"] { background: rgba(255,255,255,0.06); border-color: #3a3f4b; }

/* User avatar button */
.user-btn {
  background: transparent;
  border: 0;
  padding: 0;
  cursor: pointer;
  border-radius: 999px;
  transition: box-shadow 120ms ease;
}
.user-btn:focus-visible { outline: 2px solid rgba(124,199,255,0.42); outline-offset: 3px; }
.user-avatar {
  display: inline-grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border-radius: 999px;
  background: linear-gradient(135deg, rgba(255,122,69,0.95), rgba(192,97,255,0.95));
  color: #1a0f0a;
  font-weight: 700;
  font-size: 0.82rem;
  letter-spacing: 0.02em;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.22);
}
.user-avatar.small { width: 28px; height: 28px; font-size: 0.74rem; }
.user-btn[aria-expanded="true"] { box-shadow: 0 0 0 2px rgba(124,199,255,0.32); }

/* Pop-out menus shared shell */
.nav-menu, .user-menu {
  position: fixed;
  top: 56px;
  z-index: 40;
  min-width: 220px;
  padding: 0.4rem;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: 0 18px 44px rgba(0,0,0,0.42);
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
}
.nav-menu { left: 1rem; }
.user-menu { right: 1rem; min-width: 260px; }
.nav-menu[hidden], .user-menu[hidden] { display: none; }

.nav-menu a,
.user-menu .menu-item {
  display: block;
  padding: 0.5rem 0.7rem;
  color: var(--text);
  border-radius: 7px;
  font-size: 0.92rem;
}
.nav-menu a:hover,
.user-menu .menu-item:hover {
  background: rgba(255,255,255,0.05);
  text-decoration: none;
}

/* User menu specifics */
.user-menu-head {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.55rem 0.7rem;
  margin-bottom: 0.2rem;
  border-bottom: 1px solid var(--border);
}
.user-menu-head strong { display: block; font-size: 0.92rem; }
.user-menu-head .muted { font-size: 0.78rem; word-break: break-all; }
.user-menu-meta { min-width: 0; }
.menu-form { margin: 0; }
.user-menu .menu-item {
  width: 100%;
  text-align: left;
  border: 0;
  background: transparent;
  font: inherit;
  cursor: pointer;
}
.user-menu .menu-item.danger { color: var(--err); }
.user-menu .menu-item.danger:hover { background: rgba(255,93,108,0.08); }

@media (max-width: 600px) {
  .brand-text { display: none; }
  .nav-menu, .user-menu { left: 0.5rem; right: 0.5rem; min-width: 0; }
}

/* General layout */
.wrap { max-width: 1100px; margin: 1.5rem auto; padding: 0 1.25rem; }
.page-head { display: flex; align-items: center; justify-content: space-between; gap: 1rem; }
.grid {
  display: grid;
  gap: 1rem;
  margin-top: 1rem;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}
.card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 1rem;
  box-shadow: 0 1px 0 rgba(255,255,255,0.02);
}
.cards {
  list-style: none;
  padding: 0;
  display: grid;
  gap: 1rem;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
}
/* Cards inside a .cards grid use column flex so a trailing affordance
   (e.g. .row-toggle on the Node library page) sticks to the bottom of
   the card regardless of how long the description above it is. Cards
   in each row line up at the bottom. */
.cards li.card {
  display: flex;
  flex-direction: column;
}
.cards li.card h3 { margin: 0 0 0.35rem; }
.row-toggle {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-top: auto;
  padding-top: 0.6rem;
  cursor: pointer;
  user-select: none;
}
/* Generic card-action row — used by every card list (Agents, Tools,
   Functions, Pipelines). Single flex row, sticks to the bottom of the
   card so each row's buttons line up across the grid.
   Two-button rows (Edit + Delete) split half/half via the :first-child +
   :nth-last-child(2) combo, which only matches when there are exactly two
   children. Cards with 3+ actions (e.g. pipeline-card with Open /
   Schedules / Triggers / Delete) keep natural widths and wrap via the
   more-specific .card.pipeline-card .card-actions rule below. */
.card-actions {
  display: flex;
  gap: 0.5rem;
  margin-top: auto;
  padding-top: 0.6rem;
  flex-wrap: wrap;
}
.card-actions > .btn:first-child:nth-last-child(2),
.card-actions > .btn:first-child:nth-last-child(2) ~ .btn {
  flex: 1 1 0;
}
.card.pipeline-card {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}
.card.pipeline-card .card-body { display: flex; flex-direction: column; gap: 0.35rem; }
.card.pipeline-card .card-body > :first-child { margin-top: 0; }
.card.pipeline-card .card-body p { margin: 0; }
.card.pipeline-card .card-actions {
  margin-top: auto;
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  padding-top: 0.4rem;
}
.rows { list-style: none; padding: 0; margin: 0; }
.rows li {
  display: flex;
  justify-content: space-between;
  gap: 0.8rem;
  padding: 0.5rem 0;
  border-bottom: 1px solid var(--border);
}

/* Forms */
form.stacked label, form.stacked p > label {
  display: block;
  color: var(--muted);
  margin-bottom: 0.25rem;
}
form.stacked {
  display: grid;
  gap: 0.9rem;
}
main.wrap > form.stacked {
  max-width: 720px;
  margin-top: 1rem;
  padding: 1rem;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: 0 1px 0 rgba(255,255,255,0.02);
}
form.stacked p {
  margin: 0;
}
form.stacked input[type="text"],
form.stacked input[type="email"],
form.stacked input[type="password"],
form.stacked input[type="url"],
form.stacked input[type="number"],
form.stacked input[type="file"],
form.stacked select,
form.stacked textarea,
.chat-form textarea,
.chat-form input[type="text"],
.builder-chat-form textarea,
.builder-chat-form input[type="text"],
.params-tools input,
.param-row input,
.param-row select {
  width: 100%;
  padding: 0.55rem 0.7rem;
  background: var(--panel-2);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 7px;
  font-size: 0.95rem;
}
form.stacked input:focus,
form.stacked select:focus,
form.stacked textarea:focus,
.chat-form textarea:focus,
.chat-form input[type="text"]:focus,
.builder-chat-form textarea:focus,
.builder-chat-form input[type="text"]:focus,
.params-tools input:focus,
.param-row input:focus,
.param-row select:focus {
  border-color: #59657b;
  outline: 2px solid rgba(124, 199, 255, 0.16);
  outline-offset: 0;
}
form.stacked textarea { font-family: ui-monospace, monospace; }
.form-field {
  display: grid;
  gap: 0.35rem;
}
.helptext {
  display: block;
  color: var(--muted);
  font-size: 0.82rem;
  line-height: 1.4;
}
.errorlist {
  list-style: none;
  padding: 0;
  margin: 0.25rem 0 0;
  color: #ff9aa4;
  font-size: 0.86rem;
}
.form-errors {
  padding: 0.7rem 0.85rem;
  border: 1px solid #5a1f29;
  border-radius: 8px;
  background: rgba(255, 93, 108, 0.08);
}
/* Global checkbox restyle — matches the step-toggle's custom box look so
   every checkbox in the app reads the same: dark square that turns accent-
   orange with a dark checkmark when checked. Per-spot rules with higher
   specificity (e.g. .step-toggle input) still win, so anything that hides
   or wraps the native input keeps working. */
input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  margin: 0;
  border: 1px solid #3a4150;
  border-radius: 4px;
  background-color: var(--panel-2);
  background-repeat: no-repeat;
  background-position: center;
  background-size: 12px 12px;
  cursor: pointer;
  vertical-align: middle;
  transition: background-color 120ms ease, border-color 120ms ease;
}
input[type="checkbox"]:hover:not(:disabled) { border-color: #59657b; }
input[type="checkbox"]:focus-visible {
  outline: 2px solid rgba(124, 199, 255, 0.32);
  outline-offset: 1px;
}
input[type="checkbox"]:checked {
  background-color: var(--accent);
  border-color: var(--accent);
  /* Inline SVG checkmark (stroke #1a0f0a, same near-black the step-toggle
     uses for contrast on the orange fill). Embedded as a data URI so the
     check renders without depending on ::after pseudo-element support on
     <input>, which is unreliable across browsers. */
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'><path d='M2 6.5l2.5 2.5L10 3.5' fill='none' stroke='%231a0f0a' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/></svg>");
}
input[type="checkbox"]:indeterminate {
  background-color: var(--accent);
  border-color: var(--accent);
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'><path d='M3 6h6' fill='none' stroke='%231a0f0a' stroke-width='2' stroke-linecap='round'/></svg>");
}
input[type="checkbox"]:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.checkbox-field label {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  margin: 0;
  color: var(--text);
}
/* The global rule already sizes + colors this — the field-specific block is
   kept empty to anchor the .checkbox-field hierarchy in case a future tweak
   needs it. */
.checkbox-field input[type="checkbox"] { /* inherits the global look */ }
.form-actions {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  flex-wrap: wrap;
}
.form-actions.split {
  justify-content: space-between;
}
[hidden] { display: none !important; }
.btn {
  display: inline-block;
  padding: 0.5rem 0.9rem;
  background: var(--panel-2);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 7px;
  cursor: pointer;
  font-size: 0.9rem;
  text-decoration: none;
}
.btn:hover { background: #262a33; text-decoration: none; }
.btn:focus-visible {
  outline: 2px solid rgba(124, 199, 255, 0.42);
  outline-offset: 2px;
}
.btn.primary {
  background: var(--accent);
  border-color: var(--accent);
  color: #1a0f0a;
  font-weight: 600;
}
.btn.primary:hover { background: #ff8b5d; border-color: #ff8b5d; }
.btn.danger { color: var(--err); border-color: #3a2228; }
.btn.danger:hover { background: #2a1a1f; }
.btn.full {
  width: 100%;
  text-align: center;
}

/* Auth */
.auth-main {
  min-height: calc(100vh - 61px);
  max-width: none;
  margin: 0;
  padding: 0;
}
.auth-shell {
  width: min(980px, calc(100% - 2rem));
  min-height: calc(100vh - 61px);
  margin: 0 auto;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(340px, 420px);
  align-items: center;
  gap: 2rem;
  padding: 2rem 0;
}
.auth-shell.compact {
  grid-template-columns: minmax(320px, 460px);
  justify-content: center;
}
.auth-copy {
  max-width: 460px;
}
.auth-copy .eyebrow {
  display: inline-block;
  margin-bottom: 0.85rem;
  color: var(--ok);
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.auth-copy h1 {
  margin: 0;
  font-size: 3.25rem;
  line-height: 1;
}
.auth-copy p {
  margin: 1rem 0 0;
  max-width: 36rem;
  color: #b8bfcc;
  font-size: 1.05rem;
  line-height: 1.6;
}
.auth-card {
  background: linear-gradient(180deg, rgba(28,31,39,0.98), rgba(18,20,27,0.98));
  border: 1px solid #303642;
  border-radius: 10px;
  padding: 1.2rem;
  box-shadow: 0 18px 44px rgba(0,0,0,0.34);
}
.auth-card-head {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  margin-bottom: 1.15rem;
}
.auth-card-head h2 {
  margin: 0;
  font-size: 1.2rem;
}
.auth-card-head p {
  margin: 0.18rem 0 0;
}
.auth-mark {
  width: 40px;
  height: 40px;
  flex: 0 0 auto;
  border-radius: 9px;
  background:
    linear-gradient(135deg, rgba(255,122,69,0.95), rgba(192,97,255,0.95));
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.22), 0 10px 20px rgba(0,0,0,0.28);
}
.auth-form {
  gap: 0.8rem;
}
.auth-links,
.auth-switch {
  display: flex;
  justify-content: space-between;
  gap: 0.75rem;
  margin: 1rem 0 0;
  color: var(--muted);
  font-size: 0.9rem;
}
.auth-switch {
  display: block;
  text-align: center;
}

/* Flash */
.flash { list-style: none; padding: 0; margin: 1rem auto; max-width: 1100px; }
.flash li {
  padding: 0.6rem 1rem;
  border-radius: 7px;
  margin-bottom: 0.5rem;
  background: var(--panel);
  border: 1px solid var(--border);
}
.flash li.flash-success { border-color: #1f5a45; }
.flash li.flash-error { border-color: #5a1f29; }

/* Tables */
table.data { width: 100%; border-collapse: collapse; margin-top: 1rem; }
table.data th, table.data td {
  padding: 0.55rem 0.7rem;
  border-bottom: 1px solid var(--border);
  text-align: left;
  vertical-align: top;
}
table.data thead { background: var(--panel); }
table.data td.actions-cell { text-align: right; white-space: nowrap; }
.tag {
  display: inline-block;
  padding: 1px 6px;
  border-radius: 4px;
  font-size: 0.75rem;
  background: var(--panel-2);
  border: 1px solid var(--border);
  color: var(--muted);
}

/* Chat shell */
.chat-shell { display: grid; grid-template-columns: 380px 1fr; height: calc(100vh - 60px); }
.chat-sidebar {
  background: var(--panel);
  border-right: 1px solid var(--border);
  padding: 1rem;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
}
.chat-canvas { background: var(--bg); position: relative; }
.canvas-embed { width: 100%; height: 100%; border: 0; }
.empty-canvas {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100%;
}

#messages { flex: 1; overflow-y: auto; margin: 1rem 0; padding-right: 0.25rem; }
.msg {
  padding: 0.65rem 0.8rem;
  border-radius: 9px;
  margin-bottom: 0.6rem;
  background: var(--panel-2);
  border: 1px solid var(--border);
}
.msg header {
  display: flex;
  justify-content: space-between;
  font-size: 0.78rem;
  color: var(--muted);
  margin-bottom: 0.25rem;
}
.msg-user { border-color: #2a3742; }
.msg-assistant { border-color: #3a2533; background: #1e1820; }
.msg-progress { border-color: #2a3a30; background: #15211d; color: #b6d8c8; font-size: 0.9rem; }
.msg-system { opacity: 0.8; font-style: italic; }
.run-status { font-size: 0.85rem; color: var(--muted); }
.run-failed { color: var(--err); }
.run-running { color: var(--link); }
.run-completed { color: var(--ok); }
.run-pending { color: var(--muted); }
.run-skipped { color: var(--muted); font-style: italic; }
.chat-form textarea { resize: vertical; }

/* Pipeline workbench */
.pipeline-workbench {
  width: 100%;
  height: calc(100vh - 61px);
  margin: 0;
  max-width: none;
  --sidebar-width: 380px;
  --sidebar-min-width: 380px;
  --sidebar-max-width: 680px;
}
.workbench-frame {
  height: 100%;
  display: flex;
  flex-direction: column;
  background: linear-gradient(180deg, rgba(20,22,29,0.96), rgba(12,13,18,0.98));
}
.workbench-topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  min-height: 56px;
  border-bottom: 1px solid var(--border);
  padding: 0.65rem 1rem;
}
.topbar-left {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  min-width: 0;
}
.topbar-left h1 {
  margin: 0;
  font-size: 1rem;
  font-weight: 600;
  outline: none;
  white-space: nowrap;
  text-overflow: ellipsis;
  overflow: hidden;
}
.save-state {
  display: inline-flex;
  align-items: center;
  max-width: 260px;
  padding: 0.15rem 0.45rem;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: rgba(255,255,255,0.03);
  font-size: 0.75rem;
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.save-state.is-error {
  border-color: rgba(255, 93, 108, 0.45);
  background: rgba(255, 93, 108, 0.08);
  color: #ffb3ba;
}
.topbar-actions { display: flex; align-items: center; gap: 0.5rem; }
.workbench-body {
  display: grid;
  grid-template-columns: minmax(var(--sidebar-min-width), var(--sidebar-width)) 8px minmax(0, 1fr);
  min-height: 0;
  flex: 1;
}
.workbench-sidebar {
  background: linear-gradient(180deg, rgba(24,26,34,0.96), rgba(16,18,25,0.98));
  display: flex;
  flex-direction: column;
  min-height: 0;
}
.sidebar-resizer {
  position: relative;
  z-index: 8;
  width: 8px;
  padding: 0;
  border: 0;
  border-left: 1px solid var(--border);
  border-right: 1px solid rgba(255,255,255,0.03);
  background: rgba(255,255,255,0.015);
  cursor: col-resize;
}
.sidebar-resizer::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 2px;
  height: 42px;
  border-radius: 999px;
  background: #3d4656;
  transform: translate(-50%, -50%);
  transition: background-color 120ms ease, box-shadow 120ms ease;
}
.sidebar-resizer:hover::before,
.sidebar-resizer:focus-visible::before,
.workbench-body.is-resizing .sidebar-resizer::before {
  background: var(--accent);
  box-shadow: 0 0 12px rgba(255, 122, 69, 0.34);
}
.sidebar-resizer:focus-visible {
  outline: 2px solid rgba(124, 199, 255, 0.42);
  outline-offset: -2px;
}
.workbench-body.is-resizing {
  user-select: none;
  cursor: col-resize;
}
.workbench-body.is-resizing .canvas-wrapper {
  pointer-events: none;
}
.sidebar-tabs {
  display: flex;
  gap: 0.4rem;
  padding: 0.75rem 0.75rem 0.55rem;
  border-bottom: 1px solid var(--border);
}
.tab-btn {
  background: transparent;
  border: 0;
  color: var(--muted);
  font-size: 0.86rem;
  padding: 0.4rem 0.35rem;
  border-bottom: 2px solid transparent;
  cursor: pointer;
}
.tab-btn.is-active {
  color: var(--text);
  border-bottom-color: var(--accent);
}
/* Unread-activity indicator. The dot is hidden by default and revealed when
   the tab button carries .has-unread (set by renderThread on new activity
   while the tab isn't focused; cleared on tab activation). */
.tab-btn { position: relative; display: inline-flex; align-items: center; gap: 0.35rem; }
.tab-unread-dot {
  display: none;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 6px rgba(255, 122, 69, 0.55);
}
.tab-btn.has-unread .tab-unread-dot { display: inline-block; }
.tab-panel { display: none; min-height: 0; }
.tab-panel.is-active { display: flex; flex-direction: column; flex: 1; }
#builder-messages { flex: 1; overflow-y: auto; padding: 0.75rem; }
.assistant-model-picker {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 0.4rem 0.55rem;
  align-items: center;
  margin: 0.65rem 0.75rem 0;
  padding: 0.55rem 0.65rem;
  border: 1px solid rgba(124, 199, 255, 0.16);
  border-radius: 8px;
  background: rgba(124, 199, 255, 0.05);
}
.assistant-model-picker label {
  color: var(--muted);
  font-size: 0.78rem;
}
.assistant-model-picker select,
.assistant-model-picker input {
  min-width: 0;
  padding: 0.42rem 0.5rem;
  border: 1px solid #2a303b;
  border-radius: 6px;
  background: rgba(12, 14, 18, 0.9);
  color: var(--text);
}
.assistant-model-picker input {
  grid-column: 2;
}
.assistant-model-hint {
  grid-column: 2;
  color: var(--muted);
  font-size: 0.74rem;
  line-height: 1.35;
}
.assistant-usage-summary {
  margin: 0.6rem 0.75rem 0;
  padding: 0.45rem 0.6rem;
  border: 1px solid rgba(124, 199, 255, 0.18);
  border-radius: 999px;
  background: rgba(124, 199, 255, 0.07);
  color: var(--muted);
  font-size: 0.78rem;
}
.builder-chat-form {
  position: relative;
  margin: 0.75rem;
  padding: 0.7rem 0.65rem 0.55rem;
  border-top: 1px solid var(--border);
  border: 1px solid #2a303b;
  border-radius: 8px;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  background: linear-gradient(180deg, rgba(28,31,39,0.96), rgba(20,22,29,0.98));
  box-shadow: 0 8px 20px rgba(0,0,0,0.18);
}
.builder-chat-form:focus-within {
  border-color: #4f5d73;
  box-shadow: 0 0 0 2px rgba(124, 199, 255, 0.12), 0 8px 20px rgba(0,0,0,0.2);
}
.builder-chat-form.is-locked {
  opacity: 0.78;
}
.builder-chat-form.is-locked:focus-within {
  border-color: #2a303b;
  box-shadow: 0 8px 20px rgba(0,0,0,0.18);
}
.builder-chat-form textarea {
  min-height: 28px;
  max-height: 240px;
  padding: 0.1rem 2.2rem 0.1rem 0.2rem;
  resize: none;
  overflow-y: hidden;
  background: transparent;
  border: 0;
  border-radius: 0;
  font-family: var(--font-sans);
  line-height: 1.45;
}
.builder-chat-form textarea:focus {
  border-color: transparent;
  outline: 0;
}
.builder-chat-form textarea::placeholder {
  color: #9ca5b5;
}
.builder-chat-form textarea:disabled {
  cursor: not-allowed;
}
.chat-locked-callout {
  margin: 0.75rem;
  padding: 0.85rem;
  border: 1px solid rgba(255, 177, 66, 0.42);
  border-radius: 8px;
  background: rgba(255, 177, 66, 0.08);
  color: var(--text);
}
.chat-locked-callout strong {
  display: block;
  margin-bottom: 0.35rem;
  color: #ffd37a;
}
.chat-locked-callout p {
  margin: 0 0 0.7rem;
  color: var(--muted);
  line-height: 1.45;
}
.assistant-usage-line {
  margin-top: 0.45rem;
  color: var(--muted);
  font-size: 0.76rem;
}

.params-header {
  padding: 0.75rem;
  border-bottom: 1px solid var(--border);
}
.params-header p { margin: 0 0 0.55rem; font-size: 0.86rem; }
.params-tools {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 0.5rem;
}
.parameter-rows {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 0.75rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.param-row {
  display: grid;
  grid-template-columns: 1fr 105px 1fr auto;
  gap: 0.45rem;
  align-items: center;
}
.param-row .btn { padding: 0.45rem 0.55rem; }

.palette-header {
  padding: 0.75rem;
  border-bottom: 1px solid var(--border);
}
.palette-header h3 { margin: 0; font-size: 0.95rem; }
.palette-header p { margin: 0.3rem 0 0; font-size: 0.8rem; }
.tab-panel[data-panel="nodes"] .palette {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 0.75rem;
}
.palette { display: flex; flex-direction: column; gap: 0.4rem; }
.palette h4 {
  margin: 0.6rem 0 0.15rem;
  font-size: 0.75rem;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.palette-item {
  padding: 0.55rem 0.68rem;
  background: linear-gradient(180deg, rgba(33,36,46,0.95), rgba(25,28,37,0.98));
  border: 1px solid var(--border);
  border-radius: 8px;
  cursor: grab;
  font-size: 0.86rem;
}
.palette-item:hover {
  border-color: #4d5568;
  transform: translateY(-1px);
}
.palette-item[data-kind="agent"]    { border-left: 3px solid var(--accent-2); }
.palette-item[data-kind="tool"]     { border-left: 3px solid #3aa6ff; }
.palette-item[data-kind="function"] { border-left: 3px solid #4dd0e1; }
.palette-item[data-kind="input"]    { border-left: 3px solid var(--ok); }
.palette-item[data-kind="output"]   { border-left: 3px solid var(--warn); }

.canvas-wrapper {
  position: relative;
  /* Clip the run-drawer when it's slid off-screen via translateX(100%).
     Without this, the off-screen drawer adds a horizontal scrollbar to the
     whole page. Drawflow already manages its own canvas extents inside
     #drawflow (which is position:absolute; inset:0), so clipping here is
     safe — wires can't render outside the wrapper anyway. */
  overflow: hidden;
  background:
    radial-gradient(circle at 22% 18%, rgba(255,255,255,0.06), transparent 45%),
    radial-gradient(circle at 84% 82%, rgba(255,122,69,0.08), transparent 38%),
    #0b0e14;
}
.canvas-wrapper::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0.45;
  background-image: radial-gradient(rgba(255,255,255,0.18) 0.9px, transparent 0.9px);
  background-size: 32px 32px;
}
#drawflow { position: absolute; inset: 0; }
.canvas-toolbar {
  position: absolute;
  top: 0.85rem;
  right: 0.85rem;
  z-index: 4;
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.35rem;
  border: 1px solid rgba(255,255,255,0.1);
  border-radius: 8px;
  background: rgba(18,20,27,0.88);
  box-shadow: 0 12px 28px rgba(0,0,0,0.28);
  backdrop-filter: blur(8px);
}
.canvas-tool-btn {
  display: inline-grid;
  place-items: center;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 7px;
  background: var(--panel-2);
  color: var(--text);
  cursor: pointer;
}
.canvas-tool-btn:hover {
  background: #262a33;
}
.canvas-tool-btn:focus-visible {
  outline: 2px solid rgba(124, 199, 255, 0.42);
  outline-offset: 2px;
}
.canvas-tool-btn:disabled {
  cursor: not-allowed;
  opacity: 0.45;
}
.canvas-tool-btn svg {
  width: 17px;
  height: 17px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.zoom-readout {
  min-width: 3.1rem;
  color: var(--muted);
  font-size: 0.8rem;
  text-align: center;
}

/* Drawflow nodes */
.drawflow .drawflow-node {
  background: linear-gradient(180deg, rgba(35,38,49,0.96), rgba(24,27,36,0.98));
  border: 1px solid #333a48;
  border-radius: 11px;
  color: var(--text);
  min-width: 200px;
  /* min-height set dynamically from JS based on socket count so all the
     input circles stay inside the node footprint. Drawflow's own layout
     (display: flex; align-items: center) is what pins the inputs/outputs
     to the left/right edges — DO NOT override it here. */
  box-shadow: 0 10px 22px rgba(0,0,0,0.38);
}
.drawflow .drawflow-node .node-head {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.6rem 0.75rem;
  border-bottom: 1px solid rgba(255,255,255,0.08);
  font-size: 0.9rem;
}
.drawflow .drawflow-node .node-head .badge {
  width: 22px;
  height: 22px;
  border-radius: 6px;
  display: inline-grid;
  place-items: center;
  font-size: 0.82rem;
  background: var(--accent-2);
  color: #fff;
}
.drawflow .drawflow-node .node-body {
  padding: 0.52rem 0.75rem 0.58rem;
  font-size: 0.78rem;
  color: #b3bac8;
}
.drawflow .drawflow-node.kind-tool .node-head .badge     { background: #3aa6ff; }
.drawflow .drawflow-node.kind-function .node-head .badge { background: #4dd0e1; color: #062a33; }
.drawflow .drawflow-node.kind-input .node-head .badge    { background: var(--ok); }
.drawflow .drawflow-node.kind-output .node-head .badge   { background: var(--warn); color: #1a0f00; }

/* Agent input_2 (tools/abilities) is lifted to the TOP of the node by JS
   (positionAgentTopSocket). The class is applied at runtime so old graphs
   keep working until the JS runs. */
.drawflow .drawflow-node.kind-agent .input.agent-top-input {
  position: absolute;
  top: -10px;
  margin: 0;
  /* `left` is set inline by JS based on node width so it stays centered.
     A subtle accent helps the user identify it as the abilities socket. */
  border: 2px solid var(--accent-2);
  background: rgba(192, 97, 255, 0.18);
}
.drawflow .drawflow-node.kind-agent .inputs {
  /* Let input_2 (lifted to the top) escape the column flex stack. */
  overflow: visible;
}
.drawflow .connection .main-path { stroke: #5a6070; stroke-width: 2px; }

/* Typed-edge visualisation.
   - Output socket: colored ring around the dot at the source side.
   - Connection path: same color, but as a soft tint so the line
     doesn't read as a hard "I'm a run-traversed edge" cue.
   See pipeline_builder.js _schemaTypeForUpstream + node_io.output_type_tag
   for the source of these labels. Run-trace's `.traversed` class wins
   over these tints (it sets stroke explicitly with a glow). */
.drawflow .outputs .output {
  position: relative;
}
.drawflow .outputs .output[data-schema-type]::after {
  content: "";
  position: absolute;
  inset: -3px;
  border-radius: 50%;
  border: 2px solid transparent;
  pointer-events: none;
  z-index: 1;
}
.drawflow .outputs .output.schema-type-text::after    { border-color: #7cc7ff; }
.drawflow .outputs .output.schema-type-object::after  { border-color: #c061ff; }
.drawflow .outputs .output.schema-type-list::after    { border-color: #f0a754; }
.drawflow .outputs .output.schema-type-any::after     { border-color: #5a6070; }
.drawflow .outputs .output.schema-type-unknown::after { border-color: #3a3f4d; border-style: dashed; }

.drawflow .connection.schema-type-text    .main-path { stroke: #5b8eb8; }
.drawflow .connection.schema-type-object  .main-path { stroke: #8a59b8; }
.drawflow .connection.schema-type-list    .main-path { stroke: #b07c45; }
.drawflow .connection.schema-type-any     .main-path { stroke: #5a6070; }
.drawflow .connection.schema-type-unknown .main-path { stroke: #4a4f5e; stroke-dasharray: 6 4; }

.drawflow .drawflow-node.selected {
  background: linear-gradient(180deg, rgba(35,38,49,0.96), rgba(24,27,36,0.98)) !important;
  border-color: #8ea3c8;
  box-shadow: 0 0 0 1px rgba(142,163,200,0.85), 0 12px 26px rgba(0,0,0,0.45);
}

/* Pre-run validation error: pulses when the user tries to run but a node
   (typically the Input) is missing a required value. Auto-clears after ~3s. */
.drawflow .drawflow-node.node-error {
  border-color: #ff6b6b !important;
  animation: nodeErrorPulse 0.9s ease-in-out 0s 3;
}
@keyframes nodeErrorPulse {
  0%, 100% { box-shadow: 0 0 0 1px rgba(255, 107, 107, 0.55), 0 0 0 0 rgba(255, 107, 107, 0.0); }
  50%      { box-shadow: 0 0 0 2px rgba(255, 107, 107, 0.95), 0 0 28px 6px rgba(255, 107, 107, 0.35); }
}

/* Lint warning: amber pulse for shape mismatches the user can override. */
.drawflow .drawflow-node.node-warning {
  border-color: #f0b429 !important;
  animation: nodeWarnPulse 0.9s ease-in-out 0s 3;
}
@keyframes nodeWarnPulse {
  0%, 100% { box-shadow: 0 0 0 1px rgba(240, 180, 41, 0.55), 0 0 0 0 rgba(240, 180, 41, 0.0); }
  50%      { box-shadow: 0 0 0 2px rgba(240, 180, 41, 0.95), 0 0 28px 6px rgba(240, 180, 41, 0.35); }
}

/* Persistent lint indicators: live linter applies these on every save
   so they stick around until the underlying issue is resolved. Quieter
   than the on-Run pulse — same hue, no animation. */
.drawflow .drawflow-node.has-lint-error {
  border-color: #ff6b6b !important;
  box-shadow: 0 0 0 1px rgba(255, 107, 107, 0.55);
}
.drawflow .drawflow-node.has-lint-warning {
  border-color: #f0b429 !important;
  box-shadow: 0 0 0 1px rgba(240, 180, 41, 0.55);
}

/* Topbar lint status pill. Sits next to the Run button. The dot's color
   communicates state at a glance; the text gives counts. */
.lint-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  background: var(--panel-2);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 0.25rem 0.7rem;
  font-size: 0.78rem;
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease;
}
.lint-pill:hover { background: var(--panel); }
.lint-pill-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
}
.lint-pill-ok    .lint-pill-dot { background: #6ce0b8; box-shadow: 0 0 6px rgba(108, 224, 184, 0.7); }
.lint-pill-warn  .lint-pill-dot { background: #f0b429; box-shadow: 0 0 6px rgba(240, 180, 41, 0.7); }
.lint-pill-error .lint-pill-dot { background: #ff6b6b; box-shadow: 0 0 6px rgba(255, 107, 107, 0.7); }
.lint-pill-ok    { border-color: rgba(108, 224, 184, 0.4); }
.lint-pill-warn  { border-color: rgba(240, 180, 41, 0.4); }
.lint-pill-error { border-color: rgba(255, 107, 107, 0.5); }

/* Node type themes */
.drawflow .drawflow-node.kind-input {
  background: linear-gradient(180deg, rgba(34,66,58,0.98), rgba(20,43,38,0.98));
  border-color: #3f7d6c;
}
.drawflow .drawflow-node.kind-input .node-head {
  border-bottom-color: rgba(108, 214, 180, 0.24);
}
.drawflow .drawflow-node.kind-input .node-title {
  color: #d8fff0;
}
.drawflow .drawflow-node.kind-input .node-body {
  color: #9ad7c3;
}

.drawflow .drawflow-node.kind-output {
  background: linear-gradient(180deg, rgba(70,57,31,0.98), rgba(45,35,18,0.98));
  border-color: #8f7340;
}
.drawflow .drawflow-node.kind-output .node-head {
  border-bottom-color: rgba(255, 210, 126, 0.24);
}
.drawflow .drawflow-node.kind-output .node-title {
  color: #fff1d5;
}
.drawflow .drawflow-node.kind-output .node-body {
  color: #d5bc86;
}

.drawflow .drawflow-node.kind-agent {
  background: linear-gradient(180deg, rgba(55,34,74,0.98), rgba(35,21,50,0.98));
  border-color: #7a4bb2;
}
.drawflow .drawflow-node.kind-agent .node-head {
  border-bottom-color: rgba(196, 135, 255, 0.24);
}
.drawflow .drawflow-node.kind-agent .node-title {
  color: #f2deff;
}
.drawflow .drawflow-node.kind-agent .node-body {
  color: #c7a2e8;
}

.drawflow .drawflow-node.kind-tool {
  background: linear-gradient(180deg, rgba(24,60,79,0.98), rgba(17,38,52,0.98));
  border-color: #3f7ca0;
}
.drawflow .drawflow-node.kind-tool .node-head {
  border-bottom-color: rgba(114, 196, 255, 0.24);
}
.drawflow .drawflow-node.kind-tool .node-title {
  color: #dbf3ff;
}
.drawflow .drawflow-node.kind-tool .node-body {
  color: #9ec7de;
}

/* Connector points by type */
.drawflow .drawflow-node.kind-input .outputs .output {
  border-color: #6ce0b8;
  background: rgba(108, 224, 184, 0.18);
}
.drawflow .drawflow-node.kind-output .inputs .input {
  border-color: #ffd27e;
  background: rgba(255, 210, 126, 0.2);
}
.drawflow .drawflow-node.kind-agent .inputs .input,
.drawflow .drawflow-node.kind-agent .outputs .output {
  border-color: #c487ff;
  background: rgba(196, 135, 255, 0.18);
}
.drawflow .drawflow-node.kind-tool .inputs .input,
.drawflow .drawflow-node.kind-tool .outputs .output {
  border-color: #72c4ff;
  background: rgba(114, 196, 255, 0.18);
}

/* Control-flow nodes have two outputs that do different things — color
   each socket to match its semantics so the user can tell at a glance
   which one feeds the body / try / first match versus the
   continuation / catch / else. Tooltips on hover (set by
   decorateControlFlowSockets in pipeline_builder.js) carry the full
   explanation. */
.drawflow .drawflow-node.kind-loop .outputs .output_1 {
  border-color: var(--accent-2);
  background: rgba(192, 97, 255, 0.22);
}
.drawflow .drawflow-node.kind-loop .outputs .output_2 {
  border-color: var(--warn);
  background: rgba(255, 200, 87, 0.22);
}
.drawflow .drawflow-node.kind-try_catch .outputs .output_1 {
  border-color: var(--ok);
  background: rgba(56, 211, 159, 0.22);
}
.drawflow .drawflow-node.kind-try_catch .outputs .output_2 {
  border-color: var(--err);
  background: rgba(255, 93, 108, 0.22);
}
/* Conditional: every additional branch (output_2..N) is an "alternate"
   path, so they share the amber. The first branch — typically the
   primary match — gets the ok-green to read as the happy path. The
   per-output rule comes AFTER the catch-all so it overrides for output_1. */
.drawflow .drawflow-node.kind-conditional .outputs .output {
  border-color: var(--warn);
  background: rgba(255, 200, 87, 0.22);
}
.drawflow .drawflow-node.kind-conditional .outputs .output_1 {
  border-color: var(--ok);
  background: rgba(56, 211, 159, 0.22);
}

/* Selected state by node type (override generic highlight) */
.drawflow .drawflow-node.kind-input.selected {
  background: linear-gradient(180deg, rgba(34,66,58,0.98), rgba(20,43,38,0.98)) !important;
  border-color: #6ce0b8;
  box-shadow: 0 0 0 1px rgba(108,224,184,0.9), 0 12px 26px rgba(0,0,0,0.45);
}
.drawflow .drawflow-node.kind-output.selected {
  background: linear-gradient(180deg, rgba(70,57,31,0.98), rgba(45,35,18,0.98)) !important;
  border-color: #ffd27e;
  box-shadow: 0 0 0 1px rgba(255,210,126,0.92), 0 12px 26px rgba(0,0,0,0.45);
}
.drawflow .drawflow-node.kind-agent.selected {
  background: linear-gradient(180deg, rgba(55,34,74,0.98), rgba(35,21,50,0.98)) !important;
  border-color: #c487ff;
  box-shadow: 0 0 0 1px rgba(196,135,255,0.9), 0 12px 26px rgba(0,0,0,0.45);
}
.drawflow .drawflow-node.kind-tool.selected {
  background: linear-gradient(180deg, rgba(24,60,79,0.98), rgba(17,38,52,0.98)) !important;
  border-color: #72c4ff;
  box-shadow: 0 0 0 1px rgba(114,196,255,0.9), 0 12px 26px rgba(0,0,0,0.45);
}

.checklist { padding-left: 1.1rem; }
.checklist li { margin: 0.35rem 0; }

/* Node config button (e.g., File Search "Configure" link inside the node body) */
.node-config-btn {
  margin-top: 0.35rem;
  background: rgba(124, 199, 255, 0.12);
  border: 1px solid rgba(124, 199, 255, 0.28);
  color: var(--link);
  padding: 0.18rem 0.45rem;
  border-radius: 5px;
  font-size: 0.75rem;
  cursor: pointer;
}
.node-config-btn:hover { background: rgba(124, 199, 255, 0.18); }

/* Match the button color to the parent node's theme. */
.drawflow .drawflow-node.kind-input .node-config-btn {
  background: rgba(108, 224, 184, 0.12);
  border-color: rgba(108, 224, 184, 0.32);
  color: #d8fff0;
}
.drawflow .drawflow-node.kind-input .node-config-btn:hover {
  background: rgba(108, 224, 184, 0.2);
}

/* File-pick modal (and a generic .modal shell other features can reuse) */
.modal {
  position: fixed;
  inset: 0;
  z-index: 80;
  display: grid;
  place-items: center;
}
.modal[hidden] { display: none; }
.modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0,0,0,0.55);
  backdrop-filter: blur(2px);
}
.modal-card {
  position: relative;
  width: min(560px, calc(100vw - 2rem));
  max-height: calc(100vh - 4rem);
  display: flex;
  flex-direction: column;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: 0 24px 60px rgba(0,0,0,0.55);
  overflow: hidden;
}
.modal-head, .modal-foot {
  padding: 0.85rem 1rem;
  display: flex;
  align-items: center;
}
.modal-head { justify-content: space-between; border-bottom: 1px solid var(--border); }
.modal-head h3 { margin: 0; font-size: 1rem; }
.modal-foot { justify-content: flex-end; gap: 0.5rem; border-top: 1px solid var(--border); }
.modal-body { padding: 1rem; overflow-y: auto; flex: 1; }
.modal-close {
  background: transparent;
  border: 0;
  color: var(--muted);
  font-size: 1.4rem;
  line-height: 1;
  cursor: pointer;
  padding: 0 0.25rem;
}
.modal-close:hover { color: var(--text); }

/* Wide variant for the read-only node-detail overlay — system_prompt and
   custom_python code blocks need horizontal room to be useful. */
.modal-card-wide {
  width: min(820px, calc(100vw - 2rem));
}

/* Node detail rows: a label column above each value, with separate styling
   for short values, multi-line prose (.detail-pre), and code (.detail-code). */
.detail-row { margin-bottom: 1rem; }
.detail-row:last-child { margin-bottom: 0; }
.detail-label {
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted);
  margin-bottom: 0.3rem;
}
.detail-val {
  color: var(--text);
  word-break: break-word;
}
.detail-pre {
  margin: 0;
  padding: 0.65rem 0.8rem;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 7px;
  white-space: pre-wrap;
  word-break: break-word;
  font-family: inherit;
  font-size: 0.92rem;
  color: var(--text);
  max-height: 260px;
  overflow-y: auto;
}
.detail-code {
  margin: 0;
  padding: 0.65rem 0.8rem;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 7px;
  white-space: pre;
  overflow-x: auto;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.85rem;
  color: var(--text);
  max-height: 320px;
}
.detail-list {
  margin: 0;
  padding-left: 1.1rem;
  color: var(--text);
}
.detail-list li { padding: 0.15rem 0; }

.ndm-textarea {
  width: 100%;
  box-sizing: border-box;
  padding: 0.6rem 0.75rem;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 7px;
  color: var(--text);
  font-family: inherit;
  font-size: 0.92rem;
  resize: vertical;
}
.ndm-textarea:focus {
  outline: none;
  border-color: var(--accent, #5b9dff);
}
.ndm-text-input {
  width: 100%;
  box-sizing: border-box;
  padding: 0.55rem 0.7rem;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 7px;
  color: var(--text);
  font-size: 0.95rem;
}
.ndm-text-input:focus {
  outline: none;
  border-color: var(--accent, #5b9dff);
}
/* Structured prompt-spec editor (per-node "What does this agent do?"). */
.prompt-spec .spec-rows {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  margin-top: 0.4rem;
}
.spec-row {
  display: grid;
  grid-template-columns: auto minmax(160px, 1fr) 1.4fr;
  gap: 0.6rem;
  align-items: center;
  padding: 0.45rem 0.6rem;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 7px;
}
.spec-row.dragging {
  opacity: 0.45;
  border-style: dashed;
}
.spec-drag-handle {
  cursor: grab;
  user-select: none;
  color: var(--muted);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 1rem;
  padding: 0 0.15rem;
  line-height: 1;
}
.spec-drag-handle:active { cursor: grabbing; }
.spec-drag-handle:hover { color: var(--text); }
.spec-row code {
  background: transparent;
  font-size: 0.85rem;
}
.spec-row-tick {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  cursor: pointer;
  user-select: none;
}
.spec-row-tick input[type="checkbox"] {
  flex: 0 0 auto;
  margin: 0;
}
.spec-heading {
  width: 100%;
  box-sizing: border-box;
  padding: 0.35rem 0.55rem;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 5px;
  color: var(--text);
  font-size: 0.88rem;
}
.spec-heading:focus {
  outline: none;
  border-color: var(--accent, #5b9dff);
}
.spec-info {
  margin-top: 0.5rem;
  padding: 0.55rem 0.7rem;
  background: var(--panel-2);
  border: 1px dashed var(--border);
  border-radius: 7px;
}
.spec-info strong { color: var(--text); }
.small { font-size: 0.82rem; }

.file-pick-list { list-style: none; padding: 0; margin: 0.5rem 0 0; }
.file-pick-list li { padding: 0.35rem 0; border-bottom: 1px solid var(--border); }
.file-pick-list li:last-child { border-bottom: 0; }
.file-pick-list label {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: 0.6rem;
  align-items: center;
  cursor: pointer;
}
.fpick-name { word-break: break-word; }
.fpick-meta { font-size: 0.78rem; }

.run-btn {
  background: linear-gradient(180deg, #2b6f5c, #1f5c4a);
  border-color: #3f8c75;
  color: #e8fff5;
}
.run-btn:hover { background: linear-gradient(180deg, #338070, #266a55); }

.chat-form-foot {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.4rem;
  min-height: 32px;
}
.chat-form-foot .muted { margin-right: auto; font-size: 0.82rem; }
.composer-clear-btn,
.composer-send-btn {
  display: inline-grid;
  place-items: center;
  width: 30px;
  height: 30px;
  padding: 0;
  border-radius: 7px;
  cursor: pointer;
}
.composer-clear-btn {
  position: absolute;
  top: 0.45rem;
  right: 0.45rem;
  border: 1px solid transparent;
  background: transparent;
  color: var(--muted);
}
.composer-clear-btn:hover {
  border-color: var(--border);
  background: rgba(255,255,255,0.04);
  color: var(--text);
}
.composer-send-btn {
  border: 1px solid var(--accent);
  background: var(--accent);
  color: #1a0f0a;
}
.composer-send-btn:hover {
  background: #ff8b5d;
  border-color: #ff8b5d;
}
.composer-send-btn:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}
.composer-clear-btn:focus-visible,
.composer-send-btn:focus-visible {
  outline: 2px solid rgba(124, 199, 255, 0.42);
  outline-offset: 2px;
}
.composer-clear-btn svg,
.composer-send-btn svg {
  width: 16px;
  height: 16px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.chat-thread {
  flex: 1;
  overflow-y: auto;
  padding: 0.85rem 0.75rem 0.35rem;
  scrollbar-gutter: stable;
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
  min-height: 0;
}
.chat-empty { padding: 1rem; text-align: center; }
.workbench-sidebar .chat-thread .msg {
  width: 100%;
  max-width: none;
  margin: 0 auto;
}
.msg-body {
  line-height: 1.45;
  overflow-wrap: anywhere;
}
.msg-progress { opacity: 0.85; }
.msg-progress .msg-body { font-size: 0.85rem; font-family: ui-monospace, monospace; }
.msg-system { opacity: 0.9; }
.msg-system .msg-body { color: var(--warn, #ffc857); font-size: 0.85rem; }

.step-output {
  margin-top: 0.4rem;
}
.step-output > summary {
  cursor: pointer;
  list-style: none;
  font-size: 0.78rem;
  color: var(--muted);
  padding: 0.2rem 0;
  user-select: none;
}
.step-output > summary::-webkit-details-marker { display: none; }
.step-output > summary::before {
  content: "▸ ";
  display: inline-block;
  width: 1em;
}
.step-output[open] > summary::before { content: "▾ "; }
.step-output > summary:hover { color: var(--text); }
.step-output pre {
  margin: 0.35rem 0 0;
  padding: 0.55rem 0.7rem;
  background: rgba(0, 0, 0, 0.28);
  border: 1px solid var(--border);
  border-radius: 6px;
  font-size: 0.78rem;
  line-height: 1.45;
  max-height: 320px;
  overflow: auto;
  white-space: pre-wrap;
  word-break: break-word;
}

.proposal-card {
  margin-top: 0.55rem;
  padding: 0.7rem 0.8rem;
  background: rgba(108, 224, 184, 0.06);
  border: 1px solid rgba(108, 224, 184, 0.28);
  border-radius: 8px;
}
.proposal-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 0.45rem;
}
.proposal-badge {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: #6ce0b8;
  font-weight: 600;
}
.proposal-state {
  font-size: 0.75rem;
  color: var(--muted);
}
.proposal-card[data-proposal-state="applied"] .proposal-state { color: #6ce0b8; }
.proposal-card[data-proposal-state="dismissed"] .proposal-state { color: var(--muted); }
.proposal-card[data-proposal-state="applied"] .proposal-foot button,
.proposal-card[data-proposal-state="dismissed"] .proposal-foot button {
  opacity: 0.85;
}
.proposal-rationale {
  margin: 0 0 0.45rem;
  font-size: 0.88rem;
  line-height: 1.4;
}
.proposal-ops {
  list-style: none;
  padding: 0;
  margin: 0 0 0.55rem;
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}
.proposal-ops li {
  font-size: 0.82rem;
  line-height: 1.4;
}
.proposal-ops code {
  background: rgba(0,0,0,0.25);
  padding: 0 0.35rem;
  border-radius: 4px;
  margin-right: 0.35rem;
  font-size: 0.78rem;
}
.proposal-foot {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  justify-content: flex-end;
}
.proposal-foot .btn {
  padding: 0.32rem 0.65rem;
  font-size: 0.8rem;
  line-height: 1.25;
  border-radius: 6px;
  white-space: nowrap;
}

/* Lint card — pre-run check results. Mirrors proposal-card structure so
   it sits comfortably in the same chat thread. Severity is reflected in
   each row's accent color (red for error, amber for warning). */
.lint-card {
  margin-top: 0.55rem;
  padding: 0.7rem 0.8rem;
  background: rgba(240, 180, 41, 0.06);
  border: 1px solid rgba(240, 180, 41, 0.28);
  border-radius: 8px;
}
.lint-card[data-lint-state="overridden"] { opacity: 0.7; }
.lint-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 0.45rem;
}
.lint-badge {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: #f0b429;
}
.lint-state-pill {
  font-size: 0.72rem;
  color: var(--muted);
}
.lint-list {
  list-style: none;
  padding: 0;
  margin: 0 0 0.55rem;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}
.lint-row {
  display: flex;
  gap: 0.55rem;
  padding: 0.4rem 0.5rem;
  border-radius: 6px;
  background: rgba(0,0,0,0.2);
  cursor: pointer;
}
.lint-row:hover { background: rgba(0,0,0,0.3); }
.lint-row-error  { border-left: 3px solid #ff6b6b; }
.lint-row-warning { border-left: 3px solid #f0b429; }
.lint-sev {
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  padding: 0.05rem 0.4rem;
  border-radius: 4px;
  align-self: flex-start;
  white-space: nowrap;
}
.lint-sev-error   { background: rgba(255, 107, 107, 0.18); color: #ff8b8b; }
.lint-sev-warning { background: rgba(240, 180, 41, 0.18); color: #f0b429; }
.lint-text { flex: 1; min-width: 0; }
.lint-title { font-size: 0.86rem; font-weight: 600; line-height: 1.35; }
.lint-detail {
  margin-top: 0.18rem;
  font-size: 0.8rem;
  line-height: 1.4;
  color: var(--muted);
}
.lint-fix-row {
  margin-top: 0.45rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
}
.lint-fix-btn {
  font-size: 0.78rem;
  padding: 0.25rem 0.6rem;
}
.lint-foot {
  display: flex;
  justify-content: flex-end;
}
/* Creation ops carry extra structure (chips, descriptions, optional code or
   schema previews). The plain ops above stay one-line; these can expand. */
.op-chip {
  display: inline-block;
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 0.05rem 0.4rem;
  border-radius: 4px;
  background: rgba(192, 97, 255, 0.15);
  color: var(--accent-2);
  margin: 0 0.3rem 0 0;
  vertical-align: 1px;
}
.op-desc {
  margin: 0.18rem 0 0.25rem;
  font-size: 0.8rem;
  color: var(--muted);
}
.op-meta {
  margin-top: 0.2rem;
  font-size: 0.75rem;
}
.op-block {
  margin-top: 0.3rem;
}
.op-block > summary {
  cursor: pointer;
  font-size: 0.75rem;
  color: var(--muted);
}
.op-block > summary:hover {
  color: var(--text);
}
.op-block pre {
  margin: 0.3rem 0 0;
  padding: 0.5rem 0.6rem;
  background: rgba(0, 0, 0, 0.35);
  border: 1px solid var(--border);
  border-radius: 6px;
  font-size: 0.75rem;
  line-height: 1.4;
  max-height: 280px;
  overflow: auto;
  white-space: pre-wrap;
  word-break: break-word;
}

.seg-group {
  display: inline-flex;
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 2px;
  margin-bottom: 0.85rem;
  background: var(--panel-2);
}
.seg-btn {
  appearance: none;
  background: transparent;
  border: 0;
  color: var(--muted);
  font-size: 0.85rem;
  padding: 0.4rem 0.85rem;
  border-radius: 6px;
  cursor: pointer;
}
.seg-btn.is-active { background: var(--panel); color: var(--text); }
.seg-btn:hover:not(.is-active) { color: var(--text); }

.inm-pane[hidden] { display: none; }
.inm-label { display: block; margin-bottom: 0.35rem; font-size: 0.82rem; }
#inm-text,
#inm-test-payload,
#vsm-query-template {
  width: 100%;
  padding: 0.55rem 0.7rem;
  background: var(--panel-2);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 7px;
  font-family: ui-monospace, monospace;
  font-size: 0.9rem;
  resize: vertical;
  min-height: 140px;
  box-sizing: border-box;
}
#inm-text:focus,
#inm-test-payload:focus,
#vsm-query-template:focus {
  border-color: #59657b;
  outline: 2px solid rgba(124, 199, 255, 0.16);
}
#vsm-query-template { min-height: 80px; }
#vsm-max-results {
  background: var(--panel-2);
  color: var(--text);
  border: 1px solid var(--border);
}
#vsm-max-results:focus {
  border-color: #59657b;
  outline: 2px solid rgba(124, 199, 255, 0.16);
}
.inm-upload-row {
  display: flex;
  gap: 0.6rem;
  align-items: center;
  margin-top: 0.6rem;
}

/* ---------- Run trace (run_detail page + builder live overlay) ---------- */

/* run_detail uses the workbench frame with a full-width canvas and the
   drawer floating as an absolute overlay on the right. Floating it (rather
   than reserving a grid column) means the close button can actually slide
   it off-screen and reclaim the full canvas width — and `overflow: hidden`
   on the parent stops the off-screen drawer from creating a page-wide
   horizontal scrollbar. */
.run-trace-frame .workbench-body {
  grid-template-columns: 1fr;
  position: relative;
  overflow: hidden;
}
.run-trace-frame .workbench-body .canvas-wrapper { order: 1; }

.run-state {
  display: inline-block;
  padding: 0.15rem 0.55rem;
  border-radius: 999px;
  font-size: 0.78rem;
  border: 1px solid var(--border);
  background: var(--panel-2);
  margin-left: 0.6rem;
  text-transform: capitalize;
}
.run-state.run-running   { color: var(--link); border-color: rgba(124,199,255,0.5); }
.run-state.run-completed { color: var(--ok);   border-color: rgba(56,211,159,0.5); }
.run-state.run-failed    { color: var(--err);  border-color: rgba(255,93,108,0.5); }
.run-state.run-pending   { color: var(--muted); }

.badge {
  display: inline-block;
  padding: 0.1rem 0.5rem;
  border-radius: 6px;
  font-size: 0.72rem;
  margin-left: 0.5rem;
  border: 1px solid var(--border);
  background: var(--panel-2);
  color: var(--muted);
}
.badge-warn {
  color: var(--warn);
  border-color: rgba(255,200,87,0.4);
  background: rgba(255,200,87,0.08);
}
/* Run-page header chip showing live token + cost totals. Numeric content
   uses tabular figures so the digits don't wobble between poll ticks. */
.badge-cost {
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.01em;
}

/* Per-node trace state — applied on top of any .drawflow-node.
   NOTE: do NOT set `position: relative` here. Drawflow positions nodes with
   `position: absolute` + inline left/top; overriding that collapses every
   node to the canvas corner. The .trace-chip below uses `position: absolute`
   which already anchors to the node's absolute box without needing a
   `position: relative` override. */
.drawflow-node.node-state--pending { opacity: 0.65; }
.drawflow-node.node-state--running {
  box-shadow: 0 0 0 2px var(--link), 0 0 24px rgba(124,199,255,0.35);
  animation: trace-pulse 1.4s ease-in-out infinite;
}
.drawflow-node.node-state--completed {
  box-shadow: 0 0 0 2px var(--ok);
}
.drawflow-node.node-state--failed {
  box-shadow: 0 0 0 2px var(--err), 0 0 22px rgba(255,93,108,0.35);
}
.drawflow-node.node-state--skipped { opacity: 0.45; }
@keyframes trace-pulse {
  0%, 100% { box-shadow: 0 0 0 2px var(--link), 0 0 14px rgba(124,199,255,0.25); }
  50%      { box-shadow: 0 0 0 2px var(--link), 0 0 28px rgba(124,199,255,0.55); }
}

.trace-chip {
  position: absolute;
  top: -10px;
  right: -10px;
  min-width: 22px;
  height: 22px;
  padding: 0 6px;
  border-radius: 999px;
  background: var(--panel-2);
  color: var(--text);
  border: 1px solid var(--border);
  font-size: 0.78rem;
  display: inline-grid;
  place-items: center;
  font-weight: 600;
  z-index: 2;
  pointer-events: none;
}
.trace-chip[data-status="running"]   { background: rgba(124,199,255,0.18); color: var(--link); border-color: var(--link); }
.trace-chip[data-status="completed"] { background: rgba(56,211,159,0.18);  color: var(--ok);   border-color: var(--ok); }
.trace-chip[data-status="failed"]    { background: rgba(255,93,108,0.22);  color: var(--err);  border-color: var(--err); }
.trace-chip[data-status="skipped"]   { background: var(--panel-2);          color: var(--muted); }

/* Traversed edges — Drawflow renders SVG <path>s inside .connection.
   Color the actual <path> rather than the SVG container. */
.connection.traversed .main-path {
  stroke: var(--ok);
  stroke-width: 4px;
  filter: drop-shadow(0 0 6px rgba(56,211,159,0.45));
}

/* Side drawer for step inspection — absolutely positioned overlay so the
   close button can fully slide it off-screen. */
.run-drawer {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: min(420px, 90vw);
  display: flex;
  flex-direction: column;
  border-left: 1px solid var(--border);
  background: linear-gradient(180deg, rgba(24,26,34,0.96), rgba(16,18,25,0.98));
  box-shadow: -18px 0 36px rgba(0,0,0,0.4);
  min-height: 0;
  transform: translateX(100%);
  transition: transform 220ms ease;
  z-index: 6;
}
.run-drawer.is-open { transform: translateX(0); }
.run-drawer-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.85rem 1rem;
  border-bottom: 1px solid var(--border);
}
.run-drawer-head h3 {
  margin: 0;
  font-size: 1rem;
}
.run-drawer-body {
  padding: 0.9rem 1rem 1.4rem;
  overflow: auto;
  flex: 1;
}
.run-drawer-body h4 {
  margin: 1rem 0 0.4rem;
  font-size: 0.85rem;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.run-drawer-body pre.json {
  background: var(--panel-2);
  border: 1px solid var(--border);
  padding: 0.7rem 0.85rem;
  border-radius: 8px;
  font-size: 0.82rem;
  white-space: pre-wrap;
  word-break: break-word;
  max-height: 360px;
  overflow: auto;
}
.trace-meta {
  display: grid;
  grid-template-columns: 96px 1fr;
  gap: 0.35rem 0.85rem;
  margin: 0 0 0.6rem;
  font-size: 0.88rem;
}
.trace-meta dt { color: var(--muted); }
.trace-meta dd { margin: 0; }

.drawer-actions {
  display: flex;
  gap: 0.5rem;
  margin: 0.4rem 0 0.85rem;
  flex-wrap: wrap;
}

/* Per-failed-step "Ask assistant" debug thread. Lives at the bottom of the
   run-drawer body for any step.status === "failed". Visually distinct from
   the input/output panels (slight accent border) so it reads as an
   interactive control rather than another data block. */
.debug-chat-heading {
  margin-top: 1.1rem !important;
  color: var(--link) !important;
}
.debug-chat {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  padding: 0.7rem 0.8rem 0.8rem;
  border: 1px solid rgba(124,199,255,0.22);
  border-radius: 10px;
  background: rgba(124,199,255,0.04);
}
.debug-chat-thread {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  max-height: 320px;
  overflow-y: auto;
  margin: 0;
}
.debug-chat-empty {
  margin: 0;
  font-size: 0.82rem;
}
.debug-msg {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}
.debug-msg-label {
  font-size: 0.7rem;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.debug-msg-body {
  padding: 0.5rem 0.7rem;
  border-radius: 8px;
  border: 1px solid var(--border);
  font-size: 0.86rem;
  line-height: 1.45;
  white-space: pre-wrap;
  word-break: break-word;
}
.debug-msg-user .debug-msg-body {
  background: rgba(124,199,255,0.08);
  border-color: rgba(124,199,255,0.28);
  align-self: flex-end;
  max-width: 90%;
}
.debug-msg-assistant .debug-msg-body {
  background: var(--panel-2);
}
.debug-msg-thinking .debug-msg-body {
  color: var(--muted);
  font-style: italic;
}
.debug-thinking-dots::after {
  content: "";
  display: inline-block;
  width: 1ch;
  animation: debug-dots 1.2s steps(4, end) infinite;
}
@keyframes debug-dots {
  0%   { content: ""; }
  25%  { content: "."; }
  50%  { content: ".."; }
  75%  { content: "..."; }
  100% { content: ""; }
}
.debug-chat-presets {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}
.debug-chat-presets .link-btn {
  margin-left: 0;
  font-size: 0.8rem;
  padding: 0.2rem 0.55rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  text-decoration: none;
  background: var(--panel-2);
}
.debug-chat-presets .link-btn:hover {
  border-color: rgba(124,199,255,0.45);
}
.debug-chat-input {
  display: flex;
  gap: 0.5rem;
  align-items: flex-end;
}
.debug-chat-textarea {
  flex: 1;
  resize: vertical;
  min-height: 2.4rem;
  max-height: 8rem;
  padding: 0.45rem 0.6rem;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: var(--panel-2);
  color: inherit;
  font: inherit;
  font-size: 0.86rem;
}
.debug-chat-textarea:focus {
  outline: none;
  border-color: rgba(124,199,255,0.55);
}
.debug-chat-send {
  flex: 0 0 auto;
}
/* Highlighted action bar pinned to the top of the drawer when the run is
   paused on this node (Continue / Re-run from here). */
.drawer-actions-primary {
  margin: -0.2rem 0 1rem;
  padding: 0.7rem 0.8rem;
  background: rgba(124,199,255,0.06);
  border: 1px solid rgba(124,199,255,0.2);
  border-radius: 10px;
}
.drawer-actions-primary .btn.primary {
  border-color: var(--ok);
  color: var(--ok);
  background: rgba(56,211,159,0.08);
}
.drawer-actions-primary .btn.primary:hover {
  background: rgba(56,211,159,0.18);
}
.btn-small {
  padding: 0.3rem 0.7rem;
  font-size: 0.82rem;
}

.link-btn {
  appearance: none;
  background: transparent;
  border: 0;
  color: var(--link);
  cursor: pointer;
  font-size: 0.78rem;
  padding: 0;
  margin-left: 0.5rem;
  text-decoration: underline;
  text-underline-offset: 2px;
  font-weight: 400;
}
.link-btn:hover { color: var(--text); }
.run-drawer-body h4 { display: flex; align-items: center; }

/* Expanded view modal — bigger than the standard 560px modal-card */
.expand-modal-card {
  width: min(960px, calc(100vw - 2rem));
  max-height: calc(100vh - 3rem);
}
.expand-actions {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
}
.expand-content {
  margin: 0;
  background: var(--panel-2);
  border: 1px solid var(--border);
  padding: 0.9rem 1rem;
  border-radius: 8px;
  font-size: 0.88rem;
  white-space: pre-wrap;
  word-break: break-word;
  max-height: calc(100vh - 10rem);
  overflow: auto;
}

/* Run-detail final/error cards sit below the canvas */
.run-trace-frame .run-final,
.run-trace-frame .run-error {
  margin: 1rem;
}

/* Builder live overlay: a small floating card shown while a run is active */
.builder-trace-banner {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  top: 0.85rem;
  z-index: 5;
  display: inline-flex;
  gap: 0.6rem;
  align-items: center;
  padding: 0.35rem 0.75rem 0.35rem 0.85rem;
  border: 1px solid rgba(255,255,255,0.1);
  border-radius: 999px;
  background: rgba(18,20,27,0.88);
  backdrop-filter: blur(8px);
  font-size: 0.82rem;
  color: var(--text);
  box-shadow: 0 12px 28px rgba(0,0,0,0.28);
}
.builder-trace-banner .pip {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--link);
  box-shadow: 0 0 8px var(--link);
  animation: trace-pulse 1.4s ease-in-out infinite;
}
.builder-trace-banner.is-done .pip   { background: var(--ok);  box-shadow: 0 0 8px var(--ok);  animation: none; }
.builder-trace-banner.is-failed .pip { background: var(--err); box-shadow: 0 0 8px var(--err); animation: none; }
.builder-trace-banner.is-paused .pip { background: #f5b85a; box-shadow: 0 0 8px #f5b85a; animation: none; }
.builder-trace-banner.is-cancelled .pip { background: var(--muted); box-shadow: none; animation: none; }
.builder-trace-banner .continue-btn {
  color: var(--ok);
  border: 1px solid rgba(56,211,159,0.35);
  font-weight: 600;
}
.builder-trace-banner .continue-btn:hover {
  background: rgba(56,211,159,0.12);
  color: var(--ok);
}
.builder-trace-banner .cancel-btn {
  color: var(--err);
  border: 1px solid rgba(255,93,108,0.3);
}
.builder-trace-banner .cancel-btn:hover {
  background: rgba(255,93,108,0.12);
  color: var(--err);
}

/* Run-cluster (Step toggle + Run button) — visually grouped so the build/run
   controls read as one unit, separated from secondary actions. */
.run-group {
  display: inline-flex;
  align-items: stretch;
  gap: 0.4rem;
  padding: 0.25rem;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: rgba(255,255,255,0.02);
}
.run-group .run-btn { margin: 0; }

/* Step-mode toggle in the topbar. Native checkbox is hidden and replaced
   with a custom box drawn via .step-toggle-box so the control matches the
   rounded, dark surfaces. */
.step-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.3rem 0.7rem;
  border-radius: 7px;
  font-size: 0.85rem;
  color: var(--muted);
  cursor: pointer;
  user-select: none;
  background: transparent;
  transition: background-color 120ms ease, color 120ms ease;
}
.step-toggle:hover { color: var(--text); background: rgba(255,255,255,0.04); }
.step-toggle input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
  width: 0;
  height: 0;
}
.step-toggle-box {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  border: 1px solid #3a4150;
  border-radius: 4px;
  background: var(--panel-2);
  display: inline-grid;
  place-items: center;
  transition: background-color 120ms ease, border-color 120ms ease;
}
.step-toggle-box::after {
  content: "";
  width: 9px;
  height: 5px;
  border-left: 2px solid #1a0f0a;
  border-bottom: 2px solid #1a0f0a;
  transform: rotate(-45deg) translate(1px, -1px) scale(0);
  transition: transform 120ms ease;
}
.step-toggle:has(input:checked) {
  color: var(--text);
}
.step-toggle:has(input:checked) .step-toggle-box {
  background: var(--accent);
  border-color: var(--accent);
}
.step-toggle:has(input:checked) .step-toggle-box::after {
  transform: rotate(-45deg) translate(1px, -1px) scale(1);
}
.step-toggle:focus-within {
  outline: 2px solid rgba(124, 199, 255, 0.32);
  outline-offset: 1px;
}
.builder-trace-banner button {
  appearance: none;
  background: transparent;
  border: 0;
  color: var(--muted);
  cursor: pointer;
  font-size: 0.8rem;
  padding: 0.15rem 0.4rem;
  border-radius: 6px;
}
.builder-trace-banner button:hover { color: var(--text); background: var(--panel-2); }
.builder-trace-banner a { color: var(--link); text-decoration: none; font-weight: 500; }
.builder-trace-banner a:hover { text-decoration: underline; }

@media (max-width: 900px) {
  /* Drawer covers the canvas full-width on narrow screens. */
  .run-trace-frame .run-drawer { width: 100vw; max-width: 100vw; }
}

@media (max-width: 1120px) {
  .pipeline-workbench {
    --sidebar-width: min(380px, 42vw);
    --sidebar-min-width: 380px;
  }
  .param-row { grid-template-columns: 1fr 95px 1fr auto; }
}

@media (max-width: 900px) {
  .topnav {
    align-items: flex-start;
    gap: 0.85rem;
    flex-direction: column;
  }
  .navlinks {
    width: 100%;
    gap: 0.65rem;
    flex-wrap: wrap;
  }
  .auth-shell {
    grid-template-columns: 1fr;
    align-content: center;
    gap: 1.25rem;
  }
  .auth-copy h1 {
    font-size: 2.25rem;
  }
  .auth-copy p {
    font-size: 0.98rem;
  }
  .auth-card {
    padding: 1rem;
  }
  .auth-links {
    flex-direction: column;
  }
  main.wrap > form.stacked {
    padding: 0.85rem;
  }
  .pipeline-workbench {
    height: auto;
    min-height: calc(100vh - 61px);
  }
  .workbench-body {
    grid-template-columns: 1fr;
    grid-template-rows: minmax(48vh, auto) minmax(52vh, auto);
  }
  .sidebar-resizer { display: none; }
  .workbench-sidebar {
    border-right: 0;
    border-bottom: 1px solid var(--border);
  }
  .tab-panel[data-panel="nodes"] .palette { max-height: none; }
  .param-row { grid-template-columns: 1fr; }
  .builder-chat-form { grid-template-columns: 1fr; }
}

/* ===========================================================
   Schedules, notifications, live-run UI
   =========================================================== */

.page-head-actions { display: inline-flex; gap: 0.5rem; }

.badge-ok {
  color: var(--ok);
  border-color: rgba(56,211,159,0.4);
  background: rgba(56,211,159,0.08);
}
.badge-info {
  color: var(--link);
  border-color: rgba(124,199,255,0.4);
  background: rgba(124,199,255,0.08);
  text-decoration: none;
}
.badge-info:hover { text-decoration: none; filter: brightness(1.1); }
.badge-live {
  color: var(--accent);
  border-color: rgba(255,122,69,0.45);
  background: rgba(255,122,69,0.08);
  animation: badge-live-pulse 1.6s ease-in-out infinite;
}
@keyframes badge-live-pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.55; }
}

.run-state.run-cancelled,
.run-cancelled { color: var(--warn); }
.run-state.run-paused,
.run-paused    { color: var(--accent-2); }

table.data .row-actions {
  display: inline-flex;
  gap: 0.35rem;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
}
table.data .row-actions .btn.small,
.btn.small {
  padding: 0.3rem 0.65rem;
  font-size: 0.78rem;
  line-height: 1.2;
  border-radius: 6px;
  white-space: nowrap;
}
form.inline-form { display: inline-block; margin: 0; }

/* Schedule form — reuse the stacked-form input styling but in a sectioned
   layout so the user sees the form as four chunks (What/When/Behavior/End/
   Notifications) rather than one tall wall. */
.schedule-form fieldset {
  border: 1px solid var(--border);
  background: var(--panel);
  border-radius: 10px;
  padding: 0.75rem 1rem 1rem;
  margin: 0 0 1rem;
}
.schedule-form fieldset legend {
  padding: 0 0.4rem;
  color: var(--muted);
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.schedule-form p { margin: 0.6rem 0; display: flex; flex-direction: column; gap: 0.3rem; }
.schedule-form label { color: var(--muted); font-size: 0.85rem; }
.schedule-form input[type="text"],
.schedule-form input[type="number"],
.schedule-form input[type="date"],
.schedule-form input[type="time"],
.schedule-form select,
.schedule-form textarea {
  background: var(--panel-2);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0.4rem 0.55rem;
  font: inherit;
}
.schedule-form input[type="checkbox"] { margin-right: 0.35rem; }
.schedule-form fieldset p label[for$="checkbox"],
.schedule-form fieldset p label:has(input[type="checkbox"]) {
  display: inline-flex;
  align-items: center;
  margin-right: 1rem;
  color: var(--text);
}
.schedule-form .form-actions {
  display: flex; gap: 0.5rem; margin-top: 0.5rem;
}
.schedule-form .err { color: var(--err); font-size: 0.82rem; }
.schedule-form .small { font-size: 0.78rem; }

/* Notification bell + badge */
.notif-bell {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  position: relative;
  width: 36px; height: 36px;
  border-radius: 999px;
  color: var(--muted);
  margin-right: 0.4rem;
  transition: background 0.15s ease, color 0.15s ease;
}
.notif-bell:hover {
  background: rgba(255,255,255,0.04);
  color: var(--text);
  text-decoration: none;
}
.notif-badge {
  position: absolute;
  top: 2px; right: 2px;
  min-width: 16px; height: 16px;
  padding: 0 4px;
  border-radius: 999px;
  background: var(--err);
  color: #fff;
  font-size: 0.65rem;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
}

/* Notifications inbox */
.cards.notifications { list-style: none; padding: 0; }
.card.notif {
  border-left: 3px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}
.card.notif.notif-success  { border-left-color: var(--ok); }
.card.notif.notif-failure  { border-left-color: var(--err); }
.card.notif.notif-cancelled { border-left-color: var(--warn); }
.card.notif.unread { background: rgba(124,199,255,0.04); }
.notif-head { display: flex; justify-content: space-between; align-items: baseline; gap: 0.6rem; }
.notif-body {
  margin: 0;
  background: var(--panel-2);
  padding: 0.5rem 0.7rem;
  border-radius: 6px;
  white-space: pre-wrap;
  font-size: 0.85rem;
}
.notif-actions { display: flex; gap: 0.4rem; }

/* Native <select> — strip the OS chrome and paint our own chevron so dropdowns
   match the rest of the rounded, dark surfaces. The popup list itself is still
   browser-rendered; setting color/background on <option> covers Chromium and
   Firefox in dark mode. */
select {
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  background-color: var(--panel-2);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 7px;
  padding: 0.45rem 2rem 0.45rem 0.7rem;
  font: inherit;
  line-height: 1.3;
  cursor: pointer;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none'><path d='M1 1.5L6 6.5L11 1.5' stroke='%238b919e' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  background-repeat: no-repeat;
  background-position: right 0.7rem center;
  background-size: 12px 8px;
  transition: border-color 120ms ease, background-color 120ms ease;
}
select:hover { border-color: #3a4150; }
select:focus,
select:focus-visible {
  border-color: #59657b;
  outline: 2px solid rgba(124, 199, 255, 0.16);
  outline-offset: 0;
}
select::-ms-expand { display: none; }
select option,
select optgroup {
  background-color: var(--panel);
  color: var(--text);
}
select:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}
/* Compact selects (tighter rows in the param panel, lint controls, etc.) */
.param-row select,
select.small {
  padding: 0.32rem 1.7rem 0.32rem 0.55rem;
  background-position: right 0.5rem center;
  font-size: 0.85rem;
}

/* HTTP Request node config form — built-in function modal. Uses the */
/* same .stacked layout as the other modal forms; these two helpers add  */
/* a 2-column row and an inline checkbox-with-label row.                  */
.modal-body .grid-2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.75rem;
}
.modal-body .checkbox-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-direction: row;
}
.modal-body .checkbox-row input[type="checkbox"] { margin: 0; }
.modal-body .small { font-size: 0.82rem; }
.modal-body .builtin-secret-picker {
  font-size: 0.82rem;
  padding: 0.25rem 1.6rem 0.25rem 0.5rem;
}

/* Upstream-key chip palette — surfaces what {placeholders} the current
   node can interpolate from its parents. Sits inside integration node
   forms; click a chip to insert at the focused field's caret. */
.modal-body .chip-palette {
  margin: 0.4rem 0 0.6rem;
  padding: 0.55rem 0.65rem;
  border: 1px dashed var(--border);
  border-radius: 8px;
  background: rgba(127, 127, 127, 0.04);
}
.modal-body .chip-palette-empty {
  background: transparent;
  border-style: dotted;
}
.modal-body .chip-palette-hint {
  display: block;
  margin-bottom: 0.35rem;
}
.modal-body .chip-group {
  margin-top: 0.35rem;
}
.modal-body .chip-group-label {
  display: block;
  font-size: 0.78rem;
  color: var(--muted);
  margin-bottom: 0.2rem;
}
.modal-body .chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
}
.modal-body .chip-insert {
  appearance: none;
  border: 1px solid var(--border);
  background: var(--bg, #fff);
  color: var(--text);
  border-radius: 999px;
  padding: 0.15rem 0.55rem;
  font-size: 0.78rem;
  cursor: pointer;
  line-height: 1.4;
}
.modal-body .chip-insert:hover {
  border-color: var(--accent, #5b6cff);
  background: rgba(91, 108, 255, 0.08);
}
.modal-body .chip-insert code {
  background: transparent;
  font-size: 0.78rem;
  padding: 0;
}

/* Conditional-node config — branch fieldset + rule row layout */
.cf-branch {
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0.75rem;
  margin-bottom: 0.75rem;
}
.cf-branch legend { padding: 0 0.4rem; font-size: 0.85rem; color: var(--muted); }
.cf-rule {
  display: grid;
  grid-template-columns: 1fr 8rem 1fr auto;
  gap: 0.4rem;
  align-items: center;
  margin-bottom: 0.4rem;
}
.cf-rule input, .cf-rule select { padding: 0.3rem 0.5rem; font-size: 0.85rem; }

/* Control-flow node badge tints. Keeping them distinct from agent/tool
   colors so users can recognize routing nodes at a glance on a busy canvas. */
.drawflow .drawflow-node.kind-conditional .node-head .badge { background: #f5a524; color: #2a1500; }
.drawflow .drawflow-node.kind-loop        .node-head .badge { background: #a78bfa; color: #18103a; }
.drawflow .drawflow-node.kind-try_catch   .node-head .badge { background: #ef4444; color: #fff; }
.drawflow .drawflow-node.kind-delay       .node-head .badge { background: #94a3b8; color: #0b1220; }

/* Smart secret field — used by integration node forms to bind a
   secret-typed config value (webhook_url, connection_url, ...) to a
   user's Secret slug via a typed dropdown. "Type a value" button
   toggles to a free-text input for advanced / one-off URLs. */
.secret-field {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 0.4rem;
  align-items: center;
}
.secret-field-pane { min-width: 0; }
.secret-field-pane select,
.secret-field-pane input { width: 100%; }
.secret-field-toggle { white-space: nowrap; }

/* "Save as template" row in builtin node modals. */
.builtin-template-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 0;
  border-top: 1px solid var(--border);
  margin-top: 0.5rem;
}

/* Retry-policy accordion in the node detail modal. Lives under whatever the
   per-kind form rendered, separated by a top border so it reads as a distinct
   section. */
.ndm-retry-accordion {
  margin-top: 0.9rem;
  border-top: 1px solid var(--border);
  padding-top: 0.7rem;
}
.ndm-retry-accordion > summary {
  cursor: pointer;
  padding: 0.3rem 0;
  list-style: none;
  font-size: 0.95rem;
}
.ndm-retry-accordion > summary::-webkit-details-marker { display: none; }
.ndm-retry-accordion > summary::before {
  content: "▸";
  display: inline-block;
  margin-right: 0.4rem;
  transition: transform 0.15s ease;
  color: var(--muted);
}
.ndm-retry-accordion[open] > summary::before { transform: rotate(90deg); }
.ndm-retry-accordion .retry-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 0.7rem 1rem;
  margin-top: 0.5rem;
}
.ndm-retry-accordion .retry-grid label {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  font-size: 0.85rem;
  color: var(--text);
}
.ndm-retry-accordion .retry-grid input,
.ndm-retry-accordion .retry-grid select {
  background: var(--panel-2);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0.4rem 0.55rem;
  font-size: 0.9rem;
}

/* RunAttempt list in the trace drawer — one row per attempt, slim. */
.run-attempts {
  margin: 0.6rem 0 0.8rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
}
.run-attempts-row {
  display: grid;
  grid-template-columns: 32px 1fr auto;
  align-items: center;
  gap: 0.6rem;
  padding: 0.45rem 0.7rem;
  font-size: 0.85rem;
  border-bottom: 1px solid var(--border);
}
.run-attempts-row:last-child { border-bottom: 0; }
.run-attempts-row .ra-num { font-weight: 600; color: var(--muted); }
.run-attempts-row.ra-succeeded { background: rgba(76, 200, 110, 0.06); }
.run-attempts-row.ra-failed { background: rgba(220, 90, 90, 0.07); }
.run-attempts-row .ra-meta {
  font-family: var(--mono, ui-monospace, "SF Mono", monospace);
  font-size: 0.78rem;
  color: var(--muted);
}
.run-attempts-row .ra-err {
  display: block;
  font-family: var(--mono, ui-monospace, "SF Mono", monospace);
  font-size: 0.78rem;
  color: #d8645a;
  margin-top: 0.15rem;
}

/* Input modal — webhook banner. Shows whenever the pipeline has any
   enabled webhook attached, regardless of the Input node's mode. */
.inm-webhook-banner {
  background: rgba(124, 199, 255, 0.08);
  border: 1px solid rgba(124, 199, 255, 0.32);
  color: var(--text);
  border-radius: 8px;
  padding: 0.7rem 0.9rem;
  margin-bottom: 0.9rem;
  font-size: 0.88rem;
  line-height: 1.45;
}
.inm-webhook-banner ul.inm-webhook-list {
  margin: 0.45rem 0 0;
  padding-left: 1.2rem;
}
.inm-envelope-details { margin: 0.5rem 0 0.8rem; }
.inm-envelope-details summary { cursor: pointer; padding: 0.2rem 0; }
.inm-envelope-details pre.json-sample {
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0.6rem 0.8rem;
  margin: 0.4rem 0;
  overflow-x: auto;
  font-size: 0.78rem;
}

/* Topbar pill badge — shows the count next to "Webhooks". */
.btn .pill {
  display: inline-block;
  background: rgba(124, 199, 255, 0.18);
  color: var(--text);
  border-radius: 999px;
  padding: 0 0.45rem;
  margin-left: 0.3rem;
  font-size: 0.78rem;
  line-height: 1.4;
  font-weight: 600;
}

/* Inline "Test send" form on the webhook list page. Lives in a
   colspan-7 row beneath the webhook it belongs to. */
.webhook-test-row td {
  background: var(--panel-2);
  border-top: 1px solid var(--border);
  padding: 0.9rem 1.1rem;
}
.webhook-test-form { display: flex; flex-direction: column; gap: 0.7rem; }
.webhook-test-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.8rem;
}
.webhook-test-grid label { display: flex; flex-direction: column; gap: 0.25rem; }
.webhook-test-grid textarea {
  width: 100%;
  padding: 0.5rem 0.65rem;
  background: var(--panel);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 6px;
  font-family: ui-monospace, monospace;
  font-size: 0.85rem;
  resize: vertical;
  box-sizing: border-box;
}
.webhook-test-grid textarea:focus {
  border-color: #59657b;
  outline: 2px solid rgba(124, 199, 255, 0.16);
}
.webhook-test-actions {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.webhook-test-result {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding-top: 0.4rem;
}
.webhook-test-result .error { color: #c0392b; }

/* ---------- File upload modal (Files page) ---------- */
.um-credential {
  width: 100%;
  padding: 0.55rem 0.7rem;
  background: var(--panel-2);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 7px;
  font-size: 0.95rem;
}
.dropzone {
  /* Dotted (not dashed) and bright enough to stand out on --panel-2. */
  border: 2px dotted var(--muted);
  border-radius: 10px;
  background: var(--panel-2);
  padding: 1.8rem 1rem;
  text-align: center;
  cursor: pointer;
  transition: border-color 120ms ease, background 120ms ease, color 120ms ease;
  outline: none;
  color: var(--muted);
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 160px;
}
.dropzone:hover,
.dropzone:focus-visible {
  border-color: var(--accent);
  color: var(--accent);
  background: rgba(255, 122, 69, 0.05);
}
.dropzone.is-drag {
  border-color: var(--accent);
  color: var(--accent);
  background: rgba(255, 122, 69, 0.1);
}
.dropzone-inner { pointer-events: none; }  /* clicks bubble to the zone itself */
.dropzone-icon {
  display: block;
  width: 46px;
  height: 46px;
  margin: 0 auto 0.55rem;
  /* SVG paints use currentColor so the icon inherits the dropzone color
     and follows hover/drag state without needing extra selectors. */
}
.dropzone-title {
  margin: 0 0 0.15rem;
  font-weight: 600;
  color: var(--text);
}

.upload-queue {
  list-style: none;
  margin: 1rem 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}
.uq-row {
  display: grid;
  grid-template-columns: 22px 1fr auto auto;
  align-items: center;
  gap: 0.6rem;
  padding: 0.5rem 0.7rem;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 7px;
  font-size: 0.92rem;
}
.uq-row.uq-uploading { border-color: var(--border); }
.uq-row.uq-ok { border-color: rgba(56, 211, 159, 0.45); }
.uq-row.uq-err { border-color: rgba(255, 93, 108, 0.55); }

.uq-status {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
}
.uq-spinner {
  width: 14px;
  height: 14px;
  border: 2px solid var(--border);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: uq-spin 700ms linear infinite;
}
@keyframes uq-spin { to { transform: rotate(360deg); } }
.uq-tick { color: var(--ok); font-weight: 700; }
.uq-cross { color: var(--err); font-weight: 700; }

.uq-name {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.uq-meta { font-size: 0.85rem; }
.uq-msg { font-size: 0.85rem; }
.uq-msg-err { color: var(--err); }

.um-summary {
  margin: 0.9rem 0 0;
  padding: 0.55rem 0.7rem;
  border-radius: 7px;
  font-size: 0.92rem;
  border: 1px solid var(--border);
  background: var(--panel-2);
}
.um-summary-ok { border-color: rgba(56, 211, 159, 0.45); color: var(--ok); }
.um-summary-mixed { border-color: rgba(255, 200, 87, 0.45); color: var(--warn); }

/* ---------- Cost-intelligence dashboard ---------- */
/* Window picker — a tight row of pill buttons that drive the ?days= filter.
   Sits in .page-head-actions so it lines up with the other top-right actions
   on .wrap pages. */
.window-picker {
  display: inline-flex;
  gap: 0.3rem;
  align-items: center;
}
.btn.small {
  padding: 0.25rem 0.55rem;
  font-size: 0.85rem;
}

.cost-totals {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 0.75rem;
  margin: 1rem 0 1.5rem;
}
.cost-card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 0.85rem 1rem;
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}
.cost-card-label {
  font-size: 0.78rem;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.cost-card-value {
  font-size: 1.35rem;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.01em;
}

table.data.costs-table td.num,
table.data.costs-table th.num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}
table.data.costs-table .cost-amount { font-weight: 600; }
table.data.costs-table th.num.small,
table.data.costs-table td.num.small { font-size: 0.85rem; }

/* Bar chart — pure CSS, no chart lib. Each bar is a flex item whose height
   percentage is set inline by the script. Title attribute carries the
   tooltip so we don't have to ship a tooltip component. */
.cost-chart-card { margin-bottom: 1.5rem; }
.cost-chart {
  display: flex;
  align-items: flex-end;
  gap: 4px;
  height: 180px;
  padding: 0.5rem 0.25rem 1.4rem;
  border-bottom: 1px solid var(--border);
}
.cost-bar {
  position: relative;
  flex: 1 1 0;
  min-width: 8px;
  background: linear-gradient(180deg, var(--accent), rgba(255,122,69,0.5));
  border-radius: 3px 3px 0 0;
  cursor: pointer;
  transition: filter 120ms ease;
}
.cost-bar:hover { filter: brightness(1.2); }
.cost-bar-empty {
  background: var(--panel-2);
  border: 1px dashed var(--border);
}
.cost-bar-date {
  position: absolute;
  bottom: -1.2rem;
  left: 50%;
  transform: translateX(-50%);
  font-size: 0.65rem;
  color: var(--muted);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

/* Per-node breakdown card. List, not table, because each row has a nested
   "alternatives" sub-list and a table would force every model swap into a
   fixed column layout that doesn't read as well. */
.cost-nodes-card { margin-bottom: 1.5rem; }
.cost-node-list {
  list-style: none;
  padding: 0;
  margin: 0.5rem 0 0;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}
.cost-node {
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0.75rem 0.9rem;
  background: var(--panel-2);
}
.cost-node-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  flex-wrap: wrap;
}
.cost-node-title { display: flex; align-items: center; gap: 0.4rem; flex-wrap: wrap; }
.cost-node-totals { text-align: right; }
.cost-node-amount {
  font-size: 1.1rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.cost-node-alts {
  margin: 0.6rem 0 0;
  padding-top: 0.6rem;
  border-top: 1px dashed var(--border);
}
.cost-alt-list {
  list-style: none;
  padding: 0;
  margin: 0.35rem 0 0;
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}
.cost-alt {
  display: grid;
  grid-template-columns: minmax(140px, 1fr) auto auto;
  gap: 0.75rem;
  align-items: baseline;
  font-size: 0.92rem;
  font-variant-numeric: tabular-nums;
}
.cost-alt-amount { color: var(--muted); }
.cost-alt-savings {
  color: var(--ok);
  font-weight: 600;
  text-align: right;
}

/* AI suggestion card. The button kicks off a single LLM round-trip; status
   text replaces itself with the prose response (preserving newlines via
   white-space below). */
.cost-suggest-card { margin-bottom: 2rem; }
.cost-suggest-actions {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin: 0.5rem 0 0;
}
.cost-suggest-output {
  margin-top: 0.85rem;
  padding: 0.85rem 1rem;
  border: 1px solid rgba(192, 97, 255, 0.35);
  background: rgba(192, 97, 255, 0.06);
  border-radius: 8px;
}
.cost-suggest-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  margin-bottom: 0.4rem;
}
.cost-suggest-output p {
  margin: 0;
  white-space: pre-wrap;
  line-height: 1.5;
}
.small { font-size: 0.85rem; }
.um-summary-err { border-color: rgba(255, 93, 108, 0.55); color: var(--err); }

/* ---------- Run prompt-diff ---------- */
/* Runs list checkbox column + the sticky compare CTA bar. */
.runs-table th.runs-compare-col,
.runs-table td.runs-compare-col {
  width: 36px;
  text-align: center;
}
.runs-compare-pick {
  width: 16px;
  height: 16px;
  accent-color: var(--accent);
  cursor: pointer;
}
.runs-compare-bar {
  position: sticky;
  bottom: 12px;
  margin-top: 1rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.65rem 0.9rem;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 9px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.45);
}
.runs-compare-bar button[disabled] { opacity: 0.55; cursor: not-allowed; }

/* Diff page header — two side-by-side run summaries. */
.compare-overview .compare-overview-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem;
}
.compare-side {
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0.75rem 0.9rem;
  background: var(--panel-2);
}
.compare-side h3 {
  margin: 0 0 0.5rem;
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.compare-tag {
  display: inline-block;
  min-width: 22px;
  padding: 0 6px;
  border-radius: 4px;
  background: var(--accent);
  color: #18121d;
  font-weight: 700;
  text-align: center;
  font-size: 0.85rem;
}
.compare-side-b .compare-tag { background: var(--accent-2); color: #fff; }
.compare-side dl { display: grid; grid-template-columns: max-content 1fr; gap: 0.2rem 0.7rem; margin: 0; }
.compare-side dt { color: var(--muted); font-size: 0.9rem; }
.compare-side dd { margin: 0; font-size: 0.92rem; word-break: break-word; }
.compare-summary {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin: 0.8rem 0 0;
}
.compare-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  cursor: pointer;
  color: var(--muted);
}

/* Per-step block. */
.prompt-diff-block { margin-top: 1rem; }
.prompt-diff-block--noprompt { opacity: 0.78; }
.prompt-diff-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.8rem;
  margin-bottom: 0.5rem;
  flex-wrap: wrap;
}
.prompt-diff-head h3 { margin: 0; font-size: 1.05rem; }
.prompt-diff-status { display: flex; gap: 0.4rem; align-items: center; flex-wrap: wrap; }

.prompt-diff-section {
  border: 1px solid var(--border);
  border-radius: 7px;
  margin-top: 0.6rem;
  background: var(--panel-2);
}
.prompt-diff-section > summary {
  list-style: none;
  cursor: pointer;
  padding: 0.55rem 0.8rem;
  display: flex;
  align-items: center;
  gap: 0.6rem;
  font-weight: 600;
}
.prompt-diff-section > summary::-webkit-details-marker { display: none; }
.prompt-diff-section > summary::before {
  content: "▸";
  color: var(--muted);
  transition: transform 0.15s ease;
}
.prompt-diff-section[open] > summary::before { transform: rotate(90deg); }
.prompt-diff-section--changed { border-color: rgba(255, 200, 87, 0.5); }
.prompt-diff-section--changed > summary { color: var(--warn); }
.section-label { flex: 1 0 auto; }

/* Side-by-side diff table. The grid is two pairs of (gutter, text). */
.prompt-diff-table {
  width: 100%;
  border-collapse: collapse;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.86rem;
  table-layout: fixed;
}
.prompt-diff-table .col-no { width: 44px; }
.prompt-diff-table .col-text { width: calc(50% - 44px); }
.prompt-diff-table td {
  padding: 1px 8px;
  vertical-align: top;
  border-top: 1px solid rgba(255, 255, 255, 0.04);
}
.prompt-diff-table .diff-no {
  text-align: right;
  color: var(--muted);
  user-select: none;
  background: rgba(255, 255, 255, 0.02);
}
.prompt-diff-table .diff-text {
  white-space: pre-wrap;
  word-break: break-word;
}
.diff-row--equal { background: transparent; }
.diff-row--remove .diff-text--left,
.diff-row--change .diff-text--left {
  background: rgba(255, 93, 108, 0.18);
  color: #ffd2d6;
}
.diff-row--add .diff-text--right,
.diff-row--change .diff-text--right {
  background: rgba(56, 211, 159, 0.18);
  color: #b8f3da;
}
.diff-row--remove .diff-text--right,
.diff-row--add .diff-text--left {
  background: rgba(255, 255, 255, 0.015);
}
.prompt-diff-identical {
  margin: 0;
  padding: 0.6rem 0.8rem;
  border-top: 1px solid var(--border);
  background: var(--panel);
  max-height: 260px;
  overflow: auto;
}
