/* Место под полосу прокрутки держим всегда. Страница кабинета вырастает
   за экран через полсекунды, когда приходят данные; полоса появляется,
   ширина уменьшается на её толщину — и вся центрированная вёрстка
   съезжает вбок, а меню переносится по-другому. Только для страниц
   кабинета: лендинг этот файл не касается. */
html:has(.admin-page) { scrollbar-gutter: stable; }
/* По той же причине шрифты на страницах кабинета подключены с
   display=optional, а не swap: со swap текст через долю секунды
   перерисовывался веб-шрифтом, ссылки меню становились шире и меню
   переносилось иначе. Optional берёт шрифт, если он успел, а нет —
   остаётся на системном до следующего захода, без перерисовки. */
.admin-page { min-height: 100vh; max-width: 480px; margin: 0 auto; padding: 24px 20px 40px; background: var(--bg); }
.admin-card { background: var(--card-dark); border: 1px solid var(--divider-dark); border-radius: 12px; padding: 20px; margin-top: 16px; }
.admin-title { font-size: 20px; font-weight: 600; margin: 16px 0 8px; }
.admin-mute { color: var(--mute-on-dark); font-size: 13px; margin-bottom: 16px; }
.admin-field { display: block; width: 100%; margin-bottom: 10px; }
.admin-field input, .admin-field select, .admin-field textarea {
  width: 100%; background: #0a0f0a; border: 1px solid #233127; border-radius: 6px;
  padding: 12px 14px; font-family: inherit; font-size: 13px; color: var(--text-light);
  resize: vertical;
}
.admin-field input:focus, .admin-field select:focus, .admin-field textarea:focus { outline: none; border-color: var(--accent); }
.admin-btn {
  background: var(--accent); color: #06140a; border: none; border-radius: 6px;
  padding: 12px 16px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
  font-size: 12px; cursor: pointer; width: 100%;
}
.admin-btn.ghost { background: transparent; color: var(--accent-bright); border: 1px solid var(--divider-dark); margin-top: 8px; }
.admin-error { color: #f08a8a; font-size: 13px; min-height: 18px; margin: 8px 0; }
.admin-ok { color: var(--accent-bright); font-size: 13px; margin: 8px 0; }
/* Отказ в строке «успеха» — красным (DF_WORDS.say, аудит §7.3). */
.admin-ok.is-error, .chat-note.is-error { color: #f08a8a; }
/* Разделы админки — кнопками, а не строчкой подчёркнутых ссылок.
   Ссылки сливались с текстом над ними: раздел формально был в меню,
   а глазами не находился, и люди шли в адресную строку. */
.admin-nav { display: flex; gap: 8px; flex-wrap: wrap; margin: 14px 0 18px; }
/* Меню рисует сторож после ответа сервера. Место под строку кнопок
   держим заранее: иначе всё ниже съезжает, когда меню появляется. */
.admin-nav:empty { min-height: 40px; }
/* Панели с пустыми контейнерами не показываем до первого ответа сервера.
   Видимый пустой список, раздувшийся через секунду, толкает всё ниже —
   кнопка уезжает из-под пальца. Появление нового сдвигом не считается,
   съезжание уже видимого — считается. */
.admin-page[data-loading] .admin-pane,
.admin-page[data-loading] .admin-view { display: none !important; }
/* Переключатель витрины — одна строка, место под неё занято с самого
   начала: показывается он после ответа сервера. */
.admin-demo { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; min-height: 24px; margin: 0 0 8px; font-size: 13px; cursor: pointer; }
.admin-nav a {
  color: var(--accent-bright);
  font-size: 13px;
  text-decoration: none;
  /* 10px по вертикали — чтобы на телефоне попадали пальцем. */
  padding: 9px 14px;
  border: 1px solid var(--divider-dark);
  border-radius: 999px;
  background: #0a0f0a;
  white-space: nowrap;
  line-height: 1;
}
.admin-nav a:hover { border-color: var(--accent-bright); background: #0e1a0e; }
.admin-list { list-style: none; display: flex; flex-direction: column; gap: 8px; }
.admin-list li {
  display: flex; justify-content: space-between; align-items: flex-start; gap: 10px;
  background: #0a0f0a; border: 1px solid var(--divider-dark); border-radius: 8px; padding: 10px 12px;
}
.admin-list button { background: none; border: none; color: #f08a8a; cursor: pointer; font-size: 12px; }
.admin-hidden { display: none; }
.admin-role { font-family: var(--mono); font-size: 11px; color: var(--mute-on-dark); }
.quiz-play { margin-top: 8px; }
.quiz-step { font-size: 12px; color: var(--mute-on-dark); margin-bottom: 10px; }
.quiz-choice {
  display: block; width: 100%; text-align: left; cursor: pointer;
  background: #0a0f0a; border: 1px solid var(--divider-dark); border-radius: 10px;
  padding: 16px 18px; color: var(--text-light); font: inherit; font-size: 16px; line-height: 1.4;
}
.quiz-choice:hover, .quiz-choice:focus { border-color: var(--accent); outline: none; }
.admin-page.quiz-master { max-width: 720px; }
.admin-list li.is-current { border-color: var(--accent); }
.admin-list .row-main { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.admin-list .row-actions { display: flex; gap: 8px; flex-shrink: 0; align-items: center; }
.admin-list .row-actions a, .admin-list .row-actions button {
  background: none; border: none; cursor: pointer; font-size: 12px; padding: 0; width: auto;
  text-transform: none; letter-spacing: 0; font-weight: 500;
}
.admin-list .row-actions .edit { color: var(--accent-bright); }
/* Списки в строке (роль, тип аккаунта) — в тёмной теме, а не белые
   системные, и с переносом: на телефоне они лезли поверх логина
   (аудит §7.3). */
.admin-list .row-actions { flex-wrap: wrap; justify-content: flex-end; min-width: 0; }
.admin-list .row-actions select {
  background: var(--card-dark); color: inherit; border: 1px solid var(--divider-dark);
  border-radius: 8px; padding: 6px 8px; font: inherit; font-size: 12px; max-width: 100%;
}
@media (max-width: 640px) {
  .admin-list li { flex-direction: column; align-items: stretch; }
  .admin-list .row-actions { justify-content: flex-start; }
  .admin-list .row-actions select { flex: 1 1 100%; }
}
.admin-check { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--mute-on-dark); margin: 0 0 10px; }
.admin-check input { width: auto; }
.q-editor {
  border: 1px solid var(--divider-dark); border-radius: 10px; padding: 12px;
  margin-top: 10px; background: #0a0f0a;
}
.q-editor-top { display: flex; justify-content: space-between; gap: 8px; align-items: flex-start; margin-bottom: 8px; }
.q-editor-meta { font-size: 12px; color: var(--mute-on-dark); }
.q-type-row { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; align-items: center; }
.q-options-hint { font-size: 11px; color: var(--mute-on-dark); margin: -4px 0 10px; }
.q-editor-actions { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 4px; }
.q-editor-actions .admin-btn { width: auto; flex: 1; padding: 10px 12px; font-size: 11px; }
.admin-inline-btns { display: flex; gap: 8px; flex-wrap: wrap; }
.admin-inline-btns .admin-btn { width: auto; flex: 1; text-align: center; text-decoration: none; box-sizing: border-box; }
.admin-btn.danger {
  background: transparent; color: #f08a8a; border: 1px solid #5a2a2a; margin-top: 10px;
}
.admin-btn.danger:hover { border-color: #f08a8a; }
.q-editor .admin-field textarea { min-height: 92px; }

/* --- Админка записи: календарь, записи, справочник -------------------- */
/* Страница широкая: календарь на две недели в 480 пикселей не помещается. */
.admin-page.admin-wide { max-width: 1100px; }
.admin-tabs { display: flex; gap: 8px; flex-wrap: wrap; margin: 16px 0 0; }
.admin-tab {
  background: transparent; color: var(--mute-on-dark); border: 1px solid var(--divider-dark);
  border-radius: 8px; padding: 8px 14px; font-size: 13px; cursor: pointer; font-family: inherit;
}
.admin-tab.is-active { color: var(--accent-bright); border-color: var(--accent); }

/* Панель вкладки. Правила не было вовсе: кабинет переключал класс
   is-active, а прятать неактивные было нечем — и все шесть вкладок
   показывались разом, одна под другой. Выглядело это как «кнопки
   не работают»: подсветка переезжала, а содержимое не менялось.
   На /admin того же не случилось, потому что там панели прячут
   классом admin-hidden, у которого правило есть. */
.admin-pane { display: none; }
.admin-pane.is-active { display: block; }
.admin-tabs.subtle .admin-tab { font-size: 12px; padding: 6px 10px; }
.admin-row-between { display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap; }
.admin-grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.admin-checks { display: flex; flex-direction: column; gap: 4px; max-height: 220px; overflow-y: auto; margin-bottom: 10px; }
.admin-details { margin-top: 12px; }
.admin-details summary { color: var(--accent-bright); font-size: 13px; cursor: pointer; }

/* Календарь: две недели плитками, на телефоне — в одну колонку. */
.cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 8px; margin-top: 12px; }
.cal-day {
  background: var(--card-dark); border: 1px solid var(--divider-dark); border-radius: 10px;
  padding: 10px; min-height: 110px; display: flex; flex-direction: column; gap: 4px;
}
.cal-day.is-off { opacity: 0.55; }
.cal-day-head { display: flex; justify-content: space-between; align-items: baseline; }
.cal-date { font-weight: 600; font-size: 14px; }
.cal-wd { font-size: 11px; color: var(--mute-on-dark); }
.cal-mute { font-size: 11px; color: var(--mute-on-dark); margin: 0; }
.cal-note { font-size: 11px; color: var(--accent-bright); margin: 0; }
.cal-booking {
  display: block; width: 100%; text-align: left; font-size: 11px; font-family: inherit;
  background: rgba(255, 255, 255, 0.06); border: 1px solid var(--divider-dark);
  border-left: 2px solid var(--accent); border-radius: 6px; padding: 4px 6px; cursor: pointer;
  color: inherit; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cal-booking.is-cancelled { border-left-color: #f08a8a; text-decoration: line-through; opacity: 0.6; }
.cal-booking.is-done { border-left-color: #6fbf73; }
.cal-booking[draggable="true"] { cursor: grab; }
.cal-booking.is-dragging { opacity: 0.4; }

/* Колонки специалистов внутри дня. Плитка дня узкая, поэтому колонки
   раскладываются по ширине сами: влезли — рядом, не влезли — друг под
   другом. Имя мастера остаётся заголовком в обоих случаях, иначе на
   телефоне непонятно, чьи это записи. */
.cal-cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(84px, 1fr)); gap: 6px; }
.cal-col { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.cal-col-name {
  font-size: 10px; color: var(--mute-on-dark); text-transform: uppercase; letter-spacing: 0.04em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Пустая колонка всё равно должна принимать запись — отсюда min-height. */
.cal-col-body { display: flex; flex-direction: column; gap: 4px; min-height: 28px; border-radius: 6px; }
.cal-col-body.is-drop, .cal-day.is-drop {
  outline: 1px dashed var(--accent); outline-offset: 2px; background: rgba(255, 255, 255, 0.04);
}

.booking-row, .entry-row {
  border: 1px solid var(--divider-dark); border-radius: 10px; padding: 12px; margin-top: 10px;
  display: flex; flex-direction: column; gap: 6px;
}
.booking-row.is-cancelled, .entry-row.is-off { opacity: 0.6; }
/* Тип аккаунта: кто это, а не что ему можно. Цветом, потому что
   отличить нашего сотрудника от мастера арендатора надо глазами
   и в списке на сотню строк. */
.user-type {
  display: inline-block; font-size: 10px; padding: 1px 7px; border-radius: 999px;
  border: 1px solid var(--divider-dark); color: var(--mute-on-dark); margin-top: 2px;
}
.user-type.is-admin { border-color: var(--accent); color: var(--accent-bright); }
.user-type.is-client { border-color: #6fbf73; color: #6fbf73; }
.user-type.is-specialist { border-color: #c2a24a; color: #c2a24a; }
.user-type.is-customer { border-color: #7aa6c2; color: #7aa6c2; }
.user-type.is-temp { border-color: #c47b7b; color: #c47b7b; }

/* Предупреждение у опасной галочки: видно там, где ставят галочку. */
.cap-warn { display: block; font-size: 11px; color: #c47b7b; margin-left: 24px; }

/* Компании-арендаторы. Ожидающие выделены: заявка, потерявшаяся среди
   закрытых компаний, — это клиент, который не дождался ответа. */
.company-row {
  border: 1px solid var(--divider-dark); border-left: 3px solid var(--divider-dark);
  border-radius: 10px; padding: 12px; margin-top: 10px;
  display: flex; flex-direction: column; gap: 4px;
}
.company-row.is-active { border-left-color: #6fbf73; }
.company-row.is-pending { border-left-color: var(--accent); background: rgba(255, 255, 255, 0.03); }
.company-row.is-suspended { border-left-color: #c47b7b; opacity: 0.65; }
.company-head { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.company-row .admin-btn { width: auto; flex: 0 0 auto; margin-top: 0; padding: 6px 12px; font-size: 11px; }
.company-plan {
  background: var(--card-dark); color: inherit; border: 1px solid var(--divider-dark);
  border-radius: 8px; padding: 6px 8px; font-family: inherit; font-size: 11px;
}
/* Строка, на которую надо обратить внимание, но которая не ошибка. */
.admin-note { font-size: 12px; color: var(--accent-bright); margin: 0; }

/* Аналитика: плитки с числами. Прижимаются по ширине сами — на телефоне
   в одну колонку, на мониторе в пять. */
.stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 10px; margin-top: 12px; }
.stat-card {
  background: var(--card-dark); border: 1px solid var(--divider-dark); border-radius: 10px;
  padding: 12px; display: flex; flex-direction: column; gap: 4px;
}
.stat-title { font-size: 11px; color: var(--mute-on-dark); text-transform: uppercase; letter-spacing: 0.04em; }
.stat-value { font-size: 22px; font-weight: 600; }
.stat-note { font-size: 11px; color: var(--mute-on-dark); }

/* Полоски вместо библиотеки графиков: ради четырёх диаграмм тянуть
   с CDN пару сотен килобайт значит сделать страницу, которая без
   интернета не работает. Длина полоски считается от максимума ряда,
   а не от суммы: от суммы они одинаково короткие уже на пяти значениях. */
.bar-row { display: flex; align-items: center; gap: 8px; margin-top: 6px; }
.bar-name { flex: 0 0 34%; font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bar-track { flex: 1 1 auto; height: 10px; background: rgba(255, 255, 255, 0.06); border-radius: 5px; overflow: hidden; }
.bar-fill { height: 100%; background: var(--accent); border-radius: 5px; min-width: 2px; }
.bar-value { flex: 0 0 auto; font-size: 12px; color: var(--mute-on-dark); min-width: 48px; text-align: right; }

/* Столбики по дням. Пустые дни рисуются тоже: пропуск читается как
   «данных нет», а не как «в этот день никто не пришёл». */
.day-chart { display: flex; align-items: flex-end; gap: 3px; height: 140px; margin-top: 10px; overflow-x: auto; }
.day-col { flex: 1 0 14px; display: flex; flex-direction: column; align-items: center; gap: 4px; height: 100%; }
.day-stack { display: flex; align-items: flex-end; gap: 1px; height: 100%; width: 100%; }
.day-bar { flex: 1 1 0; min-height: 1px; border-radius: 2px 2px 0 0; background: var(--divider-dark); }
.day-bar.is-bookings { background: var(--accent); }
.day-bar.is-deals { background: #6fbf73; }
.day-bar.is-chats { background: #c2a24a; }
.day-label { font-size: 9px; color: var(--mute-on-dark); }

.chart-legend { display: flex; gap: 14px; flex-wrap: wrap; margin-top: 8px; font-size: 11px; color: var(--mute-on-dark); }
.legend-item { display: inline-flex; align-items: center; gap: 5px; }
.legend-dot { width: 8px; height: 8px; border-radius: 2px; background: var(--divider-dark); display: inline-block; }
.legend-dot.is-bookings { background: var(--accent); }
.legend-dot.is-deals { background: #6fbf73; }
.legend-dot.is-chats { background: #c2a24a; }

/* Доска воронки. Колонки прокручиваются вбок — этапов бывает десяток,
   и ужимать их до нечитаемости хуже, чем листать. */
.board { display: flex; gap: 10px; overflow-x: auto; padding-bottom: 8px; margin-top: 12px; }
.board-col {
  flex: 0 0 240px; min-width: 240px;
  background: var(--card-dark); border: 1px solid var(--divider-dark);
  border-top: 3px solid var(--divider-dark); border-radius: 10px; padding: 10px;
  display: flex; flex-direction: column; gap: 8px;
}
.board-col-head { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; }
.board-col-name { font-weight: 600; font-size: 13px; }
/* Пустая колонка всё равно принимает карточку — отсюда min-height. */
.board-col-body { display: flex; flex-direction: column; gap: 6px; min-height: 60px; border-radius: 8px; }
.board-col-body.is-drop { outline: 1px dashed var(--accent); outline-offset: 2px; }

.deal-card {
  background: rgba(255, 255, 255, 0.06); border: 1px solid var(--divider-dark);
  border-left: 2px solid var(--accent); border-radius: 8px; padding: 8px 10px; cursor: grab;
}
.deal-card.is-dragging { opacity: 0.4; }
.deal-card.is-won { border-left-color: #6fbf73; }
.deal-card.is-lost { border-left-color: #c47b7b; opacity: 0.7; }
.deal-title { margin: 0 0 4px; font-size: 13px; word-break: break-word; }

.stage-row { padding: 8px 0; border-bottom: 1px solid var(--divider-dark); }
.stage-row .admin-btn { width: auto; flex: 0 0 auto; margin-top: 0; padding: 6px 10px; font-size: 11px; }

/* Карточка сделки — выдвижная панель справа, на телефоне во всю ширину. */
.admin-drawer {
  position: fixed; inset: 0 0 0 auto; width: min(460px, 100%);
  background: var(--card-dark); border-left: 1px solid var(--divider-dark);
  overflow-y: auto; z-index: 40; box-shadow: -8px 0 24px rgba(0, 0, 0, 0.35);
  /* Под полосой модерации, а не под ней спрятанной (moderate-bar.js). */
  top: var(--moderate-h, 0px);
}
.admin-drawer-inner { padding: 16px; }
.admin-drawer .admin-btn { width: auto; flex: 0 0 auto; margin-top: 0; padding: 6px 12px; font-size: 11px; }

/* Список клиентов: строка на человека, кликается целиком. */
.client-row { width: 100%; text-align: left; margin-top: 6px; }
.admin-role.is-cancelled { text-decoration: line-through; opacity: 0.6; }
.admin-role.is-done { color: #6fbf73; }

/* Заметки: лента на карточке. Закреплённое выделено полосой — важное
   должно быть видно до чтения, а не после. */
.notes-box { border-top: 1px solid var(--divider-dark); margin-top: 12px; padding-top: 10px; }
.notes-list { display: flex; flex-direction: column; gap: 8px; }
.note-row {
  border: 1px solid var(--divider-dark); border-left: 2px solid transparent;
  border-radius: 8px; padding: 8px 10px;
}
.note-row.is-pinned { border-left-color: var(--accent); }
.note-body { margin: 0 0 4px; font-size: 13px; white-space: pre-wrap; word-break: break-word; }
.notes-form { display: flex; gap: 8px; margin-top: 10px; align-items: stretch; }
.notes-input {
  flex: 1 1 auto; min-width: 0; background: var(--card-dark); color: inherit;
  border: 1px solid var(--divider-dark); border-radius: 8px; padding: 8px 10px;
  font-family: inherit; font-size: 13px;
}
.notes-form .admin-btn { width: auto; flex: 0 0 auto; margin-top: 0; padding: 8px 14px; }

/* Закрытый доступ видно сразу: строка остаётся на месте, но гаснет. */
.admin-row.is-off { opacity: 0.55; }
.booking-row .admin-inline-btns .admin-btn, .entry-row .admin-inline-btns .admin-btn {
  width: auto; flex: 0 0 auto; padding: 8px 12px; font-size: 11px; margin-top: 0;
}
.crm-log { margin-top: 12px; border-top: 1px solid var(--divider-dark); padding-top: 10px; }

.week-row { display: grid; grid-template-columns: 1.2fr repeat(5, 1fr); gap: 6px; align-items: center; margin-bottom: 6px; }
.week-name { font-size: 12px; color: var(--mute-on-dark); }
/* Подпись над полем: четыре одинаковых поля времени без слов не
   отличить «конец дня» от «конца перерыва» (аудит §7.3). */
.week-cell { display: flex; flex-direction: column; gap: 2px; font-size: 10px; color: var(--mute-on-dark); }
.week-row input {
  background: var(--card-dark); border: 1px solid var(--divider-dark); border-radius: 8px;
  padding: 8px; color: inherit; font-family: inherit; font-size: 12px; width: 100%; box-sizing: border-box;
}

@media (max-width: 860px) {
  .cal-grid { grid-template-columns: repeat(2, 1fr); }
  .week-row { grid-template-columns: 1fr 1fr; }
  .week-name { grid-column: 1 / -1; }
  .admin-grid-2 { grid-template-columns: 1fr; }
}

/* ---------------------------------------------------------- мой день */
/* Экран мастера: строка — это один приём. Время слева крупно, потому
   что глазами ищут именно его, а не фамилию. */

.my-steps { display: flex; gap: 8px; flex-wrap: wrap; align-items: flex-end; }

.my-slot {
  display: flex; gap: 14px; align-items: flex-start;
  padding: 12px 0; border-bottom: 1px solid var(--admin-line, #272c36);
}
.my-slot:last-child { border-bottom: none; }
.my-slot.is-off { opacity: 0.5; text-decoration: line-through; }
.my-slot-time { font-size: 18px; font-weight: 600; min-width: 64px; }
.my-slot-body { flex: 1; min-width: 0; }
.my-slot-status { font-size: 12px; color: var(--admin-mute, #9aa3b2); white-space: nowrap; }

.my-upcoming { display: flex; gap: 8px; flex-wrap: wrap; }

@media (max-width: 860px) {
  .my-slot { gap: 10px; }
  .my-slot-time { min-width: 52px; font-size: 16px; }
}

/* ------------------------------------------------- полоса модерации */
/* Пока админ стоит в чужой компании, экран выглядит как свой, а правки
   уходят арендатору. Полоса поэтому яркая и не прячется. */

.moderate-bar {
  position: sticky; top: 0; z-index: 50;
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  flex-wrap: wrap;
  background: #3a2a0c; color: #ffd27a;
  border-bottom: 1px solid #6b4e14;
  padding: 10px 16px; font-size: 13px;
}
.moderate-bar .admin-btn { border-color: #6b4e14; color: #ffd27a; }

/* ===================================================== телефон: пальцы */
/* На мониторе мелкая кнопка экономит место, на телефоне она превращает
   работу в прицеливание. 38px — минимум, в который попадают не глядя.
   Правило здесь, в конце файла, чтобы перебивать точечные padding'и
   у кнопок внутри строк: их много, и править каждое значило бы
   однажды одно пропустить. */

@media (max-width: 860px) {
  .admin-btn,
  .admin-inline-btns .admin-btn,
  .company-row .admin-btn,
  .stage-row .admin-btn,
  .admin-drawer .admin-btn,
  .notes-form .admin-btn,
  .booking-row .admin-inline-btns .admin-btn,
  .entry-row .admin-inline-btns .admin-btn,
  .admin-nav a,
  .admin-tab {
    min-height: 38px;
    padding: 10px 14px;
    font-size: 13px;
    line-height: 1.2;
  }

  /* Меню на телефоне — одной строкой с прокруткой вбок. В перенос оно
     занимало пять строк, а пустое, до ответа сервера, держало место под
     одну: всё ниже уезжало на полэкрана, когда меню появлялось. Одна
     строка одной высоты — до отрисовки и после. */
  .admin-nav {
    flex-wrap: nowrap;
    overflow-x: auto;
    min-height: 40px;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }
  .admin-nav::-webkit-scrollbar { display: none; }
  .admin-nav a { flex: 0 0 auto; }

  /* Вкладки — так же: в перенос последняя («Провайдеры») оставалась
     одна на второй строке и читалась как отдельная кнопка. */
  .admin-tabs {
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }
  .admin-tabs::-webkit-scrollbar { display: none; }
  .admin-tabs .admin-tab { flex: 0 0 auto; }

  /* Карточка в карточке съедала по 40px ширины на экране в 390. */
  .admin-card { padding: 14px; }

  /* Выпадающие списки — та же история: по 30px не попасть. */
  select,
  .company-plan,
  .admin-field select,
  .admin-field input,
  .admin-field textarea {
    min-height: 38px;
    font-size: 15px; /* меньше 16px — и Safari «подъезжает» зумом */
  }

  /* Ряд кнопок в строке компании на узком экране разъезжается
     в колонку, а не сжимается в нечитаемые огрызки. */
  .company-row .admin-inline-btns,
  .admin-inline-btns { width: 100%; }
  .company-row .admin-btn { flex: 1 1 auto; }

  /* Заголовок и кнопки рядом: на телефоне им не хватает ширины,
     и кнопка уезжает за край. */
  .admin-row-between { flex-wrap: wrap; gap: 10px; }

  /* Полоса модерации не должна занимать пол-экрана. */
  .moderate-bar { padding: 8px 12px; font-size: 12px; }
}

/* --------------------------------- график мастера в его же кабинете */
/* Строка здесь на одно поле короче, чем в админке (вместимость ведёт
   владелец), а у дня есть пометка «из графика компании». Без своей
   ширины пометка вставала в столбик по слову. Правим точечно, не
   трогая .week-row в админке: там своя раскладка. */

/* Только /my: в админке контейнер с тем же id, и правило без .my-body
   сжимало её строку до пяти колонок — вместимость уезжала на новую
   строку (аудит §7.3). */
.my-body #week-rows .week-row { grid-template-columns: 1.7fr repeat(4, 1fr); }

.my-body #week-rows .week-name {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 8px;
  font-size: 13px; color: var(--text-on-dark, #e8eaee);
}

.my-body #week-rows .week-name .admin-role { white-space: nowrap; }

@media (max-width: 860px) {
  .my-body #week-rows .week-row { grid-template-columns: 1fr 1fr; }
  .my-body #week-rows .week-name { grid-column: 1 / -1; }
}

/* ------------------------------------------ состояние подключений */
/* Три состояния и три цвета: работает, заведено но с проблемой,
   не заведено. Один серый список не отвечал на главный вопрос —
   что чинить. */

.channel-row {
  border: 1px solid var(--divider-dark); border-left-width: 3px;
  border-radius: 10px; padding: 10px 12px; margin-bottom: 8px;
  background: #0a0f0a;
}
.channel-row.is-ok { border-left-color: #6fbf73; }
.channel-row.is-warn { border-left-color: #d7a13b; }
.channel-row.is-off { border-left-color: var(--divider-dark); opacity: 0.75; }
.channel-row .admin-error { margin-top: 4px; }
.channel-row .admin-note { margin-top: 4px; font-size: 12px; color: #d7a13b; }

/* ------------------------------------------ галочки прав у роли */
/* Прав у роли десяток, и в столбик они занимают экран. В две-три
   колонки видно весь набор разом — а набор и есть роль. */

.role-caps {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 4px 14px; margin: 6px 0 12px;
}

@media (max-width: 860px) {
  .role-caps { grid-template-columns: 1fr; }
}

/* ---------------------------------------------- чаты: входящие компании */
/* Разговор разворачивается НА МЕСТЕ, а не уводит на другую страницу:
   отвечая, человек держит перед глазами весь список — кто ещё ждёт.
   Уход со страницы этот список стирает. */

.chat-filters {
  display: flex; flex-wrap: wrap; gap: 12px; align-items: flex-end;
}
.chat-filters .admin-field { margin: 0; min-width: 180px; }

.chat-list { display: flex; flex-direction: column; gap: 8px; }

.chat-row {
  border: 1px solid var(--divider-dark); border-radius: 10px;
  background: #0a0f0a; overflow: hidden;
}
/* Разговор, где последним писал клиент, ждёт ответа — и это первое,
   что должно быть видно в списке. */
.chat-row.is-waiting { border-left: 3px solid var(--accent); }

.chat-head {
  display: grid; width: 100%; text-align: left; cursor: pointer;
  grid-template-columns: 130px minmax(120px, 1fr) auto minmax(0, 2fr) 90px;
  gap: 10px; align-items: center; padding: 12px 14px;
  background: none; border: 0; color: inherit; font: inherit;
}
.chat-head:hover { background: #0f1a10; }

.chat-channel {
  font-size: 11px; letter-spacing: 0.03em; padding: 3px 8px; border-radius: 999px;
  border: 1px solid var(--divider-dark); color: var(--mute-on-dark); white-space: nowrap;
  justify-self: start;
}
.chat-channel-telegram { border-color: #4a9fd8; color: #7cc0e8; }
.chat-channel-whatsapp { border-color: #55b76a; color: #7fd392; }
.chat-channel-web { border-color: var(--accent); color: var(--accent-bright); }

.chat-who { font-weight: 600; }
.chat-flags { display: flex; gap: 6px; align-items: center; justify-self: start; }
.chat-unread {
  background: var(--accent); color: #06140a; border-radius: 999px;
  padding: 1px 7px; font-size: 11px; font-weight: 600;
}
.chat-last, .chat-when { color: var(--mute-on-dark); font-size: 12.5px; }
.chat-last { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chat-when { text-align: right; white-space: nowrap; }

.chat-body { display: none; }
.chat-body.is-open { display: block; padding: 0 14px 14px; }

.chat-thread {
  display: flex; flex-direction: column; gap: 8px;
  max-height: 420px; overflow-y: auto; padding: 12px;
  border: 1px solid var(--divider-dark); border-radius: 8px; background: #070b07;
}
.chat-msg { display: grid; grid-template-columns: 110px 1fr 56px; gap: 10px; font-size: 13px; }
.chat-msg-who { color: var(--mute-on-dark); font-size: 11.5px; }
.chat-msg-text { white-space: pre-wrap; }
.chat-msg-at { color: var(--mute-on-dark); font-size: 11.5px; text-align: right; }
.chat-msg.is-client .chat-msg-text { color: var(--text-light); }
.chat-msg.is-agent .chat-msg-text { color: var(--mute-on-dark); }
/* Реплику человека видно отдельно от реплик агента: иначе разбирая
   разговор, не понять, где отвечали сами. */
.chat-msg.is-human .chat-msg-who { color: var(--accent-bright); }

.chat-reply { display: flex; flex-wrap: wrap; gap: 8px; align-items: flex-start; margin-top: 10px; }
.chat-reply textarea {
  flex: 1; min-width: 240px; padding: 10px; border-radius: 8px;
  border: 1px solid var(--divider-dark); background: #070b07; color: inherit;
  font: inherit; resize: vertical;
}
.chat-reply .chat-note { flex-basis: 100%; margin: 0; }

@media (max-width: 860px) {
  .chat-head { grid-template-columns: 1fr auto; gap: 6px; }
  .chat-last, .chat-when { grid-column: 1 / -1; }
  .chat-when { text-align: left; }
  .chat-msg { grid-template-columns: 1fr; gap: 2px; }
  .chat-msg-at { text-align: left; }
}

/* ------------------------------------- кто ведёт разговор */
/* Видно в списке, не открывая: иначе сотрудник не знает, занят
   разговор кем-то или ждёт его. */

.chat-lead {
  font-size: 11px; padding: 2px 8px; border-radius: 999px;
  border: 1px solid var(--accent); color: var(--accent-bright); white-space: nowrap;
}

.chat-handoff {
  display: flex; flex-wrap: wrap; gap: 10px; align-items: flex-end;
  margin-top: 10px;
}
.chat-handoff .admin-field { margin: 0; min-width: 220px; }
.chat-handoff-note { flex: 1; min-width: 240px; margin: 0; font-size: 12px; }

/* ------------------------------------------ запись из разговора */

.chat-booking {
  margin-top: 10px; padding: 10px 12px;
  border: 1px solid var(--divider-dark); border-radius: 8px;
}
.chat-booking-title { margin: 0 0 6px; font-size: 13px; }
.chat-booking-row {
  display: flex; flex-wrap: wrap; gap: 6px; align-items: center;
  padding: 4px 0; font-size: 13px;
}
.chat-picker:empty { display: none; }
.chat-picker { margin-top: 8px; }
.chat-picker-grid {
  display: grid; gap: 8px;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
}
/* Высота под окна держится и пока они грузятся: блок не прыгает,
   и кнопка «Записать» не уезжает из-под пальца. */
.chat-slots {
  display: flex; flex-wrap: wrap; gap: 6px; align-content: flex-start;
  min-height: 76px; margin: 8px 0;
}
.chat-slot {
  min-height: 34px; padding: 4px 10px; border-radius: 6px; cursor: pointer;
  border: 1px solid var(--divider-dark); background: #070b07; color: inherit; font: inherit;
}
.chat-slot.is-picked { border-color: var(--accent); color: var(--accent-bright); }

/* ------------------------------------------------- журнал */
.logs-lines {
  margin: 0; max-height: 70vh; overflow: auto; word-break: break-word;
  font-size: 13px; line-height: 1.45; color: var(--text-light);
}
.log-row {
  display: grid; grid-template-columns: 52px 180px 1fr; gap: 2px 12px;
  padding: 6px 0; border-bottom: 1px solid var(--divider-dark);
}
.log-time { font-family: var(--mono, 'JetBrains Mono', monospace); color: var(--mute-on-dark); }
.log-where { color: var(--mute-on-dark); font-size: 12px; }
.log-details { grid-column: 3; font-size: 11px; color: var(--mute-on-dark); }
@media (max-width: 640px) {
  .log-row { grid-template-columns: 52px 1fr; }
  .log-text, .log-details { grid-column: 1 / -1; }
}

/* «Фейковый ИИ» — выключатель над вкладками страницы агента. */
.ai-fake-row { display: flex; align-items: center; justify-content: space-between; gap: 12px 16px; flex-wrap: wrap; }
.ai-fake-row > div { flex: 1 1 260px; min-width: 0; }
.ai-fake-row .admin-title { margin: 0 0 4px; }
.ai-fake-row .admin-btn { width: auto; flex: 0 0 auto; min-width: 140px; margin-top: 0; }
.ai-fake-state { margin: 0; font-size: 14px; color: var(--accent-bright); }
.ai-fake-state.is-on { color: #f0c36a; }

/* «+ Записать» в плитке дня — открывает форму ручной записи на этот день. */
.cal-add {
  align-self: flex-start; font: inherit; font-size: 11px; color: var(--accent-bright);
  background: none; border: 1px dashed var(--divider-dark); border-radius: 6px;
  padding: 2px 8px; cursor: pointer;
}
.cal-add:hover { border-color: var(--accent); }
.cal-col-body { cursor: copy; }
.cal-col-body > * { cursor: pointer; }
button.cal-col-name { background: none; border: 0; padding: 0; font-family: inherit; text-align: left; cursor: pointer; }
button.cal-col-name:hover { color: var(--accent-bright); }

/* Настройки ИИ — подпись, поле, а под ним откуда значение и «как было»
   в конце строки, а не кнопкой посреди списка (аудит §7.3). */
.ai-setting { padding: 10px 0; border-bottom: 1px solid var(--divider-dark); }
.ai-setting .admin-field { margin-bottom: 4px; }
.ai-setting-meta { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-size: 11px; }
.ai-setting-meta .admin-btn { width: auto; margin-top: 0; }

/* Ключ провайдера: кто, откуда, состояние — строкой, кнопки маленькие
   справа (на телефоне — под ней). Раньше «Проверить» была зелёной
   кнопкой во всю ширину посреди списка (аудит мобильной версии). */
.ai-key { display: flex; justify-content: space-between; align-items: center; gap: 8px 12px;
  flex-wrap: wrap; padding: 10px 0; border-bottom: 1px solid var(--divider-dark); }
.ai-key-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ai-key-meta { font-size: 12px; color: var(--mute-on-dark); }
.ai-key-meta .is-bad { color: #f08a8a; }
.ai-key-actions { display: flex; gap: 6px; }
.ai-key-actions .admin-btn { width: auto; margin-top: 0; }
.verdicts-more { width: auto; margin-top: 10px; }

/* Значок сессии висит над страницей. На телефоне ширины на него и на
   заголовок в одну строку не хватает — опускаем страницу под значок,
   а строку «логин · роль» (#who) прячем: значок говорит то же самое.
   Сразу, а не по появлению значка: он приходит после ответа сервера,
   и отступ «по факту» сдвигал бы всю страницу. В админке вошли всегда. */
@media (max-width: 640px) {
  .admin-page { padding-top: 44px; }
  #who { display: none; }
}

/* Готовые графики над неделей (week-presets.js). */
.week-presets { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; margin: 0 0 12px; }
.week-presets .admin-btn { width: auto; margin-top: 0; }
.week-presets-label { margin: 0; }

/* Выбор цвета плашками (color-picker.js). */
.color-pick { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 8px; }
.color-pick-now { width: 28px; height: 28px; border-radius: 8px; border: 2px solid var(--divider-dark); }
.color-pick-now.is-empty { background: repeating-linear-gradient(45deg, #333 0 4px, #222 4px 8px) !important; }
.color-pick-swatch {
  width: 24px; height: 24px; min-height: 24px; padding: 0; border-radius: 6px; cursor: pointer;
  border: 1px solid rgba(255, 255, 255, .25);
}
.color-pick-swatch.is-picked { outline: 2px solid var(--accent-bright); outline-offset: 2px; }
.color-pick-own { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--mute-on-dark); cursor: pointer; }
.color-pick-own input[type="color"] { width: 28px; height: 28px; padding: 0; border: 0; background: none; cursor: pointer; }

/* «Проверить» в строке подключения — справа от названия. */
.channel-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.channel-head .channel-check { margin-left: auto; width: auto; margin-top: 0; }

/* «?» у канала — инструкция по подключению. */
.help-q {
  width: 22px; height: 22px; min-height: 22px; padding: 0; border-radius: 50%;
  border: 1px solid var(--divider-dark); background: none; color: var(--accent-bright);
  font-size: 12px; font-weight: 700; cursor: pointer; line-height: 1;
}
.channel-help { margin: 8px 0; padding: 10px 12px; border: 1px solid var(--divider-dark); border-radius: 8px; font-size: 13px; }
.channel-help ol { margin: 0; padding-left: 18px; display: flex; flex-direction: column; gap: 4px; }
.business-phone { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 8px; margin-top: 8px; }
.business-phone .admin-field { flex: 1 1 220px; margin-bottom: 0; }
.business-phone .admin-btn { width: auto; margin-top: 0; }

/* На телефоне — под палец: меньше 32px не попасть (cabinet.spec, «кнопки
   попадаемы»). Касается «?» у канала и плашек цвета. */
@media (max-width: 640px) {
  .help-q { width: 32px; height: 32px; min-height: 32px; font-size: 14px; }
  .color-pick-swatch { width: 32px; height: 32px; min-height: 32px; }
  .color-pick-now, .color-pick-own input[type="color"] { width: 32px; height: 32px; }
}

/* Заметка админов (admin-notes.js): кнопка в углу, вне потока вёрстки —
   её появление ничего на странице не сдвигает. */
.notes-fab {
  position: fixed; right: 16px; bottom: 16px; z-index: 900;
  width: 44px; height: 44px; border-radius: 50%; border: 1px solid var(--divider-dark);
  background: var(--card-dark); font-size: 20px; cursor: pointer; box-shadow: 0 4px 14px rgba(0,0,0,.35);
}
.notes-panel {
  position: fixed; right: 16px; bottom: 72px; z-index: 901;
  width: min(520px, calc(100vw - 32px)); max-height: calc(100vh - 100px);
  display: flex; flex-direction: column; gap: 6px;
  background: var(--card-dark); border: 1px solid var(--divider-dark); border-radius: 12px;
  padding: 14px; box-shadow: 0 8px 30px rgba(0,0,0,.45);
}
.notes-panel[hidden] { display: none; }
.notes-head { display: flex; justify-content: space-between; align-items: center; }
.notes-close { background: none; border: none; color: inherit; font-size: 24px; cursor: pointer; min-width: 32px; min-height: 32px; }
.notes-text {
  flex: 1; min-height: 260px; resize: vertical; width: 100%; box-sizing: border-box;
  background: var(--bg); color: inherit; border: 1px solid var(--divider-dark); border-radius: 6px;
  padding: 10px; font: 13px/1.45 ui-monospace, Consolas, monospace;
}
.notes-meta { font-size: 12px; opacity: .7; }

/* «Добавить специалиста» у компании (companies-page.js): свёрнуто, пока
   не нужно, — список компаний не превращается в стену форм. */
.company-spec { margin-top: 8px; }
.company-spec > summary { cursor: pointer; color: var(--accent-bright); font-size: 13px; min-height: 32px; display: flex; align-items: center; }
