/* editor/style.css
 *
 * Рабочее место автора. Тёмное — потому что рядом с ним всё время висят
 * кадры фильма на тёмном фоне, и светлый интерфейс сбивал бы глаз с их
 * яркости.
 */

:root {
  --bg: #0f1319;
  --panel: #161b23;
  --panel-2: #1d232d;
  --border: #262e3a;
  --text: #dfe5ee;
  --muted: #8b96a6;
  --accent: #d9622f;
  --surface: #c9776b;
  --trouble: #e0603f;
  --good: #6fae7a;
  --radius: 8px;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 15px/1.5 "Segoe UI", system-ui, sans-serif;
  height: 100vh;
  display: flex;
  flex-direction: column;
}

.top {
  display: flex;
  align-items: baseline;
  gap: 16px;
  padding: 12px 20px;
  border-bottom: 1px solid var(--border);
  background: var(--panel);
}
.name { font-size: 17px; font-weight: 600; letter-spacing: .01em; }
/* Название стало ссылкой на витрину: браузер иначе подчеркнул бы его
 * и перекрасил в свой синий. display:flex — чтобы значок и текст
 * стояли в строку, как когда это был <div>. */
a.name { display: flex; align-items: center; gap: 8px; text-decoration: none; color: inherit; }
a.name:hover { opacity: .85; }
/* Имя программы простое, «студия» — оттенком: раньше правило красило
 * ОБА слова, и они к тому же слипались, потому что имя тоже стало
 * отдельным элементом. */
.name span + span { color: var(--accent); margin-left: 6px; font-weight: 400; }
.set { color: var(--muted); font-size: 13px; }

.canvas {
  flex: 1;
  display: grid;
  grid-template-columns: 300px 1fr 340px;
  gap: 1px;
  background: var(--border);
  min-height: 0;
}

.column {
  background: var(--bg);
  padding: 16px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 20px;
  min-height: 0;
}
/* Раздел никогда не сжимается ниже своего содержимого.
 *
 * ЗАЧЕМ. Колонка — это столбик из гибких разделов, и по умолчанию каждый
 * из них ужимается, когда места мало. Ужиматься им некуда: внутри
 * кнопки и списки заданной высоты — и содержимое ВЫЛЕЗАЕТ ПОВЕРХ
 * соседнего раздела. Заголовок «Собрать фильм» ложился прямо на текст
 * замечания, «Что считается сейчас» — на подсказку.
 *
 * flex: none — не ужимать ничего; не помещается — прокручивается вся
 * колонка целиком (у неё для этого overflow-y). Одна прокрутка на
 * колонку понятнее, чем вложенные. */
.column section { display: flex; flex-direction: column; gap: 8px; flex: none; }
/* hidden обязан побеждать display:flex выше — иначе спрятанная
   секция «Собрать фильм» остаётся на экране. Атрибут сильнее
   класса только с этим правилом. */
.column section[hidden] { display: none; }
/* Растущий раздел не должен схлопываться в полоску.
 *
 * ЗАЧЕМ ЯВНАЯ ВЫСОТА. «Что считается сейчас» стоит последним в колонке и
 * при flex:1 отдаёт всё место разделам выше: кнопок и подсказок над ним
 * набралось столько, что списку задач оставалось десять точек — и автор
 * не видел, идёт ли его отрисовка вообще. Раздел с ходом работы нельзя
 * сжимать до нечитаемости: именно в него смотрят, когда ждут.
 *
 * flex-shrink: 0 — не ужимать; min-height — на что имеет право всегда;
 * прокручивается при этом вся колонка, а не отдельный список: две
 * вложенные прокрутки на узком экране не нащупать пальцем. */
.column .growing { flex: 1 0 auto; min-height: 200px; }

/* Готовые фильмы: список копится, но прежние быстрые показы убираются
 * сами, так что длинным он не станет. Своей прокрутки не заводим —
 * вложенный ползунок внутри уже прокручиваемой колонки не нащупать. */
.ready { max-height: none; overflow: visible; }

h2 {
  margin: 0;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--muted);
  font-weight: 600;
}

/* ── Списки слева ── */

.topics, .structures, .jobs { list-style: none; margin: 0; padding: 0; }

/* Список фильмов не растёт бесконечно.
 *
 * С десятком тем он вытеснял дерево структур вниз, за край экрана, и
 * добраться до структур становилось нельзя, не прокрутив всю колонку.
 * Список получает свой предел высоты и свою прокрутку — дерево остаётся
 * на месте, сколько бы фильмов ни завели. */
.topics {
  max-height: min(22vh, 190px);
  overflow-y: auto;
  flex: none;
}
.structures { overflow-y: auto; flex: 1; min-height: 60px; }

.topics li, .structures li {
  padding: 7px 10px;
  border-radius: var(--radius);
  cursor: pointer;
  font-size: 14px;
}
.topics li:hover, .structures li:hover { background: var(--panel-2); }
.topics li.chosen { background: var(--panel-2); box-shadow: inset 2px 0 0 var(--accent); }
.topics li .small-text, .structures li .small-text { color: var(--muted); font-size: 12px; }

.structures li { display: flex; justify-content: space-between; gap: 8px; }
.structures li code { color: var(--surface); font-family: inherit; }

.search, .header, input, select, textarea {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--text);
  padding: 7px 10px;
  font: inherit;
  width: 100%;
}
input:focus, select:focus, textarea:focus { outline: 2px solid var(--accent); outline-offset: -1px; }
.tally { color: var(--muted); font-size: 12px; }

/* ── Кадры ── */

.topic-head { display: flex; flex-direction: column; gap: 8px; }
.header { font-size: 18px; font-weight: 600; }
.summary { color: var(--muted); font-size: 13px; }

.shots { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 12px; }

.shot {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 12px 14px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.shot .line { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.shot .line label { display: flex; align-items: center; gap: 6px; font-size: 13px; color: var(--muted); }
.shot .line label select, .shot .line label input { width: auto; }
.shot .number { font-weight: 600; color: var(--accent); }
.shot textarea { min-height: 48px; resize: vertical; }
.shot .shown { display: flex; flex-wrap: wrap; gap: 6px; }

.icon {
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 3px 8px 3px 10px;
  font-size: 13px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.icon.highlighted { border-color: var(--accent); color: #f0a877; }
.icon button { background: none; border: 0; color: var(--muted); cursor: pointer; font-size: 15px; padding: 0 2px; }
.icon button:hover { color: var(--trouble); }

/* ── Кнопки ── */

.button {
  background: var(--accent);
  border: 0;
  color: #fff;
  border-radius: var(--radius);
  padding: 9px 14px;
  font: inherit;
  font-weight: 500;
  cursor: pointer;
}
.button:hover { filter: brightness(1.1); }
.button[disabled] { opacity: .45; cursor: default; filter: none; }
.button.quiet { background: var(--panel-2); color: var(--text); border: 1px solid var(--border); }

.render-buttons { display: flex; flex-direction: column; gap: 8px; }
.choice { display: flex; gap: 10px; }
.choice label { flex: 1; font-size: 12px; color: var(--muted); display: flex; flex-direction: column; gap: 4px; }
.tip { color: var(--muted); font-size: 12px; margin: 0; }

/* ── Замечания и задачи ── */

/* Ошибки и советы выглядят по-разному.
 *
 * Раньше и то и другое было одинаково красным, а любое замечание вдобавок
 * запрещало отрисовку — и стилистический совет выглядел как поломка.
 * Красное — то, из-за чего фильм не снимется. Жёлтое — то, что стоит
 * поправить, но решать автору.
 */
.remark {
  border-left: 2px solid var(--trouble);
  padding: 6px 0 6px 10px;
  margin-bottom: 8px;
  font-size: 13px;
  cursor: pointer;
  border-radius: 0 var(--radius) var(--radius) 0;
}
.remark:hover { background: var(--panel); }
.remark.hint { border-left-color: #d8a13a; }
.remark .where { color: var(--muted); font-size: 12px; margin-top: 2px; }
.remark.hint .where { color: #d8a13a; }

.rank {
  font-size: 11px;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 2px 0 6px;
}

/* Кадр, на который показывает замечание. */
.shot.culprit {
  border-color: var(--trouble);
  box-shadow: 0 0 0 1px var(--trouble);
}
.shot.culprit.hint { border-color: #d8a13a; box-shadow: 0 0 0 1px #d8a13a; }

.jobs { display: flex; flex-direction: column; gap: 8px; }
.job {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 8px 10px;
  font-size: 13px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.job .upper { display: flex; justify-content: space-between; gap: 8px; }
.job .state.running { color: var(--accent); }
.job .state.done { color: var(--good); }
.job .state.error { color: var(--trouble); }
.thin-bar { height: 4px; background: var(--panel-2); border-radius: 2px; overflow: hidden; }
.thin-bar i { display: block; height: 100%; background: var(--accent); transition: width .4s; }

/* ── Просмотр ── */

.preview {
  position: fixed;
  inset: 0;
  background: rgba(6, 9, 13, .88);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 32px;
  z-index: 10;
}
.preview.hidden { display: none; }
.preview-box { position: relative; max-width: 90vw; max-height: 90vh; overflow: auto; }
.preview-box img, .preview-box video { max-width: 100%; border-radius: 10px; display: block; margin-bottom: 12px; }
.close {
  position: absolute; top: -6px; right: -6px;
  background: var(--panel); border: 1px solid var(--border); color: var(--text);
  border-radius: 50%; width: 32px; height: 32px; font-size: 20px; cursor: pointer;
}

/* ── Дерево структур ───────────────────────────────────────────────────
 *
 * Раскрывается щелчком и пальцем: цели нажатия крупные, наведение мышью
 * ничего не решает. На телефоне наведения нет вовсе, и всё, что работало
 * только по нему, там просто не работает.
 */

/* Дереву гарантируется место.
 *
 * Список фильмов сверху ограничен, но и этого мало: с десятком тем
 * дерево ужималось до полутора строк — формально видно, работать нельзя.
 * Нижняя граница важнее аккуратной раскладки: если места не хватает,
 * пусть прокручивается вся колонка. */
.tree { overflow-y: auto; flex: 1; min-height: 240px; }

.target {
  color: var(--accent);
  font-size: 12px;
  min-height: 16px;
}

.no-pictures { color: var(--muted); font-size: 12px; }
.no-pictures:empty { display: none; }

/* Пояснение под кнопкой: почему своя картинка вообще нужна.
   Тихое и мелкое — оно читается один раз, а мешать выбору структур,
   ради которого сюда и смотрят, не должно. */
.explain {
  margin: 6px 2px 10px;
  color: var(--muted);
  font-size: 12px;
  line-height: 1.45;
}
.explain:empty { display: none; }

.node > .bar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 8px;
  min-height: 44px;
  border-radius: var(--radius);
  cursor: pointer;
  user-select: none;
}
.node > .bar:active { background: var(--panel-2); }
.node > .bar .tick { color: var(--muted); width: 12px; flex: none; transition: transform .15s; }
.node.expanded > .bar .tick { transform: rotate(90deg); }
.node > .bar .count { margin-left: auto; color: var(--muted); font-size: 12px; }
.node > .children { display: none; padding-left: 14px; border-left: 1px solid var(--border); margin-left: 12px; }
.node.expanded > .children { display: block; }
.my2d-tools { display: flex; flex-wrap: wrap; gap: 6px; padding: 6px 0; }
.my2d-tools .explain { flex-basis: 100%; margin: 0; }

.sheet {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 8px;
  min-height: 48px;
  border-radius: var(--radius);
  cursor: pointer;
}
.sheet .words { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.sheet .name { overflow: hidden; text-overflow: ellipsis; }

/* Картинка структуры. Место под неё держится всегда — и когда картинки
 * нет: иначе список дёргается по мере их подгрузки, а прыгающие строки
 * невозможно читать. */
.picture {
  width: 40px;
  height: 40px;
  flex: none;
  border-radius: 6px;
  background: var(--panel-2);
  object-fit: contain;
}
.picture.none { visibility: hidden; }

.icon-picture {
  width: 20px;
  height: 20px;
  border-radius: 4px;
  object-fit: contain;
  margin-inline-end: 2px;
}

/* ── Увеличение картинки ───────────────────────────────────────────────
 *
 * Сорок точек хватает, чтобы отличить кость от мышцы, и не хватает,
 * чтобы узнать, какую именно. Увеличенная картинка показывается
 * ОТДЕЛЬНЫМ окошком поверх страницы, а не растяжением на месте.
 *
 * Растяжение на месте не годится при таком размере: список прокручивается,
 * а прокручиваемая область обрезает всё, что вылезло за её край, — и
 * увеличенная картинка теряла бы половину себя у границы колонки.
 */
.loupe {
  position: fixed;
  z-index: 100;
  padding: 6px;
  border-radius: 10px;
  background: var(--panel);
  border: 1px solid var(--border);
  box-shadow: 0 10px 40px rgba(0, 0, 0, .6);
  pointer-events: none;
  opacity: 0;
  transition: opacity .1s;
}
.loupe.is-visible { opacity: 1; }
/* Вдвое крупнее прежних 250 — по просьбе владельца; но не шире 60% и не
 * выше 70% экрана, чтобы на ноутбуке окошко не вылезало за край. */
.loupe img { display: block; width: min(500px, 60vw, 70vh); height: min(500px, 60vw, 70vh); object-fit: contain; }
.loupe .loupe-name {
  margin-top: 4px;
  font-size: 12px;
  color: var(--muted);
  text-align: center;
  max-width: min(500px, 60vw, 70vh);
}

/* ── Язык ──────────────────────────────────────────────────────────────
 *
 * Переключатель стоит в шапке и виден всегда: язык интерфейса — не
 * настройка, спрятанная в углу, а первое, что человек ищет, открыв
 * незнакомую программу на чужом языке.
 */

.langs {
  width: auto;
  margin-inline-start: auto;
  padding: 5px 8px;
  font-size: 13px;
}

/* Справа налево. Одного перевода строк мало: неперевёрнутая раскладка
 * читается как чужая — колонки идут не в том порядке, в каком их читают,
 * а отступы упираются не в тот край. */
[dir="rtl"] .node > .bar .tick { transform: rotate(180deg); }
[dir="rtl"] .node.expanded > .bar .tick { transform: rotate(90deg); }
[dir="rtl"] .node > .children {
  padding-left: 0;
  padding-right: 14px;
  border-left: 0;
  border-right: 1px solid var(--border);
  margin-left: 0;
  margin-right: 12px;
}
[dir="rtl"] .topics li.chosen { box-shadow: inset -2px 0 0 var(--accent); }
[dir="rtl"] .shot .line .button { margin-left: 0; margin-right: auto; }
[dir="rtl"] .remark { border-left: 0; border-right: 2px solid var(--trouble); padding: 4px 10px 4px 0; }
[dir="rtl"] .close { right: auto; left: -6px; }

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

.strip {
  flex: none;
  display: flex;
  gap: 6px;
  overflow-x: auto;
  padding: 2px 0 8px;
  min-height: 84px;
}
.strip:empty { display: none; }

.tile {
  flex: none;
  min-width: 56px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--panel);
  overflow: hidden;
  cursor: pointer;
  position: relative;
  display: flex;
  flex-direction: column;
}
.tile:hover { border-color: var(--muted); }
.tile.current { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }

.tile .thumb {
  height: 52px;
  background: var(--panel-2);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 2px;
  overflow: hidden;
}
.tile .thumb img { height: 100%; width: 100%; object-fit: cover; display: block; }
.tile .thumb .mini { height: 30px; width: 30px; object-fit: contain; }

.tile .bottom {
  display: flex;
  justify-content: space-between;
  gap: 4px;
  padding: 3px 6px;
  font-size: 11px;
  color: var(--muted);
}
.tile .bottom b { color: var(--text); font-weight: 600; }
.tile .bottom .length { font-variant-numeric: tabular-nums; }

/* Кадр, куда диктор не успевает, помечен прямо в ленте: иначе о нём
 * узнают, только долистав до его карточки. */
.tile.wont-fit { border-color: var(--trouble); }
.tile.wont-fit .bottom .length { color: var(--trouble); }

/* ── Экран предпросмотра ───────────────────────────────────────────────
 *
 * Лента показывает фильм по кадрам, но кадр в ней размером с ноготь.
 * Экран показывает выбранный кадр целиком, а когда фильм собран — играет
 * его. Без этого автор правит вслепую: видит подписи и числа, но не то,
 * что получится.
 */

/* flex: none — обязательно.
 *
 * В колонке-столбце всё сжимается по умолчанию, и экран ужимался ниже
 * своего содержимого: картинка вылезала поверх карточек кадров и
 * перехватывала нажатия — кнопка «Смотреть фильм» была видна, но не
 * нажималась. */
.screen {
  flex: none;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
  margin-bottom: 10px;
  /* Экран не уезжает при прокрутке настроек сцены: видно, что меняешь.
   * Колонка прокручивается сама (overflow-y), поэтому top: 0 — её верх. */
  position: sticky;
  top: 0;
  z-index: 6;
}

/* ── Свёрнутые сцены ──────────────────────────────────────────────────
 *
 * Открыта только выбранная сцена; остальные — строкой. Карточка
 * открытой сцены при выборе встаёт под экраном, а не прячется под ним. */
.shot { scroll-margin-top: calc(clamp(180px, 26vh, 320px) + 110px); }
.shot.folded > *:not(.fold-head) { display: none !important; }
.shot:not(.folded) > .fold-head { display: none; }
.shot.folded { cursor: pointer; padding-top: 8px; padding-bottom: 8px; }
.fold-head {
  font-size: 13px;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.shot.folded:hover .fold-head { color: var(--text, inherit); }
/* На телефоне колонки — вкладки, и закреплённый экран занял бы полэкрана. */
@media (max-width: 900px) {
  .screen { position: static; }
  .shot { scroll-margin-top: 0; }
}

/* Что настраивает карточка сцены: всю сцену или окно, выбранное на экране. */
.window-target { flex: 1 1 100%; display: flex; align-items: center; gap: 10px; padding: 6px 10px; border-radius: 6px; font-size: 13px; color: var(--muted); border: 1px dashed var(--border); }
.window-target.on { color: inherit; border: 1px solid var(--accent, #e2672e); }

/* ── Вид студии ──────────────────────────
 *
 * Панели убирает и настройки сцены ставит сам врач (armViewBar). Только на
 * широком экране: на телефоне колонки — вкладки. */
.view-bar { display: none; align-items: center; gap: 8px; margin-left: auto; font-size: 13px; color: var(--muted); }
.view-bar[hidden] { display: none !important; }
.view-bar label { display: flex; align-items: center; gap: 6px; white-space: nowrap; }
.view-bar select { background: var(--bg); color: inherit; border: 1px solid var(--border); border-radius: 6px; padding: 4px 6px; }
.view-bar .button.off { opacity: .55; text-decoration: line-through; }
@media (min-width: 901px) {
  .view-bar { display: flex; }
  body.no-left .column.left, body.no-right .column.right { display: none; }
  body.no-left .canvas { grid-template-columns: 1fr 340px; }
  body.no-right .canvas { grid-template-columns: 300px 1fr; }
  body.no-left.no-right .canvas { grid-template-columns: 1fr; }

  /* Экран и лента с одной стороны, настройки сцены — с другой, у каждой своя
   * прокрутка: экран не уходит, пока крутишь настройки. */
  body.edit-beside .column.middle {
    display: grid;
    grid-template-columns: minmax(0, 1.7fr) minmax(320px, 1fr);
    grid-template-rows: auto auto auto minmax(0, 1fr) auto;
    gap: 10px 16px;
    overflow: hidden;
  }
  body.edit-beside .build-steps { grid-column: 1 / -1; grid-row: 1; }
  body.edit-beside .topic-head { grid-column: 1 / -1; grid-row: 2; }
  body.edit-beside .screen { grid-column: 1; grid-row: 3; position: static; margin: 0; }
  body.edit-beside .strip { grid-column: 1; grid-row: 4 / 6; align-self: start; }
  body.edit-beside .shots { grid-column: 2; grid-row: 3 / 5; overflow-y: auto; min-height: 0; margin: 0; }
  body.edit-beside #add-shot { grid-column: 2; grid-row: 5; }
  body.edit-beside .screen-field { height: auto !important; aspect-ratio: 16 / 9; }
  body.edit-beside .screen-grip { display: none; }
  body.edit-beside .shot { scroll-margin-top: 0; }
  body.edit-on-left .column.middle { grid-template-columns: minmax(320px, 1fr) minmax(0, 1.7fr); }
  body.edit-on-left .screen, body.edit-on-left .strip { grid-column: 2; }
  body.edit-on-left .shots, body.edit-on-left #add-shot { grid-column: 1; }
}

/* Высота задаётся числом, а не соотношением сторон: соотношение без
 * определённой высоты в гибкой раскладке ведёт себя непредсказуемо, а
 * вписывание картинки всё равно делает object-fit. */
.screen-field {
  height: clamp(180px, 26vh, 320px);
  background: #000;
  display: flex;
  align-items: center;
  justify-content: center;
}
.screen-field img, .screen-field video { width: 100%; height: 100%; object-fit: contain; display: block; }
/* Живой экран. Щелчки проходят сквозь него к полю: по кадру ставят
 * свои надписи (см. armPlacing). */
.screen-field iframe.live-screen { width: 100%; height: 100%; border: 0; display: block; pointer-events: none; }
.screen-field .empty {
  color: var(--muted);
  font-size: 13px;
  padding: 16px;
  text-align: center;
  max-width: 46ch;
}

.screen-bottom {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 10px;
  font-size: 13px;
  color: var(--muted);
  border-top: 1px solid var(--border);
}
.screen-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.button.small { padding: 5px 10px; font-size: 13px; }
.hidden { display: none; }

/* ── Запись своего голоса ──────────────────────────────────────────────
 *
 * Голос живого врача убеждает сильнее любого синтезатора, а для
 * азербайджанского он вообще единственный путь: готового голоса нет ни
 * у одного бесплатного синтезатора.
 */
.entry { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.entry .button { padding: 5px 10px; font-size: 13px; }
.button.writing { background: var(--trouble); }
.entry audio { height: 30px; }
.entry .mark { font-size: 12px; color: var(--good); }
.entry .drop-entry {
  background: none; border: 0; color: var(--muted);
  cursor: pointer; font-size: 12px; text-decoration: underline;
}
.entry .drop-entry:hover { color: var(--trouble); }

/* Вид подписей — сложенным блоком: настройка нужна не каждому фильму,
 * но когда нужна — нужна срочно, потому что белый текст на светлой ткани
 * пропадает целиком. */
/* Заголовок складного блока: стрелка своя, а не системная.
 *
 * Системный треугольник у разных браузеров разный и на телефоне почти
 * не виден, а по стрелке человек понимает, что здесь что-то раскроется,
 * ещё до того, как прочтёт название. */
.caption-kind summary {
  cursor: pointer;
  font-size: 12px;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: .06em;
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 6px 0;
  min-height: 32px;
  list-style: none;
  user-select: none;
}
.caption-kind summary::-webkit-details-marker { display: none; }
.caption-kind summary:hover { color: var(--text); }
.caption-kind .arrow {
  display: inline-block;
  transition: transform .15s;
  font-size: 15px;
  line-height: 1;
}
.caption-kind[open] .arrow { transform: rotate(90deg); }
[dir="rtl"] .caption-kind .arrow { transform: rotate(180deg); }
[dir="rtl"] .caption-kind[open] .arrow { transform: rotate(90deg); }
.field-kind { display: flex; gap: 14px; flex-wrap: wrap; padding: 10px 0 2px; }
.field-kind label { display: flex; flex-direction: column; gap: 4px; font-size: 12px; color: var(--muted); }
.field-kind input[type="color"] { width: 46px; height: 28px; padding: 2px; }
.field-kind input[type="range"] { width: 120px; }

/* Пометка «кадры устарели». Цветом беды, а не тихим серым: автор
 * смотрит на экран и делает по нему выводы — а видит вчерашнее. */
.outdated {
  color: var(--trouble);
  font-size: 12px;
  white-space: nowrap;
}

/* ── Образец подписи ───────────────────────────────────────────────────
 *
 * Показывается ПОВЕРХ настоящего кадра, а не рядом на сером поле: весь
 * вопрос в том, читается ли цвет на этой картинке, а не сам по себе.
 * Ждать минуту отрисовки, чтобы это узнать, — слишком дорого за выбор
 * цвета.
 *
 * Стоит в углу, а не по центру: по центру уже стоит настоящая подпись,
 * отрисованная, и две одинаковые надписи рядом сбивали бы с толку.
 */
.screen-field { position: relative; }

.sample {
  position: absolute;
  left: 12px;
  bottom: 12px;
  display: flex;
  flex-direction: column;
  gap: 3px;
  align-items: flex-start;
  pointer-events: none;
}
.sample .plate {
  padding: 3px 10px;
  border-radius: 2px;
  white-space: nowrap;
  line-height: 1.25;
}
.sample .what-is {
  font-size: 10px;
  color: rgba(255, 255, 255, .55);
  background: rgba(0, 0, 0, .45);
  padding: 1px 5px;
  border-radius: 2px;
}
[dir="rtl"] .sample { left: auto; right: 12px; align-items: flex-end; }

/* ── Подписи поверх кадра ──────────────────────────────────────────────
 *
 * Место подписи и выноски считает отрисовщик — в браузере этого не
 * повторить: оно зависит от того, где структура окажется в кадре при
 * движущейся камере. А рисует их редактор, и потому цвет, размер и сам
 * текст меняются мгновенно, а не через минуту отрисовки.
 */
.labels { position: absolute; inset: 0; pointer-events: none; }
.labels .label {
  position: absolute;
  transform: translate(-50%, -50%);
  padding: 2px 8px;
  border-radius: 2px;
  white-space: nowrap;
  line-height: 1.25;
}
.labels svg { position: absolute; inset: 0; width: 100%; height: 100%; }

/* СВОЮ надпись можно тащить, поэтому щелчки до неё доходят — в отличие
 * от указателя, который стоит там, где посчитала отрисовка. */
.labels .label.own { pointer-events: auto; cursor: move; }
.labels .label.own:hover { outline: 1px dashed var(--accent); outline-offset: 2px; }

/* Кадр ждёт щелчка: прицел вместо стрелки говорит это без слов. */
.screen-field.placing { cursor: crosshair; }
.screen-field.placing::after {
  content: "";
  position: absolute;
  inset: 0;
  border: 2px dashed var(--accent);
  pointer-events: none;
}

/* ── Свои надписи в карточке кадра ─────────────────────────────────────
 *
 * Ряд на надпись: текст, девять быстрых мест, «поставить щелчком»,
 * «убрать». Сетка мест — без слов: она объясняет себя видом.
 */
.own-captions { flex-direction: column; align-items: stretch; gap: 6px; }
.own-caption { display: flex; align-items: center; gap: 6px; }
.own-caption input { flex: 1 1 auto; min-width: 0; }
.spots {
  display: grid;
  grid-template-columns: repeat(3, 10px);
  grid-template-rows: repeat(3, 10px);
  gap: 2px;
  flex: 0 0 auto;
}
.spots .spot {
  width: 10px;
  height: 10px;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 2px;
  background: var(--panel-2);
  cursor: pointer;
}
.spots .spot:hover { border-color: var(--accent); }
.spots .spot.chosen { background: var(--accent); border-color: var(--accent); }

/* ══ Под телефон и планшет ═════════════════════════════════════════════
 *
 * ЗАЧЕМ. Врач правит фильм не только за столом: он смотрит его между
 * приёмами, с телефона, и правит там же. Три колонки рядом на экране в
 * ладонь не помещаются — но и прятать их в меню нельзя: работа состоит
 * в том, чтобы брать структуру слева и тут же видеть кадр.
 *
 * КАК СДЕЛАНО. На узком экране колонки становятся страницами, между
 * которыми переключаются внизу — как в обычном мобильном приложении.
 *
 * ПАЛЕЦ, А НЕ КУРСОР. Цели нажатия не меньше сорока четырёх точек;
 * ничего важного не спрятано за наведением мыши — на телефоне наведения
 * нет вовсе, и всё, что работало только по нему, там не работает.
 */

.tabs { display: none; }

@media (max-width: 900px) {
  body { height: 100dvh; }

  .top { padding: 10px 14px; gap: 10px; }
  .name { font-size: 15px; }
  .set { display: none; }
  .langs { padding: 8px 10px; font-size: 14px; min-height: 40px; }
  /* Шапка на телефоне: пять ссылок и язык в одну строку не помещаются —
   * строка раздвигала страницу вбок, и всё содержимое уезжало за левый
   * край. Переносим на вторую строку; ссылки не рвём посередине. */
  .top { flex-wrap: wrap; row-gap: 8px; align-items: center; }
  .top .guide { white-space: nowrap; font-size: 14px; }
  .langs { max-width: 46vw; }

  .canvas {
    grid-template-columns: 1fr;
    grid-template-rows: 1fr;
    padding-bottom: 58px;
  }

  .column { display: none; padding: 14px; }
  .column.open { display: flex; }

  .tabs {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    display: flex;
    background: var(--panel);
    border-top: 1px solid var(--border);
    z-index: 30;
  }
  .tabs button {
    flex: 1;
    min-height: 56px;
    background: none;
    border: 0;
    color: var(--muted);
    font: inherit;
    font-size: 12px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    cursor: pointer;
  }
  .tabs button .badge { font-size: 18px; line-height: 1; }
  .tabs button.current { color: var(--accent); }

  .button { min-height: 46px; padding: 12px 16px; }
  .button.small { min-height: 40px; }
  input, select, textarea { min-height: 44px; font-size: 16px; }
  .field-kind input[type="range"] { width: 100%; }
  .field-kind label { flex: 1 1 45%; }
  .topics li { padding: 12px 10px; min-height: 48px; }
  .sheet { min-height: 56px; }
  .picture { width: 48px; height: 48px; }
  .icon { padding: 8px 10px 8px 12px; font-size: 14px; }
  .icon button { font-size: 20px; padding: 0 6px; }

  .topics { max-height: 40vh; }
  .tree { min-height: 200px; }
  .screen-field { height: clamp(160px, 30vh, 260px); }
  .tile { min-width: 84px; }
}

@media (max-width: 560px) {
  .strip { min-height: 74px; }
  .tile .thumb { height: 44px; }
  .screen-bottom { flex-wrap: wrap; }
  .shot { padding: 12px 10px; }
  .shot .line { flex-direction: column; align-items: stretch; }
  .shot .line label { justify-content: space-between; }
  .shot .line .button { margin-left: 0; width: 100%; }
}

/* Устройства без мыши: наведения нет, значит опираться на него нельзя. */
@media (hover: none) {
  .sheet:hover, .topics li:hover { background: none; }
  .sheet:active, .topics li:active { background: var(--panel-2); }
}

/* ── Длительность и запас слов ─────────────────────────────────────────
 *
 * Автор пишет текст и не знает, влезет ли он: узнаёт только на озвучке.
 * Запас слов считается тут же, по той же скорости речи, по которой потом
 * будет говорить диктор, — и меняется, пока набирают.
 */
.duration { display: flex; align-items: center; gap: 4px; }
.duration input { width: 64px; text-align: center; }
.duration button {
  min-width: 34px;
  min-height: 34px;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--text);
  font: inherit;
  cursor: pointer;
}
.duration button:hover { border-color: var(--accent); }

.cache {
  font-size: 12px;
  color: var(--muted);
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}
.cache.tight { color: var(--trouble); }
.cache .align {
  background: none;
  border: 0;
  color: var(--accent);
  cursor: pointer;
  font: inherit;
  font-size: 12px;
  text-decoration: underline;
  padding: 4px 0;
}

/* Плитка «+ кадр» в конце ленты.
 *
 * Кнопка внизу под всеми карточками при трёх кадрах уже за краем экрана:
 * чтобы добавить четвёртый, приходилось листать вниз. В ленте кадр
 * добавляют там же, где на него смотрят. */
.tile.add {
  border-style: dashed;
  color: var(--muted);
  align-items: center;
  justify-content: center;
  min-width: 64px;
  font-size: 13px;
}
.tile.add:hover { color: var(--accent); border-color: var(--accent); }

/* Убрать фильм.
 *
 * Крестик виден ВСЕГДА, а не по наведению: на телефоне наведения нет,
 * и спрятанное за ним попросту недоступно. Он же тусклый и мелкий —
 * действие редкое и опасное, оно не должно спорить с названием фильма. */
.topics li { display: flex; align-items: center; gap: 8px; }
.topics li .topic-caption { flex: 1; min-width: 0; }
.topics li .drop-film {
  flex: none;
  background: none;
  border: 0;
  color: var(--muted);
  font-size: 17px;
  line-height: 1;
  cursor: pointer;
  padding: 8px;
  border-radius: var(--radius);
  opacity: .5;
}
.topics li .drop-film:hover { color: var(--trouble); opacity: 1; background: var(--panel-2); }

/* Место на диске.
 *
 * Стоит внизу и молчит, пока убирать нечего: место кончается тихо —
 * сначала перестают дорисовываться кадры, потом молча обрывается
 * отрисовка. Увидев число заранее, автор нажмёт кнопку сам. */
.disk { gap: 6px; }
.disk .small-text { color: var(--muted); font-size: 12px; }

/* ── Корзина ──────────────────────────────────────────────────────────
 *
 * Удалённый фильм лежал на диске, но добраться до него можно было только
 * через проводник, зная про папку «удалённые». Для врача это то же, что
 * потерять. Корзина — здесь, рядом со списком, и свёрнута, пока не нужна.
 */
.bin { margin-top: 10px; font-size: 13px; }
.bin summary {
  cursor: pointer;
  color: var(--muted);
  padding: 4px 0;
  user-select: none;
}
.bin summary:hover { color: var(--text); }
.bin .tally { color: var(--muted); }
.bin[hidden] { display: none; }

.deleted { list-style: none; margin: 6px 0 0; padding: 0; }
.deleted li {
  padding: 6px 8px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  margin-bottom: 6px;
  background: var(--panel);
}
.deleted .name { color: var(--text); }
.deleted .when { color: var(--muted); font-size: 12px; margin-bottom: 6px; }
.deleted .buttons { display: flex; gap: 6px; flex-wrap: wrap; }
.deleted button {
  font: inherit;
  font-size: 12px;
  padding: 4px 8px;
  min-height: 32px;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: var(--bg);
  color: var(--text);
  cursor: pointer;
}
.deleted button:hover { border-color: var(--muted); }
.deleted button.forever { color: var(--trouble); }
.deleted .empty { color: var(--muted); padding: 4px 0; }

/* Кнопка «сохранить фильм»: это ссылка, но выглядеть должна кнопкой —
 * автор ищет глазами кнопку, а не подчёркнутый текст. */
a.button.download {
  display: inline-block;
  margin-top: 12px;
  text-decoration: none;
  text-align: center;
}

/* Готовые фильмы: что уже снято и как это забрать. */
.ready { list-style: none; margin: 0; padding: 0; }
.ready li {
  padding: 8px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  margin-bottom: 8px;
  background: var(--panel);
  font-size: 13px;
}
.ready .buttons { display: flex; gap: 6px; margin-top: 8px; flex-wrap: wrap; }
.ready .buttons .button { flex: 1; margin: 0; min-height: 34px; font-size: 12px; }

/* Кадр, картинка которого сейчас пересчитывается.
 *
 * Мягкая пульсация, а не красная рамка: это не беда, а обычная работа —
 * правка уже сохранена, снимок догоняет. Тревожить незачем. */
.tile.recounting .thumb { opacity: .55; }
.tile.recounting::after {
  content: "";
  position: absolute;
  left: 6px; right: 6px; bottom: 22px;
  height: 2px;
  border-radius: 2px;
  background: var(--main);
  animation: chasing 1.4s ease-in-out infinite;
}
@keyframes chasing {
  0%, 100% { opacity: .25; transform: scaleX(.3); }
  50%      { opacity: 1;   transform: scaleX(1); }
}
@media (prefers-reduced-motion: reduce) {
  .tile.recounting::after { animation: none; opacity: .7; }
}

/* Готовые фильмы: список копится и когда-нибудь станет длинным —
 * ограничиваем, чтобы он не выдавливал раздел с ходом работы. */
.ready { max-height: 300px; overflow-y: auto; }

/* Пусто — так и говорим. Пустой раздел без слов читается как поломка. */
.jobs:empty::after,
.ready:empty::after {
  content: attr(data-empty);
  color: var(--muted);
  font-size: 13px;
}

/* «Очистить» в заголовке раздела задач: список — это память о работе,
 * а не сама работа, и забыть её должно быть можно одним нажатием. */
h2 .clear {
  float: right;
  font: inherit;
  font-size: 11px;
  letter-spacing: .04em;
  text-transform: none;
  background: none;
  border: none;
  color: var(--muted);
  cursor: pointer;
  padding: 0;
  min-height: 0;
}
h2 .clear:hover { color: var(--text); text-decoration: underline; }

/* ── Отдельное окно просмотра ────────────────────────────────────────
 *
 * ЗАЧЕМ. Экран в средней колонке узкий: фильм в нём величиной с ладонь,
 * подпись не прочесть, мелкую структуру не разглядеть. Окно открывается
 * поверх всего, тянется за правый нижний угол и помнит свой размер до
 * следующего раза.
 *
 * РАЗМЕР ПО УМОЛЧАНИЮ — 960×600: шире почти любой средней колонки, но
 * помещается и на ноутбуке 1366×768, где полноэкранного места нет.
 */
.preview-window { position: fixed; inset: 0; z-index: 60; }
.preview-window.hidden { display: none; }
.window-backdrop { position: absolute; inset: 0; background: rgba(0, 0, 0, .62); }

.window {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: min(960px, 94vw);
  height: min(600px, 88vh);
  min-width: 320px;
  min-height: 220px;
  max-width: 98vw;
  max-height: 96vh;
  /* Тянется за угол средствами самого браузера: свой обработчик мыши
   * здесь не нужен и на планшете работал бы хуже стандартного. */
  resize: both;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: 0 24px 70px rgba(0, 0, 0, .55);
}

.window-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 12px 10px 14px;
  border-bottom: 1px solid var(--border);
  color: var(--muted);
  font-size: 13px;
  flex: none;
}
.window-close {
  background: none;
  border: 0;
  color: var(--muted);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  padding: 0 4px;
  min-height: 32px;
  min-width: 32px;
}
.window-close:hover { color: var(--trouble); }

.window-body {
  flex: 1;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #000;
  padding: 0;
}
/* Видео вписывается в окно целиком, каких бы пропорций оно ни было. */
.window-body video, .window-body img { max-width: 100%; max-height: 100%; display: block; }

@media (max-width: 700px) {
  /* На телефоне тянуть окно некуда — занимаем экран целиком. */
  .window { width: 100vw; height: 100vh; border-radius: 0; resize: none; max-width: 100vw; max-height: 100vh; }
}

/* Ссылка на инструкцию в шапке: не кнопка — читать её идут редко, но
 * найти должны с первого взгляда и не искать по меню. */
.guide {
  margin-left: auto;
  color: var(--muted);
  text-decoration: none;
  font-size: 13px;
  border-bottom: 1px dashed var(--border);
  padding-bottom: 1px;
}
.guide:hover { color: var(--accent); border-bottom-color: var(--accent); }

/* Что происходит в кадре: список действий, по одному в строке. */
.line.processes { flex-direction: column; align-items: stretch; gap: 8px; }
.process {
  display: flex;
  gap: 8px;
  align-items: center;
  flex-wrap: wrap;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 6px 8px;
}
.process select { width: auto; }
.drop-process {
  margin-left: auto;
  background: none;
  border: 0;
  color: var(--muted);
  font-size: 17px;
  cursor: pointer;
  padding: 0 4px;
  min-height: 30px;
}
.drop-process:hover { color: var(--trouble); }
.line.processes .button.small { align-self: flex-start; }

/* Состояние лицензии: ровным тоном, без уговоров. */
.license { color: var(--muted); line-height: 1.4; }
.license.bought { color: var(--good); }

/* Схематичная структура: в наборе она выложена парой граней и в кадре
 * будет полоской. Не запрет, а предупреждение — решает врач. */
.sheet .schematic {
  font-size: 11px;
  color: #d8a13a;
  border: 1px solid rgba(216, 161, 58, .4);
  border-radius: 999px;
  padding: 0 6px;
  margin-left: 6px;
  white-space: nowrap;
}

/* Знак рядом с именем: бренд должен быть виден там же, где имя. */
.name { display: flex; align-items: center; gap: 8px; }
.name .badge { display: block; flex: none; }

/* Составная структура: видно, сколько частей ляжет в кадр. */
.sheet .compound {
  font-size: 11px;
  color: var(--accent);
  border: 1px solid rgba(217, 98, 47, .4);
  border-radius: 999px;
  padding: 0 6px;
  margin-left: 6px;
  white-space: nowrap;
}

/* Совет про микрофон: свёрнут, пока не нужен.
   Разворачивать его сразу нельзя — он длиннее всего, что стоит рядом,
   и оттеснил бы вниз кнопки отрисовки, ради которых сюда и смотрят. */
.about-mic { margin: 4px 0 8px; }
.about-mic > summary {
  cursor: pointer;
  color: var(--muted);
  font-size: 12px;
  list-style: none;
}
.about-mic > summary::before { content: "› "; }
.about-mic[open] > summary::before { content: "⌄ "; }
.about-mic > summary::-webkit-details-marker { display: none; }
.about-mic > summary:hover { color: var(--text); }

/* Указание авторства и предупреждение о наследовании лицензии.
   Обычное — тихим цветом: это справка, а не тревога. Наследование —
   жёлтым: оно решает, можно ли фильм продавать. */
.attribution { line-height: 1.45; }
.attribution.danger { color: #d8a13a; }

/* Остаток бесплатных фильмов. Зелёным — это хорошая новость, а не
   предупреждение: человеку сейчас ничего не мешает. */
.license.trial { color: var(--good); }

/* Приглашение войти. Полотно из трёх колонок становится одним полем:
   колонок в нём всё равно нет, а карточка должна стоять посередине. */
.canvas.invite {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--bg);
  padding: 32px;
}

.login-card {
  max-width: 460px;
  text-align: center;
  display: flex;
  flex-direction: column;
  gap: 16px;
  align-items: center;
}

.login-card h1 { font-size: 22px; margin: 0; }
.login-card p { margin: 0; color: var(--muted); line-height: 1.55; }
.login-card .button { text-decoration: none; }

/* Полоса «вышла новая сборка».
   Под шапкой, во всю ширину: её должно быть видно, но она не должна
   перебивать работу — окно на её месте закрывали бы не читая. */
.update {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 9px 18px;
  background: var(--panel-2);
  border-bottom: 1px solid var(--accent);
  font-size: 14px;
}

.update .button { margin-left: auto; text-decoration: none; }

/* Почему кнопки отрисовки погашены. Рядом с ними, а не окном: причина
   должна читаться до нажатия, а не после. */
.why-not {
  margin: 10px 0 0;
  color: var(--muted);
  line-height: 1.5;
  border-left: 2px solid var(--accent);
  padding-left: 10px;
}

/* Окно «зачем нужна программа для отрисовки».
   Читается как страница, а не как сообщение: здесь объясняют, что
   человек ставит на свой компьютер, и текста тут на минуту чтения. */
.about-download {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, .72);
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 40px 20px;
  overflow-y: auto;
  z-index: 50;
}

.about-download.hidden { display: none; }

/* Своё имя, а не «лист»: то уже занято карточкой проверочного листа,
   и она разложена в строку. Мой текст ложился её колонками — по
   слову в столбик; увидел это только на снимке экрана. */
.about-download .window-sheet {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 28px 32px 24px;
  max-width: 640px;
  width: 100%;
}

.about-download h1 { margin: 0 0 18px; font-size: 22px; }

/* Заголовок раздела — не таким же серым, как подписи колонок: здесь он
   ведёт по тексту, а не помечает угол экрана. */
.about-download h2 {
  margin: 22px 0 6px;
  font-size: 15px;
  text-transform: none;
  letter-spacing: 0;
  color: var(--accent);
  font-weight: 600;
}

.about-download p { margin: 0; line-height: 1.6; color: var(--text); }

.about-download .row {
  display: flex;
  gap: 10px;
  margin-top: 26px;
  padding-top: 18px;
  border-top: 1px solid var(--border);
}

.about-download .row .button { text-decoration: none; }

/* Строка из журнала работы: чем она занята прямо сейчас.
   Приглушённо и одной строкой — это подсказка, а не содержание. */
.log {
  color: var(--muted);
  font-size: 11.5px;
  margin-top: 2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* «Голоса для этого языка нет» — прямо под выбором диктора.
   Пустой список сам по себе тупик: рядом должна стоять кнопка, а не
   догадка, что делать дальше. */
.no-voice {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 6px;
  padding-left: 10px;
  border-left: 2px solid var(--accent);
}

.no-voice .button { align-self: flex-start; }

/* Сопровождение работы: что происходит, словами.
   Крупнее технической строки под ним — это главное, что человек
   хочет знать, а счётчик кадров нужен ему вторым. */
.commentary {
  font-size: 13.5px;
  line-height: 1.45;
  color: var(--text);
  margin: 2px 0 4px;
}

.commentary.done { color: var(--good); font-weight: 500; }


/* Перенос раскадровки: две неброские ссылки под списком фильмов.
   Действие редкое — раз на фильм, — и кричать о нём незачем. */
.carry {
  display: flex;
  gap: 14px;
  margin: 8px 2px 0;
  font-size: 12px;
}
.quiet-link {
  color: var(--dim, #8a94a6);
  cursor: pointer;
  text-decoration: none;
  border-bottom: 1px dotted currentColor;
}
.quiet-link:hover { color: var(--ink, #e8ecf2); }

/* ── Ссылка на фильм ───────────────────────────────────────────────
 *
 * Своё окно, а не окно предпросмотра: то тянется за угол и занимает
 * пол-экрана, потому что в нём смотрят фильм. Здесь дело на десять
 * секунд — взять ссылку и отдать, — и окно должно быть под стать.
 */
.share-back {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, .55);
  z-index: 60;
}
.share-card {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: min(620px, 94vw);
  z-index: 61;
  background: var(--panel, #131a24);
  border: 1px solid var(--line, #1f2836);
  border-radius: 12px;
  padding: 20px 22px 22px;
  box-shadow: 0 18px 60px rgba(0, 0, 0, .55);
}
.share-card h2 { margin: 0 0 6px; font-size: 17px; font-weight: 650; }
.share-card p { margin: 0 0 12px; }
.share-card input {
  width: 100%;
  margin-bottom: 12px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12px;
}
/* Кнопки в один ряд и с переносом: на телефоне их четыре, и в строку
   они не помещаются. */
.share-card .buttons { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 14px; }

/* ── Витрина фильмов ───────────────────────────────────────────────
 *
 * Карточки в центре: сетка, что сама подбирает число столбцов под
 * ширину — на телефоне один, на широком экране несколько. */
.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 14px;
  align-content: start;
}
.film-card {
  background: var(--panel, #131a24);
  border: 1px solid var(--line, #1f2836);
  border-radius: 10px;
  padding: 14px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.film-card-name { font-weight: 600; }
.film-card-video video { width: 100%; border-radius: 8px; background: #000; }
.film-card-buttons { display: flex; flex-wrap: wrap; gap: 6px; margin-top: auto; }
.gallery-empty { grid-column: 1 / -1; }
/* Только что снятый фильм: строка над списком и рамка у карточки. */
.gallery-made {
  grid-column: 1 / -1;
  margin: 0;
  padding: 10px 14px;
  border: 1px solid var(--accent);
  border-radius: 6px;
  color: var(--text, inherit);
}
.film-card.fresh { outline: 2px solid var(--accent); outline-offset: 2px; }
/* hidden обязан прятать карточку, несмотря на display:flex выше. */
.film-card[hidden] { display: none; }
.how { margin: 0; padding-left: 20px; display: flex; flex-direction: column; gap: 6px; }
.film-card-poster {
  width: 100%;
  border-radius: 8px;
  display: block;
  cursor: pointer;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  background: #000;
}

/* Пошаговая памятка по сборке фильма — свёрнутый блок в студии/редакторе. */
.build-steps {
  margin: 0 0 14px;
  border: 1px solid #262e3a;
  border-radius: 10px;
  padding: 8px 12px;
  background: #161b23;
}
.build-steps > summary {
  cursor: pointer;
  font-weight: 600;
  color: #ff8a5c;
}
.build-steps ol.how {
  margin: 8px 0 2px;
}

/* ── Отметки на кадре ──────────────────────────────────────────────────
 *
 * Ряд инструментов под живым экраном; выбранный — с рамкой цвета
 * акцента. Набросок, пока тянут мышью, лежит ровно по кадру. */
.mark-tools {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  padding: 6px 10px;
  border-top: 1px solid var(--border);
}
.mark-tools .button.on { border-color: var(--accent); color: var(--accent); }
.mark-hint { font-size: 12px; color: var(--accent); flex-basis: 100%; }
.mark-ghost { position: absolute; pointer-events: none; overflow: visible; }
.marks-list { flex-direction: column; align-items: stretch; gap: 6px; }
.mark-row { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.mark-row input { flex: 1 1 120px; min-width: 0; }
.mark-row input.mark-time { flex: 0 0 64px; }
.mark-row input.mark-n { flex: 0 0 48px; }
.mark-row button { background: none; border: 0; color: var(--muted); cursor: pointer; font-size: 16px; }
.mark-row button:hover { color: var(--trouble); }
.marks-list, .mark-row { justify-content: flex-start; }
.marks-list > label { align-self: flex-start; }

/* Пустая сцена: две кнопки — «из списка слева» и «из каталога». */
.empty-ways { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; width: 100%; }
/* Левый список на миг подсвечивается — видно, куда смотреть. */
.tree.flash { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 8px; transition: outline-color .3s; }

/* «+» между плитками ленты: вставить сцену в это место.
 *
 * Узкая и приглушённая, чтобы лента оставалась лентой сцен, а не
 * рядом кнопок; ярче — под мышью. */
.tile-gap {
  flex: none;
  align-self: center;
  width: 18px;
  height: 44px;
  padding: 0;
  border: 1px dashed transparent;
  border-radius: 6px;
  background: none;
  color: var(--muted);
  font: inherit;
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
  opacity: 0.45;
}
.tile-gap:hover,
.tile-gap:focus-visible {
  opacity: 1;
  color: var(--accent);
  border-color: var(--accent);
}
.shot-move.first { margin-left: auto; }
.shot-insert + .shot-drop { margin-left: 8px !important; }

/* Выделенное и остальное: свечение, его цвет, прозрачность остального. */
.glow-line { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.glow-line input[type="color"] {
  width: 34px; height: 26px; padding: 0; border: 1px solid var(--border);
  border-radius: 6px; background: none; cursor: pointer;
}
.glow-line input[type="color"]:disabled { opacity: 0.35; cursor: default; }
.glow-line select { margin-left: 6px; }

/* Перестановка сцен: плитку тащат на место другой. */
.tile[draggable="true"] { cursor: grab; }
.tile.dragging { opacity: 0.4; }
.tile.drop-here { outline: 2px dashed var(--accent); outline-offset: 2px; }
.shot-move:disabled { opacity: 0.35; cursor: default; }

/* Открытая сцена — первой, сразу под экраном; свёрнутые — под ней, по
 * порядку. Владелец: строки прошлых сцен стояли НАД открытой и
 * отодвигали её настройки вниз. Порядок в фильме не меняется — это
 * только раскладка списка. */
.shots > .shot:not(.folded) { order: -1; }

/* Под выбором голоса: минут платного голоса не хватит этому фильму. */
#voice-cost.short { color: var(--trouble, #e5534b); font-weight: 600; }

/* Ссылка «своим голосом?» под выбором голоса. */
.own-voice-hint { display: block; color: var(--accent); text-decoration: underline; }

/* Цвет отметки в списке отметок сцены. */
.mark-colour { width: 30px; height: 24px; padding: 0; border: 1px solid var(--border); border-radius: 6px; background: none; cursor: pointer; }

/* Запись поворота части рукой (нажали номер точки). */
.turn-rec { color: #c62828; font-weight: 600; font-size: 13px; animation: turn-rec-blink 1.2s ease-in-out infinite; }
@keyframes turn-rec-blink { 50% { opacity: 0.45; } }

/* Нажимаемые номера точек поверх готового фильма и окно части. */
.dot-layer { position: absolute; inset: 0; pointer-events: none; }
.dot-hot {
  position: absolute; transform: translate(-50%, -50%); pointer-events: auto;
  min-width: 30px; height: 30px; padding: 0 6px; border-radius: 15px; border: 2px solid #fff;
  background: rgba(255, 209, 102, .92); color: #1b1b1b; font-weight: 700; font-size: 14px; cursor: pointer;
  box-shadow: 0 0 0 4px rgba(255, 209, 102, .35); animation: dot-hot-pulse 1.6s ease-in-out infinite;
}
@keyframes dot-hot-pulse { 50% { box-shadow: 0 0 0 9px rgba(255, 209, 102, .12); } }
.part-shade { position: fixed; inset: 0; z-index: 1000; background: rgba(0, 0, 0, .7); display: grid; place-items: center; padding: 16px; }
.part-frame { width: min(1100px, 100%); height: min(760px, 100%); border: 0; border-radius: 14px; background: #0e1319; }
.turn-modes { display: inline-flex; gap: 4px; }
.turn-modes .button.on { outline: 2px solid var(--accent); }
.turn-clock { font-variant-numeric: tabular-nums; color: #ffb4a8; font-size: 13px; }
.dot-row { position: absolute; pointer-events: auto; background: transparent; border: 0; border-radius: 6px; cursor: pointer; padding: 0; }
.dot-row:hover { background: rgba(255, 209, 102, .18); outline: 2px solid rgba(255, 209, 102, .8); }

/* Большой экран («⛶ Крупно») и ручка высоты экрана. */
.screen-grip { height: 8px; cursor: ns-resize; background: linear-gradient(var(--border), var(--border)) center / 48px 3px no-repeat; }
.screen-grip:hover { background-color: rgba(255, 255, 255, .04); }
.screen.big { position: fixed; inset: 8px; z-index: 900; margin: 0; display: flex; flex-direction: column; overflow: auto; }
.screen.big .screen-field { height: auto !important; flex: 1 1 auto; min-height: 50vh; }
.screen.big .screen-grip { display: none; }
body.screen-big-on { overflow: hidden; }

/* Свой рисунок («Мои 2D-рисунки») убирается крестиком прямо в списке */
.sheet { position: relative; }
.sheet-remove { position: absolute; top: 4px; right: 4px; border: 0; border-radius: 50%; width: 22px; height: 22px; line-height: 20px; padding: 0; background: rgba(0, 0, 0, 0.55); color: #fff; cursor: pointer; font-size: 15px; }
.sheet-remove:hover { background: #c0392b; }
.sheet-move { right: 30px; font-size: 11px; }

/* Расположение на экране (scene-layout.js) */
.scene-layout { margin: 8px 0; border: 1px solid var(--border); border-radius: var(--radius); padding: 6px 10px; }
.scene-layout summary { cursor: pointer; color: var(--muted); min-height: 32px; display: flex; align-items: center; gap: 6px; }
.layout-presets { display: grid; grid-template-columns: repeat(auto-fill, minmax(52px, 1fr)); gap: 6px; margin: 8px 0; }
.layout-preset { position: relative; aspect-ratio: 16 / 9; padding: 0; border: 1px solid var(--border); border-radius: 4px; background: var(--panel-2); cursor: pointer; }
.layout-preset:hover, .layout-preset.on { border-color: var(--accent); }
.layout-preset i { position: absolute; background: var(--muted); box-shadow: inset 0 0 0 1px var(--panel-2); }
.layout-preset i.t { background: var(--border); }
.layout-row { display: flex; align-items: center; gap: 6px; padding: 4px 6px; border-radius: 6px; cursor: pointer; }
.layout-row.on { background: var(--panel-2); }
.layout-row .grow { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.layout-row button { min-width: 30px; min-height: 30px; padding: 0 6px; }
.layout-detail { display: grid; gap: 6px; padding: 8px 6px; }
.layout-detail label { display: flex; align-items: center; gap: 8px; color: var(--muted); font-size: 13px; }
.layout-detail label > select, .layout-detail label > input[type="range"] { flex: 1; min-width: 0; }
.layout-detail textarea { width: 100%; min-height: 64px; }
.layout-detail input[type="color"] { width: 44px; height: 28px; padding: 0; flex: none; }
.layout-parts { max-height: 140px; overflow: auto; }
.layout-add { display: flex; flex-wrap: wrap; gap: 6px; padding: 6px 0; }
.layout-frames { position: absolute; z-index: 2; pointer-events: none; }
.layout-frame { position: absolute; border: 1px dashed rgba(255, 255, 255, 0.55); pointer-events: auto; cursor: move; touch-action: none; }
.layout-frame.on { border: 2px solid var(--accent); z-index: 1; }
.layout-handle { position: absolute; width: 14px; height: 14px; border-radius: 3px; background: var(--accent); touch-action: none; }
.layout-warn { color: var(--trouble); font-size: 13px; margin: 4px 0; }
.layout-how { color: var(--muted); font-size: 13px; margin: 4px 0; }
.layout-frame.over { background: rgba(255, 255, 255, 0.14); border: 2px solid var(--accent); }
.layout-empty { position: absolute; inset: 0; display: grid; place-items: center; padding: 18px; text-align: center; color: rgba(255, 255, 255, 0.7); font-size: 13px; line-height: 1.4; pointer-events: none; }
.layout-tools { position: absolute; top: 18px; left: 18px; display: flex; gap: 4px; z-index: 2; }
.layout-kind { min-width: 30px; min-height: 28px; padding: 0 6px; border: 1px solid rgba(255, 255, 255, 0.35); border-radius: 5px; background: rgba(15, 19, 25, 0.85); color: #fff; font-size: 13px; cursor: pointer; }
.layout-kind.on { background: var(--accent); border-color: var(--accent); }
.layout-inline { position: absolute; inset: 52px 18px 18px; width: auto; height: auto; resize: none; padding: 6px; border: 1px solid rgba(255, 255, 255, 0.35); border-radius: 5px; background: rgba(15, 19, 25, 0.94); color: #fff; font: inherit; font-size: 14px; }
.sheet-move:hover { background: var(--accent); }
.m-pk-card { position: relative; }
.m-pk-move { position: absolute; top: 4px; right: 4px; width: 32px; height: 32px; line-height: 32px; text-align: center; border-radius: 50%; background: rgba(0, 0, 0, 0.55); font-size: 14px; }
