/* ═══════════════════════════════════════════════════════════════════════════
   BOARDROOM — REFERENCE PACKAGE UI
   ═══════════════════════════════════════════════════════════════════════════

   The visual system of the 16-PNG package, transferred rather than interpreted.
   Values here are read off the mockups (16 for the shell and card language, 01
   for the rail, 03 for CRM, 09/10 for tables and tabs), not invented nearby.

   WHY A THIRD STYLESHEET AND NOT AN EDIT IN PLACE. styles.css declares .sidebar
   in 13 blocks; cabinet-system.css was itself created to get the last word over
   it without rewriting 14k lines, and says so in its own header. The same
   mechanism is the honest one here: this file loads last, so it decides. What
   it does NOT do is add new blocks on top of the old look — every rule below
   replaces a legacy surface rather than decorating it.

   Rule of thumb while reading: if a legacy declaration and one of these
   disagree, this one is the package and wins.
   ═══════════════════════════════════════════════════════════════════════════ */

:root {
  /* ── palette, read off the mockups ────────────────────────────────────── */
  --rp-bg: var(--lg-surf-10);           /* content field */
  --rp-rail: var(--lg-surf-12);         /* left rail, darker than the field */
  --rp-panel: #0e1420;        /* card surface */
  --rp-panel-2: var(--lg-surf-4);      /* raised row inside a card */
  --rp-line: rgb(var(--ch-slate) / 0.13);
  --rp-line-2: rgb(var(--ch-slate) / 0.22);

  --rp-ink: #e8edf7;
  --rp-ink-2: #a7b4c8;
  --rp-ink-3: #7d8ba3;

  --rp-blue: var(--lg-blue-1);
  --rp-blue-soft: rgb(var(--ch-blue2) / 0.16);
  --rp-green: #22c55e;
  --rp-amber: #f59e0b;
  --rp-red: #ef4444;
  --rp-purple: var(--sh-violet);
  --rp-cyan: var(--lg-cyan-3);

  /* ── geometry. Flatter and tighter than the legacy system. ───────────── */
  --rp-r: 12px;
  --rp-r-sm: 8px;
  --rp-r-pill: 999px;

  /* ── rhythm ───────────────────────────────────────────────────────────── */
  --rp-1: 4px; --rp-2: 8px; --rp-3: 12px; --rp-4: 16px; --rp-5: 22px; --rp-6: 30px;

  /* MEASURED OFF THE PACKAGE, NOT CHOSEN.
     16 is 1448px wide with a 152px rail (10.5%); 01 is 1122 with 125 (11.1%).
     A fixed 176px lands on 12.2% at 1440 and 9.2% at 1920 — the closest single
     value to both references across the two widths this pass is judged at, and
     wide enough for the two-line labels («Управление AI-агентами») the mockup
     itself wraps. The old 232px was 16% at 1440: a rail half again as wide as
     any reference, which is where a lot of the "too airy" reading came from. */
  --rp-rail-w: 176px;

  /* The lead drawer's width, declared once because two things depend on it:
     the panel itself and the page padding that makes room for it. */
  --kb-drawer-w: min(420px, max(330px, 22vw), 94vw);
}

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

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

.app-shell {
  grid-template-columns: var(--rp-rail-w) minmax(0, 1fr);
  background: var(--rp-bg);
}
.app-shell.rail-collapsed { grid-template-columns: 72px minmax(0, 1fr); }

/* ── the rail ─────────────────────────────────────────────────────────────
   Flat, dark, no gradient and no drop shadow: in the package the rail reads as
   a quieter plane than the content, which is the opposite of the legacy rail's
   glowing blue-tinted panel. */
.sidebar {
  gap: var(--rp-3);
  padding: 18px var(--rp-3) var(--rp-3);
  background: var(--rp-rail);
  border-inline-end: 1px solid var(--rp-line);
  box-shadow: none;
}

/* THE RAIL BRAND IS THE MARK, NOTHING ELSE.
   16 and 01 both put a single hexagon mark at the top of the rail and no
   wordmark — the product name lives in the top bar (02), where this build
   already renders it. Keeping both meant the name appeared twice on every
   screen, once inside a 176px column that had to clip it. */
.brand {
  justify-content: flex-start;
  min-height: 54px;
  padding: 0 2px;
  margin-bottom: 0;
  background: none;
  border: 0;
}
.brand-mark {
  width: 44px; height: 44px;
  background: none;
  border: 0;
  box-shadow: none;
}
.sidebar > .brand .brand-copy { display: none; }
.brand-copy strong { font-size: 12.5px; font-weight: 640; letter-spacing: -0.01em; }
.brand-copy span { font-size: 10.5px; color: var(--rp-ink-3); }

.nav-list { display: flex; flex-direction: column; }
.nav-section { display: flex; flex-direction: column; gap: 2px; }
.nav-section + .nav-section { margin-top: 14px; }

/* THE HEADINGS WERE ALWAYS IN THE DOM. main.js has emitted .nav-section-label
   for every group since the rail was written; this rule said display:none, so
   ten items read as one undivided stack and the grouping was invisible. Small,
   quiet and uppercase — a heading has to be findable without competing with
   the items under it. */
.nav-section-label {
  display: block;
  margin-block: 0 6px; margin-inline: 9px 0;
  font-size: 10px;
  letter-spacing: .1em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--rp-nav-label);
}

/* Пункт стал <a> ради «Открыть в новой вкладке» (см. main.js). Ссылка
   приносит с собой подчёркивание и наследует цвет ссылки, а кнопка не
   приносила ни того, ни другого — эти две строки возвращают ровно тот вид,
   что был, и ничего больше. cursor: pointer у ссылки без href был бы лишним,
   но href тут есть всегда. */
.nav-item { text-decoration: none; }
.nav-item:hover, .nav-item:focus-visible { text-decoration: none; }

.nav-item {
  min-height: 36px;
  gap: 10px;
  padding: 0 9px;
  border-radius: 9px;
  color: var(--rp-ink-2);
  font-size: 13px;
  font-weight: 500;
  border: 1px solid transparent;
  background: none;
  transition: background 140ms ease, color 140ms ease, border-color 140ms ease;
}
.nav-item:hover {
  transform: none;
  background: rgb(var(--ch-lift) / 0.035);
  color: var(--rp-ink);
  border-color: transparent;
}
/* Active is a SOLID blue plate, not a translucent wash. Read off 01 at 2.6×:
   the pill is filled, its border is a lighter blue, and the glyph inside it is
   white — the item reads as selected from across the room, which a 15%-alpha
   tint over a near-black rail does not. */
.nav-item.active {
  background: linear-gradient(180deg, var(--lg-blue-1), #2a5fe0);
  border-color: rgba(130, 175, 255, 0.5);
  /* One step calmer than it was. The plate still reads as selected from across
     the room; the halo no longer bleeds into the two items either side. */
  box-shadow: 0 3px 12px rgb(var(--ch-blue2) / 0.22);
  color: var(--rp-on-accent);
  font-weight: 600;
}
.nav-item.active:hover { background: linear-gradient(180deg, #3b78ff, #2c62e8); }

/* NO ICON PLATE. In every rail the package draws — 01, 02, 16 — the glyph is a
   bare 1.5px line icon sitting on the rail, not a bordered chip. The chip was
   this build's own invention and it is what made ten items read as ten buttons
   stacked in a box. */
.nav-item .nav-icon {
  width: 22px; height: 22px;
  border-radius: 0;
  background: none;
  border: 0;
  color: var(--rp-ink-2);
}
.nav-item.active .nav-icon {
  background: none;
  border: 0;
  color: var(--rp-ink-max);
}
.nav-item .nav-icon[class*="nav-icon-"]::before { width: 19px; height: 19px; }

/* Any key without its own glyph masks to nothing rather than falling back to a
   two-letter code — the letter codes are exactly what this pass removes.
   Declared as the default at the SAME specificity as a per-key rule and above
   them in the file, so a per-key glyph always wins on order alone. Adding an
   icon is one rule, with no :not() chain to remember to update. */
[class*="nav-icon-"] {
  --nav-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='1' height='1'%3E%3C/svg%3E");
}
.nav-item .nav-icon[class*="nav-icon-"] {
  font-size: 0;
  line-height: 0;
}
.nav-item .nav-icon[class*="nav-icon-"]::before { display: block; }

/* The same mask machinery for the action-centre tiles of 16, which use the
   module's own mark. Declared here rather than duplicated per tile so a glyph
   is defined once and rendered wherever a module is named. */
.rp-tile-glyph[class*="nav-icon-"]::before {
  content: "";
  display: block;
  width: 17px; height: 17px;
  background-color: currentColor;
  -webkit-mask: var(--nav-glyph) center / contain no-repeat;
  mask: var(--nav-glyph) center / contain no-repeat;
}

/* ── the ten module glyphs, traced off 16 ────────────────────────────────── */
.nav-icon-dashboard {
  --nav-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3.6 10.4 12 3.6l8.4 6.8V20a.8.8 0 0 1-.8.8h-4.4v-6.2H8.8v6.2H4.4a.8.8 0 0 1-.8-.8z'/%3E%3C/svg%3E");
}
/* CRM и лиды — the boxed-people mark of 16, not a filter funnel. */
.nav-icon-leads {
  --nav-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3.4' y='3.4' width='17.2' height='17.2' rx='4'/%3E%3Ccircle cx='12' cy='10.2' r='2.3'/%3E%3Cpath d='M7.9 17.1c.6-2.2 2.2-3.3 4.1-3.3s3.5 1.1 4.1 3.3'/%3E%3C/svg%3E");
  font-size: 0;
  letter-spacing: 0;
}
.nav-icon-ai-agent {
  --nav-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3.4' y='3.4' width='17.2' height='17.2' rx='4'/%3E%3Cpath d='M8.4 15.2 11 8.8l2.6 6.4M9.3 13.3h3.4M16.2 8.8v6.4'/%3E%3C/svg%3E");
}
.nav-icon-conversations {
  --nav-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20.4 12.4c0 3.9-3.8 7-8.4 7-1 0-2-.15-2.9-.43L4 20.6l1.7-3.6A6.6 6.6 0 0 1 3.6 12.4c0-3.9 3.8-7 8.4-7s8.4 3.1 8.4 7z'/%3E%3Ccircle cx='8.6' cy='12.3' r='.95' fill='%23fff' stroke='none'/%3E%3Ccircle cx='12' cy='12.3' r='.95' fill='%23fff' stroke='none'/%3E%3Ccircle cx='15.4' cy='12.3' r='.95' fill='%23fff' stroke='none'/%3E%3C/svg%3E");
}
.nav-icon-voice {
  --nav-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6.3 3.9c1 0 1.6.5 2 1.5l.9 2.2c.3.8.1 1.5-.6 2l-1 .8a11.4 11.4 0 0 0 5 5l.8-1c.5-.7 1.2-.9 2-.6l2.2.9c1 .4 1.5 1 1.5 2 0 2.3-1.9 3.4-3.9 3.4C8.3 20.1 3.9 15.7 3.9 7.8c0-2 1.1-3.9 2.4-3.9z'/%3E%3Cpath d='M15.6 5.2a4.4 4.4 0 0 1 3.2 3.2M15 8.6a1.7 1.7 0 0 1 1 1'/%3E%3C/svg%3E");
}
.nav-icon-marketing {
  --nav-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3.9 3.9v14.4a1.8 1.8 0 0 0 1.8 1.8h14.4'/%3E%3Cpath d='M7.6 16.4v-3.2M11 16.4v-5.6M14.4 16.4v-2.4'/%3E%3Cpath d='M8 10.6 12.4 7l2.6 2.2 4.4-3.8M17 5.2h2.6v2.6'/%3E%3C/svg%3E");
}
/* Медиафабрика — a camera, which is what 16 draws; the old grid glyph read as
   a table and put Media Factory in the same visual family as CRM. */
.nav-icon-media-factory {
  --nav-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3.6 8.9a2 2 0 0 1 2-2h1.9l1.3-2.1h6.4l1.3 2.1h1.9a2 2 0 0 1 2 2v8.2a2 2 0 0 1-2 2H5.6a2 2 0 0 1-2-2z'/%3E%3Ccircle cx='12' cy='12.8' r='3.3'/%3E%3C/svg%3E");
}
/* Центр действий — the lightning bolt of 16, not a document. */
.nav-icon-reports {
  --nav-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M13.6 2.8 5.2 13.4h5.6l-.4 7.8 8.4-10.6h-5.6z'/%3E%3C/svg%3E");
}
/* Интеграции — a puzzle piece (16), not the three-node graph. */
.nav-icon-integrations {
  --nav-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9.6 3.4c1.3 0 2.2.9 2.2 2 0 .5-.2.9-.2 1.2 0 .4.3.6.7.6h2.5a1 1 0 0 1 1 1v2.5c0 .4.2.7.6.7.3 0 .7-.2 1.2-.2 1.1 0 2 .9 2 2.2s-.9 2.2-2 2.2c-.5 0-.9-.2-1.2-.2-.4 0-.6.3-.6.7v2.5a1 1 0 0 1-1 1h-2.5c-.4 0-.7-.2-.7-.6 0-.3.2-.7.2-1.2 0-1.1-.9-2-2.2-2s-2.2.9-2.2 2c0 .5.2.9.2 1.2 0 .4-.3.6-.7.6H4.4a1 1 0 0 1-1-1v-2.5c0-.4.2-.7.6-.7.3 0 .7.2 1.2.2 1.1 0 2-.9 2-2.2s-.9-2.2-2-2.2c-.5 0-.9.2-1.2.2-.4 0-.6-.3-.6-.7V8.2a1 1 0 0 1 1-1h2.5c.4 0 .7-.2.7-.6 0-.3-.2-.7-.2-1.2 0-1.1.9-2 2.2-2z'/%3E%3C/svg%3E");
}
.nav-icon-settings {
  --nav-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='3.1'/%3E%3Cpath d='M19.1 14.4a1.5 1.5 0 0 0 .3 1.7l.1.1a1.8 1.8 0 1 1-2.6 2.6l-.1-.1a1.5 1.5 0 0 0-1.7-.3 1.5 1.5 0 0 0-.9 1.4v.3a1.8 1.8 0 1 1-3.6 0v-.2a1.5 1.5 0 0 0-1-1.4 1.5 1.5 0 0 0-1.7.3l-.1.1a1.8 1.8 0 1 1-2.6-2.6l.1-.1a1.5 1.5 0 0 0 .3-1.7 1.5 1.5 0 0 0-1.4-.9h-.3a1.8 1.8 0 1 1 0-3.6h.2a1.5 1.5 0 0 0 1.4-1 1.5 1.5 0 0 0-.3-1.7l-.1-.1a1.8 1.8 0 1 1 2.6-2.6l.1.1a1.5 1.5 0 0 0 1.7.3h.1a1.5 1.5 0 0 0 .9-1.4v-.3a1.8 1.8 0 1 1 3.6 0v.2a1.5 1.5 0 0 0 .9 1.4 1.5 1.5 0 0 0 1.7-.3l.1-.1a1.8 1.8 0 1 1 2.6 2.6l-.1.1a1.5 1.5 0 0 0-.3 1.7v.1a1.5 1.5 0 0 0 1.4.9h.3a1.8 1.8 0 1 1 0 3.6h-.2a1.5 1.5 0 0 0-1.4.9z'/%3E%3C/svg%3E");
}
/* Экономика платформы — кошелёк. Строка в меню была пустым квадратом
   (владелец, 14 сентября: «Platform Economics просто квадратик»): ключ
   admin-economics не имел своего знака, и правило по умолчанию выше честно
   маскировало его в ничто. */
.nav-icon-admin-economics {
  --nav-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M16.4 4.6H5.8a2 2 0 0 0-2 2v10.8a2 2 0 0 0 2 2h12.4a2 2 0 0 0 2-2V9.2a2 2 0 0 0-2-2H5.8'/%3E%3Cpath d='M16.3 11.6h3.9v3.6h-3.9a1.8 1.8 0 0 1 0-3.6z'/%3E%3C/svg%3E");
}
.nav-icon-partner {
  --nav-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M16.6 20.4v-1.8a3.6 3.6 0 0 0-3.6-3.6H6.4a3.6 3.6 0 0 0-3.6 3.6v1.8'/%3E%3Ccircle cx='9.7' cy='7.6' r='3.6'/%3E%3Cpath d='M21.2 20.4v-1.8a3.6 3.6 0 0 0-2.7-3.5M15.4 4.2a3.6 3.6 0 0 1 0 7'/%3E%3C/svg%3E");
}

/* The collapse control is not in the package's Overview rail; it stays for the
   people who use it, pinned to the very bottom so the rail's own furniture —
   workspace card and «Система и связь» — sits directly under the nav, which is
   where 16 puts it. */
.rail-toggle {
  order: 99;
  min-height: 32px;
  margin-top: auto;
  color: var(--rp-ink-3);
  background: none;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-sm);
  font-size: 11px;
}

/* ── workspace card + «Система и связь» ──────────────────────────────────
   Both are package furniture the product never had. The workspace card names
   who you are acting as; the status block answers "is anything actually
   connected" without a trip to Integrations. */
.sidebar-workspace-button {
  min-height: 50px;
  gap: 9px;
  padding: 0 9px;
  margin-top: var(--rp-3);
  border: 1px solid var(--rp-line);
  border-radius: 10px;
  background: rgb(var(--ch-lift) / 0.02);
  color: var(--rp-ink);
  font-size: 12px;
}
.sidebar-workspace-button:hover { background: rgb(var(--ch-lift) / 0.045); }
.sidebar-workspace-button .sidebar-account-avatar {
  width: 30px; height: 30px; min-width: 30px;
  border-radius: 50%;
  background: rgb(var(--ch-blue2) / 0.22);
  border: 1px solid rgb(var(--ch-blue2) / 0.4);
  color: var(--sh-blue-4);
  font-size: 12px;
  font-weight: 640;
  display: grid; place-items: center;
  flex: none;
}
.sidebar-workspace-button .brand-copy { display: grid; min-width: 0; text-align: start; }
.sidebar-workspace-button .brand-copy strong,
.sidebar-workspace-button .brand-copy span {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* «Система и связь» — 16 draws a small coloured module glyph and a plain
   coloured value, not a dot and a filled pill. The pills made four status rows
   read louder than the ten navigation items above them. */
.rail-systems { display: grid; gap: 8px; padding-top: var(--rp-3); margin-top: var(--rp-3); border-top: 1px solid var(--rp-line); }
.rail-systems-label {
  margin: 0 0 1px;
  color: var(--rp-ink-3);
  font-size: 10.5px;
  letter-spacing: 0.02em;
}
.rail-system {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 20px;
  font-size: 11px;
  color: var(--rp-ink-2);
}
.rail-system-dot {
  width: 15px; height: 15px;
  flex: none;
  border-radius: 0;
  background-color: currentColor;
  -webkit-mask: var(--rail-glyph) center / contain no-repeat;
  mask: var(--rail-glyph) center / contain no-repeat;
}
.rail-system-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--rp-ink-2); }
.rail-system-pill {
  flex: none;
  padding: 0;
  border-radius: 0;
  background: none !important;
  font-size: 10.5px;
  font-weight: 600;
  white-space: nowrap;
}
.rail-system.good { color: var(--rp-green); }
.rail-system.good .rail-system-pill { color: var(--rp-green); }
.rail-system.info { color: var(--sh-blue-2); }
.rail-system.info .rail-system-pill { color: var(--sh-blue-2); }
.rail-system.warn { color: var(--rp-amber); }
.rail-system.warn .rail-system-pill { color: var(--rp-amber); }
.rail-system.off { color: var(--rp-ink-3); }
.rail-system.off .rail-system-pill { color: var(--rp-ink-3); }

.rail-system-tel {
  --rail-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6.3 3.9c1 0 1.6.5 2 1.5l.9 2.2c.3.8.1 1.5-.6 2l-1 .8a11.4 11.4 0 0 0 5 5l.8-1c.5-.7 1.2-.9 2-.6l2.2.9c1 .4 1.5 1 1.5 2 0 2.3-1.9 3.4-3.9 3.4C8.3 20.1 3.9 15.7 3.9 7.8c0-2 1.1-3.9 2.4-3.9z'/%3E%3C/svg%3E");
}
.rail-system-ai {
  --rail-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20.4 12.4c0 3.9-3.8 7-8.4 7-1 0-2-.15-2.9-.43L4 20.6l1.7-3.6A6.6 6.6 0 0 1 3.6 12.4c0-3.9 3.8-7 8.4-7s8.4 3.1 8.4 7z'/%3E%3C/svg%3E");
}
.rail-system-crm {
  --rail-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3.4' y='3.4' width='17.2' height='17.2' rx='4'/%3E%3Cpath d='M9 12h6M12 9v6'/%3E%3C/svg%3E");
}
.rail-system-int {
  --rail-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='6.2' cy='6.2' r='2.4'/%3E%3Ccircle cx='17.8' cy='6.2' r='2.4'/%3E%3Ccircle cx='12' cy='17.8' r='2.4'/%3E%3Cpath d='M8.6 6.2h6.8M7.4 8.3l3.5 7.3M16.6 8.3l-3.5 7.3'/%3E%3C/svg%3E");
}

/* The identity block goes: the workspace card above says who you are, and
   sign-out, language and billing all live in the header profile menu. Nothing
   is lost with it.

   The other two rail blocks STAY. They are the only way to reach the launch
   wizard, the registrations console and support — hiding them to match a
   picture would delete working capability, which this redesign is not allowed
   to do. They are restyled to the package's quieter voice instead, and the
   package has its own «Справочный центр →» rail footer on 03, so a support
   entry belongs there anyway. */
.sidebar-account { display: none; }

/* THE RAIL ENDS WHERE THE PACKAGE ENDS IT.
   01 and 16 both close the rail with the workspace card and «Система и связь»,
   and 02 adds «Свернуть меню» below them. Nothing else is in any reference:
   no launch wizard, no plan link, no UTILITIES caption, no EN/RU pair, no
   support block. An earlier pass kept them on the grounds that deleting
   working capability to match a picture is not on the table — correct, and the
   answer is to rehome rather than to keep. The wizard is now the first item of
   the profile menu; plan, language, support and sign-out were already there.
   So nothing is lost and the rail matches. */
.sidebar-secondary-actions,
.sidebar-support,
.sidebar-utility-row,
.sidebar-utility { display: none; }

/* «📘 Руководство» — first, small, in the page footer (owner, 13 Sep 2026:
   «аккуратно слева мелким шрифтом»). The rail was the first home, but in the
   collapsed rail it landed below the fold. Same voice as «Настроить». */
.rp-footer-guide { text-decoration: none; }

/* Long labels wrap onto a second line the way «Управление AI-агентами» does in
   01, instead of being clipped with an ellipsis. */
.nav-item { align-items: center; }
.nav-item > span:not([class*="nav-icon"]) {
  white-space: normal;
  line-height: 1.25;
  overflow: visible;
  text-overflow: clip;
}

/* The styling that used to live here — for .sidebar-secondary-actions,
   .sidebar-support, .sidebar-contact and .sidebar-utility — is deleted with
   the blocks themselves. It was declared AFTER the hide rule above and so
   silently un-hid them: the rail still shipped «Launch wizard» and «Plan»
   under a rule that said display:none. Dead styling for hidden markup is
   how that happens, so it goes rather than being out-specified. */
.rail-collapsed .rail-systems,
.rail-collapsed .sidebar-support,
.rail-collapsed .sidebar-secondary-actions span:not([class*="nav-icon"]),
.rail-collapsed .sidebar-workspace-button .brand-copy { display: none; }

/* ═══ TOP OF PAGE ════════════════════════════════════════════════════════ */

.workspace { padding: var(--rp-5) var(--rp-6) var(--rp-6); background: var(--rp-bg); }

/* ── the global top bar (02) ──────────────────────────────────────────────
   It spans the content column edge to edge, so it cancels the workspace's own
   padding with a negative margin rather than the workspace being restructured
   into a padded inner wrapper — the same result, without touching the layout
   every page already renders into. Sticky so search and the account stay
   reachable down a long board. */
.rp-topbar {
  position: sticky;
  top: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  gap: var(--rp-3);
  /* «верхние части... давай уменьшим... нижнее пространство станет больше»,
     2026-08-21: was 60px, then 50px. Every control inside (search, agent pill,
     account chip) shrank to match so nothing looks stretched inside a shorter
     bar. */
  min-height: 44px;
  /* Left/right used to cancel .workspace's fat legacy padding (56/44) to reach
     the frame edge; .workspace is 24/12 everywhere now (2026-08-21 — see its
     own comment), which is narrower than this bar would need to cancel, so
     the two per-route overrides that used to zero this out (CRM, the lead
     workspace) are gone with it and this is just 0 for everyone. Top is
     unchanged: --rp-5 exactly matches .workspace's own new padding-top,
     so it still lands flush with zero residual gap. */
  margin: calc(var(--rp-5) * -1) 0 var(--rp-5);
  padding: 0 var(--rp-6);
  background: var(--rp-topbar-bg);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--rp-line);
}

.rp-topbar-brand {
  flex: none;
  padding: 0;
  border: 0;
  background: none;
  color: var(--rp-ink-max);
  font-size: 15px;
  font-weight: 660;
  letter-spacing: -0.02em;
  cursor: pointer;
  white-space: nowrap;
}
.rp-topbar-brand:hover { color: var(--lw-ink-bright); }

/* Search sits centred and takes the slack, as in the mockup. */
.rp-topbar-search { position: relative; flex: 1 1 auto; display: flex; justify-content: center; min-width: 0; }

.rp-search-control {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  max-width: 380px;
  min-height: 28px;
  padding: 0 10px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-sm);
  background: rgb(var(--ch-lift) / 0.03);
  color: var(--rp-ink-3);
  font-size: 12.5px;
  cursor: pointer;
  text-align: start;
}
.rp-search-control:hover, .rp-search-control.open { border-color: var(--rp-line-2); color: var(--rp-ink-2); }
.rp-search-glyph {
  flex: none; width: 13px; height: 13px; border-radius: 50%;
  border: 1.6px solid currentColor;
  position: relative;
}
.rp-search-glyph::after {
  content: ""; position: absolute; inset-inline-end: -4px; bottom: -3px;
  width: 5px; height: 1.6px; background: currentColor;
  transform: rotate(45deg);
}
.rp-search-text { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rp-search-kbd {
  flex: none;
  padding: 2px 6px;
  border: 1px solid var(--rp-line);
  border-radius: 5px;
  background: rgb(var(--ch-lift) / 0.04);
  color: var(--rp-ink-3);
  font-size: 10.5px;
  font-family: inherit;
}

/* The live agent pill — a real reading of the runtime feed, not decoration. */
.rp-agent-pill {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-height: 24px;
  padding: 0 10px;
  border-radius: var(--rp-r-pill);
  font-size: 11.5px;
  font-weight: 600;
  white-space: nowrap;
}
.rp-agent-dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; flex: none; }
.rp-agent-pill.good { color: var(--rp-green); background: rgb(var(--ch-green) / 0.13); }
.rp-agent-pill.warn { color: var(--rp-amber); background: rgb(var(--ch-amber) / 0.13); }
.rp-agent-pill.info { color: var(--sh-blue-3); background: rgb(var(--ch-blue2) / 0.15); }
.rp-agent-pill.off { color: var(--rp-ink-3); background: rgb(var(--ch-slate) / 0.11); }

.rp-topbar-bell { position: relative; flex: none; }
.rp-bell {
  display: grid;
  place-items: center;
  /* min-height too: a legacy `button { min-height: 40px }` otherwise stretches
     this to 40 and the bell stops being square next to the search control. */
  width: 28px; height: 28px; min-height: 28px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-sm);
  background: rgb(var(--ch-lift) / 0.03);
  color: var(--rp-ink-2);
  cursor: pointer;
}
.rp-bell:hover, .rp-bell.open { border-color: var(--rp-line-2); color: var(--rp-ink); }
/* Drawn rather than an icon font: a bell body plus a clapper. */
.rp-bell-glyph {
  position: relative;
  width: 13px; height: 13px;
  border: 1.6px solid currentColor;
  border-radius: 6px 6px 3px 3px;
  border-bottom-color: transparent;
}
.rp-bell-glyph::before {
  content: ""; position: absolute; inset-inline-start: -3px; inset-inline-end: -3px; bottom: -1.6px;
  height: 1.6px; background: currentColor;
}
.rp-bell-glyph::after {
  content: ""; position: absolute; inset-inline-start: 50%; bottom: -5px;
  width: 4px; height: 4px; margin-inline-start: -2px;
  border-radius: 50%; background: currentColor;
}
/* Filled imperatively by paintNotificationBell. Empty text = not shown; the
   element itself always exists so an id is always available to paint into. */
.rp-bell-badge {
  position: absolute; top: -4px; inset-inline-end: -4px;
  min-width: 16px; height: 16px; padding: 0 4px;
  border-radius: 999px;
  font-size: 10px; font-weight: 700; line-height: 16px; text-align: center;
  color: #fff; background: var(--rp-red, #d8534f);
  display: none;
}
.rp-bell-badge.on { display: block; }

.rp-bell-body { display: grid; max-height: 320px; overflow-y: auto; border-top: 1px solid var(--rp-line); }
.rp-bell-row { display: grid; gap: 3px; padding: var(--rp-3, 10px) var(--rp-4, 16px); border-bottom: 1px solid var(--rp-line); }
.rp-bell-row:last-child { border-bottom: none; }
.rp-bell-row.clickable { cursor: pointer; }
.rp-bell-row.clickable:hover { background: rgb(var(--ch-lift) / 0.05); }
.rp-bell-row-main { display: flex; align-items: center; justify-content: space-between; gap: var(--rp-3, 10px); }
.rp-bell-row-label { font-size: 13.5px; color: var(--rp-ink); }
.rp-bell-row-count { font-size: 13.5px; font-weight: 700; color: var(--rp-ink-3); }
.rp-bell-row-count.has-items { color: var(--rp-red, #d8534f); }
.rp-bell-row-tag { font-size: 11.5px; text-transform: uppercase; letter-spacing: 0.03em; color: var(--rp-ink-3); }
.rp-bell-row-detail { margin: 0; font-size: 12.5px; line-height: 1.45; color: var(--rp-ink-3); }

/* GRAPHS / STATISTICS / RECOMMENDATIONS — added to the bell 2026-08-25, per
   the owner's note asking for exactly that in this dropdown. Both sections
   sit above the existing per-category rows (renderBellStatsSection /
   renderBellRecommendations in main.js) and share this popover's width —
   min(360px, calc(100vw - 32px)) from .rp-pop above — so the chart's own
   viewBox (180x54) is designed to sit comfortably inside that, never wider. */
.rp-bell-stats { padding: var(--rp-3, 10px) var(--rp-4, 16px); border-bottom: 1px solid var(--rp-line); }
.rp-bell-stats-title {
  margin: 0 0 8px; font-size: 11.5px; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.03em; color: var(--rp-ink-3);
}
.rp-bell-chart { display: flex; flex-direction: column; align-items: center; gap: 2px; }
.rp-bell-chart-svg { width: 100%; max-width: 220px; height: 54px; }
.rp-bell-chart-bar { fill: var(--rp-blue, #2f7bff); fill-opacity: 0.55; }
.rp-bell-chart-label { font-size: 8px; fill: var(--rp-ink-3); }
.rp-bell-chart-count { font-size: 8.5px; font-weight: 700; fill: var(--rp-ink); }
.rp-bell-chart-caption { margin: 2px 0 0; font-size: 12px; color: var(--rp-ink-3); }
.rp-bell-tiles { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px; margin-top: 10px; }
.rp-bell-tile {
  display: flex; flex-direction: column; gap: 2px; padding: 8px 10px;
  border-radius: 10px; background: rgb(var(--ch-lift) / .05); border: 1px solid var(--rp-line);
}
.rp-bell-tile strong { font-size: 15px; color: var(--rp-ink); }
.rp-bell-tile span { font-size: 12px; color: var(--rp-ink-3); }
.rp-bell-recos { padding: var(--rp-3, 10px) var(--rp-4, 16px); border-bottom: 1px solid var(--rp-line); }
.rp-bell-reco-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.rp-bell-reco-row {
  font-size: 13px; line-height: 1.45; color: var(--rp-ink); padding: 7px 9px;
  border-radius: 8px; background: rgb(var(--ch-lift) / .04);
}
.rp-bell-reco-row.clickable { cursor: pointer; }
.rp-bell-reco-row.clickable:hover { background: rgb(var(--ch-lift) / .08); }

/* "Написали и не получили ответа" — moved off the CRM page and in here
   2026-08-22 (see notificationCenterSources' "silence" entry). The bell is
   min(360px, ...) wide, a fraction of the page-width banner this replaced,
   so the row layout is stacked rather than the old four-column grid. */
.rp-bell-row-expandable .rp-bell-row-main::after {
  content: "▸"; margin-inline-start: 6px; color: var(--rp-ink-3); font-size: 10px;
}
.rp-bell-row-expandable.is-open .rp-bell-row-main::after { content: "▾"; }
.rp-bell-silence-list { list-style: none; margin: 0; padding: 0 var(--rp-4, 16px) 6px; }
.rp-bell-silence-row {
  display: flex; flex-direction: column; gap: 2px;
  padding: 8px 0; border-top: 1px solid var(--rp-line);
}
.rp-bell-silence-row:first-child { border-top: none; }
.rp-bell-silence-who { display: flex; align-items: baseline; gap: 6px; min-width: 0; }
.rp-bell-silence-who strong {
  color: var(--rp-ink); font-size: 12.5px; font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.rp-bell-silence-chan { color: var(--rp-ink-3); font-size: 10.5px; }
.rp-bell-silence-why { color: var(--rp-ink-3); font-size: 11px; line-height: 1.4; }
.rp-bell-silence-shut { color: var(--lw-warm); }
.rp-bell-silence-age { color: var(--rp-ink-3); font-size: 11px; }
.rp-bell-silence-open {
  align-self: flex-start; margin-top: 2px; padding: 3px 10px; border-radius: 8px;
  cursor: pointer; border: 1px solid rgb(var(--ch-red3) / .38);
  background: transparent; color: var(--t451, #d8534f); font-size: 11px;
}
.rp-bell-silence-open:hover { background: rgb(var(--ch-red3) / .14); }
.rp-bell-silence-nolead { color: var(--rp-ink-3); font-size: 11px; }

/* Shared popover shell for both honest-state panels. */
.rp-pop {
  position: absolute;
  top: calc(100% + 8px);
  z-index: 60;
  width: min(360px, calc(100vw - 32px));
  border: 1px solid var(--rp-line-2);
  border-radius: var(--rp-r);
  background: var(--rp-panel);
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.5);
  overflow: hidden;
}
/* rtl-exempt: центрирование left: 50% + translateX(-50%) симметрично и в RTL даёт тот же центр; inset-inline-start: 50% с тем же сдвигом в RTL уезжает на половину ширины (подсказки и окна в арабском, 15.09.2026). */
.rp-pop-search { left: 50%; transform: translateX(-50%); }
/* ЦЕНТР УВЕДОМЛЕНИЙ ШИРЕ ОСТАЛЬНЫХ ВЫПАДАЮЩИХ ПАНЕЛЕЙ.
   Владелец 30 августа: «текст мелкий и сдвинут вправо к борту». Замерено на
   странице: панель 360px, а надписи внутри — 10.5–12.5px, то есть заметно
   мельче всего остального в продукте. Размеры подняты выше по файлу; здесь
   вторая половина — ширина. При 400px тот же текст занимает меньше строк и
   тело панели уходит левее от правого борта, из-за которого она и читалась
   прижатой. Верхний предел по-прежнему держит окно: на узком экране
   работает calc(100vw - 32px), а не 400. */
.rp-pop-bell { inset-inline-end: 0; width: min(400px, calc(100vw - 32px)); }
.rp-pop .rp-empty { padding: var(--rp-4); }
.rp-pop-links { display: grid; border-top: 1px solid var(--rp-line); }
.rp-pop-links button {
  min-height: 40px;
  padding: 0 var(--rp-4);
  border: 0;
  border-bottom: 1px solid var(--rp-line);
  background: none;
  color: var(--sh-blue-2);
  font-size: 12.5px;
  font-weight: 550;
  text-align: start;
  cursor: pointer;
}
.rp-pop-links button:last-child { border-bottom: 0; }
.rp-pop-links button:hover { background: rgb(var(--ch-blue2) / 0.08); color: var(--sh-blue-1); }

/* ── Global search ────────────────────────────────────────────────────────
   The panel is wider than the bell's because it holds rows of results rather
   than a paragraph, and its result list is the ONE scrolling box inside it —
   the panel itself never scrolls, so the page keeps its single vertical
   scroll container. */
.rp-pop-search { width: min(560px, calc(100vw - 32px)); }
.gs-field { padding: var(--rp-3, 12px); border-bottom: 1px solid var(--rp-line); }
.gs-input {
  width: 100%;
  box-sizing: border-box;
  min-height: 38px;
  padding: 0 12px;
  border: 1px solid var(--rp-line-2);
  border-radius: 10px;
  background: rgb(var(--ch-lift) / 0.03);
  color: var(--lw-ink);
  font: inherit;
  font-size: 13.5px;
}
.gs-input:focus { outline: none; border-color: rgb(var(--ch-accent) / 0.55); }
/* WebKit draws its own clear button on type=search and it sits on top of the
   text at this height. */
.gs-input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }
.gs-results { max-height: min(56vh, 420px); overflow-y: auto; overscroll-behavior: contain; }
.gs-group {
  padding: 10px var(--rp-4, 16px) 4px;
  color: var(--u16);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.gs-row {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  width: 100%;
  padding: 8px var(--rp-4, 16px);
  border: 0;
  background: none;
  color: var(--t368);
  font: inherit;
  text-align: start;
  cursor: pointer;
}
.gs-row:hover, .gs-row.is-on { background: rgb(var(--ch-blue2) / 0.12); }
.gs-row.is-on { box-shadow: inset 2px 0 0 var(--pk-blue); }
.gs-glyph { flex: 0 0 auto; line-height: 1.4; }
/* min-width:0 is what lets the ellipsis below actually apply — without it the
   flex child refuses to shrink and the row pushes the panel wider. */
.gs-text { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1 1 auto; }
.gs-text strong { font-size: 13px; font-weight: 600; color: var(--lw-ink); }
.gs-text small,
.gs-text strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gs-text small { font-size: 11.5px; color: var(--lg-ink-4); }
.gs-panel .rp-empty { padding: var(--rp-4, 16px); }

/* The account chip of 02 and 16: avatar, workspace name, acting role, caret —
   not a bare initial. The name is real session data; when the session does not
   name the workspace the block simply does not render. */
.rp-topbar .profile-trigger {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 28px;
  padding-block: 0 0; padding-inline: 4px 8px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-sm);
  background: rgb(var(--ch-lift) / 0.02);
}
.rp-topbar .profile-trigger:hover, .rp-topbar .profile-trigger.open { border-color: var(--rp-line-2); }
.rp-topbar .profile-avatar {
  width: 24px; height: 24px; min-width: 24px;
  border-radius: 50%;
  background: rgb(var(--ch-blue2) / 0.22);
  border: 1px solid rgb(var(--ch-blue2) / 0.4);
  color: var(--sh-blue-4);
  font-size: 11.5px;
  font-weight: 640;
  display: grid; place-items: center;
}
.profile-identity-inline {
  display: grid;
  gap: 1px;
  min-width: 0;
  max-width: 178px;
  text-align: start;
  line-height: 1.2;
}
.profile-identity-inline strong {
  font-size: 12px;
  font-weight: 620;
  color: var(--rp-ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.profile-identity-inline span {
  font-size: 10.5px;
  color: var(--rp-ink-3);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.rp-topbar .profile-caret { color: var(--rp-ink-3); font-size: 10px; }
@media (max-width: 1080px) { .profile-identity-inline { display: none; } }

/* A legacy `button { min-height: 40px }` was stretching this link and, with it,
   the whole footer bar — measured 64px against the reference's 44. */
.rp-footer-link {
  padding: 0;
  min-height: 22px;
  border: 0;
  background: none;
  color: var(--sh-blue-2);
  font-size: 11.5px;
  cursor: pointer;
}
.rp-footer-link:hover { color: var(--sh-blue-1); }
.rp-footer { margin-top: var(--rp-4); }

/* The header stops being a bordered card. In the package it is simply the top
   of the page: a breadcrumb line, a large title, a subtitle, actions right. */
.workspace-header, .topbar {
  border: 0;
  border-radius: 0;
  background: none;
  backdrop-filter: none;
  box-shadow: none;
  padding: 0;
}
.workspace-header { margin-bottom: var(--rp-4); }
.topbar { align-items: flex-start; gap: var(--rp-4); margin-bottom: 0; }

.breadcrumbs {
  gap: 6px;
  margin-bottom: var(--rp-2);
  padding: 0;
  background: none;
  border: 0;
  color: var(--rp-ink-3);
  font-size: 12px;
}
.breadcrumbs button, .breadcrumbs a {
  padding: 0;
  min-height: 0;
  background: none;
  border: 0;
  color: var(--rp-ink-3);
  font-size: 12px;
}
.breadcrumbs button:hover { color: var(--rp-ink-2); }

/* ── the in-app «Назад» control, on the header's crumb line ──────────────────
   A quiet ghost square beside the breadcrumb, drawn only when the session has
   somewhere to return to. The wrapper is a flex row so the header keeps its
   own layout untouched; the button's top offset matches .pk-header's 8px
   inset (pack-design.css, shrunk 2026-08-21 from 14px, then 10px) so the
   arrow sits on the crumb's line, not above it. */
.pk-header-with-back { display: flex; align-items: flex-start; gap: 10px; }
.pk-header-with-back > .pk-header { flex: 1 1 auto; min-width: 0; }
.pk-back-button {
  flex: 0 0 auto;
  width: 26px;
  height: 26px;
  min-height: 26px;
  margin-top: 8px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 0;
  border-radius: 8px;
  background: none;
  color: var(--rp-ink-3);
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
}
.pk-back-button:hover {
  background: rgb(var(--ch-lift) / 0.06);
  color: var(--rp-ink-1);
}

/* Two cards in one dashboard tab (the learning queue above the legacy approval
   queue) without inventing a layout box: the wrapper dissolves and both stay
   direct children of .page-stack as far as the grid is concerned. */
.tab-stack-contents { display: contents; }

/* SPECIFICITY, NOT ORDER, DECIDES THIS ONE.
   styles.css declares `.topbar h1` five separate times, so the package's shell
   rules carry `.app-shell` in front of them to clear the legacy ceiling. The
   `!important` that used to be on the font-size is gone with the pin it was
   answering — `.topbar .topbar-copy h1 { … !important }` has been deleted from
   styles.css, so a normal declaration now wins on specificity alone. */
.app-shell .topbar-copy h1,
.app-shell .workspace-header h1 {
  margin: 0 0 5px;
  font-size: clamp(23px, 2.3vw, 30px);
  font-weight: 660;
  letter-spacing: -0.025em;
  line-height: 1.12;
  color: var(--rp-ink-max);
}
.app-shell .page-subtitle { margin: 0; color: var(--rp-ink-2); font-size: 13px; line-height: 1.5; }

.header-actions { gap: var(--rp-2); align-items: center; }

/* «Режим работы» — the caption 16 puts over the access switch. */
/* justify-items:end kept the track at its natural width, so inside the account
   menu «Клиент · Партнёр · Администратор» ran past the panel edge. Stretch to
   the container and let the three segments share it. */
.rp-viewmode { display: grid; justify-items: stretch; gap: 5px; min-width: 0; }
.rp-viewmode .rp-viewmode-label { justify-self: end; }
.rp-viewmode-label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--rp-ink-3);
  font-size: 11.5px;
}

/* View-mode switch: one pill-shaped track, active segment filled blue. */
.view-mode-switcher {
  gap: 0;
  padding: 3px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-sm);
  background: rgb(var(--ch-lift) / 0.02);
  max-width: 100%;
  min-width: 0;
  box-sizing: border-box;
}
.view-mode-switcher button {
  /* Natural widths, not equal thirds: `1 1 0` divided the track evenly, so the
     longest label («Администратор») spilled past its own active pill while the
     short ones sat in slack. Each segment now takes the width its word needs. */
  flex: 1 1 auto;
  min-width: 0;
  min-height: 32px;
  padding: 0 9px;
  border: 0;
  border-radius: 6px;
  background: none;
  color: var(--rp-ink-2);
  font-size: 12px;
  font-weight: 500;
  white-space: nowrap;
}
.view-mode-switcher button.active,
.view-mode-switcher button[aria-pressed="true"] {
  background: var(--rp-blue);
  color: var(--rp-on-accent);
  font-weight: 600;
}

/* ═══ PRIMITIVES ═════════════════════════════════════════════════════════ */

/* !important IS THE ONLY THING THAT WORKS HERE, AND IT IS NOT A SHORTCUT.
   styles.css does not merely declare the old look, it defends it: measured on
   the running page, `.control-card { box-shadow: … !important }` and
   `.topbar .topbar-copy h1 { font-size: 1.15rem !important }`. An `!important`
   declaration outranks every normal one regardless of specificity or load
   order, so a stylesheet that "loads last" does not replace the visual system —
   it only appears to until you measure. Both properties below were measured
   still rendering legacy values with this file loaded and parsed.

   These flags are therefore scoped to exactly the properties the old sheet
   pins, and each one is removed as its legacy declaration is deleted in the
   clean-up phase. */
.control-card, .xo-card, .module-header {
  padding: 13px var(--rp-4);
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r);
  background: var(--rp-panel);
  box-shadow: none !important;
  transition: border-color 140ms ease;
}
.control-card:hover, .xo-card:hover { transform: none; border-color: var(--rp-line-2); }

.module-header {
  grid-template-columns: minmax(0, 1fr) auto;
  gap: var(--rp-4);
  background: var(--rp-panel);
}
.module-header h2 { margin: 0 0 5px; font-size: 19px; font-weight: 640; letter-spacing: -0.02em; }
.module-header p { font-size: 12.5px; color: var(--rp-ink-2); }
.module-header .eyebrow {
  color: var(--rp-ink-3);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}

.page-stack { gap: var(--rp-3); }

/* Buttons */
.primary-button {
  min-height: 36px;
  padding: 0 14px;
  border-radius: var(--rp-r-sm);
  background: var(--rp-blue);
  border: 1px solid var(--rp-blue);
  box-shadow: none;
  font-size: 12.5px;
  font-weight: 600;
}
.primary-button:hover { background: var(--lg-blue-2); border-color: var(--lg-blue-2); transform: none; }
.ghost-button, .support-button {
  min-height: 36px;
  padding: 0 14px;
  border-radius: var(--rp-r-sm);
  background: rgb(var(--ch-lift) / 0.025);
  border: 1px solid var(--rp-line);
  color: var(--rp-ink);
  font-size: 12.5px;
  font-weight: 500;
}
.ghost-button:hover, .support-button:hover { background: rgb(var(--ch-lift) / 0.055); border-color: var(--rp-line-2); transform: none; }

/* MODULE TABS ARE A FILLED PILL ROW, NOT AN UNDERLINE.
   Measured across the package: 01 panel 7, 03, 05, 09 and 10 all draw the
   active module tab as a solid blue rounded rectangle inside a bordered track.
   Underline is used only for the INBOX sub-tabs in 06 and 08. The product had
   underline everywhere, which is why every module screen read as a generic
   dark admin rather than as these mockups. */
.group-subnav, .module-tabs {
  display: flex;
  align-items: center;
  gap: 2px;
  padding: 4px;
  border: 1px solid var(--rp-line);
  border-radius: 10px;
  background: rgb(var(--ch-lift) / 0.02);
  overflow-x: auto;
  scrollbar-width: none;
}
.group-subnav::-webkit-scrollbar, .module-tabs::-webkit-scrollbar { display: none; }
.group-subnav-item, .module-tabs button {
  flex: none;
  min-height: 32px;
  padding: 0 14px;
  border: 0;
  border-radius: 7px;
  background: none;
  color: var(--rp-ink-2);
  font-size: 12.5px;
  font-weight: 500;
  white-space: nowrap;
  cursor: pointer;
}
.group-subnav-item:hover, .module-tabs button:hover {
  color: var(--rp-ink);
  background: rgb(var(--ch-lift) / 0.05);
}
.group-subnav-item.active, .module-tabs button.active {
  color: var(--rp-on-accent);
  font-weight: 600;
  background: var(--rp-blue);
}
/* Inbox sub-tabs keep the underline the package gives them (06, 08). */
.chatpane-tabs {
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
}

/* Period chips: one bordered track with dividers, active segment tinted. */
.rp-periods {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  padding: 3px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-sm);
  background: rgb(var(--ch-lift) / 0.015);
}
.rp-periods button {
  min-height: 32px;
  padding: 0 13px;
  border: 1px solid transparent;
  border-radius: 6px;
  background: none;
  color: var(--rp-ink-2);
  font-size: 12.5px;
}
.rp-periods button:hover { color: var(--rp-ink); }
.rp-periods button.on {
  background: var(--rp-blue-soft);
  border-color: rgb(var(--ch-blue2) / 0.45);
  color: var(--rp-ink-max);
  font-weight: 600;
}

/* The resolved period window and the comparison window (16). Both are read-only
   readouts of what the chips resolved to, not pickers — there is no
   arbitrary-range query behind them, and a control that opens a calendar and
   then ignores what you pick is worse than one that plainly reports. */
/* READOUTS, NOT BUTTONS — and now dressed as what they are.
   These two report which days the period chips resolved to and which window
   the deltas subtract from. They had the same border, radius and fill as the
   clickable chips beside them, so the owner clicked one, nothing happened, and
   he reasonably reported it broken. A control that only reports must not wear
   a button's clothes: no border, no fill, no pointer affordance. */
.rp-range, .rp-compare {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 38px;
  padding: 0 4px;
  border: 0;
  background: none;
  color: var(--rp-ink-2);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  cursor: default;
  user-select: text;
}
/* Custom range picker — the tenth option beside the nine named chips. Two date
   inputs and an Apply button, styled like the rest of the toolbar rather than
   a native form dropped into a redesigned control row. */
.rp-custom-range {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  margin-top: 6px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-sm);
  background: rgb(var(--ch-lift) / 0.015);
  width: 100%;
}
.rp-custom-range label {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--rp-ink-2);
}
.rp-custom-range input[type="date"] {
  min-height: 30px;
  padding: 0 8px;
  border: 1px solid var(--rp-line);
  border-radius: 6px;
  background: var(--rp-surface, transparent);
  color: var(--rp-ink);
  font-size: 12.5px;
}
.period-selector-wrap {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 0;
}
.rp-compare { color: var(--rp-ink-2); }
.rp-compare.off { color: var(--rp-ink-3); }
.rp-compare-label { color: var(--rp-ink-3); }
/* Why the deltas are absent, said in the place that names the window they would
   have been measured against. Same weight as the label — it qualifies the range
   beside it, it is not a warning. */
.rp-compare-note { color: var(--rp-ink-3); font-size: 11px; }
.rp-range-glyph {
  flex: none;
  width: 13px; height: 12px;
  border: 1.4px solid var(--rp-ink-3);
  border-radius: 3px;
  position: relative;
}
.rp-range-glyph::before {
  content: ""; position: absolute; inset-inline-start: -1.4px; inset-inline-end: -1.4px; top: 1.5px;
  height: 1.4px; background: var(--rp-ink-3);
}

/* KPI card — the package's signature element. Five across, fixed: auto-fit was
   reflowing them to four-and-one at some widths, which is not a row 16 ever
   draws. */
.rp-kpis {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: var(--rp-3);
}
/* THE TRUTH PANEL — computed since this page existed, never actually drawn
   until 2026-08-23. One line per source, in the same live/needs-setup/
   draft/local-only/unavailable words used everywhere else on the platform. */
.rp-truth {
  display: flex; flex-direction: column; gap: 10px;
  padding: var(--rp-3) var(--rp-4);
  border: 1px solid var(--rp-line); border-radius: var(--rp-r-md, 10px);
  background: rgb(var(--ch-lift) / .03);
}
.rp-truth-title { margin: 0; font-size: 12.5px; font-weight: 620; color: var(--rp-ink-2); }
.rp-truth-rows { display: flex; flex-wrap: wrap; gap: 8px 18px; }
.rp-truth-row { display: flex; align-items: center; gap: 8px; }
.rp-truth-label { font-size: 12.5px; color: var(--rp-ink-3); }
.rp-truth-chip { font-size: 11px; }
@media (max-width: 720px) {
  .rp-truth-rows { flex-direction: column; align-items: flex-start; gap: 8px; }
}
/* 132px is the reference's KPI card, measured. */
.rp-kpi {
  display: grid;
  grid-template-rows: auto auto auto 1fr;
  gap: 1px;
  padding: 11px var(--rp-4) 0;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r);
  background: var(--rp-panel);
  overflow: hidden;
  min-height: 132px;
}
/* One line, as in 16 — see the note on kpiMark() for how the source state stays
   visible without a 108px chip in a 222px card. */
.rp-kpi-head { display: flex; align-items: center; justify-content: space-between; gap: 6px; flex-wrap: nowrap; min-width: 0; }
.rp-kpi-label { color: var(--rp-ink-2); font-size: 12.5px; font-weight: 550; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The mockup's ⓘ. It carries the source state in its tooltip; anything that is
   NOT healthy keeps a readable word on the card instead — see kpiMark(). */
.rp-kpi-info {
  flex: none;
  display: grid; place-items: center;
  width: 15px; height: 15px;
  border: 1px solid var(--rp-line-2);
  border-radius: 50%;
  color: var(--rp-ink-3);
  font-size: 9.5px;
  font-weight: 700;
  font-style: italic;
  cursor: help;
}
/* The marker carries the source state in its colour as well as its tooltip, so
   a card whose source is missing is distinguishable at a glance and not only on
   hover. The word itself is on the card's own sub-line. */
.rp-kpi-info.tone-live, .rp-kpi-info.tone-good { border-color: rgb(var(--ch-green) / 0.45); color: var(--t212); }
.rp-kpi-info.tone-info { border-color: rgb(var(--ch-blue2) / 0.45); color: var(--sh-blue-3); }
.rp-kpi-info.tone-warn { border-color: rgb(var(--ch-amber) / 0.5); color: var(--rp-amber); }
.rp-kpi-info.tone-off { border-color: rgb(var(--ch-slate) / 0.3); color: var(--rp-ink-3); }
/* The chip may shrink. `flex: none` plus nowrap made «Не подключено» wider than
   a 236px column at 1440 and pushed it through the card's clipped edge, so the
   fifth KPI card lost its right border and the chip read "Не подкл". */
.rp-kpi-head .xo-chip {
  flex: 0 1 auto;
  min-width: 0;
  font-size: 10px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* The label yields before the status does: a truncated metric name is
   recoverable from the number under it, a truncated status is not. */
.rp-kpi-label { flex: 1 1 auto; min-width: 0; }
.rp-kpi-row { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.rp-kpi-value {
  color: var(--rp-ink-max);
  font-size: clamp(19px, 1.4vw, 26px);
  font-weight: 660;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
  line-height: 1.15;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.rp-kpi-delta { font-size: 11.5px; font-weight: 620; font-variant-numeric: tabular-nums; white-space: nowrap; }
.rp-kpi-delta.up { color: var(--rp-green); }
.rp-kpi-delta.down { color: var(--rp-red); }
.rp-kpi-delta.flat { color: var(--rp-ink-3); }
.rp-kpi-sub { color: var(--rp-ink-3); font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 16 fills the lower band of every KPI card with a sparkline. A card with a
   real dated series behind it gets one; a card without keeps the BAND — same
   height, same proportions — with a dashed baseline and a dash where the line
   would be. The reference's geometry is honoured and none of its data is
   invented. The previous version put a sentence of prose here instead, which
   made the five cards different heights and read as an apology. */
.rp-kpi-nospark {
  display: grid;
  place-items: center;
  align-self: end;
  margin: var(--rp-2) calc(var(--rp-4) * -1) 0;
  height: 44px;
  border-top: 1px dashed rgb(var(--ch-slate) / 0.18);
  color: var(--rp-ink-3);
  font-size: 13px;
}

/* ═══ ANSWERING THE "ROUND 3 FIT" PINS, SCOPED TO THIS BOARD ═════════════
   styles.css declares, with !important:

     .control-card span { white-space: normal; overflow: visible;
                          text-overflow: clip; overflow-wrap: break-word; }

   — every span inside every card is force-wrapped and forbidden to ellipsis.
   It was written to stop legacy cards clipping their badges, and for legacy
   cards it still does its job. On this board it is why «Instagram» rendered as
   "Instagra / m" in a 106px legend column, why the funnel band showed the
   middle of «Квалифицированы», and why a "Не подключено" chip could not
   shorten. Measured on the running page, not read off the sheet.

   These counter-declarations are deliberately scoped to `.rp-ov` and carry
   !important only because an !important is what they answer. They are removed
   together with the block above when the legacy fit rules go — nothing here
   changes any other screen. */
.rp-ov .rp-kpi-label,
.rp-ov .rp-kpi-sub,
.rp-ov .rp-kpi-value,
.rp-ov .rp-kpi-head .xo-chip,
.rp-ov .rp-legend-name,
.rp-ov .rp-legend-pct,
.rp-ov .rp-legend-num,
.rp-ov .rp-statcell small,
.rp-ov .rp-statcell strong,
.rp-ov .rp-table td,
.rp-ov .rp-table th {
  white-space: nowrap !important;
  overflow: hidden !important;
  text-overflow: ellipsis !important;
  overflow-wrap: normal !important;
}
/* ПОДПИСЬ ПЛИТКИ — ИСКЛЮЧЕНИЕ ИЗ ОДНОСТРОЧНОГО ПРАВИЛА ВЫШЕ.
   Владелец 30 августа показал: «У 37 открытых сделок не проставлена сумма —
   считат…». Однострочность нужна ярлыку, значению и чипу — короткому тексту,
   которому перенос ломает вид. Подпись же бывает целым предложением, и она
   ЕДИНСТВЕННОЕ, что объясняет прочерк над ней: обрезанная, она обещает
   объяснение и не даёт его.

   !important здесь по той же причине, что и у блока выше, — им отвечают на
   чужой !important, а не на порядок правил. Проверено замером по таблицам
   стилей: без него побеждает строка на 20 правил выше, и на экране ничего не
   меняется. Две строки — потолок: больше сдвинуло бы график в плитке. */
.rp-ov .rp-kpi-sub {
  white-space: normal !important;
  overflow: hidden !important;
  display: -webkit-box !important;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  line-height: 1.35;
}
.rp-ov .rp-funnel-name {
  overflow: hidden !important;
  text-overflow: clip !important;
}
/* The card itself may clip again, so a table or a chip that still cannot fit is
   contained rather than drawn across the card next to it. */
.rp-ov .control-card { overflow: hidden !important; }
/* …except the two blocks whose whole job is to wrap: the honest-state copy and
   the tile labels. */
.rp-ov .rp-nosource-sub,
.rp-ov .rp-tile > span:last-child,
.rp-ov .rp-row-title,
.rp-ov .rp-row-sub {
  white-space: normal !important;
  overflow: visible !important;
}

/* Card head used inside every content card. Measured: 16's row-2 cards are 327px
   and row-3's are 311; ours were 373 and 332. The head, the card padding and
   the foot are the three things every card in both rows pays for, so they are
   where the 14% comes off — not off any block's content. */
.rp-card-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--rp-3);
  margin-bottom: 9px;
}
.rp-card-head h3 { margin: 0; font-size: 13.5px; font-weight: 620; line-height: 1.25; color: var(--rp-ink); }
.rp-card-head p { margin: 1px 0 0; font-size: 11px; line-height: 1.3; color: var(--rp-ink-3); }
.rp-card-foot {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  margin-top: 9px;
  padding-top: 9px;
  border-top: 1px solid var(--rp-line);
  color: var(--sh-blue-2);
  font-size: 12px;
  font-weight: 550;
  background: none;
  border-inline-start: 0; border-inline-end: 0; border-bottom: 0;
  width: 100%;
  min-height: 28px;
  cursor: pointer;
}
.rp-card-foot:hover { color: var(--sh-blue-1); }

/* Content grid: the package's 4-up row that collapses cleanly. */
.rp-grid { display: grid; gap: var(--rp-3); align-items: start; }
.rp-grid-4 { grid-template-columns: repeat(auto-fit, minmax(258px, 1fr)); }
.rp-grid-wide { grid-template-columns: minmax(320px, 1.55fr) repeat(auto-fit, minmax(240px, 1fr)); }

/* Rows inside list cards. */
.rp-row {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 9px 0;
  border-bottom: 1px solid var(--rp-line);
  text-align: start;
  width: 100%;
  background: none;
  border-inline-start: 0; border-inline-end: 0; border-top: 0;
  color: inherit;
}
.rp-row:last-of-type { border-bottom: 0; }
.rp-row-mark { width: 20px; height: 20px; border-radius: 6px; flex: none; display: grid; place-items: center; font-size: 10px; }
.rp-row-mark.crit { background: rgb(var(--ch-red) / 0.16); color: var(--rp-red); }
.rp-row-mark.warn { background: rgb(var(--ch-amber) / 0.16); color: var(--rp-amber); }
.rp-row-mark.info { background: rgb(var(--ch-blue2) / 0.16); color: var(--sh-blue-3); }
.rp-row-mark.good { background: rgb(var(--ch-green) / 0.16); color: var(--rp-green); }
/* Wrap, never clip. RU is the longer language and «51 лид без активности за
   период» was being cut mid-word inside a Next-actions row; the acceptance
   criteria forbid truncated text, and these rows have the vertical space. */
.rp-row-copy { min-width: 0; flex: 1 1 auto; overflow: visible; }
.rp-row-title, .rp-row-sub { white-space: normal; overflow: visible; text-overflow: clip; }
.rp-row-title { margin: 0; font-size: 12.5px; font-weight: 570; color: var(--rp-ink); }
.rp-row-sub { margin: 2px 0 0; font-size: 11.5px; color: var(--rp-ink-3); }
.rp-row-side { flex: none; text-align: end; font-size: 11.5px; color: var(--rp-ink-3); }

/* Tables. `table-layout: fixed` because the manager table's money column was
   being pushed outside its card: auto layout sizes columns to content, and
   "AED 1,236,547" is wider than the quarter-width column it lives in. Fixed
   layout plus per-cell ellipsis keeps every column inside the card. */
.rp-table { width: 100%; table-layout: fixed; border-collapse: collapse; font-size: 12px; }
.rp-table td, .rp-table th { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rp-table .num, .rp-table th.num { text-align: end; font-variant-numeric: tabular-nums; }
.rp-table tfoot td { border-top: 1px solid var(--rp-line-2); border-bottom: 0; color: var(--rp-ink); font-weight: 620; }
/* Fixed layout needs the widths declared once. The name column takes what is
   left after three numeric columns sized to the figures they hold. */
.rp-table-mgr { font-size: 11.5px; }
.rp-table-mgr col, .rp-table-mgr th:first-child, .rp-table-mgr td:first-child { width: auto; }
.rp-table-mgr th:nth-child(2), .rp-table-mgr td:nth-child(2),
.rp-table-mgr th:nth-child(3), .rp-table-mgr td:nth-child(3) { width: 21%; }
.rp-table-mgr th:nth-child(4), .rp-table-mgr td:nth-child(4) { width: 26%; }
.rp-table-mgr td { padding-top: 7px; padding-bottom: 7px; }
.rp-table th {
  text-align: start;
  /* Сверху был ноль, и подпись столбца лежала прямо на верхней границе ячейки —
     владелец 2026-08-29: «в оглавлении текст прижат к верху сильно». Заметнее
     всего там, где шапка идёт сразу под заголовком блока и двум строкам текста
     не остаётся ни просвета, ни различия. Верхний отступ чуть больше нижнего:
     снизу ячейку и так отделяет линия. */
  padding-block: 10px 8px; padding-inline: 0 8px;
  color: var(--rp-ink-3);
  font-size: 11px;
  font-weight: 600;
  border-bottom: 1px solid var(--rp-line);
}
.rp-table td { padding-block: 9px 9px; padding-inline: 0 8px; border-bottom: 1px solid var(--rp-line); color: var(--rp-ink-2); }
.rp-table td:last-child, .rp-table th:last-child { text-align: end; padding-inline-end: 0; }
.rp-table tr:last-child td { border-bottom: 0; }
.rp-table .num { font-variant-numeric: tabular-nums; color: var(--rp-ink); }

/* Honest state — the package has no name for this because it has no empty
   screens; the product does, so it gets one voice everywhere. */
.rp-empty { display: grid; gap: 5px; padding: var(--rp-5) var(--rp-4); text-align: start; }
.rp-empty-tag {
  color: var(--rp-ink-3);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}
.rp-empty h4 { margin: 0; font-size: 13.5px; font-weight: 600; color: var(--rp-ink); }
.rp-empty p { margin: 0; font-size: 12px; line-height: 1.55; color: var(--rp-ink-3); }
.rp-empty .ghost-button { justify-self: start; margin-top: 6px; }

/* ═══ OVERVIEW (mockup 16) ═══════════════════════════════════════════════ */

/* 16's row gaps are 17px (KPI→row 2) and 20px (row 2→row 3). */
.rp-ov { display: grid; gap: 17px; }

.rp-ov-controls {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--rp-3);
}
.rp-ov-controls { justify-content: flex-start; gap: var(--rp-2); }
.rp-ov-actions { display: flex; gap: var(--rp-2); flex-wrap: wrap; margin-inline-start: auto; }

/* MEASURED OFF 16 BY EDGE DETECTION, NOT BY EYE, AND THE TWO ROWS DIFFER.
   Card borders in the reference were found by scanning for thin bright lines
   along a scanline. Content spans x 178→1422 (1244px) beside a 150px rail.
   Row 2 cards land on [176-532, 545-808, 820-1077, 1089-1422] = 357/264/258/334
   with ~12px gaps. Row 3 lands on 291/323/254/344. Normalised against the third
   column those are the ratios below. The earlier `1.4/1/1/1.4` guess made the
   fourth column of row 2 6% too wide and the second 4% too narrow. */
.rp-ov-row-2 { grid-template-columns: 1.384fr 1.023fr 1fr 1.294fr; }
.rp-ov-row-3 { grid-template-columns: 1.146fr 1.272fr 1fr 1.354fr; }
/* Cards in a row are the same height, as they are on every board in the
   package. A short card no longer leaves a ragged step beside a tall one. */
.rp-ov-row { align-items: stretch; }
.rp-ov-row > .control-card { display: flex; flex-direction: column; }
/* A flex item defaults to `min-width: auto`, i.e. it refuses to shrink below
   its own min-content. Measured: the manager table's four columns want 690px
   and pushed straight out of a 416px card. Every direct child of a card in
   these rows is allowed to shrink instead. */
.rp-ov-row > .control-card > * { min-width: 0; }
.rp-ov-row > .control-card > .rp-card-foot { margin-top: auto; }
/* The body of a card takes the slack, so a short block (the sources donut) sits
   centred in its column instead of leaving the void at the bottom that the
   equal-height row would otherwise open up. */
.rp-srcbody, .rp-funnel, .rp-panels, .rp-linechart { flex: 1 1 auto; }
.rp-srcbody { align-content: center; }

.rp-notice {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--rp-3);
  flex-wrap: wrap;
  padding: var(--rp-3) var(--rp-4);
  border: 1px solid rgb(var(--ch-amber) / 0.35);
  border-radius: var(--rp-r);
  background: rgb(var(--ch-amber) / 0.08);
  color: var(--rp-ink);
  font-size: 12.5px;
}

/* ── charts: the package's own language (16, 01) ───────────────────────── */

/* Sparkline: full-bleed to the card edges, filling the lower band of a KPI
   card exactly as 16 draws it. */
.rp-spark {
  display: block;
  width: calc(100% + var(--rp-4) * 2);
  margin: var(--rp-2) calc(var(--rp-4) * -1) 0;
  height: 40px;
}
.rp-spark-line { fill: none; stroke-width: 1.6; vector-effect: non-scaling-stroke; }
/* The fill is a per-tone gradient declared inside the SVG; only its stop colour
   is set here, so a tone is one line in one place. `opacity` is gone — the fade
   now comes from the gradient's own stop-opacity, which is what makes the band
   read as a chart rather than as a coloured block. */
.rp-spark-blue .rp-spark-line { stroke: var(--sh-blue-5); }
.rp-spark-blue stop { stop-color: var(--lg-blue-1); }
.rp-spark-blue .rp-spark-dot { fill: var(--sh-blue-5); }
.rp-spark-green .rp-spark-line { stroke: var(--lg-ok-4); }
.rp-spark-green stop { stop-color: #22c55e; }
.rp-spark-green .rp-spark-dot { fill: var(--lg-ok-4); }
.rp-spark-amber .rp-spark-line { stroke: var(--lg-warm-2); }
.rp-spark-amber stop { stop-color: #f59e0b; }
.rp-spark-amber .rp-spark-dot { fill: var(--lg-warm-2); }
.rp-spark-purple .rp-spark-line { stroke: var(--lg-violet); }
.rp-spark-purple stop { stop-color: var(--sh-violet); }
.rp-spark-purple .rp-spark-dot { fill: var(--lg-violet); }

.rp-linechart { padding-top: 2px; display: flex; flex-direction: column; }
/* `.rp-spark` pins 40px for the KPI band; the page chart needs its own height
   or the 108px viewBox is squashed back to a sparkline. Full-bleed is also
   wrong here — inside a plot the line has to sit over its own gridlines. */
.rp-linechart .rp-spark { height: 100px; width: 100%; margin: 0; }

/* The plot of 16: a labelled y-axis and four gridlines under the line. */
.rp-plot { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 8px; }
.rp-plot-yaxis {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  height: 100px;
  color: var(--rp-ink-3);
  font-size: 9.5px;
  font-variant-numeric: tabular-nums;
  text-align: end;
}
.rp-plot-area { position: relative; min-width: 0; }
.rp-plot-grid {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  pointer-events: none;
}
.rp-plot-grid i { display: block; height: 1px; background: rgb(var(--ch-slate) / 0.10); }
.rp-linechart-axis {
  display: flex;
  justify-content: space-between;
  margin-top: 5px;
  padding-inline-start: 34px;
  color: var(--rp-ink-3);
  font-size: 10px;
  font-variant-numeric: tabular-nums;
}
/* 16 leads the chart with the period's own total and its change against the
   comparison window, on one line above the plot. */
.rp-linechart-lede { display: flex; align-items: baseline; gap: 9px; flex-wrap: wrap; margin-bottom: 6px; }
.rp-linechart-lede strong {
  color: var(--rp-ink-max);
  font-size: 20px;
  font-weight: 660;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
}
.rp-linechart-vs { color: var(--rp-ink-3); font-size: 11px; }

/* The three footer cells of 16's revenue card — best, weakest, average — over
   the same series the line above draws. */
.rp-statcells {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  margin-top: var(--rp-3);
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-sm);
  overflow: hidden;
}
.rp-statcell {
  display: grid;
  gap: 0;
  padding: 7px 10px;
  border-inline-end: 1px solid var(--rp-line);
  background: rgb(var(--ch-lift) / 0.015);
  min-width: 0;
}
.rp-statcell:last-child { border-inline-end: 0; }
.rp-statcell span { color: var(--rp-ink-3); font-size: 10.5px; }
.rp-statcell small { color: var(--rp-ink-3); font-size: 10px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rp-statcell strong {
  color: var(--rp-ink);
  font-size: 12.5px;
  font-weight: 640;
  font-variant-numeric: tabular-nums;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* «Риски и внимание» and «Следующие действия» are rows of RAISED PANELS in 16,
   not a list separated by hairlines. That difference is most of why those two
   cards read as generic lists rather than as the mockup. */
.rp-panels { display: grid; gap: 7px; }
.rp-panel {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  width: 100%;
  padding: 9px 10px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-sm);
  background: var(--rp-panel-2);
  text-align: start;
  color: inherit;
}
button.rp-panel { cursor: pointer; transition: border-color 130ms ease, background 130ms ease; }
button.rp-panel:hover { border-color: rgb(var(--ch-blue2) / 0.4); background: rgb(var(--ch-blue2) / 0.08); }
.rp-panel .rp-row-mark { margin-top: 1px; }
.rp-panel .rp-row-side { align-self: center; font-weight: 620; color: var(--rp-ink); }

.rp-card-note {
  margin-top: auto;
  padding-top: var(--rp-3);
  color: var(--rp-ink-3);
  font-size: 10.5px;
}

/* ── «Источники лидов»: donut + legend (16) ─────────────────────────────── */
/* The donut shrinks before the legend does. At 1440 a fixed 112px donut left
   the legend ~110px, which wrapped "Instagram" onto two lines — a legend that
   wraps is not a legend. */
.rp-srcbody { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center; gap: var(--rp-3); }
/* 16's donut is ~96px inside a 291px card — a third of the column. At 78px in a
   384px card ours read as a bullet beside its own legend. */
/* container-type is what makes `cqi` below mean "percent of this donut". Without
   it `cqi` falls back to the viewport and 17cqi would be 261px at 1536. */
.rp-donut {
  position: relative; width: clamp(92px, 7.4vw, 132px); aspect-ratio: 1; flex: none;
  container-type: inline-size;
}
.rp-donut-svg { width: 100%; height: 100%; display: block; }
/* THE LABEL BOX IS THE HOLE, NOT THE SQUARE.
   The ring is r=42, stroke-width 15, viewBox 110 (see DonutChart in main.js).
   Hole diameter = 2r − sw = 69 units, so the inset that lands exactly on the
   inner edge is (110 − 69) / 2 / 110 = 18.6%. 19% is that, rounded away from
   the stroke. `inset: 0` is what let the caption spill across the ring — the
   box was the whole 110-unit square, 1.6× the hole it was supposed to sit in.
   The caption now lives outside the ring entirely; only the figure is here. */
.rp-donut-centre {
  position: absolute; inset: 19%;
  display: grid; place-content: center; justify-items: center;
  pointer-events: none;
}
.rp-donut-centre strong {
  color: var(--rp-ink-max);
  /* Scales with the donut so a six-figure count cannot outgrow the hole the
     way the caption did. 17cqi of the 92px floor is 15.6px; of the 132px
     ceiling, 22.4px — clamped back to the 17px this card was designed at. */
  font-size: clamp(12px, 17cqi, 17px);
  font-weight: 660;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  max-width: 100%;
}
/* The donut and the sentence that labels it, stacked. This is the grid child
   of .rp-srcbody now, so it keeps the donut's "shrink before the legend does"
   behaviour and adds one line under it. */
.rp-donutfig { display: grid; justify-items: center; gap: 6px; margin: 0; }
.rp-donut-cap {
  margin: 0;
  color: var(--rp-ink-3);
  font-size: 9.5px;
  line-height: 1.35;
  text-align: center;
  max-width: clamp(92px, 7.4vw, 132px);
}

/* ── «Расписание встреч», once it had something to show ──────────────────
   One column of a four-column row, so this scrolls INSIDE itself rather than
   growing the card: `.rp-ov-row > .control-card` is a flex column and
   `.rp-card-foot` is pinned to its bottom with `margin-top: auto`, so an
   agenda that grows would otherwise push the footer out of the row. */
.rp-agenda {
  display: grid; gap: 10px; align-content: start;
  min-height: 0; max-height: 216px; overflow-y: auto;
  margin: 0 -2px; padding: 0 2px;
}
.rp-agenda-day { display: grid; gap: 5px; }
.rp-agenda-date {
  display: flex; align-items: center; gap: 8px; margin: 0;
  font-size: 10px; letter-spacing: 0.09em; text-transform: uppercase;
  color: var(--rp-ink-3); font-weight: 600;
}
.rp-agenda-count {
  margin-inline-start: auto; padding: 0 6px; border-radius: 999px;
  background: rgb(var(--ch-slate) / 0.14); letter-spacing: 0;
}
.rp-agenda-list { display: grid; gap: 4px; margin: 0; padding: 0; list-style: none; }
.rp-agenda-item {
  display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 8px; align-items: baseline;
  padding: 5px 8px; border-radius: 7px;
  border-inline-start: 2px solid rgb(var(--ch-slate) / 0.28);
  background: rgb(var(--ch-slate) / 0.06);
}
/* A meeting is the thing this card is named after, so it is the one that reads
   differently. Colour is never the only carrier — the row is also the only one
   with a filled marker weight. */
.rp-agenda-item.is-meeting { border-inline-start-color: var(--primary, var(--lg-blue-1)); background: rgb(var(--ch-blue2) / 0.10); }
.rp-agenda-item.is-late { border-inline-start-color: var(--danger, #e11d48); }
.rp-agenda-time { font-size: 11px; font-variant-numeric: tabular-nums; color: var(--rp-ink-3); }
.rp-agenda-what { display: grid; gap: 1px; min-width: 0; }
.rp-agenda-what strong {
  font-size: 12px; font-weight: 560; color: var(--rp-ink-max);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.rp-agenda-what small {
  font-size: 10px; color: var(--rp-ink-3);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* The demoted calendar sentence. It is a footnote now, not the whole card. */
.rp-agenda-note {
  margin: 8px 0 0; font-size: 10px; line-height: 1.4; color: var(--rp-ink-3);
}

.rp-legend { display: grid; gap: 6px; margin: 0; padding: 0; list-style: none; min-width: 0; }
.rp-legend li {
  display: grid;
  grid-template-columns: 8px minmax(0, 1fr) auto auto;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  color: var(--rp-ink-2);
}
.rp-legend-dot { width: 8px; height: 8px; border-radius: 50%; display: block; flex: none; }
.rp-legend-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rp-legend-pct { color: var(--rp-ink-3); font-size: 11px; font-variant-numeric: tabular-nums; }
.rp-legend-num { color: var(--rp-ink); font-size: 11.5px; font-weight: 600; font-variant-numeric: tabular-nums; }

/* A block with no source keeps its column and its height and says what is
   missing in one short line plus the one fact it does hold — never a 300px
   card whose entire content is an apology, and never a Demo sample. */
.rp-nosource {
  display: grid;
  align-content: center;
  justify-items: center;
  gap: 5px;
  flex: 1 1 auto;
  min-height: 132px;
  padding: var(--rp-4) var(--rp-3);
  border: 1px dashed rgb(var(--ch-slate) / 0.2);
  border-radius: var(--rp-r-sm);
  text-align: center;
}
.rp-nosource-mark {
  width: 22px; height: 22px;
  border: 1.5px solid var(--rp-ink-3);
  border-radius: 5px;
  opacity: 0.55;
  position: relative;
}
.rp-nosource-mark::before {
  content: ""; position: absolute; inset-inline-start: 3px; inset-inline-end: 3px; top: 6.5px;
  height: 1.5px; background: var(--rp-ink-3);
}
.rp-nosource-title { margin: 3px 0 0; color: var(--rp-ink-2); font-size: 12px; font-weight: 570; }
.rp-nosource-sub { margin: 0; color: var(--rp-ink-3); font-size: 11px; line-height: 1.45; max-width: 25ch; }
.rp-nosource-fact { margin: 4px 0 0; color: var(--rp-ink-3); font-size: 11px; }
.rp-nosource-fact strong { color: var(--rp-ink); font-size: 15px; font-weight: 660; font-variant-numeric: tabular-nums; }

/* Trapezoid funnel (16): bands narrowing downward, name inside the band,
   count outside it, conversion between rows. */
/* The funnel of 16: bands CENTRED so the stack tapers symmetrically, name
   inside the band, count and share of the top outside it on the right. */
.rp-funnel { display: grid; gap: 3px; }
.rp-funnel-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  align-items: center;
  gap: 10px;
}
.rp-funnel-track { display: flex; justify-content: center; min-width: 0; }
.rp-funnel-band {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 34px;
  padding: 0 9px;
  border-radius: 3px;
  /* The taper: each band is a trapezoid, not a bar. */
  clip-path: polygon(0 0, 100% 0, calc(100% - 8px) 100%, 8px 100%);
  /* Wide enough for «Квалифицированы», which is the longest stage name either
     language produces. Without it the narrow lower bands clipped their label
     from BOTH sides — centred text plus overflow:hidden shows the middle of the
     word, so «Квалифицированы» rendered as "алифициров". */
  min-width: 118px;
  max-width: 100%;
  overflow: hidden;
}
.rp-funnel-name {
  color: var(--rp-ink-max);
  font-size: 10.5px;
  font-weight: 600;
  line-height: 1.15;
  /* Two lines rather than a cut word: the band has the height for it and a
     half-word is not a stage name. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-align: center;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.35);
}
.rp-funnel-count {
  flex: none;
  min-width: 34px;
  text-align: end;
  color: var(--rp-ink);
  font-size: 12.5px;
  font-weight: 650;
  font-variant-numeric: tabular-nums;
}
.rp-funnel-share {
  flex: none;
  min-width: 34px;
  text-align: end;
  color: var(--rp-ink-3);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
}
/* ЛЕСТНИЦА ВОРОНКИ: ХОЛОДНЫЙ ПУТЬ, ЗЕЛЁНАЯ ПОБЕДА.
   Тона шли по номеру строки, поэтому четвёртая стадия всегда была зелёной, а
   пятая — янтарной: «Квалифицирован» выглядел успехом, а «Сделка закрыта» —
   предупреждением. Теперь t1…t4 — один остывающий синий путь без всплесков
   смысла, а зелёный принадлежит только выигранной сделке (.won) и ставится
   лишь тогда, когда последняя строка действительно про неё. Янтарный и
   фиолетовый убраны: в шкале, оканчивающейся победой, они читались как
   предупреждение и как отдельная категория. */
.rp-funnel-band.t1 { background: linear-gradient(90deg, var(--lg-blue-1), var(--sh-blue-5)); }
.rp-funnel-band.t2 { background: linear-gradient(90deg, #2f8fff, #38b6ff); }
.rp-funnel-band.t3 { background: linear-gradient(90deg, #1f8bc4, #35a7dd); }
.rp-funnel-band.t4 { background: linear-gradient(90deg, #17a2b8, var(--lg-cyan-3)); }
.rp-funnel-band.t5 { background: linear-gradient(90deg, #12a3a3, #2fc4c4); }
.rp-funnel-band.t6 { background: linear-gradient(90deg, #0e9aa7, #35c6b0); }
.rp-funnel-band.won { background: linear-gradient(90deg, #10a37f, #22c55e); }
/* Отказ — исход, а не шаг: приглушённый красный, заметный, но не тревожный. */
.rp-funnel-band.lost { background: linear-gradient(90deg, #9f3d3d, #c2544f); }

/* COMPACT HONEST STATE.
   One muted line inside the block that owns the data — never a card whose
   whole content is an apology. See the note at its call site in main.js. */
.rp-nodata {
  margin: 0;
  padding: 10px 0 2px;
  color: var(--rp-ink-3);
  font-size: 11.5px;
  line-height: 1.5;
}
.rp-nodata[title]:hover { color: var(--rp-ink-2); }

/* The 8-tile action centre (16): a 4×2 grid of icon tiles, not a list of
   text buttons. The glyph is drawn from the tile's own key so no icon font
   or asset is needed. */
/* FOUR ACROSS, AS 16 DRAWS IT. The previous pass dropped to 2×4 because the
   action centre sat in the narrowest column of a `1.35fr 1fr 1fr 1fr` row and a
   4-up grid clipped "Integrations". The row proportions are now the mockup's,
   where the action centre is the WIDEST column — so the reference grid fits,
   and the labels wrap instead of being cut. */
.rp-tiles { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 6px; }
.rp-tile {
  display: grid;
  justify-items: center;
  align-content: center;
  gap: 6px;
  min-height: 66px;
  padding: 9px 4px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-sm);
  background: rgb(var(--ch-lift) / 0.02);
  color: var(--rp-ink-2);
  font-size: 10px;
  font-weight: 550;
  line-height: 1.25;
  text-align: center;
  cursor: pointer;
  overflow: hidden;
}
.rp-tile > span:last-child { overflow-wrap: anywhere; }
.rp-tile:hover { background: rgb(var(--ch-blue2) / 0.1); border-color: rgb(var(--ch-blue2) / 0.4); color: var(--rp-ink-max); }
/* A bare line glyph, matching the rail — the mockup has no icon plate here
   either, and the plate is what made eight tiles read as eight blue chips. */
.rp-tile-glyph {
  width: 22px; height: 22px;
  display: grid; place-items: center;
  color: var(--sh-blue-3);
}
.rp-tile-glyph[class*="nav-icon-"]::before { width: 19px; height: 19px; }
.rp-tile:hover .rp-tile-glyph { color: var(--t300); }

@media (max-width: 1300px) { .rp-tiles { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (max-width: 720px) { .rp-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* A whole row of buttons made of .rp-row needs the button reset. */
button.rp-row { cursor: pointer; }
button.rp-row:hover .rp-row-title { color: var(--sh-blue-1); }

/* 16 IS A FOUR-UP BOARD AT 1440 AND THE BREAKPOINT MUST NOT ARGUE WITH IT.
   This collapsed to two columns below 1500px, so at the 1440 the acceptance
   shots are taken at, row 2 became [chart | funnel] and row 3 [risks | next],
   which is not the reference composition — and because the four blocks have
   very unequal heights, the two-column grid left ~400px of dead space that
   rule 3 forbids. Four columns hold to 1180, which is where they genuinely
   stop being readable. */
@media (max-width: 1180px) {
  .rp-ov-row, .rp-ov-row-2, .rp-ov-row-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .rp-kpis { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 720px) {
  .rp-ov-row, .rp-ov-row-2, .rp-ov-row-3 { grid-template-columns: minmax(0, 1fr); }
  .rp-kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .rp-srcbody { grid-template-columns: minmax(0, 1fr); justify-items: center; }
}
@media (max-width: 420px) {
  .rp-kpis { grid-template-columns: minmax(0, 1fr); }
}

/* ═══ CRM (mockups 03 and 12) ════════════════════════════════════════════
   The CRM already had the right STRUCTURE — KPI strip, filter bar, kanban,
   list, lead drawer — built in earlier sessions against the same reference.
   What it did not have was the package's visual language, so this section
   restyles what exists rather than rebuilding it. No markup changes, and no
   working behaviour is touched. */

/* The KPI strip becomes the package's KPI card. 03 runs six tiles across the
   full width; auto-fit at 178px reflowed them to 4+2 at 1440, which is not a
   row the reference draws. */
.crm-kpi { padding: 0; border: 0; background: none; }
/* Five counts on one shared panel, the derived conversion figure on its own
   card beside it — the composition of 03. */
/* `align-items: start`, not stretch. The conversion card is taller than the
   five-count strip in 03 (it carries a trend slot the counts do not), and
   stretching the strip to match it opened ~50px of dead space under every
   value — the density rule's exact failure mode. */
.crm-kpi-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(190px, 0.28fr);
  gap: var(--rp-3);
  align-items: start;
}
.crm-kpi-strip {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r);
  background: var(--rp-panel);
  overflow: hidden;
}
/* 03's KPI band is 66px tall; ours was 93. The cells lose padding, not
   content — every figure and its caption stay. */
.crm-kpi-strip .crm-kpi-tile {
  border: 0;
  border-inline-end: 1px solid var(--rp-line);
  border-radius: 0;
  background: none;
  padding: 7px 14px;
  gap: 0;
}
.crm-kpi-strip .crm-kpi-lbl, .crm-kpi-conv .crm-kpi-lbl { font-size: 11px; line-height: 1.25; }
.crm-kpi-strip .crm-kpi-val, .crm-kpi-conv .crm-kpi-val { font-size: 20px; line-height: 1.2; }
.crm-kpi-strip .crm-kpi-sub, .crm-kpi-conv .crm-kpi-sub { font-size: 10.5px; line-height: 1.3; }
.crm-kpi-strip .crm-kpi-tile:last-child { border-inline-end: 0; }
.crm-kpi-strip .crm-kpi-tile.accent { background: rgb(var(--ch-blue2) / 0.07); }
.crm-kpi-conv {
  display: grid;
  align-content: start;
  gap: 0;
  padding: 7px 14px 0;
  border: 1px solid rgb(var(--ch-blue2) / 0.34);
  border-radius: var(--rp-r);
  background: rgb(var(--ch-blue2) / 0.06);
  overflow: hidden;
}
.crm-kpi-conv .rp-kpi-nospark { margin-inline: calc(var(--rp-4) * -1); height: 38px; }
@media (max-width: 1240px) {
  .crm-kpi-row { grid-template-columns: minmax(0, 1fr); }
  .crm-kpi-strip { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .crm-kpi-strip .crm-kpi-tile:nth-child(3n) { border-inline-end: 0; }
}
@media (max-width: 640px) { .crm-kpi-strip { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.crm-kpi-tile > *, .crm-kpi-conv > * { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The one line that must wrap: the conversion card's formula. «of all leads in
   this pipeline» is what stops two people reading 3.3% two different ways, so
   it is not the thing to truncate. */
.crm-kpi-conv .crm-kpi-sub {
  white-space: normal;
  overflow: visible;
  text-overflow: clip;
  line-height: 1.35;
}

/* ── 03's filter row ─────────────────────────────────────────────────────── */
.crm-bar-filters { display: flex; align-items: center; gap: var(--rp-2); flex-wrap: wrap; }
.crm-search { position: relative; flex: 1 1 260px; min-width: 180px; max-width: 420px; }
/* Room for both controls, so a long number never runs under them. */
.crm-search input { width: 100%; padding-inline-end: 62px; }
/* The magnifier sits INSIDE the field on the right, as in 03 — but as a button
   now. It used to be a <span> with pointer-events: none: a picture of a
   control, on a field that searched on every keystroke instead. */
.crm-search-actions {
  position: absolute; inset-inline-end: 4px; top: 50%; transform: translateY(-50%);
  display: flex; align-items: center; gap: 2px;
}
.crm-search-go {
  position: relative;
  width: 26px; height: 26px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 0; border-radius: 6px; background: transparent; cursor: pointer;
  padding: 0;
}
.crm-search-go:hover { background: rgb(var(--ch-lift) / .06); }
.crm-search-go:focus-visible { outline: 2px solid rgb(var(--ch-blue2) / .6); outline-offset: 1px; }
.crm-search-glyph {
  position: relative;
  width: 12px; height: 12px;
  border: 1.6px solid var(--rp-ink-3);
  border-radius: 50%;
  pointer-events: none;
}
.crm-search-go:hover .crm-search-glyph { border-color: var(--rp-ink-1); }
.crm-search-glyph::after {
  content: ""; position: absolute; inset-inline-end: -4px; bottom: -3px;
  width: 5px; height: 1.6px; background: var(--rp-ink-3);
  transform: rotate(45deg);
}
.crm-search-go:hover .crm-search-glyph::after { background: var(--rp-ink-1); }
.crm-search-x {
  position: relative; inset-inline-end: auto; top: auto; transform: none;
  width: 24px; height: 24px; border: 0; border-radius: 6px;
  background: transparent; color: var(--rp-ink-3); cursor: pointer;
  font-size: 16px; line-height: 1; padding: 0;
}
.crm-search-x:hover { background: rgb(var(--ch-lift) / .06); color: var(--rp-ink-1); }

.crm-filterbtn {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  flex: none;
  min-height: 34px;
  padding: 0 12px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-sm);
  background: rgb(var(--ch-lift) / 0.03);
  color: var(--rp-ink-2);
  font-size: 12.5px;
  cursor: pointer;
}
.crm-filterbtn:hover { border-color: var(--rp-line-2); color: var(--rp-ink); }
.crm-filterbtn.on { border-color: rgb(var(--ch-blue2) / 0.45); color: var(--rp-ink-max); background: rgb(var(--ch-blue2) / 0.1); }
.crm-filterbtn-badge {
  display: grid; place-items: center;
  min-width: 19px; height: 19px;
  padding: 0 5px;
  border-radius: var(--rp-r-pill);
  background: var(--rp-blue);
  color: var(--rp-on-accent);
  font-size: 10.5px;
  font-weight: 660;
}
.crm-clearfilters {
  flex: none;
  min-height: 34px;
  padding: 0 6px;
  border: 0;
  background: none;
  color: var(--rp-ink-2);
  font-size: 12.5px;
  cursor: pointer;
}
.crm-clearfilters:hover { color: var(--sh-blue-1); }
.crm-bar-count { margin-inline-start: auto; flex: none; }
.crm-bar-more { padding-top: 2px; }
.crm-tabrow .crm-pick-pipeline select { min-height: 34px; }
.crm-kpi-tile {
  display: grid;
  gap: 3px;
  align-content: start;
  padding: var(--rp-4);
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r);
  background: var(--rp-panel);
  box-shadow: none;
}
.crm-kpi-tile.accent { border-color: rgb(var(--ch-blue2) / 0.4); background: rgb(var(--ch-blue2) / 0.06); }
.crm-kpi-lbl { color: var(--rp-ink-2); font-size: 12px; font-weight: 500; }
.crm-kpi-val {
  color: var(--rp-ink-max);
  font-size: 23px;
  font-weight: 660;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
  line-height: 1.15;
}
.crm-kpi-sub { color: var(--rp-ink-3); font-size: 11px; }
.crm-kpi-note { margin: var(--rp-3) 0 0; color: var(--rp-ink-3); font-size: 11.5px; line-height: 1.5; }

/* 03's tab row: the section tabs on the left, «Экспорт» and the «…» overflow
   menu on the right, all on one line. */
.crm-tabrow { display: flex; align-items: center; gap: var(--rp-2); }
.crm-tabrow .crm-tabs { flex: 1 1 auto; min-width: 0; }
.crm-tabrow-actions { flex: none; display: flex; align-items: center; gap: var(--rp-2); }
.crm-more { position: relative; }
.crm-more-trigger { min-width: 38px; padding: 0 10px; letter-spacing: 0.08em; }
.crm-more-menu { inset-inline-end: 0; width: min(240px, calc(100vw - 32px)); }

/* Both halves of 03's bottom row keep their column, including the one whose
   source has not answered. */
.crm-bottom { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--rp-3); align-items: stretch; }
@media (max-width: 900px) { .crm-bottom { grid-template-columns: minmax(0, 1fr); } }
.crm-attention.quiet {
  display: flex;
  flex-direction: column;
  gap: var(--rp-2);
  padding: 13px var(--rp-4);
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r);
  background: var(--rp-panel);
}
.crm-attention-title { margin: 0; font-size: 14px; font-weight: 620; color: var(--rp-ink); }
/* The queue's honest state fills its half of 03's bottom row without setting
   that row's height — it was 233px against the tasks panel's 186. */
.crm-attention.quiet .rp-nosource { flex: 1 1 auto; min-height: 108px; padding: var(--rp-3); }

/* Filter bar: flat, on the page rather than in a raised card. */
.crm-bar {
  gap: var(--rp-3);
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  box-shadow: none;
}
.crm-bar-row { gap: var(--rp-2); align-items: center; flex-wrap: wrap; }
.crm-bar-title { font-size: 15px; font-weight: 620; letter-spacing: -0.02em; color: var(--rp-ink); }
.crm-bar-count { color: var(--rp-ink-3); font-size: 11.5px; }

.crm-search input, .crm-pick, .crm-bar select, .crm-bar input[type="search"], .crm-bar input[type="text"] {
  min-height: 34px;
  padding: 0 10px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-sm);
  background: rgb(var(--ch-lift) / 0.03);
  color: var(--rp-ink);
  font-size: 12.5px;
}
.crm-search input:focus, .crm-pick:focus { border-color: rgb(var(--ch-blue2) / 0.5); outline: none; }

/* The old Канбан/Список segmented toggle is now the middle of the 03 tab row
   above. Two controls driving one piece of state is the legacy composition
   this pass exists to remove, so the toolbar copy goes. The markup stays put
   until the toolbar is next touched for real — hiding it changes nothing that
   can break, deleting it mid-pass could. */
.crm-bar .crm-viewtoggle { display: none; }

/* Kept for any other surface that still renders a segmented view switch. */
.crm-viewtoggle {
  gap: 0;
  padding: 3px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-sm);
  background: rgb(var(--ch-lift) / 0.02);
}
.crm-viewtoggle button {
  min-height: 30px;
  padding: 0 13px;
  border: 0;
  border-radius: 6px;
  background: none;
  color: var(--rp-ink-2);
  font-size: 12.5px;
}
.crm-viewtoggle button.active, .crm-viewtoggle button[aria-pressed="true"] {
  background: var(--rp-blue);
  color: var(--rp-on-accent);
  font-weight: 600;
}

/* ── the pipeline board ─────────────────────────────────────────────────── */
.kb { gap: var(--rp-3); min-width: 0; }
/* The board scrolls inside its own column instead of pushing past the page
   edge. At 1920 the fifth stage was being clipped by the viewport — 03 shows
   all five columns, and a board that loses one is not that board. */
.kb-cols {
  gap: var(--rp-2);
  overflow-x: auto;
  scrollbar-width: thin;
  padding-bottom: 4px;
}
/* FIVE COLUMNS MUST FIT BESIDE THE SEGMENT RAIL AT 1440, WHICH IS WHAT 03 AND
   12 BOTH SHOW. Measured: content column 1154px − rail 176 − gap 12 = 966 for
   the board, so a 236px minimum clipped the fifth stage off the screen and the
   acceptance shot showed a four-and-a-bit board. 03's own cards are 232px at
   1448 with no rail; 12's, which does have the rail, are narrower still. 176px
   holds a company name, a money figure and an owner chip without wrapping. */
.kb-col { min-width: 176px; flex: 1 1 176px; }
@media (min-width: 1600px) { .kb-col { min-width: 212px; flex-basis: 212px; } }

/* Columns are quieter than the cards they hold — the reverse of the legacy
   board, where the column was a raised gradient panel and the cards sank into
   it. In 03 the column is a field and each lead is a surface on top of it. */
.kb-col {
  gap: 0;
  padding: 9px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r);
  background: rgb(var(--ch-lift) / 0.014);
  box-shadow: none;
}
/* 03's cards sit ~5px apart. `gap` on the column itself was adding a second
   space on top of the body's own, which is where the airiness between the
   header, the cards and the footer buttons came from. */
.kb-col-body { gap: 5px !important; margin-top: 0 !important; }
/* 03's column header is its OWN bordered box above the cards: name and count on
   the first line, the stage total and the fold control on the second. */
.kb-col-head {
  display: grid;
  gap: 1px;
  padding: 5px 9px;
  margin-bottom: 6px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-sm);
  background: rgb(var(--ch-lift) / 0.022);
}
.kb-col-headline { display: flex; align-items: center; gap: 6px; min-width: 0; }
.kb-col-name {
  flex: 1 1 auto;
  min-width: 0;
  font-size: 12px;
  font-weight: 620;
  letter-spacing: -0.01em;
  color: var(--rp-ink);
  /* Not uppercase: the stage name is the client's own string and SHOUTING IT
     makes a Russian funnel unreadable at 12px. */
  text-transform: none;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.kb-col-count {
  flex: none;
  color: var(--rp-ink-2);
  font-size: 11.5px;
  font-weight: 620;
  font-variant-numeric: tabular-nums;
}
.kb-col-fold, .kb-col-unfold {
  flex: none;
  display: grid; place-items: center;
  width: 18px; height: 18px; min-height: 18px;
  padding: 0;
  border: 1px solid transparent;
  border-radius: 5px;
  background: none;
  color: var(--rp-ink-3);
  cursor: pointer;
}
.kb-col-fold:hover, .kb-col-unfold:hover { border-color: var(--rp-line-2); color: var(--rp-ink); }
.kb-col-chevron { font-size: 12px; line-height: 1; }

/* A folded column: 40px of rail with the stage name turned on its side and its
   count at the top, so what it is worth is never hidden by putting it away. */
.kb-col.kb-col-folded {
  min-width: 40px;
  max-width: 40px;
  flex: 0 0 40px;
  padding: var(--rp-2) 0;
  align-content: start;
}
.kb-col-unfold {
  width: 100%;
  height: auto;
  min-height: 120px;
  display: grid;
  justify-items: center;
  align-content: start;
  gap: 8px;
  padding: 4px 0;
}
.kb-col-foldname {
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  max-height: 190px;
  overflow: hidden;
  color: var(--rp-ink-2);
  font-size: 11.5px;
  font-weight: 600;
  white-space: nowrap;
}
.kb-col-foldcount {
  color: var(--rp-ink);
  font-size: 11px;
  font-weight: 660;
  font-variant-numeric: tabular-nums;
}

/* The per-column money total from 03 and 12 — already computed, now legible. */
.kb-col-sum {
  flex: 1 1 auto;
  margin: 0;
  color: var(--rp-ink);
  font-size: 12px;
  font-weight: 620;
  font-variant-numeric: tabular-nums;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* «+ Добавить лид» closes every column in 03. */
.kb-col-add {
  width: 100%;
  min-height: 28px;
  margin-top: 5px;
  border: 1px dashed rgb(var(--ch-slate) / 0.28);
  border-radius: var(--rp-r-sm);
  background: none;
  color: var(--rp-ink-3);
  font-size: 11.5px;
  cursor: pointer;
}
.kb-col-add:hover:not(.is-off) { border-color: rgb(var(--ch-blue2) / 0.5); color: var(--sh-blue-1); }
.kb-col-add.is-off { cursor: not-allowed; opacity: 0.5; }

/* Lead temperature (03): the record's own priority field, as a word. */
.kb-temp {
  flex: none;
  padding: 1px 7px;
  border-radius: var(--rp-r-pill);
  font-size: 9.5px;
  font-weight: 650;
  white-space: nowrap;
}
.kb-temp.high { background: rgb(var(--ch-red) / 0.16); color: var(--lg-red-4); }
.kb-temp.normal { background: rgb(var(--ch-amber) / 0.15); color: var(--sh-warm); }
.kb-temp.low { background: rgb(var(--ch-slate) / 0.14); color: var(--rp-ink-3); }
.kb-card-row { display: flex; align-items: center; justify-content: space-between; gap: 6px; line-height: 1.2; }
.kb-card-value.muted { color: var(--rp-ink-3); }
.kb-col-empty { color: var(--rp-ink-3); font-size: 11.5px; padding: var(--rp-2) 0; }
/* The «показано N из M» line and «Показать ещё» were three separate stacked
   blocks with their own margins. They are one footer now, tight under the last
   card, so the space 03 gives to cards is not spent on chrome. */
.kb-col-more { display: grid; gap: 4px; margin-top: 6px; }
.kb-col-more > span { color: var(--rp-ink-3); font-size: 10.5px; }
.kb-col-morebtn {
  min-height: 26px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-sm);
  background: rgb(var(--ch-lift) / 0.02);
  color: var(--rp-ink-2);
  font-size: 11px;
}

/* Lead cards: dense, flat, 8px. 03 fits five columns of these on one screen. */
/* 03's card is 91px tall in a 175px column — four rows and 10px of padding.
   Ours measured 136 in a 279px column, so the gaps and padding come down; the
   rows themselves are unchanged. */
.kb-card {
  display: grid;
  gap: 2px;
  padding: 6px 9px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-sm);
  background: var(--rp-panel);
  box-shadow: none;
  cursor: pointer;
  transition: border-color 130ms ease, background 130ms ease;
}
.kb-card:hover { border-color: rgb(var(--ch-blue2) / 0.45); background: var(--rp-panel-2); transform: none; }
.kb-card-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; }
.kb-card-top strong {
  min-width: 0;
  font-size: 12.5px; font-weight: 590; line-height: 1.3; color: var(--rp-ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* The square action button of 03, top-right of every card. */
.kb-card-go {
  flex: none;
  display: grid; place-items: center;
  /* 16px in the reference, measured at 16×. */
  width: 16px; height: 16px; min-height: 16px;
  padding: 0;
  border: 1px solid var(--rp-line-2);
  border-radius: 5px;
  background: rgb(var(--ch-lift) / 0.03);
  cursor: pointer;
}
.kb-card-go:hover { border-color: rgb(var(--ch-blue2) / 0.55); background: rgb(var(--ch-blue2) / 0.14); }
.kb-card-go-glyph {
  width: 11px; height: 11px;
  background-color: var(--rp-ink-2);
  -webkit-mask: var(--kb-arrow) center / contain no-repeat;
  mask: var(--kb-arrow) center / contain no-repeat;
  --kb-arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h13M12.5 5.5 19 12l-6.5 6.5'/%3E%3C/svg%3E");
}
.kb-card-go:hover .kb-card-go-glyph { background-color: var(--sh-blue-1); }

/* The owner line of 03: avatar, name, and the channel's own glyph on the far
   right. The contact line and the tag strip are not on this card — they are in
   the drawer, where the reference puts them. */
.kb-card-owner { display: flex; align-items: center; gap: 6px; min-width: 0; }
.kb-card-ava {
  flex: none;
  display: grid; place-items: center;
  width: 16px; height: 16px;
  border-radius: 50%;
  background: rgb(var(--ch-blue2) / 0.18);
  color: var(--sh-blue-4);
  font-size: 8.5px;
  font-weight: 640;
}
.kb-card-ownername {
  flex: 1 1 auto; min-width: 0;
  color: var(--rp-ink-2); font-size: 11px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.kb-card-ownername.muted { color: var(--rp-ink-3); }
/* The channel badge is 24px by default and was the tallest thing on the row,
   setting the card's last line. 03's is the size of the avatar beside it. */
.kb-card-owner .provider-avatar { width: 18px; height: 18px; min-width: 18px; flex: none; }
.kb-card-owner .provider-avatar img { width: 18px; height: 18px; }
.kb-card-source { flex: 1 1 auto; min-width: 0; color: var(--rp-ink-3); font-size: 10.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kb-card-source.muted { opacity: 0.7; }
.kb-card-value {
  flex: none;
  color: var(--rp-ink-max);
  font-size: 12px;
  font-weight: 640;
  font-variant-numeric: tabular-nums;
}
.kb-card-contact { margin: 0; color: var(--rp-ink-3); font-size: 11.5px; }
/* 03 separates the money line from the channel/owner lines with a hairline. */
.kb-card-meta {
  display: flex; align-items: center; gap: 6px;
  padding-top: 4px;
  border-top: 1px solid var(--rp-line);
  line-height: 1.2;
}
.kb-card-age { flex: none; color: var(--rp-ink-3); font-size: 10.5px; white-space: nowrap; }
.kb-card-tags { display: flex; gap: 4px; flex-wrap: wrap; }
.kb-tag, .kb-chip {
  padding: 2px 7px;
  border-radius: var(--rp-r-pill);
  border: 1px solid var(--rp-line);
  background: rgb(var(--ch-lift) / 0.03);
  color: var(--rp-ink-2);
  font-size: 10px;
  font-weight: 550;
}
.kb-chip.task { border-color: rgb(var(--ch-amber) / 0.35); background: rgb(var(--ch-amber) / 0.12); color: var(--rp-amber); }

/* ═══ THE LEAD DRAWER OF 03 ══════════════════════════════════════════════
   Measured on the reference: the column is 293px of a 1448px board — 20.2% —
   leaving the pipeline 78–80% and still readable. 420px at 1920 is 21.9%, which
   is the same column. */
.kb-panel.kb-panel-lead {
  /* The RATIO is what the reference fixes, not the pixel count: 293 of 1448
     leaves the board 79.8%. A fixed 420px holds that at 1920 (78.1%) but drops
     the board to 70.1% at 1440, so the width tracks the viewport and the board
     keeps 77–78% at both. The 330px floor is where the contact row and the five
     quick-action tiles stop fitting. */
  width: var(--kb-drawer-w);
  padding: 0;
  overflow-y: auto;
}

/* THE DRAWER IS A COLUMN, SO THE PAGE MAKES ROOM FOR IT.
   In 03 the whole content column — filter row, KPI strip, board and the two
   bottom blocks — is narrower while the card is open; the drawer does not lie
   over it. Ours was an overlay, so the sixth KPI cell and the fifth pipeline
   stage were simply hidden underneath it, which is why the board "keeping 78%"
   did not mean the board was readable. The top bar keeps its full width by
   cancelling the extra padding, exactly as it already cancels the workspace's
   own — in the reference the account row spans the screen and the drawer starts
   below it.

   `!important` here is answering one, not starting one: styles.css pins
   `.workspace { padding-inline-end: 44px !important }`. Everywhere else in this
   redesign the legacy pin has been DELETED instead — but that one also sets
   padding-left, so removing it would move the Overview's content column, and
   the Overview is already visually accepted. Scoped to the drawer-open state,
   this changes nothing anywhere else. */
.app-shell:has(.kb-panel-lead) .workspace {
  padding-inline-end: calc(var(--kb-drawer-w) + var(--rp-5)) !important;
}
/* The bar still reaches the screen edge; only the page under it narrows. */
.app-shell:has(.kb-panel-lead) .rp-topbar {
  margin-inline-end: calc((var(--kb-drawer-w) + var(--rp-5)) * -1);
}
/* With the card open the board has ~1030px for five stages, so the ≥1600px
   floor of 212 has to give — otherwise the fifth column is pushed 62px past the
   edge and «Сделки» is clipped, which is the exact defect this pass fixed on
   the closed board. 176 is where a company name and a money figure still fit. */
.app-shell:has(.kb-panel-lead) .kb-col:not(.kb-col-folded) {
  min-width: 176px;
  flex-basis: 176px;
}
.kb-panel-lead .kb-fields { grid-template-columns: minmax(0, 1fr); }
.kb-panel-lead .kb-summary { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.kb-panel-lead .kb-readonly { grid-template-columns: minmax(0, 1fr); }

/* ── 1 · header ─────────────────────────────────────────────────────────── */
/* ── DENSITY: THE NINE BLOCKS FIT 1080 WITHOUT SCROLLING ─────────────────
   03 stacks all nine in ~930px of a 1086px canvas. This panel needed 1305px,
   so the timeline fell below the fold and the card had to be scrolled to be
   read — which is not the reference's screen. Every value below is a vertical
   one: paddings, gaps, control heights and line-heights. No block is removed,
   no font drops below 11px, and nothing horizontal changes. */
.kb-panel-lead .kb-panel-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--rp-3);
  padding: 13px var(--rp-4) 10px;
  border-bottom: 1px solid var(--rp-line);
  background: none;
}
.kb-panel-lead .kb-head-copy { min-width: 0; }
.kb-panel-lead .kb-panel-head h3 {
  margin: 0 0 4px;
  font-size: 17px;
  font-weight: 660;
  letter-spacing: -0.02em;
  line-height: 1.2;
  color: var(--rp-ink-max);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.kb-head-meta { display: flex; align-items: center; gap: 9px; }
.kb-head-id { color: var(--rp-ink-3); font-size: 11px; font-variant-numeric: tabular-nums; }
.kb-panel-lead .kb-close {
  flex: none;
  display: grid; place-items: center;
  width: 28px; height: 28px; min-height: 28px;
  padding: 0;
  border: 1px solid var(--rp-line);
  border-radius: 8px;
  background: rgb(var(--ch-lift) / 0.03);
  color: var(--rp-ink-2);
  font-size: 15px;
  cursor: pointer;
}
.kb-panel-lead .kb-close:hover { border-color: var(--rp-line-2); color: var(--rp-ink-max); }

/* Blocks are separated by the reference's hairlines, not by cards-in-a-card. */
.kb-read-block { padding: 11px var(--rp-4); border-bottom: 1px solid var(--rp-line); }
.kb-read-block:last-child { border-bottom: 0; padding-bottom: var(--rp-4); }
.kb-read-cap { margin: 0 0 7px; color: var(--rp-ink-3); font-size: 11px; line-height: 1.2; }
.kb-read-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--rp-3); margin-bottom: 7px; }
.kb-read-head h4 { margin: 0; font-size: 13.5px; font-weight: 640; line-height: 1.2; color: var(--rp-ink); }
.kb-linkbtn {
  padding: 0; border: 0; background: none;
  color: var(--sh-blue-2); font-size: 12px; font-weight: 550; cursor: pointer;
}
.kb-linkbtn:hover { color: var(--sh-blue-1); }

/* ── 2 · deal parameters ────────────────────────────────────────────────── */
.kb-params { display: grid; gap: 8px; }
.kb-param { display: grid; grid-template-columns: 96px minmax(0, 1fr); align-items: center; gap: 10px; }
.kb-param > span { color: var(--rp-ink-2); font-size: 12px; line-height: 1.25; }
.kb-param > strong {
  color: var(--rp-ink-max); font-size: 13.5px; font-weight: 640;
  line-height: 1.25;
  font-variant-numeric: tabular-nums;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.kb-param > strong.muted { color: var(--rp-ink-3); font-weight: 550; }
.kb-param-select {
  width: 100%;
  min-height: 32px;
  padding: 0 10px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-sm);
  background: rgb(var(--ch-lift) / 0.03);
  color: var(--rp-ink);
  font-size: 12.5px;
}
/* Срок закрытия набирается прямо на карточке: это единственное поле, которое
   читает прогноз, и прятать его за формой правки значит оставить прогноз
   пустым. Тот же размер, что и у селектора этапа рядом. */
.kb-param-date {
  width: 100%;
  min-height: 32px;
  padding: 0 10px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-sm);
  background: rgb(var(--ch-lift) / 0.03);
  color: var(--rp-ink);
  font-size: 12.5px;
  font-variant-numeric: tabular-nums;
}

/* 03 puts the percentage and its bar on the same line as the label. */
.kb-param-prob { grid-template-columns: 96px auto minmax(0, 1fr); }
.kb-param-prob > strong { font-size: 13px; }
.kb-param-prob .kb-prob-track, .kb-param-prob .kb-prob-slider { margin: 0; }

/* ── 3 · company ────────────────────────────────────────────────────────── */
.kb-company { display: flex; align-items: center; gap: 10px; }
.kb-company-mark {
  flex: none;
  width: 30px; height: 30px;
  border: 1px solid var(--rp-line);
  border-radius: 9px;
  background: rgb(var(--ch-blue2) / 0.10) var(--kb-building) center / 17px no-repeat;
  --kb-building: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%237fb0ff' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 20.5h16M6 20.5V5.5a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v15M14 20.5V10h3a1 1 0 0 1 1 1v9.5'/%3E%3Cpath d='M8.4 8h2.6M8.4 11.4h2.6M8.4 14.8h2.6'/%3E%3C/svg%3E");
}
.kb-company strong { font-size: 14px; font-weight: 620; line-height: 1.2; color: var(--rp-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kb-company strong.muted { color: var(--rp-ink-3); }

/* ── 4 · contact ────────────────────────────────────────────────────────── */
.kb-contact { display: flex; align-items: center; gap: 10px; }
.kb-contact-avatar {
  flex: none;
  display: grid; place-items: center;
  width: 34px; height: 34px;
  border-radius: 50%;
  border: 1px solid rgb(var(--ch-blue2) / 0.35);
  background: rgb(var(--ch-blue2) / 0.16);
  color: var(--sh-blue-4);
  font-size: 14px;
  font-weight: 640;
}
.kb-contact-id { flex: 1 1 auto; min-width: 0; display: grid; gap: 1px; }
.kb-contact-id strong { font-size: 12.5px; font-weight: 620; line-height: 1.25; color: var(--rp-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kb-contact-id span { font-size: 11px; line-height: 1.25; color: var(--rp-ink-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kb-contact-actions { flex: none; display: flex; gap: 5px; }
.kb-cbtn {
  display: grid; place-items: center;
  width: 30px; height: 30px; min-height: 30px;
  padding: 0;
  border: 1px solid rgb(var(--ch-blue2) / 0.32);
  border-radius: 9px;
  background: rgb(var(--ch-blue2) / 0.10);
  cursor: pointer;
}
.kb-cbtn::before {
  content: "";
  width: 15px; height: 15px;
  background-color: var(--sh-blue-3);
  -webkit-mask: var(--kb-glyph) center / contain no-repeat;
  mask: var(--kb-glyph) center / contain no-repeat;
}
.kb-cbtn:hover { background: rgb(var(--ch-blue2) / 0.2); }
.kb-cbtn.is-off { border-color: var(--rp-line); background: rgb(var(--ch-lift) / 0.02); cursor: not-allowed; }
.kb-cbtn.is-off::before { background-color: var(--rp-ink-3); opacity: 0.6; }
.kb-cbtn-call { --kb-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6.3 3.9c1 0 1.6.5 2 1.5l.9 2.2c.3.8.1 1.5-.6 2l-1 .8a11.4 11.4 0 0 0 5 5l.8-1c.5-.7 1.2-.9 2-.6l2.2.9c1 .4 1.5 1 1.5 2 0 2.3-1.9 3.4-3.9 3.4C8.3 20.1 3.9 15.7 3.9 7.8c0-2 1.1-3.9 2.4-3.9z'/%3E%3C/svg%3E"); }
.kb-cbtn-wa { --kb-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20.4 11.8c0 4.2-3.5 7.6-7.8 7.6a7.9 7.9 0 0 1-3.7-.9L4.4 20l1.6-4.3a7.4 7.4 0 0 1-1.2-4c0-4.2 3.5-7.6 7.8-7.6s7.8 3.4 7.8 7.7z'/%3E%3Cpath d='M9.4 9.2c.2 1.9 2 3.9 4.1 4.5l1-1.2 1.7.8c-.2 1.2-1.5 1.6-2.6 1.3-2.6-.6-4.7-2.8-5.2-5.2-.2-1 .3-2.1 1.4-2.3l.8 1.7z'/%3E%3C/svg%3E"); }
.kb-cbtn-wa:not(.is-off) { border-color: rgb(var(--ch-green) / 0.4); background: rgb(var(--ch-green) / 0.12); }
.kb-cbtn-wa:not(.is-off)::before { background-color: var(--lg-ok-2); }
.kb-cbtn-mail { --kb-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='5.5' width='18' height='13' rx='2.4'/%3E%3Cpath d='m3.6 7 8.4 5.6L20.4 7'/%3E%3C/svg%3E"); }
.kb-cbtn-in { --kb-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3.4' y='3.4' width='17.2' height='17.2' rx='3'/%3E%3Cpath d='M8 10.6v6M8 7.4v.1M12 16.6v-3.4a2 2 0 0 1 4 0v3.4M12 16.6v-6'/%3E%3C/svg%3E"); }

.kb-contact-lines { display: grid; gap: 5px; margin-top: 9px; }
.kb-cline { display: flex; align-items: center; gap: 9px; min-width: 0; font-size: 12px; line-height: 1.35; }
.kb-cline::before {
  content: "";
  flex: none;
  width: 14px; height: 14px;
  background-color: var(--rp-ink-3);
  -webkit-mask: var(--kb-glyph) center / contain no-repeat;
  mask: var(--kb-glyph) center / contain no-repeat;
}
.kb-cline a { color: var(--sh-blue-2); text-decoration: none; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kb-cline a:hover { text-decoration: underline; }
.kb-cline span { color: var(--rp-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kb-cline span.muted { color: var(--rp-ink-3); }
.kb-cline-phone { --kb-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6.3 3.9c1 0 1.6.5 2 1.5l.9 2.2c.3.8.1 1.5-.6 2l-1 .8a11.4 11.4 0 0 0 5 5l.8-1c.5-.7 1.2-.9 2-.6l2.2.9c1 .4 1.5 1 1.5 2 0 2.3-1.9 3.4-3.9 3.4C8.3 20.1 3.9 15.7 3.9 7.8c0-2 1.1-3.9 2.4-3.9z'/%3E%3C/svg%3E"); }
.kb-cline-mail { --kb-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='5.5' width='18' height='13' rx='2.4'/%3E%3Cpath d='m3.6 7 8.4 5.6L20.4 7'/%3E%3C/svg%3E"); }
.kb-cline-pin { --kb-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 21s7-5.6 7-10.6A7 7 0 0 0 5 10.4C5 15.4 12 21 12 21z'/%3E%3Ccircle cx='12' cy='10.3' r='2.5'/%3E%3C/svg%3E"); }

/* ── 5 · service data + tags ────────────────────────────────────────────── */
.kb-service { display: grid; gap: 5px; }
.kb-srow { display: grid; grid-template-columns: 132px minmax(0, 1fr); align-items: center; gap: 10px; }
.kb-srow > span { color: var(--rp-ink-3); font-size: 11.5px; line-height: 1.35; }
.kb-srow > strong {
  font-size: 12px; font-weight: 570; line-height: 1.35; color: var(--rp-ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.kb-srow > strong.muted { color: var(--rp-ink-3); }
.kb-srow-tags { margin-top: 8px; align-items: center; }
.kb-tagrow { display: flex; align-items: center; gap: 5px; flex-wrap: wrap; }
.kb-tagrow .kb-tag.muted { color: var(--rp-ink-3); }
/* 03 tints VIP amber — keyed on the tag's own name, see the call site. */
.kb-tagrow .kb-tag.vip {
  border-color: rgb(var(--ch-amber) / 0.45);
  background: rgb(var(--ch-amber) / 0.12);
  color: var(--rp-amber);
  font-weight: 640;
}
.kb-tagadd {
  display: grid; place-items: center;
  width: 22px; height: 22px; min-height: 22px;
  padding: 0;
  border: 1px solid var(--rp-line);
  border-radius: 7px;
  background: rgb(var(--ch-lift) / 0.03);
  color: var(--rp-ink-2);
  font-size: 13px;
  cursor: pointer;
}
.kb-tagadd:hover { border-color: var(--rp-line-2); color: var(--rp-ink-max); }

/* ── 6 · notes ──────────────────────────────────────────────────────────── */
/* Three lines is the reference's note block; a longer note is clamped rather
   than allowed to push the timeline off the screen. */
.kb-notetext {
  margin: 0;
  color: var(--rp-ink-2);
  font-size: 12px;
  line-height: 1.45;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.kb-notetext.muted { color: var(--rp-ink-3); }

/* ── 7 · quick actions ──────────────────────────────────────────────────── */
.kb-quick { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 5px; }
.kb-qa {
  display: grid;
  justify-items: center;
  gap: 5px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--rp-ink-2);
  cursor: pointer;
}
.kb-qa-icon {
  width: 38px; height: 38px;
  border: 1px solid var(--rp-line);
  border-radius: 11px;
  background: rgb(var(--ch-lift) / 0.03);
  display: grid; place-items: center;
}
.kb-qa-icon::before {
  content: "";
  width: 17px; height: 17px;
  background-color: var(--rp-ink-2);
  -webkit-mask: var(--kb-glyph) center / contain no-repeat;
  mask: var(--kb-glyph) center / contain no-repeat;
}
.kb-qa-label { font-size: 9.5px; line-height: 1.2; text-align: center; overflow-wrap: anywhere; }
.kb-qa:hover:not(.is-off) .kb-qa-icon { border-color: rgb(var(--ch-blue2) / 0.45); background: rgb(var(--ch-blue2) / 0.12); }
.kb-qa:hover:not(.is-off) .kb-qa-icon::before { background-color: var(--sh-blue-3); }
.kb-qa.is-off { cursor: not-allowed; color: var(--rp-ink-3); }
.kb-qa.is-off .kb-qa-icon { opacity: 0.45; }
.kb-qa.accent .kb-qa-icon { border-color: rgb(var(--ch-blue2) / 0.4); background: rgb(var(--ch-blue2) / 0.14); }
.kb-qa.accent .kb-qa-icon::before { background-color: var(--sh-blue-3); }
/* 03 colours the channel glyphs by channel — WhatsApp green, Email blue — and
   leaves the rest neutral. Five identical grey tiles is not that row. */
.kb-qa:not(.is-off) .kb-qa-wa::before { background-color: var(--lg-ok-2); }
.kb-qa:not(.is-off) .kb-qa-mail::before { background-color: var(--sh-blue-2); }
.kb-qa-call { --kb-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6.3 3.9c1 0 1.6.5 2 1.5l.9 2.2c.3.8.1 1.5-.6 2l-1 .8a11.4 11.4 0 0 0 5 5l.8-1c.5-.7 1.2-.9 2-.6l2.2.9c1 .4 1.5 1 1.5 2 0 2.3-1.9 3.4-3.9 3.4C8.3 20.1 3.9 15.7 3.9 7.8c0-2 1.1-3.9 2.4-3.9z'/%3E%3C/svg%3E"); }
.kb-qa-wa { --kb-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20.4 11.8c0 4.2-3.5 7.6-7.8 7.6a7.9 7.9 0 0 1-3.7-.9L4.4 20l1.6-4.3a7.4 7.4 0 0 1-1.2-4c0-4.2 3.5-7.6 7.8-7.6s7.8 3.4 7.8 7.7z'/%3E%3Cpath d='M9.4 9.2c.2 1.9 2 3.9 4.1 4.5l1-1.2 1.7.8c-.2 1.2-1.5 1.6-2.6 1.3-2.6-.6-4.7-2.8-5.2-5.2-.2-1 .3-2.1 1.4-2.3l.8 1.7z'/%3E%3C/svg%3E"); }
.kb-qa-mail { --kb-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='5.5' width='18' height='13' rx='2.4'/%3E%3Cpath d='m3.6 7 8.4 5.6L20.4 7'/%3E%3C/svg%3E"); }
.kb-qa-task { --kb-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3.6' y='4.6' width='16.8' height='16' rx='2.6'/%3E%3Cpath d='M8 3v3.2M16 3v3.2M9 13.4l2 2 4-4'/%3E%3C/svg%3E"); }
.kb-qa-open { --kb-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M13.6 4.4h6v6M19.6 4.4 11 13'/%3E%3Cpath d='M18.4 13.6v5a1.4 1.4 0 0 1-1.4 1.4H5.4A1.4 1.4 0 0 1 4 18.6V7a1.4 1.4 0 0 1 1.4-1.4h5'/%3E%3C/svg%3E"); }

.kb-openfull {
  width: 100%;
  min-height: 36px;
  margin-top: 11px;
  border: 1px solid rgb(var(--ch-blue2) / 0.4);
  border-radius: 10px;
  background: rgb(var(--ch-blue2) / 0.09);
  color: var(--sh-blue-1);
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
}
.kb-openfull:hover { background: rgb(var(--ch-blue2) / 0.16); color: var(--sh-blue-4); }

/* ── 9 · activity timeline ──────────────────────────────────────────────── */
.kb-timeline { display: grid; gap: 6px; margin: 0; padding: 0; list-style: none; }
.kb-timeline li {
  position: relative;
  display: grid;
  grid-template-columns: 12px 78px minmax(0, 1fr);
  align-items: start;
  gap: 8px;
}
.kb-tl-dot {
  position: relative;
  width: 7px; height: 7px;
  margin-block: 9px 0; margin-inline: 3px 0;
  border-radius: 50%;
  background: var(--rp-blue);
}
/* The connecting rule of 03 — drawn between dots, never past the last one. */
.kb-timeline li:not(:last-child) .kb-tl-dot::after {
  content: "";
  position: absolute;
  inset-inline-start: 50%; top: 10px;
  width: 1px; height: calc(100% + 26px);
  margin-inline-start: -0.5px;
  background: rgb(var(--ch-slate) / 0.22);
}
.kb-tl-when { padding-top: 6px; color: var(--rp-ink-3); font-size: 10.5px; line-height: 1.3; }
.kb-tl-body {
  display: grid;
  gap: 1px;
  min-width: 0;
  padding: 6px 9px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-sm);
  background: var(--rp-panel-2);
}
.kb-tl-body strong { font-size: 11.5px; font-weight: 600; line-height: 1.3; color: var(--rp-ink); }
/* One line: a long note in an event row is what pushed the third event under
   the fold. The full text is in the note block above and in «Вся история». */
.kb-tl-body span {
  font-size: 11px;
  line-height: 1.3;
  color: var(--rp-ink-3);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* The rehomed editor keeps its own padding, since the read blocks own theirs. */
.kb-panel-lead.is-editing .kb-panel-body,
.kb-panel-lead.is-editing .kb-tabs,
.kb-panel-lead.is-editing .crm-comm,
.kb-panel-lead.is-editing .kb-clientlink { margin-inline: var(--rp-4); }
.kb-backbtn {
  margin: var(--rp-3) var(--rp-4) 0;
  padding: 0;
  border: 0;
  background: none;
  color: var(--sh-blue-2);
  font-size: 12px;
  font-weight: 550;
  cursor: pointer;
  text-align: start;
}
.kb-backbtn:hover { color: var(--sh-blue-1); }
/* Six tab labels do not fit 460px, and a tab reading «Заметк…» is a tab nobody
   can identify. They keep their full names and the row scrolls. */
.kb-panel-lead .kb-tabs {
  overflow-x: auto;
  scrollbar-width: none;
  flex-wrap: nowrap;
}
.kb-panel-lead .kb-tabs::-webkit-scrollbar { display: none; }
.kb-panel-lead .kb-tabs > button {
  flex: none;
  white-space: nowrap;
  overflow: visible;
  text-overflow: clip;
}

/* 03's five round quick actions stay in one row at the narrower width. */
.kb-panel-lead .crm-comm-actions { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 6px; }
.kb-panel-lead .crm-comm-action { min-height: 58px; padding: 8px 4px; font-size: 10.5px; }
.kb-panel-lead .crm-comm-action span:last-child { overflow-wrap: anywhere; }

/* «Вероятность» from 03 — a labelled value over a track. Real and writable
   where the workspace declares the field, an empty track and a dash where it
   does not. */
.kb-prob { display: grid; gap: 6px; margin-top: var(--rp-3); }
.kb-prob-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.kb-prob-head span { color: var(--rp-ink-3); font-size: 11.5px; }
.kb-prob-head strong { color: var(--rp-ink); font-size: 13px; font-weight: 660; font-variant-numeric: tabular-nums; }
.kb-prob-track {
  height: 6px;
  border-radius: var(--rp-r-pill);
  background: rgb(var(--ch-slate) / 0.16);
  overflow: hidden;
}
.kb-prob-track i { display: block; height: 100%; background: var(--rp-blue); border-radius: inherit; }
.kb-prob-slider {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 6px;
  min-height: 6px;
  padding: 0;
  border: 0;
  border-radius: var(--rp-r-pill);
  /* Filled to the value, as 03 draws it — see the note at the call site. */
  background: linear-gradient(90deg,
    var(--rp-blue) 0,
    var(--rp-blue) var(--kb-prob-fill, 0%),
    rgb(var(--ch-slate) / 0.16) var(--kb-prob-fill, 0%),
    rgb(var(--ch-slate) / 0.16) 100%);
  cursor: pointer;
}
.kb-prob-slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 14px; height: 14px;
  border-radius: 50%;
  border: 2px solid #fff;
  background: var(--rp-blue);
  cursor: pointer;
}
.kb-prob-slider::-moz-range-thumb {
  width: 12px; height: 12px;
  border-radius: 50%;
  border: 2px solid #fff;
  background: var(--rp-blue);
  cursor: pointer;
}
.kb-prob.off .kb-prob-head strong { color: var(--rp-ink-3); }

/* The lead drawer. */
.kb-panel {
  border-inline-start: 1px solid var(--rp-line-2);
  border-radius: 0;
  background: var(--rp-panel);
  box-shadow: -22px 0 56px rgba(0, 0, 0, 0.5);
}
.kb-panel-head { padding: var(--rp-4); border-bottom: 1px solid var(--rp-line); background: none; }
.kb-panel-body { padding: var(--rp-4); }
/* THE BOARD IS NOT DIMMED WHILE THE LEAD DRAWER IS OPEN.
   03 shows the pipeline at full contrast beside the open card — that is the
   point of a drawer rather than a modal, and it is what makes "the board keeps
   75–78% of the width" mean anything. A 62% scrim with a blur made those 78%
   unreadable, so the sheet stays (click-outside-to-close is what everyone
   expects of it) and simply stops painting. The settings and import panels,
   which ARE modal, keep the dimming. */
.kb-scrim { background: rgba(4, 6, 11, 0.62); backdrop-filter: blur(2px); }
.kb-scrim:has(+ .kb-panel-lead) { background: transparent; backdrop-filter: none; }

/* Attention / queue panel. */
.crm-attention {
  padding: var(--rp-4);
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r);
  background: var(--rp-panel);
  box-shadow: none;
}
.crm-attention-head { margin-bottom: var(--rp-3); font-size: 14px; font-weight: 620; }
.crm-attention-row { padding: 9px 0; border-bottom: 1px solid var(--rp-line); font-size: 12.5px; }
.crm-attention-row:last-child { border-bottom: 0; }

/* ── the section tab row (03) and the segment rail (12) ─────────────────── */
.crm-tabs { margin-bottom: 2px; }

.crm-workarea {
  display: grid;
  grid-template-columns: 194px minmax(0, 1fr);
  gap: var(--rp-3);
  align-items: start;
}
.crm-boardarea { min-width: 0; }
/* The board with no rail beside it: one track, full width. Set as a modifier
   rather than by editing .crm-workarea, because the list view and other
   screens still use the two-track version. */
.crm-workarea-full { grid-template-columns: minmax(0, 1fr); }

.crm-segrail {
  display: grid;
  gap: 2px;
  align-content: start;
  padding: var(--rp-3);
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r);
  background: var(--rp-panel);
  position: sticky;
  top: 76px;
}
.crm-seg {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--rp-2);
  min-height: 32px;
  padding: 0 9px;
  border: 1px solid transparent;
  border-radius: var(--rp-r-sm);
  background: none;
  color: var(--rp-ink-2);
  font-size: 12px;
  font-weight: 500;
  text-align: start;
  cursor: pointer;
}
.crm-seg:hover:not(:disabled) { background: rgb(var(--ch-lift) / 0.035); color: var(--rp-ink); }
.crm-seg.on {
  background: var(--rp-blue-soft);
  border-color: rgb(var(--ch-blue2) / 0.42);
  color: var(--rp-ink-max);
  font-weight: 600;
}
/* «Мои лиды» — visibly present, visibly not available, reason on hover. */
.crm-seg:disabled { opacity: 0.42; cursor: not-allowed; }
.crm-seg-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.crm-seg-count {
  flex: none;
  padding: 1px 6px;
  border-radius: var(--rp-r-pill);
  background: rgb(var(--ch-lift) / 0.07);
  color: var(--rp-ink-2);
  font-size: 10.5px;
  font-weight: 650;
  font-variant-numeric: tabular-nums;
}
.crm-seg.on .crm-seg-count { background: rgb(var(--ch-lift) / 0.18); color: var(--rp-ink-max); }
.crm-seg-count.muted { background: none; color: var(--rp-ink-3); }
.crm-seg-sep { height: 1px; margin: 5px 0; background: var(--rp-line); }

@media (max-width: 1050px) {
  /* The rail becomes a horizontal segment strip above the board rather than
     eating a third of a narrow screen. */
  .crm-workarea { grid-template-columns: minmax(0, 1fr); }
  .crm-segrail {
    position: static;
    display: flex;
    gap: 6px;
    overflow-x: auto;
    scrollbar-width: none;
  }
  .crm-segrail::-webkit-scrollbar { display: none; }
  .crm-seg { flex: none; white-space: nowrap; }
  .crm-seg-sep { display: none; }
}

/* The group sub-nav is superseded on CRM by the 03 tab row, which now carries
   Recovery too. Two stacked tab rows repeating CRM and Meetings is the
   duplicated control the brief rules out; 03 has exactly one. */
.crm-page > .group-subnav { display: none; }

/* Same on Marketing: the single 09 tab row carries SEO now, so the group
   sub-nav above it — whose first item was also "Marketing" — goes. */
.marketing-page > .group-subnav { display: none; }

/* 03's bottom row: tasks beside the queue, under the board. */
.crm-bottom {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--rp-3);
  align-items: start;
}
.crm-tasks-all {
  padding: 0;
  border: 0;
  background: none;
  color: var(--sh-blue-2);
  font-size: 11.5px;
  cursor: pointer;
}
.crm-tasks-all:hover { color: var(--sh-blue-1); }
.crm-task-row {
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr) auto auto;
  align-items: center;
  gap: 10px;
  padding: 8px 0;
  border-bottom: 1px solid var(--rp-line);
  font-size: 12px;
}
.crm-task-row:last-child { border-bottom: 0; }
.crm-task-time { color: var(--rp-ink-2); font-variant-numeric: tabular-nums; font-weight: 600; }
.crm-task-title { color: var(--rp-ink); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.crm-task-type, .crm-task-owner { color: var(--rp-ink-3); font-size: 11px; white-space: nowrap; }

@media (max-width: 1050px) { .crm-bottom { grid-template-columns: minmax(0, 1fr); } }

/* ── the list lens (12, panel 3) ─────────────────────────────────────────────
   12 draws the CRM as one bordered panel with a quiet field inside it and a
   money total pinned to its bottom edge. The Kanban already reads that way; the
   list was the same records spilled onto the page with no panel around them, no
   foot under them and a row rhythm of its own — 939px of table where the
   accepted board is 589, which pushed «Мои задачи» and «Очередь» 321px further
   down the page on one lens than on the other.

   So: the same panel, the same field, the same foot. The rows scroll inside it
   the way the reference's panels do, which is what keeps the page one height on
   both lenses and the bottom row in one place.

   Everything here is scoped to the list view — `.crm-listv`, `.crm-list*`. None
   of it is reachable from the Overview, the board or the drawer. */
.crm-listv {
  display: grid;
  gap: 6px;
  padding: 9px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r);
  background: rgb(var(--ch-lift) / 0.014);
  min-width: 0;
}

/* The scroller. The legacy rule gives this element the panel's own border and
   radius; now that it is INSIDE the panel, a second frame 9px in from the first
   is a box in a box. Answered here rather than deleted there because
   `.crm-list-wrap` is the class the table has always been in. */
.crm-listv > .crm-list-wrap {
  border: 0;
  border-radius: 0;
  background: none;
  overflow: auto;
  scrollbar-width: thin;
  /* Fifteen rows and the head — 34 × 15 + 36 = 546, against the accepted
     board's 589. Below that the panel shrinks to its content instead of
     holding open a half-empty frame. */
  max-height: 546px;
}

.crm-list { width: 100%; border-collapse: collapse; font-size: 12px; }

/* 10.5px caption, the same one the KPI strip and the card sub-lines use. */
.crm-list th {
  position: sticky;
  top: 0;
  z-index: 1;
  /* «в CRM список… строки слишком мелкие» — 2026-08-21: was 36px. */
  height: 40px;
  padding: 0 10px;
  border-bottom: 1px solid var(--rp-line);
  background: var(--rp-panel);
  color: var(--rp-ink-3);
  font-size: 10.5px;
  font-weight: 620;
  letter-spacing: 0.04em;
  text-align: start;
  text-transform: uppercase;
  white-space: nowrap;
}
.crm-list th.sorted { color: var(--rp-ink-2); }
.crm-list th > button {
  letter-spacing: inherit;
  font-size: inherit;
  line-height: 1;
  /* ЗАПРЕТ ПЕРЕНОСА ПОВТОРЯЕТСЯ ЗДЕСЬ, И ЭТО НЕ ДУБЛИРОВАНИЕ.
     Он объявлен у ячейки выше, но текст сортируемого заголовка лежит внутри
     кнопки — отдельного блочного контекста, куда наследование не доходит.
     Из-за этого рвались пополам ровно сортируемые колонки: «ОТВЕТСТВЕНН/ЫЙ»,
     «ПРИОРИТЕ/Т», «ИСТОЧНИ/К», «АКТИВНОС/ТЬ». */
  white-space: nowrap;
}

/* КОЛОНКАМ НУЖНА ШИРИНА, А НЕ СЖАТИЕ.
   Двенадцать колонок в узком окне таблица ужимала до неразборчивого, вместо
   того чтобы позволить прокрутку вбок — а обёртка выше уже умеет прокручивать
   (overflow: auto). Минимум подобран по сумме колонок при их естественной
   ширине. */
.crm-list { min-width: 1180px; }
/* The select-all box sat 11px above the labels beside it, because a cell with a
   control in it and a cell with text in it were resolving their own baselines. */
.crm-list th, .crm-list td { vertical-align: middle; }
.crm-list input[type="checkbox"] { display: block; margin: 0; }

.crm-list td {
  /* Was 34px, matching th's own bump above. */
  height: 42px;
  padding: 0 10px;
  border-bottom: 1px solid var(--rp-line);
  color: var(--rp-ink-2);
  font-size: 12.5px;
  white-space: nowrap;
}
.crm-list tbody tr:last-child td { border-bottom: 0; }
.crm-list tbody tr:hover td { background: rgb(var(--ch-lift) / 0.025); }
.crm-list tbody tr.picked td { background: var(--rp-blue-soft); }

.crm-list .c-title { color: var(--rp-ink); font-weight: 600; }
/* Было 210px: «Привет! Можно узнат…» — по такой строке лид не узнать, а
   первые слова у пришедших из рекламы совпадают. Триста двадцать вмещают
   осмысленный кусок и не съедают остальные колонки. */
.crm-list .c-title > span, .crm-list .c-title > a { max-width: 320px; }
.crm-list .c-title > a { color: inherit; text-decoration: none; }
.crm-list .c-title > a:hover { text-decoration: underline; }
.crm-list .c-value { color: var(--rp-ink); font-weight: 600; }
.crm-list .c-phone, .crm-list .c-value { font-variant-numeric: tabular-nums; }

/* The stage chip is the segment rail's pill at card scale, not a second-tier
   button — the stage is a label here, the way the channel is on a card. */
.crm-list-stage {
  display: inline-block;
  max-width: 130px;
  padding: 2px 8px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-pill);
  background: rgb(var(--ch-lift) / 0.03);
  color: var(--rp-ink-2);
  font-size: 10.5px;
  font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  vertical-align: middle;
}

/* The bulk bar becomes the panel's head strip instead of a floating band with
   its own border above the table. */
/* ПОЛОСА МАССОВЫХ ДЕЙСТВИЙ ПРИЛИПАЕТ — ЗНАЧИТ ДОЛЖНА БЫТЬ НЕПРОЗРАЧНОЙ.
   Владелец, 7 сентября: «текст идёт вместе с экраном» — при прокрутке списка
   строки таблицы просвечивали сквозь панель и накладывались на её кнопки.
   Причина: базовое правило делает полосу sticky, а этот вид убирал у неё фон
   («background: none»), оставляя прилипание. Фон панели возвращён, слой поднят
   выше строк, и добавлен нижний отступ, чтобы под полосой не оставалось щели. */
.crm-listv > .crm-bulk {
  gap: 8px;
  padding: 8px 0;
  border-bottom: 1px solid var(--rp-line);
  border-radius: 0;
  background: var(--rp-panel);
  z-index: 5;
}
.crm-listv > .crm-bulk > strong { font-size: 12px; color: var(--rp-ink); }
.crm-listv > .crm-bulk select { padding: 4px 9px; font-size: 11.5px; }

/* 12's «Сумма: 18,500 AED» edge, carrying what is on screen and the pager
   beside it. Card-foot rule: a hairline, then a 28px row. */
.crm-listv-foot {
  display: flex;
  align-items: center;
  gap: var(--rp-3);
  min-height: 28px;
  padding-top: 7px;
  border-top: 1px solid var(--rp-line);
}
.crm-listv-sum { display: inline-flex; align-items: baseline; gap: 6px; flex: none; }
.crm-listv-sumlabel { color: var(--rp-ink-3); font-size: 11px; }
.crm-listv-sum > strong {
  color: var(--rp-ink);
  font-size: 12.5px;
  font-weight: 620;
  font-variant-numeric: tabular-nums;
}
.crm-listv-sum > strong.muted { color: var(--rp-ink-3); font-weight: 500; }
.crm-listv-range { flex: 1 1 auto; min-width: 0; color: var(--rp-ink-3); font-size: 11px; }
.crm-listv-range.is-error { color: var(--rp-red, var(--lg-red-4)); }
.crm-listv-pager { display: flex; gap: 6px; flex: none; }
.crm-listv-page {
  min-height: 24px;
  padding: 0 10px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-sm);
  background: none;
  color: var(--rp-ink-2);
  font-size: 11.5px;
  cursor: pointer;
}
.crm-listv-page:hover:not(:disabled) { border-color: var(--rp-line-2); color: var(--rp-ink); }
.crm-listv-page:disabled { opacity: 0.42; cursor: default; }

/* No source, no match, still the panel — the density rule says a block with
   nothing in it keeps its geometry and says why, and the foot stays put. */
.crm-listv-empty {
  display: grid;
  place-items: center;
  min-height: 180px;
  color: var(--rp-ink-3);
  font-size: 12px;
}
.crm-listv-empty > p { margin: 0; }
/* Пока список читается, место держит высоту прошлой таблицы (~1300 px), и
   надпись по центру оказывалась ниже края экрана — рамка выглядела пустой
   (владелец, 26.09.2026). Надпись — к верху места. */
.crm-listv-empty.is-loading { place-items: start center; padding-top: 32px; }

@media (max-width: 1050px) {
  /* The table keeps its columns and scrolls inside the panel; the page itself
     never scrolls sideways. */
  .crm-listv > .crm-list-wrap { max-height: 60vh; }
  .crm-listv-foot { flex-wrap: wrap; row-gap: 6px; }
  .crm-listv-range { order: 3; flex-basis: 100%; }
}

/* ═══ DIALOGUES (mockups 02, 06, 07, 08) ═════════════════════════════════ */

.chatpane { display: grid; gap: var(--rp-3); }
.chatpane-topline {
  display: flex;
  align-items: center;
  gap: var(--rp-3);
  padding: 0;
  border: 0;
  background: none;
}
/* Six cards at 172px each wrapped their labels to three lines and pushed the
   source chip past the card edge. 07 runs six KPI cards across the full width
   with the label on ONE line; giving each card more room and letting the head
   stack when it must is what makes that hold. */
/* SIX ACROSS, EXPLICITLY. `auto-fit` with a 196px minimum fits five at 1440
   and orphans the sixth onto a row of its own, which is neither 02 nor 07 —
   both run all six across the full width. A fixed six-column track holds them
   together and only drops to three when there is genuinely no room. */
.chat-kpis { grid-template-columns: repeat(6, minmax(0, 1fr)); }
@media (max-width: 1240px) { .chat-kpis { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 720px) { .chat-kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.chat-kpis .rp-kpi-head { flex-wrap: wrap; row-gap: 3px; }
.chat-kpis .rp-kpi-label { line-height: 1.25; }
.chat-kpis .xo-chip { flex: none; max-width: 100%; }
/* A card with no source is dimmed as a whole, so the eye skips it on the way
   to the four that carry real counts. */
.rp-kpi.is-off { background: rgb(var(--ch-lift) / 0.012); }
.rp-kpi.is-off .rp-kpi-value { color: var(--rp-ink-3); }
/* 07's KPI band is 75px tall — an edge scan down x=1100 puts the tiles at
   84→159. Ours ran 132 (+76%), which pushed the inbox 57px down the page for
   six numbers that fit in half that. */
.chat-kpis .rp-kpi { padding: 8px 12px; min-height: 75px; gap: 1px; }
.chat-kpis .rp-kpi-label { font-size: 10.5px; }
.chat-kpis .rp-kpi-value { font-size: 20px; line-height: 1.1; }
.chat-kpis .rp-kpi-sub { font-size: 10px; line-height: 1.25; }
.chat-kpis .xo-chip { font-size: 9.5px; padding: 1px 6px; }

/* ── THE CHANNEL MARK, ONE STYLE FOR THE WHOLE PRODUCT ────────────────────
   The tile the Integrations desk draws (.idesk-mark in pack-design.css), at the
   sizes the rest of the cabinet needs. Same shape language, same neutral group
   tints, and the provider's own colour arrives inline from
   src/pages/shared/channelMarks.js — because it is per-provider data, not a
   theme decision, and thirty-odd id rules here would be that table again,
   further from the list it belongs to.

   NOTHING IN THIS BLOCK ENCODES A STATE. There is no .is-live, no .is-off, no
   green-for-connected. A brand tint says which channel; whether it is connected
   is said in words, by the status chip, and only there. */
.chan-mark {
  flex: none;
  width: 22px; height: 22px;
  border-radius: 7px;
  display: inline-flex; align-items: center; justify-content: center;
  background: rgb(var(--ch-lift) / 0.10);
  color: var(--rp-ink-2);
}
.chan-mark-icon { display: block; }
/* The fallback tints, for a channel whose brand colour we do not know. Same six
   families as the desk, so an unrecognised connector still looks like it
   belongs to the set rather than like a rendering failure. */
.chan-mark-site       { background: rgba(120,160,255,.16); color: #a8c2ff; }
.chan-mark-messengers { background: rgba( 80,200,140,.16); color: #7fd7ac; }
.chan-mark-telephony  { background: rgba(255,180,100,.16); color: #ffc98a; }
.chan-mark-crm        { background: rgba(180,140,255,.16); color: #cbb0ff; }
.chan-mark-ads        { background: rgba(255,130,150,.16); color: #ff9fb2; }
.chan-mark-office     { background: rgba(120,210,230,.16); color: #97dfec; }

/* Inline sizes, so one tile serves a 34px pill and a 15px inbox tag. */
.chat-chpill .chan-mark { width: 22px; height: 22px; border-radius: 7px; }
.chatrow-channel .chan-mark,
.chatpane-headcopy .chan-mark,
.channel-pill .chan-mark { width: 17px; height: 17px; border-radius: 5px; }
.gs-glyph .chan-mark { width: 20px; height: 20px; border-radius: 6px; }
.chats-item-ch .chan-mark { width: 17px; height: 17px; border-radius: 5px; }
/* styles.css upper-cases this tag, which was fine for an emoji plus a raw key
   and is wrong for a brand: WhatsApp is not WHATSAPP, and amoCRM is not
   AMOCRM. The provider spells its own name. */
.chats-item-ch { text-transform: none; }
.breakdown-name .chan-mark { width: 17px; height: 17px; border-radius: 5px; }

/* The name always sits beside the mark — the glyph is aria-hidden and carries
   nothing on its own, so these are one unit and wrap as one. */
.chatrow-channel, .chats-item-ch, .channel-pill.provider-channel-pill {
  display: inline-flex; align-items: center; gap: 5px;
}
.chatpane-headcopy .chan-mark { vertical-align: -4px; margin-inline-end: 4px; }
.breakdown-row .breakdown-name {
  display: inline-flex; align-items: center; gap: 6px; min-width: 0;
}
.breakdown-row .breakdown-name > span { min-width: 0; }

/* Channel pills (07). */
.chat-channels { display: flex; gap: 7px; flex-wrap: wrap; }
.chat-chpill {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-height: 34px;
  padding: 0 12px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-pill);
  background: rgb(var(--ch-lift) / 0.025);
  color: var(--rp-ink-2);
  font-size: 12.5px;
  font-weight: 500;
  cursor: pointer;
}
.chat-chpill:hover { border-color: var(--rp-line-2); color: var(--rp-ink); }
.chat-chpill.on {
  background: var(--rp-blue-soft);
  border-color: rgb(var(--ch-blue2) / 0.45);
  color: var(--rp-ink-max);
  font-weight: 600;
}
.chat-chcount {
  padding: 1px 7px;
  border-radius: var(--rp-r-pill);
  background: rgb(var(--ch-lift) / 0.07);
  font-size: 10.5px;
  font-weight: 650;
  font-variant-numeric: tabular-nums;
}
.chat-chpill.on .chat-chcount { background: rgb(var(--ch-lift) / 0.18); }

/* FOUR panes — 02's own composition, and 08's. Measured off 02 with an edge
   scan at y=600: the content column runs 192→1421 (1229px) and breaks
   277 / 474 / 312 / 139 with 7–10px gutters. Normalised on the actions rail
   that is 1.99 : 3.41 : 2.24 : 1.

   The old grid had three columns and no actions rail, so the thread absorbed
   the fourth column's width and ran 876px at 1920 against a scaled 634. */
.chatpane-body {
  display: grid;
  /* Minimums decide whether four columns survive, not the fractions. Below
     1450 the rail folds under the context column; below 1150 the context
     column goes under the thread; below 900 everything stacks. */
  grid-template-columns:
    minmax(224px, 1.99fr) minmax(0, 3.41fr) minmax(236px, 2.24fr) minmax(150px, 1fr);
  gap: var(--rp-3);
  align-items: stretch;
  min-height: 560px;
}
.chatpane-list, .chatpane-thread, .chatpane-lead, .chatpane-acts {
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r);
  background: var(--rp-panel);
  box-shadow: none;
  min-width: 0;
}
.chatpane-list { display: flex; flex-direction: column; overflow: hidden; }
.chatpane-listhead { padding: var(--rp-3); border-bottom: 1px solid var(--rp-line); background: none; }
.chatpane-search input {
  width: 100%;
  min-height: 34px;
  padding-block: 0 0; padding-inline: 28px 10px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-sm);
  background: rgb(var(--ch-lift) / 0.03);
  color: var(--rp-ink);
  font-size: 12.5px;
}
.chatpane-tabs { gap: 0; margin-top: var(--rp-2); border-bottom: 0; }
.chatpane-tab {
  min-height: 30px;
  padding: 0 9px;
  border: 0;
  border-bottom: 2px solid transparent;
  border-radius: 0;
  background: none;
  color: var(--rp-ink-3);
  font-size: 11.5px;
}
.chatpane-tab.on { color: var(--rp-ink-max); font-weight: 600; border-bottom-color: var(--rp-blue); background: none; }
.chatpane-listscroll { flex: 1 1 auto; overflow-y: auto; }

/* 02's inbox row is 62px — an edge scan down x=200 gives boundaries at 254,
   316, 569, 632, 696, 758: 62, 63, 64, 62. Ours was 88 (+42%), which is why
   only six rows reached the fold where the reference shows ten. */
.chatrow {
  gap: 9px;
  padding: 5px var(--rp-3);
  border: 0;
  border-bottom: 1px solid var(--rp-line);
  border-radius: 0;
  background: none;
  cursor: pointer;
}
.chatrow-body { gap: 1px; }
.chatrow-tags { gap: 6px; align-items: center; }
.chatrow-channel, .chatrow-state, .chatrow-lead { font-size: 10px; line-height: 15px; }
.chatrow-state, .chatrow-lead { padding: 0 6px; }
.chatrow-channel .provider-avatar { width: 13px; height: 13px; min-width: 13px; }
.chatrow-channel .provider-avatar img { width: 13px; height: 13px; }
.chatrow-avatar { width: 30px; height: 30px; min-width: 30px; font-size: 11px; }
.chatrow-top strong { line-height: 1.25; }
.chatrow-snippet { line-height: 1.3; }
.chatrow:hover { background: rgb(var(--ch-lift) / 0.03); }
.chatrow.active { background: var(--rp-blue-soft); border-inline-start: 2px solid var(--rp-blue); padding-inline-start: calc(var(--rp-3) - 2px); }
.chatrow-top strong { font-size: 12.5px; font-weight: 590; color: var(--rp-ink); }
.chatrow-time { color: var(--rp-ink-3); font-size: 10.5px; }
.chatrow-snippet { color: var(--rp-ink-3); font-size: 11.5px; }

.chatpane-thread { display: flex; flex-direction: column; overflow: hidden; }
/* 02's thread header is 59px: one row, contact on the left, a state pill and a
   single control on the right. Five controls used to live on that right side
   and wrapped it to 145px — two and a half times the reference, eating the
   conversation it was supposed to introduce. */
.chatpane-head {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 59px;
  padding: 0 var(--rp-3);
  border-bottom: 1px solid var(--rp-line);
  /* NOT `background: none`. cabinet-system.css gives this header an opaque
     --bd-panel-2, and this file loads after it, so `none` turned the header
     transparent and the message list showed straight through it — the phone
     number and the CRM meta line sat on top of a chat bubble. A header above a
     scrolling list has to paint. */
  background: var(--rp-panel-2, var(--bd-panel-2, var(--lg-surf-4)));
  position: relative;
  z-index: 1;
}
/* The meta line — channel · deal · number · language · last seen — is longer
   than the row is wide. It was wrapping out of the 59px box and over the
   messages below; one line with an ellipsis keeps it inside its own header. */
.chatpane-headcopy p {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.chatpane-head.empty { padding: 0 var(--rp-3); }
.chatpane-headavatar { width: 32px; height: 32px; min-width: 32px; font-size: 11.5px; }
.chatpane-headcopy { min-width: 0; flex: 1 1 auto; }
.chatpane-headcopy h2 { margin: 0; font-size: 13.5px; font-weight: 620; line-height: 1.2; }
.chatpane-headcopy p {
  margin: 1px 0 0;
  display: flex; align-items: center; gap: 5px; flex-wrap: nowrap;
  min-width: 0; overflow: hidden;
  color: var(--rp-ink-3); font-size: 11px; white-space: nowrap;
}
.chatpane-headside { display: flex; align-items: center; gap: 6px; flex: none; }
.chatpane-headbtn {
  min-height: 26px;
  padding: 0 10px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-sm);
  background: none;
  color: var(--rp-ink-2);
  font-size: 11px;
  cursor: pointer;
}
.chatpane-headbtn:hover { border-color: var(--rp-line-2); color: var(--rp-ink); }
.chatpane-pill { font-size: 10.5px; padding: 2px 8px; }

.chatpane-scroll { flex: 1 1 auto; overflow-y: auto; padding: var(--rp-3) var(--rp-4); }
.chatpane-composer { padding: var(--rp-2) var(--rp-3) var(--rp-3); border-top: 1px solid var(--rp-line); background: none; }
.chatpane-composerbox { gap: var(--rp-2); }

/* «Ответ от AI-агента | Ответ от оператора» — 02 draws these directly above the
   box. Underline tabs, not buttons: they choose a mode, they do not fire. */
.chatpane-who {
  display: flex;
  align-items: center;
  gap: 2px;
  margin-bottom: 7px;
  border-bottom: 1px solid var(--rp-line);
}
.chatpane-whotab {
  min-height: 28px;
  padding: 0 10px;
  border: 0;
  border-bottom: 2px solid transparent;
  background: none;
  color: var(--rp-ink-3);
  font-size: 11.5px;
  cursor: pointer;
}
.chatpane-whotab.on { color: var(--rp-ink-max); font-weight: 600; border-bottom-color: var(--rp-blue); }
.chatpane-whostate {
  margin-inline-start: auto;
  color: var(--rp-ink-3);
  font-size: 10.5px;
  font-variant-numeric: tabular-nums;
}

/* 02's opener strip under the box. */
.chatpane-quick {
  display: flex;
  align-items: center;
  gap: var(--rp-3);
  min-height: 30px;
  margin-top: 7px;
  padding-top: 7px;
  border-top: 1px solid var(--rp-line);
}
.chatpane-quicknote { flex: 1 1 auto; min-width: 0; color: var(--rp-ink-3); font-size: 11px; }
.chatpane-quickcta {
  flex: none;
  min-height: 26px;
  padding: 0 10px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-sm);
  background: none;
  color: var(--rp-ink-2);
  font-size: 11px;
  cursor: pointer;
}
.chatpane-quickcta:hover { border-color: var(--rp-line-2); color: var(--rp-ink); }
.chatpane-composer textarea {
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-sm);
  background: rgb(var(--ch-lift) / 0.03);
  color: var(--rp-ink);
  font-size: 12.5px;
  padding: 9px 11px;
}
.chatpane-composernote { color: var(--rp-ink-3); font-size: 11px; margin: 6px 0 0; }

/* The context column and the actions rail. 02 draws BOTH as a stack of small
   bordered cards inside the column, not as one padded panel — which is why the
   column border itself goes and each card carries its own. */
.chatpane-lead, .chatpane-acts {
  padding: 0;
  border: 0;
  background: none;
  overflow-y: auto;
  display: grid;
  gap: var(--rp-2);
  align-content: start;
}
.chat-card {
  padding: 10px 12px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r);
  background: var(--rp-panel);
}
.chat-cardhead {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--rp-2);
  margin-bottom: 6px;
}
.chat-cardhead h3 { margin: 0; font-size: 12.5px; font-weight: 620; color: var(--rp-ink); }
.chat-cardtag {
  flex: none;
  padding: 1px 7px;
  border-radius: var(--rp-r-pill);
  background: rgb(var(--ch-lift) / 0.05);
  color: var(--rp-ink-3);
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}
.chat-cardlink {
  flex: none; padding: 0; border: 0; background: none;
  color: var(--sh-blue-2); font-size: 11px; cursor: pointer;
}
.chat-cardlink:hover { color: var(--sh-blue-1); }
.chat-cardnote { margin: 6px 0 0; color: var(--rp-ink-3); font-size: 11px; line-height: 1.45; }

/* 02's «Рекомендуемый ответ» is a raised block inside the AI card with the
   «Использовать ответ» button under it. Keeps that shape with no draft in it. */
.chat-aidraft {
  padding: 9px 10px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-sm);
  background: rgb(var(--ch-lift) / 0.022);
}
.chat-aidraft h4 { margin: 0 0 4px; font-size: 11.5px; font-weight: 620; color: var(--rp-ink-2); }
.chat-aidraft p { margin: 0 0 8px; color: var(--rp-ink-3); font-size: 11px; line-height: 1.45; }
.chat-aiuse {
  width: 100%;
  min-height: 28px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-sm);
  background: var(--rp-blue-soft);
  color: var(--rp-ink-2);
  font-size: 11.5px;
  font-weight: 600;
  cursor: pointer;
}
.chat-aiuse:disabled { opacity: 0.45; cursor: not-allowed; background: none; }

/* The actions rail: 02 stacks full-width buttons, one per line, in three
   labelled groups. A disabled one keeps its place and carries its reason. */
.chat-acts { padding: 10px; }
.chat-actlist { display: grid; gap: 5px; }
.chat-act {
  width: 100%;
  min-height: 30px;
  padding: 0 10px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-sm);
  background: rgb(var(--ch-lift) / 0.022);
  color: var(--rp-ink-2);
  font-size: 11.5px;
  text-align: start;
  cursor: pointer;
}
.chat-act:hover:not(:disabled) { border-color: var(--rp-line-2); color: var(--rp-ink); }
.chat-act.on { background: var(--rp-blue-soft); border-color: rgb(var(--ch-blue2) / 0.42); color: var(--rp-ink-max); font-weight: 600; }
.chat-act:disabled { opacity: 0.42; cursor: not-allowed; }

.chat-facts { display: grid; gap: 0; }
.chat-fact {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--rp-3);
  padding: 8px 0;
  border-bottom: 1px solid var(--rp-line);
}
.chat-fact:last-child { border-bottom: 0; }
.chat-fact-k { color: var(--rp-ink-3); font-size: 11.5px; flex: none; }
.chat-fact-v {
  color: var(--rp-ink);
  font-size: 12px;
  font-weight: 550;
  text-align: end;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.chat-leadblock { padding-top: var(--rp-3); border-top: 1px solid var(--rp-line); }
.chat-leadblock h4 { margin: 0 0 4px; font-size: 12px; font-weight: 600; color: var(--rp-ink-2); }
.chat-leadblock p { margin: 0; font-size: 12px; line-height: 1.5; color: var(--rp-ink-3); }
.chat-leadempty { padding: var(--rp-3) 0 0; border-top: 1px solid var(--rp-line); }
.chat-leadcta { width: 100%; justify-content: center; }

/* Status bar (07, 08).
   NOT sticky. `position: sticky; bottom: 0` pins it to the bottom of the
   VIEWPORT, so on a page taller than the screen it floated across the middle
   of the inbox and cut through the lead pane behind it — visible in the 02
   acceptance shot as a bar lying over the conversation rows. 07 draws it at
   the foot of the panel, which is where it sits now. */
.chat-statusbar {
  display: flex;
  align-items: center;
  gap: var(--rp-2);
  flex-wrap: wrap;
  padding: 10px var(--rp-4);
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r);
  background: var(--rp-veil);
  backdrop-filter: blur(8px);
  color: var(--rp-ink-2);
  font-size: 11.5px;
}
.chat-status-dot { width: 7px; height: 7px; border-radius: 50%; flex: none; }
.chat-status-dot.good { background: var(--rp-green); }
.chat-status-dot.off { background: var(--rp-ink-3); }
.chat-status-sep { color: var(--rp-ink-3); }

/* Four columns need ~1450 of content. Below that they shed one at a time
   rather than all at once, so the screen keeps as much of 02 as the width
   allows instead of dropping straight to a stack. */
/* Four columns need ~1450px of content. Below that the rail joins the context
   column as a THIRD card stack rather than becoming its own grid row — the
   first attempt moved it to row 2 and spanned the inbox and thread across both
   rows, which left the inbox ending at its content height while the thread ran
   on, and dropped the status bar through the middle of the conversation. One
   column that holds both stacks has no rows to disagree about. */
/* NO INTERMEDIATE BREAKPOINT. Reflowing the rail under the context column at
   1560 was tried twice and is wrong both ways: give the slack to the context
   row and the rail is allotted nothing and disappears; give it to the rail and
   the context column is squeezed to one card and a scrollbar. Four columns
   survive 1440 on their own — the minimums come to 610px against 1164px of
   content — and 1440 keeps all four of 02's columns, which is the point. */
@media (max-width: 1150px) {
  /* Below this the columns stop being readable, so the context and the rail
     drop under the thread rather than the inbox being squeezed out. */
  .chatpane-body {
    grid-template-columns: minmax(224px, 0.9fr) minmax(0, 2fr);
    grid-template-rows: auto auto auto;
  }
  .chatpane-list, .chatpane-thread { grid-row: 1; }
  .chatpane-lead { grid-column: 1 / -1; grid-row: 2; }
  .chatpane-acts { grid-column: 1 / -1; grid-row: 3; }
  .chatpane-lead, .chatpane-acts {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    align-content: start;
  }
}
@media (max-width: 900px) {
  .chatpane-body {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: none;
    min-height: 0;
  }
  .chatpane-list, .chatpane-thread, .chatpane-lead, .chatpane-acts {
    grid-column: auto; grid-row: auto;
  }
  .chatpane-lead, .chatpane-acts { grid-template-columns: minmax(0, 1fr); }
}

/* ═══ VOICE & CALLS (mockup 04) ══════════════════════════════════════════
   The module already had 04's structure — header with the telephony pill, four
   tabs, panes, status footer — and, more importantly, it was already honest.
   04 draws a working softphone: dialpad, live waveform, streaming transcript,
   emotion timeline, «Доступно агентов 6». None of that can exist here. The
   number routes via an External SIP URI straight to ElevenLabs, so the PBX is
   bypassed, there is no browser call leg and no `callinfo` event ever fires.
   This section restyles what is there; it does not switch any of it on. */

.voice-page { display: grid; gap: var(--rp-3); }

/* ── 04's active-call composition ────────────────────────────────────────────
   Measured off 04 by edge scan. The content column runs 207→1435 (1228px) and
   splits into a 245px dialpad column and a 969px working area with a 14px
   gutter — 1 : 3.955. Inside the working area, row 1 is 304 / 327 / 310
   (1 : 1.076 : 1.020) and row 2 is 595 / 374 (1.591 : 1).

   What was here before: a page-wide amber notice and a card holding one
   paragraph. Six of 04's blocks did not exist at all — the dialpad column, the
   transcript, the quality panel and the call notes among them — and the screen
   read as one big empty state, which is the shape the reference rules out. */
.voice-comp {
  display: grid;
  grid-template-columns: minmax(210px, 1fr) minmax(0, 3.955fr);
  grid-template-rows: auto auto;
  gap: 14px;
  align-items: start;
}
.voice-comp-side { grid-row: 1 / -1; align-self: start; display: grid; gap: 14px; align-content: start; }
.voice-comp-top {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.076fr) minmax(0, 1.020fr);
  gap: 14px;
  align-items: stretch;
}
.voice-comp-low {
  display: grid;
  grid-template-columns: minmax(0, 1.591fr) minmax(0, 1fr);
  gap: 14px;
  align-items: stretch;
}
.voice-comp .control-card { padding: 12px 14px; }
.voice-cardhead {
  display: flex;
  align-items: center;
  gap: 7px;
  flex-wrap: wrap;
  margin-bottom: 9px;
}
.voice-cardhead h3 { margin: 0; font-size: 13.5px; font-weight: 620; color: var(--rp-ink); }
.voice-cardsub { color: var(--rp-ink-3); font-size: 11px; }
.voice-cardstate { color: var(--rp-ink-2); font-size: 11px; }
.voice-cardtag {
  margin-inline-start: auto;
  padding: 1px 7px;
  border-radius: var(--rp-r-pill);
  background: rgb(var(--ch-lift) / 0.05);
  color: var(--rp-ink-3);
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}
.voice-dot { width: 7px; height: 7px; border-radius: 50%; flex: none; }
.voice-dot.good { background: var(--rp-green, #22c55e); }
.voice-dot.off { background: var(--rp-ink-3); }

/* header — 04's is 65px and holds one line. Ours ran 101 because it carried a
   repeated title stacked over the subtitle. */
.voice-header {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 62px;
  padding: 12px 16px;
}
.voice-headmark {
  display: grid; place-items: center;
  width: 34px; height: 34px; flex: none;
  border-radius: var(--rp-r-sm);
  background: var(--rp-blue-soft);
  font-size: 16px;
}
.voice-headcopy { flex: 1 1 auto; min-width: 0; }
.voice-headcopy p { margin: 0; color: var(--rp-ink-2); font-size: 12.5px; }
.voice-header-side { display: flex; align-items: center; gap: var(--rp-2); flex-wrap: wrap; }
/* УЗКИЙ ЭКРАН: ПОДПИСЬ — СВОЕЙ СТРОКОЙ, КНОПКИ — ПОД НЕЙ (24.09.2026,
   мобильный проход). В одну строку со значком и тремя кнопками подписи
   «Управление звонками, история…» оставалось 58 px на 375, и длинные слова
   вылезали из своей колонки прямо под «Настройки телефонии». cabinet-system.css
   на ≤900 px просил одну колонку через grid-template-columns, но шапка — flex
   (здесь, выше), и та просьба не действовала. */
@media (max-width: 900px) {
  .voice-header { flex-wrap: wrap; }
  /* Подпись — рядом со значком (основа 0: не выталкивает себя на новую
     строку), кнопки — следующей строкой во всю ширину. */
  .voice-headcopy { flex: 1 1 0; }
  .voice-header-side { flex: 1 1 100%; }
}
.voice-headbtn, .voice-headcta {
  min-height: 32px;
  padding: 0 13px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-sm);
  background: none;
  color: var(--rp-ink-2);
  font-size: 12px;
  cursor: pointer;
}
.voice-headbtn:hover { border-color: var(--rp-line-2); color: var(--rp-ink); }
.voice-headcta { background: var(--rp-blue); border-color: var(--rp-blue); color: var(--rp-on-accent); font-weight: 600; }
.voice-headcta.is-off { background: none; border-color: var(--rp-line); color: var(--rp-ink-3); cursor: not-allowed; }
.voice-headpill {
  display: inline-flex; align-items: center; gap: 6px;
  min-height: 32px; padding: 0 11px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-pill);
  color: var(--rp-ink-2);
  font-size: 11.5px;
}

/* keypad column */
.voice-pad { display: grid; gap: 9px; justify-items: center; }
.voice-pad h3 { justify-self: start; margin: 0; font-size: 13.5px; font-weight: 620; }
.voice-padnum {
  display: flex; align-items: center; gap: 7px;
  width: 100%; min-height: 34px; padding: 0 10px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-sm);
  background: rgb(var(--ch-lift) / 0.03);
}
.voice-padflag { color: var(--rp-ink-3); font-size: 12px; }
.voice-padinput {
  flex: 1 1 auto; min-width: 0;
  border: 0; background: none; color: var(--rp-ink);
  font-size: 12.5px; font-variant-numeric: tabular-nums;
}
.voice-padinput:disabled { color: var(--rp-ink-3); }
.voice-call {
  width: 58px; height: 38px;
  border: 0; border-radius: var(--rp-r-pill);
  background: var(--rp-blue);
  color: var(--rp-on-accent); font-size: 15px; cursor: pointer;
}
/* The plain handset button only — a call action is green everywhere else in
   the product (the lead card's own dialable phone icon uses the same
   --rp-green). Scoped off .voice-call-maria on purpose: that button is a
   different action (Maria places the call, not this line) and nobody has
   asked for it to look the same as this one. */
.voice-call:not(.voice-call-maria) { background: var(--rp-green); }
.voice-call.is-off { background: rgb(var(--ch-blue2) / 0.28); cursor: not-allowed; }
/* .voice-call's own 58x38 pill fits a single glyph (the plain handset button
   above), not "🤖 Позвонить Марией"/"🤖 Call via Maria" — reported live
   2026-08-23: the label wrapped inside that fixed box and the 38px height
   clipped everything after the first line, leaving only the robot emoji and
   "Позв." visible. This button gets its own width instead of sharing one
   sized for an icon-only sibling. */
.voice-call.voice-call-maria {
  width: auto; height: 38px; padding: 0 16px;
  display: inline-flex; align-items: center; gap: 6px;
  white-space: nowrap; font-size: 13px;
}
.voice-padnote { margin: 0; color: var(--rp-ink-3); font-size: 10.5px; line-height: 1.4; }

.voice-quick { display: grid; gap: 7px; }
.voice-quick h3 { margin: 0; font-size: 12.5px; font-weight: 620; }
.voice-quicklist { display: grid; gap: 3px; }
.voice-quickitem {
  width: 100%; min-height: 28px; padding: 0 8px;
  border: 0; border-radius: var(--rp-r-sm);
  background: none; color: var(--rp-ink-2);
  font-size: 11.5px; text-align: start; cursor: pointer;
}
.voice-quickitem:hover:not(:disabled) { background: rgb(var(--ch-lift) / 0.035); color: var(--rp-ink); }
.voice-quickitem:disabled { opacity: 0.42; cursor: not-allowed; }

/* active call */
.voice-live { display: grid; gap: 8px; align-content: start; }
.voice-liveface { display: grid; justify-items: center; gap: 2px; }
.voice-liveava {
  display: grid; place-items: center;
  width: 48px; height: 48px;
  border-radius: 50%;
  background: rgb(var(--ch-lift) / 0.05);
  color: var(--rp-ink-3);
  font-size: 15px;
}
.voice-livename { font-size: 14px; font-weight: 620; color: var(--rp-ink-2); }
.voice-livesub { color: var(--rp-ink-3); font-size: 11px; }
.voice-livenum {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  color: var(--rp-ink-2); font-size: 13px; font-variant-numeric: tabular-nums;
}
.voice-livechip {
  padding: 1px 8px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-pill);
  color: var(--rp-ink-3);
  font-size: 10.5px;
}
.voice-timer {
  text-align: center;
  color: var(--rp-ink-3);
  font-size: 19px;
  font-weight: 620;
  font-variant-numeric: tabular-nums;
}
/* 04 animates a waveform. There is no browser call leg to draw one from. */
.voice-wave {
  display: grid; place-items: center;
  min-height: 40px;
  border: 1px dashed var(--rp-line);
  border-radius: var(--rp-r-sm);
  color: var(--rp-ink-3);
  font-size: 10.5px;
}
.voice-ctrls { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 7px; }
.voice-ctrl {
  display: grid; justify-items: center; gap: 3px;
  min-height: 52px; padding: 6px 2px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-sm);
  background: rgb(var(--ch-lift) / 0.022);
  color: var(--rp-ink-3);
  font-size: 10.5px;
  cursor: pointer;
}
.voice-ctrl:disabled { opacity: 0.5; cursor: not-allowed; }
.voice-ctrl-g { font-size: 14px; }
.voice-end {
  width: 100%; min-height: 36px;
  border: 0; border-radius: var(--rp-r-sm);
  background: rgb(var(--ch-red) / 0.75);
  color: var(--rp-ink-max); font-size: 12.5px; font-weight: 620;
  cursor: pointer;
}
.voice-end:disabled { background: rgb(var(--ch-red) / 0.26); color: var(--rp-ink-max); cursor: not-allowed; }

/* transcript */
.voice-tr { display: grid; gap: 9px; align-content: start; }
.voice-trbody { display: grid; gap: 7px; }
.voice-trbody p { margin: 0; color: var(--rp-ink-3); font-size: 11.5px; line-height: 1.5; }
.voice-trmore {
  width: 100%; min-height: 32px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-sm);
  background: none; color: var(--rp-ink-2);
  font-size: 11.5px; cursor: pointer;
}
.voice-trmore:hover { border-color: var(--rp-line-2); color: var(--rp-ink); }

/* quality and analytics */
.voice-qa { display: grid; gap: 7px; align-content: start; }
.voice-qa h4 { margin: 4px 0 0; font-size: 11.5px; font-weight: 620; color: var(--rp-ink-2); }
.voice-qatop {
  display: flex; align-items: center; justify-content: space-between; gap: var(--rp-3);
  padding: 9px 11px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-sm);
  background: rgb(var(--ch-lift) / 0.022);
}
.voice-qascore { display: flex; align-items: baseline; gap: 5px; flex-wrap: wrap; }
.voice-qascore > strong { color: var(--rp-ink-3); font-size: 25px; font-weight: 660; }
.voice-qamax { color: var(--rp-ink-3); font-size: 12px; }
.voice-qaword { flex-basis: 100%; color: var(--rp-ink-3); font-size: 10.5px; }
.voice-qadonut {
  display: grid; place-items: center;
  width: 54px; height: 54px; flex: none;
  border: 3px solid var(--rp-line);
  border-radius: 50%;
  color: var(--rp-ink-3);
  font-size: 12px;
}
.voice-qachart, .voice-qawords {
  display: grid; place-items: center;
  border: 1px dashed var(--rp-line);
  border-radius: var(--rp-r-sm);
  color: var(--rp-ink-3);
  font-size: 10.5px;
}
.voice-qachart { min-height: 74px; }
.voice-qawords { min-height: 44px; }
.voice-qanote { margin: 2px 0 0; color: var(--rp-ink-3); font-size: 10.5px; line-height: 1.4; }

/* linked lead — 04's three sub-columns */
.voice-lead { display: grid; gap: 9px; align-content: start; }
.voice-leadgrid {
  display: grid;
  grid-template-columns: minmax(150px, 1fr) minmax(0, 1.15fr) minmax(0, 1.15fr);
  gap: var(--rp-3);
  align-items: start;
}
.voice-leadwho {
  display: grid; justify-items: center; gap: 4px;
  padding-inline-end: var(--rp-3);
  border-inline-end: 1px solid var(--rp-line);
}
.voice-leadava {
  display: grid; place-items: center;
  width: 46px; height: 46px;
  border-radius: 50%;
  background: rgb(var(--ch-lift) / 0.05);
  color: var(--rp-ink-3);
  font-size: 15px;
}
.voice-leadwho > strong { color: var(--rp-ink-2); font-size: 12.5px; font-weight: 620; }
.voice-leadcity { color: var(--rp-ink-3); font-size: 11px; }
.voice-leadicons { display: flex; gap: 5px; }
.voice-leadicon {
  display: grid; place-items: center;
  width: 22px; height: 22px;
  border: 1px solid var(--rp-line);
  border-radius: 50%;
  color: var(--rp-ink-3);
  font-size: 10px;
}
.voice-leadicon.is-off { opacity: 0.4; }
.voice-leadopen {
  width: 100%; min-height: 28px; margin-top: 2px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-sm);
  background: none; color: var(--rp-ink-2);
  font-size: 11px; cursor: pointer;
}
.voice-leadopen:hover { border-color: var(--rp-line-2); color: var(--rp-ink); }
.voice-leadcol { display: grid; gap: 1px; align-content: start; }
.voice-leadcol h4 { margin: 6px 0 0; font-size: 10.5px; font-weight: 600; color: var(--rp-ink-3); }
.voice-leadcol h4:first-child { margin-top: 0; }
.voice-leadval { margin: 0; color: var(--rp-ink-2); font-size: 12px; }
.voice-leadnote { margin: 0; color: var(--rp-ink-3); font-size: 10.5px; line-height: 1.4; }

/* call notes */
.voice-notes { display: grid; gap: 7px; align-content: start; }
.voice-notes h4 { margin: 4px 0 0; font-size: 11.5px; font-weight: 620; color: var(--rp-ink-2); }
.voice-notesbody { margin: 0; color: var(--rp-ink-3); font-size: 11.5px; line-height: 1.5; }
.voice-noteacts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; }
.voice-noteact, .voice-noteapply {
  min-height: 30px; padding: 0 10px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-sm);
  background: rgb(var(--ch-lift) / 0.022);
  color: var(--rp-ink-2);
  font-size: 11.5px;
  cursor: pointer;
}
.voice-noteact:disabled, .voice-noteapply:disabled { opacity: 0.42; cursor: not-allowed; }
.voice-notetpl { display: flex; gap: 6px; align-items: center; }
.voice-notetplbox {
  flex: 1 1 auto; min-width: 0;
  min-height: 30px; padding: 6px 10px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-sm);
  color: var(--rp-ink-3);
  font-size: 11px;
}

/* status bar */
.voice-footdot { width: 7px; height: 7px; border-radius: 50%; flex: none; }
.voice-footdot.good { background: var(--rp-green, #22c55e); }
.voice-footdot.off { background: var(--rp-ink-3); }
.voice-footsep { color: var(--rp-ink-3); }
.voice-footer strong { color: var(--rp-ink); font-weight: 620; }
.voice-footer strong.good { color: var(--rp-green, #22c55e); }
.voice-footlink {
  margin-inline-start: auto;
  padding: 0; border: 0; background: none;
  color: var(--sh-blue-2); font-size: 11.5px; cursor: pointer;
}
.voice-footlink:hover { color: var(--sh-blue-1); }

@media (max-width: 1240px) {
  /* The dialpad column goes full width above the working area rather than
     being squeezed under its own 210px minimum. */
  .voice-comp { grid-template-columns: minmax(0, 1fr); }
  .voice-comp-side { grid-row: auto; grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .voice-comp-top { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 900px) {
  .voice-comp-side, .voice-comp-top, .voice-comp-low { grid-template-columns: minmax(0, 1fr); }
  .voice-leadgrid { grid-template-columns: minmax(0, 1fr); }
  .voice-leadwho { border-inline-end: 0; padding-inline-end: 0; }
}

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

/* The keypad is drawn because 04 draws it, and disabled because the browser is
   not the phone. It reads as a diagram of the thing, not as a control that was
   left broken — hence the dimmed keys and the notice directly beneath. */
.voice-keypad { display: grid; gap: var(--rp-3); }
.voice-keypad h3 { margin: 0; font-size: 14px; font-weight: 620; color: var(--rp-ink); }
.voice-dial {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--rp-2);
  max-width: 300px;
}
/* 04's key is two lines — the digit, then its letters in a small caption under
   it. Rendered as one flow string they read as "2ABC". */
.voice-key {
  display: grid;
  align-content: center;
  justify-items: center;
  gap: 0;
  min-height: 44px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-sm);
  background: rgb(var(--ch-lift) / 0.02);
  color: var(--rp-ink-2);
  cursor: pointer;
}
.voice-key-d { font-size: 15px; font-weight: 560; line-height: 1.15; font-variant-numeric: tabular-nums; }
.voice-key-s { color: var(--rp-ink-3); font-size: 8px; letter-spacing: 0.06em; line-height: 1.1; }
.voice-key:hover:not(:disabled) { border-color: var(--rp-line-2); color: var(--rp-ink); }
.voice-key:disabled { opacity: 0.45; cursor: not-allowed; }

.voice-facts { display: grid; gap: 0; margin: 0; }
.voice-facts > div {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--rp-3);
  padding: 9px 0;
  border-bottom: 1px solid var(--rp-line);
}
.voice-facts > div:last-child { border-bottom: 0; }
.voice-facts dt { color: var(--rp-ink-3); font-size: 11.5px; margin: 0; }
.voice-facts dd { color: var(--rp-ink); font-size: 12px; font-weight: 550; margin: 0; text-align: end; }

/* The honest-state block, in the package's voice. */
.voice-notice {
  display: grid;
  gap: 5px;
  align-content: start;
  padding: var(--rp-5) var(--rp-4);
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r);
  background: var(--rp-panel);
}
.voice-notice-setup { border-color: rgb(var(--ch-amber) / 0.32); background: rgb(var(--ch-amber) / 0.05); }
.voice-notice-state {
  margin: 0;
  color: var(--rp-ink-3);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}
.voice-notice-setup .voice-notice-state { color: var(--rp-amber); }
.voice-notice h3 { margin: 0; font-size: 13.5px; font-weight: 620; color: var(--rp-ink); }
.voice-notice-body { margin: 0; color: var(--rp-ink-3); font-size: 12px; line-height: 1.55; }
.voice-notice .ghost-button { justify-self: start; margin-top: 6px; }

/* Status footer (04 pins it to the bottom of the screen). */
/* Same fix as the dialogue status bar: sticky-bottom pins to the viewport and
   draws across whatever is under it on a tall page. 04 puts this at the foot of
   the module, not floating over it. */
.voice-footer {
  display: flex;
  align-items: center;
  gap: var(--rp-4);
  flex-wrap: wrap;
  padding: 10px var(--rp-4);
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r);
  background: var(--rp-veil);
  backdrop-filter: blur(8px);
  color: var(--rp-ink-2);
  font-size: 11.5px;
}

@media (max-width: 900px) {
  .voice-grid, .voice-grid-keypad { grid-template-columns: minmax(0, 1fr); }
  .voice-dial { max-width: none; }
}

/* ═══ AI AGENTS (mockups 05 and 13) ══════════════════════════════════════
   13 draws the agent panel with a VERTICAL sub-nav, which is what this cabinet
   already had; 05 draws a KPI row over it, which it did not. Both are here. */

.agent-page { display: grid; gap: var(--rp-3); }
.agent-kpis { grid-template-columns: repeat(auto-fit, minmax(176px, 1fr)); }
/* .rp-kpi's shared min-height (132px) is sized for a card that also carries a
   sparkline or a delta row elsewhere in the product; these two cards are
   just a label and a number, so half that height was mostly empty air below
   the text. Owner-flagged live, "в два раза" (шrink by half) — halved, and
   the cabinets grid right below moves up to take the reclaimed space. */
.agent-kpis .rp-kpi { padding-bottom: 10px; min-height: 66px; }

/* «Кабинеты AI-агентов» (05). Four across at 1440, the density the reference
   keeps; the cards are compact because 05's are — name, language, tier, one
   action, and nothing that would have to be invented. */
/* ── the agent board (05) ────────────────────────────────────────────────────
   Edge scan at y=930: the catalogue panel runs 192→661 (469px) and the cabinet
   674→1414 (740px) on a 1222px content column — 1 : 1.578, 13px gutter. They
   were stacked full-width, so the catalogue ran as a four-across strip and the
   cabinet began below the fold; 05 reads both at once. */
.agent-board {
  display: grid;
  grid-template-columns: minmax(300px, 1fr) minmax(0, 1.578fr);
  gap: var(--rp-3);
  align-items: start;
}
.agent-cards-panel {
  padding: var(--rp-4);
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r);
  background: var(--rp-panel);
  min-width: 0;
}
/* Two across in the narrower column, which is what 05 draws. */
.agent-cards {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--rp-2);
}
.agent-cabwrap { display: grid; gap: var(--rp-3); min-width: 0; }

/* the cabinet header 05 draws and this screen had none of */
.agent-cabhead {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 11px 14px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r);
  background: var(--rp-panel);
}
.agent-cabava {
  display: grid; place-items: center;
  width: 38px; height: 38px; flex: none;
  border-radius: 50%;
  background: var(--rp-blue-soft);
  color: var(--sh-blue-1);
  font-size: 12px; font-weight: 700;
}
.agent-cabcopy { flex: 1 1 auto; min-width: 0; }
.agent-cabtitle { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.agent-cabtitle > strong { font-size: 13.5px; font-weight: 620; color: var(--rp-ink); }
.agent-cabchip.on { color: var(--pk-green, #1f8a4c); border-color: currentColor; }
.agent-cabchip {
  padding: 1px 8px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-pill);
  color: var(--rp-ink-3);
  font-size: 10.5px;
}
.agent-cabcopy p { margin: 2px 0 0; color: var(--rp-ink-3); font-size: 11.5px; }
.agent-cabfacts { display: flex; gap: var(--rp-3); flex: none; }
.agent-cabfacts > div { display: grid; gap: 1px; }
.agent-cabfactk { color: var(--rp-ink-3); font-size: 10px; text-transform: uppercase; letter-spacing: 0.03em; }
.agent-cabfactv { color: var(--rp-ink-2); font-size: 12px; font-weight: 600; }
.agent-cabfactv.muted { color: var(--rp-ink-3); font-weight: 500; }
.agent-cabacts { display: flex; gap: 6px; flex: none; }
.agent-cabbtn {
  min-height: 30px; padding: 0 12px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-sm);
  background: none; color: var(--rp-ink-2);
  font-size: 11.5px; cursor: pointer;
}
.agent-cabbtn:disabled { opacity: 0.42; cursor: not-allowed; }

/* 05's right-hand rail inside the cabinet */
.agent-rail { display: grid; gap: var(--rp-2); align-content: start; min-width: 0; }
.agent-railcard {
  padding: 10px 12px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-sm);
  background: var(--rp-panel-2);
}
.agent-railcard h4 { margin: 0 0 7px; font-size: 12.5px; font-weight: 620; color: var(--rp-ink); }
.agent-railrows { display: grid; gap: 0; }
.agent-railrow {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--rp-2);
  padding: 7px 0;
  border-bottom: 1px solid var(--rp-line);
}
.agent-railrow:last-child { border-bottom: 0; }
.agent-railk { color: var(--rp-ink-3); font-size: 11px; min-width: 0; }
.agent-railv { color: var(--rp-ink); font-size: 12px; font-weight: 620; font-variant-numeric: tabular-nums; }
.agent-railv.muted { color: var(--rp-ink-3); font-weight: 500; }
.agent-railnote { margin: 0 0 8px; color: var(--rp-ink-3); font-size: 11px; line-height: 1.45; }
.agent-raillink {
  width: 100%; min-height: 28px; margin-top: 8px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-sm);
  background: none; color: var(--rp-ink-2);
  font-size: 11.5px; cursor: pointer;
}
.agent-raillink:hover { border-color: var(--rp-line-2); color: var(--rp-ink); }

/* 05's linked-integration chips under the cabinet */
.agent-integrations {
  padding: 11px 14px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r);
  background: var(--rp-panel);
}
.agent-integrations h4 { margin: 0 0 8px; font-size: 12.5px; font-weight: 620; color: var(--rp-ink); }
.agent-intchips { display: flex; gap: 7px; flex-wrap: wrap; align-items: center; }
.agent-intchip {
  display: grid; gap: 1px;
  padding: 6px 11px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-sm);
  background: rgb(var(--ch-lift) / 0.022);
}
.agent-intchip > strong { color: var(--rp-ink-2); font-size: 11.5px; font-weight: 600; }
.agent-intchip > span { color: var(--rp-ink-3); font-size: 10px; }
.agent-intmore {
  margin-inline-start: auto;
  padding: 0; border: 0; background: none;
  color: var(--sh-blue-2); font-size: 11.5px; cursor: pointer;
}
.agent-intmore:hover { color: var(--sh-blue-1); }

/* card internals 05 draws */
.agent-card-state { display: flex; align-items: center; gap: 6px; color: var(--rp-ink-3); font-size: 10px; }
.agent-card-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--rp-ink-3); flex: none; }
.agent-card-langs { display: flex; align-items: center; gap: 4px; }
.agent-card-lang {
  padding: 1px 6px;
  border: 1px solid var(--rp-line);
  border-radius: 4px;
  color: var(--rp-ink-3);
  font-size: 9.5px; font-weight: 650;
}
.agent-card-lang.on { border-color: rgb(var(--ch-blue2) / 0.45); background: var(--rp-blue-soft); color: var(--sh-blue-1); }
.agent-card-langauto { color: var(--rp-ink-3); font-size: 10px; }
.agent-card-chans { display: flex; gap: 4px; flex-wrap: wrap; }
.agent-card-chan {
  display: grid; place-items: center;
  min-width: 20px; height: 18px; padding: 0 3px;
  border: 1px solid var(--rp-line);
  border-radius: 4px;
  color: var(--rp-ink-3);
  font-size: 8.5px; font-weight: 600;
}
.agent-card-chan.is-off { opacity: 0.42; }
/* Real network colours, at the same muted opacity a preset's inactive
   channel already carries — "мрачные, сделай реальными": the glyph should
   read as "the actual network, not yet connected", not as an unlabelled
   grey box. WhatsApp/Telegram/Instagram get their own brand colour. Phone,
   e-mail and the generic @ handle answer to no single brand, so inventing
   three unrelated colours for them would be arbitrary rather than
   meaningful — "доделай иконки все" was about finishing the SET, not about
   assigning brands that do not exist, so all three get the same shared
   accent instead of staying the one plain-grey trio left over. */
.agent-card-chan[data-net="wa"] { border-color: rgb(37 211 102 / .5); color: #25d366; }
.agent-card-chan[data-net="tg"] { border-color: rgb(34 158 217 / .5); color: #229ed9; }
.agent-card-chan[data-net="ig"] { border-color: rgb(225 48 108 / .5); color: #e1306c; }
.agent-card-chan[data-net="generic"] { border-color: rgb(var(--ch-blue2) / .45); color: var(--sh-blue-3); }
.agent-card-meta {
  display: flex; justify-content: flex-end; align-items: flex-start;
  gap: var(--rp-2);
}
/* WAS a 2-column grid reserving half the row's width for a SECOND cell that
   never had content — the "Тариф" stack was the only thing ever rendered,
   so half the row read as unexplained empty space. flex + justify-end
   sizes it to its own content and sits it at the right edge instead,
   matching where the owner's own arrow pointed. */
.agent-card-meta > div { display: grid; gap: 1px; min-width: 0; text-align: end; }
.agent-card-metak { color: var(--rp-ink-3); font-size: 9.5px; }
.agent-card-metav { color: var(--rp-ink-2); font-size: 11px; font-weight: 600; }
.agent-card-metav.muted { color: var(--rp-ink-3); font-weight: 500; }
.agent-card-open {
  width: 100%; min-height: 30px;
  border: 1px solid rgb(var(--ch-blue2) / 0.42);
  border-radius: var(--rp-r-sm);
  background: var(--rp-blue-soft);
  color: var(--sh-blue-1);
  font-size: 11.5px; font-weight: 600;
  cursor: pointer;
}
.agent-card-open:hover { border-color: rgb(var(--ch-blue2) / 0.7); color: var(--rp-ink-max); }

@media (max-width: 1400px) {
  /* The board stacks before the cabinet's three inner columns become unusable;
     the catalogue widens back to four across as it does at full width. */
  .agent-board { grid-template-columns: minmax(0, 1fr); }
  .agent-cards { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
@media (max-width: 1100px) {
  .agent-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .agent-cabhead { flex-wrap: wrap; }
}
@media (max-width: 760px) {
  .agent-cards { grid-template-columns: minmax(0, 1fr); }
}
.agent-card {
  display: grid;
  gap: 10px;
  align-content: space-between;
  /* "саму плашку чуть меньше" — trimmed from the shared --rp-3 token. */
  padding: 12px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-sm);
  background: var(--rp-panel-2);
}
.agent-card:hover { border-color: rgb(var(--ch-blue2) / 0.4); }
.agent-card-top { display: flex; align-items: flex-start; gap: 10px; }
.agent-card-avatar {
  flex: none;
  width: 34px; height: 34px;
  display: grid; place-items: center;
  border-radius: var(--rp-r-sm);
  background: rgb(var(--ch-blue2) / 0.16);
  color: var(--sh-blue-3);
  font-size: 14px;
  font-weight: 700;
}
.agent-card-copy { min-width: 0; display: grid; gap: 3px; }
/* WAS 12.5px/600 — the same weight as the role line right under it, so the
   agent's own name carried no more visual priority than its caption.
   Requested live, 2026-08-21: "шрифт названия самого агента чуть более
   сделал поинтереснее". Bumped size and weight only — colour stays the
   page's own ink token, not a new accent, so this reads as emphasis rather
   than a second, competing highlight next to the CRM stage-age indicator's
   colour system. */
.agent-card-copy strong { font-size: 14px; font-weight: 800; line-height: 1.3; color: var(--rp-ink-max, var(--rp-ink)); letter-spacing: -0.01em; }
/* "тусклые надписи... текст мелкий грустный" — --rp-ink-3 is this theme's
   dimmest tone, right for a truly secondary label but not for the preset's
   own role line, which is half of what identifies the card. One step
   brighter, one step larger. */
.agent-card-copy span { font-size: 11.5px; color: var(--rp-ink-2); }
.agent-card-foot { display: flex; align-items: center; justify-content: space-between; gap: 8px; flex-wrap: wrap; }
.agent-card-open { min-height: 30px; padding: 0 10px; font-size: 11.5px; }

@media (max-width: 1240px) { .agent-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 720px) { .agent-cards { grid-template-columns: minmax(0, 1fr); } }

/* nav · body · rail. 05 splits the cabinet body into the editing cards and a
   right-hand column carrying «Текущие показатели» and «Последние диалоги»;
   the rail is that column. The nav stays vertical, which is how 13 draws this
   same cabinet — recorded as the one structural deviation from 05. */
.agent-cabinet {
  display: grid;
  grid-template-columns: 196px minmax(0, 1fr) minmax(200px, 0.55fr);
  gap: var(--rp-3);
  align-items: start;
}
@media (max-width: 1400px) {
  .agent-cabinet { grid-template-columns: 224px minmax(0, 1fr) minmax(220px, 0.5fr); }
}
@media (max-width: 1100px) {
  .agent-cabinet { grid-template-columns: 200px minmax(0, 1fr); }
  .agent-rail { grid-column: 1 / -1; grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 760px) {
  .agent-cabinet { grid-template-columns: minmax(0, 1fr); }
  .agent-rail { grid-template-columns: minmax(0, 1fr); }
}

.ac-nav {
  display: grid;
  gap: 2px;
  align-content: start;
  padding: var(--rp-3);
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r);
  background: var(--rp-panel);
  position: sticky;
  top: 76px;
}
.ac-nav-head {
  padding: 0 8px 8px;
  margin-bottom: 4px;
  border-bottom: 1px solid var(--rp-line);
  color: var(--rp-ink-3);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
}
.ac-nav-item {
  display: flex;
  align-items: center;
  gap: 9px;
  min-height: 36px;
  padding: 0 9px;
  border: 1px solid transparent;
  border-radius: var(--rp-r-sm);
  background: none;
  color: var(--rp-ink-2);
  font-size: 12.5px;
  font-weight: 500;
  text-align: start;
  cursor: pointer;
}
.ac-nav-item:hover { background: rgb(var(--ch-lift) / 0.035); color: var(--rp-ink); }
.ac-nav-item.on {
  background: var(--rp-blue-soft);
  border-color: rgb(var(--ch-blue2) / 0.42);
  color: var(--rp-ink-max);
  font-weight: 600;
}
.ac-nav-ic { flex: none; width: 18px; text-align: center; font-size: 12px; }

.ac-body { min-width: 0; display: grid; gap: var(--rp-3); }
.ac-section {
  padding: var(--rp-4);
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r);
  background: var(--rp-panel);
  box-shadow: none;
}
.ac-soon {
  display: grid;
  gap: 5px;
  padding: var(--rp-5) var(--rp-4);
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r);
  background: var(--rp-panel);
}
.ac-soon h3 { margin: 0; font-size: 13.5px; font-weight: 620; color: var(--rp-ink); }
.ac-soon p { margin: 0; color: var(--rp-ink-3); font-size: 12px; line-height: 1.55; }

@media (max-width: 900px) {
  .agent-cabinet { grid-template-columns: minmax(0, 1fr); }
  .ac-nav { position: static; display: flex; flex-wrap: wrap; gap: 6px; }
  .ac-nav-head { width: 100%; }
}

/* ═══ SHARED PRIMITIVES — Marketing, Media, Reports, Integrations, Settings ═
   Phases 7 and 8 in one pass, because these five screens are not five design
   problems. They are built from ONE vocabulary — campaign-card, route-card,
   report-card, integration-card, readiness-card, detail-grid, split-layout,
   empty-state, badge-row — and 09, 10, 12, 13 and 15 draw that vocabulary the
   same way in every panel. Restyling the primitive lifts every screen that
   uses it, which is also why the legacy look survived so long: it lived in
   these shared classes, not on any one page. */

/* Every card variant lands on the same surface: 12px, flat, one hairline. */
.campaign-card, .route-card, .report-card, .integration-card, .readiness-card,
.roi-input-card, .integration-detail, .context-panel, .drawer-block,
.integrations-command, .revenue-integration-grid > *, .media-empty-panel {
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r);
  background: var(--rp-panel);
  box-shadow: none !important;
  padding: var(--rp-4);
}
.campaign-card:hover, .route-card:hover, .integration-card:hover, .report-card:hover {
  border-color: var(--rp-line-2);
  transform: none;
}

/* Grids: the package's 4-up that collapses cleanly, not fixed columns. */
.campaign-grid, .route-card-grid, .report-grid, .integration-grid,
/* The 250px floor is a MINIMUM, so in a container narrower than one track the
   track keeps its 250px and the cards spill past the grid. Measured on
   /integrations: the readiness grid ran 38px wider than its box at 1920 and
   36px at 1440, and two readiness cards physically overlapped by 24×202.
   `min(250px, 100%)` collapses the floor only when it cannot fit — a layout
   that already fits is unchanged, which is why this is safe to share. */
.readiness-grid, .revenue-integration-grid, .metric-grid, .roi-input-grid,
.xo-dist-grid, .detail-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(250px, 100%), 1fr));
  gap: var(--rp-3);
  align-items: start;
}

/* CRM-распределения: ряд должен читаться как ОДИН объект, а не как три-четыре
   разных прямоугольника. Общее правило выше ставит `align-items: start`, и
   каждая карточка садится ровно по своему содержимому: «Leads by stage» — 364px,
   «Leads by owner» — 240, «Leads by pipeline» с одной воронкой — 137. Владелец
   увидел рваный низ и спросил, дозаполнится ли пустое место, когда сотрудников
   станет больше. Ответ: пустого места от короткого списка меньше не становится —
   при `start` оно просто уходит ПОД карточку, за её границу, и ряд выглядит
   сломанным. Тянем карточки на всю высоту ряда, а список внутри прижат к верху:
   появятся сотрудники и воронки — строки заполнят то же место сверху вниз, и
   высота ряда не дрогнет. Никаких фиктивных строк: пустое место внутри карточки
   — это и есть честный ответ «здесь пока одна воронка».
   `min-height: 0` обязателен: без него flex-элемент не даёт себя сжать ниже
   содержимого, и внутренняя прокрутка списка перестаёт работать. */
.xo-dist-grid { align-items: stretch; }
.xo-dist-grid > .xo-card {
  height: 100%;
  display: flex;
  flex-direction: column;
}
.xo-dist-grid > .xo-card > .xo-stage-scroll {
  flex: 1 1 auto;
  min-height: 0;
  align-content: start;
}
.split-layout, .roi-layout {
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) minmax(260px, 1fr);
  gap: var(--rp-3);
  align-items: start;
}

/* THE SECOND COLUMN THIS GRID WAS PAIRED WITH NO LONGER EXISTS.
   .integration-workbench held the 118-row connector catalogue on the left and
   its detail pane on the right. The catalogue was deleted; the two-column rule
   stayed, so the workbench's remaining children alternated between a wide
   empty column and a ~300px one. That is why Settings > Partners drew the whole
   partner cabinet as one narrow strip down the right edge with half the page
   blank beside it. One column, full width. */
.integration-workbench {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--rp-3);
  align-items: start;
}

/* Card headings across all five screens. */
.card-head, .card-title-row, .campaign-card-header, .provider-card-head,
.integration-detail-head, .campaign-detail-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--rp-3);
  margin-bottom: var(--rp-3);
  padding: 0;
  border: 0;
  background: none;
}
.card-head h3, .card-title-row h3, .campaign-title, .report-card h3,
.integration-card h3, .readiness-card h3, .route-card h3 {
  margin: 0;
  font-size: 14px;
  font-weight: 620;
  letter-spacing: -0.01em;
  color: var(--rp-ink);
}
.source-note, .microcopy, .business-source, .cs-note {
  color: var(--rp-ink-3);
  font-size: 11.5px;
  line-height: 1.55;
}

/* Honest/empty states get one voice everywhere rather than five. */
.empty-state, .route-empty-state, .media-empty-panel {
  display: grid;
  gap: 5px;
  padding: var(--rp-5) var(--rp-4);
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r);
  background: var(--rp-panel);
  text-align: start;
}
.empty-state h2, .empty-state h3, .route-empty-state h2 {
  margin: 0;
  font-size: 13.5px;
  font-weight: 620;
  color: var(--rp-ink);
}
.empty-state p, .route-empty-state p { margin: 0; color: var(--rp-ink-3); font-size: 12px; line-height: 1.55; }

.badge-row { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }
.page-actions, .row-actions, .integration-actions { display: flex; gap: var(--rp-2); flex-wrap: wrap; }

/* Status chips — one set of semantics, the package's colours. */
.xo-chip, .status-pill, .provider-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 8px;
  border-radius: var(--rp-r-pill);
  font-size: 10.5px;
  font-weight: 620;
  white-space: nowrap;
}
.xo-chip.live, .status-pill.good { color: var(--rp-green); background: rgb(var(--ch-green) / 0.14); }
.xo-chip.warn, .status-pill.warning { color: var(--rp-amber); background: rgb(var(--ch-amber) / 0.14); }
.xo-chip.crit, .status-pill.critical { color: var(--rp-red); background: rgb(var(--ch-red) / 0.14); }
.xo-chip.partial { color: var(--sh-blue-3); background: rgb(var(--ch-blue2) / 0.16); }
.xo-chip.off, .xo-chip.demo, .status-pill.neutral { color: var(--rp-ink-3); background: rgb(var(--ch-slate) / 0.12); }

/* Tabs inside modules already share .module-tabs with the shell; the panel and
   settings variants join them rather than keeping their own chip row. */
.panel-mode-tabs {
  display: flex;
  gap: 0;
  padding: 0;
  border: 0;
  border-bottom: 1px solid var(--rp-line);
  border-radius: 0;
  background: none;
  overflow-x: auto;
}
.panel-mode-tabs button {
  min-height: 36px;
  padding: 0 13px;
  border: 0;
  border-bottom: 2px solid transparent;
  border-radius: 0;
  background: none;
  color: var(--rp-ink-3);
  font-size: 12.5px;
  white-space: nowrap;
}
.panel-mode-tabs button.active, .panel-mode-tabs button[aria-pressed="true"] {
  color: var(--rp-ink-max);
  font-weight: 600;
  border-bottom-color: var(--rp-blue);
  background: none;
}

/* Form controls, which Settings is mostly made of. */
input[type="text"], input[type="email"], input[type="search"], input[type="url"],
input[type="number"], input[type="tel"], input[type="password"], select, textarea {
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-sm);
  background: rgb(var(--ch-lift) / 0.03);
  color: var(--rp-ink);
  font-size: 12.5px;
  font-family: inherit;
}
input:focus, select:focus, textarea:focus {
  border-color: rgb(var(--ch-blue2) / 0.5);
  outline: none;
  box-shadow: 0 0 0 3px rgb(var(--ch-blue2) / 0.12);
}
label, .field-label { color: var(--rp-ink-2); font-size: 12px; }

/* Tables across Marketing campaigns, Reports and the reconciliation views. */
table { border-collapse: collapse; width: 100%; font-size: 12px; }
th {
  text-align: start;
  padding-block: 0 8px; padding-inline: 0 8px;
  border-bottom: 1px solid var(--rp-line);
  color: var(--rp-ink-3);
  font-size: 11px;
  font-weight: 600;
}
td { padding-block: 9px 9px; padding-inline: 0 8px; border-bottom: 1px solid var(--rp-line); color: var(--rp-ink-2); }
tr:last-child td { border-bottom: 0; }

@media (max-width: 1100px) {
  .split-layout, .roi-layout, .integration-workbench { grid-template-columns: minmax(0, 1fr); }
}

/* ═══ MEDIA FACTORY (mockup 10) ══════════════════════════════════════════
   This module kept its own namespace and, with it, its own design system.
   Measured on the running page it carried SIX different card backgrounds
   (var(--lg-surf-7), var(--lg-surf-11), var(--lg-surf-9), var(--lg-surf-8), var(--lg-surf-13), var(--lg-surf-6)), five radii (6, 9, 10,
   12, 14px) and three drop shadows. The tab set already matches 10 exactly —
   what did not match was that no two cards on the screen agreed with each
   other. One surface, one radius, no shadow. */

.media-workspace-header, .media-workspace-nav, .media-hub-metric,
.mf-mix-card, .mf-pulse-card, .mf-onboard-step, .media-hub-channels,
.media-channel-card, .media-hub-boro, .media-cs-banner, .media-safety-note {
  border-radius: var(--rp-r) !important;
  background: var(--rp-panel) !important;
  border: 1px solid var(--rp-line);
  box-shadow: none !important;
}
/* Rows nested INSIDE a card sit one step up, not on a different palette. */
.mf-onboard-step, .media-channel-card, .media-hub-metric {
  background: var(--rp-panel-2) !important;
  border-radius: var(--rp-r-sm) !important;
}
.media-workspace-nav {
  display: flex;
  gap: 0;
  padding: 0 !important;
  border: 0;
  border-bottom: 1px solid var(--rp-line);
  border-radius: 0 !important;
  background: none !important;
  overflow-x: auto;
}
.media-workspace-nav button, .media-workspace-nav a {
  min-height: 38px;
  padding: 0 13px;
  border: 0;
  border-bottom: 2px solid transparent;
  border-radius: 0;
  background: none;
  color: var(--rp-ink-3);
  font-size: 12.5px;
  white-space: nowrap;
}
.media-workspace-nav .active, .media-workspace-nav [aria-current="page"] {
  color: var(--rp-ink-max);
  font-weight: 600;
  border-bottom-color: var(--rp-blue);
  background: none;
}
.media-hub-metric strong, .mf-pulse-card strong {
  font-size: 21px;
  font-weight: 660;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
  color: var(--rp-ink-max);
}
.media-safety-note { border-radius: var(--rp-r) !important; color: var(--rp-ink-3); font-size: 11.5px; }

/* ═══ THE LAST LEGACY CONTROLS ═══════════════════════════════════════════
   Found by walking the rendered DOM of every route and listing each element
   that still painted a surface of its own. These are the stragglers: controls
   shared by Marketing, Reports and Settings that kept a navy-tinted panel and
   a drop shadow from the old system. `!important` is used where the legacy
   declaration is itself `!important` — the same rule the file header sets out,
   and each one goes when its original does. */
.crm-connect-card, .roi-input-card, .readiness-card-button {
  background: var(--rp-panel) !important;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r) !important;
  box-shadow: none !important;
}
.primary-button, .secondary-button, .ghost-button, .compact-button,
.segmented-control button.active {
  box-shadow: none !important;
}
.secondary-button {
  min-height: 36px;
  padding: 0 14px;
  border-radius: var(--rp-r-sm) !important;
  border: 1px solid var(--rp-line);
  background: rgb(var(--ch-lift) / 0.03);
  color: var(--rp-ink);
  font-size: 12.5px;
}
.secondary-button:hover { background: rgb(var(--ch-lift) / 0.06); border-color: var(--rp-line-2); }
.status-pill { background: rgb(var(--ch-slate) / 0.12); }
.workspace-selector, .period-selector, .segmented-control {
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-sm) !important;
  background: rgb(var(--ch-lift) / 0.025) !important;
}
.data-source-badge { border-radius: var(--rp-r-pill); font-size: 10.5px; font-weight: 620; }

/* Page footer, straight from 16. */
.rp-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--rp-3);
  padding: 10px var(--rp-4);
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r);
  background: var(--rp-panel);
  color: var(--rp-ink-3);
  font-size: 11.5px;
}
.rp-footer-side { display: flex; align-items: center; gap: var(--rp-3); flex-wrap: wrap; }

/* Legacy chrome the package does not have, removed rather than restyled. */
.launch-strip,
.dashboard-onboarding-panel,
.data-status-line { display: none; }

/* ═══ RESPONSIVE ═════════════════════════════════════════════════════════ */

@media (max-width: 1100px) {
  .rp-grid-wide { grid-template-columns: minmax(0, 1fr); }
  .workspace { padding: var(--rp-4) var(--rp-4) var(--rp-6); }
}

@media (max-width: 900px) {
  .topbar { flex-direction: column; align-items: stretch; }
  .header-actions { flex-wrap: wrap; }
  .module-header { grid-template-columns: minmax(0, 1fr); }
  /* The wordmark is the first thing to go: the rail already carries the brand,
     and search is worth more than a repeated name. */
  .rp-topbar-brand { display: none; }
  .rp-agent-pill { max-width: 150px; overflow: hidden; }
}

@media (max-width: 720px) {
  :root { --rp-rail-w: 100%; }
  .rp-kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .rp-kpi-value { font-size: 21px; }
  .rp-kpi-spark { height: 38px; }
  .rp-periods { width: 100%; max-width: 100%; overflow-x: auto; flex-wrap: nowrap; }
  /* …и кнопки в ней не сжимаются (24.09.2026, замер 375×812): полоса
     прокручивается, но кнопки с overflow: hidden сжимались до 30 px, и от
     «Вчера», «7 дней», «Год» оставались обрезки. Не влезло — листается. */
  .rp-periods button { flex: none; }
  /* Полоса периодов (9 кнопок, 761px) не сжималась: элементы сетки .rp-ov по
     умолчанию min-width: auto и отказывались уже своего содержимого, и на
     телефоне весь «Обзор» становился 756px шириной и обрезался (найдено
     14 сентября). Разрешаем детям сжиматься — полоса прокручивается сама. */
  .rp-ov > *, .rp-ov-controls > * { min-width: 0; }
  /* ПОДВАЛ НА ТЕЛЕФОНЕ — ОДНА СТРОКА (24 сентября 2026). Здесь стояло
     flex-direction: column: «Руководство · Обновлено · Часовой пояс ·
     Настроить» вставали в три строки, и 111 px из 812 у КАЖДОГО экрана
     уходили на подвал, который не прокручивается (страница листается внутри
     .page-stack, подвал — под ней). Теперь одна строка ~40 px; что не
     влезло — листается вбок, ссылки — в рост пальца. */
  .rp-footer {
    flex-direction: row; flex-wrap: nowrap; align-items: center; justify-content: flex-start;
    gap: 14px; padding: 4px 12px; margin-top: 8px;
    overflow-x: auto; scrollbar-width: none; white-space: nowrap;
    font-size: 12px;
  }
  .rp-footer::-webkit-scrollbar { display: none; }
  .rp-footer-side { flex: none; flex-wrap: nowrap; gap: 14px; }
  .rp-footer-link { display: inline-flex; align-items: center; min-height: 32px; font-size: 12px; }
  .app-shell .topbar-copy h1, .app-shell .workspace-header h1 { font-size: 22px; }
  /* At phone width the bar keeps only what cannot be reached another way:
     search, the agent state and the account. The ⌘K hint goes with the
     keyboard that cannot produce it. */
  .rp-topbar {
    gap: var(--rp-2);
    margin: calc(var(--rp-4) * -1) calc(var(--rp-4) * -1) var(--rp-4);
    padding: 0 var(--rp-4);
  }
  .rp-search-kbd { display: none; }
  .rp-agent-pill { max-width: 96px; }
  .rp-agent-pill, .rp-search-control { font-size: 11px; }
}

@media (max-width: 460px) {
  .rp-kpis { grid-template-columns: minmax(0, 1fr); }
}

/* ═══ MOBILE PASS (the phone frames in mockup 13) ════════════════════════
   13 ends with four phone frames — главный экран, AI-агенты, диалоги, воронка
   — which the map read as a real requirement rather than decoration. Below
   980px styles.css already turns .app-shell into a block, so the rail becomes
   a normal band at the top of the document; these rules make that band behave
   like navigation instead of a 232px column lying on its side. */
@media (max-width: 980px) {
  .app-shell, .app-shell.rail-collapsed { grid-template-columns: minmax(0, 1fr); }

  /* The rail turns into a horizontal scroller of the same 10 items. */
  .sidebar {
    position: sticky;
    top: 0;
    z-index: 45;
    gap: var(--rp-2);
    padding: var(--rp-2) var(--rp-3);
    border-inline-end: 0;
    border-bottom: 1px solid var(--rp-line);
  }
  .nav-list {
    display: flex;
    gap: 6px;
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }
  .nav-list::-webkit-scrollbar { display: none; }
  .nav-section { display: contents; }
  .nav-item { flex: none; min-height: 38px; padding: 0 10px; white-space: nowrap; }
  /* On a phone the icon carries the item; the label would force a scroller
     three screens wide. The accessible name stays on the button. */
  .nav-item span:not([class*="nav-icon"]):not(.nav-badge) { display: none; }
  .nav-item.active span:not([class*="nav-icon"]):not(.nav-badge) { display: inline; }
  /* The count on «На решение» is not a label: it is the reason to tap. It keeps
     its own rules (and stays hidden when there is nothing to decide). */

  /* Rail furniture that is not navigation goes; all of it is reachable from
     the profile menu or its own screen. */
  .rail-systems, .sidebar-support, .sidebar-secondary-actions,
  .rail-toggle, .brand-copy { display: none; }
  .sidebar-workspace-button { display: none; }

  .workspace { padding: var(--rp-4) var(--rp-3) var(--rp-6); }
  .rp-topbar { margin: calc(var(--rp-4) * -1) calc(var(--rp-3) * -1) var(--rp-4); padding: 0 var(--rp-3); }

  /* КОЛОНКА СТРАНИЦЫ НЕ ШИРЕ ЭКРАНА (24 сентября 2026). .page-stack — сетка
     с неявной колонкой auto, и её распирало до самого широкого содержимого:
     на телефоне «Бухгалтерия» была 1461 px шириной, полоса вкладок финансов —
     614, а overflow: hidden у .page-stack молча отрезал всё правее 357 px —
     кнопки, суммы, половину таблиц. 23 сентября то же самое поправили только
     для стола интеграций (pack-design.css, .page-stack:has(> section.idesk));
     здесь — для всех страниц на ширине телефона и планшета. */
  .page-stack { grid-template-columns: minmax(0, 1fr); }
  /* One column everywhere, and tables scroll inside their own card rather
     than making the page scroll sideways. */
  .rp-ov-row, .rp-grid-4, .rp-grid-wide, .campaign-grid, .route-card-grid,
  .report-grid, .integration-grid, .readiness-grid, .metric-grid,
  .detail-grid, .xo-dist-grid, .crm-kpi-row, .kb-cols {
    grid-template-columns: minmax(0, 1fr) !important;
  }
  .rp-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .control-card, .xo-card, .ac-section, .campaign-card, .route-card,
  .report-card, .integration-card, .readiness-card { padding: var(--rp-3); }
  table { display: block; overflow-x: auto; white-space: nowrap; }
  /* …и min-width: 0 (24.09.2026): styles.css даёт КАЖДОЙ таблице
     min-width: 690px, и блочная таблица с прокруткой внутри сама была шире
     экрана — прокрутка не включалась, а правый край срезался вместе со
     столбцами (кампании в «Маркетинге», отчёты «Центра действий»,
     эндпоинты API). Теперь коробка таблицы — по ширине карточки, строки
     листаются внутри неё. */
  table { min-width: 0; }

  /* The board scrolls horizontally, one column at a time — the only sane
     kanban on a phone. */
  .kb-cols {
    display: flex !important;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    gap: var(--rp-2);
  }
  .kb-col { flex: 0 0 84%; scroll-snap-align: start; }

  .chatpane-body { min-height: 0; }
  .chatpane-list, .chatpane-thread { max-height: none; }
  .chat-statusbar, .voice-footer { font-size: 11px; gap: var(--rp-2); }
}

@media (max-width: 560px) {
  .rp-search-control { max-width: none; }
  .rp-topbar { min-height: 54px; }
  .rp-tiles { grid-template-columns: minmax(0, 1fr); }
  .rp-kpi-value { font-size: 20px; }
  .voice-dial { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  /* Touch targets: 38px is fine under a mouse and small under a thumb.
     `.nav-item` needs the flag — styles.css pins `min-height: auto !important`
     on it, the eighth such flag found so far and the reason a plain
     declaration here measured as `auto` on the running page. Scoped to the one
     property, and it goes when the legacy declaration does. */
  .chat-chpill, .primary-button, .secondary-button, .ghost-button,
  .crm-viewtoggle button, .module-tabs button, .group-subnav-item { min-height: 42px; }
  .nav-item { min-height: 42px !important; }
  /* Девятый такой флаг (24.09.2026, замер 375×812): styles.css держит
     `.module-tabs button{ min-height:auto !important }` (вкладки переносятся
     строками вместо прокрутки), и строка выше до них не доходила — фильтры
     «Возврата лидов», вкладки «Маркетинга» и AI-директора были 20 px в
     высоту. */
  .module-tabs button { min-height: 42px !important; }
  /* «Открыть отчёты →», «Все задачи →» под карточками обзора были 29 px в
     высоту — под мышь, не под палец (24.09.2026). */
  .rp-card-foot { min-height: 40px; }
  /* Обычные галочки браузера — 13×13: выбор лидов в списке, «позвать на
     совещание», каналы рассылки, уведомления. На телефоне — 20 px; галочки со
     своим оформлением (классом) это правило не трогает — оно слабее. */
  input[type="checkbox"], input[type="radio"] { width: 20px; height: 20px; }
  /* И не сжимаются: в строке-подписи (label — flex) длинный текст сжимал
     галочку до 13 px в ширину — «Включить инструкцию», база знаний голоса,
     «Счёт из сделки», AI-совет (замер 375×812, 24.09.2026). */
  input[type="checkbox"], input[type="radio"] { flex-shrink: 0; }
  /* Раскрывающиеся строки («Последние решения», «Пригласить списком»,
     «Счёт из сделки», «Чек-лист приёмки») — 19–26 px в высоту. */
  summary { min-height: 32px; padding-block: 6px; box-sizing: border-box; }
}

/* ВЕРХНЯЯ ПОЛОСА НА ТЕЛЕФОНЕ (24 сентября 2026). В 351 px стояли поиск,
   состояние AI-агентов, колокольчик и профиль — и стояли плохо: «AI-агенты:
   Акт» обрезалось на полуслове (max-width 96 px), кнопки были 28 px в высоту,
   подпись поиска резалась до «Поиск по систе…» шрифтом 11 px. Поиск на
   телефоне — значок лупы (он понятен без подписи; открывает тот же поиск),
   состояние агентов — целиком, при нехватке места в две строки, а не
   обрезкой; кнопки — 36 px. */
@media (max-width: 480px) {
  .rp-topbar-search { flex: 0 0 auto; }
  .rp-search-control { width: 40px; min-width: 40px; justify-content: center; padding: 0; }
  .rp-search-control .rp-search-text { display: none; }
  .rp-search-control, .rp-bell { height: 36px; min-height: 36px; }
  .rp-bell { width: 36px; }
  .rp-topbar .profile-trigger { min-height: 36px; }
  .rp-topbar .profile-avatar { font-size: 12px; }
  .rp-agent-pill {
    flex: 0 1 auto; min-width: 0; max-width: none; min-height: 30px;
    padding: 3px 10px; border-radius: 12px;
    white-space: normal; line-height: 1.2; font-size: 12px;
  }
}

/* ═══ MARKETING & SOURCES (mockup 09) ════════════════════════════════════
   09 draws six KPI tiles, then dynamics · traffic sources · attribution, then
   campaigns · insights. In Client View with no ad account this route used to
   collapse to a header and one route-empty-state, so an owner could not see
   what connecting would give them. Every block is present now and each states
   its own absence — no fabricated spend, CPL, ROAS or campaign rows. */
.mk-board { display: grid; gap: var(--rp-3); }
.mk-kpis { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: var(--rp-3); }
.mk-kpi {
  display: grid; gap: 2px; align-content: start;
  padding: 11px 13px; min-height: 118px;
  border: 1px solid var(--rp-line); border-radius: var(--rp-r);
  background: var(--rp-panel);
}
.mk-kpi.is-off { background: rgb(var(--ch-lift) / 0.012); }
.mk-kpi-head { display: flex; align-items: center; justify-content: space-between; gap: 6px; flex-wrap: wrap; row-gap: 3px; }
.mk-kpi-label { color: var(--rp-ink-2); font-size: 11px; }
.mk-kpi-value { color: var(--rp-ink-3); font-size: 22px; font-weight: 660; line-height: 1.15; font-variant-numeric: tabular-nums; }
.mk-kpi-was { color: var(--rp-ink-3); font-size: 10.5px; }
/* 09 puts a sparkline in every tile. No series exists, so the band keeps its
   height and stays empty rather than drawing a shape that means nothing. */
.mk-spark { min-height: 34px; margin-top: 4px; border: 1px dashed var(--rp-line); border-radius: var(--rp-r-sm); }

.mk-rowa { display: grid; grid-template-columns: minmax(0, 1.32fr) minmax(0, 1fr) minmax(0, 1.04fr); gap: var(--rp-3); align-items: start; }
.mk-rowb { display: grid; grid-template-columns: minmax(0, 2.24fr) minmax(0, 1fr); gap: var(--rp-3); align-items: start; }
.mk-card { padding: 12px 14px; }
.mk-cardhead { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 9px; }
.mk-cardhead h3 { margin: 0; font-size: 13.5px; font-weight: 620; color: var(--rp-ink); }
.mk-cardtag {
  margin-inline-start: auto; padding: 1px 7px;
  border-radius: var(--rp-r-pill); background: rgb(var(--ch-lift) / 0.05);
  color: var(--rp-ink-3); font-size: 10px; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.03em;
}
.mk-note { margin: 8px 0 0; color: var(--rp-ink-3); font-size: 10.5px; line-height: 1.45; }

.mk-metrictabs { display: flex; gap: 5px; flex-wrap: wrap; margin-bottom: 8px; }
.mk-metrictab {
  padding: 2px 9px; border: 1px solid var(--rp-line); border-radius: var(--rp-r-pill);
  color: var(--rp-ink-3); font-size: 10.5px;
}
.mk-metrictab.on { border-color: rgb(var(--ch-blue2) / 0.42); background: var(--rp-blue-soft); color: var(--sh-blue-1); }
.mk-chart, .mk-donut, .mk-insight.is-off {
  border: 1px dashed var(--rp-line); border-radius: var(--rp-r-sm);
  color: var(--rp-ink-3);
}
.mk-chart { display: grid; place-items: center; min-height: 196px; padding: var(--rp-3); text-align: center; font-size: 11px; line-height: 1.5; }
.mk-srcwrap { display: flex; align-items: flex-start; gap: var(--rp-3); }
.mk-donut { display: grid; place-items: center; width: 104px; height: 104px; flex: none; border-radius: 50%; font-size: 15px; }
/* The table is a flex child beside the donut and could not shrink, so its
   Лиды / % / CPL columns were clipped by the card edge. */
.mk-srctable { flex: 1 1 auto; min-width: 0; width: 100%; table-layout: fixed; border-collapse: collapse; font-size: 11px; }
.mk-srctable td:first-child, .mk-srctable th:first-child { overflow: hidden; text-overflow: ellipsis; }
.mk-srctable th, .mk-srctable td { padding: 4px 4px; text-align: end; white-space: nowrap; }
.mk-srctable th:first-child, .mk-srctable td:first-child { text-align: start; }
.mk-srctable thead th { color: var(--rp-ink-3); font-size: 10px; font-weight: 600; border-bottom: 1px solid var(--rp-line); }
.mk-srctable tbody td { color: var(--rp-ink-2); border-bottom: 1px solid var(--rp-line); }
.mk-srctable tfoot th, .mk-srctable tfoot td { color: var(--rp-ink); font-weight: 620; padding-top: 6px; }

.mk-accounts { display: grid; gap: 5px; }
.mk-account {
  display: flex; align-items: center; justify-content: space-between; gap: var(--rp-2);
  padding: 7px 10px; border: 1px solid var(--rp-line); border-radius: var(--rp-r-sm);
  background: rgb(var(--ch-lift) / 0.022);
}
.mk-accname { display: grid; gap: 1px; min-width: 0; }
.mk-accname > strong { color: var(--rp-ink-2); font-size: 11.5px; font-weight: 600; }
.mk-accname > span { color: var(--rp-ink-3); font-size: 10px; }
.mk-accchip { flex: none; padding: 1px 8px; border-radius: var(--rp-r-pill); font-size: 10px; font-weight: 600; }
.mk-accchip.on { background: rgb(var(--ch-green) / 0.16); color: var(--sh-ok); }
.mk-accchip.off { background: rgb(var(--ch-amber) / 0.15); color: var(--sh-warm); }
.mk-accchip.na { background: rgb(var(--ch-slate) / 0.14); color: var(--rp-ink-3); }
.mk-accadd {
  width: 100%; min-height: 30px; margin-top: 8px;
  border: 1px solid var(--rp-line); border-radius: var(--rp-r-sm);
  background: none; color: var(--rp-ink-2); font-size: 11.5px; cursor: pointer;
}
.mk-accadd:hover { border-color: var(--rp-line-2); color: var(--rp-ink); }

.mk-filters { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-inline-start: auto; }
.mk-filter { padding: 3px 10px; border: 1px solid var(--rp-line); border-radius: var(--rp-r-sm); color: var(--rp-ink-3); font-size: 10.5px; }
.mk-filter.is-off { opacity: 0.55; }
.mk-newcamp {
  min-height: 26px; padding: 0 11px;
  border: 1px solid var(--rp-line); border-radius: var(--rp-r-sm);
  background: none; color: var(--rp-ink-3); font-size: 11px; cursor: not-allowed; opacity: 0.5;
}
.mk-camptable { width: 100%; border-collapse: collapse; font-size: 11px; }
.mk-camptable th { padding: 0 8px 7px; color: var(--rp-ink-3); font-size: 10px; font-weight: 600; text-align: start; white-space: nowrap; border-bottom: 1px solid var(--rp-line); }
.mk-campempty { padding: 30px 10px; color: var(--rp-ink-3); font-size: 11.5px; line-height: 1.5; text-align: center; }
.mk-pager { display: flex; align-items: center; gap: var(--rp-2); margin-top: 8px; padding-top: 7px; border-top: 1px solid var(--rp-line); color: var(--rp-ink-3); font-size: 10.5px; }

.mk-insights { display: grid; gap: 6px; }
.mk-insight { padding: 9px 11px; }
.mk-insight > strong { display: block; color: var(--rp-ink-2); font-size: 11.5px; font-weight: 620; }
.mk-insight > p { margin: 3px 0 0; color: var(--rp-ink-3); font-size: 10.5px; line-height: 1.45; }

@media (max-width: 1500px) {
  .mk-kpis { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .mk-rowa { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .mk-rowa > *:first-child { grid-column: 1 / -1; }
  .mk-rowb { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 900px) {
  .mk-kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .mk-rowa { grid-template-columns: minmax(0, 1fr); }
  .mk-rowa > *:first-child { grid-column: auto; }
  .mk-srcwrap { flex-wrap: wrap; }
}

/* ═══ INTEGRATIONS (mockup 13, «Интеграции» panel) ═══════════════════════
   A headline count and a five-across connector grid. The catalogue that was
   here marked every connector with a `demo` badge; a connector is Connected,
   Not connected or Unavailable, and nothing else. */
.int13 {
  padding: 12px 14px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r);
  background: var(--rp-panel);
}
.int13-head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 10px; }
.int13-head h3 { margin: 0; font-size: 13.5px; font-weight: 620; color: var(--rp-ink); }
.int13-count { color: var(--rp-ink-3); font-size: 11.5px; }
.int13-grid { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: var(--rp-2); }
.int13-card {
  display: grid; gap: 8px; align-content: start;
  padding: 10px 11px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-sm);
  background: var(--rp-panel-2);
}
.int13-cardtop { display: flex; align-items: center; gap: 7px; min-width: 0; }
.int13-cardtop > strong {
  min-width: 0; color: var(--rp-ink-2); font-size: 11.5px; font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.int13-chip {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 26px; padding: 0 9px;
  border-radius: var(--rp-r-sm);
  font-size: 10.5px; font-weight: 600;
}
.int13-chip.on { background: rgb(var(--ch-green) / 0.16); color: var(--sh-ok); }
.int13-chip.na { background: rgb(var(--ch-slate) / 0.14); color: var(--rp-ink-3); }
.int13-connect {
  min-height: 26px; padding: 0 9px;
  border: 1px solid var(--rp-line); border-radius: var(--rp-r-sm);
  background: none; color: var(--rp-ink-2);
  font-size: 10.5px; cursor: pointer;
}
.int13-connect:hover { border-color: rgb(var(--ch-blue2) / 0.5); color: var(--sh-blue-1); }
@media (max-width: 1400px) { .int13-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (max-width: 1100px) { .int13-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 760px) { .int13-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* ═══ SETTINGS (mockup 13, «Настройки» panel) ════════════════════════════
   A seven-item section rail beside the section itself. The route opened on a
   command header and a flat readiness grid; the company profile — the first
   thing 13 shows — was not represented at all. Fields are read-only because
   there is no settings-write contract, and the save says so. */
.set13 {
  display: grid;
  grid-template-columns: minmax(180px, 1fr) minmax(0, 2.4fr);
  gap: var(--rp-3);
  padding: 12px 14px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r);
  background: var(--rp-panel);
  align-items: start;
}
.set13-rail { display: grid; gap: 2px; align-content: start; }
.set13-rail h3 { margin: 0 0 7px; font-size: 13.5px; font-weight: 620; color: var(--rp-ink); }
.set13-railitem {
  min-height: 32px; padding: 0 11px;
  border: 1px solid transparent; border-radius: var(--rp-r-sm);
  background: none; color: var(--rp-ink-2);
  font-size: 12px; text-align: start; cursor: pointer;
}
.set13-railitem:hover:not(:disabled) { background: rgb(var(--ch-lift) / 0.035); color: var(--rp-ink); }
.set13-railitem.on { background: var(--rp-blue-soft); border-color: rgb(var(--ch-blue2) / 0.42); color: var(--rp-ink-max); font-weight: 600; }
.set13-railitem:disabled { opacity: 0.45; cursor: not-allowed; }
.set13-body { min-width: 0; border-inline-start: 1px solid var(--rp-line); padding-inline-start: var(--rp-3); }
.set13-body h4 { margin: 0 0 10px; font-size: 13.5px; font-weight: 620; color: var(--rp-ink); }
.set13-form { display: grid; grid-template-columns: 168px minmax(0, 1fr); gap: var(--rp-3); align-items: start; }
.set13-logo { display: grid; gap: 7px; }
.set13-logomark {
  display: grid; place-items: center;
  height: 132px;
  border: 1px solid var(--rp-line); border-radius: var(--rp-r-sm);
  background: rgb(var(--ch-lift) / 0.022);
  color: var(--rp-ink-3); font-size: 30px;
}
.set13-logobtn, .set13-savebtn {
  min-height: 30px; padding: 0 12px;
  border: 1px solid var(--rp-line); border-radius: var(--rp-r-sm);
  background: none; color: var(--rp-ink-2); font-size: 11.5px; cursor: pointer;
}
.set13-logobtn:disabled, .set13-savebtn:disabled { opacity: 0.45; cursor: not-allowed; }
.set13-savebtn { background: var(--rp-blue-soft); border-color: rgb(var(--ch-blue2) / 0.42); color: var(--sh-blue-1); font-weight: 600; }
.set13-fields { display: grid; gap: 8px; min-width: 0; }
.set13-field { display: grid; gap: 3px; min-width: 0; }
.set13-field > span { color: var(--rp-ink-3); font-size: 10.5px; }
.set13-input {
  min-height: 32px; padding: 7px 10px;
  border: 1px solid var(--rp-line); border-radius: var(--rp-r-sm);
  background: rgb(var(--ch-lift) / 0.03);
  color: var(--rp-ink-2); font-size: 12px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.set13-select { background-image: none; }
.set13-area { min-height: 58px; white-space: normal; }
.set13-save { grid-column: 1 / -1; display: flex; align-items: center; gap: var(--rp-3); flex-wrap: wrap; margin-top: 10px; padding-top: 9px; border-top: 1px solid var(--rp-line); }
.set13-savenote { color: var(--rp-ink-3); font-size: 10.5px; }
/* «Сохранить» больше не прилипает к подсказке над собой.
   Форма профиля компании — это три блока подряд (сетка полей, плашка «Пароли,
   ключи и платёжные данные здесь не запрашиваются», кнопка), и у всех трёх
   margin: 0. Измерено 14 сентября: расстояние между низом плашки и верхом
   кнопки было РОВНО 0 px — кнопка читалась как часть плашки.
   Воздух даётся контейнером, а не кнопкой: gap разводит все три блока сразу,
   и следующий, кто допишет сюда четвёртый, получит отступ бесплатно. */
.set13-profile-form { display: grid; gap: 14px; }
.set13-profile-form > .setup-form-grid { margin: 0; }
/* Кнопка в grid растянулась бы на всю ширину формы — прижимаем к началу строки
   (в RTL — к правому краю, поэтому start, а не left). */
.set13-profile-form > button[type="submit"] { justify-self: start; }
@media (max-width: 900px) {
  .set13 { grid-template-columns: minmax(0, 1fr); }
  .set13-body { border-inline-start: 0; padding-inline-start: 0; }
  .set13-form { grid-template-columns: minmax(0, 1fr); }
}

/* The legacy Workspace Settings screen was rendering directly under the new
   reference panel, so /settings read as two screens stacked. It is neither
   deleted nor duplicated — it is hidden by a class on the page and revealed by
   the Настройка lens, so the default Settings view ends at the reference
   panel. Hidden, not unmounted: every control keeps its state and handlers. */
.set13-lens { display: flex; gap: 2px; border-bottom: 1px solid var(--rp-line); }
.set13-lensbtn {
  min-height: 30px; padding: 0 12px;
  border: 0; border-bottom: 2px solid transparent;
  background: none; color: var(--rp-ink-3);
  font-size: 12px; cursor: pointer;
}
.set13-lensbtn.on { color: var(--rp-ink-max); font-weight: 600; border-bottom-color: var(--rp-blue); }
/* superseded below — the allow-list now also carries .suplegal */


/* ═══ ACTION CENTER (15: Tasks & Follow ups + Reports) ═══════════════════
   Two surfaces side by side. Neither has a per-owner source in this product —
   no task ledger on this screen, no cost-per-lead, no meeting count, no
   attributed revenue — so each block keeps its shape and names what is
   missing rather than drawing a figure from nothing. */
.ac15 { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.9fr); gap: var(--rp-3); align-items: start; }
.ac15 .control-card { padding: 12px 14px; }
.ac15-head { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
.ac15-head h3 { margin: 0; font-size: 13.5px; font-weight: 620; color: var(--rp-ink); }
.ac15-tag {
  margin-inline-start: auto; padding: 1px 7px;
  border-radius: var(--rp-r-pill); background: rgb(var(--ch-lift) / 0.05);
  color: var(--rp-ink-3); font-size: 10px; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.03em;
}
.ac15-empty {
  padding: 18px 14px;
  border: 1px dashed var(--rp-line); border-radius: var(--rp-r-sm);
  color: var(--rp-ink-3);
}
.ac15-empty > strong { display: block; color: var(--rp-ink-2); font-size: 12.5px; font-weight: 620; }
.ac15-empty > p { margin: 5px 0 0; font-size: 11px; line-height: 1.5; }
.ac15-link {
  width: 100%; min-height: 30px; margin-top: 9px;
  border: 1px solid var(--rp-line); border-radius: var(--rp-r-sm);
  background: none; color: var(--rp-ink-2); font-size: 11.5px; cursor: pointer;
}
.ac15-link:hover { border-color: var(--rp-line-2); color: var(--rp-ink); }
.ac15-kpis { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--rp-2); }
.ac15-kpi {
  display: grid; gap: 3px;
  padding: 9px 11px; min-height: 62px;
  border: 1px solid var(--rp-line); border-radius: var(--rp-r-sm);
  background: rgb(var(--ch-lift) / 0.022);
}
.ac15-kpilabel { color: var(--rp-ink-3); font-size: 10.5px; }
.ac15-kpi > strong { color: var(--rp-ink-3); font-size: 19px; font-weight: 660; font-variant-numeric: tabular-nums; }
.ac15-charts { display: grid; grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr); gap: var(--rp-2); margin-top: var(--rp-2); }
.ac15-chart {
  display: grid; place-items: center; gap: 4px;
  min-height: 128px; padding: var(--rp-3);
  border: 1px dashed var(--rp-line); border-radius: var(--rp-r-sm);
  color: var(--rp-ink-3); text-align: center;
}
.ac15-chart > span { font-size: 11.5px; font-weight: 600; }
.ac15-chart > em { font-size: 10.5px; font-style: normal; }
.ac15 h4 { margin: var(--rp-3) 0 6px; font-size: 12px; font-weight: 620; color: var(--rp-ink-2); }
.ac15-table { width: 100%; border-collapse: collapse; font-size: 11px; }
.ac15-table th { padding: 0 8px 6px; color: var(--rp-ink-3); font-size: 10px; font-weight: 600; text-align: start; border-bottom: 1px solid var(--rp-line); }
.ac15-tableempty { padding: 24px 10px; color: var(--rp-ink-3); font-size: 11.5px; line-height: 1.5; text-align: center; }
@media (max-width: 1200px) { .ac15 { grid-template-columns: minmax(0, 1fr); } }
@media (max-width: 820px) {
  .ac15-kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ac15-charts { grid-template-columns: minmax(0, 1fr); }
}

/* Action Center uses the same lens the Settings face uses: the reference
   surfaces are the default page, and the legacy governance panel plus the
   source-report catalogue sit behind «Отчёты и контроль». Hidden by a class,
   not unmounted — the report tabs and every handler keep their state.
   The reveal repeats the :not() chain deliberately: those arguments count
   toward specificity, and without them the hide rule wins and the lens
   reveals nothing (the bug caught on Settings). */
.face-lensbar { display: flex; gap: 2px; border-bottom: 1px solid var(--rp-line); }
/* TWO LENSES, TWO SCREENS. Until 4 September both tabs showed the same thing:
   .ac15 was outside the toggle set (identical above the fold on both), the
   revealed blocks landed BELOW it with nothing scrolling to them, and the
   reveal rule said `display: revert` — which rolls back to the UA value
   (block), not to the author value, so .module-tabs lost its flex and
   .report-grid its grid. The owner: «один и тот же экран, ничего не меняется».
   Now the hide rule is conditional (no reveal rule needed, every block keeps
   its own display), and the Action Center leaves when Reports takes over. */
.face-lens:not(.show-legacy) > *:not(.ac15):not(.face-lensbar) { display: none; }
.face-lens.show-legacy > .ac15 { display: none; }

/* ═══ SUPPORT & LEGAL ════════════════════════════════════════════════════
   Four action widgets and a quiet legal row on the Settings face. Only the
   Support Center has a destination that exists in this product; the rest are
   visibly unavailable with the reason on hover, because inventing a handle,
   a number or a policy URL would put a contact nobody owns into a live
   product. Added to the face-lens allow-list on purpose. */
.suplegal {
  padding: 12px 14px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r);
  background: var(--rp-panel);
}
.suplegal h3 { margin: 0 0 9px; font-size: 12.5px; font-weight: 620; color: var(--rp-ink); }
.suplegal-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--rp-2); }
.suplegal-card {
  display: flex; align-items: center; gap: 9px;
  min-height: 50px; padding: 8px 11px;
  border: 1px solid var(--rp-line); border-radius: var(--rp-r-sm);
  background: rgb(var(--ch-lift) / 0.022);
  text-align: start; cursor: pointer;
}
.suplegal-card:hover:not(:disabled) { border-color: rgb(var(--ch-blue2) / 0.5); background: var(--rp-blue-soft); }
.suplegal-card.is-off, .suplegal-card:disabled { opacity: 0.45; cursor: not-allowed; }
.suplegal-glyph { flex: none; font-size: 15px; }
.suplegal-copy { display: grid; gap: 1px; min-width: 0; }
.suplegal-copy > strong { color: var(--rp-ink-2); font-size: 11.5px; font-weight: 620; }
.suplegal-copy > span {
  color: var(--rp-ink-3); font-size: 10.5px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.suplegal-legal {
  display: flex; align-items: center; gap: var(--rp-3); flex-wrap: wrap;
  margin-top: 9px; padding-top: 8px; border-top: 1px solid var(--rp-line);
}
/* Live anchors now — privacy.html and terms.html are real documents at the
   repository root. The previous rules styled them as permanently unavailable,
   which was wrong about the product. */
.suplegal-legallink {
  color: var(--rp-ink-3);
  font-size: 10.5px;
  text-decoration: none;
  border-bottom: 1px solid transparent;
}
.suplegal-legallink:hover { color: var(--rp-ink-2); border-bottom-color: var(--rp-line-2); }
/* The Settings face shows the reference panel, its lens strip and this block. */
/* Same shape as .face-lens above: a conditional hide instead of a `revert`
   reveal, so the legacy settings blocks keep their own display values. */
.settings-lens:not(.show-legacy) > *:not(.set13):not(.set13-lens):not(.suplegal) { display: none; }
@media (max-width: 1100px) { .suplegal-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 620px) { .suplegal-grid { grid-template-columns: minmax(0, 1fr); } }

/* ═══ MEDIA FACTORY (mockup 10) ══════════════════════════════════════════
   The hub had the content mix, the approval queue, getting-started and
   platform status. Reference 10 also draws a 2x3 KPI grid, a production
   timeline, publishing channels, recent materials and an activity feed.
   Those are added here; the existing blocks and every handler are untouched. */
.mf10-kpis { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--rp-2); }
.mf10-row { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--rp-3); align-items: start; }
.mf10-card {
  padding: 12px 14px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r);
  background: var(--rp-panel);
  min-width: 0;
}
.mf10-head { display: flex; align-items: center; gap: 8px; margin-bottom: 9px; }
.mf10-head h3 { margin: 0; font-size: 13px; font-weight: 620; color: var(--rp-ink); }
.mf10-tag {
  margin-inline-start: auto; padding: 1px 7px;
  border-radius: var(--rp-r-pill); background: rgb(var(--ch-lift) / 0.05);
  color: var(--rp-ink-3); font-size: 10px; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.03em;
}
.mf10-note, .mf10-empty { margin: 8px 0 0; color: var(--rp-ink-3); font-size: 10.5px; line-height: 1.5; }
.mf10-empty { margin: 0; }
.mf10-lanes { display: grid; gap: 6px; }
.mf10-lane { display: grid; grid-template-columns: 104px minmax(0, 1fr); align-items: center; gap: 9px; }
.mf10-lane > span { color: var(--rp-ink-3); font-size: 11px; }
.mf10-lanebar { height: 16px; border: 1px dashed var(--rp-line); border-radius: 4px; }
.mf10-chans { display: grid; gap: 4px; }
.mf10-chan { display: flex; align-items: center; gap: 8px; padding: 5px 0; border-bottom: 1px solid var(--rp-line); }
.mf10-chan:last-child { border-bottom: 0; }
.mf10-chanmark {
  display: grid; place-items: center; flex: none;
  width: 22px; height: 22px; border-radius: 6px;
  color: var(--rp-on-brand); font-size: 9px; font-weight: 700;
}
.mf10-channame { flex: 1 1 auto; min-width: 0; color: var(--rp-ink-2); font-size: 11.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mf10-chanstate { flex: none; padding: 1px 8px; border-radius: var(--rp-r-pill); font-size: 10px; font-weight: 600; }
.mf10-chanstate.on { background: rgb(var(--ch-green) / 0.16); color: var(--sh-ok); }
.mf10-chanstate.off { background: rgb(var(--ch-slate) / 0.14); color: var(--rp-ink-3); }
/* The third state: the mapping has not been read, or the read was refused.
   Deliberately fainter than `off` — "we do not know" must not be mistaken for
   "we checked and it is off". */
.mf10-chanstate.unknown { background: transparent; border: 1px solid rgb(var(--ch-slate) / 0.28); color: var(--rp-ink-3); }
.mf10-mats { display: grid; gap: 5px; }
.mf10-mat { display: flex; align-items: center; gap: 9px; min-width: 0; }
.mf10-matthumb {
  display: grid; place-items: center; flex: none;
  width: 30px; height: 30px; border-radius: var(--rp-r-sm);
  border: 1px solid var(--rp-line); background: rgb(var(--ch-lift) / 0.03);
  color: var(--rp-ink-3); font-size: 11px; font-weight: 600;
}
.mf10-mattitle { flex: 1 1 auto; min-width: 0; color: var(--rp-ink-2); font-size: 11.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mf10-matkind { flex: none; color: var(--rp-ink-3); font-size: 10px; }
@media (max-width: 1200px) { .mf10-row { grid-template-columns: minmax(0, 1fr); } }
@media (max-width: 820px) { .mf10-kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* «Не проверено» is not «не подключено». displayIntegrationStatus() is a
   safety chokepoint that refuses to claim a connection without server-side
   health; the card now says exactly that instead of asserting the connector
   is down, and the action reads «Открыть» rather than «Подключить». */
.int13-head { flex-wrap: wrap; }
.int13-note { flex-basis: 100%; margin-top: 1px; color: var(--rp-ink-3); font-size: 10px; }
.int13-chip.unver { background: rgb(var(--ch-slate) / 0.14); color: var(--rp-ink-2); }
.int13-chip.warn { background: rgb(var(--ch-amber) / 0.15); color: var(--sh-warm); }
.int13-unver { display: grid; gap: 5px; }

/* /integrations client-view catalogue: a second legacy .readiness-grid rule in
   styles.css sets repeat(auto-fit, minmax(150px, 1fr)), which builds ten tracks
   for thirteen cards and runs 38px past the grid box at 1920 (36px at 1440) —
   two cards physically overlapped by 24x202. Raised specificity so the floor
   collapses when it cannot fit; a grid that already fits is untouched. */
.page-stack > .readiness-grid > .readiness-card,
.page-stack > .readiness-grid > .readiness-card > * {
  min-width: 0;
}
.page-stack > .readiness-grid > .readiness-card { overflow-wrap: anywhere; }

/* A tab row with one item is not navigation. /integrations rendered a single
   «Обзор» tab above the connector grid — the same precedent already applied to
   CRM and Marketing, whose group sub-navs are hidden for the same reason. */
.page-stack > .module-tabs:has(> button:only-child) { display: none; }

/* «CRM» in the CRM tab row is the module name, not a destination — rendered as
   a label so it reads as the row's subject rather than a tab that never
   activates. Keeps 03's four-item shape without the dead control. */
.crm-tabs-modulename {
  display: inline-flex;
  align-items: center;
  padding-block: 0 0; padding-inline: 0 11px;
  margin-inline-end: 4px;
  border-inline-end: 1px solid var(--rp-line);
  color: var(--rp-ink-3);
  font-size: 11.5px;
  font-weight: 620;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

/* VOICE AFFORDANCE — the screen read as a wall of placeholders because an
   ENABLED control and a DISABLED one looked almost identical: both transparent,
   both the same hairline border, differing only in opacity. Telephony really is
   disconnected and none of that changes here — what changes is that the things
   you CAN press now look pressable. */
.voice-comp button:not(:disabled),
.voice-header button:not(:disabled) {
  border-color: var(--rp-line-2);
  background: rgb(var(--ch-lift) / 0.04);
  color: var(--rp-ink);
  cursor: pointer;
}
.voice-comp button:not(:disabled):hover,
.voice-header button:not(:disabled):hover {
  border-color: rgb(var(--ch-blue2) / 0.55);
  background: var(--rp-blue-soft);
  color: var(--rp-ink-max);
}
/* The three real destinations are navigation, not decoration. */
.voice-trmore:not(:disabled), .voice-leadopen:not(:disabled) {
  border-color: rgb(var(--ch-blue2) / 0.42);
  color: var(--sh-blue-1);
}
.voice-quickitem:not(:disabled) { color: var(--rp-ink); }
.voice-quickitem:not(:disabled)::after { content: " →"; color: var(--rp-ink-3); }
/* DATA-GAP panels must not read as broken buttons: dashed, no pointer, no
   hover — an informational surface rather than a control that refuses. */
.voice-wave.is-off, .voice-qachart.is-off, .voice-qawords.is-off, .voice-qadonut.is-off {
  cursor: default;
  background: rgb(var(--ch-lift) / 0.012);
}
/* Disabled stays unmistakably disabled. */
.voice-comp button:disabled, .voice-header button:disabled { opacity: 0.38; }

/* LANDING VOICE CONTROLS — muted was a 15px glyph swap and nothing else, so
   people could not tell whether Boro was going to speak. Off now reads as off. */
.boro-panel-voice.boro-voice-muted {
  opacity: 0.55;
  border-color: rgb(var(--ch-slate) / 0.28);
  background: rgb(var(--ch-slate) / 0.08);
}
.boro-panel-voice.boro-voice-muted:hover { opacity: 1; }

/* PERIOD SCOPE MARKERS — a state figure must never read as a figure for the
   selected window. `now` sits quietly beside the headline; the delta moved to
   the secondary line, next to the flow figure it actually measures. */
.rp-kpi-scope {
  font-size: 11px;
  line-height: 1;
  padding: 3px 6px;
  border-radius: 5px;
  color: var(--rp-ink-3);
  background: rgb(var(--ch-slate) / 0.12);
  border: 1px solid rgb(var(--ch-slate) / 0.2);
  white-space: nowrap;
  align-self: center;
}
.rp-kpi-sub { display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap; }
.rp-kpi-subdelta { font-size: 11px; font-weight: 600; white-space: nowrap; }
.rp-kpi-subdelta.up { color: var(--lg-ok-3); }
.rp-kpi-subdelta.down { color: var(--lg-red-3); }
.rp-kpi-subdelta.flat { color: var(--rp-ink-3); }

/* The open Settings section is a position indicator, not an offer to navigate
   somewhere — it should not invite a click that goes nowhere. */
.set13-railitem.is-current { cursor: default; }

/* Boro's corner. The launcher reads its safe-area allowance from these, because
   env() is only available to CSS — JS clamps the draggable position against the
   computed values so a phone's home indicator can never swallow the button. */
.boro-root {
  --boro-safe-left: env(safe-area-inset-left, 0px);
  --boro-safe-right: env(safe-area-inset-right, 0px);
  --boro-safe-bottom: env(safe-area-inset-bottom, 0px);
}

/* The rest of the lead-activity feed, behind a disclosure the browser owns. */
.runtime-events-more { margin-top: 10px; }
.runtime-events-more > summary {
  cursor: pointer;
  font-size: 13px;
  color: var(--rp-ink-2, var(--sh-blue-1));
  padding: 6px 0;
  list-style: none;
}
.runtime-events-more > summary::-webkit-details-marker { display: none; }
.runtime-events-more > summary::before { content: "▸ "; }
.runtime-events-more[open] > summary::before { content: "▾ "; }
.runtime-events-more > summary:hover { text-decoration: underline; }

/* PER-MESSAGE DELIVERY EVIDENCE. Quiet by default — this is a footnote on a
   message, not a badge competing with the text. Only «не доставлено» raises its
   voice, because that is the one an operator has to act on. */
.chatmsg-state {
  display: inline-block;
  margin-top: 4px;
  font-size: 11px;
  line-height: 1;
  color: var(--rp-ink-3);
}
.chatmsg-state.ok   { color: var(--lg-ok-3); }
.chatmsg-state.wait { color: var(--rp-ink-3); }
.chatmsg-state.bad  { color: var(--lg-red-3); font-weight: 600; }
/* An operator's message is outbound like the agent's, but it is not the agent.
   A left accent separates the two without inventing a third bubble colour. */
.chatmsg.operator { border-inline-start: 2px solid rgb(var(--ch-blue2) / 0.55); }

/* One line where four status rows used to be. The .rail-system* rules above are
   left in place — buildRailSystems still computes the same facts and they are
   the truth behind this summary; only the permanent four-row rendering is gone.
   Detail belongs on Integrations, which is where this button leads. */
.rail-health {
  display: flex; align-items: center; gap: 8px; width: 100%;
  margin-top: var(--rp-3); padding: 9px 10px;
  border: 1px solid var(--rp-line); border-radius: 10px;
  background: rgb(var(--ch-lift) / .03); color: var(--rp-ink-2);
  font: inherit; font-size: 12px; text-align: start; cursor: pointer;
}
.rail-health:hover { background: rgb(var(--ch-lift) / .06); color: var(--rp-ink); }
.rail-health-dot { font-size: 10px; line-height: 1; flex: 0 0 auto; }
.rail-health-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rail-health-ok .rail-health-dot { color: var(--t223); }
.rail-health-warn .rail-health-dot { color: var(--lw-warm); }
.rail-health-checking .rail-health-dot { color: var(--lw-ink-mid); }
/* Nothing has answered on this screen, and nothing is being asked — the dot
   must not carry the same "work in progress" grey as «проверяем», because for
   a month that grey sat there permanently on every page that does not load the
   dashboard snapshot. Quieter still: this row is a doorway, not a status. */
.rail-health-idle .rail-health-dot { color: var(--rp-ink-3); opacity: .6; }

/* ═══ RAIL GROUPS: one calm accent each ═════════════════════════════════════
   Brighter glyphs, but not ten separate colours. The accent says which part of
   the product an item belongs to; the item itself stays the same two-letter
   glyph it has always been — the iconography is not being replaced here. */
.nav-section-work .nav-item .nav-icon { color: var(--nav-accent-work); }
.nav-section-ai .nav-item .nav-icon { color: var(--nav-accent-ai); }
/* Media Factory carries the cyan half of the AI accent. Needs the same
   .nav-item depth as the rule above it — at one class less specific it lost to
   the group violet and the accent silently did nothing. */
.nav-section-ai .nav-item .nav-icon-media-factory { color: var(--nav-accent-media); }
.nav-section-system .nav-item .nav-icon { color: var(--nav-accent-system); }
.nav-item .nav-icon { opacity: .95; font-weight: 700; }
.nav-item:hover .nav-icon { opacity: 1; }
/* The active plate wins over every accent — a glyph tinted violet on a blue
   plate is the one place this scheme could hurt legibility. */
.nav-item.active .nav-icon,
.nav-section-work .nav-item.active .nav-icon,
.nav-section-ai .nav-item.active .nav-icon,
.nav-section-ai .nav-item.active .nav-icon-media-factory,
.nav-section-system .nav-item.active .nav-icon { color: var(--rp-ink-max); opacity: 1; }

/* ═══ COLLAPSED RAIL: glyphs only, name on hover AND focus ══════════════════
   72px. The native title attribute is kept for pointer users, but it never
   appears for a keyboard user and cannot be styled — so the label also travels
   as data-label and the bubble is ours. */
.rail-collapsed .nav-section-label,
.rail-collapsed .nav-item .nav-item-text { display: none; }
.rail-collapsed .nav-item { justify-content: center; padding: 0; position: relative; }
.rail-collapsed .nav-section + .nav-section {
  margin-top: 10px; padding-top: 10px; border-top: 1px solid rgb(var(--ch-line) / .12);
}
.rail-collapsed .nav-item::after {
  content: attr(data-label);
  position: absolute; inset-inline-start: calc(100% + 8px); top: 50%; transform: translateY(-50%);
  z-index: 40; padding: 6px 9px; border-radius: 8px; white-space: nowrap;
  background: var(--lw-panel); border: 1px solid rgb(var(--ch-line) / .28); color: var(--lw-ink-bright);
  font-size: 12px; font-weight: 500; box-shadow: 0 10px 26px rgba(0, 0, 0, .45);
  opacity: 0; visibility: hidden; pointer-events: none;
}
.rail-collapsed .nav-item:hover::after,
.rail-collapsed .nav-item:focus-visible::after { opacity: 1; visibility: visible; }

/* ═══ FULL-HEIGHT SCREENS OWN THE CONTENT COLUMN ═══════════════════════════
   The Lead Workspace and the Inbox are pinned-to-the-window screens: a header,
   a scrolling middle, a composer fixed at the bottom. They declared height:100vh
   and were only ever measured as the root of a harness document — where "the
   viewport" and "the space I was given" happen to be the same thing.

   In the product they are not. .workspace sits below a sticky .rp-topbar and a
   .header, and carries its own padding, so a 100vh child ends up 94px past the
   bottom of the window: the composer's tool row is cut off and the page itself
   scrolls 124px, which is the one thing these screens exist to avoid.

   The fix is a flex column with no magic numbers. The topbar and header keep
   their natural height, the screen takes exactly what is left, and no rule has
   to know how tall the chrome above it happens to be today. */
.workspace:has(.lw-page),
.workspace:has(.dw) {
  display: flex;
  flex-direction: column;
  height: 100vh;
  min-height: 0;
  padding: 0;
  overflow: hidden;
}

/* The topbar cancels the workspace padding with negative margins. With that
   padding gone the negatives would drag it outside the column, so they are
   reset and its own inset restored. */
.workspace:has(.lw-page) .rp-topbar,
.workspace:has(.dw) .rp-topbar {
  margin: 0;
  padding: 0 var(--rp-5);
  flex: 0 0 auto;
}
.workspace:has(.lw-page) .header,
.workspace:has(.dw) .header { flex: 0 0 auto; }

/* Whatever is left, the screen takes — and min-height:0 is what lets its inner
   scroll regions actually scroll instead of stretching the column. */
/* Descendant, not child: PageRouter may wrap a page, and a wrapper with
   display:contents keeps the screen a flex item of .workspace while breaking a
   > selector. Caught by the shell harness, which mounts through exactly such a
   wrapper. */
.workspace:has(.lw-page) .lw-page,
.workspace:has(.dw) .dw {
  flex: 1 1 auto;
  min-height: 0;
  height: auto;
}

/* ═══ META TEMPLATE CATALOGUE ══════════════════════════════════════════════
   A read-only table of what Meta has approved on our own number. Scoped under
   .watc-card so it cannot reach the board tables, which have their own rules. */
.watc-card { display: flex; flex-direction: column; gap: 12px; align-items: stretch; }
.watc-actions { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.watc-dim { color: var(--lw-ink-mid); font-size: 12px; }
.watc-bad { color: var(--lw-warm); }

/* Составитель шаблона из обычного текста. Отделён линией сверху: это не
   продолжение каталога, а другое действие — там читают, здесь заводят. */
.watc-composer {
  display: flex; flex-direction: column; gap: 10px;
  border-top: 1px solid var(--rp-line, rgba(148, 178, 255, 0.14));
  padding-top: 14px;
}
.watc-composer h3 { margin: 0; font-size: 15px; }
.watc-textarea {
  width: 100%; box-sizing: border-box; min-height: 120px; resize: vertical;
  padding: 10px 12px; border-radius: 10px; font-size: 13.5px; line-height: 1.5;
  border: 1px solid var(--rp-line, rgba(148, 178, 255, 0.18));
  background: var(--rp-panel, rgba(12, 18, 28, 0.5)); color: inherit;
}
.watc-composer-row { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.watc-composer-out { display: flex; flex-direction: column; gap: 8px; }
/* Предпросмотр — то, что реально уйдёт в Meta. Моноширинным, потому что здесь
   важны переносы и пробелы: именно из-за них Meta чаще всего отказывает. */
.watc-preview {
  margin: 0; padding: 10px 12px; border-radius: 10px; white-space: pre-wrap;
  font-size: 12.5px; line-height: 1.5;
  background: var(--rp-panel-2, rgba(8, 13, 24, 0.55));
  border: 1px solid var(--rp-line, rgba(148, 178, 255, 0.12));
}
.watc-changes { margin: 0; padding-inline-start: 18px; font-size: 12px; color: var(--lw-ink-mid); }

/* The table scrolls inside its own box. A wide catalogue must never make the
   page scroll sideways — the same rule the workspace screens live by. */
.watc-scroll { overflow-x: auto; max-height: 420px; overflow-y: auto; }
.watc-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.watc-table th {
  position: sticky; top: 0; z-index: 1; text-align: start; white-space: nowrap;
  padding: 8px 10px; background: var(--lw-panel); color: var(--lw-ink-soft);
  font-size: 11px; letter-spacing: .05em; text-transform: uppercase;
  border-bottom: 1px solid rgb(var(--ch-line) / .18);
}
.watc-table td {
  padding: 8px 10px; color: var(--lw-ink); vertical-align: top;
  border-bottom: 1px solid rgb(var(--ch-line) / .08);
}
.watc-table tr:last-child td { border-bottom: 0; }
.watc-table code {
  font-size: 12px; color: var(--lw-ink-bright); word-break: break-all;
  background: rgb(var(--ch-lift) / .04); padding: 2px 5px; border-radius: 5px;
}

/* ═══ TASKS ════════════════════════════════════════════════════════════════
   The day's work in one list. Scoped under .tsk-page so nothing here can reach
   the board tables, which have their own rules. */
.tsk-head { display: flex; flex-direction: column; gap: 8px; align-items: stretch; }

.tsk-tabs { display: flex; flex-wrap: wrap; gap: 6px; }
.tsk-tab {
  display: inline-flex; align-items: center; gap: 7px; height: 34px; padding: 0 13px;
  border-radius: 999px; border: 1px solid rgb(var(--ch-line) / .22);
  background: rgb(var(--ch-lift) / .03); color: var(--lw-ink-bright); font: inherit; font-size: 13px;
  cursor: pointer;
}
.tsk-tab:hover { border-color: rgb(var(--ch-line) / .4); }
.tsk-tab.active { background: var(--pk-blue); border-color: rgb(var(--ch-accent) / .5); color: var(--rp-on-accent); font-weight: 600; }
.tsk-count { font-size: 11px; opacity: .75; font-variant-numeric: tabular-nums; }

.tsk-filters { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.tsk-search, .tsk-select {
  height: 34px; padding: 0 11px; border-radius: 9px; font: inherit; font-size: 13px;
  border: 1px solid rgb(var(--ch-line) / .24); background: rgb(var(--ch-lift) / .03); color: var(--lw-ink);
}
.tsk-search { min-width: 240px; flex: 1 1 240px; max-width: 420px; }
/* `.workspace select` / `.workspace input[type="search"]` (cabinet-system.css
   ~1019) is (0,1,1) and outranks `.tsk-select` (0,1,0) whatever the load order:
   it pushed 11px of vertical padding into a 34px border-box control — a 10px
   content box for a 16px line, so «Любой ответственный» rode up into the top
   border — and `width: 100%` made every filter its own full-width flex line.
   The owner's screenshot of 3 September. Two classes beat one class + one tag.
   The dev harness never showed it: it mounts TasksPage without `main.workspace`. */
.tsk-page .tsk-search,
.tsk-page .tsk-select {
  width: auto;
  padding: 0 11px;
  border-radius: 9px;
}
.tsk-page .tsk-search { flex: 1 1 240px; }
.tsk-page .tsk-select { max-width: 220px; }

/* The table scrolls inside its own box: a wide list must never make the page
   scroll sideways — the same rule the workspace screens live by. */
.tsk-scroll { overflow-x: auto; }
.tsk-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.tsk-table th {
  position: sticky; top: 0; z-index: 1; text-align: start; white-space: nowrap;
  padding: 9px 11px; background: var(--lw-panel); color: var(--lw-ink-soft);
  font-size: 11px; letter-spacing: .05em; text-transform: uppercase;
  border-bottom: 1px solid rgb(var(--ch-line) / .18);
}
.tsk-table td {
  padding: 10px 11px; color: var(--lw-ink); vertical-align: top;
  border-bottom: 1px solid rgb(var(--ch-line) / .08);
}
.tsk-table tr:last-child td { border-bottom: 0; }
.tsk-clickable { cursor: pointer; }
.tsk-clickable:hover td { background: rgb(var(--ch-lift) / .035); }
.tsk-title { color: var(--lw-ink); }
.tsk-doneflag { color: var(--t231); }
.tsk-dim { color: var(--lw-ink-dim); }
.tsk-bad { color: var(--lw-warm); }
/* Overdue is stated in the date column rather than by painting the whole row:
   a list where a third of the rows are red stops meaning anything. */
.tsk-due-bad { color: var(--u54); }

.tsk-empty { display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 9px; padding: 42px 24px; text-align: center; }
.tsk-empty-title { margin: 0; color: var(--lw-ink-bright); font-size: 15px; }
.tsk-empty-copy { margin: 0; color: var(--lw-ink-dim); font-size: 13px; max-width: 44ch; }

/* ═══ BULK CONFIRMATION ════════════════════════════════════════════════════
   The bar used to write from a select's onChange: one mis-click moved every
   selected deal, with no preview and no way back. Every control now only
   PROPOSES, and this panel is the only thing that writes. */
.crm-bulk-confirm {
  flex-basis: 100%; margin-top: 10px; padding: 12px; border-radius: 12px;
  background: rgb(var(--ch-blue) / .1); border: 1px solid rgb(var(--ch-accent) / .34);
  display: flex; flex-direction: column; gap: 7px;
}
.crm-bulk-what { margin: 0; color: var(--lw-ink); font-size: 14px; font-weight: 600; }
/* Причина, по которой массовое действие не выполнилось, и сколько сделок
   вернётся из закрытых стадий — обе строки в том же подтверждении. */
.crm-bulk-error { color: var(--rp-warn, #f0b429); font-weight: 600; }
/* Результат массового действия: остаётся после снятия выделения, снимается
   крестиком или следующим действием. */
.crm-bulk-done {
  display: flex; align-items: center; gap: 8px;
  margin: 0 0 8px; padding: 7px 10px;
  border: 1px solid var(--rp-line); border-radius: 8px;
  background: rgb(var(--ch-green, 46 160 67) / 0.12);
  color: var(--rp-ink); font-size: 12.5px; font-weight: 600;
}
.crm-bulk-done-x {
  margin-inline-start: auto; border: 0; background: none; cursor: pointer;
  color: var(--rp-muted, #9aa7bd); font-size: 15px; line-height: 1; padding: 0 2px;
}
.crm-bulk-reopen { margin: 0; font-size: 12.5px; color: var(--rp-muted, #9aa7bd); }
.crm-bulk-span { margin: 0; color: var(--lw-ink-bright); font-size: 12px; }
.crm-bulk-skip { margin: 0; color: var(--lw-warm); font-size: 12px; }
.crm-bulk-includeclosed {
  display: flex; align-items: center; gap: 7px; color: var(--lw-ink-soft); font-size: 12px; cursor: pointer;
}
.crm-bulk-taskform { display: flex; flex-wrap: wrap; gap: 7px; }
.crm-bulk-taskform > * {
  height: 32px; padding: 0 9px; border-radius: 9px; font: inherit; font-size: 13px;
  border: 1px solid rgb(var(--ch-line) / .24); background: rgb(var(--ch-lift) / .04); color: var(--lw-ink);
}
.crm-bulk-taskform > input:first-child { flex: 1 1 240px; min-width: 0; }
.crm-bulk-actions { display: flex; gap: 8px; align-items: center; }
.crm-bulk-apply {
  height: 34px; padding: 0 18px; border-radius: 999px; cursor: pointer; font: inherit; font-size: 13px;
  border: 1px solid rgb(var(--ch-accent) / .45); background: var(--pk-blue); color: var(--rp-on-accent); font-weight: 600;
}
.crm-bulk-apply[disabled] { opacity: .5; cursor: not-allowed; }
.crm-bulk-task {
  height: 32px; padding: 0 14px; border-radius: 999px; cursor: pointer; font: inherit; font-size: 13px;
  border: 1px solid rgb(var(--ch-line) / .28); background: rgb(var(--ch-lift) / .03); color: var(--lw-ink-bright);
}
.crm-bulk-task:hover { border-color: rgb(var(--ch-accent) / .55); }
/* Массовое удаление (26.09.2026): кнопка на полосе — красной обводкой, два
   шага подтверждения — красной рамкой, кнопка шага — красной заливкой. */
.crm-bulk-task.crm-bulk-delete { border-color: rgb(239 68 68 / .45); color: light-dark(#b91c1c, #fca5a5); }
.crm-bulk-task.crm-bulk-delete:hover { border-color: rgb(239 68 68 / .8); }
.crm-bulk-confirm.crm-bulk-delete-confirm { background: var(--danger-bg); border-color: var(--danger); }
.crm-bulk-apply.crm-bulk-apply-danger { background: var(--danger); border-color: var(--danger); color: #fff; }
.crm-bulk-delete-reason {
  height: 32px; max-width: 360px; padding: 0 9px; border-radius: 9px; font: inherit; font-size: 13px;
  border: 1px solid rgb(var(--ch-line) / .24); background: rgb(var(--ch-lift) / .04); color: var(--lw-ink);
}

/* Losing a deal and booking a meeting carry a fact the stage id does not. */
.kb-stagemoves { display: flex; flex-direction: column; gap: 7px; margin-top: 10px; }
.kb-stagemove { display: flex; gap: 7px; align-items: center; }
.kb-stagemove input {
  flex: 1 1 auto; min-width: 0; height: 32px; padding: 0 9px; border-radius: 9px;
  font: inherit; font-size: 13px; border: 1px solid rgb(var(--ch-line) / .24);
  background: rgb(var(--ch-lift) / .03); color: var(--lw-ink);
}
.kb-stagemove button { flex: 0 0 auto; }
/* The lost-reason row grew a preset chip strip ahead of its free-text input —
   wrapping, not the single-line flex every other stagemove row uses, or six
   presets plus an input would overflow the card's own width. */
.kb-stagemove-lost { flex-wrap: wrap; }
.kb-lostreason-presets { display: flex; flex-wrap: wrap; gap: 6px; width: 100%; }
/* 26.09.2026: причины отказа — выпадающим списком во всю ширину карточки,
   под ним поле «Или своя причина…» и кнопка «Отказ». */
.kb-stagemove .kb-lostreason-pick {
  flex: 1 1 100%; min-width: 0; height: 32px; padding: 0 9px; border-radius: 9px;
  font: inherit; font-size: 13px; border: 1px solid rgb(var(--ch-line) / .24);
  background: rgb(var(--ch-lift) / .03); color: var(--lw-ink);
}

/* ═══ VOICE WITHOUT A LINE ═════════════════════════════════════════════════
   The screen used to draw the whole telephone with every key disabled: keypad,
   six call controls, End call, Record, Transfer, Hold, Contacts, an empty
   transcript and score widgets with nothing behind them. A disabled keypad
   reads as "the phone is here and something is temporarily wrong". None of it
   is rendered now until the server says the line is up. */
/* One small card pinned to the top of a 900px window leaves a 432px slab of
   nothing under it, which reads as a page that failed to load the rest of
   itself.
   TRUE CENTRING WAS TRIED AND REVERTED. It needs the container's own height,
   which means subtracting the shell's chrome as a constant; two measured
   guesses (220px, 280px) both still produced a vertical scrollbar, because the
   stack contributes height this rule cannot see. A scrollbar on a screen whose
   whole point is that there is nothing to scroll is worse than the void it was
   meant to fix. A fixed offset cannot overshoot: it only spends slack that is
   already there. */
.voice-page-offline { max-width: 720px; margin-top: min(10vh, 96px); }
.voice-setup { display: flex; flex-direction: column; gap: 12px; align-items: flex-start; }
.voice-setup-title { margin: 0; font-size: 19px; color: var(--lw-ink); }
.voice-setup-copy { margin: 0; color: var(--lw-ink-soft); font-size: 13px; line-height: 1.6; max-width: 62ch; }
.voice-setup-facts {
  display: grid; grid-template-columns: minmax(140px, auto) 1fr; gap: 6px 16px;
  margin: 4px 0 0; width: 100%;
}
.voice-setup-facts dt { color: var(--lw-ink-soft); font-size: 12px; }
.voice-setup-facts dd { margin: 0; color: var(--lw-ink); font-size: 13px; }
.telephony-settings .control-card { display: flex; flex-direction: column; gap: 14px; align-items: flex-start; }

/* ── Voice: two truths, side by side ──────────────────────────────────────
   The screen used to report one status for both directions. Inbound is proven
   and outbound is blocked, and a single pill cannot say that — it either
   buried a working half or would later imply a dead one is alive. */
.voice-truths { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-bottom: 16px; }
.voice-truth {
  border: 1px solid rgb(var(--ch-line) / .14); border-radius: 14px;
  padding: 14px 16px; background: rgb(var(--ch-lift) / .015);
  display: flex; flex-direction: column; gap: 6px; align-items: flex-start;
}
.voice-truth h3 { margin: 2px 0 0; font-size: 15px; color: var(--lw-ink); }
.voice-truth p { margin: 0; font-size: 12px; line-height: 1.5; color: var(--lw-ink-soft); }
/* Green is proven and nothing else; amber is a real blocker and nothing else. */
.voice-truth-ok { border-color: rgb(var(--ch-green) / .26); }
.voice-truth-blocked { border-color: rgb(var(--ch-amber) / .26); }
@media (max-width: 1100px) { .voice-truths { grid-template-columns: 1fr; } }

/* ── Voice: main column + a 300px operational column ──────────────────────
   The offline screen used to be a single 720px card centred in a page of black.
   The inbound history and the "what to connect" note now fill that space with
   things a manager can act on. */
.voice-page-offline { max-width: none; margin-top: 0; }
.voice-cols { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: 20px; align-items: start; }
.voice-col-main { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.voice-oper h3 { margin: 0 0 6px; font-size: 15px; color: var(--lw-ink); }
.voice-oper h4 { margin: 12px 0 4px; font-size: 12px; color: var(--lw-ink-soft); text-transform: uppercase; letter-spacing: .05em; }
.voice-oper p { margin: 0; font-size: 12px; line-height: 1.55; color: var(--lw-ink-note); }
.voice-oper-list { margin: 0; padding-inline-start: 16px; color: var(--lw-ink-note); font-size: 12px; line-height: 1.6; }
.voice-oper-note { margin-top: 12px; color: var(--lg-ok-1); }

.voice-history-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.voice-history-head h3 { margin: 0; font-size: 15px; color: var(--lw-ink); }
.voice-history-count { color: var(--lw-ink-dim); font-size: 12px; }
.voice-search { width: 100%; margin: 10px 0 12px; }
.voice-empty { margin: 0; color: var(--lw-ink-dim); font-size: 13px; }
.voice-calllist { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
/* THE WHOLE ROW OPENS THE CARD. This desk exists to find a call and hand it to
   the client card where it is worked; answering only to a small link at the end
   of the row taught people to aim at it. A call with no local card keeps the
   flat styling and is not clickable — there is nothing to open. */
.voice-callrow {
  border: 1px solid rgb(var(--ch-line) / .12); border-radius: 12px;
  padding: 10px 12px; background: rgb(var(--ch-lift) / .02);
}
.voice-callrow.is-openable { cursor: pointer; }
.voice-callrow.is-openable:hover {
  border-color: rgb(var(--ch-accent) / .40); background: rgb(var(--ch-blue) / .08);
}
.voice-callrow.is-openable:focus-visible {
  outline: 2px solid rgb(var(--ch-accent) / .65); outline-offset: 2px;
}
.voice-callrow.is-openable:hover .voice-callrow-open { text-decoration: underline; }
.voice-callrow-main { display: flex; flex-wrap: wrap; align-items: baseline; gap: 10px; font-size: 13px; }
.voice-callrow-dir { color: var(--lg-ok-1); font-weight: 600; }
.voice-callrow-when { color: var(--lw-ink-bright); }
.voice-callrow-turns, .voice-callrow-score { color: var(--lw-ink-soft); font-size: 12px; }
.voice-callrow-intent { margin: 5px 0 0; color: var(--lw-ink-note); font-size: 12.5px; line-height: 1.5; }
/* A visible affordance, not the target: the row already answers. */
.voice-callrow-open {
  display: block; margin-top: 8px; color: var(--t234); font-size: 12.5px;
}
.voice-callrow-nocard { display: inline-block; margin-top: 8px; color: var(--lw-ink-dim); font-size: 12px; }
@media (max-width: 1100px) { .voice-cols { grid-template-columns: 1fr; } }

/* The search commits on a press, not on a keystroke: typing repaints nothing,
   so the field cannot lose focus, and Search / Enter move the draft into the
   filter. Clear appears only when there is something to clear. */
.voice-search-actions { display: flex; gap: 8px; margin-bottom: 12px; }
.voice-search { margin-bottom: 8px; }
.voice-search-go, .voice-search-clear { font-size: 12.5px; padding: 0 12px; min-height: 32px; }

/* ── The view lens: a segmented toggle, because a <select> popup is the OS's ──
 *
 * The owner opened the old control and got a white list with a blue highlight
 * in the middle of a dark screen. That popup is painted by the operating
 * system; no CSS on a <select> reaches its option list, in any browser. So the
 * control had to go, not be restyled.
 *
 * Declared here rather than in pack-design.css because another agent owns that
 * file right now. It is safe: `.pk-seg*` appears nowhere in it, so load order
 * decides nothing, and a class (0,1,0) outranks the legacy bare
 * `button { min-height: 40px }` (0,0,1) that has silently inflated three
 * controls in this codebase already — which is why the height below is explicit
 * rather than inherited.
 */
.pk-seg {
  display: inline-flex;
  align-items: stretch;
  gap: 2px;
  padding: 3px;
  border-radius: 10px;
  border: 1px solid var(--pk-line, var(--lg-surf-15));
  background: var(--pk-surface-2, var(--lg-surf-5));
}
.pk-seg-btn {
  appearance: none;
  min-height: 0;
  /* Tracks .pk-ctl's own shell, 2026-08-21: was 32px inside a 44px tray. */
  height: 28px;
  padding: 0 13px;
  border: 0;
  border-radius: 7px;
  background: transparent;
  color: var(--pk-text-dim, #8a93a6);
  font: inherit;
  font-size: 13px;
  font-weight: 500;
  line-height: 1;
  cursor: pointer;
  white-space: nowrap;
  transition: background-color 120ms ease, color 120ms ease;
}
.pk-seg-btn:hover { color: var(--pk-text, var(--sh-mist)); }
.pk-seg-btn.is-on {
  background: var(--pk-accent-soft, var(--lg-surf-14));
  color: var(--pk-text, var(--sh-mist));
  font-weight: 600;
}
/* Focus must stay visible on the unselected half too, so keyboard users can see
   where they are before they commit to a lens. */
.pk-seg-btn:focus-visible {
  outline: 2px solid var(--pk-accent, #3f7dfb);
  outline-offset: -2px;
}

/* The composer's mode switch sits in the same row as Эмодзи / Шаблоны / Файл,
   so it matches their 30px rather than the CRM toolbar's 32px. It shrinks to its
   content — the width the old <select> ate now belongs to the message field,
   which is what the owner asked for: «длинное поле место кушает, смысла нет».

   The old control also showed «..» instead of the current mode: tinyReact does
   not apply a `selected` ATTRIBUTE to an <option>, so the select rendered with
   no value chosen. Nobody could see which mode they were in. Gone with it. */
.ck-mode-seg { padding: 2px; border-radius: 9px; }
.ck-mode-seg .pk-seg-btn { height: 26px; padding: 0 11px; font-size: 12px; }

/* ── ОБЗВОН · the campaign dialler on the Voice page ─────────────────────────
   Ordered so the page reads top to bottom as the decision actually goes: what
   state the dialler is in, who gets called, when and how fast, what it costs,
   and only then the runs. The cost block is not a footnote — it is the last
   thing somebody reads before they press start, so it sits directly above the
   button rather than in a sidebar they can miss. */
.voice-campaign-page { display: flex; flex-direction: column; gap: 18px; max-width: 880px; }
.voice-campaign-head h2 { margin: 0 0 4px; }
.voice-campaign-head p { margin: 0; color: var(--pk-dim, var(--sh-slate-1)); font-size: 13px; }

/* The honest state, first and unmissable. It is the one thing on this page that
   can be true while every control still looks usable. */
.voice-campaign-state {
  display: flex; flex-direction: column; gap: 6px;
  padding: 12px 14px; border-radius: 12px;
  border: 1px solid rgb(var(--ch-line) / .18); background: rgb(var(--ch-lift) / .03);
}
.voice-campaign-state p { margin: 0; font-size: 13px; }

.voice-campaign-form { display: flex; flex-direction: column; gap: 12px; }
.voice-campaign-form h3 {
  margin: 8px 0 0; font-size: 13px; letter-spacing: .04em; text-transform: uppercase;
  color: var(--pk-dim, var(--sh-slate-1));
}
.voice-campaign-field { display: flex; flex-direction: column; gap: 5px; }
.voice-campaign-field > span { font-size: 13px; font-weight: 600; }
.voice-campaign-field small { color: var(--pk-dim, var(--sh-slate-1)); font-size: 12px; line-height: 1.45; }
.voice-campaign-field input, .voice-campaign-field select, .voice-campaign-field textarea {
  padding: 7px 9px; border-radius: 9px; font: inherit; font-size: 13px;
  border: 1px solid rgb(var(--ch-line) / .22);
  background: rgb(var(--ch-lift) / .04); color: var(--pk-text, var(--sh-mist));
}
.voice-campaign-field textarea { resize: vertical; min-height: 62px; }
.voice-campaign-window { display: flex; align-items: center; gap: 8px; }
.voice-campaign-window input { width: 72px; }
.voice-campaign-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 6px; }

.voice-campaign-preview {
  padding: 12px 14px; border-radius: 12px;
  border: 1px solid rgb(var(--ch-line) / .18); background: rgb(var(--ch-lift) / .03);
}
.voice-campaign-preview h3 { margin: 0 0 8px; font-size: 14px; }

/* ── «НЕ ЗВОНИТЬ» · /voice/do-not-call (27.09.2026) ─────────────────────────
   Форма добавления сверху, список ниже. Номер — главное в строке, причина —
   чипом рядом, дата и заметка — мелко под ним. «Убрать» уходит к правому краю
   и подтверждается в самой строке: вернуть номер в обзвон — единственное
   действие здесь, которым можно навредить. */
.dnc-card { display: flex; flex-direction: column; gap: 14px; max-width: 880px; }
.dnc-add {
  display: flex; flex-direction: column; gap: 10px;
  padding: 12px 14px; border-radius: 12px;
  border: 1px solid rgb(var(--ch-line) / .18); background: rgb(var(--ch-lift) / .03);
}
.dnc-add h3, .dnc-count {
  margin: 0; font-size: 13px; letter-spacing: .04em; text-transform: uppercase;
  color: var(--pk-dim, var(--sh-slate-1));
}
.dnc-add-row {
  display: grid; gap: 10px; align-items: start;
  grid-template-columns: minmax(170px, 1fr) minmax(150px, .8fr) minmax(190px, 1.4fr);
}
.dnc-ok { margin: 0; font-size: 13px; color: var(--rp-green); }
.dnc-search {
  width: 100%; max-width: 360px; padding: 7px 9px; border-radius: 9px; font: inherit; font-size: 13px;
  border: 1px solid rgb(var(--ch-line) / .22); background: rgb(var(--ch-lift) / .04);
  color: var(--pk-text, var(--sh-mist));
}
.dnc-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.dnc-row {
  display: flex; flex-direction: column; gap: 4px;
  padding: 10px 12px; border-radius: 10px; border: 1px solid rgb(var(--ch-line) / .16);
}
.dnc-row.is-confirming { border-color: rgb(var(--ch-red) / .5); background: rgb(var(--ch-red) / .05); }
.dnc-row-main { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.dnc-phone { font-weight: 600; font-variant-numeric: tabular-nums; }
.dnc-reason { font-size: 12px; padding: 2px 8px; border-radius: 999px; background: rgb(var(--ch-lift) / .07); }
.dnc-reason-refused_on_call, .dnc-reason-complaint { background: rgb(var(--ch-red) / .12); color: var(--rp-red); }
.dnc-remove { margin-inline-start: auto; }
.dnc-row-meta { display: flex; gap: 12px; flex-wrap: wrap; font-size: 12px; color: var(--pk-dim, var(--sh-slate-1)); }
.dnc-note { overflow-wrap: anywhere; }
.dnc-confirm p { margin: 4px 0; font-size: 13px; }
@media (max-width: 720px) {
  .dnc-add-row { grid-template-columns: 1fr; }
}
.voice-campaign-preview ul { margin: 0; padding-inline-start: 18px; font-size: 13px; line-height: 1.7; }
/* The cost carries its own arithmetic underneath it, at a size that is readable
   rather than fine print: a number nobody can check is a number they are right
   not to trust. */
.voice-campaign-cost {
  display: flex; flex-direction: column; gap: 3px; margin-top: 10px;
  padding-top: 10px; border-top: 1px solid rgb(var(--ch-line) / .16);
}
.voice-campaign-cost strong { font-size: 15px; }
.voice-campaign-cost small { color: var(--pk-dim, var(--sh-slate-1)); font-size: 12px; }

.voice-campaign-list { display: flex; flex-direction: column; gap: 10px; }
.voice-campaign-card {
  padding: 12px 14px; border-radius: 12px;
  border: 1px solid rgb(var(--ch-line) / .18); background: rgb(var(--ch-lift) / .03);
}
.voice-campaign-card header { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.voice-campaign-card p { margin: 6px 0 0; font-size: 13px; }

/* ── ОБЗВОН · список, расписание, правила ОАЭ (25 сентября 2026) ──────────────
   Всё переносится: на телефоне (375 px) ни одна строка не шире экрана — номер,
   имя и причина пропуска встают друг под другом, кнопки — в столбик. */
.voice-campaign-uae {
  display: flex; flex-direction: column; gap: 6px;
  padding: 12px 14px; border-radius: 12px;
  border: 1px solid rgba(245, 158, 11, .35); background: rgba(245, 158, 11, .06);
}
.voice-campaign-uae h3 { margin: 0; font-size: 14px; }
.voice-campaign-uae ul { margin: 0; padding-inline-start: 18px; font-size: 13px; line-height: 1.6; }
.voice-campaign-uae p { margin: 0; font-size: 13px; }
.voice-campaign-licence { font-weight: 600; }
.voice-campaign-segs { display: flex; flex-wrap: wrap; gap: 6px; }
.voice-campaign-seg {
  padding: 7px 12px; border-radius: 9px; font: inherit; font-size: 13px; cursor: pointer;
  border: 1px solid rgb(var(--ch-line) / .25); background: rgb(var(--ch-lift) / .04);
  color: var(--pk-text, var(--sh-mist));
  white-space: normal; text-align: start; max-width: 100%;
}
.voice-campaign-seg.is-on { border-color: var(--accent, #60a5fa); background: rgba(96, 165, 250, .14); font-weight: 600; }
.voice-campaign-seg[disabled] { opacity: .55; cursor: not-allowed; }
.voice-campaign-upload { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; }
.voice-campaign-count { font-size: 13px; font-weight: 600; overflow-wrap: anywhere; }
.voice-campaign-list-note { flex-basis: 100%; font-size: 12px; color: var(--pk-dim, var(--sh-slate-1)); }
.voice-campaign-list-input { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
.voice-campaign-cc { max-width: 110px; }
.voice-campaign-when { max-width: 260px; margin-top: 6px; }
.voice-campaign-uae-lines { margin: 8px 0 0; padding-inline-start: 18px; font-size: 13px; line-height: 1.7; }
.voice-campaign-rows-box { margin-top: 10px; }
.voice-campaign-rows-box > summary { cursor: pointer; font-size: 13px; font-weight: 600; }
.voice-campaign-rows {
  list-style: none; margin: 8px 0 0; padding: 0; max-height: 360px; overflow: auto;
  display: flex; flex-direction: column; gap: 4px;
}
.voice-campaign-rows li {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 10px;
  padding: 6px 8px; border-radius: 8px; font-size: 13px;
  border: 1px solid rgb(var(--ch-line) / .14);
}
.voice-campaign-rows li.is-skip { border-color: rgba(245, 158, 11, .35); background: rgba(245, 158, 11, .05); }
.voice-campaign-row-number { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; overflow-wrap: anywhere; }
.voice-campaign-row-name { font-weight: 600; overflow-wrap: anywhere; }
.voice-campaign-row-verdict { color: var(--pk-dim, var(--sh-slate-1)); overflow-wrap: anywhere; }
.voice-campaign-rows small { flex-basis: 100%; overflow-wrap: anywhere; }
.voice-campaign-created p { margin: 0 0 4px; }
.voice-campaign-plan { font-weight: 600; }
.voice-campaign-plan-edit, .voice-campaign-queue {
  margin-top: 10px; padding: 10px 12px; border-radius: 10px;
  border: 1px dashed rgb(var(--ch-line) / .25); display: flex; flex-direction: column; gap: 8px;
}
.voice-campaign-queue > p { margin: 0; }
@media (max-width: 480px) {
  .voice-campaign-actions > button { flex: 1 1 100%; }
  .voice-campaign-seg { flex: 1 1 100%; }
}
/* Конструктор обзвона внутри «Рассылок» — тот же экран, отступ как у блоков. */
.bc-voice-tool { margin-top: 4px; }

/* The legend under each role matrix. Quiet — it explains the table, it is not
   part of it — but always present, because the hover title it replaces is
   invisible on a phone and on paper. */
.team-matrix-legend { margin: 6px 0 0; font-size: .78rem; opacity: .8; }

/* The setup hero lost its 36px H2 when the screen stopped naming itself three
   times, so one sentence was left sitting at the top of a card kept 186px tall
   by the counter beside it — a big empty rectangle above the fold. Centre the
   two against each other and take the padding down; nothing is removed, the
   card just stops reserving room for a heading that is gone. */
.setup-hero { align-items: center; padding: 20px 24px; }
.setup-hero > div:first-child > p { margin: 0; }

/* ── /seo — the audit surface ──────────────────────────────────────────────
   Two shapes, and both of them existed to hold a hole open.

   1. `.seo-layout` was a THREE-column grid — dial, checks, context panel — and
      the panel it reserved a whole column for has been deleted (an eyebrow, a
      title and one generic sentence, with every stat filtered away for being a
      dash). A NEW class rather than an override of the old one: `.seo-layout`
      is declared five times in styles.css, twice inside media queries, and a
      plain later rule of equal specificity would have beaten the mobile
      collapse as well as the desktop rule.

   2. `.seo-grid` is a fixed two-column grid, so thirteen cards ended the last
      row with one card and an empty cell beside it. Flex-wrap with grow closes
      that at any card count and any width: whatever lands on the final row
      widens to fill it, so there is no arithmetic to keep in step with the
      number of checks. */
.seo-audit-layout {
  display: grid;
  grid-template-columns: minmax(260px, 0.34fr) minmax(0, 1fr);
  gap: 14px;
  align-items: start;
}

@media (max-width: 1120px) {
  .seo-audit-layout {
    grid-template-columns: 1fr;
  }
}

.seo-grid.seo-grid--fill {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
}

.seo-grid.seo-grid--fill > .audit-card {
  flex: 1 1 232px;
  min-width: min(232px, 100%);
  max-width: 100%;
}

/* This tab's own count, under the site-wide one. Specificity has to clear
   `.seo-score-card p`, which sets the size and colour of everything in there. */
.seo-score-card p.seo-scope-line {
  margin-top: 2px;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-secondary);
}

/* What a failing check asks for, under what it measured — separated by a rule
   so the instruction cannot be misread as part of the measurement. */
.audit-card p.seo-fix-line {
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid rgb(var(--ch-line) / .18);
  color: var(--text-secondary);
}

/* A real provider logo instead of the drawn kind-glyph, for the six marks we
   actually ship. It brings its own colours, so the tile drops the brand tint it
   would otherwise fight and sits on a neutral ground that reads on both themes. */
.chan-mark.chan-mark-logo {
  background: rgb(var(--ch-lift) / .07);
  color: inherit;
}
.chan-mark-img { display: block; object-fit: contain; }

/* ═══ THE FRONT DOOR ══════════════════════════════════════════════════════
   The sign-in screen used to be assembled from the Setup Centre's spare
   parts. It is now a split: the form on the left, short and focused; the
   product's own face on the right — one claim, three sentences, the real
   channel marks. No workspace claims, because at this moment there is no
   workspace to speak of. */
.auth-split {
  display: grid;
  grid-template-columns: minmax(360px, 460px) minmax(320px, 1fr);
  gap: 28px;
  align-items: stretch;
  max-width: 1060px;
  margin: 0 auto;
  width: 100%;
}
.auth-form-pane { display: grid; gap: 18px; align-content: start; }
.auth-form-head { display: grid; gap: 8px; }
.auth-form-head h2 { margin: 0; font-size: clamp(24px, 3vw, 30px); line-height: 1.15; }
.auth-form-intro { margin: 0; color: var(--rp-ink-2); line-height: 1.55; }
.auth-otp-badge { justify-self: start; }

.auth-brand-pane {
  border: 1px solid var(--rp-line);
  border-radius: 12px;
  /* The same ground the app's cards sit on, one step deeper, so the pane reads
     as the product it is describing rather than as a poster about it. */
  background:
    radial-gradient(120% 90% at 85% 0%, rgb(59 130 246 / 0.14), transparent 55%),
    rgb(var(--ch-lift) / 0.03);
  padding: 30px 28px;
  display: flex;
}
.auth-brand-inner { display: grid; gap: 16px; align-content: center; }
.auth-brand-pane h3 { margin: 0; font-size: clamp(19px, 2.2vw, 24px); line-height: 1.3; }
.auth-value-list { margin: 0; padding: 0; list-style: none; display: grid; gap: 10px; }
.auth-value-list li {
  position: relative;
  padding-inline-start: 22px;
  color: var(--rp-ink-2);
  line-height: 1.5;
}
.auth-value-list li::before {
  content: "";
  position: absolute;
  inset-inline-start: 0; top: 0.42em;
  width: 12px; height: 12px;
  border-radius: 50%;
  background: rgb(59 130 246 / 0.18);
  box-shadow: inset 0 0 0 4px rgb(59 130 246 / 0.55);
}
.auth-channel-row { display: flex; gap: 10px; }
.auth-channel-row .chan-mark { width: 34px; height: 34px; border-radius: 9px; display: inline-flex; align-items: center; justify-content: center; }

/* One column on a phone: the form is the whole point there, and the brand
   pane follows it rather than pushing it below the fold. */
@media (max-width: 940px) {
  .auth-split { grid-template-columns: 1fr; max-width: 520px; }
  .auth-brand-pane { padding: 22px 20px; }
}

/* The one road from the door back to the shop window. Quiet on purpose. */
.auth-demo-line { margin: 4px 0 0; text-align: center; font-size: 12.5px; }
.auth-demo-line a { color: var(--rp-ink-3); text-decoration: underline; text-underline-offset: 3px; }
.auth-demo-line a:hover { color: var(--rp-ink-2); }

/* ONE SCREEN (owner, 24 Sep 2026). «Получить код» does not open a new page:
   the code field — and, for a new e-mail on /login, the company field — stands
   UNDER the fields already filled, in the same form. A rule and some air mark
   it as the next step of the same card, not a second card. */
.auth-next-step {
  display: grid;
  gap: 12px;
  margin-top: 18px;
  padding-top: 16px;
  border-top: 1px solid var(--rp-line);
}
.auth-next-step .draft-field { margin-top: 0; }
.auth-next-step > .primary-button,
.auth-next-step > .secondary-button { width: 100%; }
.auth-next-note { margin: 0; color: var(--rp-ink-2); font-size: 13px; line-height: 1.5; overflow-wrap: anywhere; }
/* The address the code went to stays visible but reads as settled. */
.auth-one-screen input[readonly] { opacity: 0.78; }

/* ═══ ВЫУЧЕННЫЕ ОТВЕТЫ — the learning approval queue on «Согласования» ═══ */
.agent-learning-card .learn-row {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 10px 0;
  border-top: 1px solid var(--rp-line);
}
.agent-learning-card .learn-q { font-size: 13.5px; color: var(--rp-ink-1); }
.agent-learning-card .learn-a { margin: 0; font-size: 13px; color: var(--rp-ink-2); white-space: pre-wrap; }
.agent-learning-card .learn-meta { color: var(--rp-ink-3); font-size: 11.5px; }
.agent-learning-card .learn-actions { margin-top: 6px; }

/* «Сделки без движения»: seven rows, then the list scrolls inside the card so
   the board's row keeps its height, and the way to the rest is a real control. */
.deal-risk-card .deal-risk-mini { max-height: 216px; overflow-y: auto; }
.deal-risk-more {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin: 2px 0 8px;
  padding: 0;
  min-height: 0;
  border: 0;
  background: none;
  color: var(--sh-blue-1);
  font-size: 12.5px;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
}
.deal-risk-more:hover { color: var(--rp-ink-1); }

/* ═══ AGENT CABINET REBUILD (night 2026-08-19, queue 00:3x) ═══════════════════
   Three frames, one family: the WIDE two-column cabinet (rail + working
   surface — the right drawer is gone and its width went to the work), the full
   standalone pages (knowledge / quality / analyzer / broadcasts / presets /
   library), and the channels status board that replaced the connect forms.
   Selectors are deliberately 2-3 classes deep: redesign.css loads before
   pack-design.css, so these win by specificity, not by order. */

/* The cabinet grid: rail + body, nothing else. pack-design's three-column rule
   (rail · body · drawer) still exists for older layouts; this page opts out. */
.agent-cabwrap .agent-cabinet.agent-cabinet-wide {
  grid-template-columns: var(--pk-local-w, 300px) minmax(0, 1fr);
}
@media (max-width: 1080px) {
  .agent-cabwrap .agent-cabinet.agent-cabinet-wide { grid-template-columns: minmax(0, 1fr); }
}
.agent-cabacts .agent-cablink { cursor: pointer; }

/* Departure rows in the rail: the sections that open as their own pages. */
.ac-nav .ac-nav-item.ac-nav-go { color: var(--rp-ink-2, inherit); }
.ac-nav .ac-nav-item .ac-nav-arrow {
  margin-inline-start: auto;
  opacity: 0.45;
  transition: transform 0.15s ease, opacity 0.15s ease;
}
.ac-nav .ac-nav-item.ac-nav-go:hover .ac-nav-arrow { opacity: 1; transform: translateX(2px); }

/* ── the full standalone pages ── */
.agent-fullpage { display: grid; gap: var(--rp-3, 14px); min-width: 0; }
.agent-fullpage-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 12px 18px;
  padding: 16px 18px;
  border: 1px solid var(--rp-line, rgba(148, 178, 255, 0.16));
  border-radius: 16px;
  background: var(--rp-surface, rgba(255, 255, 255, 0.02));
}
.agent-fullpage-title { min-width: 220px; flex: 1 1 260px; }
.agent-fullpage-title h2 { margin: 0 0 4px; font-size: 20px; letter-spacing: -0.01em; }
.agent-fullpage-title p { margin: 0; color: var(--rp-ink-3, #a7b4cc); font-size: 13px; }
.agent-fullpage-strip { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; width: 100%; }
.agent-fullpage-chip {
  border: 1px solid var(--rp-line, rgba(148, 178, 255, 0.2));
  border-radius: 999px;
  background: none;
  color: var(--rp-ink-2, inherit);
  font-size: 12px;
  padding: 5px 12px;
  cursor: pointer;
}
.agent-fullpage-chip:hover { border-color: var(--rp-line-2, rgba(148, 178, 255, 0.4)); }
.agent-fullpage-chip.on {
  background: var(--pk-blue-soft, rgba(79, 140, 255, 0.14));
  border-color: transparent;
  font-weight: 600;
  cursor: default;
}
.agent-fullpage-body { min-width: 0; display: grid; gap: var(--rp-3, 14px); }
/* The transition the owner asked for — a page you ARRIVE at, not a pane that
   blinks. Skipped entirely for readers who asked motion to stay away. */
@media (prefers-reduced-motion: no-preference) {
  .agent-fullpage { animation: agent-page-in 0.22s ease; }
  @keyframes agent-page-in {
    from { opacity: 0; transform: translateY(6px); }
    to { opacity: 1; transform: none; }
  }
}

/* ── the channels status board ── */
.chx-go { width: 100%; text-align: start; cursor: pointer; }
.chx-group {
  border: 1px solid var(--rp-line, rgba(148, 178, 255, 0.14));
  border-radius: 14px;
  padding: 6px 14px 10px;
  margin-top: 14px;
}
.chx-cat {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  padding: 8px 0 4px;
  font-weight: 620;
  font-size: 13px;
}
.chx-row {
  padding: 10px 0;
  border-top: 1px solid var(--rp-line, rgba(148, 178, 255, 0.1));
}
.chx-main { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.chx-name { font-weight: 600; font-size: 13.5px; }
.chx-note { color: var(--rp-ink-3, #a7b4cc); font-size: 11.5px; }
.chx-row .channel-owner-row { border-top: 0; margin-top: 8px; padding-top: 0; }

/* НИЧТО НА ЭТОЙ ВКЛАДКЕ НЕ ШИРЕ СВОЕЙ КОЛОНКИ (8 сентября 2026).
   Владелец прислал скриншот: слова «подключено N из M» уехали за правый край
   страницы, за рамку карточки. Причина — не сам счётчик: он прижат к правому
   краю группы (.chx-cat, space-between), а группу раздвигало содержимое,
   которое не переносится. Самый длинный такой кусок — адреса в списке
   приостановленных диалогов вида «WhatsApp · AE.28570254195903031»: один
   неразрывный токен в 20 символов, при nowrap он тянет всю секцию.
   Поэтому: группа не шире контейнера, шапка умеет переноситься, а длинные
   идентификаторы рвутся по любому месту — читаемость адреса от переноса не
   страдает, а вёрстка от его длины больше не зависит. */
#ac-channels, #ac-channels .chx-group { max-width: 100%; box-sizing: border-box; }
#ac-channels .chx-cat { flex-wrap: wrap; }
#ac-channels .chx-main { min-width: 0; }
#ac-channels .chx-name, #ac-channels .chx-note { overflow-wrap: anywhere; }

/* ── the instruction editor: «всё видно» ──
   A prompt is prose someone re-reads; give it a real page of room. The wide
   two-column cabinet supplies the width, this supplies the height. */
#ac-instruction textarea#instr-persona {
  min-height: 380px;
  font-size: 13.5px;
  line-height: 1.55;
  resize: vertical;
}
#ac-settings textarea { min-height: 72px; resize: vertical; }

/* ── Settings: where things live ─────────────────────────────────────────
   Four rows replacing six empty tabs. Each one answers "where do I set this
   up" and takes you there; the tabs they replace existed only to say "not
   here". Same card language as the rest of the page — no new shapes. */
.settings-elsewhere-rows {
  display: grid;
  gap: 8px;
  margin-top: 12px;
}
.settings-elsewhere-row {
  display: grid;
  grid-template-columns: minmax(120px, 200px) 1fr auto;
  gap: 14px;
  align-items: center;
  width: 100%;
  padding: 12px 14px;
  border-radius: 10px;
  border: 1px solid rgb(var(--ch-lift) / .08);
  background: rgb(var(--ch-lift) / .03);
  color: inherit;
  font: inherit;
  text-align: start;
  cursor: pointer;
  transition: background .15s ease, border-color .15s ease;
}
.settings-elsewhere-row:hover {
  background: rgb(var(--ch-lift) / .07);
  border-color: rgb(var(--ch-blue2) / .35);
}
.settings-elsewhere-row strong { font-size: .92rem; }
.settings-elsewhere-row span {
  color: var(--rp-ink-2);
  font-size: .82rem;
  line-height: 1.45;
  min-width: 0;
}
.settings-elsewhere-row small {
  color: var(--pk-accent, rgb(var(--ch-blue2)));
  font-size: .78rem;
  white-space: nowrap;
}
@media (max-width: 720px) {
  .settings-elsewhere-row { grid-template-columns: 1fr; gap: 4px; }
  .settings-elsewhere-row small { justify-self: start; }
}

/* ── Settings: requests that are actually waiting ────────────────────────
   Replaces a number on a card that nobody could open. The oldest row had
   been waiting a month while the card said "Attention" and stopped there. */
.settings-request-rows { display: grid; gap: 6px; margin-top: 12px; }
.settings-request-row {
  display: grid;
  grid-template-columns: 1fr minmax(90px, auto) auto;
  gap: 12px;
  align-items: baseline;
  padding: 10px 12px;
  border-radius: 8px;
  border: 1px solid rgb(var(--ch-lift) / .07);
  background: rgb(var(--ch-lift) / .025);
}
.settings-request-row strong { font-size: .88rem; font-weight: 600; min-width: 0; overflow-wrap: anywhere; }
.settings-request-row span { color: var(--rp-ink-3); font-size: .76rem; text-transform: capitalize; }
.settings-request-row small { color: var(--rp-ink-2); font-size: .78rem; white-space: nowrap; }
/* Two weeks is where "in flight" stops being true. The row says so rather
   than leaving the reader to subtract dates. */
.settings-request-row.is-old { border-color: rgb(var(--ch-amber, 240 182 77) / .38); }
.settings-request-row.is-old small { color: var(--lw-warm, #f0b64d); font-weight: 600; }
@media (max-width: 720px) {
  .settings-request-row { grid-template-columns: 1fr; gap: 3px; }
}

/* СВОЙ КРЕСТИК ИЛИ БРАУЗЕРНЫЙ — НО НЕ ОБА СРАЗУ.
   Владелец 30 августа: «крудочек и крестик сразу один на другом в строке».
   У input[type=search] браузер рисует СВОЮ кнопку очистки, а мы поверх ставим
   собственные — лупу и крестик (.crm-search-actions). Две кнопки очистки в
   одной точке — это не только некрасиво: половина нажатий попадает не туда.

   Гасим браузерную ровно там, где есть наша. Поля без своих кнопок —
   «Задачи», голос, бухгалтерия, реестр — сохраняют браузерную: убрать её у
   них значило бы отнять единственный способ очистить строку одним движением. */
.crm-search input[type="search"]::-webkit-search-cancel-button,
.pk-search input[type="search"]::-webkit-search-cancel-button,
.dw-search input[type="search"]::-webkit-search-cancel-button {
  -webkit-appearance: none;
  appearance: none;
}

/* ДЛИННАЯ ПОДПИСЬ ПЛИТКИ ПЕРЕНОСИТСЯ, А НЕ ОБРЕЗАЕТСЯ.
   Владелец 30 августа показал «У 37 открытых сделок не проставлена сумма —
   считат…»: подпись стояла в одну строку с многоточием. Обрезанная фраза хуже
   отсутствующей — она обещает объяснение и не даёт его, а это как раз тот
   случай, когда объяснение и есть всё сообщение (почему пайплайн пуст).

   Две строки максимум: столько же места, сколько занимал бы график, и не
   больше. Что не поместилось за две строки — по-прежнему многоточие, но такие
   подписи в продукте короче. */
/* Селектор из ДВУХ классов, а не одного, и это не случайность: строкой выше
   в этом же файле стоит `.rp-ov .rp-kpi-sub … white-space: nowrap`, и одним
   классом его не перебить — специфичность выше, порядок не помогает. Первая
   версия правки это и показала: файл новый, правило последнее, а на экране
   по-прежнему nowrap. Замер по таблицам стилей назвал победителя поимённо. */
.rp-ov .rp-kpi-sub,
.rp-kpi-sub {
  white-space: normal;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  line-height: 1.35;
}

/* ТЕКСТ В ТАБЛИЦАХ НЕ ПРИЖИМАЕТСЯ К БОРТУ КАРТОЧКИ.
   «Текст весь прижат к левому борту, некрасиво» — про таблицу кампаний, но
   правило общее: у ячеек есть боковые поля, а у КРАЙНИХ столбцов их не хватало,
   и первая колонка вставала вплотную к рамке. Логические свойства, чтобы при
   арабской раскладке отступ ушёл на нужную сторону вместе с текстом. */
.table-wrap table th:first-child,
.table-wrap table td:first-child { padding-inline-start: 16px; }
.table-wrap table th:last-child,
.table-wrap table td:last-child { padding-inline-end: 16px; }

/* Переключатель звука в центре уведомлений. Настройка рабочего МЕСТА, а не
   пространства: у одного наушники, у другого открытый офис. Стоит над ссылкой
   на центр действий — рядом с тем, о чём он и уведомляет. */
.rp-bell-sound {
  display: flex; align-items: center; gap: 8px;
  padding: 9px 2px 3px; font-size: 12.5px; color: var(--rp-ink-2);
  cursor: pointer;
}
.rp-bell-sound input { inline-size: 15px; block-size: 15px; cursor: pointer; }

/* Кликабельная метка состояния в «Системе»: подпись обещает причину, значит
   метка обязана до неё вести. Кнопка, а не span — с фокусом и курсором, чтобы
   с клавиатуры это тоже было достижимо. Внешне не отличается от обычной метки:
   разница появляется под курсором, а не в покое, иначе строка состояния стала
   бы рядом кнопок. */
.rp-truth-chip-act {
  border: 0;
  font: inherit;
  font-size: 11px;
  cursor: pointer;
  text-decoration: underline dotted transparent;
  text-underline-offset: 3px;
}
.rp-truth-chip-act:hover { text-decoration-color: currentColor; }
.rp-truth-chip-act:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }

/* КАРТОЧКИ ПРЕСЕТОВ ПЕРЕСТАЛИ БЫТЬ ОДИНАКОВЫМИ.
   Двадцать три кружка одного цвета неразличимы: салон красоты и клинику
   приходилось читать текстом. Оттенок считается из ключа пресета, поэтому у
   одного пресета он всегда один и тот же — по нему карточку запоминают и
   находят глазом во второй раз. Насыщенность и светлота фиксированы, чтобы ни
   один оттенок не оказался ярче остальных и не притянул внимание без причины. */
.agent-card-avatar {
  width: 40px;
  height: 40px;
  font-size: 15px;
  background: hsl(var(--agent-hue, 210) 62% 52% / 0.18);
  color: hsl(var(--agent-hue, 210) 70% 72%);
  border: 1px solid hsl(var(--agent-hue, 210) 62% 58% / 0.35);
}
/* Пояснение про каналы — один раз над сеткой вместо шести неактивных значков
   на каждой из карточек. */
.agent-cards-note {
  margin: 6px 0 0;
  max-width: 68ch;
  font-size: 12.5px;
  line-height: 1.55;
  color: var(--rp-ink-3, #8b95a5);
}

/* ═══ COMPACT RAIL — icon over a one-word label (2026-09-04) ═══════════════
   The amoCRM-style rail the owner asked for: narrow, every item still named,
   no tooltip needed. Layered ON TOP of .rail-collapsed (whose rules and tests
   stay as they are) rather than replacing it: the class pair is
   "rail-collapsed rail-compact". Self-headed screens (lead card, dialogues,
   agent cabinet) force it and hide the toggle — the screen owns the width.
   Selectors carry .app-shell and the element name on purpose: the collapsed
   rules in cabinet-system.css hide the label with
   `.rail-collapsed .nav-item > span:not([class*="nav-icon"])`, which outranks
   a plain three-class selector. */
.app-shell.rail-compact { grid-template-columns: 84px minmax(0, 1fr); }
.app-shell.rail-compact .nav-list { width: 76px; }
.app-shell.rail-compact .nav-item {
  flex-direction: column;
  justify-content: center;
  gap: 3px;
  width: 76px;
  min-height: 54px;
  padding: 6px 2px;
}
.app-shell.rail-compact .nav-item > span.nav-item-text {
  display: block;
  max-width: 72px;
  font-size: 10.5px;
  line-height: 1.15;
  text-align: center;
  white-space: normal;
  letter-spacing: 0;
}
.app-shell.rail-compact .nav-item::after { display: none; }
.app-shell.rail-compact .nav-section + .nav-section { margin-top: 6px; padding-top: 6px; }
.app-shell.self-headed .rail-toggle { display: none; }
/* The section-title row («← CRM») is gone on screens that carry their own
   header; the topbar stays as the one thin line on top. */
.app-shell.self-headed .pk-header-with-back { display: none; }

/* ── SELF-HEADED SCREENS LOSE THE TOP BAR TOO (2026-09-04, evening) ─────────
   The owner on the lead card: «вверху убрать — поиск, "AI agents", колокольчик
   и название пусть будут только на главной; за счёт этого подними рабочее
   поле». The card, the dialogues and the agent cabinet carry their own header
   already; the product's top bar above it was a second strip of chrome over a
   working screen. The rail's account card stays reachable at the bottom of
   the rail on every screen. */
.app-shell.self-headed .rp-topbar { display: none; }

/* ── CLOSER TO THE RAIL, AND A GLOW BETWEEN THE THREE (2026-09-05) ─────────
   Owner: «ещё наполовину приблизь к левому блоку» and «между блоками —
   окантовку, наше свечение, чтобы отделить визуально: меню | карточка |
   диалог». Self-headed screens drop the workspace's 30px side padding to
   12px; the card and the dialogue carry a soft blue ring instead of a
   hairline, so the three surfaces read as three without a wall of space. */
.app-shell.self-headed .workspace { padding: 12px 12px 12px; }
.app-shell.self-headed .lw-card,
.app-shell.self-headed .lw-main,
.app-shell.self-headed .lw-drawer {
  border-color: rgba(47, 123, 255, 0.30);
  box-shadow: 0 0 0 1px rgba(47, 123, 255, 0.10), 0 0 24px rgba(47, 123, 255, 0.12), inset 0 0 0 1px rgba(148, 178, 255, 0.05);
}
.app-shell.self-headed .lw-page.has-card { column-gap: 8px; }

/* ── TASKS IN THE RAIL (2026-09-05): a checked square, the day's work ────── */
.nav-icon-tasks {
  --nav-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3.5' y='3.5' width='17' height='17' rx='3.5'/%3E%3Cpath d='M8 12.2l2.7 2.7L16.3 9.4'/%3E%3C/svg%3E");
}

/* ── THE TOP BAR STARTS AT THE TOP (2026-09-05, the owner's red line) ────────
   styles.css pins `.workspace { padding-top: 22px !important }`, so the bar's
   own negative margin never gained anything: sticky positioning kept it inside
   the content box, 22px down, with a dead strip above it that the owner drew
   a line across. Same specificity war, won by the more specific selector.
   Self-headed screens (the lead card) keep their own top inset. */
body.has-rail .app-shell:not(.self-headed) .workspace { padding-top: 0 !important; }
body.has-rail .app-shell:not(.self-headed) .rp-topbar { margin-top: 0; margin-bottom: 14px; }

/* ── ON A PHONE THE RAIL IS A DRAWER, OUT OF THE FLOW (2026-09-24, audit G1) ─
   Measured at 390×844 on /dashboard: styles.css moved the rail off-canvas
   (translateX(-102%)), but the ≤980px band in this file re-declared it
   `position: sticky` and cabinet-system.css gave it `height: auto` — so an
   invisible 1,026px column still stood in the flow and <main> began at
   y=1026. The shell is the viewport (pack-design.css, `overflow: hidden`), so
   the page below could not even be scrolled to: every screen opened on an
   empty dark rectangle under the menu bar. Opened, the drawer sat BEHIND its
   own scrim (z-index 45 against the scrim's 58).
   The phone band is ≤700px — the line pack-design.css draws for its 701–980
   tablet rail (owner's item 19, 19.09.2026). Every rule sits inside a media
   query, so the desktop shell does not change by a pixel.
   scripts/test-phone-shell-drawer.mjs holds this. */
@media (max-width: 700px) {
  body.has-rail .app-shell { height: 100vh; height: 100dvh; }
  body.has-rail .app-shell > aside.sidebar {
    position: fixed;
    height: 100vh;
    height: 100dvh;
    min-height: 0;
    z-index: 59;
    overflow: hidden auto;
    align-items: stretch;
  }
  /* <main> fills the viewport, so .page-stack is the scroller again, and it
     starts under the fixed menu bar (65px + the notch) instead of behind it. */
  body.has-rail .app-shell > main.workspace { height: 100%; }
  body.has-rail .app-shell:not(.self-headed) > main.workspace,
  body.has-rail .app-shell.self-headed > main.workspace {
    padding-top: calc(65px + env(safe-area-inset-top)) !important;
  }
  /* Inside the drawer: named rows, not the desktop's 76px icon column. */
  body.has-rail .app-shell > aside.sidebar .nav-list {
    display: flex;
    flex-direction: column;
    width: auto;
    gap: 2px;
    overflow: visible;
  }
  body.has-rail .app-shell > aside.sidebar .nav-section { display: flex; flex-direction: column; gap: 2px; }
  /* `[href]` lifts the rule over pack-design's (0,6,0) Tasks indent, which
     otherwise pulled that one row 12px left of the others. */
  body.has-rail .app-shell > aside.sidebar .nav-list .nav-item[href] {
    flex-direction: row;
    justify-content: flex-start;
    width: auto;
    gap: 12px;
    padding: 0 12px;
    white-space: nowrap;
  }
  body.has-rail .app-shell > aside.sidebar .nav-item > span.nav-item-text {
    display: inline;
    max-width: none;
    font-size: 14px;
    text-align: start;
    white-space: nowrap;
  }
}
/* 701–767px: styles.css draws its phone drawer up to 767px, and those rules
   leaked into the tablet rail — the rail was translated off-screen, leaving an
   empty 84px column, and the phone menu bar covered the top bar. In this band
   the narrow rail is the navigation, so the drawer pieces stand down. */
@media (min-width: 701px) and (max-width: 767px) {
  body.has-rail .app-shell > aside.sidebar { transform: none; width: auto; max-width: none; }
  body.has-rail .mobile-bar,
  body.has-rail .nav-scrim { display: none; }
}

/* Встречи из календаря на странице «Задачи» (владелец, 5 сентября). */
.tsk-mode { display: flex; gap: 6px; margin-bottom: 8px; }
.tsk-meetings { display: flex; flex-direction: column; gap: 14px; }
.tsk-mday-head { font-size: 13px; text-transform: uppercase; letter-spacing: .04em; color: var(--bd-ink-3); margin: 0 0 6px; display: flex; align-items: center; gap: 8px; }
.tsk-meet { display: flex; gap: 12px; padding: 10px 12px; border: 1px solid rgb(var(--ch-line) / .18); border-radius: 12px; background: rgb(var(--ch-lift) / .03); margin-bottom: 6px; }
.tsk-meet-time { flex: 0 0 auto; min-width: 92px; font-variant-numeric: tabular-nums; color: var(--bd-ink-2); font-size: 13px; }
.tsk-meet-main { min-width: 0; flex: 1 1 auto; }
.tsk-meet-title { font-weight: 600; color: var(--bd-ink); }
.tsk-meet-meta { display: flex; flex-wrap: wrap; gap: 6px 14px; margin-top: 4px; font-size: 12px; color: var(--bd-ink-3); }
.tsk-meet-owner { color: var(--bd-ink-2); }
.tsk-meet-owner.is-none { opacity: .7; }
.tsk-meet-lead, .tsk-meet-link { color: var(--sh-blue-2, #6ea8fe); text-decoration: none; }
.tsk-meet-lead:hover, .tsk-meet-link:hover { text-decoration: underline; }

/* КНОПКА ПРОСЛУШИВАНИЯ ГОЛОСА ОТВЕЧАЕТ НА НАЖАТИЕ (7 сентября 2026).
   Между щелчком и первым звуком проходит секунда-две: без видимого состояния
   это читается как «кнопка не работает», и человек жмёт её ещё раз. */
.secondary-button.is-busy { opacity: 0.75; cursor: progress; }
.secondary-button.is-playing {
  border-color: rgb(var(--ch-green, 46 160 67) / 0.55);
  box-shadow: 0 0 0 2px rgb(var(--ch-green, 46 160 67) / 0.18);
}


/* ВАЛЮТА В МЕНЮ ПРОФИЛЯ — В ОДИН РОСТ С СОСЕДЯМИ (владелец, 7 сентября:
   «сделай тут аккуратнее»). Рядом стоят сегментные переключатели языка и темы;
   голый <select> был выше их, светлее фона и растягивался на всю строку. */
/* ВАЛЮТА В МЕНЮ ПРОФИЛЯ. Первая версия рисовала стрелку фоном и снимала
   родное оформление (appearance: none) — в тёмной теме поле осталось белым
   столбцом без текста (владелец, 7 сентября: «валюта что то совсем не то,
   столбец»). Родное оформление возвращено: браузер сам рисует и стрелку, и
   текст, а мы задаём только размер, рамку и ЯВНЫЕ цвета — прозрачный фон у
   select в тёмной теме и есть та самая белая заливка. */
.profile-row-currency .profile-currency-select {
  max-width: 190px;
  padding: 5px 8px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-sm, 8px);
  /* Токены темы, а не свои цвета: у select прозрачный фон в тёмной теме
     рисуется белым, поэтому фон и текст задаются явно — но из палитры. */
  background-color: var(--rp-panel);
  color: var(--rp-ink);
  font: inherit;
  font-size: 12px;
  line-height: 1.4;
}
.profile-row-currency .profile-currency-select option {
  background-color: var(--rp-panel);
  color: var(--rp-ink);
}
.profile-row-currency .profile-currency-select:focus-visible {
  outline: 2px solid rgb(var(--ch-blue, 56 132 255) / 0.55);
  outline-offset: 1px;
}


/* ПРОСТОРНЕЕ, А НЕ ПЛОТНЕЕ (владелец, 7 сентября: «не мельчи, всё не засовывай
   на одну страницу, пусть будет просторнее, удобнее, понятнее»).
   Три блока, добавленные сегодня, получают воздух и разбиваются на карточки
   вместо плотного списка: правила стадий, документы сделки, экран операций. */

/* Правила стадий: строка — карточка, а не строчка списка. Флажок, название,
   пояснение и выбор стадии перестают тесниться в одну линию. */
.set-stage-rules { display: grid; gap: 10px; margin-top: 10px; }
.set-stage-rules .set-stage-rule {
  grid-template-columns: 20px minmax(160px, 1fr) auto;
  align-items: center;
  gap: 6px 12px;
  padding: 12px 14px;
  border: 1px solid var(--rp-line);
  border-radius: 10px;
  background: rgb(var(--ch-lift, 255 255 255) / 0.02);
}
.set-stage-rules .set-stage-rule .set-auto-text { font-size: 13.5px; font-weight: 600; }
.set-stage-rules .set-stage-rule .set-auto-hint {
  grid-column: 2 / -1; margin-top: 2px;
  color: var(--rp-muted, #9aa7bd); font-size: 12px;
}
.set-stage-rules .set-stage-select {
  grid-row: 1; grid-column: 3;
  min-width: 190px; padding: 7px 10px;
  border: 1px solid var(--rp-line); border-radius: 8px;
  background: rgb(var(--ch-lift, 255 255 255) / 0.03);
  color: var(--rp-ink); font: inherit; font-size: 12.5px;
}
.set-stage-rules .set-stage-min {
  grid-row: 1; grid-column: 3; justify-self: end;
  width: 74px; padding: 7px 8px;
  border: 1px solid var(--rp-line); border-radius: 8px;
  background: rgb(var(--ch-lift, 255 255 255) / 0.03);
  color: var(--rp-ink); font: inherit; font-size: 12.5px;
}
.set-stage-locked { gap: 8px; margin: 8px 0 4px; }
.set-stage-locked .set-stage-lock { padding: 6px 12px; font-size: 12.5px; }
/* Правила стадий на телефоне (26 сентября 2026). Три колонки карточки —
   флажок 20 px, текст не уже 160 px и выбор стадии не уже 190 px — вместе с
   полями дают 424 px, а у списка правил на экране 375 px есть 297. Карточка
   уезжала вправо, .page-stack молча срезал лишнее: выбор стадии и конец
   пояснения пропадали, прокрутки не было. На узком экране название,
   пояснение и выбор стадии идут друг под другом во всю ширину текста, а
   третья колонка остаётся только под число порога квалификации — пояснение
   к «Квалифицирован» обещает «число справа». Лишний .set-auto-row в
   селекторах нужен: pack-design.css подключён позже и ставит порог в строку 3
   селектором той же силы, а @media силы не добавляет. Рабочий стол не
   меняется. */
@media (max-width: 560px) {
  .set-stage-rules .set-auto-row.set-stage-rule { grid-template-columns: 20px minmax(0, 1fr) auto; }
  .set-stage-rules .set-auto-row.set-stage-rule .set-auto-text { grid-column: 2 / -1; }
  .set-stage-rules .set-auto-row.set-stage-rule .set-stage-select {
    grid-row: auto; grid-column: 2 / -1;
    min-width: 0; width: 100%;
  }
  .set-stage-rules .set-auto-row.set-stage-rule .set-stage-min-label,
  .set-stage-rules .set-auto-row.set-stage-rule .set-stage-min { grid-row: auto; }
  .set-stage-rules .set-auto-row.set-stage-rule .set-stage-min { width: 74px; }
}

/* Документы сделки: карточка дышит, предпросмотр не жмётся к краям. */
.lw-docs-panel { gap: 16px; padding-block: 4px; }
.lw-docs-pick { gap: 10px; }
.lw-docs-preview { padding: 14px 16px; }
.lw-docs-row { padding: 10px 12px; }

/* Экран операций: карточки в две колонки на широком экране, с полями. */
.ops-page { display: grid; gap: 18px; }
.ops-grid {
  display: grid; gap: 14px;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
}
.ops-card {
  display: grid; gap: 10px;
  padding: 18px 20px;
  border: 1px solid var(--rp-line); border-radius: 12px;
  background: rgb(var(--ch-lift, 255 255 255) / 0.02);
}
.ops-card-head { display: flex; align-items: center; gap: 10px; }
.ops-card-head h3 { margin: 0; font-size: 15px; }
.ops-card-icon { font-size: 18px; line-height: 1; }
.ops-card-phase {
  margin-inline-start: auto; padding: 3px 9px;
  border: 1px solid var(--rp-line); border-radius: 999px;
  color: var(--rp-muted, #9aa7bd); font-size: 11px; white-space: nowrap;
}
.ops-card-desc { margin: 0; color: var(--rp-ink-2, #c3ccda); font-size: 13px; line-height: 1.55; }
.ops-card-foot { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; }
.ops-card-price { font-size: 13.5px; font-weight: 640; }
.ops-card-count { color: var(--rp-muted, #9aa7bd); font-size: 12px; }
.ops-state { padding: 12px 14px; border-radius: 10px; line-height: 1.55; }
.ops-org { margin: 0; color: var(--rp-muted, #9aa7bd); font-size: 12.5px; }

/* РЕДАКТОР ШАБЛОНОВ ДОКУМЕНТОВ на экране операций (8 сентября 2026).
   Текст документа правят редко и вдумчиво, поэтому поле большое, моноширинное
   и с переносом: человек должен видеть поля {{…}} ровно там, где они стоят. */
.ops-templates { display: grid; gap: 12px; margin-top: 4px; }
.ops-templates h2 { margin: 0; font-size: 16px; }
.ops-tpl-list { display: grid; gap: 8px; }
.ops-tpl-row {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 10px 12px; border: 1px solid var(--rp-line); border-radius: 10px;
  background: rgb(var(--ch-lift, 255 255 255) / 0.02);
}
.ops-tpl-title { font-size: 13.5px; font-weight: 600; }
.ops-tpl-row .ghost-button { margin-inline-start: auto; }
/* Заголовок секции и кнопка «+ Свой шаблон» — одной строкой: кнопка стоит там,
   где человек читает название раздела, а не под одиннадцатью карточками. */
.ops-tpl-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.ops-tpl-head h2 { margin: 0; }
.ops-tpl-editor { display: grid; gap: 10px; }
.ops-tpl-editor-title { margin: 0; font-size: 15px; }
.ops-tpl-meta { display: flex; gap: 12px; flex-wrap: wrap; }
.ops-tpl-metafield { display: grid; gap: 4px; font-size: 12px; min-width: 160px; }
.ops-tpl-metafield > span { color: var(--rp-ink-3, #6b7a90); }
.ops-tpl-input,
.ops-tpl-body {
  width: 100%; padding: 10px 12px;
  border: 1px solid var(--rp-line); border-radius: 10px;
  background-color: var(--rp-panel); color: var(--rp-ink);
  font: inherit; font-size: 13px;
}
.ops-tpl-body {
  min-height: 260px; resize: vertical; white-space: pre-wrap;
  font: 12.5px/1.6 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
.ops-tpl-actions { display: flex; gap: 8px; flex-wrap: wrap; }

/* УСЛОВИЯ У МАРШРУТА — фаза 3 (10 сентября 2026).
   Блок намеренно отделён рамкой и подложкой: это единственное место на
   экране, где человек описывает поведение автоматики, и оно не должно
   читаться как ещё одна строчка настроек. */
.ops-conds {
  display: grid;
  gap: 9px;
  padding: 12px 14px;
  border: 1px solid var(--rp-line);
  border-radius: 10px;
  background: var(--rp-panel-2);
}

.ops-conds-head { margin: 0; font-size: 13px; font-weight: 640; color: var(--rp-ink); }

/* ДЕНЬГИ ПОД РИСКОМ на карточке «Сделки без движения» (10 сентября 2026).
   Сумма набрана крупнее счётчика штук: в Revenue Control деньги — главное
   число экрана, а количество сделок — способ до них добраться. */
.deal-risk-money {
  margin: 2px 0 0;
  display: flex;
  align-items: baseline;
  gap: 8px;
  flex-wrap: wrap;
}

.deal-risk-money strong {
  font-size: 22px;
  font-weight: 660;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  color: var(--rp-red);
}

.deal-risk-money span { font-size: 12px; color: var(--rp-ink-2); }

.ops-cond-list { display: grid; gap: 8px; }

/* Поле, сравнение, значение, «убрать». На узком экране складывается в
   столбец сам — прибитые четыре колонки ломались бы на планшете. */
.ops-cond-row {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  align-items: center;
}

.ops-cond-row > .ops-tpl-input { flex: 1 1 140px; min-width: 0; }
.ops-cond-match { max-width: 320px; }

/* ФРАЗА. Она здесь не украшение: правило, которое нельзя прочитать вслух,
   нельзя и проверить глазами. Поэтому её видно, а не прячут в подсказку. */
.ops-cond-sentence {
  margin: 0;
  padding: 10px 12px;
  border-inline-start: 3px solid var(--rp-blue);
  border-radius: 8px;
  background: color-mix(in srgb, var(--rp-blue) 8%, transparent);
  font-size: 13px;
  line-height: 1.55;
  color: var(--rp-ink);
}


/* ОПЕРАЦИИ: рабочее сверху, план под свёрнутым заголовком (10 сентября).
   Экран открывался сеткой из пяти цен, и владелец прочитал его как витрину
   тарифов — до двух работающих редакторов ниже он просто не долистал. */
.ops-h2 { margin: 6px 0 0; font-size: 15px; font-weight: 640; color: var(--rp-ink, #e9eef7); }

.ops-plan {
  border: 1px solid var(--rp-line, rgba(148, 178, 255, 0.10));
  border-radius: 12px;
  padding: 4px 14px;
  background: var(--rp-panel, #121821);
}

.ops-plan > summary {
  cursor: pointer;
  padding: 11px 0;
  font-size: 13px;
  font-weight: 620;
  color: var(--rp-ink-2, #94a3b8);
  list-style-position: inside;
}

.ops-plan > summary:hover { color: var(--rp-ink, #e9eef7); }
.ops-plan > summary:focus-visible { outline: 2px solid var(--rp-blue, #2f7bff); outline-offset: 2px; border-radius: 6px; }
.ops-plan[open] > summary { border-bottom: 1px solid var(--rp-line, rgba(148, 178, 255, 0.10)); margin-bottom: 12px; }
.ops-plan > .ops-card-desc { margin-bottom: 12px; }
.ops-plan > .sw-row { padding-bottom: 14px; }


/* Маршруты. Шаг — одна строка: номер, что делает, чем назвать, сам или
   спросить. На узком экране поля переносятся, но номер остаётся слева, чтобы
   лестница читалась сверху вниз даже с телефона. */
/* СОСТАВИТЕЛЬ ПИСЬМА В КАРТОЧКЕ. Кнопка и запасной выход в Gmail стоят в
   одну строку; сам составитель разворачивается под ними на всю ширину панели,
   потому что письмо пишут абзацами, а не в одну строку. */
.lw-mail-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
/* «НАЗНАЧИТЬ ВСТРЕЧУ» (23 сентября 2026). Кнопка — под письмом, панель
   разворачивается под ней на всю ширину карточки. Окна — чипы по дням,
   переносятся строками; на 390 px ничего не выходит за край. */
.lw-book-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 8px; }
.lw-book-button {
  padding: 7px 12px; border-radius: var(--rp-r-pill, 999px);
  border: 1px solid var(--rp-blue); background-color: var(--rp-panel);
  color: var(--rp-blue); font: inherit; font-size: 13px; font-weight: 600; cursor: pointer;
}
.lw-book-button:hover, .lw-book-button.is-open { background-color: var(--rp-blue-soft, rgba(59, 130, 246, 0.12)); }
.lw-book-panel {
  display: grid; gap: 10px; margin-top: 10px; padding: 12px;
  border: 1px solid var(--rp-line); border-radius: 12px;
  background-color: var(--rp-panel-2, var(--rp-panel)); color: var(--rp-ink);
  min-width: 0; max-width: 100%; box-sizing: border-box; overflow-wrap: anywhere;
}
.lw-book-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.lw-book-head strong { font-size: 14px; }
.lw-book-x { border: 0; background: transparent; color: var(--rp-ink-3); font-size: 20px; line-height: 1; cursor: pointer; padding: 2px 6px; }
.lw-book-source, .lw-book-note { margin: 0; color: var(--rp-muted, #9aa7bd); font-size: 12px; line-height: 1.45; }
.lw-book-empty { margin: 0; font-size: 13px; line-height: 1.5; }
.lw-book-empty.is-bad, .lw-book-note.is-bad { color: var(--rp-red, #e5484d); }
.lw-book-tabs { display: flex; gap: 4px; flex-wrap: wrap; }
.lw-book-tab {
  padding: 6px 11px; border-radius: 8px; border: 1px solid var(--rp-line);
  background-color: var(--rp-panel); color: var(--rp-ink-3); font: inherit; font-size: 12.5px; cursor: pointer;
}
.lw-book-tab.is-on { border-color: var(--rp-blue); color: var(--rp-blue); font-weight: 600; }
.lw-book-days { display: grid; gap: 8px; max-height: 320px; overflow-y: auto; }
.lw-book-day { display: grid; gap: 5px; }
.lw-book-day-name { font-size: 12px; font-weight: 600; color: var(--rp-ink-3); }
.lw-book-times { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; min-width: 0; }
.lw-book-near { font-size: 12px; color: var(--rp-ink-3); }
.lw-book-chip {
  padding: 5px 10px; border-radius: var(--rp-r-pill, 999px);
  border: 1px solid var(--rp-line); background-color: var(--rp-panel);
  color: var(--rp-ink); font: inherit; font-size: 12.5px; line-height: 1.3; cursor: pointer;
  max-width: 100%; white-space: normal; text-align: start;
}
.lw-book-chip:hover { border-color: var(--rp-blue); }
.lw-book-chip.is-on { border-color: var(--rp-blue); background-color: var(--rp-blue); color: #fff; font-weight: 600; }
.lw-book-length { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; font-size: 12px; color: var(--rp-ink-3); }
.lw-book-fields { display: flex; gap: 10px; flex-wrap: wrap; }
.lw-book-field { display: grid; gap: 4px; font-size: 12px; color: var(--rp-ink-3); min-width: 0; }
.lw-book-wide { width: 100%; }
.lw-book-field input, .lw-book-field textarea {
  width: 100%; box-sizing: border-box; padding: 8px 10px;
  border: 1px solid var(--rp-line); border-radius: 9px;
  background-color: var(--rp-panel); color: var(--rp-ink); font: inherit; font-size: 13px;
}
/* Специфичнее общего `.workspace textarea { min-height: 132px }`: заметка к
   встрече — строка-две, а не письмо. */
.lw-book-panel textarea.lw-book-notes { resize: vertical; min-height: 58px; line-height: 1.45; }
.lw-book-check { margin: 0; font-size: 12.5px; line-height: 1.45; display: grid; gap: 6px; }
.lw-book-check p { margin: 0; }
.lw-book-check.is-ok { color: var(--rp-green, #30a46c); }
.lw-book-check.is-bad { color: var(--rp-red, #e5484d); }
.lw-book-check.is-warn { color: var(--rp-amber, #d9a400); }
.lw-book-invite { display: flex; gap: 8px; align-items: flex-start; font-size: 13px; cursor: pointer; }
.lw-book-invite input { margin-top: 2px; }
.lw-book-summary { margin: 0; font-size: 13.5px; font-weight: 600; }
.lw-book-error {
  display: grid; gap: 6px; padding: 8px 10px; border-radius: 9px;
  border: 1px solid var(--rp-red, #e5484d); color: var(--rp-ink); font-size: 13px;
}
.lw-book-error p { margin: 0; }
.lw-book-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.lw-book-result { display: grid; gap: 6px; }
.lw-book-done { margin: 0; font-size: 14px; font-weight: 600; color: var(--rp-green, #30a46c); }
.lw-book-when { margin: 0; font-size: 13.5px; font-weight: 600; }
.lw-book-meet { margin: 0; font-size: 13px; }
.lw-book-meet-link, .lw-book-open { color: var(--rp-blue); word-break: break-all; }
.lw-book-open { font-size: 13px; font-weight: 600; }
.lw-mail-gmail { font-size: 12px; color: var(--rp-ink-3); text-decoration: underline; }
.lw-mail-gmail:hover { color: var(--rp-ink); }
.lw-mail-composer { display: grid; gap: 8px; margin-top: 10px; }
.lw-mail-field,
.lw-mail-body {
  width: 100%; padding: 9px 11px;
  border: 1px solid var(--rp-line); border-radius: 9px;
  background-color: var(--rp-panel); color: var(--rp-ink);
  font: inherit; font-size: 13px;
}
.lw-mail-body { min-height: 190px; resize: vertical; line-height: 1.55; }
.lw-mail-note { margin: 0; color: var(--rp-muted, #9aa7bd); font-size: 11.5px; line-height: 1.45; }
.lw-mail-actions { display: flex; gap: 8px; flex-wrap: wrap; }
/* AI, ШАБЛОНЫ И МАТЕРИАЛЫ В ПИСЬМЕ (23 сентября 2026). Та же плотность, что у
   инструментов под строкой чата: маленькие кнопки в одну-две строки, главная —
   «Сгенерировать письмо» — выделена цветом. */
.lw-mail-ai,
.lw-mail-extras { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }
.lw-mail-ai-btn,
.lw-mail-quick {
  padding: 5px 10px; border-radius: var(--rp-r-pill, 999px);
  border: 1px solid var(--rp-line); background-color: var(--rp-panel);
  color: var(--rp-ink); font: inherit; font-size: 12px; line-height: 1.3; cursor: pointer;
}
.lw-mail-ai-btn:hover:not([disabled]),
.lw-mail-quick:hover:not([disabled]) { border-color: var(--rp-blue); }
.lw-mail-ai-btn[disabled],
.lw-mail-quick[disabled] { opacity: 0.45; cursor: not-allowed; }
.lw-mail-ai-btn.is-main { border-color: var(--rp-blue); color: var(--rp-blue); font-weight: 600; }
.lw-mail-ai-btn.is-open { border-color: var(--rp-blue); background-color: var(--rp-blue-soft, rgba(59, 130, 246, 0.12)); }
.lw-mail-ai-btn.is-undo { border-style: dashed; color: var(--rp-ink-3); }
.lw-mail-quick { font-size: 12px; }
.lw-mail-panel {
  display: grid; gap: 6px; padding: 8px; border-radius: 9px;
  border: 1px solid var(--rp-line); background-color: var(--rp-panel-2, var(--rp-panel));
}
.lw-mail-pick { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; max-height: 240px; overflow-y: auto; }
.lw-mail-pick button {
  width: 100%; display: grid; gap: 2px; text-align: start; padding: 6px 8px;
  border: 1px solid transparent; border-radius: 7px; background: none;
  color: var(--rp-ink); font: inherit; font-size: 12.5px; cursor: pointer;
}
.lw-mail-pick button:hover { border-color: var(--rp-line); background-color: var(--rp-panel); }
.lw-mail-pick strong { font-weight: 600; }
.lw-mail-pick span { color: var(--rp-ink-3); font-size: 11.5px; overflow-wrap: anywhere; }
/* «Всё уже в карточке» — утвердительно, а не серым отказом. */
.lw-enrich-note.is-ok { color: var(--rp-green, #16a34a); }
/* ОТВЕТ СОСТАВИТЕЛЯ ВИДНО, А НЕ УГАДЫВАЕТСЯ. Двенадцатый кегль приглушённым
   серым под кнопками владелец 20 сентября не увидел вовсе и решил, что кнопка
   мёртвая. Удача — обычной строкой, отказ — своим цветом и с рамкой: человек,
   нажавший «Отправить», обязан увидеть ответ, не приглядываясь. */
.lw-mail-said {
  margin: 0; color: var(--rp-ink, #e6ecf5); font-size: 13px; line-height: 1.45;
  padding: 8px 10px; border-radius: 9px;
  border: 1px solid var(--rp-line); background-color: var(--rp-panel);
}
.lw-mail-said.is-err {
  color: var(--rp-red, #ef4444);
  border-color: var(--rp-red, #ef4444);
  background-color: rgba(239, 68, 68, 0.10);
}

.ops-routes { display: grid; gap: 12px; margin-top: 4px; }
.ops-routes h2 { margin: 0; font-size: 16px; }
.ops-steps { display: grid; gap: 8px; }
.ops-step {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 8px 10px; border: 1px solid var(--rp-line); border-radius: 10px;
  background: rgb(var(--ch-lift, 255 255 255) / 0.02);
}
.ops-step-no {
  flex: none; inline-size: 22px; block-size: 22px; border-radius: 50%;
  display: grid; place-items: center;
  background: rgb(var(--ch-lift, 255 255 255) / 0.06);
  color: var(--rp-muted, #9aa7bd); font-size: 11.5px; font-weight: 700;
}
.ops-step-kind, .ops-step-mode, .ops-step-title {
  padding: 8px 10px; border: 1px solid var(--rp-line); border-radius: 9px;
  background-color: var(--rp-panel); color: var(--rp-ink);
  font: inherit; font-size: 12.5px;
}
.ops-step-title { flex: 1 1 200px; min-inline-size: 140px; }
.ops-step .ghost-button { margin-inline-start: auto; }
.ops-step-switch {
  display: flex; align-items: center; gap: 8px;
  color: var(--rp-ink-2, #c3ccda); font-size: 13px;
}

/* ── Оповещения команды (Настройки → Команда) и бот уведомлений (10 сентября) ── */
.tn-h { margin: 18px 0 8px; font-size: 14px; font-weight: 600; color: var(--rp-ink-1, #e6ebf3); }
.tn-list { display: flex; flex-direction: column; gap: 8px; }
.tn-row {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 10px 12px; border: 1px solid var(--rp-line, rgba(255,255,255,0.08)); border-radius: 10px;
}
.tn-who { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.tn-state { font-size: 12.5px; color: var(--rp-ink-3, #8a94a6); }
.tn-state.is-on { color: var(--rp-green, #3ecf8e); }
.tn-link {
  margin: 2px 0 6px; padding: 12px 14px; border-radius: 10px;
  border: 1px dashed var(--rp-blue, #4f8cff); background: rgba(79, 140, 255, 0.06);
}
.tn-steps { margin: 0 0 10px; padding-inline-start: 20px; font-size: 13px; line-height: 1.55; color: var(--rp-ink-2, #c3ccda); }
.tn-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }
.tn-actions a { text-decoration: none; }
.tn-url { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; word-break: break-all; color: var(--rp-ink-3, #8a94a6); }
.tn-err { color: var(--rp-amber, #f5a524); }
.team-bot-form { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-top: 8px; }
.team-bot-form input { flex: 1 1 280px; min-width: 0; }

/* ── Группы сотрудников (Команда, 10 сентября) ── */
.tg-list { display: flex; flex-direction: column; gap: 10px; margin-top: 10px; }
.tg-card { padding: 12px 14px; border: 1px solid var(--rp-line, rgba(255,255,255,0.08)); border-radius: 12px; }
.tg-card.is-open { border-color: var(--rp-blue, #4f8cff); }
.tg-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.tg-title { font-weight: 600; font-size: 14.5px; }
.tg-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.tg-chip {
  font-size: 12px; padding: 2px 8px; border-radius: 999px;
  border: 1px solid var(--rp-line, rgba(255,255,255,0.1)); color: var(--rp-ink-2, #c3ccda);
}
.tg-chip.is-on { border-color: rgba(62, 207, 142, 0.5); color: var(--rp-green, #3ecf8e); }
.tg-chip.is-off { color: var(--rp-ink-3, #8a94a6); }
.tg-line { font-size: 12.5px; color: var(--rp-ink-3, #8a94a6); margin-top: 4px; }
.tg-editor { display: flex; flex-direction: column; gap: 14px; margin-top: 12px; }
.tg-field { display: flex; flex-direction: column; gap: 6px; }
.tg-label { font-size: 13px; font-weight: 600; color: var(--rp-ink-1, #e6ebf3); }
.tg-hint { font-size: 12.5px; color: var(--rp-ink-3, #8a94a6); }
.tg-field input[type="text"], .tg-field select {
  padding: 8px 10px; border: 1px solid var(--rp-line); border-radius: 9px;
  background-color: var(--rp-panel); color: var(--rp-ink); font: inherit; font-size: 13px; max-inline-size: 420px;
}
.tg-checks { display: flex; flex-wrap: wrap; gap: 6px 14px; }
.tg-check { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; color: var(--rp-ink-2, #c3ccda); }
.tg-pipe { font-size: 12px; color: var(--rp-ink-3, #8a94a6); inline-size: 100%; margin-top: 4px; }
.tg-days { display: flex; flex-wrap: wrap; gap: 6px; }
.tg-days button {
  min-inline-size: 40px; padding: 5px 8px; border-radius: 8px; font: inherit; font-size: 12.5px; cursor: pointer;
  border: 1px solid var(--rp-line, rgba(255,255,255,0.1)); background: transparent; color: var(--rp-ink-3, #8a94a6);
}
.tg-days button.on { border-color: var(--rp-blue, #4f8cff); color: var(--rp-ink-1, #e6ebf3); background: rgba(79, 140, 255, 0.12); }
.tg-hours { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 13px; }
.tg-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.tg-danger { margin-inline-start: auto; color: var(--rp-amber, #f5a524); }

/* ── Условия группы, запасной путь оповещений, повторная сделка (26 сентября, план п. 10A) ── */
.tg-criteria { display: flex; flex-direction: column; gap: 10px; margin-top: 4px; }
.tg-criterion { display: flex; flex-direction: column; gap: 4px; min-inline-size: 0; }
.tg-criterion input[type="text"] { inline-size: 100%; box-sizing: border-box; }
.tn-state.tn-fallback { font-size: 12px; overflow-wrap: anywhere; }
.set-repeat-deal {
  display: flex; flex-direction: column; gap: 6px; margin-top: 10px; padding: 10px 12px;
  border: 1px solid var(--rp-line, rgba(255,255,255,0.08)); border-radius: 10px;
}
.set-repeat-deal .set-auto-text { font-size: 13.5px; font-weight: 600; }
.set-repeat-deal .set-repeat-line { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; font-size: 13px; }
.set-repeat-deal .set-repeat-days { inline-size: 84px; }
.set-repeat-deal .set-auto-hint { font-size: 12px; }

/* ── Структура компании (Операции, 10 сентября) — схема как в Битрикс24 ── */
.ops-tabs { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 12px; }
.ops-tab {
  padding: 7px 14px; border-radius: 999px; font: inherit; font-size: 13px; cursor: pointer;
  border: 1px solid var(--rp-line, rgba(255,255,255,0.1)); background: transparent; color: var(--rp-ink-2, #c3ccda);
}
.ops-tab.is-active { background: rgba(79, 140, 255, 0.16); border-color: var(--rp-blue, #4f8cff); color: var(--rp-ink-1, #e6ebf3); }
.ops-tab.is-soon { cursor: default; opacity: .55; }
.org-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-bottom: 12px; }
.org-title { display: flex; flex-direction: column; gap: 2px; margin-inline-end: auto; min-width: 220px; }
.org-title strong { font-size: 16px; }
.org-seg { display: inline-flex; border: 1px solid var(--rp-line, rgba(255,255,255,0.1)); border-radius: 10px; overflow: hidden; }
.org-seg button { padding: 7px 12px; font: inherit; font-size: 13px; border: 0; background: transparent; color: var(--rp-ink-3, #8a94a6); cursor: pointer; }
.org-seg button.is-on { background: rgba(79, 140, 255, 0.18); color: var(--rp-ink-1, #e6ebf3); }
.org-search {
  min-width: 200px; flex: 0 1 260px; padding: 8px 10px; border-radius: 9px; font: inherit; font-size: 13px;
  border: 1px solid var(--rp-line); background-color: var(--rp-panel); color: var(--rp-ink);
}
.org-zoom { display: inline-flex; gap: 4px; }
.org-zoom button {
  min-width: 34px; height: 32px; padding: 0 9px; border-radius: 8px; font: inherit; font-size: 13px; cursor: pointer;
  border: 1px solid var(--rp-line, rgba(255,255,255,0.1)); background: transparent; color: var(--rp-ink-2, #c3ccda);
}
.org-empty {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-bottom: 10px; padding: 12px 14px;
  border: 1px dashed var(--rp-blue, #4f8cff); border-radius: 12px; background: rgba(79, 140, 255, 0.06);
}
.org-body { display: flex; gap: 12px; align-items: stretch; }
.org-canvas {
  position: relative; flex: 1 1 auto; min-width: 0; height: min(68vh, 680px); overflow: hidden; border-radius: 14px; cursor: grab;
  border: 1px solid var(--rp-line, rgba(255,255,255,0.08)); touch-action: none; color: rgba(160, 175, 200, 0.55);
  background-color: var(--rp-panel, #0f1626);
  background-image: radial-gradient(rgba(255,255,255,0.06) 1px, transparent 1px); background-size: 22px 22px;
}
.org-canvas.is-panning { cursor: grabbing; }
.org-svg { width: 100%; height: 100%; display: block; }
.org-edge { fill: none; stroke: currentColor; stroke-width: 1.6; }
.org-node {
  box-sizing: border-box; width: 100%; height: 100%; overflow: hidden; cursor: pointer; user-select: none;
  display: flex; flex-direction: column; gap: 6px; padding: 0 12px 10px; border-radius: 12px;
  background: var(--rp-surface, #151e31); border: 1px solid var(--rp-line, rgba(255,255,255,0.1));
  color: var(--rp-ink-1, #e6ebf3); font-size: 12.5px; box-shadow: 0 6px 18px rgba(0,0,0,0.25);
  transition: border-color .15s ease, box-shadow .15s ease, opacity .15s ease;
}
.org-node:hover { border-color: rgba(79, 140, 255, 0.6); }
.org-node.is-selected { border-color: var(--rp-blue, #4f8cff); box-shadow: 0 0 0 2px rgba(79, 140, 255, 0.35); }
.org-node.is-match { border-color: #f5a524; box-shadow: 0 0 0 2px rgba(245, 165, 36, 0.35); }
.org-node.is-dim { opacity: .35; }
.org-node.is-drop { border-color: #3ecf8e; box-shadow: 0 0 0 3px rgba(62, 207, 142, 0.4); }
.org-node.is-dragging { opacity: .45; }
.org-node-top { height: 5px; margin: 0 -12px 2px; }
/* Содержимое не сжимается: иначе flex сплющивал название отдела до 8px. */
.org-node > * { flex-shrink: 0; }
.org-node-name { font-weight: 700; font-size: 14px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.org-node-meta { color: var(--rp-ink-3, #8a94a6); font-size: 11.5px; }
.org-person { display: flex; align-items: center; gap: 8px; min-width: 0; }
.org-person-txt { display: flex; flex-direction: column; min-width: 0; }
.org-person-txt b { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.org-person-txt small { color: var(--rp-ink-3, #8a94a6); font-size: 11px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.org-av {
  flex: 0 0 auto; width: 30px; height: 30px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center;
  color: #fff; font-size: 11px; font-weight: 700; letter-spacing: .02em;
}
.org-av.sm { width: 22px; height: 22px; font-size: 9.5px; margin-inline-end: -5px; border: 2px solid var(--rp-surface, #151e31); }
.org-faces { display: flex; align-items: center; }
.org-more { margin-inline-start: 10px; font-size: 11px; color: var(--rp-ink-3, #8a94a6); }
.org-ghost {
  position: absolute; z-index: 5; pointer-events: none; padding: 6px 10px; border-radius: 8px; font-size: 12.5px;
  background: var(--rp-blue, #4f8cff); color: #fff; box-shadow: 0 6px 18px rgba(0,0,0,0.35);
}
.org-side {
  position: relative; flex: 0 0 320px; max-height: min(68vh, 680px); overflow-y: auto; padding: 14px 14px 16px; border-radius: 14px;
  border: 1px solid var(--rp-line, rgba(255,255,255,0.08)); display: flex; flex-direction: column; gap: 10px;
}
.org-side h4 { margin: 0; padding-inline-end: 28px; font-size: 15px; }
.org-side h5 { margin: 6px 0 0; font-size: 13px; color: var(--rp-ink-2, #c3ccda); }
.org-close { position: absolute; top: 8px; inset-inline-end: 8px; width: 28px; height: 28px; border-radius: 8px; border: 0; background: transparent; color: var(--rp-ink-3, #8a94a6); font-size: 18px; cursor: pointer; }
.org-field { display: flex; flex-direction: column; gap: 4px; font-size: 12.5px; color: var(--rp-ink-3, #8a94a6); }
.org-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.org-danger { color: var(--rp-amber, #f5a524); }
.org-list { display: flex; flex-direction: column; gap: 6px; }
.org-list-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 6px 8px; border-radius: 9px; border: 1px solid var(--rp-line, rgba(255,255,255,0.06)); }
.org-hint { margin-top: 8px; }
/* «Не распределены» — люди платформы без отдела (10 сентября, вечер). */
.org-ghost.is-fixed { position: fixed; z-index: 1000; }
.org-tray { margin-top: 12px; padding: 12px 14px; border-radius: 14px; border: 1px dashed var(--rp-line, rgba(255,255,255,0.14)); display: flex; flex-direction: column; gap: 10px; }
.org-tray-head { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; }
.org-tray-head .cs-note { flex: 1 1 240px; }
.org-tray-list { display: flex; flex-wrap: wrap; gap: 8px; }
.org-tray-chip { display: inline-flex; padding: 6px 10px; border-radius: 10px; border: 1px solid var(--rp-line, rgba(255,255,255,0.1)); background: transparent; color: inherit; font: inherit; cursor: grab; touch-action: none; max-width: 260px; }
.org-tray-chip:hover { border-color: var(--rp-blue, #4f8cff); }
@media (max-width: 900px) {
  .org-body { flex-direction: column; }
  .org-side { flex: 0 0 auto; max-height: none; }
  .org-canvas { height: 60vh; }
}

/* ── Зарплаты (Операции, 10 сентября) ── */
.pay-head { display: flex; flex-direction: column; gap: 2px; margin-bottom: 12px; }
.pay-head strong { font-size: 16px; }
.pay-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 10px; margin-bottom: 12px; }
.pay-kpi { display: flex; flex-direction: column; gap: 3px; padding: 12px 14px; border-radius: 12px; border: 1px solid var(--rp-line, rgba(255,255,255,0.08)); }
.pay-kpi-label { font-size: 12px; color: var(--rp-ink-3, #8a94a6); }
.pay-kpi-value { font-size: 18px; font-weight: 700; }
.pay-kpi-hint { font-size: 11.5px; color: var(--rp-ink-3, #8a94a6); }
.pay-tabs { margin-bottom: 12px; flex-wrap: wrap; }
.pay-section { display: flex; flex-direction: column; gap: 10px; }
.pay-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: flex-end; }
.pay-list { display: flex; flex-direction: column; gap: 8px; }
.pay-row { display: flex; align-items: center; gap: 12px; padding: 10px 12px; border-radius: 10px; border: 1px solid var(--rp-line, rgba(255,255,255,0.08)); }
.pay-row.is-off { opacity: .55; }
.pay-row-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.pay-row-money { display: flex; flex-direction: column; align-items: flex-end; gap: 2px; text-align: end; }
.pay-sub { font-size: 12px; color: var(--rp-ink-3, #8a94a6); }
.pay-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.pay-chip { font-size: 11.5px; padding: 2px 8px; border-radius: 999px; border: 1px solid var(--rp-line, rgba(255,255,255,0.1)); color: var(--rp-ink-2, #c3ccda); }
.pay-chip.is-on { border-color: rgba(62, 207, 142, 0.5); color: var(--rp-green, #3ecf8e); }
/* «Live» на СВЕТЛОЙ панели терялся: рамка rgba(...,0.5) на белом читается как
   выключенное состояние, а не как работающее (владелец, 14 сентября: «live на
   белой панели прозрачный, показателей не видно, зелёного цвета нет»).
   Заливка берётся из того же токена, что и текст, — цвет остаётся один, просто
   перестаёт растворяться в белом. Тёмная тема этого правила не замечает:
   подмешивание 12% к прозрачному на тёмном фоне и было её обычным видом. */
.pay-chip.is-on { background: color-mix(in srgb, var(--rp-green, #3ecf8e) 14%, transparent);
  border-color: color-mix(in srgb, var(--rp-green, #3ecf8e) 45%, transparent); }
.pay-chip.is-warn { background: color-mix(in srgb, var(--rp-amber, #f5a524) 12%, transparent); }
.pay-chip.is-warn { border-color: rgba(245, 165, 36, 0.5); color: var(--rp-amber, #f5a524); }
/* «Выключено» — тоже состояние, а не отсутствие состояния: до этого у is-off
   была только рамка (контраст плашки к панели 1.00:1). Тот же приём, что у
   is-on/is-warn выше, только нейтральным цветом. */
.pay-chip.is-off { color: var(--rp-ink-3, #8a94a6);
  background: color-mix(in srgb, var(--rp-ink-3, #8a94a6) 10%, transparent); }
.pay-form { display: flex; flex-direction: column; gap: 10px; padding: 14px; border-radius: 12px; border: 1px solid var(--rp-blue, #4f8cff); background: rgba(79, 140, 255, 0.05); }
.pay-form h4 { margin: 0; font-size: 15px; }
.pay-form h5 { margin: 6px 0 0; font-size: 13px; color: var(--rp-ink-2, #c3ccda); }
.pay-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 10px 14px; }
.pay-field { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.pay-field-label { font-size: 12.5px; font-weight: 600; color: var(--rp-ink-2, #c3ccda); }
.pay-field-hint { font-size: 11.5px; color: var(--rp-ink-3, #8a94a6); }
.pay-mini-list { display: flex; flex-direction: column; gap: 4px; font-size: 12.5px; color: var(--rp-ink-2, #c3ccda); }
.pay-progress { height: 6px; border-radius: 999px; background: rgba(255,255,255,0.08); overflow: hidden; max-width: 420px; }
.pay-progress span { display: block; height: 100%; background: var(--rp-blue, #4f8cff); }
.pay-progress span.is-done { background: var(--rp-green, #3ecf8e); }
.pay-danger { color: var(--rp-amber, #f5a524); }
.pay-table-wrap { overflow-x: auto; border: 1px solid var(--rp-line, rgba(255,255,255,0.08)); border-radius: 12px; }
.pay-table { width: 100%; border-collapse: collapse; font-size: 12.5px; min-width: 980px; }
.pay-table th, .pay-table td { padding: 8px 10px; text-align: start; border-bottom: 1px solid var(--rp-line, rgba(255,255,255,0.06)); white-space: nowrap; }
.pay-table th { font-weight: 600; color: var(--rp-ink-3, #8a94a6); }
.pay-cell { width: 96px; padding: 5px 7px; }
.pay-strong { font-weight: 700; }
.pay-honest { margin-top: 12px; }
/* Кадровые письма и документы (10 сентября, вечер). */
.pay-subform { display: flex; flex-direction: column; gap: 8px; padding-top: 10px; border-top: 1px dashed var(--rp-line, rgba(255,255,255,0.12)); }
.pay-subform h5 { margin: 0; font-size: 13px; color: var(--rp-ink-2, #c3ccda); }
.pay-doc { border-color: var(--rp-violet, #8b5cf6); background: rgba(139, 92, 246, 0.06); }
.pay-doc-subject { font-size: 13px; font-weight: 600; }
.pay-doc-frame { width: 100%; height: 560px; border: 1px solid var(--rp-line, rgba(255,255,255,0.1)); border-radius: 10px; background: transparent; }
.pay-textarea { width: 100%; min-height: 220px; resize: vertical; font-family: ui-monospace, "SFMono-Regular", Consolas, monospace; font-size: 12.5px; line-height: 1.5; }
.pay-grid-1 { grid-template-columns: 1fr; }
/* ПОЛЯ ОДНОГО РЯДА — НА ОДНОЙ ЛИНИИ (15 сентября 2026). В настройках зарплаты
   подпись «Взносы работодателя, % от начислений» занимала две строки, и её
   поле стояло ниже соседей — «средняя плашка ниже из-за текста». Подпись, поле
   и подсказка каждого поля ложатся в общие строки сетки (subgrid): высота
   подписи в ряду одна, поля выровнены. */
@supports (grid-template-rows: subgrid) {
  .pay-grid-aligned > .pay-field { display: grid; grid-row: span 3; grid-template-rows: subgrid; row-gap: 4px; align-content: start; }
  .pay-grid-aligned > .pay-field > .pay-field-label { align-self: end; }
  .pay-grid-aligned > .pay-field > input[type="checkbox"] { justify-self: start; align-self: center; }
}
.pay-field-chips { align-items: center; }
.pay-chip-btn { cursor: pointer; background: transparent; font: inherit; font-size: 11.5px; }
.pay-chip-btn:hover { border-color: var(--rp-blue, #4f8cff); color: var(--rp-blue, #4f8cff); }
.pay-suggest { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; padding: 12px 14px; border-radius: 12px; border: 1px solid rgba(62, 207, 142, 0.45); background: rgba(62, 207, 142, 0.07); }
.pay-suggest > span { flex: 1 1 260px; font-size: 13.5px; }
/* «Прибыль»: выручка против ФОТ и расходов по месяцам. */
.pay-kpi.is-pos .pay-kpi-value { color: var(--rp-green, #3ecf8e); }
.pay-kpi.is-neg .pay-kpi-value, .pnl-neg, .pnl-profit.is-neg { color: var(--rp-amber, #f5a524); }
.pnl-chart { display: grid; grid-template-columns: repeat(auto-fit, minmax(60px, 1fr)); gap: 10px; align-items: end; padding: 12px; border-radius: 12px; border: 1px solid var(--rp-line, rgba(255,255,255,0.08)); }
.pnl-col { display: flex; flex-direction: column; align-items: center; gap: 4px; min-width: 0; }
.pnl-bars { display: flex; align-items: flex-end; gap: 4px; height: 140px; width: 100%; justify-content: center; }
.pnl-bar { display: block; width: 14px; min-height: 2px; border-radius: 4px 4px 0 0; }
.pnl-bar.is-rev { background: var(--rp-blue, #4f8cff); }
.pnl-bar.is-cost { background: var(--rp-violet, #8b5cf6); opacity: .75; }
.pnl-label { font-size: 11.5px; color: var(--rp-ink-3, #8a94a6); }
.pnl-profit { font-size: 11.5px; font-weight: 600; white-space: nowrap; }
.pnl-legend.is-rev { border-color: var(--rp-blue, #4f8cff); }
.pnl-legend.is-cost { border-color: var(--rp-violet, #8b5cf6); }
.pnl-table { min-width: 720px; }

/* ── Обзор (Admin View): карточки вместо списков строк (10 сентября) ─────── */
.dash-card { display: flex; flex-direction: column; gap: 12px; }
.dash-card .dash-actions { margin-top: auto; display: flex; flex-wrap: wrap; gap: 8px; align-items: center; padding-top: 4px; }
.dash-big { font-size: 30px; font-weight: 800; line-height: 1.1; letter-spacing: -0.01em; }
.dash-big.is-pos { color: var(--rp-green, #22c55e); }
.dash-big.is-neg { color: var(--rp-amber, #f5a524); }
.dash-sub { font-size: 12.5px; color: var(--rp-ink-3, #8a94a6); }
.dash-int-head { display: flex; flex-direction: column; gap: 4px; }
.dash-meter { height: 6px; border-radius: 999px; background: rgba(127, 127, 127, 0.18); overflow: hidden; margin-top: 4px; }
.dash-meter i { display: block; height: 100%; border-radius: inherit; background: linear-gradient(90deg, var(--rp-blue, #4f8cff), var(--rp-green, #22c55e)); }
.dash-meter.is-low i { background: linear-gradient(90deg, var(--rp-amber, #f5a524), var(--rp-blue, #4f8cff)); }
.dash-int-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 6px; }
.dash-int-tile { display: flex; align-items: center; gap: 7px; min-width: 0; padding: 7px 9px; border-radius: 10px; border: 1px solid var(--rp-line, rgba(127,127,127,0.18)); font-size: 12.5px; }
.dash-int .dash-int-tile .dash-int-name { flex: 1 1 auto; min-width: 0; overflow: hidden !important; text-overflow: ellipsis; white-space: nowrap !important; font-weight: 600; }
/* !important — общий .control-card в styles.css держит white-space: normal !important для всех подписей карточек. */
.dash-int-state { flex: 0 0 auto; font-size: 11px; color: var(--rp-ink-3, #8a94a6); }
.dash-int-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--rp-ink-3, #8a94a6); flex: 0 0 auto; }
.dash-int-tile.is-ok { border-color: rgba(34, 197, 94, 0.35); }
.dash-int-tile.is-ok .dash-int-state { color: var(--rp-green, #22c55e); }
.dash-int-tile.is-wait { border-color: rgba(245, 165, 36, 0.4); }
.dash-int-tile.is-wait .dash-int-state { color: var(--rp-amber, #f5a524); }
.dash-int-tile.is-bad { border-color: rgba(239, 68, 68, 0.5); }
.dash-int-tile.is-bad .dash-int-state { color: #ef4444; }
.dash-int-tile.is-off { opacity: .75; }
.dash-list { display: flex; flex-direction: column; gap: 6px; }
.dash-list-row { display: flex; align-items: center; gap: 8px; padding: 8px 10px; border-radius: 10px; border: 1px solid var(--rp-line, rgba(127,127,127,0.16)); font-size: 13px; min-width: 0; }
.dash-card .dash-list .dash-list-row > span:not(.chan-mark):not(.dash-list-icon) { min-width: 0; overflow: hidden !important; text-overflow: ellipsis; white-space: nowrap !important; }
.dash-list-text { flex: 1 1 auto; }
.dash-list-icon { flex: 0 0 auto; }
.dash-stat { display: flex; flex-direction: column; gap: 3px; padding: 10px 12px; border-radius: 12px; border: 1px solid var(--rp-line, rgba(127,127,127,0.16)); }
.dash-stat-label { font-size: 12px; color: var(--rp-ink-3, #8a94a6); }
.dash-stat-value { font-size: 20px; font-weight: 800; }
.dash-heat { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
.dash-heat-cell { display: flex; flex-direction: column; gap: 2px; padding: 10px; border-radius: 12px; border: 1px solid var(--rp-line, rgba(127,127,127,0.16)); font-size: 12px; }
.dash-heat-cell strong { font-size: 22px; font-weight: 800; }
.dash-heat-cell.is-hot { border-color: rgba(239, 68, 68, 0.45); }
.dash-heat-cell.is-warm { border-color: rgba(245, 165, 36, 0.45); }
.dash-heat-cell.is-cold { border-color: rgba(79, 140, 255, 0.4); }
.runtime-breakdown-card.dash-hot.is-wide { grid-column: span 2; }
.dash-money-rows { display: flex; flex-direction: column; gap: 4px; }
.dash-money-row { display: flex; justify-content: space-between; gap: 8px; font-size: 13px; padding: 4px 0; border-bottom: 1px dashed var(--rp-line, rgba(127,127,127,0.16)); }
.dash-spark { display: flex; align-items: flex-end; gap: 4px; height: 44px; }
.dash-spark i { flex: 1 1 0; min-height: 3px; border-radius: 3px 3px 0 0; background: var(--rp-green, #22c55e); opacity: .8; }
.dash-spark i.is-neg { background: var(--rp-amber, #f5a524); }
@media (max-width: 1180px) { .runtime-breakdown-card.dash-hot.is-wide { grid-column: span 2; } }
@media (max-width: 720px) { .runtime-breakdown-card.dash-hot.is-wide { grid-column: auto; } }
.dash-count { flex: 0 0 auto; font-size: 11.5px; font-weight: 700; padding: 1px 7px; border-radius: 999px; background: rgba(79, 140, 255, 0.14); color: var(--rp-blue, #4f8cff); }
/* Зарплаты: пустой экран — три шага (11 сентября). */
.pay-start { display: flex; flex-direction: column; gap: 10px; padding: 16px 18px; border-radius: 14px; border: 1px dashed rgba(79, 140, 255, 0.45); background: rgba(79, 140, 255, 0.05); }
.pay-start-title { font-size: 15px; }
.pay-start-steps { margin: 0; padding: 0; list-style: none; counter-reset: paystep; display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 10px; }
.pay-start-steps li { counter-increment: paystep; display: flex; flex-direction: column; gap: 4px; padding: 12px 14px; padding-inline-start: 44px; position: relative; border-radius: 12px; border: 1px solid var(--rp-line, rgba(127,127,127,0.16)); font-size: 12.5px; color: var(--rp-ink-3, #8a94a6); }
.pay-start-steps li::before { content: counter(paystep); position: absolute; inset-inline-start: 12px; top: 12px; width: 22px; height: 22px; border-radius: 50%; display: grid; place-items: center; font-size: 12px; font-weight: 800; color: #fff; background: linear-gradient(135deg, var(--rp-blue, #4f8cff), var(--rp-violet, #8b5cf6)); }
.pay-start-steps li b { color: var(--rp-ink-1, inherit); font-size: 13.5px; }
/* ── Встречи — живой экран (11 сентября) ─────────────────────────────────── */
.meet-head { display: flex; flex-wrap: wrap; gap: 14px 20px; align-items: flex-start; justify-content: space-between; margin-bottom: 14px; }
.meet-title { display: flex; flex-direction: column; gap: 2px; min-width: 240px; flex: 1 1 320px; }
.meet-title strong { font-size: 16px; }
.meet-stats { display: grid; grid-template-columns: repeat(4, minmax(92px, 1fr)); gap: 8px; flex: 1 1 420px; }
.meet-stat { display: flex; flex-direction: column; gap: 2px; padding: 10px 12px; border-radius: 12px; border: 1px solid var(--rp-line, rgba(127,127,127,0.16)); }
.meet-stat strong { font-size: 22px; font-weight: 800; line-height: 1.1; }
.meet-stat span { font-size: 12px; color: var(--rp-ink-3, #8a94a6); }
.meet-stat.is-today { border-color: rgba(79, 140, 255, 0.5); background: rgba(79, 140, 255, 0.06); }
.meet-stat.is-past strong { color: var(--rp-ink-3, #8a94a6); }
.meet-tabs { margin-bottom: 12px; }
.meet-list { display: flex; flex-direction: column; gap: 8px; }
.meet-day { margin: 10px 0 2px; font-size: 12.5px; font-weight: 700; letter-spacing: .02em; color: var(--rp-ink-2, #c3ccda); }
.meet-item { display: grid; grid-template-columns: 96px minmax(0, 1fr) auto; gap: 14px; align-items: center; padding: 12px 14px; border-radius: 14px; border: 1px solid var(--rp-line, rgba(127,127,127,0.16)); }
.meet-item.is-now { border-color: rgba(34, 197, 94, 0.6); background: rgba(34, 197, 94, 0.07); }
.meet-item.is-soon { border-color: rgba(79, 140, 255, 0.5); }
.meet-item.is-past { opacity: .72; }
.meet-time { display: flex; flex-direction: column; gap: 2px; }
.meet-time strong { font-size: 22px; font-weight: 800; line-height: 1; }
.meet-rel { font-size: 11.5px; color: var(--rp-ink-3, #8a94a6); }
.meet-item.is-now .meet-rel { color: var(--rp-green, #22c55e); font-weight: 700; }
.meet-item.is-soon .meet-rel { color: var(--rp-blue, #4f8cff); font-weight: 700; }
.meet-main { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.meet-who { display: flex; align-items: center; gap: 8px; min-width: 0; }
.meet-who strong { font-size: 14.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.meet-sub { font-size: 12px; color: var(--rp-ink-3, #8a94a6); }
.meet-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.meet-actions { display: flex; flex-wrap: wrap; gap: 8px; justify-content: flex-end; }
.meet-join { text-decoration: none; }
.meet-empty { display: flex; flex-direction: column; gap: 8px; align-items: flex-start; padding: 22px; border-radius: 14px; border: 1px dashed var(--rp-line, rgba(127,127,127,0.24)); }
.meet-foot { margin-top: 12px; }
@media (max-width: 720px) {
  .meet-item { grid-template-columns: 72px minmax(0, 1fr); }
  .meet-actions { grid-column: 1 / -1; justify-content: flex-start; }
  .meet-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
/* Задачи: галочка выполнения прямо в списке (11 сентября). */
.tsk-check-col { width: 38px; }
.tsk-table .tsk-check { width: 22px; height: 22px; min-height: 0; }
.tsk-error { color: var(--rp-amber, #f5a524); font-size: 12.5px; margin: 4px 0 0; }
/* Центр действий: живые задачи (11 сентября). */
.ac15-task-chips { display: flex; flex-wrap: wrap; gap: 6px; margin: 8px 0; }
.ac15-task-chip { display: inline-flex; align-items: baseline; gap: 6px; padding: 5px 10px; border-radius: 999px; border: 1px solid var(--rp-line, rgba(127,127,127,0.2)); font-size: 12px; }
.ac15-task-chip b { font-size: 15px; font-weight: 800; }
.ac15-task-chip.is-bad { border-color: rgba(239, 68, 68, 0.5); }
.ac15-task-chip.is-bad b { color: #ef4444; }
.ac15-task-chip.is-warn { border-color: rgba(245, 165, 36, 0.5); }
.ac15-task-chip.is-warn b { color: var(--rp-amber, #f5a524); }
.ac15-task-list { margin: 4px 0 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 4px; font-size: 12.5px; }
.ac15-task-list li { padding: 6px 10px; border-radius: 8px; border: 1px solid var(--rp-line, rgba(127,127,127,0.14)); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ac15-task-list li.is-bad { border-color: rgba(239, 68, 68, 0.35); }
.ac15-task-list li em { font-style: normal; color: var(--rp-ink-3, #8a94a6); }
/* На телефоне задача читается целиком, а не «Уточнить у клиента удобн…»
   (24.09.2026): строка переносится, многоточие остаётся широким экранам. */
@media (max-width: 560px) {
  .ac15-task-list li { white-space: normal; }
}

/* ── CONTRACTS IN THE RAIL (2026-09-12): a page with a signature line ────── */
.nav-icon-contracts {
  --nav-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M14 3.5H7a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8.5z'/%3E%3Cpath d='M14 3.5v5h5'/%3E%3Cpath d='M8.5 12.5h7M8.5 16h3.5'/%3E%3C/svg%3E");
}

/* ── FINANCE (2026-09-12): one home for money — rail glyph, tabs, tiles, charts ── */
.nav-icon-finance {
  --nav-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 20h16'/%3E%3Cpath d='M7 16.5v-4M12 16.5V9M17 16.5V6'/%3E%3Cpath d='M5 10l5-4 4 2.5L19 4'/%3E%3C/svg%3E");
}
/* overflow-x:auto (from .group-subnav) makes the strip a scroll container, and
   a scroll container's automatic minimum size is zero: inside the .page-stack
   grid its row collapsed to 9.6px under 34px buttons, and the card below sat
   on top of the tabs. Measured on the first open. Visible + wrap instead. */
.fin-tabs { margin: 0; overflow: visible; flex-wrap: wrap; justify-self: start; }
.fin-top { justify-content: space-between; align-items: center; margin-bottom: 12px; }
.fin-sources { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 14px; }
.fin-source { display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px; border-radius: 999px; border: 1px solid var(--rp-line, rgba(127,127,127,0.18)); font-size: 12px; }
.fin-source-name { color: var(--rp-ink-2, #94a3b8); }
.fin-block { margin-bottom: 14px; }
.fin-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 6px; }
.fin-head h4, .fin-chart h4 { margin: 0; font-size: 14px; }
.fin-kpi .pay-kpi-value { font-size: 20px; font-variant-numeric: tabular-nums; }
.fin-kpi.is-off .pay-kpi-value { color: var(--rp-ink-3, #6b7a90); }
.fin-approx { color: var(--rp-ink-2, #94a3b8); font-variant-numeric: tabular-nums; }
.fin-charts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; margin-bottom: 14px; }
.fin-chart { display: flex; flex-direction: column; gap: 10px; padding: 14px; border-radius: 12px; border: 1px solid var(--rp-line, rgba(127,127,127,0.18)); background: var(--rp-panel-2, transparent); min-width: 0; }
.fin-chart:first-child { grid-column: 1 / -1; }
.fin-legend { display: flex; flex-wrap: wrap; gap: 12px; font-size: 12px; color: var(--rp-ink-2, #94a3b8); }
.fin-legend-item { display: inline-flex; align-items: center; gap: 6px; }
.fin-swatch { width: 10px; height: 10px; border-radius: 3px; display: inline-block; }
.fin-svg-wrap { width: 100%; overflow-x: auto; }
.fin-svg { width: 100%; min-width: 320px; height: auto; display: block; }
.fin-grid { stroke: var(--rp-line, rgba(127,127,127,0.2)); stroke-width: 1; }
.fin-axis { fill: var(--rp-ink-3, #6b7a90); font-size: 11px; font-variant-numeric: tabular-nums; }
.fin-row-label { fill: var(--rp-ink-2, #94a3b8); font-size: 12px; }
.fin-track { fill: var(--rp-line, rgba(127,127,127,0.12)); }
.fin-bar.fin-c-rev, .fin-swatch.fin-c-rev { fill: var(--rp-green, #4ade80); background: var(--rp-green, #4ade80); }
.fin-bar.fin-c-exp, .fin-swatch.fin-c-exp { fill: var(--rp-amber, #fbbf24); background: var(--rp-amber, #fbbf24); }
.fin-bar.fin-c-pay, .fin-swatch.fin-c-pay { fill: var(--rp-blue, #2f7bff); background: var(--rp-blue, #2f7bff); }
.fin-bar.fin-c-open, .fin-swatch.fin-c-open { fill: var(--rp-blue, #2f7bff); background: var(--rp-blue, #2f7bff); }
.fin-bar.fin-c-late, .fin-swatch.fin-c-late { fill: var(--rp-amber, #fbbf24); background: var(--rp-amber, #fbbf24); }
.fin-bar.fin-c-good { fill: var(--rp-green, #4ade80); }
.fin-bar.fin-c-muted { fill: var(--rp-ink-3, #6b7a90); }
.fin-bar.is-estimate { opacity: 0.45; }
.fin-status-block { display: flex; flex-direction: column; gap: 6px; }
.fin-actions { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.fin-action { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 10px 12px; border-radius: 10px; border: 1px solid var(--rp-line, rgba(127,127,127,0.18)); }
.fin-action.is-warn { border-color: rgba(245, 165, 36, 0.45); }
.fin-action.is-neg { border-color: rgba(239, 68, 68, 0.45); }
.fin-action-text { font-size: 13px; min-width: 0; }
/* «Вам должны» (26.09.2026): одна строка плиток — по плитке на валюту. На
   телефоне по две в ряд, чтобы «Куда смотреть» не уезжал на второй экран. */
.fin-owed-cards { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); margin-bottom: 8px; }
.fin-owed-source { margin: 2px 0 0; }
@media (max-width: 900px) {
  .fin-charts { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 720px) {
  .fin-action { flex-direction: column; align-items: flex-start; }
}
@media (max-width: 560px) {
  .fin-owed-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
  .fin-owed-cards .pay-kpi { padding: 10px; min-width: 0; }
  .fin-owed-cards .pay-kpi-value { font-size: 17px; overflow-wrap: anywhere; }
  /* «Договоры и счета»: три ежедневные плитки — в одну строку. */
  .ctr-daily { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
  .ctr-daily .pay-kpi { padding: 10px; min-width: 0; }
  .ctr-daily .pay-kpi-label, .ctr-daily .pay-kpi-hint { overflow-wrap: anywhere; }
}

/* «Мои агенты» (/agents/roster) — место под список держится с первой отрисовки.
   Заглушка «Загрузка агентов…» была в одну строку, потом приходили карточка
   живого агента и библиотека, и страница прыгала дважды (владелец, 13 сентября
   2026: «передёргивает экран 2 раза»). Резерв — высота карточки агента и формы
   создания; реальный список всё равно растёт вниз, но уже не толкает шапку. */
#ac-roster { min-height: 520px; }

/* «Ещё ▾» в полоске настроек (23 сентября 2026): редкие вкладки — «Филиалы»
   у пространства с одним филиалом — раскрываются в той же строке, а не
   выпадающим окном: у полоски overflow-x:auto, и всплывающий список был бы
   обрезан её краем. */
.group-subnav-more { display: flex; align-items: center; flex: none; }
.group-subnav-more > summary { list-style: none; display: inline-flex; align-items: center; }
.group-subnav-more > summary::-webkit-details-marker { display: none; }
.group-subnav-more-list { display: flex; align-items: center; gap: 2px; }

/* Карточка «доступно по запросу / только для партнёров» на вкладках настроек
   (23 сентября 2026) и строка «Вы · владелец» в оповещениях команды. */
.plat-lock { display: grid; gap: 10px; max-width: 640px; }
.plat-lock-list { margin: 0; padding-inline-start: 18px; color: var(--rp-ink-2); font-size: 13px; line-height: 1.55; }
.tn-you { display: inline-block; margin-inline-start: 8px; padding: 1px 8px; border-radius: 999px; font-size: 11.5px; font-weight: 600; background: rgb(var(--ch-lift) / 0.06); color: var(--rp-ink-2); }
/* Пространства в меню профиля (23 сентября 2026): все, где человек участник,
   галочка у открытого, переход одним нажатием. */
.profile-workspaces { display: grid; gap: 2px; padding: 8px 0; border-bottom: 1px solid var(--rp-line); }
.profile-workspaces-label { font-size: 11px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--rp-ink-3, var(--rp-ink-2)); padding: 0 10px 4px; }
.profile-ws { display: flex; align-items: center; gap: 8px; width: 100%; min-height: 34px; padding: 0 10px; border: 0; border-radius: 7px; background: none; color: var(--rp-ink); font: inherit; font-size: 13px; text-align: start; cursor: pointer; }
.profile-ws:hover:not([disabled]) { background: rgb(var(--ch-lift) / 0.06); }
.profile-ws.is-current { cursor: default; font-weight: 600; }
.profile-ws[disabled]:not(.is-current) { opacity: .6; cursor: progress; }
.profile-ws-check { width: 14px; flex: none; color: var(--rp-blue); font-weight: 700; }
.profile-ws-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.profile-ws-wait { font-size: 11.5px; color: var(--rp-ink-2); }
.tn-staff-only { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; margin: 6px 0 10px; }

/* ═══ «ОБЗОР» — P0 ПО АУДИТУ ЭКРАНОВ (24 сентября 2026) ═════════════════════
   artifacts/audit-2026-09-24/C_ux_audit.md, Top-15 №2–8. Только токены темы и
   логические свойства (арабский зеркалится сам). */

/* «Требует внимания сегодня» — одна полоса над всем «Обзором». Число слева,
   что это — справа; цвет кромки говорит, горит ли (красный), ждёт ли
   (янтарный) или спокойно (зелёный: настоящий ноль из ответившего источника). */
.ov-today {
  display: grid;
  gap: 8px;
  padding: 12px 14px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r);
  background: var(--rp-panel);
}
.ov-today-title {
  margin: 0;
  font-size: 11.5px;
  font-weight: 650;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--rp-ink-3);
}
.ov-today-note { margin: 0; font-size: 12px; color: var(--rp-ink-3); }
.ov-today-items {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 8px;
}
/* На планшете (24.09.2026, замер 768×1024): три карточки по 200 px, и в
   карточке «100 259 AED · выручка под риском» сумма забирала всё — подписи
   оставалось 37 px, «движения» вылезало за край карточки. На узком экране
   карточка не уже 240 px (на 768 — две в ряд, на телефоне — одна). */
@media (max-width: 980px) {
  .ov-today-items { grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr)); }
}
.ov-today-item {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  column-gap: 10px;
  row-gap: 2px;
  align-items: baseline;
  padding: 10px 12px;
  border: 1px solid var(--rp-line);
  border-inline-start-width: 3px;
  border-radius: var(--rp-r-sm);
  background: var(--rp-panel-2);
  color: inherit;
  text-decoration: none;
  transition: border-color 130ms ease, background 130ms ease;
}
.ov-today-item:hover { background: rgb(var(--ch-blue2) / 0.07); }
.ov-today-item:focus-visible { outline: 2px solid var(--sh-blue-2); outline-offset: 2px; }
.ov-today-item.tone-crit { border-inline-start-color: var(--rp-red); }
.ov-today-item.tone-warn { border-inline-start-color: var(--rp-amber); }
.ov-today-item.tone-good { border-inline-start-color: var(--rp-green); }
.ov-today-value {
  grid-row: span 2;
  font-size: 21px;
  font-weight: 700;
  line-height: 1.15;
  color: var(--rp-ink-max);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.ov-today-item.tone-good .ov-today-value { color: var(--rp-ink-2); }
.ov-today-label { font-size: 12.5px; font-weight: 600; color: var(--rp-ink); }
.ov-today-sub { grid-column: 2; font-size: 11.5px; color: var(--rp-ink-3); }

/* «Риски и внимание»: строки стали кнопками — подписи внутри кнопки идут
   блоками, как были абзацами; «Выручка под риском» несёт пять сделок. */
.rp-panel .rp-row-copy > .rp-row-title,
.rp-panel .rp-row-copy > .rp-row-sub { display: block; }
.rp-risk-deals { display: grid; gap: 3px; margin-top: 6px; }
.rp-risk-deal {
  display: flex;
  align-items: baseline;
  gap: 8px;
  min-width: 0;
  font-size: 11.5px;
  color: var(--rp-ink-2);
}
.rp-risk-deal-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rp-risk-deal-idle { flex: none; color: var(--rp-amber); font-variant-numeric: tabular-nums; }
.rp-risk-deal-value { flex: none; color: var(--rp-ink); font-variant-numeric: tabular-nums; }

/* Две ссылки в подвале карточки: список лидов под риском и все задачи. */
.rp-card-foots { display: flex; gap: 8px; }
.rp-card-foots > .rp-card-foot { flex: 1 1 0; min-width: 0; }
.rp-ov-row > .control-card > .rp-card-foots { margin-top: auto; }

/* «Что сделал AI»: Сегодня · 7 дн. · 30 дн. — тот же вид, что у периодов. */
.ai-workforce-window {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 2px;
  margin-top: 8px;
  padding: 3px;
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-r-sm);
  background: rgb(var(--ch-lift) / 0.015);
}
.ai-workforce-window button {
  min-height: 30px;
  padding: 0 12px;
  border: 1px solid transparent;
  border-radius: 6px;
  background: none;
  color: var(--rp-ink-2);
  font-size: 12.5px;
  cursor: pointer;
}
.ai-workforce-window button:hover { color: var(--rp-ink); }
.ai-workforce-window button.on {
  background: var(--rp-blue-soft);
  border-color: rgb(var(--ch-blue2) / 0.45);
  color: var(--rp-ink-max);
  font-weight: 600;
}
@media (max-width: 560px) {
  .ai-workforce-window button { min-height: 40px; }
}

/* «AI-совет» в рельсе: круглый стол на троих. */
.nav-icon-ai-board {
  --nav-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='5.2' r='2'/%3E%3Ccircle cx='4.8' cy='12.4' r='2'/%3E%3Ccircle cx='19.2' cy='12.4' r='2'/%3E%3Crect x='8' y='9.6' width='8' height='5.6' rx='2.4'/%3E%3Cpath d='M8.4 19.8c.7-1.6 2-2.5 3.6-2.5s2.9.9 3.6 2.5'/%3E%3C/svg%3E");
}
