/* Таогун · общие стили интерфейса специалиста (static/sino.css).
   Значения — только переменные из app/web/design.py: theme_css()
   подставляется в <style> base.html до этого файла. Цвет, кегль или
   радиус числом здесь — ошибка (docs/design/system.md).

   Часть 1 перенесена из <style> base.html без изменений, кроме
   области действия селекторов header/nav. Часть 2 — компоненты
   Design Platform v1. */

/* ===== Часть 1 — перенесено из base.html ===== */
/* Оформление направления «Рабочий инструмент».
   Цвета и размеры приходят переменными из app/web/design.py — здесь
   их не задают заново. Правила системы: docs/design/system.md. */

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  padding: 0 16px;
  padding-block: 0 32px;
  background: var(--bg);
  color: var(--text-colour);
  font: 400 var(--text)/var(--line) var(--font-body);
}

/* ===== Шапка ===== */

body > header {
  margin: 0 -16px 12px;
  padding: 14px 16px 10px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
}

h1 {
  margin: 0;
  font-family: var(--font-heading);
  font-size: var(--text-lg);
  font-weight: 700;
  line-height: 1.25;
  color: var(--heading);
  text-wrap: balance;
  font-variant-numeric: lining-nums;
}

header .counts {
  margin-top: 2px;
  font-size: var(--text-sm);
  color: var(--muted);
}

header > nav { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 10px; }

/* Нажимаемое — не меньше 48px по короткой стороне: подушечка пальца
   шире, чем кажется, а специалист жмёт одной рукой между клиентами. */
header > nav a {
  display: flex;
  align-items: center;
  min-height: var(--tap);
  padding: 0 12px;
  font-size: 16px;
  color: var(--accent);
  text-decoration: none;
  border-radius: var(--radius);
}
header > nav a[aria-current="page"] {
  background: var(--note-bg);
  color: var(--note-text);
  font-weight: 600;
}

/* ===== Поиск ===== */

.search { display: flex; flex-wrap: wrap; gap: var(--gap); align-items: center; }

.search input {
  flex: 1 1 200px;
  min-width: 0;
  min-height: var(--tap);
  padding: 0 12px;
  font: inherit;
  color: var(--text-colour);
  background: var(--surface);
  border: 1px solid var(--control-border);
  border-radius: var(--radius);
}

.search button {
  min-height: var(--tap);
  min-width: var(--tap);
  padding: 0 18px;
  font: inherit;
  font-weight: 600;
  color: var(--on-accent);
  background: var(--accent);
  border: 1px solid var(--accent);
  border-radius: var(--radius);
  cursor: pointer;
}

/* «Сбросить» — второстепенное действие: ссылка, а не кнопка, и
   отдельной строкой, а не вплотную к «Найти». Правило целиком —
   docs/design/system.md, «Второстепенное и разрушительное». */
.search .reset {
  flex-basis: 100%;
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
  font-size: var(--text-sm);
  color: var(--muted);
}

/* Подсказка под строкой поиска (#89, static/typeahead.js). Список
   лежит поверх содержимого, строки — во всю ширину и не ниже
   нажимаемого минимума: попасть пальцем с первого раза. */
.typeahead { position: relative; flex: 1 1 200px; min-width: 0; display: flex; }
.typeahead input { flex: 1 1 auto; }
.typeahead-list {
  position: absolute;
  z-index: 10;
  top: calc(100% + var(--space-1));
  left: 0;
  right: 0;
  max-height: min(60vh, 420px);
  overflow-y: auto;
  margin: 0;
  padding: var(--space-1) 0;
  list-style: none;
  background: var(--surface);
  border: 1px solid var(--control-border);
  border-radius: var(--radius);
  box-shadow: 0 6px 20px rgb(0 0 0 / 0.12);
}
.typeahead-list [role=option] {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: var(--tap);
  padding: var(--space-1) var(--space-3);
  cursor: pointer;
}
.typeahead-list [role=option][aria-selected=true],
.typeahead-list [role=option]:hover { background: var(--note-bg); }
.typeahead-label { font-weight: 600; }
.typeahead-hint { font-size: var(--text-sm); color: var(--muted); }
.typeahead-empty {
  display: flex;
  align-items: center;
  min-height: var(--tap);
  padding: 0 var(--space-3);
  color: var(--muted);
}
.typeahead-status {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

:where(a, button, input):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ===== Карточка позиции ===== */

.card {
  margin: var(--gap) 0 0;
  padding: 12px var(--pad);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}

.row { display: flex; justify-content: space-between; gap: 12px; align-items: baseline; }
.name { font-weight: 600; }
.working { margin-top: 2px; font-size: var(--text-sm); color: var(--muted); }
.price { white-space: nowrap; font-variant-numeric: tabular-nums; text-align: right; }

/* Строка применения — то, что прочитает клиент. Её сверяют чаще
   всего, поэтому она выделена подложкой, а не курсивом. */
.example {
  margin-top: var(--gap);
  padding: 8px 10px;
  font-size: 16px;
  background: var(--note-bg);
  color: var(--note-text);
  border-radius: var(--radius);
}

/* Статус несёт и цвет, и слово: цветом одним пользоваться нельзя —
   его не различает часть людей и не видно на солнце. */
.neutral, .warning, .note {
  margin-top: var(--gap);
  padding: 8px 10px;
  font-size: 16px;
  border-radius: var(--radius);
}
.neutral { background: var(--success-bg); color: var(--success-text); }
.warning { background: var(--warning-bg); color: var(--warning-text); }
.note    { background: var(--note-bg);    color: var(--note-text); }

.card.note {
  margin-top: var(--gap);
  padding: 10px 12px;
  font-size: var(--text-sm);
  border: 1px solid var(--border);
}

.memo-body { margin-top: var(--gap); white-space: pre-wrap; }

/* ===== Вход специалиста ===== */

.signin { display: flex; flex-direction: column; gap: 14px; max-width: 420px; }

.signin label {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: var(--text-sm);
  color: var(--muted);
}

.signin input {
  min-height: var(--tap);
  padding: 0 12px;
  font: inherit;
  color: var(--text-colour);
  background: var(--surface);
  border: 1px solid var(--control-border);
  border-radius: var(--radius);
}

/* Флажок — в строку с подписью, а не полем на всю ширину. */
.signin label.check {
  flex-direction: row;
  align-items: center;
  gap: 10px;
  min-height: var(--tap);
  font-size: var(--text-base, inherit);
}
.signin label.check input { min-height: 0; width: 22px; height: 22px; padding: 0; }

.signin button {
  min-height: var(--tap);
  padding: 0 18px;
  font: inherit;
  font-weight: 600;
  color: var(--on-accent);
  background: var(--accent);
  border: 1px solid var(--accent);
  border-radius: var(--radius);
  cursor: pointer;
}

/* ===== Рабочее место специалиста ===== */

/* Основное действие — сплошная кнопка на акценте, в единственном
   числе на экране. docs/design/system.md, «Второстепенное и
   разрушительное». */
.primary {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: var(--tap);
  margin: var(--gap) 0 0;
  padding: 0 18px;
  font-weight: 600;
  color: var(--on-accent);
  background: var(--accent);
  border-radius: var(--radius);
  text-decoration: none;
}

/* Второстепенное действие рядом с основным: та же высота и место
   под палец, но контуром, а не заливкой — основное на экране одно.
   docs/design/system.md, «Второстепенное и разрушительное». */
.primary.secondary {
  color: var(--accent);
  background: var(--surface);
  border: 1px solid var(--accent);
}

/* Главное действие главного экрана — крупнее обычной кнопки: на
   экране оно одно, и ради него экран открывают (#83). */
.primary.lead {
  min-height: calc(var(--tap) + 16px);
  font-size: var(--text-lg);
  gap: 12px;
}
/* Плюс — заметнее самой надписи: крупный знак в светлом круге
   (OWNER UX review 3, п. 2). Спокойно, без украшательства. */
.primary.lead .plus {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; border-radius: 50%;
  font-size: 26px; line-height: 1; font-weight: 500;
  /* Светлый круг с плюсом цвета действия — дружелюбный знак, а не
     тёмная «плашка» (владелец, #85). */
  background: var(--on-accent);
  color: var(--accent);
}

/* Пустой экран нового специалиста. Кнопка не прижата к шапке: на
   пустой странице ей нужно место, иначе она читается как часть
   заголовка. */
.start { margin-top: 24px; }
.start .primary { margin-top: 0; }

.hint {
  margin: 10px 2px 0;
  font-size: var(--text-sm);
  color: var(--muted);
}

/* Клиент в списке — целиком нажимаемый: попасть в имя одной рукой
   между клиентами труднее, чем кажется. */
a.card.client {
  display: block;
  color: inherit;
  text-decoration: none;
}

.when { white-space: nowrap; font-size: var(--text-sm); color: var(--muted); }

/* Дата и время рядом: на 375 px они умещаются в строку вдвоём и
   переносятся, когда нет. */
.pair { display: flex; flex-wrap: wrap; gap: var(--gap); }
.pair label { flex: 1 1 140px; }

.add-visit {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-top: var(--gap);
  padding: 12px var(--pad);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}

.add-visit input {
  width: 100%;
  min-height: var(--tap);
  padding: 0 12px;
  font: inherit;
  color: var(--text-colour);
  background: var(--bg);
  border: 1px solid var(--control-border);
  border-radius: var(--radius);
}

.add-visit label {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: var(--text-sm);
  color: var(--muted);
}

.add-visit button {
  min-height: var(--tap);
  padding: 0 18px;
  font: inherit;
  font-weight: 600;
  color: var(--on-accent);
  background: var(--accent);
  border: 1px solid var(--accent);
  border-radius: var(--radius);
  cursor: pointer;
}

.section {
  margin: 24px 0 0;
  font-family: var(--font-heading);
  font-size: var(--text);
  font-weight: 700;
  color: var(--heading);
}

/* Записи дня (#93): обычная строка-раскрытие с шевроном, как в
   системных списках телефона, — без собственного календаря. */
.appointments { margin-top: 24px; }
.appointments summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-height: var(--tap);
  list-style: none;
  cursor: pointer;
}
.appointments summary::-webkit-details-marker { display: none; }
.appointments summary .section { margin: 0; }
.appointments summary .when::after {
  content: "›";
  display: inline-block;
  margin-left: 10px;
  font-size: var(--text-lg);
  transition: transform .15s;
}
.appointments[open] summary .when::after { transform: rotate(90deg); }

.daynav { display: flex; flex-wrap: wrap; align-items: center; gap: var(--gap); }
.daynav .step {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: var(--tap); min-height: var(--tap);
  font-size: var(--text-lg); color: var(--accent); text-decoration: none;
  border: 1px solid var(--border); border-radius: var(--radius);
}
.daypick { flex: 1 1 140px; display: flex; gap: var(--gap); }
.daypick input {
  flex: 1 1 auto; min-width: 0; min-height: var(--tap); padding: 0 12px;
  font: inherit; color: var(--text-colour); background: var(--surface);
  border: 1px solid var(--control-border); border-radius: var(--radius);
}
.daypick button {
  min-height: var(--tap); padding: 0 14px; font: inherit;
  color: var(--accent); background: var(--surface);
  border: 1px solid var(--accent); border-radius: var(--radius);
}
.daynav .today {
  display: inline-flex; align-items: center; min-height: var(--tap);
  font-size: var(--text-sm); color: var(--accent);
}
/* Сделанная запись — тише остальных, но читается: статус словом и
   галочкой, фон не меняется. */
a.card.client.done { background: var(--bg); }
a.card.client.done .working { color: var(--success-text); }

/* «Выйти» — второстепенное действие: ссылкой, не кнопкой, и не
   рядом с рабочими элементами. docs/design/system.md. */
.signout { margin-top: 24px; }
.signout a { font-size: var(--text-sm); color: var(--muted); }

.signout button {
  min-height: var(--tap);
  padding: 0;
  font: inherit;
  font-size: var(--text-sm);
  color: var(--muted);
  background: none;
  border: none;
  text-decoration: underline;
  cursor: pointer;
}

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}

/* =====================================================================
   Design Platform v1 — компоненты (02.10.2026).
   Классы, на которые опираются тесты и JS (`primary`, `primary lead`,
   `card`, `card client`, `appointments`, классы конструктора), —
   это и есть API компонентов: оформление меняется здесь, разметка и
   контракты шаблонов остаются. Каталог: docs/design/components.md.
   ===================================================================== */

:root {
  --icon-check: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5l4.5 4.5L19 7'/%3E%3C/svg%3E");
  --icon-chevron-right: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9 6l6 6-6 6'/%3E%3C/svg%3E");
}

/* ----- Foundations ----- */
body { display: flex; flex-direction: column; min-height: 100dvh; }
main { flex: 1 0 auto; width: 100%; max-width: var(--content-max); margin: 0 auto; }
.icon { width: 24px; height: 24px; flex: none; stroke: currentColor; fill: none;
        stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round; }
.icon--sm { width: 20px; height: 20px; }
.icon--xs { width: 16px; height: 16px; stroke-width: 2.25; }
.visually-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
:where(a, button, input, textarea, select, summary):focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.brand-mark { display: block; width: 26px; height: auto; margin-bottom: var(--space-2); }
.brand-signin { display: flex; flex-direction: column; align-items: center; gap: 14px; margin: var(--space-6) auto var(--space-4); }
.brand-signin img { display: block; height: auto; }
/* Название в SVG чёрное: в тёмной теме инвертируется, master-файл не трогаем. */
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .brand-wordmark { filter: invert(1); } }
:root[data-theme="dark"] .brand-wordmark { filter: invert(1); }
.login-head { text-align: center; }
.login-head > * { grid-column: 1 / -1 !important; }
.working, h1 { overflow-wrap: anywhere; }
/* Имена людей переносим только между словами: разрыв «Васильев\nна» на 375 px — дефект чтения. */
.name { overflow-wrap: normal; word-break: normal; }

/* ----- AppNav: BottomNav < 1024 px, TopNav ≥ 1024 px (одна разметка) -----
   Макрос стоит в DOM дважды (до шапки и после main), видим ровно один:
   порядок фокуса совпадает с видимым без flex order. */
.appnav.appnav--top { display: none; }
.appnav { position: sticky; bottom: 0; z-index: 5; margin: var(--space-6) -16px 0;
          padding: 6px var(--space-2) calc(10px + env(safe-area-inset-bottom));
          background: var(--surface); border-top: 1px solid var(--border); }
.appnav__brand { display: none; }
.appnav__links { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: var(--gap); }
.appnav__links a { display: flex; flex-direction: column; align-items: center; gap: 2px; min-height: 56px;
                   padding-top: var(--space-1); font-size: var(--text-xs); color: var(--muted); text-decoration: none; }
.appnav__pill { display: flex; align-items: center; justify-content: center; width: 56px; height: 30px; border-radius: var(--radius-pill); }
.appnav__links a[aria-current="page"] { color: var(--accent-soft-text); font-weight: 600; }
.appnav__links a[aria-current="page"] .appnav__pill { background: var(--accent-soft); }
@media (min-width: 1024px) {
  main { max-width: var(--content-max-wide); }
  .appnav.appnav--top { display: flex; }
  .appnav.appnav--bottom { display: none; }
  .appnav { position: sticky; top: 0; bottom: auto; margin: 0 -16px; padding: 0 var(--space-6);
            display: flex; align-items: center; gap: var(--space-6); min-height: 64px; border-top: 0; border-bottom: 1px solid var(--border); }
  .appnav__brand { display: flex; align-items: center; gap: 10px; font-weight: 700; color: var(--heading); text-decoration: none; }
  .appnav__brand img { width: 30px; height: auto; }
  .appnav__links { display: flex; gap: var(--space-1); }
  .appnav__links a { flex-direction: row; min-height: var(--tap); padding: 0 14px; font-size: var(--text); color: var(--text-colour); border-radius: var(--radius); }
  .appnav__links a:hover { background: var(--note-bg); }
  .appnav__pill { display: none; }
  .appnav__links a[aria-current="page"] { background: var(--accent-soft); }
}

/* ----- PrimaryButton / SecondaryButton / Lead / Destructive ----- */
.primary { gap: var(--space-2); width: 100%; border: 1px solid var(--accent); font: inherit; font-weight: 600; cursor: pointer; }
.primary:hover { background: var(--accent-hover); border-color: var(--accent-hover); color: var(--on-accent); }
.primary:active { background: var(--accent-pressed); border-color: var(--accent-pressed); }
.primary.secondary:hover { background: var(--accent-soft); color: var(--accent); }
.primary.secondary:active { background: var(--accent-soft); color: var(--accent-soft-text); }
.primary:disabled, .primary[aria-disabled="true"] { color: var(--muted); background: var(--disabled-bg); border-color: var(--border); cursor: not-allowed; }
.primary[aria-busy="true"] { cursor: progress; }
.primary[aria-busy="true"]::before { content: ""; width: 16px; height: 16px; border-radius: 50%;
  border: 2px solid currentColor; border-right-color: transparent; animation: sino-spin .8s linear infinite; }
@keyframes sino-spin { to { transform: rotate(1turn); } }
.primary.lead .plus { font-weight: 600; }
.primary.danger { color: var(--on-accent); background: var(--danger-strong); border-color: var(--danger-strong); width: auto; }
.link-action { display: inline-flex; align-items: center; min-height: var(--tap); padding: 0 var(--space-1); font: inherit;
               font-size: var(--text-sm); color: var(--muted); background: none; border: 0; text-decoration: underline; cursor: pointer; }
.link-action--accent { color: var(--accent); }
.link-action--danger { color: var(--danger-text); }
.icon-btn { display: inline-flex; align-items: center; justify-content: center; width: var(--tap); height: var(--tap); flex: none;
            padding: 0; color: var(--text-colour); background: none; border: 0; border-radius: var(--radius); text-decoration: none; cursor: pointer; }
.icon-btn:hover { background: var(--note-bg); }
.daynav .step { background: var(--surface); }
.daynav .step:hover { background: var(--accent-soft); }

/* ----- TopBar (шапка страницы) ----- */
body > header { display: grid; grid-template-columns: auto minmax(0, 1fr); column-gap: var(--space-1); align-items: center; }
body > header > :not(.back) { grid-column: 2; }
body > header > .back { grid-row: 1 / span 2; margin-left: calc(-1 * var(--space-3)); }
body > header .counts:empty { display: none; }
.home-head { background: none; border-bottom: 0; }

/* ----- Fields ----- */
.field { display: flex; flex-direction: column; gap: var(--space-1); font-size: var(--text-sm); color: var(--muted); }
.signin input:focus-visible, .search input:focus-visible, .daypick input:focus-visible, .add-visit input:focus-visible,
.picker input[type=search]:focus-visible, textarea:focus-visible, #new-client input:focus-visible, input.manual:focus-visible {
  outline: none; border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.field--error input, input[aria-invalid="true"] { border-color: var(--danger-text); box-shadow: 0 0 0 1px var(--danger-text); }
.field__error { display: flex; gap: 6px; align-items: flex-start; color: var(--danger-text); }

/* ----- Grouped list: соседние карточки — одна поверхность ----- */
.card { border-radius: var(--radius-card); }
.card:not(.note, .warning, .neutral) + .card:not(.note, .warning, .neutral) {
  margin-top: 0; border-top-left-radius: 0; border-top-right-radius: 0; }
.card:not(.note, .warning, .neutral):has(+ .card:not(.note, .warning, .neutral)) {
  border-bottom: 0; border-bottom-left-radius: 0; border-bottom-right-radius: 0; }

/* ----- ClientRow / AppointmentRow ----- */
:is(a, button).card.client { display: flex; align-items: center; gap: var(--space-3); min-height: 56px; padding: 10px var(--pad); }
:is(a, button).card.client:hover { background: var(--bg); }
/* Выбор клиента под записью (#172) — кнопка формы, та же строка. */
button.card.client { width: 100%; text-align: left; font: inherit; color: inherit; cursor: pointer; }
a.card.client > .row, a.card.client > .body { flex: 1; min-width: 0; }
a.card.client > .body { display: flex; flex-direction: column; }
a.card.client .time { width: 48px; flex: none; font-size: var(--text-sm); font-weight: 600; font-variant-numeric: tabular-nums; }
a.card.client .chev { flex: none; display: flex; color: var(--muted); }
a.card.client.done { background: var(--surface); }
a.card.client.done .time { color: var(--muted); }
a.card.client.done .working { display: flex; align-items: center; gap: var(--space-1); font-size: var(--text-xs); font-weight: 600; }
.appointment-static { display: flex; align-items: center; gap: var(--space-3); min-height: 56px; padding: 10px var(--pad); }
.appointment-static > .body { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.appointment-static .time { width: 48px; flex: none; font-size: var(--text-sm); font-weight: 600; color: var(--muted); font-variant-numeric: tabular-nums; }

/* ----- MetricRow (админка, #409): строка grouped list, число справа ----- */
.card.metric { display: flex; align-items: center; gap: var(--space-3); min-height: 56px; padding: 10px var(--pad);
               color: inherit; text-decoration: none; }
.card.metric > .body { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.metric__value { flex: none; font-size: var(--text-lg); font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap; }
.card.metric .chev { flex: none; display: flex; color: var(--muted); }
a.card.metric:hover { background: var(--bg); }
.metric-groups > section > .section { margin-top: var(--space-6); }
/* Образец AppNav админки в /design-system: на месте, а не прилипшим. */
.ds-nav-preview .appnav.appnav--bottom { display: block; position: static; margin: var(--space-3) 0 0; }
/* Строка без перехода (div.card.client): та же раскладка, без hover. */
div.card.client { display: flex; flex-direction: column; justify-content: center; min-height: 56px; padding: 10px var(--pad); }
/* Со статусом (tag) — строки друг под другом, как у RecommendationRow. */
a.card.client:has(> .status-tag) { flex-direction: column; align-items: stretch; gap: 0; }
.card.client > .status-tag { margin-top: var(--space-1); }
/* Фильтр статуса и страницы списков админки — ссылки, состояние в адресе. */
.admin-filter { display: flex; flex-wrap: wrap; gap: var(--space-2); margin: var(--space-3) 0; }
.admin-filter a { display: inline-flex; align-items: center; min-height: var(--tap); padding: 0 var(--space-3);
                  border: 1px solid var(--border); border-radius: var(--radius-sm); color: inherit; text-decoration: none; font-size: var(--text-sm); }
.admin-filter a[aria-current] { background: var(--accent-soft); color: var(--accent-soft-text); border-color: var(--accent-soft); font-weight: 600; }
.pager { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-3); margin-top: var(--space-3); }
@media (min-width: 1024px) {
  .metric-groups { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--space-6); align-items: start; }
}

/* ----- Status / EmptyState / InlineError ----- */
.status-tag { display: inline-flex; align-items: center; gap: var(--space-1); align-self: flex-start; padding: 2px var(--space-2);
              font-size: var(--text-xs); font-weight: 600; border-radius: var(--radius-sm); }
.status-tag--success { background: var(--success-bg); color: var(--success-text); }
.status-tag--note { background: var(--note-bg); color: var(--note-text); }
.status-tag--warning { background: var(--warning-bg); color: var(--warning-text); }
.done-link { display: inline-flex; align-items: center; gap: var(--space-1); min-height: var(--tap); color: var(--success-text); font-weight: 600; text-decoration: none; }
.action-link { display: inline-flex; align-items: center; gap: var(--space-1); min-height: var(--tap); color: var(--accent); font-weight: 600; text-decoration: none; }
.card.note, .card.warning { display: flex; gap: var(--space-2); align-items: flex-start; border-radius: var(--radius); }
.card.note { border: 0; }

/* ----- Disclosure (записи дня) ----- */
.appointments summary .when::after { content: ""; width: 20px; height: 20px; margin-left: var(--space-2); vertical-align: -4px;
  background: currentColor; -webkit-mask: var(--icon-chevron-right) center / contain no-repeat; mask: var(--icon-chevron-right) center / contain no-repeat; }

/* ----- Chip ----- */
.chip { display: inline-flex; align-items: center; justify-content: center; gap: var(--space-1); min-width: var(--tap); min-height: var(--tap);
        padding: 0 14px; font: inherit; color: var(--text-colour); background: var(--surface); white-space: nowrap; flex: none;
        border: 1px solid var(--control-border); border-radius: var(--radius-pill); cursor: pointer; }
.chip:hover { background: var(--bg); }
/* Выбранное — мягкой подложкой: сплошной акцент только у главной кнопки экрана (02.10.2026). */
.chip[aria-pressed="true"] { color: var(--accent-soft-text); background: var(--accent-soft); border-color: var(--accent); font-weight: 600; }
.chip[aria-pressed="true"]::before { content: ""; width: 14px; height: 14px; flex: none; background: currentColor;
  -webkit-mask: var(--icon-check) center / contain no-repeat; mask: var(--icon-check) center / contain no-repeat; }
.chip:disabled { color: var(--muted); background: var(--disabled-bg); border-color: var(--border); cursor: not-allowed; }
.chips { display: flex; flex-wrap: wrap; gap: var(--gap); margin: var(--space-2) 0; align-items: center; }
.chips .label { flex: 0 0 100%; font-size: var(--text-sm); color: var(--muted); }

/* ----- RecommendationConstructor: CourseCard / PreparationRow / CostSummary -----
   Перенесено из локального <style> recommend_constructor.html (классы
   строит его JS). Жёсткие белый и зелёный цвета заменены токенами. */
.course { margin: var(--space-3) 0; padding: var(--space-3) var(--pad); background: var(--surface);
          border: 1px solid var(--border); border-radius: var(--radius-card); }
.course-head { display: flex; justify-content: space-between; align-items: baseline; gap: var(--space-2); }
.course-head h2 { margin: 0; font-size: var(--text-lg); }
.chip.small { min-width: var(--tap); min-height: var(--tap); padding: 0; }
.chip.danger { color: var(--on-accent); background: var(--danger-strong); border-color: transparent; border-radius: var(--radius); }
.item { margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--border); }
.item-head { display: flex; justify-content: space-between; gap: var(--space-2); align-items: center; }
.item-name { font-size: var(--text-sm); font-weight: 500; color: var(--muted); }
.usage { margin: 2px 0 var(--space-2); font-size: var(--text); color: var(--text-colour); text-wrap: pretty; }
.row-actions { display: flex; flex-wrap: wrap; gap: var(--gap); margin-top: 10px; }
.picker { margin-top: 10px; }
.picker .results .chip { text-align: left; border-radius: var(--radius); }
.preview .line { margin: var(--space-1) 0; }
#constructor .status { margin: var(--space-2) 0; font-size: var(--text-sm); color: var(--muted); }
#constructor .error { padding: var(--space-2) var(--space-3); color: var(--danger-text); background: var(--danger-bg); border-radius: var(--radius-sm); }
.picker input[type=search], #constructor textarea, #new-client input, label.age input, input.manual {
  font: inherit; color: var(--text-colour); background: var(--surface); border: 1px solid var(--control-border); border-radius: var(--radius); }
.picker input[type=search] { width: 100%; min-height: var(--tap); padding: 0 var(--space-3); }
#constructor textarea { width: 100%; min-height: 4.5em; padding: 10px var(--space-3); }
.manual { width: 5.5em; min-height: var(--tap); padding: 0 var(--space-2); }
.notes label { display: block; margin: var(--space-2) 0; }
button.disclosure { display: flex; justify-content: space-between; align-items: center; width: 100%; min-height: var(--tap);
  padding: 0 14px; margin-top: var(--space-3); font: inherit; font-weight: 600; color: var(--text-colour);
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); cursor: pointer; }
button.disclosure .chevron { color: var(--muted); }
.cost { margin: var(--space-3) 0; padding: var(--space-3) var(--pad); background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-card); }
.cost-title { margin-bottom: 6px; font-weight: 600; }
.cost table { width: 100%; border-collapse: collapse; font-size: var(--text-sm); }
.cost th { padding: var(--space-1) 0; text-align: left; font-weight: 500; color: var(--muted); }
.cost td { padding: var(--space-1) 0; vertical-align: top; border-top: 1px solid var(--border); overflow-wrap: anywhere; }
.cost .num { padding-left: var(--space-2); text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
.cost .total { margin-top: var(--space-2); font-size: var(--text); }
.confirm-delete { margin-top: var(--space-3); padding: var(--space-3); border-radius: var(--radius-card); background: var(--danger-bg); color: var(--danger-text); }
.link-danger { min-height: var(--tap); margin-top: 10px; padding: 0 var(--space-1); font: inherit; color: var(--danger-text);
               background: none; border: 0; text-decoration: underline; cursor: pointer; }
.add-course { display: flex; align-items: center; justify-content: center; gap: var(--space-2); width: 100%; min-height: var(--tap);
              margin: var(--space-1) 0 var(--space-3); font: inherit; font-weight: 600; font-size: var(--text-lg); color: var(--accent);
              background: var(--surface); border: 1.5px solid var(--accent); border-radius: var(--radius); cursor: pointer; }
.chip.add-item { font-weight: 600; color: var(--accent); border-color: var(--accent); border-radius: var(--radius); }
.add-course:hover, .chip.add-item:hover { background: var(--accent-soft); }
.add-course .plus, .add-item .plus { font-size: 1.3em; line-height: 1; }
.packs-note { margin: 0 0 var(--space-2); font-size: var(--text-sm); color: var(--muted); }
.packs-note.manual-check { padding: var(--space-1) var(--space-2); color: var(--warning-text); background: var(--warning-bg); border-radius: var(--radius-sm); }
.link-inline { min-height: var(--tap); padding: 0 var(--space-1); font: inherit; color: var(--accent); background: none; border: 0; text-decoration: underline; cursor: pointer; }
#new-client h2 { margin: 0 0 var(--space-1); font-size: var(--text-lg); }
#new-client label, label.age { display: block; margin: 10px 0 0; }
#new-client input, label.age input { display: block; width: 100%; min-height: var(--tap); margin-top: var(--space-1); padding: 0 10px; }
label.age input { width: 6em; }

/* ----- SearchField / TextArea / Disclosure / States (Design Platform v1.1) ----- */
.search[aria-busy="true"] button { cursor: progress; color: var(--muted); }
.textarea { width: 100%; min-height: calc(var(--tap) * 2); padding: 10px var(--space-3); font: inherit; color: var(--text-colour);
            background: var(--surface); border: 1px solid var(--control-border); border-radius: var(--radius); resize: vertical; }
.textarea:disabled { color: var(--muted); background: var(--disabled-bg); border-color: var(--border); }
.field--error .textarea { border-color: var(--danger-text); box-shadow: 0 0 0 1px var(--danger-text); }
.field__hint { font-size: var(--text-xs); color: var(--muted); }
.disclosure { margin: var(--space-3) 0; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); }
.disclosure > summary { display: flex; align-items: center; gap: var(--space-2); min-height: var(--tap); padding: 0 14px;
                        font-weight: 600; cursor: pointer; list-style: none; }
.disclosure > summary::-webkit-details-marker { display: none; }
.disclosure > summary > span:first-child { flex: 1; min-width: 0; }
.disclosure__meta { font-size: var(--text-sm); font-weight: 400; color: var(--muted); }
.disclosure > summary .icon { color: var(--muted); transition: transform .15s; }
.disclosure[open] > summary .icon { transform: rotate(180deg); }
.disclosure__body { padding: 0 14px var(--space-3); }
.state { display: flex; flex-direction: column; gap: var(--space-2); align-items: flex-start; padding: var(--space-4) var(--pad);
         border-radius: var(--radius-card); background: var(--note-bg); color: var(--note-text); }
.state p { margin: 0; }
.state__title { display: flex; align-items: center; gap: var(--space-2); font-weight: 600; }
.state__text { font-size: var(--text-sm); }
.state--error { background: var(--danger-bg); color: var(--danger-text); }
.state--done { background: var(--success-bg); color: var(--success-text); }
.state--loading { flex-direction: row; align-items: center; background: none; color: var(--muted); }
.spinner { width: 20px; height: 20px; flex: none; border-radius: 50%; border: 2px solid currentColor; border-right-color: transparent; animation: sino-spin .8s linear infinite; }
.state .primary { width: auto; }
a.card.client.rec .status-tag { margin-top: var(--space-1); }
@media (prefers-reduced-motion: reduce) { .spinner, .primary[aria-busy="true"]::before { animation-duration: 2.4s; } .disclosure > summary .icon { transition: none; } }

/* ----- /design-system: раскладка витрины ----- */
.ds-section { margin-top: var(--space-6); }
.ds-frames { display: flex; flex-wrap: wrap; gap: var(--space-6); align-items: flex-start; }
.ds-frame { flex: none; max-width: 100%; padding: var(--space-4); background: var(--bg); border: 1px dashed var(--control-border); border-radius: var(--radius-card); }
.ds-frame--320 { width: 320px; } .ds-frame--375 { width: 375px; } .ds-frame--393 { width: 393px; } .ds-frame--wide { width: min(100%, 960px); }
.ds-frame.theme-dark { color: var(--text-colour); background: var(--bg); }
.ds-states { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: var(--space-2) var(--space-3); align-items: center; }
.ds-states > span { font-size: var(--text-xs); color: var(--muted); }
