/* Quillon Ops — экран календаря встреч (#/calendar).
 *
 * Почему здесь свой CSS, а не Tailwind-утилиты: tailwind.js — это Play CDN,
 * он компилирует классы В БРАУЗЕРЕ уже после вставки узлов в DOM. Сетка недели
 * это 7×18 ячеек плюс подписи — на среднем Android такой объём новых классов
 * даёт заметную паузу с белым экраном перед первой краской. Всё, что здесь,
 * приходит уже скомпилированным и рисуется в первом же кадре.
 *
 * Порядок правил — МОБИЛЬНЫЙ ПЕРВЫМ: база описывает телефон, десктоп
 * добавляется через min-width. В style.css нет ни одного @media, потому что там
 * экраны табличные и переживают горизонтальный скролл; календарь — нет: им
 * пользуются с телефона между звонками, и лента дня это основной вид, а не
 * деградация недельной сетки.
 *
 * Все классы с префиксом .cal-, все переменные с префиксом --cal-: файл
 * подключается рядом со style.css, и общие имена (--border, --ink) там уже
 * заняты — переопредели я их, поехала бы вёрстка воронки и таблицы заявок.
 */

/* ========================= токены: светлая ========================= */

.cal-root {
  /* Высота верхней полоски приложения: к ней прибита собственная sticky-шапка
     календаря. Значение приходит из style.css (--app-topbar-h) и НЕ дублируется
     здесь числом. Раньше дублировалось — стояло 58px от старого верхнего
     навбара; когда навбар заменили боковым меню, полоска пропала, а отступ
     остался, и шапка календаря накрыла строку дней недели вместе с числами.
     Запасное значение 0px — на случай, если calendar.css подключат без style.css. */
  --cal-hdr: var(--app-topbar-h, 0px);

  /* высота кликабельного слота на телефоне: 56px — минимум под палец,
     карточка встречи 64px, чтобы в неё влезли две строки с бейджами. */
  --cal-row: 56px;
  --cal-card: 64px;
  /* на десктопе мышь точнее, полчаса = 40px: 18 слотов укладываются
     в 720px и день целиком виден без вертикального скролла. */
  --cal-cell: 40px;

  --cal-bg: #f8fafc;
  --cal-panel: #ffffff;
  --cal-ink: #0f172a;
  --cal-muted: #64748b;
  --cal-faint: #94a3b8;
  --cal-line: #e2e8f0;
  --cal-line-2: #cbd5e1;
  --cal-brand: #1d4ed8;
  --cal-brand-ink: #ffffff;
  --cal-brand-soft: #eff6ff;

  --cal-free: #ffffff;
  --cal-off: #f1f5f9;
  --cal-past: #f8fafc;
  --cal-hold: #faf5ff;

  --cal-now: #dc2626;
  /* Конфликт (две встречи в одном слоте) — отдельный цвет. Раньше рамка брала
     --cal-no-bd, и двойная бронь читалась глазами как «клиент не пришёл». */
  --cal-clash: #f97316;

  /* Состояния встречи повторяют смысл badge-* из style.css, но своими
     токенами: там значения зашиты в классы и переиспользовать их нельзя. */
  --cal-plan-bg: #dbeafe;   --cal-plan-bd: #93c5fd;  --cal-plan-ink: #1e3a8a;
  --cal-conf-bg: #cffafe;   --cal-conf-bd: #67e8f9;  --cal-conf-ink: #155e75;
  --cal-held-bg: #e0e7ff;   --cal-held-bd: #a5b4fc;  --cal-held-ink: #3730a3;
  --cal-no-bg:   #fee2e2;   --cal-no-bd:   #fca5a5;  --cal-no-ink:   #991b1b;
  --cal-move-bg: #fef3c7;   --cal-move-bd: #fcd34d;  --cal-move-ink: #92400e;
  --cal-closed-bg: #f1f5f9; --cal-closed-bd: #cbd5e1; --cal-closed-ink: #475569;

  --cal-a-bg: #dcfce7; --cal-a-ink: #166534;
  --cal-b-bg: #fef3c7; --cal-b-ink: #92400e;
  --cal-n-bg: #f1f5f9; --cal-n-ink: #64748b;

  --cal-shadow: 0 1px 2px rgba(15, 23, 42, .06);
  --cal-shadow-lg: 0 12px 32px -8px rgba(15, 23, 42, .25);
}

/* ========================= токены: тёмная =========================
 * Тёмная НЕ включается автоматически по prefers-color-scheme, и это
 * осознанно: index.html жёстко задаёт body class="bg-slate-50 text-slate-900",
 * а в style.css нет ни одного тёмного правила. Автопереключение дало бы
 * тёмный календарь внутри белой страницы с белой шапкой — хуже, чем светлый.
 * Поэтому темнота ждёт явного согласия документа: <html data-theme="dark">
 * (или class="dark"), а data-theme="auto" отдаёт решение системе.
 * Когда в приложении появится общий переключатель — календарь подхватит его
 * без единой правки здесь. Значения — те же, что в frontend/playbook.html,
 * чтобы два тёмных экрана проекта не разъезжались по оттенкам.
 */

:root[data-theme="dark"] .cal-root,
:root.dark .cal-root {
  --cal-bg: #0a0f1a;
  --cal-panel: #0f172a;
  --cal-ink: #e8eefc;
  --cal-muted: #94a3b8;
  --cal-faint: #64748b;
  --cal-line: #1e293b;
  --cal-line-2: #334155;
  --cal-brand: #60a5fa;
  --cal-brand-ink: #06121f;
  --cal-brand-soft: #12203c;

  --cal-free: #0f172a;
  --cal-off: #0c1424;
  --cal-past: #0b1220;
  --cal-hold: #1a1430;

  --cal-now: #f87171;
  --cal-clash: #fb923c;

  --cal-plan-bg: #12203c;   --cal-plan-bd: #1e3a5f;  --cal-plan-ink: #93c5fd;
  --cal-conf-bg: #082f36;   --cal-conf-bd: #155e75;  --cal-conf-ink: #67e8f9;
  --cal-held-bg: #1b1f45;   --cal-held-bd: #312e81;  --cal-held-ink: #a5b4fc;
  --cal-no-bg:   #2a1010;   --cal-no-bd:   #7f1d1d;  --cal-no-ink:   #fca5a5;
  --cal-move-bg: #2a1e05;   --cal-move-bd: #78450a;  --cal-move-ink: #fbbf24;
  --cal-closed-bg: #131c2e; --cal-closed-bd: #334155; --cal-closed-ink: #94a3b8;

  --cal-a-bg: #0e2a1a; --cal-a-ink: #4ade80;
  --cal-b-bg: #2a1e05; --cal-b-ink: #fbbf24;
  --cal-n-bg: #131c2e; --cal-n-ink: #94a3b8;

  --cal-shadow: 0 1px 2px rgba(0, 0, 0, .4);
  --cal-shadow-lg: 0 12px 32px -8px rgba(0, 0, 0, .7);
}

@media (prefers-color-scheme: dark) {
  :root[data-theme="auto"] .cal-root {
    --cal-bg: #0a0f1a;
    --cal-panel: #0f172a;
    --cal-ink: #e8eefc;
    --cal-muted: #94a3b8;
    --cal-faint: #64748b;
    --cal-line: #1e293b;
    --cal-line-2: #334155;
    --cal-brand: #60a5fa;
    --cal-brand-ink: #06121f;
    --cal-brand-soft: #12203c;

    --cal-free: #0f172a;
    --cal-off: #0c1424;
    --cal-past: #0b1220;
    --cal-hold: #1a1430;

    --cal-now: #f87171;
    --cal-clash: #fb923c;

    --cal-plan-bg: #12203c;   --cal-plan-bd: #1e3a5f;  --cal-plan-ink: #93c5fd;
    --cal-conf-bg: #082f36;   --cal-conf-bd: #155e75;  --cal-conf-ink: #67e8f9;
    --cal-held-bg: #1b1f45;   --cal-held-bd: #312e81;  --cal-held-ink: #a5b4fc;
    --cal-no-bg:   #2a1010;   --cal-no-bd:   #7f1d1d;  --cal-no-ink:   #fca5a5;
    --cal-move-bg: #2a1e05;   --cal-move-bd: #78450a;  --cal-move-ink: #fbbf24;
    --cal-closed-bg: #131c2e; --cal-closed-bd: #334155; --cal-closed-ink: #94a3b8;

    --cal-a-bg: #0e2a1a; --cal-a-ink: #4ade80;
    --cal-b-bg: #2a1e05; --cal-b-ink: #fbbf24;
    --cal-n-bg: #131c2e; --cal-n-ink: #94a3b8;

    --cal-shadow: 0 1px 2px rgba(0, 0, 0, .4);
    --cal-shadow-lg: 0 12px 32px -8px rgba(0, 0, 0, .7);
  }
}

/* ========================= каркас ========================= */

.cal-root {
  color: var(--cal-ink);
  background: var(--cal-bg);
  /* Съедаем px-4/py-6 у #app-main: на телефоне сетка должна доходить до
     краёв экрана, 16px полей с каждой стороны — это минус 32px ширины слота. */
  margin: -10px -16px 0;
  min-height: calc(100vh - var(--cal-hdr));
  font-size: 14px;
  line-height: 1.35;
}

.cal-root *,
.cal-root *::before,
.cal-root *::after { box-sizing: border-box; }

/* ---- собственная sticky-шапка: прибита под шапку приложения ---- */
.cal-top {
  position: sticky;
  top: var(--cal-hdr);
  z-index: 6;                    /* ниже 10 у #app-header, иначе перекроет нав */
  background: var(--cal-panel);
  border-bottom: 1px solid var(--cal-line);
  padding: 8px 12px 0;
}

.cal-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 36px;
}
.cal-h1 {
  font-size: 16px;
  font-weight: 600;
  margin: 0;
  white-space: nowrap;
}
.cal-spacer { flex: 1 1 auto; min-width: 0; }

.cal-sel {
  height: 32px;
  max-width: 46vw;
  padding: 0 8px;
  font-size: 13px;
  color: var(--cal-ink);
  background: var(--cal-panel);
  border: 1px solid var(--cal-line-2);
  border-radius: 8px;
}

.cal-nav { display: flex; align-items: center; gap: 4px; }

.cal-btn {
  height: 32px;
  min-width: 32px;
  padding: 0 10px;
  font: inherit;
  font-size: 13px;
  color: var(--cal-ink);
  background: var(--cal-panel);
  border: 1px solid var(--cal-line-2);
  border-radius: 8px;
  cursor: pointer;
}
.cal-btn:hover:not(:disabled) { background: var(--cal-brand-soft); border-color: var(--cal-brand); }
.cal-btn:disabled { opacity: .45; cursor: default; }

/* Кнопка «Записать» в шапке на телефоне не помещается рядом с ‹Сегодня›:
   360px экрана делятся между заголовком и навигацией по датам. На телефоне
   вход в запись — через слот и через карточку встречи. */
.cal-only-wide { display: none; }
.cal-qtoggle { display: none; }

/* Точка актуальности: пульсирует только в момент прихода новой версии.
   Красных плашек об ошибках нет намеренно — тик поллинга падает молча. */
.cal-live {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--cal-line-2);
  flex: 0 0 auto;
}
.cal-live.is-fresh { background: #22c55e; }

/* ---- дата-стрип на 14 дней ---- */
.cal-strip {
  display: flex;
  gap: 6px;
  padding: 8px 0;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  overscroll-behavior-x: contain;
}
.cal-strip::-webkit-scrollbar { display: none; }

.cal-chip {
  flex: 0 0 auto;
  scroll-snap-align: center;
  width: 50px;
  min-height: 56px;
  padding: 5px 0 6px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  font: inherit;
  color: var(--cal-ink);
  background: var(--cal-panel);
  border: 1px solid var(--cal-line);
  border-radius: 12px;
  cursor: pointer;
}
.cal-chip-wd { font-size: 10px; color: var(--cal-muted); text-transform: uppercase; letter-spacing: .04em; }
.cal-chip-d  { font-size: 17px; font-weight: 600; line-height: 1; font-variant-numeric: tabular-nums; }
.cal-chip-n  { font-size: 10px; color: var(--cal-muted); min-height: 12px; }
.cal-chip.is-off { background: var(--cal-off); }
.cal-chip.is-today .cal-chip-d { color: var(--cal-now); }
.cal-chip.is-sel {
  background: var(--cal-brand);
  border-color: var(--cal-brand);
  color: var(--cal-brand-ink);
}
.cal-chip.is-sel .cal-chip-wd,
.cal-chip.is-sel .cal-chip-n,
.cal-chip.is-sel .cal-chip-d { color: var(--cal-brand-ink); }

/* ---- переключатель «Сетка / Без даты»: только телефон ---- */
.cal-tabs {
  display: flex;
  gap: 4px;
  padding: 0 0 8px;
}
.cal-tab {
  flex: 1 1 0;
  height: 34px;
  font: inherit;
  font-size: 13px;
  font-weight: 500;
  color: var(--cal-muted);
  background: var(--cal-off);
  border: 1px solid transparent;
  border-radius: 9px;
  cursor: pointer;
}
.cal-tab.is-on {
  color: var(--cal-ink);
  background: var(--cal-panel);
  border-color: var(--cal-line-2);
  box-shadow: var(--cal-shadow);
}
.cal-tab-n {
  display: inline-block;
  min-width: 18px;
  margin-left: 4px;
  padding: 0 5px;
  font-size: 11px;
  font-weight: 700;
  color: var(--cal-b-ink);
  background: var(--cal-b-bg);
  border-radius: 999px;
}

/* ========================= общие мелочи ========================= */

.cal-b {
  display: inline-block;
  padding: 1px 7px;
  font-size: 11px;
  font-weight: 600;
  line-height: 1.5;
  border-radius: 999px;
  white-space: nowrap;
}
.cal-q {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px; height: 18px;
  font-size: 11px;
  font-weight: 700;
  border-radius: 50%;
  flex: 0 0 auto;
}
.cal-q-А { background: var(--cal-a-bg); color: var(--cal-a-ink); }
.cal-q-Б { background: var(--cal-b-bg); color: var(--cal-b-ink); }
.cal-q-Н { background: var(--cal-n-bg); color: var(--cal-n-ink); }

.cal-muted { color: var(--cal-muted); }
.cal-empty { padding: 28px 16px; text-align: center; color: var(--cal-faint); font-size: 13px; }

/* Плейсхолдер первой загрузки. Серый, а не красный: ошибка сети здесь
   почти всегда одноразовая, следующий тик через 10 секунд её закрывает. */
.cal-skeleton { padding: 40px 16px; text-align: center; color: var(--cal-faint); font-size: 13px; }

.cal-root :focus-visible {
  outline: 2px solid var(--cal-brand);
  outline-offset: 2px;
}

/* ========================= лента дня (телефон) ========================= */

.cal-body { padding: 0 0 32px; }

.cal-lane {
  position: relative;
  padding: 10px 12px 0;
}

.cal-slotrow {
  position: relative;
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr);
  gap: 8px;
  padding-bottom: 6px;
}
.cal-t {
  font-size: 11px;
  color: var(--cal-faint);
  text-align: right;
  padding-top: 3px;
  font-variant-numeric: tabular-nums;
  user-select: none;
}
.cal-t.is-half { opacity: .55; }

/* Свободный слот — кнопка на всю ширину. Пока disabled: запись не включена,
   но разметка и высота уже те, что будут после включения. */
.cal-free {
  width: 100%;
  min-height: var(--cal-row);
  font: inherit;
  font-size: 13px;
  color: var(--cal-faint);
  background: var(--cal-free);
  border: 1px dashed var(--cal-line-2);
  border-radius: 10px;
  cursor: pointer;
}
.cal-free:disabled { cursor: default; }
.cal-free.is-past { background: var(--cal-past); border-style: solid; border-color: var(--cal-line); opacity: .6; }
.cal-free.is-off  { background: var(--cal-off);  border-style: solid; border-color: var(--cal-line); }
.cal-free.is-held { background: var(--cal-hold); border-color: #c4b5fd; }

/* Карточка встречи */
.cal-mt {
  display: flex;
  flex-direction: column;
  gap: 4px;
  width: 100%;
  min-height: var(--cal-card);
  padding: 8px 10px;
  font: inherit;
  text-align: left;
  border: 1px solid var(--cal-line-2);
  border-left-width: 4px;
  border-radius: 10px;
  background: var(--cal-panel);
  color: var(--cal-ink);
  cursor: pointer;
  overflow: hidden;
}
.cal-mt:hover { box-shadow: var(--cal-shadow); }
.cal-mt-h { display: flex; align-items: center; gap: 6px; min-width: 0; }
.cal-mt-t {
  flex: 1 1 auto;
  min-width: 0;
  font-weight: 600;
  font-size: 13px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.cal-mt-f { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.cal-mt-time { font-size: 11px; color: var(--cal-muted); font-variant-numeric: tabular-nums; }

/* Время у клиента. Плашкой, а не текстом в строку: рядом стоит диапазон
   «09:00–10:00», и третье число без границы читается как его продолжение.
   Приглушённый фон, а не яркий, — это справка, а не тревога. */
.cal-mt-ct {
  font-size: 11px;
  line-height: 15px;
  padding: 0 5px;
  border-radius: 999px;
  background: var(--cal-brand-soft);
  color: var(--cal-ink);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Кто назначил встречу — прижимаем вправо: взгляд идёт по левому краю
   (время → стадия), а автор нужен вторым вопросом, не первым. */
/* Значок открытого канала связи — в самом углу плитки, правее имени.
   Постоянный, в отличие от быстрых кнопок: «с человеком можно связаться» это
   свойство встречи, а не действие, и выяснять его наведением на каждую плитку
   по очереди невозможно.

   Приглушён намеренно: это фон, а не призыв. Кричать он начинает только когда
   клиент написал и ждёт ответа — тогда это уже не свойство, а долг. */
.cal-mt-ch {
  flex: 0 0 auto;
  font-size: 10px;
  line-height: 1;
  opacity: .45;
  color: var(--cal-muted);
  /* Имя назначившего прижато вправо через margin-left:auto; значок идёт следом,
     и небольшой отступ не даёт им слипнуться в «Андрей✈». */
  margin-left: 4px;
}
.cal-mt-ch-tg   { color: #0369a1; }
.cal-mt-ch-max  { color: #6d28d9; }
.cal-mt-ch-vk   { color: #3730a3; }
.cal-mt-ch-web  { color: #15803d; }
.cal-mt-ch-mail { color: #92400e; }
/* Клиент написал и ждёт: тот же значок, но в полную силу и с точкой-акцентом. */
.cal-mt-ch.has-unread {
  opacity: 1;
  font-size: 11px;
  text-shadow: 0 0 0 currentColor;
}
.cal-mt-ch.has-unread::after {
  content: "";
  display: inline-block; vertical-align: super;
  width: 4px; height: 4px; margin-left: 1px;
  border-radius: 50%; background: var(--cal-no-ink, #b91c1c);
}

.cal-mt-by {
  margin-left: auto;
  font-size: 11px;
  color: var(--cal-muted);
  opacity: .85;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 40%;
}

/* Цвет = состояние встречи из calendar_logic, не стадия сделки:
   стадий 12, состояний 7, и глазами различимы именно состояния. */
.cal-s-plan   { background: var(--cal-plan-bg);   border-color: var(--cal-plan-bd);   color: var(--cal-plan-ink); }
.cal-s-conf   { background: var(--cal-conf-bg);   border-color: var(--cal-conf-bd);   color: var(--cal-conf-ink); }
.cal-s-held   { background: var(--cal-held-bg);   border-color: var(--cal-held-bd);   color: var(--cal-held-ink); }
.cal-s-no     { background: var(--cal-no-bg);     border-color: var(--cal-no-bd);     color: var(--cal-no-ink); }
.cal-s-move   { background: var(--cal-move-bg);   border-color: var(--cal-move-bd);   color: var(--cal-move-ink); }
.cal-s-closed { background: var(--cal-closed-bg); border-color: var(--cal-closed-bd); color: var(--cal-closed-ink); }
.cal-s-plan .cal-b, .cal-s-conf .cal-b, .cal-s-held .cal-b,
.cal-s-no .cal-b, .cal-s-move .cal-b, .cal-s-closed .cal-b {
  background: rgba(255, 255, 255, .55);
  color: inherit;
}
:root[data-theme="dark"] .cal-mt .cal-b,
:root.dark .cal-mt .cal-b { background: rgba(0, 0, 0, .28); }

/* Мусорное время (00:00/03:00 из старого поля-даты) — штриховка,
   чтобы такую встречу не путали с реально назначенной на этот час. */
.cal-mt.is-garbage {
  background-image: repeating-linear-gradient(
    45deg, transparent 0 6px, rgba(148, 163, 184, .25) 6px 12px);
}

/* Конфликт: две встречи в одном слоте. Двойная бронь разрешена сознательно
   (иногда надо втиснуть горячего), поэтому не блокируем, а помечаем рамкой. */
.cal-blk { display: flex; gap: 4px; min-width: 0; }
.cal-blk > .cal-mt { flex: 1 1 0; min-width: 0; }
.cal-blk.is-conflict { outline: 2px solid var(--cal-clash); outline-offset: 1px; border-radius: 12px; }


/* Красная линия «сейчас». Позиция внутри слота задаётся в процентах, а не в
   пикселях: строки разной высоты (56px свободная, 64+ занятая), проценты
   переживают это без пересчёта на каждый тик. */
.cal-nowline {
  position: absolute;
  left: 40px;
  right: 0;
  height: 2px;
  background: var(--cal-now);
  pointer-events: none;
  z-index: 3;
}
.cal-nowline::before {
  content: "";
  position: absolute;
  left: -4px; top: -3px;
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--cal-now);
}

/* Встречи, которым не нашлось строки в сетке 09:00–17:30 (18:30, 03:00) —
   отдельным блоком под лентой. Иначе они бы просто исчезли с экрана. */
.cal-offgrid {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 14px 12px 0;
}

/* Недельная сетка на телефоне не показывается вовсе */
.cal-gridwrap { display: none; }

/* Вкладки: на телефоне видна ровно одна панель */
.cal-root[data-tab="grid"]  .cal-queue { display: none; }
.cal-root[data-tab="queue"] .cal-main  { display: none; }

/* ========================= очередь «Без даты» ========================= */

.cal-queue { padding: 10px 12px 0; }
.cal-queue-h {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 0 2px 8px;
  font-size: 12px;
  font-weight: 600;
  color: var(--cal-muted);
  text-transform: uppercase;
  letter-spacing: .05em;
}
.cal-qlist {
  background: var(--cal-panel);
  border: 1px solid var(--cal-line);
  border-radius: 12px;
  overflow: hidden;
}
.cal-qi {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  min-height: 56px;
  padding: 9px 12px;
  font: inherit;
  text-align: left;
  color: var(--cal-ink);
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--cal-line);
  cursor: pointer;
}
.cal-qi:last-child { border-bottom: 0; }
.cal-qi:hover { background: var(--cal-brand-soft); }
.cal-qi-b { flex: 1 1 auto; min-width: 0; }
.cal-qi-t {
  font-weight: 500;
  font-size: 13px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.cal-qi-s { font-size: 11px; color: var(--cal-muted); margin-top: 2px; }

/* ========================= десктоп: недельная сетка ========================= */

@media (min-width: 768px) {
  /* Оболочка дашборда — max-w-7xl (1280px). Семь дней в ней это 121px на
     колонку, а в 121px имя клиента не помещается: карточки показывали «Л..».
     Календарю отдаём всю ширину экрана — таблицам воронки и заявок она не
     нужна, поэтому правило прицельное, через :has(). */
  #app-main:has(.cal-root) {
    max-width: none;
    padding-left: 20px;
    padding-right: 20px;
    /* Раздел занимает ровно окно: страница не прокручивается, прокрутка живёт
       внутри сетки. Пока высоту считали формулой с высотой верхней шапки,
       страница ездила на 44px, карточка вылезала за низ на 20px, а сетка на 5
       (замер в браузере 29.08.2026). */
    height: calc(100vh - var(--app-topbar-h, 0px));
    display: flex;
    flex-direction: column;
  }

  /* Замер в браузере: .cal-top стоял на 140…186, а строка дней на 141…181 —
     шапка календаря накрывала дни недели целиком и срезала первую строку
     очереди «Без даты». Причина — overflow:hidden ниже: он делает карточку
     скролл-портом, и sticky-шапка липнет на 58px ВНУТРЬ карточки вместо того,
     чтобы встать под шапку приложения. overflow:clip режет углы так же,
     но скролл-контейнером не становится, и sticky снова считается от страницы. */
  .cal-root {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    margin: 0;
    border: 1px solid var(--cal-line);
    border-radius: 14px;
    overflow: clip;
    min-height: 0;
  }
  .cal-top { flex: 0 0 auto; padding: 10px 14px 0; }
  .cal-body { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
  .cal-main { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
  .cal-h1 { font-size: 18px; }
  .cal-strip { display: none; }         /* на неделе стрип не нужен: видны все дни */
  .cal-tabs { display: none; }          /* вкладки — телефонные, тут кнопка в шапке */
  /* На десктопе вкладки панели не переключают — main виден всегда. Здесь
     стоял display:block, и он по специфичности перебивал flex-раскладку ниже:
     сетка переставала получать высоту от родителя и вырастала по содержимому
     до 1125px при окне 900 (замер в браузере). */
  .cal-root[data-tab] .cal-main {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
  }

  /* Очередь «Без даты» держала 300px ширины постоянно, хотя это рабочий список
     на десяток позиций, к которому обращаются наездами. Прячем и открываем
     кнопкой — освободившееся уходит колонкам дня. */
  .cal-queue { display: none; }
  .cal-root[data-queue="on"] .cal-queue { display: block; }
  .cal-qtoggle { display: inline-flex; align-items: center; gap: 2px; }
  .cal-root[data-queue="on"] .cal-qtoggle {
    background: var(--cal-brand-soft);
    border-color: var(--cal-brand);
    color: var(--cal-brand);
  }
  .cal-qtoggle .cal-tab-n[hidden] { display: none; }

  .cal-lane { display: none; }
  /* overflow-x:auto сам по себе делал обёртку скролл-портом и по вертикали
     (спека: visible рядом с не-visible вычисляется в auto), но высоту ей никто
     не ограничивал — контейнер был ровно по контенту, скроллиться ему было
     некуда, и sticky-строка дней уезжала вверх вместе со страницей.
     Ограничиваем высоту — строка дней и колонка времени наконец липнут. */
  .cal-gridwrap {
    display: block;
    overflow: auto;
    /* Высоту даёт flex-родитель, а не calc с константами. Прежняя формула
       вычитала высоту верхней шапки приложения, которой на десктопе больше
       нет, и высоту шапки календаря числом 47px — при настоящих 90px. */
    flex: 1 1 auto;
    min-height: 0;
    overscroll-behavior: contain;
    /* Верхнего отступа тут быть не может. Липкая строка дней прибивается к
       ВЕРХУ скролл-порта, то есть под padding-top, — и в оставшуюся щель было
       видно, как проезжают ячейки сетки. Отступ убран, строка дней встаёт
       вплотную под шапку календаря. */
    padding: 0 14px;
  }

  .cal-grid {
    display: grid;
    /* 56px — колонка времени; дни поровну, но не уже 92px, иначе название
       стадии перестаёт читаться и включается горизонтальный скролл. */
    grid-template-columns: 56px repeat(7, minmax(92px, 1fr));
    grid-template-rows: auto;          /* строка дней — по содержимому */
    grid-auto-rows: var(--cal-cell);
    min-width: 700px;
    position: relative;
    /* Слои внутри сетки считаются между собой и не могут перебить шапку
       календаря (z-index:6) — сколько бы их тут ни завелось. */
    z-index: 0;
  }

  /* Колонка времени липнет к левому краю при горизонтальном скролле —
     без неё на 700px‑скролле непонятно, какой это час. */
  .cal-gt {
    position: sticky;
    left: 0;
    z-index: 3;
    grid-column: 1;
    display: flex;
    align-items: flex-start;
    justify-content: flex-end;
    padding: 0 8px 0 0;
    font-size: 11px;
    color: var(--cal-faint);
    background: var(--cal-panel);
    font-variant-numeric: tabular-nums;
    transform: translateY(-6px);
    user-select: none;
  }
  .cal-gt.is-half { opacity: .5; }
  /* Подписи времени сдвинуты на 6px вверх, чтобы стоять НА линии часа.
     Первой сдвигаться некуда: над ней липкая строка дней с непрозрачным
     фоном и z-index выше — она срезала «09:00» ровно на эти 6px. */
  .cal-gt.is-first { transform: none; }
  /* Угловая ячейка липнет сразу к левому краю и к верху — она обязана быть
     выше и колонки времени, и строки с днями, иначе они проезжают сквозь неё. */
  .cal-gt.cal-gh { transform: none; align-items: center; z-index: 5; }

  .cal-gh {
    grid-row: 1;
    position: sticky;
    top: 0;
    /* было 2 — ровно столько же, сколько у .cal-blk, и блоки встреч
       перекрывали строку дней просто потому, что идут в разметке позже. */
    z-index: 4;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 1px;
    padding: 4px 0;
    background: var(--cal-panel);
    border-bottom: 1px solid var(--cal-line-2);
  }
  .cal-gh-wd { font-size: 10px; color: var(--cal-muted); text-transform: uppercase; letter-spacing: .05em; }
  .cal-gh-row { display: flex; align-items: center; gap: 6px; }
  .cal-gh-d  { font-size: 14px; font-weight: 600; font-variant-numeric: tabular-nums; }

  /* Сколько в дне назначено и сколько сорвалось. Синее — встречи, которые
     стоят; красное — не пришёл и перенос. Полная разбивка в подсказке. */
  /* Два числа рядом слипались в одно: «4» и «1» читались как «41». Разводим
     зазором и даём каждому свой фон во всю плашку. */
  .cal-gh-n { display: inline-flex; gap: 5px; }
  .cal-gh-n b {
    min-width: 16px;
    padding: 0 4px;
    font-size: 10px;
    font-weight: 700;
    line-height: 15px;
    text-align: center;
    border-radius: 999px;
    font-variant-numeric: tabular-nums;
  }
  .cal-n-plan { background: var(--cal-plan-bg); color: var(--cal-plan-ink); }
  .cal-n-fail { background: var(--cal-no-bg);   color: var(--cal-no-ink); }
  .cal-gh.is-today .cal-gh-d { color: var(--cal-now); }
  .cal-gh.is-off { background: var(--cal-off); }
  .cal-gh.is-today { background: var(--cal-brand-soft); }

  .cal-cell {
    border-right: 1px solid var(--cal-line);
    border-bottom: 1px solid var(--cal-line);
    background: var(--cal-free);
  }
  /* Получас внутри часа отделяем пунктиром, час — сплошной линией:
     иначе 18 одинаковых полос читаются как каша. */
  .cal-cell.is-half { border-bottom-style: dashed; }
  .cal-cell.is-free  { cursor: default; }
  .cal-cell.is-past  { background: var(--cal-past); }
  .cal-cell.is-off   { background: var(--cal-off); }
  .cal-cell.is-held  { background: var(--cal-hold); }

  /* Блок встречи ложится поверх ячеек тем же grid-area.
     Час = grid-row: span 2 — ровно то, что просили: одна плитка на час,
     а не две склеенных получасовки. */
  .cal-blk {
    z-index: 2;
    padding: 1px 2px;
    align-self: stretch;
  }
  .cal-blk > .cal-mt {
    min-height: 0;
    padding: 4px 6px;
    border-radius: 7px;
    gap: 2px;
  }
  /* Плитка на час — это 80px, в которых жила одна обрезанная строка и пустота.
     Имя получает две строки, а интервал времени приходит из разметки: карточка
     перестаёт быть наполовину пустой, а имя клиента наконец читается. */
  .cal-blk > .cal-mt .cal-mt-t {
    font-size: 12px;
    white-space: normal;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    line-height: 1.25;
  }
  .cal-blk > .cal-mt .cal-mt-h { align-items: flex-start; }
  .cal-blk > .cal-mt .cal-mt-f { gap: 4px; }
  /* Конфликт в колонке 121px: делить её поровну — значит оставить карточке
     58px, где от имени видно «Л..», а от стадии «назнач». Кладём внахлёст со
     сдвигом, как это делают обычные календари: отрицательный margin возвращает
     во flex свободное место, и каждая карточка получает уже ~2/3 колонки.
     Левый край нижней остаётся виден и кликабелен, наведение поднимает её. */
  .cal-blk.is-conflict > .cal-mt + .cal-mt {
    margin-left: -34%;
    box-shadow: -2px 0 6px -2px rgba(15, 23, 42, .35);
  }
  .cal-blk.is-conflict > .cal-mt:hover,
  .cal-blk.is-conflict > .cal-mt:focus-visible {
    position: relative;
    z-index: 1;
    box-shadow: 0 2px 10px -2px rgba(15, 23, 42, .45);
  }
  /* Подпись стадии в 80px всё ещё не помещается целиком — состояние читается
     по цвету, а полное имя и стадия висят в подсказке карточки. */
  .cal-blk.is-conflict .cal-b { display: none; }

  .cal-only-wide { display: inline-flex; align-items: center; justify-content: center; }
  /* Во всю ширину одна встреча с мусорным временем весила визуально как
     половина рабочего дня. Раскладываем плитками в строку. */
  .cal-offgrid {
    flex-direction: row;
    flex-wrap: wrap;
    padding: 14px 0 12px;
  }
  .cal-offgrid > .cal-sec-h { flex: 1 0 100%; margin-bottom: 0; }
  .cal-offgrid > .cal-mt { flex: 0 1 260px; }

  .cal-nowline { left: 0; }
  .cal-gnow {
    position: relative;
    z-index: 3;
    pointer-events: none;
  }

  .cal-queue { padding: 14px; }
  .cal-body { padding-bottom: 14px; }
}

/* ≥1120px — очередь «Без даты» переезжает в правую колонку и висит
   постоянно: это рабочий список, ради которого не должно быть кликов. */
@media (min-width: 1120px) {
  .cal-root[data-queue="on"] .cal-body {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 320px;
    /* stretch, а не start: колонки должны занять всю высоту тела, иначе
       очередь схлопывается по содержимому и её собственная прокрутка не
       включается. */
    align-items: stretch;
    min-height: 0;
  }
  .cal-root[data-queue="on"] .cal-queue {
    border-left: 1px solid var(--cal-line);
    /* Высота — от родителя-грида фиксированной высоты; своя прокрутка внутри. */
    min-height: 0;
    overflow: auto;
    overscroll-behavior: contain;
  }
}

/* ========================= карточка встречи (модалка) ========================= */

.cal-dlg {
  padding: 0;
  border: 0;
  background: transparent;
  max-width: 100%;
  max-height: 100%;
  width: 100%;
  /* телефон — шторка снизу: до неё дотягивается большой палец */
  margin: auto auto 0;
}
.cal-dlg::backdrop { background: rgba(15, 23, 42, .55); }

.cal-sheet {
  background: var(--cal-panel);
  color: var(--cal-ink);
  border-radius: 16px 16px 0 0;
  box-shadow: var(--cal-shadow-lg);
  max-height: 88vh;
  overflow-y: auto;
  padding: 14px 16px 24px;
}
.cal-sheet-grab {
  width: 36px; height: 4px;
  margin: 0 auto 10px;
  border-radius: 2px;
  background: var(--cal-line-2);
}
.cal-sh-h { display: flex; align-items: flex-start; gap: 8px; }
.cal-sh-t { flex: 1 1 auto; min-width: 0; font-size: 16px; font-weight: 600; }
.cal-x {
  flex: 0 0 auto;
  width: 32px; height: 32px;
  font: inherit; font-size: 18px; line-height: 1;
  color: var(--cal-muted);
  background: var(--cal-off);
  border: 0; border-radius: 8px;
  cursor: pointer;
}
.cal-sh-sub { font-size: 13px; color: var(--cal-muted); margin-top: 2px; }

/* Карточка читается сверху вниз: когда → кто → чем живёт → что было.
   Без разделителей четыре списка подряд сливаются в одно полотно. */
.cal-sec { margin-top: 14px; }
.cal-sec + .cal-sec {
  margin-top: 16px;
  padding-top: 15px;
  border-top: 1px solid var(--cal-line);
}

/* Состояние встречи и стадия сделки — плашками под датой, а не текстом
   через точку: цвет плашки тот же, что у плитки в сетке. */
.cal-sh-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 9px; }

/* Температура приходит как hot/warm/cold — по-русски и цветом. */
.cal-temp-hot  { background: var(--cal-no-bg);   color: var(--cal-no-ink); }
.cal-temp-warm { background: var(--cal-move-bg); color: var(--cal-move-ink); }
.cal-temp-cold { background: var(--cal-plan-bg); color: var(--cal-plan-ink); }

.cal-hint { margin-top: 10px; font-size: 12px; line-height: 1.45; color: var(--cal-muted); }
.cal-sec-h {
  font-size: 11px;
  font-weight: 700;
  color: var(--cal-muted);
  text-transform: uppercase;
  letter-spacing: .06em;
  margin-bottom: 6px;
}
/* 92px не хватало «Рекомендации», а зазор 4px склеивал строки в простыню. */
.cal-kv { display: grid; grid-template-columns: 104px minmax(0, 1fr); gap: 9px 12px; font-size: 13px; line-height: 1.45; }
.cal-kv dt { color: var(--cal-muted); }
.cal-kv dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }

.cal-a {
  color: var(--cal-brand);
  text-decoration: none;
  font-weight: 500;
}
.cal-a:hover { text-decoration: underline; }

/* Телефон отдельной крупной кнопкой: со звонка чаще всего и начинается
   работа с карточкой, ссылкой в 13px в неё не попасть пальцем. */
/* Кнопка входа в комнату — вторичная рядом со звонком: звонок ведёт к клиенту,
   комната к самому миту, и путать их по весу нельзя. */
.cal-meet {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  min-height: 42px;
  margin-top: 8px;
  font-size: 14px;
  font-weight: 600;
  color: var(--cal-brand);
  background: var(--cal-brand-soft);
  border: 1px solid var(--cal-brand);
  border-radius: 10px;
  text-decoration: none;
}
.cal-meet:hover { background: var(--cal-panel); }

.cal-call {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  min-height: 44px;
  margin-top: 10px;
  font-size: 15px;
  font-weight: 600;
  color: var(--cal-brand-ink);
  background: var(--cal-brand);
  border-radius: 10px;
  text-decoration: none;
}
/* Полоса действий липнет к низу панели. Раньше кнопки лежали последней секцией,
   и до главного действия надо было мотать через бриф и историю — то есть дальше
   всего от начала. Фон непрозрачный: под полосой проезжает содержимое. */
.cal-bar {
  position: sticky;
  bottom: 0;
  /* Отрицательные боковые поля выводят полосу на всю ширину панели, съедая её
     горизонтальные отступы. Нижнего отрицательного поля тут быть НЕ должно:
     sticky прибивается к нижней границе ОТСТУПОВ контейнера, и полоса вставала
     на 28px выше дна панели — в эту щель просвечивал текст истории. Вместо
     подгонки полями убираем нижний отступ у самой панели, когда полоса есть. */
  margin: 18px -20px 0;
  padding: 12px 20px 16px;
  background: var(--cal-panel);
  border-top: 1px solid var(--cal-line);
  z-index: 2;                      /* содержимое проезжает ПОД полосой */
}
.cal-sheet:has(.cal-bar) { padding-bottom: 0; }
.cal-bar-btns { display: flex; gap: 8px; }
/* flex-basis по содержимому, а свободное место делим поровну: длинная подпись
   получает больше по праву, короткая не остаётся зажатой. Фиксированные доли
   (сначала 1:1, потом 2:1) каждый раз жали то одну кнопку, то другую —
   при разной длине слов доли для этого не годятся. */
.cal-bar-btns > * { flex: 1 1 auto; min-height: 40px; padding: 0 16px; }
/* «Написать» в полосе действий — ссылка, ведущая себя как кнопка. Растёт по
   содержимому и НЕ отбирает ширину у «Подтвердить» и «Перенести», за которую
   уже боролись: flex-basis по содержимому, а не поровну. */
.cal-btn-chat {
  display: inline-flex; align-items: center; justify-content: center;
  text-decoration: none; flex: 0 1 auto; white-space: nowrap;
}

/* Вопрос перед действием: свой блок, а не confirm() браузера — тот выглядит
   чужеродно и не даёт объяснить, что именно произойдёт. */
.cal-ask {
  margin-top: 10px;
  padding: 12px 14px;
  background: var(--cal-off);
  border-radius: 10px;
}
.cal-ask[hidden] { display: none; }
.cal-ask-t { margin: 0 0 10px; font-size: 13.5px; line-height: 1.45; color: var(--cal-ink); }
.cal-ask-btns { display: flex; gap: 8px; }
.cal-ask-btns > * { flex: 1 1 0; }
.cal-ask-warn {
  margin: 8px 0 0;
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--flag, var(--cal-move-ink));
}

/* Быстрые кнопки в плитке. Накладываются поверх, а не встраиваются в поток:
   плитка получасовой встречи — 38px высоты, и ряд кнопок съел бы имя клиента. */
.cal-quick {
  position: absolute;
  top: 2px;
  right: 2px;
  display: flex;
  gap: 3px;
  opacity: 0;                     /* на десктопе проявляются по наведению */
  transition: opacity .12s;
}
.cal-mt { position: relative; }
.cal-mt:hover .cal-quick,
.cal-mt:focus-within .cal-quick { opacity: 1; }
.cal-q-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 20px;
  height: 20px;
  padding: 0 5px;
  font-size: 12px;
  line-height: 1;
  color: var(--cal-ink);
  background: var(--cal-panel);
  border: 1px solid var(--cal-line-2);
  border-radius: 6px;
  cursor: pointer;
  white-space: nowrap;
}
.cal-q-btn:hover { border-color: var(--cal-brand); color: var(--cal-brand); }
.cal-q-btn.is-ask {
  padding: 0 8px;
  font-size: 11px;
  color: var(--cal-brand-ink);
  background: var(--cal-brand);
  border-color: var(--cal-brand);
}
.cal-q-btn.is-done { color: #15803d; border-color: #15803d; }
/* «Написать клиенту» — третья быстрая кнопка в плитке, ссылкой: переход в
   другой раздел, и средний клик должен открывать новую вкладку. Счётчик
   непрочитанных вписан ВНУТРЬ значка: отдельный бейдж рядом на плитке высотой
   38px просто не помещается. */
.cal-q-btn.has-unread { background: #fee2e2; border-color: #fca5a5; color: #b91c1c; }
.cal-q-btn > i {
  font-style: normal; font-size: 9px; font-weight: 700;
  margin-left: 1px; vertical-align: super;
}
.cal-q-btn.is-err  { color: var(--cal-no-ink); border-color: var(--cal-no-bd); }

/* На телефоне наведения нет, а карточка в ленте вдвое просторнее — показываем
   кнопки всегда. */
@media (hover: none) {
  .cal-quick { opacity: 1; }
}

.cal-actions { display: flex; gap: 8px; margin-top: 12px; flex-wrap: wrap; }
.cal-actions > * { flex: 1 1 140px; min-height: 40px; }
.cal-btn-main {
  color: var(--cal-brand-ink);
  background: var(--cal-brand);
  border-color: var(--cal-brand);
  font-weight: 600;
}
.cal-btn-main:hover:not(:disabled) { filter: brightness(1.08); background: var(--cal-brand); }

/* Форма переноса. Слоты те же, что в сетке: записать на время, которого на
   экране нет, — это встреча, которую никто не увидит. */
.cal-move { margin-top: 10px; display: flex; flex-direction: column; gap: 8px; }
.cal-move[hidden] { display: none; }
.cal-move-row { display: flex; gap: 8px; }
.cal-move-row > * { flex: 1 1 0; min-width: 0; }
.cal-inp {
  height: 40px;
  padding: 0 10px;
  font: inherit;
  font-size: 14px;
  color: var(--cal-ink);
  background: var(--cal-panel);
  border: 1px solid var(--cal-line-2);
  border-radius: 9px;
}
.cal-move-msg { font-size: 12px; line-height: 1.45; color: var(--cal-muted); min-height: 16px; }
.cal-move-msg.is-ok  { color: #15803d; }
.cal-move-msg.is-err { color: var(--cal-no-ink); }

.cal-quote {
  margin: 6px 0 0;
  padding: 8px 10px;
  font-size: 13px;
  font-style: italic;
  color: var(--cal-ink);
  background: var(--cal-off);
  border-left: 3px solid var(--cal-line-2);
  border-radius: 0 8px 8px 0;
}
/* Лента истории: переходы стадий и комментарии лида вперемешку по времени.
   Дата — подзаголовком на группу, в строке только часы: 104px под полную дату
   в каждой строке съедали четверть ширины панели и повторяли одно и то же. */
.cal-tl { display: flex; flex-direction: column; }
.cal-tl-day {
  margin: 14px 0 5px;
  font-size: 11px;
  font-weight: 700;
  color: var(--cal-faint);
  text-transform: uppercase;
  letter-spacing: .05em;
}
.cal-tl-day:first-child { margin-top: 0; }
.cal-tl-i {
  display: grid;
  grid-template-columns: 42px minmax(0, 1fr);
  gap: 10px;
  padding: 3px 0;
  font-size: 13px;
  line-height: 1.45;
}
.cal-tl-t {
  color: var(--cal-faint);
  font-size: 11px;
  padding-top: 3px;
  font-variant-numeric: tabular-nums;
}
.cal-tl-b { min-width: 0; overflow-wrap: anywhere; color: var(--cal-muted); }

/* Комментарий писал живой человек — он и должен читаться первым, а не
   теряться среди служебных переходов стадий. */
.cal-tl-i.is-comment { padding: 4px 0; }
.cal-tl-i.is-comment .cal-tl-b {
  color: var(--cal-ink);
  white-space: pre-wrap;
  background: var(--cal-off);
  border-left: 2px solid var(--cal-line-2);
  border-radius: 0 8px 8px 0;
  padding: 7px 10px;
}
.cal-tl-who {
  display: block;
  margin-bottom: 3px;
  font-size: 11px;
  font-weight: 600;
  color: var(--cal-muted);
}

/* Панель справа, не окно по центру. Шторка снизу — телефонный жест; мышью до
   неё тянуться через весь экран, а панель у правого края встаёт рядом с той
   колонкой, из которой её открыли, и не закрывает саму сетку. Затемнение —
   штатный ::backdrop модального <dialog>, он же ловит клик «закрыть». */
@media (min-width: 768px) {
  .cal-dlg {
    width: min(460px, 100vw);
    max-width: min(460px, 100vw);
    height: 100%;
    max-height: 100%;
    margin: 0 0 0 auto;
  }
  .cal-dlg[open] { animation: cal-drawer-in .18s ease-out; }
  @keyframes cal-drawer-in { from { transform: translateX(28px); opacity: 0; } }

  .cal-sheet {
    height: 100%;
    max-height: 100%;
    border-radius: 0;
    padding: 18px 20px 28px;
    box-shadow: -18px 0 44px -22px rgba(15, 23, 42, .5);
  }
  .cal-sheet-grab { display: none; }   /* «ручка» — жест телефона */
}

/* Анимации выключаем для тех, кто их отключил в системе. */
@media (prefers-reduced-motion: reduce) {
  .cal-root *, .cal-dlg * { transition: none !important; animation: none !important; }
}

/* ── оплата в карточке встречи ────────────────────────────────────────────── */

.cal-pay-row {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 8px;
}
/* Сумма уже способа: способ — длинная строка вроде «Рассрочка POSCREDIT»,
   а сумма это пять цифр, и растягивать её на половину строки незачем. */
.cal-pay .cal-inp { flex: 1 1 200px; min-width: 0; }
.cal-pay .cal-pay-amt { flex: 0 1 150px; }
.cal-pay #cal-pay-product { width: 100%; margin-top: 8px; }

.cal-pay-msg { flex: 1 1 100%; font-size: 13px; line-height: 1.5; word-break: break-word; }
.cal-pay-msg.is-ok { color: #15803d; }
.cal-pay-msg.is-err { color: #b91c1c; }

/* Маленькая кнопка «Копировать» рядом со ссылкой — не должна спорить по весу
   с основной «Сгенерить». */
.cal-btn-s { padding: 3px 9px; font-size: 12px; margin-left: 6px; }
