/* Shared light foundations, using the V2 voice workspace palette. */
:root {
  color-scheme: light;
  font: 14px/1.45 -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  font-optical-sizing: auto;

  --font-body: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --font-display: var(--font-body);
  --font-mono: ui-monospace, Menlo, Consolas, monospace;
  --r-sm: 4px;
  --r-md: 6px;
  --r-lg: 8px;
  --sp-1: 4px;
  --sp-2: 8px;
  --sp-3: 12px;
  --sp-4: 16px;
  --sp-5: 24px;

  --bg: #f7f8fa;
  --card: #fff;
  --surface: var(--card);
  --field-bg: var(--card);
  --fg: #25292d;
  --text: var(--fg);
  --muted: #616871;
  --line: #dfe3e7;
  --border: var(--line);
  --border-soft: var(--line);
  --control-border: #bdc5cd;
  --accent: #176849;
  --accent-2: #145c40;
  --accent-ink: #fff;
  --blue: #175ba5;
  --link: var(--blue);
  --track: #eef1f4;
  --hover: #edf1f3;
  --pressed: #e1e6e9;
  --focus: #2675c7;

  --danger: #ab3039;
  --danger-bg: #fff1f1;
  --danger-border: #ecc5c8;
  --ok: var(--accent);
  --ok-bg: #e8f3ec;
  --warning: #765512;
  --warning-bg: #fbf2d9;
  --st-plan: var(--blue);
  --st-plan-bg: #edf3fb;
  --st-done: var(--accent);
  --st-done-bg: var(--ok-bg);
  --st-paid: var(--accent);
  --st-paid-bg: var(--ok-bg);
  --st-cancel: var(--muted);
  --st-cancel-bg: var(--track);
  --error-bg: var(--danger-bg);
  --error-fg: var(--danger);
  --success-bg: var(--ok-bg);
  --success-fg: var(--ok);

  /* Existing templates retain these aliases without decorative effects. */
  --card-grad: var(--card);
  --shadow-card: none;
  --shadow-btn: none;
  --glow: none;
  --nav-bg: var(--card);
  --scene-bg: var(--bg);
  --chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23616871' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");

  --crm-header-height: 56px;
  --crm-nav-width: 0px;
  --crm-bottom-height: 58px;
}

*, *::before, *::after { box-sizing: border-box; letter-spacing: 0; }
[hidden] { display: none !important; }
html, body { margin: 0; background: var(--bg); color: var(--fg); }
html { scroll-padding-top: calc(var(--crm-header-height) + 12px); }
body {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100dvh;
  font: 14px/1.45 var(--font-body);
  -webkit-font-smoothing: antialiased;
}
body.crm-shell {
  padding-top: var(--crm-header-height);
  padding-left: var(--crm-nav-width);
  padding-bottom: calc(var(--crm-bottom-height) + env(safe-area-inset-bottom, 0px));
}
main {
  width: 100%;
  min-width: 0;
  max-width: none;
  margin: 0;
  padding: 16px 20px 28px;
  flex: 1;
}
main:not(.wide):not(.call-workpage):not(.unified-operator):not(.voice-shell) {
  max-width: 960px;
  margin-inline: auto;
}
main.voice-shell { flex: 1; min-height: 0; margin: 0; padding: 0; max-width: none; }
body.voice-page { display: flex; flex-direction: column; height: 100dvh; overflow: hidden; }
a { color: var(--link); text-decoration: none; }
a:hover { text-decoration: underline; }
img { max-width: 100%; }
::selection { background: #dcece3; }
:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
button, input, select, textarea { font: inherit; }
button, select, input, textarea {
  min-width: 0;
  border: 1px solid var(--control-border);
  border-radius: var(--r-md);
  background: var(--card);
  color: inherit;
}
button { min-height: 34px; padding: 6px 10px; cursor: pointer; font-weight: 550; touch-action: manipulation; }
button:hover:not(:disabled) { background: var(--hover); }
button:active:not(:disabled) { background: var(--pressed); }
button:disabled { cursor: not-allowed; opacity: .48; }
input, select, textarea { padding: 7px 9px; }
textarea { resize: vertical; }
fieldset { min-width: 0; border: 1px solid var(--line); border-radius: var(--r-md); }
h1, .page-title { font: 600 20px/1.3 var(--font-body); margin: 0 0 16px; overflow-wrap: anywhere; }
h2, .section-title { font: 650 14px/1.4 var(--font-body); color: var(--fg); margin: 20px 0 10px; }
h3 { font: 650 13px/1.4 var(--font-body); }
.muted { color: var(--muted); }
.small { font-size: 12px; }
.amount, .mono { font-variant-numeric: tabular-nums; font-size: .95em; }
.mono { font-family: var(--font-mono); }
.amount { font-weight: 600; white-space: nowrap; }

.card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: 14px;
  margin-bottom: 12px;
}
a.card { color: inherit; display: block; }
a.card:hover { text-decoration: none; border-color: var(--control-border); }

/* полоса статуса слева у карточек выездов */
.card.status-plan { border-left: 3px solid var(--st-plan); }
.card.status-done { border-left: 3px solid var(--st-done); }
.card.status-paid { border-left: 3px solid var(--st-paid); }
.card.status-cancelled { border-left: 3px solid var(--st-cancel); opacity: 0.75; }

.card-head {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 6px;
}

.alert {
  border-radius: var(--r-md);
  padding: 12px 14px;
  margin-bottom: 12px;
  font-size: 0.95rem;
  border: 1px solid var(--border-soft);
}
.alert-error {
  background: var(--danger-bg);
  color: var(--danger);
  border-color: var(--danger-border);
}
.alert-ok {
  background: var(--ok-bg);
  color: var(--ok);
}

/* ---------- стат-карточки (дашборд/отчёты) ---------- */

.stat-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
  margin-bottom: 4px;
}

.stat { margin-bottom: 0; }

.stat .muted { font-size: 0.8rem; }

.stat-value {
  font-family: var(--font-display);
  font-size: 24px;
  font-weight: 700;
  line-height: 1.15;
  font-variant-numeric: tabular-nums;
  margin-top: 2px;
  white-space: nowrap; /* «1 262 720 ₽» — одной строкой, см. .amount */
}

.stat-sub { font-size: 0.8rem; margin-top: 2px; }

.kv-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px 12px;
  margin-top: 8px;
  font-size: 0.92rem;
}

/* ---------- кнопки ---------- */

.btn {
  min-height: 36px;
  font: 550 14px/1.4 var(--font-body);
  border: 1px solid var(--accent);
  border-radius: var(--r-md);
  background: var(--accent);
  color: var(--accent-ink);
  cursor: pointer;
  padding: 7px 12px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  max-width: 100%;
  overflow-wrap: anywhere;
  text-decoration: none;
  touch-action: manipulation;
}
.btn:hover:not(:disabled) { text-decoration: none; background: var(--accent-2); }
.btn:active:not(:disabled) { background: var(--accent-2); }
.btn-ghost { background: var(--card); color: var(--blue); border-color: var(--control-border); }
.btn-ghost:hover:not(:disabled), .btn-ghost:active:not(:disabled) { background: var(--hover); }
.btn-danger { background: var(--danger-bg); color: var(--danger); border-color: var(--danger-border); }
.btn-danger:hover:not(:disabled), .btn-danger:active:not(:disabled) { background: var(--danger-bg); border-color: var(--danger); }
.btn-block { width: 100%; }
.btn-icon { width: 36px; height: 36px; padding: 0; flex-shrink: 0; }

.icon { width: 18px; height: 18px; flex: 0 0 18px; vertical-align: middle; }
.icon-button {
  width: 36px;
  height: 36px;
  min-height: 36px;
  flex: 0 0 36px;
  display: inline-grid;
  place-items: center;
  padding: 0;
  border-color: transparent;
  background: transparent;
}
.text-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  color: var(--blue);
  border-color: transparent;
  background: transparent;
}
.primary { color: var(--accent-ink); background: var(--accent); border-color: var(--accent); }
.primary:hover:not(:disabled), .primary:active:not(:disabled) { background: var(--accent-2); }
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }

/* ---------- бейджи, чипы ---------- */

.badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border-radius: var(--r-md);
  padding: 2px 6px;
  font-size: 12px;
  font-weight: 500;
  background: var(--track);
  color: var(--fg);
  border: 1px solid transparent;
  overflow-wrap: anywhere;
}

.badge[data-tone="good"] { background: var(--ok-bg); color: var(--accent); }
.badge[data-tone="warn"] { background: var(--warning-bg); color: var(--warning); }
.badge[data-tone="bad"] { background: var(--danger-bg); color: var(--danger); }
.badge-plan { background: var(--st-plan-bg); color: var(--st-plan); }
.badge-done { background: var(--st-done-bg); color: var(--st-done); }
.badge-paid { background: var(--st-paid-bg); color: var(--st-paid); }
.badge-cancelled { background: var(--st-cancel-bg); color: var(--st-cancel); }
.badge-plan::before, .badge-done::before,
.badge-paid::before, .badge-cancelled::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
}

.badge-warn { background: var(--danger-bg); color: var(--danger); }
.badge-ok { background: var(--ok-bg); color: var(--ok); }

/* номер точки маршрута в списке «Сегодня» */
.route-num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: var(--r-md);
  flex-shrink: 0;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.95rem;
  background: var(--accent);
  color: var(--accent-ink);
}

.chips { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 12px; }
.chip {
  display: inline-flex;
  align-items: center;
  border-radius: var(--r-md);
  padding: 3px 10px;
  font-size: 0.78rem;
  background: var(--st-paid-bg);
  color: var(--st-paid);
  border: 1px solid var(--border-soft);
}

/* ---------- поля и формы ---------- */

label { font-size: 13px; color: var(--muted); }

.field {
  width: 100%;
  min-height: 36px;
  padding: 7px 9px;
  font-size: 1rem;
  font-family: var(--font-body);
  border: 1px solid var(--control-border);
  border-radius: var(--r-md);
  background: var(--field-bg);
  color: var(--fg);
  transition: border-color 0.12s ease;
}
.field:focus { border-color: var(--focus); outline: 2px solid var(--focus); outline-offset: 1px; }

textarea.field { padding: 10px 12px; min-height: 80px; resize: vertical; }

select.field {
  appearance: none;
  -webkit-appearance: none;
  background-image: var(--chevron);
  background-repeat: no-repeat;
  background-position: right 10px center;
  padding-right: 34px;
}

input[type="checkbox"], input[type="radio"] { accent-color: var(--accent-2); }

.form-col { display: flex; flex-direction: column; gap: 14px; }
.form-row label { display: block; margin-bottom: 5px; }

/* ---------- фильтры списков ---------- */

details summary { list-style: none; }
details summary::-webkit-details-marker { display: none; }

.filters summary {
  min-height: 44px;
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 600;
  font-size: 0.92rem;
  cursor: pointer;
  color: var(--muted);
}
.filters summary::after {
  content: "";
  width: 16px;
  height: 16px;
  background: var(--chevron) no-repeat center;
  transition: transform 0.15s ease;
}
.filters[open] > summary::after,
.filters details[open] > summary::after { transform: rotate(180deg); }

.filter-grid {
  display: grid;
  /* minmax(0,1fr): нативный date-input шире половины карточки и на 1fr
     раздувал колонки за край */
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
  margin-top: 6px;
}
.filter-grid .wide { grid-column: 1 / -1; }
.filter-grid input[type="date"] { padding: 0 8px; font-size: 0.95rem; }

.check {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 40px;
  font-size: 0.95rem;
  color: var(--fg);
}
.check input { width: 20px; height: 20px; }
/* вариант для подписей в 2 строки (исходы звонка): кнопка у первой строки,
   а не по вертикальному центру всего блока (находка UX-ревью) */
.check-start { align-items: flex-start; min-height: 36px; }
.check-start input { margin-top: 3px; flex-shrink: 0; }

.found-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  margin: 2px 0 10px;
}
.found { font-weight: 600; }

.pager {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-top: 14px;
}

/* ---------- прогресс-полосы (выручка) ---------- */

.meter {
  flex: 1;
  height: 8px;
  border-radius: var(--r-md);
  background: var(--track);
  overflow: hidden;
}
.meter i {
  display: block;
  height: 100%;
  border-radius: inherit;
  background: var(--accent);
}
.meter-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 8px;
}
.meter-row .m-label { width: 3em; flex-shrink: 0; }
.meter-row .m-val { min-width: 70px; text-align: right; flex-shrink: 0; }

/* ---------- таблицы (отчёты) ---------- */

.table-wrap { overflow-x: auto; }

.table { width: 100%; border-collapse: collapse; }
.table th {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 12px;
  color: var(--muted);
  text-align: left;
  padding: 6px 0;
  border-bottom: 1px solid var(--border-soft);
}
.table th.num, .table td.num { text-align: right; padding-left: 10px; }
.table td {
  padding: 8px 0;
  border-bottom: 1px solid var(--line);
  vertical-align: top;
}
/* зазор между соседними колонками — на 375px «Клиент» и «Город»
   слипались («нет телефонаПавловка», находка UX-ревью) */
.table td:not(:last-child), .table th:not(:last-child) { padding-right: 8px; }
.table tr:last-child td { border-bottom: none; }
.table td .meter { height: 5px; margin-top: 4px; }

/* Shared header and navigation. */
.topbar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 70;
  display: flex;
  align-items: center;
  gap: 16px;
  width: 100%;
  height: var(--crm-header-height);
  margin: 0;
  padding: 0 16px;
  background: var(--card);
  border-bottom: 1px solid var(--line);
}
.brand {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
  font-size: 16px;
  font-weight: 700;
  color: var(--fg);
  white-space: nowrap;
}
.brand:hover { text-decoration: none; }
.brand-accent { color: var(--accent); }
.brand img, .brand svg { width: 22px; height: 22px; flex: 0 0 22px; object-fit: contain; }
.topbar-sub { color: var(--muted); font-size: 12px; }
.crm-page-title { min-width: 0; border-left: 1px solid var(--line); padding-left: 16px; font-size: 14px; line-height: 1.25; font-weight: 600; margin: 0; overflow-wrap: anywhere; }
.crm-header-actions { display: flex; align-items: center; gap: 6px; min-width: 0; margin-left: auto; }
.crm-header-actions .connection { min-width: 0; font-size: 12px; color: var(--muted); overflow-wrap: normal; }
.crm-header-actions :is(.icon-button, .btn-icon) {
  display: inline-grid;
  place-items: center;
  width: 36px;
  height: 36px;
  min-height: 36px;
  flex: 0 0 36px;
  padding: 0;
}
.crm-header-actions :is(.icon-button, .btn-icon) svg { width: 18px; height: 18px; }

nav.bottom-nav {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 60;
  display: flex;
  height: calc(var(--crm-bottom-height) + env(safe-area-inset-bottom, 0px));
  background: var(--nav-bg);
  border-top: 1px solid var(--line);
  padding-bottom: env(safe-area-inset-bottom, 0px);
}
nav.bottom-nav > a, nav.bottom-nav .more > summary {
  flex: 1 1 0;
  min-width: 0;
  height: var(--crm-bottom-height);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  padding: 4px;
  color: var(--muted);
  text-decoration: none;
  cursor: pointer;
  font-size: 11px;
  font-weight: 500;
  line-height: 1.25;
}
nav.bottom-nav > a:hover, nav.bottom-nav .more > summary:hover { text-decoration: none; background: var(--hover); }
nav.bottom-nav svg { width: 20px; height: 20px; flex-shrink: 0; }
nav.bottom-nav > a.active, nav.bottom-nav .more > summary.active { color: var(--accent); background: var(--ok-bg); }
nav.bottom-nav .more { flex: 1 1 0; min-width: 0; }
nav.bottom-nav > a.nav-brand { display: none; }
.more-sheet {
  position: fixed;
  bottom: calc(var(--crm-bottom-height) + env(safe-area-inset-bottom, 0px) + 8px);
  right: 8px;
  width: min(280px, calc(100vw - 16px));
  max-height: calc(100dvh - var(--crm-header-height) - var(--crm-bottom-height) - env(safe-area-inset-bottom, 0px) - 16px);
  overflow-y: auto;
  overscroll-behavior: contain;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: 6px;
  display: flex;
  flex-direction: column;
}
.more-sheet a, .more-sheet button {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  padding: 8px 10px;
  border: 0;
  background: none;
  border-radius: var(--r-sm);
  color: var(--fg);
  font: 500 13px/1.35 var(--font-body);
  text-align: left;
  cursor: pointer;
  text-decoration: none;
  overflow-wrap: anywhere;
  width: 100%;
  flex-shrink: 0;
}
.more-sheet a:hover, .more-sheet button:hover { background: var(--hover); text-decoration: none; }
.more-sheet svg { width: 18px; height: 18px; color: var(--muted); flex-shrink: 0; }
.more-sheet a.active { color: var(--accent); background: var(--ok-bg); }
.more-sheet a.active svg { color: var(--accent); }
.more-sheet .sheet-sep { height: 1px; flex-shrink: 0; background: var(--line); margin: 6px 8px; }
.more-sheet form { margin: 0; display: flex; }

/* Login keeps the same authentication controls and passkey hooks. */
body.login-body { align-items: center; justify-content: center; padding: 24px 16px; }
.login-scene { width: 100%; max-width: 400px; }
.login-card { padding: 24px; margin: 0; }
.login-brand { display: flex; align-items: center; gap: 10px; font-size: 22px; font-weight: 700; }
.login-brand img { width: 28px; height: 28px; object-fit: contain; }
.login-tag { font-size: 13px; color: var(--muted); margin: 6px 0 24px; }

@media (min-width: 1024px) {
  :root { --crm-nav-width: 168px; --crm-bottom-height: 0px; }
  body.crm-shell { padding-bottom: 0; }
  main { padding: 20px 24px 32px; }
  nav.bottom-nav {
    top: var(--crm-header-height);
    bottom: 0;
    right: auto;
    width: var(--crm-nav-width);
    height: auto;
    flex-direction: column;
    gap: 2px;
    padding: 10px 6px;
    border-top: 0;
    border-right: 1px solid var(--line);
    overflow-y: auto;
    overscroll-behavior: contain;
  }
  nav.bottom-nav > a, nav.bottom-nav .more-sheet a, nav.bottom-nav .more-sheet button {
    flex: 0 0 auto;
    width: 100%;
    min-height: 36px;
    height: auto;
    padding: 8px;
    flex-direction: row;
    justify-content: flex-start;
    gap: 8px;
    border-radius: var(--r-sm);
    font-size: 13px;
    line-height: 1.3;
  }
  nav.bottom-nav svg { width: 18px; height: 18px; }
  nav.bottom-nav .more { flex: 0 0 auto; width: 100%; }
  nav.bottom-nav .more > summary { display: none; }
  /* Desktop exposes secondary routes even while details remains closed. */
  nav.bottom-nav .more::details-content { display: block; content-visibility: visible; }
  nav.bottom-nav .more > .more-sheet {
    display: flex !important;
    position: static;
    width: 100%;
    max-height: none;
    overflow: visible;
    padding: 0;
    border: 0;
    border-radius: 0;
  }
  nav.bottom-nav .more-sheet a:not(:has(svg)) { padding-left: 34px; }
  .stat-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .call-btn { width: fit-content; min-width: 200px; }
  .kv-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .filter-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .filter-grid .wide { grid-column: span 2; }
}
@media (max-width: 1023px) {
  main { padding: 12px 12px 24px; }
  .topbar { gap: 8px; padding: 0 10px; }
  .topbar-sub { display: none; }
  .brand { font-size: 14px; gap: 6px; }
  .brand img, .brand svg { width: 20px; height: 20px; flex-basis: 20px; }
  .crm-page-title { padding-left: 8px; }
  .crm-header-actions { gap: 2px; }
  .crm-header-actions :is(.icon-button, .btn-icon) { width: 44px; height: 44px; min-height: 44px; flex-basis: 44px; }
  .crm-header-actions .connection { max-width: 90px; font-size: 11px; }
  .btn, .field { min-height: 44px; }
  .btn-icon { width: 44px; height: 44px; }
  .icon-button { width: 44px; height: 44px; min-height: 44px; flex-basis: 44px; }
  /* Keep embedded controls above the iOS focus-zoom threshold. */
  body.crm-shell :is(input, select, textarea), body.login-body :is(input, select, textarea) { font-size: 16px !important; }
}
@media (max-width: 600px) {
  .topbar:has(.crm-page-title) { display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-rows: 1fr 1fr; gap: 0 8px; }
  .topbar:has(.crm-page-title) .brand { grid-column: 1; grid-row: 1; align-self: end; }
  .crm-page-title { grid-column: 1; grid-row: 2; align-self: start; padding-left: 0; border: 0; }
  .crm-header-actions { grid-column: 2; grid-row: 1 / -1; }
  .crm-header-actions .connection { max-width: 52px; }
}
@media (max-height: 500px) and (orientation: landscape) {
  :root { --crm-header-height: 38px; }
  .topbar:has(.crm-page-title) { display: flex; }
  .crm-page-title { align-self: auto; }
  .crm-header-actions :is(.icon-button, .btn-icon) { width: 36px; height: 36px; min-height: 36px; flex-basis: 36px; }
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation: none !important; transition: none !important; }
}
@media print {
  .topbar, nav.bottom-nav, .call-fab, .client-fab, .no-print { display: none !important; }
  body, body.crm-shell, body.voice-page { padding: 0; height: auto; min-height: 0; overflow: visible; background: #fff; color: #111; }
  main, main:not(.wide):not(.call-workpage):not(.unified-operator):not(.voice-shell) { max-width: none; margin: 0; padding: 0; }
  .card.kp-sheet { border: 0; background: none; padding: 0; }
}

/* ---------- обучение (/training) и markdown-тело ---------- */

/* В ui.css не было правил для blockquote/ul/li вообще, а теория уроков
   собрана из скриптов БЗ (29 блок-цитат в skript-holodnyj-zvonok.md):
   браузерный margin-inline 40px на 375px съедал ширину карточки. Правило
   чинит и уже существующий .kb-body на карточке звонка, а не только урок. */
.kb-body blockquote {
  margin: 10px 0;
  padding: 2px 0 2px 12px;
  border-left: 3px solid var(--accent);
  color: var(--fg);
}
.kb-body ul, .kb-body ol { padding-left: 20px; margin: 8px 0; }
.kb-body li { margin: 4px 0; }

/* Chevron для новых <details>: глобальные `details summary { list-style:none }`
   выше гасят маркер у ВСЕХ раскрывающихся блоков, а стрелка нарисована только
   для .filters summary — без этого правила блок остаётся вовсе без аффорданса
   (так уже выглядит «Сменить пароль» в admin.html). */
.reveal summary {
  min-height: 44px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  font-weight: 600;
  font-size: 0.92rem;
  cursor: pointer;
  color: var(--fg);
}
.reveal summary::after {
  content: "";
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  background: var(--chevron) no-repeat center;
  transition: transform 0.15s ease;
}
.reveal[open] > summary::after { transform: rotate(180deg); }

/* Группа вариантов ответа читается скринридером как одна группа (fieldset +
   legend), но дефолтная рамка и отступы браузера в этой системе — визуальный
   шум; min-width:0 не даёт fieldset распирать флекс-контейнер на 375px. */
fieldset.quiz { border: 0; padding: 0; margin: 0; min-width: 0; }
fieldset.quiz > legend { padding: 0; margin-bottom: 6px; }

/* ---------- захват клиента в обзвоне (crm/locks.py) ---------- */

/* Пометка «в работе у …» в списке /calls. Красным (--danger), а не серым:
   это не примечание, а причина, по которой соседняя кнопка не нажимается —
   серую подпись оператор пролистывает и потом жмёт мёртвую кнопку. */
.lock-note {
  margin: 8px 0 6px;
  color: var(--danger);
  font-size: 0.85rem;
  line-height: 1.35;
}

/* Кнопка «Позвонить» у занятого клиента остаётся на месте (строка списка не
   должна прыгать в высоте, когда клиента кто-то взял), но выключена. */
.call-btn[disabled] {
  opacity: 0.5;
  cursor: not-allowed;
}

/* Имя владельца — отдельной строкой над объяснением: во время смены оператор
   считывает именно «у кого», остальное дочитывает при необходимости. */
.call-lock strong {
  display: block;
  margin-bottom: 2px;
}

/* Работа оператора, не принятая из-за чужого захвата (call_card.html, ответ
   409). Рамка цветом опасности, но фон обычной карточки: это не ошибка ввода,
   а спасённый текст, который человек сейчас будет копировать — он должен
   читаться, а не мигать. */
.call-conflict {
  border-color: var(--danger);
}

.call-conflict textarea[readonly] {
  background: var(--bg);
}

/* ---------- пульт оператора: карточка звонка на одной странице ----------
   Просьба владелицы: во время звонка не должно быть переходов. Скрипт,
   калькулятор+прайс и поиск по БЗ живут в общей рабочей области
   (.op-workspace/.op-tabs — см. ниже, тот же приём, что на /pricing-panel):
   три sticky-колонки на десктопе, вкладки на узком экране — всегда на
   экране без скролла. Реже нужное (карточка клиента, шпаргалка возражений,
   история, исход) — обычным скроллом ниже; плавающая кнопка держит «Исход»
   всегда на экране. */



/* якоря секций ниже рабочей области (возражения/история/исход) — на случай
   прямой ссылки с фрагментом (#outcome и т.п.), скролл с отступом. */
.call-anchor { scroll-margin-top: calc(var(--crm-header-height) + 12px); }

.call-fab {
  position: fixed;
  right: 14px;
  bottom: calc(var(--crm-bottom-height) + 14px + env(safe-area-inset-bottom, 0px));
  z-index: 45;
  min-height: 50px;
  padding: 0 20px;
  border-radius: var(--r-md);
}

@media (min-width: 760px) {
  /* на широком экране карточка не листается настолько, чтобы кнопка
     закрывала контент своим краем — сдвигаем чуть внутрь от края */
  .call-fab { right: 14px; }
}

/* ---------- дашборд/«сегодня»: тренд выручки, «Требуют внимания», прогресс дня ----------
   Просьба владелицы: минимум переходов, ключевые действия сразу на виду.
   Плановые визиты на / и на /today используют один и тот же партиал
   _visit_row.html с hx-post — статус меняется на месте, без перезагрузки,
   уже на обеих страницах. /today добавляет живой счётчик «выполнено N из
   M»: он приходит тем же ответом POST /visits/{id}/status через
   hx-swap-oob (crm/routes/today.py::_progress_fragment), отдельного опроса
   не заводим. */

.stat-trend-up { color: var(--ok); }
.stat-trend-down { color: var(--danger); }

/* «Требуют внимания» — построчный список вместо четырёх одинаковых
   inline-стилей, которые раньше были в dashboard.html */
.attn-list { display: flex; flex-direction: column; }
.attn-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  min-height: 42px;
  padding: 5px 0;
  border-bottom: 1px solid var(--line);
}
.attn-row:last-child { border-bottom: none; }
.attn-row a { font-weight: 700; }

/* прогресс дня на /today: карточка «выполнено N из M» + полоса */
.today-progress-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 8px;
}
.today-progress-row strong { font-family: var(--font-mono); color: var(--accent); }
.today-progress-done .today-progress-row strong { color: var(--ok); }
.today-progress-done .meter i { background: var(--ok); box-shadow: none; }
/* ---------- карточка клиента: быстрый переход по разделам ----------
   Визиты и звонки на этой карточке и так не разнесены по вкладкам/URL —
   звонки подтягиваются htmx'ом прямо в страницу, — но длинную историю без
   якорей приходилось листать в поисках нужного раздела. Тот же приём, что
   «пульт оператора» на карточке звонка (call-fab выше):
   полоса ведёт по секциям ЭТОЙ ЖЕ страницы (scroll, не переход), а
   плавающая кнопка держит «＋ Выезд» на экране всегда — не только пока не
   проскроллили мимо статичной кнопки в начале карточки. */
.client-quicknav {
  position: sticky;
  top: var(--crm-header-height);
  z-index: 40;
  display: flex;
  gap: 6px;
  overflow-x: auto;
  scrollbar-width: none;
  margin: 0 -16px 12px;
  padding: 10px 16px;
  background: var(--card);
  border-bottom: 1px solid var(--line);
}
.client-quicknav::-webkit-scrollbar { display: none; }
.client-quicknav .chip { flex-shrink: 0; }

.client-anchor { scroll-margin-top: calc(var(--crm-header-height) + 62px); }

.client-fab {
  position: fixed;
  right: 14px;
  bottom: calc(var(--crm-bottom-height) + 14px + env(safe-area-inset-bottom, 0px));
  z-index: 45;
  min-height: 50px;
  padding: 0 20px;
  border-radius: var(--r-md);
}
@media (min-width: 760px) {
  /* на широком экране карточка не листается настолько, чтобы кнопка
     закрывала контент своим краем — сдвигаем чуть внутрь от края */
  .client-fab { right: 14px; }
}
/* ---------- отчёты/обзвон/журнал/админка: таблично-цифровые экраны ----------
   Просьба владелицы: минимум переходов между смежными разделами. Вместо
   мелкой ссылки «→» в углу — вкладки: обе стороны пары всегда на виду,
   переключение — один тап без «где я, куда назад» (Отчёты↔Обзвон,
   Обзвон↔Журнал, Люди↔Роли). Сами отчёты — таблицы цифр для владелицы:
   тут сознательно нет декора уровня «пульта оператора» — упор на
   типографику чисел (.amount/.mono уже есть) и сканируемые группировки. */

.tabs {
  display: flex;
  gap: 4px;
  padding: 4px;
  margin-bottom: 14px;
  background: var(--field-bg);
  border: 1px solid var(--border-soft);
  border-radius: var(--r-md);
}
.tabs a {
  flex: 1;
  min-height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  border-radius: calc(var(--r-md) - 4px);
  font-weight: 600;
  font-size: 0.86rem;
  color: var(--muted);
  text-decoration: none;
  text-align: center;
}
.tabs a:hover { color: var(--fg); text-decoration: none; }
.tabs a.active {
  background: var(--ok-bg);
  color: var(--accent);
}

/* группы чекбоксов в фильтрах /calls — тот же inline-flex, что раньше был
   продублирован style="" в шести местах шаблона */
.check-group { display: flex; flex-wrap: wrap; gap: 2px 14px; }

@media (min-width: 1024px) {
  /* Списки карточек (сегодня, заявки, дашборд «план на сегодня», клиенты,
     история визитов на карточке клиента) — сеткой в несколько колонок,
     а не одной на всю ширину main.wide (1320px). */
  #visits-list,
  #dash-today-list,
  .cards-grid,
  .client-visits-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 340px), 1fr));
    gap: 12px;
    align-items: start;
  }
  #visits-list > .card,
  #dash-today-list > .card,
  .cards-grid > .card,
  .client-visits-grid > .card {
    margin-bottom: 0;
  }

  /* Дашборд: «Требуют внимания» и «Выручка по месяцам» рядом, не друг под другом */
  .dash-two-col {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 16px;
    align-items: start;
  }

  /* Формы визита/клиента (.form-grid рядом с .form-col — сам .form-col
     общий для форм за пределами этих экранов, его трогать нельзя): поля
     парами, кроме textarea/кнопки/инфоблоков — те помечены .wide и тянутся
     на всю ширину. */
  .form-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 4px 16px;
  }
  .form-grid > .wide {
    grid-column: 1 / -1;
  }
}
@media (min-width: 1024px) {
  /* ---------- десктоп: списки-карточки в несколько колонок вместо одной
     пустой на всю ширину — статьи БЗ (kb.html/_kb_results.html), уроки и
     ручной допуск (training.html/training_progress.html), кандидаты на
     обзвон и журнал звонков (calls.html/calls_journal.html). Мобильная
     раскладка (одна колонка) не тронута — правила только здесь. ---------- */
  main.wide .kb-article-grid,
  main.wide .lesson-grid,
  main.wide .cand-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 320px), 1fr));
    align-items: start;
    gap: 12px;
  }
  main.wide .kb-article-grid > .card,
  main.wide .lesson-grid > .card,
  main.wide .cand-grid > .card {
    margin-bottom: 0;
  }

  /* форма статьи БЗ: заголовок/категория/теги в два столбца, текст статьи —
     во всю ширину ниже (см. kb_form.html) */
  main.wide .kb-form-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 14px 16px;
  }
}
/* ---------- density-admin: отчёты/админка на широком экране (main.wide) ---------- */
/* Экраны: reports.html, reports_calls.html, admin.html, admin_roles.html,
   segments.html. На main.wide (1320px) их списки/формы одной колонкой
   оставляли пустой правую половину — здесь только раскладка внутри уже
   существующих карточек, мобильный вид (< 1024px) не меняется. */

@media (min-width: 1024px) {
  /* «По месяцам» в отчётах (reports.html, reports_calls.html) — список из
     13 строк в одну колонку на 1320px, переносим в 2 колонки. */
  .month-list {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0 32px;
  }

  /* .form-grid — модификатор поверх .form-col только для форм admin.html и
     admin_roles.html (Новый пользователь / Новая роль / права роли). Сам
     .form-col не трогаем: его используют и другие экраны (login.html и
     карточки клиента/звонка/заявки), где узкая колонка — то, что нужно. */
  .form-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 4px 20px;
  }
  .form-grid > *:not(.form-row) { grid-column: 1 / -1; }

  /* Чекбоксы прав в форме роли — тоже в 2 колонки, иначе список из 9 прав
     одной колонкой на всю ширину карточки. */
  .form-grid fieldset {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 4px 20px;
  }
  .form-grid fieldset > legend { grid-column: 1 / -1; }

  /* Списки карточек (типы клиентов, пользователи в admin.html; сохранённые
     аудитории в segments.html) — в 2 колонки вместо одной на всю ширину. */
  .type-grid,
  .user-grid,
  .segment-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 14px;
    align-items: start;
  }
}

/* ---------- рабочая область оператора (/pricing-panel, /calls/{id}) ----------
   Скрипт звонка | калькулятор + прайс | база знаний — на одном экране:
   оператор ведёт живой разговор, переходы и поиск по разделам недопустимы.
   Общий блок для полноэкранной панели калькулятора И карточки звонка (там
   ниже рабочей области ещё карточка клиента/возражения/история/исход —
   реже нужны во время разговора, обычным скроллом). ≥1100px — три колонки;
   уже — вкладки внутри страницы (.op-tabs видимы, общий JS-партиал
   _op_tabs_script.html вешает .op-tabbed и переключает .op-pane-active).
   Без JS вкладок нет и панели остаются в потоке — всё доступно скроллом. */

.op-tabs { display: none; }

.call-calculator {
  display: block;
  width: 100%;
  height: 720px;
  height: clamp(320px, calc(100dvh - var(--crm-header-height) - var(--crm-bottom-height) - 32px), 860px);
  border: 1px solid var(--border);
  border-radius: 8px;
  background: #fff;
}

@media (max-width: 1099px) {
  .op-tabs {
    display: flex;
    position: sticky;
    top: calc(var(--crm-header-height) + 8px);
    z-index: 30;
  }
  .op-workspace.op-tabbed .op-pane { display: none; }
  .op-workspace.op-tabbed .op-pane-active { display: block; }
}

@media (min-width: 1100px) {
  .op-workspace {
    display: grid;
    grid-template-columns: minmax(0, 3fr) minmax(0, 4fr) minmax(0, 3fr);
    gap: 0 20px;
    align-items: start;
  }
  .op-pane { min-width: 0; }
  /* боковые панели (скрипт и БЗ) скроллятся сами и не уезжают при
     прокрутке длинного центра — sticky, не fixed: колонок три, и
     fixed-позиционирование одной из них не разделить с остальными */
  .op-workspace > .op-pane:first-child,
  .op-workspace > .op-pane:last-child {
    position: sticky;
    top: calc(var(--crm-header-height) + 12px);
    max-height: calc(100dvh - var(--crm-header-height) - 24px);
    overflow-y: auto;
  }
  .op-workspace .op-pane > h2:first-child { margin-top: 4px; }
}

/* скрипт читают вслух в трубку — крупнее и просторнее обычного текста */
.op-script-body { font-size: 1.06rem; line-height: 1.6; }

/* прайс-подсказка около калькулятора на карточке звонка: свёрнутый
   <details class="reveal">, разворачивается без перехода */
.calc-price-hint { padding: 4px 14px 8px; }
.calc-price-hint-section { margin: 4px 0 10px; }

/* разбор цены оператора в #calc-result: база → скидки строками → итог */
#calc-result .calc-op-total {
  color: var(--fg);
  font-family: var(--font-mono);
  font-weight: 600;
  font-size: 1.02rem;
  margin-top: 4px;
}
#calc-result .badge { margin: 2px 0; }

/* ---------- живой поиск единой БЗ в рабочей области ----------
   Карточка звонка и /pricing-panel: результаты /kb/search группами по
   категориям + inline-просмотр статьи/урока прямо под поиском (панель
   .kb-inline-view создаёт JS в _pricing_calc_embed.html). На трёхколоночном
   десктопе всё живёт в скроллируемой колонке БЗ — скрипт звонка остаётся
   виден в соседней; на узких экранах — внутри вкладки «База знаний». */

.kb-cat-head {
  font-family: var(--font-display);
  font-size: 0.78rem;
  color: var(--muted);
  margin: 10px 0 4px;
}
.kb-result-group {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.kb-result {
  display: block;
  padding: 8px 12px;
  border: 1px solid var(--border-soft);
  border-radius: var(--r-sm);
  background: var(--card);
  color: var(--fg);
  text-decoration: none;
  cursor: pointer;
}
.kb-result:hover,
.kb-result.active {
  border-color: var(--accent);
  text-decoration: none;
}
.kb-result.active { background: var(--ok-bg); }
.kb-result-title { font-weight: 600; }
/* Match highlighting uses the shared success surface. */
.kb-result mark,
#kb-live mark,
.kb-inline-view mark {
  background: var(--ok-bg);
  color: inherit;
  border-radius: 3px;
  padding: 0 1px;
}

/* .kb-inline-view — панель просмотра, создаёт JS embed'а; сам фрагмент
   бэкенда внутри неё — <article class="kb-inline"> (crm/routes/kb.py) */
.kb-inline-view { margin-top: 10px; }
/* кнопки «← результаты» и «×» не должны уезжать при чтении длинной статьи:
   sticky работает и в скроллируемой колонке БЗ, и при скролле страницы.
   top: 62px — запас под закреплённую полосу вкладок (.op-tabs, узкая
   панель, ~56px с отступом) с небольшим зазором. */
.kb-inline-bar {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 8px;
  position: sticky;
  top: calc(var(--crm-header-height) + 62px);
  z-index: 5;
  background: var(--card);
}
@media (min-width: 1100px) {
  /* внутри трёхколоночной рабочей области колонка БЗ скроллится сама и
     закреплённых полос над ней нет — липнем к верху колонки без поправки */
  .op-workspace .kb-inline-bar { top: 0; }
}
.kb-inline-bar .btn { padding: 4px 10px; }
.kb-inline-title {
  margin: 0 0 8px;
  font-size: 1.05rem;
  overflow-wrap: anywhere;
}

/* Call card only: compact workspace, preserving the shared calculator styles. */
.phone-operator { display: inline-block; max-width: 100%; margin: 4px 0; font-size: 12px; color: var(--muted); vertical-align: top; overflow-wrap: anywhere; }
.phone-operator > summary { cursor: pointer; min-height: 28px; padding: 4px 0; color: var(--blue); }
.phone-operator[open] { display: block; }
.phone-operator p { margin: 4px 0; font-size: 13px; color: var(--fg); }
.unified-operator .operator-contact > .phone-operator { margin: 0; }
main.call-workpage { max-width: none; padding: 8px 12px 24px; }
.call-workpage .found-row { margin: 0 0 8px; gap: 8px; flex-wrap: wrap; }
.call-workpage .op-workspace { gap: 12px; }
.call-workpage .op-pane { min-width: 0; overflow-wrap: anywhere; }
.call-workpage .op-pane > h2:first-child { margin: 0 0 8px; font-size: 1rem; }
.call-workpage .op-script-body { font-size: .9rem; line-height: 1.45; }
.call-workpage .op-script-body h2,
.call-workpage .op-script-body h3 { margin: 10px 0 6px; font-size: .95rem; }
.call-workpage .op-script-body p { margin: 6px 0; }
.call-workpage .op-script-body blockquote { margin: 6px 0; padding: 6px 10px; }
.call-workpage .op-script-body ul,
.call-workpage .op-script-body ol { margin: 6px 0; padding-left: 20px; }
.call-workpage .op-script-body li { margin: 3px 0; }
.call-workpage .call-script-greeting > h2 { margin-top: 0; }
.call-workpage .call-script-warning {
  margin: 8px 0;
  padding: 6px 10px;
  border-left: 3px solid var(--danger);
  background: var(--danger-bg);
  font-size: .82rem;
}
.call-workpage .call-script-warning > h2 { margin-top: 0; }
.call-workpage .call-script-branch > summary { padding: 9px 26px 9px 0; font-size: .9rem; }
.call-workpage .call-script-branch > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.call-workpage .call-contact { margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--border); }
.call-workpage .call-contact .card-head { margin-bottom: 4px; }
.call-workpage .call-contact .btn { white-space: normal; overflow-wrap: anywhere; max-width: 100%; }
.call-workpage > .card,
.call-workpage > form.card { padding: 10px 0; border: 0; border-radius: 0; background: none; box-shadow: none; }
.call-workpage > h2 { margin: 16px 0 8px; font-size: 1.05rem; }
@media (min-width: 1100px) {
  .call-workpage .op-workspace {
    grid-template-columns: minmax(0, 1.15fr) minmax(0, 1.4fr) minmax(0, .85fr);
  }
  .call-workpage .op-workspace > .op-pane { top: calc(var(--crm-header-height) + 8px); }
}
@media (max-width: 1099px) {
  .call-workpage .op-tabs { margin: 0 0 8px; top: var(--crm-header-height); }
  .call-workpage .op-tabs a { flex: 1; padding: 10px 6px; text-align: center; font-size: .85rem; }
}
@media print {
  .call-workpage .op-workspace.op-tabbed .op-pane { display: block; position: static; max-height: none; overflow: visible; }
}
