/*
 * ЭТОЧАТБОТ — глобальные стили
 * Tailwind CDN подключается в layout-ах.
 * Здесь — только кастомные override'ы.
 */

/* Системный шрифт клиентского устройства:
 * Mac/iOS → San Francisco, Windows → Segoe UI, Android → Roboto,
 * Linux → Cantarell/Ubuntu, эмодзи — нативные шрифты ОС.
 * Это даёт нативное ощущение ЛК на каждой платформе без подгрузки веб-шрифтов. */
html, body, button, input, select, textarea, optgroup {
  font-family:
    -apple-system,
    BlinkMacSystemFont,
    "SF Pro Text",
    "Segoe UI",
    Roboto,
    Oxygen,
    Ubuntu,
    Cantarell,
    "Helvetica Neue",
    Arial,
    "Noto Sans",
    sans-serif,
    "Apple Color Emoji",
    "Segoe UI Emoji",
    "Segoe UI Symbol",
    "Noto Color Emoji";
  font-feature-settings: "cv02", "cv03", "cv04", "cv11";
}

/* Плавный переход страниц */
*, *::before, *::after {
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

/* Скрыть спиннер числовых inputs в Firefox */
input[type=number] {
  -moz-appearance: textfield;
}

/* Убрать стрелки числовых inputs в Chrome/Safari */
input[type=number]::-webkit-outer-spin-button,
input[type=number]::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

/* Анимация спиннера кнопок */
@keyframes spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}
.animate-spin {
  animation: spin 1s linear infinite;
}

/* Global text tone override requested by design */
.text-gray-600 {
  color: #0c0c0c;
}

/* Global background override requested by design */
.bg-white {
  background-color: #fafafa;
}

/* Interactive controls: always show pointer for clickable buttons/links */
button:not(:disabled),
[role="button"]:not([aria-disabled="true"]),
a[href] {
  cursor: pointer;
}

/*
 * ---------------------------------------------------------------------------
 * Floating tooltips (`[data-tip]`).
 *
 * Рендерятся через JS в body с `position: fixed`, чтобы гарантированно
 * не подрезаться overflow-контейнерами (напр. scroll-панелью сайдбара).
 * См. public/assets/js/panel.js, блок `initFloatingTooltips`.
 * ---------------------------------------------------------------------------
 */
.tooltip-floating {
  position: fixed;
  z-index: 9999;
  pointer-events: none;
  background: #111827;
  color: #ffffff;
  font-size: 12px;
  font-weight: 500;
  line-height: 1.2;
  padding: 7px 10px;
  border-radius: 8px;
  white-space: nowrap;
  box-shadow: 0 6px 16px rgba(0,0,0,0.18);
  opacity: 0;
  transform: translateX(-4px);
  transition: opacity .14s ease, transform .14s ease;
  max-width: 280px;
}
.tooltip-floating.is-visible {
  opacity: 1;
  transform: translateX(0);
}
.tooltip-floating::before {
  content: '';
  position: absolute;
  top: 50%;
  right: 100%;
  transform: translateY(-50%);
  border: 5px solid transparent;
  border-right-color: #111827;
  border-left: 0;
}
.tooltip-floating.is-below::before {
  top: 0;
  right: 50%;
  transform: translate(50%, -100%);
  border: 5px solid transparent;
  border-bottom-color: #111827;
  border-top: 0;
}

/*
 * Font Awesome icons rendered via <i class="fa-…"> use a web-font glyph, so
 * Tailwind's size-* utilities (width/height) don't control the actual icon
 * size — font-size does. Bring the two back in sync so existing markup
 * (`<i class="fa-solid fa-house size-5">`) renders predictably.
 */
i.fa-solid, i.fa-regular, i.fa-brands, i.fa-light, i.fa-thin, i.fa-duotone {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
}
i.fa-solid.size-3, i.fa-regular.size-3, i.fa-brands.size-3,
i.fa-light.size-3, i.fa-thin.size-3, i.fa-duotone.size-3 { font-size: 12px; }
i.fa-solid.size-3\.5, i.fa-regular.size-3\.5, i.fa-brands.size-3\.5,
i.fa-light.size-3\.5, i.fa-thin.size-3\.5, i.fa-duotone.size-3\.5 { font-size: 13px; }
i.fa-solid.size-4, i.fa-regular.size-4, i.fa-brands.size-4,
i.fa-light.size-4, i.fa-thin.size-4, i.fa-duotone.size-4 { font-size: 14px; }
i.fa-solid.size-5, i.fa-regular.size-5, i.fa-brands.size-5,
i.fa-light.size-5, i.fa-thin.size-5, i.fa-duotone.size-5 { font-size: 17px; }
i.fa-solid.size-6, i.fa-regular.size-6, i.fa-brands.size-6,
i.fa-light.size-6, i.fa-thin.size-6, i.fa-duotone.size-6 { font-size: 19px; }
i.fa-solid.size-7, i.fa-regular.size-7, i.fa-brands.size-7,
i.fa-light.size-7, i.fa-thin.size-7, i.fa-duotone.size-7 { font-size: 22px; }
i.fa-solid.size-8, i.fa-regular.size-8, i.fa-brands.size-8,
i.fa-light.size-8, i.fa-thin.size-8, i.fa-duotone.size-8 { font-size: 26px; }

/*
 * ---------------------------------------------------------------------------
 * daterangepicker (jquery) — перекраска под фирменные цвета ЛК.
 * Библиотека рендерит свой UI и ingнорирует Tailwind; здесь мы мапим все
 * ключевые состояния (active, in-range, hover, preset rangbuttons, apply)
 * на CSS-переменные --color-brand-*, которые уже прокинуты в <html> через
 * BotTheme::cssVars(). Поэтому пикер автоматически будет следовать активной
 * теме, где бы он ни использовался (stats, broadcasts, conversations и т.д.).
 * ---------------------------------------------------------------------------
 */
.daterangepicker {
  border: 1px solid #e5e7eb;
  border-radius: 14px;
  box-shadow: 0 12px 32px rgba(17, 24, 39, .08);
  font-family: inherit;
  color: #111827;
}
.daterangepicker:before, .daterangepicker:after { display: none; }
.daterangepicker .calendar-table {
  border-radius: 10px;
  border: 0;
  background: transparent;
}
.daterangepicker .calendar-table th,
.daterangepicker .calendar-table td {
  border-radius: 8px;
  color: #111827;
}
.daterangepicker td.available:hover,
.daterangepicker th.available:hover {
  background: var(--color-brand-50, #eef2ff);
  color: var(--color-brand-700, #1e3a8a);
  border-color: transparent;
}
.daterangepicker td.in-range {
  background: var(--color-brand-50, #eef2ff);
  color: var(--color-brand-700, #1e3a8a);
}
.daterangepicker td.active,
.daterangepicker td.active:hover,
.daterangepicker td.start-date,
.daterangepicker td.end-date {
  background: var(--color-brand-600, #1d4ed8);
  color: #ffffff;
  border-color: transparent;
}
.daterangepicker td.start-date.end-date {
  border-radius: 8px;
}
.daterangepicker td.start-date { border-top-left-radius: 8px; border-bottom-left-radius: 8px; }
.daterangepicker td.end-date   { border-top-right-radius: 8px; border-bottom-right-radius: 8px; }
.daterangepicker td.week { color: #9ca3af; font-weight: 500; }
.daterangepicker td.off,
.daterangepicker td.off.in-range,
.daterangepicker td.off.start-date,
.daterangepicker td.off.end-date {
  background: transparent;
  color: #cbd5e1;
}
.daterangepicker .ranges ul { padding: 6px; }
.daterangepicker .ranges li {
  border-radius: 8px;
  color: #111827;
  padding: 7px 10px;
  font-size: 13px;
  transition: background .12s ease, color .12s ease;
}
.daterangepicker .ranges li:hover {
  background: var(--color-brand-50, #eef2ff);
  color: var(--color-brand-700, #1e3a8a);
}
.daterangepicker .ranges li.active {
  background: var(--color-brand-600, #1d4ed8);
  color: #ffffff;
}
.daterangepicker .drp-buttons .btn {
  border-radius: 8px;
  font-weight: 600;
  padding: 6px 12px;
  border: 1px solid transparent;
}
.daterangepicker .drp-buttons .btn.btn-primary,
.daterangepicker .drp-buttons .applyBtn {
  background: var(--color-brand-700, #1d4ed8);
  color: #ffffff;
}
.daterangepicker .drp-buttons .btn.btn-primary:hover,
.daterangepicker .drp-buttons .applyBtn:hover {
  background: var(--color-brand-600, #2563eb);
}
.daterangepicker .drp-buttons .btn.btn-default,
.daterangepicker .drp-buttons .cancelBtn {
  background: #ffffff;
  color: #111827;
  border-color: #e5e7eb;
}
.daterangepicker .drp-buttons .btn.btn-default:hover,
.daterangepicker .drp-buttons .cancelBtn:hover {
  background: #f9fafb;
}
.daterangepicker select.monthselect,
.daterangepicker select.yearselect,
.daterangepicker select.hourselect,
.daterangepicker select.minuteselect,
.daterangepicker select.secondselect,
.daterangepicker select.ampmselect {
  border: 1px solid #e5e7eb;
  border-radius: 6px;
  padding: 3px 6px;
  color: #111827;
  background: #ffffff;
}
.daterangepicker select.monthselect:focus,
.daterangepicker select.yearselect:focus {
  outline: 2px solid var(--color-brand-500, #3b82f6);
  outline-offset: 1px;
  border-color: transparent;
}
.daterangepicker .drp-selected { color: #6b7280; font-size: 12px; }

/*
 * ---------------------------------------------------------------------------
 * Responsive baseline — максимальная совместимость с телефонами, планшетами
 * и компьютерами разных размеров. Не затрагивает конструктор автоматизации
 * (там используются абсолютные координаты блоков на canvas).
 * ---------------------------------------------------------------------------
 */

/* Никогда не даём таблицам, предварительным просмотрам и коду растягивать
 * страницу в ширину на узких экранах. Таблицы — всегда со скроллом. */
@media (max-width: 767px) {
  main table {
    display: block;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }
}

/* Картинки по умолчанию отзывчивые. */
main img, main video { max-width: 100%; height: auto; }

/* Длинные строки (emails, токены, ссылки) не должны разрывать layout. */
.break-anywhere { overflow-wrap: anywhere; word-break: break-word; }

/* На узких экранах плотнее паддинги основного контейнера. */
@media (max-width: 639px) {
  main .px-4, main .sm\:px-6, main .lg\:px-8 { padding-left: 14px; padding-right: 14px; }
  /* Крупные H1 — чуть меньше, чтобы не переполнять экран. */
  main h1.text-2xl, main h1.text-3xl { font-size: 20px; line-height: 1.25; }
  main .text-2xl { font-size: 20px; }
  main .text-3xl { font-size: 22px; }
}

/* Хлебные крошки — прячем лишние элементы на совсем узких экранах. */
@media (max-width: 380px) {
  nav[aria-label="Breadcrumb"] li:not(:last-child):not(:first-child) { display: none; }
}

/*
 * Страница диалогов (conversations / channels) — мобильный UX.
 * На мобильных устройствах, когда открыт диалог, сайдбар со списком скрыт
 * (`.dialogs-sidebar.hidden md:flex`). Показываем кнопку «←» в заголовке чата
 * — она возвращает к списку без перезагрузки.
 */
.chat-root { min-height: 0; }
@media (max-width: 767px) {
  .chat-root .dialogs-sidebar { width: 100% !important; }
  .chat-root #chat-panel .compose-wrap { margin-left: 6px; margin-right: 6px; }
  .chat-root #meta-panel { padding-left: 12px; padding-right: 12px; }
}

/* Аккуратные чипсы-фильтры: единое состояние активного фильтра. */
.filter-chip.active-chip {
  background-color: var(--color-brand-600, #0057cc);
  color: #ffffff;
}
.filter-chip.active-chip span { color: rgba(255,255,255,0.75); }

/* Группа тегов: плавное разворачивание. */
[data-tag-extra].hidden { display: none !important; }

/* ---------------------------------------------------------------------------
 * Мобильный UX: tap-highlight, iOS-zoom-on-focus, safe-area, viewport.
 * Эти правила применяются глобально и дают «нативное» ощущение на iPhone/iPad
 * и Android без дополнительной разметки.
 * --------------------------------------------------------------------------- */

/* Отключаем синее/серое «пятно» тапа на тач-устройствах — оно выглядит дёшево.
 * Focus-visible ring остаётся рабочим (используем outline, не tap-highlight). */
html {
  -webkit-tap-highlight-color: transparent;
}

/* iOS Safari увеличивает масштаб при фокусе на input c font-size < 16px.
 * Минимум 16px для всех интерактивных полей убирает этот прыжок. Визуально —
 * сохраняем класс text-sm через line-height, чтобы не ломать макет. */
@media (max-width: 767px) {
  input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="file"]),
  select,
  textarea {
    font-size: 16px !important;
  }
}

/* Safe-area для айфонов с нотчем/Dynamic Island и Android 13+ edge-to-edge.
 * В standalone-режиме PWA статус-бар прозрачный — без этого кнопка меню
 * «прилипает» к самой верхушке. Применяем только там, где это реально нужно:
 * top — мобильный топбар; bottom — input-бар чата; inline — общий контент. */
@supports (padding-top: env(safe-area-inset-top)) {
  /* Мобильный топбар (hamburger+лого) в panel-layout-е — добавляем отступ сверху. */
  body > div.flex > div.flex > #ec-panel-mobile-topbar,
  body > div.flex > div.flex > div.h-14.lg\:hidden {
    padding-top: env(safe-area-inset-top);
    height: calc(3.5rem + env(safe-area-inset-top));
  }
  /* В fullscreen-режиме (чат) safe-area на уровне main — обеспечивается
   * внутренними правилами .chat-root ниже. */
}

/* 100dvh на iOS: даже в обычных браузерных окнах Chrome/Safari URL-бар
 * прячется и 100vh «прыгает». dvh устраняет это. Где мы явно используем
 * 100vh/h-screen — превращаем в dvh. */
.h-dvh { height: 100dvh; }
.min-h-dvh { min-height: 100dvh; }
.max-h-dvh { max-height: 100dvh; }

/* Чтобы `<body class="h-full">` + `<html class="h-full">` корректно вёл себя
 * на iOS (не добавлял прокрутку из-за адресной строки) — используем dvh. */
@media (max-width: 767px) {
  html.h-full { height: 100dvh; }
  body.h-full { height: 100dvh; }
}

/* ---------------------------------------------------------------------------
 * Страница диалогов — доп. мобильные правила.
 * Чат с композером должен корректно вести себя при появлении экранной
 * клавиатуры, учитывать safe-area-inset-bottom (home indicator) и не
 * скроллить страницу за пределы видимой области.
 * --------------------------------------------------------------------------- */
@media (max-width: 767px) {
  /* Контейнер чата НИЧЕМ не форсим по высоте — на мобильном он живёт
   * внутри <main class="min-h-0 flex-1 overflow-hidden">. Любая попытка
   * выставить .chat-root { min-height: 100dvh } раздувала #dialogs-root
   * за пределы main, и main с overflow:hidden обрезал НИЖНИЕ ~50–80 px
   * (композер уезжал из видимой области, а на стороне списка — посадил
   * последний диалог под home-indicator). h-full уже даёт корректную
   * высоту, а клавиатуру обрабатываем через visualViewport (см.
   * initMobileViewport в dialogs_v4.php). */

  /* Composer-бар — sticky снизу с учётом home-indicator'а. Без этого на
   * iPhone 14/15/16 нижняя кромка кнопки «отправить» съедается. */
  .chat-root .compose-wrap {
    padding-bottom: calc(env(safe-area-inset-bottom, 0px) + 4px);
  }

  /* Шапка чата — чуть плотнее на маленьких экранах. */
  .chat-root #chat-header { padding-top: 8px; padding-bottom: 8px; }

  body.ec-panel-fullscreen.ec-v4-mobile-chat-active #ec-panel-mobile-topbar {
    display: none !important;
  }

  /* Мобильная версия списка диалогов не должна «жевать» аватарки. */
  .chat-root .dialogs-sidebar .dialog-row { min-height: 56px; }
}

/* Компактные tap-targets: все интерактивные элементы в админке — не меньше
 * 36px по вертикали (WCAG минимум 44px, но в плотной admin-UI допустим 36px
 * со штатной пикcелной сеткой Tailwind). Применяется только к явно отмеченным
 * иконочным кнопкам, чтобы не ломать inline-ссылки в тексте. */
@media (max-width: 767px) {
  button.size-8, a.size-8 { min-height: 32px; min-width: 32px; }
  button.size-9, a.size-9 { min-height: 36px; min-width: 36px; }
  button.size-10, a.size-10 { min-height: 40px; min-width: 40px; }
}

/* Убираем overscroll-bounce в чатовом скролле и на фиксированных layout-ах —
 * это частый источник «страница подпрыгивает, когда дошёл до низа» на iOS. */
.no-overscroll { overscroll-behavior: contain; }
.chat-root, .chat-root > main, #messages-area, #dialogs-list { overscroll-behavior: contain; }

/* ---------------------------------------------------------------------------
 * Универсальная модалка приложения (<dialog class="ec-modal">).
 *
 * Проблема: в iOS Safari / WebKit и в некоторых Android-браузерах нативный
 *   <dialog>[open] при showModal() не всегда получает корректные
 *   position/inset/margin — из-за CSS-контейнеров с transform/overflow-hidden
 *   в layout-е модалка «улетает» в левый/правый верхний угол.
 * Решение: задаём надёжные геометрические правила на явный класс .ec-modal,
 *   чтобы ни один родительский stacking context не мог сломать центровку.
 * --------------------------------------------------------------------------- */
dialog.ec-modal[open] {
  position: fixed;
  inset: 0;
  margin: auto;
  /* Защита от «улетевших» модалок: width/height не зажимаются, но и не
   * растягиваются больше экрана. Конкретные ширины остаются на Tailwind-
   * утилитах у самого <dialog>, это лишь верхняя граница. */
  max-width: min(96vw, 640px);
  max-height: min(92dvh, 92vh);
  overflow: auto;
  /* iOS momentum scroll внутри модалки. */
  -webkit-overflow-scrolling: touch;
}
dialog.ec-modal[open]::backdrop {
  background: rgba(15, 23, 42, .55);
}
/* На узких экранах делаем модалку «листом» снизу — так удобнее дотянуться
 * большим пальцем, и не страдает safe-area-inset-bottom. */
@media (max-width: 480px) {
  dialog.ec-modal[open] {
    inset: auto 0 0 0;
    margin: 0;
    width: 100%;
    max-width: 100%;
    max-height: 88dvh;
    border-bottom-left-radius: 0;
    border-bottom-right-radius: 0;
    padding-bottom: env(safe-area-inset-bottom, 0);
  }
}

/* ---------------------------------------------------------------------------
 * Плавающая панель действий в нижней части длинных форм (например, при
 * редактировании канала): кнопка «Сохранить» всегда доступна, не требует
 * прокручивать страницу до конца.
 * --------------------------------------------------------------------------- */
.ec-sticky-actions {
  position: sticky;
  bottom: calc(env(safe-area-inset-bottom, 0px) + 8px);
  z-index: 30;
}

@media (max-width: 767px) {
  body.ec-panel-fullscreen #ec-asst-fab {
    bottom: calc(env(safe-area-inset-bottom, 0px) + 5.75rem);
  }
}

/* ---------------------------------------------------------------------------
 * Личный кабинет: единый вид нативных <select>.
 *
 * 1) С классами — добавляем только снятие system appearance, SVG-стрелку
 *    и запас справа под неё (остальное остаётся на Tailwind-утилитах).
 * 2) Без атрибута class — полный «карточный» вид в фирменных нейтралях + brand focus.
 * Исключения: [multiple], .ec-select--plain (нативный вид без кастомизации).
 * --------------------------------------------------------------------------- */
body.ec-panel main select:not([multiple]):not(.ec-select--plain),
body.ec-panel dialog select:not([multiple]):not(.ec-select--plain) {
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='%2364748b' stroke-width='2'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.65rem center;
  background-size: 1rem 1rem;
  padding-inline-end: 2.25rem;
  cursor: pointer;
}

body.ec-panel main select:not([multiple]):not(.ec-select--plain):not([class]),
body.ec-panel dialog select:not([multiple]):not(.ec-select--plain):not([class]) {
  display: block;
  width: 100%;
  max-width: 100%;
  box-sizing: border-box;
  min-height: 2.5rem;
  padding: 0.5rem 2.25rem 0.5rem 0.75rem;
  font-size: 0.875rem;
  line-height: 1.25rem;
  font-weight: 500;
  color: #0f172a;
  background-color: #fafafa;
  border: 1px solid #e2e8f0;
  border-radius: 0.5rem;
  transition: border-color 0.15s ease, box-shadow 0.15s ease, background-color 0.15s ease;
}

body.ec-panel main select:not([multiple]):not(.ec-select--plain):not([class]):hover,
body.ec-panel dialog select:not([multiple]):not(.ec-select--plain):not([class]):hover {
  border-color: #cbd5e1;
  background-color: #f8fafc;
}

body.ec-panel main select:not([multiple]):not(.ec-select--plain):not([class]):focus,
body.ec-panel dialog select:not([multiple]):not(.ec-select--plain):not([class]):focus {
  outline: none;
  border-color: var(--color-brand-600, #0057cc);
  box-shadow: 0 0 0 3px rgba(0, 87, 204, 0.15);
  background-color: #fff;
}

body.ec-panel main select:not([multiple]):not(.ec-select--plain):not([class]):disabled,
body.ec-panel dialog select:not([multiple]):not(.ec-select--plain):not([class]):disabled {
  opacity: 0.55;
  cursor: not-allowed;
  background-color: #f1f5f9;
}

/* ---------------------------------------------------------------------------
 * Запас под FAB ИИ-помощника на обычных страницах ЛК.
 *
 * FAB фиксирован в правом-нижнем углу (см. partials/panel/ai_assistant.php).
 * Без отступа он перекрывает CTA в самом конце контента — заметно на
 * биллинге, обзоре бота и других «обычных» (не fullscreen) страницах.
 * Здесь добавляем нижний padding только к нашему стандартному контейнеру
 * `<main class="flex-1 overflow-y-auto"> > <div class="px-4 py-8 …">`,
 * чтобы FAB всегда оставался поверх «воздуха», а не активных элементов.
 *
 * На fullscreen-страницах (редактор сценария, ИИ-помощник сценария,
 * диалоги) FAB не подключается — там этот класс не применяется.
 * --------------------------------------------------------------------------- */
/* ────────────────────────────────────────────────────────────────────────
 * Запас под FAB ИИ-помощника — РЕШЕНИЕ #2.
 *
 * Раньше мы давали `padding-bottom: 76px+safe-area` всему main > div.
 * Это вызывало «белое пространство снизу» на коротких страницах:
 * контент заканчивается раньше main, и 76px-полоса висит пустой, ниже
 * остаётся ещё незаполненная высота main. На iOS PWA это особенно
 * заметно, потому что динамический viewport (100dvh) иногда отдаёт
 * чуть большую высоту, чем фактически видно при холодном старте, а
 * после скролла «садится» обратно — пустота сразу пропадает (это та
 * самая жалоба пользователя «потяну вверх — пустота уходит»).
 *
 * Новая логика:
 *   1. main scroll-padding-bottom — гарантирует, что при скролле к
 *      нижнему элементу под ним есть запас под FAB.
 *   2. Margin-bottom только на ПОСЛЕДНЕМ прямом потомке `main > div`.
 *      Это создаёт «воздух» под последним блоком, но не превращает
 *      пустую часть main в монолитную пустоту: высота main всё равно
 *      определяется flex-1 и совпадает с видимой областью.
 *   3. ec-page-pad-bottom — утилитный класс, который страницы могут
 *      явно ставить корневому контейнеру, если им хочется свой запас.
 * ──────────────────────────────────────────────────────────────────── */
body.ec-panel.ec-has-assistant-fab:not(.ec-panel-fullscreen) main {
  scroll-padding-bottom: calc(76px + env(safe-area-inset-bottom));
}
body.ec-panel.ec-has-assistant-fab:not(.ec-panel-fullscreen) main > div > *:last-child {
  margin-bottom: calc(60px + env(safe-area-inset-bottom));
}

@media (min-width: 1024px) {
  body.ec-panel.ec-has-assistant-fab:not(.ec-panel-fullscreen) main {
    scroll-padding-bottom: 96px;
  }
  body.ec-panel.ec-has-assistant-fab:not(.ec-panel-fullscreen) main > div > *:last-child {
    margin-bottom: 10px;
  }
}

/* ────────────────────────────────────────────────────────────────────────
 * iOS PWA: используем 100dvh для корневых контейнеров вместо 100%.
 *
 * Tailwind-классы `html.h-full` / `body.h-full` дают `height: 100%`.
 * На iOS PWA standalone это иногда округляется до большего значения,
 * чем реальный визуальный viewport (особенно на старте, до первого
 * жеста). Из-за этого возникает «белая полоса снизу» — body длиннее
 * визуального viewport'а, и под ним просвечивает фон html (gray-50).
 * 100dvh — динамическая viewport-единица: iOS пересчитывает её при
 * любом изменении видимой области (бары, клавиатура, ротация).
 * ──────────────────────────────────────────────────────────────────── */
@supports (height: 100dvh) {
  html.h-full {
    height: 100dvh;
  }
  body.ec-panel.h-full {
    height: 100dvh;
  }
}

/* ---------------------------------------------------------------------------
 * Глобальная защита от горизонтального скролла в ЛК.
 *
 * Контент кабинета не должен «утекать» вправо ни на одной странице, кроме
 * fullscreen-страниц (редактор автоматизации использует абсолютные
 * координаты canvas — там X-скролл обязан быть; диалоги имеют собственный
 * управляемый стек панелей).
 *
 * Правило аккуратное: ставим overflow-x: hidden только на самом контейнере
 * <main> на узких экранах, не трогая внутренние блоки. Sticky-элементы и
 * tooltip-popover работают через position: fixed (см. .tooltip-floating),
 * поэтому их не «обрезает». А вот случайно перетекающие за viewport
 * широкие таблицы/инпуты — теперь не дают появиться X-скроллу страницы:
 * скролл создаётся внутри элемента-обёртки (overflow-x-auto), как и
 * задумано.
 * --------------------------------------------------------------------------- */
@media (max-width: 1023.98px) {
  body.ec-panel:not(.ec-panel-fullscreen) main {
    overflow-x: hidden;
  }
  /* Tab-trap для всего documentа на iOS Safari: фиксируем body, чтобы при
   * скролле страницы не «выбрасывало» topbar из safe-area. */
  body.ec-panel {
    overscroll-behavior-x: contain;
  }
}

/* ---------------------------------------------------------------------------
 * Адаптивные «карточки» сеток на телефоне.
 *
 * Часто стандартный grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 не хватает
 * на средних мобилках (370–420px) — внутри карточек контент уплотняется и
 * текст с long-username превращается в ровную полосу. Дадим карточкам
 * (.ec-card, любой .rounded-2xl.bg-white) гарантированный break-anywhere и
 * min-width: 0, чтобы внутренний flex-min-content не растягивал родителя.
 * Это решает классическую багу «email с длинным доменом ломает карточку».
 * --------------------------------------------------------------------------- */
body.ec-panel main .rounded-2xl.bg-white,
body.ec-panel main .ec-card {
  min-width: 0;
}
body.ec-panel main .rounded-2xl.bg-white .truncate,
body.ec-panel main .ec-card .truncate {
  min-width: 0;
}

/* Длинные user-mention'ы, email'ы, токены — никогда не должны выкидывать
 * родителя за viewport. Если ребро truncate-блока не справилось — последний
 * рубеж overflow-wrap. */
body.ec-panel main a,
body.ec-panel main span,
body.ec-panel main p {
  overflow-wrap: anywhere;
}

/* ---------------------------------------------------------------------------
 * PWA: standalone-режим. Убираем focus-outline у топовой кнопки-«гамбургера»
 * сразу после клика (предотвращает «застрявшую» рамку, которая на iOS
 * визуально не пропадает после открытия модалки), а также корректируем
 * безопасную область на iPad Pro / Surface (windowing-mode display-mode).
 * --------------------------------------------------------------------------- */
@media (display-mode: standalone), (display-mode: minimal-ui), (display-mode: window-controls-overlay) {
  /* Standalone: запрещаем выделение текста двойным тапом по топбару — это
   * системный жест PWA-приложений (как в нативном UI). */
  body.ec-panel > div.flex > div.flex > #ec-panel-mobile-topbar,
  body.ec-panel > div.flex > div.flex > div.h-14.lg\:hidden {
    -webkit-user-select: none;
    user-select: none;
  }
  /* iPad Pro в standalone: layout не должен «прыгать» на повороте экрана.
   * dvh уже частично решает, но дополнительно стопорим горизонтальный body
   * scroll, который может появиться при resize. */
  html, body { overflow-x: hidden; }
}

/* ---------------------------------------------------------------------------
 * Pull-to-refresh: в PWA-режиме абсолютно ничего не должно «тянуться вниз»,
 * потому что в standalone это просто пустой жест, который сбивает скролл-
 * контейнер чата. На обычных страницах ЛК pull-to-refresh бессмысленен
 * (никаких feed'ов нет, обновление контента у нас всегда live через SSE).
 * --------------------------------------------------------------------------- */
html, body { overscroll-behavior-y: contain; }

/* ---------------------------------------------------------------------------
 * Page-loader: тонкая прогресс-полоска сверху + лёгкий fade-in main-контента.
 *
 * UX-цель — то самое «как у Facebook/YouTube»: переход между страницами
 * больше не выглядит как «белая вспышка». На клик по внутренней ссылке мы:
 *   1) Запускаем top progress bar (брендовый цвет, 2px, зафиксирован сверху).
 *   2) При загрузке новой страницы main стартует с opacity:0 и плавно
 *      выезжает (translateY 4px → 0). Длительность ~ 220ms — без задержки
 *      ощущения, но с ощущением «контент проявился».
 *   3) Bar финиширует на DOMContentLoaded (быстрый рывок до 100% и fade out).
 *
 * Реализация — public/assets/js/panel.js (см. ec-page-loader).
 * --------------------------------------------------------------------------- */
.ec-page-progress {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  z-index: 99999;
  pointer-events: none;
  background: transparent;
}
.ec-page-progress::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  width: 0%;
  background: linear-gradient(90deg, var(--color-brand-500, #8b5cf6) 0%, var(--color-brand-700, #6d28d9) 100%);
  box-shadow: 0 0 8px rgba(109, 40, 217, .35);
  transition: width .25s cubic-bezier(.4, 0, .2, 1), opacity .35s ease;
}
.ec-page-progress.is-active::before {
  width: var(--ec-progress, 30%);
}
.ec-page-progress.is-finishing::before {
  width: 100%;
  opacity: 0;
  transition: width .15s ease, opacity .35s ease .12s;
}

/* Контент страницы: лёгкий fade-in. Применяем только в режиме «есть JS»,
 * чтобы при отключённом JS не получить «вечно невидимую» страницу.
 * Класс ec-js-on ставится inline в <head> через document.documentElement,
 * поэтому правило срабатывает ДО первого paint'а — без FOUC. */
html.ec-js-on body.ec-panel main > div.w-full.px-4 {
  opacity: 0;
  transform: translateY(4px);
  animation: ec-page-in .22s cubic-bezier(.4, 0, .2, 1) .03s forwards;
}
@keyframes ec-page-in {
  to { opacity: 1; transform: translateY(0); }
}

/* Fade-out main-контента в момент клика по ссылке: добавляется JS-логикой
 * page-loader'а (ec-page-leaving). Делает переход «фейсбучнее» — пока
 * полоска ползёт, текущий контент мягко гасится, и при появлении новой
 * страницы fade-in выглядит естественным продолжением. */
html.ec-js-on.ec-page-leaving body.ec-panel main {
  opacity: .55;
  transition: opacity .18s ease-out;
}

/* Skeleton-shimmer: лёгкая «дышащая» подложка для тех мест, где данные
 * подгружаются после рендера страницы. Используется и в готовых
 * «макетных» скелетонах (см. .ec-sk-* helpers ниже), и в одиночных
 * <div class="ec-skel h-4 w-32"> для точечной подсветки. */
@keyframes ec-skel-shimmer {
  0%   { background-position: -200% 0; }
  100% { background-position: 200% 0; }
}
.ec-skel {
  background: linear-gradient(90deg, #eef0f4 0%, #f7f8fa 50%, #eef0f4 100%);
  background-size: 200% 100%;
  animation: ec-skel-shimmer 1.4s linear infinite;
  border-radius: 8px;
}

/* Готовые «строительные кирпичики» скелетона в стиле Facebook/Instagram:
 *   • .ec-sk-line   — текстовая строка (нейтральная высота 12px)
 *   • .ec-sk-line.lg — крупная строка (16px, заголовки)
 *   • .ec-sk-line.sm — мелкая строка (10px, мета)
 *   • .ec-sk-circle — круглый аватар (по умолчанию 40×40)
 *   • .ec-sk-rect   — карточка/превью (произвольные ширина/высота)
 *
 * Использование:
 *   <div class="ec-sk-card">
 *     <div class="ec-sk-circle"></div>
 *     <div class="flex-1 space-y-2">
 *       <div class="ec-sk-line lg" style="width:65%"></div>
 *       <div class="ec-sk-line" style="width:88%"></div>
 *       <div class="ec-sk-line sm" style="width:30%"></div>
 *     </div>
 *   </div>
 */
.ec-sk-line,
.ec-sk-circle,
.ec-sk-rect {
  background: linear-gradient(90deg, #eef0f4 0%, #f7f8fa 50%, #eef0f4 100%);
  background-size: 200% 100%;
  animation: ec-skel-shimmer 1.4s linear infinite;
  display: block;
}
.ec-sk-line    { height: 12px; border-radius: 6px; width: 100%; }
.ec-sk-line.sm { height: 10px; border-radius: 5px; }
.ec-sk-line.lg { height: 16px; border-radius: 7px; }
.ec-sk-circle  { width: 40px; height: 40px; border-radius: 9999px; flex: 0 0 auto; }
.ec-sk-rect    { width: 100%; height: 80px; border-radius: 12px; }

/* «Строка» скелетона: аватар + текст в две колонки. Готовый паттерн для
 * списков диалогов/комментариев/задач. */
.ec-sk-row {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 10px 12px;
}
.ec-sk-row .ec-sk-body {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding-top: 4px;
}

/* «Карточка» скелетона: заголовок + контент. Готовый паттерн для
 * страниц-дэшбордов (services/staff/booking-index и т.д.). */
.ec-sk-card {
  background: #fff;
  border-radius: 16px;
  padding: 16px;
  display: flex;
  align-items: flex-start;
  gap: 12px;
  box-shadow: inset 0 0 0 1px #f1f3f5;
}

/* Soft preloader-overlay для in-page переходов (например, фильтры списка
 * записей применяются и до получения ответа показываем скелетон поверх). */
.ec-overlay-loader {
  position: relative;
}
.ec-overlay-loader::after {
  content: '';
  position: absolute;
  inset: 0;
  background: rgba(255, 255, 255, .55);
  pointer-events: none;
  border-radius: inherit;
}
.ec-overlay-loader::before {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 22px;
  height: 22px;
  margin: -11px 0 0 -11px;
  border: 2.5px solid rgba(109, 40, 217, .25);
  border-top-color: var(--color-brand-700, #6d28d9);
  border-radius: 50%;
  animation: spin .9s linear infinite;
  z-index: 1;
}

/* Уважаем prefers-reduced-motion: пользователю с настройкой «меньше
 * анимаций» не должно подёргиваться. */
@media (prefers-reduced-motion: reduce) {
  html.ec-js-on body.ec-panel main > div.w-full.px-4 {
    opacity: 1;
    transform: none;
    animation: none;
  }
  html.ec-js-on.ec-page-leaving body.ec-panel main {
    opacity: 1;
    transition: none;
  }
  .ec-page-progress::before,
  .ec-page-progress.is-finishing::before { transition: none; }
  .ec-skel,
  .ec-sk-line,
  .ec-sk-circle,
  .ec-sk-rect { animation: none; }
}

/* ============================================================================
 * iOS PWA standalone — COLD-START full-height fix.
 *
 * ПРОБЛЕМА. В установленном PWA на iOS (status-bar black-translucent +
 * viewport-fit=cover) на ХОЛОДНОМ старте, БЕЗ касания, ДИНАМИЧЕСКИЙ вьюпорт
 * (100dvh / window.innerHeight / visualViewport.height) равен «маленькому»
 * боксу 793 = 852 − 59 (верхний инсет Dynamic Island) и держится 793, пока
 * пользователь реально не проскроллит/не свернёт-развернёт приложение
 * (программный скролл НЕ считается — проверено на устройстве). А выше по
 * файлу html.h-full / body.ec-panel.h-full прибиты к 100dvh (строки 383-384
 * и 615-621), поэтому html+body+шелл считаются как 793, и полоса 793..852
 * красится фоном html = белая щель снизу на НЕ-fullscreen страницах.
 *
 * РЕШЕНИЕ. Статическая единица vh резолвится против LAYOUT-вьюпорта, который
 * на iOS standalone равен полному 852 уже с первого кадра. Поэтому в
 * standalone перебиваем цепочку 100dvh на статический 100vh на html, body и
 * шелле — и не-fullscreen контент заполняет экран до home-indicator'а без
 * единого касания.
 *
 * ПОЧЕМУ ПРЕДЫДУЩИЕ ПОПЫТКИ «100vh не дал ничего». 100vh раньше вешали ТОЛЬКО
 * на #ec-app-shell, а body.h-full{height:100dvh}=793 над шеллом + body
 * overflow:hidden зажимали видимую область до 793 — 100vh был замаскирован,
 * а не опровергнут. Перебить надо ИМЕННО html И body, не только шелл.
 *
 * ОБЛАСТЬ ДЕЙСТВИЯ (важно):
 *  • html таргетим как html.ec-pwa-shell — отдельный маркер-класс, который
 *    стоит ТОЛЬКО на <html> в views/layouts/panel.php. НЕ трогаем bare
 *    html.h-full: его делят auth.php и marketing.php (длинная скролл-страница
 *    с html,body{overflow-x:clip}), и они тоже грузят app.css в scope:"/" —
 *    height:100vh там сломал бы их прокрутку/фон.
 *  • body НЕ-fullscreen только (:not(.ec-panel-fullscreen)). Страница диалогов
 *    (fullscreen) выглядит корректно и при 793, и при 852 (absolute-overlay
 *    модель), поэтому ей 100vh не нужен; оставляем ей body=100dvh, чтобы НЕ
 *    менять её клавиатурное поведение (dvh сам ужимается под клавиатуру как
 *    бэкап к initMobileViewport).
 *  • Весь блок под @media (display-mode: standalone),(display-mode: fullscreen):
 *    обычный мобильный Safari, Android PWA (нет верхнего инсета → 100vh==100dvh)
 *    и десктоп остаются на прежней корректной логике.
 *
 * Последним в порядке источника — гарантированно перебивает 100dvh-правила.
 * ============================================================================ */
@media (display-mode: standalone), (display-mode: fullscreen) {
  /* html: статический 100vh = полный 852 на холодном старте iOS.
     НЕ добавлять сюда min-height > 100vh (например calc(100% + inset)) — на
     <html> 100% резолвится против ICB(852), и min-height стал бы 911px,
     раздув документ и вернув щель уже как СКРОЛЛ. height:100vh самодостаточен. */
  html.ec-pwa-shell {
    height: 100vh;
    background: #f5f5f5;            /* подложка под island-зоной — не белая */
  }

  /* body: статический 100vh ТОЛЬКО на не-fullscreen страницах.
     Fullscreen-диалоги намеренно оставляем на 100dvh (см. шапку). */
  body.ec-panel.h-full:not(.ec-panel-fullscreen) {
    height: 100vh;
    background: #f5f5f5;
  }

  /* Шелл следует за теперь-корректной 852-цепочкой. Уходим от прежнего
     position:fixed;inset:0 (на части iOS-сборок он переякоривается на
     ВИЗУАЛЬНЫЙ вьюпорт и возвращает 793, плюс баг WebKit 237961 «fixed+cover
     даёт нижнюю щель»): обычный поток + height:100vh. position:relative (а не
     static), чтобы шелл оставался containing-block'ом для возможных
     position:absolute потомков. */
  #ec-app-shell {
    position: relative !important;
    top: auto !important; right: auto !important;
    bottom: auto !important; left: auto !important;
    width: auto !important;
    height: 100vh !important;
    min-height: 0 !important;
    max-height: none !important;
  }

  /* На fullscreen-странице шелл живёт внутри body=100dvh, поэтому и шеллу
     там даём 100dvh — чтобы не получить шелл выше body и нижний просвет. */
  body.ec-panel-fullscreen #ec-app-shell {
    height: 100dvh !important;
  }

  /* Не-fullscreen скролл-область не должна залезать под home-indicator. */
  body.ec-panel:not(.ec-panel-fullscreen) #ec-app-shell main {
    padding-bottom: env(safe-area-inset-bottom, 0px) !important;
  }
}

