/* ─────────────────────────────────────────────────────────────
   Varyag · общая дизайн-система для всех мини-аппов
   Меняешь цвет/фон/тему здесь — обновляется во всех страницах.
   Специфика страницы (компоненты, календарь, мастер) — в её <style>.
   ───────────────────────────────────────────────────────────── */

/* фирменный serif для заголовков — вшит в сайт (woff2 рядом, без внешних загрузок).
   Кириллица и латиница — отдельными файлами, браузер грузит нужный по unicode-range. */
@font-face {
  font-family: "Playfair Display";
  font-style: normal; font-weight: 600; font-display: swap;
  src: url("fonts/playfair-display-cyrillic-600-normal.woff2") format("woff2");
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: "Playfair Display";
  font-style: normal; font-weight: 600; font-display: swap;
  src: url("fonts/playfair-display-latin-600-normal.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                 U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC,
                 U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* парный к нему sans для всего интерфейса — вариативный (один файл = все толщины).
   Ставит текст в одну «семью по духу» с Playfair и одинаково на всех устройствах. */
@font-face {
  font-family: "Montserrat";
  font-style: normal; font-weight: 100 900; font-display: swap;
  src: url("fonts/montserrat-cyrillic-wght-normal.woff2") format("woff2");
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+20BD, U+2116;
}
@font-face {
  font-family: "Montserrat";
  font-style: normal; font-weight: 100 900; font-display: swap;
  src: url("fonts/montserrat-latin-wght-normal.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                 U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC,
                 U+20BD, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  --ink:      #0f2143;   /* основной текст */
  --ink-soft: #3c5378;   /* второстепенный текст */
  --paper:    #e6eef8;   /* фон (день) — чуть глубже, не бумажно-белый */
  --line:     #e2e9f3;   /* тонкие линии/границы */
  --accent:   #1d4e89;   /* основной синий */
  --accent-2: #2f6cb3;   /* акцент светлее (фокус, ховер) */
  --accent-fill: var(--accent);   /* заливка под белым текстом (см. тёмную тему) */
  /* Подписи. Прошлый #5e78a1 давал на фоне 3.84:1 — ниже нормы (4.5), а именно
     этим цветом набраны все мелкие надписи над полями. Здесь 4.9:1, и от --ink
     он по-прежнему отличается заметно: подпись читается как второстепенная. */
  --muted:    #4e678e;
  --ok:       #277547;   /* успех/скидка (4.8:1 к фону) */
  --warn:     #8f5a0f;   /* перерыв/предупреждение (4.9:1 к фону) */
  --danger:   #c25b5b;   /* отмена, удаление */
  --warn-bg:  #fbf3e6;

  --serif: "Playfair Display", "New York", Georgia, "Times New Roman", serif;
  --sans: "Montserrat", -apple-system, system-ui, "Segoe UI", Roboto, sans-serif;
  --flake-rgb: 108, 148, 208;   /* снежинки: днём синие */

  /* ───── движение ─────
     Одна кривая и три длительности на весь продукт. Раньше в файлах жили
     двенадцать разных значений (.1s, .12s, .15s, .18s, .2s, .22s…) — по
     отдельности незаметно, а вместе интерфейс ощущается собранным из кусков:
     одно нажатие отвечает мгновенно, соседнее будто залипает. */
  --ease: cubic-bezier(.22, .61, .36, 1);   /* быстро стартует, мягко тормозит */
  --fast: .16s;                 /* отклик на касание */
  --base: .24s;                 /* появление и скрытие */
  --slow: .36s;                 /* смена экрана */

  --radius: 20px;               /* скругление карточек */
  --shadow-card: 0 1px 3px rgba(15, 33, 67, .07), 0 6px 16px rgba(15, 33, 67, .09);
  --grad-accent: linear-gradient(180deg, #2a62a6, var(--accent));
}

/* Тёмная тема. Палитра спокойная, без «игровых» градиентов и полосок:
   поверхности плоские, глубина задаётся мягкой тенью, а цвет работает только
   как статус (занято / перерыв / свободно) и как одна акцентная кнопка. */
html.dark {
  --ink:      #e5e7eb;   /* основной текст */
  --ink-soft: #cbd5e1;
  --muted:    #9ca3af;   /* вторичный текст */
  /* Самый тихий уровень. Прошлый #6b7280 давал на поверхности 2.99:1 — этим
     цветом набраны плейсхолдеры с образцом формата телефона и подписи под
     цифрами («записей нет»), их читают, а не игнорируют. Здесь 4.7:1 и всё
     ещё заметно тише --muted. */
  --faint:    #8b93a1;
  --accent:   #3b82f6;   /* главный акцент */
  --accent-2: #60a5fa;   /* наведение */
  /* Заливка под белым текстом — чуть глубже акцента. Белое на #3b82f6 даёт
     контраст 3.7:1: для крупной надписи хватает, для 15-пиксельной подписи на
     выбранном чипе — нет. #2f6fdb на глаз тот же синий, но 4.75:1. */
  --accent-fill: #2f6fdb;
  --ok:       #22c55e;   /* свободно */
  --warn:     #f59e0b;   /* перерыв */
  --warn-bg:  rgba(245, 158, 11, .10);
  --busy:     #3b82f6;   /* занято */
  --violet:   #8b5cf6;   /* второстепенный акцент */
  --danger:   #ef4444;   /* отмена, удаление */
  --paper:    #0b1220;   /* фон приложения */
  --paper-2:  #0e172a;   /* второй уровень фона */

  /* ЛЕСТНИЦА ПОВЕРХНОСТЕЙ.
     В тёмном интерфейсе глубину нельзя строить так же, как в светлом. Тёмная
     тень на тёмном фоне не видна вообще, а заливка «3% белого» неотличима от
     фона: карточка получалась контрастом 1.00 к странице — то есть её просто
     не было. Поэтому поверхности здесь НЕПРОЗРАЧНЫЕ и светлеют с каждым
     уровнем, а край задаёт светлая полоска сверху (inset), а не тень снизу. */
  --surface:  #161f33;   /* карточка */
  --surface-2:#1e2942;   /* блок внутри карточки */
  --surface-3:#26334f;   /* наведение, выделение */
  --line:     rgba(255, 255, 255, .07);
  --flake-rgb: 200, 220, 255;
  --shadow-card: 0 8px 24px rgba(0, 0, 0, .4), inset 0 1px 0 rgba(255, 255, 255, .05);
}

* { box-sizing: border-box; margin: 0; padding: 0; -webkit-tap-highlight-color: transparent; }

html { -webkit-text-size-adjust: 100%; }
body {
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  line-height: 1.5;
  /* сглаживание — текст чётче и «дороже», особенно светлый на тёмном небе */
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

/* ───────── фон + снег ───────── */
#bg {
  position: fixed; inset: 0; z-index: -2; pointer-events: none;
  background:
    radial-gradient(1100px 520px at 50% -10%, rgba(255, 255, 255, .7), transparent 60%),
    radial-gradient(900px 500px at 88% 6%, rgba(170, 200, 235, .42), transparent 64%),
    linear-gradient(180deg, #cbdcef 0%, #d9e6f4 42%, #e6eef8 100%);
}
/* Ровный фон вместо трёх наложенных градиентов: подсветка «сверху» тянула взгляд
   к шапке и делала экран пёстрым. Оставлено едва заметное свечение по центру —
   ощущение глубины без узора. */
html.dark #bg {
  background:
    radial-gradient(760px 420px at 50% 0%, rgba(59, 130, 246, .10), transparent 62%),
    linear-gradient(180deg, var(--paper-2) 0%, var(--paper) 42%);
}
body::before, body::after {
  content: ""; display: none; position: fixed; left: 0; pointer-events: none; z-index: -1;
}
html.dark body::before, html.dark body::after { display: block; }
/* Снег оставлен как знак школы, но приглушён втрое: раньше он читался как шум
   поверх интерфейса, а теперь это едва заметная фактура. */
body::before {
  top: -320px; height: calc(100vh + 320px); width: 100%;
  background:
    radial-gradient(1.6px 1.6px at 44px 58px,  rgba(var(--flake-rgb), .5) 55%, transparent),
    radial-gradient(1.8px 1.8px at 250px 96px, rgba(var(--flake-rgb), .4) 55%, transparent),
    radial-gradient(1.4px 1.4px at 214px 288px, rgba(var(--flake-rgb), .35) 55%, transparent);
  background-size: 340px 340px; opacity: .16; animation: snow 30s linear infinite;
}
@keyframes snow { from { transform: translateY(-320px); } to { transform: translateY(0); } }
@keyframes fade { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

/* Смена вкладки — короткое проявление вместо мгновенной подмены.
   Без него экран «моргает»: содержимое меняется целиком за один кадр, и глазу
   непонятно, то же это место или другое. */
.view.on { animation: viewIn var(--slow) var(--ease) both; }
@keyframes viewIn { from { opacity: 0; transform: translateY(6px); } }

/* ───────── базовые компоненты (общие для всех страниц) ───────── */
/* Безопасные зоны: на iPhone с «чёлкой» и полосой-домой контент иначе уезжает
   под них. Учитываются и боковые — в альбомной ориентации вырез слева. */
.wrap {
  max-width: 560px; margin: 0 auto;
  padding-left:  max(20px, env(safe-area-inset-left));
  padding-right: max(20px, env(safe-area-inset-right));
}
body { padding-bottom: env(safe-area-inset-bottom); }

/* Очень узкие экраны (iPhone SE, 320px): поля сужаются, чтобы карточки
   не выталкивали друг друга и не появлялась горизонтальная прокрутка. */
@media (max-width: 360px) {
  .wrap { padding-left: max(14px, env(safe-area-inset-left));
          padding-right: max(14px, env(safe-area-inset-right)); }
  .card { padding: 16px; }
}

.card {
  background: rgba(255, 255, 255, .82);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 22px;                       /* воздуха больше: 20–28px */
  box-shadow: var(--shadow-card);
}
/* Непрозрачная поверхность + светлая полоска по верхнему краю. Размытие убрано:
   за карточкой ровный фон, размывать нечего, а на слабом телефоне это лишняя
   работа для видеокарты при каждой прокрутке. */
html.dark .card {
  background: var(--surface);
  border-color: var(--line);
}

.muted-note { font-size: 12.5px; color: var(--muted); }

/* кнопка смены темы */
#themeBtn {
  width: 40px; height: 40px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--line); border-radius: 50%;
  background: rgba(255, 255, 255, .78);
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  font-size: 16px; line-height: 1; cursor: pointer;
  box-shadow: 0 2px 5px rgba(15, 33, 67, .1);
  transition: transform var(--fast) var(--ease), box-shadow var(--base) var(--ease);
}
#themeBtn:active { transform: scale(.9); }
html.dark #themeBtn {
  background: linear-gradient(180deg, rgba(35, 58, 99, .78), rgba(24, 42, 74, .78));
}

/* полоса «нет связи»: видно сразу, что на экране нет свежих данных */
#offline {
  margin: 0 0 14px;
  padding: 11px 14px;
  background: var(--warn-bg);
  border: 1px solid rgba(201, 138, 46, .35);
  border-radius: 12px;
  color: var(--warn);
  font-size: 13px; font-weight: 600; line-height: 1.4;
}
#offline[hidden] { display: none; }

/* всплывающее уведомление — сверху: снизу его загораживают кнопки и клавиатура */
#toast {
  position: fixed; left: 50%;
  top: calc(14px + env(safe-area-inset-top));
  transform: translateX(-50%) translateY(-16px) scale(.97);
  padding: 13px 20px;
  background: #ffffff;
  color: var(--ink);
  -webkit-backdrop-filter: blur(14px) saturate(1.6); backdrop-filter: blur(14px) saturate(1.6);
  border: 1px solid var(--line);
  font-family: var(--sans);
  font-size: 13.5px; font-weight: 600; line-height: 1.35;
  border-radius: 16px;
  box-shadow: 0 10px 34px rgba(15, 33, 67, .28);
  opacity: 0; pointer-events: none;
  transition: transform var(--slow) cubic-bezier(.22, .8, .36, 1), opacity var(--slow) var(--ease);
  z-index: 40; max-width: min(92vw, 460px); text-align: center;
}
#toast.show { transform: translateX(-50%) translateY(0) scale(1); opacity: 1; }
html.dark #toast {
  background: #16233c;
  color: var(--ink);
  border-color: rgba(150, 180, 224, .26);
  box-shadow: 0 10px 34px rgba(0, 0, 0, .6);
}

/* ───────── анкета в форме записи (админка и кабинет) ─────────
   Свёрнута по умолчанию: чаще всего админ записывает по телефону, и хватает
   имени с номером. Но прокат и подъёмник меняют сумму, поэтому блок назван
   «влияет на цену» — иначе его никто не откроет и цена будет занижена. */
.bf-more {
  display: block; width: 100%; margin: 4px 0 0; padding: 10px;
  font-family: var(--sans); font-size: 12.5px; font-weight: 600;
  color: var(--accent-2); background: transparent;
  border: 1px dashed var(--line); border-radius: 12px; cursor: pointer;
  transition: border-color var(--fast), color var(--fast);
}
.bf-more.on { border-style: solid; }
/* ─────────── поля ввода ───────────
   Жили копиями внутри страниц: в admin.html своя, в index.html своя, а в
   кабинете инструктора — никакой, хотя разметка класс использует. Четыре поля
   там рисовались браузерными: белыми на тёмном и в чужой типографике. Ровно то
   же случилось со страницей входа, когда она подключила только shared.css.

   Здесь лежит вариант ПАНЕЛЕЙ: скруглённый прямоугольник. Клиентская форма
   переопределяет его своими «таблетками» — там это осознанный другой облик, а
   не расхождение: страница подключается после общей системы и выигрывает. */
.field {
  width: 100%;
  padding: 12px 16px;
  font-size: 16px;              /* ≥16px — иначе iOS приближает страницу при фокусе */
  font-weight: 500;
  font-family: var(--sans);
  color: var(--ink);
  background: rgba(255, 255, 255, .9);
  border: 1px solid var(--line);
  border-radius: 12px;
  outline: none;
  margin-bottom: 10px;
  box-shadow: 0 1px 2px rgba(15, 33, 67, .05);
  transition: border-color var(--base), box-shadow var(--base);
}
.field::placeholder { color: var(--faint, var(--muted)); font-weight: 400; }
.field:focus {
  border-color: var(--accent-2);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 12%, transparent);
}
html.dark .field { background: var(--surface-2); border-color: var(--line); }
html.dark .field::placeholder { color: var(--faint); }

.bf-extra { margin-top: 10px; animation: fade var(--base) var(--ease) both; }
.bf-extra > label,
.bf-extra .bf-row > label {
  display: block; margin: 10px 0 6px;
  font-size: 11px; font-weight: 700; letter-spacing: .4px;
  text-transform: uppercase; color: var(--muted);
}
.bf-extra .bf-row {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-top: 10px;
}
.bf-extra .bf-row > label { margin: 0; }
.bf-extra .bf-num { width: 72px; margin: 0; text-align: center; }

/* Кликер в панелях. Раньше количество набирали с клавиатуры, и это был худший
   способ из возможных: на телефоне ради одной цифры выезжала цифровая
   клавиатура и закрывала форму вместе с итоговой суммой — той самой, ради
   которой админ и открывает анкету, когда диктует цену по телефону.
   Ввод с клавиатуры полностью убран (readonly): промахнуться мимо диапазона
   нельзя, а значит нечего и проверять. */
.bf-count { display: flex; align-items: center; gap: 8px; }
.bf-count .cnt-btn {
  width: 32px; height: 32px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--line); border-radius: 50%;
  background: var(--surface); color: var(--ink);
  font-size: 18px; line-height: 1; cursor: pointer;
  transition: transform var(--fast), border-color var(--base), color var(--base);
}
.bf-count .cnt-btn:hover { border-color: var(--accent-2); color: var(--accent); }
.bf-count .cnt-btn:active { transform: scale(.9); }
.bf-count .cnt-btn:disabled { opacity: .35; pointer-events: none; }
.bf-count .bf-num {
  width: 46px; pointer-events: none; font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.bf-extra .bf-row[hidden], .book-form .bf-row[hidden] { display: none; }
.bf-extra .chips-mini[hidden] { display: none; }

/* Итог виден до сохранения: админ диктует сумму клиенту по телефону прямо
   во время записи, и узнавать её после сохранения поздно. */
.bf-total {
  margin-top: 12px; padding-top: 10px;
  border-top: 1px solid var(--line);
  font-size: 13px; color: var(--muted);
}
.bf-total b {
  float: right; font-size: 17px; font-weight: 700; color: var(--ink);
  font-variant-numeric: tabular-nums;
}

/* ───────── загруженность дня в календаре ─────────
   Раньше 31 клетка выглядела одинаково, и на вопрос «а когда можно?» админ
   тыкал в дни по очереди. Теперь полоска снизу показывает долю занятых часов:
   «где есть окно» видно, не открывая ни одного дня. */
.day .load {
  position: absolute; left: 22%; right: 22%; bottom: 5px;
  height: 3px; border-radius: 2px;
  background: rgba(148, 163, 184, .25);
  overflow: hidden;
}
.day .load i {
  display: block; height: 100%;
  width: var(--busy, 0%);
  background: var(--inst-c, var(--accent-fill));
  border-radius: 2px;
}
/* день закрыт целиком — предлагать его клиенту нечего, поэтому он тише */
.day.full .dnum { opacity: .45; }
.day.full .load i { background: var(--muted); }
.day.sel .load { background: rgba(255, 255, 255, .3); }
.day.sel .load i { background: #fff; }

/* ───────── быстрые переходы по календарю ─────────
   «Суббота» — самый частый запрос при записи по телефону, а доскроллить до неё
   и попасть в клетку дольше, чем нажать чип. */
.quick {
  display: flex; gap: 6px; flex-wrap: wrap;
  margin: 12px 0 0;
}
.quick button {
  flex: 1 1 auto; min-width: 62px;
  padding: 8px 10px;
  font-family: var(--sans); font-size: 12.5px; font-weight: 600;
  color: var(--muted); background: transparent;
  border: 1px solid var(--line); border-radius: 999px;
  cursor: pointer; white-space: nowrap;
  transition: color var(--fast), border-color var(--fast), background var(--fast);
}
.quick button:active { transform: scale(.96); }
.quick button.on {
  color: #fff; background: var(--inst-c, var(--accent-fill)); border-color: transparent;
}

/* ───────── карточка клиента (общая для админки и кабинета) ───────── */

/* Запись клиента — ОДНА строка: время, имя, значок заметки, шеврон, действие.
   Расписание листают глазами сверху вниз, и день из шести занятий должен
   помещаться на экран. Всё остальное (телефон, снаряд, текст заметки, анкета)
   лежит в раскрывающейся карточке — тапом по строке. */
.slot.booking { cursor: pointer; }
.slot.booking .sl-name {
  flex: 1; min-width: 0; font-size: 15px; font-weight: 700;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* значок вместо текста заметки: сама заметка бывает длинной и раздувала строку,
   а знать на ходу нужно лишь то, что про этого клиента что-то записано */
.slot .note-dot { flex-shrink: 0; font-size: 13px; line-height: 1; }

/* Шеврон вместо кружка с «i»: кружок не читался как действие, а стрелка
   привычно означает «раскрыть». Тапается вся строка, шеврон лишь подсказывает. */
.slot .chev {
  flex-shrink: 0; width: 14px; text-align: center;
  color: var(--muted); user-select: none; pointer-events: none;
}
.slot .chev::after {
  content: "⌄"; display: block; font-size: 15px; line-height: 1;
  transition: transform var(--base);
}
.slot.open .chev { color: var(--accent-2); }
.slot.open .chev::after { transform: rotate(180deg); }

/* Полное имя — здесь. В строке расписания стоит только имя без фамилии:
   «Константин Мирошниченко» требует 230px, а рядом со временем и кнопками
   столько не бывает ни на одном телефоне. */
.client-info .ci-name {
  font-size: 17px; font-weight: 700; letter-spacing: -.2px;
  margin-bottom: 2px; color: var(--ink);
}

/* телефон в карточке — крупно и нажимаемо: чаще всего её и открывают, чтобы позвонить */
.client-info .ci-phone {
  display: inline-block; margin-bottom: 8px;
  font-size: 15px; font-weight: 700; color: var(--accent);
  text-decoration: none; font-variant-numeric: tabular-nums;
}
html.dark .client-info .ci-phone { color: #7fb2ec; }

.client-info {
  margin: 2px 0 10px; padding: 14px;
  border: 1px solid var(--line); border-radius: 14px;
  background: rgba(110, 140, 190, .07);
  animation: fade .2s ease-out both;
}
.client-info .ci-row {
  display: flex; gap: 10px; align-items: baseline;
  padding: 4px 0; font-size: 13px;
}
.client-info .ci-row + .ci-row { border-top: 1px dashed var(--line); }
.client-info .ci-row span { flex: 0 0 96px; color: var(--muted); font-size: 12px; }
.client-info .ci-row b { flex: 1; font-weight: 600; }

.client-info .ci-note { margin-top: 10px; }
.client-info .ci-note label {
  display: block; margin-bottom: 6px;
  font-size: 11px; font-weight: 700; letter-spacing: .4px;
  text-transform: uppercase; color: var(--muted);
}
.client-info .ci-text {
  width: 100%; padding: 12px 14px; resize: vertical;
  /* 16px — ниже этого iOS увеличивает страницу при фокусе и ломает вёрстку */
  font-family: var(--sans); font-size: 16px; color: var(--ink);
  background: rgba(255, 255, 255, .88);
  border: 1px solid var(--line); border-radius: 12px; outline: none;
}
html.dark .client-info { background: var(--surface-3); border-color: transparent; }
html.dark .client-info .ci-text { background: var(--paper); border-color: var(--line); }
.client-info .ci-text:focus { border-color: var(--accent-2); }
.client-info .ci-save {
  margin-top: 8px; padding: 9px 16px;
  border: 1px solid var(--accent-2); border-radius: 999px;
  background: transparent; color: var(--accent-2);
  font-family: var(--sans); font-size: 13px; font-weight: 600; cursor: pointer;
  transition: background var(--base), color var(--base), transform var(--fast);
}
.client-info .ci-save:active { transform: scale(.96); }

/* Уважение к системной настройке «уменьшить движение»: раньше отключался только
   снег, а карточки и переходы продолжали ездить. Для человека с вестибулярной
   чувствительностью это и есть проблема. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}
