/*
  Вид экранов службы файлов: проводник и настройки.

  Один файл на оба нарочно: они обязаны выглядеть одинаково, а два
  набора правил расходятся на первой же правке.

  Цвета — переменными, и тёмный набор объявлен рядом. Браузер тут
  у человека свой, и навязывать ему светлое окно в тёмной системе
  незачем.
*/

:root {
  color-scheme: light dark;
  --фон: #f3f4f6;
  --полотно: #ffffff;
  --панель: #fafbfc;
  --рамка: #e2e5ea;
  --рамка-сильная: #cbd1d9;
  --текст: #16191d;
  --тихий: #6b7280;
  --свой: #2563eb;
  --свой-нажат: #1d4ed8;
  /* Что пишется на залитой кнопке. В светлом наборе заливка тёмная —
     белым; в тёмном она светлая, и белое по ней не прочесть
     (контраст 2.5 при нужных 4.5). Проверено счётом, а не на глаз. */
  --на-залитой: #ffffff;
  --свой-фон: #eaf1fe;
  --беда: #b42318;
  --беда-нажат: #912018;
  --беда-фон: #fdf1f0;
  --удача: #067647;
  --тень: 0 1px 2px rgba(16, 24, 40, .06), 0 2px 6px rgba(16, 24, 40, .06);
}

@media (prefers-color-scheme: dark) {
  :root {
    --фон: #0f1115;
    --полотно: #171a1f;
    --панель: #1c2026;
    --рамка: #2a2f37;
    --рамка-сильная: #39414b;
    --текст: #e8eaed;
    --тихий: #9aa3af;
    --свой: #60a5fa;
    --свой-нажат: #3b82f6;
    --на-залитой: #0b1220;
    --свой-фон: #1b3356;
    --беда: #f97066;
    --беда-нажат: #e14b3f;
    --беда-фон: #3a1d1b;
    --удача: #47cd89;
    --тень: none;
  }
}

* { box-sizing: border-box; }

/* Скрытое прячется всегда: `display` из класса иначе перебивает
   `hidden` браузера, и кнопки корзины видны там, где их быть не должно. */
[hidden] { display: none !important; }

body {
  margin: 0;
  background: var(--фон);
  color: var(--текст);
  font: 13.5px/1.5 -apple-system, "Segoe UI", Roboto, system-ui, sans-serif;
  height: 100vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

button, input, select { font: inherit; color: inherit; }
a { color: var(--свой); }

/* --- верхняя полоса --------------------------------------------------- */

.шапка {
  display: flex; align-items: center; gap: 12px;
  padding: 8px 12px; background: var(--полотно);
  border-bottom: 1px solid var(--рамка); flex: 0 0 auto;
}
.шапка h1 { font-size: 15px; margin: 0; font-weight: 650; white-space: nowrap; }
.шапка .тихо { font-size: 12px; }
.растяжка { flex: 1 1 auto; }

.полоса {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  padding: 7px 12px; background: var(--панель);
  border-bottom: 1px solid var(--рамка); flex: 0 0 auto;
}

.кнопка {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--полотно); border: 1px solid var(--рамка-сильная);
  border-radius: 7px; padding: 5px 11px; cursor: pointer; white-space: nowrap;
}
.кнопка:hover:not(:disabled) { border-color: var(--свой); color: var(--свой); background: var(--свой-фон); }
.кнопка:disabled { opacity: .45; cursor: default; }

/* Своя кнопка — залитая. На hover она **темнеет**, а не перекрашивает
   текст: прежнее правило красило надпись в синий на синем, и кнопка
   «Загрузить» под указателем становилась нечитаемой. */
.кнопка.своя {
  background: var(--свой); border-color: var(--свой); color: var(--на-залитой);
}
.кнопка.своя:hover:not(:disabled) {
  background: var(--свой-нажат); border-color: var(--свой-нажат); color: var(--на-залитой);
}
.кнопка.опасная:hover:not(:disabled) {
  border-color: var(--беда); color: var(--беда); background: var(--беда-фон);
}
.кнопка.опасная-своя {
  background: var(--беда); border-color: var(--беда); color: var(--на-залитой);
}
.кнопка.опасная-своя:hover:not(:disabled) {
  background: var(--беда-нажат); border-color: var(--беда-нажат); color: var(--на-залитой);
}

/* Значок кнопки красится цветом текста — через маску, а не картинкой:
   картинка осталась бы чёрной на синей кнопке и невидимой в тёмном
   наборе. */
.кнопка[data-значок]::before, .узел[data-значок]::before,
.меню button[data-значок]::before {
  content: ""; width: 15px; height: 15px; flex: 0 0 auto;
  background: currentColor;
  -webkit-mask: var(--значок) center / contain no-repeat;
  mask: var(--значок) center / contain no-repeat;
}
.переключатель button[data-значок] { display: inline-flex; align-items: center; }
.переключатель button[data-значок]::before {
  content: ""; width: 15px; height: 15px; background: currentColor;
  -webkit-mask: var(--значок) center / contain no-repeat;
  mask: var(--значок) center / contain no-repeat;
}
.кнопка.мелкая { padding: 3px 8px; font-size: 12px; }

.разделитель { width: 1px; height: 22px; background: var(--рамка); margin: 0 3px; }

input[type=text], input[type=search], input[type=number], input[type=date], select {
  background: var(--полотно); border: 1px solid var(--рамка-сильная);
  border-radius: 7px; padding: 5px 9px; min-width: 0;
}
input:focus-visible, button:focus-visible, select:focus-visible {
  outline: 2px solid var(--свой); outline-offset: 1px;
}

.переключатель { display: flex; border: 1px solid var(--рамка-сильная); border-radius: 7px; overflow: hidden; }
.переключатель button { background: var(--полотно); border: 0; padding: 5px 10px; cursor: pointer; }
.переключатель button[aria-pressed="true"] { background: var(--свой-фон); color: var(--свой); }

/* --- рабочая область --------------------------------------------------- */

.рабочее { display: flex; flex: 1 1 auto; min-height: 0; }

.дерево {
  width: 240px; flex: 0 0 auto; overflow: auto; padding: 8px 6px;
  background: var(--панель); border-right: 1px solid var(--рамка);
}
.узел {
  display: flex; align-items: center; gap: 6px; padding: 4px 8px;
  border-radius: 6px; cursor: pointer; white-space: nowrap;
}
.узел:hover { background: var(--фон); }
.узел[aria-current="true"] { background: var(--свой-фон); color: var(--свой); font-weight: 550; }
.узел img { width: 16px; height: 16px; flex: 0 0 auto; }
.узел .подпись { overflow: hidden; text-overflow: ellipsis; }

.содержимое { flex: 1 1 auto; overflow: auto; padding: 10px 12px 60px; position: relative; }
.содержимое.принимает { outline: 2px dashed var(--свой); outline-offset: -8px; }

/* --- режим выбора ------------------------------------------------------ */
/*
   Флажок — не подсветка. Подсветка строки значит «над этим сейчас
   действие» (вырезать, удалить), а флажок — «это уйдёт по кнопке
   Выбрать». Два разных смысла на одном экране, и выглядеть они обязаны
   по-разному: иначе человек удалит то, что набирал к передаче.
*/
.флажок {
  width: 20px; height: 20px; flex: 0 0 auto; padding: 0; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--полотно); border: 1.5px solid var(--рамка-сильная);
  border-radius: 6px;
}
.флажок::before {
  content: ""; width: 13px; height: 13px; background: transparent;
  -webkit-mask: url(icons/ui/check.svg) center / contain no-repeat;
  mask: url(icons/ui/check.svg) center / contain no-repeat;
}
.флажок:hover { border-color: var(--свой); }
.флажок[aria-pressed="true"] { background: var(--свой); border-color: var(--свой); }
.флажок[aria-pressed="true"]::before { background: var(--на-залитой); }
/* В плитке флажок лежит углом поверх значка, в таблице — первым
   столбцом слева. */
.плитка .вещь { position: relative; }
.плитка .флажок { position: absolute; top: 6px; left: 6px; }
table.перечень td.столбец-флажка, table.перечень th.столбец-флажка {
  width: 34px; padding-right: 0;
}

.дерево-набора { max-height: 52vh; overflow: auto; }
.дерево-набора .ветка { margin-bottom: 10px; }
.дерево-набора .строка {
  display: flex; align-items: center; gap: 8px;
  padding: 5px 8px; border-radius: 6px;
}
.дерево-набора .строка:hover { background: var(--свой-фон); }
.дерево-набора .лист { padding-left: 26px; }
.дерево-набора img { width: 18px; height: 18px; flex: 0 0 auto; }
.дерево-набора .имя { flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis;
                      white-space: nowrap; }
.дерево-набора .путь { font-family: ui-monospace, Consolas, monospace; font-size: 12px; }

/* --- вид плиткой ------------------------------------------------------- */

.плитка { display: grid; grid-template-columns: repeat(auto-fill, minmax(116px, 1fr)); gap: 4px; }
.плитка .вещь {
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  padding: 10px 6px; border-radius: 8px; cursor: default; text-align: center;
  border: 1px solid transparent;
}
.плитка .вещь img { width: 48px; height: 48px; }
.плитка .вещь .подпись {
  font-size: 12px; line-height: 1.3; word-break: break-word;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}

/* --- вид таблицей ------------------------------------------------------ */

table.перечень { width: 100%; border-collapse: collapse; }
table.перечень th {
  text-align: left; font-size: 12px; font-weight: 600; color: var(--тихий);
  padding: 6px 10px; border-bottom: 1px solid var(--рамка); cursor: pointer;
  position: sticky; top: -10px; background: var(--фон); white-space: nowrap;
}
table.перечень th:hover { color: var(--текст); }
table.перечень td { padding: 5px 10px; border-bottom: 1px solid var(--рамка); }
table.перечень .вещь td:first-child { display: flex; align-items: center; gap: 8px; }
table.перечень img { width: 20px; height: 20px; flex: 0 0 auto; }
td.число { text-align: right; white-space: nowrap; color: var(--тихий); }
td.когда { white-space: nowrap; color: var(--тихий); }

/* --- выделение --------------------------------------------------------- */

.вещь[aria-selected="true"] { background: var(--свой-фон); border-color: var(--свой); }
.вещь[aria-selected="true"] td { background: var(--свой-фон); }
.вещь:hover { background: color-mix(in srgb, var(--свой-фон) 45%, transparent); }
.вещь.вырезана { opacity: .5; }

.пусто { padding: 48px 12px; text-align: center; color: var(--тихий); }

/* --- вести и попапы ---------------------------------------------------- */

.вести { position: fixed; right: 14px; bottom: 14px; display: flex;
         flex-direction: column; gap: 8px; z-index: 40; max-width: 420px; }
.весть {
  background: var(--полотно); border: 1px solid var(--рамка-сильная);
  border-left-width: 3px; border-radius: 8px; padding: 9px 12px;
  box-shadow: var(--тень); font-size: 13px;
}
.весть.беда { border-left-color: var(--беда); }
.весть.удача { border-left-color: var(--удача); }

dialog {
  border: 1px solid var(--рамка); border-radius: 12px; padding: 0;
  background: var(--полотно); color: var(--текст); box-shadow: var(--тень);
  max-width: 560px; width: calc(100% - 32px);
}
dialog::backdrop { background: rgba(16, 24, 40, .45); }
dialog .внутри { padding: 18px 20px; }
dialog h2 { margin: 0 0 14px; font-size: 16px; font-weight: 650; word-break: break-word; }
dialog .низ { display: flex; justify-content: flex-end; gap: 8px;
              padding: 12px 20px; border-top: 1px solid var(--рамка); background: var(--панель); }

dl.свойства { display: grid; grid-template-columns: auto 1fr; gap: 7px 16px; margin: 0; font-size: 13px; }
dl.свойства dt { color: var(--тихий); }
dl.свойства dd { margin: 0; word-break: break-word; }
.сумма { font-family: ui-monospace, "Cascadia Mono", Consolas, monospace; font-size: 11.5px; }

.меню {
  position: fixed; z-index: 50; background: var(--полотно);
  border: 1px solid var(--рамка-сильная); border-radius: 9px;
  box-shadow: var(--тень); padding: 4px; min-width: 190px;
}
/* Кнопка группы помечена уголком: иначе её не отличить
   от кнопки, которая делает дело сразу. */
.кнопка.группа::after {
  content: ""; width: 12px; height: 12px; margin-left: 1px; opacity: .65;
  background: currentColor; transform: rotate(90deg);
  -webkit-mask: url(icons/ui/chevron-right.svg) center / contain no-repeat;
  mask: url(icons/ui/chevron-right.svg) center / contain no-repeat;
}
.кнопка.группа[aria-expanded="true"] {
  border-color: var(--свой); color: var(--свой); background: var(--свой-фон);
}
.кнопка.группа.своя[aria-expanded="true"] {
  background: var(--свой-нажат); border-color: var(--свой-нажат);
  color: var(--на-залитой);
}

.меню button {
  display: flex; align-items: center; gap: 8px; width: 100%; text-align: left;
  background: none; border: 0; color: inherit;
  padding: 7px 12px; border-radius: 6px; cursor: pointer;
}
.меню .подпись { flex: 1 1 auto; }
/* Горячая клавиша рядом с пунктом — чтобы меню учило ею
   пользоваться, а не только им. */
.меню .ключи { color: var(--тихий); font-size: 11.5px; flex: 0 0 auto; }
.меню button.опасное:hover:not(:disabled) {
  background: var(--беда-фон); color: var(--беда);
}
.меню button:hover:not(:disabled) { background: var(--свой-фон); color: var(--свой); }
.меню button:disabled { opacity: .4; cursor: default; }
.меню hr { border: 0; border-top: 1px solid var(--рамка); margin: 4px 0; }

/* --- страница настроек -------------------------------------------------- */

body.настройки { display: block; overflow: auto; }
.страница { max-width: 980px; margin: 0 auto; padding: 20px 16px 80px; }
.страница.широкая { max-width: 1180px; }
.карта {
  background: var(--полотно); border: 1px solid var(--рамка);
  border-radius: 12px; padding: 18px 20px; margin-bottom: 16px; box-shadow: var(--тень);
}
.карта h2 { margin: 0 0 4px; font-size: 15px; font-weight: 650; }
/* Пояснения под заголовком нет — отступ держит сам заголовок. */
.карта > h2 + .ряд, .карта > h2 + div, .карта > h2 + table { margin-top: 14px; }
.карта .пояснение { color: var(--тихий); font-size: 12.5px; margin: 0 0 14px; }
.числа { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; }
.число-карта { background: var(--панель); border: 1px solid var(--рамка); border-radius: 9px; padding: 10px 12px; }
.число-карта .значение { font-size: 19px; font-weight: 600; }
.число-карта .подпись { font-size: 12px; color: var(--тихий); }
.журнал { margin: 12px 0 0; white-space: pre-wrap; font-family: ui-monospace, Consolas, monospace;
          font-size: 12px; color: var(--тихий); max-height: 240px; overflow: auto; }
.тихо { color: var(--тихий); }
.мелко { font-size: 12px; }
.ряд { display: flex; flex-wrap: wrap; gap: 8px; align-items: flex-end; }
.ряд > label { display: block; font-size: 12px; color: var(--тихий); }
/* Флажок без подписи сверху встаёт вровень с полями, а не по середине
   чужой высоты: `align-items: flex-end` у ряда считает высоту вместе
   с подписью, и флажок повисает над строкой ввода. */
.ряд > label.вровень {
  display: flex; align-items: center; gap: 6px; height: 31px; margin: 0;
}
.ряд > label.вровень input { margin: 0; }

/* --- очередь загрузки --------------------------------------------------- */

.очередь {
  position: fixed; left: 14px; bottom: 14px; width: 330px; z-index: 35;
  background: var(--полотно); border: 1px solid var(--рамка-сильная);
  border-radius: 10px; box-shadow: var(--тень); overflow: hidden;
}
.очередь-шапка { display: flex; align-items: center; gap: 8px; padding: 8px 10px;
                 background: var(--панель); border-bottom: 1px solid var(--рамка); font-size: 13px; }
.очередь-строка { padding: 7px 10px; border-bottom: 1px solid var(--рамка); font-size: 12px; }
.очередь-строка:last-child { border-bottom: 0; }
.очередь-строка .имя { display: flex; justify-content: space-between; gap: 8px; }
.очередь-строка .имя span:first-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.полоска { height: 4px; border-radius: 2px; background: var(--рамка); margin-top: 5px; overflow: hidden; }
.полоска i { display: block; height: 100%; background: var(--свой); width: 0; transition: width .15s; }
.очередь-строка.беда .полоска i { background: var(--беда); }
.очередь-строка.готово .полоска i { background: var(--удача); }
#очередь-строки { max-height: 260px; overflow: auto; }

/* --- предпросмотр ------------------------------------------------------- */

dialog#предпросмотр { max-width: 900px; }
.предпросмотр { min-height: 180px; display: flex; align-items: center; justify-content: center; }
.предпросмотр img, .предпросмотр video { max-width: 100%; max-height: 66vh; border-radius: 8px; }
.предпросмотр iframe { width: 100%; height: 66vh; border: 0; border-radius: 8px; background: #fff; }
.предпросмотр pre { width: 100%; max-height: 60vh; overflow: auto; margin: 0; white-space: pre-wrap;
                    word-break: break-word; font-family: ui-monospace, Consolas, monospace; font-size: 12.5px; }
.предпросмотр .разметка { width: 100%; max-height: 60vh; overflow: auto; }
.предпросмотр .разметка h1, .предпросмотр .разметка h2, .предпросмотр .разметка h3 { margin: 12px 0 6px; }
.предпросмотр .разметка code { background: var(--панель); padding: 1px 4px; border-radius: 4px; }
.предпросмотр .нечем { color: var(--тихий); text-align: center; }

/* Ярлык помечается уголком — как в Windows, чтобы его было видно значком.
   Стрелка — из Lucide и маской. Прежде здесь стоял типографский знак
   «↗»: его рисует шрифт, то есть в каждом наборе по-своему, и рядом
   с очертаниями Lucide он выглядел чужим. Маске нужен свой цвет,
   а подложке — свой, поэтому их двое: `::before` — рамка с фоном,
   `::after` — сама стрелка. */
.вещь .значок { position: relative; display: inline-flex; }
.вещь .значок::before {
  content: ""; position: absolute; left: -3px; bottom: -3px;
  width: 13px; height: 13px; background: var(--полотно);
  border: 1px solid var(--свой); border-radius: 5px;
}
.вещь .значок::after {
  content: ""; position: absolute; left: -1px; bottom: -1px;
  width: 9px; height: 9px; background: var(--свой);
  -webkit-mask: url(icons/ui/arrow-up-right.svg) center / contain no-repeat;
  mask: url(icons/ui/arrow-up-right.svg) center / contain no-repeat;
}
/* Стрелка порядка в шапке столбца — маской, цветом подписи. */
.стрелка-порядка {
  display: inline-block; width: 11px; height: 11px; margin-left: 4px;
  vertical-align: -1px; background: currentColor;
  -webkit-mask: var(--значок) center / contain no-repeat;
  mask: var(--значок) center / contain no-repeat;
}

.ссылка-строка { display: flex; align-items: center; gap: 6px; }
.ссылка-строка input { flex: 1 1 auto; font-family: ui-monospace, Consolas, monospace; font-size: 11.5px; }

/* --- свои окна вопросов -------------------------------------------------- */

#свой-вопрос { max-width: 440px; }
#свой-вопрос .поля { display: flex; flex-direction: column; gap: 12px; }
#свой-вопрос label { display: block; }
#свой-вопрос label span { display: block; font-size: 12px; color: var(--тихий); margin-bottom: 4px; }
#свой-вопрос input { width: 100%; }
#свой-вопрос .поля:empty { display: none; }

/* Поля в своих окнах — такие же, как на полосе: два разных поля ввода
   на одном экране человек читает как две разные вещи. */
dialog input[type=text], dialog input[type=date], dialog input[type=number],
dialog select {
  background: var(--фон); border: 1px solid var(--рамка-сильная);
  border-radius: 7px; padding: 6px 9px;
}
dialog input[readonly] { color: var(--тихий); }

/* Значок у заголовка карты — тем же способом, что у кнопок. */
.карта h2[data-значок] { display: flex; align-items: center; gap: 8px; }
.карта h2[data-значок]::before {
  content: ""; width: 17px; height: 17px; background: var(--свой);
  -webkit-mask: var(--значок) center / contain no-repeat;
  mask: var(--значок) center / contain no-repeat;
}
.ссылка-строка { margin-top: 5px; }
.ссылка-строка input { max-width: 320px; }

/* --- правка ограничений ---------------------------------------------------- */

.имя-ограничения { display: flex; align-items: center; gap: 6px; }
.почему {
  display: inline-flex; align-items: center; justify-content: center;
  width: 15px; height: 15px; border-radius: 50%; cursor: help;
  border: 1px solid var(--рамка-сильная); color: var(--тихий);
  font-size: 10px; line-height: 1;
}
.почему:hover { border-color: var(--свой); color: var(--свой); }
input.значение-ограничения { width: 150px; text-align: right; font-variant-numeric: tabular-nums; }

/* --- экраны словаря: отчёт, замечания, объекты ---------------------------
   Замечание — не сообщение об ошибке, а вопрос с кнопками: экран рисует
   их по ответу службы, и родов у замечания два. Поэтому род виден
   полосой слева, а не словом в тексте: слово человек прочтёт вторым. */

.приговор {
  margin: 0 0 14px; padding: 9px 12px; border-radius: 9px; font-size: 13px;
  background: var(--панель); border-left: 3px solid var(--рамка-сильная);
}
.приговор.clean { border-left-color: var(--удача); }
.приговор.warnings { border-left-color: #c98a16; }
.приговор.errors { border-left-color: var(--беда); }
.приговор.unknown { border-left-color: var(--тихий); }

.замечание {
  border: 1px solid var(--рамка); border-left: 3px solid var(--рамка-сильная);
  border-radius: 9px; padding: 10px 12px; margin-bottom: 10px; background: var(--полотно);
}
.замечание.error { border-left-color: var(--беда); }
.замечание.warning { border-left-color: #c98a16; }
.замечание-шапка { display: flex; align-items: baseline; gap: 8px; margin-bottom: 4px; }
.замечание-шапка b { font-size: 13px; }
.замечание-сказано { margin: 0 0 8px; font-size: 13px; }
.замечание-решения { gap: 6px; }
.замечание-решения .кнопка[aria-pressed="true"] {
  border-color: var(--свой); color: var(--свой); background: var(--свой-фон); font-weight: 600;
}

/* Таблица объектов: строки — объекты, столбцы — поля. Значение
   правится на месте, потому что иначе человек правит окно, а не
   данные, и не видит соседей. */
table.перечень input.клетка {
  width: 100%; min-width: 90px; border: 1px solid transparent; background: transparent;
  border-radius: 6px; padding: 3px 6px; font: inherit; color: inherit;
}
table.перечень input.клетка:hover { border-color: var(--рамка); }
table.перечень input.клетка:focus { border-color: var(--свой); background: var(--полотно); outline: none; }
table.перечень input.клетка.правлено { border-color: #c98a16; }
.поля-объекта { display: grid; gap: 10px; }
.поля-объекта label { display: block; font-size: 12px; color: var(--тихий); }
.поля-объекта input, .поля-объекта select { width: 100%; }
.метка {
  display: inline-block; padding: 1px 7px; border-radius: 20px; font-size: 11.5px;
  background: var(--панель); border: 1px solid var(--рамка); color: var(--тихий);
}


/* --- таблицы словаря ----------------------------------------------------
   Столбцы объявлены классом на заголовке; клетка берёт тот же класс.
   Узкие столбцы ужимаются до содержимого (`width: 1%` при запрете
   переноса), и вся оставшаяся ширина достаётся первому — имени. */

table.перечень.словарь th {
  /* Заголовок читается наравне с данными: одиннадцать с половиной
     точек он был шёпотом над тем, что подписывает. Указатель-рука
     появляется только там, где за ней есть сортировка. */
  cursor: default; font-size: 13px; font-weight: 550; color: var(--текст);
  padding: 0 12px 9px; top: 0; background: var(--полотно);
}
table.перечень.словарь th:hover { color: var(--текст); }
table.перечень.словарь th.сортирует { cursor: pointer; user-select: none; }
table.перечень.словарь th.сортирует:hover { color: var(--свой); }
table.перечень.словарь th.по-этому { color: var(--свой); }
table.перечень.словарь td {
  padding: 8px 12px; vertical-align: middle; font-size: 13px;
}
table.перечень.словарь tbody tr:last-child td { border-bottom: 0; }
table.перечень.словарь td.поле { padding: 5px 5px; }

/* Проводник кладёт в первую клетку значок рядом с именем и делает её
   флексом. Значков в словаре нет, а флекс в клетке отнимает у таблицы
   ширину столбца: заголовки съезжают с того, что под ними. */
table.перечень.словарь .вещь td:first-child { display: table-cell; }

table.перечень.словарь th.число, table.перечень.словарь td.число,
table.перечень.словарь th.когда, table.перечень.словарь td.когда,
table.перечень.словарь th.узко, table.перечень.словарь td.узко,
table.перечень.словарь th.действия, table.перечень.словарь td.действия {
  width: 1%; white-space: nowrap;
}
table.перечень.словарь th.число, table.перечень.словарь th.вправо,
table.перечень.словарь td.вправо { text-align: right; }
table.перечень.словарь input.клетка.вправо {
  text-align: right; font-variant-numeric: tabular-nums;
}
table.перечень.словарь td.число { font-variant-numeric: tabular-nums; }
table.перечень.словарь th.действия, table.перечень.словарь td.действия {
  text-align: right; padding-left: 16px;
}
/* Кнопки стоят в клетке как есть: флекс здесь сделал бы с последним
   столбцом ровно то, что проводник сделал с первым. */
table.перечень.словарь td.действия .кнопка + .кнопка { margin-left: 6px; }
table.перечень.словарь td.сумма {
  font-family: ui-monospace, Consolas, monospace; font-size: 12px; color: var(--тихий);
}

/* --- складная карточка ---------------------------------------------------
   Заголовок карточки — кнопка: он складывает и раскладывает. Дела
   карточки («Завести», «Обновить») стоят справа от заголовка, а не
   внутри него: щелчок по заголовку складывает, щелчок по делу делает,
   и одно не должно случаться вместо другого.

   Сетка в два столбца, а не флекс: нутро ложится через оба, и при
   узком окне дела не отрываются от своего заголовка. */

/* `clip`, а не `hidden`: оба обрезают содержимое по скруглённому углу,
   но `hidden` делает карточку **полосой прокрутки** — пусть и
   не прокручиваемой, — и прилипшая шапка таблицы липнет к ней,
   то есть не липнет никуда. С `clip` полосы прокрутки не заводится,
   и шапка липнет к окну, как и задумано. */
.карта.складная {
  padding: 0; display: grid; grid-template-columns: minmax(0, 1fr) auto;
  align-items: center; overflow: clip;
}
.карта.складная > .верх {
  display: flex; align-items: center; gap: 9px; min-width: 0;
  background: none; border: 0; color: inherit; cursor: pointer;
  text-align: left; padding: 13px 8px 13px 18px; font: inherit;
}
.карта.складная > .верх h2 { margin: 0; font-size: 14.5px; }
.карта.складная > .верх:hover h2 { color: var(--свой); }
.карта.складная > .верх .сводка {
  color: var(--тихий); font-size: 12px; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
}
/* Уголок повёрнут, а не нарисован вторым значком: стрелки вниз
   в наборе нет, а похожая на неё — враньё в картинке. */
.карта.складная .галка {
  width: 13px; height: 13px; flex: 0 0 auto; background: var(--тихий);
  -webkit-mask: var(--значок) center / contain no-repeat;
  mask: var(--значок) center / contain no-repeat;
  transition: transform .12s;
}
.карта.складная > .верх[aria-expanded="true"] .галка { transform: rotate(90deg); }
.карта.складная > .дела {
  display: flex; align-items: center; gap: 8px; padding: 13px 18px 13px 8px;
}
.карта.складная > .нутро {
  grid-column: 1 / -1; border-top: 1px solid var(--рамка); padding: 14px 18px 16px;
}
/* Крайние клетки стоят вровень с краем карточки: их собственный
   отступ повторял бы отступ карточки вторым слоем, и столбец имён
   оказывался бы вдвинут неизвестно почему. */
.карта.складная > .нутро > table.перечень th:first-child,
.карта.складная > .нутро > table.перечень td:first-child { padding-left: 0; }
.карта.складная > .нутро > table.перечень th:last-child,
.карта.складная > .нутро > table.перечень td:last-child { padding-right: 0; }

/* Полоска отбора — над перечнем, в теле карточки. Подписей над полями
   нет: у каждого есть подсказка внутри, а подпись над селектом
   в один ряд с кнопками поднимает всю полоску на две строки. */
.полоска-отбора {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-bottom: 14px;
}
.полоска-отбора label.вровень {
  display: flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--тихий);
}
.полоска-отбора label.вровень input { margin: 0; }

/* --- строка как выбор ----------------------------------------------------
   Там, где строка выбирает (тип, запись решения), она и нажимается.
   Кнопка «Поля» в каждой строке была тем же самым, только лишней. */

table.перечень.словарь tbody tr.выбираемая { cursor: pointer; }

/* Кнопка с тремя точками — одна на строку, с действиями внутри.
   Ширину и значок ей даёт класс «значком», общий со всеми кнопками
   без подписи; здесь остаётся только её приглушённый цвет. */
.кнопка.ещё { color: var(--тихий); }
.кнопка.ещё[aria-expanded="true"] {
  border-color: var(--свой); color: var(--свой); background: var(--свой-фон);
}

/* Выбор в своём окне выглядит как поле ввода рядом с ним. */
#свой-вопрос select { width: 100%; }

/* Кнопка без подписи — ровно такая же клетка, что и «⋯»: столбец
   кнопок разной ширины читается как разный смысл. Негодное действие
   гасится, а не прячется: исчезая, оно сдвигает соседей. */
.кнопка.значком { padding: 2px 0; width: 26px; justify-content: center; }
.кнопка.значком[data-значок]::before { width: 13px; height: 13px; }
.кнопка.вниз[data-значок]::before { transform: rotate(180deg); }

/* Подпись поля в окне стоит над ним: рядом она сдвигает все поля
   на ширину самой длинной из них. */
.поля-объекта label span { display: block; margin-bottom: 4px; }

/* Распор — пустой столбец, который забирает лишнюю ширину. Без него
   её забирает первый столбец, и у таблицы из четырёх столбцов имя
   растягивается через весь экран, а данные уезжают к правому краю,
   к чужим кнопкам. С распором данные стоят слева группой, а действия
   остаются прибиты к краю карточки. */
table.перечень.словарь:has(th.распор) th,
table.перечень.словарь:has(th.распор) td { width: 1%; }
table.перечень.словарь th.распор, table.перечень.словарь td.распор {
  width: auto; padding: 0;
}

/* Флажок среди дел карточки — вровень с кнопками и их же ростом. */
.карта.складная > .дела label.вровень {
  display: flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--тихий);
}
.карта.складная > .дела label.вровень input { margin: 0; }

/* Черта между своим у записи и полями её типа. */
hr.разрез { border: 0; border-top: 1px solid var(--рамка); margin: 16px 0; }

/* Несложная карточка носит ту же шапку — заголовок слева, дела
   справа, — но ни уголка, ни нажатия у неё нет. */
.карта.складная > .верх:not(button) { cursor: default; }

/* Пусто внутри карточки — короче, чем пусто на весь экран: карточка
   и так обрамлена, и высота в полсотни точек делает её выше работы. */
.карта.складная .нутро .пусто { padding: 22px 0; }

/* Клетка со значением показывает, что в неё пишут. Без рамки пустая
   клетка неотличима от пустого места, и про правку на месте человек
   узнаёт, только случайно наведя указатель. Рамка тихая: в таблице
   из пяти столбцов на двадцать строк яркая была бы сеткой поверх
   данных. */
table.перечень.словарь input.клетка { border-color: var(--рамка); }
table.перечень.словарь input.клетка:hover { border-color: var(--рамка-сильная); }
table.перечень.словарь input.клетка:read-only {
  border-color: transparent; color: var(--тихий);
}

/* Ширина столбца значений — от вида поля. Браузер делит поровну,
   потому что длины значений не знает: у ввода её нет в разметке.
   Вид поля знает экран, и он же говорит, сколько места столбцу надо.

   Это **предпочтение**, а не пол: `min-width` здесь был ошибкой —
   сумма наименьших ширин оказывалась шире карточки на узком окне,
   и таблица вылезала за её край вместе со столбцом действий. Меню
   строки становилось недостижимым вовсе. Заданная ширина уступает
   под нажимом, и столбцы жмутся все разом, а не срезается последний. */
table.перечень.словарь th.имя, table.перечень.словарь td.имя { width: 170px; }
table.перечень.словарь td.вид-number { width: 90px; }
table.перечень.словарь td.вид-string { width: 190px; }
table.перечень.словарь td.вид-file_ref { width: 140px; }
table.перечень.словарь td.вид-number input.клетка { min-width: 0; }

/* Столбец тэгов: метки в ряд, клетка нажимается. Ширина его —
   по содержимому, но не в ущерб остальным: много тэгов переносятся,
   а не растягивают строку. */
table.перечень.словарь th.тэги, table.перечень.словарь td.тэги {
  width: 1%; white-space: nowrap;
}
table.перечень.словарь td.тэги { cursor: pointer; display: table-cell; }
table.перечень.словарь td.тэги .метка.ещё-тэги {
  font-variant-numeric: tabular-nums; color: var(--свой); border-color: var(--свой-фон);
  background: var(--свой-фон);
}
table.перечень.словарь td.тэги .метка + .метка { margin-left: 4px; }
table.перечень.словарь td.тэги:hover .метка { border-color: var(--свой); color: var(--свой); }
table.перечень.словарь td.тэги:hover .тихо { color: var(--свой); }

/* --- подвал перечня ------------------------------------------------------
   Сколько показано и чем листать. Стоит под таблицей нарочно — это
   не действие над перечнем, а место в нём: «где я сейчас». Действия
   над всем перечнем живут в шапке карточки. */

.подвал-перечня {
  display: flex; align-items: center; gap: 8px;
  margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--рамка);
}
.подвал-перечня label.вровень {
  display: flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--тихий);
}
.подвал-перечня select { padding: 3px 6px; }
/* Уголок «назад» — тот же значок, повёрнутый: стрелки влево
   в наборе нет, а похожая на неё — враньё в картинке. */
.кнопка.значком.обратно[data-значок]::before { transform: rotate(180deg); }

/* Шапка таблицы прилипает к верху окна: пятьдесят строк листаются,
   а над столбцом по-прежнему стоит его имя. Тень снизу — чтобы
   уехавшая под шапку строка не казалась её частью. */
table.перечень.словарь thead th {
  position: sticky; top: 0; z-index: 2;
  box-shadow: inset 0 -1px 0 var(--рамка);
}

/* Заполненность: доля читается цифрами одной ширины, неполное
   помечено цветом — по столбцу сразу видно, где работа. */
table.перечень.словарь th.полно, table.перечень.словарь td.полно {
  width: 1%; white-space: nowrap; text-align: right;
}
table.перечень.словарь td.полно {
  font-variant-numeric: tabular-nums; font-size: 12px; cursor: default;
}
table.перечень.словарь td.полно-всё { color: var(--удача); }
table.перечень.словарь td.полно-не-всё { color: #c98a16; font-weight: 550; }

/* У поля ввода в словарной таблице своего пола ширины нет: он был
   девяносто точек, и на пяти столбцах это четыреста пятьдесят, ниже
   которых таблица не жалась ни при каком окне — а значит на узком
   она вылезала за карточку вместе со столбцом действий, и меню
   строки становилось недостижимым. Ширину столбцам задаёт вид поля
   выше; здесь снят только пол, чтобы под нажимом жалось всё разом. */
table.перечень.словарь input.клетка { min-width: 0; }

/* Заголовок столбца значений переносится. Запрет переноса стоит
   в общем правиле таблицы, и имя поля вроде «Изображение · архив»
   держало столбец шире, чем нужно, на любом окне. Узкие столбцы
   своего запрета не теряют — он у них в собственном правиле. */
table.перечень.словарь thead th { white-space: normal; }

/* --- экран-окно: верх стоит, едут только строки ---------------------------
   Обычная страница прокручивается целиком, и вместе с ней уезжают
   и полоса с переходами, и отбор, и шапка таблицы — то есть всё,
   по чему человек понимает, на что он смотрит. Здесь экран заперт
   в высоту окна, а полосой прокрутки становится само полотно
   перечня: шапка таблицы липнет к нему и остаётся на месте. */

body.окно-перечня { height: 100vh; display: flex; flex-direction: column; overflow: hidden; }
/* `width: 100%` здесь не украшение: `margin: 0 auto` у страницы
   отменяет растяжение по поперечной оси — поле со значением `auto`
   сжимает гибкий элемент до содержимого и центрирует его. Без ширины
   карточка съёживалась до своих кнопок посреди пустого экрана. */
body.окно-перечня .страница {
  flex: 1 1 auto; min-height: 0; width: 100%; display: flex; padding-bottom: 16px;
}
body.окно-перечня .карта.складная {
  flex: 1 1 auto; min-height: 0; margin-bottom: 0;
  grid-template-rows: auto minmax(0, 1fr);
}
/* Нутро растягивается на свою строку: у карточки `align-items: center`,
   и без этого оно вставало по середине высоты, оставляя над собой
   пустое поле в полэкрана. */
body.окно-перечня .карта.складная > .нутро {
  min-height: 0; align-self: stretch; display: flex; flex-direction: column;
}
.полотно-перечня { flex: 1 1 auto; min-height: 0; overflow: auto; }
/* Полотно прокручивается, значит шапка таблицы липнет к нему —
   а не к окну, из которого она всё равно уехала бы. */
.полотно-перечня table.перечень.словарь thead th { top: 0; }

/* --- свойства объекта -----------------------------------------------------
   Разделами, а не сплошной формой: своё у записи, поля типа, тэги,
   ссылка и сведения — это пять разных разговоров, и смешанные
   в один список они читаются как один. */

dialog#свойства { max-width: 620px; }
dialog#свойства .внутри { max-height: 74vh; overflow: auto; }
.ряд-заголовка { display: flex; align-items: center; gap: 8px; margin-bottom: 14px; }
.ряд-заголовка h2 { margin: 0; }
.раздел-свойств { margin-bottom: 18px; }
.раздел-свойств:last-child { margin-bottom: 0; }
.раздел-имя {
  font-size: 11.5px; letter-spacing: .02em; color: var(--тихий);
  padding-bottom: 7px; margin-bottom: 10px; border-bottom: 1px solid var(--рамка);
}
.набор-тэгов { display: flex; flex-wrap: wrap; gap: 4px; align-items: center; flex: 1 1 auto; }
.пара-свойства { display: flex; align-items: baseline; gap: 8px; margin-top: 8px; }
dialog#свойства input.правлено { border-color: #c98a16; }

/* --- окно свойств: одно на все экраны -------------------------------------
   Разметка его живёт в `svoystva.js`, и разделы выбираются по тому,
   что у записи есть. Здесь только вид. */

/* Шапка: значок типа, имя и чем эта запись является. Значок крупнее
   табличного — он здесь один и стоит за всё окно. */
/* Шапка стоит снаружи прокрутки: имя записи, уехавшее вверх,
   оставляет человека гадать, чьи свойства он правит. */
dialog#свойства > .ряд-заголовка {
  padding: 16px 20px 12px; margin: 0; border-bottom: 1px solid var(--рамка);
}
dialog#свойства > .внутри { padding-top: 14px; }
.ряд-заголовка .значок-типа { width: 20px; height: 20px; color: var(--тихий); }
.имя-записи { min-width: 0; }
.имя-записи .подзаголовок { margin-top: 2px; }

/* Поля парами. Имя и срок коротки, и держать их друг под другом
   на всю ширину значит гнать окно вниз на пустом месте. Длинное —
   описание, каталог, ссылка — просит всю ширину классом «во-всю»:
   рядом с ссылкой живут имя выбранного и три кнопки, и в половине
   ширины они встают друг на друга. */
dialog#свойства .поля-объекта.парами {
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 10px 12px;
}
dialog#свойства .поля-объекта.парами > .во-всю { grid-column: 1 / -1; }

/* Метка «принимает image» стоит в подписи поля, а не отдельной
   строкой: подпись у поля — блок, и метка внутри него без этого
   правила уезжала бы под него полосой во всю ширину. */
.поля-объекта label span .метка { display: inline-block; margin: 0 0 0 6px; }

/* Свёрнутый раздел — складкой самого браузера: своего механизма
   вкладок окно не заводит. Сводка стоит в самой складке, иначе
   свёрнутое никто не развернёт. */
.складка-свойств > summary {
  display: flex; align-items: baseline; gap: 8px; cursor: pointer;
  list-style: none; padding-bottom: 7px; margin-bottom: 10px;
  border-bottom: 1px solid var(--рамка);
}
.складка-свойств > summary::-webkit-details-marker { display: none; }
.складка-свойств > summary .раздел-имя {
  padding: 0; margin: 0; border: 0; flex: 0 0 auto;
}
/* Уголок поворачивается: без него складка не выглядит складкой,
   а выглядит заголовком, который почему-то нажимается. Он тот же
   `chevron-right` из Lucide, что у кнопки группы, — маской. */
.складка-свойств > summary .раздел-имя::before {
  content: ""; display: inline-block; width: 12px; height: 12px;
  margin-right: 5px; vertical-align: -2px; background: currentColor;
  -webkit-mask: url(icons/ui/chevron-right.svg) center / contain no-repeat;
  mask: url(icons/ui/chevron-right.svg) center / contain no-repeat;
  transition: transform .12s ease;
}
.складка-свойств[open] > summary .раздел-имя::before { transform: rotate(90deg); }
.складка-свойств > summary:hover .раздел-имя { color: var(--текст); }

/* Низа у окна свойств нет вовсе: «Сохранить» здесь не бывает, а
   кроме него низу нечего было нести. Крестик стоит в шапке, где
   его и ищут глазами. */

/* --- столбцы общего перечня ----------------------------------------------
   Название, Описание, Тэги, Заведён — то, что есть у всякой записи.
   Описание забирает остаток ширины: оно одно здесь бывает длинным,
   и распора поэтому не нужно. */

/* Описание забирает остаток ширины: оно одно здесь бывает длинным,
   и распор поэтому не нужен. Длинное обрезается **в тексте**, а не
   многоточием из стилей: в таблице с самоподбором ширины клетка
   сама по себе не обрезается, она растягивает таблицу, и обрезка
   стилями работала бы только при заданной ширине столбцов. */
table.перечень.словарь th.описание, table.перечень.словарь td.описание { width: auto; }
table.перечень.словарь th.имя, table.перечень.словарь td.имя { width: 1%; white-space: nowrap; }

/* --- поле ссылки на запись -----------------------------------------------
   Вместо адреса `files://<знак>` показано имя того, на что он
   показывает: знак человеку не говорит ничего. Сам адрес лежит
   в подсказке и в скрытом поле — его ждёт служба. */

.ссылка-поле { display: flex; align-items: center; gap: 6px; }
.ссылка-поле input.ссылка-имя {
  flex: 1 1 auto; min-width: 0; background: var(--панель); color: var(--текст);
}
.ссылка-поле input.ссылка-имя::placeholder { color: var(--тихий); }
/* Ссылка в никуда выглядит ссылкой в никуда: запись могли снести
   начисто, и молчать об этом хуже, чем сказать. */
.ссылка-поле input.нет-записи { color: var(--беда); border-color: var(--беда); }
dialog .ссылка-поле input.ссылка-имя { background: var(--фон); }

/* Окно выбора: в рамке живёт сам проводник, и высота ему нужна
   заданная — он занимает всё, что ему дали. Шире обычного окна
   нарочно: внутри дерево каталогов и сетка плиток. */
dialog#выбор { max-width: 1000px; }
.место-выбора {
  height: 68vh; min-height: 360px; width: 100%;
  border: 1px solid var(--рамка); border-radius: 9px; background: var(--фон);
}

/* --- картинка в плитке ----------------------------------------------------
   Плитка значков — сетка одинаковых квадратов, по которой картинку
   не выбрать. Там, где служба сказала, что браузер покажет содержимое
   сам, в плитку встаёт сама картинка. Короб 4:3: квадрат обрезает
   её сильнее, а разнобой высот ломает сетку. */

.плитка .вещь .значок-место.превью {
  display: block; width: 100%; aspect-ratio: 4 / 3;
  border-radius: 7px; overflow: hidden; background: var(--панель);
  border: 1px solid var(--рамка);
}
.плитка .вещь .значок-место.превью img {
  width: 100%; height: 100%; object-fit: cover; display: block;
}
/* Плитка с картинками крупнее: сто шестнадцать точек хватало значку,
   а картинке нет. */
.плитка:has(.значок-место.превью) {
  grid-template-columns: repeat(auto-fill, minmax(164px, 1fr));
}

/* Клетка, которую правят щелчком. Пунктир говорит это до наведения:
   указатель-рука виден только тому, кто уже навёл, а наводить
   на каждую клетку в поисках правки человек не станет. */
table.перечень.словарь td.правится {
  cursor: pointer;
  /* Цвет тихого текста, а не рамки: рамкой пунктир не виден вовсе,
     а невидимый знак не знак. */
  text-decoration: underline dotted var(--тихий);
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
}
table.перечень.словарь td.правится:hover {
  color: var(--свой); text-decoration-color: var(--свой);
}

/* --- выбор значка ---------------------------------------------------------
   Сетка самих значков, а не имён: имя `heart` человеку не говорит
   ничего, а значок говорит всё. */

dialog#выбор-значка { max-width: 560px; }
.сетка-значков {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(44px, 1fr));
  gap: 6px; margin-top: 12px; max-height: 46vh; overflow: auto;
}
.значок-клетка {
  display: flex; align-items: center; justify-content: center;
  aspect-ratio: 1; background: var(--полотно); color: var(--текст);
  border: 1px solid var(--рамка); border-radius: 8px; cursor: pointer;
}
.значок-клетка:hover { border-color: var(--свой); color: var(--свой); background: var(--свой-фон); }
.значок-клетка.выбран { border-color: var(--свой); background: var(--свой-фон); color: var(--свой); }
.значок-клетка::before {
  content: ""; width: 20px; height: 20px; background: currentColor;
  -webkit-mask: var(--значок) center / contain no-repeat;
  mask: var(--значок) center / contain no-repeat;
}

/* Значок типа в строке перечня и в плитке проводника. Маской, а не
   картинкой: значки одноцветные, и картинкой такой SVG был бы чёрным
   — невидимым в тёмном наборе. */
.значок-типа {
  display: inline-block; width: 16px; height: 16px; flex: 0 0 auto;
  background: currentColor; vertical-align: -3px;
  -webkit-mask: var(--значок) center / contain no-repeat;
  mask: var(--значок) center / contain no-repeat;
}
/* Значок типа стоит в клетке имени, перед именем. Своим столбцом он
   висел бы сам по себе, да и ширину такой столбец в таблице
   с самоподбором держит плохо — проверено глазами.

   Класс при этом не «значок» нарочно: у проводника так зовётся место
   значка ярлыка, и правило `.вещь .значок::after` дорисовывает ему
   уголок — в строке типа этот уголок появлялся сам собой. */
table.перечень.словарь td .значок-типа { margin-right: 8px; color: var(--тихий); }
.значок-типа.правится-щелчком { cursor: pointer; }
.значок-типа.правится-щелчком:hover { color: var(--свой); }

/* В плитке проводника значок типа занимает место картинки: он крупнее
   и приглушён, чтобы не спорить с настоящими превью рядом. */
.плитка .вещь .значок-место.значок-типа-место {
  display: flex; align-items: center; justify-content: center;
  width: 100%; aspect-ratio: 4 / 3; border-radius: 7px;
  background: var(--панель); border: 1px solid var(--рамка); color: var(--тихий);
}
.плитка .вещь .значок-место.значок-типа-место .значок-типа { width: 28px; height: 28px; }

/* --- экран в две колонки: перечень слева, выбранное справа ---------------
   Три карточки друг под другом (типы, поля, решения) читались сверху
   вниз и ломались на длине: поля стояли **под** перечнем, то есть
   на сотне типов — за краем окна. Человек выбирал тип и ехал вниз
   искать, что выбралось.

   Здесь перечень и выбранное стоят рядом, каждый столбец
   прокручивается сам, а страница не прокручивается вовсе. Высоту
   держит `body.окно-перечня`, тот же, которым заперт экран объектов.

   Складок у столбцов нет нарочно: складка нужна там, где карточки
   спорят за одну полосу прокрутки. Здесь полосы разные, и прятать
   содержимое незачем. */

.карта.столбцами { padding: 0; display: flex; overflow: clip; }
body.окно-перечня .карта.столбцами { flex: 1 1 auto; min-height: 0; margin-bottom: 0; }
.столб { display: flex; flex-direction: column; min-height: 0; min-width: 0; }
.столб.перечнем { flex: 0 0 290px; border-right: 1px solid var(--рамка); }
.столб.делом { flex: 1 1 auto; background: var(--фон); }

/* Оголовок столбца — заголовок слева, дела справа. Это та же шапка,
   что у складной карточки, только без уголка и без нажатия: складывать
   здесь нечего. */
.оголовок {
  display: flex; align-items: center; gap: 9px; flex: none; min-width: 0;
  padding: 10px 12px; border-bottom: 1px solid var(--рамка); background: var(--полотно);
}
.оголовок h2 {
  margin: 0; font-size: 14px; display: flex; align-items: center; gap: 7px; min-width: 0;
}
.оголовок h2 span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.оголовок .сводка {
  color: var(--тихий); font-size: 12px; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; min-width: 0;
}
/* Отбор и подвал внутри столбца стоят своими полосами, с рамкой,
   а не отступом: в карточке их отделял воздух, здесь — край столба. */
.столб .полоска-отбора {
  margin: 0; padding: 8px 10px; flex: none;
  border-bottom: 1px solid var(--рамка); background: var(--полотно);
}
.столб .подвал-перечня {
  margin: 0; padding: 6px 10px; flex: none;
  border-top: 1px solid var(--рамка); background: var(--панель);
}
.столб .полотно-перечня { background: var(--полотно); }
.столб .пусто { padding: 30px 16px; }
/* Прямой ребёнок столбца — это «тип не выбран»: оно стоит по
   середине. Прижатое к верху, оно читается как заголовок пустой
   таблицы, а таблицы там нет вовсе. */
.столб > .пусто { margin: auto; }

/* Строка перечня — не таблица: в столбце шириной в три сотни точек
   таблица из трёх столбцов жмётся до нечитаемого. Когда тип заведён,
   сказано в оголовке справа — у выбранного, где это и нужно. */
.строка-перечня {
  display: flex; align-items: center; gap: 8px; width: 100%; text-align: left;
  padding: 7px 12px; border: 0; border-bottom: 1px solid var(--рамка);
  background: none; color: inherit; font: inherit; cursor: pointer;
}
.строка-перечня:hover { background: var(--панель); }
.строка-перечня:hover .имя { color: var(--свой); }
.строка-перечня[aria-selected="true"] {
  background: var(--свой-фон); box-shadow: inset 3px 0 0 var(--свой);
}
.строка-перечня[aria-selected="true"] .имя { font-weight: 600; }
.строка-перечня .имя {
  flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.строка-перечня .счёт {
  color: var(--тихий); font-size: 12px; font-variant-numeric: tabular-nums;
}

/* Вкладки правого столбца. Поля, объекты и решения — три разговора
   об одном типе, и стоять им друг под другом значит снова гнать
   экран вниз. Счёт стоит на самой вкладке: сколько у типа объектов,
   видно не раскрывая её. */
.вкладки {
  display: flex; gap: 2px; flex: none; padding: 0 10px;
  background: var(--панель); border-bottom: 1px solid var(--рамка);
}
.вкладка {
  display: flex; align-items: center; gap: 7px; padding: 9px 12px; font: inherit;
  background: none; border: 0; border-bottom: 2px solid transparent;
  color: var(--тихий); cursor: pointer;
}
.вкладка:hover { color: var(--текст); }
.вкладка[aria-selected="true"] {
  color: var(--свой); border-bottom-color: var(--свой); font-weight: 600;
}
.вкладка[data-значок]::before { width: 14px; height: 14px; }
.вкладка .счёт {
  font-size: 11px; color: var(--тихий); background: var(--фон);
  border: 1px solid var(--рамка); border-radius: 9px; padding: 0 6px;
  font-variant-numeric: tabular-nums;
}
.вкладка[aria-selected="true"] .счёт { background: var(--полотно); }

/* Узкое окно: столбцы встают друг на друга — три сотни точек слева
   и таблица справа в телефонной ширине не уживаются. Перечень берёт
   верхнюю треть и прокручивается в ней. */
@media (max-width: 820px) {
  .карта.столбцами { flex-direction: column; }
  .столб.перечнем { flex: 0 0 38%; border-right: 0; border-bottom: 1px solid var(--рамка); }
}

/* Экран в две колонки берёт всю ширину окна: полоса в тысячу точек
   по центру оставляла по трети экрана пустыми с обеих сторон, а поля
   при этом жались в остаток. */
.страница.во-всю { max-width: none; }

/* --- настройки группами --------------------------------------------- */
/*
   Тот же уклад, что на экране типов: перечень слева, выбранное справа.
   Столб с группами шире перечня типов — имена групп длиннее, а счёта
   у них нет.
*/
.столб.группами { flex: 0 0 230px; }
.столб.группами .строка-перечня { padding: 9px 12px; }
.столб.группами .строка-перечня .значок-типа { color: var(--тихий); }
.столб.группами .строка-перечня[aria-selected="true"] .значок-типа { color: var(--свой); }

/* Нутро группы прокручивается само, страница — не прокручивается вовсе. */
.нутро-группы {
  flex: 1 1 auto; min-height: 0; overflow: auto;
  padding: 14px 16px; background: var(--полотно);
}
.нутро-группы > table.перечень { margin-top: 0; }
.нутро-группы > .числа { margin: 0; }
.нутро-группы > .журнал { margin-bottom: 0; }
.оголовок .дела { gap: 8px; flex: none; }

/* Строка службы: поля правятся по месту, ответ пробы стоит рядом
   с адресом, ручки справа. */
table.перечень.службы input[type="text"] { width: 100%; }
table.перечень.службы td.ответ { font-size: 12.5px; }
table.перечень.службы tr.база td.имя { font-weight: 600; }
table.перечень.службы tr.новая td { background: var(--панель); }
.годна { color: var(--удача); }
.негодна { color: var(--беда); }
.ручки { text-align: right; white-space: nowrap; }
.ручки .кнопка + .кнопка { margin-left: 4px; }


/* ============================================================
   Слой бота: каркас, компоненты и паттерны модулей.
   Оформление и поведение — из старого UI бота (web-service/src,
   ветка main), см. design/v1. Три палитры по модулям, два формата:
   ПК ≥1024 · растяжка 768–1024 · мобильный ≤768.
   ============================================================ */

/* ── токены слоя (латиница, чтобы не путать со словами скелета) ── */
:root {
  --bg: #f4f5f7;
  --card: #ffffff;
  --soft: #f7f8fa;
  --soft-2: #edeef1;
  --line: #e4e4e8;
  --line-strong: #d3d3da;
  --text: #1f1c1a;
  --muted: #6f6a66;
  --accent: #5b5754;
  --accent-dark: #3f3c39;
  --accent-ink: #ffffff;
  --danger: #b3544d;
  --ok: #5d8066;
  --shadow: 0 20px 48px rgba(40, 35, 32, 0.14);
  --radius: 8px;
  --page-pad: 32px;
  --serif: Georgia, "Times New Roman", serif;
  --mono: ui-monospace, SFMono-Regular, Consolas, "Liberation Mono", monospace;
}

body.mod-meditations {
  --bg: #efeeeb;
  --card: #ffffff;
  --soft: #fbf8f6;
  --soft-2: #f6e9e7;
  --line: #e8dbd7;
  --line-strong: #dcc9c4;
  --text: #2f2928;
  --muted: #766c68;
  --accent: #b8706c;
  --accent-dark: #874c49;
  --danger: #b3544d;
  --ok: #5d8066;
  --shadow: 0 20px 48px rgba(68, 53, 49, 0.14);
}
body.mod-booking {
  --bg: #f7f5f1;
  --card: #ffffff;
  --soft: #faf8f4;
  --soft-2: #f1ece3;
  --line: #e4ded5;
  --line-strong: #d8d0c5;
  --text: #1f1b18;
  --muted: #6b6158;
  --accent: #7b4b86;
  --accent-dark: #5d3564;
  --danger: #8f3524;
  --ok: #5d8066;
  --shadow: 0 20px 48px rgba(53, 45, 35, 0.13);
}

/* навигация в шапке служебных страниц скелета */
.нав-службы { display: flex; gap: 2px; flex-wrap: wrap; }
.нав-службы a {
  padding: 7px 12px; border-radius: var(--radius, 8px);
  color: var(--тихий); text-decoration: none; font-size: 14px;
}
.нав-службы a:hover { background: var(--панель); color: var(--текст); }
.нав-службы a.here {
  background: var(--свой-фон); color: var(--свой);
  font-weight: 600;
}

/* ── каркас слоя ── */
.muteline {
  position: sticky; top: 0; z-index: 30;
  display: flex; align-items: center; gap: 16px;
  padding: 12px var(--page-pad);
  background: color-mix(in srgb, var(--card) 88%, transparent);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--line);
}
.muteline .titles { min-width: 0; }
.muteline .titles .sub { font-size: 13px; color: var(--muted); margin-top: 2px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.spacer { flex: 1; }
.mnav { display: flex; gap: 2px; }
.mnav a {
  padding: 7px 12px; border-radius: var(--radius);
  color: var(--muted); text-decoration: none; font-size: 14px;
}
.mnav a:hover { background: var(--soft-2); color: var(--text); }
.mnav a.active { background: var(--accent); color: var(--accent-ink); }
.mnavmenu { display: none; position: relative; }
.mnavmenu summary {
  list-style: none; cursor: pointer;
  width: 38px; height: 38px; border-radius: var(--radius);
  display: grid; place-items: center;
  border: 1px solid var(--line); background: var(--card);
}
.mnavmenu summary::-webkit-details-marker { display: none; }
.mnavmenu .menu {
  position: absolute; top: 44px; left: 0; min-width: 220px;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: var(--shadow); padding: 6px; display: grid; gap: 2px;
}
.mnavmenu .menu a { padding: 10px 12px; border-radius: 6px; text-decoration: none;
  color: var(--text); font-size: 14px; }
.mnavmenu .menu a.active { background: var(--soft-2); color: var(--accent-dark); font-weight: 600; }

.notice2 {
  margin: 16px var(--page-pad) 0;
  padding: 12px 16px;
  background: var(--card); border: 1px solid var(--line);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius); font-size: 14px;
}
.notice2.danger { border-left-color: var(--danger); }

/* ── кнопки и поля ── */
.btn {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 9px 16px; border-radius: var(--radius);
  border: 1px solid transparent; background: var(--accent); color: var(--accent-ink);
  cursor: pointer; font-size: 14px; text-decoration: none;
}
.btn:hover { background: var(--accent-dark); }
.btn-quiet { background: var(--card); color: var(--text); border-color: var(--line); }
.btn-quiet:hover { background: var(--soft-2); }
.btn.small { padding: 6px 10px; font-size: 13px; }
.btn-row { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }

.minp, textarea.minp, select.minp {
  width: 100%; padding: 9px 12px;
  border: 1px solid var(--line-strong); border-radius: var(--radius);
  background: var(--card); color: var(--text);
}
.minp:focus { outline: 2px solid color-mix(in srgb, var(--accent) 45%, transparent);
  border-color: var(--accent); }
.mfield { display: grid; gap: 6px; margin-bottom: 14px; }
.mfield > span { font-size: 13px; color: var(--muted); }

/* ── chips, вкладки, фильтры ── */
.mchip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 10px; border-radius: 999px;
  font-size: 12.5px; font-weight: 600;
  background: var(--soft-2); color: var(--muted); white-space: nowrap;
}
.mchip.ok { background: color-mix(in srgb, var(--ok) 16%, var(--card)); color: var(--ok); }
.mchip.accent { background: color-mix(in srgb, var(--accent) 16%, var(--card)); color: var(--accent-dark); }

.mtabs { display: flex; gap: 4px; flex-wrap: wrap; padding: 0 var(--page-pad); margin-top: 14px; }
.mtabs button {
  border: 1px solid var(--line); background: var(--card);
  padding: 8px 14px; border-radius: var(--radius); cursor: pointer;
  color: var(--muted); font-size: 14px;
}
.mtabs button.active { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
.mtabs button .cnt { opacity: .75; font-size: 12.5px; margin-left: 4px; }
.mtabpick { display: none; margin: 14px var(--page-pad) 0; }

/* ── вспомогательное ── */
.back-row { margin-bottom: 10px; }
.back-btn { border: 0; background: none; cursor: pointer; padding: 4px 0;
  color: var(--accent-dark); font-size: 14px; }
.back-btn:hover { text-decoration: underline; }
.mempty { padding: 28px 16px; text-align: center; color: var(--muted); font-size: 14px; }
.mkv { display: grid; grid-template-columns: 120px 1fr; gap: 6px 12px; font-size: 14px; margin: 12px 0; }
.mkv dt { color: var(--muted); font-size: 13px; }
.mkv dd { margin: 0; min-width: 0; }
.markdown { font-family: var(--serif); font-size: 15.5px; line-height: 1.6; }
.mcode { font-family: var(--mono); font-size: 12.5px; }

/* ── паттерн «список + карточка» ── */
.mworkspace {
  display: grid; grid-template-columns: 380px minmax(0, 1fr); gap: 20px;
  padding: 16px var(--page-pad) 40px; align-items: start;
}
.mcol-list { min-width: 0; }
.mcol-detail { min-width: 0; position: sticky; top: 76px; }
.mitem {
  display: block; width: 100%; text-align: left; cursor: pointer;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 12px 14px; margin-bottom: 8px; color: var(--text);
}
.mitem.active { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.mitem .top { display: flex; align-items: center; gap: 8px; }
.mitem .nm { font-weight: 600; }
.mitem .tm { margin-left: auto; font-size: 12px; color: var(--muted); white-space: nowrap; }
.mitem .pr { font-size: 13px; color: var(--muted); margin-top: 6px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mdetail { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); }
.mdetail .dhead { padding: 16px 20px; border-bottom: 1px solid var(--line);
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.mdetail .dbody { padding: 16px 20px 20px; }
.mcover { border-radius: 6px; background: linear-gradient(135deg, var(--soft-2), var(--line-strong));
  display: grid; place-items: center; color: var(--muted); font-size: 11px; flex: none; }

/* ── модальное окно ── */
.mmodal-overlay { position: fixed; inset: 0; z-index: 60;
  background: rgba(20, 16, 14, .44); display: none;
  align-items: center; justify-content: center; padding: 16px; }
.mmodal-overlay.open { display: flex; }
.mmodal { width: min(560px, 100%); max-height: calc(100vh - 64px);
  background: var(--card); border-radius: var(--radius); box-shadow: var(--shadow);
  display: flex; flex-direction: column; }
.mmodal .mhead { display: flex; align-items: center; padding: 14px 18px;
  border-bottom: 1px solid var(--line); }
.mmodal .mbody { padding: 18px; overflow-y: auto; }
.mmodal .x { margin-left: auto; border: 0; background: none; cursor: pointer;
  font-size: 20px; color: var(--muted); }

/* ── плеер ── */
.player { max-width: 480px; margin: 0 auto; padding: 28px var(--page-pad) 60px; }
.player audio { width: 100%; margin: 14px 0; }
.survey { margin-top: 26px; padding-top: 20px; border-top: 1px solid var(--line); }

/* ── мобильный формат ── */
.mb-only { display: none; }
@media (max-width: 1024px) {
  :root { --page-pad: 24px; }
  .mworkspace { grid-template-columns: 320px minmax(0, 1fr); gap: 16px; }
}
@media (max-width: 768px) {
  :root { --page-pad: 16px; }
  .mnav { display: none; }
  .mnavmenu { display: block; }
  .muteline { flex-wrap: nowrap; }
  .muteline .titles .sub { display: none; }

  .mworkspace { display: block; padding-top: 12px; }
  .mcol-detail { display: none; position: static; }
  body.view-detail .mcol-detail { display: block; }
  body.view-detail .mcol-list { display: none; }
  body.view-detail .mb-only { display: inline-flex; }
  .mtabs { display: none; }
  .mtabpick { display: block; }
  .mmodal { max-height: calc(100dvh - 32px); }
}

/* фильтры-кнопки (выпадашка статусов на мобильном) */
.filter-row { display: flex; gap: 6px; flex-wrap: wrap; }
.filter-button {
  border: 1px solid var(--line); background: var(--card); color: var(--muted);
  padding: 6px 12px; border-radius: 999px; cursor: pointer; font-size: 13px; margin: 0 6px 6px 0;
}
.filter-button.active, .filter-button:hover { color: var(--accent-dark); border-color: var(--accent); }
