/* Вид системы: лёгкий, «как переписка и календарь», поверх klan.css.
 *
 * Файл отдельный и подключён ПОСЛЕ klan.css по одной причине: пока окна экранов
 * дописывают свои блоки в конец klan.css, править его значило бы сталкиваться
 * с ними в одном файле. Поэтому здесь нет разметки, только селекторы по уже
 * существующим классам и элементам, а блоки окон (.kal-*, .zay-*, .abn-*,
 * .dng-*, .loy-*, .seg-*, .nas-*) не переопределяются вовсе — они берут новый
 * вид через переменные :root ниже, названные так же, как в klan.css.
 * Слияние с klan.css — отдельным шагом, когда окна закончат.
 *
 * Шрифты — те же файлы, что объявлены в klan.css (@font-face там); новых
 * начертаний и внешних адресов здесь нет.
 */

/* --- переменные ----------------------------------------------------------- */

:root {
  /* Нейтральные — холодные серые. */
  --fon: #f4f4f5;
  --kartochka: #fff;
  --sinii: #18181b;          /* основной текст; имя осталось от прежней палитры */
  /* Тихий серый темнее ориентира #71717a на полтона: #71717a на фоне #f4f4f5
   * даёт 4.40:1, а подписи под заголовком стоят именно на фоне. */
  --seryi: #66666e;
  --razdelitel: #e4e4e7;
  /* Акцент — оранжевый КЛАНа, взятый на тон глубже фирменного #ec652b. Белый
   * текст на #ec652b даёт 3.25:1, а оранжевым залиты кнопки с белой надписью
   * 15px и пункт меню — это обычный, не крупный текст, ему нужно 4.5:1.
   * Фирменный тон остался там, где на нём нет текста: кольцо фокуса, отметки. */
  --akcent: #c94a12;
  --akcent-yarkiy: #ec652b;
  --akcent-8: #fcefe8;       /* выделение строки: акцент ~8% на белом */
  --akcent-10: #fbeae1;      /* вторичная кнопка: акцент ~10% */
  --akcent-tekst: #b23f0c;   /* акцентный текст на светлой заливке, 5.2:1 */
  --dengi: #127262;
  --radius: 10px;
  --radius-karta: 12px;
  --ten: 0 1px 2px rgba(0, 0, 0, .06);
  --navedenie: #f4f4f5;
  --pole: #f4f4f5;

  /* Статусы — приглушённые: фон светлый, текст тёмный того же тона. */
  --uspeh: #15803d;       --uspeh-fon: #eef8f1;
  --preduprezhdenie: #92400e; --preduprezhdenie-fon: #fdf6e7;
  --oshibka: #b42318;     --oshibka-fon: #fdf0ef;

  /* Числа — тем же Inter с табличными цифрами (правило ниже на body).
   * Моноширинный рядом с текстом выглядел «кодом», а в расписании и суммах
   * это не код: разряды выравнивает `tabular-nums`, и шрифт при этом один.
   * JetBrains Mono остаётся в --kod: номер запроса и подобное сверяют посимвольно. */
  --chisla: var(--tekst);
  --kod: 'JetBrains Mono', ui-monospace, SFMono-Regular, 'SF Mono', Menlo,
    Consolas, 'Liberation Mono', 'Courier New', monospace;

  /* Календарь: сетка, часы, «сегодня» и пастельная палитра направлений с
   * тёмным текстом. Сам календарь ведёт окно 1 — здесь только переменные. */
  --kal-liniya-chasa: #e4e4e7;
  --kal-liniya-polchasa: #f0f0f2;
  --kal-segodnya-fon: #fff7f2;
  --kal-segodnya: var(--akcent-tekst);
  --kal-seychas: #d92d20;
  --kal-tekst-bloka: #27272a;
  --napravlenie-1: #dbe8fb;  --napravlenie-1-kraj: #3b6fb6;
  --napravlenie-2: #dcf1e4;  --napravlenie-2-kraj: #2f8a5b;
  --napravlenie-3: #fde9d4;  --napravlenie-3-kraj: #c2701f;
  --napravlenie-4: #ebe1f8;  --napravlenie-4-kraj: #7b4fb5;
  --napravlenie-5: #fbe0e7;  --napravlenie-5-kraj: #b8435f;
  --napravlenie-6: #d9f0f3;  --napravlenie-6-kraj: #2b8795;
  --napravlenie-7: #f5efcc;  --napravlenie-7-kraj: #968521;
  --napravlenie-8: #e6e9ee;  --napravlenie-8-kraj: #5d6c80;
  --napravlenie-9: #f8e3da;  --napravlenie-9-kraj: #a9573a;
  --napravlenie-10: #e2ecd6; --napravlenie-10-kraj: #5d823b;
  /* Ещё два — палитра типов событий и залов в двенадцать цветов (16.10). */
  --napravlenie-11: #fdf1c7; --napravlenie-11-kraj: #a87d00;
  --napravlenie-12: #e3e5fa; --napravlenie-12-kraj: #4b53b8;

  --perehod: 140ms ease;
  --shirina-paneli: 240px;
}

/* --- текст ---------------------------------------------------------------- */

body {
  background: var(--fon);
  color: var(--sinii);
  font-size: 15px;
  line-height: 1.45;
  font-variant-numeric: tabular-nums;
  -webkit-font-smoothing: antialiased;
}

h1 { font-size: 23px; line-height: 1.25; font-weight: 600; letter-spacing: -.01em; margin: 0 0 6px; }
h2 { font-size: 16px; line-height: 1.3; }
.podpis { font-size: 14px; color: var(--seryi); }
.tiho, .poyasnenie { color: var(--seryi); }

a { color: var(--sinii); transition: color var(--perehod); }
main a:not([class]):hover, .stroka a:hover { color: var(--akcent-tekst); text-decoration: none; }

/* Длинные имена и слова не распирают ячейку и карточку: ломаются по месту
 * (`overflow-wrap`), но не по слогам. Перенос по правилам языка на телефоне
 * резал обычные слова в узких ячейках — «на-личные», «при-ход» — и читался как
 * опечатка (штаб, 17.10, 22:28: «ничего не переносится по слогам»). */
.karta, .stroka, .tablica td, .zay-karta, .soobshchenie, .beda, .prinyato {
  overflow-wrap: anywhere;
  hyphens: manual;
}

/* Обязательное поле помечается звёздочкой у подписи — само, по `required` у
 * поля, если подпись стоит прямо перед ним. Где подпись обнимает поле или
 * стоит не вплотную, звёздочку ставит шаблон: `<span class="obyazatelno">*</span>`.
 * На входе не помечаем: там обязательно всё, и звёздочки были бы шумом. */
label:has(+ :is(input, select, textarea):required):not(.vhod label)::after {
  content: " *";
  color: var(--akcent);
  font-weight: 600;
}
.obyazatelno { margin-left: 2px; color: var(--akcent); font-weight: 600; }

.beda .nomer, .nomer-zaprosa, .nomer-zaprosa .chislo { font-family: var(--kod); }

/* --- каркас: боковая панель ----------------------------------------------- */

/* Сетка вешается на body только там, где есть шапка: у страницы входа её нет,
 * и та же сетка поставила бы форму входа в узкую левую колонку. */
body:has(> .shapka) {
  display: grid;
  grid-template-columns: var(--shirina-paneli) minmax(0, 1fr);
  min-height: 100vh;
}

.shapka {
  /* Неподвижная, во всю высоту окна. `sticky` в ячейке сетки держалась, пока
   * строка сетки не кончалась, и на длинной странице панель обрывалась. Левая
   * колонка сетки остаётся местом под неё; `main` поставлен во вторую явно. */
  position: fixed;
  top: 0;
  bottom: 0;
  left: 0;
  z-index: 20;
  width: var(--shirina-paneli);
  /* `auto`, а не число: у klan.css здесь 56px от верхней полосы, и без сброса
   * панель схлопывалась в неё, пряча меню. Высоту задают top и bottom. */
  height: auto;
  display: grid;
  grid-template-rows: auto 1fr auto auto;
  align-items: start;
  gap: 0;
  padding: 18px 12px 14px;
  background: var(--kartochka);
  border-bottom: none;
  border-right: 1px solid var(--razdelitel);
  overflow-y: auto;
}
.shapka .znak {
  padding: 4px 12px 18px;
  font-size: 15px;
  letter-spacing: .14em;
  color: var(--sinii);
}
.shapka nav { display: flex; flex-direction: column; gap: 2px; }
.shapka nav a,
.shapka .kto,
.shapka form button {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 40px;
  padding: 8px 12px;
  border-radius: var(--radius);
  color: #3f3f46;
  font-size: 15px;
  line-height: 1.2;
  text-decoration: none;
  white-space: nowrap;
  transition: background var(--perehod), color var(--perehod);
}
.shapka nav a:hover,
a.kto:hover,
.shapka form button:hover { background: var(--navedenie); color: var(--sinii); text-decoration: none; }
.shapka nav a.zdes { background: var(--akcent); color: #fff; font-weight: 600; }
.shapka nav a.zdes:hover { background: var(--akcent); color: #fff; }

/* Иконка пункта — встроенный спрайт (`<svg class="ik"><use href="#ik-…">`,
 * `shablony.sprait_ikonok`), красится цветом текста пункта через currentColor:
 * у активного белая, у остальных серая. Прежде — маской CSS на внешний файл,
 * и меню около секунды стояло без значков, пока файлы догружались (штаб 18.10,
 * 19:06). Размер задан здесь, место под значок есть сразу. */
.ik {
  flex: none;
  width: 22px;
  height: 22px;
  opacity: .85;
}
.shapka nav a.zdes .ik { opacity: 1; }
/* Сам спрайт — вне потока: атрибут `hidden` у SVG внутри HTML его не прячет, и
 * без этого он занимал 300×150 и первую ячейку сетки страницы — плашка «ДЕМО»
 * и шапка съезжали. Символы по `<use>` из такого спрайта рисуются. */
.sprait-ikonok { position: absolute; width: 0; height: 0; overflow: hidden; }

/* Кнопка меню телефона и её флажок на широком экране не нужны. `display: none`
 * снимает их и с сетки панели: ряды сетки (знак, меню, логин, выход) не
 * сдвигаются. */
.menyu-flag, .menyu-knopka { display: none; }

/* Логин и «Выйти» — внизу панели, строками того же ряда, что меню. */
.shapka .kto { margin-top: 12px; border-top: 1px solid var(--razdelitel);
               border-radius: 0 0 var(--radius) var(--radius); padding-top: 14px;
               white-space: normal; overflow-wrap: anywhere; color: var(--seryi); font-size: 14px; }
a.kto:hover { border-radius: var(--radius); }
.shapka form { margin: 0; }
.shapka form button {
  width: 100%;
  justify-content: flex-start;
  border: none;
  background: transparent;
  font: inherit;
  font-size: 14px;
  color: var(--seryi);
  cursor: pointer;
}

main {
  width: 100%;
  max-width: 1148px;              /* ~1100px содержимого + поля */
  margin: 0 auto;
  padding: 28px 24px 64px;
  min-width: 0;
}
/* Календарь — во всю ширину: сетке недели тесно в полосе чтения. */
main:has(.kal-telo) { max-width: none; }
body:has(> .shapka) > main { grid-column: 2; }

/* Плашка демо-стенда (`templates/_demo.html`): полоса во всю ширину над всем.
 * На широком экране с панелью — первая строка сетки через обе колонки высотой
 * 32px (20 + 6·2), и неподвижная панель опускается ровно на неё; строка
 * содержимого берёт остаток, иначе сетка растянула бы и строку плашки. */
.demo-plashka {
  padding: 6px 16px;
  background: #b42318;
  color: #fff;
  font-size: 14px;
  font-weight: 600;
  line-height: 20px;
  text-align: center;
}
body:has(> .shapka):has(> .demo-plashka) { grid-template-rows: auto 1fr; }
body:has(> .shapka) > .demo-plashka {
  grid-column: 1 / -1;
  height: 32px;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
body:has(> .demo-plashka) > .shapka { top: 32px; }
@media (max-width: 899px) {
  /* Узкий экран: панель в потоке, плашка — обычная полоса над ней и переносится. */
  body:has(> .shapka) > .demo-plashka { height: auto; white-space: normal; }
}

/* Узкий экран: панель становится верхней полосой с прокруткой вбок. */
@media (max-width: 899px) {
  body:has(> .shapka) { display: block; }
  /* Полоса не липкая: липкая панель занятия (`.kal-panel`, top 16px) уезжала
   * бы под неё, а высоту полосы окно 1 знать не обязано. */
  .shapka {
    position: static;
    width: auto;
    height: auto;
    display: flex;
    flex-wrap: nowrap;
    align-items: center;
    gap: 4px;
    padding: 8px 12px;
    border-right: none;
    border-bottom: 1px solid var(--razdelitel);
    overflow-x: auto;
    overflow-y: hidden;
    scrollbar-width: none;
  }
  .shapka::-webkit-scrollbar { display: none; }
  .shapka .znak { padding: 0 8px 0 4px; font-size: 14px; }
  .shapka nav { flex-direction: row; gap: 2px; flex: none; }
  .shapka nav a, .shapka .kto, .shapka form button {
    min-height: 40px; padding: 6px 10px; gap: 6px; font-size: 14px;
  }
  .shapka nav .ik, .shapka .kto .ik, .shapka form button .ik { width: 18px; height: 18px; }
  .shapka .kto { margin: 0 0 0 8px; border-top: none; padding-top: 6px; border-radius: var(--radius);
                flex: none; white-space: nowrap; }
  .shapka form button { width: auto; }
}

/* Телефон и планшет: в полосе — знак и кнопка «Меню»; пункты, логин и выход
 * раскрываются под ней сеткой по флажку. Флажок не `display: none`, а убран
 * из вида: так он остаётся в порядке обхода с клавиатуры, и рамка фокуса
 * рисуется на кнопке. Цель нажатия — 44 px, по пальцу. До 899 px, а не до
 * 620: на планшете (768) полоса пунктов была шире экрана (≈1400 px), полоса
 * прокрутки скрыта, и половина меню просто не была видна (находка T3). */
@media (max-width: 899px) {
  .shapka { flex-wrap: wrap; overflow: visible; padding: 8px 16px; row-gap: 8px; }
  .shapka .znak { flex: 1; }
  .menyu-flag { display: block; position: absolute; width: 1px; height: 1px; opacity: 0; }
  .menyu-knopka {
    display: flex; align-items: center; gap: 8px; min-height: 44px; padding: 8px 14px;
    border: 1px solid var(--razdelitel); border-radius: var(--radius);
    font-size: 15px; color: var(--sinii); cursor: pointer; user-select: none;
  }
  .menyu-knopka .ik { width: 20px; height: 20px; opacity: 1; }
  .menyu-flag:focus-visible + .menyu-knopka { outline: 2px solid var(--sinii); outline-offset: 2px; }
  .menyu-flag:checked + .menyu-knopka { background: var(--navedenie); }
  .shapka nav, .shapka .kto, .shapka form { display: none; }
  .menyu-flag:checked ~ nav {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 4px;
    flex-basis: 100%;
  }
  .menyu-flag:checked ~ .kto, .menyu-flag:checked ~ form { display: flex; flex: 1 1 40%; margin: 0; }
  .menyu-flag:checked ~ form button { width: 100%; }
  .shapka nav a, .shapka .kto, .shapka form button { min-height: 44px; font-size: 15px; white-space: normal; }
}
@media (max-width: 620px) {
  main { padding: 18px 16px 48px; }
  h1 { font-size: 22px; }
}

/* Режим «Скрыть персональные данные» (`apps/web/skrytie.py`): глаз рядом со
 * знаком на любой ширине — правило `.shapka form { display: none }` телефона
 * его не прячет, у формы свой класс посильнее. Цель нажатия — 44 px. */
.shapka-verh { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.shapka-verh { padding-bottom: 14px; }
.shapka-verh .znak { padding-bottom: 4px; }
.shapka .skryt-forma { display: flex; margin: 0; flex: none; }
.shapka .skryt-knopka {
  width: 44px; min-width: 44px; min-height: 44px; padding: 0;
  justify-content: center; border-radius: 50%; color: var(--seryi);
}
.shapka .skryt-knopka .ik { width: 22px; height: 22px; }
.shapka .skryt-knopka.vklyucheno,
.shapka .skryt-knopka.vklyucheno:hover { background: var(--akcent); color: #fff; }
.skryt-plashka {
  display: flex; align-items: center; gap: 8px;
  margin: 0 0 16px; padding: 8px 14px; border-radius: var(--radius);
  background: var(--navedenie); color: var(--sinii); font-size: 14px; font-weight: 600;
}
.skryt-plashka .ik { width: 18px; height: 18px; }
@media (max-width: 899px) {
  .shapka-verh { flex: 1; padding-bottom: 0; }
  .shapka-verh .znak { flex: 1; padding-bottom: 0; }
}

/* --- карточки ------------------------------------------------------------- */

.karta {
  border: none;
  border-radius: var(--radius-karta);
  box-shadow: var(--ten);
  padding: 20px 24px;
}
@media (max-width: 620px) { .karta { padding: 16px; } }

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

/* Вторичная — по умолчанию: светлая заливка акцента и акцентный текст. */
button,
a.knopkoy {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 40px;
  padding: 0 16px;
  border: none;
  border-radius: var(--radius);
  background: var(--akcent-10);
  color: var(--akcent-tekst);
  font: inherit;
  font-size: 15px;
  font-weight: 600;
  line-height: 1.2;
  cursor: pointer;
  text-decoration: none;
  transition: background var(--perehod), color var(--perehod), box-shadow var(--perehod);
}
button:hover, a.knopkoy:hover { background: #f9e2d6; border-color: transparent; text-decoration: none; }
button:active, a.knopkoy:active { background: #f4cfbb; }

button.glavnaya { background: var(--akcent); color: #fff; border: none; }
button.glavnaya:hover { background: #b54210; filter: none; }
button.glavnaya:active { background: #a03a0e; }

/* Тихая — только текст. */
button.tihaya {
  min-height: 32px;
  padding: 0 10px;
  background: transparent;
  color: var(--seryi);
  font-weight: 400;
  font-size: 14px;
}
button.tihaya:hover { background: var(--navedenie); color: var(--sinii); }

/* Вторичная явным классом — для кнопки, которую из основной переводят во
 * вторую (например «Пришёл» на «Сегодня»): вид тот же, что у кнопки без класса. */
button.vtorichnaya, a.knopkoy.vtorichnaya { background: var(--akcent-10); color: var(--akcent-tekst); }
button.vtorichnaya:hover, a.knopkoy.vtorichnaya:hover { background: #f9e2d6; }
button.vtorichnaya:active, a.knopkoy.vtorichnaya:active { background: #f4cfbb; }

/* Опасная — отмена, удаление, сгорание: красный текст на светлом. Класс
 * `opasnaya` на кнопке или ссылке-кнопке; пока окна не вывели его в разметку,
 * те же формы узнаются по адресу. Класс сильнее `glavnaya`: опасное действие
 * не бывает оранжевым. */
button.opasnaya, a.knopkoy.opasnaya, button.glavnaya.opasnaya,
form[action$="/otmenit"] button,
form[action$="/otmena"] button,
form[action^="/abonementy/sgoranie"] button {
  background: var(--oshibka-fon);
  color: var(--oshibka);
}
button.opasnaya:hover, button.opasnaya:active,
a.knopkoy.opasnaya:hover, a.knopkoy.opasnaya:active,
form[action$="/otmenit"] button:hover,
form[action$="/otmena"] button:hover,
form[action^="/abonementy/sgoranie"] button:hover,
form[action$="/otmenit"] button:active,
form[action$="/otmena"] button:active,
form[action^="/abonementy/sgoranie"] button:active { background: #fbe1df; color: #99190f; }

/* Неактивная сильнее и основной, и опасной: выключенная красная «Сжечь»
 * выглядела бы нажимаемой. */
button[disabled], button[disabled]:hover,
button.glavnaya[disabled], button.opasnaya[disabled], button.glavnaya.opasnaya[disabled] {
  background: var(--fon);
  color: #8e8e96;           /* неактивное — вне требования 4.5:1 (WCAG 1.4.3) */
  cursor: default;
}

/* Кольцо фокуса — клавиатурному пользователю, не мыши; и никогда не `none`. */
:focus-visible { outline: 2px solid var(--akcent-yarkiy); outline-offset: 2px; }
button:focus-visible, a.knopkoy:focus-visible, .shapka a:focus-visible {
  outline: 2px solid var(--akcent-yarkiy);
  outline-offset: 2px;
}

/* --- поля ----------------------------------------------------------------- */

input[type=text], input[type=password], input[type=search], input[type=date],
input[type=number], input[type=time], input[type=datetime-local],
input[type=email], input[type=tel], select, textarea,
.forma select {
  min-height: 40px;
  padding: 8px 12px;
  border: 1px solid var(--razdelitel);
  border-radius: var(--radius);
  background: var(--kartochka);
  color: var(--sinii);
  font: inherit;
  font-size: 15px;
  transition: background var(--perehod), box-shadow var(--perehod);
}
/* Серая заливка без рамки — только внутри белой карточки. На фоне страницы
 * (выбор периода в отчётах, дата в календаре) такое поле сливается с фоном
 * до невидимости, поэтому там оно белое с рамкой. */
.karta :is(input[type=text], input[type=password], input[type=search], input[type=date],
  input[type=number], input[type=time], input[type=datetime-local], input[type=email],
  input[type=tel], select, textarea),
main > form.forma :is(input[type=text], input[type=search], input[type=date],
  input[type=number], input[type=time], input[type=datetime-local], select, textarea) {
  border-color: transparent;
  background: var(--pole);
}
.karta :is(input, select, textarea):hover,
main > form.forma :is(input, select, textarea):hover { background: #ececef; }
/* Форма, стоящая прямо в `main` без карточки (новое занятие, правка занятия),
 * оформляется карточкой: иначе два десятка полей висят на сером фоне. */
main > form.forma {
  max-width: 560px;
  padding: 24px;
  background: var(--kartochka);
  border-radius: var(--radius-karta);
  box-shadow: var(--ten);
}
@media (max-width: 620px) { main > form.forma { padding: 16px; } }
textarea { min-height: 88px; line-height: 1.45; width: 100%; }
input::placeholder, textarea::placeholder { color: var(--seryi); }
input:not([type=checkbox]):not([type=radio]):focus, select:focus, textarea:focus,
.karta :is(input:not([type=checkbox]):not([type=radio]), select, textarea):focus,
main > form.forma :is(input:not([type=checkbox]):not([type=radio]), select, textarea):focus {
  outline: none;
  background: var(--kartochka);
  border-color: var(--akcent-yarkiy);
  box-shadow: 0 0 0 2px rgba(236, 101, 43, .25);
}
input[type=checkbox], input[type=radio] { accent-color: var(--akcent); width: 16px; height: 16px; }
/* Выбор причины в строке списка остаётся узким, но той же формы. */
.ryadom select, .karta .ryadom select { min-height: 32px; padding: 4px 8px; font-size: 14px;
                border: none; background: var(--pole); }

.forma label, .vhod label, .period label { font-size: 13px; color: var(--seryi); }

/* Ошибка формы — мягкий красный фон. */
.beda {
  border: none;
  border-radius: var(--radius);
  background: var(--oshibka-fon);
  color: #5c1610;
  padding: 12px 14px;
}
.beda a { color: var(--oshibka); text-decoration: underline; }
.prinyato {
  border: none;
  border-radius: var(--radius);
  background: var(--uspeh-fon);
  color: #14532d;
}

/* --- вход ----------------------------------------------------------------- */

.vhod { max-width: 380px; margin: 12vh auto 48px; padding: 0 16px; }
.vhod .karta { padding: 32px 28px 28px; }
.vhod h1 { letter-spacing: .14em; font-size: 22px; }
.vhod .podpis { margin-bottom: 20px; }
.vhod label { margin: 16px 0 6px; }
.vhod button { width: 100%; margin-top: 24px; }

/* --- строки списков (как список диалогов) --------------------------------- */

/* Строка вытянута до краёв карточки, чтобы подсветка наведения шла от края до
 * края, а разделитель — только под текстом: линия от края режет список на
 * полосы, от текста — отделяет записи. Отступ карточки 24px, на узком 16px. */
/* `.zay-prosrochena` — полоса окна 2 со своим отступом; её не растягиваем. */
.karta > .stroka:not(.zay-prosrochena), .karta > div > .stroka:not(.zay-prosrochena),
#stroki > .stroka:not(.zay-prosrochena) {
  margin: 0 -24px;
  padding: 10px 24px;
}
/* В боковой панели календаря у карточки нет боковых полей — тянуть некуда. */
.kal-panel .karta > .stroka, .kal-panel .karta > div > .stroka { margin: 0; padding: 10px 0; }
.kal-panel .stroka + .stroka { background-size: 100% 1px; background-position: 0 0; }
/* Там же кнопки отметки уходят под имя во всю ширину — предел 45% их сминал. */
.kal-panel .stroka .sboku { max-width: none; }
.stroka {
  align-items: center;
  min-height: 56px;
  gap: 16px;
  border-bottom: none;
  border-radius: 0;
  transition: background-color var(--perehod);
}
.stroka + .stroka {
  background-image: linear-gradient(var(--razdelitel), var(--razdelitel));
  background-repeat: no-repeat;
  background-size: calc(100% - 48px) 1px;
  background-position: 24px 0;
}
.stroka:hover { background-color: var(--navedenie); }
/* Выделенной разметка строку не помечает; ближайшее — строка, в которой
 * сейчас фокус (нажата «Открыть» в переписке). */
.stroka:focus-within { background-color: var(--akcent-8); }
.stroka .glavnoe { min-width: 0; line-height: 1.4; }
/* Первая ссылка строки — имя или заголовок. */
.stroka .glavnoe > a:first-child { font-weight: 600; }
/* Фамилию по слогам не переносим: «Алексан-дровна» читается как опечатка.
 * Длинное имя ломается по месту (overflow-wrap выше), а не по правилам языка. */
.stroka .glavnoe > a:first-child, .tablica td > a:first-child, .tablica td > .avatar + a,
h1, h2, .pusto,
.podpis { hyphens: manual; }
.stroka .glavnoe .tiho, .stroka .glavnoe .poyasnenie { font-size: 14px; }
.stroka .sboku { font-size: 13px; line-height: 1.4; flex: none; max-width: 45%; }
@media (max-width: 620px) {
  .karta > .stroka:not(.zay-prosrochena), .karta > div > .stroka:not(.zay-prosrochena),
  #stroki > .stroka:not(.zay-prosrochena) { margin: 0 -16px; padding: 10px 16px; }
  .stroka + .stroka { background-size: calc(100% - 32px) 1px; background-position: 16px 0; }
  .stroka .sboku { max-width: none; }
}

/* Круг с инициалами — первым элементом строки: `<span class="avatar">ИП</span>`.
 * Цвет один, спокойный: разные цвета по человеку потребовали бы хеша в
 * разметке, а одинаковый круг и так ловит глаз как «здесь человек». Окно,
 * которое захочет различать, ставит `avatar-1…avatar-10` — это палитра
 * направлений, тёмный текст на пастели, контраст от 11.8:1. */
.avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--akcent-10);
  color: var(--akcent-tekst);
  font-size: 14px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: .02em;
  text-transform: uppercase;
  user-select: none;
  overflow: hidden;
  white-space: nowrap;
}
.avatar-1 { background: var(--napravlenie-1); color: var(--kal-tekst-bloka); }
.avatar-2 { background: var(--napravlenie-2); color: var(--kal-tekst-bloka); }
.avatar-3 { background: var(--napravlenie-3); color: var(--kal-tekst-bloka); }
.avatar-4 { background: var(--napravlenie-4); color: var(--kal-tekst-bloka); }
.avatar-5 { background: var(--napravlenie-5); color: var(--kal-tekst-bloka); }
.avatar-6 { background: var(--napravlenie-6); color: var(--kal-tekst-bloka); }
.avatar-7 { background: var(--napravlenie-7); color: var(--kal-tekst-bloka); }
.avatar-8 { background: var(--napravlenie-8); color: var(--kal-tekst-bloka); }
.avatar-9 { background: var(--napravlenie-9); color: var(--kal-tekst-bloka); }
.avatar-10 { background: var(--napravlenie-10); color: var(--kal-tekst-bloka); }
/* В строке с кругом разделитель начинается от текста, а не от круга — как в
 * списке диалогов: 24px поле + 40px круг + 16px зазор. */
.stroka:has(> .avatar) { min-height: 64px; }
.stroka + .stroka:has(> .avatar) {
  background-size: calc(100% - 104px) 1px;
  background-position: 80px 0;
}
/* В панели календаря у карточки нет полей — разделитель от края панели. */
.kal-panel .stroka + .stroka:has(> .avatar) { background-size: 100% 1px; background-position: 0 0; }
/* В таблице круг меньше: строка таблицы плотнее строки списка. */
.tablica .avatar { width: 32px; height: 32px; font-size: 12px; margin-right: 10px; vertical-align: middle; }
@media (max-width: 620px) {
  .stroka + .stroka:has(> .avatar) { background-size: calc(100% - 88px) 1px; background-position: 72px 0; }
  /* На телефоне круг, имя и правая колонка в одну строку не встают: имя
   * сминалось в столбик по слову. Правая колонка уходит под текст, с отступом
   * на круг (40px + зазор 16px), — как подзаголовок в списке диалогов. */
  .stroka:has(> .avatar) { flex-wrap: wrap; row-gap: 2px; }
  .stroka:has(> .avatar) > .glavnoe { flex: 1 1 0; }
  .stroka:has(> .avatar) > .sboku { flex: 1 0 100%; max-width: none; padding-left: 56px; text-align: left; }
  /* В строке без круга имени оставлена хотя бы половина: правая колонка,
   * которая не помещается рядом, переносится целиком, а не сжимает имя. */
  .stroka > .glavnoe { flex: 1 1 180px; }
}

/* Сообщения переписки — пузыри, как в мессенджере: клиент слева на светлом, клуб
 * справа на акцентном, время мелко внутри. Сторону показывает пузырь, а не слово. */
.perepiska-lenta { display: flex; flex-direction: column; gap: 6px; margin: 12px 0 16px; }
.soobshchenie {
  max-width: 80%;
  padding: 8px 12px 6px;
  border: none;
  border-radius: 16px;
  background: var(--pole);
  align-self: flex-start;
}
.soobshchenie:last-child { border-bottom: none; }
.soobshchenie.nashe { align-self: flex-end; padding-left: 12px; background: var(--kal-segodnya-fon); }
/* Переводы строк клиента сохраняются: «адрес\nвремя\nимя ребёнка» не
 * сливается в одну строку. */
.soobshchenie .tekst { margin: 0; color: var(--sinii); white-space: pre-line; }
.soobshchenie.nashe .tekst { color: var(--sinii); }
.soobshchenie .vremya { display: block; margin-top: 2px; font-size: 11px; color: var(--seryi); text-align: right; }
/* Строка списка чатов — как в Telegram, одной формы на любой ширине: круг со
 * значком канала; сверху имя и время справа; снизу канал с превью серой строкой
 * и счётчик справа. Сетка, а не перенос: имя не сминается в столбик. */
.stroka.chat-ryad {
  display: grid;
  grid-template-columns: 48px minmax(0, 1fr) auto;
  grid-template-areas: "av imya kogda" "av prevyu schet";
  column-gap: 12px;
  row-gap: 2px;
  align-items: center;
  padding-top: 10px;
  padding-bottom: 10px;
}
.chat-ryad > .chat-avatar { grid-area: av; position: relative; width: 48px; height: 48px;
  font-size: 16px; overflow: visible; }
.chat-ryad > .chat-imya { grid-area: imya; min-width: 0; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; font-size: 16px; }
.chat-ryad.chat-novoe > .chat-imya { font-weight: 600; }
.chat-ryad > .lenta-kogda { grid-area: kogda; font-size: 13px; color: var(--seryi); }
.chat-ryad.chat-novoe > .lenta-kogda { color: var(--akcent); }
/* Превью — до двух строк, как в списке чатов на телефоне: метка «новый клиент»
 * не должна уходить за многоточие. */
.chat-ryad > .chat-prevyu { grid-area: prevyu; min-width: 0; overflow: hidden; font-size: 14px;
  color: var(--seryi); display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  line-clamp: 2; }
/* «новый клиент» в строке — мельче имени и превью: подсказка, а не заголовок. */
.chat-ryad > .chat-prevyu .metka { margin-left: 4px; padding: 0 6px; font-size: 11px; }
.chat-ryad > .chat-schet { grid-area: schet; display: flex; align-items: center; gap: 6px;
  justify-content: flex-end; }
/* Значок канала — кружок в углу аватара, как значок мессенджера у контакта. */
.kanal-znak {
  position: absolute; right: -4px; bottom: -4px;
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 20px; height: 20px; padding: 0 3px; border-radius: 10px;
  border: 2px solid var(--kartochka);
  background: #71717a; color: #fff; font-size: 9px; font-weight: 700; letter-spacing: 0;
}
/* Круг канала на карточке «Мессенджеры клуба» — тот же цвет, что значок в чате. */
.kanal-krug {
  display: inline-flex; align-items: center; justify-content: center; flex: none;
  width: 40px; height: 40px; border-radius: 50%;
  background: #71717a; color: #fff; font-size: 13px; font-weight: 700;
}
/* Сетка, а не перенос: на телефоне статус остаётся справа, а не уезжает под
 * текст; «Отключить» — под статусом. */
.stroka.kanal-karta { display: grid; grid-template-columns: 40px minmax(0, 1fr) auto;
  column-gap: 12px; align-items: start; }
.kanal-karta > .sboku { display: flex; flex-direction: column; align-items: flex-end; gap: 4px;
  max-width: none; padding-left: 0; text-align: right; }
.kanal-karta > .sboku form { margin: 0; }
.kanal-karta .kanal-fraza { display: block; }
.kanal-telegram { background: #1d7fc1; }
.kanal-whatsapp { background: #1a8f4e; }
.kanal-vk { background: #2161c4; }
.kanal-max { background: #6a3fd1; }
.kanal-instagram_direct { background: #c1356f; }
/* Разделитель — от текста, а не от круга: 24px поле + 48px круг + 12px зазор. */
.stroka + .stroka.chat-ryad { background-size: calc(100% - 108px) 1px; background-position: 84px 0; }
/* Поиск по чатам — над списком, во всю ширину. */
.chat-poisk { display: flex; gap: 8px; align-items: center; margin: 0 0 12px; }
.chat-poisk input[type="search"] { flex: 1 1 auto; min-width: 0; margin: 0; min-height: 44px;
  border-radius: 22px; padding: 0 16px; }
@media (max-width: 620px) {
  .stroka + .stroka.chat-ryad { background-size: calc(100% - 92px) 1px; background-position: 76px 0; }
}
/* Чат как в мессенджере (шаг 3 волны 4). Строка ленты нажимается целиком;
 * шапка чата с действиями; быстрые ответы лентой над полем; поле закреплено
 * внизу. На телефоне чат — отдельный экран: открытый чат прячет список, «‹ Назад»
 * возвращает к нему. */
.chat-stroka { cursor: pointer; }
.chat-stroka:focus-visible { outline: 2px solid var(--akcent); outline-offset: 2px; }
.chat-nazad { display: none; }
.chat-shapka h2 { margin: 0; font-size: 17px; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; }
/* Шапка чата одной строкой (штаб 02:50): «‹», круг, имя с каналом, справа «⋯». */
.chat-verh { display: flex; align-items: center; gap: 10px; }
.chat-verh .chat-kto { flex: 1 1 auto; min-width: 0; display: block; }
.chat-verh .chat-nazad { font-size: 28px; line-height: 1; padding: 6px 8px 6px 0; min-width: 44px;
  min-height: 44px; align-items: center; color: var(--akcent); text-decoration: none; }
/* «⋯» — список действий без скрипта: details/summary, раскрывается под шапкой. */
.chat-menyu { position: relative; flex: none; }
.chat-menyu > summary { list-style: none; display: inline-flex; align-items: center;
  justify-content: center; width: 44px; height: 44px; border-radius: 50%; cursor: pointer;
  font-size: 24px; line-height: 1; color: var(--seryi); user-select: none; }
.chat-menyu > summary::-webkit-details-marker { display: none; }
/* Общий треугольник раскрывашки (`main details > summary::before`) у «⋯» лишний;
 * правило общего вида стоит ниже по файлу, поэтому — с той же опорой на `main`. */
main .chat-menyu > summary::before, main .chat-menyu[open] > summary::before { content: none; }
.chat-menyu > summary:hover, .chat-menyu[open] > summary { background: var(--navedenie); }
.chat-menyu-spisok { position: absolute; right: 0; top: 48px; z-index: 20; width: min(320px, 86vw);
  display: flex; flex-direction: column; padding: 6px; border-radius: var(--radius);
  background: var(--kartochka); box-shadow: 0 8px 24px rgba(0, 0, 0, .14); }
.chat-menyu-spisok > a, .chat-menyu-spisok button { display: flex; align-items: center;
  width: 100%; min-height: 44px; padding: 0 12px; border: 0; border-radius: 8px;
  background: none; color: var(--sinii); font: inherit; text-align: left; text-decoration: none;
  justify-content: flex-start; cursor: pointer; }
.chat-menyu-spisok > a:hover, .chat-menyu-spisok button:hover { background: var(--navedenie); }
.chat-menyu-spisok form { margin: 0; }
.chat-menyu-spisok .karta { margin: 4px 0; padding: 8px 12px; box-shadow: none; }
.chat-menyu-podpis { margin: 6px 12px 2px; font-size: 12px; color: var(--seryi); }
/* Круглая «Отправить» со стрелкой. */
.otvet-stroka .chat-otpravit { width: 44px; height: 44px; min-height: 44px; padding: 0;
  border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; }
/* Шапка чата — круг и имя рядом, ниже серой строкой канал (как в Telegram). */
.chat-verh .chat-avatar { width: 40px; height: 40px; font-size: 14px; }
.chat-podpis { margin: 2px 0 0; font-size: 13px; color: var(--seryi); }
.chat-podpis .metka { margin-left: 4px; padding: 0 6px; font-size: 11px; }
/* Разделитель дня между пузырями — по центру, мелко, на подложке. */
.chat-den { align-self: center; margin: 8px 0 2px; }
.chat-den span { display: inline-block; padding: 2px 10px; border-radius: 10px;
  background: var(--fon); color: var(--seryi); font-size: 12px; }
/* Вложение — плиткой крупно: вид словом и где открыть. */
.chat-vlozhenie { display: flex; flex-direction: column; gap: 2px; min-width: 180px;
  padding: 10px 12px; border-radius: 12px; background: var(--kartochka); }
.chat-vlozhenie-vid { font-size: 16px; font-weight: 600; }
/* Галочки доставки у исходящего — в строке времени; прочитано — акцентом. */
.soobshchenie .dostavka { margin-left: 4px; letter-spacing: -2px; }
.soobshchenie .dostavka-read { color: var(--akcent); }
.soobshchenie .dostavka-net { letter-spacing: 0; color: var(--oshibka); }
.chat-deystviya { display: flex; flex-wrap: wrap; gap: 8px; margin: 8px 0 0; }
/* В шапке чата действия — одной строкой с прокруткой вбок, как кнопки под
 * профилем в мессенджере: на телефоне они не съедают пол-экрана. */
.chat-shapka .chat-deystviya { flex-wrap: nowrap; overflow-x: auto; margin-top: 10px; }
.chat-shapka .chat-deystviya > a { flex: 0 0 auto; white-space: nowrap; }
/* Быстрые ответы — плитками над полем, как подсказки-кнопки в мессенджере:
 * обведённые, крупные под палец, лентой с прокруткой вбок. */
.bystrye-otvety { display: flex; gap: 8px; overflow-x: auto; margin: 0 0 8px; padding-bottom: 2px; }
.bystrye-otvety button { flex: 0 0 auto; white-space: nowrap; min-height: 40px; padding: 0 16px;
  border: 1px solid var(--razdelitel); border-radius: 20px; background: var(--kartochka);
  color: var(--akcent); font-weight: 500; }
.bystrye-otvety button:hover { background: var(--navedenie); }
.otvet-zona { position: sticky; bottom: 0; z-index: 5; padding: 8px 0; background: var(--kartochka); }
/* Карточка чата — не прокручиваемый контейнер: общее `.karta { overflow-x: auto }`
 * (klan.css) делало #dialog контейнером прокрутки, и поле ответа прилипало внутри
 * карточки, а «⋯» обрезалось её рамкой (ревью T0 03:30). */
#dialog.karta { overflow: visible; }
.chat-assistent { margin: 0 0 6px; font-size: 13px; color: var(--seryi); }
@media (max-width: 899px) {
  /* Над нижней панелью вкладок (61px + домашняя полоса iPhone), а не под ней. */
  body:has(.vkladki-niz) .otvet-zona { bottom: calc(61px + env(safe-area-inset-bottom)); }
}
/* Таблетки «Ждут ответа · Все» — одной высоты. */
.deystviya.perepiska-spisok .abn-otbor { display: inline-flex; align-items: center; height: 40px;
  min-height: 40px; box-sizing: border-box; padding: 0 14px; white-space: nowrap; }
/* До планшета включительно (≤ 820 — там `.dvumya` в klan.css встаёт в одну колонку), и
 * открытый чат оказывался под списком — его приходилось искать прокруткой.
 * Как на телефоне: открытый чат — отдельный экран, «‹ Назад» к списку. */
@media (max-width: 820px) {
  .chat-nazad { display: inline-flex; }
  .dvumya:has(#dialog .chat-shapka) > .karta:first-child,
  main:has(#dialog .chat-shapka) .perepiska-spisok { display: none; }
  /* Ссылка «заявка» в строке ленты — сама не ниже 44 (мобильная приёмка T6:
   * 43×41): строка и так выше, и ссылка растёт внутрь неё. */
  .chat-ryad .chat-schet > a.metka-ssylka { display: inline-flex; align-items: center;
    min-height: 44px; min-width: 44px; margin: -12px 0; padding: 0 0 0 8px;
    background: none; border: 0; border-radius: 0; font-size: 13px; }
  /* Пока чат не открыт, пустая половина «Выберите чат» на телефоне не нужна. */
  #dialog:not(:has(.chat-shapka)) { display: none; }
}
/* Поле ответа и «Отправить» — одной строкой; на телефоне кнопка не уезжает. */
.otvet-stroka { display: flex; gap: 8px; align-items: flex-end; margin-top: 8px; }
.otvet-stroka textarea { flex: 1 1 auto; min-width: 0; margin: 0; resize: vertical; }
.otvet-stroka button { flex: 0 0 auto; min-height: 44px; }

/* --- метки ---------------------------------------------------------------- */

.metka {
  padding: 2px 9px;
  border: none;
  border-radius: 999px;
  background: var(--fon);
  color: #52525b;
  font-size: 12px;
  line-height: 1.5;
  font-weight: 400;
  vertical-align: 1px;
}
.metka.svobodno { background: var(--uspeh-fon); color: var(--uspeh); }
.metka.net-mest { background: #fdf0e7; color: #9a3412; }
.stroka .glavnoe .metka { margin-left: 6px; }

.neprochitano { border-radius: 999px; min-width: 20px; line-height: 20px; }

/* --- таблицы -------------------------------------------------------------- */

/* Липкая шапка: в отчёте за месяц строк больше, чем экран, и без неё
 * столбцы теряют названия на второй прокрутке. Работает сегодня только там,
 * где у предков таблицы нет своей прокрутки: в отчётах на широком экране. В
 * `.zay-tablica` (прокрутка вбок всегда) и на узком экране, где карточке дана
 * прокрутка вбок, шапка остаётся на месте. Линия под шапкой — тенью: при
 * `border-collapse` рамка ячейки вместе с липкой шапкой не едет. */
.tablica th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--kartochka);
  padding: 10px 12px 8px 0;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .04em;
  color: var(--seryi);
  border-bottom: none;
  box-shadow: inset 0 -1px 0 var(--razdelitel);
}
.tablica td { padding: 11px 12px 11px 0; border-bottom-color: #efeff1; vertical-align: top; }
.tablica tbody tr { transition: background-color var(--perehod); }
.tablica tbody tr:hover { background: #fafafa; }
.tablica .k-chislu { font-variant-numeric: tabular-nums; }
.tablica tfoot td { border-top: 1px solid #d4d4d8; font-weight: 600; }
/* На узком экране — прокрутка внутри контейнера, а не всей страницы. */
@media (max-width: 899px) {
  .karta:has(> .tablica), .karta:has(> div > .tablica) { overflow-x: auto; }
}
/* `.tablica.kartochkami` на телефоне и планшете: строка — карточка, ячейка —
 * строка с подписью из `data-podpis`. Прокрутка вбок прятала «Входящих» и
 * «Отказов» за край, а на 768 широкие числовые колонки сжимали текстовые до
 * разрыва слов по буквам («Telegra|m»). */
@media (max-width: 899px) {
  .tablica.kartochkami, .tablica.kartochkami tbody { display: block; width: 100%; }
  .tablica.kartochkami thead { display: none; }
  /* Кнопка «Ждать: аккаунт клуба через Telegram Business» и выбор подключения
   * в одну строку раздвигали карточку за край экрана. */
  .tablica.kartochkami button, .tablica.kartochkami select { max-width: 100%; white-space: normal; text-align: left; }
  .tablica.kartochkami tr { display: block; padding: 10px 0; border-bottom: 1px solid var(--razdelitel); }
  .tablica.kartochkami tbody tr:last-child { border-bottom: none; }
  .tablica.kartochkami td { display: block; padding: 3px 0; border-bottom: none; text-align: left; }
  .tablica.kartochkami td.glavnaya-yacheyka { font-weight: 600; }
  .tablica.kartochkami td[data-podpis]::before { content: attr(data-podpis) ": "; color: var(--seryi); }
  /* Пустое поле («—») в карточке строки не показывается: «Срок шага: —». */
  .tablica.kartochkami td.pustaya { display: none; }
}
/* Подпись шага над полосой — ссылка на список шага, и это должно быть видно. */
.zay-po-shagam a.zay-shag { text-decoration: underline; text-underline-offset: 3px;
  text-decoration-color: var(--seryi); }
/* Карточка канала: название, аккаунт и числа за сутки — каждая строкой. */
.kanal-karta .poyasnenie { display: block; }

/* Крупные числа сводок. */
.odno-chislo .velichina { font-size: 28px; font-weight: 600; letter-spacing: -.01em; }
.odno-chislo { color: var(--seryi); }
.odno-chislo .velichina { color: var(--sinii); }
.odno-chislo .velichina.dengi { color: var(--dengi); }

/* --- пустые состояния и сообщения ----------------------------------------- */

/* Пусто — спокойная фраза по центру карточки, а не строка серого в углу. */
.karta > .pusto, #stroki > .pusto {
  padding: 28px 16px;
  text-align: center;
  color: var(--seryi);
}
.pusto a { color: var(--akcent-tekst); }

.obrezano {
  padding: 10px 14px;
  border-radius: var(--radius);
  background: var(--preduprezhdenie-fon);
  color: var(--preduprezhdenie);
}

/* Страница отказа и сбоя — одна карточка по центру. */
.odna-mysl {
  max-width: 480px;
  margin: 10vh auto;
  padding: 28px;
  background: var(--kartochka);
  border-radius: var(--radius-karta);
  box-shadow: var(--ten);
}

/* Ссылки-действия рядом с кнопками. */
.tihaya-ssylka { color: var(--seryi); }
.tihaya-ssylka:hover { color: var(--akcent-tekst); text-decoration: none; }
.deystviya { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 4px; }
.perelistat a { border: none; border-radius: var(--radius); background: var(--kartochka);
                box-shadow: var(--ten); }
.perelistat a:hover { background: var(--navedenie); }

/* Браузер без `:has` (Safari до 15.4, Firefox до 121): сетка на body не
 * включается, и неподвижная панель легла бы поверх левого края содержимого.
 * Там панель остаётся верхней полосой в потоке — как на узком экране. */
@supports not selector(:has(*)) {
  .shapka { position: static; width: auto; display: flex; flex-wrap: wrap; align-items: center;
            gap: 4px; padding: 8px 12px; border-right: none; border-bottom: 1px solid var(--razdelitel); }
  .shapka nav { flex-direction: row; flex-wrap: wrap; }
  .shapka .kto { margin: 0 0 0 8px; border-top: none; padding-top: 8px; }
}

/* --- печать --------------------------------------------------------------- */

/* Печатная форма согласия наследует основу. У klan.css на печати панель
 * спрятана, но `display: grid` отсюда идёт позже и возвращал её на бумагу —
 * неподвижной, поверх текста на каждом листе, да ещё с пустой колонкой слева.
 * Поэтому печать повторена здесь и сильнее. */
@media print {
  body:has(> .shapka) { display: block; background: #fff; }
  body:has(> .shapka) > .shapka, .shapka.shapka { display: none; }
  main { max-width: none; padding: 0; }
  .karta, main > form.forma { box-shadow: none; border: 1px solid #d4d4d8; break-inside: avoid; }
}

/* --- движение ------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition: none !important; animation: none !important; scroll-behavior: auto !important; }
}

/* Текстовые ссылки под палец (штаб, 17.10, 22:28: «кнопки нажимаются пальцем»).
 * На сенсорном экране ссылка в таблице, в подписи и в форме получает зону
 * нажатия 44px: невидимое поле вокруг текста, а не крупный шрифт — строки
 * таблицы не раздуваются, попасть пальцем можно. Прошлый размер был ~17px. */
@media (pointer: coarse), (max-width: 620px) {
  .tablica td a, .podpis a, .stroka a, .otmena, .abn-otmena, .tihaya-ssylka,
  .deystviya a:not(.knopkoy) {
    display: inline-block;
    min-height: 44px;
    line-height: 44px;
  }
  /* min-height 44, а не 0: строка 1.3 + отступы 12 давали 43,5 — на полпикселя
   * меньше цели, и замер приёмки (T6) считал их мелкими. */
  .tablica td a, .podpis a, .stroka a { line-height: 1.3; padding: 12px 0; min-height: 44px; }
  /* Волна 4 (T5, штаб 12:45): «Ещё фильтры» и прочие свёрнутые блоки, подписи
   * флажков и поля ввода — не меньше 44 px. Ссылки и таблетки отборов
   * закрывает поле поверх ссылки (T2, ниже), своих правил для них нет. */
  main details > summary { min-height: 44px; display: flex; align-items: center; }
  /* Таблетки отборов (абонементы, деньги, журнал) — сама таблетка 44 px, а не
   * только поле поверх неё: мобильная приёмка T6 (15:57) мерит элемент. */
  a.abn-otbor { min-height: 44px; display: inline-flex; align-items: center; }
  /* Остальное, что мобильная приёмка T6 мерит меньше 44 по самому элементу:
   * вкладки отчётов и лояльности, ссылки в строках и плитках, «Скачать для
   * Excel» в подписях, свёрнутый отбор журнала (klan.css задаёт ему 32 px). */
  .vkladki a, .loy-vkladki a, .perelistat a, .gr-plitka a, p.tiho > a, .karta > p > a,
  p.podpis > a, .gr-stroka-statusa a, .stroka .glavnoe a, .stroka .sboku > a {
    min-height: 44px; display: inline-flex; align-items: center;
  }
  .zhr-eshche > summary { min-height: 44px; }
  label.bns-flag, label.ryadom { min-height: 44px; display: inline-flex; align-items: center; gap: 8px; }
  label.bns-flag input, label.ryadom input { width: 22px; height: 22px; }
  main input:not([type=checkbox]):not([type=radio]):not([type=hidden]), main select,
  .forma select, .karta .ryadom select { min-height: 44px; }

  /* Остальные ссылки (штаб, 18.10, 12:00: «в кассу», «Отмена», время чека,
   * вкладки, «Скачать CSV» — по 17–36px): невидимое поле не меньше 44×44
   * поверх ссылки, по её центру. Ни размер, ни отступы самой ссылки не
   * меняются — строки и вкладки не раздвигаются, вид тот же. Условие —
   * «сенсорный экран ИЛИ узкое окно»: планшет с пальцем тоже.
   *
   * Вне правила — где поле одной ссылки легло бы на соседнюю (ревью T0):
   * - сетка расписания, неделя и месяц (`.kal-setka`, `.kal-mesyac`): клетки,
   *   блоки, «ещё N» и числа дней стоят вплотную — поле числа следующей
   *   недели забирало низ «ещё 1»;
   * - блоки занятий (`.kal-blok`, и в «Списке» они крупнее 44 сами);
   * - ссылки в тексте, где их несколько подряд (`p`/`span` с двумя и более
   *   ссылками — кроме строк-кнопок `.deystviya`, `.abn-otbory`,
   *   `.zay-metki`, там каждая ссылка — отдельный блок): перенесённая на две
   *   строки ссылка строит поле от кусков, и оно съезжало на соседнюю
   *   («Заявки» → «Журнал действий» в «Отчёте за день»). */
  main a:not(.kal-blok, .kal-setka a, .kal-mesyac a,
             :is(p, span):not(.deystviya, .abn-otbory, .zay-metki):has(> a ~ a) > a) {
    position: relative;
  }
  main a:not(.kal-blok, .kal-setka a, .kal-mesyac a,
             :is(p, span):not(.deystviya, .abn-otbory, .zay-metki):has(> a ~ a) > a)::after {
    content: "";
    position: absolute;
    left: 50%;
    top: 50%;
    width: max(100%, 44px);
    height: max(100%, 44px);
    transform: translate(-50%, -50%);
  }
  /* Ссылки по нескольку в строке (вне поля выше): каждой — своя высота 44
   * блоком, без переноса посреди ссылки. Блок не дробится на куски, и
   * соседние ссылки не перекрываются: «чек: …» и «Вернуть» в списке оплат,
   * «Красить по», «От кого» в кассе, «Раньше → · Выгрузить CSV» (ревью T0). */
  main :is(p, span):not(.deystviya, .abn-otbory, .zay-metki):has(> a ~ a) > a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }
  /* Переключатель видов расписания обрезает содержимое (`overflow: hidden` —
   * ради скругления выбранного), и поле поверх ссылки срезалось бы до 32px:
   * здесь сама ссылка вырастает до 44. В рядах вкладок и меток, которые
   * переносятся, ряды разводятся так, чтобы поля соседних рядов не
   * перекрывались. */
  .kal-vidy a { display: flex; align-items: center; min-height: 44px; }
  .abn-otbory, .zay-metki { row-gap: 14px; }
  /* Кнопки — 44 и тихие тоже (Волна 4, простота: «Отменить», «Не пришёл»,
   * «Сохранить» — тихие, и было 32px). Сама кнопка выше, а не поле поверх:
   * у кнопки рамки нет, и на телефоне лишние 12px не видны как перемена. */
  button, button.tihaya, a.knopkoy { min-height: 44px; }
  /* Мобильная приёмка (T6, 18.10, 15:57) меряет рамку самого элемента, а поле
   * ::after невидимо и в её замер не входит. Поэтому 44 получают сами:
   * вкладки-ссылки разделов, стрелки и «Сегодня» листания, поля ввода и
   * списки, одиночная ссылка в строке («Скачать чеки за период»). */
  input[type=text], input[type=password], input[type=search], input[type=date],
  input[type=number], input[type=time], input[type=datetime-local],
  input[type=email], input[type=tel], select, textarea, .kal-filtry select, .forma select,
  .karta .ryadom select {
    min-height: 44px;
  }
  /* Число плитки — ссылка на подробности («на проверке 5»): цифра узкая, 17×34. */
  .gr-plitka .velichina a,
  .abn-otbor, .vkladki a, .loy-vkladki a, .perelistat a, .zay-metki .metka {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 44px;
    min-width: 44px;
  }
  main p > a:only-child:not(.knopkoy) { display: inline-flex; align-items: center; min-height: 44px; }
  /* Короткое слово-ссылка («Мои», «Все», «Залы») — не уже 44: ширина у блочной
   * ссылки иначе по тексту. На строчную ссылку min-width не действует, и
   * строка текста не меняется. Сетка расписания — вне правила (вплотную). */
  main a:not(.kal-blok, .kal-setka a, .kal-mesyac a) { min-width: 44px; }
  /* Скрытое поле даты календаря (1px, прозрачное, без нажатий — по нему
   * открывается выбор из заголовка периода) правилом полей выше не раздувать. */
  .kal-js #kal-data { min-height: 0; }
  /* Раскрывашки («Отменить запись», «Другая дата», «Фильтры») — та же зона:
   * строка выше, текст по центру; рамки нет, и вид не меняется. */
  main :is(summary, .zhr-eshche > summary) { padding-block: 12px; min-height: 44px; }
  /* Подпись с флажком («на проверку (5)») — нажимают по всей подписи. */
  main label:has(> input[type=checkbox], > input[type=radio]) {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    min-height: 44px;
  }
}

/* Широкая таблица на телефоне прокручивается внутри своей карточки, а не
 * распирает её за край экрана (T4: таблица состояния каналов на 375). Страница
 * вбок не ездит; карточкой каждую таблицу не переразмечаем — это шаблоны всех
 * экранов, а прокрутка в карточке решает то же одним правилом. */
@media (max-width: 620px) {
  .karta:has(table) { overflow-x: auto; }
  /* Внутри прокрутки столбцы не сжимаются до буквы в строке: подпись строки
   * держит ширину, числа и шапка не переносятся (снимки Волны 4, 375). */
  .karta .tablica th, .karta .tablica td.k-chislu { white-space: nowrap; }
  .karta .tablica td:first-child { min-width: 9em; }
}

/* Свёрнутый блок узнаётся по стрелке. `display: flex` у summary (поле нажатия)
 * снимает встроенный маркер, поэтому стрелка — своя. */
main details > summary { cursor: pointer; color: var(--akcent-tekst); list-style: none; }
main details > summary::-webkit-details-marker { display: none; }
main details > summary::before { content: "▸"; margin-right: 6px; }
main details[open] > summary::before { content: "▾"; }
main select { max-width: 100%; }

/* Блок И (T6, волна 4): свёрнутое «Дополнительно» и «Как это работает» — под
 * палец. Редкие поля прячутся, а не удаляются: форма уходит целиком. */
details.svernuto { margin: 8px 0; }
details.svernuto > summary {
  cursor: pointer; min-height: 44px; display: flex; align-items: center;
  color: var(--sinii); font-size: 15px; list-style: none;
}
details.svernuto > summary::-webkit-details-marker { display: none; }
details.svernuto > summary::before { content: "▸"; margin-right: 8px; color: var(--seryi); }
details.svernuto[open] > summary::before { content: "▾"; }

/* --- графики: плитки, столбцы, полосы, светофор, тепловая карта (волна 4, T6) --- */
/* Сервером, без сценариев: SVG и разметка из templates/_grafiki.html. style= под
 * CSP нельзя — поэтому ширины полос ступенями по 5 % (gr-w-N), цвет только здесь.
 * Палитра и контраст — _plan/itogi/obzor-vizual.md, раздел 2.1. */
:root {
  --grafik: #3b6fb6;           /* счётное: занятия, люди, заявки (5.1:1 к белому) */
  --grafik-fon: #e3ebf7;       /* дорожка полосы — светлая ступень того же тона */
  --grafik-segodnya: var(--akcent-yarkiy); /* «сегодня» на графике — как в календаре */
  --znak-vnimanie: #d97706;    /* жёлтая фигура: светлее текста, чтобы не слиться с красной */
  --teplo-0: #eef3fb; --teplo-1: #c9daf2; --teplo-2: #93b5e3; --teplo-3: #4f82c8; --teplo-4: #23508f;
}

/* Плитки — тот же .odno-chislo, только сеткой: на 375 по две в ряд, не «лесенкой». */
.chisla-vryad.gr-plitki { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 18px 24px; }
.gr-plitka .gr-podpis { font-size: 13px; color: var(--seryi); }
.gr-plitka .velichina { font-variant-numeric: normal; }
.gr-plitka .velichina a { color: inherit; text-decoration: none; }
.gr-sravnenie { font-size: 13px; color: var(--seryi); }
.gr-sravnenie.gr-luchshe { color: var(--uspeh); }
.gr-sravnenie.gr-huzhe { color: var(--oshibka); }
.gr-sravnenie .tiho { color: var(--seryi); }

/* Светофор: точка + слово, никогда цвет один. */
.gr-status { font-size: 13px; font-weight: 600; }
.gr-status::before { content: ""; display: inline-block; width: 8px; height: 8px; margin-right: 6px;
  border-radius: 50%; vertical-align: 1px; background: currentColor; }
.gr-status.ok { color: var(--uspeh); }
.gr-status.vnimanie { color: var(--preduprezhdenie); }
.gr-status.vnimanie::before { background: var(--znak-vnimanie); }
.gr-status.ploho { color: var(--oshibka); }
.gr-status.net { color: var(--seryi); }

/* Столбцы по дням: рисунок не растягивается (скругления целы), подписи — той же сеткой. */
.gr-stolbcy { margin: 12px 0 0; max-width: 420px; }
.gr-stolbcy svg { display: block; width: 100%; height: auto; overflow: visible; }
.gr-stolb path { fill: var(--grafik); }
.gr-stolb.gr-dengi path { fill: var(--dengi); }
.gr-stolb.gr-vydelen path { fill: var(--grafik-segodnya); }
.gr-stolb .gr-nol { fill: var(--razdelitel); }
.gr-stolb .gr-zona { fill: transparent; }
.gr-stolb:hover path { opacity: .8; }
.gr-os { stroke: var(--razdelitel); stroke-width: 1; }
.gr-podpisi { display: flex; font-size: 11px; color: var(--seryi); margin-top: 4px; }
/* Подпись дня не переносится и не распирает ось (min-width: 0): видна каждая
 * n-я, текст выходит на пустых соседей; крайние прижаты к краю рисунка. */
/* Подпись шире столбца выходит в обе стороны поровну (flex-центр), крайние —
 * внутрь рисунка: обычный текст переполняется только вправо. */
.gr-podpisi span { flex: 1 1 0; min-width: 0; display: flex; justify-content: center;
  white-space: nowrap; }
.gr-podpisi span:first-child { justify-content: flex-start; }
.gr-podpisi span:last-child { justify-content: flex-end; }
.gr-podpisi .gr-vydelen { color: var(--sinii); font-weight: 600; }

/* Полоса доли: дорожка светлая, заливка того же тона; полный — тёмно-жёлтым (не
 * путать с оранжевым «сегодня» на столбцах), слово рядом. */
.gr-polosa { display: block; height: 6px; margin-top: 6px; border-radius: 3px;
  background: var(--grafik-fon); overflow: hidden; min-width: 64px; }
.gr-polosa > span { display: block; height: 100%; border-radius: 3px; background: var(--grafik); }
.gr-polosa.polno > span { background: var(--preduprezhdenie); }
.gr-w-0 { width: 0%; }
.gr-w-5 { width: 5%; }
.gr-w-10 { width: 10%; }
.gr-w-15 { width: 15%; }
.gr-w-20 { width: 20%; }
.gr-w-25 { width: 25%; }
.gr-w-30 { width: 30%; }
.gr-w-35 { width: 35%; }
.gr-w-40 { width: 40%; }
.gr-w-45 { width: 45%; }
.gr-w-50 { width: 50%; }
.gr-w-55 { width: 55%; }
.gr-w-60 { width: 60%; }
.gr-w-65 { width: 65%; }
.gr-w-70 { width: 70%; }
.gr-w-75 { width: 75%; }
.gr-w-80 { width: 80%; }
.gr-w-85 { width: 85%; }
.gr-w-90 { width: 90%; }
.gr-w-95 { width: 95%; }
.gr-w-100 { width: 100%; }

/* Шкала остатка ячейками: закрашенная — осталось, пустая — прошло. */
.gr-yachejki { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 6px; }
.gr-yach { width: 10px; height: 10px; border-radius: 50%; border: 1.5px solid var(--grafik);
  background: transparent; }
.gr-yach.est { background: var(--grafik); }

/* Тепловая карта загрузки (зал × час): одна краска, светлее — свободнее. */
/* Карта шире телефона (смена 10–20 — 11 часов) прокручивается внутри обёртки,
 * название зала стоит на месте. */
.gr-teplo-obertka { overflow-x: auto; }
.gr-teplo td.k-chislu { text-align: center; font-size: 12px; min-width: 32px; }
/* Зал × 6–8 часов влезает в 375 без прокрутки: узкие клетки, название обычным
 * регистром (общий th таблиц — капсом и шире). */
.gr-teplo th, .gr-teplo td { padding: 8px 4px; }
.gr-teplo thead th { text-align: center; }
.gr-teplo th[scope="row"] { text-transform: none; letter-spacing: 0; font-size: 13px;
  color: var(--sinii); text-align: left; padding-right: 8px;
  /* Длинное название переносится, а не закрывает карту липкой колонкой. */
  min-width: 6em; max-width: 9em; white-space: normal; overflow-wrap: break-word;
  position: sticky; left: 0; z-index: 2; background: var(--kartochka); }
/* Угол шапки — над прочими клетками шапки (у .tablica th они тоже липкие, z-index 1). */
.gr-teplo thead th:first-child { position: sticky; left: 0; z-index: 2; background: var(--kartochka); }
/* Значения дней таблицей — под «По дням»: подсказку на телефоне не вызвать. */
.gr-po-dnyam .tablica td { padding: 4px 8px; font-size: 13px; }
.gr-t0 { background: var(--teplo-0); } .gr-t1 { background: var(--teplo-1); }
.gr-t2 { background: var(--teplo-2); } .gr-t3 { background: var(--teplo-3); }
.gr-t4 { background: var(--teplo-4); color: #fff; }
.gr-legenda { display: flex; align-items: center; gap: 4px; font-size: 12px; color: var(--seryi); }
.gr-legenda span { display: inline-block; width: 16px; height: 10px; border-radius: 2px; }

@media print {
  .gr-stolb path, .gr-polosa > span, .gr-yach.est, .gr-teplo td {
    print-color-adjust: exact; -webkit-print-color-adjust: exact;
  }
}

/* Волна 4, шаг 3 (T5): виды абонемента карточками на экране продажи. Выбор —
 * нажатием на карточку целиком (подпись с radio внутри); выбранная — рамкой
 * акцента. На телефоне — по одной в ряд, крупно, под палец. */
.vid-kartochki { border: 0; padding: 0; margin: 0 0 16px; display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 12px; }
.vid-kartochki legend { font-weight: 600; margin-bottom: 8px; padding: 0; }
/* `.forma .vid-kartochki label` — сильнее общего `.forma label` (klan.css). */
.forma .vid-kartochki label.vid-kartochka { display: grid; margin: 0; font-size: 15px; color: inherit; grid-template-columns: auto 1fr; column-gap: 10px; row-gap: 4px;
  align-items: baseline; padding: 14px 16px; min-height: 44px; cursor: pointer;
  border: 2px solid var(--razdelitel); border-radius: var(--radius); background: var(--kartochka); }
.vid-kartochka input { grid-row: 1 / span 3; align-self: start; width: 20px; height: 20px; margin: 2px 0 0; }
.vid-kartochka:has(input:checked) { border-color: var(--akcent); background: var(--akcent-10); }
.vid-kartochka:has(input:focus-visible) { outline: 2px solid var(--sinii); outline-offset: 2px; }
.vid-nazvanie { font-weight: 600; font-size: 16px; }
.vid-podrobno { color: var(--seryi); font-size: 14px; }
.vid-cena { font-size: 20px; font-weight: 600; }
@media (max-width: 620px) { .vid-kartochki { grid-template-columns: 1fr; } }

/* Волна 4, шаг 3 (T5): «Абонементы» на телефоне — карточками. Строка списка
 * становится своей карточкой: аватар и название сверху, шкала остатка и срок —
 * во всю ширину под ними, под палец. На широком экране — прежние строки. */
@media (max-width: 620px) {
  .karta.abn-spisok { background: transparent; box-shadow: none; padding: 0; }
  .karta.abn-spisok > .stroka {
    display: grid; grid-template-columns: auto 1fr; column-gap: 12px; row-gap: 8px;
    background: var(--kartochka); border-radius: var(--radius); padding: 14px 16px;
    margin-bottom: 10px; border-bottom: 0;
  }
  .karta.abn-spisok > .stroka > .sboku { grid-column: 1 / -1; text-align: left; }
}

/* Касса (T3, волна 4, шаг 3): способы оплаты крупными плитками, сумма крупно,
 * «Принять» во всю ширину на телефоне. Разметка — у T3 (kassa/glavnaya.html).
 * Селекторы через `.kassa-sposoby label` — сильнее общего `.forma label`
 * (klan.css), который иначе снимает плитке `display`. */
.kassa-sposoby { border: 0; padding: 0; margin: 12px 0; display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 8px; }
.kassa-sposoby legend { padding: 0; margin-bottom: 6px; color: var(--seryi); }
.kassa-sposoby label.kassa-sposob { position: relative; display: flex; align-items: center;
  justify-content: center; min-height: 56px; margin: 0; padding: 8px 12px;
  border: 1px solid var(--razdelitel); border-radius: var(--radius); background: var(--kartochka);
  color: inherit; font-size: 15px; font-weight: 600; text-align: center; cursor: pointer; }
.kassa-sposoby label.kassa-sposob input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.kassa-sposoby label.kassa-sposob:has(input:checked) { border-color: var(--akcent);
  box-shadow: inset 0 0 0 2px var(--akcent); }
.kassa-sposoby label.kassa-sposob:has(input:focus-visible) { outline: 2px solid var(--akcent);
  outline-offset: 2px; }
/* Дашборд «Обзор» (штаб 22:30, Salesforce Lightning): компоненты-карточки сеткой —
 * телефон одна колонка, планшет две, широкий экран три. Карточка растягивается по
 * высоте ряда, «Открыть отчёт ›» прижат к низу. */
.dash-setka { display: grid; grid-template-columns: 1fr; gap: 16px; margin-top: 16px; }
@media (min-width: 700px) { .dash-setka { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1100px) { .dash-setka { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.dash-setka > .karta.dash-komponent { margin: 0; display: flex; flex-direction: column; min-width: 0; }
.dash-komponent h2 { margin-bottom: 2px; }
.dash-otkryt { margin: auto 0 0; padding-top: 8px; }
.dash-otkryt > a { display: inline-flex; align-items: center; min-height: 44px; font-weight: 600; }
.dash-filtr { display: flex; flex-wrap: wrap; gap: 8px 12px; align-items: flex-end; margin: 0 0 8px; }
.dash-filtr label { display: flex; flex-direction: column; gap: 4px; flex: 1 1 220px; max-width: 360px; }

/* Рассылки: образец сообщения — пузырём, как его увидит клиент; переносы шаблона
 * сохраняются. */
.rss-obrazec { white-space: pre-line; margin: 8px 0 12px; padding: 12px 14px;
  border: 1px solid var(--razdelitel); border-radius: var(--radius); background: var(--kartochka); }

/* «Сегодня»: «ещё N ›» под первыми пятью строками списка — палец, а не строчка. */
p.eshche { margin: 4px 0 0; }
p.eshche > a { display: inline-flex; align-items: center; min-height: 44px; font-weight: 600; }
/* «Ждут ответа», дни рождения, «Пора продлить» на телефоне — правая колонка
 * остаётся справа, а не уходит второй строкой: строка ниже на треть (штаб 19:02).
 * Заморозок здесь нет: у них справа метка и фраза, в узкой колонке строка выше.
 * Через id — сильнее общего переноса `.stroka` (klan.css). */
@media (max-width: 620px) {
  #zhdut-otveta .stroka, #dni-rozhdeniya .stroka, #pora-prodlit .stroka {
    flex-wrap: nowrap; gap: 12px; }
  #zhdut-otveta .stroka .sboku, #dni-rozhdeniya .stroka .sboku, #pora-prodlit .stroka .sboku {
    text-align: right; max-width: 45%; }
}

/* «За что» и «Что именно» — плитки-ссылками (T3, штаб 17:55): выбранная помечена
 * aria-current, а не классом — тот же признак читает экранный диктор. Плитка —
 * и ссылка, и неактивный `<span class="knopkoy">` («оплачен ✓»). Шире 150 px и
 * без `overflow-wrap: anywhere` от `.karta`: иначе на 1440 «Абонемен/т» (штаб 21:10). */
.kassa-plitki { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
.kassa-plitki .knopkoy { min-height: 56px; display: flex; align-items: center;
  justify-content: center; text-align: center; white-space: normal; overflow-wrap: normal; }
.kassa-plitki a.knopkoy[aria-current="true"] { background: var(--kartochka);
  box-shadow: inset 0 0 0 2px var(--akcent); color: var(--akcent-tekst); }
input.kassa-summa { font-size: 40px; font-weight: 600; min-height: 64px; }
@media (max-width: 620px) { button.kassa-prinyat { width: 100%; min-height: 52px; font-size: 18px; } }

/* Строка с долей (этап воронки, направление, статья): полоса — отдельной строкой,
 * дорожка у всех строк одной ширины, длина суммы справа шкалу не сдвигает. */
.gr-voronka-etap, .gr-dolya { border-bottom: 1px solid var(--razdelitel); padding-bottom: 8px; }
.gr-voronka-etap .stroka, .gr-dolya .stroka { border-bottom: 0; padding-bottom: 0; }

/* --- нижняя панель вкладок (Волна 4, шаг 3) ------------------------------- */

/* На широком экране панели нет, а обёртка пункта прозрачна — меню прежнее. */
.vkladki-niz { display: none; }
.v-paneli { display: contents; }

/* Телефон и планшет: главные вкладки роли внизу, как в мессенджере; «Ещё» —
 * остальные пункты списком над панелью (та же шапка, поднятая к панели). Пункт
 * из вкладок в «Ещё» не повторяется. Кнопка «Меню» наверху не нужна: её флажок
 * переключает «Ещё». Высота вкладки 52px — больше 44, под большой палец; снизу
 * — отступ «домашней полосы» iPhone (`env(safe-area-inset-bottom)`). */
@media (max-width: 899px) {
  .vkladki-niz {
    display: flex;
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 30;
    gap: 2px;
    padding: 4px 4px calc(4px + env(safe-area-inset-bottom));
    background: var(--kartochka);
    border-top: 1px solid var(--razdelitel);
  }
  .vkladki-niz a, .vkladki-eshche {
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    min-height: 52px;
    border-radius: var(--radius);
    color: #3f3f46;
    font-size: 12px;
    line-height: 1.2;
    text-align: center;
    text-decoration: none;
    cursor: pointer;
    user-select: none;
  }
  .vkladki-niz a.zdes,
  body:has(.menyu-flag:checked) .vkladki-eshche { color: var(--akcent-tekst, var(--akcent)); font-weight: 600; }
  /* Метка непрочитанного — поверх угла иконки, а не в строке: в строке она
   * сдвигала подпись «Переписка» вниз и вбок (ревью T0). */
  .vkladki-niz a { position: relative; }
  .vkladki-niz .neprochitano-vkladka {
    position: absolute;
    top: 2px;
    left: calc(50% + 4px);
    min-width: 18px;
    padding: 0 5px;
    font-size: 11px;
    line-height: 18px;
  }
  body:has(.vkladki-niz) main { padding-bottom: calc(80px + env(safe-area-inset-bottom)); }
  body:has(.vkladki-niz) .menyu-knopka { display: none; }
  .shapka nav .v-paneli { display: none; }
  /* «Ещё» открыто: шапка со списком, логином и выходом встаёт над панелью. */
  body:has(.menyu-flag:checked) > .shapka {
    position: fixed;
    top: auto;
    left: 0;
    right: 0;
    bottom: calc(61px + env(safe-area-inset-bottom));
    z-index: 29;
    max-height: calc(100dvh - 80px);
    overflow-y: auto;
    box-shadow: 0 -8px 24px rgba(0, 0, 0, .12);
  }
}

/* ---- Дашборды (ночь 18→19.10, «в стиле Salesforce»): сетка карточек, кольцо,
 * спидометр, спарклайн, столбцы с накоплением, линия со сравнением. Палитра долей
 * — одна на всю систему, по убыванию доли; каждый цвет не меньше 3:1 к белому
 * (WCAG 1.4.11 для графики), «прочее» — серым. Цвет только классом: style= под
 * CSP нельзя. */
:root {
  --gr-1: #3b6fb6; --gr-2: #127262; --gr-3: #c94a12;
  --gr-4: #7c3aed; --gr-5: #0e7490; --gr-6: #be185d; --gr-0: #8a8a93;
}
.gr-c1 { fill: var(--gr-1); stroke: var(--gr-1); background: var(--gr-1); }
.gr-c2 { fill: var(--gr-2); stroke: var(--gr-2); background: var(--gr-2); }
.gr-c3 { fill: var(--gr-3); stroke: var(--gr-3); background: var(--gr-3); }
.gr-c4 { fill: var(--gr-4); stroke: var(--gr-4); background: var(--gr-4); }
.gr-c5 { fill: var(--gr-5); stroke: var(--gr-5); background: var(--gr-5); }
.gr-c6 { fill: var(--gr-6); stroke: var(--gr-6); background: var(--gr-6); }
.gr-c0 { fill: var(--gr-0); stroke: var(--gr-0); background: var(--gr-0); }

/* Сетка: 1 колонка на телефоне, 2 на планшете, 3 на широком. */
.gr-dashboard { display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; }
@media (min-width: 700px) { .gr-dashboard { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1280px) { .gr-dashboard { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.gr-dashboard > .gr-komponent { margin: 0; display: flex; flex-direction: column; min-width: 0; }
.gr-komponent-shapka { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 8px; margin-bottom: 8px; }
.gr-komponent-shapka h2 { margin: 0; font-size: 15px; }
.gr-period { font-size: 13px; color: var(--seryi); }
.gr-otkryt { margin-top: auto; padding-top: 12px; font-size: 14px; display: inline-flex;
  align-items: center; min-height: 44px; }
.gr-period-plitki { margin-bottom: 16px; }
.gr-pusto { color: var(--seryi); font-size: 14px; margin: 8px 0; }

/* Число с трендом. */
.gr-metrika .gr-plitka { margin: 0; }
.gr-sparklayn { display: block; width: 100%; max-width: 160px; height: 28px; margin-top: 6px; overflow: visible; }
.gr-sparklayn polyline { fill: none; stroke: var(--grafik); stroke-width: 1.5; stroke-linejoin: round;
  vector-effect: non-scaling-stroke; }
.gr-sparklayn circle { fill: var(--grafik); }

/* Кольцо: итог в центре — разметкой поверх рисунка, а не текстом SVG: шрифт
 * и перенос — как у страницы. */
.gr-kolco { margin: 0; }
.gr-kolco-risunok { position: relative; width: 168px; max-width: 100%; margin: 4px auto 12px; }
.gr-kolco-risunok svg { display: block; width: 100%; height: auto; }
.gr-kolco-dorozhka { fill: none; stroke: var(--grafik-fon); stroke-width: 6; }
.gr-kolco-dolya { fill: none; stroke-width: 6; }
.gr-kolco a:hover .gr-kolco-dolya, .gr-kolco-dolya:hover { stroke-width: 7.5; }
.gr-kolco-centr { position: absolute; inset: 0; display: flex; flex-direction: column;
  align-items: center; justify-content: center; text-align: center; padding: 0 30px; }
.gr-kolco-centr .velichina { font-size: 18px; line-height: 1.2; overflow-wrap: anywhere; }
.gr-kolco-centr .gr-podpis { font-size: 12px; color: var(--seryi); }
.gr-legenda-spisok { list-style: none; margin: 0; padding: 0; }
.gr-legenda-spisok li { display: flex; align-items: baseline; gap: 8px; padding: 4px 0;
  border-bottom: 1px solid var(--razdelitel); font-size: 14px; }
.gr-legenda-spisok li:last-child { border-bottom: 0; }
.gr-legenda-spisok .glavnoe { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
.gr-legenda-spisok .sboku { flex: 0 0 auto; color: var(--seryi); font-variant-numeric: tabular-nums; }
.gr-metka { flex: 0 0 auto; display: inline-block; width: 10px; height: 10px; border-radius: 3px; }
.gr-legenda-vryad { display: flex; flex-wrap: wrap; gap: 4px 12px; margin-top: 8px; }
.gr-legenda-vryad li { border: 0; padding: 0; font-size: 13px; align-items: center; }

/* Спидометр. */
.gr-spidometr { margin: 0; text-align: center; }
.gr-spidometr svg { display: block; width: 200px; max-width: 100%; height: auto; margin: 0 auto; }
.gr-spidometr-dorozhka, .gr-spidometr-dolya { fill: none; stroke-width: 6; stroke-linecap: round; }
.gr-spidometr-dorozhka { stroke: var(--grafik-fon); }
.gr-spidometr-dolya { stroke: var(--grafik); }
.gr-spidometr-dolya.gr-sverh { stroke: var(--uspeh); }
.gr-spidometr figcaption { display: flex; flex-direction: column; align-items: center; gap: 2px; margin-top: 4px; }
.gr-spidometr .gr-podpis { font-size: 13px; color: var(--seryi); }

/* Столбцы с накоплением и линия. */
.gr-nakoplenie rect { stroke: none; }
.gr-nakoplenie rect:hover { opacity: .8; }
.gr-liniya { margin: 12px 0 0; max-width: 420px; }
.gr-liniya svg { display: block; width: 100%; height: auto; overflow: visible; }
.gr-liniya polyline { fill: none; stroke-width: 2; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.gr-seychas { stroke: var(--grafik); }
.gr-ranshe { stroke: var(--gr-0); stroke-dasharray: 5 4; }
.gr-tochka { fill: var(--grafik); }
.gr-tochka:hover { fill: var(--grafik-segodnya); }
.gr-legenda-liniy { margin-top: 6px; gap: 6px; }
.gr-legenda-liniy span { display: inline-block; width: 18px; height: 0; border-radius: 0; }
.gr-liniya-seychas { border-top: 2px solid var(--grafik); }
.gr-liniya-ranshe { border-top: 2px dashed var(--gr-0); margin-left: 10px; }
.gr-perehod { display: block; font-size: 12px; color: var(--seryi); margin-top: 4px; }
@media print {
  .gr-c1, .gr-c2, .gr-c3, .gr-c4, .gr-c5, .gr-c6, .gr-c0, .gr-metka {
    print-color-adjust: exact; -webkit-print-color-adjust: exact;
  }
}

/* Отметка на занятии: «Пришёл» зелёная, «Не пришёл» красная; выбранная
 * залита, вторая контуром. 44 px на любой ширине — нажимают по разу на
 * каждого ребёнка, быстро и не глядя. */
button.otm {
  min-height: 44px; min-width: 44px; padding: 0 14px;
  background: transparent; border: 2px solid currentColor; font-weight: 600;
}
button.otm-prishel { color: var(--uspeh); }
button.otm-ne-prishel { color: var(--oshibka); }
button.otm.vybrano { color: #fff; opacity: 1; cursor: default; }
button.otm-prishel.vybrano { background: var(--uspeh); border-color: var(--uspeh); }
button.otm-ne-prishel.vybrano { background: var(--oshibka); border-color: var(--oshibka); }
.otm-para { gap: 8px; flex-wrap: nowrap; }
/* Окно «+ Новый клиент» (п.15): раскрывается касанием, без скриптов. */
details.novyy-klient { margin: 12px 0; }
details.novyy-klient > summary { list-style: none; cursor: pointer; display: inline-flex;
  align-items: center; min-height: 44px; padding: 0 16px; }
details.novyy-klient > summary::-webkit-details-marker { display: none; }
details.novyy-klient[open] > summary { margin-bottom: 8px; }
details.novyy-klient .nk-gruppa { border: 0; padding: 0; margin: 0 0 12px; }
details.novyy-klient .nk-gruppa legend { padding: 0; margin-bottom: 4px; color: var(--seryi);
  font-weight: 600; }
details.novyy-klient .nk-galochka { display: flex; align-items: center; gap: 8px; min-height: 44px; }
details.novyy-klient .nk-tekst-soglasiya { white-space: pre-line; max-height: 40vh; overflow: auto; }

/* Лист дня для печати (`templates/raspisanie/pechat.html`): на бумаге — таблицы
 * без теней, занятие не рвётся между страницами, кнопки и ссылки скрыты. */
.pechat-den { margin-bottom: 24px; }
.pechat-zanyatie { margin-bottom: 14px; break-inside: avoid; }
.pechat-shapka { margin: 0 0 4px; }
.pechat-tablica { width: 100%; border-collapse: collapse; font-size: 14px; }
.pechat-tablica th, .pechat-tablica td { text-align: left; padding: 4px 8px; border-bottom: 1px solid var(--razdelitel); }
.pechat-galka { width: 64px; font-size: 18px; }
@media print {
  .pechat-ne-pechatat, .skryt-forma { display: none; }
  .pechat-tablica { font-size: 12px; }
  .pechat-tablica th, .pechat-tablica td { border-bottom: 1px solid #999; }
}
