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

   Главное правило вёрстки здесь: кнопки не лепятся друг к другу и не
   сваливаются под текст. Дела документа живут в полосе наверху, редкие —
   в «ещё», а весь остальной экран занимает лист. */

:root {
  --brand: #0F6E66;
  --brand-dark: #0B5751;
  --ink: #1A1815;
  --quiet: #6F6B65;
  --paper: #FFFFFF;
  --surface: #F7F7F5;
  --field: #FFFFFF;
  --line: #E6E4E0;
  /* Красный удаления. Два, а не один: «--danger» — заливка под белыми
     буквами, и она обязана оставаться тёмной в обеих темах; «--danger-ink»
     — сами красные буквы на подложке страницы, и в тёмной теме им надо
     светлеть, иначе на «--field» они опускаются до контраста 3.3. */
  --danger: #C0392B;
  --danger-ink: #C0392B;
  /* Буква НА фирменной заливке. Роль, а не цвет, и по той же причине, что
     у «--danger-ink»: в светлой теме заливка тёмная и буква на ней белая, а
     в тёмной «--brand» светлеет — и белой букве светлеть уже некуда, выходит
     3.3 при нужных 4.5. Тёмная буква на светлой заливке даёт 5.37. */
  --on-brand: #FFFFFF;
  /* Горящая звезда. Один цвет на обе темы нарочно: звезда живёт на семи
     разных подложках — «--surface», «--field», «--paper» (та белая и в
     тёмной теме) и на взятой строке, крашенной «--brand» в 14%, — и
     перебирать ей цвет по теме значило бы промахнуться на одной из них.
     Значку нужны 3.0; замерено на всех семи, худшая — 3.23 (взятая строка
     на светлой теме), лучшая — 4.23. Прежний #E0A21A давал 2.09. */
  --star: #A3720A;
  --shadow: 0 1px 2px rgba(26, 24, 21, .06), 0 8px 24px rgba(26, 24, 21, .08);
  --radius: 10px;
}

@media (prefers-color-scheme: dark) {
  :root {
    --brand: #2E9D93;
    --brand-dark: #38B3A8;
    --ink: #ECE9E4;
    --quiet: #9A958D;
    --paper: #FFFFFF;
    --surface: #201F1D;
    --field: #2A2926;
    --line: #3A3835;
    /* Заливка та же — белым буквам на ней светлеть некуда; буквы светлее. */
    --danger: #C0392B;
    --danger-ink: #F0705F;
    /* «--brand» здесь светлая, и буква на ней обязана потемнеть. Не
       «--ink»: тот в тёмной теме сам светлый. */
    --on-brand: #1A1815;
    --shadow: 0 1px 2px rgba(0, 0, 0, .4), 0 10px 30px rgba(0, 0, 0, .35);
  }
}

* { box-sizing: border-box; }

/* `hidden` — это «спрятано», и никакой `display` из наших правил не
   имеет права это перебить. Иначе полоска поиска и меню, объявленные
   гибкими, открыты всегда. */
[hidden] { display: none !important; }

html, body { height: 100%; }

/* Свой шрифт: тот же, которым набраны программы на маке, айфоне и
   Android. Без него веб выглядел бы чужим приложением с тем же именем. */
@font-face {
  font-family: 'Ziewnull Sans';
  src: url('шрифт/ZiewnullSans-Regular.ttf') format('truetype');
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: 'Ziewnull Sans';
  src: url('шрифт/ZiewnullSans-Bold.ttf') format('truetype');
  font-weight: 700;
  font-display: swap;
}
@font-face {
  font-family: 'Ziewnull Sans Display';
  src: url('шрифт/ZiewnullSansDisplay-Bold.ttf') format('truetype');
  font-weight: 700;
  font-display: swap;
}

body {
  margin: 0;
  background: var(--surface);
  color: var(--ink);
  font: 15px/1.5 'Ziewnull Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI',
        Roboto, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
}

/* ——— Общее ——— */

.button, label.button, button.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  min-height: 36px;
  padding: 8px 16px;
  border-radius: var(--radius);
  border: 1px solid transparent;
  background: var(--brand);
  color: #fff;
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  line-height: 1.2;
  white-space: nowrap;
  cursor: pointer;
  text-decoration: none;
  -webkit-appearance: none;
  appearance: none;
}

.button:hover { background: var(--brand-dark); }
.button:active { transform: translateY(1px); }
.button.small { min-height: 30px; padding: 5px 12px; font-size: 13px; }

.button.ghost {
  background: transparent;
  color: var(--ink);
  border-color: var(--line);
}
.button.ghost:hover { background: var(--line); }

.icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  padding: 0;
  border: 1px solid transparent;
  border-radius: var(--radius);
  background: transparent;
  color: var(--ink);
  cursor: pointer;
}
.icon:hover { background: var(--line); }
.icon svg {
  width: 20px; height: 20px;
  fill: none; stroke: currentColor; stroke-width: 1.6;
  stroke-linecap: round; stroke-linejoin: round;
}

.quiet { color: var(--quiet); font-size: 13px; }

input[type=search], input[type=text], select {
  min-height: 34px;
  padding: 6px 10px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--field);
  color: var(--ink);
  font: inherit;
  font-size: 14px;
}
input:focus-visible, select:focus-visible, .button:focus-visible,
.icon:focus-visible, [contenteditable]:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}

/* ——— Экран приёма ——— */

.welcome { padding-bottom: 72px; }

/* Та же ширина и те же поля, что у страниц tiho.one (tiho.css: --wrap). */
.welcome .wrap {
  width: 100%;
  max-width: 940px;
  margin: 0 auto;
  padding: 0 24px;
}

/* Шапка сайта — как на tiho.one: имя слева, соседи и язык справа. */
.site-top {
  position: sticky;
  top: 0;
  z-index: 5;
  background: color-mix(in srgb, var(--surface) 88%, transparent);
  backdrop-filter: saturate(180%) blur(12px);
  -webkit-backdrop-filter: saturate(180%) blur(12px);
  border-bottom: 1px solid var(--line);
}
.site-top .wrap {
  display: flex;
  align-items: center;
  gap: 20px;
  min-height: 60px;
  flex-wrap: wrap;
}
.brand {
  font-family: 'Ziewnull Sans Display', 'Ziewnull Sans', -apple-system, sans-serif;
  font-weight: 700;
  font-size: 19px;
  letter-spacing: -0.02em;
  color: var(--ink);
  text-decoration: none;
}
.brand span { color: var(--brand); }
.site-top nav { display: flex; gap: 18px; margin-left: auto; }
.site-top nav a { color: var(--quiet); text-decoration: none; font-size: 15px; }
.site-top nav a:hover { color: var(--ink); }
.site-top nav a[aria-current='page'] { color: var(--ink); font-weight: 600; }
.site-top select {
  font: inherit;
  font-size: 14px;
  color: var(--ink);
  background: transparent;
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 5px 8px;
}
/* Телефон: имя, соседи и язык — одной строкой, с полями в 16 пикселей. */
@media (max-width: 480px) {
  .welcome .wrap { padding-left: 16px; padding-right: 16px; }
  .site-top .wrap { gap: 12px; flex-wrap: nowrap; min-height: 54px; }
  .brand { font-size: 17px; }
  .site-top nav { gap: 12px; }
  .site-top nav a { font-size: 14px; }
  .site-top select { font-size: 13px; padding: 4px 4px; max-width: 96px; }
}
.site-top nav a:focus-visible, .brand:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 3px;
  border-radius: 4px;
}

/* Первый экран — масштабом главной tiho.one: крупный заголовок, спокойный
   вводный абзац, и сразу дело — место для файла. */
/* Вес двух классов нарочно: у блока есть и «wrap», а «.welcome .wrap» задаёт
   поля целиком и иначе обнулил бы отступ сверху. */
.welcome .hero { padding-top: clamp(40px, 8vw, 88px); }

.welcome h1 {
  font-family: 'Ziewnull Sans Display', 'Ziewnull Sans', -apple-system, sans-serif;
  margin: 0 0 16px;
  font-size: clamp(34px, 6vw, 54px);
  line-height: 1.08;
  letter-spacing: -0.02em;
  font-weight: 700;
  text-wrap: balance;
  max-width: 16ch;
}

.lead {
  margin: 0 0 36px;
  color: var(--quiet);
  font-size: clamp(16px, 2vw, 19px);
  line-height: 1.55;
  max-width: 60ch;
}

.drop {
  display: block;
  padding: clamp(36px, 6vw, 56px) 24px;
  border: 1.5px dashed var(--line);
  border-radius: 18px;
  background: var(--field);
  box-shadow: var(--shadow);
  text-align: center;
  cursor: pointer;
  transition: border-color .15s ease;
}
.drop:hover, .drop.over { border-color: var(--brand); }
.drop .button { font-size: 16px; padding: 12px 24px; }
@media (prefers-reduced-motion: reduce) { .drop { transition: none; } }
.drop input { display: none; }
.drop .quiet { margin: 12px 0 0; }

.cloud {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin: 20px 0 0;
}

.files { list-style: none; margin: 16px 0 0; padding: 0; }
.files li {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--field);
  margin-bottom: 8px;
  cursor: pointer;
}
.files li:hover { border-color: var(--brand); }

.say { margin: 20px 0 0; font-size: 14px; color: var(--ink); }

/* ——— Экран правки ——— */

.editor {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 10px 16px;
  background: var(--field);
  border-bottom: 1px solid var(--line);
  position: sticky;
  top: 0;
  z-index: 5;
}

.bar-left { display: flex; align-items: center; gap: 10px; min-width: 0; }

.name { display: flex; flex-direction: column; min-width: 0; }
.name strong {
  font-size: 14px;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Дела документа: одинаковый рост, одинаковые промежутки, перенос без
   налипания — на узком экране полоса складывается, а не слипается. */
.bar-right {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  justify-content: flex-end;
}

.more { position: relative; }

.menu {
  position: absolute;
  right: 0;
  top: calc(100% + 6px);
  min-width: 220px;
  padding: 6px;
  background: var(--field);
  border: 1px solid var(--line);
  border-radius: 12px;
  box-shadow: var(--shadow);
  display: flex;
  flex-direction: column;
  z-index: 10;
}
.menu button, .menu label {
  display: block;
  width: 100%;
  padding: 9px 12px;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--ink);
  font: inherit;
  font-size: 14px;
  text-align: left;
  cursor: pointer;
}
.menu button:hover, .menu label:hover { background: var(--surface); }
.menu .sep-line { display: block; height: 1px; margin: 6px 4px; background: var(--line); }

.find {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  padding: 8px 16px;
  background: var(--field);
  border-bottom: 1px solid var(--line);
}
.find input[type=search] { width: 220px; }
.find input[type=text] { width: 200px; }
.find .count { min-width: 64px; }
.case { display: inline-flex; align-items: center; gap: 6px; }
.find .icon:last-child { margin-left: auto; }

.canvas {
  flex: 1;
  overflow: auto;
  padding: 28px 16px 40px;
}

/* Панель работы с текстом. */
.tools {
  display: flex;
  align-items: center;
  gap: 4px;
  flex-wrap: wrap;
  padding: 6px 16px;
  background: var(--field);
  border-bottom: 1px solid var(--line);
}
.tools .sep {
  width: 1px;
  height: 22px;
  margin: 0 6px;
  background: var(--line);
}
.tools .icon { width: 32px; height: 32px; font-size: 15px; }
.tools .icon.on { background: var(--brand); color: #fff; }
.pick.narrow { min-width: 118px; }
.pick.tiny { min-width: 56px; }

/* Цвет: обычный выбор цвета браузера, спрятанный под букву. */
.colour { position: relative; overflow: hidden; }
.colour input[type=color] {
  position: absolute; inset: 0; width: 100%; height: 100%;
  opacity: 0; border: 0; padding: 0; cursor: pointer;
}
.colour .letter {
  font-weight: 700; font-size: 15px;
  border-bottom: 3px solid currentColor; line-height: 1.1;
  pointer-events: none;
}
/* Прописные, капитель, индексы, маркер и заливка: кнопка-переключатель
   и рядом узкая плашка цвета для маркера и заливки. */
.icon .sc { font-variant: small-caps; font-size: 15px; }
.icon sup, .icon sub { font-size: 9px; }
.icon .marker { background: #FFFF00; color: #1A1815; padding: 0 3px; border-radius: 3px; font-size: 13px; }
.icon .fill { background: #E7E6E6; color: #1A1815; padding: 0 3px; border-radius: 3px; font-size: 13px; }
.tools .icon.swatch { width: 18px; }
.swatch .letter { border-bottom: 0; font-size: 11px; }

.pick {
  min-height: 32px;
  min-width: 140px;
  padding: 4px 8px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--field);
  color: var(--ink);
  font: inherit;
  font-size: 14px;
}

/* Увеличение: таблетка в углу поверх листа. Полоса во всю ширину
   отнимала у документа сантиметр экрана ради двух знаков. */
.zoom {
  position: fixed;
  right: 18px;
  bottom: 18px;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 4px 6px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--field);
  box-shadow: var(--shadow);
  font-size: 13px;
  color: var(--quiet);
  z-index: 6;
}
.zoom .icon { width: 28px; height: 28px; }

/* Сказанное всплывает и уходит: держать под него полосу незачем. */
.toast {
  position: fixed;
  left: 50%;
  bottom: 22px;
  transform: translateX(-50%);
  max-width: min(560px, 90vw);
  padding: 10px 16px;
  border-radius: 999px;
  background: var(--ink);
  color: var(--surface);
  font-size: 13px;
  box-shadow: var(--shadow);
  z-index: 20;
}

dialog {
  border: 1px solid var(--line);
  border-radius: 16px;
  padding: 20px;
  background: var(--field);
  color: var(--ink);
  box-shadow: var(--shadow);
  max-width: 520px;
}
dialog::backdrop { background: rgba(0, 0, 0, .35); }
dialog h2 { margin: 0 0 12px; font-size: 17px; }
dialog ul { margin: 0 0 16px; padding-left: 20px; font-size: 14px; }

/* Окно вопроса: одна колонка полей, подпись над полем, беда — под полями,
   кнопки справа, главная — последней. На телефоне окно во всю ширину. */
dialog.ask {
  width: min(420px, calc(100vw - 32px));
  padding: 28px 28px 22px;
  border-radius: 18px;
}
dialog.ask[open] { animation: ask-in .16s ease-out; }
@keyframes ask-in { from { opacity: 0; transform: translateY(8px) scale(.98); } }
@media (prefers-reduced-motion: reduce) { dialog.ask[open] { animation: none; } }
dialog.ask::backdrop { background: rgba(20, 18, 15, .45); backdrop-filter: blur(2px); }
dialog.ask h2 { margin: 0 0 6px; font-size: 20px; letter-spacing: -.01em; }
.ask-lead { margin: 0 0 18px; color: var(--quiet); font-size: 14px; line-height: 1.45; }
#askfields { display: grid; gap: 14px; margin-top: 16px; }
.ask-field { display: grid; gap: 6px; }
.ask-field > span { font-size: 13px; font-weight: 600; color: var(--ink); }
.ask-field input[type=email], .ask-field input[type=password],
.ask-field input[type=text], .ask-field input[type=number] {
  width: 100%;
  box-sizing: border-box;
  padding: 11px 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  font-size: 15px;
  transition: border-color .12s, box-shadow .12s, background .12s;
}
.ask-field input:hover { border-color: var(--quiet); }
.ask-field input:focus-visible {
  outline: none;
  border-color: var(--brand);
  background: var(--field);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 22%, transparent);
}
.ask-field input[readonly] { font-family: ui-monospace, SFMono-Regular, Consolas, monospace; font-size: 13px; }
/* Код из письма: шесть цифр — крупно и вразрядку, чтобы сверять глазами. */
.ask-field input.code {
  font-size: 24px;
  font-variant-numeric: tabular-nums;
  letter-spacing: .4em;
  text-align: center;
  padding-left: calc(12px + .4em);
}
.ask-field .hint { font-size: 12px; font-weight: 400; color: var(--quiet); }
.ask-check { display: flex; align-items: center; gap: 10px; font-size: 14px; }
.ask-check input { width: 18px; height: 18px; accent-color: var(--brand); }
.ask-trouble {
  margin: 14px 0 0;
  padding: 10px 12px;
  border-radius: var(--radius);
  background: color-mix(in srgb, #C0392B 10%, var(--field));
  border: 1px solid color-mix(in srgb, #C0392B 35%, var(--line));
  color: var(--ink);
  font-size: 13.5px;
}
.ask-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 22px; }
.ask-actions .button { min-width: 108px; justify-content: center; }
.ask-actions .button[disabled] { opacity: .6; cursor: progress; }
.ask-side {
  margin: 18px -28px -22px;
  padding: 14px 28px;
  border-top: 1px solid var(--line);
  background: var(--surface);
  border-radius: 0 0 18px 18px;
  font-size: 13.5px;
  display: flex;
  flex-wrap: wrap;
  gap: 6px 18px;
}
.ask-side button {
  padding: 0;
  border: 0;
  background: none;
  color: var(--brand);
  font: inherit;
  cursor: pointer;
}
.ask-side button:hover { text-decoration: underline; }
@media (max-width: 480px) {
  .ask-actions { flex-direction: column-reverse; }
  .ask-actions .button { width: 100%; }
}

/* ——— Лист ——— */

.page {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 24px;
  transform-origin: top center;
}

/* Бумага документа. Именно бумага, а не стол книги: у них был один
   класс на двоих, и `overflow: hidden`, которым бумага обрезает свои
   строки, делал стол своим же прокручиваемым ящиком — оттого ни шапка
   колонок, ни закреплённые строки в книге не липли никуда. */
div.sheet {
  position: relative;
  background: var(--paper);
  color: #1A1815;
  border-radius: 2px;
  box-shadow: var(--shadow);
  overflow: hidden;
  /* Бумага правится как бумага: курсор ставится куда угодно. */
  caret-color: var(--brand);
}
div.sheet:focus { outline: none; }

.tabseg, .rowhead { position: absolute; top: 0; white-space: pre; }
/* Отточие: точки должны стоять ровно тем шагом, каким их смерили, — без
   кернинга, без лигатур и без разрядки. */
.leader { position: absolute; top: 0; white-space: pre;
          font-kerning: none; font-variant-ligatures: none; letter-spacing: 0; }
.row {
  position: absolute;
  white-space: pre;
  /* СВОЯ СЕТКА БРАУЗЕРА — ПРОЧЬ. «white-space: pre» велит чтить знак
     табуляции, и браузер чтит его по своей сетке (восемь пробелов), а не
     по «w:tab@w:pos». С нулём знак остаётся в дереве живым — поиск,
     каретка и сборка правки читают его по-прежнему, — но ширины не
     несёт, и место куску назначаем только мы. */
  tab-size: 0;
  font-family: Carlito, Calibri, 'Helvetica Neue', Arial, sans-serif;
  color: #1A1815;
  /* СВОЙ ПРОСВЕТ, А НЕ НАСЛЕДОВАННЫЙ. Без этого «.row» брала множитель
     1.5 у «body», и половина просвета опускала букву на треть кегля ниже
     того места, куда её ставит вёрстка. Место строки считает
     «верхСтроки» в «проба.js», и считает оно под «normal»: при нём
     половины просвета нет, и базовая линия стоит ровно на подъёме
     браузера от верха коробки. */
  line-height: normal;
}

/* Место картинки: пока сама она не рисуется, видно, что она тут есть и
   сколько занимает, — это честнее пустоты и куда честнее коробочки
   «OBJ», которую браузер рисует вместо знака объекта. */
img.picture {
  display: inline-block;
  vertical-align: middle;
  border: 0;
  background: none;
  object-fit: contain;
}

span.picture {
  display: inline-block;
  vertical-align: middle;
  border: 1px dashed #C9C5BE;
  border-radius: 2px;
  background: repeating-linear-gradient(45deg, #F4F2EF, #F4F2EF 4px,
                                        #EDEAE5 4px, #EDEAE5 8px);
}

/* Колонтитул — часть листа, но не часть текста: он тише и не правится
   вместе с ним. */
.row.side { color: #55514C; }
/* Сноска: те же строки, что и текст, только внизу полосы и под чертой. */
.row.note { color: #3A3733; }
.note-rule {
  position: absolute;
  width: 33%;
  border-top: 0.75pt solid #B7B2AB;
}

/* Найденное подсвечивается на самом листе — там, где оно и лежит. */
mark.hit { background: #FFE58A; color: inherit; padding: 0; }
mark.hit.now { background: var(--brand); color: #fff; }

@font-face {
  font-family: Carlito;
  src: url('шрифт/Carlito-Regular.ttf') format('truetype');
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: Carlito;
  src: url('шрифт/Carlito-Bold.ttf') format('truetype');
  font-weight: 700;
  font-display: swap;
}

@media (max-width: 700px) {
  .bar { flex-wrap: wrap; }
  .find input[type=search], .find input[type=text] { width: 100%; }
  .welcome { padding: 32px 16px 48px; }
}

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

.sheets { display: flex; flex-direction: column; height: 100%; }

.cellbar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 16px;
  background: var(--field);
  border-bottom: 1px solid var(--line);
}
.cellbar .where {
  min-width: 72px;
  padding: 4px 8px;
  border: 1px solid var(--line);
  border-radius: 8px;
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  text-align: center;
  color: var(--quiet);
}
.cellbar input {
  flex: 1;
  min-width: 0;
  font-family: Carlito, Calibri, 'Helvetica Neue', Arial, sans-serif;
}

.grid {
  flex: 1;
  overflow: auto;
  background: var(--paper);
}

table.sheet {
  border-collapse: collapse;
  table-layout: fixed;
  /* Числа и слова в ячейках — теми же буквами, что и в Excel: книга
     показывается своим шрифтом, а не нашим. Заголовки строк и колонок
     ниже — наши, и они наши же шрифтом. */
  font: 13px/1.3 Carlito, Calibri, 'Helvetica Neue', Arial, sans-serif;
  color: #1A1815;
}
table.sheet th, table.sheet td {
  border: 1px solid #D8D5D0;
  padding: 1px 4px;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: clip;
  vertical-align: bottom;
}
/* Шапки строк и колонок стоят на месте, пока сетка едет под ними:
   без этого на пятой сотне строк уже не понять, где ты. */
table.sheet thead th {
  position: sticky;
  top: 0;
  z-index: 2;
}
table.sheet th {
  font-family: 'Ziewnull Sans', sans-serif;
  background: var(--surface);
  color: var(--quiet);
  font-weight: 500;
  font-size: 12px;
  text-align: center;
}
table.sheet tbody th {
  position: sticky;
  left: 0;
  z-index: 1;
  width: 44px;
  min-width: 44px;
}
table.sheet thead th:first-child { left: 0; z-index: 3; }
/* Закреплённые строки и колонки книги: то, что в Excel держат на месте
   при прокрутке, — шапки таблиц. Место им считает движок, а держит их
   здесь. Фон непрозрачный: сквозь них не должно ехать содержимое. */
table.sheet td.frozen, table.sheet tr.frozen td, table.sheet tr.frozen th {
  position: sticky;
  background: var(--paper, #FFFFFF);
  z-index: 1;
}
/* Номер закреплённой строки стоит на месте и вбок, и вниз: иначе в
   левом столбце под шапкой видны номера уехавших строк. */
table.sheet tr.frozen th { background: var(--surface); z-index: 3; }
table.sheet tr.frozen td.frozen { z-index: 2; }
table.sheet td.num { text-align: right; font-variant-numeric: tabular-nums; }
table.sheet td.on {
  outline: 2px solid var(--brand);
  outline-offset: -2px;
}
table.sheet td.bad { color: #B3261E; }

.tabs {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 6px 12px;
  background: var(--field);
  border-top: 1px solid var(--line);
  overflow-x: auto;
}
.tabs button {
  padding: 6px 12px;
  border: 1px solid transparent;
  border-radius: 8px;
  background: transparent;
  color: var(--ink);
  font: inherit;
  font-size: 13px;
  white-space: nowrap;
  cursor: pointer;
}
.tabs button:hover { background: var(--surface); }
.tabs button.on { background: var(--brand); color: #fff; }

/* Окошко пароля: закрытый файл спрашивает слово, а не отказывает. */
.пароль-окно {
  position: fixed;
  inset: 0;
  display: grid;
  place-items: center;
  background: rgba(0, 0, 0, 0.35);
  z-index: 50;
}

.пароль-лист {
  background: var(--бумага, #fff);
  color: var(--чернила, #111);
  border-radius: 12px;
  padding: 20px 22px;
  min-width: 280px;
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.25);
  display: grid;
  gap: 10px;
}

.пароль-слово { font-weight: 600; margin: 0; }
.пароль-имя { margin: 0; opacity: 0.7; font-size: 0.9em; word-break: break-all; }

.пароль-поле {
  font: inherit;
  padding: 8px 10px;
  border: 1px solid rgba(0, 0, 0, 0.25);
  border-radius: 8px;
}

.пароль-кнопки { display: flex; gap: 8px; justify-content: flex-end; }
.пароль-кнопки button { font: inherit; padding: 7px 14px; border-radius: 8px; }
.пароль-да { background: var(--свой, #2b6cb0); color: #fff; border: none; }
.пароль-мимо { background: transparent; border: 1px solid rgba(0, 0, 0, 0.25); }

/* Клетка, залитая чужим рядом: она не своя, и править её нельзя. */
#grid td.spill { color: var(--тише, #6b6b6b); font-style: italic; }

/* Линейки листа: коробки обведённых абзацев. Тонкая полоска, положенная
   под строки, — рисовать её рамкой нельзя, толщина у неё своя на каждую
   сторону и приходит из файла. */
.sheet .rule {
  position: absolute;
  pointer-events: none;
}

/* Заливка абзаца: прямоугольник под строками. Лежит ниже линеек и ниже
   букв — так же, как её кладёт Word. */
.sheet .fill {
  position: absolute;
  pointer-events: none;
}

/* ——— Экран облака ———
   Распорядитель документов: слева разделы, справа опись. Цвета, отступы
   и скругления — те же, что у остальной программы; ничего своего здесь
   не заведено, кроме красного у удаления, и тот взят у окна вопроса.

   Имена с «оп-» — те, которыми зовёт узлы опись.js. Кириллица в именах
   классов браузеру безразлична, а читать их рядом с русским кодом,
   который их ставит, легче, чем переводить в уме. */

.оп-экран {
  display: flex;
  height: 100%;
  background: var(--surface);
  color: var(--ink);
}

/* Разделы. На широком экране — столбик слева, на узком — полоса
   наверху: отдавать четверть телефона под пять слов нельзя. */
.оп-разделы {
  width: 232px;
  flex: none;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 16px 12px;
  border-right: 1px solid var(--line);
  overflow: auto;
}
.оп-разделы h2 {
  margin: 4px 8px 12px;
  font-family: 'Ziewnull Sans Display', 'Ziewnull Sans', -apple-system, sans-serif;
  font-size: 15px;
}
.оп-раздел {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border: 0;
  border-radius: var(--radius);
  background: transparent;
  color: var(--ink);
  font: inherit;
  font-size: 14px;
  text-align: left;
  white-space: nowrap;
  cursor: pointer;
}
.оп-раздел:hover { background: var(--line); }
/* Заливка — та же фирменная, что у кнопок: два разных зелёных рядом были
   бы хуже низкого контраста. Меняется буква, и меняется ролью. */
.оп-раздел.на { background: var(--brand); color: var(--on-brand); }
.оп-раздел svg, .оп-значок {
  width: 18px;
  height: 18px;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.оп-значок { width: 20px; height: 20px; stroke: var(--brand); stroke-width: 1.5; }

/* «min-height: 0» — не украшение. На узком экране разделы и правая
   половина лежат столбиком, и правая половина по умолчанию («auto»)
   имеет право вырасти НИЖЕ экрана: тогда прокручивается вся страница, а
   опись внутри не прокручивается вовсе — её «overflow: auto» не при чём,
   места ей дали с запасом. Ноль запирает её в высоту экрана, и лишнее
   уходит в прокрутку самой описи, как и задумано. */
.оп-право { flex: 1; min-width: 0; min-height: 0; display: flex; flex-direction: column; }

.оп-шапка {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding: 12px 16px;
  background: var(--field);
  border-bottom: 1px solid var(--line);
}

/* Дорожка папок. Последняя часть — та, где стоим, — не кнопка: нажимать
   на «здесь» некуда. */
.оп-дорожка {
  display: flex;
  align-items: center;
  gap: 4px;
  flex-wrap: wrap;
  min-width: 0;
  margin-right: auto;
  font-size: 15px;
}
.оп-дорожка button {
  padding: 4px 6px;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: var(--ink);
  font: inherit;
  cursor: pointer;
}
.оп-дорожка button:hover { background: var(--line); }
.оп-дорожка b {
  padding: 4px 6px;
  font-family: 'Ziewnull Sans Display', 'Ziewnull Sans', -apple-system, sans-serif;
}
.оп-дорожка .оп-косая { color: var(--quiet); }

.оп-найти { width: 220px; }
.оп-шапка select { min-width: 0; }

/* Полоса дел. Рост держится и пустой: иначе опись подпрыгивает вверх на
   каждое снятие выделения. */
.оп-дела {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  min-height: 50px;
  padding: 8px 16px;
  background: var(--field);
  border-bottom: 1px solid var(--line);
}
.оп-дела .button[disabled] { opacity: .45; cursor: default; }
.оп-дела .оп-сколько { margin-left: auto; color: var(--quiet); font-size: 13px; }

.оп-беда {
  margin: 12px 16px 0;
  padding: 10px 12px;
  border-radius: var(--radius);
  background: color-mix(in srgb, #C0392B 10%, var(--field));
  border: 1px solid color-mix(in srgb, #C0392B 35%, var(--line));
  color: var(--ink);
  font-size: 13.5px;
}

.оп-тело { flex: 1; overflow: auto; padding: 8px 16px 24px; }

/* ——— Опись таблицей ——— */

.оп-таблица { width: 100%; border-collapse: collapse; font-size: 14px; }
.оп-таблица th {
  padding: 8px 10px;
  border-bottom: 1px solid var(--line);
  color: var(--quiet);
  font-size: 12px;
  font-weight: 600;
  text-align: left;
  white-space: nowrap;
}
.оп-таблица th.оп-жмётся { cursor: pointer; }
.оп-таблица th.оп-жмётся:hover { color: var(--ink); }
.оп-таблица td {
  padding: 8px 10px;
  border-bottom: 1px solid var(--line);
  vertical-align: middle;
}
/* Столбец имени забирает всё, что осталось, и ужимает имя многоточием.
   Без этого длинное имя раздвигает таблицу, и опись уезжает вбок вместе
   со всей страницей — а вбок страница ехать не должна нигде. */
.оп-таблица td:first-child, .оп-таблица th:first-child { width: 100%; max-width: 1px; }
.оп-таблица tbody tr:hover { background: var(--field); }
.оп-таблица tbody tr.оп-взято { background: color-mix(in srgb, var(--brand) 14%, transparent); }
.оп-таблица tbody tr:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: -2px;
}

.оп-имя { display: flex; align-items: center; gap: 10px; min-width: 0; }
.оп-имя span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.оп-тихо { color: var(--quiet); font-size: 13px; white-space: nowrap; }

.оп-звезда {
  padding: 2px;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: var(--quiet);
  line-height: 1;
  cursor: pointer;
}
.оп-звезда svg {
  width: 18px; height: 18px;
  fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linejoin: round;
}
.оп-звезда.горит { color: var(--star); }
.оп-звезда.горит svg { fill: currentColor; }
.оп-звезда:hover { color: var(--star); }
.оп-звезда:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }

/* ——— Опись плитками ——— */

.оп-плитки {
  display: grid;
  gap: 14px;
  padding-top: 12px;
  grid-template-columns: repeat(auto-fill, minmax(176px, 1fr));
}
.оп-плитка {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 14px;
  /* Поле, а не бумага: «--paper» остаётся белой и в тёмной теме — это
     цвет листа документа, и плитка на нём светилась бы белым пятном со
     светлыми же буквами. */
  background: var(--field);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  cursor: default;
}
.оп-плитка:hover { border-color: var(--quiet); }
.оп-плитка .оп-имя { font-weight: 600; }
.оп-плитка.оп-взято {
  border-color: var(--brand);
  background: color-mix(in srgb, var(--brand) 12%, var(--field));
}
.оп-плитка:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }

/* Пустое место: всегда со словом, что делать дальше. */
.оп-пусто { max-width: 420px; margin: 64px auto; text-align: center; color: var(--quiet); }
.оп-пусто .button + .button { margin-left: 8px; }
/* Гостю — только приглашение войти: разделы, шапка и дела спрятаны
   (атрибутом hidden, а класс нужен, чтобы display: flex его не перебил). */
.оп-гость .оп-разделы, .оп-гость .оп-шапка, .оп-гость .оп-дела { display: none; }
.оп-гость .оп-пусто { margin-top: 20vh; }
.оп-пусто h3 {
  margin: 0 0 8px;
  color: var(--ink);
  font-family: 'Ziewnull Sans Display', 'Ziewnull Sans', -apple-system, sans-serif;
  font-size: 16px;
}
.оп-пусто p { margin: 0 0 16px; font-size: 14px; line-height: 1.5; }

/* ——— Боковик сведений ——— */

.оп-сведения {
  width: 292px;
  flex: none;
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 16px;
  background: var(--field);
  border-left: 1px solid var(--line);
  overflow: auto;
}
.оп-сведения-шапка { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.оп-сведения-шапка h2 {
  margin: 0;
  font-family: 'Ziewnull Sans Display', 'Ziewnull Sans', -apple-system, sans-serif;
  font-size: 15px;
}
.оп-сведения-тело { display: grid; gap: 10px; font-size: 14px; }
/* Строка сведений: подпись сверху тихо, значение под ней. Двумя
   колонками длинный адрес почты ломает вторую в лапшу. */
.оп-сведения-тело div { display: grid; gap: 2px; }
.оп-сведения-тело dt, .оп-сведения-тело b {
  color: var(--quiet);
  font-size: 12px;
  font-weight: 600;
}
.оп-сведения-тело span { overflow-wrap: anywhere; }
.оп-сведения-пусто { margin: 0; color: var(--quiet); font-size: 13px; line-height: 1.5; }
.оп-место { margin-top: auto; display: grid; gap: 6px; }
/* Полоска в два куска: занятое документами и занятое корзиной. «flex» —
   чтобы второй кусок встал ЗА первым, а не под ним: они меряют одну и ту
   же полосу, и лежать друг на друге им нельзя. */
.оп-место-полоска {
  display: flex;
  height: 6px;
  border-radius: 999px;
  background: var(--line);
  overflow: hidden;
}
.оп-место-полоска i { display: block; height: 100%; width: 0; background: var(--brand); }
.оп-место-полоска i.полна { background: #C0392B; }
/* Корзина — тем же цветом, каким набраны тихие строки рядом: это тоже
   занятое место, но занятое тем, что человек уже выбросил. Другой цвет
   нужен затем, чтобы было видно, сколько вернётся, если её вычистить. */
.оп-место-полоска i.оп-место-корзина { background: var(--quiet); }

/* ——— Окна экрана облака ———
   Все они носят класс «ask» и берут его оформление. Здесь только то,
   чего у окна вопроса не было: список, дерево папок и красная кнопка. */

dialog.ask.wide { width: min(560px, calc(100vw - 32px)); }
.ask-field.narrow { width: 108px; }
/* Поля этих окон стоят прямо в форме, а не в «askfields», и промежутка
   между ними им никто не даёт: подпись поля липла к списку над ней. */
dialog.ask > form > .ask-field,
dialog.ask > form > .ask-check { margin-top: 16px; }

.button.danger { background: #C0392B; border-color: transparent; color: #fff; }
.button.danger:hover { background: #A53124; }

/* Списки в окнах: кому дан доступ, какие ссылки выданы, какие редакции
   были. Один вид на все три. */
.оп-кому, .оп-редакции, #sharelinks {
  list-style: none;
  margin: 16px 0 0;
  padding: 0;
  max-height: 300px;
  overflow: auto;
  font-size: 14px;
}
.оп-кому li, .оп-редакции li, #sharelinks li {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 0;
  border-bottom: 1px solid var(--line);
}
.оп-кому li:last-child, .оп-редакции li:last-child,
#sharelinks li:last-child { border-bottom: 0; }
.оп-кому span, .оп-редакции span, #sharelinks span {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Первое в строке растягивается, кнопки прижимаются вправо. */
.оп-кому li > :first-child, .оп-редакции li > :first-child,
#sharelinks li > :first-child { flex: 1; }

/* Ссылки в окне доступа: подвал окна, как «ask-side» у входа. */
.оп-ссылки {
  margin: 18px -28px -22px;
  padding: 14px 28px 18px;
  border-top: 1px solid var(--line);
  background: var(--surface);
  border-radius: 0 0 18px 18px;
}
.оп-ссылки h3 { margin: 0; font-size: 13px; font-weight: 600; color: var(--quiet); }
.оп-ссылка-новая { display: flex; align-items: flex-end; gap: 10px; margin-top: 12px; }

/* ——— Узкий экран ———
   Телефон: разделы ложатся полосой наверху, боковик сведений уходит из
   ряда и всплывает снизу поверх описи, а из столбцов остаются имя и
   дата — размер и «кто поделился» и на широком экране читают не они. */
@media (max-width: 720px) {
  .оп-экран { flex-direction: column; }
  .оп-разделы {
    width: auto;
    flex-direction: row;
    padding: 8px 12px;
    border-right: 0;
    border-bottom: 1px solid var(--line);
    overflow-x: auto;
  }
  .оп-разделы h2 { display: none; }
  .оп-найти { width: 100%; }
  .оп-шапка { padding: 10px 12px; }
  .оп-дела, .оп-тело { padding-left: 12px; padding-right: 12px; }
  .оп-беда { margin-left: 12px; margin-right: 12px; }
  /* Столбцы размера и «поделился» — вторая и четвёртая клетки: их
     порядок задан в опись.js, и если он там переменится, переменить
     надо и здесь. */
  .оп-таблица th:nth-child(2), .оп-таблица td:nth-child(2),
  .оп-таблица th:nth-child(4), .оп-таблица td:nth-child(4) { display: none; }
  .оп-плитки { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); }

  /* Шторка всплывает ПОВЕРХ описи, и низ списка уходит под неё: по
     накрытым строкам не щёлкнуть (elementFromPoint отдаёт шторку) и не
     доскроллить до них — тело описи и так кончается у нижнего края
     окна. Отдаём списку столько отступа снизу, какова шторка. Высоту её
     знает только браузер: она зависит от языка и от того, сколько
     сведений влезло, — потому её меряет опись-доступ.js и кладёт сюда
     числом «--шторка». Шторка закрыта или экран широк — число нулевое,
     и отступ остаётся прежним. */
  .оп-тело {
    padding-bottom: calc(24px + var(--шторка, 0px));
    /* Отступ даёт списку место, куда УЕХАТЬ из-под шторки; это второе
       говорит браузеру, что низ описи занят, — иначе «scrollIntoView»
       (им ходят стрелки по строкам и им же строку показывают после
       поиска) аккуратно поставит строку к нижнему краю окна, то есть
       ровно под шторку. */
    scroll-padding-bottom: var(--шторка, 0px);
  }

  .оп-сведения {
    position: fixed;
    left: 0; right: 0; bottom: 0;
    width: auto;
    max-height: 62vh;
    border-left: 0;
    border-top: 1px solid var(--line);
    border-radius: 16px 16px 0 0;
    box-shadow: var(--shadow);
    z-index: 30;
  }
}

/* ——— Дела над документами ———
   Весть внизу экрана, окно вопроса, меню по правой кнопке, правка имени
   прямо в строке и подсветка при перетаскивании. Всё это ставит
   опись-действия.js; имена с «опд-» — его.

   Прежде эти правила жили в нём самом, своим «<style>» в head, и оттого
   всегда перебивали здешние — что бы тут ни стояло. Два следа этого
   стоит помнить, чтобы не завести их снова: подложкой бралась «--paper»,
   а она белая и в тёмной теме (это цвет ЛИСТА документа, не поверхности),
   и «--ink» на ней давал контраст 1.21; беда писалась красными буквами по
   красной подложке — 2.36. Здесь и там, и там взяты роли «--field» и
   «--ink», а красным светится только фон. */

/* Весть внизу: показывает, что долгое дело идёт, и предлагает «отменить»
   сразу после переноса или удаления. Не «toast»: у той нет кнопок. */
.опд-весть {
  position: fixed;
  left: 50%;
  bottom: 24px;
  transform: translateX(-50%);
  z-index: 40;
  display: flex;
  align-items: center;
  gap: 14px;
  max-width: min(560px, 92vw);
  padding: 10px 12px 10px 16px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--field);
  color: var(--ink);
  font-size: 14px;
  box-shadow: var(--shadow);
}
.опд-весть-слово {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* «Отменить» в вести. Цвет взят «--brand-dark», а не «--brand», и это не
   прихоть: в тёмной теме «--brand» (#2E9D93) на подложке вести
   («--field», #2A2926) даёт 4.41 при норме 4.5 для мелкого текста. Мерили
   тогда текст вести и пункты меню, а единственную НАЖИМАЕМУЮ вещь в
   полосе — нет, и она единственная же и не добрала. «--brand-dark» в
   тёмной теме светлее «--brand» (там роли перевёрнуты: #38B3A8) и даёт
   5.67; в светлой это #0B5751 на белом — 8.41.
   Подсветка под рукой — не «--line»: на ней тот же «--brand-dark» падает
   до 4.55, впритык. Своя примесь брендового к подложке держит 4.83. */
.опд-весть-ход {
  padding: 4px 6px;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: var(--brand-dark);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}
.опд-весть-ход:hover { background: color-mix(in srgb, var(--brand) 12%, var(--field)); }
.опд-весть-долой {
  padding: 2px 6px;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: var(--quiet);
  font: inherit;
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
}
.опд-весть-долой:hover { background: var(--line); color: var(--ink); }

/* Окно вопроса действий: имя папки, новое имя, переспрос, дерево папок.
   Своё, а не «ask»: то окно строит проба.js и поля у него другие. Рама и
   цвета — общие с «dialog». */
.опд-окно {
  max-width: min(460px, 92vw);
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 16px;
  background: var(--field);
  color: var(--ink);
  box-shadow: var(--shadow);
}
.опд-окно::backdrop { background: rgba(20, 18, 15, .45); }
.опд-форма { display: flex; flex-direction: column; gap: 12px; padding: 20px; }
.опд-заглавие {
  margin: 0;
  font-family: 'Ziewnull Sans Display', 'Ziewnull Sans', -apple-system, sans-serif;
  font-size: 16px;
}
.опд-вступление {
  margin: 0;
  color: var(--quiet);
  font-size: 13px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.опд-нутро { display: flex; flex-direction: column; gap: 10px; }
.опд-вход {
  width: 100%;
  min-height: 36px;
  padding: 7px 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  font-size: 14px;
}
.опд-вход:focus-visible {
  outline: none;
  border-color: var(--brand);
  background: var(--field);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 22%, transparent);
}
/* Отказ в окне — тем же видом, что «ask-trouble» и «оп-беда». */
.опд-беда {
  margin: 0;
  padding: 8px 10px;
  border: 1px solid color-mix(in srgb, var(--danger) 35%, var(--line));
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--danger) 10%, var(--field));
  color: var(--ink);
  font-size: 13px;
}
/* Строка под вопросом: вернётся удалённое или нет. Читается тихо —
   страшно здесь само дело, а не цвет букв. */
.опд-грозно { margin: 0; color: var(--quiet); font-size: 13px; }
.опд-кнопки { display: flex; justify-content: flex-end; gap: 8px; }
/* Красная кнопка — та же, что «button danger». */
.опд-опасно, button.опд-опасно {
  background: var(--danger);
  border-color: transparent;
  color: #fff;
}
.опд-опасно:hover, button.опд-опасно:hover { background: #A53124; }
.опд-мимо { align-self: flex-start; }
.опд-ковсем {
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--quiet);
  font-size: 13px;
}

/* Дерево папок в окне «куда перенести». Своя прокрутка: папок бывает
   сотня, а окно при этом не должно перерасти экран. */
.опд-дерево {
  display: flex;
  flex-direction: column;
  max-height: 46vh;
  padding: 4px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  overflow: auto;
}
.опд-ветка {
  padding: 7px 10px;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: var(--ink);
  font: inherit;
  font-size: 14px;
  text-align: left;
  cursor: pointer;
}
.опд-ветка:hover:not(:disabled) { background: var(--line); }
/* Та же пара, что у «.оп-раздел.на», и та же беда: белым на светлой
   «--brand» выходит 3.3. Строка тоже новая — чинится тем же ходом. */
.опд-ветка.на { background: var(--brand); color: var(--on-brand); }
.опд-ветка:disabled { color: var(--quiet); cursor: default; }
.опд-ветка:focus-visible { outline: 2px solid var(--brand); outline-offset: -2px; }

/* Меню по правой кнопке. Тот же вид, что у «menu» наверху экрана. */
.опд-меню {
  position: fixed;
  z-index: 50;
  min-width: 196px;
  padding: 6px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--field);
  box-shadow: var(--shadow);
  display: flex;
  flex-direction: column;
}
.опд-пункт {
  padding: 8px 10px;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--ink);
  font: inherit;
  font-size: 14px;
  text-align: left;
  cursor: pointer;
}
.опд-пункт:hover, .опд-пункт:focus { background: var(--surface); outline: none; }
/* Опасное в меню — красными буквами, а не красной плиткой: плитка в
   списке читается как «уже выбрано». */
.опд-пункт.опд-опасно {
  background: transparent;
  border: 0;
  color: var(--danger-ink);
}
.опд-пункт.опд-опасно:hover { background: color-mix(in srgb, var(--danger) 14%, var(--field)); }

/* Правка имени прямо в строке описи. */
.опд-правка {
  width: 100%;
  max-width: 340px;
  min-width: 0;
  padding: 2px 6px;
  border: 1px solid var(--brand);
  border-radius: 6px;
  background: var(--field);
  color: var(--ink);
  font: inherit;
  font-size: 14px;
}

/* Перетаскивание: папка под рукой и экран, готовый принять файл с диска.
   Рамка встаёт только там, куда и правда положат, — см. «наОписи». */
.опд-цель {
  outline: 2px solid var(--brand);
  outline-offset: -2px;
  background: color-mix(in srgb, var(--brand) 16%, transparent) !important;
}
.опд-ливень { outline: 2px dashed var(--brand); outline-offset: -6px; }
