/* ═══════════════════════════════════════════════════════════════════════════
   BOARDROOM CABINET — DESIGN SYSTEM
   ═══════════════════════════════════════════════════════════════════════════

   One source of truth for the shell and Executive Overview, carrying the same
   visual language as the public landing page so that signing in does not feel
   like arriving at a different product.

   WHY A SEPARATE FILE. styles.css declares `.sidebar` in 13 blocks, `.topbar`
   in 11 and `.workspace` in 7; its outcome depends on source order, so editing
   any one of them is guesswork. This file is loaded last, which gives it the
   final word at equal specificity without rewriting 13,700 lines underneath.
   Every component it touches is defined here once and completely.

   TOKENS ARE COPIED BY VALUE FROM landing.html, not re-invented. The cabinet is
   a working operating system, so the ratio is deliberate: roughly 80% legible
   management interface, 20% Boardroom's digital environment. No hero video, no
   permanent motion, nothing that makes a number harder to read.
   ═══════════════════════════════════════════════════════════════════════════ */

:root {
  /* ── surfaces ─────────────────────────────────────────────────────────── */
  --bd-bg: #05070c;
  --bd-bg-2: #080b13;
  --bd-panel: #0b1018;
  --bd-panel-2: #0e141f;
  --bd-raised: rgb(var(--ch-lift) / 0.022);

  /* ── lines ────────────────────────────────────────────────────────────── */
  --bd-line: rgb(var(--ch-line) / 0.14);
  --bd-line-2: rgb(var(--ch-line) / 0.28);
  --bd-edge: rgb(var(--ch-accent) / 0.45);

  /* ── text ─────────────────────────────────────────────────────────────── */
  --bd-ink: var(--lw-ink);
  --bd-ink-2: #a7b4cc;
  --bd-ink-3: var(--lw-ink-dim);

  /* ── signal accents. Each one means something; none is decoration. ────── */
  --bd-brand: var(--pk-blue);      /* active, connected, intelligence */
  --bd-cyan: #37d2ff;       /* signal in motion */
  --bd-ok: #38d39f;         /* healthy, recovered, completed */
  --bd-warn: #e8b155;       /* attention, pending */
  --bd-risk: var(--lg-red-2);       /* risk, lost revenue, urgent */
  --bd-off: var(--lw-ink-dim);        /* disabled, unavailable, historical */

  /* ── geometry ─────────────────────────────────────────────────────────── */
  --bd-r: 14px;
  --bd-r-lg: 20px;
  --bd-r-pill: 999px;

  /* ── rhythm. One scale, so spacing stops drifting between screens. ────── */
  --bd-1: 6px;  --bd-2: 10px; --bd-3: 14px;
  --bd-4: 20px; --bd-5: 28px; --bd-6: 40px;

  /* ── motion ───────────────────────────────────────────────────────────── */
  --bd-fast: 0.16s;
  --bd-slow: 0.34s;
  --bd-ease: cubic-bezier(0.2, 0.8, 0.2, 1);
}

/* ═══ APP SHELL ═══════════════════════════════════════════════════════════ */

body {
  background: var(--bd-bg);
  color: var(--bd-ink);
}

/* The landing's coordinate grid, at the strength where it gives the page a
   floor without ever competing with a figure sitting on it. Fixed, masked away
   from the centre, and behind everything.
   CONFIRMED NOT THE "засвет" BUG, 2026-08-24: briefly deleted on suspicion of
   being it (test-body-left-glow-removed.mjs's own section 4 already pinned
   this exact rule as "the unrelated coordinate-grid backdrop" and asserted it
   survives) — restored once that test caught the mistake. Its mask keeps a
   ring VISIBLE from 6% out to 88% of an ellipse at 62%/34% at only 4.5% line
   opacity: real texture, not a colour wash, and not the smooth gradient a
   screenshot would show as a glow. The actual second copy of that bug turned
   out to be in styles.css: a whole leftover "Codex visual redesign pass"
   block, 4900 lines past the header's own already-fixed body{} rule, still
   carrying its own diagonal body{} and off-axis .app-shell{} gradients that
   nobody thought to check when the first fix shipped. See that file's own
   comment at the same spot. */
/* ═══════════════════════════════════════════════════════════════════════════
   THE «ЗАСВЕТ». FOUND 2026-08-28, AFTER A MONTH OF LOOKING PAST IT.
   ═══════════════════════════════════════════════════════════════════════════

   A decorative grid used to live here: two 1px line gradients in
   rgb(var(--ch-accent) / 0.045), tiled every 72px, on a position:fixed inset:0
   pseudo-element, masked into a vignette. --ch-accent on dark is 120 190 255 —
   a pale blue. So the product painted a faint luminous blue field over the
   ENTIRE viewport, on every page, permanently.

   On a busy screen nobody notices it. On a page that is mostly empty dark space
   — Маркетинг before an ad account is connected, ИИ-бухгалтерия — it is the
   whole background, and it reads exactly as the owner described it for a month:
   a wash that is «темнее, но всё равно есть».

   WHY THE DIAGNOSTIC NEVER FOUND IT, twice. src/dev/glareProbe.js samples with
   document.elementsFromPoint, and elementsFromPoint SKIPS anything with
   pointer-events: none. Every decorative overlay carries pointer-events: none
   by definition — it must not eat clicks. So the probe was structurally blind
   to the one category of element that causes this, and answered «one layer, the
   body's own gradient» both times, truthfully and uselessly. That blind spot is
   fixed in the same commit as this line.

   Removing it rather than dimming it: it is decoration nobody asked for,
   standing between a client and their own numbers. If it is missed, one
   revert brings it back — and scripts/test-no-viewport-wash.mjs will then fail
   and say why it was taken away.
   ═══════════════════════════════════════════════════════════════════════════ */
.sidebar, .workspace { position: relative; z-index: 1; }

/* ── Sidebar ─────────────────────────────────────────────────────────────
   Was a mid-blue slab with every destination in its own filled box, so twelve
   equally loud buttons competed and the current one was hard to find. Now the
   rail is quiet and only the active row carries light. */
.sidebar {
  background: linear-gradient(180deg, rgba(9, 13, 22, 0.96), rgba(5, 8, 14, 0.98));
  border-inline-end: 1px solid var(--bd-line);
  box-shadow: none;
  padding: var(--bd-4) var(--bd-3);
  gap: var(--bd-4);
}

.brand {
  display: flex;
  align-items: center;
  gap: var(--bd-2);
  padding: var(--bd-2);
  border: 1px solid transparent;
  border-radius: var(--bd-r);
  background: transparent;
  transition: border-color var(--bd-fast), background var(--bd-fast);
}
.brand:hover { border-color: var(--bd-line); background: var(--bd-raised); }
.brand-mark {
  width: 30px; height: 30px; border-radius: 9px;
  display: grid; place-items: center;
  font-weight: 700; font-size: 13px; color: var(--rp-on-accent);
  /* The same mark the landing header carries. */
  background: radial-gradient(circle at 30% 25%, var(--bd-cyan), var(--bd-brand) 55%, #12306b);
  box-shadow: 0 0 18px rgb(var(--ch-cyan2) / 0.3);
}
.brand-copy strong { font-size: 14.5px; font-weight: 650; letter-spacing: -0.01em; color: var(--bd-ink); }
.brand-copy span { font-size: 11px; color: var(--bd-ink-3); letter-spacing: 0.02em; }

.nav-section-label {
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--bd-ink-3);
  margin: 0 0 var(--bd-1);
  padding-inline-start: var(--bd-2);
}

.nav-item {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--bd-2);
  width: 100%;
  min-height: 40px;
  padding-block: 0 0; padding-inline: var(--bd-3) var(--bd-2);
  border: 1px solid transparent;
  border-radius: var(--bd-r);
  background: transparent;
  color: var(--bd-ink-2);
  font-size: 13.5px;
  font-weight: 500;
  text-align: start;
  cursor: pointer;
  transition: color var(--bd-fast), background var(--bd-fast), border-color var(--bd-fast);
}
.nav-item:hover { color: var(--bd-ink); background: var(--bd-raised); }
.nav-item.active {
  color: var(--bd-ink);
  font-weight: 600;
  background: linear-gradient(90deg, rgb(var(--ch-blue) / 0.16), rgb(var(--ch-blue) / 0.04));
  border-color: rgb(var(--ch-cyan2) / 0.26);
}
/* A cyan marker on the active row — the signal language of the landing, used
   here to answer one question: where am I. */
.nav-item.active::before {
  content: "";
  position: absolute;
  inset-inline-start: 0; top: 50%;
  width: 3px; height: 20px;
  transform: translateY(-50%);
  border-radius: 0 3px 3px 0;
  background: linear-gradient(180deg, var(--bd-cyan), var(--bd-brand));
  box-shadow: 0 0 12px rgb(var(--ch-cyan2) / 0.55);
}
.nav-icon {
  width: 26px; height: 22px; flex: none;
  display: grid; place-items: center;
  border-radius: 7px;
  background: rgb(var(--ch-line) / 0.07);
  color: var(--bd-ink-3);
  font-size: 9.5px; font-weight: 700; letter-spacing: 0.04em;
}
.nav-item.active .nav-icon { background: rgb(var(--ch-cyan2) / 0.16); color: var(--bd-cyan); }

/* ── Workspace and topbar ───────────────────────────────────────────────── */
.workspace { padding: var(--bd-5) var(--bd-5) 112px; }

.workspace-header, .topbar {
  border: 1px solid var(--bd-line);
  border-radius: var(--bd-r-lg);
  background: linear-gradient(180deg, var(--bd-header-a), rgb(var(--ch-ink9) / 0.72));
  backdrop-filter: blur(10px);
}
.topbar-copy h1, .workspace-header h1 {
  font-size: clamp(21px, 2vw, 27px);
  font-weight: 640;
  letter-spacing: -0.022em;
  color: var(--bd-ink);
}

/* ═══ COMPONENTS ══════════════════════════════════════════════════════════ */

/* ── Card ────────────────────────────────────────────────────────────────
   One surface for the whole cabinet: a dark glass panel, a hairline border,
   and light that arrives only under the cursor. */
.xo-card, .control-card {
  border: 1px solid var(--bd-line);
  border-radius: var(--bd-r-lg);
  background: linear-gradient(180deg, rgb(var(--ch-panel9) / 0.66), rgb(var(--ch-ink9) / 0.66));
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.32);
  transition: border-color var(--bd-slow), transform var(--bd-slow), box-shadow var(--bd-slow);
}
.xo-card:hover, .control-card:hover {
  border-color: var(--bd-line-2);
  transform: translateY(-1px);
  box-shadow: 0 24px 56px rgba(0, 0, 0, 0.42);
}

/* ── KPI card ────────────────────────────────────────────────────────────
   The four figures a manager reads first. Tabular numerals so digits line up
   between cards, a quiet label above, and the data state stated on the card
   itself rather than assumed. */
.xo-kpi {
  position: relative;
  overflow: hidden;
  padding: var(--bd-4);
  border: 1px solid var(--bd-line);
  border-radius: var(--bd-r-lg);
  background: linear-gradient(180deg, rgb(var(--ch-panel9) / 0.72), rgb(var(--ch-ink9) / 0.72));
  transition: border-color var(--bd-slow), transform var(--bd-slow), box-shadow var(--bd-slow);
}
.xo-kpi:hover {
  border-color: var(--bd-edge);
  transform: translateY(-2px);
  box-shadow: 0 22px 50px rgba(0, 0, 0, 0.42);
}
/* A hairline of signal along the top edge — the card's own state, read at a
   glance without stopping to read the badge. */
.xo-kpi::after {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 2px;
  background: linear-gradient(90deg, var(--bd-brand), var(--bd-cyan) 60%, transparent);
  opacity: 0.5;
  transition: opacity var(--bd-slow);
}
.xo-kpi:hover::after { opacity: 1; }
.xo-kpi.accent::after { background: linear-gradient(90deg, var(--bd-cyan), var(--bd-brand) 70%, transparent); }

.xo-kpi-top {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--bd-2); margin-bottom: var(--bd-2);
  font-size: 10.5px; letter-spacing: 0.15em; text-transform: uppercase;
  color: var(--bd-ink-3); font-weight: 600;
}
.xo-val {
  font-size: clamp(26px, 2.4vw, 34px);
  font-weight: 660;
  letter-spacing: -0.03em;
  line-height: 1.05;
  color: var(--bd-ink);
  font-variant-numeric: tabular-nums;
}
.xo-sub { margin-top: var(--bd-1); font-size: 12.5px; color: var(--bd-ink-3); }

/* ── Data-state badge ────────────────────────────────────────────────────
   Live, Demo, Not connected, Needs setup — four states, four colours, always
   the same four. A card never has to be guessed at. */
.xo-chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 9px;
  border-radius: var(--bd-r-pill);
  border: 1px solid transparent;
  font-size: 10.5px; font-weight: 650; letter-spacing: 0.04em;
  white-space: nowrap;
}
.xo-chip::before { content: ""; width: 5px; height: 5px; border-radius: 50%; background: currentColor; }
.xo-chip.live { color: var(--bd-ok);   background: rgb(var(--ch-ok4) / 0.11); border-color: rgb(var(--ch-ok4) / 0.28); }
.xo-chip.warn { color: var(--bd-warn); background: rgb(var(--ch-warm4) / 0.11);  border-color: rgb(var(--ch-warm4) / 0.3); }
.xo-chip.risk { color: var(--bd-risk); background: rgb(var(--ch-red2) / 0.11); border-color: rgb(var(--ch-red2) / 0.3); }
.xo-chip.off  { color: var(--bd-off);  background: rgba(111, 125, 151, 0.1);  border-color: rgba(111, 125, 151, 0.26); }

/* ── Buttons ─────────────────────────────────────────────────────────────
   Three roles and nothing else: one primary per screen, ghost for everything
   else, quiet for tertiary. Every state declared, so nothing can fall back to
   the browser's own near-white control. */
.primary-button {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 38px; padding: 0 var(--bd-4);
  border: 1px solid transparent; border-radius: 11px;
  background: linear-gradient(135deg, var(--bd-brand), #1a5fe0);
  color: var(--rp-on-accent); font-size: 13.5px; font-weight: 600; cursor: pointer;
  box-shadow: 0 8px 24px rgb(var(--ch-blue) / 0.28);
  transition: transform var(--bd-fast), box-shadow var(--bd-fast), opacity var(--bd-fast);
}
.primary-button:hover { transform: translateY(-1px); box-shadow: 0 12px 32px rgb(var(--ch-blue) / 0.4); }
.primary-button:active { transform: translateY(0); }
.primary-button[disabled] { opacity: 0.5; cursor: default; transform: none; box-shadow: none; }

.ghost-button, .secondary-button, .compact-button {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 38px; padding: 0 var(--bd-3);
  border: 1px solid var(--bd-line); border-radius: 11px;
  background: rgb(var(--ch-lift) / 0.025);
  color: var(--bd-ink); font-size: 13.5px; font-weight: 550; cursor: pointer;
  transition: color var(--bd-fast), border-color var(--bd-fast), background var(--bd-fast);
}
.ghost-button:hover, .secondary-button:hover, .compact-button:hover {
  border-color: var(--bd-edge);
  background: rgb(var(--ch-accent) / 0.08);
}

/* ── Tabs ───────────────────────────────────────────────────────────────── */
.module-tabs {
  display: flex; flex-wrap: wrap; gap: var(--bd-1);
  padding: var(--bd-1);
  border: 1px solid var(--bd-line);
  border-radius: var(--bd-r-pill);
  background: rgb(var(--ch-ink9) / 0.6);
}
.module-tabs button {
  min-height: 32px; padding: 0 var(--bd-3);
  border: 0; border-radius: var(--bd-r-pill);
  background: transparent; color: var(--bd-ink-2);
  font-size: 13px; font-weight: 550; cursor: pointer;
  transition: color var(--bd-fast), background var(--bd-fast);
}
.module-tabs button:hover { color: var(--bd-ink); background: rgb(var(--ch-lift) / 0.04); }
.module-tabs button.active, .module-tabs button[aria-selected="true"] {
  color: var(--bd-ink);
  background: linear-gradient(rgb(var(--ch-cyan2) / 0.16), rgb(var(--ch-cyan2) / 0.05));
  box-shadow: inset 0 0 0 1px rgb(var(--ch-cyan2) / 0.4);
}

/* ── Inputs ─────────────────────────────────────────────────────────────── */
.workspace input[type="text"], .workspace input[type="email"], .workspace input[type="tel"],
.workspace input[type="search"], .workspace input[type="number"],
.workspace select, .workspace textarea {
  background: var(--rp-inset);
  border: 1px solid var(--bd-line);
  border-radius: 11px;
  color: var(--bd-ink);
  padding: 10px 13px;
  transition: border-color var(--bd-fast), box-shadow var(--bd-fast);
}
.workspace input:focus, .workspace select:focus, .workspace textarea:focus {
  outline: none;
  border-color: var(--bd-edge);
  box-shadow: 0 0 0 3px rgb(var(--ch-accent) / 0.13);
}

/* ── Focus ──────────────────────────────────────────────────────────────── */
.sidebar :focus-visible, .workspace :focus-visible {
  outline: 2px solid rgb(var(--ch-accent) / 0.85);
  outline-offset: 2px;
  border-radius: 8px;
}

/* ═══ SOURCES → INTELLIGENCE → PIPELINE → REVENUE ═════════════════════════
   The one piece of Boardroom's own visual language that earns its place on a
   management screen: it is a status display, not an ornament. Each node is a
   real state, and the pulse crosses once when the screen opens. */
.bd-flow {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--bd-3);
  position: relative;
  margin: var(--bd-4) 0 0;
  padding: var(--bd-4);
  border: 1px solid var(--bd-line);
  border-radius: var(--bd-r-lg);
  background: linear-gradient(180deg, var(--bd-flow-a), var(--bd-flow-b));
  overflow: hidden;
}
.bd-flow::before {
  content: "";
  position: absolute;
  inset-inline-start: 0; inset-inline-end: 0; top: 50%;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--bd-line-2) 12%, var(--bd-line-2) 88%, transparent);
}
.bd-flow::after {
  content: "";
  position: absolute;
  top: 50%; inset-inline-start: -18%;
  width: 18%; height: 1px;
  background: linear-gradient(90deg, transparent, var(--bd-cyan), transparent);
  animation: bd-pulse 2.4s var(--bd-ease) 0.5s 1 forwards;
}
@keyframes bd-pulse { to { inset-inline-start: 100%; } }

.bd-node {
  position: relative;
  z-index: 1;
  padding: var(--bd-3);
  border: 1px solid var(--bd-line);
  border-radius: var(--bd-r);
  background: rgb(var(--ch-ink9) / 0.86);
  transition: border-color var(--bd-slow), transform var(--bd-slow);
}
.bd-node:hover { border-color: var(--bd-edge); transform: translateY(-2px); }
.bd-node b {
  display: block;
  font-size: 10.5px; letter-spacing: 0.15em; text-transform: uppercase;
  color: var(--bd-ink-3); font-weight: 650;
}
.bd-node span {
  display: block; margin-top: 5px;
  font-size: 15px; font-weight: 600; color: var(--bd-ink);
  font-variant-numeric: tabular-nums;
}
.bd-node i {
  display: block; margin-top: 3px;
  font-style: normal; font-size: 11.5px; color: var(--bd-ink-3);
}

/* ═══ STATES ══════════════════════════════════════════════════════════════ */
.bd-skeleton {
  border-radius: var(--bd-r);
  background: linear-gradient(90deg, rgb(var(--ch-line) / 0.05), rgb(var(--ch-line) / 0.11), rgb(var(--ch-line) / 0.05));
  background-size: 200% 100%;
  animation: bd-shimmer 1.5s linear infinite;
}
@keyframes bd-shimmer { to { background-position: -200% 0; } }

.bd-empty {
  padding: var(--bd-5);
  border: 1px dashed var(--bd-line-2);
  border-radius: var(--bd-r-lg);
  background: rgb(var(--ch-ink9) / 0.4);
  color: var(--bd-ink-2);
  text-align: center;
}

/* Nothing here may animate for a reader who asked for stillness. */
@media (prefers-reduced-motion: reduce) {
  .bd-flow::after, .bd-skeleton { animation: none; }
  .xo-kpi, .xo-card, .bd-node, .control-card { transition: none; }
  .bd-flow::after { display: none; }
}

/* ═══ THE CHAT CABINET ════════════════════════════════════════════════════
   Two panes and nothing else: who is waiting on the left, what was said on
   the right. The old screen spent its width on five tabs of metadata about
   conversations and never showed a single message, so the operator had to
   leave the product to do the one job this page exists for.

   Both panes scroll independently and the page itself does not: an inbox that
   makes you scroll the window to reach the newest message is an inbox you
   stop opening. Heights are computed from the viewport so the composer stays
   parked at the bottom of the screen the way every messenger does it. */

.chatpane {
  display: flex;
  flex-direction: column;
  gap: var(--bd-3);
  min-height: 0;
}

.chatpane-topline {
  display: flex;
  align-items: center;
  gap: var(--bd-3);
  flex-wrap: wrap;
}

.chatpane-topline .section-title { flex: 1 1 auto; }

.chatpane-source {
  font-size: 12px;
  color: var(--bd-ink-3);
}

.chatpane-body {
  display: grid;
  grid-template-columns: minmax(300px, 380px) minmax(0, 1fr);
  gap: var(--bd-3);
  align-items: stretch;
  height: calc(100vh - 210px);
  min-height: 520px;
}

/* ── left: the list ─────────────────────────────────────────────────────── */

.chatpane-list,
.chatpane-thread {
  display: flex;
  flex-direction: column;
  min-height: 0;
  background: var(--bd-panel);
  border: 1px solid var(--bd-line);
  border-radius: var(--bd-r-lg);
  overflow: hidden;
}

.chatpane-listhead {
  padding: var(--bd-3);
  border-bottom: 1px solid var(--bd-line);
  display: flex;
  flex-direction: column;
  gap: var(--bd-2);
  background: var(--bd-panel-2);
}

.chatpane-search { position: relative; }

/* Was the Unicode glyph "⌕" in the JSX — same fragile-glyph fix as
   .dw-search-ico (src/dialogue-workspace.css): drawn as a circle + handle
   instead of relying on font coverage for an uncommon character. */
.chatpane-searchicon {
  position: absolute;
  inset-inline-start: 12px;
  top: 50%;
  transform: translateY(-50%);
  width: 11px;
  height: 11px;
  border-radius: 50%;
  border: 1.5px solid var(--bd-ink-3);
  pointer-events: none;
}
.chatpane-searchicon::after {
  content: "";
  position: absolute;
  inset-inline-end: -4px;
  bottom: -3px;
  width: 5px;
  height: 1.5px;
  background: var(--bd-ink-3);
  transform: rotate(45deg);
}

.chatpane-search input {
  width: 100%;
  padding-block: 11px 11px; padding-inline: 32px 12px;
  border-radius: var(--bd-r-pill);
  border: 1px solid var(--bd-line);
  background: rgb(var(--ch-lift) / 0.03);
  color: var(--bd-ink);
  font-size: 14px;
}

.chatpane-search input::placeholder { color: var(--bd-ink-3); }

.chatpane-search input:focus {
  outline: none;
  border-color: var(--bd-edge);
  box-shadow: 0 0 0 3px rgb(var(--ch-blue) / 0.16);
}

.chatpane-tabs {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}

.chatpane-tab {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 11px;
  border-radius: var(--bd-r-pill);
  border: 1px solid var(--bd-line);
  background: transparent;
  color: var(--bd-ink-2);
  font-size: 12.5px;
  cursor: pointer;
  transition: background var(--bd-fast) var(--bd-ease), color var(--bd-fast) var(--bd-ease);
}

.chatpane-tab:hover { color: var(--bd-ink); border-color: var(--bd-line-2); }

.chatpane-tab.on {
  background: rgb(var(--ch-blue) / 0.16);
  border-color: var(--bd-edge);
  color: var(--bd-ink);
}

.chatpane-tabcount {
  font-variant-numeric: tabular-nums;
  color: var(--bd-ink-3);
  font-size: 11.5px;
}

.chatpane-tab.on .chatpane-tabcount { color: var(--bd-cyan); }

.chatpane-listmeta {
  margin: 0;
  font-size: 12px;
  color: var(--bd-ink-3);
  display: flex;
  align-items: center;
  gap: 8px;
}

.chatpane-count { color: var(--bd-ink); font-weight: 600; font-variant-numeric: tabular-nums; }

.chatpane-live {
  margin-inline-start: auto;
  color: var(--bd-ok);
  display: inline-flex;
  align-items: center;
  gap: 5px;
}

.chatpane-live::before {
  content: "";
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--bd-ok);
}

.chatpane-listscroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 6px;
}

.chatrow {
  width: 100%;
  display: flex;
  gap: 11px;
  align-items: flex-start;
  padding: 11px;
  border: 1px solid transparent;
  border-radius: var(--bd-r);
  background: transparent;
  color: inherit;
  text-align: start;
  cursor: pointer;
  transition: background var(--bd-fast) var(--bd-ease), border-color var(--bd-fast) var(--bd-ease);
}

.chatrow:hover { background: rgb(var(--ch-lift) / 0.035); }

.chatrow.active {
  background: rgb(var(--ch-blue) / 0.12);
  border-color: var(--bd-edge);
}

.chatrow-avatar {
  position: relative;
  flex: 0 0 38px;
  width: 38px; height: 38px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: linear-gradient(140deg, rgb(var(--ch-blue) / 0.32), rgb(var(--ch-cyan2) / 0.18));
  border: 1px solid var(--bd-line-2);
  font-size: 13px;
  font-weight: 600;
  color: var(--bd-ink);
  font-variant-numeric: tabular-nums;
}

.chatrow-dot {
  position: absolute;
  inset-inline-end: -1px; bottom: -1px;
  width: 11px; height: 11px;
  border-radius: 50%;
  border: 2px solid var(--bd-panel);
}

.chatrow-dot.waiting { background: var(--bd-warn); }
.chatrow-dot.draft { background: var(--bd-risk); }
.chatrow-dot.answered { background: var(--bd-ok); }
.chatrow-dot.paused { background: var(--bd-off); }

.chatrow-body {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.chatrow-top {
  display: flex;
  align-items: baseline;
  gap: 8px;
}

.chatrow-top strong {
  flex: 1 1 auto;
  min-width: 0;
  font-size: 14px;
  font-weight: 600;
  color: var(--bd-ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.chatrow-time {
  flex: 0 0 auto;
  font-size: 11.5px;
  color: var(--bd-ink-3);
  font-variant-numeric: tabular-nums;
}

.chatrow-snippet {
  font-size: 12.5px;
  color: var(--bd-ink-2);
  line-height: 1.45;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.chatrow-tags {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  font-size: 11px;
}

.chatrow-channel {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  color: var(--bd-ink-3);
  text-transform: capitalize;
}

.chatrow-state {
  padding: 2px 8px;
  border-radius: var(--bd-r-pill);
  border: 1px solid transparent;
}

.chatrow-state.waiting { color: var(--bd-warn); border-color: rgb(var(--ch-warm4) / 0.35); }
.chatrow-state.draft { color: var(--bd-risk); border-color: rgb(var(--ch-red2) / 0.35); }
.chatrow-state.answered { color: var(--bd-ok); border-color: rgb(var(--ch-ok4) / 0.3); }

.chatrow-lead {
  color: var(--bd-ink-3);
  font-variant-numeric: tabular-nums;
}

.chatpane-noresults,
.chatpane-placeholder {
  padding: var(--bd-5) var(--bd-4);
  text-align: center;
  color: var(--bd-ink-3);
  font-size: 13px;
}

.chatpane-placeholder strong { display: block; color: var(--bd-ink-2); margin-bottom: 6px; }

/* ── right: the thread ──────────────────────────────────────────────────── */

.chatpane-head {
  display: flex;
  align-items: center;
  gap: var(--bd-3);
  padding: var(--bd-3) var(--bd-4);
  border-bottom: 1px solid var(--bd-line);
  background: var(--bd-panel-2);
  flex-wrap: wrap;
}

.chatpane-headavatar {
  flex: 0 0 44px;
  width: 44px; height: 44px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: linear-gradient(140deg, rgb(var(--ch-blue) / 0.34), rgb(var(--ch-cyan2) / 0.2));
  border: 1px solid var(--bd-line-2);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.chatpane-headcopy { flex: 1 1 260px; min-width: 0; }

.chatpane-headcopy h2 {
  margin: 0 0 3px;
  font-size: 18px;
  line-height: 1.25;
  color: var(--bd-ink);
}

.chatpane-headcopy p {
  margin: 0;
  display: flex;
  align-items: center;
  gap: 7px;
  flex-wrap: wrap;
  font-size: 12.5px;
  color: var(--bd-ink-3);
}

.chatpane-headside {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.chatpane-pill {
  padding: 5px 11px;
  border-radius: var(--bd-r-pill);
  border: 1px solid var(--bd-line);
  font-size: 12px;
  white-space: nowrap;
}

.chatpane-pill.waiting { color: var(--bd-warn); border-color: rgb(var(--ch-warm4) / 0.35); }
.chatpane-pill.draft { color: var(--bd-risk); border-color: rgb(var(--ch-red2) / 0.35); }
.chatpane-pill.answered { color: var(--bd-ok); border-color: rgb(var(--ch-ok4) / 0.3); }

.chatpane-scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: var(--bd-4);
}

.chat-stream {
  display: flex;
  flex-direction: column;
  gap: var(--bd-3);
  max-width: 940px;
  margin: 0 auto;
}

.chat-daymark {
  display: flex;
  align-items: center;
  gap: var(--bd-3);
  color: var(--bd-ink-3);
  font-size: 11.5px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.chat-daymark::before,
.chat-daymark::after {
  content: "";
  flex: 1 1 auto;
  height: 1px;
  background: var(--bd-line);
}

/* A message is a block, not a table row: the text gets the width it needs and
   the metadata stays out of the way above it. */
.chatmsg {
  max-width: 78%;
  padding: var(--bd-3) var(--bd-4);
  border-radius: var(--bd-r-lg);
  border: 1px solid var(--bd-line);
  background: rgb(var(--ch-lift) / 0.028);
}

.chatmsg.customer {
  align-self: flex-start;
  border-end-start-radius: 6px;
}

.chatmsg.agent {
  align-self: flex-end;
  background: rgb(var(--ch-blue) / 0.13);
  border-color: rgb(var(--ch-blue) / 0.3);
  border-end-end-radius: 6px;
}

.chatmsg.draft {
  background: rgb(var(--ch-red2) / 0.08);
  border-color: rgb(var(--ch-red2) / 0.34);
  border-style: dashed;
}

.chatmsg-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--bd-3);
  margin-bottom: 5px;
  font-size: 11.5px;
  color: var(--bd-ink-3);
}

.chatmsg-head strong { color: var(--bd-ink-2); font-weight: 600; }

.chatmsg-text {
  margin: 0;
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--bd-ink);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* ── ВЛОЖЕНИЕ В «ДИАЛОГАХ» ─────────────────────────────────────────────────
   Те же правила, что и в карточке сделки (lead-workspace.css): фото видно,
   голосовое слушается, и ни то ни другое не растягивает ленту. */
.chatmsg-att { display: block; margin-top: 8px; }
.chatmsg-att-image { line-height: 0; border-radius: 10px; overflow: hidden; }
.chatmsg-att-img {
  display: block; max-width: 100%; max-height: 320px; width: auto; height: auto;
  border-radius: 10px;
}
.chatmsg-att-image:hover .chatmsg-att-img { filter: brightness(1.06); }
.chatmsg-att-video { max-width: 100%; max-height: 320px; border-radius: 10px; }
.chatmsg-att-player { display: block; width: 100%; max-width: 320px; height: 34px; }
.chatmsg-att-file {
  display: inline-flex; align-items: center; gap: 8px; padding: 8px 12px;
  border-radius: 10px; text-decoration: none;
  background: rgba(148, 178, 255, .08); border: 1px solid rgba(148, 178, 255, .18);
  color: var(--bd-ink); font-size: 13.5px;
}
.chatmsg-att-file:hover { border-color: rgba(47, 123, 255, .40); }

.chatmsg-draftmark {
  display: inline-block;
  margin-top: 8px;
  font-size: 11.5px;
  color: var(--bd-risk);
}

.chatpane-composer {
  border-top: 1px solid var(--bd-line);
  padding: var(--bd-3) var(--bd-4);
  background: var(--bd-panel-2);
}

.chatpane-composerbox {
  display: flex;
  gap: var(--bd-2);
  align-items: flex-end;
}

.chatpane-composerbox textarea {
  flex: 1 1 auto;
  resize: none;
  padding: 11px var(--bd-3);
  border-radius: var(--bd-r);
  border: 1px solid var(--bd-line);
  background: rgb(var(--ch-lift) / 0.02);
  color: var(--bd-ink);
  font: inherit;
  font-size: 14px;
}

.chatpane-composerbox textarea:disabled,
.chatpane-composerbox button:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

.chatpane-composernote {
  margin: 8px 0 0;
  font-size: 11.5px;
  line-height: 1.5;
  color: var(--bd-ink-3);
  max-width: 760px;
}

/* Below a laptop the two panes stop fitting side by side; the list keeps its
   own scroll so it never pushes the thread off the screen. */
@media (max-width: 1100px) {
  .chatpane-body {
    grid-template-columns: minmax(0, 1fr);
    height: auto;
  }
  .chatpane-listscroll { max-height: 320px; }
  .chatpane-thread { min-height: 60vh; }
  .chatmsg { max-width: 92%; }
}

/* ═══ ROOM TO WORK ════════════════════════════════════════════════════════
   Screens where the operator FILLS something in were inheriting the same
   narrow measure as screens they only read. A prompt, a knowledge-base entry
   or an action step is written in paragraphs; typing one into a 320px box
   with three visible lines is how a five-minute edit becomes a chore.

   Reading measure stays capped — long prose lines are harder to read, and
   that has not changed. This widens inputs, not paragraphs. */

.workspace textarea {
  width: 100%;
  min-height: 132px;
  line-height: 1.6;
  padding: 12px 14px;
}

.workspace textarea.compact-textarea,
.workspace .chatpane-composerbox textarea {
  min-height: 0;
}

.workspace input[type="text"], .workspace input[type="email"],
.workspace input[type="tel"], .workspace input[type="search"],
.workspace input[type="url"], .workspace input[type="password"],
.workspace input[type="number"], .workspace select {
  width: 100%;
  padding: 11px 13px;
}

/* A form row that has room becomes two columns instead of a stack of narrow
   boxes; below a laptop it falls back to one. */
.form-grid, .field-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: var(--bd-3);
}

.control-card .detail-grid,
.detail-grid {
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}

/* The real mark replaces the letter B that stood in for it. The box that used
   to draw a lettered tile now just holds the artwork. */
.brand-mark.has-logo,
.auth-brand-mark.has-logo {
  background: none;
  border: 0;
  box-shadow: none;
  display: grid;
  place-items: center;
  padding: 0;
}

.brand-mark.has-logo img,
.auth-brand-mark.has-logo img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

/* ═══ THE RAIL ════════════════════════════════════════════════════════════
   It had its own scrollbar and its own scroll position, pinned to the
   viewport. Two scrollbars on one screen means two places a wheel gesture can
   land, and the owner's verdict was the right one: it should behave like part
   of the page.

   So it does. The rail is a tall column that scrolls WITH the document, and
   when the working screen needs the width it collapses to its icons. The
   choice is remembered, because it is a working preference, not a mood. */

.sidebar {
  position: static;
  height: auto;
  min-height: 100vh;
  overflow: visible;
}

.rail-toggle {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
  width: 100%;
  padding: 7px 10px;
  border: 1px solid var(--bd-line);
  border-radius: var(--bd-r-pill);
  background: transparent;
  color: var(--bd-ink-3);
  font-size: 12px;
  cursor: pointer;
  transition: color var(--bd-fast) var(--bd-ease), border-color var(--bd-fast) var(--bd-ease);
}

.rail-toggle:hover {
  color: var(--bd-ink);
  border-color: var(--bd-line-2);
}

.rail-toggle-icon { font-size: 14px; line-height: 1; }

/* ── collapsed ─────────────────────────────────────────────────────────── */

.app-shell.rail-collapsed {
  grid-template-columns: 78px minmax(0, 1fr);
}

.rail-collapsed .sidebar {
  padding-inline-start: 9px;
  padding-inline-end: 9px;
  align-items: center;
  gap: var(--bd-3);
}

.rail-collapsed .rail-toggle {
  justify-content: center;
  padding: 7px 0;
}

/* Everything that is words rather than a symbol steps aside. */
.rail-collapsed .rail-toggle-text,
.rail-collapsed .brand-copy,
.rail-collapsed .nav-section-label,
.rail-collapsed .nav-item > span:not([class*="nav-icon"]),
.rail-collapsed .sidebar-workspace-button > span:not([class*="nav-icon"]),
.rail-collapsed .sidebar-secondary-actions,
.rail-collapsed .sidebar-account-copy,
.rail-collapsed .sidebar-signout-button,
.rail-collapsed .sidebar-contact-row,
.rail-collapsed .sidebar-utility-row,
.rail-collapsed .support-label,
.rail-collapsed .help-center-button {
  display: none;
}

/* The icon is the whole control now, so it is centred rather than a label that
   lost its text. */
.rail-collapsed .brand,
.rail-collapsed .nav-item,
.rail-collapsed .sidebar-workspace-button,
.rail-collapsed .sidebar-account {
  justify-content: center;
  padding: 10px 0;
  gap: 0;
}

.rail-collapsed .brand-mark,
.rail-collapsed .brand-mark.has-logo {
  width: 36px;
  height: 36px;
}

.rail-collapsed .sidebar-account-avatar { margin: 0; }

@media (max-width: 900px) {
  /* The mobile drawer already owns this width — a collapse control here would
     be a second, conflicting way to do the same thing. */
  .rail-toggle { display: none; }
  .app-shell.rail-collapsed { grid-template-columns: minmax(0, 1fr); }
}

/* ── Take-over ────────────────────────────────────────────────────────────
   The switch an operator reaches for mid-conversation, and the rules behind
   it. Green means the agent is answering — the state a client should be able
   to read from across the room. */

.chatpane-agentswitch {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 13px;
  border-radius: var(--bd-r-pill);
  border: 1px solid var(--bd-line);
  background: rgb(var(--ch-lift) / 0.03);
  color: var(--bd-ink-2);
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  transition: border-color var(--bd-fast) var(--bd-ease), color var(--bd-fast) var(--bd-ease);
}

.chatpane-agentdot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: currentColor;
}

.chatpane-agentswitch.on { color: var(--t195); border-color: rgb(var(--ch-ok3) / 0.4); }
.chatpane-agentswitch.off { color: var(--bd-ink-3); }
.chatpane-agentswitch:hover { border-color: var(--bd-line-2); }

.chatpane-rules {
  margin-top: var(--bd-4);
  padding: var(--bd-3) var(--bd-4);
  border: 1px solid var(--bd-line);
  border-radius: var(--bd-r-lg);
  background: var(--bd-panel);
}

.chatpane-rules > summary {
  display: flex;
  align-items: baseline;
  gap: 12px;
  cursor: pointer;
  font-weight: 600;
  color: var(--bd-ink);
}

.chatpane-rulesnote { color: var(--bd-ink-3); font-size: 12px; font-weight: 400; }

.chatpane-rulesrow { margin-top: var(--bd-3); }

.chatpane-ruleslabel {
  display: block;
  margin-bottom: 7px;
  color: var(--bd-ink-2);
  font-size: 13px;
}

.chatpane-ruleschips { display: flex; flex-wrap: wrap; gap: 8px; }

.chatpane-chip {
  padding: 6px 13px;
  border-radius: var(--bd-r-pill);
  border: 1px solid var(--bd-line);
  background: transparent;
  color: var(--bd-ink-2);
  font-size: 12px;
  cursor: pointer;
}

.chatpane-chip.on {
  border-color: rgb(var(--ch-accent) / 0.55);
  background: rgb(var(--ch-blue) / 0.14);
  color: var(--bd-ink);
}

.chatpane-chip:disabled { opacity: 0.5; cursor: not-allowed; }

.chatpane-rules textarea {
  width: 100%;
  padding: 10px 12px;
  border-radius: var(--bd-r-md);
  border: 1px solid var(--bd-line);
  background: rgb(var(--ch-lift) / 0.03);
  color: var(--bd-ink);
  font: inherit;
  font-size: 13px;
  resize: vertical;
}

.chatpane-rulesactions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: var(--bd-3);
}
.chatpane-rulesactions .compact-button { white-space: nowrap; flex: 0 0 auto; }
.chatpane-template-setlang { flex: 0 0 auto; width: auto; min-width: 150px; }

/* Отчёт о подаче набора — своей строкой под кнопками, по абзацу на шаблон,
   с текстом шаблона в кавычках: владелец видит, ЧТО именно подано. */
.chatpane-template-report { margin-top: 10px; font-size: 13px; line-height: 1.55; color: var(--bd-ink-2); }
.chatpane-template-report:empty { display: none; }
.chatpane-template-report p { margin: 0 0 6px; white-space: pre-line; }

/* ── The account menu ─────────────────────────────────────────────────────
   Necessary rather than decorative: sign-out, the language switch and the
   workspace links live at the foot of the rail, and a collapsed rail hides
   them. A cabinet you cannot sign out of is not a nicety. */

.profile-menu { position: relative; }

.profile-trigger {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding-block: 4px 4px; padding-inline: 4px 8px;
  border: 1px solid var(--bd-line);
  border-radius: var(--bd-r-pill);
  background: transparent;
  color: var(--bd-ink-2);
  cursor: pointer;
}

.profile-trigger:hover, .profile-trigger.open { border-color: var(--bd-line-2); color: var(--bd-ink); }

.profile-avatar {
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--bd-brand), var(--bd-brand-2));
  color: var(--rp-on-accent);
  font-size: 13px;
  font-weight: 700;
}

.profile-avatar.large { width: 40px; height: 40px; font-size: 17px; }
.profile-caret { font-size: 10px; }

/* Covers the viewport so a click anywhere dismisses the panel — the behaviour
   everyone expects, and the one a popover with no document listener misses. */
.profile-scrim {
  position: fixed;
  inset: 0;
  z-index: 40;
  border: 0;
  padding: 0;
  background: transparent;
  cursor: default;
}

.profile-panel {
  position: absolute;
  top: calc(100% + 10px);
  inset-inline-end: 0;
  z-index: 41;
  width: 280px;
  padding: var(--bd-3);
  border: 1px solid var(--bd-line-2);
  border-radius: var(--bd-r-lg);
  background: var(--bd-panel);
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.5);
}

.profile-identity {
  display: flex;
  align-items: center;
  gap: 11px;
  padding-bottom: var(--bd-3);
  border-bottom: 1px solid var(--bd-line);
}

.profile-identity strong {
  display: block;
  max-width: 190px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--bd-ink);
  font-size: 13px;
}

.profile-identity span { color: var(--bd-ink-3); font-size: 12px; }

.profile-links { display: grid; padding: var(--bd-2) 0; }

.profile-links button {
  padding: 9px 8px;
  border: 0;
  border-radius: var(--bd-r-sm);
  background: transparent;
  color: var(--bd-ink-2);
  font: inherit;
  font-size: 13px;
  text-align: start;
  cursor: pointer;
}

.profile-links button:hover { background: rgb(var(--ch-lift) / 0.05); color: var(--bd-ink); }

.profile-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--bd-2) 8px;
  border-top: 1px solid var(--bd-line);
  color: var(--bd-ink-3);
  font-size: 12px;
}

.profile-actions {
  display: flex;
  gap: 8px;
  padding-top: var(--bd-2);
  border-top: 1px solid var(--bd-line);
}

.profile-actions button { flex: 1; }

/* A provider tile that carries a real mark drops the coloured background and
   the letters — the logo IS the identification, and a brand colour behind a
   brand logo reads as a mistake. */
.provider-avatar.has-logo {
  background: none;
  border: 0;
  box-shadow: none;
  padding: 0;
  color: transparent;
  font-size: 0;
}

.provider-avatar.has-logo img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  border-radius: 6px;
}

/* Partner earnings: three counted facts and one honest sentence, in place of
   three cards that offered "Request approval" and did nothing. */
.partner-earnings { margin-top: var(--bd-3); }

.partner-earn-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: var(--bd-3);
  margin: var(--bd-3) 0;
}

.partner-earn-stats > div {
  padding: var(--bd-3);
  border: 1px solid var(--bd-line);
  border-radius: var(--bd-r-md);
  background: rgb(var(--ch-lift) / 0.02);
}

.partner-earn-stats span {
  display: block;
  margin-bottom: 5px;
  color: var(--bd-ink-3);
  font-size: 12px;
}

.partner-earn-stats strong { color: var(--bd-ink); font-size: 22px; }

/* Reset the test conversation. A test chat carries its history into the model,
   so after a few probing questions the agent answers in a context the next
   test does not want. */
.agent-chat-reset {
  padding: 5px 11px;
  border: 1px solid var(--bd-line);
  border-radius: var(--bd-r-pill);
  background: transparent;
  color: var(--bd-ink-3);
  font-size: 12px;
  cursor: pointer;
}

.agent-chat-reset:hover { color: var(--bd-ink); border-color: var(--bd-line-2); }

/* ── The duty rota ────────────────────────────────────────────────────────
   One row per person: who they are, their id in the client's CRM, how to
   reach them, and the days and hours they are on. */

.managers-table { display: grid; gap: var(--bd-2); margin: var(--bd-3) 0; }

.managers-row {
  display: grid;
  gap: var(--bd-2);
  padding: var(--bd-3);
  border: 1px solid var(--bd-line);
  border-radius: var(--bd-r-md);
  background: rgb(var(--ch-lift) / 0.02);
}

.managers-row.off { opacity: 0.55; }

.managers-fields {
  display: grid;
  grid-template-columns: minmax(120px, 1.4fr) minmax(90px, 0.8fr) minmax(140px, 1.2fr);
  gap: var(--bd-2);
}

.managers-fields input,
.managers-hours input {
  padding: 8px 10px;
  border: 1px solid var(--bd-line);
  border-radius: var(--bd-r-sm);
  background: rgb(var(--ch-lift) / 0.03);
  color: var(--bd-ink);
  font: inherit;
  font-size: 13px;
  min-width: 0;
}

.managers-duty {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--bd-2);
}

.managers-days { display: flex; flex-wrap: wrap; gap: 4px; }

.managers-day {
  min-width: 38px;
  padding: 5px 0;
  border: 1px solid var(--bd-line);
  border-radius: var(--bd-r-sm);
  background: transparent;
  color: var(--bd-ink-3);
  font-size: 12px;
  cursor: pointer;
}

.managers-day[aria-pressed="true"] {
  border-color: rgb(var(--ch-accent) / 0.55);
  background: rgb(var(--ch-blue) / 0.16);
  color: var(--bd-ink);
}

.managers-hours { display: flex; align-items: center; gap: 6px; color: var(--bd-ink-3); }
.managers-hours input { width: 62px; text-align: center; }

.managers-remove {
  margin-inline-start: auto;
  width: 30px;
  height: 30px;
  border: 1px solid var(--bd-line);
  border-radius: 50%;
  background: transparent;
  color: var(--bd-ink-3);
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
}

.managers-remove:hover { color: var(--lg-red-2); border-color: rgb(var(--ch-red2) / 0.5); }

@media (max-width: 700px) {
  .managers-fields { grid-template-columns: minmax(0, 1fr); }
}

/* ── Exactly what the agent may touch ─────────────────────────────────────
   A capability toggle with no list beneath it grants everything or nothing,
   and the owner cannot tell which. These are the client's own stages and
   fields, read from their own CRM. */

.agent-scope {
  margin: var(--bd-3) 0;
  padding: var(--bd-3);
  border: 1px solid var(--bd-line);
  border-radius: var(--bd-r-md);
  background: rgb(var(--ch-lift) / 0.02);
}

.agent-scope-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--bd-3);
  flex-wrap: wrap;
  color: var(--bd-ink-2);
  font-size: 13px;
}

.agent-scope-group { margin-top: var(--bd-3); }

.agent-scope-label {
  margin: 0 0 7px;
  color: var(--bd-ink-3);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.agent-scope-chips { display: flex; flex-wrap: wrap; gap: 6px; }

.agent-scope-note {
  margin: 8px 0 0;
  color: var(--bd-ink-3);
  font-size: 12px;
}

/* ── Analyzer sources ─────────────────────────────────────────────────────
   Three ways to get a conversation onto the screen, because a client rarely
   has one as plain text to hand. */

.an-sources {
  display: flex;
  flex-wrap: wrap;
  gap: var(--bd-3);
  margin: var(--bd-3) 0;
}

.an-source {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 9px 13px;
  border: 1px solid var(--bd-line);
  border-radius: var(--bd-r-md);
  background: rgb(var(--ch-lift) / 0.02);
  color: var(--bd-ink-2);
  font-size: 13px;
}

/* The file input itself is hidden (.bc-file, main.js) — this chip's visible
   span is the whole trigger now, so it needs the pointer cursor the native
   input's own OS button used to carry. Scoped to :has(input[type="file"])
   so the sibling "live conversation" chip (a <select>, not a hidden input)
   is untouched. */
.an-source:has(input[type="file"]) { cursor: pointer; }
.an-source select { min-width: 210px; }
.an-row { margin-bottom: 6px; }

@media (max-width: 640px) {
  .an-sources { flex-direction: column; align-items: stretch; }
  .an-source { justify-content: space-between; }
}

/* ═══ THE CABINET'S OWN CRM ═══════════════════════════════════════════════
   Kommo is the reference: a board of stages you drag a deal across, and a
   card holding the money, the people, the notes, the tasks and the
   conversation. Not all of Kommo — everything a business doing fifteen deals
   a month actually opens. */

.kb {
  margin-bottom: var(--bd-5);
  /* WITHOUT THIS THE WHOLE PAGE SCROLLS SIDEWAYS.
     .page-stack is a grid, so this section is a grid ITEM, and a grid item's
     default min-width:auto refuses to shrink below its content's intrinsic
     width. Six 268px columns therefore pushed this section to 1678px inside a
     1222px track, which pushed the document to 1702px in a 1280px viewport.
     Measured, not guessed — the comment on .kb-cols below promised the board
     would scroll instead of the page, and it could not keep that promise until
     this line existed. */
  min-width: 0;
}

.kb-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--bd-3);
  flex-wrap: wrap;
  margin-bottom: var(--bd-3);
}

.kb-head h3 { margin: 2px 0 4px; font-size: 22px; color: var(--bd-ink); }

/* The board scrolls sideways as a board — the page does not. A kanban whose
   columns push the whole document wide is the classic way to break a layout. */
.kb-cols {
  display: flex;
  gap: var(--bd-3);
  overflow-x: auto;
  padding-bottom: var(--bd-2);
  scroll-snap-type: x proximity;
}

.kb-col {
  flex: 0 0 268px;
  display: flex;
  flex-direction: column;
  min-height: 220px;
  padding: var(--bd-3);
  border: 1px solid var(--bd-line);
  border-radius: var(--bd-r-lg);
  background: rgb(var(--ch-lift) / 0.02);
  scroll-snap-align: start;
}

/* Won and lost are not just two more columns — they are where the money
   lands or does not, and the eye should find them without reading. */
.kb-col.won { border-color: rgb(var(--ch-ok3) / 0.35); }
.kb-col.lost { border-color: rgb(var(--ch-red2) / 0.28); }

.kb-col-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.kb-col-name { color: var(--bd-ink); font-size: 13px; font-weight: 600; }

.kb-col-count {
  min-width: 22px;
  padding: 1px 7px;
  border-radius: var(--bd-r-pill);
  background: rgb(var(--ch-lift) / 0.06);
  color: var(--bd-ink-3);
  font-size: 11px;
  text-align: center;
}

.kb-col-sum { margin: 6px 0 0; color: var(--bd-ink-3); font-size: 12px; }

.kb-col-body { display: grid; gap: 8px; margin-top: var(--bd-3); }

.kb-col-empty {
  margin: 0;
  padding: var(--bd-4) 0;
  color: var(--bd-ink-3);
  font-size: 12px;
  text-align: center;
}

.kb-card {
  padding: 11px 12px;
  border: 1px solid var(--bd-line);
  border-radius: var(--bd-r-md);
  background: var(--bd-panel);
  cursor: grab;
  transition: border-color var(--bd-fast) var(--bd-ease), transform var(--bd-fast) var(--bd-ease);
}

.kb-card:hover { border-color: var(--bd-line-2); transform: translateY(-1px); }
.kb-card:active { cursor: grabbing; }

.kb-card-top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
}

.kb-card-top strong { color: var(--bd-ink); font-size: 13px; line-height: 1.35; }
.kb-card-value { color: var(--lg-cyan-2); font-size: 12px; font-weight: 600; white-space: nowrap; }
.kb-card-contact { margin: 5px 0 0; color: var(--bd-ink-2); font-size: 12px; }

.kb-card-meta {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  margin-top: 9px;
}

.kb-chip {
  padding: 2px 8px;
  border-radius: var(--bd-r-pill);
  background: rgb(var(--ch-lift) / 0.05);
  color: var(--bd-ink-3);
  font-size: 11px;
}

.kb-chip.task { color: var(--lg-warm-1); }
.kb-card-age { margin-inline-start: auto; color: var(--bd-ink-3); font-size: 11px; }
.kb-card-tags { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 8px; }

.kb-tag {
  padding: 1px 7px;
  border-radius: var(--bd-r-sm);
  border: 1px solid var(--bd-line);
  color: var(--bd-ink-3);
  font-size: 11px;
}

/* ── the card panel ───────────────────────────────────────────────────── */

.kb-scrim {
  position: fixed;
  inset: 0;
  z-index: 60;
  border: 0;
  background: rgba(3, 6, 12, 0.6);
  cursor: default;
}

.kb-panel {
  position: fixed;
  top: 0;
  inset-inline-end: 0;
  z-index: 61;
  display: flex;
  flex-direction: column;
  width: min(520px, 100vw);
  height: 100vh;
  border-inline-start: 1px solid var(--bd-line-2);
  background: var(--bd-panel);
  box-shadow: -30px 0 70px rgba(0, 0, 0, 0.5);
}

.kb-panel-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--bd-3);
  padding: var(--bd-4);
  border-bottom: 1px solid var(--bd-line);
}

.kb-panel-head h3 { margin: 0 0 4px; font-size: 18px; color: var(--bd-ink); }

.kb-close {
  border: 0;
  background: transparent;
  color: var(--bd-ink-3);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
}

.kb-panel-body { flex: 1; overflow-y: auto; padding: var(--bd-4); }

.kb-fields {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: var(--bd-3);
  margin-bottom: var(--bd-3);
}

.kb-field { display: grid; gap: 5px; }
.kb-field > span { color: var(--bd-ink-3); font-size: 12px; }

.kb-field input, .kb-field select, .kb-add input {
  padding: 9px 11px;
  border: 1px solid var(--bd-line);
  border-radius: var(--bd-r-sm);
  background: rgb(var(--ch-lift) / 0.03);
  color: var(--bd-ink);
  font: inherit;
  font-size: 13px;
  min-width: 0;
}

.kb-sub {
  margin: var(--bd-4) 0 var(--bd-2);
  color: var(--bd-ink-2);
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.kb-tasks { list-style: none; margin: 0; padding: 0; display: grid; gap: 7px; }

.kb-tasks li {
  display: flex;
  align-items: center;
  gap: 9px;
  color: var(--bd-ink-2);
  font-size: 13px;
}

.kb-tasks li.done { color: var(--bd-ink-3); text-decoration: line-through; }
.kb-tasks li small { margin-inline-start: auto; color: var(--bd-ink-3); font-size: 11px; }

.kb-task-check {
  width: 22px;
  height: 22px;
  border: 1px solid var(--bd-line);
  border-radius: 50%;
  background: transparent;
  color: inherit;
  cursor: pointer;
  flex: 0 0 auto;
}

.kb-add { display: flex; gap: 8px; margin-top: var(--bd-2); }
.kb-add input { flex: 1; }

.kb-notes { display: grid; gap: 8px; }

.kb-note {
  padding: 9px 11px;
  border-radius: var(--bd-r-sm);
  background: rgb(var(--ch-lift) / 0.03);
}

.kb-note p { margin: 0 0 4px; color: var(--bd-ink-2); font-size: 13px; }
.kb-note small { color: var(--bd-ink-3); font-size: 11px; }

.kb-chat { display: grid; gap: 7px; }

.kb-msg { max-width: 86%; padding: 8px 11px; border-radius: var(--bd-r-md); font-size: 13px; }
.kb-msg p { margin: 0; }
.kb-msg.customer { background: rgb(var(--ch-lift) / 0.05); color: var(--bd-ink); }
.kb-msg.agent { margin-inline-start: auto; background: rgb(var(--ch-blue) / 0.16); color: var(--bd-ink); }

.kb-msg-draft {
  display: block;
  margin-bottom: 3px;
  color: var(--lg-warm-1);
  font-size: 11px;
}

@media (max-width: 720px) {
  .kb-col { flex-basis: 82vw; }
  .kb-panel { width: 100vw; }
}

/* ── The client's card, and the workspace's own fields ────────────────────
   The person is the durable record; a deal is an episode in their history. */

.kb-clientlink {
  display: block;
  width: calc(100% - var(--bd-4) * 2);
  margin: var(--bd-3) var(--bd-4) 0;
  padding: 9px 12px;
  border: 1px solid var(--bd-line);
  border-radius: var(--bd-r-pill);
  background: rgb(var(--ch-lift) / 0.03);
  color: var(--bd-ink-2);
  font-size: 13px;
  cursor: pointer;
}

.kb-clientlink:hover { color: var(--bd-ink); border-color: var(--bd-line-2); }

.kb-deal {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--bd-line);
  border-radius: var(--bd-r-sm);
  background: rgb(var(--ch-lift) / 0.02);
  color: var(--bd-ink-2);
  font: inherit;
  font-size: 13px;
  text-align: start;
  cursor: pointer;
}

.kb-deal:hover { border-color: var(--bd-line-2); }
.kb-deal-title { color: var(--bd-ink); }

.kb-deal-stage {
  padding: 1px 8px;
  border-radius: var(--bd-r-pill);
  background: rgb(var(--ch-lift) / 0.06);
  font-size: 11px;
}

.kb-deal-stage.won { background: rgb(var(--ch-ok3) / 0.16); color: var(--t195); }
.kb-deal-stage.lost { background: rgb(var(--ch-red2) / 0.14); color: var(--lg-red-1); }
.kb-deal-value { margin-inline-start: auto; color: var(--lg-cyan-2); font-size: 12px; }
.kb-deal small { color: var(--bd-ink-3); font-size: 11px; }

.kb-fielddefs {
  padding: var(--bd-3);
  border: 1px solid var(--bd-line);
  border-radius: var(--bd-r-md);
  background: rgb(var(--ch-lift) / 0.02);
}

.kb-fielddefs > summary { color: var(--bd-ink-2); font-size: 13px; cursor: pointer; }

.kb-fielddef {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-top: 8px;
  color: var(--bd-ink-2);
  font-size: 13px;
}

.kb-fielddef small { color: var(--bd-ink-3); font-size: 11px; }

.kb-fielddef-x {
  margin-inline-start: auto;
  border: 0;
  background: transparent;
  color: var(--bd-ink-3);
  font-size: 16px;
  cursor: pointer;
}

.kb-fielddef-x:hover { color: var(--lg-red-2); }

/* A failed send must not look like a note. The operator has to know their
   message did not reach the customer. */
.chatpane-composernote.error { color: var(--lg-red-1); }

/* A failure, and the one action available on it. The card used to show a count
   and point at a diagnostics screen that does not exist. */
.aj-error {
  display: flex;
  align-items: flex-start;
  gap: var(--bd-3);
  margin-top: var(--bd-2);
  padding: 10px 12px;
  border: 1px solid rgb(var(--ch-red2) / 0.24);
  border-radius: var(--bd-r-md);
  background: rgb(var(--ch-red2) / 0.05);
}

/* THE HALF-EMPTY BOXES WITH TWO WORDS PER LINE.
 *
 * .aj-grid lays every card into a repeat(auto-fill, minmax(220px, 1fr)) track.
 * That is right for a card holding two numbers and wrong for the one holding
 * paragraphs: a provider's sentence — «Gmail API has not been used in project
 * 155567071468…» — wrapped to two words a line inside 220px and turned the card
 * into a tall, mostly empty rectangle. The owner has reported the text spilling
 * out of its box repeatedly, and this is where it does it.
 *
 * The card that carries prose takes the full row. Selected by what it CONTAINS
 * rather than by a new class, so any future card with error rows in it gets the
 * same treatment without anybody remembering to ask. */
.aj-card:has(.aj-error) { grid-column: 1 / -1; }

/* And inside it, the button stopped sitting on top of the code.
 *
 * `align-items: flex-start` put the two children on one line and nothing
 * stopped the button overlapping the heading when the column was narrow — which
 * is exactly what the screenshot shows: «Решено» printed across
 * VOICE_CARD_SKIPPED_NO_CALLER. The row wraps now, and the button keeps its
 * own width instead of being squeezed into the text. */
.aj-error { flex-wrap: wrap; }
.aj-error > div { flex: 1 1 260px; min-width: 0; }
.aj-error > button { flex: 0 0 auto; align-self: flex-start; }
.aj-error strong { display: block; color: var(--bd-ink); font-size: 13px; overflow-wrap: anywhere; }
.aj-error small { display: block; margin-top: 2px; color: var(--bd-ink-3); font-size: 11px; overflow-wrap: anywhere; }
/* `word-break: break-word` is deprecated and does not break a long URL the way
 * `anywhere` does — and a provider's message is where the long URLs are. */
.aj-error p { margin: 5px 0 0; color: var(--bd-ink-2); font-size: 12px; overflow-wrap: anywhere; }

/* ============================================================================
   ONE STATUS VOCABULARY
   ============================================================================
   Measured on 2026-08-09, not assumed: `.status-pill` is defined FIVE separate
   times in styles.css — lines 85, 467, 2687, 4190 and 5158 — and used in 70
   places. Which definition wins depends on source order, which is why the same
   badge looks like two different components on two screens. Around it grew
   twelve modifier vocabularies: good, live, warning, risk, pending, error,
   danger, neutral, muted, off, disabled, draft, demo, info, admin, local_only.
   Sixteen words for five meanings.

   This block is the single source of truth. It sits in the stylesheet that
   loads last precisely so it has the final word, and it maps every legacy
   modifier onto one of five semantic families instead of deleting them — a
   rename across 70 call sites would be a large diff whose only merit is
   tidiness, and this achieves the same visual result with none of the risk.

   GREEN   live, connected, ready
   YELLOW  attention, partial, needs validation
   RED     error, action required
   GRAY    not connected, disabled, unavailable
   BLUE    demo, test, draft — never mistakable for production
   ============================================================================ */

.status-pill,
.status-badge,
.ch-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 10px;
  border: 1px solid transparent;
  border-radius: var(--bd-r-pill);
  font-size: 11px;
  font-weight: 600;
  line-height: 1.5;
  letter-spacing: 0.01em;
  white-space: nowrap;
}

/* The dot carries the state at a glance; the word confirms it. Together they
   survive both colour-blindness and a screenshot pasted into a chat. */
.status-pill::before,
.status-badge::before,
.ch-badge::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  flex: 0 0 auto;
}

/* GREEN — it is working, and that has been verified. */
.status-pill.good, .status-pill.live, .status-pill.connected, .status-pill.ready,
.status-badge.good, .status-badge.live, .ch-badge.ch-ok, .status-good, .status-live {
  color: var(--t195);
  background: rgb(var(--ch-ok3) / 0.10);
  border-color: rgb(var(--ch-ok3) / 0.28);
}

/* YELLOW — it exists but is not finished, or it needs a human to look. */
.status-pill.warning, .status-pill.risk, .status-pill.pending, .status-pill.partial,
.status-badge.warning, .ch-badge.ch-warn, .status-warning, .status-risk, .status-pending {
  color: var(--t442);
  background: rgba(251, 191, 36, 0.10);
  border-color: rgba(251, 191, 36, 0.26);
}

/* RED — something is broken and somebody has to act. */
.status-pill.error, .status-pill.danger, .status-pill.failed,
.status-badge.error, .status-error, .status-danger {
  color: var(--lg-red-2);
  background: rgb(var(--ch-red2) / 0.10);
  border-color: rgb(var(--ch-red2) / 0.28);
}

/* GRAY — not connected. Deliberately the quietest: a client's screen should not
   be a wall of things they have not done. */
.status-pill.neutral, .status-pill.off, .status-pill.disabled, .status-pill.muted,
.status-pill.unavailable, .status-badge.neutral, .ch-badge.ch-off,
.status-neutral, .status-muted, .status-off {
  color: var(--bd-ink-3);
  background: rgb(var(--ch-lift) / 0.04);
  border-color: var(--bd-line);
}

/* BLUE — demo, draft, test. THE MOST IMPORTANT ONE.
   Sample data that looks like production data is not a design flaw, it is a
   lie a client can act on. Blue is reserved for it and used for nothing else. */
.status-pill.demo, .status-pill.draft, .status-pill.test, .status-pill.info,
.status-pill.local_only, .status-pill.admin, .status-badge.draft, .status-badge.info,
.status-info, .status-draft {
  color: var(--t235);
  background: rgba(122, 167, 255, 0.10);
  border-color: rgba(122, 167, 255, 0.30);
}

/* ============================================================================
   THE PIPELINE IS THE WORKSPACE, NOT A WIDGET
   ============================================================================
   Columns were 268px wide. With twelve stages that is a board you read through
   a letterbox: the stage name truncates, the money hides, and the cards go
   narrow enough that a company name wraps to three lines. The instinct is to
   shrink further so everything fits on one screen — that is the instinct that
   made it hard to scan.

   Horizontal scrolling is the correct answer for a pipeline. Kommo scrolls,
   Trello scrolls, every board anyone actually works in scrolls. So the columns
   get the width they need and the board scrolls, and the stage header stays put
   while the cards move under it.
   ============================================================================ */

.kb-col {
  flex: 0 0 312px;
  padding: var(--bd-3) var(--bd-3) var(--bd-2);
  scroll-snap-align: start;
}

.kb-col-head {
  position: sticky;
  top: 0;
  z-index: 2;
  padding-bottom: 6px;
  /* The header sits on the column's own background so cards scrolling beneath
     it disappear rather than showing through. */
  background: inherit;
}

.kb-col-name {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--bd-ink-2);
}

/* "12 · 9,500 AED" — the money is why anyone opens a pipeline, so it is not
   micro-text tucked under a counter. */
.kb-col-sum {
  position: sticky;
  top: 26px;
  z-index: 2;
  margin: 0 0 var(--bd-3);
  padding-bottom: 8px;
  border-bottom: 1px solid var(--bd-line);
  background: inherit;
  color: var(--bd-ink);
  font-size: 13px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.kb-col-body { gap: 10px; margin-top: 0; }

/* A card answers "who, how much, how long" and stops. Everything else is one
   click away, and a card that tries to be the lead workspace is why the board
   stopped being scannable. */
.kb-card {
  padding: 12px;
  border-radius: var(--bd-r-2);
  line-height: 1.45;
}

.kb-card-top { align-items: baseline; gap: 10px; }
.kb-card-top strong { font-size: 13px; font-weight: 600; }
.kb-card-value { font-size: 13px; font-weight: 600; font-variant-numeric: tabular-nums; }
.kb-card-contact { margin: 4px 0 0; color: var(--bd-ink-3); font-size: 12px; }
.kb-card-meta { margin-top: 10px; gap: 8px; font-size: 11px; }
.kb-card-age { color: var(--bd-ink-4, var(--bd-ink-3)); font-size: 11px; }

/* Empty is a fact, not an occasion. One quiet line, no illustration, no card. */
.kb-col-empty {
  padding: 14px 0;
  color: var(--bd-ink-4, var(--bd-ink-3));
  font-size: 12px;
  text-align: center;
  opacity: 0.7;
}

/* One line where four "not connected" tiles used to be. It states the fact and
   offers the one place to change it — nothing else belongs on a client's CRM
   screen about the plumbing behind their pipeline. */
.crm-ext-strip {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding: 10px var(--bd-3);
  border: 1px solid var(--bd-line);
  border-radius: var(--bd-r-2);
  background: rgb(var(--ch-lift) / 0.02);
  color: var(--bd-ink-3);
  font-size: 12px;
}
.crm-ext-strip .linklike {
  margin-inline-start: auto;
  padding: 0;
  border: 0;
  background: none;
  color: var(--bd-accent, #7aa7ff);
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
}
.crm-ext-strip .linklike:hover { text-decoration: underline; }

/* ============================================================================
   CRM CONTROL BAR — the board's own header, not a dashboard card
   ============================================================================
   Custom-field management used to sit as a large button in the middle of the
   board, between the pipeline title and "+ Лид". It is schema configuration:
   something an owner does once, next to a thing a manager does forty times a
   day. Putting them side by side made both harder to find.

   It is now a quiet control on the right of the bar, visually subordinate to
   "+ Лид", and it stays out of the way of the columns.
   ============================================================================ */

.kb-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--bd-3);
  flex-wrap: wrap;
  margin-bottom: var(--bd-3);
  padding-bottom: var(--bd-3);
  border-bottom: 1px solid var(--bd-line);
}

.kb-head > div:first-child .eyebrow { margin-bottom: 2px; }
.kb-head > div:first-child h3 { margin: 0; font-size: 19px; line-height: 1.2; }
.kb-head > div:first-child .source-note { margin: 4px 0 0; font-size: 12px; }

/* Configuration reads as configuration: no fill, no accent, no competition
   with the one button a manager actually presses. */
.kb-fielddefs {
  margin-inline-start: auto;
  order: 2;
}
.kb-fielddefs > summary {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  border: 1px solid var(--bd-line);
  border-radius: var(--bd-r-pill);
  background: transparent;
  color: var(--bd-ink-3);
  font-size: 12px;
  font-weight: 500;
  cursor: pointer;
  list-style: none;
  white-space: nowrap;
}
.kb-fielddefs > summary::-webkit-details-marker { display: none; }
.kb-fielddefs > summary:hover { color: var(--bd-ink); border-color: var(--bd-ink-4, var(--bd-ink-3)); }

/* Open it and it becomes a panel that floats over the board rather than
   pushing every column down the page. */
.kb-fielddefs[open] {
  position: relative;
}
.kb-fielddefs[open] > :not(summary) {
  position: absolute;
  inset-inline-end: 0;
  top: calc(100% + 8px);
  z-index: 20;
  width: min(420px, 90vw);
  padding: var(--bd-3);
  border: 1px solid var(--bd-line);
  border-radius: var(--bd-r-2);
  background: var(--bd-surface-2, #0e1420);
  box-shadow: 0 18px 48px rgba(0, 0, 0, 0.55);
}
.kb-fielddefs[open] > .source-note { top: calc(100% + 8px); }

/* "+ Лид" is the only filled control on this bar, so it is unmistakably the
   primary action. */
.kb-head > .primary-button { order: 3; }

/* ===================================================================
   CRM CONTROL BAR — the strip a manager touches all day.

   One row of actions, one row of filters. Schema configuration is not
   here: it is behind the gear, because it is done once by an owner and
   every pixel it takes on this bar is taken from work.
   =================================================================== */
.crm-page { min-width: 0; }

.crm-bar {
  display: grid;
  gap: var(--bd-2);
  padding: var(--bd-3) var(--bd-3) var(--bd-2);
  margin-bottom: var(--bd-3);
  border: 1px solid var(--bd-line);
  border-radius: var(--bd-r-lg);
  background: rgb(var(--ch-lift) / 0.025);
}

.crm-bar-row {
  display: flex;
  align-items: center;
  gap: var(--bd-2);
  flex-wrap: wrap;
  min-width: 0;
}

.crm-bar-title { color: var(--bd-ink); font-size: 15px; font-weight: 650; }

.crm-bar-filters {
  padding-top: var(--bd-2);
  border-top: 1px solid var(--bd-line);
}

.crm-pick > select,
.crm-bar select {
  padding: 7px 10px;
  border: 1px solid var(--bd-line);
  border-radius: 999px;
  background: rgb(var(--ch-lift) / 0.03);
  color: var(--bd-ink-2);
  font: inherit;
  font-size: 12.5px;
  cursor: pointer;
  max-width: 190px;
}
/* An active filter is why the board is short. It says so in colour before
   anyone has to read the count. */
.crm-bar select.on {
  color: var(--bd-ink);
  border-color: var(--bd-line-2);
  background: rgb(var(--ch-accent) / 0.12);
}
.crm-pick-pipeline > select {
  font-size: 14px;
  font-weight: 650;
  color: var(--bd-ink);
  max-width: 240px;
}

.crm-viewtoggle {
  display: inline-flex;
  padding: 3px;
  border: 1px solid var(--bd-line);
  border-radius: 999px;
  background: rgb(var(--ch-lift) / 0.03);
}
.crm-viewtoggle > button {
  padding: 5px 14px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--bd-ink-3);
  font: inherit;
  font-size: 12.5px;
  cursor: pointer;
}
.crm-viewtoggle > button.on { background: rgb(var(--ch-accent) / 0.16); color: var(--bd-ink); }

/* The search box takes the space nothing else needs, and never less than
   enough to read a company name back. */
.crm-search { position: relative; flex: 1 1 240px; min-width: 200px; }
.crm-search > input {
  width: 100%;
  padding-block: 8px 8px; padding-inline: 12px 30px;
  border: 1px solid var(--bd-line);
  border-radius: 999px;
  background: rgb(var(--ch-lift) / 0.03);
  color: var(--bd-ink);
  font: inherit;
  font-size: 13px;
}
.crm-search > input::placeholder { color: var(--bd-ink-3); }
.crm-search-x {
  position: absolute;
  top: 50%;
  inset-inline-end: 8px;
  transform: translateY(-50%);
  border: 0;
  background: transparent;
  color: var(--bd-ink-3);
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
}

.crm-newlead { margin-inline-start: auto; }

.crm-gear {
  width: 34px;
  height: 34px;
  border: 1px solid var(--bd-line);
  border-radius: 50%;
  background: transparent;
  color: var(--bd-ink-3);
  font-size: 15px;
  cursor: pointer;
}
.crm-gear:hover { color: var(--bd-ink); border-color: var(--bd-line-2); }

.crm-clearfilters {
  padding: 6px 12px;
  border: 1px solid var(--bd-line-2);
  border-radius: 999px;
  background: transparent;
  color: var(--bd-ink-2);
  font: inherit;
  font-size: 12px;
  cursor: pointer;
}
.crm-bar-count { margin-inline-start: auto; color: var(--bd-ink-3); font-size: 12px; }

/* ===================================================================
   REQUIRES ATTENTION — the first thing on the screen, because the first
   question of the day is not "where is everything" but "who is waiting".
   =================================================================== */
.crm-attention {
  margin-bottom: var(--bd-3);
  padding: var(--bd-3);
  border: 1px solid rgb(var(--ch-warm3) / 0.28);
  border-radius: var(--bd-r-lg);
  background: rgb(var(--ch-warm3) / 0.05);
}
.crm-attention.quiet {
  border-color: var(--bd-line);
  background: rgb(var(--ch-lift) / 0.02);
}
.crm-attention-clear { margin: 0; color: var(--bd-ink-3); font-size: 12.5px; }
.crm-attention-head h3 { margin: 0 0 2px; font-size: 15px; color: var(--bd-ink); }
.crm-attention-head .source-note { margin: 0 0 var(--bd-2); }

.crm-attention-buckets { display: flex; flex-wrap: wrap; gap: var(--bd-2); }
.crm-bucket {
  display: grid;
  gap: 2px;
  min-width: 118px;
  padding: 9px 14px;
  border: 1px solid var(--bd-line);
  border-radius: var(--bd-r);
  background: rgb(var(--ch-lift) / 0.03);
  color: var(--bd-ink-2);
  font: inherit;
  text-align: start;
  cursor: pointer;
}
.crm-bucket:hover:not(:disabled) { border-color: var(--bd-line-2); }
.crm-bucket.static { cursor: default; }
.crm-bucket > strong { color: var(--bd-ink); font-size: 20px; line-height: 1.1; }
.crm-bucket > span { color: var(--bd-ink-3); font-size: 11.5px; }

.crm-attention-list { margin-top: var(--bd-3); }
.crm-attention-list h4 {
  margin: 0 0 6px;
  color: var(--bd-ink-3);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.crm-attention-row {
  display: grid;
  grid-template-columns: minmax(120px, 1fr) minmax(0, 2fr) auto;
  gap: var(--bd-2);
  width: 100%;
  padding: 7px 10px;
  border: 0;
  border-radius: var(--bd-r);
  background: transparent;
  color: var(--bd-ink-2);
  font: inherit;
  font-size: 12.5px;
  text-align: start;
  cursor: pointer;
}
.crm-attention-row:hover:not(:disabled) { background: rgb(var(--ch-lift) / 0.04); }
.crm-attention-row:disabled { cursor: default; opacity: 0.75; }
.crm-attention-who { color: var(--bd-ink); font-weight: 600; }
.crm-attention-msg {
  overflow: hidden;
  color: var(--bd-ink-3);
  text-overflow: ellipsis;
  white-space: nowrap;
}
.crm-attention-age { color: var(--lg-warm-1); font-variant-numeric: tabular-nums; }
.crm-attention-age.overdue { color: var(--lg-red-1); }

/* ===================================================================
   LIST VIEW — dense on purpose. A salesperson looking for a name reads
   rows; a table that fits eight deals on a screen is one nobody opens.
   =================================================================== */
.crm-list-wrap {
  min-width: 0;
  overflow-x: auto;
  border: 1px solid var(--bd-line);
  border-radius: var(--bd-r-lg);
  background: rgb(var(--ch-lift) / 0.02);
}
.crm-list { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.crm-list th {
  position: sticky;
  top: 0;
  z-index: 1;
  padding: 9px 12px;
  border-bottom: 1px solid var(--bd-line);
  background: var(--t28);
  color: var(--bd-ink-3);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-align: start;
  text-transform: uppercase;
  white-space: nowrap;
}
.crm-list th.sorted { color: var(--bd-ink); }
.crm-list th > button {
  border: 0;
  padding: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  cursor: pointer;
}
.crm-list td {
  padding: 9px 12px;
  border-bottom: 1px solid rgb(var(--ch-line) / 0.08);
  color: var(--bd-ink-2);
  white-space: nowrap;
}
.crm-list tbody tr { cursor: pointer; }
.crm-list tbody tr:hover { background: rgb(var(--ch-accent) / 0.07); }
.crm-list .c-title { color: var(--bd-ink); font-weight: 600; max-width: 260px; }
.crm-list .c-title > span, .crm-list .c-title > a {
  display: inline-block;
  max-width: 220px;
  overflow: hidden;
  text-overflow: ellipsis;
  vertical-align: bottom;
}
/* The cell content became a real <a href> (right-click "open in new tab" —
   3 сентября) so the browser stops rendering it like generic body text. */
.crm-list .c-title > a { color: inherit; text-decoration: none; }
.crm-list .c-title > a:hover { text-decoration: underline; }
.crm-list-tasks { margin-inline-start: 6px; color: var(--lg-warm-1); font-size: 11px; font-style: normal; }
.crm-list-tasks.overdue { color: var(--lg-red-1); }
.crm-list .c-phone, .crm-list .c-value { font-variant-numeric: tabular-nums; }
.crm-list .c-value { color: var(--lg-cyan-2); }
.crm-list .c-overdue { color: var(--lg-red-1); }
.crm-list-stage {
  display: inline-block;
  padding: 2px 9px;
  border: 1px solid var(--bd-line);
  border-radius: 999px;
  font-size: 11.5px;
}
.crm-list-empty {
  padding: var(--bd-5);
  border: 1px dashed var(--bd-line);
  border-radius: var(--bd-r-lg);
  color: var(--bd-ink-3);
  text-align: center;
}
.crm-list-empty > p { margin: 0; }

/* ===================================================================
   THE LEAD WORKSPACE — wide enough for serious work, tabbed so that six
   kinds of record do not become one endless scroll.
   =================================================================== */
.kb-panel-wide { width: min(760px, 100vw); }

.kb-summary {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: var(--bd-2);
  padding: var(--bd-3) var(--bd-4);
  border-bottom: 1px solid var(--bd-line);
}
.kb-summary > div { display: grid; gap: 2px; min-width: 0; }
.kb-summary span { color: var(--bd-ink-3); font-size: 11px; }
.kb-summary strong {
  overflow: hidden;
  color: var(--bd-ink);
  font-size: 13px;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.kb-summary-tags { padding: 0 var(--bd-4) var(--bd-2); }

.kb-tabs {
  display: flex;
  gap: 2px;
  overflow-x: auto;
  padding: 0 var(--bd-4);
  border-bottom: 1px solid var(--bd-line);
}
.kb-tabs > button {
  padding: 10px 12px;
  border: 0;
  border-bottom: 2px solid transparent;
  background: transparent;
  color: var(--bd-ink-3);
  font: inherit;
  font-size: 12.5px;
  white-space: nowrap;
  cursor: pointer;
}
.kb-tabs > button.on { border-bottom-color: var(--pk-blue); color: var(--bd-ink); }
.kb-tabbody { display: grid; gap: var(--bd-3); }

.kb-readonly {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: var(--bd-2);
  padding: var(--bd-3);
  border: 1px solid var(--bd-line);
  border-radius: var(--bd-r);
  background: rgb(var(--ch-lift) / 0.02);
}
.kb-readonly > div { display: grid; gap: 2px; }
.kb-readonly span { color: var(--bd-ink-3); font-size: 11px; }
.kb-readonly strong { color: var(--bd-ink-2); font-size: 12.5px; font-weight: 600; }

.kb-msg-meta {
  display: flex;
  justify-content: space-between;
  gap: var(--bd-2);
  margin-bottom: 3px;
  color: var(--bd-ink-3);
  font-size: 10.5px;
}
.kb-task-title { flex: 1; }
.kb-tasks li.overdue .kb-task-title { color: var(--lg-red-1); }
.kb-add-task { flex-wrap: wrap; }
.kb-add-task input[type="datetime-local"], .kb-add-task select { flex: 0 0 auto; }

.kb-activity { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.kb-activity > li {
  display: grid;
  gap: 2px;
  padding-inline-start: var(--bd-3);
  border-inline-start: 2px solid var(--bd-line-2);
}
.kb-act-text { color: var(--bd-ink-2); font-size: 12.5px; }
.kb-activity small { color: var(--bd-ink-3); font-size: 11px; }

/* Schema setup, over the board rather than in it. */
.crm-setup-list { display: grid; gap: 6px; }
.crm-setup-row {
  display: flex;
  align-items: center;
  gap: 8px;
}
.crm-setup-row > input {
  flex: 1;
  min-width: 0;
  padding: 7px 10px;
  border: 1px solid var(--bd-line);
  border-radius: var(--bd-r);
  background: rgb(var(--ch-lift) / 0.03);
  color: var(--bd-ink);
  font: inherit;
  font-size: 12.5px;
}
.crm-setup-name { flex: 1; color: var(--bd-ink); font-size: 12.5px; }
.crm-setup-row > small {
  min-width: 26px;
  color: var(--bd-ink-3);
  font-size: 11px;
  text-align: end;
}
.crm-setup-row > button {
  width: 26px;
  height: 26px;
  border: 1px solid var(--bd-line);
  border-radius: 7px;
  background: transparent;
  color: var(--bd-ink-3);
  font-size: 12px;
  cursor: pointer;
}
.crm-setup-row > button:disabled { opacity: 0.35; cursor: default; }
.crm-setup-x:hover { color: var(--lg-red-2); border-color: rgb(var(--ch-red2) / 0.4); }

/* ── the stage-name colour strip ──────────────────────────────────────────
   One stage is now two rows — the name row and its swatches — so the row and
   the strip are wrapped together and the list's 6px gap separates STAGES
   rather than lines of one stage. */
.crm-setup-stage { display: grid; gap: 5px; }
.crm-setup-swatches {
  display: flex;
  align-items: center;
  gap: 5px;
  /* Aligned under the name field rather than the panel edge, so the strip
     reads as belonging to the name above it. */
  padding-block: 0 2px; padding-inline: 2px 0;
}
/* Deliberately NOT `.crm-setup-row > button`: these are 14px dots, not 26px
   square controls, and they are inside .crm-setup-swatches precisely so that
   rule cannot reach them. */
.crm-swatch {
  width: 14px;
  height: 14px;
  /* min-height, not just height. styles.css carries a bare
     `button { min-height: 40px }` from the legacy cabinet — redesign.css
     already names it twice as the reason two other controls were stretched.
     `height: 14px` loses to it, because a minimum beats a preference no matter
     how specific the selector is, and the dots rendered as 14×40 ellipses.
     Verified in the browser at 1536, not inferred from the cascade. */
  min-height: 14px;
  padding: 0;
  flex: 0 0 auto;
  border: 1px solid rgb(var(--ch-lift) / 0.16);
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
  /* The selected swatch is marked by a ring drawn OUTSIDE the dot, not by
     shrinking or recolouring it. A selection state that alters the colour
     would misreport the colour it is offering. */
  box-shadow: none;
  transition: box-shadow 90ms linear, transform 90ms linear;
}
.crm-swatch:hover { transform: scale(1.18); }
.crm-swatch.is-on {
  box-shadow: 0 0 0 2px var(--bd-bg, #0b0f16), 0 0 0 3.5px var(--bd-ink, #e9eef7);
}
/* "No colour" is a control, not a colour, so it is drawn as one: an em dash in
   a hollow ring. It must not look like an eleventh hue, and it must not look
   like a disabled swatch either — the default is a choice. */
.crm-swatch-none {
  width: auto;
  min-width: 18px;
  height: 14px;
  min-height: 14px;
  border-radius: 8px;
  color: var(--bd-ink-3);
  font-size: 10px;
  line-height: 1;
}
.crm-swatch-none:hover { transform: none; color: var(--bd-ink); }
.crm-swatch:focus-visible {
  outline: 2px solid var(--pk-blue, var(--pk-blue));
  outline-offset: 2px;
}

@media (max-width: 720px) {
  .crm-newlead, .crm-bar-count { margin-inline-start: 0; }
  .kb-summary { grid-template-columns: repeat(auto-fit, minmax(104px, 1fr)); }
}

/* MEASURED ON A 1280-WIDE LAPTOP. At 312px, four columns need 1290px and only
   three fit the 1180px track — a pipeline you scroll to see a third of. 284px
   is the widest column that lets four stand side by side (4x284 + 3x14 = 1178),
   and it keeps the reason 312 was chosen: wide enough that a stage name and the
   money on it are still read, not truncated. */
.kb-col { flex: 0 0 284px; }

/* The queue keeps its counts open and its rows behind a click. Expanded by
   default it stood 414px tall and pushed the top of the board to y=714 — the
   pipeline below the fold, which is the failure this panel was built to fix. */
.crm-attention-head { display: flex; align-items: baseline; gap: var(--bd-2); flex-wrap: wrap; }
.crm-attention-head .source-note { margin: 0; }
.crm-attention-head h3 { margin: 0 0 var(--bd-2); }
.crm-attention-more { margin-top: var(--bd-2); }
.crm-attention-more > summary {
  color: var(--bd-ink-3); font-size: 12px; cursor: pointer; list-style: none;
}
.crm-attention-more > summary::-webkit-details-marker { display: none; }
.crm-attention-more > summary::before { content: "▸ "; }
.crm-attention-more[open] > summary::before { content: "▾ "; }
.crm-attention-more > summary:hover { color: var(--bd-ink); }

/* Replying to the customer, from the deal. Sits under the thread, not over it:
   the last thing read should be what they said, and the next thing done is
   directly beneath it. */
.kb-reply {
  display: grid;
  gap: 8px;
  padding-top: var(--bd-3);
  border-top: 1px solid var(--bd-line);
}
.kb-reply > textarea {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--bd-line);
  border-radius: var(--bd-r);
  background: rgb(var(--ch-lift) / 0.03);
  color: var(--bd-ink);
  font: inherit;
  font-size: 13px;
  resize: vertical;
}
.kb-reply > textarea:disabled { opacity: 0.6; }
.kb-reply-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--bd-2);
  flex-wrap: wrap;
}
/* Said plainly and once: the message goes out as the person, and the agent
   stops talking in this dialogue. Both are consequences a manager should read
   before pressing, not discover afterwards. */
.kb-reply-row > small { flex: 1; min-width: 180px; color: var(--bd-ink-3); font-size: 11px; }
.kb-reply-error {
  margin: 0;
  color: var(--lg-red-1);
  font-size: 12px;
}
.kb-reply-off { padding-top: var(--bd-3); border-top: 1px solid var(--bd-line); }

/* Priority, readable at a glance. A scale nobody can read without stopping is a
   field people stop setting. */
.crm-prio { font-size: 11.5px; }
.crm-prio.p-high { color: var(--lg-red-1); font-weight: 650; }
.crm-prio.p-low { color: var(--bd-ink-3); }
.crm-prio.p-normal { color: var(--bd-ink-2); }

/* Doing one thing to eighty deals. Appears only when something is selected and
   sits above the rows it will act on. */
.crm-bulk {
  position: sticky;
  top: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: var(--bd-2);
  flex-wrap: wrap;
  padding: 9px var(--bd-3);
  border-bottom: 1px solid var(--bd-line-2);
  background: rgb(var(--ch-blue) / 0.14);
}
.crm-bulk > strong { color: var(--bd-ink); font-size: 12.5px; }
.crm-bulk select {
  padding: 6px 10px;
  border: 1px solid var(--bd-line-2);
  border-radius: 999px;
  background: rgba(11, 16, 24, 0.75);
  color: var(--bd-ink-2);
  font: inherit;
  font-size: 12px;
  cursor: pointer;
}

.crm-list th.c-pick, .crm-list td.c-pick { width: 34px; padding-inline-end: 0; }
.crm-list td.c-pick { cursor: default; }
.crm-list tbody tr.picked { background: rgb(var(--ch-blue) / 0.12); }
.crm-list tbody tr.picked:hover { background: rgb(var(--ch-blue) / 0.18); }

/* A question the board asks, not a browser prompt: the stages are listed
   because typing one by name fails on a typo and shows nobody the choices. */
/* rtl-exempt: центрирование left: 50% + translateX(-50%) симметрично и в RTL даёт тот же центр; inset-inline-start: 50% с тем же сдвигом в RTL уезжает на половину ширины (подсказки и окна в арабском, 15.09.2026). */
.crm-dialog {
  position: fixed;
  top: 50%;
  left: 50%;
  z-index: 62;
  transform: translate(-50%, -50%);
  display: grid;
  gap: var(--bd-2);
  width: min(440px, calc(100vw - 32px));
  padding: var(--bd-4);
  border: 1px solid var(--bd-line-2);
  border-radius: var(--bd-r-lg);
  background: var(--bd-panel);
  box-shadow: 0 30px 70px rgba(0, 0, 0, 0.55);
}
.crm-dialog h3 { margin: 0; font-size: 17px; color: var(--bd-ink); }
.crm-dialog p { margin: 0; color: var(--bd-ink-2); font-size: 13px; }
.crm-dialog select {
  padding: 9px 12px;
  border: 1px solid var(--bd-line);
  border-radius: var(--bd-r);
  background: rgb(var(--ch-lift) / 0.03);
  color: var(--bd-ink);
  font: inherit;
  font-size: 13px;
}
.crm-dialog-row { display: flex; justify-content: flex-end; gap: var(--bd-2); }
/* Loss-reason presets on the kanban drop / lead-workspace stage select — the
   same .crm-dialog shell, one added grid of preset chips plus a free-text
   fallback row. */
.crm-lost-reason-grid { display: flex; flex-wrap: wrap; gap: 6px; }
.crm-lost-reason-other { display: flex; gap: 6px; align-items: center; }
.crm-lost-reason-other input {
  flex: 1 1 auto;
  min-width: 0;
  padding: 9px 12px;
  border: 1px solid var(--bd-line);
  border-radius: var(--bd-r);
  background: rgb(var(--ch-lift) / 0.03);
  color: var(--bd-ink);
  font: inherit;
  font-size: 13px;
}

/* 26.09.2026 — причина удаления: выпадающий список, поле только для
   «Другое — впишу сам», «Отмена» и «Удалить лид» в одной строке. Три класса
   в селекторе: .workspace input[type=text] (0,2,1) иначе перебивает поле. */
.crm-dialog.crm-lost-reason .crm-lost-reason-select,
.crm-dialog.crm-lost-reason .crm-lost-reason-input {
  width: 100%;
  min-height: 40px;
  box-sizing: border-box;
}
.crm-dialog.crm-lost-reason .crm-lost-reason-input {
  padding: 9px 12px;
  border: 1px solid var(--bd-line);
  border-radius: var(--bd-r);
  background: rgb(var(--ch-lift) / 0.03);
  color: var(--bd-ink);
  font: inherit;
  font-size: 13px;
}
.crm-dialog.crm-lost-reason .crm-lost-reason-actions { justify-content: space-between; }
/* Телефон: 16px, иначе iPhone приближает страницу при нажатии на список. */
@media (max-width: 767px) {
  .crm-dialog.crm-lost-reason .crm-lost-reason-select,
  .crm-dialog.crm-lost-reason .crm-lost-reason-input { font-size: 16px; }
}

/* Import sits on the working bar, not inside setup: for a client arriving from
   another CRM it is the first thing they do. Outlined, so it never competes
   with "+ Lead" for the eye. */
.crm-import-open {
  padding: 7px 14px;
  border: 1px solid var(--bd-line-2);
  border-radius: 999px;
  background: transparent;
  color: var(--bd-ink-2);
  font: inherit;
  font-size: 12.5px;
  cursor: pointer;
}
.crm-import-open:hover { color: var(--bd-ink); background: rgb(var(--ch-accent) / 0.1); }

.crm-import-steps > button { opacity: 0.5; cursor: default; }
.crm-import-steps > button.on { opacity: 1; }

.crm-import-body { display: grid; gap: var(--bd-3); }
.crm-import-body > p { margin: 0; color: var(--bd-ink-2); font-size: 13px; }
.crm-import-body input[type="file"] {
  padding: var(--bd-3);
  border: 1px dashed var(--bd-line-2);
  border-radius: var(--bd-r);
  background: rgb(var(--ch-lift) / 0.02);
  color: var(--bd-ink-2);
  font: inherit;
  font-size: 12.5px;
}

/* One row per column of the client's file: what it is called there, our guess,
   and a control to correct it. A guess is marked as a guess. */
.crm-map-list { display: grid; gap: 6px; max-height: 320px; overflow-y: auto; }
.crm-map-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 5px 8px;
  border-radius: var(--bd-r);
  background: rgb(var(--ch-lift) / 0.02);
}
.crm-map-col {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  color: var(--bd-ink);
  font-size: 12.5px;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.crm-map-row > small { color: var(--bd-ink-3); font-size: 11.5px; }
.crm-map-row select {
  flex: 0 0 auto;
  max-width: 200px;
  padding: 5px 9px;
  border: 1px solid var(--bd-line);
  border-radius: 999px;
  background: rgb(var(--ch-lift) / 0.03);
  color: var(--bd-ink-2);
  font: inherit;
  font-size: 12px;
}
.crm-map-guess {
  width: 17px;
  height: 17px;
  border-radius: 50%;
  background: rgb(var(--ch-warm3) / 0.2);
  color: var(--lg-warm-1);
  font-size: 11px;
  font-style: normal;
  line-height: 17px;
  text-align: center;
}

.crm-import-choices { display: flex; gap: 6px; flex-wrap: wrap; }
.crm-import-choices > button {
  padding: 6px 12px;
  border: 1px solid var(--bd-line);
  border-radius: 999px;
  background: transparent;
  color: var(--bd-ink-3);
  font: inherit;
  font-size: 12px;
  cursor: pointer;
}
.crm-import-choices > button.on {
  border-color: var(--bd-line-2);
  background: rgb(var(--ch-accent) / 0.14);
  color: var(--bd-ink);
}

.crm-import-actions { display: flex; justify-content: flex-end; gap: var(--bd-2); }
.crm-import-warn {
  margin: 0;
  padding: 9px 12px;
  border: 1px solid rgb(var(--ch-warm3) / 0.3);
  border-radius: var(--bd-r);
  background: rgb(var(--ch-warm3) / 0.07);
  color: var(--lg-warm-1);
  font-size: 12.5px;
}

/* ===================================================================
   NATIVE CONTROLS, IN A DARK PRODUCT

   The white dropdown was not a styling oversight on any one screen — it
   was one missing declaration for the whole application. `color-scheme`
   is what tells the browser which palette to draw the parts of a control
   it renders ITSELF: the popup list of a <select>, the calendar of a date
   input, scrollbars, focus rings. CSS cannot reach inside those; the
   keyword is the only lever.

   It existed in exactly one place in this codebase — on a single date
   input at styles.css:3238 — so all twenty-one selects in the product
   opened a light popup over a dark interface, and on Windows that lands
   as near-white text on near-white.

   Declared on :root so it applies once, everywhere, including controls
   added later.
   =================================================================== */
:root {
  color-scheme: dark;
}

/* Belt and braces: Firefox and older Chromium honour color-scheme
   inconsistently for option lists, and a client seeing an unreadable menu
   does not care which engine was right. Explicit colours cost nothing and
   remove the whole class of report. */
select option,
select optgroup {
  background-color: var(--t10);
  color: var(--lw-ink);
}

/* One select, everywhere. Modules may set their own shape — the CRM bar
   uses pills, forms use rounded rectangles — but none of them should have
   to restate the colours, and before this they each did it differently or
   not at all. Low specificity on purpose: a module that has already made a
   deliberate choice keeps it. */
select {
  color: var(--bd-ink, var(--lw-ink));
  background-color: rgb(var(--ch-lift) / 0.03);
  border: 1px solid var(--bd-line, rgb(var(--ch-line) / 0.14));
  border-radius: var(--bd-r, 14px);
  font: inherit;
}
select:hover:not(:disabled) {
  border-color: var(--bd-line-2, rgb(var(--ch-line) / 0.28));
}
/* A visible focus ring is not decoration: it is the only way a keyboard
   user knows where they are. */
select:focus-visible,
input:focus-visible,
textarea:focus-visible {
  outline: 2px solid rgb(var(--ch-accent) / 0.55);
  outline-offset: 1px;
}
select:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* ═══════════════════════════════════════════════════════════════════════════
   UI/UX REFERENCE PACKAGE — BATCH 1
   Implements docs/UI_UX_MOCKUP_IMPLEMENTATION_MAP.md rows 1, 3 and 16.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Navigation glyphs ────────────────────────────────────────────────────
   The rail carried two- and three-letter codes — EO, CRM, AI, MS, ME, AC, IN,
   ST — because that is what `pages[]` has always supplied as an icon. Every
   reference in the package draws glyphs instead, and the codes cost the reader
   a translation step on every glance: "MS" is Marketing & Sources only to
   whoever wrote it. Collapsed, the rail was nothing BUT those codes.

   Masks rather than inline <svg>: the renderer builds nodes with
   document.createElement, which has no SVG namespace, so an <svg> child would
   come back as an unknown element and draw nothing. The glyph inherits
   currentColor, so it keeps the active/hover states already defined above.

   The letter code stays in the DOM as the fallback for any page without a
   glyph — those keep rendering exactly as before. */
.nav-item .nav-icon[class*="nav-icon-"] {
  font-size: 0;
  line-height: 0;
}
.nav-item .nav-icon[class*="nav-icon-"]::before {
  content: "";
  display: block;
  width: 15px;
  height: 15px;
  background-color: currentColor;
  -webkit-mask: var(--nav-glyph) center / contain no-repeat;
  mask: var(--nav-glyph) center / contain no-repeat;
}
/* THE :not() BLACKLIST IS GONE, AND THAT IS THE POINT.
   It named the eight keys that had a glyph and forced every other key back to
   its two-letter code — at (0,11,0) specificity, which no clean selector in a
   later sheet can out-rank. That is why «Диалоги» and «Голос и звонки» still
   rendered "CV" and "VC" after redesign.css had drawn glyphs for them: the
   blacklist was written before those keys existed and silently vetoed them.
   redesign.css now owns the whole mechanism — it declares a transparent default
   glyph, so a key with no icon shows nothing rather than a letter code, and
   adding an icon is one rule with no list to remember to update. */

/* The eight per-key glyphs that used to live here are deleted, not commented
   out. redesign.css declares all ten rail glyphs plus a transparent default,
   at a higher specificity, so these were dead rules that still read as the
   source of truth — which is exactly how the blacklist above survived two
   passes unnoticed. One file owns the rail glyphs now. */
/* ── CRM: the numbers above the pipeline ──────────────────────────────────
   Tabular figures because these are compared down a row, and a proportional
   "1" makes two totals of the same magnitude look different lengths. */
.crm-kpi {
  display: grid;
  gap: 8px;
}
.crm-kpi-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(148px, 1fr));
  gap: var(--bd-2);
}
.crm-kpi-tile {
  display: grid;
  align-content: start;
  gap: 2px;
  padding: 12px var(--bd-3);
  border: 1px solid var(--bd-line);
  border-radius: var(--bd-r);
  background: linear-gradient(180deg, rgb(var(--ch-panel9) / 0.66), rgb(var(--ch-ink9) / 0.66));
}
/* The open pipeline is the one figure an owner opens this page for. */
.crm-kpi-tile.accent {
  border-color: rgb(var(--ch-cyan2) / 0.3);
  background: linear-gradient(180deg, var(--crm-accent-a), var(--crm-accent-b));
}
.crm-kpi-lbl {
  color: var(--bd-ink-3);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}
.crm-kpi-val {
  color: var(--bd-ink);
  font-size: 21px;
  font-weight: 660;
  line-height: 1.15;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.015em;
}
.crm-kpi-tile.accent .crm-kpi-val { color: var(--lg-cyan-2); }
.crm-kpi-sub {
  color: var(--bd-ink-3);
  font-size: 11.5px;
  line-height: 1.35;
}
.crm-kpi-note {
  margin: 0;
  color: var(--bd-ink-3);
  font-size: 11.5px;
  line-height: 1.4;
}

@media (max-width: 720px) {
  .crm-kpi-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .crm-kpi-val { font-size: 18px; }
}

/* ── Overview: a finished workspace opens on its business ─────────────────
   When the board has moved above it, the setup panel is a footnote confirming
   a finished state, not the headline. It reads as one, and stops competing
   with the figures for the top of the page. */
.dashboard-onboarding-panel.settled {
  padding: var(--bd-3) var(--bd-4);
  background: rgb(var(--ch-lift) / 0.018);
  border-color: var(--bd-line);
  box-shadow: none;
}
.dashboard-onboarding-panel.settled .dashboard-onboarding-copy strong {
  font-size: 14px;
}
.dashboard-onboarding-panel.settled .dashboard-onboarding-copy p {
  font-size: 12.5px;
  color: var(--bd-ink-3);
}

/* ── Boro yields to an open workflow surface ──────────────────────────────
   While a lead card, a stage dialog or an import panel is open, the companion
   steps out of the way completely. It is not removed from the product and it
   is not hidden anywhere else — closing the drawer brings it straight back,
   in the same place, with no state to remember.

   :has() is the whole mechanism, so there is no JS and nothing to keep in sync.
   Where :has() is unsupported the overlap returns, and only a stacking-context
   change can fix it there — see below for why z-index alone cannot.

   WHY visibility AND NOT opacity. Fading to 0.18 was not enough, and the live
   check after the 014c6e1 deploy proved it: Boro was still PAINTED over the
   drawer, just faintly. Lowering its z-index to 50 could not fix that either,
   because `main.workspace` carries `position: relative; z-index: 1` and so
   opens its own stacking context — the drawer's z-index 61 is scoped INSIDE
   that context, and against Boro in the root context the whole workspace
   competes at 1. Boro at 50 outranks it no matter what the drawer declares.

   So the widget is taken out of the picture entirely for as long as a modal
   surface is open. `visibility: hidden` keeps its box and its position, so
   nothing is re-laid-out and its drag coordinates survive untouched; it simply
   stops being rendered and stops being a hit target. */
/* The workspaces own their whole window. Boro is position:fixed and mounted
   outside the tree, so on those screens it floats over the composer and the
   send button — the two controls an operator reaches for most. Same rule that
   already hides it over panels and dialogs, extended to the new screens. */
/* The support drawer joins the list. Measured at 1536x830: it mounts as a
   viewport-sized fixed layer at z-index 40 while Boro sits at 50, so the
   companion floated on top of the very form the client opened to ask us for
   help — the same failure as the lead drawer, one z-index later. */
body:has(.lw-page) .boro-root,
body:has(.dw) .boro-root,
body:has(.kb-panel) .boro-root,
body:has(.support-drawer.open) .boro-root,
body:has(.crm-dialog) .boro-root {
  visibility: hidden;
  pointer-events: none;
}
/* A drag in progress outranks it: releasing the pointer must not strand a
   half-dragged widget in a dead state, and a drawer opening mid-drag must not
   make the thing under the cursor vanish. */
body:has(.kb-panel) .boro-root.boro-dragging,
body:has(.crm-dialog) .boro-root.boro-dragging {
  visibility: visible;
  pointer-events: auto;
  opacity: 1;
}

/* ── CRM: which store am I looking at? ────────────────────────────────────
   The explaining variant of the external strip. It is deliberately quiet —
   a bordered notice with an amber edge would read as an error, and there is
   no error here: two stores, one of them not yet filled, by design. */
.crm-ext-explain {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--bd-3);
  flex-wrap: wrap;
}
.crm-ext-copy {
  display: flex;
  align-items: flex-start;
  gap: var(--bd-2);
  min-width: 0;
  flex: 1 1 420px;
}
.crm-ext-line {
  margin: 0;
  color: var(--bd-ink-2);
  font-size: 12.5px;
  line-height: 1.5;
}
.crm-ext-line strong {
  color: var(--bd-ink);
  font-weight: 620;
}
.crm-ext-actions {
  display: flex;
  align-items: center;
  gap: var(--bd-2);
  flex: 0 0 auto;
}

/* The KPI strip explaining its own zeros. Same voice as the note above it —
   one line, no icon, no colour. It disappears by itself once the pipeline
   holds anything, so it never becomes furniture. */
.crm-kpi-why {
  color: var(--bd-ink-2);
}

@media (max-width: 720px) {
  .crm-ext-explain { align-items: stretch; }
  .crm-ext-actions { flex-direction: column; align-items: stretch; }
  .crm-ext-actions .primary-button { width: 100%; }
}

/* ── Voice & calls ────────────────────────────────────────────────────────
   The module the package draws on four of its rails and details in 04, and
   which the product did not have. Everything here either reports a real server
   contract or states plainly why it cannot — there is no drawn waveform and no
   invented call log. */
/* The voice glyph moved to redesign.css with the other nine — see the note at
   the deleted per-key block above. */

.voice-header { grid-template-columns: minmax(0, 1fr) auto; align-items: start; }
.voice-header-side {
  display: flex;
  align-items: center;
  gap: var(--bd-2);
  flex-wrap: wrap;
  justify-content: flex-end;
}

.voice-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: var(--bd-3);
  align-items: start;
}
.voice-grid-keypad { grid-template-columns: minmax(300px, 0.9fr) minmax(280px, 1.1fr); }

/* An honest block, not an error. The state label is the quietest thing in it;
   the sentence under the heading is the part that has to be read. */
.voice-notice {
  display: grid;
  gap: 6px;
  padding: var(--bd-4);
  border: 1px solid var(--bd-line);
  border-radius: var(--bd-r-lg);
  background: linear-gradient(180deg, rgb(var(--ch-panel9) / 0.66), rgb(var(--ch-ink9) / 0.66));
}
.voice-notice h3 { margin: 0; font-size: 15px; color: var(--bd-ink); }
.voice-notice-state {
  margin: 0;
  color: var(--bd-ink-3);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.voice-notice-setup .voice-notice-state { color: var(--bd-warn); }
.voice-notice-backend .voice-notice-state { color: var(--bd-off); }
.voice-notice-body {
  margin: 0;
  color: var(--bd-ink-2);
  font-size: 12.5px;
  line-height: 1.55;
}
.voice-notice .ghost-button { justify-self: start; margin-top: 4px; }

.voice-dial {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
  margin: var(--bd-3) 0;
}
/* Deliberately inert, and it looks it. A keypad that appears live and does
   nothing is worse than one that plainly is not the way to place a call. */
.voice-key {
  min-height: 44px;
  border: 1px solid var(--bd-line);
  border-radius: var(--bd-r);
  background: rgb(var(--ch-lift) / 0.02);
  color: var(--bd-ink-3);
  font-size: 15px;
  font-weight: 600;
  cursor: not-allowed;
}

.voice-facts { display: grid; gap: 8px; margin: var(--bd-3) 0; }
.voice-facts > div {
  display: flex;
  justify-content: space-between;
  gap: var(--bd-2);
  padding-bottom: 6px;
  border-bottom: 1px solid var(--bd-line);
}
.voice-facts dt { margin: 0; color: var(--bd-ink-3); font-size: 12px; }
.voice-facts dd { margin: 0; color: var(--bd-ink); font-size: 12.5px; text-align: end; }

.voice-footer {
  display: flex;
  flex-wrap: wrap;
  gap: var(--bd-3);
  padding: 10px var(--bd-3);
  border: 1px solid var(--bd-line);
  border-radius: var(--bd-r);
  color: var(--bd-ink-3);
  font-size: 11.5px;
}

@media (max-width: 900px) {
  .voice-grid-keypad { grid-template-columns: minmax(0, 1fr); }
  .voice-header { grid-template-columns: minmax(0, 1fr); }
  .voice-header-side { justify-content: flex-start; }
}

/* ── The dialogue list, one size up ─────────────────────────────────────────
 *
 * «слишком мелко, чуть увеличить строки» — 2026-08-16. The list is the screen
 * somebody scans for minutes at a time looking for one conversation, and it was
 * set at 11.5–14px with 11px padding: dense enough to fit more rows than anyone
 * actually reads, and small enough to make the snippet — the only part that
 * tells you which conversation this IS — the hardest thing on the page to read.
 *
 * Raised one step, not two. The snippet gains the most because it carries the
 * most meaning; the timestamp stays quiet because nobody scans by timestamp.
 * Declared at the end of the file so it wins over the block above without
 * touching rules other screens share.
 *
 * Also: the search field's magnifier sat at left:12px against a 32px text
 * indent, which reads as the icon touching the placeholder at this font size.
 * Widened the indent rather than moving the icon — the icon is where the eye
 * expects it; it was the text that was too close.
 */
.chatpane-search input { padding-inline-start: 38px; font-size: 14.5px; }
/* font-size no longer does anything here — the icon is drawn, not a glyph —
   left alone since it repositions the icon for this wider indent. */
.chatpane-searchicon { inset-inline-start: 13px; }

.chatrow { padding: 13px 12px; gap: 12px; }
.chatrow-avatar { width: 42px; height: 42px; font-size: 14px; }
.chatrow-top { font-size: 14.5px; }
.chatrow-snippet { font-size: 13.5px; line-height: 1.5; }

/* Two questions, not one blob. The status chips (Все / Ждут ответа / Черновики)
   and the channel chips (Все каналы / whatsapp / telegram …) were a single
   wrapping row, so three lines of pills read as one undifferentiated cloud —
   «тут так несуразно». A hairline and a little air separate the two questions
   without adding a heading nobody needs. */
.chatpane-tabs { gap: 7px; row-gap: 7px; }
.chatpane-tabs + .chatpane-tabs {
  margin-top: 9px;
  padding-top: 9px;
  border-top: 1px solid var(--bd-line);
}

/* ── AI-СОТРУДНИКИ: ЛИНЗЫ НА РАБОТУ ОДНОГО АГЕНТА ─────────────────────────
   Простаивающая линза приглушается, а не прячется: клиент, у которого голос
   молчит, должен видеть, что голос ЕСТЬ и молчит, — иначе панель показывает
   только хорошие новости, а такой панели перестают верить. */
.ai-workforce-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 12px;
  margin-top: 12px;
}

/* «Вернул AI-агент» — фраза, которую владелец показывает клиенту как факт
   (15 сентября 2026). Одна строка над плитками, спокойный зелёный акцент. */
.ai-workforce-returns {
  margin: 10px 0 0;
  padding: 10px 14px;
  border-radius: var(--bd-r-2);
  border: 1px solid color-mix(in srgb, var(--bd-ok) 45%, transparent);
  background: color-mix(in srgb, var(--bd-ok) 10%, transparent);
  font-size: 13.5px;
  font-weight: 600;
}

.ai-workforce-card {
  border: 1px solid var(--bd-line);
  border-radius: var(--bd-r-2);
  background: var(--bd-panel-2);
  padding: 14px 15px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.ai-workforce-card h4 {
  margin: 0;
  font-size: 14px;
  letter-spacing: .01em;
}

.ai-workforce-job {
  margin: 0;
  font-size: 12px;
  color: var(--bd-ink-3);
}

.ai-workforce-figure {
  margin: 6px 0 0;
  display: flex;
  align-items: baseline;
  gap: 6px;
}

.ai-workforce-figure strong {
  font-size: 26px;
  line-height: 1.1;
  /* Цифры выстраиваются в колонку между карточками, поэтому моноширинные. */
  font-variant-numeric: tabular-nums;
}

.ai-workforce-figure span,
.ai-workforce-sub {
  font-size: 12px;
  color: var(--bd-ink-3);
}

.ai-workforce-sub { margin: 2px 0 0; }

.ai-workforce-card.idle { opacity: .72; }

.ai-workforce-idle {
  margin: 6px 0 0;
  font-size: 13px;
  color: var(--bd-ink-3);
}

.ai-workforce-jump {
  margin-top: auto;
  padding: 6px 0 0;
  align-self: flex-start;
  background: none;
  border: 0;
  color: var(--bd-brand);
  font: inherit;
  font-size: 12px;
  cursor: pointer;
  text-align: start;
}

.ai-workforce-jump:hover { text-decoration: underline; }

.ai-workforce-attention {
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--bd-line);
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px 16px;
}

.ai-workforce-attention h4 {
  margin: 0;
  font-size: 13px;
  color: var(--bd-ink-2);
}

/* ── ГОТОВЫЕ ОТРАСЛЕВЫЕ ВОРОНКИ ───────────────────────────────────────────
   Уже установленная строка приглушается, но остаётся на месте и с кнопкой:
   владельцу нужно видеть, что пакет существует и стоит, а не гадать, куда он
   делся после нажатия. */
.crm-blueprints {
  margin-bottom: 18px;
  padding-bottom: 16px;
  border-bottom: 1px solid var(--bd-line);
}

.crm-blueprint-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 10px;
}

.crm-blueprint-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 12px;
  border: 1px solid var(--bd-line);
  border-radius: var(--bd-r-2);
  background: var(--bd-panel-2);
}

.crm-blueprint-row strong { display: block; font-size: 13px; }
.crm-blueprint-row p { margin: 2px 0 4px; }
.crm-blueprint-row small { font-size: 11px; color: var(--bd-ink-3); }
.crm-blueprint-row.is-installed { opacity: .74; }
.crm-blueprint-row button { flex: 0 0 auto; }

.crm-blueprint-done { color: var(--bd-ink-2); }

/* ── ПРОГНОЗ ──────────────────────────────────────────────────────────────
   Дыры прогноза набраны тем же кеглем, что и сами числа: сделки без суммы и
   без даты закрытия — это не сноска, а работа на сегодня. */
.crm-forecast-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 12px;
  margin-top: 12px;
}

.crm-forecast-card {
  border: 1px solid var(--bd-line);
  border-radius: var(--bd-r-2);
  background: var(--bd-panel-2);
  padding: 14px 15px;
}

.crm-forecast-card h4 {
  margin: 0 0 6px;
  font-size: 13px;
  text-transform: capitalize;
}

.crm-forecast-figure { margin: 0; display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap; }
.crm-forecast-figure strong { font-size: 22px; font-variant-numeric: tabular-nums; }
.crm-forecast-figure span,
.crm-forecast-sub,
.crm-forecast-won,
.crm-forecast-gap { font-size: 12px; color: var(--bd-ink-3); }
.crm-forecast-sub { margin: 6px 0 0; }
.crm-forecast-won { margin: 2px 0 0; color: var(--bd-ok); }
.crm-forecast-gap { margin: 2px 0 0; }

.crm-forecast-attention {
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--bd-line);
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px 16px;
}

.crm-forecast-attention h4 { margin: 0; font-size: 13px; color: var(--bd-ink-2); }

/* Вероятность стадии в настройке воронки. Узкая: это два знака, а не поле
   для текста, и рядом с именем стадии она не должна отбирать ширину. */
.crm-setup-prob {
  width: 54px;
  flex: 0 0 auto;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

/* ── КОМПАНИЯ КЛИЕНТА НА КАРТОЧКЕ ─────────────────────────────────────────
   Счёт по всему клиенту, а не реквизиты. Текущая сделка помечена, чтобы
   человек видел, где он стоит среди сделок этой компании. */
.kb-company-panel {
  margin-top: 8px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  align-items: flex-start;
}

.kb-company-money {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 12px;
  font-size: 12px;
  color: var(--bd-ink-3);
  font-variant-numeric: tabular-nums;
}

.kb-company-deals { display: flex; flex-direction: column; gap: 4px; width: 100%; }

.kb-company-deal {
  display: flex;
  flex-direction: column;
  gap: 1px;
  width: 100%;
  text-align: start;
  background: none;
  border: 0;
  border-inline-start: 2px solid var(--bd-line);
  padding-block: 3px 3px; padding-inline: 8px 0;
  font: inherit;
  font-size: 12px;
  color: var(--bd-ink-2);
  cursor: pointer;
}

.kb-company-deal:hover { border-inline-start-color: var(--bd-brand); }
.kb-company-deal.is-current { border-inline-start-color: var(--bd-brand); font-weight: 600; }
.kb-company-deal small { color: var(--bd-ink-3); font-size: 11px; }

.kb-company-naming { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.kb-company-naming input {
  border: 1px solid var(--bd-line);
  border-radius: var(--bd-r-2);
  padding: 4px 9px;
  font: inherit;
  font-size: 12px;
}

/* ═══════════════════════════════════════════════════════════════════════════
   ЦВЕТ, КОТОРЫЙ ЧТО-ТО ЗНАЧИТ
   ═══════════════════════════════════════════════════════════════════════════

   Владелец, 2026-08-28: «скучно, приукрась цветами, единая гамма по всему
   дашборду, кнопки чтобы хотелось нажать».

   Одна шкала на весь продукт, и у каждого цвета есть смысл. Красить одинаковые
   строки в разные цвета «для веселья» — это шум, который через неделю
   перестают видеть; шкала, наоборот, читается без цифр и работает на каждом
   экране одинаково.

   Холодный → горячий: этим же набором окрашиваются оценки звонков, приоритеты
   и всё, где есть степень. Полутона взяты так, чтобы каждая пара соседних
   ступеней различалась и на тёмном, и на светлом фоне. */
:root {
  --scale-1: light-dark(#c2410c, #f97362);  /* холодно / плохо  */
  --scale-2: light-dark(#b45309, #fbbf5c);
  --scale-3: light-dark(#6b7280, #9aa7bd);  /* нейтрально       */
  --scale-4: light-dark(#0e7490, #38bdf8);
  --scale-5: light-dark(#15803d, #4ade80);  /* горячо / хорошо  */
}

/* ── Оценка звонков: распределение, а не список цифр ────────────────────── */
.voice-rate { display: flex; flex-direction: column; gap: 7px; margin-top: 12px; }

.voice-rate-row {
  display: grid;
  grid-template-columns: 64px minmax(0, 1fr) 34px;
  align-items: center;
  gap: 10px;
}

.voice-rate-stars { font-size: 12px; letter-spacing: 1px; color: var(--rate-ink, var(--bd-ink-3)); }
.voice-rate-count { text-align: end; font-variant-numeric: tabular-nums; font-size: 14px; }

.voice-rate-bar {
  height: 8px;
  border-radius: 999px;
  background: rgb(var(--ch-lift) / 0.06);
  overflow: hidden;
}
.voice-rate-bar i {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: var(--rate-ink, var(--bd-brand));
  /* Ноль обязан остаться нулём: полоса нулевой длины не рисуется, а не
     превращается в тонкую засечку, которую можно принять за «немного». */
  min-width: 0;
}

.voice-rate-row.rate-1 { --rate-ink: var(--scale-1); }
.voice-rate-row.rate-2 { --rate-ink: var(--scale-2); }
.voice-rate-row.rate-3 { --rate-ink: var(--scale-3); }
.voice-rate-row.rate-4 { --rate-ink: var(--scale-4); }
.voice-rate-row.rate-5 { --rate-ink: var(--scale-5); }
.voice-rate-row.rate-1 .voice-rate-count,
.voice-rate-row.rate-5 .voice-rate-count { color: var(--rate-ink); font-weight: 650; }

/* ═══════════════════════════════════════════════════════════════════════════
   КНОПКИ, КОТОРЫЕ ХОЧЕТСЯ НАЖАТЬ
   ═══════════════════════════════════════════════════════════════════════════

   Владелец, 2026-08-28: «скучные кнопки», «сделай цветные, единый цвет для всех
   блоков, примени везде».

   Одно определение на весь кабинет — не по кнопке в каждом экране. Пять правил
   ниже красят ВСЕ вторичные кнопки, все ряды вкладок и все таблетки подразделов
   сразу, потому что все они уже носят эти классы. Отдельная раскраска каждого
   экрана — это то, из-за чего интерфейс и разъезжается. */

/* Вторичная кнопка перестаёт быть серым прямоугольником: на наведении она
   подсвечивается фирменным цветом и слегка поднимается — ровно тот же жест,
   что и у главной кнопки, чтобы ряд из главной и вторичной читался как одно
   семейство. */
.ghost-button:hover, .secondary-button:hover, .compact-button:hover {
  color: var(--bd-ink);
  border-color: rgb(var(--ch-blue) / 0.55);
  background: linear-gradient(180deg, rgb(var(--ch-blue) / 0.14), rgb(var(--ch-blue) / 0.06));
  transform: translateY(-1px);
  box-shadow: 0 8px 20px -12px rgb(var(--ch-blue) / 0.9);
}
.ghost-button, .secondary-button, .compact-button {
  transition: color var(--bd-fast), border-color var(--bd-fast),
              background var(--bd-fast), transform var(--bd-fast), box-shadow var(--bd-fast);
}
.ghost-button:active, .secondary-button:active, .compact-button:active { transform: translateY(0); }

/* Активная вкладка — сплошная фирменная заливка вместо еле заметной подсветки:
   раньше «выбрано» и «не выбрано» отличались настолько слабо, что ряд читался
   как один серый блок. */
.module-tabs button.active, .module-tabs button[aria-selected="true"] {
  color: var(--rp-on-accent);
  background: linear-gradient(135deg, var(--bd-brand), var(--bd-brand-2));
  box-shadow: 0 6px 18px -10px rgb(var(--ch-blue) / 0.95);
}
.module-tabs button:not(.active):hover {
  color: var(--bd-ink);
  background: rgb(var(--ch-blue) / 0.10);
}

/* Таблетки подразделов («База знаний · Контроль качества · Анализатор …») —
   тот же язык, что и у вкладок, чтобы человек не гадал, чем один ряд кнопок
   отличается от другого. */
.pill-nav button, .subnav-pill, .agent-subnav button {
  transition: color var(--bd-fast), border-color var(--bd-fast),
              background var(--bd-fast), transform var(--bd-fast);
}
.pill-nav button:hover, .subnav-pill:hover, .agent-subnav button:hover {
  border-color: rgb(var(--ch-blue) / 0.5);
  background: rgb(var(--ch-blue) / 0.10);
  transform: translateY(-1px);
}
.pill-nav button.active, .subnav-pill.is-active, .agent-subnav button.active {
  color: var(--rp-on-accent);
  background: linear-gradient(135deg, var(--bd-brand), var(--bd-brand-2));
  border-color: transparent;
}

/* ── «AI-агенты»: страница объясняет, а не выкладывает товар ───────────── */
.agent-intro { display: flex; flex-direction: column; gap: 14px; }
.agent-intro-head h2 { margin: 0 0 6px; font-size: 20px; }
.agent-intro-head p { margin: 0; color: var(--bd-ink-3); max-width: 76ch; }

.agent-intro-facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 10px;
}

.agent-fact {
  display: flex; flex-direction: column; gap: 2px;
  padding: 12px 14px;
  border: 1px solid var(--bd-line);
  border-inline-start: 3px solid var(--fact-ink, var(--bd-brand));
  border-radius: var(--bd-r-2);
  background: var(--bd-panel-2);
  text-align: start;
}
.agent-fact strong { font-size: 22px; line-height: 1.1; font-variant-numeric: tabular-nums; color: var(--fact-ink, inherit); }
.agent-fact span { font-size: 12px; color: var(--bd-ink-3); }

/* Та же шкала, что и у оценок звонков: у цвета один смысл на весь продукт. */
.agent-fact.scale-hot  { --fact-ink: var(--scale-5); }
.agent-fact.scale-warm { --fact-ink: var(--scale-4); }
.agent-fact.scale-good { --fact-ink: var(--scale-5); }
.agent-fact.scale-cold { --fact-ink: var(--scale-1); }

.agent-fact-act { cursor: pointer; font: inherit; }
.agent-fact-act:hover { border-color: var(--fact-ink); }

.agent-intro-empty { margin: 0; color: var(--bd-ink-2); }

.agent-steps { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }

.agent-step {
  display: grid;
  grid-template-columns: 28px minmax(0, 1fr) auto;
  align-items: center;
  gap: 12px;
  padding: 11px 13px;
  border: 1px solid var(--bd-line);
  border-radius: var(--bd-r-2);
  background: var(--bd-panel-2);
}
.agent-step strong { display: block; font-size: 14px; }
.agent-step p { margin: 2px 0 0; font-size: 12.5px; color: var(--bd-ink-3); }

.agent-step-num {
  display: grid; place-items: center;
  width: 26px; height: 26px; border-radius: 999px;
  background: rgb(var(--ch-lift) / 0.06);
  color: var(--bd-ink-2);
  font-size: 12px; font-weight: 650;
}

/* Пройденный шаг гаснет, следующий — единственный, который выделен. Три
   одинаково ярких шага не подсказывают ничего. */
.agent-step.is-done { opacity: .62; }
.agent-step.is-done .agent-step-num { background: rgb(var(--ch-blue) / 0.18); color: var(--scale-5); }
.agent-step.is-next { border-color: rgb(var(--ch-blue) / 0.5); background: rgb(var(--ch-blue) / 0.07); }
.agent-step.is-next .agent-step-num { background: var(--bd-brand); color: var(--rp-on-accent); }

/* ── База знаний: документ правится на месте ───────────────────────────── */
.kb-doc-editor {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: -2px 0 10px;
  padding: 12px 14px;
  border: 1px solid rgb(var(--ch-blue) / 0.35);
  border-radius: var(--bd-r-2);
  background: rgb(var(--ch-blue) / 0.05);
}

.kb-doc-name {
  font: inherit;
  font-weight: 600;
  padding: 7px 10px;
  border: 1px solid var(--bd-line);
  border-radius: var(--bd-r-2);
  background: var(--rp-inset);
  color: var(--bd-ink);
}

.kb-doc-text {
  font: inherit;
  font-size: 13px;
  line-height: 1.55;
  padding: 10px 12px;
  border: 1px solid var(--bd-line);
  border-radius: var(--bd-r-2);
  background: var(--rp-inset);
  color: var(--bd-ink);
  resize: vertical;
  /* Документы базы знаний — это абзацы, а не код: перенос по словам, иначе
     длинная строка уезжает вбок и её приходится листать. */
  white-space: pre-wrap;
}

/* Часы работы: варианты, чтобы не набирать руками. */
.kb-hours-chips { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 6px; }
.kb-hours-chip {
  min-height: 26px;
  padding: 3px 10px;
  border: 1px solid var(--bd-line);
  border-radius: 999px;
  background: rgb(var(--ch-lift) / 0.03);
  color: var(--bd-ink-3);
  font: inherit;
  font-size: 11.5px;
  cursor: pointer;
  transition: color var(--bd-fast), border-color var(--bd-fast), background var(--bd-fast);
}
.kb-hours-chip:hover { color: var(--bd-ink); border-color: rgb(var(--ch-blue) / 0.5); }
.kb-hours-chip.is-on {
  color: var(--rp-on-accent);
  background: var(--bd-brand);
  border-color: transparent;
}

/* ССЫЛКА В ПЕРЕПИСКЕ ВЫГЛЯДИТ КАК ССЫЛКА.
   Одно правило на обе поверхности, где показывается разговор: карточка лида
   (.lw-text) и «Диалоги» (.chatmsg-text). Подчёркивание, а не только цвет, —
   в исходящем пузыре текст и так светлый на синем, и один цвет там не читается
   как «сюда можно нажать». Адрес длиннее пузыря переносится, а не растягивает
   его: у нас в переписке ходят ссылки с путём и параметрами. */
.msg-link {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 2px;
  text-decoration-thickness: 1px;
  text-decoration-color: color-mix(in srgb, currentColor 55%, transparent);
  overflow-wrap: anywhere;
  word-break: break-word;
}
.msg-link:hover,
.msg-link:focus-visible { text-decoration-color: currentColor; }
.msg-link:focus-visible { outline: 2px solid var(--bd-accent, #6ba8ff); outline-offset: 2px; border-radius: 3px; }

/* АДРЕС, ПРИСЛАННЫЙ КЛИЕНТОМ, — ВИДЕН, НО НЕ ОТКРЫВАЕТСЯ НАЖАТИЕМ.
   Пунктир вместо сплошной черты: глаз сразу видит, что это адрес, и что он
   не такой, как наш. Курсор — текстовый, потому что единственное, что с ним
   можно сделать, это выделить и скопировать. Почему так — в linkify.js. */
.msg-link-inert {
  text-decoration: underline dotted;
  text-underline-offset: 2px;
  text-decoration-color: color-mix(in srgb, currentColor 40%, transparent);
  cursor: text;
  overflow-wrap: anywhere;
  word-break: break-word;
  opacity: .92;
}

/* ВЕРДИКТ О ВХОДЯЩЕМ.
   Полоса на карточке лида и метка на доске. Цвет несёт смысл и только его:
   красный — фишинг (опасность), янтарный — спам (мусор), синий — «проверить»
   (сомнение, а не приговор). Ничего не скрывается и не сворачивается: карточку,
   которую нельзя увидеть, нельзя и вернуть, а классификатор ошибается. */
.lw-intake {
  display: flex; flex-direction: column; gap: 6px;
  padding: 12px 14px; margin: 0 0 12px;
  border-radius: 10px;
  border: 1px solid var(--bd-line, rgba(255,255,255,.12));
  border-inline-start-width: 3px;
  background: color-mix(in srgb, var(--bd-surface-2, #171b22) 88%, transparent);
}
.lw-intake-phishing { border-inline-start-color: #e0574f; }
.lw-intake-spam     { border-inline-start-color: #d9a441; }
.lw-intake-unclear  { border-inline-start-color: #6ba8ff; }
.lw-intake-head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.lw-intake-title { font-weight: 650; font-size: 14px; color: var(--bd-ink, #e8edf5); }
.lw-intake-who { font-size: 12px; color: var(--bd-ink-3, #8b95a5); }
.lw-intake-reason,
.lw-intake-effect { margin: 0; font-size: 13px; line-height: 1.5; color: var(--bd-ink-2, #b9c2d0); }
.lw-intake-warn {
  margin: 0; font-size: 13px; line-height: 1.5; font-weight: 600; color: #f0a19b;
}
.lw-intake button { align-self: flex-start; margin-top: 2px; }

.pk-lead-intake {
  display: inline-flex; align-items: center; gap: 5px;
  margin: 6px 0 0; padding: 2px 8px;
  border-radius: 999px; font-size: 11.5px; font-weight: 600; line-height: 1.6;
  border: 1px solid currentColor;
}
.pk-lead-intake-phishing { color: #e0574f; }
.pk-lead-intake-spam     { color: #d9a441; }
.pk-lead-intake-unclear  { color: #6ba8ff; }

/* Строка «убрано из чисел» в панели качества данных. Тон приглушённый: это
   отчёт о сделанной работе, а не задача — она не должна конкурировать за
   внимание с плитками замечаний, которые действительно надо разгребать. */
.crm-quality-filtered {
  margin: 0 0 10px;
  font-size: 12.5px;
  line-height: 1.55;
  color: var(--bd-ink-3, #8b95a5);
}

/* ── Профиль человека для распределения ───────────────────────────────────
   Раскрывающийся блок в строке графика: язык, рынок, навыки, ёмкость, вес,
   пояс, адреса и разрешённые каналы. Свёрнут по умолчанию — строка графика и
   без него плотная, а девять полей в ряд превратили бы её в анкету. */

.managers-more { margin-top: var(--bd-2); }

.managers-more > summary {
  cursor: pointer;
  font-size: 12px;
  color: var(--bd-ink-2);
  padding: 4px 0;
  list-style: none;
}
.managers-more > summary::-webkit-details-marker { display: none; }
.managers-more > summary::before { content: "▸ "; }
.managers-more[open] > summary::before { content: "▾ "; }
.managers-more > summary:hover { color: var(--bd-ink); }

.managers-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: var(--bd-2);
  margin-top: var(--bd-2);
}

.managers-field { display: grid; gap: 4px; min-width: 0; }

.managers-field-label {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--bd-ink-3, var(--bd-ink-2));
}

.managers-field input {
  padding: 8px 10px;
  border: 1px solid var(--bd-line);
  border-radius: var(--bd-r-sm);
  background: rgb(var(--ch-lift) / 0.03);
  color: var(--bd-ink);
  font: inherit;
  font-size: 13px;
  min-width: 0;
}

/* Подпись под полем — требование раздела 11 мастер-промпта: экран объясняется
   сам. Мельче основного текста и не кричит цветом. */
.managers-field-hint {
  font-size: 11px;
  line-height: 1.35;
  color: var(--bd-ink-2);
  opacity: 0.85;
}

.managers-channels {
  display: grid;
  gap: 6px;
  margin-top: var(--bd-3);
  padding-top: var(--bd-2);
  border-top: 1px solid var(--bd-line);
}

.managers-channel {
  display: grid;
  grid-template-columns: auto auto 1fr;
  align-items: baseline;
  gap: 8px;
  font-size: 12px;
}

.managers-channel-name { color: var(--bd-ink); }

/* Недоступный канал не прячется и не выключается: человек должен видеть, что
   он существует, и прочитать, чего не хватает. Гасим только подпись. */
.managers-channel-note { font-size: 11px; color: var(--bd-ink-2); opacity: 0.8; }
.managers-channel.is-blocked .managers-channel-note { opacity: 1; color: var(--bd-warn, var(--bd-ink-2)); }

/* ── Очереди распределения ────────────────────────────────────────────────
   Строка = команда: имя, правило выдачи, приоритет, состав галочками из
   ростера выше. Очередь ссылается на людей, а не хранит их копию. */

.queues-table { display: grid; gap: var(--bd-2); margin: var(--bd-3) 0; }

.queue-row {
  display: grid;
  gap: 6px;
  padding: var(--bd-3);
  border: 1px solid var(--bd-line);
  border-radius: var(--bd-r-md);
  background: rgb(var(--ch-lift) / 0.02);
}

.queue-row.off { opacity: 0.55; }

.queue-head {
  display: grid;
  grid-template-columns: minmax(140px, 1.6fr) minmax(150px, 1fr) 90px auto;
  gap: var(--bd-2);
  align-items: center;
}
/* На телефоне — два поля в строке (24.09.2026): 140 + 150 + 90 px минимума
   и кнопка давали строку в 470 px в карточке на 255, и «Приоритет» с
   выключателем уезжали за край экрана. */
@media (max-width: 560px) {
  .queue-head { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.queue-head input,
.queue-head select {
  padding: 8px 10px;
  border: 1px solid var(--bd-line);
  border-radius: var(--bd-r-sm);
  background: rgb(var(--ch-lift) / 0.03);
  color: var(--bd-ink);
  font: inherit;
  font-size: 13px;
  min-width: 0;
}

.queue-members {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 10px;
  padding-top: 6px;
  border-top: 1px solid var(--bd-line);
}

.queue-member {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--bd-ink);
}
