/* =====================================================   Админка бота-аутрича – стили
   Vanilla CSS, без сборки и внешних зависимостей.

   Визуальный язык – общий с LMS (lms.larkinmd7.ru, `app/web/static/lms.css`):
   кремовый бумажный холст, три ступени поверхностей (canvas → ivory → white),
   один электрический кобальт #0068f9 на все интерактивные элементы,
   hairline #efefef вместо серых рамок, почти невидимые трёхслойные тени,
   капсулы у кнопок и пунктов меню, карточки 16px, Inter с ss01.
   Имена классов и разметка не менялись: это слой оформления, не вёрстки.
   ============================================================ */

:root {
  /* Палитра – токены LMS под именами, которые уже использует эта админка */
  --canvas:       #faf9f7;   /* кремовый холст */
  --ivory:        #fbfaf7;   /* вторая ступень поверхности */
  --lavender:     #f4f0ff;
  --sky:          #d5ecff;
  --powder:       #d6e4f1;

  --bg:           var(--canvas);
  --surface:      #ffffff;
  --surface-2:    var(--ivory);
  /* Панель навигации белая, как сайдбар админки LMS: она отделена от холста
     hairline-полосой, а не цветом. */
  --surface-nav:  #ffffff;
  --border:       #efefef;
  --border-2:     #efefef;
  --faint:        #cccccc;

  --text:         #121722;   /* ink */
  --text-2:       #666b75;   /* slate – подписи и мелкий текст */
  --text-3:       #8a8a8a;   /* steel – служебные цифры, метки времени */
  --text-nav:     #121722;
  --text-nav-on:  #024bb1;

  --accent:       #0068f9;   /* cobalt */
  --accent-dark:  #024bb1;   /* cobalt-deep */
  --accent-soft:  #e8f1ff;
  --accent-line:  #cddffd;   /* рамка активного состояния на accent-soft */
  --danger:       #b42318;   /* rust */
  --danger-soft:  #fff4f3;
  --danger-line:  #f5cfcb;
  --ok:           #046645;   /* forest */
  --warning:      #d99a1c;   /* amber */
  /* Панель навигации теперь светлая, и отдельный осветлённый зелёный не нужен:
     на белом читается тот же forest, что и во всём остальном интерфейсе. */
  --ok-nav:       var(--ok);
  --violet:       #6736eb;   /* декоративная метка, как в LMS */

  /* Геометрия: капсулы у кнопок и пунктов меню, 16px у карточек */
  --nav-w:        220px;
  --list-w:       308px;
  --profile-w:    320px;   /* панель профиля в разделе «Чат» */
  --r-sm:         8px;
  --r-md:         12px;
  --r-lg:         16px;
  --r-button:     48px;
  --r-pill:       100px;

  /* Тени LMS: трёхслойная микротень и мягкая 20px вместо «поднятых» блоков */
  --shadow-sm:    rgba(0,0,0,.07) 0 1px 1px 0, rgba(0,0,0,.04) 0 -1px 1px 0 inset, rgba(0,0,0,.14) 0 0 0 .5px inset;
  --shadow-md:    rgba(0,0,0,.07) 0 1px 1px 0, rgba(0,0,0,.14) 0 0 0 .5px inset, rgba(0,0,0,.04) 0 20px 20px -8px;
  --shadow-lg:    rgba(0,0,0,.06) 0 24px 40px -10px, rgba(0,0,0,.14) 0 0 0 .5px inset;

  --font: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI",
          "Helvetica Neue", Arial, "Noto Sans", sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
               "Liberation Mono", monospace;
}

* { box-sizing: border-box; }

html, body {
  height: 100%;
  margin: 0;
}

body {
  font-family: var(--font);
  font-size: 14px;
  line-height: 1.52;
  color: var(--text);
  background: var(--bg);
  /* ss01 и cv11 – те же начертания Inter, что и в LMS: одинаковая «a» и цифры */
  font-feature-settings: "ss01", "kern", "cv11";
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

[hidden] { display: none !important; }

button, input, textarea, select { font: inherit; color: inherit; }
/* Галки и радио красятся системой: без этого они остаются синими «как в ОС»
   и не попадают в кобальт остального интерфейса. */
input[type="checkbox"], input[type="radio"] { accent-color: var(--accent); }
/* Общий фокус: без внешних колец после мыши/Escape, нейтральный для Tab.
   !important перекрывает локальные кольца поздно загружаемых разделов. */
:focus { outline: none !important; }
html[data-keyboard-focus="true"] :focus-visible { outline: 1px solid var(--text-2) !important; outline-offset: -1px !important; }
html[data-keyboard-focus="true"] :is(.btn-primary,.pubv-close,.fxv-frame):focus-visible { outline-color: var(--surface) !important; }

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-thumb {
  background: #d8d8d6;
  border-radius: 8px;
  border: 3px solid transparent;
  background-clip: content-box;
}
::-webkit-scrollbar-thumb:hover { background: var(--faint); background-clip: content-box; }
::-webkit-scrollbar-track { background: transparent; }

/* =====================================================   Базовые элементы управления
   ============================================================ */

/* Капсула 48px, как в LMS: одна форма у всех кнопок интерфейса, различается
   только заливка – кобальт у главного действия, белый ghost у остальных. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  height: 38px;
  padding: 0 18px;
  border: 1px solid transparent;
  border-radius: var(--r-button);
  background: transparent;
  font-size: 14px;
  font-weight: 500;
  white-space: nowrap;
  cursor: pointer;
  transition: background .15s ease, border-color .15s ease, color .15s ease;
}
.btn:disabled { opacity: .5; cursor: default; box-shadow: none; }
.btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.btn-primary { background: var(--accent); border-color: var(--accent); color: #fff; }
.btn-primary:hover:not(:disabled) { background: var(--accent-dark); border-color: var(--accent-dark); }

/* Кнопка «Подключить Instagram» и подсказка под ней – отдельный блок над
   полем токена, чтобы основной путь читался первым, а ручной ввод – запасным. */
.channel-connect { display: flex; flex-direction: column; gap: 8px; margin-top: 16px; }
.channel-connect .btn { align-self: flex-start; }
.channel-connect .hint { margin: 0; }
.channel-connected { display: flex; flex-direction: column; gap: 12px; margin-top: 16px; }
.channel-connect-form { display: flex; gap: 8px; align-items: stretch; }
.channel-connect-form .input { flex: 1 1 240px; min-width: 0; }
.channel-connect-form .btn { flex: 0 0 auto; }
.channel-connect-form-col { flex-direction: column; align-items: stretch; max-width: 460px; }
.channel-connect-form-col .input { flex: 0 0 auto; width: 100%; }
.channel-connect-form-col .btn { align-self: flex-start; }
.channel-connected-foot { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.channel-connected-foot .hint { margin: 0; flex: 1 1 240px; }
.channel-extra { margin-top: 24px; padding-top: 20px; border-top: 1px solid var(--border); }
.channel-extra-head h3 { margin: 0 0 4px; font-size: 15px; }
.channel-extra-head .hint { margin: 0; }
.channel-extra-list { display: grid; gap: 8px; margin: 14px 0; }
.channel-extra-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 10px 12px; border: 1px solid var(--border); border-radius: 10px; }
.channel-extra-row strong, .channel-extra-row span { display: block; }
.channel-extra-row span { margin-top: 2px; color: var(--text-2); font-size: 13px; }
.channel-extra-form { flex-wrap: wrap; }
.channel-extra-form .input { flex: 1 1 210px; }

.btn-ghost {
  background: var(--surface);
  border-color: var(--border);
  color: var(--text);
  box-shadow: var(--shadow-sm);
}
.btn-ghost:hover:not(:disabled) { background-color: var(--ivory); border-color: var(--faint); color: var(--text); }

.btn-danger { background: var(--danger); border-color: var(--danger); color: #fff; }
.btn-danger:hover:not(:disabled) { background: #8f1c12; border-color: #8f1c12; }

.btn-danger-ghost { background: var(--surface); border-color: var(--border); color: var(--danger); box-shadow: var(--shadow-sm); }
.btn-danger-ghost:hover:not(:disabled) { background: var(--danger-soft); border-color: var(--danger-line); }

.btn-sm { height: 32px; padding: 0 14px; font-size: 13px; }
.btn-block { width: 100%; }

/* Поля: белые, hairline, 12px, фокус – кобальтовое кольцо (то же, что в LMS) */
.input, .textarea, .select {
  width: 100%;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface);
  padding: 9px 13px;
  color: var(--text);
  box-shadow: rgba(0,0,0,.04) 0 1px 1px 0;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.input::placeholder, .textarea::placeholder { color: var(--text-3); }
.input:hover:not(:focus), .textarea:hover:not(:focus), .select:hover:not(:focus) { border-color: var(--faint); }
.input:focus, .textarea:focus, .select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(0, 104, 249, .16);
}
.input { height: 40px; }
/* Однострочное поле: длинная подсказка не должна ломать высоту. */
.input::placeholder {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.textarea { resize: vertical; line-height: 1.55; }
.mono { font-family: var(--font-mono); font-size: 12.8px; }

.select {
  height: 40px;
  appearance: none;
  padding-right: 36px;
  background-image: var(--select-chevron);
  background-repeat: no-repeat;
  background-position: right 13px center;
}

.field { display: block; }
.field-label {
  display: block;
  margin-bottom: 6px;
  font-size: 13px;
  font-weight: 500;
  color: var(--text);
}

.hint { margin: 8px 0 0; font-size: 12.5px; line-height: 1.5; color: var(--text-2); }

.status { font-size: 12.5px; color: var(--text-2); }
.status.is-ok { color: var(--ok); }
.status.is-error { color: var(--danger); }

/* Сообщение об ошибке – плашка LMS: подложка, hairline в тон, 12px */
.alert {
  margin: 0;
  padding: 11px 14px;
  border-radius: var(--r-md);
  background: var(--danger-soft);
  border: 1px solid var(--danger-line);
  color: var(--danger);
  font-size: 13px;
}

/* =====================================================   Экран логина
   ============================================================ */

/* Вход повторяет `.auth-page` LMS: вертикальный градиент cream → sky → lavender
   и белая карточка 20px с мягкой тенью по центру. */
.login-screen {
  min-height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: linear-gradient(180deg, var(--canvas) 0%, var(--sky) 55%, var(--lavender) 100%);
}

.login-card {
  width: 100%;
  max-width: 400px;
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 28px;
  background: var(--surface);
  border-radius: 20px;
  box-shadow: var(--shadow-sm), rgba(0,0,0,.04) 0 20px 20px -8px;
}

/* Марка над заголовком – та же кобальтовая капсула-«док», что в шапке LMS */
.login-card::before {
  content: "";
  display: block;
  width: 30px;
  height: 20px;
  border-radius: var(--r-pill);
  background: var(--accent) linear-gradient(90deg, transparent 0 8px, #fff 8px 14px, transparent 14px);
}

.login-title {
  margin: 0;
  font-size: 30px;
  font-weight: 600;
  line-height: 1.12;
  letter-spacing: -.028em;
}
/* Подпись стоит под заголовком, а не над ним, поэтому это лид LMS (18px,
   обычное начертание), а не eyebrow капсом. */
.login-sub {
  margin: -12px 0 4px;
  font-size: 16px;
  line-height: 1.5;
  color: var(--text-2);
}

/* =====================================================   Каркас приложения
   ============================================================ */

.app {
  height: 100%;
  display: flex;
  align-items: stretch;
}

.view {
  flex: 1;
  min-width: 0;
  display: flex;
}

/* ---------- Левая панель навигации ---------- */

/* Сайдбар как в админке LMS (`.admin-side`): белая колонка 220px, отделённая
   от холста hairline-полосой, марка сверху, пункты – капсулы с иконкой и
   подписью в строку. Тёмный рельс 88px заменён именно здесь: это то, по чему
   интерфейс опознаётся как часть одной системы. */
.nav {
  flex: 0 0 var(--nav-w);
  width: var(--nav-w);
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 2px;
  padding: 20px 14px;
  background: var(--surface-nav);
  border-right: 1px solid var(--border);
  color: var(--text-nav);
}

/* Марка: кобальтовая капсула-«док» и название, как `.brand` в LMS */
.nav-brand {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 18px;
  padding-inline: 10px;
  color: var(--text);
  font-size: 16px;
  font-weight: 600;
  letter-spacing: -.012em;
}
.nav-brand::before {
  content: "";
  flex: none;
  width: 30px;
  height: 20px;
  border-radius: var(--r-pill);
  background: var(--accent) linear-gradient(90deg, transparent 0 8px, #fff 8px 14px, transparent 14px);
}
.nav-brand small { color: var(--text-2); font-size: 13px; font-weight: 500; letter-spacing: .01em; }

/* Тумблер «Отвечает / Молчит» под логотипом. Геометрия повторяет .nav-item:
   вертикальный блок с подписью мелким шрифтом, чтобы в узкой панели он читался
   как часть меню, а не как чужеродный виджет. */
/* Тумблер стоит в одной сетке с пунктами меню: та же строка «значок + подпись»,
   только на ivory-подложке с hairline, чтобы читаться органом управления,
   а не шестым разделом. */
.nav-switch {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 10px;
  margin-bottom: 14px;
  padding: 9px 14px;
  border: 1px solid var(--border);
  border-radius: var(--r-button);
  background: var(--ivory);
  box-shadow: var(--shadow-sm);
  color: var(--text);
  cursor: pointer;
  transition: background .15s ease, border-color .15s ease;
}
.nav-switch:hover { background: var(--surface); border-color: var(--faint); }
.nav-switch:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.nav-switch:disabled { cursor: default; opacity: .55; }

.nav-switch-track {
  position: relative;
  display: block;
  flex: none;
  width: 34px;
  height: 19px;
  border-radius: 999px;
  /* Выключен – нейтральный серый: «молчит» не тревога, а осознанный режим. */
  background: #c9c9c7;
  transition: background .15s ease;
}

.nav-switch-knob {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 15px;
  height: 15px;
  border-radius: 50%;
  background: #fff;
  transition: transform .15s ease;
}

.nav-switch[aria-checked="true"] .nav-switch-track { background: var(--ok-nav); }
.nav-switch[aria-checked="true"] .nav-switch-knob { transform: translateX(15px); }
.nav-switch[aria-checked="true"] .nav-switch-label { color: var(--ok-nav); }

.nav-switch-label {
  font-size: 14px;
  font-weight: 500;
  transition: color .15s ease;
}

/* Пункт меню – капсула в строку: иконка, подпись. Активный не «подсвечен
   ярче», а залит бледно-голубым с кобальтовой рамкой, как `aria-current`
   в сайдбаре LMS. */
.nav-item {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 10px;
  min-height: 40px;
  padding: 0 14px;
  border: 0;
  border-radius: var(--r-md);
  background: transparent;
  color: var(--text-nav);
  text-align: left;
  cursor: pointer;
  transition: background .15s ease, color .15s ease;
}
.nav-item:hover { background: var(--canvas); color: var(--text); }
.nav-item.is-active {
  background: var(--accent-soft);
  color: var(--text-nav-on);
  box-shadow: inset 0 0 0 1px var(--accent-line);
}
.nav-item:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

.nav-icon {
  flex: none;
  width: 20px;
  height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.nav-label { font-size: 15px; font-weight: 500; }

.nav-spacer { flex: 1; }
/* В колонке 220px «Автоматизация» помещается целиком: мягкий перенос из узкого
   рельса больше не нужен и только рвал бы слово посреди строки. */
.nav-label-wrap { white-space: nowrap; hyphens: none; }

/* «Выход» отделён чертой снизу, как `.admin-side-foot` в LMS */
.nav-item-quiet {
  margin-top: 6px;
  padding-top: 0;
  border-top: 1px solid var(--border);
  border-radius: 0 0 var(--r-md) var(--r-md);
  color: var(--text-2);
  min-height: 46px;
}
.nav-item-quiet:hover { color: var(--text); }

/* =====================================================   Раздел «Чат»
   ============================================================ */

.view-chat { display: flex; min-height: 0; }

/* ---------- Список чатов ---------- */

.chat-list {
  flex: 0 0 var(--list-w);
  width: var(--list-w);
  min-width: 0;
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border-right: 1px solid var(--border);
}

.pane-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  height: 64px;
  padding: 0 14px 0 18px;
  border-bottom: 1px solid var(--border-2);
}

.pane-title {
  margin: 0;
  font-size: 18px;
  font-weight: 600;
  letter-spacing: -.014em;
}

.chat-search { padding: 8px 10px 4px; }
.chat-search-input { width: 100%; height: 34px; padding: 0 10px; font-size: 13px; }
.chat-search-input::-webkit-search-cancel-button { -webkit-appearance: searchfield-cancel-button; }
/* Найденная реплика в превью: подсвечена, чтобы отличаться от «последнего сообщения». */
.chat-item-match { color: var(--accent-dark); }

.chat-list-more-wrap { padding: 10px 12px 14px; flex-shrink: 0; }
.chat-list-more-wrap .btn { width: 100%; }
.chat-list-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 6px 8px 12px;
}

.chat-item {
  width: 100%;
  /*
    min-width: 0 обязателен: элемент списка это <button>, а кнопки не
    сжимаются ниже содержимого. Без него длинное превью растягивало кнопку
    (замер: 2988px при колонке 307px), ellipsis не срабатывал, и весь список
    уезжал в горизонтальную прокрутку.
  */
  min-width: 0;
  max-width: 100%;
  /* flex, а не block: слева кружок канала, справа – тело с именем и превью.
     Тело обязано иметь свой min-width: 0, иначе ellipsis внутри него не
     сработает и список снова уедет в горизонтальную прокрутку. */
  display: flex;
  align-items: flex-start;
  gap: 10px;
  text-align: left;
  padding: 10px 12px;
  border: 0;
  border-radius: var(--r-md);
  background: transparent;
  cursor: pointer;
  transition: background .12s ease;
}
.chat-item + .chat-item { margin-top: 2px; }
.chat-item:hover { background: var(--canvas); }
/* Выбранная строка: бледно-голубая заливка с кобальтовой рамкой – та же
   механика, что у активного пункта меню и `aria-current` в LMS. */
.chat-item.is-active { background: var(--accent-soft); box-shadow: inset 0 0 0 1px var(--accent-line); }
.chat-item:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* ---------- Кружок канала в списке чатов ----------

   Из какого канала пришёл человек. Значок, а не буква: в списке из десятков
   диалогов это единственное, что различает одноимённых собеседников из
   Telegram и Instagram. Цвета брендовые, потому что узнаются мгновенно. */

.chat-avatar {
  flex: 0 0 auto;
  width: 30px;
  height: 30px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  color: #fff;
}
.chat-avatar svg { width: 17px; height: 17px; fill: currentColor; }

.chat-avatar.is-telegram { background: #2aabee; }
/* Instagram: узнаваемый градиент вместо плоского цвета. */
.chat-avatar.is-instagram {
  background: linear-gradient(45deg, #f9ce34 0%, #ee2a7b 50%, #6228d7 100%);
}
.chat-avatar.is-instagram svg { fill: none; }
.chat-avatar.is-instagram svg circle:last-of-type { fill: currentColor; }
/* Чат, созданный в админке: внешнего канала нет, значок нейтральный. */
.chat-avatar.is-local { background: var(--ivory); border: 1px solid var(--border); color: var(--text-2); }
.chat-avatar.is-local svg { fill: none; }

/* Аватарка собеседника: буква имени плюс бейдж канала снизу справа.

   Фото профиля Meta отдаёт только по тем, кто сам написал в Direct, и ссылка
   на него живёт несколько дней. Поэтому буква остаётся всегда, а фото
   ложится поверх неё (.chat-avatar-img): не открылось – под ним уже готовый
   кружок. Бейдж сохраняет то, ради чего кружок и заводился, – видно, из
   какого канала человек пришёл. */
.chat-avatar-wrap {
  position: relative;
  flex: 0 0 auto;
  width: 30px;
  height: 30px;
}

.chat-avatar-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  object-fit: cover;
  background: var(--ivory);
}

.chat-avatar.is-letter {
  width: 100%;
  height: 100%;
  font-size: 13px;
  font-weight: 600;
  /* Кириллица и латиница в кружке сидят ровнее без тесных межбуквенных
     интервалов основного шрифта. */
  letter-spacing: 0;
  line-height: 1;
  user-select: none;
}

/* Восемь спокойных оттенков: кружки должны различать собеседников, а не
   спорить с интерфейсом. Цвет закреплён за именем, поэтому при поиске и
   переупорядочивании чат остаётся того же цвета. */
.chat-avatar.tone-0 { background: #e8f1ff; color: #024bb1; }
.chat-avatar.tone-1 { background: #f4f0ff; color: #5b3fc4; }
.chat-avatar.tone-2 { background: #e6f6ef; color: #146c47; }
.chat-avatar.tone-3 { background: #fff2e4; color: #9a5312; }
.chat-avatar.tone-4 { background: #fdeef1; color: #a52a4a; }
.chat-avatar.tone-5 { background: #e4f4f7; color: #11626f; }
.chat-avatar.tone-6 { background: #f0f1e8; color: #5a6019; }
.chat-avatar.tone-7 { background: #efeef0; color: #4a4a55; }

/* Бейдж канала: кружок поверх правого нижнего угла аватарки. Обводка цветом
   подложки вырезает его из кружка, иначе значок сливается с буквой. */
.chat-avatar-badge {
  position: absolute;
  right: -2px;
  bottom: -2px;
  width: 14px;
  height: 14px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  color: #fff;
  box-shadow: 0 0 0 2px var(--surface);
}
.chat-avatar-badge svg { width: 9px; height: 9px; fill: currentColor; }
.chat-avatar-badge.is-telegram { background: #2aabee; }
.chat-avatar-badge.is-instagram {
  background: linear-gradient(45deg, #f9ce34 0%, #ee2a7b 50%, #6228d7 100%);
}
.chat-avatar-badge.is-instagram svg { fill: none; }
.chat-avatar-badge.is-instagram svg circle:last-of-type { fill: currentColor; }
.chat-avatar-badge.is-local {
  background: var(--ivory);
  border: 1px solid var(--border);
  color: var(--text-2);
}
.chat-avatar-badge.is-local svg { fill: none; }

/* В активном элементе списка подложка другая – обводка бейджа тоже. */
.chat-item.is-active .chat-avatar-badge { box-shadow: 0 0 0 2px var(--accent-soft); }

/* Тело элемента списка: всё, кроме кружка. */
.chat-item-body { flex: 1 1 auto; min-width: 0; }

.chat-item-top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  min-width: 0;
}

/* Нижняя строка элемента: точка окна, превью, счётчик. Сжимается только
   превью, точка и счётчик держат размер. */
.chat-item-bottom {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  margin-top: 2px;
}

/* Окно ответа Instagram: зелёная – писать можно, красная – закрыто. Видна
   прямо в списке, чтобы оператор не открывал чат, не писал ответ и только
   потом не узнавал, что отправить нельзя. */
.chat-item-window {
  flex: 0 0 auto;
  width: 7px;
  height: 7px;
  border-radius: 50%;
}
.chat-item-window.is-open { background: #1fa971; }
.chat-item-window.is-closed { background: #e5484d; }

/* Реплики человека без нашего ответа. */
.chat-item-unread {
  flex: 0 0 auto;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: 9px;
  background: var(--accent);
  color: #fff;
  font-size: 11px;
  font-weight: 600;
  line-height: 18px;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

/* Галочки статуса: одна – доставлено, две – прочитано. */
.ticks {
  flex: 0 0 auto;
  display: inline-flex;
  align-self: center;
  color: var(--text-3);
}
.ticks.is-read { color: #1fa971; }
.chat-item-top .ticks { margin-right: -6px; }
.bubble-time .ticks,
.att-time .ticks { margin-left: 4px; vertical-align: -1px; color: inherit; }
.msg-bot .bubble-time .ticks.is-read { color: #fff; }

.chat-item-title {
  display: block;
  min-width: 0;
  flex: 1 1 auto;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.chat-item.is-active .chat-item-title { color: var(--accent-dark); }

.chat-item-time {
  flex: 0 0 auto;
  font-size: 11.5px;
  color: var(--text-3);
  font-variant-numeric: tabular-nums;
}

/* Подписчики и «подписан на нас» между именем и временем. Оба flex: 0 0 auto:
   сжимается только имя, иначе цифра ломалась бы переносом, а многоточие
   уходило из имени, где оно и должно быть. Появляются лишь когда данные есть:
   профиль Instagram отдаёт только по написавшим в Direct. */
.chat-item-followers,
.chat-item-follows {
  flex: 0 0 auto;
  font-size: 11.5px;
  color: var(--text-3);
  line-height: 1;
}
.chat-item-followers { font-variant-numeric: tabular-nums; }
.chat-item-follows { color: var(--ok); font-weight: 600; }

.chat-item-preview {
  /*
    display: block обязателен. В разметке это <span>, а у строчного элемента
    ширина, overflow и text-overflow не действуют вовсе: превью раздувалось до
    10249px внутри кнопки шириной 291px и уводило список в горизонтальную
    прокрутку. Блочное отображение даёт ellipsis точку отсчёта.
  */
  display: block;
  flex: 1 1 auto;
  min-width: 0;
  font-size: 12.5px;
  color: var(--text-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ---------- Переписка ---------- */

/* Лента переписки лежит на кремовом холсте, а шапка и поле ввода – белые:
   те же три ступени поверхностей, что во всём LMS. */
.chat-room {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  background: var(--canvas);
}

.chat-head {
  display: flex;
  align-items: center;
  gap: 12px;
  height: 64px;
  padding: 0 18px;
  background: var(--surface);
  border-bottom: 1px solid var(--border-2);
}

.chat-head-text { flex: 1; min-width: 0; }

.chat-title {
  margin: 0;
  /* Кружок канала стоит перед именем, поэтому заголовок – flex. Обрезка
     переехала на .chat-title-text: на самом flex-контейнере ellipsis не
     действует. */
  display: flex;
  align-items: center;
  gap: 9px;
  min-width: 0;
  font-size: 18px;
  font-weight: 600;
  letter-spacing: -.014em;
}
.chat-title .chat-avatar { width: 26px; height: 26px; }
.chat-title .chat-avatar svg { width: 15px; height: 15px; }
/* Аватарка с буквой в шапке чуть меньше, чем в списке: заголовок и так
   крупный, и кружок не должен спорить с именем собеседника. */
.chat-title .chat-avatar-wrap { width: 26px; height: 26px; }
.chat-title .chat-avatar.is-letter { font-size: 12px; }
.chat-title .chat-avatar-badge { width: 13px; height: 13px; }
.chat-title .chat-avatar-badge svg { width: 8px; height: 8px; }

.chat-title-text {
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.chat-subtitle {
  margin: 1px 0 0;
  font-size: 12.5px;
  color: var(--text-3);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.btn-back {
  display: none;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  margin-left: -6px;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--text-2);
  cursor: pointer;
}
.btn-back:hover { background: var(--canvas); color: var(--text); }
.btn-back svg {
  width: 20px; height: 20px;
  fill: none; stroke: currentColor; stroke-width: 1.7;
  stroke-linecap: round; stroke-linejoin: round;
}

/* ---------- Тумблер «ИИ отвечает» в шапке чата (§ 5.38) ----------

   Сам тумблер – общий .channel-switch. Подпись срока стоит под ним
   столбиком и читается вместе с подписью тумблера: «ИИ молчит / вернётся
   через 12 мин». В строку они не помещаются: колонка переписки на 1280
   рядом с панелью профиля около 430px, и имя собеседника сжималось до
   одной аватарки. На узком экране подпись тумблера скрыта общим правилом,
   а срок уходит второй строкой шапки (блок в адаптивной части). */
.chat-ai {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  min-width: 0;
}
.chat-ai[hidden] { display: none; }
.chat-ai .channel-switch { padding-top: 4px; padding-bottom: 4px; }
.chat-ai-note {
  order: 2;
  margin-top: -2px;
  padding-right: 12px;
  font-size: 12px;
  line-height: 1.3;
  color: var(--text-3);
  white-space: nowrap;
}
.chat-ai-note[hidden] { display: none; }

/* ---------- Панель профиля ----------

   Третья колонка раздела «Чат»: шапка профиля собеседника и история его
   взаимодействий с аккаунтом. На широком экране открыта всегда; уже 1100px
   рядом с перепиской не помещается и выезжает поверх неё по кнопке
   «Профиль» (блок в адаптивной части файла). */

.chat-profile {
  flex: 0 0 var(--profile-w);
  width: var(--profile-w);
  min-width: 0;
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border-left: 1px solid var(--border);
}
.chat-profile[hidden] { display: none; }

.chat-profile-close { display: none; margin-left: 0; margin-right: -6px; }
.chat-profile-open { display: none; gap: 6px; }
.chat-profile-open svg {
  width: 16px; height: 16px;
  fill: none; stroke: currentColor; stroke-width: 1.7;
  stroke-linecap: round; stroke-linejoin: round;
}

.chat-profile-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 0 0 20px;
}

/* Шапка строкой, а не столбиком по центру: панель узкая, и главное в ней –
   лента ниже. Аватарка слева, справа имя, ник и одна строка статуса. */
.profile-card {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  border-bottom: 1px solid var(--border-2);
}

/* Крупная аватарка собирается из того же channelAvatar, что и в списке:
   размеры переопределяются здесь, разметка одна. */
.profile-avatar { display: flex; flex: 0 0 auto; }
.profile-avatar .chat-avatar-wrap { width: 48px; height: 48px; }
.profile-avatar .chat-avatar.is-letter { font-size: 19px; }
.profile-avatar .chat-avatar { width: 48px; height: 48px; }
.profile-avatar .chat-avatar svg { width: 22px; height: 22px; }
.profile-avatar .chat-avatar-badge { width: 17px; height: 17px; right: -1px; bottom: -1px; }
.profile-avatar .chat-avatar-badge svg { width: 10px; height: 10px; }

.profile-names { min-width: 0; flex: 1 1 auto; }
.profile-contact { padding: 16px; border-bottom: 1px solid var(--border-2); }
.profile-contact-row { display: flex; flex-direction: column; gap: 5px; margin-bottom: 12px; }
.profile-contact-label { font-size: 12px; color: var(--text-3); }
.profile-contact-phone { font-size: 14px; color: var(--text); overflow-wrap: anywhere; }
.profile-phone-line { display: flex; flex-wrap: wrap; align-items: baseline; gap: 5px 12px; }
.profile-phone-origin { font-size: 12px; color: var(--text-3); }
.profile-person-channels { margin: 2px 0 10px; }
.profile-person-channel { display: flex; align-items: center; gap: 10px; width: 100%; padding: 8px 0; border: 0; border-radius: var(--r-sm); background: transparent; font: inherit; color: var(--text); text-align: left; cursor: pointer; }
.profile-person-channel:hover { background: var(--canvas); }
.profile-person-channel-body { display: flex; flex: 1; min-width: 0; flex-direction: column; overflow-wrap: anywhere; }
.profile-person-channel-body strong { font-size: 13px; font-weight: 500; }
.profile-person-channel-body > span { font-size: 12px; color: var(--text-3); }
.profile-person-origin { margin: 8px 0 16px; font-size: 12px; color: var(--text-2); }
.profile-funnel-path { padding: 14px 16px; border-bottom: 1px solid var(--border-2); }
.profile-funnel-path > h3 { margin-bottom: 12px; }
.profile-route-event { display: flex; align-items: flex-start; gap: 9px; margin-top: 12px; }
.profile-route-icon { flex: 0 0 20px; display: flex; justify-content: center; color: var(--text-3); }
.profile-route-icon svg { width: 15px; height: 15px; fill: currentColor; }
.profile-route-body { display: flex; flex: 1; min-width: 0; flex-direction: column; overflow-wrap: anywhere; }
.profile-route-body strong { font-size: 12.5px; font-weight: 500; }
.profile-route-body > span, .profile-route-event time { font-size: 12px; color: var(--text-3); }
.profile-route-event time { flex-shrink: 0; }
.chat-linked-badges { display: flex; gap: 3px; position: absolute; right: -7px; bottom: -2px; }
.chat-linked-badges .chat-avatar-badge { position: static; }
.chat-title .chat-avatar-wrap:has(.chat-linked-badges) { margin-right: 5px; }
.chat-head:has(.chat-person-tabs:not([hidden])) { position: relative; height: auto; min-height: 92px; padding-bottom: 43px; }
.chat-person-tabs { position: absolute; left: 16px; bottom: 8px; max-width: calc(100% - 32px); padding: 2px; box-shadow: none; }
.chat-person-tabs .segmented-item { min-height: 28px; padding: 0 12px; display: inline-flex; align-items: center; justify-content: center; gap: 6px; font-size: 13px; }
.chat-person-tabs .segmented-item svg { width: 15px; height: 15px; fill: currentColor; }
@media (pointer: coarse) {
  .chat-person-tabs .segmented-item { min-height: 44px; }
  .chat-head:has(.chat-person-tabs:not([hidden])) { min-height: 108px; padding-bottom: 59px; }
}
.profile-contact .profile-telegram-link { margin-bottom: 16px; font-size: 13px; line-height: 1.5; color: var(--accent); overflow-wrap: anywhere; }
.profile-contact-tags { display: flex; flex-wrap: wrap; gap: 6px; margin: 10px 0; }
.profile-contact-tag { padding: 5px 9px; background: var(--accent-soft); color: var(--accent); border-radius: var(--r-pill); font-size: 13px; overflow-wrap: anywhere; max-width: 100%; }
.profile-tag-form { margin-top: 12px; }
.profile-tag-form[hidden] { display: none; }
.profile-tag-form .input { width: 100%; }
.profile-tag-options { display: flex; flex-direction: column; gap: 4px; max-height: 180px; overflow-y: auto; margin-top: 8px; }
.profile-tag-option { height: auto; min-height: 32px; flex-shrink: 0; text-align: left; justify-content: flex-start; white-space: normal; overflow-wrap: anywhere; }
.profile-tag-status { margin: 8px 0; }
.profile-tag-actions { display: flex; justify-content: flex-end; flex-wrap: wrap; gap: 6px; }
.profile-name {
  margin: 0;
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -.011em;
  min-width: 0;
}
.profile-name,
.profile-username { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.profile-username {
  display: block;
  font-size: 13px;
  color: var(--accent-dark);
  text-decoration: none;
}
.profile-username:hover { text-decoration: underline; }
.profile-username:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
/* Ника без имени: он и есть заголовок карточки. */
.profile-names > .profile-username:first-child { font-size: 15px; font-weight: 600; color: var(--text); }

.profile-verified { flex: 0 0 auto; display: inline-flex; }
.profile-verified svg { width: 15px; height: 15px; fill: var(--accent); }
.profile-verified .profile-verified-tick {
  fill: none; stroke: #fff; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
}

/* Подписчики, взаимность и счётчик ленты одной строкой через точку. */
.profile-stat {
  margin: 3px 0 0;
  font-size: 12px;
  line-height: 1.35;
  color: var(--text-3);
}

/* Описание профиля Instagram по API не отдаёт (проверено живым запросом),
   поэтому вместо пустого места – ссылка туда, где оно видно целиком. */
.profile-bio-link {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  margin-top: 3px;
  font-size: 12px;
  color: var(--text-2);
  text-decoration: none;
}
.profile-bio-link:hover { color: var(--accent-dark); }
.profile-bio-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
.profile-bio-link svg {
  width: 13px; height: 13px;
  fill: none; stroke: currentColor; stroke-width: 1.8;
  stroke-linecap: round; stroke-linejoin: round;
}

/* Строка про ограничение платформы стоит под шапкой, а не внутри неё:
   в строчной раскладке ей там места нет. */
.profile-note-row { padding: 10px 16px 0; }

.profile-note {
  margin: 0;
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--text-3);
  text-wrap: pretty;
}
.profile-loading { padding: 22px 18px; text-align: center; }
.profile-history > .profile-note { padding: 4px 0 0; }

.profile-history { padding: 14px 16px 0; }
.profile-history-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 8px;
}
.profile-history-title { margin: 0; font-size: 14px; font-weight: 600; letter-spacing: -.006em; }

/* Вид взаимодействий: кнопка с выпадающим списком. Рядом чипов со
   счётчиками в узкой панели занимал две строки и переносился по-разному у
   каждого человека; строка заголовка не должна прыгать. */
.profile-kind-btn {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  height: 26px;
  padding: 0 6px 0 10px;
  border: 1px solid var(--border);
  border-radius: var(--r-pill);
  background: var(--surface-2);
  font: inherit;
  font-size: 12.5px;
  color: var(--text);
  cursor: pointer;
  white-space: nowrap;
}
.profile-kind-btn:hover { border-color: var(--faint); }
.profile-kind-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.profile-kind-btn[aria-expanded="true"] {
  background: var(--accent-soft);
  border-color: var(--accent-line);
  color: var(--accent-dark);
}
.profile-kind-btn svg {
  width: 13px; height: 13px;
  fill: none; stroke: currentColor; stroke-width: 1.9;
  stroke-linecap: round; stroke-linejoin: round;
}
.profile-kind-btn[aria-expanded="true"] svg { transform: rotate(180deg); }

.profile-kind-count {
  font-size: 11.5px;
  color: var(--text-3);
  font-variant-numeric: tabular-nums;
  /* Своё поле слева: без него цифра читается как часть слова – «Все5». */
  margin-left: 2px;
}
.profile-kind-btn[aria-expanded="true"] .profile-kind-count { color: var(--accent-dark); }

.profile-kind-menu { min-width: 172px; }

/* Порядок ушёл на свою строку под заголовок: в одной строке с кнопкой вида
   ему на 320px уже не хватало места. */
.profile-sort {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  margin: 0 0 10px -8px;
  padding: 3px 4px 3px 8px;
  border: 0;
  border-radius: var(--r-sm);
  background: none;
  font: inherit;
  font-size: 12.5px;
  color: var(--text-2);
  cursor: pointer;
}
.profile-sort:hover { background: var(--canvas); color: var(--text); }
.profile-sort:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.profile-sort svg {
  width: 14px; height: 14px;
  fill: none; stroke: currentColor; stroke-width: 1.8;
  stroke-linecap: round; stroke-linejoin: round;
}
.profile-sort svg.is-up { transform: rotate(180deg); }

.profile-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.profile-item {
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface);
}
.profile-item-head { display: flex; align-items: center; gap: 6px; min-width: 0; }
.profile-item-kind {
  flex: 1 1 auto;
  min-width: 0;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.profile-item-time { flex: 0 0 auto; font-size: 11.5px; color: var(--text-3); font-variant-numeric: tabular-nums; }
.profile-item-text {
  margin: 5px 0 0;
  font-size: 13.5px;
  line-height: 1.4;
  overflow-wrap: anywhere;
  white-space: pre-wrap;
}
.profile-item-text.is-clamped {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  overflow: hidden;
}
.profile-item-sub { margin: 5px 0 0; font-size: 12px; color: var(--text-3); overflow-wrap: anywhere; }
.profile-item-sub + .profile-item-text { margin-top: 2px; }
.profile-item-sub + .profile-item-sub { margin-top: 1px; }

.profile-media {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 8px;
  padding: 5px 8px 5px 5px;
  border-radius: var(--r-sm);
  background: var(--canvas);
  color: var(--text-2);
  text-decoration: none;
  min-width: 0;
}
a.profile-media:hover { color: var(--accent-dark); }
a.profile-media:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.profile-media-thumb {
  flex: 0 0 auto;
  width: 30px;
  height: 38px;
  border-radius: 5px;
  object-fit: cover;
  background: var(--border);
}
.profile-media-body { min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.profile-media-text {
  min-width: 0;
  font-size: 12px;
  line-height: 1.35;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
}
/* Дата выхода и просмотры: то, по чему ролик узнаётся быстрее, чем по подписи. */
.profile-media-meta {
  font-size: 11.5px;
  color: var(--text-3);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.profile-empty { padding: 18px 4px; }

/* ---------- Сообщения ---------- */

.messages {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 22px 24px 8px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

/* Стороны как в мессенджерах: собеседник (user) слева нейтральным пузырём,
   наш аккаунт (assistant: бот или оператор) справа акцентным. */
.message-day { display: flex; justify-content: center; margin: 8px 0 2px; }
.message-day time {
  padding: 5px 12px;
  border-radius: var(--r-pill);
  background: var(--surface-2);
  color: var(--text-2);
  font-size: 12px;
  font-weight: 600;
  line-height: 1.4;
}

.msg { display: flex; }
.msg-user { justify-content: flex-start; }
.msg-bot  { justify-content: flex-end; }

/* Пузырь – карточка LMS в миниатюре: 16px, hairline, микротень. Ответ от нас
   залит кобальтом, реплика собеседника белая. */
.bubble {
  max-width: min(640px, 74%);
  padding: 11px 15px 8px;
  border-radius: var(--r-lg);
  word-wrap: break-word;
  overflow-wrap: anywhere;
}

.msg-user .bubble {
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-sm);
  border-bottom-left-radius: 6px;
}
.msg-bot .bubble {
  background: var(--accent);
  color: #fff;
  border-bottom-right-radius: 6px;
}

.bubble-text {
  margin: 0;
  font-size: 14.5px;
  line-height: 1.52;
  white-space: pre-wrap;
}

.bubble-text a { color: inherit; text-decoration: underline; }
.bubble-text code { font-family: monospace; overflow-wrap: anywhere; }

/* Вложение: пузырь пунктиром вместо заливки.

   Содержимого у нас нет и не будет, пока Meta не откроет доступ: ссылки на
   медиа живут около суток, в базе лежит только тип. Пунктир честно говорит
   «здесь медиа, которого админка не показывает», и отличает такую запись от
   настоящей реплики – в ленте, где половина сообщений это вложения, иначе
   не прочитать, где человек писал текстом, а где прислал фото. */
.bubble.is-attachment {
  padding: 8px 13px;
  background: transparent;
  border: 1px dashed var(--faint);
  box-shadow: none;
  color: var(--text-2);
  /* По содержимому, а не во всю разрешённую ширину: пометка из двух слов не
     должна занимать столько же места, сколько абзац текста. */
  max-width: max-content;
}
.msg-bot .bubble.is-attachment {
  border-color: var(--accent-line);
  color: var(--accent-dark);
  background: var(--accent-soft);
}

.att {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 14px;
  line-height: 1.4;
}
.att-icon {
  flex: 0 0 auto;
  width: 16px;
  height: 16px;
  opacity: .85;
}
.att-label { font-weight: 500; }

/* Карточка с кнопками – то, что человек реально получил от имени Михаила.

   Рисуется белой карточкой, а не синим пузырём ответа: это не реплика
   словами, а элемент интерфейса Instagram, и в ленте он должен читаться как
   отдельная сущность. Кнопки живые: под роликом обещано «отправил в директ»,
   и проверить, куда именно ведёт кнопка, оператор должен одним кликом. */
.bubble.is-card {
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-sm);
  padding: 10px 12px 8px;
  border-bottom-right-radius: 6px;
}

/* Подпись сверху: иначе белая карточка справа читается как реплика
   собеседника, которая почему-то оказалась не с той стороны. */
.card-tag {
  display: flex;
  align-items: center;
  gap: 5px;
  margin-bottom: 7px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .02em;
  text-transform: uppercase;
  color: var(--accent-dark);
}
.card-tag svg { width: 13px; height: 13px; }

.card-image {
  display: block;
  width: 100%;
  max-height: 180px;
  object-fit: cover;
  border-radius: var(--r-md);
  margin-bottom: 8px;
}

.card-title {
  margin: 0;
  font-size: 14.5px;
  font-weight: 600;
  line-height: 1.4;
}
.card-subtitle {
  margin: 3px 0 0;
  font-size: 13px;
  line-height: 1.45;
  color: var(--text-2);
}

/* Кнопки столбиком и во всю ширину – так их показывает сам Instagram. */
.card-buttons {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 9px;
}
.card-button {
  display: block;
  padding: 7px 10px;
  border: 1px solid var(--accent-line);
  border-radius: var(--r-md);
  background: var(--accent-soft);
  color: var(--accent-dark);
  font-size: 13px;
  font-weight: 500;
  text-align: center;
  text-decoration: none;
  overflow-wrap: anywhere;
}
.card-button:hover { background: #dbe9ff; }
/* Кнопка без рабочей ссылки: показываем, но кликать нечего. */
.card-button.is-dead {
  background: var(--ivory);
  border-color: var(--border);
  color: var(--text-3);
}

/* Откуда сообщение, если не из админки. Приглушённая строка над текстом:
   это справка, а не часть того, что увидел человек. */
.bubble-origin {
  display: block;
  margin-bottom: 4px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .02em;
  text-transform: uppercase;
  opacity: .72;
}

/* Текст с кнопками в синем пузыре ответа: кнопки белые, как у Instagram,
   и остаются живыми ссылками. */
.msg-bot .bubble.has-buttons .card-buttons { margin: 9px 0 4px; }
.msg-bot .bubble.has-buttons .card-button {
  border-color: transparent;
  background: #fff;
  color: var(--accent-dark);
  font-weight: 600;
}
.msg-bot .bubble.has-buttons .card-button:hover { background: var(--accent-soft); }

/* Время в той же строке: пометка короткая, и время под ней растягивало пузырь
   почти вдвое ради двух слов. */
.att-time {
  margin-left: 4px;
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  color: var(--text-3);
  white-space: nowrap;
}
.msg-bot .bubble.is-attachment .att-time { color: var(--accent-dark); opacity: .7; }

.bubble-time {
  display: block;
  margin-top: 3px;
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  text-align: right;
  color: var(--text-3);
}
.msg-bot .bubble-time { color: rgba(255, 255, 255, .78); }

/* Ошибка ответа модели – видимой строкой прямо в переписке */
.msg .bubble-error {
  background: var(--danger-soft);
  border: 1px solid var(--danger-line);
  box-shadow: none;
  color: var(--danger);
}
.msg .bubble-error .bubble-time { color: var(--text-3); }

/* Индикатор «печатает» */
.typing { display: flex; align-items: center; gap: 7px; }
.typing-dots { display: inline-flex; gap: 4px; }
.typing-dots i {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: rgba(255, 255, 255, .85);
  animation: typing-bounce 1.1s infinite ease-in-out;
}
.typing-dots i:nth-child(2) { animation-delay: .16s; }
.typing-dots i:nth-child(3) { animation-delay: .32s; }
.typing-label { font-size: 12.5px; color: rgba(255, 255, 255, .85); }

@keyframes typing-bounce {
  0%, 70%, 100% { transform: translateY(0);   opacity: .45; }
  35%           { transform: translateY(-4px); opacity: 1;  }
}
@media (prefers-reduced-motion: reduce) {
  .typing-dots i { animation: none; opacity: .6; }
}

/* ---------- Поле ввода ---------- */

/* Боевой чат: над полем ввода стоит переключатель роли, поэтому внешний
   контейнер – колонка, а сама строка ввода живёт в .composer-line.
   Тестовый чат остаётся одной строкой: там роль всегда одна и та же. */
.composer {
  display: flex;
  flex-direction: column;
  gap: 9px;
  padding: 12px 24px 18px;
  background: var(--surface);
  border-top: 1px solid var(--border-2);
}
.composer-line {
  display: flex;
  align-items: flex-end;
  gap: 10px;
  min-width: 0;
}
/* Композер тестового чата: строка, а не столбец; отступы и фон под панель
   справа от промпта. */
.composer-test {
  flex-direction: row;
  align-items: flex-end;
  gap: 10px;
  padding: 12px 22px 10px;
  background: var(--surface);
  border-top: 0;
}

/* Строка над полем ввода: подпись, куда уйдёт сообщение. Переключатель
   роли отсюда убран, из админки пишут только от имени бота. */
.composer-role {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px 10px;
  min-width: 0;
}
.composer-role-note {
  font-size: 12.5px;
  line-height: 1.4;
  color: var(--text-3);
  min-width: 0;
  /* С панелью профиля колонка переписки уже, и подпись переносится: без
     балансировки на второй строке оставалась одна буква «ч». */
  text-wrap: balance;
}

/* ---------- Окно ответа закрыто ----------

   Instagram принимает ответ только в сутки после сообщения человека. Когда
   окно закрыто, отправка невозможна ни в какой роли, и композер это
   показывает целиком: причина красным и приглушённое поле.

   Красный здесь уместен, в отличие от бейджа канала: канал жив и это не
   поломка, но действие сейчас недоступно, и оператор должен понять это до
   того, как наберёт текст. */
.composer-role-note.is-blocked { color: var(--danger); font-weight: 500; }
.composer.is-blocked .composer-input { background: var(--surface-2); }
.composer.is-blocked .composer-input::placeholder { color: var(--text-3); }

/* Компактный вариант переключателя: он служебный и не должен спорить по весу
   с полем ввода и кнопкой отправки. */
.segmented-sm { padding: 2px; }
.segmented-sm .segmented-item { padding: 5px 11px; font-size: 12.5px; }

.composer-input {
  flex: 1;
  min-height: 42px;
  max-height: 180px;
  padding: 10px 15px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface);
  box-shadow: rgba(0,0,0,.04) 0 1px 1px 0;
  line-height: 1.45;
  resize: none;
  overflow-y: hidden;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.composer-input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(0, 104, 249, .16);
}
/*
  Подсказка не прокручивается вместе с содержимым: если она не влезает в
  строку, вторая строка просто срезается по высоте поля. Держим её в одну
  строку с многоточием, а сам ввод по-прежнему переносится и прокручивается.
*/
.composer-input::placeholder {
  color: var(--text-3);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.btn-send { height: 42px; flex: 0 0 auto; }

/* ---------- Пустые состояния ---------- */

/* Пунктирная рамка на ivory – блок `.empty` из LMS */
.empty {
  margin: auto;
  max-width: 360px;
  padding: 28px 20px;
  text-align: center;
  border: 1px dashed var(--border);
  border-radius: var(--r-lg);
  background: var(--ivory);
  color: var(--text-2);
}
.empty-title {
  margin: 0 0 4px;
  font-size: 15px;
  font-weight: 600;
  color: var(--text);
}
.empty-text { margin: 0; font-size: 13.5px; line-height: 1.5; }

.list-empty {
  padding: 24px 16px;
  text-align: center;
  font-size: 13.5px;
  color: var(--text-2);
}

/* =====================================================   Раздел «Настройки»
   ============================================================ */

.view-settings { display: flex; min-height: 0; }

.settings-scroll {
  flex: 1;
  min-width: 0;
  overflow-y: auto;
}

/* Ширина колонки как в админке LMS (`.admin-shell`): контент не растягивается
   на всю ширину монитора, по краям остаётся воздух. */
.settings-inner {
  max-width: 1360px;
  margin: 0 auto;
  padding: 28px 32px 64px;
}
/* Вкладка «Промпт» живёт в один экран: страница не прокручивается, всю
   прокрутку берут на себя блоки внутри карточек. Остальные вкладки остаются
   обычными – они длинные по смыслу. */
@media (min-width: 1101px) {
  .settings-inner:has(> #tabpanel-prompt:not([hidden])) {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    height: 100vh;
    padding-bottom: 22px;
  }
  .settings-inner:has(> #tabpanel-prompt:not([hidden])) > .page-head,
  .settings-inner:has(> #tabpanel-prompt:not([hidden])) > .segmented-tabs { flex: 0 0 auto; }
  .settings-inner:has(> #tabpanel-prompt:not([hidden])) > #tabpanel-prompt {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
  }
}

/* Заголовок раздела в масштабе админки LMS: плотный крупный заголовок и лид
   обычным начертанием под ним. */
.page-head { margin-bottom: 20px; }
.page-title {
  margin: 0;
  font-size: clamp(28px, 3.2vw, 34px);
  font-weight: 600;
  line-height: 1.12;
  letter-spacing: -.028em;
}
.page-sub { margin: 8px 0 0; max-width: 900px; font-size: 16px; line-height: 1.5; color: var(--text-2); }

/* ---------- Сегментированный переключатель вкладок ---------- */

/* Вкладки-капсула LMS (`.tabs`): белый контейнер с hairline и тенью, активная
   вкладка залита кобальтом. Один индикатор вместо «белая плашка потолще». */
.segmented {
  display: inline-flex;
  gap: 2px;
  padding: 4px;
  border: 1px solid var(--border);
  border-radius: var(--r-button);
  background: var(--surface);
  box-shadow: var(--shadow-sm);
}

.segmented-item {
  min-height: 34px;
  padding: 0 16px;
  border: 0;
  border-radius: var(--r-button);
  background: transparent;
  color: var(--text);
  font: inherit;
  font-size: 14px;
  font-weight: 500;
  white-space: nowrap;
  cursor: pointer;
  transition: background .15s ease, color .15s ease;
}
.segmented-item:hover { background: var(--canvas); }
.segmented-item.is-active {
  background: var(--accent);
  color: #fff;
  box-shadow: none;
}
.segmented-item.is-active:hover { background: var(--accent); }
.segmented-item:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* Полоса вкладок раздела «Настройки». На узком экране не ломает вёрстку:
   прокручивается по горизонтали внутри себя, страница остаётся неподвижной. */
.segmented-tabs {
  display: flex;
  /* Полоса шире своих вкладок выглядит как пустая плашка: прижимаем ширину
     к содержимому и позволяем ей сжиматься на узком экране. */
  width: fit-content;
  max-width: 100%;
  margin-bottom: 20px;
  overflow-x: auto;
  scrollbar-width: none;
}
.segmented-tabs .segmented-item { flex: 0 0 auto; }
.segmented-tabs::-webkit-scrollbar { display: none; }

.tabpanel:focus { outline: none; }
/* Каналы и мониторинг – узкие списки, промпт и база знаний во всю ширину */
.tabpanel-narrow { max-width: 760px; }

/* Карточка LMS: белая, hairline, 16px, трёхслойная микротень */
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
}
.card + .card { margin-top: 20px; }
/* В сетке колонок соседство карточек – горизонтальное, зазор даёт gap.
   Вертикальный margin здесь сдвигал бы правую колонку вниз относительно левой. */
.settings-cols > .card + .card { margin-top: 0; }

/* Промпт слева, тестовый чат справа. Ниже 1100px – одна колонка.

   На вкладке «Промпт» обе карточки должны вставать в один экран целиком, без
   прокрутки страницы. Поэтому сетка берёт остаток высоты вьюпорта: от него
   вычитается всё, что стоит над ней (заголовок раздела, полоса вкладок,
   верхний отступ) и нижний отступ страницы. Прокрутка уходит внутрь карточек:
   в поле промпта, в .prompt-compose и в ленту тестового чата. */
.settings-cols {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 20px;
  align-items: stretch;
}
/* Высоту сетка получает остатком: .settings-inner на этой вкладке – колонка
   во всю высоту вьюпорта, заголовок и полоса вкладок в ней фиксированы, а
   сетка забирает то, что осталось. Магической константы отступа нет: сдвинется
   заголовок или вкладки – высота пересчитается сама. */
@media (min-width: 1101px) {
  #tabpanel-prompt .settings-cols {
    flex: 1;
    min-height: 460px;
  }
}
.settings-cols + .card { margin-top: 20px; }

.card-col {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
  overflow: hidden;
}
/* Карточка промпта не растёт вслед за содержимым: она держит рабочую высоту
   экрана, а длинный промпт прокручивается внутри своего поля. 128px – это
   отступы страницы плюс её заголовок над карточкой. */
/* Высота карточки – по экрану, но не ниже рабочего минимума: 520px самого
   поля промпта плюс его слот, блок «Отдельные сообщения», итоги, шапка и
   подвал. Раньше минимум стоял 520px на всю карточку, и полю оставалось
   порядка двух строк.

   Ниже минимума карточка перестаёт влезать в экран и прокручивается вместе
   со страницей: место под чтение промпта важнее, чем экран без прокрутки. */
/* Высоту карточка берёт от сетки, а не от содержимого: блок промпта стал
   примерно на 20% ниже прежних 860px, а место под переменные, «Отдельные
   сообщения» и итоги освободилось. Не влезло – прокручивается .prompt-compose
   внутри карточки, страница остаётся неподвижной. */
.card-col-prompt { height: 100%; min-height: 0; }

/* Заголовок карточки промпта компактнее обычного: подпись под ним длинная,
   а высота нужна полю. */
.card-col-prompt > .card-head { padding-top: 13px; padding-bottom: 13px; }
.card-col-prompt > .card-head .card-sub { margin-bottom: 0; }
/* Тестовый чат держит ту же высоту, что и карточка промпта: обе колонки
   встают в один экран целиком – заголовок, лента и поле ввода. Лента внутри
   прокручивается сама. */
#tabpanel-prompt .settings-cols > .card-col:not(.card-col-prompt) {
  height: 100%;
  min-height: 0;
}

.card-body-grow {
  flex: 1;
  min-height: 0;
  display: flex;
}
/* Общее правило для textarea, растянутой на всю карточку. Поле промпта из
   него исключено: у .prompt-editable свой рабочий минимум, а этот селектор
   специфичнее и раньше обнулял его до нуля – из-за чего промпт и показывался
   окошком в пару строк независимо от заданной высоты. */
.card-body-grow .textarea:not(.prompt-editable) {
  flex: 1;
  min-height: 0;
  resize: none;
}

/* ---------- Тестовый чат ---------- */

/* Лента тестового чата – кремовый холст внутри белой карточки: та же ступень
   поверхностей, что у боевой переписки. */
.messages-test {
  flex: 1;
  min-height: 0;
  padding: 16px 22px 8px;
  background: var(--canvas);
  border-bottom: 1px solid var(--border-2);
}
.messages-test .bubble { max-width: 88%; }

/* В тесте оператор играет собеседника: его user справа, ответ бота слева.
   Роли API сохраняются; боевой чат по-прежнему смотрит со стороны оператора. */
.messages-test .msg-user { justify-content: flex-end; }
.messages-test .msg-bot { justify-content: flex-start; }
.messages-test .msg-user .bubble {
  background: var(--accent);
  color: var(--surface);
  border-color: var(--accent);
  border-bottom-left-radius: var(--r-lg);
  border-bottom-right-radius: 6px;
}
.messages-test .msg-bot .bubble:not(.bubble-error) {
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-sm);
  border-bottom-left-radius: 6px;
  border-bottom-right-radius: var(--r-lg);
}
.messages-test .msg-user .bubble-time { color: var(--surface); opacity: .78; }
.messages-test .msg-bot .bubble-time { color: var(--text-3); }
.messages-test .typing-label { color: var(--text-3); }
.messages-test .typing-dots i { background: var(--text-3); }

.test-note {
  margin: 0;
  padding: 0 22px 16px;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--text-2);
  background: var(--surface);
}

.card-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 14px;
  padding: 18px 24px;
  border-bottom: 1px solid var(--border-2);
}

/* ---------- Карточка промпта: правка + плашки подстановок ----------

   Одна колонка сверху вниз в том же порядке, в каком запрос уходит в модель:
   редактируемый промпт, затем переменные на своих местах подстановки.
   -------------------------------------------------------------------- */

/* Прокрутка живёт внутри поля промпта, а переменные, служебные подписи и
   итоги остаются на виду. На узком экране плашки и итоги переносятся и
   перестают влезать целиком – тогда прокручивается и сама карточка, иначе
   поле промпта схлопнулось бы до пары строк. */
.prompt-compose {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
  overflow-y: auto;
}

/* Слот = одно сообщение запроса. Системный обведён, чтобы граница «промпт и
   база знаний уходят одним сообщением» читалась без подписи. */
.prompt-slot {
  display: flex;
  flex-direction: column;
  gap: 7px;
  min-height: 0;
}
/* Системный слот забирает всю свободную высоту карточки. Поле промпта тянется
   внутри него и прокручивается само; чип базы знаний и его подпись прижаты
   снизу и никуда не уезжают. */
.prompt-slot-system {
  /* Слот забирает всю свободную высоту и отдаёт её textarea. basis:0 нужен,
     чтобы за точку отсчёта бралась не собственная высота содержимого
     (промпт на десять тысяч символов), а свободное место карточки.
     min-height удерживает рабочий размер поля, когда места мало; на широком
     экране свободного места больше и слот растёт сам.
     560px = 520px гарантированного поля плюс заголовок слота, чип базы
     знаний и внутренние отступы. */
  flex: 1 1 0;
  /*
    min-content, а не число: слот обязан вмещать заголовок, поле промпта,
    подпись про заголовок базы знаний и сам чип {{БАЗА_ЗНАНИЙ}}. С жёсткими
    300px чип вылезал за нижнюю границу на 21px и визуально обрезался блоком
    ниже. Здесь высота считается от реального содержимого.
  */
  min-height: min-content;
  padding: 12px 14px 14px;
  border: 1px solid var(--accent-line);
  border-radius: var(--r-md);
  background: var(--accent-soft);
}
.prompt-slot-messages {
  flex: 0 0 auto;
  padding: 10px 14px 11px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--ivory);
}
/* Плашки остаются в столбик: имя переменной и счётчик рядом читаются, а в
   два столбца счётчик переносится и строка становится выше, а не ниже. */
.prompt-slot-messages .var-chip { padding-top: 6px; padding-bottom: 6px; }

/* Подпись слота – eyebrow LMS: капс, разрядка .077em, slate */
.prompt-slot-title {
  margin: 0;
  font-size: 11.5px;
  font-weight: 500;
  letter-spacing: .077em;
  text-transform: uppercase;
  color: var(--text-2);
}
.prompt-slot-system .prompt-slot-title { color: var(--accent); }

/* Единственное, что правится руками. Промпт на десять тысяч символов не должен
   растягивать карточку – он прокручивается внутри поля. */
.prompt-editable {
  flex: 1 1 0;
  /* Промпт – главный рабочий текст админки, и читать его надо целиком, а не
     в окошко на две строки. 520px – нижняя граница: дальше поле растёт вслед
     за высотой экрана, а длинный промпт прокручивается внутри себя. */
  min-height: 200px;
  resize: vertical;
  overflow-y: auto;
  background: var(--surface);
}

.prompt-vars {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.prompt-vars:empty { display: none; }

/* Служебная вставка: показывает точный текст, который склейка добавляет
   от себя. Только чтение – правится он не здесь, а кодом сборки промпта.
   Одна строка по умолчанию: важен факт вставки и её точный текст, а место
   в карточке принадлежит промпту. */
.slot-note {
  flex: 0 0 auto;
  margin: 0;
  font-size: 11.5px;
  line-height: 1.5;
  color: var(--text-3);
}
.slot-note-code {
  padding: 1px 6px;
  border: 1px dashed var(--faint);
  border-radius: var(--r-sm);
  background: var(--surface);
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-2);
  white-space: nowrap;
  user-select: text;
}
/* Длинный перечень вставок прячется под «показать»: разворачивается по
   требованию и не отъедает высоту у поля промпта. */
.slot-note-more { margin-top: 4px; }
.slot-note-more > summary {
  cursor: pointer;
  color: var(--accent);
  font-size: 11.5px;
  list-style: none;
}
.slot-note-more > summary::-webkit-details-marker { display: none; }
.slot-note-more > summary::before { content: "▸ "; }
.slot-note-more[open] > summary::before { content: "▾ "; }
.slot-note-more > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.slot-note-rows {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-top: 5px;
}
.slot-note-row { display: flex; gap: 6px; align-items: baseline; flex-wrap: wrap; }

/* ---------- Плашка-переменная ---------- */

.var-chip {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  width: 100%;
  padding: 8px 12px;
  text-align: left;
  border: 1px dashed var(--faint);
  border-radius: var(--r-md);
  background: var(--surface);
  cursor: help;
  transition: border-color .15s ease, background .15s ease;
}
.var-chip:hover,
.var-chip:focus-visible {
  border-color: var(--accent);
  border-style: solid;
  background: var(--surface);
}
.var-chip:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
/* Пустая подстановка не должна выглядеть как заполненная. */
.var-chip.is-empty { opacity: .72; }

.var-chip-name {
  font-family: var(--font-mono);
  font-size: 12.4px;
  font-weight: 600;
  color: var(--accent);
  white-space: nowrap;
}
.var-chip-count {
  font-size: 12px;
  color: var(--text-2);
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* ---------- Итоги ---------- */

/* Итоги с выбором модели стоят в потоке карточки, но прилипают к её низу:
   прокручиваются промпт, переменные и блок «Отдельные сообщения», а модель и
   объём запроса остаются на виду. Иначе на экране 900px они уезжали под
   нижний край карточки, и до них приходилось долистывать. */
.prompt-summary {
  /*
    Без sticky. Прилипание к низу карточки визуально накладывало итоги на
    переменные {{ИСТОРИЯ_ДИАЛОГА}} и {{СООБЩЕНИЕ_ПОЛЬЗОВАТЕЛЯ}}: они уходили
    под непрозрачную плашку и переставали читаться. Пусть прокручивается
    вместе с остальным содержимым карточки.
  */
  flex: 0 0 auto;
  padding: 12px 16px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--ivory);
}
.prompt-summary:empty { display: none; }


.preview-totals-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(124px, 1fr));
  gap: 7px 16px;
}
.preview-total { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.preview-total-key {
  font-size: 12px;
  color: var(--text-2);
}
.preview-total-val {
  font-size: 13px;
  font-weight: 600;
  overflow-wrap: anywhere;
  font-variant-numeric: tabular-nums;
}

/* Модель выбирается прямо в итогах: она и так первая строка сводки, и держать
   ради неё отдельную карточку внизу страницы было незачем. */
/* Модель занимает свою строку целиком: подпись, список и текущее значение
   в одну линию – так строка стоит одну высоту, а не три. */
.preview-total-model {
  grid-column: 1 / -1;
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  min-height: 30px;
}
.preview-total-model .preview-total-key { flex: 0 0 auto; }
.preview-total-model .hint {
  flex: 1 1 auto;
  min-width: 0;
  margin: 0;
  font-size: 11.5px;
  overflow-wrap: anywhere;
}
.model-inline {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 0 1 260px;
  min-width: 0;
}
.model-inline .select {
  flex: 1 1 220px;
  min-width: 0;
  max-width: 420px;
  height: 30px;
  padding: 0 26px 0 8px;
  font-size: 12.5px;
}
.model-inline-status { font-size: 11.5px; }
.model-inline-status:empty { display: none; }
.preview-note {
  margin: 7px 0 0;
  padding-top: 7px;
  border-top: 1px solid var(--border-2);
  font-size: 11.5px;
  line-height: 1.4;
  color: var(--text-3);
}

.preview-state {
  margin: 0;
  padding: 10px 0;
  font-size: 13px;
  color: var(--text-3);
}
.preview-state.is-error {
  padding: 12px 14px;
  border: 1px solid var(--danger-line);
  border-radius: var(--r-md);
  background: var(--danger-soft);
  color: var(--danger);
}

/* ---------- Всплывающее превью переменной ----------

   position: fixed – координаты считаются от вьюпорта в placeVarPop(), чтобы
   панель не обрезалась прокруткой карточки и не вылезала за экран.
   -------------------------------------------------------------------- */

.var-pop {
  position: fixed;
  z-index: 60;
  width: min(420px, calc(100vw - 20px));
  max-height: min(460px, 72vh);
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 12px 14px 14px;
  border: 1px solid var(--border);
  border-radius: 14px;
  background: var(--surface);
  box-shadow: var(--shadow-lg);
}

.var-pop-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 4px;
}
.var-pop-name {
  font-family: var(--font-mono);
  font-size: 12.4px;
  font-weight: 600;
  color: var(--accent);
}
.var-pop-count {
  font-size: 11.5px;
  color: var(--text-3);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.var-pop-hint {
  margin: 0 0 8px;
  font-size: 12px;
  line-height: 1.45;
  color: var(--text-2);
}
.var-pop-empty {
  margin: 0;
  font-size: 12.5px;
  color: var(--text-3);
}

.var-pop-list {
  margin: 0 0 8px;
  padding: 0;
  list-style: none;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  overflow: hidden;
}
.var-pop-item + .var-pop-item { border-top: 1px solid var(--border-2); }

/* Строка файла – кнопка целиком: раскрывает полный текст под собой. */
.var-pop-item-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  width: 100%;
  padding: 6px 8px;
  border: 0;
  background: none;
  font: inherit;
  font-size: 12px;
  color: inherit;
  text-align: left;
  cursor: pointer;
}
.var-pop-item-head:hover { background: var(--canvas); }
.var-pop-item-head:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

/* Каретка: вправо закрыто, вниз раскрыто. */
.var-pop-item-caret {
  flex: 0 0 auto;
  align-self: center;
  width: 0;
  height: 0;
  border-top: 4px solid transparent;
  border-bottom: 4px solid transparent;
  border-left: 5px solid var(--text-3);
  transition: transform .12s ease;
}
.var-pop-item.is-open .var-pop-item-caret {
  transform: rotate(90deg) translateX(1px);
}

.var-pop-item-name { min-width: 0; flex: 1 1 auto; overflow-wrap: anywhere; }
.var-pop-item-chars {
  flex: 0 0 auto;
  color: var(--text-3);
  font-variant-numeric: tabular-nums;
}

/* Раскрытое содержимое: своя прокрутка, чтобы длинный файл не растягивал
   панель. overscroll-behavior не даёт докрутке уйти на страницу под панелью. */
.var-pop-file-body {
  padding: 0 8px 8px;
}
.var-pop-file-text {
  margin: 0;
  max-height: 260px;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 9px 11px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--ivory);
  font-family: var(--font-mono);
  font-size: 11.5px;
  line-height: 1.5;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  color: var(--text);
}
.var-pop-file-text.is-muted { color: var(--text-3); }

.var-pop-turns { display: flex; flex-direction: column; gap: 8px; }
.var-pop-turn { display: flex; flex-direction: column; gap: 4px; align-items: flex-start; }

.var-pop-text {
  margin: 0;
  width: 100%;
  padding: 9px 11px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--ivory);
  font-family: var(--font-mono);
  font-size: 12px;
  line-height: 1.5;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  color: var(--text);
}

/* Метка роли – та же капсула `.tag` LMS: 8px, ivory, hairline */
.role-badge {
  padding: 2px 9px;
  border-radius: var(--r-sm);
  border: 1px solid var(--border);
  background: var(--ivory);
  font-size: 11.5px;
  font-weight: 500;
  color: var(--text);
  white-space: nowrap;
}
.role-badge.role-system { background: var(--accent-soft); border-color: var(--accent-line); color: var(--accent-dark); }
.role-badge.role-user { background: var(--ivory); border-color: var(--border); color: var(--text-2); }
.role-badge.role-assistant { background: #edf9f1; border-color: #c6ecd3; color: var(--ok); }

.card-title {
  margin: 0;
  font-size: 18px;
  font-weight: 600;
  line-height: 1.38;
  letter-spacing: -.014em;
}
.card-sub { margin: 4px 0 0; font-size: 13.5px; line-height: 1.5; color: var(--text-2); }

.card-body { padding: 20px 24px; }
.card-body-flush { padding: 0; }

.card-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 14px 24px;
  background: var(--ivory);
  border-top: 1px solid var(--border-2);
}

/* ---------- Файлы базы знаний ---------- */

.kb-item { border-bottom: 1px solid var(--border-2); }
.kb-item:last-child { border-bottom: 0; }

.kb-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 13px 24px;
}

.kb-toggle {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: var(--text-2);
  cursor: pointer;
  user-select: none;
}
.kb-toggle input { width: 16px; height: 16px; accent-color: var(--accent); cursor: pointer; }

/* Имя файла – кнопка раскрытия: сброс вида кнопки, строка остаётся строкой. */
.kb-main {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 10px;
  margin: -6px -8px;
  padding: 6px 8px;
  border: 0;
  border-radius: var(--r-md);
  background: transparent;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.kb-main:hover { background: var(--canvas); }
.kb-main:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.kb-main-text { min-width: 0; display: flex; flex-direction: column; }
.kb-caret {
  flex: 0 0 auto;
  width: 8px;
  height: 8px;
  border-right: 1.6px solid var(--text-2);
  border-bottom: 1.6px solid var(--text-2);
  transform: rotate(-45deg);
  transition: transform .15s ease;
}
.kb-main[aria-expanded="true"] .kb-caret { transform: rotate(45deg); }

.kb-name {
  font-size: 15px;
  font-weight: 500;
  letter-spacing: -.01em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.kb-item.is-off .kb-name { color: var(--text-2); font-weight: 400; }

.kb-meta { margin-top: 2px; font-size: 12.5px; color: var(--text-2); }

/* Действия убраны под кнопку с тремя точками: в строке файла важны имя и
   переключатель, а «Удалить» рядом с ними слишком легко нажать мимо. */
.kb-actions { flex: 0 0 auto; display: flex; gap: 6px; position: relative; }

/* Кнопка «⋯» и всплывающее меню – механика `.rmenu` из LMS: круглая кнопка,
   меню карточкой 12px с мягкой тенью, пункты капсулами 10px. */
.kb-menu-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  padding: 0;
  border: 1px solid transparent;
  border-radius: 50%;
  background: transparent;
  color: var(--text-2);
  cursor: pointer;
  line-height: 1;
  font-size: 17px;
  transition: background .15s ease, border-color .15s ease;
}
.kb-menu-btn:hover { background: var(--canvas); border-color: var(--border); color: var(--text); }
.kb-menu-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.kb-menu-btn[aria-expanded="true"] { background: var(--canvas); border-color: var(--border); color: var(--text); }

.kb-menu {
  /* Все меню «···» живут в fixed-слое: у .card стоит overflow: hidden ради
     скруглённых углов, и абсолютное меню резалось нижней границей карточки.
     Координаты ставит placeMenu() в app.js по кнопке вызова. */
  position: fixed;
  z-index: 40;
  min-width: 168px;
  padding: 6px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface);
  box-shadow: var(--shadow-lg);
  display: flex;
  flex-direction: column;
  gap: 1px;
}
.kb-menu[hidden] { display: none; }

.kb-menu-item {
  display: block;
  width: 100%;
  padding: 8px 11px;
  border: 0;
  border-radius: 10px;
  background: transparent;
  text-align: left;
  font-size: 14px;
  color: var(--text);
  cursor: pointer;
}
.kb-menu-item:hover { background: var(--canvas); }
.kb-menu-item:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.kb-menu-item.is-danger { color: var(--danger); }

/* Пункт меню вида взаимодействий. Стоит НИЖЕ .kb-menu-item намеренно: у того
   display: block, вес селекторов одинаковый, и при обратном порядке блочный
   пункт выигрывал – space-between не работал, а счётчик прилипал к подписи
   вплотную («Все1»). */
.profile-kind-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}
.profile-kind-item .profile-kind-count { flex: 0 0 auto; }
.profile-kind-item.is-active { background: var(--accent-soft); color: var(--accent-dark); }
.profile-kind-item.is-active .profile-kind-count { color: var(--accent-dark); }
.profile-kind-item:disabled { opacity: .5; cursor: default; background: none; }

.kb-editor {
  padding: 0 24px 18px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.kb-editor-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
}
.kb-editor .textarea { min-height: 220px; }
.kb-editor .kb-content { min-height: min(60vh, 520px); font-size: 13px; line-height: 1.55; }
.kb-editor-hint { margin: 0 auto 0 0; font-size: 12px; }

/* ---------- Раздел «Рассылка» ---------- */

.camp-list { display: flex; flex-direction: column; gap: 0; }
.camp-list-columns { display: grid; grid-template-columns: minmax(0, 1.4fr) 120px minmax(0, 1fr) minmax(0, 1fr) 34px; align-items: center; gap: 16px; padding: 10px 0; border-bottom: 1px solid var(--border); font-size: 12px; color: var(--text-3); }
.camp-item-identity { display: flex; align-items: center; gap: 10px; min-width: 0; }
.camp-item-results { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.camp-item-state { min-width: 0; }
.camp-overview .card-body { padding-top: 4px; }

.camp-item {
  display: flex;
  align-items: center;
  gap: 16px;
  border: 0;
  border-bottom: 1px solid var(--border);
  border-radius: 0;
  background: var(--surface);
  padding: 16px 0;
}
.camp-item:last-child { border-bottom: 0; }
.camp-item:hover { background-color: var(--canvas); }

/* Строка кампании – flex, а тело внутри с min-width: 0: иначе длинное
   название не обрезается и список уезжает в горизонтальную прокрутку.
   Тем же болел список чатов. */
.camp-item-main {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) 120px minmax(0, 1fr) minmax(0, 1fr);
  align-items: center;
  gap: 16px;
  flex: 1;
  min-width: 0;
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
}
.camp-item-body { display: flex; flex-direction: column; gap: 4px; min-width: 0; flex: 1; }

.camp-item-top {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}
.camp-item-name {
  font-size: 15px;
  font-weight: 500;
  letter-spacing: -.01em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.camp-item-meta {
  font-size: 12.5px;
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
}

/* Статус кампании – метка `.tag` LMS: 8px, ivory, hairline, цвет несёт состояние */
.camp-status {
  flex: none;
  font-size: 11.5px;
  font-weight: 500;
  padding: 2px 9px;
  border-radius: var(--r-sm);
  background: var(--ivory);
  border: 1px solid var(--border);
  color: var(--text-2);
}
.camp-status.is-running { background: var(--accent-soft); border-color: var(--accent-line); color: var(--accent-dark); }
.camp-status.is-done { background: #edf9f1; border-color: #c6ecd3; color: var(--ok); }
.camp-status.is-failed { background: var(--danger-soft); border-color: var(--danger-line); color: var(--danger); }

.camp-progress {
  display: block;
  height: 4px;
  border-radius: 999px;
  background: var(--border-2);
  overflow: hidden;
}
.camp-progress-bar {
  display: block;
  height: 100%;
  width: 0;
  border-radius: 999px;
  background: var(--accent);
  transition: width .3s ease;
}

/* Цифры кампании в её строке: отправлено, пропущено, ошибки. Общая
   сводка по всем кампаниям сразу ни на один вопрос оператора не отвечала:
   спрашивают «как прошла вот эта», а не «сколько всего за всё время». */
.camp-item-stats {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  margin-top: 0;
}
.camp-item-stat {
  font-size: 12px;
  color: var(--text-2);
  padding: 0;
  font-variant-numeric: tabular-nums;
  white-space: normal;
}
.camp-item-stat b { color: var(--text); font-weight: 600; }
.camp-item-stat.is-failed b { color: var(--danger); }
.camp-item-stat.is-sent b { color: var(--ok); }
/* Исход неизвестен (инвариант 96): не ошибка и не успех, цвет журнала warn. */
.camp-item-stat.is-unknown b { color: #8a5a00; }

/* Меню действий кампании: та же механика, что у файлов базы знаний. */
.camp-actions { position: relative; flex: none; }
/* «Продолжить (осталось 2)» не рвётся на узком экране: число с подписью –
   одна строка, как у пунктов меню каналов. */
.camp-actions .kb-menu-item { white-space: nowrap; }

/* Форма создания.

   Компактность здесь не вкусовщина: форму открывают, чтобы отметить людей и
   написать текст, а до правок половину экрана занимал воздух между полями,
   и список получателей приходилось искать прокруткой. */

.camp-form { display: flex; flex-direction: column; gap: 0; }
.camp-section { padding: 20px 0; border-bottom: 1px solid var(--border); min-width: 0; }
.camp-section:first-child { padding-top: 0; }
.camp-section:last-child { border-bottom: 0; padding-bottom: 0; }
.camp-section-title { margin: 0 0 14px; color: var(--text); font-size: 15px; font-weight: 600; letter-spacing: -.01em; }
.camp-section > .field { margin-bottom: 0; }
.camp-connection-field { margin-top: 16px; max-width: 600px; }
.camp-connection-help { display: flex; align-items: center; gap: 10px; margin-top: 6px; }
.camp-connection-help .field-note { margin: 0; font-size: 13px; line-height: 1.5; }
.camp-connection-help .btn { flex: none; }
.camp-section .camp-mode-head .camp-section-title { margin-bottom: 0; }
.camp-section .camp-aud-head .camp-section-title { margin-bottom: 0; }

/* Название и канал рядом: два коротких поля не стоят двух экранных строк. */
.camp-row { display: flex; gap: 12px; align-items: flex-start; }
.camp-row > .field { margin: 0; }
.camp-field-name { flex: 1 1 auto; min-width: 0; }
.camp-field-channel { flex: 0 0 auto; }
.camp-row-tail { flex-wrap: wrap; align-items: flex-start; }
.camp-when-field { flex: 1 1 auto; min-width: 0; }

.camp-channels { display: flex; gap: 8px; flex-wrap: wrap; }

.camp-channel {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 16px 8px 10px;
  border: 1px solid var(--border);
  border-radius: var(--r-button);
  background: var(--surface);
  box-shadow: var(--shadow-sm);
  font: inherit;
  font-size: 14px;
  font-weight: 500;
  color: var(--text);
  cursor: pointer;
  /* 44px по высоте: на телефоне это нижняя граница удобного касания. */
  min-height: 44px;
}
.camp-channel.is-active { border-color: var(--accent-line); background: var(--accent-soft); color: var(--accent-dark); }

.camp-no-channels { margin: 6px 0 0; margin-left: 0; }

.linklike {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  font-weight: 500;
  color: var(--accent);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
}

.input-sm { height: 34px; font-size: 13px; }

.camp-aud-head {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 6px;
}
.camp-aud-label { margin: 0; }
.camp-aud-count { font-size: 13px; font-weight: 600; font-variant-numeric: tabular-nums; }
.camp-aud-tools { display: flex; align-items: center; gap: 8px; margin-left: auto; }
.camp-aud-search { max-width: 200px; }
.camp-filters-btn { flex: none; }
.camp-filters-btn[aria-expanded="true"] {
  border-color: var(--accent);
  color: var(--accent-dark);
}

/* Блок фильтров. Свёрнут до клика: развёрнутым он занимал больше места,
   чем список людей, ради которого форму и открывают. */
.camp-filters {
  padding: 12px 14px;
  margin-bottom: 8px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--ivory);
}
.camp-filters-row {
  display: flex;
  align-items: center;
  gap: 8px 14px;
  flex-wrap: wrap;
}
.camp-filter-group { display: flex; align-items: center; gap: 6px; min-width: 0; }
.camp-filter-label { font-size: 12px; color: var(--text-3); white-space: nowrap; }
.camp-filter-dash { color: var(--text-3); font-size: 12px; }
.camp-filter-group input { width: 132px; box-sizing: border-box; }
.camp-filters-reset { margin-left: auto; }

.camp-filter-window {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  font-size: 12.5px;
  cursor: pointer;
  white-space: nowrap;
}
.camp-filter-window input { width: 16px; height: 16px; flex: none; }
/* Заблокированная галка в Instagram: платформа не даст отправить вне окна,
   и снятая галка обещала бы отправку, которая кончится ошибкой в отчёте. */
.camp-filter-window input:disabled { cursor: default; }
.camp-filter-window:has(input:disabled) { color: var(--text-3); cursor: default; }
.camp-filter-note { margin: 4px 0 0; font-size: 11.5px; line-height: 1.45; }

.camp-aud-note {
  margin: 0 0 6px;
  font-size: 12px;
  color: var(--text-3);
  line-height: 1.45;
}

/* «Выбрать все» над списком, вне прокрутки: внутри неё оно уезжало бы
   из виду вместе с первыми получателями. */
.camp-aud-all {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 9px 14px;
  border: 1px solid var(--border);
  border-bottom: 0;
  border-radius: var(--r-md) var(--r-md) 0 0;
  background: var(--ivory);
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
}
.camp-aud-all input { width: 16px; height: 16px; flex: none; }

.camp-aud-list {
  /* Фиксированная высота с прокруткой внутри: аудитория из ста человек
     растягивала форму на пять экранов, и до текста сообщения было не
     добраться иначе как листанием. */
  max-height: 210px;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface);
}
/* Список под «выбрать все» – одна карточка: верхний угол скругляет шапка. */
.camp-aud-all:not([hidden]) + .camp-aud-list { border-radius: 0 0 var(--r-md) var(--r-md); }

.camp-aud-item {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 7px 12px;
  border-bottom: 1px solid var(--border-2);
  cursor: pointer;
  min-height: 38px;
  box-sizing: border-box;
}
.camp-aud-item:last-child { border-bottom: 0; }
/* Недоступные не прячем, а гасим: оператору нужен масштаб «доступно N из M»,
   а молча укоротившийся список читается как потеря людей. */
.camp-aud-item.is-off { opacity: .55; cursor: default; }
.camp-aud-item input { margin-top: 3px; flex: none; width: 16px; height: 16px; }
.camp-aud-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.camp-aud-name { font-size: 13px; overflow-wrap: anywhere; }
.camp-aud-note-item { font-size: 11.5px; color: var(--text-3); overflow-wrap: anywhere; }

/* Режим текста и два столбца */

.camp-mode-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 6px;
}
.camp-mode-head .field-label { margin: 0; }

/* В режиме «каждому свой» шаблон встаёт вторым столбцом справа: исходный
   текст и его разложенный вариант читаются только рядом, а не по очереди. */
.camp-msg-cols { display: grid; grid-template-columns: 1fr; gap: 12px; }
.camp-msg-cols.is-split { grid-template-columns: 1fr 1fr; }
.camp-msg-col { display: flex; flex-direction: column; min-width: 0; }
.camp-msg-col .camp-textarea { flex: 1 1 auto; }
/* В split обе шапки видны, и поля начинаются на одной высоте. */
.camp-msg-cols.is-split .camp-msg-head-src { display: flex; }

.camp-spin-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 6px;
  /* Одна высота у обеих шапок: справа стоит кнопка, слева только подпись,
     и без этого поля начинались на разной высоте. */
  min-height: 30px;
}
.camp-spin-title { font-size: 12.5px; font-weight: 600; color: var(--text-2); }
.camp-spin-hint { margin: 6px 0 0; margin-left: 0; font-size: 11.5px; line-height: 1.45; }
/* Пример синтаксиса – отдельной строкой: разорванный посередине, он читается
   не как образец, а как часть предложения вокруг. */
.camp-spin-hint code {
  display: block;
  margin-top: 3px;
  font-size: 11.5px;
  padding: 3px 7px;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--ivory);
  overflow-wrap: anywhere;
}
.camp-spin-status { margin: 5px 0 0; font-size: 12px; color: var(--text-2); }
.camp-spin-status.is-error { color: var(--danger); }
.camp-spin-status.is-ok { color: var(--ok); }

/* Высота задаётся здесь, а не атрибутом rows: rows считает строки шрифтом
   браузера, и одно и то же поле выходило на треть выше расчёта. */
.camp-textarea { min-height: 92px; height: 92px; }

.camp-pace-field { flex: 0 0 auto; }
.camp-pace { max-width: 120px; }

.camp-eta { margin: 0; font-size: 12.5px; color: var(--text-2); }
.camp-risk {
  margin: 6px 0 0;
  font-size: 12px;
  line-height: 1.5;
  color: var(--danger);
}

.camp-when { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.radio {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 13px;
  cursor: pointer;
  min-height: 32px;
}
.radio input { width: 16px; height: 16px; }
.camp-at { max-width: 230px; }

/* Карточка кампании */

.camp-detail-actions { display: flex; gap: 8px; flex-wrap: wrap; }
#camp-detail-card .camp-counters { gap: 0; border-bottom: 1px solid var(--border); padding: 8px 0 20px; }
#camp-detail-card .camp-counter { flex: 1 1 130px; display: flex; flex-direction: column; gap: 4px; border: 0; border-radius: 0; background: transparent; padding: 8px 16px 8px 0; }
#camp-detail-card .camp-counter b { font-size: 24px; font-weight: 600; }
#camp-detail-card .camp-detail-message { background: var(--canvas); }

#camp-detail-card .camp-progress { margin-bottom: 12px; height: 6px; }

/* Счётчики – плитки с разделителем: подряд, через один пробел, «0 Отправлено
   12 В очереди» читается одной строкой мусора, и число не привязывается к
   своей подписи. */
.camp-counters { display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 14px; }
.camp-counter {
  font-size: 13px;
  color: var(--text-2);
  padding: 8px 14px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--ivory);
  white-space: nowrap;
}
.camp-counter b { font-size: 16px; font-weight: 600; color: var(--text); font-variant-numeric: tabular-nums; }

.camp-detail-message {
  margin: 0 0 16px;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--ivory);
  font-size: 13px;
  line-height: 1.55;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* Отметки времени кампании: подпись и значение парой, в одну строку. */
.camp-dates {
  display: flex;
  gap: 6px 18px;
  flex-wrap: wrap;
  margin: 0 0 14px;
  font-size: 12.5px;
}
.camp-dates > div { display: flex; gap: 6px; }
.camp-dates dt { color: var(--text-3); }
.camp-dates dd { margin: 0; color: var(--text); font-variant-numeric: tabular-nums; }

.camp-targets-toggle {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 10px 14px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--ivory);
  font: inherit;
  font-size: 13px;
  font-weight: 500;
  color: var(--text);
  cursor: pointer;
  text-align: left;
  min-height: 38px;
}
.camp-targets-toggle[aria-expanded="true"] { border-radius: var(--r-md) var(--r-md) 0 0; border-bottom: 0; }
.camp-targets-chevron {
  margin-left: auto;
  width: 8px;
  height: 8px;
  border-right: 1.5px solid var(--text-3);
  border-bottom: 1.5px solid var(--text-3);
  transform: rotate(-45deg);
  transition: transform .15s ease;
}
.camp-targets-toggle[aria-expanded="true"] .camp-targets-chevron { transform: rotate(45deg); }

.camp-targets {
  border: 1px solid var(--border);
  border-radius: 0 0 var(--r-md) var(--r-md);
  overflow: hidden;
  max-height: 420px;
  overflow-y: auto;
}
.camp-target {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding: 8px 12px;
  border-bottom: 1px solid var(--border-2);
  font-size: 12.5px;
}
.camp-target:last-child { border-bottom: 0; }
.camp-target-name { min-width: 0; overflow-wrap: anywhere; }
/* Значки веса аккаунта идут сразу за именем: без отступа цифра слипается с
   ником и читается его частью («@anna265»). */
.camp-target-name .chat-item-follows,
.camp-target-name .chat-item-followers { margin-left: 6px; }
/* Имя не сжимается в столбик по букве, даже если справа длинная ошибка:
   правая часть уступает место и переносится сама (min-width у неё 0). */
.camp-target-body { display: flex; flex-direction: column; gap: 3px; min-width: min(40%, 12em); flex: 1 1 auto; }
/* Точный текст этому человеку: в режиме «каждому свой» он у каждого свой,
   и проверить раскладку можно только увидев её до запуска. */
.camp-target-text {
  font-size: 11.5px;
  line-height: 1.45;
  color: var(--text-3);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.camp-target-right { display: flex; align-items: center; gap: 8px; flex: 0 1 auto; min-width: 0; }
.camp-target-chat { flex: none; }
.camp-target-status { flex: 0 1 auto; min-width: 0; color: var(--text-3); text-align: right; }
.camp-target.is-sent .camp-target-status { color: var(--ok); }
.camp-target.is-failed .camp-target-status { color: var(--danger); }
/* Ожидающая отправки запись – нейтральная: она ещё ни успех, ни отказ.
   Цветом выделены только состоявшиеся исходы, иначе вся очередь горит. */
.camp-target.is-pending .camp-target-status { color: var(--text-3); }
/* Исход неизвестен: запрос пережил перезапуск, дошло ли – проверяют по
   переписке. Тот же тёплый тон, что у warn в журнале: внимание, не авария. */
.camp-target.is-unknown .camp-target-status { color: #8a5a00; }

/* Отложенные отправки в панели профиля. Тот же скелет, что у истории
   взаимодействий: это соседний блок, и разная вёрстка читалась бы как разные
   по важности вещи. */
.profile-postponed { margin-top: 18px; }
.profile-item.is-postponed .profile-item-head {
  display: flex;
  align-items: center;
  gap: 8px;
}
/* Имя автоматизации занимает остаток строки, время и кнопка не сжимаются:
   иначе «в 14:20» ломалось бы переносом на узкой панели.
   Сам заголовок – тоже flex: иначе многоточие съедало бы пометку «правлено»
   вместе с хвостом названия, и оператор не видел бы, что текст изменён. */
.profile-item.is-postponed .profile-item-kind {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 6px;
  overflow: hidden;
}
/* Обрезается только название, пометка остаётся целой. */
.profile-item.is-postponed .postponed-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.profile-item.is-postponed .profile-item-time,
.postponed-actions { flex: 0 0 auto; }
/* Кнопка меню в строке мельче общей: в панели 34 px перевешивают саму строку. */
.postponed-actions .kb-menu-btn { width: 28px; height: 28px; font-size: 15px; }
.postponed-menu { width: 196px; }
.postponed-text { margin-top: 4px; }
.postponed-custom {
  flex: 0 0 auto;
  padding: 1px 6px;
  border-radius: 999px;
  background: var(--canvas);
  color: var(--text-3);
  font-size: 11px;
  font-weight: 400;
}
.postponed-edit { margin-top: 6px; }
.postponed-input {
  width: 100%;
  box-sizing: border-box;
  resize: vertical;
  font: inherit;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--surface);
  color: var(--text);
}
.postponed-edit-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 6px;
}

/* Ошибка бывает длинной: на узком экране она обязана переноситься, иначе
   выдавит имя получателя за край. */
.camp-target-status { overflow-wrap: anywhere; }

.stop-words-textarea {
  min-height: 200px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 13px;
  line-height: 1.6;
}

/* Таймер «Возврат ИИ после оператора»: число и его расшифровка в строку. */
.manual-seconds-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px 12px;
}
.manual-seconds-input { width: 160px; max-width: 100%; }
.manual-seconds-input[aria-invalid="true"] { border-color: var(--danger); }
.manual-seconds-human { font-size: 13px; color: var(--text-2); }
.manual-seconds-human.is-error { color: var(--danger); }

.field-note {
  margin-left: 6px;
  font-weight: 400;
  color: var(--text-3);
}

/* =====================================================   Раздел «Публикации»
   ============================================================ */

/* Плитки над сеткой – те же .camp-counter; здесь только отступ от подсказки. */
.pub-counters { margin-bottom: 6px; }
.pub-quota-note, .pub-grid-note {
  margin: 0 0 14px;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--text-3);
}
.pub-grid-note { color: var(--danger); }
.pub-grid-note .linklike { margin-left: 4px; }

/* Пустые состояния раздела: кнопки под текстом, на 375 – в столбик. */
.pub-empty-actions {
  display: flex;
  justify-content: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 14px;
}
.pub-no-permission { max-width: 420px; }
.pub-no-permission code { font-family: var(--font-mono); font-size: 12.5px; }
.pub-no-permission .status { margin: 10px 0 0; }
.pub-no-permission .status:empty { display: none; }

/* Сетка аккаунта – как вкладка Reels в Instagram: обложки 9:16 вплотную, цифра
   просмотров в углу, остальное в окне поста. Без прокрутки внутри: это
   главный экран раздела, а не вложенный список в форме. */
.pub-grid {
  display: grid;
  /* 9:16 вдвое выше 4:5: плитки уже, чтобы на экран входило больше ряда. */
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: 4px;
}
.pub-grid .list-empty { grid-column: 1 / -1; }
.pub-tile {
  position: relative;
  display: block;
  padding: 0;
  border: 0;
  border-radius: 6px;
  overflow: hidden;
  background: var(--border-2);
  color: #fff;
  font: inherit;
  cursor: pointer;
  min-width: 0;
  aspect-ratio: 9 / 16;
}
/* Пробный Reels: серая рамка поверх обложки и подпись, в обоих местах. */
.pub-tile.is-trial::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  border: 3px solid #a3a7ae;
  border-radius: inherit;
  pointer-events: none;
}
.pub-trial-chip {
  position: absolute;
  top: 9px;
  left: 9px;
  z-index: 1;
  padding: 2px 8px;
  border-radius: var(--r-sm);
  background: #a3a7ae;
  color: #fff;
  font-size: 11px;
  font-weight: 600;
  line-height: 1.4;
  pointer-events: none;
}
.pub-tile:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.pub-tile-thumb {
  display: block;
  width: 100%;
  height: 100%;
  /* contain: обложка видна целиком. У Reels она и так 9:16 и заполняет плитку,
     фото 4:5 или 1:1 вписывается с полями, а не обрезается. */
  object-fit: contain;
}
.pub-tile-thumb-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-3);
  font-size: 12px;
}
.pub-tile-icon {
  width: 18px;
  height: 18px;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}
/* Цифра лежит на обложке любого цвета: читаемость держит тень, а не плашка,
   как в самом Instagram. */
.pub-tile-corner, .pub-tile-kind, .pub-tile-bar {
  position: absolute;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, .55));
  pointer-events: none;
}
.pub-tile-corner {
  left: 10px;
  bottom: 9px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 14px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.pub-tile-kind { top: 9px; right: 9px; display: inline-flex; }
.pub-tile-kind .pub-tile-icon { width: 20px; height: 20px; }
/* Нижний градиент только там, где на обложке стоит текст. */
.pub-tile::after {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 34%;
  background: linear-gradient(to top, rgba(0, 0, 0, .42), rgba(0, 0, 0, 0));
  pointer-events: none;
}
.pub-tile-corner, .pub-tile-bar { z-index: 1; }
.pub-tile-hover {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 22px;
  background: rgba(0, 0, 0, .38);
  font-size: 15px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  opacity: 0;
  transition: opacity .12s ease;
}
.pub-tile-hover > span { display: inline-flex; align-items: center; gap: 7px; }
.pub-tile-hover .pub-tile-icon { width: 20px; height: 20px; fill: currentColor; }
.pub-tile:hover .pub-tile-hover, .pub-tile:focus-visible .pub-tile-hover { opacity: 1; }
/* Метка статуса лежит на миниатюре: у черновика и очереди она важнее цифр. */
.pub-tile-tag { position: absolute; top: 9px; left: 9px; z-index: 1; }
.pub-tile-bar {
  left: 10px;
  right: 10px;
  bottom: 9px;
  font-size: 12.5px;
  font-weight: 500;
  text-align: left;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ---------- Окно поста ---------- */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}
body.is-pubv-open { overflow: hidden; }
.pubv-backdrop {
  position: fixed;
  inset: 0;
  z-index: 65;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 28px 72px;
  background: rgba(17, 19, 26, .72);
}
.pubv-backdrop[hidden] { display: none; }
.pubv {
  display: flex;
  max-width: min(1240px, 100%);
  height: min(860px, calc(100vh - 56px));
  background: var(--surface);
  border-radius: var(--r-md);
  overflow: hidden;
  box-shadow: var(--shadow-lg);
}
/* Ширина медиа идёт от его пропорций при полной высоте окна, как в Instagram:
   вертикальный ролик даёт узкое окно, фото 4:5 – широкое, чёрных полей нет.
   Пропорцию ставит app.js: сначала догадка по типу, затем точная по файлу. */
.pubv-media {
  flex: 0 1 auto;
  height: 100%;
  aspect-ratio: var(--pubv-ratio, 4 / 5);
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #000;
}
.pubv-video, .pubv-img { display: block; width: 100%; height: 100%; object-fit: contain; }
.pubv-media-empty { color: rgba(255, 255, 255, .6); font-size: 13px; }
.pubv-side {
  flex: 0 0 440px;
  min-width: 0;
  display: flex;
  flex-direction: column;
  border-left: 1px solid var(--border);
}
.pubv-head {
  flex: none;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  border-bottom: 1px solid var(--border);
}
.pubv-avatar {
  flex: none;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: var(--accent-soft);
  color: var(--accent-dark);
  font-size: 15px;
  font-weight: 600;
  text-transform: uppercase;
}
.pubv-avatar-sm { width: 32px; height: 32px; font-size: 13px; background: var(--ivory); color: var(--text-2); box-shadow: inset 0 0 0 1px var(--border); }
.pubv-who { min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.pubv-name { font-size: 14px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pubv-sub { font-size: 12px; color: var(--text-3); }
.pubv-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.pubv-comment { display: flex; gap: 12px; min-width: 0; }
.pubv-comment-main { min-width: 0; flex: 1; }
.pubv-text {
  margin: 0;
  font-size: 14px;
  line-height: 1.45;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.pubv-text b { font-weight: 600; }
.pubv-text .pub-tagword { color: var(--accent); }
.pubv-meta { margin: 5px 0 0; font-size: 12px; color: var(--text-3); }
.pubv-meta:empty { display: none; }
/* Черта перед «Показать ответы» – узнаваемая деталь ветки в Instagram. */
.pubv-replies-toggle {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  margin-top: 10px;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-2);
  cursor: pointer;
}
.pubv-replies-toggle::before { content: ""; width: 24px; height: 1px; background: var(--faint); }
.pubv-replies-toggle:hover { color: var(--text); }
.pubv-replies-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 4px; }
.pubv-replies { display: flex; flex-direction: column; gap: 14px; margin-top: 14px; }
.pubv-replies[hidden] { display: none; }
.pubv-state { margin: 0; font-size: 13px; color: var(--text-3); }
.pubv-state.is-error { color: var(--danger); }
.pubv-foot { flex: none; padding: 12px 16px 14px; border-top: 1px solid var(--border); }
.pubv-stats { display: flex; flex-wrap: wrap; gap: 6px 18px; }
.pubv-stat { display: inline-flex; align-items: center; gap: 6px; font-size: 14px; font-variant-numeric: tabular-nums; }
.pubv-stat b { font-weight: 600; }
.pubv-stat-icon {
  width: 22px;
  height: 22px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.pubv-note { margin: 8px 0 0; font-size: 12px; line-height: 1.45; color: var(--text-3); }
.pubv-links { display: flex; flex-wrap: wrap; gap: 6px 16px; margin-top: 10px; font-size: 13.5px; }
.pubv-link { font-weight: 500; color: var(--accent); text-underline-offset: 3px; }
.pubv-link[hidden] { display: none; }
.pubv-close, .pubv-nav {
  position: absolute;
  display: grid;
  place-items: center;
  border: 0;
  cursor: pointer;
}
.pubv-close svg, .pubv-nav svg { fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.pubv-close { top: 14px; right: 16px; width: 40px; height: 40px; background: none; color: #fff; }
.pubv-close svg { width: 26px; height: 26px; }
.pubv-nav {
  top: 50%;
  width: 36px;
  height: 36px;
  margin-top: -18px;
  border-radius: 50%;
  background: #fff;
  color: var(--text);
  box-shadow: var(--shadow-sm);
}
.pubv-nav svg { width: 20px; height: 20px; }
.pubv-nav-prev { left: 18px; }
.pubv-nav-next { right: 18px; }
.pubv-nav[hidden] { display: none; }
.pubv-close:focus-visible, .pubv-nav:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }

/* Метка статуса – та же капсула .tag LMS, что у кампаний; цвет несёт состояние */
.pub-tag {
  display: inline-block;
  flex: none;
  font-size: 11.5px;
  font-weight: 500;
  line-height: 1.4;
  padding: 2px 9px;
  border-radius: var(--r-sm);
  background: var(--ivory);
  border: 1px solid var(--border);
  color: var(--text-2);
  white-space: nowrap;
}
.pub-tag.is-live { background: var(--accent-soft); border-color: var(--accent-line); color: var(--accent-dark); }
.pub-tag.is-done { background: #edf9f1; border-color: #c6ecd3; color: var(--ok); }
.pub-tag.is-failed { background: var(--danger-soft); border-color: var(--danger-line); color: var(--danger); }

/* Форма: одна колонка сверху вниз в порядке сборки поста. */
.pub-form { display: flex; flex-direction: column; gap: 16px; }
.pub-form .field { display: flex; flex-direction: column; gap: 6px; }
.pub-form .field-label { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 6px; }
.pub-kind { align-self: flex-start; }
.segmented-item:disabled { opacity: .45; cursor: not-allowed; }
.segmented-item:disabled:hover { background: transparent; }

/* Ошибка под полем: красным блоком, чтобы не спутать с подсказкой. */
.field-error {
  margin: 0;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--danger);
}
.pub-detail-error {
  padding: 12px 14px;
  border: 1px solid var(--danger-line);
  border-radius: var(--r-md);
  background: var(--danger-soft);
}
.pub-detail-error-text { margin: 0; font-size: 14px; line-height: 1.5; color: var(--danger); }
.pub-detail-error-code { margin: 4px 0 0; font-size: 12px; color: var(--text-2); font-family: var(--font-mono); }
.pub-detail-error-code:empty { display: none; }
.pub-detail-error-actions { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 10px; }
.pub-detail-error-actions:empty { display: none; }

/* Макет поста. Ширина 470px – столько занимает пост в вебе Instagram:
   уже макет перестаёт читаться как пост, шире растягивает кадр. */
.pub-compose { display: flex; }
.pub-post {
  width: 100%;
  max-width: 470px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface);
  overflow: hidden;
}

/* Шапка: аватар и ник, как в посте. */
.pub-post-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
}
.pub-post-avatar {
  flex: none;
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--accent-soft);
  border: 1px solid var(--accent-line);
  color: var(--accent-dark);
  font-size: 14px;
  font-weight: 600;
  text-transform: uppercase;
  line-height: 1;
}
.pub-post-who { min-width: 0; }
.pub-post-name {
  display: block;
  font-size: 13.5px;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Медиа: до загрузки квадрат, после – пропорции самого файла, чтобы кадр
   выглядел так, как его увидит подписчик. Пропорции задаёт JS в style. */
.pub-post-media {
  position: relative;
  /* Заглушка ниже квадрата: пустой квадрат 470px уводил подпись и
     комментарии за сгиб, и оператор не видел, что ниже вообще есть пост.
     После загрузки область встаёт в пропорции самого файла. */
  aspect-ratio: 16 / 11;
  background: var(--surface-2);
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
}
/* С загруженным файлом высоту задаёт сама картинка: aspect-ratio
   контейнера спорил с её max-height и оставлял пустую полосу под кадром. */
.pub-post-media.is-filled { aspect-ratio: auto; }
/* Кадр не выше 460px: вертикальное фото 4:5 в полную величину уводило
   подпись и комментарии за сгиб, и оператор правил подпись, не видя кадра.
   Пропорции сохраняются, лишнее режется по краям, как в ленте. */
.pub-post-img {
  display: block;
  width: 100%;
  height: auto;
  max-height: 460px;
  object-fit: cover;
}

/* Заглушка – она же кнопка загрузки, поэтому занимает всю область. */
.pub-drop {
  position: absolute;
  inset: 8px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 12px;
  border: 1.5px dashed var(--faint);
  border-radius: var(--r-md);
  background: transparent;
  color: var(--text-2);
  font: inherit;
  text-align: center;
  cursor: pointer;
}
.pub-drop:hover { border-color: var(--accent); background: var(--accent-soft); color: var(--accent-dark); }
.pub-drop:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.pub-drop-icon {
  width: 34px;
  height: 34px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.4;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.pub-drop-title { font-size: 14px; font-weight: 500; }
.pub-drop-hint { font-size: 12.5px; color: var(--text-3); }
.pub-drop:hover .pub-drop-hint { color: inherit; }
/* Требования к файлу: мелким серым в самой заглушке. Под макетом отдельной
   строки им больше нет – там они висели и когда файл уже загружен. */
.pub-drop-req { font-size: 11.5px; color: var(--text-3); margin-top: 2px; }
.pub-drop:hover .pub-drop-req { color: inherit; }

/* Перетаскивание: видимое состояние «отпустите файл» поверх области. */
.pub-drop-over {
  position: absolute;
  inset: 0;
  display: none;
  place-items: center;
  background: var(--accent-soft);
  border: 2px dashed var(--accent);
  color: var(--accent-dark);
  font-size: 14px;
  font-weight: 600;
}
.pub-post-media.is-dragover .pub-drop-over { display: grid; }

/* «Заменить» и «Убрать» поверх кадра: в макете им места нет, а рядом с
   кадром они ломали бы вид поста. */
.pub-media-actions {
  position: absolute;
  top: 10px;
  right: 10px;
  display: flex;
  gap: 6px;
}
.pub-media-actions .btn {
  background: rgba(255,255,255,.94);
  box-shadow: var(--shadow-sm);
}

/* Строка действий: декорация, повторяющая вид Instagram. */
.pub-post-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 14px 2px;
  color: var(--text-3);
}
.pub-post-actions-left { display: flex; align-items: center; gap: 14px; }
/* Иконка и её число рядом, как в Instagram. Числа декоративные. */
.pub-post-action { display: inline-flex; align-items: center; gap: 5px; }
.pub-post-action-n { font-size: 13px; font-variant-numeric: tabular-nums; }
.pub-ig-icon {
  width: 22px;
  height: 22px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.pub-post-likes {
  margin: 0;
  padding: 4px 14px 0;
  font-size: 13px;
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
}
.pub-post-likes b { font-weight: 600; color: var(--text); }

/* Подпись: ник жирным и текст в одном потоке, как в посте.
   Вся область подписи – зона клика: `cursor: text` и обработчик в app.js
   ставят фокус в поле, даже если ткнули в ник или в пустое место справа. */
.pub-post-caption {
  display: flex;
  align-items: baseline;
  gap: 5px;
  padding: 8px 14px 10px;
  font-size: 13.5px;
  line-height: 1.55;
  cursor: text;
}
.pub-post-caption[hidden] { display: none; }
.pub-post-caption-name { flex: 0 1 auto; max-width: 40%; overflow-wrap: anywhere; font-weight: 600; }
/* Поле занимает остаток строки рядом с именем и растёт по высоте вместе
   с текстом. Пустая подсказка также участвует в расчёте высоты. */
.pub-caption {
  display: block;
  flex: 1 1 0;
  min-height: 1.55em;
  min-width: 0;
  outline: none;
  overflow-wrap: anywhere;
  white-space: pre-wrap;
  /* Цвет каретки задаётся явно токеном: у contenteditable внутри блока с
     серым placeholder браузер иначе берёт унаследованный цвет, и на светлом
     фоне курсор терялся. */
  caret-color: var(--text);
}
/* Подсказка скрывается по фокусу; в пустом поле она задаёт реальную
   высоту строки, включая перенос на узком экране. */
#pub-form-card:not([hidden]) .pub-caption:empty:not(:focus)::before {
  content: attr(data-placeholder);
  position: static;
  color: var(--text-3);
  pointer-events: none;
}
.pub-caption:empty { position: relative; }
.pub-caption:focus-visible { outline: none; }
/* Фокус подписи обозначается полосой слева, без заливки: залитая строка
   читалась как выделенный элемент списка, а не как поле ввода. */
.pub-post-caption:focus-within { box-shadow: inset 2px 0 0 var(--accent); }
/* Хэштег и упоминание – синим, как ссылка в Instagram. */
.pub-caption .pub-tagword { color: var(--accent); }

/* Первый комментарий: поле рабочее, текст уходит в черновик и публикуется
   сразу после выхода поста. Вид остаётся видом комментария Instagram –
   ник жирным, текст рядом, без рамки поля ввода. */
.pub-post-comments { border-top: 1px solid var(--border); padding: 10px 14px 12px; }
.pub-post-comments-note { margin: 0; font-size: 12.5px; color: var(--text-3); }
/* Ник обтекается текстом, как в Instagram: `float` вместо колонки flex,
   иначе вторая строка комментария начиналась под ником лестницей, а не у
   левого края (замер 15.09.2026 на 1280). */
.pub-post-comment-row {
  display: block;
  margin-top: 8px;
  cursor: text;
}
.pub-post-comment-name {
  float: left;
  margin-right: 5px;
  font-size: 13px;
  font-weight: 600;
  line-height: 1.5;
}
.pub-post-comment-field {
  display: block;
  width: 100%;
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  /* `font-family` отдельно, а не через `font: inherit`: шорткат сбрасывал бы
     размер на унаследованный от карточки. На узком экране размер всё равно
     станет 16px общим правилом ниже по файлу: iPhone приближает страницу
     при фокусе в поле со шрифтом меньше, и это правило сильнее вида. */
  font-family: inherit;
  font-size: 13px;
  line-height: 1.5;
  color: var(--text);
  caret-color: var(--text);
  resize: none;
  overflow: hidden;
  outline: none;
}
.pub-post-comment-field::placeholder { color: var(--text-3); }
.pub-post-comments .field-error { margin: 6px 0 0; }

/* Состояние первого комментария в карточке публикации. */
.pub-detail-comment {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--surface-2);
}
.pub-detail-comment-label {
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: .02em;
  text-transform: uppercase;
  color: var(--text-3);
}
.pub-detail-comment-text { margin: 0; font-size: 13px; line-height: 1.5; }
.pub-detail-comment-state { margin: 0; font-size: 12.5px; color: var(--text-2); }
.pub-detail-comment.is-error .pub-detail-comment-state { color: var(--danger); }

/* Служебное под макетом: требования, счётчик, ошибки, проба адреса. */
.pub-compose-meta {
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-width: 470px;
}
.pub-compose-meta > p { margin: 0; }
.pub-compose-meta .status:empty { display: none; }
.pub-compose-meta .pub-items:empty { display: none; }
.pub-compose-meta .field-note:empty { display: none; }
.pub-progress {
  display: block;
  height: 6px;
  border-radius: 3px;
  background: var(--border-2);
  overflow: hidden;
}
.pub-progress-bar { display: block; height: 100%; width: 0; background: var(--accent); transition: width .15s ease; }
.pub-caption-count { font-variant-numeric: tabular-nums; }
.pub-caption-count.is-over { color: var(--danger); }

/* Файл, принятый сервером: размер, размеры и вердикт пробы. Строка идёт под
   макетом: внутри поста ей места нет, там сам кадр. */
.pub-items { display: flex; flex-direction: column; gap: 8px; }
.pub-items[hidden] { display: none; }
.pub-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 9px;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--surface-2);
}
.pub-item-thumb {
  flex: none;
  width: 40px;
  height: 40px;
  object-fit: cover;
  border-radius: 6px;
  background: var(--border-2);
}
.pub-item-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.pub-item-title { font-size: 12.5px; font-weight: 500; overflow-wrap: anywhere; }
.pub-item-ok { font-size: 12px; color: var(--ok); }
.pub-item-warn { font-size: 12px; color: var(--danger); }
/* «Убрать» живёт поверх кадра: в строке файла это был бы второй такой же
   элемент управления на один и тот же файл. */
.pub-item [data-pub-item-action="remove"] { display: none; }

.pub-share-feed { display: inline-flex; align-items: center; gap: 8px; font-size: 14px; }
.pub-share-feed input { width: 16px; height: 16px; margin: 0; }
.pub-check { display: flex; flex-direction: column; gap: 6px; align-items: flex-start; }
.pub-check .field-note, #pub-detail-check-result {
  margin: 0;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  font-size: 12.5px;
  line-height: 1.5;
}
#pub-detail-check-result { margin-top: 8px; }

/* Подвал формы: «Отмена» слева со статусом, действия справа. */
.pub-foot-left { display: flex; align-items: center; gap: 12px; min-width: 0; }

/* Карточка публикации */
.pub-detail { display: flex; flex-direction: column; gap: 16px; }
.pub-detail-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.pub-detail-step { font-size: 13.5px; line-height: 1.5; color: var(--text-2); }
.pub-detail-link-row { margin: 0; }
.pub-detail-link { font-size: 14px; }
.pub-detail-caption {
  margin: 0;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--ivory);
  font-size: 13.5px;
  line-height: 1.5;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.pub-detail-items { display: flex; gap: 10px; flex-wrap: wrap; }
.pub-detail-items:empty { display: none; }
.pub-detail-item { display: flex; flex-direction: column; gap: 4px; max-width: 100%; }
.pub-detail-thumb {
  display: block;
  width: 160px;
  max-width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  border-radius: var(--r-md);
  background: var(--border-2);
}
.pub-detail-item-meta { font-size: 11.5px; color: var(--text-3); white-space: nowrap; }
.pub-detail-insights { margin-bottom: 0; }
.pub-detail-insights:empty { display: none; }
.pub-insights-attempt { margin: 4px 0 10px; }
.pub-insights-notice { margin: 10px 0; padding: 10px 12px; border-radius: var(--r-md); background: var(--canvas); color: var(--text-2); font-size: 12px; }
.pub-insights-notice[data-tone="error"] { background: var(--danger-soft); color: var(--danger); }
.pub-insights-history { margin-top: 10px; color: var(--text-2); font-size: 12px; }
.pub-insights-history summary { padding: 4px 0; width: fit-content; cursor: pointer; }
.pub-insights-history .field-note { margin-top: 8px; }
.pub-insights-boundary { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--border); }
.pub-detail-insights + .field-note[data-tone="fresh"] { color: var(--ok); }
.pub-detail .field { display: flex; flex-direction: column; gap: 6px; }
.pub-detail .field-note { margin: 0; font-size: 12.5px; line-height: 1.5; color: var(--text-3); }

/* Меню карточки: тот же fixed-слой (.kb-menu), фиксированная ширина. */
.pub-detail-menu-wrap { position: relative; }
.pub-detail-menu { width: 172px; }

/* Чипы ключевых слов: поле выглядит как input, слова внутри плашками. */
.chips {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  min-height: 34px;
  padding: 4px 8px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface);
  cursor: text;
}
.chips:focus-within { border-color: var(--accent); }
.chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 6px 2px 9px;
  border-radius: 999px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  font-size: 12.5px;
}
.chip-x {
  border: 0;
  background: none;
  font: inherit;
  font-size: 14px;
  line-height: 1;
  color: var(--text-3);
  cursor: pointer;
  padding: 0 2px;
}
.chip-x:hover { color: var(--danger); }
.chips-input {
  flex: 1 1 80px;
  min-width: 80px;
  border: 0;
  outline: 0;
  background: none;
  font: inherit;
  font-size: 13px;
  padding: 3px 0;
}

/* =====================================================   Раздел «Каналы»
   ============================================================ */


/* Метка состояния канала – `.tag` LMS: капсула 8px на ivory с hairline */
.badge {
  flex: 0 0 auto;
  padding: 3px 10px;
  border-radius: var(--r-sm);
  border: 1px solid var(--border);
  background: var(--ivory);
  font-size: 12px;
  font-weight: 500;
  color: var(--text-2);
  white-space: nowrap;
}
.badge.is-on { background: #edf9f1; border-color: #c6ecd3; color: var(--ok); }
.badge.is-off { background: var(--ivory); color: var(--text-2); }
.badge.is-error { background: var(--danger-soft); border-color: var(--danger-line); color: var(--danger); }


/* ---------- Компактный список каналов ----------

   Канал – строка, а не карточка: в свёрнутом виде видно название,
   состояние и имя бота, всё остальное открывается по нажатию. Так раздел
   остаётся списком, когда рядом с Telegram встанут Instagram и WhatsApp. */

.channels-card { padding: 0; }

.channel-item { border-bottom: 1px solid var(--border-2); }
.channel-item:last-child { border-bottom: 0; }

.channel-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 6px 20px 6px 12px;
}

/* Название и состояние – одна большая кнопка: попасть по ней легко,
   в том числе пальцем на телефоне. */
.channel-toggle {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px;
  border: 0;
  border-radius: var(--r-md);
  background: none;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
}
.channel-toggle:hover { background: var(--canvas); }
.channel-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

.channel-caret {
  flex: 0 0 auto;
  width: 8px;
  height: 8px;
  border-right: 1.8px solid var(--text-2);
  border-bottom: 1.8px solid var(--text-2);
  transform: rotate(-45deg);
  transition: transform .15s ease;
}
.channel-item.is-open .channel-caret { transform: rotate(45deg); }

.channel-ident { min-width: 0; }

.channel-name {
  display: block;
  font-size: 15px;
  font-weight: 500;
  letter-spacing: -.01em;
}

.channel-sub {
  display: block;
  margin-top: 2px;
  font-size: 13px;
  color: var(--text-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.channel-row-right {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 10px;
}

/* ---------- Тумблер «ИИ отвечает» в строке канала ----------

   Живёт в самой строке, а не в раскрытой части: отвечает ли бот в канале –
   то, что нужно видеть и переключать не разворачивая канал, наравне со
   статусом подключения. Форма та же, что у глобального тумблера в левом
   меню (.nav-switch), поэтому оба читаются как один и тот же орган
   управления, только на разных уровнях: там – все каналы, здесь – один. */

.channel-switch {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 12px;
  border: 0;
  border-radius: var(--r-button);
  background: none;
  font: inherit;
  /* Подпись одного веса в обоих состояниях: «ИИ отвечает» – название
     органа управления, а не индикатор. Гасить её в серый при выключении
     значило бы показывать рабочий режим «отвечаю руками» как неактивный. */
  color: var(--text-2);
  cursor: pointer;
  transition: background .13s ease, color .13s ease;
}
.channel-switch:hover { background: var(--canvas); }
.channel-switch:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
/* Канал не подключён: переключать нечего. Дорожка гасится до нейтральной
   независимо от aria-checked – иначе тумблер у ненастроенного канала выглядит
   включённым и обещает, что ИИ там отвечает. Само aria-checked при этом не
   врёт: флаг в базе действительно «отвечает», просто канала ещё нет. */
.channel-switch:disabled { cursor: default; opacity: .45; }

.channel-switch-label {
  font-size: 13px;
  font-weight: 500;
  white-space: nowrap;
  transition: color .15s ease;
}

/* В Промпте текст называет состояние ИИ и остаётся видимым на телефоне. */
#bot-replies-enabled .channel-switch-label,
#prompt-ai-channels .channel-switch-label { display: inline; }
#bot-replies-enabled,
#prompt-ai-channels .channel-switch { gap: 8px; }
#prompt-ai-channels .channel-ident { overflow-wrap: anywhere; max-width: 100%; }

.channel-switch-track {
  position: relative;
  display: block;
  width: 32px;
  height: 18px;
  border-radius: 999px;
  /* Выключен – нейтральный серый: «отвечаю руками» рабочий режим, не тревога. */
  background: #c9c9c7;
  transition: background .15s ease;
}

.channel-switch-knob {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 1px 2px rgba(16, 24, 40, .2);
  transition: transform .15s ease;
}

/* :not(:disabled) в самом правиле, а не отдельным блоком ниже: у
   `.channel-switch:disabled .track` и `.channel-switch[aria-checked] .track`
   одинаковая специфичность, и кто победит, решал бы порядок строк – хрупко.
   У неподключённого канала тумблер обязан выглядеть нейтральным: зелёный
   обещал бы, что ИИ там отвечает, хотя канала ещё нет. */
.channel-switch[aria-checked="true"]:not(:disabled) .channel-switch-track { background: var(--ok); }
.channel-switch[aria-checked="true"]:not(:disabled) .channel-switch-knob { transform: translateX(14px); }

/* В Промпте disabled означает права/ожидание, а не отсутствие подключения. */
#bot-replies-enabled[aria-checked="true"]:disabled .channel-switch-track,
#prompt-ai-channels [data-ai-channel][aria-checked="true"]:disabled .channel-switch-track { background: var(--ok); }
#bot-replies-enabled[aria-checked="true"]:disabled .channel-switch-knob,
#prompt-ai-channels [data-ai-channel][aria-checked="true"]:disabled .channel-switch-knob { transform: translateX(14px); }

/* Меню канала повторяет меню файла базы знаний – те же .kb-menu-btn
   и .kb-menu внутри, отличается только позиционирующая обёртка. */
.channel-actions { flex: 0 0 auto; display: flex; position: relative; }

/* «Обновить подключение» длиннее пунктов файлового меню и в 168px переносится
   на две строки. Пункт действия должен читаться одной строкой. */
.channel-actions .kb-menu { min-width: 208px; }
.channel-actions .kb-menu-item { white-space: nowrap; }

.channel-details {
  padding: 4px 24px 20px;
  border-top: 1px solid var(--border-2);
}
.channel-details[hidden] { display: none; }
.channel-details .field { margin-top: 14px; }
.channel-details > .status:empty { display: none; }
.channel-details > .status { display: block; margin-top: 12px; }

.channel-status {
  margin-top: 14px;
  padding: 14px 16px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--ivory);
}

.channel-status-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 14px;
  padding: 3px 0;
  font-size: 13px;
}
.channel-status-key { color: var(--text-2); }
.channel-status-val {
  min-width: 0;
  text-align: right;
  color: var(--text);
  overflow-wrap: anywhere;
}
.channel-status-val.is-ok { color: var(--ok); }
.channel-status-val.is-off { color: var(--text-2); }
.channel-status-val.is-error { color: var(--danger); }
.channel-status-val a { color: var(--accent); }

.channel-error {
  margin: 10px 0 0;
  padding: 10px 13px;
  border-radius: var(--r-md);
  background: var(--danger-soft);
  border: 1px solid var(--danger-line);
  font-size: 13px;
  color: var(--danger);
  overflow-wrap: anywhere;
}

.card-foot-actions { display: flex; align-items: center; gap: 8px; }

/* =====================================================   Уведомления и модальное окно
   ============================================================ */

/* Плавающая панель сохранения. Держится над контентом внизу экрана, пока
   настройки расходятся с сохранёнными. Ниже панели тостов по z-index, чтобы
   «Сохранено · Отменить» ложилось поверх, а не под неё. */
.savebar {
  position: fixed;
  left: var(--nav-w, 84px);
  right: 0;
  bottom: 0;
  z-index: 55;
  padding: 14px 24px calc(14px + env(safe-area-inset-bottom, 0px));
  background: var(--surface);
  border-top: 1px solid var(--border);
  box-shadow: rgba(0,0,0,.05) 0 -12px 24px -8px;
  animation: savebar-in .16s ease-out;
}
.savebar[hidden] { display: none; }

.savebar-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  max-width: 1180px;
  margin: 0 auto;
}
.savebar-text { font-size: 14.5px; font-weight: 500; min-width: 0; }
.savebar-actions { flex: 0 0 auto; display: flex; align-items: center; gap: 8px; }

@keyframes savebar-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

.toasts {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: 60;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 8px;
  pointer-events: none;
}
/* Панель сохранения занимает низ экрана – тосты поднимаются над ней. */
.toasts.has-savebar { bottom: calc(20px + var(--savebar-h, 62px)); }

/* Тост как в LMS: светлая карточка с hairline в тон состояния, а не тёмная
   плашка. Успех – зелёный, ошибка – rust, нейтральный – белый. */
.toast {
  min-width: 210px;
  max-width: 360px;
  padding: 12px 16px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface);
  color: var(--text);
  font-size: 13.5px;
  box-shadow: rgba(18,23,34,.04) 0 1px 2px, rgba(18,23,34,.08) 0 8px 20px, rgba(18,23,34,.06) 0 24px 48px;
  animation: toast-in .16s ease-out;
}
.toast.is-error { background: var(--danger-soft); border-color: var(--danger-line); color: var(--danger); }
.toast.is-ok { background: #edf9f1; border-color: #c6ecd3; color: var(--ok); }

/* Тост с действием кликабелен, поэтому возвращает себе события мыши:
   контейнер их не принимает, иначе он перехватывал бы клики по странице. */
.toast-action-row {
  pointer-events: auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
}
.toast-action-text { min-width: 0; }
.toast-undo {
  flex: 0 0 auto;
  padding: 4px 12px;
  border: 1px solid var(--border);
  border-radius: var(--r-button);
  background: var(--surface);
  color: var(--text);
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
}
.toast-undo:hover { background: var(--canvas); border-color: var(--faint); }
.toast-undo:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.toast-undo[disabled] { opacity: .55; cursor: default; }

@keyframes toast-in {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: translateY(0); }
}

.modal-backdrop {
  position: fixed;
  inset: 0;
  z-index: 70;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  background: rgba(17, 19, 26, .48);
}

.modal {
  width: 100%;
  max-width: 420px;
  padding: 24px 24px 20px;
  background: var(--surface);
  border-radius: 20px;
  box-shadow: var(--shadow-lg);
}
.modal-title { margin: 0 0 8px; font-size: 20px; font-weight: 600; letter-spacing: -.014em; }
.modal-text { margin: 0 0 20px; font-size: 14.5px; line-height: 1.5; color: var(--text-2); }
.modal-actions { display: flex; justify-content: flex-end; gap: 8px; }

/* =====================================================   Адаптив
   ============================================================ */

@media (max-width: 1100px) {
  /* Панель профиля рядом с перепиской уже не помещается: она выезжает
     поверх правого края по кнопке «Профиль» в шапке чата. */
  .view-chat { position: relative; }
  .chat-profile-open { display: inline-flex; }
  .chat-profile-open[hidden] { display: none; }
  .chat-profile-close { display: inline-flex; }
  .chat-profile {
    position: absolute;
    top: 0; right: 0; bottom: 0;
    z-index: 5;
    width: min(var(--profile-w), 100%);
    box-shadow: var(--shadow-lg);
    display: none;
  }
  .view-chat.is-profile-open .chat-profile:not([hidden]) { display: flex; }

  /* Колонки складываются: промпт сверху, тестовый чат под ним */
  .settings-cols { grid-template-columns: minmax(0, 1fr); }
  .card-col { min-height: 0; }
  /* В одну колонку карточка не тянется сама: задаём ей рабочую высоту, чтобы
     поле промпта осталось высоким и прокручивалось внутри себя. Высоту берём
     от экрана, но не ниже рабочего минимума. */
  .card-col.card-col-prompt { height: auto; min-height: max(700px, calc(100vh - 118px)); }
  /* В одну колонку тестовый чат снова растёт по содержимому: экранной
     высоты на две карточки всё равно не хватит, и страница прокручивается. */
  .settings-cols > .card-col:not(.card-col-prompt) { height: auto; }
  /* В одну колонку плашки и итоги переносятся и занимают больше высоты –
     поле промпта защищаем отдельным минимумом. */
  /* В одну колонку карточка растёт вниз, места хватает: поле остаётся
     полноразмерным, а не ужимается до трёх строк. */
  /* Слот сохраняет общий min-content: переносы плашек на телефоне
     увеличивают его высоту и не должны накрывать следующий блок. */
  .prompt-editable { min-height: 384px; }
  .messages-test { min-height: 260px; max-height: 420px; }
}

@media (max-width: 1000px) {
  /* Сайдбар 220px и список чатов 308px вместе съедают половину планшета, и
     переписке остаётся полоса. Обе колонки ужимаются, пункты меню остаются
     подписанными: прятать их в значки на этой ширине незачем. */
  :root { --nav-w: 184px; --list-w: 264px; }
  .nav { padding: 16px 10px; }
  .nav-item { padding: 0 12px; gap: 9px; }
  .nav-label { font-size: 14px; }
  .settings-inner { padding: 26px 20px 56px; }
  .messages { padding: 18px 16px 6px; }
  .composer { padding: 10px 16px 14px; }
}

@media (max-width: 720px) {
  :root { --nav-w: 64px; }

  /* На телефоне меню уезжает вниз (блок в конце файла), здесь остаются только
     размеры, общие для узких экранов. */
  .nav { padding: 8px 6px; gap: 2px; }
  .nav-label { font-size: 10px; letter-spacing: 0; }
  .nav-brand { margin-bottom: 8px; font-size: 14px; }
  .nav-item { min-height: auto; padding: 7px 2px 6px; gap: 3px; }
  .nav-icon { width: 19px; height: 19px; }

  /* Тумблер сжимается вместе с меню: подпись остаётся – без неё непонятно,
     в каком режиме бот, а это единственное место, где режим виден. */
  .nav-switch { margin-bottom: 6px; padding: 7px 2px 6px; gap: 4px; }
  .nav-switch-label { font-size: 10px; }
  .nav-switch-track { width: 30px; height: 17px; }
  .nav-switch-knob { width: 13px; height: 13px; }
  .nav-switch[aria-checked="true"] .nav-switch-knob { transform: translateX(13px); }

  /* Список и переписка показываются по очереди */
  .chat-list {
    flex: 1;
    width: auto;
    border-right: 0;
  }
  .chat-room { display: none; }

  .view-chat.is-room-open .chat-list { display: none; }
  .view-chat.is-room-open .chat-room { display: flex; flex: 1; }
  /* На телефоне профиль занимает весь экран раздела, как и переписка. */
  /* Двум подписанным кнопкам в шапке на 375 тесно: ник собеседника
     обрезался до «@mari…». Кнопка профиля остаётся значком, подпись читает
     скринридер из aria-label. */
  .chat-profile-open { padding: 0; width: 34px; justify-content: center; }
  .chat-profile-open-label { display: none; }
  .chat-profile { width: 100%; box-shadow: none; border-left: 0; }

  .btn-back { display: inline-flex; }

  .bubble { max-width: 86%; }
  .btn-send { padding: 0 13px; }

  /* Панель сохранения прижимается к левому краю вслед за узкой навигацией */
  .savebar { left: var(--nav-w); padding-left: 16px; padding-right: 16px; }
}

@media (max-width: 560px) {
  /* Полоса вкладок на узком экране: чуть плотнее, прокрутка остаётся внутри */
  .segmented-tabs { margin-bottom: 16px; }
  .segmented-item { padding: 7px 12px; font-size: 13px; }
  /* Переключатель роли остаётся компактным: правило выше по файлу задано с
     той же специфичностью и иначе перебило бы его. Подпись уходит под
     переключатель – в строку они на 375px не помещаются. */
  .segmented-sm .segmented-item { padding: 5px 10px; font-size: 12.5px; }
  .composer-role { flex-direction: column; align-items: flex-start; gap: 5px; }
  .composer-role-note { font-size: 12px; }

  /* Шапка карточки: заголовок и кнопка в столбик */
  .card-head { flex-direction: column; align-items: stretch; gap: 10px; }
  .card-head .btn { align-self: flex-start; }

  /* Узкий экран: имя переменной сверху, счётчик под ним – иначе они жмутся */
  .var-chip { flex-direction: column; align-items: flex-start; gap: 3px; }
  .var-chip-count { text-align: left; }

  /* Файл базы знаний: имя сверху, переключатель и кнопки под ним */
  .kb-row {
    flex-wrap: wrap;
    align-items: flex-start;
    row-gap: 10px;
  }
  .kb-main {
    order: -1;
    flex: 1 0 100%;
  }
  .kb-name { white-space: normal; }
  .kb-toggle { flex: 1 1 auto; }
  .kb-actions { flex: 0 0 auto; }

  .card-foot { flex-direction: column; align-items: stretch; gap: 10px; }
  .card-foot .btn { width: 100%; }
  .card-foot .status:empty { display: none; }

  .card-foot-actions { flex-direction: column-reverse; align-items: stretch; }

  /* Ключ сверху, значение под ним – иначе длинный username жмётся в угол */
  .channel-status-row { flex-direction: column; gap: 1px; }
  .channel-status-val { text-align: left; }

  /* Строка канала: бейдж состояния уводим из строки – там уже есть та же
     информация словами в подписи под названием, а места на узком экране нет. */
  .channel-row { padding: 4px 12px 4px 6px; gap: 6px; }
  .channel-row .badge { display: none; }

  /* Тумблер остаётся, подпись уходит: на узком экране места нет, а состояние
     читается и по самому переключателю. Но тогда он безымянный, поэтому
     доступное имя обязано жить в aria-label кнопки, а не только в подписи. */
  .channel-switch { padding: 6px 4px; gap: 0; }
  .channel-switch-label { display: none; }

  /* Бейдж на узком экране скрыт, значит режим «отвечаете руками» читается
     только из подписи – а она в одну строку обрезается на середине имени
     бота. Разрешаем две строки: место под строкой канала есть, а потерять
     режим нельзя, иначе «бот молчит» выглядит как поломка. */
  .channel-sub {
    white-space: normal;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
  }
  .channel-details { padding: 4px 16px 16px; }

  /* Раздел «Рассылка» на телефоне.
     Заголовок карточки складывается в колонку, кнопки растягиваются на
     всю ширину: «Новая рассылка» и «Остановить» на 375px иначе жмутся в
     угол и мажутся мимо пальца. */
  #camp-list-card .card-head,
  #camp-detail-card .card-head { flex-direction: column; align-items: stretch; gap: 10px; }
  #camp-list-card .card-head > .btn { width: 100%; }
  .camp-detail-actions > .btn { flex: 1; }

  /* У формы «Отмена» остаётся сбоку от заголовка, а подзаголовок уходит
     совсем: в столбик они съедали треть экрана над самой формой, ради
     которой её и открыли. Это выход из формы, а не главное действие. */
  #camp-form-card .card-head { align-items: flex-start; gap: 10px; }
  #camp-form-card .card-head .card-sub { display: none; }
  #camp-form-card .card-head > .btn { flex: none; }

  /* Строка кампании: кнопка «Остановить» уходит под название, а не
     отжимает его в одну букву. */
  .camp-item { flex-wrap: nowrap; align-items: flex-start; gap: 8px; padding: 16px 0; }
  .camp-list-columns { display: none; }
  .camp-item-main { grid-template-columns: minmax(0, 1fr); gap: 8px; }
  .camp-item-name { white-space: normal; overflow-wrap: anywhere; }
  .camp-item-results, .camp-item-state, .camp-item-dates { padding-left: 42px; }
  .camp-section { padding: 20px 0; }
  .camp-connection-field { max-width: none; }
  .camp-connection-help { align-items: flex-start; }
  .camp-item > .btn { width: 100%; }

  .camp-channel { flex: 1; justify-content: center; }
  /* На телефоне два поля рядом не помещаются: каждое сжималось бы до
     нечитаемой ширины, и «в одну строку» переставало экономить место. */
  .camp-row { flex-direction: column; gap: 10px; }
  .camp-row > .field { width: 100%; }
  .camp-aud-head { align-items: stretch; gap: 6px; }
  .camp-aud-tools { margin-left: 0; width: 100%; min-width: 0; }
  .camp-aud-search { max-width: none; flex: 1 1 auto; }
  /* На телефоне экран короче, а форма та же: список ужимается сильнее,
     иначе он один съедает треть доступной высоты. */
  .camp-aud-list { max-height: 156px; }
  .camp-textarea { min-height: 76px; height: 76px; }
  /* Подписи фильтров выравниваются по нижнему краю: «Последнее сообщение от»
     переносится в две строки, и её поле уезжало ниже соседнего «до». */
  /* На телефоне подпись занимает свою строку, а два поля дат делят
     следующую: иначе тире и второе поле переносились вразнобой. */
  .camp-filter-group { flex-wrap: wrap; width: 100%; }
  .camp-filter-label { width: 100%; }
  .camp-filter-group input { flex: 1 1 0; width: auto; min-width: 0; }
  .camp-filters-reset { margin-left: 0; }
  /* Второй столбец уходит под первый: рядом они на 375px нечитаемы. */
  .camp-msg-cols.is-split { grid-template-columns: 1fr; }
  .camp-mode-head { align-items: stretch; }
  .camp-pace, .camp-at { max-width: none; }
  .camp-pace-field { width: 100%; }
  .camp-target-right { align-self: flex-start; }
  .camp-when { gap: 12px; }
  .camp-counters { gap: 8px; }

  /* Строка получателя: статус переезжает под имя, иначе длинная причина
     («Окно 24 часа закрыто…») выдавливает имя за край. */
  .camp-target { flex-direction: column; gap: 2px; }
  .camp-target-status { text-align: left; }

  /* Панель сохранения: текст сверху, кнопки в ряд под ним. «Сохранить» справа
     остаётся под большим пальцем. */
  .savebar-inner { flex-direction: column; align-items: stretch; gap: 9px; }
  .savebar-actions { justify-content: flex-end; }
  .savebar-actions .btn { flex: 1 1 0; }

  /* Меню файла раскрывается вправо от края экрана – прижимаем к правому краю
     строки и ограничиваем ширину, иначе оно вылезает за вьюпорт. */
  .kb-menu { min-width: 150px; max-width: calc(100vw - 40px); }

  /* Селект модели в итогах занимает всю ширину строки */
  .model-inline { align-items: stretch; }
  .model-inline .select { max-width: none; flex: 1 1 100%; }

  /* Тост с кнопкой отмены не должен упираться в края */
  .toasts { left: 12px; right: 12px; align-items: stretch; }
  .toast { max-width: none; }
}

/* Тумблер «ИИ отвечает» в шапке чата на узком экране (§ 5.38). Шапка
   растёт второй строкой только когда есть срок: имя собеседника не делит
   первую строку с подписью. display: contents выводит срок и тумблер прямо
   в строку шапки, и срок переносится под неё. */
@media (max-width: 560px) {
  .chat-head { gap: 8px; }
  .chat-head:has(.chat-ai:not([hidden]) .chat-ai-note:not([hidden])) {
    flex-wrap: wrap;
    align-content: center;
    height: auto;
    min-height: 64px;
    padding-top: 8px;
    padding-bottom: 8px;
    row-gap: 2px;
  }
  .chat-ai { display: contents; }
  .chat-ai[hidden] { display: none; }
  .chat-ai-note {
    order: 10;
    flex: 1 0 100%;
    margin-top: 0;
    padding-right: 0;
    text-align: right;
    color: var(--text-2);
  }
  /* Подпись тумблера на узком экране скрыта – срок называет режим сам. */
  .chat-ai-note::before { content: 'ИИ молчит · '; }
}

@media (max-width: 420px) {
  .pane-head, .chat-head { padding-left: 14px; padding-right: 12px; }
  .settings-inner { padding: 20px 14px 48px; }
  .card-head, .card-body, .card-foot, .kb-row { padding-left: 14px; padding-right: 14px; }
  .kb-editor { padding-left: 14px; padding-right: 14px; }
  .messages-test, .composer-test, .test-note { padding-left: 14px; padding-right: 14px; }
  .prompt-compose { padding-left: 14px; padding-right: 14px; }
}

/* =====================================================   Телефон (≤720px): навигация уезжает вниз, контент во всю ширину.
   Блок стоит последним и намеренно перекрывает правила выше: на узком
   экране боковое меню в 64px съедало шестую часть ширины, а нижняя
   полоса – привычный для телефона паттерн и не мешает большому пальцу.
   ============================================================ */
@media (max-width: 720px) {
  :root { --bottom-nav-h: 62px; }

  .app {
    flex-direction: column;
    /* dvh учитывает адресную строку мобильного браузера; vh на iOS
       оставлял композер под панелью Safari. */
    height: 100vh;
    height: 100dvh;
  }
  .view { flex: 1; min-height: 0; }

  .nav {
    order: 2;
    flex: 0 0 auto;
    width: 100%;
    flex-direction: row;
    align-items: stretch;
    justify-content: flex-start;
    overflow-x: auto;
    gap: 2px;
    padding: 6px 6px calc(6px + env(safe-area-inset-bottom, 0px));
    border-right: 0;
    border-top: 1px solid var(--border);
  }
  .nav-brand, .nav-spacer { display: none; }
  /* В нижней полосе значок снова встаёт над подписью: в строку семь пунктов
     на 375px не помещаются. Подложка тумблера и рамка «Выхода» тоже снимаются –
     в горизонтальном ряду они читались бы чужеродными плашками. */
  .nav-item, .nav-switch {
    flex: 0 0 64px;
    min-width: 64px;
    min-height: auto;
    margin: 0;
    padding: 7px 2px 5px;
    gap: 4px;
    flex-direction: column;
    align-items: center;
    justify-content: center;
  }
  .nav-switch { border: 0; background: transparent; box-shadow: none; border-radius: var(--r-md); }
  .nav-item-quiet { border-top: 0; border-radius: var(--r-md); }
  /* Восемь пунктов на 375px (с «Публикациями»): кегль меньше, и подпись
     переносится по мягкому дефису внутри своей доли ширины, а не режется
     многоточием – «Расс…» и «Отвеч…» не читались. hyphens здесь обязателен:
     базовое правило выключает переносы под широкую колонку сайдбара, и без
     возврата слово вылезало на «Выход». Без обрезки: она отсекала хвост
     второй строки, и «зация» превращалась в «заци». */
  .nav-label, .nav-switch-label, .nav-label-wrap {
    font-size: 9.5px;
    letter-spacing: -.01em;
    line-height: 1.05;
    max-width: 100%;
    text-align: center;
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
    hyphens: manual;
  }
  .nav-icon { width: 22px; height: 22px; }
  .nav-switch-track { width: 34px; height: 19px; }
  .nav-switch-knob { width: 15px; height: 15px; }
  .nav-switch[aria-checked="true"] .nav-switch-knob { transform: translateX(15px); }

  /* Панель сохранения и тосты живут над нижним меню, а не под ним. */
  .savebar {
    left: 0;
    bottom: calc(var(--bottom-nav-h) + env(safe-area-inset-bottom, 0px));
    padding-bottom: 12px;
  }
  .toasts { bottom: calc(var(--bottom-nav-h) + 12px + env(safe-area-inset-bottom, 0px)); }
  .toasts.has-savebar { bottom: calc(var(--bottom-nav-h) + 12px + var(--savebar-h, 62px) + env(safe-area-inset-bottom, 0px)); }

  /* Поля ввода не меньше 16px: иначе iPhone приближает страницу при фокусе. */
  .input, .textarea, .composer-input, select.select { font-size: 16px; }

  /* Композер чата: меньше воздуха, подсказка короче по высоте, поле выше. */
  .composer { padding: 8px 12px 10px; gap: 6px; }
  .composer-role-note { font-size: 11.5px; line-height: 1.3; }
  .composer-input { min-height: 44px; }
  .btn-send { height: 44px; }
  .messages { padding: 14px 12px 6px; }
  .bubble { max-width: 88%; }

  /* Настройки: заголовок компактнее, вкладки в две строки вместо скрытой
     горизонтальной прокрутки – так видно все пять сразу. */
  .settings-inner { padding: 16px 14px calc(40px + env(safe-area-inset-bottom, 0px)); }
  .page-head { margin-bottom: 12px; }
  .page-title { font-size: 22px; }
  .page-sub { font-size: 13px; }
  .segmented-tabs {
    width: 100%;
    flex-wrap: wrap;
    overflow: visible;
    margin-bottom: 14px;
  }
  .segmented-tabs .segmented-item { flex: 1 1 auto; text-align: center; }

  /* Список чатов: чуть крупнее строки под палец. */
  .pane-head { padding-left: 14px; padding-right: 12px; }
  .chat-item { padding-top: 12px; padding-bottom: 12px; }
}

/* iOS Safari: документ прокручивается целиком, даже когда контент влезает в
   экран – так работают его выезжающие панели. Для чата это значит, что при
   попытке пролистать ленту уезжает весь интерфейс вместе с меню и
   композером. Стандартное решение: на телефоне документу нечего
   прокручивать – body зафиксирован, скроллят только внутренние ленты. */
@media (max-width: 720px) {
  html, body {
    height: 100%;
    overflow: hidden;
    overscroll-behavior: none;
  }
  body {
    position: fixed;
    inset: 0;
    width: 100%;
  }
  .app { height: 100%; }
  .login-screen { height: 100%; overflow-y: auto; }

  /* Ленты прокручиваются сами и не передают скролл наружу. */
  .messages, .chat-list-body, .settings-scroll {
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
  }

  /* Тап без серой вспышки, как в нативных приложениях. */
  * { -webkit-tap-highlight-color: transparent; }
}

/* iPhone приближает страницу при фокусе в поле со шрифтом меньше 16px.
   Правило выше задавало 16px, но у отдельных полей (содержимое базы знаний,
   поле промпта, моно-поля) свой размер стоит позже по файлу и перебивает.
   Этот блок последний, поэтому побеждает он. touch-action убирает и зум по
   двойному тапу, чтобы прокрутка не превращалась в увеличение. */
@media (max-width: 720px) {
  .input, .textarea, .textarea.mono, .kb-editor .kb-content, .prompt-editable,
  .composer-input, .camp-textarea, select.select, input, textarea, select {
    font-size: 16px !important;
  }
  html, body, .app { touch-action: manipulation; }
}

/* =====================================================   Вкладка «Журнал»
   ============================================================ */

/* Плитки очереди над списком автоматизаций: те же .camp-counter, только
   отступ снизу чуть больше, чтобы плитки не липли к подсказке про Instagram. */

/* Фильтры в одну строку; поиск забирает остаток. На узком экране переносятся. */
.events-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  padding: 14px 24px;
  border-bottom: 1px solid var(--border-2);
}
.events-select { flex: 0 1 180px; min-width: 140px; }
.events-search { flex: 1 1 200px; min-width: 160px; }

/* Таблица шире карточки прокручивается внутри своего контейнера, а не
   растягивает страницу: у .card стоит overflow: hidden ради углов. */
.events-scroll { overflow-x: auto; }

.events-table {
  width: 100%;
  border-collapse: collapse;
  table-layout: fixed;
  font-size: 13px;
}
.events-table th {
  padding: 8px 12px;
  text-align: left;
  font-size: 11.5px;
  font-weight: 500;
  letter-spacing: .02em;
  text-transform: uppercase;
  color: var(--text-3);
  border-bottom: 1px solid var(--border-2);
  white-space: nowrap;
}
.events-table th:first-child, .events-table td:first-child { padding-left: 24px; }
.events-table th:last-child, .events-table td:last-child { padding-right: 24px; }
.events-table td {
  padding: 9px 12px;
  vertical-align: top;
  border-bottom: 1px solid var(--border-2);
  line-height: 1.45;
}
.events-table tbody tr:last-child td { border-bottom: 0; }
.ev-row:hover td { background: var(--ivory); }

/* Ширины колонок: время и уровень фиксированы, сообщение забирает остаток
   и переносится по словам. Без этого длинный текст ошибки Meta раздвигал
   бы таблицу за край карточки. */
.ev-col-time { width: 84px; }
.ev-col-level { width: 92px; }
.ev-col-area { width: 130px; }

.ev-time { color: var(--text-3); font-variant-numeric: tabular-nums; white-space: nowrap; }
.ev-area { color: var(--text-2); overflow-wrap: anywhere; }
.ev-msg { overflow-wrap: anywhere; }
.ev-msg-text { color: var(--text); }
.ev-ctx-btn { font-size: 12.5px; white-space: nowrap; }

/* Уровень: цветная точка плюс слово. Цвет один не остаётся: без слова
   различить серый и жёлтый маркер на бледном фоне трудно. */
.ev-level { white-space: nowrap; color: var(--text-2); }
.ev-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  margin-right: 7px;
  border-radius: 50%;
  background: var(--faint);
  vertical-align: 1px;
}
.ev-row.is-warn .ev-dot { background: #d99a1c; }
.ev-row.is-warn .ev-level { color: #8a5a00; }
.ev-row.is-error .ev-dot { background: var(--danger); }
.ev-row.is-error .ev-level { color: var(--danger); }

/* Раскрытый контекст: на всю ширину, с переносом длинных строк, чтобы
   тело ответа Meta не уезжало вправо. */
.ev-ctx td { padding: 0 24px 12px; background: var(--ivory); border-bottom: 1px solid var(--border-2); }
.ev-ctx-pre {
  margin: 0;
  padding: 10px 12px;
  max-height: 320px;
  overflow: auto;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12px;
  line-height: 1.5;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  color: var(--text-2);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
}

.events-foot .status:empty { display: none; }
.events-foot:has(.status:empty) { justify-content: flex-end; }

@media (max-width: 560px) {
  /* На 375px четыре колонки не помещаются: строка складывается в карточку –
     время, уровень и область в одну служебную строку, сообщение под ней. */
  .events-table thead { display: none; }
  .events-table, .events-table tbody, .events-table tr, .events-table td { display: block; width: auto; }
  .ev-row { padding: 10px 16px; border-bottom: 1px solid var(--border-2); }
  .ev-row td { display: inline; padding: 0; border: 0; line-height: 1.5; }
  .ev-row .ev-time::after, .ev-row .ev-level::after { content: ' · '; color: var(--text-3); }
  .ev-row .ev-msg { display: block; margin-top: 2px; }
  .ev-row:hover td { background: transparent; }
  .ev-ctx td { padding: 0 16px 12px; }
  .events-filters { padding: 12px 16px; }
  .events-select { flex: 1 1 45%; min-width: 0; }
  .events-search { flex: 1 1 100%; }
  .events-table th:first-child, .events-table td:first-child,
  .events-table th:last-child, .events-table td:last-child { padding-left: 0; padding-right: 0; }
}

/* Узкий экран раздела «Публикации»: сетка в две колонки, кнопки во всю
   ширину, слайд и миниатюры карточки на всю строку. Блок в конце файла,
   чтобы не перебивать порядок узкоэкранных правил соседних разделов. */
@media (max-width: 560px) {
  .pub-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 2px; }
  .pub-tile { border-radius: 2px; }
  .pub-tile-corner { left: 7px; bottom: 6px; font-size: 12.5px; gap: 4px; }
  .pub-tile-corner .pub-tile-icon { width: 15px; height: 15px; }
  .pub-tile-kind { top: 6px; right: 6px; }
  .pub-tile-kind .pub-tile-icon { width: 16px; height: 16px; }
  .pub-tile-tag, .pub-tile .pub-trial-chip { top: 6px; left: 6px; font-size: 10.5px; padding: 1px 6px; }
  .pub-tile.is-trial::before { border-width: 2px; }
  .pub-tile-bar { left: 7px; right: 7px; bottom: 6px; font-size: 11px; }
  /* Окно поста на телефоне – во весь экран и в столбик: медиа сверху, под
     ним подпись и комментарии одной прокруткой. */
  .pubv-backdrop { padding: 0; align-items: stretch; }
  .pubv { flex-direction: column; height: auto; max-width: none; border-radius: 0; overflow-y: auto; }
  .pubv-media { flex: none; height: 56vh; aspect-ratio: auto; }
  .pubv-side { flex: 1 0 auto; border-left: 0; }
  .pubv-body { overflow: visible; flex: none; }
  .pubv-close { top: 8px; right: 8px; background: rgba(0, 0, 0, .45); border-radius: 50%; z-index: 2; }
  .pubv-nav { top: 28vh; z-index: 2; }
  .pubv-nav-prev { left: 8px; }
  .pubv-nav-next { right: 8px; }
  /* Кнопки шапки списка растягиваются на всю ширину, как у рассылки. */
  #pub-list-card .card-head .btn, #pub-detail-card .card-head .btn { flex: 1 1 auto; }
  .pub-detail-actions .btn, #pub-list-card .camp-detail-actions .btn { align-self: stretch; }
  .pub-empty-actions { flex-direction: column; align-items: stretch; }
  .pub-foot-left { flex-direction: column; align-items: stretch; }
  .pub-foot-left .btn { width: 100%; }
  /* Макет поста на телефоне занимает всю ширину карточки: телефонная
     ширина и есть его родная среда, ограничение 470px тут только сузило бы. */
  .pub-post, .pub-compose-meta { max-width: none; }
  /* Комментарий переносится под ник, а не висячим отступом от него: на узком
     экране на строку рядом с ником влезает пара слов, и текст читался
     лестницей. Ник остаётся первой строкой, текст идёт во всю ширину. */
  /* На узком экране ник остаётся в потоке текста, обтекание сохраняется. */
  .pub-post-comment-name { float: left; }
  /* Строка принятого файла узкая: «Убрать» на всю ширину разорвал бы её
     на три этажа внутри поста. */
  .pub-item { flex-wrap: nowrap; }
  .pub-detail-item, .pub-detail-thumb { width: 100%; }
  .pub-detail-item-meta { white-space: normal; }
}

/* =====================================================   Раздел «Аналитика»
   =====================================================   Плитки, таблицы и графики. Графики нарисованы inline SVG: в проекте нет
   сборки и внешних зависимостей на фронте, и библиотека ради трёх графиков
   меняла бы это ради мелочи. */

.an-head-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

/* Строка свежести в шапке: «Обновлено 5 мин назад · Обновить». Подпись
   тихая, кнопка обычная призрачная; точка-разделитель рисуется CSS, чтобы
   при скрытой подписи не оставалось висячего знака. */
.an-fresh { display: inline-flex; align-items: center; gap: 8px; }
.an-fresh-text { font-size: 12.5px; color: var(--text-3); white-space: nowrap; }
.an-fresh-text::after { content: ' ·'; }
.an-fresh-text.is-warn { color: var(--danger); }

/* Полоса вкладок раздела. Своя, а не общая с «Промптом»: там вкладки правят
   один документ, здесь переключают разные наборы данных. */
.an-tabs {
  display: flex;
  gap: 4px;
  flex-wrap: wrap;
  border-bottom: 1px solid var(--border);
  margin-bottom: 18px;
}

.an-tab {
  appearance: none;
  border: 0;
  background: transparent;
  color: var(--text-dim, #5b6472);
  font: inherit;
  font-size: 14px;
  padding: 9px 14px;
  border-radius: var(--r-sm) var(--r-sm) 0 0;
  cursor: pointer;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}

.an-tab:hover { background: var(--canvas); color: var(--text); }

.an-tab.is-active {
  color: var(--accent-dark);
  border-bottom-color: var(--accent);
  font-weight: 500;
}

.an-h3 {
  font-size: 15px;
  font-weight: 600;
  color: var(--text);
  margin: 24px 0 12px;
}

.an-h4 {
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
  margin: 0 0 10px;
}

.an-note {
  font-size: 13px;
  color: var(--text-dim, #5b6472);
  margin: 8px 0;
}

.an-freshness {
  margin-top: 20px;
  padding-top: 14px;
  border-top: 1px solid var(--border);
}

.an-muted { color: var(--faint); }

/* Плитки: число крупно, дельта под ним. */
.an-tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 12px;
}

.an-tile {
  background: var(--ivory);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: 14px 16px;
}

.an-tile-title {
  font-size: 12.5px;
  color: var(--text-dim, #5b6472);
  margin-bottom: 6px;
}

.an-tile-value {
  font-size: 24px;
  font-weight: 600;
  color: var(--text);
  line-height: 1.15;
  /* Длинные числа не должны распирать плитку на узком экране. */
  overflow-wrap: anywhere;
}

.an-tile-delta { margin-top: 6px; font-size: 12px; }

.an-delta-up { color: var(--ok); }
.an-delta-down { color: var(--danger); }
.an-delta-flat, .an-delta-none { color: var(--faint); }

/* Простые показатели без дельты. */
.an-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 12px;
}

.an-stat {
  background: var(--ivory);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: 12px 14px;
}

.an-stat-title { font-size: 12.5px; color: var(--text-dim, #5b6472); }
.an-stat-value { font-size: 19px; font-weight: 600; margin-top: 4px; overflow-wrap: anywhere; }

/* Графики. */
.an-chart-wrap { margin-top: 20px; }

.an-chart {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: 12px;
}

.an-svg { width: 100%; height: auto; display: block; }

.an-grid-line { stroke: var(--border); stroke-width: 1; }
.an-axis { fill: var(--faint); font-size: 10px; }

.an-line {
  fill: none;
  stroke-width: 2;
  stroke-linejoin: round;
  stroke-linecap: round;
}

.an-line-0 { stroke: var(--accent); }
/* Вторая серия – оранжевая: пара кобальт и оранжевый проверена на
   различимость при нарушениях цветового зрения, кобальт и фиолетовый – нет. */
.an-line-1 { stroke: #eb6834; }
circle.an-line-0 { fill: var(--accent); stroke: none; }
circle.an-line-1 { fill: #eb6834; stroke: none; }

.an-legend {
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
  margin-top: 10px;
  font-size: 12.5px;
  color: var(--text-dim, #5b6472);
}

.an-legend-item { display: inline-flex; align-items: center; gap: 6px; }

.an-legend-dot {
  width: 10px;
  height: 3px;
  border-radius: 2px;
  display: inline-block;
}

.an-legend-dot.an-line-0 { background: var(--accent); }
.an-legend-dot.an-line-1 { background: #eb6834; }

/* «Требует внимания»: каждая строка ведёт на свою вкладку. */
.an-attention { margin-top: 24px; }

.an-alert {
  display: block;
  width: 100%;
  text-align: left;
  appearance: none;
  font: inherit;
  font-size: 13.5px;
  background: var(--danger-soft);
  border: 1px solid var(--danger-line);
  color: var(--danger);
  border-radius: var(--r-sm);
  padding: 10px 14px;
  margin-bottom: 8px;
  cursor: pointer;
}

.an-alert:hover { background: #ffeceb; }

.an-ok {
  font-size: 13.5px;
  color: var(--ok);
  background: #f1f8f5;
  border: 1px solid #cfe7dc;
  border-radius: var(--r-sm);
  padding: 10px 14px;
}

/* Таблицы. На узком экране прокручиваются вбок сами, страница не едет. */
.an-table-wrap {
  overflow-x: auto;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
}

.an-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13.5px;
  min-width: 560px;
}

.an-table th,
.an-table td {
  padding: 9px 12px;
  text-align: left;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}

.an-table th {
  background: var(--ivory);
  font-weight: 600;
  font-size: 12.5px;
  color: var(--text-dim, #5b6472);
}

.an-table tbody tr:last-child td { border-bottom: 0; }
.an-table tbody tr:hover { background: var(--canvas); }
.an-table .an-num { text-align: right; font-variant-numeric: tabular-nums; }

/* Первая колонка таблиц может быть длинной подписью: ей перенос разрешён. */
.an-table td:first-child { white-space: normal; max-width: 340px; }

/* Демография столбиками. */
.an-bars {
  background: var(--ivory);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: 14px 16px;
}

.an-bar-row {
  display: grid;
  grid-template-columns: minmax(70px, 1fr) 2fr auto;
  align-items: center;
  gap: 10px;
  margin-bottom: 7px;
  font-size: 12.5px;
}

.an-bar-name {
  color: var(--text-dim, #5b6472);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.an-bar-track {
  background: var(--border);
  border-radius: var(--r-pill);
  height: 7px;
  overflow: hidden;
}

.an-bar-fill {
  display: block;
  height: 100%;
  background: var(--accent);
  border-radius: var(--r-pill);
}

.an-bar-value { font-variant-numeric: tabular-nums; color: var(--text); }

.an-filters { margin-bottom: 14px; }

/* ---------- Аналитика: внимание, вкладки по макету ---------- */

/* «Требует внимания»: важность меткой и цветом, подсказка второй строкой.
   Есть срочное – рамка карточки красноватая, иначе жёлтая. */
.an-attn.has-critical { border-color: var(--danger-line); }
.an-attn.has-critical .an-attn-head { color: var(--danger); background: var(--danger-soft); }
.an-attn .an-attn-row { align-items: flex-start; }
.an-attn-text { flex: 1; min-width: 0; }
.an-attn-text small { display: block; font-size: 12px; color: var(--text-2); margin-top: 2px; }
.an-sev {
  flex: none;
  min-width: 84px;
  font-size: 12px;
  font-weight: 600;
  padding-top: 1px;
}
.an-sev::before { content: '● '; }
.an-sev.is-critical { color: var(--danger); }
.an-sev.is-warning { color: #8a5300; }

/* Записи за строкой «внимания» в боковой панели. */
.an-record {
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: 10px 12px;
  margin: 6px 4px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.an-record-head { display: flex; justify-content: space-between; gap: 8px; font-size: 13.5px; }
.an-record-head span { color: var(--text-3); font-size: 12px; white-space: nowrap; }
.an-record-detail { font-size: 12px; color: var(--text-3); }
.an-record-reason { font-size: 13px; color: var(--text); }
.an-record-foot { display: flex; justify-content: space-between; align-items: center; gap: 8px; flex-wrap: wrap; }
.an-record-action { font-size: 12px; color: var(--text-2); }

/* Ряды плиток на вкладках без главной цифры. */
.an-kpis.an-kpis-5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
.an-kpis.an-kpis-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.an-kpi-value small { font-size: 13px; font-weight: 500; color: var(--text-2); letter-spacing: 0; }
.an-kinds { margin-top: 10px; }

/* Источник как фильтр: выбранный подсвечен, остальные приглушены. */
.an-src-row.is-selected { background: var(--accent-soft); }
.an-src-row.is-dim { opacity: .45; }
.an-src-row.is-static { cursor: default; }
.an-src-row.is-static:hover { background: none; }
.an-src-row.is-bad .an-src-track i { background: #d03b3b; }
.an-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  height: 30px;
  padding: 0 4px 0 12px;
  border-radius: var(--r-pill);
  background: var(--accent-soft);
  border: 1px solid var(--accent-line);
  color: var(--accent-dark);
  font-size: 12.5px;
  font-weight: 500;
  max-width: 280px;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.an-chip button {
  appearance: none;
  border: 0;
  background: none;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  cursor: pointer;
  color: inherit;
  font-size: 15px;
  flex: none;
}
.an-chip button:hover { background: var(--surface); }

/* Чип фильтра источника – над сводкой, не в шапке: шапку он перестраивал
   в два ряда. Текст обрезается многоточием, крестик всегда виден. */
.an-source-row:empty { display: none; }
.an-source-row { margin-bottom: 12px; }
.an-chip-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.an-chip { max-width: 100%; }

/* Пока идёт загрузка, прежние цифры видны приглушёнными: без скачка. */
#an-body.is-busy .an-panel { opacity: .5; transition: opacity .15s; }
.an-bar.is-today { opacity: .45; }
.an-freshness.is-off { display: none; }
.an-fstep-conv { line-height: 1.35; }
.an-person-meta { white-space: normal; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.an-empty-inline { display: flex; flex-direction: column; align-items: center; text-align: center; }
.an-empty-inline span { max-width: 520px; }
.an-tip-float { white-space: pre-line; }
#an-rules-table td:first-child, #an-camp-table td:first-child { min-width: 200px; }

/* Полоса доставки рассылки: статусные цвета с зазором, расшифровка в подсказке. */
.an-stack {
  display: flex;
  gap: 2px;
  width: 140px;
  height: 8px;
  border-radius: 4px;
  overflow: hidden;
  background: var(--surface);
}
.an-stack i { display: block; height: 100%; }
.an-stack .is-good { background: #0ca30c; }
.an-stack .is-bad { background: #d03b3b; }
.an-stack .is-unknown { background: #fab219; }
.an-stack .is-pending { background: #dcdad4; }
.an-warn-num { color: #8a5300; font-weight: 600; }
.an-bad-num { color: var(--danger); font-weight: 600; }
.an-empty-inline { padding: 18px; gap: 8px; }

/* Полнота данных. */
/* В «Полноте данных» ограничения длинные: ячейкам разрешён перенос. */
#an-data-table td { white-space: normal; min-width: 110px; }
.an-dot-ok, .an-dot-no { font-size: 12px; font-weight: 600; white-space: nowrap; }
.an-dot-ok { color: var(--ok); }
.an-dot-no { color: var(--text-3); }
.an-dot-ok::before, .an-dot-no::before { content: '● '; }
.an-sync-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  padding: 9px 4px;
  border-bottom: 1px solid var(--border);
}
.an-sync-row:last-child { border-bottom: 0; }
.an-sync-row small { display: block; font-size: 12px; color: var(--text-3); }

/* Всплывающая подсказка раздела. */
.an-tip-float {
  position: fixed;
  z-index: 60;
  max-width: 280px;
  pointer-events: none;
  background: var(--text);
  color: #fff;
  border-radius: 10px;
  padding: 8px 11px;
  font-size: 12px;
  line-height: 1.45;
  box-shadow: 0 8px 24px rgba(0, 0, 0, .18);
}

@media (max-width: 1100px) {
  .an-kpis.an-kpis-5, .an-kpis.an-kpis-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 700px) {
  /* Строка внимания: метка и «Показать» сверху, текст на всю ширину. */
  .an-sev { min-width: 0; order: 1; }
  .an-attn .an-attn-row { flex-wrap: wrap; row-gap: 4px; }
  .an-attn-go { order: 2; margin-left: auto; }
  .an-attn-text { order: 3; flex-basis: 100%; }
  /* Вкладки раздела – одной прокручиваемой полосой, а не тремя рядами. */
  .an-tabs { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; }
  .an-tabs::-webkit-scrollbar { display: none; }
  .an-tab { white-space: nowrap; flex: none; }
  .an-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ---------- Сводка аналитики ----------
   Спека – docs/superpowers/specs/2026-09-23-аналитика-сводка.md. Каждое число
   кликабельно и открывает людей за ним, поэтому плитки, шаги и источники –
   кнопки с видимым наведением. */

/* Плашки «нет права» и «данные собираются». Классы стояли в разметке с
   первой ревизии раздела, а стилей у них не было: текст висел голым. */
.notice {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  background: var(--ivory);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: 12px 16px;
  margin-bottom: 16px;
}
.notice-warn { background: #fff7e6; border-color: #f6dfae; }
.notice-text { margin: 0; font-size: 13.5px; color: var(--text); }

.an-block {
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: var(--surface);
  padding: 16px 18px;
  margin-top: 16px;
  min-width: 0;
}
.an-block-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 12px;
}
.an-block-head .an-h3 { margin: 0; }
.an-block .an-legend { margin-top: 0; }
.an-hint { font-size: 12.5px; color: var(--text-3); }

.an-sum-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr);
  gap: 16px;
}
.an-sum-grid .an-block { margin-top: 16px; }

/* «Требует внимания»: одна жёлтая карточка со строками, а не россыпь
   красных плашек – красный остаётся для настоящих отказов в строке. */
.an-attention { margin: 0 0 16px; }
.an-attn {
  border: 1px solid #f6dfae;
  background: #fff7e6;
  border-radius: var(--r-lg);
  overflow: hidden;
}
.an-attn-head {
  padding: 10px 16px;
  font-size: 13px;
  font-weight: 600;
  color: #8a5300;
}
.an-attn-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  appearance: none;
  border: 0;
  border-top: 1px solid #f6dfae;
  background: rgba(255, 255, 255, .6);
  font: inherit;
  font-size: 13.5px;
  color: var(--text);
  text-align: left;
  padding: 10px 16px;
  cursor: pointer;
}
.an-attn-row:hover { background: #fff; }
.an-attn-go { font-size: 12.5px; color: var(--accent-dark); font-weight: 500; white-space: nowrap; }

/* Плитки: первая – главная цифра с кобальтовой кромкой и спарклайном. */
.an-kpis {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) repeat(4, minmax(0, 1fr));
  gap: 12px;
}
.an-kpi {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
  appearance: none;
  font: inherit;
  color: inherit;
  text-align: left;
  background: var(--ivory);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: 13px 15px 12px;
}
.an-kpi.is-link { cursor: pointer; transition: border-color .12s, box-shadow .12s, background .12s; }
.an-kpi.is-link:hover { background: var(--surface); border-color: var(--accent-line); box-shadow: var(--shadow-sm); }
.an-kpi-title { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; font-size: 12.5px; color: var(--text-2); }
.an-kpi-value { font-size: 24px; font-weight: 600; letter-spacing: -.015em; line-height: 1.2; overflow-wrap: anywhere; }
.an-kpi-meta { font-size: 12px; display: flex; flex-wrap: wrap; gap: 4px; align-items: baseline; }
.an-kpi-hero { background: var(--surface); border-color: var(--accent-line); box-shadow: inset 3px 0 0 var(--accent); }
.an-kpi-hero .an-kpi-value { font-size: 38px; letter-spacing: -.025em; }
.an-info {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 15px;
  height: 15px;
  border-radius: 50%;
  border: 1px solid var(--faint);
  color: var(--text-3);
  font-size: 9.5px;
  font-weight: 700;
  cursor: help;
  flex: none;
}
.an-small-n {
  font-size: 12px;
  color: #8a5300;
  background: #fff7e6;
  border: 1px solid #f6dfae;
  border-radius: var(--r-pill);
  padding: 0 8px;
}
.an-spark { display: block; width: 100%; height: 34px; margin-top: 4px; }
.an-spark-fill { fill: var(--accent); fill-opacity: .09; }
.an-spark-line { fill: none; stroke: var(--accent); stroke-width: 1.6; vector-effect: non-scaling-stroke; }
.an-spark-dot { fill: var(--accent); }

/* Воронка: подпись, полоса, доля от предыдущего шага. */
.an-funnel { display: flex; flex-direction: column; gap: 4px; }
.an-fstep {
  display: grid;
  grid-template-columns: 170px minmax(0, 1fr) 96px;
  gap: 12px;
  align-items: center;
  width: 100%;
  appearance: none;
  border: 0;
  background: none;
  font: inherit;
  color: inherit;
  text-align: left;
  padding: 6px 8px;
  border-radius: var(--r-sm);
}
.an-fstep.is-link { cursor: pointer; }
.an-fstep.is-link:hover { background: var(--accent-soft); }
.an-fstep-label { font-size: 13px; }
.an-fstep-label small { display: block; font-size: 11.5px; color: var(--text-3); }
.an-fbar { position: relative; height: 26px; background: var(--canvas); border-radius: 4px; overflow: hidden; }
.an-fbar i { position: absolute; inset: 0 auto 0 0; background: var(--accent); border-radius: 0 4px 4px 0; }
.an-fbar b {
  position: absolute;
  left: 10px;
  top: 50%;
  transform: translateY(-50%);
  font-size: 12.5px;
  font-weight: 600;
  color: #fff;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.an-fbar b.is-out { color: var(--text); }
.an-fstep-conv { text-align: right; font-size: 12px; color: var(--text-2); font-variant-numeric: tabular-nums; }
.an-fstep-conv b { color: var(--text); font-weight: 600; }
.an-fdrop {
  align-self: flex-start;
  margin: -2px 0 0 186px;
  appearance: none;
  border: 0;
  background: none;
  font: inherit;
  font-size: 12px;
  color: var(--danger);
  padding: 2px 8px;
  border-radius: 6px;
  cursor: pointer;
  text-align: left;
}
.an-fdrop:hover { background: var(--danger-soft); }
.an-fdrop.is-quiet { color: var(--text-3); cursor: default; }
.an-fdrop.is-quiet:hover { background: none; }

/* Источники: полоса одного цвета, свои входящие светлее. */
.an-src { display: flex; flex-direction: column; gap: 2px; }
.an-src-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas: "name val" "track val";
  column-gap: 12px;
  row-gap: 6px;
  align-items: center;
  width: 100%;
  appearance: none;
  border: 0;
  background: none;
  font: inherit;
  color: inherit;
  text-align: left;
  padding: 7px 8px;
  border-radius: var(--r-sm);
  cursor: pointer;
}
.an-src-row:hover { background: var(--canvas); }
.an-src-name { grid-area: name; display: flex; align-items: center; gap: 6px; min-width: 0; font-size: 13px; }
.an-src-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.an-src-val { grid-area: val; text-align: right; font-weight: 600; font-size: 13px; font-variant-numeric: tabular-nums; }
.an-src-val small { display: block; font-weight: 400; font-size: 11.5px; color: var(--text-3); }
.an-src-track { grid-area: track; height: 8px; background: var(--canvas); border-radius: 4px; overflow: hidden; }
.an-src-track i { display: block; height: 100%; background: var(--accent); border-radius: 0 4px 4px 0; }
.an-src-row.is-inbound .an-src-track i { background: #8fb5ee; }

.an-pill {
  display: inline-flex;
  align-items: center;
  height: 18px;
  padding: 0 7px;
  border-radius: var(--r-pill);
  font-size: 10.5px;
  font-weight: 600;
  flex: none;
  vertical-align: 1px;
}
.an-pill-ig { background: #fdf0f6; color: #a3245f; border: 1px solid #f6d3e3; }
.an-pill-tg { background: #eaf5fd; color: #1a6597; border: 1px solid #cfe6f7; }

/* График сводки: столбики и линия прошлого периода на одной оси. */
.an-chart-bare { position: relative; border: 0; padding: 0; }
/* Подписи оси сводки темнее общих: на белом #ccc в 10 px почти не читался. */
.an-chart-bare .an-axis { fill: var(--text-3); font-size: 11px; }
.an-bar { fill: var(--accent); transition: opacity .1s; }
.an-bar.is-dim { opacity: .5; }
.an-prev-line { fill: none; stroke: #c4c2bb; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.an-base-line { stroke: #d9d7d0; stroke-width: 1; }
.an-cross { stroke: var(--text); stroke-opacity: .25; }
.an-hit { cursor: pointer; }
.an-legend-box { width: 10px; height: 10px; border-radius: 2px; background: var(--accent); display: inline-block; }
.an-legend-dot.an-prev { background: #c4c2bb; }
.an-tip {
  position: absolute;
  pointer-events: none;
  background: var(--text);
  color: #fff;
  border-radius: 10px;
  padding: 7px 10px;
  font-size: 12px;
  line-height: 1.45;
  white-space: nowrap;
  box-shadow: 0 8px 24px rgba(0, 0, 0, .18);
  z-index: 2;
}
.an-tip b { font-size: 13.5px; font-weight: 600; display: block; }

/* Боковая панель людей: немодальная, поверх раздела справа. */
.an-drawer {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  width: 440px;
  max-width: 100%;
  background: var(--surface);
  border-left: 1px solid var(--border);
  box-shadow: var(--shadow-lg);
  display: flex;
  flex-direction: column;
  z-index: 40;
}
.an-drawer-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 12px;
  padding: 18px 20px 12px;
  border-bottom: 1px solid var(--border);
}
.an-drawer-title { margin: 0; font-size: 16px; font-weight: 600; }
.an-drawer-sub { margin: 2px 0 0; font-size: 12.5px; color: var(--text-2); }
.an-drawer-x { width: 34px; padding: 0; font-size: 18px; flex: none; }
.an-drawer-list { flex: 1; overflow-y: auto; padding: 6px 8px calc(12px + env(safe-area-inset-bottom, 0px)); }
.an-person {
  display: grid;
  grid-template-columns: 34px minmax(0, 1fr) auto;
  gap: 10px;
  align-items: center;
  padding: 9px 10px;
  border-radius: var(--r-md);
}
.an-person:hover { background: var(--canvas); }
.an-ava {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--accent-soft);
  color: var(--accent-dark);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 600;
  font-size: 13px;
}
.an-person-main { min-width: 0; display: flex; flex-direction: column; }
.an-person-name { font-size: 13.5px; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.an-person-meta { font-size: 12px; color: var(--text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

@media (max-width: 1100px) {
  .an-kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .an-kpi-hero { grid-column: 1 / -1; }
  .an-sum-grid { grid-template-columns: minmax(0, 1fr); gap: 0; }
}

@media (max-width: 700px) {
  .an-block { padding: 14px; }
  .an-kpi-hero .an-kpi-value { font-size: 32px; }
  .an-fstep { grid-template-columns: minmax(0, 1fr) 84px; row-gap: 4px; }
  .an-fstep-label { grid-column: 1 / -1; }
  .an-fdrop { margin-left: 0; }
  .an-drawer { width: 100%; }
}


@media (max-width: 700px) {
  /* Период и «Обновить» уезжают под заголовок, а не жмут его в угол. */
  .an-head-actions { width: 100%; }
  .an-tiles { grid-template-columns: repeat(auto-fit, minmax(132px, 1fr)); }
  .an-tile-value { font-size: 21px; }
  .an-bar-row { grid-template-columns: minmax(60px, 1fr) 1.4fr auto; }
}

/* ===============================================================   Раздел «Контент фабрика»

   Ролики показываются карточками, а не таблицей: в строке два десятка
   чисел (просмотры, лайки, комментарии, три прироста, две нормы, разрыв),
   и таблица такой ширины на 375 px нечитаема – её пришлось бы скроллить
   вбок на каждой строке.
   ====================================================================== */

.fx-pane { min-height: 120px; }

.fx-filter {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  align-items: center;
  margin-bottom: 14px;
}

.fx-filter .input { flex: 1 1 220px; min-width: 0; }

/* Ленты конкурентов – той же сеткой, что лента своего аккаунта: плитка 9:16
   с просмотрами в углу, под ней дата и «В работу». Остальное в окне ролика. */
.fx-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
  gap: 16px 8px;
  align-items: start;
}

.fx-card { min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.fx-tile { width: 100%; }
.fx-tile .fx-frame-empty { position: absolute; inset: 0; display: grid; place-items: center; }
.fx-tile .fx-frame-empty[hidden] { display: none; }
.fx-tile-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 0 2px;
}
.fx-tile-date { font-size: 12.5px; color: var(--text-3); font-variant-numeric: tabular-nums; white-space: nowrap; }

.fx-stat-delta { color: var(--accent-dark); font-size: 12px; font-variant-numeric: tabular-nums; }

.fx-chips { display: flex; gap: 4px; flex-wrap: wrap; }

.fx-chip {
  background: var(--accent-soft);
  color: var(--accent-dark);
  border-radius: var(--r-pill, 999px);
  padding: 2px 9px;
  font-size: 12px;
  white-space: nowrap;
}

/* Оценка просмотров – не замер, и выглядеть она должна тише: путать их
   нельзя, коэффициент пересчёта гуляет от 32 до 87. */
.fx-chip-soft { background: var(--surface-2); color: var(--text-3); }

.fx-inwork {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 13px;
  cursor: pointer;
  /* Цель клика не меньше 24 px по высоте: правило интерфейса. */
  min-height: 24px;
}

/* Доска идей */
.fx-board { display: flex; flex-direction: column; gap: 14px; }

.fx-idea {
  border: 1px solid var(--border);
  border-radius: var(--r-md, 12px);
  background: var(--surface);
  padding: 14px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.fx-idea-head { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.fx-idea-title { flex: 1 1 220px; min-width: 0; font-weight: 600; }
.fx-idea-status { flex: 0 0 auto; width: auto; }

.fx-idea-ref { display: flex; gap: 12px; align-items: flex-start; }
.fx-idea-frame {
  width: 72px;
  aspect-ratio: 9 / 16;
  object-fit: cover;
  border-radius: var(--r-sm, 8px);
  background: var(--surface-2);
  flex: 0 0 auto;
}
.fx-idea-refbody { min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.fx-idea-stats { margin: 0; color: var(--text-2); font-size: 13px; font-variant-numeric: tabular-nums; }
.fx-idea-noref { margin: 0; color: var(--text-3); font-size: 13px; }

.fx-idea-fields {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 10px;
}

.fx-idea-field { display: flex; flex-direction: column; gap: 4px; }
.fx-idea-input { width: 100%; }
.fx-material-control { position: relative; }
.fx-material-control .input { padding-right: 44px; }
.fx-material-picker { position: absolute; right: 2px; top: 2px; min-height: 36px; width: 36px; padding: 0; border-radius: var(--r-md); background-image: var(--select-chevron); background-repeat: no-repeat; background-position: center; }
.fx-material-picker:hover { background-color: var(--canvas); }
.fx-keywords { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; height: auto; min-height: 40px; padding: 5px 8px; }
.fx-keywords input { flex: 1; width: 95px; min-width: 95px; max-width: 100%; height: 28px; padding: 2px 4px; border: 0; background: transparent; color: var(--text); font: inherit; }
.fx-keywords input:focus { outline: none; box-shadow: none; }
.fx-material-input:focus, .input.fx-keywords:has(input:focus) { border-color: var(--accent); box-shadow: none; }
html[data-keyboard-focus="true"] :is(.fx-material-input, .fx-keywords input):focus-visible { outline: none !important; }
.fx-keyword-chip { display: inline-flex; align-items: center; gap: 6px; max-width: 100%; padding: 2px 5px 2px 8px; border-radius: 8px; background: var(--accent-soft); color: var(--accent-dark); font-size: 12px; }
.fx-keyword-chip span { min-width: 0; overflow-wrap: anywhere; }
.fx-keyword-chip button { flex-shrink: 0; width: 24px; height: 24px; padding: 0; border: 0; background: transparent; color: inherit; font: inherit; font-size: 18px; }
.fx-material-menu { position: fixed; z-index: 450; width: min(360px, calc(100vw - 16px)); max-height: var(--menu-available-height, 320px); overflow-y: auto; }
.fx-material-menu .kb-menu-item { white-space: normal; overflow-wrap: anywhere; }
.fx-material-menu .field-note { padding: 8px 10px; }
.fx-lead-magnet-form { display: flex; flex-direction: column; gap: 14px; }
.fx-lead-magnet-form .field, .fx-lead-magnet-form .field-note { margin: 0; }
.fx-lead-magnet-form > [data-preview-toggle] { align-self: flex-start; }
.fx-lead-magnet-form textarea { min-height: 108px; resize: vertical; }
.fx-material-preview { padding: 14px; background: var(--canvas); border-radius: var(--r-md); }
.fx-material-preview [data-preview-text] { white-space: pre-wrap; overflow-wrap: anywhere; background: var(--surface); padding: 12px; border-radius: var(--r-md); }
.fx-material-preview [data-preview-button] { text-align: center; overflow-wrap: anywhere; color: var(--accent); background: var(--surface); padding: 10px; margin-top: 6px; border-radius: var(--r-md); }
.fx-idea-field .is-error, .fx-lead-magnet-form .is-error { color: var(--danger); }
@media (max-width: 760px) { .fx-keywords input { font-size: 16px; } }
@media (pointer: coarse) { .fx-keyword-chip button { width: 44px; height: 44px; } .fx-material-picker { width: 44px; } }

/* Пул конкурентов: единственная таблица раздела – у неё ровные короткие
   колонки, карточки здесь только раздули бы список на 892 строки. */
.fx-table-wrap { overflow-x: auto; }
.fx-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.fx-table th, .fx-table td {
  text-align: left;
  padding: 8px 10px;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
.fx-table th { color: var(--text-2); font-weight: 500; }
.fx-table td.fx-num { font-variant-numeric: tabular-nums; text-align: right; }

.fx-settings { display: flex; flex-direction: column; gap: 10px; max-width: 640px; }
.fx-h3 { margin: 10px 0 0; font-size: 15px; }

.fx-thresholds {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 12px;
  align-items: end;
}

.fx-threshold { display: flex; flex-direction: column; gap: 4px; }
.fx-secret { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

@media (max-width: 700px) {
  .fx-idea-fields { grid-template-columns: 1fr; }
  .fx-thresholds { grid-template-columns: 1fr; }
  .fx-idea-head { flex-direction: column; align-items: stretch; }
  .fx-idea-status { width: 100%; }
}

/* Ключи раздела: карточка на провайдера, поле ввода всегда пустое (сам ключ
   наружу не приходит никогда, приходит только маска). */
.fx-secret-card {
  border: 1px solid var(--border);
  border-radius: var(--r-md, 12px);
  padding: 12px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.fx-secret-card .fx-filter { margin-bottom: 0; }
.fx-secret-error { color: var(--danger, #c0392b); }

/* Настройки раздела: компактно. Объяснения живут под раскрытием – их
   читают один раз при настройке, а заходят сюда поправить число. */
.fx-settings-row {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 6px;
}

.fx-settings-row .fx-h3 { margin: 0; }

.fx-help { font-size: 13px; color: var(--text-2); }
.fx-help summary { cursor: pointer; }
.fx-help p { margin: 6px 0 0; line-height: 1.5; max-width: 60ch; }

.fx-collector { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.fx-collector .fx-inwork { margin-right: 4px; }

/* Транскрипция абзацами, как в исходной таблице: сплошную простыню на две
   тысячи знаков читать невозможно. */
.fx-transcript-text { margin-top: 6px; }
.fx-transcript-text p {
  margin: 0 0 10px;
  line-height: 1.6;
  color: var(--text);
  max-width: 68ch;
}
.fx-transcript-text p:last-child { margin-bottom: 0; }
.fx-transcript-editor { position: relative; min-width: 0; }
.fx-transcript-editor .fx-transcript-text {
  margin-top: 6px; min-height: 88px; padding: 8px 40px 8px 8px;
  border: 1px solid transparent; border-radius: var(--r-sm);
  white-space: pre-wrap; overflow-wrap: anywhere; cursor: text; line-height: 1.7;
}
.fx-transcript-editor .fx-transcript-text:hover { border-color: var(--border); }
.fx-transcript-editor .fx-transcript-text:focus { outline: none; border-color: var(--accent); }
.fx-transcript-editor .fx-transcript-text[data-empty="true"]::before { content: attr(data-placeholder); color: var(--text-3); pointer-events: none; }
.fx-transcript-toolbar { position: absolute; top: 11px; right: 5px; z-index: 1; }
.fx-transcript-bold.btn { width: 28px; height: 28px; min-height: 28px; padding: 0; font-size: 13px; font-weight: 700; background: var(--surface); }
.fx-transcript-bold[aria-pressed="true"] { color: var(--accent); background: var(--accent-soft); }
.fx-transcript-actions { display: flex; justify-content: flex-end; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.fx-transcript-actions .btn { height: 32px; min-height: 32px; padding: 0 10px; font-size: 12px; }
.fx-transcript-status { margin: 8px 0 0; font-size: 12px; color: var(--danger); line-height: 1.5; overflow-wrap: anywhere; }
.fx-transcript-editor.is-saving .fx-transcript-text { cursor: progress; color: var(--text-2); }
@media (max-width: 720px) {
  .fx-transcript-editor .fx-transcript-text { font-size: 16px; }
  .fx-transcript-actions .btn { min-height: 40px; }
}

/* «Показать ещё» под сеткой карточек. */
.fx-more { display: flex; justify-content: center; margin-top: 14px; }
.message-anchor{display:contents}.message-anchor.is-anchor>.msg .bubble{outline:3px solid rgba(2,75,177,.28);outline-offset:3px}

/* ---------- Видео-посты YouTube и TikTok (спека 2026-09-18-youtube-tiktok § 6) ---------- */

.pub-channel-tabs { margin-bottom: 14px; }

.vp-list { display: flex; flex-direction: column; gap: 8px; }
.vp-row {
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr) auto;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  border: 1px solid var(--border-2);
  border-radius: 10px;
  background: var(--surface);
  cursor: pointer;
  text-align: left;
}
.vp-row:hover { border-color: var(--faint); background: var(--canvas); }
.vp-row:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.vp-row-thumb {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; border-radius: 8px;
  background: var(--ivory); color: var(--text-2); font-size: 16px;
}
.vp-row-main { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.vp-row-title { font-weight: 600; font-size: 14px; line-height: 1.35; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vp-row-meta { font-size: 12.5px; color: var(--text-2); line-height: 1.4; overflow: hidden; text-overflow: ellipsis; }
.vp-row-error { color: var(--danger); }
.vp-row-right { display: inline-flex; align-items: center; gap: 10px; white-space: nowrap; }
.vp-row-link { font-size: 13px; }

.vp-form .field + .field { margin-top: 16px; }
.vp-drop {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 14px; border: 1px dashed var(--faint); border-radius: 10px; background: var(--canvas);
}
.vp-drop.is-over { border-color: var(--accent); background: var(--accent-soft); }
.vp-drop-req { font-size: 12.5px; color: var(--text-2); line-height: 1.4; }
.vp-file-info { margin: 8px 0 0; font-size: 13px; color: var(--text); }
.vp-check { display: flex; align-items: center; gap: 8px; font-size: 14px; line-height: 1.4; margin-top: 6px; cursor: pointer; }
.vp-check input { width: 16px; height: 16px; margin: 0; }

.vp-detail-meta { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: 6px 16px; margin: 14px 0 0; font-size: 13.5px; }
.vp-meta-row { display: contents; }
.vp-detail-meta dt { color: var(--text-2); }
.vp-detail-meta dd { margin: 0; white-space: pre-wrap; word-break: break-word; }

@media (max-width: 640px) {
  .vp-row { grid-template-columns: 36px minmax(0, 1fr); }
  .vp-row-thumb { width: 36px; height: 36px; }
  .vp-row-right { grid-column: 2; justify-content: flex-start; }
  .vp-detail-meta { grid-template-columns: 1fr; gap: 2px 0; }
  .vp-detail-meta dd { margin-bottom: 8px; }
}

.vp-section-title { margin: 18px 0 8px; font-size: 12.5px; font-weight: 600; letter-spacing: .02em; text-transform: uppercase; color: var(--text-2); }
.vp-feed-wrap { margin-top: 6px; }
.vp-feed { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 12px; margin-top: 8px; }
.vp-feed-tile { display: flex; flex-direction: column; gap: 6px; text-decoration: none; color: inherit; min-width: 0; }
.vp-feed-tile:hover .vp-feed-title { color: var(--accent); }
.vp-feed-thumb { position: relative; display: block; aspect-ratio: 9 / 16; border-radius: 10px; overflow: hidden; background: var(--ivory); }
.vp-feed-cover { display: block; width: 100%; height: 100%; object-fit: cover; }
.vp-feed-cover-empty { display: flex; align-items: center; justify-content: center; color: var(--text-3); font-size: 22px; }
.vp-feed-privacy { position: absolute; left: 6px; top: 6px; }
.vp-feed-title { font-size: 13px; font-weight: 600; line-height: 1.35; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.vp-feed-meta { font-size: 12px; color: var(--text-2); }
#btn-vp-feed-more { margin-top: 12px; }
@media (max-width: 640px) { .vp-feed { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; } }

/* Фабрика: список для обзора, один редактор для работы. */
.fx-overview { margin-bottom: 20px; border: 1px solid var(--border); border-radius: var(--r-md, 12px); background: var(--surface-2); }
.fx-overview > .field-note { margin: 0; padding: 12px; overflow-wrap: anywhere; }
#fx-fresh { flex-wrap: wrap; }
#fx-fresh-text { white-space: normal; }
.fx-overview-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); }
.fx-overview-cell { min-width: 0; padding: 14px 16px; display: flex; flex-direction: column; gap: 6px; }
.fx-overview-cell + .fx-overview-cell { border-left: 1px solid var(--border); }
.fx-overview-cell > span { color: var(--text-2); font-size: 12px; }
.fx-overview-cell > strong { font-size: 17px; font-weight: 650; line-height: 1.3; overflow-wrap: anywhere; }
.fx-overview-cell > small { color: var(--text-2); font-size: 11px; line-height: 1.45; }
.fx-spend-details { border-top: 1px solid var(--border); font-size: 13px; }
.fx-spend-details > summary { padding: 10px 16px; cursor: pointer; color: var(--text-2); }
.fx-spend-body { padding: 4px 16px 16px; display: grid; grid-template-columns: 1fr 1fr; gap: 24px; }
.fx-spend-body h3 { margin: 8px 0; font-size: 14px; }
.fx-spend-body p { line-height: 1.5; margin: 8px 0; }
.fx-spend-table { width: 100%; border-collapse: collapse; font-size: 12px; }
.fx-spend-table td, .fx-spend-table th { padding: 6px 0; border-bottom: 1px solid var(--border); text-align: right; font-variant-numeric: tabular-nums; }
.fx-spend-table td:first-child, .fx-spend-table th:first-child { text-align: left; }
.fx-spend-table td + td, .fx-spend-table th + th { padding-left: 12px; }
.fx-reel-toolbar, .fx-board-toolbar { display: flex; gap: 10px; align-items: center; margin-bottom: 12px; flex-wrap: wrap; }
.fx-search-label { display: flex; flex-direction: column; min-width: 0; flex: 1 1 200px; gap: 5px; }
.fx-status-filter { flex: 0 1 185px; min-width: 0; }
.fx-status-filter .input { width: 100%; }
.fx-add-reference { font-size: 12px; color: var(--text-2); margin: 0 0 16px; }
.fx-add-reference > summary { cursor: pointer; padding: 4px 0; width: fit-content; }
.fx-add-reference .fx-filter { margin-top: 10px; align-items: end; }
.fx-add-reference .fx-filter .input { flex: none; min-height: 40px; height: 40px; width: 100%; }
.fx-workspace { display: grid; grid-template-columns: 290px minmax(0, 1fr); border-top: 1px solid var(--border); min-height: 470px; }
.fx-ideas-sidebar { min-width: 0; border-right: 1px solid var(--border); padding: 14px 14px 0 0; }
.fx-ideas-sidebar > .field-note { margin: 0 0 12px; }
.fx-board { display: flex; flex-direction: column; gap: 5px; max-height: 730px; overflow-y: auto; padding: 2px; }
.fx-idea-row { display: flex; gap: 10px; width: 100%; padding: 10px; min-height: 92px; border: 1px solid transparent; border-radius: 9px; text-align: left; background: transparent; color: var(--text); cursor: pointer; font: inherit; }
.fx-idea-row:hover { background: var(--surface-2); }
.fx-idea-row.is-selected { background: var(--accent-soft); border-color: var(--accent); }
.fx-idea-row:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.fx-row-frame { width: 42px; height: 62px; flex: 0 0 42px; display: flex; align-items: center; justify-content: center; background: var(--surface-2); color: var(--text-3); border-radius: 5px; overflow: hidden; }
.fx-row-frame img { width: 100%; height: 100%; object-fit: cover; }
.fx-row-main { min-width: 0; display: flex; flex-direction: column; align-items: flex-start; gap: 4px; }
.fx-row-main strong { font-size: 13px; line-height: 1.35; font-weight: 600; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; overflow-wrap: anywhere; }
.fx-row-meta, .fx-row-platforms { color: var(--text-2); font-size: 11px; overflow-wrap: anywhere; }
.fx-row-status { font-size: 10px; line-height: 1.4; padding: 2px 6px; background: var(--surface); border: 1px solid var(--border); border-radius: 4px; color: var(--text-2); }
.fx-row-status[data-status="edited"], .fx-row-status[data-status="published"] { color: var(--accent-dark); border-color: var(--accent-soft); }
.fx-editor-column { min-width: 0; padding: 16px 0 0 22px; position: relative; }
.fx-editor { min-width: 0; }
.fx-editor-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 16px; }
.fx-editor-kicker { font-size: 11px; letter-spacing: .06em; text-transform: uppercase; color: var(--text-3); }
.fx-editor-back { display: none; }
.fx-editor-basics { display: grid; grid-template-columns: minmax(0, 1fr) 140px 32px; align-items: center; gap: 10px; }
.fx-editor .fx-idea-title { flex: none; width: 100%; }
.fx-editor .fx-idea-field { min-width: 0; }
.fx-editor .input { min-width: 0; max-width: 100%; }
.fx-editor textarea { height: auto; min-height: 96px; resize: vertical; line-height: 1.55; }
.fx-editor-section { margin-top: 22px; }
.fx-editor-section > h3 { margin: 0 0 12px; font-size: 13px; font-weight: 650; }
.fx-editor-reference { display: flex; gap: 14px; background: var(--surface-2); border-radius: 8px; padding: 12px; }
.fx-editor-reference .fx-idea-frame { width: 58px; max-height: 103px; }
.fx-editor-reference .fx-idea-refbody { flex: 1; min-width: 0; }
.fx-editor-reference .fx-idea-stats { font-size: 12px; }
.fx-platform-fields { display: flex; flex-direction: column; gap: 14px; }
.fx-platform-group { border: 1px solid var(--border); border-radius: 8px; margin-top: 8px; }
.fx-platform-group > summary { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 12px; cursor: pointer; font-size: 13px; font-weight: 600; }
.fx-platform-group > summary::after { content: '+'; color: var(--text-3); font-size: 16px; }
.fx-platform-group[open] > summary::after { content: '−'; }
.fx-platform-count { margin-left: auto; font-size: 11px; color: var(--text-3); font-weight: 400; }
.fx-platform-group > .fx-platform-fields { padding: 4px 12px 14px; }
.fx-editor-savebar { position: fixed; left: calc(var(--nav-w) + 20px); right: 20px; bottom: 16px; margin: 0 auto; max-width: 900px; padding: 12px 16px; display: flex; flex-direction: row; align-items: center; justify-content: space-between; gap: 8px; border: 1px solid var(--border); border-radius: 12px; background: var(--surface); box-shadow: var(--shadow-lg); z-index: 55; }
.fx-editor-savebar[hidden] { display: none; }
.fx-editor-column:has(.fx-editor-savebar:not([hidden])) { padding-bottom: 150px; }
.fx-reference-frame { width: 108px; flex: 0 0 108px; aspect-ratio: 9 / 16; display: flex; align-items: center; justify-content: center; background: var(--surface); border-radius: 6px; overflow: hidden; }
.fx-reference-frame img { width: 100%; height: 100%; object-fit: contain; }
.fx-reference-frame[href] { color: inherit; text-decoration: none; }
.fx-reference-frame[href]:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.fx-frame-empty { padding: 8px; text-align: center; font-size: 11px; color: var(--text-3); }
.fx-reference-date { font-size: 12px; margin: 8px 0; }
.fx-summary-row { display: flex; align-items: flex-start; gap: 8px; margin-bottom: 12px; }
.fx-summary-row .fx-overview { flex: 1; min-width: 0; margin-bottom: 0; }
.fx-summary-row > .btn { flex-shrink: 0; min-height: 36px; }
#btn-fx-refresh.is-loading::before { content: ''; display: inline-block; width: 12px; height: 12px; margin-right: 6px; border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%; animation: fx-refresh-spin .7s linear infinite; }
@keyframes fx-refresh-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { #btn-fx-refresh.is-loading::before { animation: none; } }
/* Референс идеи ещё разбирается сборщиком: мягкая пульсация вместо «Кадр недоступен». */
@keyframes fx-ref-loading { 50% { opacity: .45; } }
.fx-frame-empty.is-loading { color: var(--text-2); animation: fx-ref-loading 1.6s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) { .fx-frame-empty.is-loading { animation: none; } }
.fx-editor-savebar > span { font-size: 12px; color: var(--text-2); }
.fx-editor-savebar > span.is-error { color: var(--danger, #b42318); }
.fx-save-actions { display: flex; justify-content: flex-end; gap: 8px; flex-wrap: wrap; }
.fx-list-empty, .fx-editor-empty { padding: 30px 12px; }
.vp-prepared-actions { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; margin: 16px 0; }
@media (max-width: 1050px) {
  .fx-workspace { grid-template-columns: 245px minmax(0, 1fr); }
  .fx-editor-column { padding-left: 16px; }
  .fx-editor-basics { grid-template-columns: minmax(0, 1fr) 120px 28px; gap: 6px; }
}
@media (max-width: 760px) {
  .fx-overview-grid { grid-template-columns: 1fr 1fr; }
  .fx-overview-cell { padding: 12px; }
  .fx-overview-cell:nth-child(3) { border-left: 0; }
  .fx-overview-cell:nth-child(n+3) { border-top: 1px solid var(--border); }
  .fx-overview-cell > strong { font-size: 15px; }
  .fx-spend-body { grid-template-columns: 1fr; gap: 12px; }
  .fx-workspace { display: block; min-height: 0; }
  .fx-ideas-sidebar { border-right: 0; padding-right: 0; }
  .fx-board { max-height: none; overflow: visible; }
  .fx-editor-column { display: none; padding-left: 0; }
  .fx-workspace.is-editing .fx-ideas-sidebar { display: none; }
  .fx-workspace.is-editing .fx-editor-column { display: block; }
  .fx-editor-back { display: inline-flex; }
  .fx-editor-kicker { display: none; }
  .fx-board-toolbar { gap: 8px; }
  .fx-board-toolbar > .fx-search-label { flex-basis: 100%; }
  .fx-status-filter { flex: 1; }
  .fx-board-toolbar .btn { min-height: 40px; }
  .fx-editor .input, .fx-editor .fx-idea-title { flex: none; height: auto; min-height: 40px; }
  .fx-editor textarea.input { min-height: 90px; }
  .fx-reel-toolbar .segmented { max-width: 100%; }
  .fx-editor-savebar { flex-direction: column; align-items: stretch; padding: 10px; }
  .fx-save-actions { display: flex; flex-wrap: nowrap; }
  .fx-save-actions .btn { flex: 1; padding-left: 8px; padding-right: 8px; }
  .fx-reference-frame { width: 88px; flex-basis: 88px; }
  .fx-editor-reference { gap: 10px; padding: 10px; }
  .fx-editor-back { margin-bottom: 12px; }
  .fx-editor .btn, .fx-editor-savebar .btn { min-height: 40px; }
}

@media (max-width: 720px) {
  .fx-editor-savebar { left: 8px; right: 8px; bottom: calc(var(--bottom-nav-h, 62px) + 8px + env(safe-area-inset-bottom, 0px)); }
}

/* В рабочей доске сводка остаётся доступной, но не отнимает её экран. */
.fx-status-summary { display: none; }
.fx-overview.is-compact { margin-bottom: 10px; }
.fx-overview.is-compact .fx-status-summary { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 9px 12px; cursor: pointer; font-size: 11px; color: var(--text-2); }
.fx-status-summary strong { color: var(--text); font-weight: 600; }
.fx-overview.is-compact .fx-status-summary > span:last-child { color: var(--accent-dark); }
#fx-card.is-ideas > .card-head { padding-top: 14px; padding-bottom: 10px; }
#fx-card.is-ideas > .card-body { padding-top: 10px; }
#fx-card.is-ideas #fx-sub { display: none; }
#fx-card.is-ideas .an-tabs { margin-bottom: 12px; }
#fx-card.is-ideas .fx-add-reference { margin-bottom: 8px; }
#fx-card.is-ideas .fx-board-toolbar { margin-bottom: 5px; }
.fx-idea-row { flex: 0 0 auto; min-height: 88px; padding: 8px; align-items: flex-start; }
.fx-row-main { flex: 1 0 0; }
.fx-row-main strong, .fx-row-meta, .fx-row-foot { flex-shrink: 0; }
.fx-row-foot { display: flex; align-items: center; gap: 5px; max-width: 100%; }
.fx-row-foot .fx-row-platforms { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; font-size: 10px; }
.fx-row-status { flex: 0 0 auto; }
@media (max-width: 760px) {
  .fx-overview.is-compact .fx-status-summary { flex-wrap: wrap; gap: 4px; }
  .fx-overview.is-compact .fx-status-summary > span:last-child { font-size: 10px; }
}

#fx-card > .card-head { display: none; }
#fx-card > .card-body { padding-top: 14px; }
.fx-idea-row { min-height: 80px; padding: 7px; gap: 9px; }
.fx-row-frame { width: 36px; height: 54px; flex-basis: 36px; }
.fx-row-main { gap: 3px; }
.fx-row-main strong { font-size: 12.5px; line-height: 1.3; }
.fx-row-meta { max-width: 100%; font-size: 11px; line-height: 1.4; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fx-row-status { padding: 1px 5px; }
@media (max-width: 760px) {
  .fx-board-toolbar .fx-status-filter { flex-basis: 100%; }
  .fx-board-toolbar > .btn { flex: 1; }
  .fx-row-main strong { font-size: 13px; }
}

@media (max-width: 760px) {
  #fx-pane-ideas:has(.fx-workspace.is-editing) .fx-board-toolbar,
  #fx-pane-ideas:has(.fx-workspace.is-editing) .fx-add-reference { display: none; }
}

/* Второй уровень внутри выбранного канала, спокойнее основной навигации. */
.fx-view-toolbar { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin-bottom: 14px; }
.fx-view-toolbar .segmented button { min-height: 36px; }
.fx-kanban { display: flex; gap: 12px; overflow-x: auto; align-items: stretch; padding: 2px 2px 16px; min-height: 360px; }
.fx-kanban-column { flex: 0 0 max(185px, calc((100% - 48px) / 5)); min-width: 0; padding: 10px; background: var(--surface-2); border: 1px solid var(--border); border-radius: 12px; transition: background .12s; }
.fx-kanban-column > h3 { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin: 2px 2px 14px; font-size: 12px; font-weight: 600; }
.fx-kanban-column > h3 > span { color: var(--text-3); font-weight: 400; }
.fx-kanban-cards { display: flex; flex-direction: column; gap: 10px; }
.fx-kanban-card { background: var(--surface); border: 1px solid var(--border); border-radius: 9px; box-shadow: var(--shadow-sm); overflow: hidden; }
.fx-kanban-column.is-drop-target { background: var(--accent-soft); border-color: var(--accent); }
.fx-kanban-open { display: flex; align-items: flex-start; gap: 9px; width: 100%; padding: 11px 9px; text-align: left; border: 0; background: transparent; color: var(--text); cursor: pointer; font: inherit; }
.fx-kanban-open > span:last-child { min-width: 0; flex: 1; }
.fx-kanban-open strong { display: block; font-size: 12px; line-height: 1.45; overflow-wrap: anywhere; }
.fx-kanban-open small { display: block; margin-top: 6px; font-size: 11px; color: var(--text-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fx-kanban-status { display: block; padding: 0 9px 9px; }
.fx-kanban-status .input { width: 100%; min-width: 0; height: 32px; padding: 4px 32px 4px 10px; font-size: 11px; background-color: var(--surface-2); }
.fx-kanban-empty { padding: 24px 0; text-align: center; color: var(--text-3); font-size: 12px; }
.fx-idea-modal-backdrop { position: fixed; inset: 0; display: flex; align-items: center; justify-content: center; padding: 24px; background: rgba(17,19,26,.48); z-index: 60; }
.fx-idea-modal { display: flex; flex-direction: column; background: var(--surface); border-radius: var(--r-lg); box-shadow: var(--shadow-lg); width: min(1280px, 100%); height: min(960px, calc(100dvh - 48px)); overflow: hidden; overscroll-behavior: contain; }
.fx-modal-open { overflow: hidden; }
.fx-modal-heading { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.fx-idea-navigation { display: flex; align-items: center; gap: 4px; }
.fx-idea-navigation .btn { width: 32px; height: 32px; padding: 0; }
@media (max-width: 600px) {
  .fx-modal-head { flex-wrap: wrap; }
  .fx-modal-heading { flex: 1 0 100%; justify-content: space-between; }
  .fx-modal-actions { margin-left: auto; }
}
.fx-modal-actions { display: flex; align-items: center; gap: 8px; }
.fx-modal-head { display: flex; flex: 0 0 auto; align-items: center; justify-content: space-between; gap: 16px; padding: 12px 24px; border-bottom: 1px solid var(--border); font-size: 13px; font-weight: 600; color: var(--text-2); }
#fx-modal-close { width: 32px; padding: 0; }
#fx-modal-editor-slot { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.fx-idea-modal .fx-editor-column { display: flex; flex: 1; min-height: 0; flex-direction: column; padding: 24px; }
.fx-modal-columns { display: grid; grid-template-columns: 220px minmax(260px, .9fr) minmax(0, 1.1fr); gap: 24px; align-items: start; }
.fx-modal-columns > * { min-width: 0; min-height: 0; }
.fx-modal-columns h3 { margin: 0 0 12px; font-size: 13px; font-weight: 600; }
.fx-modal-reel .fx-reference-frame { width: 100%; height: auto; max-height: min(360px, calc(100dvh - 280px)); }
.fx-modal-reel > p { margin: 12px 0; font-size: 12px; }
.fx-reference-author { display: block; max-width: 100%; color: var(--accent); text-decoration: none; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fx-reference-author:hover { color: var(--accent-dark); text-decoration: underline; }
.fx-reference-caption { display: flex; flex-direction: column; gap: 6px; min-width: 0; width: 100%; margin-top: 12px; text-align: left; }
.fx-caption-label { flex: 0 0 auto; font-size: 11px; color: var(--text-3); }
.fx-caption-text { white-space: pre-wrap; overflow-wrap: anywhere; font-size: 12px; line-height: 1.6; }
.fx-caption-text:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 2px; }
.fx-caption-empty.field-note { margin: 0; font-size: 11px; color: var(--text-3); text-align: left; }
.fx-modal-fields .fx-editor-basics { grid-template-columns: minmax(0, 1fr) 32px; gap: 8px; }
.fx-modal-fields .fx-editor-basics > label:first-child { grid-column: 1 / -1; }
.fx-modal-fields .input { font-size: 13px; }
.fx-modal-fields .fx-idea-title { font-size: 15px; }
.fx-modal-fields .fx-editor-section { margin-top: 24px; }
.fx-modal-fields .field-label { font-size: 12px; color: var(--text-2); }
.fx-modal-metrics .fx-reference-date { margin: 8px 0 4px; color: var(--text-2); }
.fx-modal-metrics .field-note { display: block; margin: 0; font-size: 11px; }
.fx-modal-transcript { border-left: 1px solid var(--border); padding-left: 20px; }
.fx-modal-transcript .fx-transcript-text { font-size: 13px; line-height: 1.7; overflow-wrap: anywhere; }
.fx-modal-transcript .fx-transcript-text > p { margin: 0 0 12px; }
.fx-modal-transcript .fx-transcript-text > p:last-child { margin-bottom: 0; }
.fx-idea-modal .fx-editor-savebar { position: static; flex: 0 0 auto; max-width: none; width: 100%; margin: 16px 0 0; z-index: 61; }
.fx-idea-modal .fx-editor-filter-note { display: none; }
/* Тот же редактор в списке: место справа принадлежит расшифровке,
   поля остаются одной центральной колонкой, кадр не растёт вместе с текстом. */
@media (min-width: 1201px) {
  .fx-workspace { grid-template-columns: 180px minmax(0, 1fr); }
  .fx-workspace .fx-editor-column { padding-left: 16px; }
}
@media (min-width: 761px) and (max-width: 1200px) {
  .fx-workspace { display: block; }
  .fx-workspace.is-editing .fx-ideas-sidebar { display: none; }
  .fx-workspace .fx-editor-column { display: none; padding-left: 0; }
  .fx-workspace.is-editing .fx-editor-column { display: block; }
  .fx-workspace .fx-editor-back { display: inline-flex; margin-bottom: 12px; }
}
/* Две строки управления оставляют большую часть окна рабочему редактору. */
.fx-navigation-row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; border-bottom: 1px solid var(--border); margin-bottom: 10px; }
.fx-navigation-row #fx-tabs { flex: 1 0 auto; margin: 0; border-bottom: 0; flex-wrap: nowrap; }
.fx-navigation-row .an-tab { min-height: 36px; padding: 7px 10px; font-size: 13px; }
.fx-navigation-row .fx-summary-row { flex: 0 1 auto; align-items: center; margin: 0; padding-bottom: 4px; }
.fx-navigation-row .fx-overview.is-compact { margin: 0; border: 0; background: transparent; }
.fx-navigation-row .fx-overview .fx-status-summary { padding: 6px 0; gap: 10px; min-height: 32px; }
.fx-navigation-row .fx-status-period { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.fx-navigation-row .fx-summary-row:has(.fx-status-details[open]) { flex-basis: 100%; align-items: flex-start; }
.fx-navigation-row .fx-status-details[open] { border: 1px solid var(--border); border-radius: var(--r-md); background: var(--surface-2); }
.fx-navigation-row .fx-status-details[open] > summary { padding: 8px 12px; }
.fx-idea-controls { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 10px; }
.fx-idea-controls .fx-view-toolbar { flex: 0 0 auto; margin: 0; }
.fx-idea-controls .fx-board-toolbar { flex: 1; flex-wrap: nowrap; margin: 0; gap: 8px; }
.fx-idea-controls .fx-search-label { flex-basis: 160px; }
.fx-idea-controls .fx-status-filter { flex: 0 0 145px; }
.fx-idea-controls .fx-add-reference { flex: 0 0 auto; margin: 0; }
.fx-idea-controls .fx-add-reference > summary { display: flex; align-items: center; gap: 6px; min-height: 36px; padding: 0 10px; border: 1px solid var(--border); border-radius: var(--r-button); color: var(--text); background: var(--surface); font-size: 12px; font-weight: 500; white-space: nowrap; }
.fx-idea-controls .fx-add-reference > summary::before { content: '+'; font-size: 17px; line-height: 1; }
.fx-idea-controls .fx-add-reference > summary::-webkit-details-marker { display: none; }
.fx-idea-controls .fx-add-reference > summary:hover { background: var(--surface-2); }
.fx-idea-controls .fx-add-reference > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.fx-idea-controls .fx-add-reference[open] { flex-basis: 100%; }
.fx-idea-controls .fx-add-reference[open] > summary::before { content: '−'; }
.fx-idea-controls .fx-add-reference .fx-filter { margin-bottom: 0; }
#fx-kanban-hint { margin: 0 0 10px; }
@media (min-width: 901px) {
  .settings-inner:has(> #tabpanel-factory:not([hidden])) { max-width: none; margin: 0; padding: 0; }
  #fx-card { border-radius: 0; border-width: 0 0 1px; box-shadow: none; }
  .settings-inner:has(> #tabpanel-factory:not([hidden])) > .page-head { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  #fx-card > .card-body { padding: 10px 16px 16px; }
  .fx-idea-controls .segmented { padding: 2px; }
  .fx-idea-controls .segmented button { min-height: 30px; padding: 5px 12px; font-size: 12px; }
  .fx-idea-controls .input { height: 36px; min-height: 36px; font-size: 12px; }
  .fx-idea-controls .btn { min-height: 36px; height: 36px; font-size: 12px; white-space: nowrap; }
}
@media (max-width: 1100px) {
  .fx-navigation-row { gap: 2px 12px; }
  .fx-navigation-row #fx-tabs { flex-basis: 100%; }
}
@media (max-width: 900px) {
  .settings-inner:has(> #tabpanel-factory:not([hidden])) > .page-head { margin-bottom: 10px; }
  .settings-inner:has(> #tabpanel-factory:not([hidden])) .page-title { font-size: 22px; }
  #fx-card > .card-body { padding: 10px 12px 16px; }
  .fx-navigation-row #fx-tabs { min-width: 0; overflow-x: auto; overflow-y: hidden; scrollbar-width: thin; }
  .fx-navigation-row .an-tab { flex-shrink: 0; min-height: 40px; padding-inline: 8px; }
  .fx-navigation-row .fx-summary-row { flex-basis: 100%; }
  .fx-navigation-row .fx-summary-row:has(.fx-status-details[open]) { flex-wrap: wrap; }
  .fx-navigation-row .fx-summary-row:has(.fx-status-details[open]) .fx-overview { flex-basis: 100%; }
  .fx-navigation-row .fx-summary-row:has(.fx-status-details[open]) > .btn { margin-left: auto; }
  .fx-navigation-row .fx-overview .fx-status-summary { min-height: 40px; }
  .fx-navigation-row .fx-summary-row > .btn { min-height: 40px; }
  .fx-idea-controls .fx-board-toolbar { flex: 1 0 100%; flex-wrap: wrap; }
  .fx-idea-controls .fx-board-toolbar .fx-search-label { flex-basis: 100%; }
  .fx-idea-controls .fx-board-toolbar .fx-status-filter { flex: 1 1 145px; }
  .fx-idea-controls .fx-add-reference > summary { min-height: 40px; }
}
/* У каждой колонки своя высота и прокрутка: соседний контекст не уезжает.
   Savebar занимает собственную строку и не закрывает последние поля. */
@media (min-width: 901px) {
  .settings-inner:has(#tabpanel-factory:not([hidden]) #fx-pane-ideas:not([hidden]) #fx-workspace:not([hidden])) { padding-bottom: 0; }
  #fx-card:has(#fx-pane-ideas:not([hidden]) #fx-workspace:not([hidden])) > .card-body { padding-bottom: 8px; }
  .fx-workspace { height: var(--fx-workspace-height, 400px); min-height: 0; grid-template-rows: minmax(0, 1fr); }
  .fx-workspace .fx-ideas-sidebar { display: flex; flex-direction: column; height: 100%; min-height: 0; }
  .fx-workspace .fx-ideas-sidebar > .field-note { flex: 0 0 auto; }
  .fx-workspace .fx-editor-column { height: 100%; }
  .fx-workspace .fx-editor-column,
  .fx-workspace.is-editing .fx-editor-column { display: flex; flex-direction: column; min-height: 0; }
  .fx-workspace .fx-modal-columns { grid-template-columns: clamp(168px, 14vw, 210px) minmax(230px, .8fr) minmax(0, 1.2fr); gap: 16px; }
  .fx-workspace .fx-modal-transcript { padding-left: 16px; }
  .fx-editor-column:has(.fx-editor-savebar:not([hidden])) { padding-bottom: 0; }
  .fx-idea-modal .fx-editor-column:has(.fx-editor-savebar:not([hidden])) { padding-bottom: 24px; }
  .fx-editor { display: flex; flex-direction: column; flex: 1; min-height: 0; }
  .fx-editor-back { flex: 0 0 auto; align-self: flex-start; }
  .fx-modal-columns { flex: 1; min-height: 0; align-items: stretch; }
  .fx-modal-fields { overflow-y: auto; overscroll-behavior-y: contain; scrollbar-gutter: stable; padding: 3px 8px 16px 3px; }
  .fx-modal-reel { display: flex; flex-direction: column; align-items: flex-start; overflow-y: auto; }
  .fx-modal-reel > h3, .fx-modal-reel > p, .fx-modal-reel > .btn { flex-shrink: 0; }
  .fx-modal-reel > p { align-self: stretch; }
  .fx-modal-reel .fx-reference-frame { flex: 0 1 auto; min-height: 0; }
  .fx-modal-reel:has(.fx-reference-caption) .fx-reference-frame { min-height: 90px; max-height: min(360px, 50%); }
  .fx-modal-reel .fx-reference-caption { flex: 1 1 100px; min-height: 96px; }
  .fx-modal-reel .fx-caption-text { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior-y: contain; scrollbar-gutter: stable; padding-right: 4px; }
  .fx-modal-transcript { display: flex; flex-direction: column; }
  .fx-modal-transcript h3 { flex: 0 0 auto; }
  .fx-modal-transcript .fx-transcript-heading { flex: 0 0 auto; }
  .fx-modal-transcript .fx-own-transcript { min-height: 0; overflow-y: auto; overscroll-behavior-y: contain; scrollbar-gutter: stable; resize: none; }
  .fx-modal-transcript .fx-transcript-editor { display: flex; flex-direction: column; flex: 1; min-height: 0; }
  .fx-modal-transcript .fx-transcript-text { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior-y: contain; scrollbar-gutter: stable; }
  .fx-modal-transcript .fx-transcript-actions, .fx-modal-transcript .fx-transcript-status { flex: 0 0 auto; }
  .fx-editor-savebar { position: static; flex: 0 0 auto; max-width: none; width: 100%; margin: 12px 0 0; padding: 10px 12px; }
  .fx-workspace .fx-editor-savebar { flex-wrap: wrap; }
  .fx-workspace .fx-save-actions { margin-left: auto; }
  .fx-workspace .fx-board { flex: 1; min-height: 0; max-height: none; }
}
@media (min-width: 901px) and (max-width: 1200px) {
  .fx-workspace:not(.is-editing) .fx-editor-column { display: none; }
}
@media (max-width: 900px) {
  .fx-modal-columns { display: flex; flex-direction: column; gap: 24px; }
  .fx-modal-columns > * { width: 100%; }
  .fx-modal-transcript { padding: 20px 0 0; border-left: 0; border-top: 1px solid var(--border); }
  .fx-modal-reel .fx-reference-frame { width: 142px; max-height: 252px; margin: 0 auto; }
  .fx-modal-reel { text-align: center; }
  .fx-modal-reel .fx-caption-text { font-size: 14px; }
  .fx-idea-modal .fx-editor { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior-y: contain; padding: 3px; }
  .fx-idea-modal .fx-editor-column:has(.fx-editor-savebar:not([hidden])) { padding-bottom: 16px; }
  .fx-idea-modal .fx-editor-savebar { flex-direction: column; align-items: stretch; }
}
@media (max-width: 600px) {
  .fx-modal-transcript .fx-transcript-text { font-size: 16px; }
  .fx-kanban-column { flex-basis: 240px; }
  .fx-idea-modal-backdrop { padding: 8px; }
  .fx-idea-modal { height: calc(100dvh - 16px); border-radius: var(--r-lg); }
  .fx-idea-modal .fx-editor-column { display: flex; padding: 16px; }
  .fx-modal-head { padding: 10px 16px; }
  .fx-idea-modal .fx-editor-savebar { padding-bottom: calc(10px + env(safe-area-inset-bottom, 0px)); }
}

.pub-format-tabs { display: flex; flex-wrap: wrap; gap: 4px; border-bottom: 1px solid var(--border); margin: 18px 0 16px; padding-bottom: 8px; }
.pub-format-tab { border: 0; background: transparent; color: var(--text-2); font: inherit; font-size: 13px; font-weight: 500; padding: 9px 12px; min-height: 36px; border-radius: 8px; cursor: pointer; }
.pub-format-tab:hover { color: var(--accent); background: var(--surface-2); }
.pub-format-tab.is-active { color: var(--accent); background: var(--accent-soft); }
.pub-format-tab:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.vp-feed > .list-empty { grid-column: 1 / -1; }
@media (max-width: 720px) {
  .pub-format-tab { padding: 9px 10px; font-size: 12px; }
}

/* TikTok / YouTube: локальная студия видео, без влияния на Instagram. */
.vp-library-tabs { margin: 20px 0 16px; border-bottom: 1px solid var(--border); padding-bottom: 10px; }
.vp-studio-compose { display: grid; grid-template-columns: minmax(0, 1fr) minmax(250px, .78fr); gap: 32px; align-items: start; }
.vp-studio-editor, .vp-studio-summary, .vp-studio-preview-column { min-width: 0; }
.vp-studio-eyebrow { margin: 0 0 12px; font-size: 12px; font-weight: 600; color: var(--text-2); text-transform: uppercase; letter-spacing: .06em; }
.vp-studio-preview { border: 1px solid var(--border); border-radius: 16px; overflow: hidden; background: #fff; color: #0f0f0f; }
.vp-studio-platform { padding: 12px 16px; font-size: 13px; font-weight: 700; border-bottom: 1px solid #ececec; }
.vp-studio-player { position: relative; aspect-ratio: 16 / 9; background: #101114; overflow: hidden; }
.vp-studio-player.is-portrait { aspect-ratio: 9 / 16; max-height: 460px; margin-inline: auto; }
.vp-studio-player video { display: block; width: 100%; height: 100%; position: absolute; inset: 0; object-fit: contain; }
.vp-studio-placeholder { position: absolute; inset: 0; display: flex; flex-direction: column; justify-content: center; align-items: center; color: #bbbfc8; text-align: center; padding: 24px; gap: 12px; }
.vp-studio-placeholder span { display: grid; place-items: center; width: 52px; height: 52px; border: 1px solid #41434b; border-radius: 50%; font-size: 18px; }
.vp-studio-placeholder p { font-size: 13px; line-height: 1.5; margin: 0; max-width: 240px; }
.vp-studio-post { padding: 16px; }
.vp-studio-account { font-size: 13px; font-weight: 650; overflow-wrap: anywhere; }
.vp-studio-caption { font-size: 17px; font-weight: 600; line-height: 1.45; white-space: pre-wrap; overflow-wrap: anywhere; margin: 8px 0 0; }
.vp-studio-description { white-space: pre-wrap; overflow-wrap: anywhere; font-size: 13px; line-height: 1.6; color: var(--text-2); }
.vp-studio-comment { margin-top: 16px; padding-top: 12px; border-top: 1px solid var(--border); font-size: 13px; }
.vp-studio-comment p { white-space: pre-wrap; overflow-wrap: anywhere; color: var(--text-2); margin: 6px 0 0; }
.vp-studio-preview.is-tiktok { background: #101114; color: #fff; max-width: 310px; margin-inline: auto; border-color: #26272b; }
.vp-studio-preview.is-tiktok .vp-studio-platform { border-color: #26272b; display: flex; justify-content: space-between; }
.vp-studio-preview.is-tiktok .vp-studio-platform::after { content: 'Предпросмотр'; color: #aaa; font-size: 11px; font-weight: 400; }
.vp-studio-preview.is-tiktok .vp-studio-caption { font-weight: 400; font-size: 13px; margin-top: 6px; max-height: 160px; overflow-y: auto; }
.vp-studio-preview-column > .field-note { margin-top: 12px; }
.vp-studio-detail { display: grid; grid-template-columns: minmax(0, 1fr) minmax(230px, .8fr); gap: 28px; align-items: start; }
.vp-studio-summary .pub-detail-head { flex-wrap: wrap; }
.vp-studio-summary .pub-detail-step { display: block; line-height: 1.5; }
.vp-studio-summary .vp-detail-meta { grid-template-columns: 1fr; gap: 4px; }
.vp-studio-summary .vp-detail-meta dd { margin-bottom: 10px; }
.vp-studio-history { border-top: 1px solid var(--border); margin-top: 20px; padding-top: 18px; }
.vp-studio-history h3 { font-size: 14px; margin: 0 0 14px; font-weight: 600; }
.vp-studio-history ol { list-style: none; padding: 0; margin: 0; }
.vp-studio-event { position: relative; padding: 0 0 18px 22px; margin-left: 4px; border-left: 1px solid var(--border); font-size: 13px; }
.vp-studio-event:last-child { border-left-color: transparent; padding-bottom: 0; }
.vp-studio-event::before { content: ''; position: absolute; left: -4px; top: 4px; width: 7px; height: 7px; border-radius: 50%; background: #adb2ba; }
.vp-studio-event.is-success::before { background: #21825a; }
.vp-studio-event.is-error::before { background: #bd3643; }
.vp-studio-event.is-info::before { background: var(--accent); }
.vp-studio-event time { display: block; color: var(--text-2); margin-top: 4px; font-size: 12px; }
.vp-studio-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(215px, 1fr)); gap: 16px; }
.vp-studio-grid > .list-empty { grid-column: 1 / -1; }
.vp-studio-grid .vp-row { display: flex; flex-direction: column; padding: 0; gap: 0; overflow: hidden; border-radius: 12px; }
.vp-studio-grid .vp-row-thumb { position: relative; width: 100%; height: auto; aspect-ratio: 16 / 9; border-radius: 0; background: #17181c; color: #a4a7b0; }
.vp-studio-grid .vp-row-thumb video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; pointer-events: none; }
.vp-studio-grid.is-tiktok { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
.vp-studio-grid.is-tiktok .vp-row-thumb { aspect-ratio: 9 / 16; max-height: 280px; }
.vp-studio-grid .vp-row-main { padding: 12px 12px 8px; width: 100%; box-sizing: border-box; }
.vp-studio-grid .vp-row-right { padding: 0 12px 12px; flex-wrap: wrap; white-space: normal; }
/* Лента канала как на YouTube: «Видео» – 16:9 по три в ряд с длительностью,
   Shorts – вертикальные плитки по пять, обложка во всю плитку. */
.vp-feed-tile { border: 0; padding: 0; background: none; text-align: left; font: inherit; cursor: pointer; gap: 8px; }
.vp-feed { grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 28px 16px; }
.vp-feed.is-shorts { grid-template-columns: repeat(auto-fill, minmax(165px, 1fr)); gap: 24px 8px; }
.vp-feed-thumb { aspect-ratio: 16 / 9; border-radius: 12px; background: #17181c; }
.vp-feed.is-shorts .vp-feed-thumb { aspect-ratio: 9 / 16; }
.vp-feed-cover { object-fit: cover; }
.vp-feed-duration { position: absolute; right: 6px; bottom: 6px; padding: 1px 5px; border-radius: 4px; background: rgba(0, 0, 0, .8); color: #fff; font-size: 12px; font-weight: 600; line-height: 18px; font-variant-numeric: tabular-nums; }
.vp-feed-title { font-size: 15px; line-height: 1.35; }
.vp-feed.is-shorts .vp-feed-title { font-size: 14px; }
.vp-feed-meta { font-size: 13px; }
.vp-counters-line { gap: 18px; margin: 0 0 6px; }
.vp-counters-line .camp-counter { padding: 0; border: 0; background: none; }
.vp-counters-line .camp-counter b { font-size: 13px; }
@media (max-width: 640px) {
  .vp-feed { grid-template-columns: minmax(0, 1fr); gap: 20px; }
  .vp-feed.is-shorts { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px 8px; }
  .vp-feed-title { font-size: 14px; }
}
.vp-studio-embed { min-height: 200px; aspect-ratio: 16 / 9; width: 100%; background: #101114; color: #ddd; border-radius: 12px; overflow: hidden; }
.vp-studio-embed.is-portrait { aspect-ratio: 9 / 16; max-width: 360px; margin-inline: auto; }
.vp-studio-embed iframe { width: 100%; height: 100%; border: 0; display: block; }
.vp-studio-watch-meta { color: var(--text-2); font-size: 13px; margin: 16px 0; }
@media (max-width: 800px) {
  .vp-studio-compose, .vp-studio-detail { grid-template-columns: minmax(0, 1fr); gap: 24px; }
  .vp-studio-preview-column { max-width: 440px; width: 100%; margin-inline: auto; }
  .vp-studio-detail #vp-detail-preview { max-width: 500px; width: 100%; margin-inline: auto; }
}
@media (max-width: 480px) {
  .vp-studio-grid { grid-template-columns: minmax(0, 1fr); }
  .vp-studio-grid.is-tiktok { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
  .vp-studio-grid .vp-row-title { font-size: 13px; }
  .vp-studio-grid .vp-row-meta { font-size: 11px; }
  .vp-studio-grid .pub-tag { white-space: normal; }
  .vp-library-tabs { gap: 4px; }
  .vp-library-tabs button { padding-inline: 10px; }
}

/* ---------- Окно ролика конкурента ----------
   Каркас и классы – от окна поста своей ленты (.pubv-*), третья колонка –
   расшифровка на русском, её правят прямо здесь. */
.fxv { max-width: min(1400px, 100%); }
.fxv-media { --pubv-ratio: 0.5625; }
.fxv-frame { display: flex; align-items: center; justify-content: center; width: 100%; height: 100%; color: rgba(255, 255, 255, .6); text-decoration: none; }
.fxv-frame .fx-frame-empty { color: rgba(255, 255, 255, .6); font-size: 13px; }
.fxv-frame:focus-visible { outline: 2px solid #fff; outline-offset: -4px; }
.fxv .pubv-side { flex: 0 0 380px; }
.fxv-name { color: var(--text); text-decoration: none; }
.fxv-name:hover { text-decoration: underline; }
.fxv .pubv-text { white-space: pre-wrap; overflow-wrap: anywhere; }
.fxv .fx-chips { margin-top: 2px; }
.fxv .pubv-stat .fx-stat-delta { font-size: 12px; font-weight: 500; }
.fxv-links { align-items: center; }
.fxv-links .fx-inwork { margin-left: auto; }
.fxv-transcript {
  flex: 0 0 400px;
  min-width: 0;
  display: flex;
  flex-direction: column;
  border-left: 1px solid var(--border);
}
.fxv-transcript-title {
  flex: none;
  margin: 0;
  padding: 18px 16px;
  border-bottom: 1px solid var(--border);
  font-size: 14px;
  font-weight: 600;
}
.fxv-transcript-body { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: 12px 16px 16px; font-size: 14px; line-height: 1.55; }

@media (max-width: 1240px) {
  .fxv .pubv-side { flex-basis: 320px; }
  .fxv-transcript { flex-basis: 340px; }
}

/* Уже 1100 px три колонки не помещаются: окно в столбик одной прокруткой –
   кадр, подпись и цифры, под ними расшифровка. */
@media (max-width: 1100px) {
  #fxv { padding: 0; align-items: stretch; }
  .fxv { flex-direction: column; height: auto; max-width: none; width: 100%; border-radius: 0; overflow-y: auto; }
  .fxv .pubv-media { flex: none; height: 56vh; width: 100%; aspect-ratio: auto; }
  .fxv .pubv-side { flex: none; border-left: 0; }
  .fxv .pubv-body { overflow: visible; flex: none; }
  .fxv-transcript { flex: none; border-left: 0; border-top: 1px solid var(--border); }
  .fxv-transcript-body { overflow: visible; }
  #fxv .pubv-close { top: 8px; right: 8px; background: rgba(0, 0, 0, .45); border-radius: 50%; z-index: 2; }
  #fxv .pubv-nav { top: 28vh; z-index: 2; }
  #fxv .pubv-nav-prev { left: 8px; }
  #fxv .pubv-nav-next { right: 8px; }
}

@media (max-width: 560px) {
  .fx-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px 6px; }
  .fx-tile-foot { flex-wrap: wrap; gap: 0 8px; }
}

/* Подтверждённые исходы воронки: блоки, вопросы и внешние операции. */
.funnel-outcome-summary { border-top:1px solid var(--border); margin-top:8px; padding-top:8px; }
.funnel-outcome-summary p { display:flex; align-items:baseline; justify-content:space-between; gap:8px; margin:4px 0; font-size:12px; }
.funnel-outcome-summary span { min-width:0; overflow-wrap:anywhere; }
.funnel-outcome-summary strong { flex-shrink:0; }
.funnel-run-source { border-bottom:1px solid var(--border); margin-bottom:12px; padding-bottom:8px; overflow-wrap:anywhere; }

.funnel-outcome-unit { display:block; margin-top:2px; color:var(--text-2); font-size:11px; line-height:1.4; font-weight:normal; }

.funnel-entry-event { display:grid; gap:4px; margin:12px 0; min-width:0; overflow-wrap:anywhere; }
.funnel-entry-event small { color:var(--text-2); line-height:1.4; }

/* Вложенная панель каналов использует прежние контролы внутри Интеграций. */
#integrations-root > #tabpanel-channels { max-width: none; }


/* Канбан: карточка под курсором и место назначения, как на доске Trello. */
.fx-kanban-open { cursor: grab; touch-action: none; }
.fx-kanban-card[hidden] { display: none; }
.fx-kanban-drag-active, .fx-kanban-drag-active * { cursor: grabbing !important; user-select: none !important; }
.fx-kanban-placeholder { flex: 0 0 auto; border-radius: 9px; background: rgba(30, 45, 65, .12); border: 1px dashed rgba(30, 45, 65, .18); }
.fx-kanban-ghost { position: fixed; z-index: 1000; margin: 0; pointer-events: none; transform: rotate(2deg); box-shadow: 0 12px 28px rgba(17, 19, 26, .25); opacity: .98; }
.fx-kanban-column:has(.fx-kanban-placeholder) .fx-kanban-empty { display: none; }
@media (prefers-reduced-motion: reduce) { .fx-kanban-ghost { transform: none; } }

/* Аналитика всех каналов */
.sa-calendar { display:flex; align-items:end; flex-wrap:wrap; gap:8px; width:100%; justify-content:flex-end; }
.sa-calendar label { display:grid; gap:4px; color:var(--text-muted,#6b7280); font-size:12px; }
.sa-calendar input,.sa-select-label select { border:1px solid var(--border,#e5e7eb); border-radius:8px; padding:8px 10px; background:var(--surface,#fff); color:var(--text,#17202c); font:inherit; min-height:36px; }
#sa-range-error { color:var(--danger,#d33); width:100%; font-size:12px; }
.sa-section-head { display:flex; align-items:center; justify-content:space-between; gap:16px; margin:6px 0 20px; }
.sa-section-head h3 { font-size:22px; line-height:1.25; margin:7px 0 0; }
.sa-eyebrow { font-size:10px; font-weight:700; letter-spacing:.12em; color:var(--text-muted,#6b7280); }
.sa-period-note,.sa-footnote { color:var(--text-muted,#6b7280); font-size:12px; line-height:1.6; }
.sa-footnote { margin:12px 0 0; }
.sa-channel-grid,.sa-kpis { display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:14px; margin-bottom:24px; }
.sa-channel-card { text-align:left; border:1px solid var(--border,#e5e7eb); border-radius:14px; padding:18px; background:var(--surface,#fff); color:var(--text,#17202c); font:inherit; cursor:pointer; min-width:0; box-shadow:inset 0 3px 0 var(--sa-color); }
.sa-channel-card:hover { border-color:var(--sa-color); }
.sa-telegram { --sa-color:#229ed9; }.sa-instagram { --sa-color:#c83982; }.sa-youtube { --sa-color:#e14545; }.sa-tiktok { --sa-color:#168b88; }
.sa-channel-name { display:flex; align-items:center; justify-content:space-between; font-size:14px; font-weight:600; }
.sa-channel-name span { color:var(--text-muted,#6b7280); }
.sa-channel-card>strong { display:block; font-size:32px; letter-spacing:-.04em; line-height:1.3; margin-top:16px; }
.sa-channel-card>small { display:block; min-height:32px; color:var(--text-muted,#6b7280); font-size:11px; line-height:1.5; }
.sa-card-metrics { display:grid; grid-template-columns:1fr 1fr; margin-top:16px; padding-top:12px; border-top:1px solid var(--border,#e5e7eb); gap:8px; }
.sa-card-metrics span { font-size:11px; color:var(--text-muted,#6b7280); }.sa-card-metrics b { display:block; color:var(--text,#17202c); font-size:17px; margin-top:4px; }
.sa-comparison,.sa-trends,.sa-main-chart,.sa-content,.sa-breakdown { margin-bottom:24px; }
.sa-outreach-head { border-top:1px solid var(--border,#e5e7eb); padding-top:28px; margin-top:32px; }
.sa-link { color:var(--primary,#06f); background:none; padding:0; border:0; font:inherit; cursor:pointer; }
.sa-trend-grid { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:24px; }
.sa-trend { min-width:0; color:var(--sa-color); }.sa-trend h4 { margin:10px 0; color:var(--text,#17202c); font-size:14px; }
.sa-chart { display:block; width:100%; min-height:150px; color:var(--sa-color,var(--primary,#06f)); }
.sa-empty { padding:32px 12px; text-align:center; background:var(--bg,#fafafa); border-radius:10px; color:var(--text-muted,#6b7280); font-size:13px; }
.sa-series { font-size:12px; color:var(--text-muted,#6b7280); margin-top:8px; }.sa-series summary { cursor:pointer; }.sa-series .an-table-wrap { max-height:240px; margin-top:10px; }
.sa-select-label { display:flex; align-items:center; flex-wrap:wrap; gap:8px; font-size:12px; color:var(--text-muted,#6b7280); }
.sa-kpi { border:1px solid var(--border,#e5e7eb); background:var(--surface,#fff); border-radius:12px; padding:16px; min-width:0; }
.sa-kpi span,.sa-kpi small { display:block; font-size:12px; color:var(--text-muted,#6b7280); line-height:1.5; }.sa-kpi strong { display:block; font-size:28px; margin:8px 0; line-height:1.2; }
.sa-media td:first-child { min-width:200px; max-width:340px; white-space:normal; overflow-wrap:anywhere; }.sa-warning { overflow-wrap:anywhere; font-size:13px; line-height:1.6; }
@media (max-width:1100px) { .sa-channel-grid,.sa-kpis { grid-template-columns:repeat(2,minmax(0,1fr)); }.sa-section-head h3 { font-size:20px; } }
@media (max-width:600px) {
  .sa-calendar { justify-content:flex-start; }.sa-calendar input { width:130px; max-width:100%; }.sa-calendar label { min-width:0; }
  .sa-section-head { align-items:flex-start; flex-direction:column; gap:10px; }.sa-channel-grid,.sa-kpis { gap:10px; }
  .sa-channel-card { padding:13px; }.sa-channel-card>strong { font-size:26px; }.sa-card-metrics { grid-template-columns:1fr; }.sa-channel-name { font-size:13px; }
  .sa-trend-grid { grid-template-columns:1fr; gap:16px; }.sa-kpi { padding:12px; }.sa-kpi strong { font-size:24px; }.sa-period-note { font-size:11px; }
  #an-card .an-tabs { overflow-x:auto; flex-wrap:nowrap; white-space:nowrap; }.sa-main-chart .an-block-head,.sa-content .an-block-head,.sa-trends .an-block-head { align-items:flex-start; flex-direction:column; gap:10px; }
}

/* Варианты текстов в существующем редакторе автоматизаций. */
[data-variants-list] { width: 100%; }

.vp-feed-tags { display: flex; flex-wrap: wrap; gap: 4px; }
.vp-feed-tile > .pub-tag { align-self: flex-start; }
.vp-feed-tags .pub-tag { white-space: normal; }

/* Период без повторного заголовка и пустого этажа над аналитикой. */
#an-card > .card-head { padding:14px 20px; }
#an-card .an-head-actions { width:100%; gap:10px 16px; }
#an-card .sa-calendar { width:auto; margin-left:auto; align-items:center; gap:8px; }
#an-card .sa-calendar label { display:flex; align-items:center; gap:6px; }
#an-card .sa-calendar input { width:138px; padding:6px 8px; min-height:34px; }
#an-card .an-fresh { margin-left:auto; }
#an-card .an-fresh-text { font-size:11px; }
#an-card .segmented-item { padding:7px 14px; }
.sa-subtabs { display:flex; gap:6px; flex-wrap:nowrap; overflow-x:auto; padding:4px 0 12px; margin-bottom:18px; border-bottom:1px solid var(--border); }
.sa-subtab { flex:none; border:0; background:transparent; color:var(--text-3); font:inherit; font-size:13px; font-weight:500; border-radius:8px; padding:8px 14px; min-height:34px; cursor:pointer; white-space:nowrap; }
.sa-subtab.is-active { background:var(--blue-light,#edf4ff); color:var(--blue,#06f); }
.sa-subtab:focus-visible { outline:2px solid var(--blue,#06f); outline-offset:2px; }
.sa-subpanel > .sa-footnote { margin:12px 0 18px; }
@media (max-width:600px) {
  #an-card > .card-head { padding:12px; }
  #an-card .an-head-actions { gap:10px; }
  #an-card .an-fresh { margin-left:0; flex:1; justify-content:flex-end; }
  #an-card .an-fresh-text { display:none; }
  #an-card .sa-calendar { order:3; display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1fr) auto; width:100%; gap:6px; margin:0; }
  #an-card .sa-calendar label { display:grid; gap:3px; min-width:0; }
  #an-card .sa-calendar input { width:100%; min-width:0; box-sizing:border-box; font-size:12px; }
  #an-card .sa-calendar .btn { align-self:end; padding:7px 9px; font-size:12px; }
  #an-card #sa-range-error { grid-column:1/-1; }
  #an-card .segmented-item { padding:7px 10px; font-size:12px; }
  .sa-subtabs { gap:2px; margin-bottom:14px; }
  .sa-subtab { padding:8px 11px; }
}
@media (max-width:600px) {
  #an-card .sa-calendar { grid-template-columns:minmax(0,1fr) minmax(0,1fr); }
  #an-card .sa-calendar input { padding:6px 4px; }
  #an-card .sa-calendar .btn { grid-column:2; justify-self:end; }
}
/* Instagram formats share the existing composer and its account/caption fields. */
.pub-reel-options { display: flex; flex-direction: column; gap: 14px; max-width: 480px; }
.pub-cover-tools { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.pub-cover-tools label.field { display: flex; flex-direction: column; align-items: stretch; gap: 6px; margin: 0; }
.pub-cover-tools input[type=number] { width: 110px; min-height: 40px; }
.pub-cover-tools .field-note { flex-basis: 100%; }
.pub-items .pub-item { flex-wrap: wrap; gap: 6px; }
.pub-items .pub-item-body { min-width: 100px; flex: 1; }
.pub-carousel-nav { position: absolute; inset: auto 8px 10px; display: flex; justify-content: center; align-items: center; gap: 5px; color: white; background: #0009; border-radius: 20px; padding: 5px; z-index: 3; font-size: 12px; }
.pub-carousel-nav button { border: 0; background: none; color: inherit; cursor: pointer; padding: 4px; }
.pub-carousel-nav .pub-slide-dot { opacity: .4; padding: 0; }
.pub-carousel-nav .pub-slide-dot.is-active { opacity: 1; }
.pub-compose[data-kind=carousel] .pub-post-img { width: 100%; height: 100%; object-fit: cover; max-height: none; }
.pub-compose[data-kind=reel] .pub-post, .pub-compose[data-kind=story] .pub-post { max-width: min(280px, calc((100dvh - 140px) * 9 / 16)); }
.pub-compose[data-kind=reel] .pub-post-media, .pub-compose[data-kind=story] .pub-post-media { aspect-ratio: 9 / 16 !important; background: var(--text); }
.pub-compose[data-kind=reel] .pub-post-img, .pub-compose[data-kind=story] .pub-post-img { position: absolute; inset: 0; width: 100%; height: 100%; max-height: none; object-fit: contain; }
.pub-compose[data-kind=reel] .pub-post-head, .pub-compose[data-kind=story] .pub-post-head,
.pub-compose[data-kind=reel] .pub-post-actions, .pub-compose[data-kind=story] .pub-post-actions,
.pub-compose[data-kind=reel] .pub-post-likes, .pub-compose[data-kind=story] .pub-post-likes { display: none; }
.pub-compose[data-kind=reel] .pub-post-caption { background: var(--bg); }
.pub-vertical-deco { position: absolute; inset: 0; pointer-events: none; color: white; text-shadow: 0 1px 4px #000; }
.pub-reel-caption { position: absolute; bottom: 70px; left: 14px; right: 65px; font-size: 13px; }
.pub-reel-caption p { white-space: pre-wrap; max-height: 100px; overflow: hidden; margin: 6px 0 0; }
.pub-reel-icons { position: absolute; bottom: 110px; right: 14px; display: flex; flex-direction: column; gap: 22px; }
.pub-reel-icons [data-demo] { display: none; }
.pub-reel-icons svg { stroke: white; }
.pub-story-progress { position: absolute; top: 8px; left: 8px; right: 8px; height: 3px; border-radius: 4px; background: #fff8; }
.pub-story-name { position: absolute; top: 22px; left: 14px; font-weight: 600; }
.pub-story-reply { position: absolute; bottom: 68px; left: 12px; right: 12px; padding: 12px; border: 1px solid #fffa; border-radius: 25px; font-size: 12px; }
@media (max-width: 600px) { .pub-kind { width: 100%; } .pub-kind .segmented-item { padding-inline: 8px; flex: 1; } .pub-reel-options { max-width: 100%; } .pub-carousel-nav { gap: 3px; } .pub-item .btn { padding-inline: 7px; } }
.pub-compose[data-kind=reel] .pub-post-caption { position: relative; background: var(--surface); color: var(--text); max-height: 180px; overflow: auto; }
.pub-detail-item video.pub-detail-thumb { width: min(260px, 100%); height: auto; max-height: 380px; object-fit: contain; background: #111; }
/* Native video toolbar and seekbar remain clickable below the slide pager. */
.pub-compose[data-kind=carousel] .pub-post-media:has(> video.pub-post-img) .pub-carousel-nav { bottom: 72px; }

/* Общие списки и календарь: тот же источник значений, собственная панель. */
.dc-select { cursor: pointer; }
.dc-panel {
  position: fixed; z-index: 210; width: 300px;
  max-width: calc(100vw - 16px); max-height: min(calc(100dvh - 16px), var(--menu-available-height, 100dvh));
  overflow: auto; overscroll-behavior: contain;
  border: 1px solid var(--border); border-radius: var(--r-lg);
  background: var(--surface); box-shadow: var(--shadow-md);
  padding: 8px; font: 14px/1.4 var(--font); color: var(--text);
}
.dc-options { width: max-content; min-width: 180px; max-height: min(360px, calc(100dvh - 16px), var(--menu-available-height, 100dvh)); }
.dc-option {
  display: block; width: 100%; border: 0; background: transparent;
  border-radius: var(--r-pill); padding: 10px 14px; text-align: left;
  font: inherit; color: var(--text); cursor: pointer; white-space: normal;
  overflow-wrap: anywhere;
}
.dc-option:hover, .dc-option:focus-visible { background: var(--accent-soft); color: var(--accent-dark); }
.dc-option.is-selected { background: var(--accent); color: var(--surface); }
.dc-option:disabled { color: var(--text-3); cursor: default; background: transparent; }
.dc-option-group { padding: 10px 14px 4px; color: var(--text-2); font-size: 12px; font-weight: 600; }
.dc-date-field { display: inline-flex; position: relative; min-width: 0; max-width: 100%; vertical-align: middle; }
.field > .dc-date-field, .funnel-field > .dc-date-field { display: flex; width: 100%; }
.dc-date-field > .dc-date-input { padding-right: 40px; min-width: 0; }
.dc-date-input::-webkit-calendar-picker-indicator { display: none; }
.dc-calendar-trigger {
  position: absolute; right: 4px; top: 50%; transform: translateY(-50%);
  display: grid; place-items: center; width: 32px; height: 32px;
  border: 0; border-radius: var(--r-pill); background: transparent;
  color: var(--text-2); cursor: pointer;
}
.dc-calendar-trigger:hover { background: var(--accent-soft); color: var(--accent); }
.dc-calendar-trigger:disabled { cursor: default; color: var(--text-3); }
.dc-calendar { padding: 14px; }
.dc-calendar-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; gap: 8px; }
.dc-month-title { text-transform: capitalize; font-weight: 600; }
.dc-month-nav { width: 32px; height: 32px; border: 0; border-radius: var(--r-pill); background: var(--canvas); font-size: 24px; line-height: 1; cursor: pointer; }
.dc-calendar-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 4px; }
.dc-weekday { text-align: center; padding: 5px 0; font-size: 12px; color: var(--text-3); }
.dc-day { height: 34px; border: 0; border-radius: var(--r-pill); background: transparent; font: inherit; cursor: pointer; }
.dc-day:hover { background: var(--accent-soft); color: var(--accent-dark); }
.dc-day.is-today { color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent-line); }
.dc-day.is-selected { color: var(--surface); background: var(--accent); }
.dc-day:disabled { color: var(--faint); cursor: default; background: transparent; box-shadow: none; }
.dc-calendar-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--border); }
.dc-action { border: 0; border-radius: var(--r-pill); padding: 8px 10px; background: var(--canvas); color: var(--text-2); font: inherit; font-size: 12px; cursor: pointer; }
.dc-action:hover { background: var(--accent-soft); color: var(--accent-dark); }
.dc-action:disabled { color: var(--text-3); cursor: default; }
.dc-primary { background: var(--accent); color: var(--surface); }
.dc-time { display: flex; gap: 12px; padding-top: 12px; }
.dc-time label { flex: 1; min-width: 0; font-size: 12px; color: var(--text-2); }
.dc-time .input { margin-top: 6px; }
.dc-error { margin-top: 10px; font-size: 12px; color: var(--danger); }
@media (max-width: 720px) {
  .dc-panel { font-size: 16px; }
  .dc-calendar { width: 320px; }
  .dc-day { height: 36px; }
  .dc-date-field { max-width: 100%; }
}
/* Обёртка сохраняет прежнюю flex/grid геометрию фильтров. */
.camp-filter-group > .dc-date-field { flex: 0 1 154px; }
.camp-filter-group .dc-date-input { width: 100%; }
#an-card .sa-calendar .dc-date-input, .sa-calendar .dc-date-input {
  border-radius: var(--r-md); height: 36px; min-height: 36px;
  padding: 6px 40px 6px 8px; font: 14px var(--font); color: var(--text);
}
.sa-select-label .dc-select { border-radius: var(--r-md); padding-right: 36px; }
@media (max-width: 720px) {
  .camp-filter-group > .dc-date-field { flex: 1 1 0; width: auto; min-width: 0; }
  .camp-filter-group .dc-date-input { width: 100%; font-size: 16px; padding-left: 6px; }
  #an-card .sa-calendar .dc-date-field { width: 100%; }
  #an-card .sa-calendar .dc-date-input, .sa-calendar .dc-date-input { width: 100%; font-size: 16px; padding: 6px 36px 6px 6px; }
  .sa-select-label .dc-select { font-size: 16px; }
}
.dc-calendar-end { display: flex; gap: 4px; margin-left: auto; }
/* Поздние background shorthand локальных экранов не стирают общий значок. */
:root { --select-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5l5-5' fill='none' stroke='%23666b75' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); }
select.dc-select, .sa-select-label select.dc-select, .funnel-field select.dc-select {
  background-image: var(--select-chevron); background-repeat: no-repeat;
  background-position: right 13px center; padding-right: 36px;
}

/* Фото готовится локально, принятый сервером файл заменяется после успеха. */
.pub-crop-backdrop { z-index: 200; }
.pub-crop-modal { max-width: 600px; max-height: calc(100dvh - 32px); overflow: auto; }
.pub-crop-modal > .field-note { margin: 0 0 16px; overflow-wrap: anywhere; }
.pub-crop-stage { display: flex; justify-content: center; align-items: center; height: min(320px, 38dvh); background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--r-md); overflow: hidden; }
.pub-crop-stage canvas { display: block; max-width: 100%; max-height: 100%; object-fit: contain; }
.pub-crop-controls { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin: 16px 0; }
.pub-crop-controls .field { margin: 0; min-width: 0; }
.pub-crop-controls input[type=range] { width: 100%; padding: 8px 0; accent-color: var(--accent); cursor: pointer; border: 0; box-shadow: none; min-height: 36px; }
.pub-crop-controls input:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.pub-crop-ratios { width: 100%; }
.pub-crop-ratios .segmented-item { flex: 1; padding-inline: 10px; }
.pub-item [data-pub-item-action="remove"] { display: inline-flex; }
#pub-add-files { align-self: flex-start; }
.pub-compose[data-kind=story] .pub-carousel-nav { bottom: 10px; }
.pub-compose[data-kind=story] .pub-post-media:has(> video.pub-post-img) .pub-carousel-nav { bottom: 64px; }
.pub-compose[data-kind=story] .pub-post-media:has(> video.pub-post-img) .pub-story-reply { bottom: 108px; }
@media (max-width: 600px) {
  .pub-crop-backdrop { padding: 8px; }
  .pub-crop-modal { padding: 18px 16px; max-height: calc(100dvh - 16px); }
  .pub-crop-controls { gap: 10px; }
  .pub-crop-controls > .field:first-child { grid-column: 1 / -1; }
  .pub-crop-ratios .segmented-item { min-height: 40px; }
  .pub-items .pub-item { flex-wrap: wrap; }
  .pub-items .pub-item-body { min-width: 150px; }
}

/* Кадры карусели и Stories добавляются в компактную ленту рядом с превью. */
.pub-frame-sidebar { min-width: 0; width: 220px; display: flex; flex-direction: column; gap: 12px; }
.pub-frame-sidebar:not(:has(.pub-items:not([hidden]))):not(:has(#pub-add-files:not([hidden]))) { display: none; }
.pub-compose:has(.pub-frame-sidebar:not(:empty)) { gap: 20px; align-items: flex-start; }
.pub-compose > .pub-post { flex: 0 1 470px; min-width: 0; }
.pub-items-series { gap: 12px; }
.pub-frame-strip { display: flex; flex-wrap: wrap; gap: 8px; }
.pub-frame-choice { display: flex; flex-direction: column; gap: 5px; width: 98px; padding: 5px; border: 1px solid var(--border); border-radius: var(--r-md); background: var(--surface); color: var(--text); font: inherit; font-size: 12px; cursor: pointer; }
.pub-frame-choice img, .pub-frame-choice video { width: 100%; height: 100px; object-fit: cover; border-radius: var(--r-sm); pointer-events: none; }
.pub-frame-choice.is-active { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); color: var(--accent); }
.pub-frame-choice:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.pub-frame-tools { display: flex; flex-direction: column; gap: 8px; }
.pub-frame-tools p { margin: 0; }
.pub-frame-actions { display: flex; flex-wrap: wrap; gap: 6px; }
@media (max-width: 700px) {
  .pub-compose { flex-direction: column; }
  .pub-compose > .pub-post { flex: none; }
  .pub-frame-sidebar { width: 100%; }
  .pub-frame-strip { flex-wrap: nowrap; overflow-x: auto; padding: 3px; }
  .pub-frame-strip > div { flex: none; }
}

.pub-compose:has(.pub-items:not(.pub-items-series):not([hidden])) { flex-direction: column; }
.pub-frame-sidebar:has(.pub-items:not(.pub-items-series):not([hidden])) { width: 100%; max-width: 470px; }

/* Как в YouTube/TikTok: настройки слева, контент справа. */
.pub-editor-layout { display: grid; grid-template-columns: minmax(240px, 280px) minmax(0, 1fr); gap: 24px; align-items: start; }
.pub-settings, .pub-content { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.pub-settings .pub-kind { width: 100%; }
.pub-settings .pub-kind .segmented-item { flex: 1; padding-inline: 6px; }
.pub-settings .pub-reel-options { max-width: 100%; gap: 12px; }
.pub-settings #pub-reel-mode { align-self: flex-start; }
.pub-settings .pub-cover-tools { flex-direction: column; align-items: stretch; gap: 10px; }
.pub-settings .pub-cover-tools input[type=number] { width: 100%; }
.pub-cover-row { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 12px; align-items: start; }
.pub-cover-row .field { min-width: 0; }
.pub-cover-upload { display: flex; flex-direction: column; gap: 8px; min-width: 0; padding-top: 32px; }
.pub-cover-upload #pub-cover-add { min-height: 40px; width: 100%; }
.pub-settings .pub-cover-tools .field-note { flex-basis: auto; margin: 0; }
.pub-settings .pub-post-comments { border-top: 1px solid var(--border); padding: 16px 0 0; }
.pub-settings .pub-post-comment-row { display: flex; flex-direction: column; gap: 6px; }
.pub-settings .pub-post-comment-name { display: none; }
.pub-settings .pub-post-comment-field { min-height: 90px; padding: 10px 12px; border: 1px solid var(--border); border-radius: var(--r-md); background: var(--surface); }
.pub-settings .pub-post-comments-note { margin-bottom: 10px; }
.pub-content .pub-frame-sidebar { width: 168px; flex: 0 0 168px; }
.pub-content .pub-frame-choice { width: 78px; }
.pub-content .pub-frame-choice img, .pub-content .pub-frame-choice video { height: 80px; }
.pub-content .pub-compose { gap: 16px; }
@media (max-width: 1050px) {
  .pub-editor-layout { grid-template-columns: minmax(220px, 250px) minmax(0, 1fr); gap: 20px; }
  .pub-content .pub-compose { flex-direction: column; }
  .pub-content .pub-compose > .pub-post { flex: none; }
  .pub-content .pub-frame-sidebar { width: 100%; flex: none; }
  .pub-content .pub-frame-strip { flex-wrap: nowrap; overflow-x: auto; padding: 3px; }
  .pub-content .pub-frame-strip > div { flex: none; }
}
@media (max-width: 760px) {
  .pub-editor-layout { grid-template-columns: minmax(0, 1fr); gap: 20px; }
  .pub-settings { gap: 12px; }
}
.pub-compose:has(.pub-items:not(.pub-items-series):not([hidden])) > .pub-post { flex: none; }

/* Вертикальный контент использует свободное место справа, настройки шире. */
@media (min-width: 761px) {
  .pub-editor-layout:has(.pub-compose[data-kind=reel]),
  .pub-editor-layout:has(.pub-compose[data-kind=story]) {
    grid-template-columns: minmax(300px, 1fr) minmax(0, 1.15fr);
    gap: 32px;
  }
  .pub-content .pub-compose[data-kind=reel],
  .pub-content .pub-compose[data-kind=story] { justify-content: flex-end; }
  .pub-content .pub-compose[data-kind=reel]:has(.pub-items:not(.pub-items-series):not([hidden])) { align-items: flex-end; }
}
@media (min-width: 761px) and (max-width: 1050px) {
  .pub-content .pub-compose[data-kind=reel],
  .pub-content .pub-compose[data-kind=story] { align-items: flex-end; }
}

/* Диагностика медиа: спокойное примечание и компактный результат. */
.pub-item-notice { color: var(--muted); font-size: 12px; line-height: 1.5; }
.pub-item-notice summary, .pub-check-result summary { cursor: pointer; }
.pub-item-notice p { margin: 8px 0; }
.pub-check-result > p { margin: 0 0 8px; }
.pub-check-result > button { margin-top: 10px; }
.pub-check-details { margin-top: 8px; white-space: pre-wrap; overflow-wrap: anywhere; }

/* Карточка публикации: фото и видео занимают одинаковые ячейки. */
.pub-detail-items { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 12px; }
.pub-detail-items .pub-detail-item { width: 100%; min-width: 0; }
.pub-detail-items .pub-detail-item .pub-detail-thumb { width: 100%; height: auto; aspect-ratio: 4 / 5; max-height: none; object-fit: contain; background: var(--border-2); }
.pub-detail-items .pub-detail-item-meta { white-space: normal; overflow-wrap: anywhere; }

/* Публикация сейчас и однократный выбор времени. */
.pub-publish-split { display: inline-flex; align-items: stretch; }
.pub-publish-split[hidden] { display: none; }
.pub-publish-split > .btn:first-child { border-top-right-radius: 0; border-bottom-right-radius: 0; }
.pub-publish-split > .pub-publish-arrow { border-top-left-radius: 0; border-bottom-left-radius: 0; min-width: 38px; padding-inline: 10px; border-left: 1px solid rgba(255,255,255,.28); }
.pub-publish-arrow svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.8; }
.pub-publish-menu { z-index: 75; }
.pub-schedule-modal .modal-actions { flex-wrap: wrap; margin-top: 20px; }
.pub-schedule-modal .modal-actions .btn-primary { white-space: normal; text-align: center; }
.pub-schedule-modal .field-error { margin-top: 12px; }
.pub-tile-tag { max-width: calc(100% - 16px); white-space: normal; }

/* Ход публикации обновляется вместе с существующим опросом карточки. */
.pub-detail-progress {
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--ivory);
  overflow-wrap: anywhere;
}
.pub-detail-progress-stage { font-size: 14px; font-weight: 600; line-height: 1.5; color: var(--text); }
.pub-detail-progress-time { margin: 4px 0 0; font-size: 12.5px; line-height: 1.5; color: var(--text-3); font-variant-numeric: tabular-nums; }
.pub-detail-progress-note { margin: 8px 0 0; font-size: 13px; line-height: 1.5; color: var(--text-2); }
.pub-detail-error.is-prepared { background: var(--ivory); border-color: var(--border); color: var(--text-2); }
.pub-detail-error.is-prepared .pub-detail-error-text { color: var(--text-2); }

/* Этапы отправки: текущая операция, без вымышленного процента Meta. */
.pub-progress-steps { display: flex; flex-wrap: wrap; gap: 8px 18px; list-style: none; padding: 0; margin: 0 0 14px; font-size: 12px; color: var(--text-3); }
.pub-progress-steps li { display: flex; align-items: center; gap: 6px; }
.pub-progress-steps li > span { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; flex: 0 0 22px; border-radius: var(--r-pill); border: 1px solid var(--border); }
.pub-progress-steps .is-current { color: var(--accent); font-weight: 600; }
.pub-progress-steps .is-current > span { color: white; background: var(--accent); border-color: var(--accent); }
.pub-progress-steps .is-done { color: var(--text-2); }
.pub-progress-steps .is-done > span { color: var(--accent); border-color: var(--accent); }
.pub-detail-progress-expectation { margin: 8px 0; font-size: 13px; line-height: 1.6; color: var(--text-2); max-width: 72ch; }

/* Published carousel: compact preview and distinct slide navigation. */
.pubv:not(.fxv) { height: min(720px, calc(100dvh - 64px)); max-width: min(1000px, 100%); }
.pubv:not(.fxv) .pubv-side { flex-basis: 360px; }
.pubv-media { position: relative; }
.pubv-slide-controls { position: absolute; bottom: 16px; left: 50%; transform: translateX(-50%); display: flex; align-items: center; gap: 12px; padding: 5px; border-radius: var(--r-pill); background: var(--surface); color: var(--text); box-shadow: var(--shadow-sm); }
.pubv-slide-controls .btn { min-width: 40px; }
.pubv-media:has(video) .pubv-slide-controls { bottom: 60px; }
.pub-detail-items { grid-template-columns: repeat(auto-fill, minmax(140px, 180px)); }
.pub-detail-thumb.pub-tile-thumb-empty { display: flex; align-items: center; justify-content: center; text-align: center; padding: 16px; }
@media(max-width:600px) { .pubv:not(.fxv) { height: calc(100dvh - 24px); } .pubv:not(.fxv) .pubv-side { flex-basis: auto; } .pubv:not(.fxv) .pubv-media { height: 48dvh; width: 100%; } .pub-detail-items { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* Текст своей идеи для чтения во время записи. */
.fx-own-transcript { width: 100%; min-height: 320px; flex: 1; font-size: 16px; line-height: 1.7; resize: vertical; }

/* Telegram connection labels share the native select value and keyboard control. */
.dc-bot-field { display: block; position: relative; width: 100%; min-width: 0; }
.dc-bot-field > select { width: 100%; min-height: 64px; color: transparent !important; }
.dc-bot-label { position: absolute; inset: 0 36px 0 14px; pointer-events: none; display: flex; align-items: center; gap: 10px; }
.dc-bot-logo { display: inline-grid; place-items: center; flex: 0 0 30px; width: 30px; height: 30px; border-radius: var(--r-sm); background: var(--accent); color: var(--surface); }
.dc-bot-text { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 4px; min-width: 0; overflow-wrap: anywhere; line-height: 1.35; }
.dc-bot-username { color: var(--text-2); font-size: .9em; }
.dc-bot-option { display: flex; align-items: center; gap: 10px; border-radius: var(--r-sm); }
.dc-bot-option.is-selected { background: var(--accent-soft); color: var(--accent); }

/* Редактор обработки STT продолжает общие поля и кнопки настроек. */
.fx-settings-layout { display: grid; grid-template-columns: minmax(0, .86fr) minmax(0, 1.14fr); gap: 30px; align-items: start; }
.fx-settings-layout > .fx-settings { min-width: 0; max-width: none; }
.fx-settings-layout .fx-thresholds { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.fx-prompt { min-width: 0; border-left: 1px solid var(--border); padding-left: 30px; }
.fx-prompt .fx-h3 { margin: 0; }
.fx-prompt-heading { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 8px; }
.fx-prompt-model { color: var(--text-2); background: var(--canvas); border-radius: var(--r-sm); padding: 4px 9px; font-size: 12px; overflow-wrap: anywhere; }
.fx-prompt-input { width: 100%; resize: vertical; line-height: 1.65; margin-top: 8px; }
.fx-prompt-actions { display: flex; gap: 8px; justify-content: flex-end; margin-top: 16px; }
.fx-prompt-restore { margin-top: 10px; }
.fx-prompt-test { border-top: 1px solid var(--border); margin-top: 24px; padding-top: 24px; }
.fx-prompt-test > .fx-h3 { margin-bottom: 16px; }
.fx-prompt-test .select { margin-top: 8px; width: 100%; min-width: 0; }
.fx-prompt-test-actions { display: flex; justify-content: space-between; gap: 8px; flex-wrap: wrap; margin: 14px 0 18px; }
.fx-prompt-source { margin-bottom: 20px; }
.fx-prompt-source-text { color: var(--text); white-space: pre-wrap; overflow-wrap: anywhere; margin-top: 12px; line-height: 1.65; }
.fx-prompt-result-title { font-size: 14px; margin: 0; }
.fx-prompt-result { min-height: 120px; border: 1px solid var(--border); border-radius: var(--r-md); padding: 16px; margin-top: 10px; overflow-wrap: anywhere; line-height: 1.7; }
.fx-prompt-result p { margin: 0 0 14px; white-space: pre-wrap; }
.fx-prompt-result p:last-child { margin-bottom: 0; }
@media (max-width: 900px) {
  .fx-settings-layout { grid-template-columns: 1fr; gap: 28px; }
  .fx-prompt { grid-row: 1; border-left: 0; padding-left: 0; }
  .fx-settings-layout > .fx-settings { border-top: 1px solid var(--border); padding-top: 20px; }
}
@media (max-width: 500px) {
  .fx-settings-layout .fx-thresholds { grid-template-columns: 1fr; }
  .fx-prompt-input { font-size: 16px; }
  .fx-prompt-test-actions .btn { min-height: 44px; }
  .fx-prompt-test-actions { justify-content: flex-end; }
  .fx-prompt-test-actions .btn:first-child { margin-right: auto; }
}

/* Lifted frame and insertion gap, consistent with the Factory board. */
.pub-frame-sort-hint { margin: 0; }
.pub-frame-tile { position: relative; flex: none; }
.pub-frame-tile[hidden] { display: none; }
.pub-frame-tile .pub-frame-choice { cursor: grab; user-select: none; }
.pub-frame-handle { position: absolute; top: 6px; right: 6px; display: grid; place-items: center; width: 28px; height: 28px; padding: 0; border: 1px solid var(--border); border-radius: var(--r-sm); background: var(--surface); color: var(--text-2); box-shadow: var(--shadow-sm); cursor: grab; touch-action: none; }
.pub-frame-handle:hover { background: var(--surface-2); color: var(--text); }
.pub-frame-handle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.pub-frame-handle:disabled { cursor: default; opacity: .5; }
.pub-frame-placeholder { flex: none; border: 1px dashed var(--accent); border-radius: var(--r-md); background: var(--accent-soft); }
.pub-frame-ghost { position: fixed; z-index: 10000; pointer-events: none; transform: rotate(2deg); filter: drop-shadow(0 12px 18px rgba(0,0,0,.16)); }
.pub-frame-ghost .pub-frame-choice { width: 100%; }
.pub-frame-ghost .pub-frame-choice img, .pub-frame-ghost .pub-frame-choice video { height: 80px; }
.pub-frame-drag-active, .pub-frame-drag-active * { cursor: grabbing !important; user-select: none !important; }
@media (max-width: 700px) { .pub-frame-handle { width: 44px; height: 44px; } }
@media (prefers-reduced-motion: reduce) { .pub-frame-ghost { transform: none; } }

.fx-transcript-heading {position:relative;display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:12px;}
.fx-transcript-heading h3 {margin:0;}
.fx-transcript-help {position:static;font-size:13px;cursor:auto;}
.fx-transcript-help summary {display:grid;place-items:center;width:28px;height:28px;border:1px solid var(--border);border-radius:var(--r-pill);color:var(--text-2);cursor:pointer;list-style:none;}
.fx-transcript-help summary::-webkit-details-marker {display:none;}
.fx-transcript-help summary:hover,.fx-transcript-help[open] summary {background:var(--canvas);}
.fx-transcript-help-content {position:absolute;z-index:6;right:0;top:calc(100% + 6px);width:min(280px,100%);padding:12px 16px;border:1px solid var(--border);border-radius:var(--r-md);box-shadow:var(--shadow-md);background:var(--surface);font-weight:400;line-height:1.6;}
.fx-transcript-help-content p {margin:0 0 8px;}
.fx-transcript-help-content p:last-child {margin:0;}
.fx-own-transcript {white-space:pre-wrap;overflow-wrap:anywhere;cursor:text;}
.fx-own-transcript:empty::before {content:attr(data-placeholder);color:var(--text-3);pointer-events:none;}

@media (max-width: 560px) {
  .chat-person-tabs { left: 14px; max-width: calc(100% - 26px); }
  .chat-person-tabs .segmented-item { padding: 0 10px; min-height: 44px; }
  .chat-head:has(.chat-person-tabs:not([hidden])) { min-height: 108px; padding-bottom: 59px; }
}
