/* ─────────────────────────────────────────────────────────────────────────────
   SXEMA2 — админка и публичные страницы. Компоненты дизайн-системы
   (токены и шрифты — в theme.css). Стиль «Верстак»: парящий сайдбар-карточка,
   белые карточки, чёрные пилюли-кнопки, таблицы с прописными шапками.
   ───────────────────────────────────────────────────────────────────────────── */

/* ── Каркас приложения ── */
.app {
  display: flex;
  height: 100vh;
  padding: 16px 0 16px 16px;
  gap: 8px;
}

.main {
  flex: 1;
  overflow-y: auto;
  padding: 16px 28px 64px;
  min-width: 0;
}

.page-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 20px;
  flex-wrap: wrap;
}
.page-head h1 { font-size: var(--text-2xl); }
.page-head .sub {
  display: block;
  margin-top: 4px;
  color: var(--ink-faint);
  font-size: var(--text-sm);
  font-weight: 500;
}

.sec-title {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin: 28px 0 14px;
  /* на узком экране заголовок переносился, а счётчик с подписью улетали
     к правому краю — теперь просто продолжают строку */
  flex-wrap: wrap;
}
/* заголовок сжимается, если не влезает, а не выталкивает страницу вбок */
.sec-title h2 { min-width: 0; }
.sec-title h2 { font-size: var(--text-lg); font-weight: 800; }
.sec-title .cnt, .sec-title .sub {
  font-size: var(--text-sm);
  color: var(--ink-faint);
  font-weight: 500;
}

.muted { color: var(--ink-faint); }
.small { font-size: var(--text-xs); }

/* ── Сайдбар: «парящая» белая карточка ── */
.sidebar {
  width: var(--sidebar-w);
  flex-shrink: 0;
  background: var(--paper-raised);
  border: 1px solid var(--card-border);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-1);
  color: var(--ink);
  display: flex;
  flex-direction: column;
  padding: 24px 14px 20px;
}
.sidebar .logo {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 10px 24px;
}
.sidebar .logo:hover { text-decoration: none; }
.logo-mark {
  width: 32px;
  height: 32px;
  border-radius: 10px;
  background: var(--ink);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.logo-mark svg {
  width: 17px;
  height: 17px;
  stroke: var(--on-ink);
  fill: none;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.logo-name {
  font-weight: 800;
  font-size: 1.05rem;
  letter-spacing: -0.01em;
}
.logo-name small {
  display: block;
  font-size: 10px;
  font-weight: 600;
  color: var(--ink-faint);
  letter-spacing: 0.06em;
}
.sidebar-nav { display: contents; } /* обёртка <nav> не должна ломать раскладку сайдбара */
.nav-item {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 10px 14px;
  border-radius: var(--r-pill);
  color: var(--ink-soft);
  font-size: var(--text-sm);
  font-weight: 600;
  margin-bottom: 4px;
  transition: background 0.15s, color 0.15s, box-shadow 0.15s;
}
.nav-item:hover {
  background: var(--paper-sunken);
  color: var(--ink);
  text-decoration: none;
}
.nav-item.active {
  background: var(--ink);
  color: var(--on-ink);
  box-shadow: var(--shadow-dark);
}
.nav-item .ico {
  width: 17px;
  height: 17px;
  flex-shrink: 0;
  display: inline-flex;
}
.nav-item .ico svg {
  width: 100%;
  height: 100%;
  stroke: currentColor;
  fill: none;
  stroke-width: 1.9;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.nav-sec {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-faint);
  padding: 20px 14px 6px;
}
.sidebar .spacer { flex: 1; }
.sidebar .user-box {
  border-top: 1px solid var(--line);
  margin: 0 4px;
  padding: 14px 6px 0;
  display: flex;
  align-items: center;
  gap: 10px;
}
.ava {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--ink);
  color: var(--on-ink);
  font-weight: 700;
  font-size: var(--text-sm);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.sidebar .user-box .name {
  color: var(--ink);
  font-weight: 700;
  font-size: var(--text-sm);
  line-height: 1.2;
}
.sidebar .user-box a {
  background: none;
  border: none;
  padding: 2px 0;
  color: var(--ink-faint);
  font-size: var(--text-xs);
  font-weight: 500;
}
.sidebar .user-box a:hover { color: var(--ink); }
.theme-btn {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: 1.5px solid var(--line-strong);
  background: none;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  margin-left: auto;
  transition: border-color 0.15s, transform 0.15s;
}
.theme-btn:hover {
  border-color: var(--ink);
  transform: translateY(-1px);
}
.theme-btn svg {
  width: 15px;
  height: 15px;
  stroke: var(--ink-soft);
  fill: none;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.theme-btn:hover svg { stroke: var(--ink); }

/* ── Карточки ── */
.card {
  background: var(--paper-raised);
  border: 1px solid var(--card-border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-1);
  padding: 18px 20px;
  margin: 0 0 16px;
  overflow: hidden;
}
.card.flush { padding: 0; }
.card-head {
  display: flex;
  align-items: center;
  /* заголовок и счётчик держатся вместе слева, действия уезжают вправо сами */
  justify-content: flex-start;
  gap: 12px;
  padding: 18px 20px 12px;
}
.card-head > form,
.card-head > .actions { margin-left: auto; }
/* внутри обычной карточки отступ уже есть — не удваиваем его */
.card:not(.flush) > .card-head { padding: 0 0 12px; }
.card.flush .card-head { padding: 16px 20px 10px; }
.card-head h2 { font-size: var(--text-lg); font-weight: 700; }
.card > .tbl { margin: 0; }

/* ── Кнопки ── */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border: 1.5px solid var(--line-strong);
  background: var(--paper-raised);
  color: var(--ink);
  border-radius: var(--r-pill);
  padding: 7px 16px;
  font-size: var(--text-sm);
  font-weight: 600;
  line-height: 1.2;
  cursor: pointer;
  text-decoration: none;
  transition: all 0.15s var(--ease);
}
.btn:hover {
  border-color: var(--ink);
  text-decoration: none;
  transform: translateY(-1px);
}
.btn:active { transform: none; }
.btn.primary {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--on-ink);
  box-shadow: var(--shadow-dark);
}
.btn.primary:hover { background: #000000; color: var(--on-ink); }
.btn.danger { color: var(--danger); }
.btn.danger:hover { border-color: var(--danger); }
.btn.danger.primary {
  background: var(--danger);
  border-color: var(--danger);
  color: var(--on-danger);
}
.btn.sm { padding: 4px 12px; font-size: var(--text-xs); }
.btn:disabled { opacity: 0.5; pointer-events: none; }
.btn svg {
  width: 15px;
  height: 15px;
  stroke: currentColor;
  fill: none;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* ── Формы ── */
form label { display: block; margin-bottom: 12px; }
/* В ряду подписи стоят рядом, а не друг под другом: нижний отступ здесь
   опускал кнопку ниже полей — она переставала стоять с ними на одной линии. */
.row > label, form.inline > label, .row > .filefield { margin-bottom: 0; }
form label input, form label select, form label .sel-btn, form label textarea {
  display: block;
  width: 100%;
  margin-top: 5px;
}
form label small {
  display: block;
  margin-top: 5px;
  font-weight: 500;
}
/* Ряд «поле + поле + кнопка»: равняем по нижнему краю, иначе кнопка,
   у которой нет подписи сверху, всплывает выше полей. */
form.inline, .card > form.inline, .card .inline { display: flex; gap: 12px; align-items: flex-end; flex-wrap: wrap; }
form.inline > label { margin-bottom: 0; }
/* Поля прямо в ряду сохраняют свою ширину; поля внутри подписи тянутся
   по подписи — иначе select уже своей ячейки и рядом зияет дыра. */
form.inline > input, form.inline > select, form.inline > .sel-btn { width: auto; flex: 0 1 auto; }
details summary {
  cursor: pointer;
  color: var(--ink-soft);
  font-size: var(--text-sm);
  font-weight: 600;
  margin-top: 10px;
}
details summary:hover { color: var(--ink); }
details[open] summary { margin-bottom: 10px; }

/* Ряд полей, выровненный по ВЕРХУ. Нужен там, где под полем есть подсказка:
   при выравнивании по низу (обычном для ряда) такое поле поднимается на
   высоту подсказки, и соседние поля встают на разной высоте. Голая кнопка в
   таком ряду опускается на высоту строки подписи — иначе она окажется выше
   полей. */
/* Селектор нарочно такой длинный: ряд внутри карточки ловится правилом
   «.card > form.inline», и оно весомее простого «.inline.top» — короткая
   запись молча не срабатывала. */
.inline.top, .card .inline.top, .card > form.inline.top { align-items: flex-start; }
/* Подпись, поле, подсказка — три строки сетки. Первая строка одинаковой
   высоты у всех подписей ряда, поэтому поля начинаются на одном уровне
   независимо от того, есть ли под соседним полем подсказка и насколько
   высок сам виджет (выбор файла выше обычного поля на три точки). */
.inline.top > label, .card .inline.top > label { display: grid; grid-template-rows: minmax(22px, auto) auto auto; }
.inline.top > label > *, .card .inline.top > label > * { margin-top: 5px; }
.inline.top > .btn, .inline.top > button,
.card .inline.top > .btn, .card .inline.top > button { margin-top: 27px; }

/* ── Таблицы ── */
.table-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
.tbl {
  width: 100%;
  border-collapse: collapse;
}
.tbl th {
  text-align: left;
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  /* был --ink-faint: на тёмной теме заголовки таблиц давали 3.4:1 при норме 4.5 */
  color: var(--ink-soft);
  font-weight: 700;
  padding: 10px 12px;
  border-bottom: 1px solid var(--line);
  background: var(--paper-raised);
}
.tbl td {
  padding: 12px;
  border-bottom: 1px solid var(--line);
  vertical-align: top;
}
.tbl th:first-child, .tbl td:first-child { padding-left: 20px; }
.tbl th:last-child, .tbl td:last-child { padding-right: 20px; }
.tbl tr:last-child td { border-bottom: none; }
.tbl td .btn { margin-right: 6px; }
.tbl .num {
  font-family: var(--font-mono);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* ── Прочее ── */
.row {
  display: flex;
  /* Раньше здесь стояло space-between — и любой ряд из двух-трёх полей
     растаскивало по всей ширине экрана. Прижимаем влево; там, где нужно
     развести по краям, ставим .row.spread. */
  justify-content: flex-start;
  gap: 10px;
  align-items: center;
  flex-wrap: wrap;
}
.row.spread { justify-content: space-between; }
/* Кнопок в шапке страницы бывает и шесть — на телефоне они уезжали
   за край и тащили за собой всю страницу. Переносим на вторую строку. */
.actions { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }

.kv {
  margin-top: 4px;
  font-size: var(--text-sm);
  display: grid;
  gap: 7px;
}
.kv .k { color: var(--ink-faint); }

code.sel {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 600;
  background: var(--paper-sunken);
  padding: 3px 8px;
  border-radius: 8px;
  user-select: all;
  word-break: break-all;
}

.tag, .chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 11px;
  border-radius: var(--r-pill);
  font-size: var(--text-xs);
  font-weight: 600;
  background: var(--paper-sunken);
  color: var(--ink-soft);
  white-space: nowrap;
}
.tag.ok {
  background: var(--ink);
  color: var(--on-ink);
}

/* Ряд производителей над библиотекой текстур: их полсотни, поэтому
   переносятся и прокручиваются, а не растягивают страницу вбок. */
.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
a.chip {
  text-decoration: none;
  border: 1px solid transparent;
}
a.chip:hover {
  border-color: var(--line);
}
a.chip span {
  color: var(--ink-faint);
  font-weight: 500;
}
a.chip.on {
  background: var(--ink);
  color: var(--on-ink);
}
a.chip.on span {
  color: var(--on-ink);
  opacity: .7;
}
.pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--text-xs);
  font-weight: 600;
  padding: 3px 11px;
  border-radius: var(--r-pill);
  white-space: nowrap;
}
.pill::before {
  content: '';
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: currentColor;
}
.pill.new { color: var(--st-new); background: var(--st-new-bg); }
.pill.work { color: var(--st-work); background: var(--st-work-bg); }
.pill.done { color: var(--st-done); background: var(--st-done-bg); }

.list { list-style: none; padding: 0; margin: 0; }
.list li {
  background: var(--paper-raised);
  border: 1px solid var(--card-border);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-1);
  padding: 12px 16px;
  margin: 8px 0;
  font-size: var(--text-sm);
  line-height: 1.45;
}

.alert {
  border-left: 3px solid var(--danger);
  background: #faeae7;
  color: #8c2b20;
  border-radius: var(--r-sm);
  padding: 10px 14px;
  margin: 0 0 16px;
  font-size: var(--text-sm);
  font-weight: 500;
}
/* Ссылка внутри плашки берёт её цвет. Свой синий на красном фоне не читается —
   на тёмной теме получалось 1.04 при норме 4.5, то есть почти невидимо. */
.alert a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* Предупреждение: не поломка, а «скоро кончится». Цвета — из темы,
   чтобы в тёмной не остаться чёрным по бежевому. */
.alert.warn {
  border-left-color: var(--warn);
  background: var(--warn-bg);
  color: var(--warn);
}

.alert.ok {
  border-left-color: var(--ink);
  background: var(--paper-raised);
  color: var(--ink);
  box-shadow: var(--shadow-1);
}

/* Пустое состояние */
.empty {
  text-align: center;
  color: var(--ink-faint);
  padding: 34px 16px;
  font-size: var(--text-sm);
}

/* ── Библиотека текстур ── */
.tex-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: 14px;
}
.tex-card {
  display: flex;
  flex-direction: column;
  margin: 0;
  padding: 0;
  /* Без рамки: картинка лежит вплотную к краю, и однопиксельная рамка
     карточки светилась вокруг тёмных декоров тонким контуром. */
  border: 0;
}
.tex-card img {
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  display: block;
  background: var(--paper-sunken);
  /* скругление повторяем на самой картинке: тогда её край и край карточки
     совпадают и между ними не остаётся светлой полоски */
  border-radius: var(--r-lg) var(--r-lg) 0 0;
}
.tex-meta {
  padding: 12px 14px 4px;
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}
.tex-meta b { font-size: var(--text-sm); overflow-wrap: anywhere; }
.tex-card form { padding: 8px 14px 14px; margin-top: auto; }

/* ── Страница входа ── */
.login-body {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  padding: 16px;
}
.login { width: 360px; padding: 28px 26px; }
.login h1 {
  display: flex;
  align-items: center;
  gap: 12px;
  font-size: var(--text-xl);
  margin-bottom: 4px;
}
.login h1 .logo-mark { width: 38px; height: 38px; border-radius: 12px; }
.login h1 .logo-mark svg { width: 20px; height: 20px; }
.login .sub {
  color: var(--ink-faint);
  font-size: var(--text-sm);
  margin: 0 0 18px;
}
.login .btn { width: 100%; justify-content: center; margin-top: 6px; padding: 9px 16px; }

/* ── Телефон: сайдбар превращается в нижнюю панель ── */
@media (max-width: 900px) {
  .app { padding: 0; gap: 0; flex-direction: column; height: auto; min-height: 100vh; }
  .main { padding: 18px 14px 110px; overflow: visible; }
  .sidebar {
    position: fixed;
    bottom: 0; left: 0; right: 0; top: auto;
    width: auto;
    flex-direction: row;
    align-items: stretch;
    justify-content: flex-start;
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    gap: 2px;
    padding: 6px 8px calc(6px + env(safe-area-inset-bottom, 0px));
    z-index: 40;
    border-radius: 18px 18px 0 0;
    box-shadow: 0 -8px 30px rgba(20, 20, 20, 0.12);
  }
  .sidebar::-webkit-scrollbar { display: none; }
  .sidebar .logo, .sidebar .spacer, .sidebar .nav-sec { display: none; }

  /* На телефоне «Выйти» и переключатель темы раньше просто пропадали —
     выйти из админки было нечем. Оставляем их в конце нижней панели. */
  .sidebar .user-box {
    display: flex; flex: 0 0 auto; align-items: center; gap: 4px;
    margin: 0 0 0 4px; padding: 0 2px 0 8px; border: 0;
    border-left: 1px solid var(--line); border-radius: 0;
    /* прилипает к правому краю панели — «Выйти» не надо искать прокруткой */
    position: sticky; right: 0; background: var(--paper-raised);
    box-shadow: -10px 0 12px -6px var(--paper-raised);
  }
  .sidebar .user-box .ava, .sidebar .user-box .name { display: none; }
  .sidebar .user-box a {
    display: flex; align-items: center; justify-content: center;
    min-width: 58px; min-height: 40px; padding: 7px 10px;
    font-size: var(--text-xs); white-space: nowrap; border-radius: var(--r-md);
  }
  .sidebar .user-box .theme-btn { min-width: 40px; min-height: 40px; }

  /* Пальцем в кнопку 24px не попасть — на телефоне все кнопки крупнее */
  .btn.sm { min-height: 36px; padding: 7px 12px; }
  .tbl td .btn.sm { min-height: 34px; }
  .pickbox { width: 22px; height: 22px; }
  .nav-item {
    position: relative;
    flex: 0 0 auto;
    min-width: 58px;
    justify-content: center;
    align-items: center;
    padding: 7px 10px;
    margin: 0;
    font-size: var(--text-xs);
    flex-direction: column;
    gap: 3px;
    border-radius: var(--r-md);
    white-space: nowrap;
  }
}

@media print {
  .sidebar, .no-print { display: none !important; }
  .app { display: block !important; height: auto; padding: 0; }
  .main { padding: 0 !important; overflow: visible; }
  body { background: #fff; }
}


/* ---- Доступность: видимый фокус с клавиатуры ----------------------------
   Раньше полагались на обводку браузера: на тёмных кнопках её почти не видно,
   а по Tab должно быть однозначно понятно, где ты находишься. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--focus, #2f6feb);
  outline-offset: 2px;
  border-radius: 6px;
}
.btn:focus-visible, .nav-item:focus-visible { outline-offset: 3px; }
/* мышью обводку не показываем — она мешает и путает */
:where(a, button, input, select, textarea, summary):focus:not(:focus-visible) { outline: none; }

/* Ссылка «к содержимому» для тех, кто ходит с клавиатуры */
.skip-link {
  position: absolute; left: 8px; top: -60px; z-index: 100;
  padding: 10px 16px; border-radius: 10px;
  background: var(--ink); color: var(--on-ink); font-weight: 600;
  transition: top .15s ease;
}
.skip-link:focus { top: 8px; }

/* Шапка длинной таблицы держится при прокрутке — иначе на 100 строках
   непонятно, что за колонка перед тобой */
.tbl thead th {
  position: sticky; top: 0; z-index: 1;
  /* своим фоном шапка отделяется от заголовка карточки — раньше они
     сливались в две одинаковые строки заголовков подряд */
  background: var(--paper-sunken);
  box-shadow: inset 0 -1px 0 var(--line);
}
.table-scroll { max-height: min(70vh, 760px); overflow: auto; }
.table-scroll.short { max-height: none; }

/* Текст только для скринридеров: колонка без заголовка на экране, но
   называется вслух — «Выбор», «Скачать», «Действия» */
.vh {
  position: absolute; width: 1px; height: 1px; margin: -1px;
  padding: 0; border: 0; overflow: hidden; white-space: nowrap;
  clip: rect(0 0 0 0); clip-path: inset(50%);
}

/* Поиск над таблицей: иконка внутри поля, края — по колонкам таблицы */
.tbl-search { padding: 0 20px 12px; }
.tbl-search-in { position: relative; display: block; }
.tbl-search input {
  width: 100%; padding: 9px 12px 9px 36px;
  border: 1.5px solid var(--line-strong); border-radius: var(--r-sm);
  background: var(--paper-raised); color: var(--ink); font: inherit;
  font-size: var(--text-sm);
}
.tbl-search-in svg {
  position: absolute; left: 13px; top: 50%; transform: translateY(-50%);
  width: 15px; height: 15px; fill: none; stroke: currentColor;
  stroke-width: 2; opacity: .45; pointer-events: none;
}
.tbl-empty td { padding: 22px 16px; color: var(--ink-faint); }

/* Кнопка-заголовок для сортировки: выглядит как обычный заголовок */
.tbl th .th-sort {
  all: unset; display: inline-flex; align-items: center; gap: 5px;
  cursor: pointer; width: 100%; font: inherit; color: inherit;
  white-space: nowrap;    /* иначе «ТОЛЩ.» ломается пополам из-за стрелки */
}
.tbl th .th-sort:focus-visible { outline: 2px solid var(--focus, #2f6feb); outline-offset: 2px; border-radius: 6px; }
.tbl th .th-arw { width: 0; height: 0; opacity: 0; flex: none; }
.tbl th[aria-sort="ascending"] .th-arw,
.tbl th[aria-sort="descending"] .th-arw {
  opacity: .6; border-left: 4px solid transparent; border-right: 4px solid transparent;
  width: 0; height: 0;
}
.tbl th[aria-sort="ascending"]  .th-arw { border-bottom: 5px solid currentColor; }
.tbl th[aria-sort="descending"] .th-arw { border-top: 5px solid currentColor; }

/* Кнопка в работе */
.spin {
  display: inline-block; width: 13px; height: 13px; margin-right: 7px;
  vertical-align: -2px; flex: none;
  border: 2px solid currentColor; border-right-color: transparent;
  border-radius: 50%; opacity: .8;
  animation: dq-spin .7s linear infinite;
}
@keyframes dq-spin { to { transform: rotate(360deg); } }
.btn.is-busy, .is-busy { cursor: progress; }
.btn.is-busy { opacity: .75; }
@media (prefers-reduced-motion: reduce) {
  .spin { animation-duration: 2.4s; }
}


/* ── Флажки ──────────────────────────────────────────────────────────
   Общее правило для input давало флажку padding и рамку — он разъезжался
   с подписью и уползал на свою строку. */
input[type="checkbox"], input[type="radio"] {
  width: 17px; height: 17px; margin: 0; padding: 0;
  border-radius: 5px; border-width: 1.5px;
  accent-color: var(--ink); flex: none; cursor: pointer;
}
input[type="radio"] { border-radius: 50%; }
label.chk {
  display: inline-flex; align-items: center; gap: 9px;
  font-weight: 500; color: var(--ink); cursor: pointer;
}

/* ── Выбор файла ─────────────────────────────────────────────────────
   Родное поле показывает англоязычное «Choose File / No file chosen»
   в стиле операционной системы. Прячем его и рисуем своё; настоящий
   input остаётся сверху — значит, клик и Tab работают как раньше. */
/* Выбор файла внутри подписи — со своей строки, как обычное поле. Пока он
   был inline, он вставал рядом с текстом подписи, и в ряду соседние поля
   оказывались на 22 точки ниже: подпись сверху у одного, сбоку у другого. */
form label > .filefield { display: flex; margin-top: 5px; }
.filefield {
  position: relative; display: inline-flex; align-items: center; gap: 10px;
  max-width: 100%; padding: 5px 14px 5px 5px;
  border: 1.5px solid var(--line-strong); border-radius: var(--r-sm);
  background: var(--paper-raised);
}
.filefield input[type="file"] {
  position: absolute; inset: 0; width: 100%; height: 100%;
  opacity: 0; padding: 0; border: 0; cursor: pointer;
}
.filefield .ff-btn {
  flex: none; padding: 5px 14px; border-radius: var(--r-pill);
  border: 1.5px solid var(--line-strong); background: var(--paper-sunken);
  font-size: var(--text-sm); font-weight: 600; color: var(--ink);
}
.filefield .ff-name {
  font-size: var(--text-sm); font-weight: 500; color: var(--ink-faint);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.filefield.has .ff-name { color: var(--ink); }
.filefield:hover { border-color: var(--ink); }
.filefield:focus-within { border-color: var(--ink); box-shadow: 0 0 0 3px rgba(20, 20, 20, 0.1); }

/* Действия в строке таблицы: раньше на td стоял display:flex — ячейка
   переставала быть ячейкой и теряла нижнюю линию. */
.tbl td.acts { white-space: nowrap; }
.tbl td.acts > .in { display: flex; gap: 6px; align-items: center; justify-content: flex-end; }
.tbl td.acts form { display: contents; }

/* Картинка, которой может не быть (пропавший файл текстуры) — прячем,
   а не показываем значок битой картинки */
img[data-optional] { background: var(--paper-sunken); }

/* ── Поле внутри подписи ─────────────────────────────────────────────
   input был строчным: под ним оставался «хвост» строки в 4–5 px, и
   кнопка рядом переставала совпадать по нижнему краю с полями. */
label > input:not([type="checkbox"]):not([type="radio"]),
label > select,
label > .sel-btn,
label > textarea,
label > .filefield {
  display: block; width: 100%; margin-top: 5px;
}
label > .filefield { display: inline-flex; width: auto; max-width: 100%; }
label > .muted, label > small { display: block; margin-top: 5px; }

/* Таблица с заданными ширинами колонок: длинные названия получают место,
   пустые колонки его не занимают */
.tbl.fixed { table-layout: fixed; }
.tbl.fixed td, .tbl.fixed th { overflow-wrap: anywhere; }

/* Плитка библиотеки, у которой пропал файл картинки */
.tex-card { position: relative; }
.tex-card .nofile {
  position: absolute; left: 0; right: 0; top: 0; aspect-ratio: 1;
  border-radius: var(--r-lg) var(--r-lg) 0 0;
  display: flex; align-items: center; justify-content: center;
  background: var(--paper-sunken); color: var(--ink-faint);
  font-size: var(--text-xs); text-align: center; padding: 8px;
}

/* Имя кабинета в углу меню: длинное — подрезаем, кнопка «Выйти» не уезжает */
.user-box .who { min-width: 0; flex: 1; }
.user-box .who .name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ── Страницы под таблицей ───────────────────────────────────────────── */
.tbl-pager { border-top: 1px solid var(--line); background: var(--paper-sunken); }
.pg-wrap { padding: 12px 20px; display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.tbl-pager .pg-info { color: var(--ink-faint); font-size: var(--text-sm); font-variant-numeric: tabular-nums; }
.tbl-pager .pg { display: flex; align-items: center; gap: 4px; margin-left: auto; flex-wrap: wrap; }
.pg-btn {
  min-width: 34px; height: 34px; padding: 0 9px;
  border: 1.5px solid transparent; border-radius: var(--r-sm);
  background: transparent; color: var(--ink);
  font-size: var(--text-sm); font-weight: 600; font-variant-numeric: tabular-nums;
}
.pg-btn:hover:not(:disabled) { border-color: var(--line-strong); }
.pg-btn.cur { background: var(--ink); color: var(--on-ink); border-color: var(--ink); }
.pg-btn:disabled { opacity: .35; cursor: default; }
.pg-btn.nav { font-size: 16px; }
.pg-gap { color: var(--ink-faint); padding: 0 2px; }
@media (max-width: 640px) {
  .pg-wrap { padding: 10px 14px; }
  .tbl-pager .pg { margin-left: 0; }
  .pg-btn { min-width: 38px; height: 38px; }
}

/* Широкое поле: просторное там, где есть место, и не вылезает за узкий экран */
.inp.wide { min-width: 340px; max-width: 100%; }
@media (max-width: 640px) {
  .inp.wide { min-width: 0; width: 100%; }
}


/* ── Заказы: раскладка папками, как в Finder ────────────────────────────────
   Крупная иконка, подпись под ней, ряды сами переносятся. Названия заказов
   бывают длинные («06-6 (196-224)»), поэтому подпись переносится по словам,
   а не обрезается многоточием: номер заказа нужно прочитать целиком. */
.finder {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(148px, 1fr));
  gap: 10px;
}
.fold {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 14px 8px 12px;
  border-radius: var(--r-md);
  text-decoration: none;
  color: var(--ink);
  text-align: center;
}
.fold:hover { background: var(--paper-sunken); }
.fold:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.fold-ico {
  position: relative;
  width: 78px;
  height: 66px;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 6px;
}
.fold-ico svg { width: 100%; height: 100%; overflow: visible; }
.fold-back  { fill: #6fb2e8; }
.fold-front { fill: #8fc9f5; }
.fold:hover .fold-back  { fill: #5aa3e0; }
.fold:hover .fold-front { fill: #7dbef2; }
/* счётчик моделей — кружком на уголке папки */
.fold-cnt {
  position: absolute;
  right: 4px;
  top: 2px;
  min-width: 20px;
  padding: 1px 6px;
  border-radius: var(--r-pill);
  background: var(--ink);
  color: var(--on-ink);
  font-size: 11px;
  font-weight: 700;
  line-height: 18px;
}
.fold.file .fold-ico { width: 60px; }
/* плитка стала контейнером: внутри ссылка на весь размер, галочка выбора
   и меню «…». Раньше плитка сама была ссылкой — в неё нельзя вложить ни то,
   ни другое. */
.fold { position: relative; }
.fold-hit {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  text-decoration: none;
  color: inherit;
}
.fold-hit:focus-visible { outline: 2px solid var(--focus); outline-offset: 4px; border-radius: var(--r-md); }
.fold-pick {
  position: absolute;
  left: 8px;
  top: 8px;
  z-index: 2;
  width: 18px;
  height: 18px;
  opacity: 0;
  cursor: pointer;
}
.fold:hover .fold-pick,
.fold-pick:focus-visible,
.fold-pick:checked { opacity: 1; }
.fold:has(.fold-pick:checked) { background: var(--paper-sunken); box-shadow: inset 0 0 0 2px var(--focus); }
.fold-up { fill: none; stroke: #2c5f8a; stroke-width: 6; stroke-linecap: round; stroke-linejoin: round; }
/* меню папки: переименовать и убрать */
.fold-menu { position: absolute; right: 6px; top: 4px; z-index: 3; }
.fold-menu > summary {
  list-style: none;
  cursor: pointer;
  width: 26px;
  height: 22px;
  line-height: 18px;
  text-align: center;
  border-radius: var(--r-sm);
  color: var(--ink-faint);
  opacity: 0;
  font-weight: 700;
}
.fold-menu > summary::-webkit-details-marker { display: none; }
.fold:hover .fold-menu > summary,
.fold-menu[open] > summary,
.fold-menu > summary:focus-visible { opacity: 1; background: var(--paper-sunken); }
.fold-pop {
  position: absolute;
  right: 0;
  top: 26px;
  width: 300px;
  padding: 12px;
  text-align: left;
  background: var(--paper-raised);
  border: 1px solid var(--card-border);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-2);
}
.fold.over { background: var(--paper-sunken); box-shadow: inset 0 0 0 2px var(--focus); }
/* полоска «перенести выбранное» — прилипает к низу экрана */
.movebar { position: sticky; bottom: 12px; margin-top: 14px; z-index: 4; }
.file-body   { fill: #f4f6f8; stroke: #c3ccd6; stroke-width: 2; }
.file-corner { fill: #d8e0e8; }
.file-lines rect { fill: #b6c2cd; }
.fold:hover .file-body { fill: #fff; stroke: #9fb0bf; }
.fold-name {
  font-weight: 650;
  font-size: var(--text-sm);
  line-height: 1.25;
  overflow-wrap: anywhere;
}
.fold-sub {
  font-size: var(--text-xs);
  color: var(--ink-faint);
  line-height: 1.3;
  overflow-wrap: anywhere;
}
/* Хлебные крошки над заголовком заказа */
.crumbs {
  font-size: var(--text-xs);
  color: var(--ink-faint);
  margin-bottom: 4px;
}
.crumbs a { color: var(--ink-soft); }

/* ── «Что нового»: карточка в углу после обновления ─────────────────────────
   Появляется один раз на версию и уходит по крестику или сама через 25 секунд.
   На узком экране растягивается на всю ширину — иначе перекрывает содержимое. */
.whatsnew {
  position: fixed;
  right: 18px;
  bottom: 18px;
  z-index: 60;
  width: min(360px, calc(100vw - 36px));
  padding: 14px 16px;
  background: var(--paper-raised);
  border: 1px solid var(--card-border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-2);
  animation: wn-in .25s ease-out;
}
@keyframes wn-in { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .whatsnew { animation: none; } }
.wn-head { display: flex; align-items: baseline; gap: 8px; margin-bottom: 8px; }
.wn-head b { font-size: var(--text-sm); }
.wn-x {
  margin-left: auto;
  border: 0;
  background: none;
  color: var(--ink-faint);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
  padding: 0 4px;
  border-radius: var(--r-sm);
}
.wn-x:hover { color: var(--ink); background: var(--paper-sunken); }
.wn-x:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.whatsnew ul { margin: 0; padding-left: 18px; }
.whatsnew li { font-size: var(--text-xs); line-height: 1.45; color: var(--ink-soft, var(--ink)); }
.whatsnew li + li { margin-top: 6px; }

/* ---- «Кто пользуется»: плитки и столбики по дням ---------------------- */
.u-tiles { display: flex; flex-wrap: wrap; gap: 26px 34px; }
.u-tile { display: flex; flex-direction: column; gap: 2px; min-width: 96px; }
.u-tile b { font-family: var(--font-display); font-size: 26px; line-height: 1.1;
            font-variant-numeric: tabular-nums; }
.u-tile span { color: var(--ink-faint); font-size: 12px; }
.u-chart { display: flex; align-items: flex-end; gap: 3px; height: 140px;
           padding: 4px 16px 8px; }
.u-day { flex: 1 1 0; display: flex; flex-direction: column; align-items: center;
         gap: 4px; height: 100%; min-width: 0; }
.u-bars { flex: 1 1 auto; width: 100%; display: flex; align-items: flex-end;
          justify-content: center; gap: 2px; }
.u-bars i { display: block; width: 44%; min-height: 1px; border-radius: 2px 2px 0 0; }
/* пустой день — тонкая полоска у основания, чтобы шкала читалась */
.u-b1 { background: var(--ink); }
.u-b2 { background: var(--line-strong); }
.u-lbl { color: var(--ink-faint); font-size: 9px; font-variant-numeric: tabular-nums; }
.u-nowrap { white-space: nowrap; }
.u-plan { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 6px; }
.u-plan .btn { padding: 3px 8px; font-size: 11px; }
.u-leg { display: inline-flex; align-items: center; gap: 6px; }
.u-leg i { display: inline-block; width: 10px; height: 10px; border-radius: 2px; }
.u-leg i + * { margin-right: 6px; }
@media (max-width: 900px) { .u-lbl { display: none; } }

/* ---- Подписка ------------------------------------------------------ */
/* Карточки тарифов: три в ряд на широком экране, в столбик на телефоне.
   Высоту задаёт содержимое, а не фиксированное значение — иначе у пакета
   картинок внизу зияет пустота. */
.pay-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 14px;
  padding: 0 16px 16px;
}
.pay-card {
  display: flex;
  flex-direction: column;
  gap: 10px;
  border: 1px solid var(--card-border);
  border-radius: var(--r-md);
  padding: 16px;
  background: var(--paper-raised);
}
.pay-card.on {
  border-color: var(--ink);
  box-shadow: var(--shadow-1);
}
.pay-name {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-display);
  font-size: 18px;
  font-weight: 600;
}
.pay-price { color: var(--ink-soft); font-size: var(--text-sm); }
.pay-price b {
  font-family: var(--font-display);
  font-size: 28px;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.pay-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 5px;
  font-size: var(--text-sm);
  color: var(--ink-soft);
}
.pay-list li { padding-left: 16px; position: relative; }
.pay-list li::before {
  content: '';
  position: absolute;
  left: 2px;
  top: .55em;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--ink-faint);
}
/* Кнопки прижаты к низу карточки, чтобы в ряду они стояли на одной линии
   даже когда списки возможностей разной длины. */
.pay-buy { margin-top: auto; }
.pay-buy + .pay-buy { margin-top: 6px; }
.pay-buy .btn { width: 100%; justify-content: center; }

/* ---- Публичные страницы -------------------------------------------- */
/* Главная — не только витрина для человека, но и то, что вручную читает
   проверяющий из банка. Значит это сплошной текст со списками, а не плитки:
   ему важно найти сведения, а не полюбоваться раскладкой. */
.pub {
  padding: 0 16px 16px;
  font-size: var(--text-sm);
  line-height: 1.6;
  color: var(--ink-soft);
}
/* Ширину ограничиваем тексту, а не всей колонке: иначе таблица цен
   зажимается вместе с абзацами и «1 900 ₽» переносится на две строки. */
.pub p, .pub ul, .pub ol { max-width: 68ch; }
.pub p { margin: 0 0 10px; }
.pub b { color: var(--ink); }
.pub ul, .pub ol { margin: 0 0 10px; padding-left: 20px; }
.pub li { margin: 4px 0; }
.pub .table-scroll { margin: 0 0 10px; }
.pub table { font-size: var(--text-sm); }
.pub table .num { white-space: nowrap; }
/* Ссылки на оферту и политику проверяющий из банка должен увидеть сразу.
   Общего стиля у ссылок здесь нет, и в сплошном тексте они сливались с ним. */
.pub a {
  color: var(--ink);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.pub a:hover { text-decoration-thickness: 2px; }

/* Возврат в строке платежа: поле суммы и кнопка на одной линии. Сумма
   подставляется за неиспользованные дни, но её можно исправить руками —
   договориться с человеком можно и на другую. */
.pay-back { display: flex; gap: 6px; align-items: center; }
.pay-back input {
  width: 72px;
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* Галочка «запомнить карту» под тарифами. */
.pay-remember {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: var(--text-sm);
  color: var(--ink);
  cursor: pointer;
}
.pay-remember input { margin: 0; }

/* ---- Картинка для клиента ------------------------------------------- */
.rn-row {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: flex-end;
  margin-top: 12px;
}
.rn-row label {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: var(--text-xs);
  color: var(--ink-faint);
}
.rn-act {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 14px;
}
/* Галерея: карточки одной ширины, высоту задаёт картинка. Кадры бывают
   16:9 и 4:3, и подгонять их под общую высоту значило бы обрезать мебель —
   ровно то, ради чего картинка и делалась. */
.rn-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 14px;
  padding: 0 16px 16px;
}
.rn-item { margin: 0; }
.rn-item img {
  width: 100%;
  height: auto;
  display: block;
  border-radius: var(--r-md);
  border: 1px solid var(--card-border);
}
.rn-item figcaption {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-top: 6px;
  font-size: var(--text-xs);
  color: var(--ink-faint);
}

/* Главная: две кнопки до текста — живой пример и «попробовать». */
.cta-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 14px;
  margin: 0 0 16px;
}
.cta-row .small { flex-basis: 100%; }
