/* BlackSynq client dashboard — design system.
   Light default + dark via [data-theme="dark"]. Brand: white/near-black + #6a5bfd. */
*, *::before, *::after { box-sizing: border-box; }

:root {
  /* Brand */
  --acc:#6a5bfd; --acc-press:#5749e6; --acc-soft:rgba(106,91,253,.12); --on-acc:#fff;
  /* Light surfaces + text */
  --bg:#f4f4f6; --panel:#ffffff; --panel2:#f7f7f9; --panel3:#eeeef1;
  --line:#e6e6ea; --line2:#d9d9e0;
  --fg:#0d0d0f; --fg2:#42424c; --mut:#8a8a93;
  /* Semantic */
  --ok:#1f9d57; --ok-soft:rgba(31,157,87,.12);
  --bad:#e0455a; --bad-soft:rgba(224,69,90,.12);
  --warn:#b5790a; --warn-soft:rgba(181,121,10,.12);
  /* Radius / spacing / shadow / motion */
  --r:14px; --r-sm:9px; --r-xs:6px; --r-pill:999px;
  --sh-1:0 1px 2px rgba(16,16,24,.06), 0 1px 3px rgba(16,16,24,.04);
  --sh-2:0 4px 14px rgba(16,16,24,.08), 0 2px 6px rgba(16,16,24,.05);
  --sh-3:0 18px 50px rgba(16,16,24,.18), 0 6px 18px rgba(16,16,24,.10);
  --ease:cubic-bezier(.2,.8,.2,1); --dur:.18s; --dur-lg:.28s;
  --sidebar-w:248px;
  color-scheme: light;
}
[data-theme="dark"] {
  --bg:#0a0a0b; --panel:#161619; --panel2:#1c1c22; --panel3:#23232b;
  --line:#26262e; --line2:#34343d;
  --fg:#f5f5f7; --fg2:#b6b6c0; --mut:#74747e;
  --acc-soft:rgba(106,91,253,.16);
  --ok:#4ec479; --ok-soft:rgba(78,196,121,.14);
  --bad:#f0626b; --bad-soft:rgba(240,98,107,.14);
  --warn:#e0a93b; --warn-soft:rgba(224,169,59,.14);
  --sh-1:0 1px 2px rgba(0,0,0,.4);
  --sh-2:0 6px 20px rgba(0,0,0,.45);
  --sh-3:0 24px 60px rgba(0,0,0,.6);
  color-scheme: dark;
}

html, body { height:100%; }
body {
  margin:0; background:var(--bg); color:var(--fg);
  font:15px/1.5 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  -webkit-font-smoothing:antialiased; text-rendering:optimizeLegibility;
  transition:background var(--dur) var(--ease), color var(--dur) var(--ease);
}
a { color:var(--acc); text-decoration:none; }
/* Logo is a white wordmark — invert it to dark on light themes so it stays visible. */
[data-theme="light"] .brand img, [data-theme="light"] .auth-card .logo img { filter:invert(1); }
.mono { font-family:ui-monospace,SFMono-Regular,Menlo,monospace; font-size:12.5px; }
.mut { color:var(--mut); } .fg2 { color:var(--fg2); }
::selection { background:var(--acc-soft); }
@media (prefers-reduced-motion: reduce) { * { animation-duration:.001ms !important; transition-duration:.001ms !important; } }

/* Typography */
h1 { font-size:24px; line-height:1.2; letter-spacing:-.02em; font-weight:680; margin:0; }
h2 { font-size:18px; letter-spacing:-.01em; font-weight:650; margin:0; }
/* Card headings sit ABOVE their description, so they must not be smaller than it — 12px against a 12.5px
   description inverted the order a reader expects. 13px keeps title > description (12.5) > body (12). */
h3 { font-size:13px; text-transform:uppercase; letter-spacing:.06em; color:var(--mut); font-weight:650; margin:0; }
.sub { color:var(--mut); font-size:14px; margin-top:4px; }
.hint { font-size:12.5px; color:var(--mut); line-height:1.45; }
.hint.bad { color:var(--bad); } .hint.ok { color:var(--ok); }

/* ── App layout: sidebar + content ─────────────────────────────────────────── */
.app { display:grid; grid-template-columns:var(--sidebar-w) 1fr; min-height:100vh; }
/* draggable sidebar width — thin handle at the sidebar's right edge (desktop only) */
.sidebar-resize { position:fixed; top:0; bottom:0; left:calc(var(--sidebar-w) - 3px); width:6px; cursor:col-resize; z-index:40; }
.sidebar-resize::after { content:""; position:absolute; inset:0 2px; background:transparent; transition:background var(--dur) var(--ease); }
.sidebar-resize:hover::after, .sidebar-resize.dragging::after { background:var(--acc); }
.sidebar {
  position:sticky; top:0; height:100vh; background:var(--panel); border-right:1px solid var(--line);
  display:flex; flex-direction:column; padding:14px 12px; gap:4px; z-index:30;
  transition:transform var(--dur-lg) var(--ease);
}
.sidebar .brand { display:flex; align-items:center; gap:9px; padding:6px 8px 14px; }
.sidebar .brand img { height:20px; }
.sidebar .brand-sub { font-size:11px; color:var(--mut); font-weight:600; letter-spacing:.04em; text-transform:uppercase; }

.botswitch { position:relative; margin-bottom:10px; }
.botswitch > button { width:100%; display:flex; align-items:center; gap:9px; padding:9px 11px; border-radius:var(--r-sm);
  background:var(--panel2); border:1px solid var(--line); color:var(--fg); cursor:pointer; font:inherit; text-align:left; }
.botswitch > button:hover { border-color:var(--line2); }
.botswitch .bs-ava { width:24px; height:24px; border-radius:7px; background:var(--acc); color:#fff; display:flex; align-items:center; justify-content:center; font-size:12px; font-weight:700; flex:none; }
.botswitch .bs-nm { flex:1; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-weight:560; font-size:14px; }
.botswitch .bs-chev { color:var(--mut); }
.botmenu { position:absolute; left:0; right:0; top:calc(100% + 4px); background:var(--panel); border:1px solid var(--line2);
  border-radius:var(--r-sm); box-shadow:var(--sh-2); padding:5px; z-index:40; max-height:50vh; overflow:auto;
  animation:pop var(--dur) var(--ease); }
.botmenu .item { display:flex; align-items:center; gap:9px; padding:8px 9px; border-radius:var(--r-xs); cursor:pointer; }
.botmenu .item:hover { background:var(--panel2); } .botmenu .item.active { background:var(--acc-soft); }
.botmenu .item .bs-ava { width:22px; height:22px; font-size:11px; }
.botmenu .add { color:var(--acc); font-weight:600; }

.nav { display:flex; flex-direction:column; gap:2px; }
.nav a { display:flex; align-items:center; gap:11px; padding:9px 11px; border-radius:var(--r-sm); color:var(--fg2);
  font-weight:540; cursor:pointer; transition:background var(--dur) var(--ease), color var(--dur) var(--ease); }
.nav a svg { width:18px; height:18px; flex:none; opacity:.85; }
.nav a:hover { background:var(--panel2); color:var(--fg); }
.nav a.active { background:var(--acc-soft); color:var(--acc); }
.nav a.active svg { opacity:1; }
.side-foot { margin-top:auto; padding-top:10px; border-top:1px solid var(--line); display:flex; flex-direction:column; gap:8px; }
.acct { display:flex; align-items:center; gap:9px; padding:4px 6px; }
.acct .bs-ava { width:30px; height:30px; border-radius:9px; background:var(--panel3); color:var(--fg); font-size:13px; display:flex; align-items:center; justify-content:center; font-weight:700; flex:none; }
.acct .meta { overflow:hidden; } .acct .meta .e { font-size:13px; font-weight:560; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.acct .meta .w { font-size:11.5px; color:var(--mut); }
.side-foot .row2 { display:flex; gap:8px; }

/* Content */
.content { min-width:0; display:flex; flex-direction:column; }
.topbar { display:none; align-items:center; gap:12px; height:54px; padding:0 16px; border-bottom:1px solid var(--line); background:var(--panel); position:sticky; top:0; z-index:20; }
main { padding:28px 32px; max-width:1080px; width:100%; margin:0 auto; }
.page-head { margin-bottom:22px; }
.view { animation:fade var(--dur-lg) var(--ease); }

@keyframes fade { from { opacity:0; transform:translateY(6px); } to { opacity:1; transform:none; } }
@keyframes pop { from { opacity:0; transform:scale(.97) translateY(-4px); } to { opacity:1; transform:none; } }
@keyframes shimmer { 100% { background-position:-200% 0; } }
@keyframes spin { to { transform:rotate(360deg); } }

/* ── Cards / tiles ──────────────────────────────────────────────────────────── */
.card { background:var(--panel); border:1px solid var(--line); border-radius:var(--r); padding:22px; margin-bottom:16px; box-shadow:var(--sh-1); }
.card.sub { background:var(--panel2); box-shadow:none; }
.card-title { display:flex; align-items:center; gap:10px; margin-bottom:16px; }
.card-title .right, .right { margin-left:auto; }
.grid2 { display:grid; gap:14px; grid-template-columns:1fr 1fr; }
.row { display:flex; gap:12px; flex-wrap:wrap; align-items:flex-end; }
.row > .field { flex:1; min-width:180px; margin:0; }
.flush { display:flex; gap:10px; align-items:center; flex-wrap:wrap; }

.tiles { display:grid; grid-template-columns:repeat(auto-fill,minmax(150px,1fr)); gap:12px; }
.tile { background:var(--panel); border:1px solid var(--line); border-radius:var(--r-sm); padding:16px; box-shadow:var(--sh-1); }
.tile .ic { width:30px;height:30px;border-radius:8px;background:var(--acc-soft);color:var(--acc);display:flex;align-items:center;justify-content:center;margin-bottom:10px; }
.tile .ic svg { width:17px;height:17px; }
.tile .n { font-size:26px; font-weight:700; letter-spacing:-.02em; }
.tile .k { font-size:12.5px; color:var(--mut); margin-top:2px; }

/* ── Forms ──────────────────────────────────────────────────────────────────── */
.field { margin-bottom:16px; }
label { display:block; font-size:13px; color:var(--fg2); margin-bottom:6px; font-weight:560; }
input, textarea, select {
  font:inherit; width:100%; background:var(--panel); border:1px solid var(--line2); color:var(--fg);
  padding:10px 12px; border-radius:var(--r-sm); transition:border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
input:focus, textarea:focus, select:focus { outline:none; border-color:var(--acc); box-shadow:0 0 0 3px var(--acc-soft); }
input::placeholder, textarea::placeholder { color:var(--mut); }
textarea { min-height:120px; resize:vertical; line-height:1.55; }
.char { font-size:11.5px; color:var(--mut); text-align:right; margin-top:4px; }
.char.over { color:var(--bad); }

/* Buttons */
button { font:inherit; cursor:pointer; border:1px solid var(--line2); background:var(--panel); color:var(--fg);
  padding:9px 16px; border-radius:var(--r-sm); font-weight:560; display:inline-flex; align-items:center; gap:7px; justify-content:center;
  transition:transform .08s var(--ease), border-color var(--dur) var(--ease), background var(--dur) var(--ease), filter var(--dur) var(--ease); }
button:hover { border-color:var(--line2); background:var(--panel2); }
button:active { transform:scale(.97); }
button:disabled { opacity:.5; cursor:default; transform:none; }
button.primary { background:var(--acc); border-color:var(--acc); color:var(--on-acc); }
button.primary:hover { background:var(--acc-press); border-color:var(--acc-press); }
button.danger { color:var(--bad); border-color:var(--bad-soft); background:transparent; }
button.danger:hover { background:var(--bad-soft); }
button.ghost { background:transparent; border-color:transparent; }
button.ghost:hover { background:var(--panel2); }
button.sm { padding:6px 11px; font-size:13px; }
button.icon { padding:8px; border-radius:var(--r-sm); }
button.icon svg { width:17px; height:17px; }
button .spin { width:14px; height:14px; border:2px solid currentColor; border-right-color:transparent; border-radius:50%; animation:spin .6s linear infinite; }

/* Toggle switch */
.switch { position:relative; display:inline-flex; align-items:center; cursor:pointer; gap:10px; }
.switch input { position:absolute; opacity:0; width:0; height:0; }
.switch .track { position:relative; width:42px; height:24px; border-radius:var(--r-pill); background:var(--line2); transition:background var(--dur) var(--ease); flex:none; }
.switch .track::after { content:""; position:absolute; top:3px; left:3px; width:18px; height:18px; border-radius:50%; background:#fff; box-shadow:var(--sh-1); transition:transform var(--dur) var(--ease); }
.switch input:checked + .track { background:var(--acc); }
.switch input:checked + .track::after { transform:translateX(18px); }
.switch .lbl { font-size:14px; color:var(--fg); }

/* Segmented control */
.seg { display:inline-flex; background:var(--panel2); border:1px solid var(--line); border-radius:var(--r-sm); padding:3px; }
.seg button { border:none; background:transparent; padding:5px 13px; font-size:13px; border-radius:var(--r-xs); color:var(--mut); }
.seg button:hover { background:transparent; color:var(--fg2); }
.seg button.on { background:var(--panel); color:var(--fg); box-shadow:var(--sh-1); }

/* Chips / badges */
.chips { display:flex; gap:8px; flex-wrap:wrap; align-items:center; }
.chip { font-size:12.5px; padding:5px 11px; border-radius:var(--r-pill); background:var(--panel2); border:1px solid var(--line); color:var(--fg2); display:inline-flex; gap:7px; align-items:center; }
.chip b { color:var(--fg); }
.chip .d { width:7px; height:7px; border-radius:50%; background:var(--mut); }
.chip .d.ok { background:var(--ok); } .chip .d.bad { background:var(--bad); } .chip .d.acc { background:var(--acc); } .chip .d.warn { background:var(--warn); }
.badge { font-size:11px; padding:3px 9px; border-radius:var(--r-pill); background:var(--panel3); color:var(--fg2); }
.badge.acc { background:var(--acc-soft); color:var(--acc); }

/* Tables */
/* app.js already wraps the columnar tables (Branches, message templates) in .tbl-wrap, but this
   sheet never defined the class — so on a phone those tables pushed the document to 450–563px
   wide and the page itself scrolled sideways. Scroll the table, never the body. */
.tbl-wrap { overflow-x:auto; }
table { width:100%; border-collapse:collapse; font-size:14px; }
th, td { text-align:left; padding:11px 12px; border-bottom:1px solid var(--line); }
th { color:var(--mut); font-weight:560; font-size:11.5px; text-transform:uppercase; letter-spacing:.05em; }
tr.clickable { cursor:pointer; } tr.clickable:hover td { background:var(--panel2); }

/* Logs panel */
.logs { font-family:ui-monospace,Menlo,monospace; font-size:12.5px; background:var(--panel2); border:1px solid var(--line); border-radius:var(--r-sm); max-height:56vh; overflow:auto; }

/* Chat bubbles (transcript) */
.chat { display:flex; flex-direction:column; gap:8px; padding:14px; background:var(--panel2); border:1px solid var(--line); border-radius:var(--r-sm); max-height:56vh; overflow:auto; }
.bub { max-width:78%; padding:9px 13px; border-radius:16px; font-size:14px; line-height:1.45; white-space:pre-wrap; word-break:break-word; }
.bub.them { align-self:flex-start; background:var(--panel3); color:var(--fg); border-bottom-left-radius:5px; }
.bub.us { align-self:flex-end; background:var(--acc); color:var(--on-acc); border-bottom-right-radius:5px; }

/* Empty states */
.empty { color:var(--mut); padding:34px 18px; text-align:center; }
.empty .ic { width:46px; height:46px; border-radius:13px; background:var(--panel2); display:flex; align-items:center; justify-content:center; margin:0 auto 12px; color:var(--mut); }
.empty .ic svg { width:24px; height:24px; }
.empty .t { color:var(--fg); font-weight:600; font-size:15px; margin-bottom:4px; }

/* Skeleton */
.sk { background:linear-gradient(90deg,var(--panel2) 25%,var(--panel3) 37%,var(--panel2) 63%); background-size:200% 100%; animation:shimmer 1.3s infinite; border-radius:var(--r-xs); }
.sk-line { height:13px; margin:9px 0; }
.sk-card { height:90px; border-radius:var(--r); margin-bottom:16px; }

/* Top progress bar */
#progress { position:fixed; top:0; left:0; height:2.5px; width:0; background:var(--acc); z-index:100; opacity:0; transition:width .2s var(--ease), opacity .3s; box-shadow:0 0 8px var(--acc); }
#progress.on { opacity:1; }

/* Modal */
.modal-bg { position:fixed; inset:0; background:rgba(10,10,14,.5); backdrop-filter:blur(4px); display:none; align-items:center; justify-content:center; z-index:60; }
.modal-bg.show { display:flex; animation:fade var(--dur) var(--ease); }
.modal { background:var(--panel); border:1px solid var(--line2); border-radius:var(--r); padding:26px; width:480px; max-width:calc(100vw - 32px); max-height:88vh; overflow:auto; box-shadow:var(--sh-3); animation:pop var(--dur-lg) var(--ease); }
.modal h2 { margin-bottom:18px; }
/* t027: the campaign modal carries the variable mapping AND a live preview side by side. Stacked at 480px
   they push Create below the fold, and a preview you must scroll away from to edit is not a live preview.
   An opt-in class, removed on close, so every other modal stays 480px. */
.modal.wide { width:860px; }
.ob-vars { display:grid; grid-template-columns:1fr 300px; gap:18px; align-items:start;
  margin-top:14px; padding:12px; border:1px solid var(--line2); border-radius:8px; }
.ob-vhead { font-weight:600; }
.ob-vpreview { position:sticky; top:0; }
.ob-vpage { text-align:center; margin-top:6px; display:flex; align-items:center; justify-content:center; gap:10px; }
.ob-vpage button { padding:0 8px; }
.ob-varrow { display:flex; align-items:center; gap:8px; margin-top:9px; }
.ob-varrow code { min-width:40px; opacity:.75; }
.ob-varrow select { flex:1.2; min-width:0; }
.ob-varrow input { flex:.9; min-width:0; }
.ob-varwarn { margin-left:48px; font-size:12px; color:var(--warn, #e3a93c); }
/* Below the two-column breakpoint the preview stacks under the controls rather than being squeezed. */
@media (max-width:820px) {
  .modal.wide { width:480px; }
  .ob-vars { grid-template-columns:1fr; }
  .ob-vpreview { position:static; }
}

/* Toast */
#toast { position:fixed; bottom:22px; left:50%; transform:translateX(-50%) translateY(20px); background:var(--fg); color:var(--bg);
  padding:12px 18px; border-radius:var(--r-pill); font-size:14px; font-weight:560; box-shadow:var(--sh-3); z-index:80;
  opacity:0; pointer-events:none; transition:opacity var(--dur) var(--ease), transform var(--dur-lg) var(--ease); display:flex; gap:9px; align-items:center; }
#toast.show { opacity:1; transform:translateX(-50%) translateY(0); }
#toast .dot { width:8px; height:8px; border-radius:50%; background:var(--ok); }
#toast.bad .dot { background:var(--bad); }

/* Carousel image dropzone */
.cdrop { position:relative; width:120px; height:120px; border-radius:var(--r-sm); border:1px dashed var(--line2); overflow:hidden; display:flex; align-items:center; justify-content:center; cursor:pointer; background:var(--panel); }
.cdrop:hover { border-color:var(--acc); }
.cdrop-ov { position:absolute; inset:0; display:flex; align-items:center; justify-content:center; gap:6px; background:rgba(10,10,14,.55); color:#fff; font-size:12px; font-weight:560; opacity:0; transition:opacity var(--dur) var(--ease); }
.cdrop:hover .cdrop-ov { opacity:1; }

/* Drag reorder */
.drag-handle { cursor:grab; color:var(--mut); display:inline-flex; touch-action:none; }
.dragging { opacity:.5; }

/* Sticky save bar */
.savebar { position:sticky; bottom:0; background:linear-gradient(to top, var(--bg) 72%, transparent); padding:14px 0 6px; display:flex; gap:12px; align-items:center; margin-top:4px; z-index:10; }

/* Auth */
.auth-wrap { min-height:100vh; display:flex; align-items:center; justify-content:center; padding:20px; background:radial-gradient(1200px 600px at 50% -10%, var(--acc-soft), transparent 60%), var(--bg); }
.auth-card { width:380px; max-width:100%; background:var(--panel); border:1px solid var(--line); border-radius:var(--r); padding:30px; box-shadow:var(--sh-2); animation:pop var(--dur-lg) var(--ease); }
.auth-card .logo { display:flex; justify-content:center; margin-bottom:8px; } .auth-card .logo img { height:26px; }
.auth-card h1 { text-align:center; font-size:21px; margin-bottom:4px; }
.auth-card .sub { text-align:center; margin-bottom:22px; margin-top:0; }
.gbtn { width:100%; justify-content:center; }
.auth-sep { display:flex; align-items:center; gap:12px; color:var(--mut); font-size:12px; margin:18px 0; }
.auth-sep::before, .auth-sep::after { content:""; flex:1; height:1px; background:var(--line); }
.link-btn { background:none; border:none; color:var(--acc); padding:0; font-weight:560; cursor:pointer; }

/* ── Responsive ─────────────────────────────────────────────────────────────── */
.backdrop { display:none; position:fixed; inset:0; background:rgba(10,10,14,.45); z-index:25; }

/* ── Hover help: ⓘ cue + shared floating tooltip ─────────────────────────────── */
.helpcue { display:inline-flex; align-items:center; vertical-align:middle; margin-left:6px; color:var(--mut); cursor:help; border-radius:50%; transition:color var(--dur) var(--ease); }
.helpcue:hover, .helpcue:focus-visible { color:var(--acc); }
.helpcue:focus-visible { outline:none; box-shadow:0 0 0 3px var(--acc-soft); }
.card-title .helpcue { margin-left:2px; }
#tip { position:fixed; z-index:90; max-width:260px; padding:8px 11px; background:var(--panel); color:var(--fg2); border:1px solid var(--line); border-radius:var(--r-sm); box-shadow:var(--sh-2); font-size:12.5px; line-height:1.45; pointer-events:none; opacity:0; transform:translateY(3px); transition:opacity var(--dur) var(--ease), transform var(--dur) var(--ease); }
#tip.show { opacity:1; transform:none; }

/* ── KB source-list pager ─────────────────────────────────────────────────── */
.pager { display:flex; gap:5px; align-items:center; margin-top:14px; flex-wrap:wrap; }
.pager button { padding:4px 10px; font-size:12px; min-width:32px; }
.pager button.cur { background:var(--acc); border-color:var(--acc); color:#fff; font-weight:600; }
.pager .pinfo { color:var(--mut); font-size:11.5px; margin-left:auto; }

@media (max-width:900px) {
  .app { grid-template-columns:1fr; }
  .sidebar-resize { display:none; }
  .sidebar { position:fixed; left:0; top:0; width:var(--sidebar-w); transform:translateX(-100%); box-shadow:var(--sh-3); }
  .sidebar.open { transform:none; }
  .backdrop.show { display:block; }
  .topbar { display:flex; }
  main { padding:20px 16px; }
}
@media (max-width:640px) {
  main { padding:16px 13px; }
  .grid2 { grid-template-columns:1fr; }
  h1 { font-size:21px; }
  table.stack thead { display:none; }
  table.stack tr { display:block; border:1px solid var(--line); border-radius:var(--r-sm); margin-bottom:10px; padding:6px 10px; }
  table.stack td { display:flex; justify-content:space-between; gap:12px; border:none; padding:6px 0; }
  table.stack td::before { content:attr(data-l); color:var(--mut); font-size:12px; }
  /* Safari on iOS zooms the whole page when a focused field is under 16px, and never zooms back.
     Fields here inherit the 14px body font, so every one of them triggered it. */
  input, textarea, select { font-size:16px; }
  /* Thumb-sized targets: nav rows sat at 41px, icon buttons at 35px, the KB pager at 28px. */
  button, .nav a, .tab { min-height:44px; }
}

/* ── AI Auto-Build (Studio) ─────────────────────────────────────────────── */
.st-steps { display:flex; align-items:center; gap:9px; margin:4px 0 18px; font-size:12px; font-weight:600; }
.st-step { color:var(--mut); }
.st-step.on { color:var(--acc); } .st-step.done { color:var(--fg2); }
.st-sep { color:var(--line2); }
.st-form .row { gap:14px; }
.st-reason-wrap summary { cursor:pointer; }
.st-reason { background:#000; border:1px solid var(--line); border-radius:10px; padding:11px 13px; margin-top:8px; max-height:32vh; overflow:auto;
  font-family:ui-monospace,Menlo,monospace; font-size:12px; color:#ccc; white-space:pre-wrap; }
.st-h { font-size:12px; text-transform:uppercase; letter-spacing:.05em; color:var(--mut); margin:22px 0 10px; font-weight:700; }
.st-review { max-width:860px; }
.st-change { border:1px solid var(--line); border-radius:12px; padding:13px 15px; margin-bottom:9px; background:var(--panel); transition:border-color .15s,opacity .15s; }
.st-change.off { opacity:.5; }
.st-chead { display:flex; align-items:center; gap:10px; }
.st-ck { display:flex; align-items:center; }
.st-ck input { width:16px; height:16px; accent-color:var(--acc); cursor:pointer; }
.st-ctitle { font-size:13.5px; font-weight:650; color:var(--fg); flex:1; }
.st-cbadge { font-size:9.5px; font-weight:700; letter-spacing:.04em; }
.st-cdesc { font-size:12px; color:var(--mut); margin:5px 0 0 26px; }
.st-clinks { display:flex; gap:16px; margin:9px 0 0 26px; }
.st-clinks a { font-size:12px; font-weight:600; color:var(--acc); }
.st-diff { margin:11px 0 0 26px; display:grid; gap:8px; }
.st-before, .st-after { font-size:12px; line-height:1.5; white-space:pre-wrap; word-break:break-word; border-left:3px solid var(--line2); padding:8px 11px; border-radius:0 7px 7px 0; background:var(--panel2); max-height:240px; overflow:auto; }
.st-before { color:var(--mut); } .st-after { color:var(--ok); border-left-color:var(--ok); }
.st-note { margin:10px 0 0 26px; display:flex; gap:8px; align-items:flex-start; }
.st-note textarea { flex:1; }
.st-customrow { display:flex; gap:8px; margin-bottom:8px; align-items:center; }
.st-customrow input { flex:1; }
.st-cats { display:grid; grid-template-columns:repeat(auto-fill,minmax(220px,1fr)); gap:9px; }
.st-cats .st-change { margin-bottom:0; }
.logrow { display:flex; gap:10px; padding:3px 13px; white-space:nowrap; }
.logrow .lt { color:var(--mut); } .logrow .lv { width:34px; } .logrow .lm { white-space:pre-wrap; word-break:break-word; color:var(--fg2); }
.deploylog { font-family:ui-monospace,Menlo,monospace; font-size:12px; background:#000; border:1px solid var(--line); border-radius:var(--r-sm); max-height:36vh; overflow:auto; padding:8px 0; margin-top:14px; }
.deploylog .logrow { white-space:normal; color:#ddd; }
.l-ok { color:var(--ok); } .l-err { color:var(--bad); } .l-warn { color:var(--warn); }
/* A step that is still RUNNING. Replaces a static "…", which read as a stalled build. Sized and centred to
   match the ✓ it becomes, so the row does not shift on completion. Scoped to .logrow — `button .spin` above
   is the separate busy-button spinner and is drawn in currentColor against a button, not against black. */
.logrow .spin { display:inline-block; align-self:center; width:11px; height:11px; border-radius:50%;
  border:2px solid rgba(255,255,255,.22); border-top-color:var(--acc); animation:spin .7s linear infinite; }
@media (prefers-reduced-motion:reduce) { .logrow .spin { animation-duration:2.4s; } }

/* ── Outbound: WhatsApp message preview + template builder (ported from outbound UI) ── */
.ob-builder-grid { display:grid; grid-template-columns:minmax(0,1.25fr) minmax(260px,.75fr); gap:22px; align-items:start; }
@media (max-width:820px){ .ob-builder-grid { grid-template-columns:1fr; } }
.ob-preview-aside h4 { margin:0 0 8px; font-size:13px; color:var(--mut); }
.wa { -webkit-font-smoothing:antialiased; --wp:#0a0a0a; --bub:#242626; --txt:#ededed; --sec:#888989; --hdr:#151616; --grn:#23c063; --div:#393a3a; }
.wa.light { --wp:#efeae2; --bub:#fff; --txt:#111b21; --sec:#667781; --hdr:#f0f2f5; --grn:#008069; --div:#0000000f; }
.wa-chat { background:var(--wp); border-radius:10px; padding:14px 12px; margin-top:6px; position:relative; overflow:hidden; }
.wa-bubble { background:var(--bub); border-radius:8px 8px 8px 0; max-width:300px; overflow:hidden; box-shadow:0 1px 1px rgba(0,0,0,.2); font:14.5px/1.42 -apple-system,BlinkMacSystemFont,"Helvetica Neue",Arial,sans-serif; }
.wa-img { display:block; width:100%; }
.wa-content { padding:7px 9px 5px; }
.wa-hdrtext { font-weight:600; color:var(--txt); margin-bottom:3px; }
.wa-body { color:var(--txt); white-space:pre-wrap; word-wrap:break-word; }
.wa-body.clamp { display:-webkit-box; -webkit-line-clamp:4; -webkit-box-orient:vertical; overflow:hidden; }
.wa-body b { font-weight:600; }
.wa-readmore { display:block; width:max-content; max-width:100%; background:transparent; border:0; padding:6px 0; color:var(--grn); font:inherit; text-align:left; cursor:pointer; }
.wa-footer { color:var(--sec); font-size:12.5px; margin-top:9px; }
.wa-meta { text-align:right; color:var(--sec); font-size:11px; margin-top:2px; }
.wa-btns { background:var(--bub); }
.wa-btn { display:flex; align-items:center; justify-content:center; gap:7px; padding:10px 8px; border-top:1px solid var(--div); color:var(--grn); font-weight:500; text-decoration:none; cursor:pointer; }
button.wa-btn { width:100%; background:var(--bub); border-radius:0; font:inherit; font-weight:500; }
.wa-btn svg { width:18px; height:18px; fill:none; stroke:var(--grn); stroke-width:2; stroke-linecap:round; stroke-linejoin:round; }
.wa-phone { width:320px; max-width:84vw; background:#000; border-radius:38px; padding:10px; margin:0 auto; }
.wa-screen { border-radius:28px; overflow:hidden; background:var(--wp); display:flex; flex-direction:column; height:560px; position:relative; }
.wa-sheet-back { position:absolute; inset:0; background:rgba(0,0,0,.5); display:flex; align-items:flex-end; z-index:20; }
.wa-sheet { width:100%; background:var(--bub); border-radius:16px 16px 0 0; max-height:88%; overflow-y:auto; padding-bottom:6px; }
.wa-sheet-head { position:relative; text-align:center; color:var(--txt); font-weight:600; padding:14px; }
.wa-sheet-x { position:absolute; right:6px; top:4px; background:transparent; border:0; color:var(--sec); cursor:pointer; font:inherit; }
.wa-sgrp + .wa-sgrp { border-top:6px solid var(--wp); }
.wa-sheet .wa-btn { justify-content:flex-start; gap:14px; padding:14px 18px; }
.wa-topbar { background:var(--hdr); display:flex; align-items:center; gap:9px; padding:12px; }
.wa-back { color:var(--grn); font-size:22px; line-height:1; }
.wa-avatar { width:36px; height:36px; border-radius:50%; background:#6a7a82; flex:0 0 36px; display:flex; align-items:center; justify-content:center; color:#fff; font-weight:700; font-size:13px; }
.wa-who { flex:1; line-height:1.2; }
.wa-name { color:var(--txt); font-weight:600; font-size:15.5px; }
.wa-sub { color:var(--sec); font-size:12px; }
.wa-acts { display:flex; gap:16px; }
.wa-acts svg { width:20px; height:20px; fill:none; stroke:var(--grn); stroke-width:2; stroke-linecap:round; stroke-linejoin:round; }
.wa-scroll { flex:1; overflow-y:auto; padding:14px 12px; }
.wa-input { display:flex; align-items:center; gap:8px; padding:8px 10px; }
.wa-field { flex:1; background:var(--bub); border-radius:20px; height:36px; display:flex; align-items:center; padding:0 14px; color:var(--sec); font-size:14px; }
.wa-send { width:36px; height:36px; border-radius:50%; background:var(--grn); flex:0 0 36px; display:flex; align-items:center; justify-content:center; }
.wa-send svg { width:17px; height:17px; fill:#fff; }

/* Utility. app.js toggles this class in ~20 places (schedule field, segment condition inputs, template
   header value, the phone-preview options sheet, the campaign code field) and it was never defined here —
   so every one of those show/hide toggles was inert and the element stayed visible. Found by rendering the
   campaign modal in a browser; no API test can see it. !important and last in the file because it has to
   beat same-specificity display rules like .wa-sheet-back{display:flex}. */
.hidden { display:none !important; }

/* Reveal-password toggle. The wrapper is added by app.js at runtime (it scans for input[type=password]), so
   these rules have to work for a field in ANY container — hence positioning against .pw-wrap, not the form. */
.pw-wrap { position:relative; display:block; }
.pw-wrap > input { width:100%; padding-right:38px; }          /* room for the button, so text never runs under it */
.pw-eye {
  position:absolute; right:6px; top:50%; transform:translateY(-50%);
  display:flex; align-items:center; justify-content:center;
  width:26px; height:26px; padding:0; border:0; border-radius:6px;
  background:transparent; color:var(--mut,#74747e); cursor:pointer;
}
.pw-eye:hover { color:var(--fg); background:var(--panel2); }
.pw-eye:focus-visible { outline:2px solid var(--acc,#6a5bfd); outline-offset:1px; }
.pw-eye svg { width:15px; height:15px; display:block; }

/* The `hidden` ATTRIBUTE must actually hide. The UA stylesheet's [hidden]{display:none} loses to any author
   `display` rule, so `.st-diff { display:grid }` silently defeated `<div class="st-diff" hidden>` — the box was
   always visible and its "Show update" toggle appeared to do nothing. Same failure as the `.hidden` class, which
   was used in ~20 places and defined nowhere. Declared once, globally, so neither can recur. */
[hidden] { display:none !important; }

/* Build screen — its own step, with real progress. The build used to append a log to the bottom of the review
   page, which you had to scroll to find and which gave no sense of how far along it was. */
.st-buildhead { display:flex; align-items:flex-start; gap:12px; margin-bottom:12px; }
.st-buildhead > div { flex:1; }
.st-buildtitle { font-size:15px; font-weight:650; color:var(--fg); }
.st-bar { height:6px; border-radius:99px; background:var(--panel2); overflow:hidden; }
.st-bar-fill { height:100%; width:4%; border-radius:99px; background:linear-gradient(90deg,var(--acc),#8b7bff); transition:width .5s ease; }
.st-bar-fill.bad { background:var(--bad); }
/* A grouped child change (the expert's hand-off / sign-off) shown inside its parent's panel. */
.st-sub { margin-top:10px; padding-top:10px; border-top:1px dashed var(--line); }
.st-subh { font-size:11.5px; font-weight:600; color:var(--fg2); margin-bottom:5px; }

/* Confirmation that an ingest landed — deliberately a panel, not a hint line, because the previous one-line
   version was erased by the tab re-render before anyone could read it. */
.kb-added { display:flex; gap:10px; align-items:flex-start; margin-top:14px; padding:11px 13px;
  background:var(--ok-soft); border:1px solid var(--ok); border-radius:var(--r-sm); font-size:13px; }
.kb-added svg { color:var(--ok); flex:none; margin-top:1px; }
.kb-added .hint { margin-top:3px; }
.nowrap { white-space:nowrap; }

/* TYPE HIERARCHY IN CONTENT BOXES — title (13.5) > description (12.5) > body (12).
   Long-form boxes inherit body's 15px, so a prompt's own text rendered THREE pixels larger than the sentence
   describing it and the descending order a reader expects was inverted. This is the whole set of places that
   holds prose the bot will say: the auto-build refine notes, the four agent prompt editors, and the
   knowledge-source viewer. Single-line form fields (name, city, URL) are left at body size — there the label
   is a label, not a description, and shrinking an input people type into helps nobody. */
.st-note textarea,
#pe-prompt, #kb-prompt, .au-prompt { font-size:12px; line-height:1.6; }
/* …except on a phone: iOS zooms the page in when a focused field is under 16px and never zooms back,
   stranding the rest of the dashboard off-screen. Density loses to that. Sits here rather than in the
   responsive section because it has to beat the rule directly above on source order. */
@media (max-width:640px) { .st-note textarea, #pe-prompt, #kb-prompt, .au-prompt { font-size:16px; } }

/* WhatsApp inline styles in the preview — the full set, so the preview matches the delivered message. */
.wa-body i, .wa-footer i { font-style:italic; }
.wa-body s, .wa-footer s { text-decoration:line-through; }
.wa-body code, .wa-footer code { font-family:ui-monospace,Menlo,monospace; font-size:.92em;
  background:rgba(255,255,255,.10); padding:1px 4px; border-radius:4px; }
/* Formatting toolbar above the message body. */
.fmt-bar { display:flex; gap:6px; align-items:center; flex-wrap:wrap; margin-bottom:6px; }
.fmt-bar button { padding:3px 9px; font-size:12.5px; line-height:1.4; min-width:28px; }
.fmt-bar .fmt-emoji { font-size:15px; padding:2px 6px; }
.fmt-bar .sep { width:1px; height:18px; background:var(--line2); margin:0 2px; }

/* Image-header well: click or drop a file. Sized to the 1.91:1 ratio WhatsApp renders a header at, so what
   you drop is framed the way the customer will see it. */
.hdr-thumb { flex:0 0 150px; height:79px; border:1px dashed var(--line2); border-radius:var(--r-sm);
  display:flex; align-items:center; justify-content:center; text-align:center; cursor:pointer;
  color:var(--mut); font-size:12px; overflow:hidden; background:var(--panel2);
  transition:border-color var(--dur) var(--ease), background var(--dur) var(--ease); }
.hdr-thumb:hover, .hdr-thumb.over { border-color:var(--acc); background:var(--acc-soft); color:var(--fg2); }
.hdr-thumb img { width:100%; height:100%; object-fit:cover; display:block; }

/* Inline "working" spinner for status lines. More specific rules (button .spin, .logrow .spin) still win. */
.spin { display:inline-block; width:11px; height:11px; border:2px solid var(--line2); border-top-color:var(--acc);
  border-radius:50%; animation:spin .7s linear infinite; vertical-align:-1px; margin-right:5px; }
@media (prefers-reduced-motion:reduce) { .spin { animation-duration:2.4s; } }

/* Why a campaign didn't go out (#160). Sits under the status badge, and ONLY when the verdict adds something
   the badge does not already say — a blocked campaign used to look exactly like a sent one. Muted on purpose:
   it explains, it does not alarm. Client token spelling (--fg2/--line2); --fg-2 is the ADMIN dashboard's and
   silently resolves to nothing here (see __tests__/client/css-vars.test.js). */
.ob-verdict { display:flex; align-items:center; gap:5px; margin-top:5px; font-size:11.5px; color:var(--fg2); line-height:1.35; }
.ob-verdict svg { flex:none; opacity:.75; }
.ob-verdict .link { font-size:11.5px; }

/* The WhatsApp conversation thread (.wa-thread / .wa-bub / .wa-cards / …) used to live here, and an identical
   copy lived in the other console's stylesheet. It is now shared/public/wa-thread.css, linked from index.html
   after this file — see that file's header for why, and for the chained-token trick that lets one stylesheet read
   correctly in this console and the other. The layout it sits inside stays below, because that IS per-console. */

/* ── Conversations: list left, one chat right ───────────────────────────────── */
/* The transcript used to render BELOW the list, so reaching a chat meant scrolling past every customer the bot
   had ever spoken to. Each column scrolls on its own. Tokens only — this file ships a light default and a dark
   override, and both have to read. */
/* minmax(0,1fr), not 1fr: a bare `1fr` track is floored at its content's min-content width, so the carousel strip
   inside a bubble (150px per card, ten of them) widened the column instead of scrolling inside itself — and the
   whole page then scrolled sideways. minmax(0,…) lets the track shrink and hands the overflow back to the strip. */
.conv-split { display:grid; grid-template-columns:minmax(240px,340px) minmax(0,1fr); gap:14px; align-items:start; }
.conv-list { max-height:calc(100vh - 210px); overflow:auto; }
.conv-pane { position:sticky; top:0; }
.conv-card { display:flex; flex-direction:column; max-height:calc(100vh - 210px); }
.conv-body { overflow:auto; flex:1; margin-top:12px; }
.conv-head { display:flex; align-items:center; justify-content:space-between; gap:10px; }
tr[data-p].sel > td { background:var(--acc-soft); }

/* Segmented control, not two loose buttons — it is one choice with two states. */
.conv-switch { display:inline-flex; background:var(--panel2); border:1px solid var(--line2); border-radius:8px; padding:2px; }
.cv-tab { border:0; background:none; color:var(--mut); font:inherit; font-size:12px; padding:5px 12px; border-radius:6px; cursor:pointer; }
.cv-tab.on { background:var(--panel); color:var(--fg); }
.cv-tab:hover:not(.on) { color:var(--fg2); }

/* One column on a phone: two narrow columns are worse than a stack. */
@media (max-width:900px) {
  .conv-split { grid-template-columns:1fr; }
  .conv-list, .conv-card { max-height:none; }
  .conv-pane { position:static; }
}
