/* =====================================================================
   ПЛЁНКА — видеоредактор, который не нужно изучать
   styles.css v1.0 — дизайн-система Modernist (Claude Design, «new design red 0.1»)

   Токены из Handoff Spec:
   — вся палитра через переменные, хексы в коде не пишем;
   — акцент #ec3013 ТОЛЬКО как метка выбора и первичное действие;
   — Archivo (или системный гротеск): 400 текст, 800 заголовки;
   — скругления: 16 превью, 10–12 карточки/кнопки, 8 дорожки, 99 пилюли;
   — глубина светлая: фон #f3f2f2, поверхность #eae9e9.
   ===================================================================== */

/* ---------- Шрифт: Inter Tight (локально, fonts/) ----------
   Archivo из макетов не содержит кириллицы — на русском интерфейсе он
   не работал бы. Inter Tight — ближайший по пластике плотный гротеск
   с полной кириллицей; вес 800 держит заголовки, как в макете. */

/* Узкий жирный гротеск для блоков поверх видео (b268): Oswald 700, OFL,
   только кириллица и латиница. */
@font-face {
  font-family: "Oswald";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/oswald-cyrillic-700-normal.woff2") format("woff2");
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: "Oswald";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/oswald-latin-700-normal.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Inter Tight";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/inter-tight-cyrillic-400-normal.woff2") format("woff2");
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: "Inter Tight";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/inter-tight-latin-400-normal.woff2") format("woff2");
}
@font-face {
  font-family: "Inter Tight";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("../fonts/inter-tight-cyrillic-500-normal.woff2") format("woff2");
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: "Inter Tight";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("../fonts/inter-tight-latin-500-normal.woff2") format("woff2");
}
@font-face {
  font-family: "Inter Tight";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("../fonts/inter-tight-cyrillic-600-normal.woff2") format("woff2");
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: "Inter Tight";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("../fonts/inter-tight-latin-600-normal.woff2") format("woff2");
}
@font-face {
  font-family: "Inter Tight";
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url("../fonts/inter-tight-cyrillic-800-normal.woff2") format("woff2");
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: "Inter Tight";
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url("../fonts/inter-tight-latin-800-normal.woff2") format("woff2");
}

:root {
  --color-bg: #f3f2f2;
  --color-surface: #eae9e9;
  --color-text: #201e1d;

  --color-accent: #ec3013;
  --color-accent-100: #fce4df;
  --color-accent-300: #f5a293;
  --color-accent-400: #f1755f;
  --color-accent-600: #c9280f;

  --color-neutral-100: #edecec;
  --color-neutral-200: #e2e0df;
  --color-neutral-300: #d4d1cf;
  --color-neutral-400: #b5b1ae;
  --color-neutral-600: #8a8683;
  --color-neutral-700: #6b6764;
  --color-neutral-800: #403d3b;
  --color-neutral-900: #262423;

  --font-heading: "Inter Tight", -apple-system, "Helvetica Neue", Arial, sans-serif;
  --font-heading-weight: 800;
  --font-body: "Inter Tight", -apple-system, "Helvetica Neue", Arial, sans-serif;

  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-6: 24px;
  --space-8: 32px;

  --radius-preview: 16px;
  --radius-card: 10px;
  --radius-control: 8px;  /* внутренние контролы: кнопки, поля, опции переключателя */
  --radius-track: 8px;
  --radius-chip: 6px;     /* образцы цвета, чертёж кадра */
  --radius-pill: 99px;

  --shadow-sm: 0 2px 8px rgba(32, 30, 29, 0.10);

  /* Словарь движения: три длительности и одна кривая на всё.
     Каждая отвечает за свой род движения, и новое значение по месту не
     заводится — берётся подходящее из этих трёх. */
  --dur: 160ms;        /* состояния интерфейса: наведение, нажатие, фокус,
                          появление накладок — всё, что отвечает руке */
  --dur-move: 420ms;   /* движение содержимого: заполнение кадра, переезд
                          сцены, разворот списка — едет вещь, а не состояние */
  --tip-out: 900ms;    /* уход накладок поверх кадра. Единственная асимметрия
                          в системе, и она осмысленная: подсказка уходит,
                          когда человек уже занят кадром. Это число читает
                          plenka.js, чтобы менять текст после того, как
                          старый догорел. */
  --ease: cubic-bezier(0.2, 0.7, 0.3, 1);

  /* геометрия ленты */
  --scrub-h: 34px;
  --video-h: 134px;   /* +42 от снятой дорожки МУЗЫКА: сцены крупнее, кадр читаемее */
  --au-h: 34px;
  --track-gap: 8px;
  --title-h: 24px;    /* дорожка ТЕКСТ: титру нужна только строка, не кадр */
  --gfx-h: 24px;      /* дорожка ГРАФИКА — такая же строка (b269) */

  /* совместимость с движком */
  --handle-w: 10px;
  --ui-opacity: 1;
}

/* ---------- База ---------- */

* { margin: 0; padding: 0; box-sizing: border-box; }
html, body { height: 100%; }

body {
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: 14px;
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.hidden { display: none !important; }

/* Полоса «не запомнится»: память браузера закрыта (страница открыта файлом,
   приватное окно). Заглушкой это состояние не закрываем никогда — смонтировать
   и скачать фильм здесь можно, отнимать это ради предупреждения нельзя.
   Правило живёт тут, а не в welcome.css: полоса стоит в редакторе, а он тот
   лист стилей не подключает. */
.warnbar {
  display: flex; align-items: center; gap: var(--space-3); height: 40px; padding: 0 var(--space-6);
  background: var(--color-neutral-200); border-bottom: 1px solid var(--color-neutral-300);
  font: 500 13px/1 var(--font-body); color: var(--color-neutral-800);
}
.warnbar-mark { flex: none; width: 3px; height: 16px; background: var(--color-accent); }
.warnbar-x {
  margin-left: auto; flex: none; width: 26px; height: 26px;
  display: flex; align-items: center; justify-content: center; color: var(--color-neutral-600);
}
.warnbar-x:hover { color: var(--color-text); }

:focus-visible { outline: 2px solid var(--color-text); outline-offset: 2px; }

button { font: inherit; color: inherit; background: none; border: none; cursor: pointer; }
button:disabled { opacity: 0.45; cursor: not-allowed; }

* { scrollbar-width: thin; scrollbar-color: var(--color-neutral-400) transparent; }
::-webkit-scrollbar { width: 9px; height: 9px; }
::-webkit-scrollbar-thumb { background: var(--color-neutral-400); border-radius: 5px; border: 2px solid transparent; background-clip: padding-box; }

/* ---------- Знак STYK ----------
   Слово STYK, где последняя буква собрана из двух фигур: красной стойки
   (вертикаль курсора с ленты) и чернильной развилки (треугольник острым
   углом влево, к стойке). Красный в имени один и стоит там же, где стоит в
   продукте. Всё считается от кегля, поэтому знак живёт на любом размере.
   Спецификация: docs/brand/ЛОГОТИП.md. */

.styk-logo { display: inline-flex; align-items: center; }
.styk-word {
  font: var(--font-heading-weight) 1em/1 var(--font-heading);
  letter-spacing: -0.03em;
  color: var(--color-text);
}
.styk-stem {
  flex: none;
  width: 0.17em; height: 0.72em;
  margin-left: 0.11em;
  background: var(--color-accent);
}
.styk-fork {
  flex: none;
  width: 0.35em; height: 0.72em;
  background: var(--color-text);
  clip-path: polygon(0 50%, 100% 0, 100% 100%);
}

/* Шапка продукта: буквы и развилка нейтральные, стойка красная */
.topbar .styk-logo .styk-word,
.topbar .styk-logo .styk-fork { color: var(--color-neutral-600); background: currentColor; }
.topbar .styk-logo .styk-word { background: none; }

/* Выворотка на чернильной плашке */
.styk-logo.on-ink .styk-word { color: var(--color-bg); }
.styk-logo.on-ink .styk-fork { background: var(--color-bg); }

/* Монохром: печать, водяные знаки */
.styk-logo.mono .styk-stem { background: var(--color-text); }

/* Неактивное */
.styk-logo.off .styk-word { color: var(--color-neutral-600); }
.styk-logo.off .styk-stem,
.styk-logo.off .styk-fork { background: var(--color-neutral-600); }

/* ---------- Шапка (64px) ---------- */

.topbar {
  flex: none;
  height: 64px;
  display: flex;
  align-items: center;
  gap: var(--space-4);
  padding: 0 var(--space-8);
  border-bottom: 1px solid var(--color-neutral-300);
  background: var(--color-bg);
}

.logo {
  font: var(--font-heading-weight) 15px/1 var(--font-heading);
  letter-spacing: 0.02em;
  color: var(--color-neutral-600);
}

.topbar-sep { width: 1px; height: 20px; background: var(--color-neutral-300); flex: none; }

/* На стартовом экране шапка отвечает только за продукт. Имя, формат, отмена
   и «Скачать результат» принадлежат проекту, которого ещё нет: раньше кнопка
   экспорта пряталась в бургере и её никто там не видел, а красной в шапке она
   предлагала бы скачать пустоту. Бургер остаётся — из него берут журнал. */
.topbar:has(~ .workspace > #editor.hidden) .project-name-wrap,
.topbar:has(~ .workspace > #editor.hidden) .topbar-sep,
.topbar:has(~ .workspace > #editor.hidden) #btn-undo,
.topbar:has(~ .workspace > #editor.hidden) #btn-redo,
.topbar:has(~ .workspace > #editor.hidden) #btn-export { display: none; }

.project-name-wrap { display: flex; align-items: center; gap: 8px; min-width: 0; }

.project-name {
  font: var(--font-heading-weight) 19px/1 var(--font-heading);
  letter-spacing: -0.02em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  cursor: text;
  padding: 4px 2px;
  border-radius: 6px;
}
.project-name:hover { background: var(--color-surface); }
.project-name[contenteditable="true"] { outline: 2px solid var(--color-text); outline-offset: 2px; background: #fff; }

.icon-plain { display: flex; color: var(--color-neutral-600); padding: 4px; border-radius: 6px; }
.icon-plain:hover { color: var(--color-text); background: var(--color-surface); }

.topbar-right { margin-left: auto; display: flex; align-items: center; gap: var(--space-4); }

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

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 9px 14px;
  border-radius: var(--radius-card);
  font-size: 13px;
  font-weight: 500;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease),
              box-shadow var(--dur) var(--ease), opacity var(--dur) var(--ease);
}

.btn-ghost { color: var(--color-text); }
.btn-ghost:hover:not(:disabled) { background: var(--color-surface); }
.btn-ghost:disabled { color: var(--color-neutral-600); }

.btn-secondary { background: var(--color-surface); color: var(--color-text); }
.btn-secondary:hover:not(:disabled) { background: var(--color-neutral-200); box-shadow: var(--shadow-sm); }
.btn-secondary:active:not(:disabled) { background: var(--color-neutral-300); }

.btn-primary { background: var(--color-accent); color: var(--color-bg); }
.btn-primary:hover:not(:disabled) { background: var(--color-accent-600); box-shadow: var(--shadow-sm); }

.btn-icon { width: 40px; height: 40px; padding: 0; }
.btn-wide { width: 100%; justify-content: space-between; padding: var(--space-3) var(--space-4); }

/* ---------- Бургер-меню ---------- */

.menu-wrap { position: relative; }

.menu-dropdown {
  position: absolute;
  right: 0;
  top: calc(100% + 8px);
  min-width: 230px;
  background: var(--color-bg);
  border: 1px solid var(--color-neutral-300);
  border-radius: 12px;
  box-shadow: 0 14px 36px -10px rgba(32, 30, 29, 0.28);
  padding: 6px;
  z-index: 60;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.menu-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 10px 12px;
  border-radius: 8px;
  font-size: 13px;
  text-align: left;
  color: var(--color-text);
}
.menu-item:hover:not(:disabled) { background: var(--color-surface); }

.menu-build {
  padding: 6px 12px 4px;
  border-top: 1px solid var(--color-neutral-200);
  margin-top: 4px;
  font: 400 10px/1 var(--font-body);
  letter-spacing: 0.06em;
  color: var(--color-neutral-400);
}

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

.workspace { flex: 1; display: flex; flex-direction: column; min-height: 0; }

/* ---------- Дропзона ---------- */

.dropzone {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: var(--space-6) var(--space-8);
  border-radius: var(--radius-preview);
  outline: 2px dashed var(--color-neutral-400);
  outline-offset: -2px;
  cursor: pointer;
  text-align: center;
  transition: background var(--dur) var(--ease), outline-color var(--dur) var(--ease);
}
.dropzone:hover { background: var(--color-surface); }
.dropzone.dragover { background: var(--color-neutral-200); outline-color: var(--color-text); }

.dropzone-inner { display: flex; flex-direction: column; align-items: center; max-width: 520px; padding: 24px; }
/* Марка над заголовком. Кегль — та же доля от заголовка, что на первой
   странице (44 при 68), чтобы марка везде была подчинена ему одинаково.
   Отступ снизу не меньше 0.72em: это охранное поле лого. */
.dropzone-icon { font-size: clamp(20px, 2.2vw, 26px); margin-bottom: var(--space-6); }

.dropzone h1 {
  font: var(--font-heading-weight) clamp(30px, 3.4vw, 40px)/1.02 var(--font-heading);
  letter-spacing: -0.04em;
  margin-bottom: var(--space-3);
  text-wrap: balance;
}

/* Пояснение под заголовком — это инструкция, а не мелкий шрифт для
   галочки: читаемый кегль и тёмный нейтральный, а не серая муть. */
.dz-sub {
  font-size: 16px;
  line-height: 1.35;
  color: var(--color-neutral-800);
  max-width: 400px;
  text-wrap: pretty;
  margin-bottom: var(--space-6);
}

/* Главное действие: одно, крупное, акцентом. Второго яркого пятна на
   экране нет — чтобы вопрос «куда жать» не возникал. */
.dz-cta {
  /* Воздух над кнопкой отделяет её от списка проектов; скругление — как у
     всех кнопок (--radius-card), а не пилюля: одна форма на все кнопки. */
  margin-top: var(--space-4);
  font-size: 15px;
  font-weight: 600;
  padding: 13px 26px;
  border-radius: var(--radius-card);
}

/* Черта «или» отделяет второй сценарий от первого */
.dz-or {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 240px;
  margin: var(--space-6) 0 var(--space-4);
  color: var(--color-neutral-600);
  font-size: 12px;
}
.dz-or::before, .dz-or::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--color-neutral-300);
}

.dz-second {
  font-size: 13px;
  color: var(--color-neutral-700);
  margin-bottom: var(--space-2);
}


.dropzone-note {
  margin-top: var(--space-8);
  font-size: 13px;
  color: var(--color-neutral-700);
  max-width: 380px;
  text-wrap: pretty;
}

.btn-pick-dz { margin-top: var(--space-2); font-size: 12px; padding: 6px 12px; }

.restore-box {
  margin-top: var(--space-6);
  padding: var(--space-4) var(--space-4);
  background: var(--color-bg);
  border: 1px solid var(--color-neutral-300);
  border-radius: 12px;
  box-shadow: var(--shadow-sm);
  cursor: default;
  text-align: left;
  display: inline-block;
}
.restore-title { font: var(--font-heading-weight) 14px/1.2 var(--font-heading); letter-spacing: -0.01em; margin-bottom: 4px; }
.restore-desc { font-size: 12px; color: var(--color-neutral-700); margin-bottom: var(--space-3); }
.restore-actions { display: flex; gap: 8px; }
.restore-actions .btn { background: var(--color-accent); color: var(--color-bg); }
.restore-actions .btn:hover { background: var(--color-accent-600); }
.restore-actions .btn-ghost { background: var(--color-surface); color: var(--color-text); }
.restore-actions .btn-ghost:hover { background: var(--color-neutral-200); }

/* ---------- Редактор: сетка ---------- */

.editor { flex: 1; display: flex; flex-direction: column; min-height: 0; }

.work-grid {
  flex: 1;
  min-height: 0;
  display: grid;
  /* левая колонка · превью (по центру) · резервная зона справа —
     оба края тянутся ползунками, у превью минимум 320px */
  grid-template-columns:
    minmax(300px, var(--left-w, clamp(300px, 30%, 460px)))
    0px
    minmax(320px, 1fr)
    0px
    minmax(16px, var(--right-w, clamp(280px, 30%, 460px)));
  position: relative;
}

.spare-col { min-width: 0; min-height: 0; }

/* Левая колонка */

.left-col {
  min-width: 0;
  min-height: 0;
  container-type: inline-size;
  display: flex;
  flex-direction: column;
  /* Отступы — из утверждённого макета: сверху 32, справа 24, слева 32.
     Снизу — страховочные 64 (b261): последним в колонке стоит блок ТЕКСТ,
     и с 24 его нижняя строка упиралась в край и читалась обрезанной. */
  padding: var(--space-8) var(--space-6) 64px var(--space-8);
  overflow-y: auto;
}

/* Содержимое колонки не растягивается бесконечно: даже если колонку
   растянули широко (чтобы ужать превью), кнопки и карточки держат
   комфортную ширину и прижаты к левому краю. */
.left-col > * {
  width: 100%;
  max-width: 440px;
}

.scene-head { display: flex; align-items: flex-start; gap: var(--space-4); min-width: 0; }

.scene-num {
  font-family: var(--font-heading);
  font-weight: var(--font-heading-weight);
  font-size: clamp(60px, 20cqw, 104px);
  line-height: 0.82;
  letter-spacing: -0.06em;
  flex: none;
}

.scene-head-side { display: flex; flex-direction: column; gap: 6px; padding-top: 8px; min-width: 0; }
.scene-of { font: var(--font-heading-weight) 12px/1 var(--font-heading); letter-spacing: 0.14em; color: var(--color-neutral-600); white-space: nowrap; }
.scene-range { font: 400 13px/1 var(--font-body); color: var(--color-neutral-700); font-variant-numeric: tabular-nums; white-space: nowrap; }


.icon-btn {
  width: 34px; height: 34px;
  display: grid; place-items: center;
  border-radius: 8px;
  background: var(--color-surface);
  color: var(--color-neutral-700);
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.icon-btn:hover:not(:disabled) { background: var(--color-neutral-200); color: var(--color-text); box-shadow: var(--shadow-sm); }

.scene-name {
  font-family: var(--font-heading);
  font-weight: var(--font-heading-weight);
  font-size: clamp(26px, 9cqw, 46px);
  line-height: 0.95;
  letter-spacing: -0.035em;
  margin: var(--space-3) 0 var(--space-6);
  text-wrap: balance;
  min-width: 0;
  overflow-wrap: anywhere;
  cursor: text;
  border-radius: 8px;
}
.scene-name:hover { background: var(--color-surface); }
.scene-name[contenteditable="true"] { outline: 2px solid var(--color-text); outline-offset: 2px; background: #fff; }

/* Карточки значений */

/* Плитка одна и во всю ширину. Сетка 2×2 вернётся сама, когда появится
   ВТОРАЯ работающая плитка: четыре тайла, из которых три не работали,
   читались как «тут я чего-то не умею», а не как план. */
.value-cards { display: grid; grid-template-columns: 1fr; gap: var(--space-2); }

.value-card {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-card);
  background: var(--color-surface);
  min-width: 0;
  text-align: left;
  transition: background var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.value-card:hover:not(:disabled) { background: var(--color-neutral-200); box-shadow: var(--shadow-sm); }

.vc-label { font: 400 11px/1 var(--font-body); letter-spacing: 0.1em; color: var(--color-neutral-700); }
.vc-row { display: flex; align-items: center; gap: 6px; color: var(--color-neutral-600); }
.vc-value { font: var(--font-heading-weight) 22px/1.1 var(--font-heading); letter-spacing: -0.01em; color: var(--color-text); font-variant-numeric: tabular-nums; }
.vc-row svg { margin-left: auto; flex: none; }

/* Кадрирование сцены — плитка-инструмент вместо строки-сообщения.
   Состояние кадра показывает сам блок, поэтому текстовая строка .frame-box
   из колонки убрана. */
.crop-card {
  display: flex;
  flex-direction: column;
  gap: 9px;
  margin-top: var(--space-2);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-card);
  background: var(--color-surface);
  text-align: left;
}
.crop-row { display: flex; align-items: center; gap: var(--space-3); }

/* Чертёж кадра, в оттенках серого: светлый прямоугольник — картинка, серые
   полосы по краям — поля. Полосы горизонтальные или вертикальные — смотря с
   какой стороны поля у этой сцены; у заполненной их нет вовсе. */
.crop-fig {
  position: relative;
  flex: none;
  width: 52px; height: 32px;
  border-radius: 6px;
  overflow: hidden;
  background: var(--color-neutral-300);
}
.crop-fig::before, .crop-fig::after { content: ""; position: absolute; background: var(--color-neutral-600); }
.crop-fig-h::before { left: 0; right: 0; top: 0; height: 7px; }
.crop-fig-h::after { left: 0; right: 0; bottom: 0; height: 7px; }
.crop-fig-v::before { top: 0; bottom: 0; left: 0; width: 9px; }
.crop-fig-v::after { top: 0; bottom: 0; right: 0; width: 9px; }
.crop-fig-full::before, .crop-fig-full::after { content: none; }

.crop-body { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.crop-value { font: var(--font-heading-weight) 15px/1.1 var(--font-heading); color: var(--color-text); }
.crop-note { font: 400 12px/1.35 var(--font-body); color: var(--color-neutral-700); }

/* Действие в плитке — лёгкая кнопка, а не подчёркнутое слово: подчёркивание
   читается внутри фразы, а здесь действие стоит отдельно, и опознавать его
   надо по форме. Вид взят у кнопок зума: светлая заливка на серой плитке и
   кольцо в 1px внутрь. Красного нет — это не главное действие экрана. */
.crop-btn {
  flex: none;
  margin-left: auto;
  padding: 7px 12px;
  border-radius: 8px;
  background: var(--color-bg);
  color: var(--color-text);
  font: 500 12px/1 var(--font-body);
  box-shadow: inset 0 0 0 1px var(--color-neutral-300);
  transition: box-shadow var(--dur) var(--ease), background var(--dur) var(--ease);
}
.crop-btn:hover { box-shadow: inset 0 0 0 1px var(--color-neutral-400); }
.crop-btn:active { background: var(--color-neutral-200); }

/* Строка о файлах */

/* Ритм колонки: шаг между блоками 12 px, и задан он ВЕРХНИМ полем у каждого.
   В колонке flex, поля соседей не схлопываются — если задавать и сверху, и
   снизу, между блоками получится 24, а под скрытым блоком повиснет лишнее. */
.file-info { margin-top: var(--space-3); }
.file-info:empty { display: none; }

/* Вариант 1b Claude Design: список свёрнут в одну строку. Цветные метки
   показывают, сколько файлов и какого цвета, рядом счёт и вес. Разворот
   по клику — при двадцати файлах колонка, которая принадлежит выбранной
   сцене, иначе превращается в реестр. Свёрнуто — 56px вместо 260. */
.fi-toggle {
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 0;
  padding: 11px 12px;
  border-radius: var(--radius-card);
  background: var(--color-surface);
  text-align: left;
  transition: background var(--dur) var(--ease);
}
.fi-toggle:hover { background: var(--color-neutral-200); }

.fi-toggle-row { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-3); }
.fi-count { font: 600 13px/1 var(--font-body); color: var(--color-text); }
.fi-meta {
  display: flex;
  align-items: center;
  gap: 4px;
  font: 400 12px/1 var(--font-body);
  color: var(--color-neutral-600);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.fi-chev { flex: none; transition: transform var(--dur) var(--ease); }
.file-info.expanded .fi-chev { transform: rotate(180deg); }

.fi-list { display: none; margin-top: var(--space-4); }
.file-info.expanded .fi-list { display: block; }

.fi-row {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
  padding: 8px 0;
  border-bottom: 1px solid var(--color-neutral-200);
}

/* Метка-полоска вместо кружка: тот же цвет, что у сцены на ленте */
.fi-name {
  flex: 1;
  min-width: 0;
  font: 400 13px/1.3 var(--font-body);
  color: var(--color-text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  cursor: default;
}
.fi-file { display: none; }
.file-info.names-original .fi-label { display: none; }
.file-info.names-original .fi-file { display: inline; }

/* Сцены отдают место имени первыми: их можно дочитать на ленте */
.fi-scenes {
  flex: 0 1 auto;
  min-width: 0;
  font: 400 12px/1.3 var(--font-body);
  color: var(--color-neutral-600);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  font-variant-numeric: tabular-nums;
}

.fi-names {
  margin-top: var(--space-3);
  font: 400 12px/1.3 var(--font-body);
  color: var(--color-neutral-600);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: var(--color-neutral-400);
}
.fi-names:hover { color: var(--color-text); text-decoration-color: var(--color-neutral-600); }
.fi-names-b { display: none; }
.file-info.names-original .fi-names-a { display: none; }
.file-info.names-original .fi-names-b { display: inline; }

.fi-dur {
  flex: none;
  font: 400 12px/1.3 var(--font-body);
  color: var(--color-neutral-700);
  font-variant-numeric: tabular-nums;
}

.tip {
  position: fixed;
  z-index: 60;
  max-width: 380px;
  padding: 7px 10px;
  border-radius: 8px;
  background: var(--color-neutral-900);
  color: var(--color-bg);
  font: 400 12px/1.35 var(--font-body);
  overflow-wrap: anywhere;
  box-shadow: var(--shadow-sm);
  pointer-events: none;
}
.tip.hidden { display: none; }

/* Разделитель колонок */

.col-splitter {
  position: relative;
  width: 0;
  cursor: col-resize;
  z-index: 5;
}
.col-splitter::before {
  content: "";
  position: absolute;
  top: 0; bottom: 0;
  left: -6px; right: -6px;
}
.col-splitter::after {
  content: "";
  position: absolute;
  top: 0; bottom: 0;
  left: -0.5px;
  width: 1px;
  background: var(--color-neutral-300);
}
.col-splitter-grip {
  position: absolute;
  left: -2.5px;
  top: 50%;
  transform: translateY(-50%);
  width: 5px; height: 56px;
  border-radius: var(--radius-pill);
  background: var(--color-neutral-400);
  transition: background var(--dur) var(--ease), height var(--dur) var(--ease);
}
.col-splitter:hover .col-splitter-grip { background: var(--color-neutral-600); height: 72px; }
.col-splitter.dragging .col-splitter-grip { background: var(--color-text); height: 84px; }

/* Правая колонка: превью */

.right-col {
  min-width: 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  padding: var(--space-6) var(--space-6) var(--space-4);
  container-type: inline-size;
}

/* Поле превью — это вся свободная площадь, но фона у неё нет: тёмный
   прямоугольник теперь и есть сам кадр. Размер кадра считается так, чтобы
   он вписался в площадь СРАЗУ ПО ОБЕИМ сторонам — иначе в высокой колонке
   кадр упирается в ширину, а сверху и снизу остаётся чернота (ровно это и
   вышло в первом заходе, b54). Пропорцию и натуральную ширину даёт оболочка
   в --video-ar и --video-w. */
.player-wrap {
  position: relative;
  flex: 1;
  min-height: 120px;
  display: flex;
  align-items: center;
  justify-content: center;
  container-type: size;
  /* Ширина КАДРА ФИЛЬМА. Ею пользуются и рамка, и подсказка поверх неё:
     держать две копии одной формулы нельзя, разъедутся при первой правке. */
  --video-box-w: min(100cqw, calc(100cqh * var(--video-ar, 1.7778)), var(--video-w, 100cqw));
  --frame-h: calc(var(--video-box-w) / var(--video-ar, 1.7778));
  /* Пропорция коробки видео СЕЙЧАС. Пока сцена не заполняет кадр — её
     собственная: тогда «cover» ничего не режет и видно всё. Заполнили —
     пропорция фильма, и «cover» обрезает лишнее. Между этими двумя
     значениями коробка едет плавно, и картинка на глазах съедает поля. */
  --ar-now: var(--scene-ar, var(--video-ar, 1.7778));
  /* Насколько рамка отстоит от краёв поля превью. Всё, что лежит поверх
     кадра, привязывается к РАМКЕ, а не к полю: поле больше неё и по бокам,
     и по высоте. Считаем один раз здесь. */
  --frame-inset-y: calc((100cqh - var(--frame-h)) / 2);
  --frame-inset-x: calc((100cqw - var(--video-box-w)) / 2);
}
.player-wrap.fill-frame { --ar-now: var(--video-ar, 1.7778); }

/* Кадр фильма — отдельной подложкой позади картинки. Раньше поля рисовал
   фон самого видео, но теперь его коробка меняет размер, и фон уезжал бы
   вместе с ней. Рамка же обязана стоять: картинка растёт ВНУТРИ неё. */
.player-wrap::before {
  content: "";
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: var(--video-box-w);
  aspect-ratio: var(--video-ar, 1.7778);
  background: var(--color-neutral-900);
  border-radius: var(--radius-preview);
  z-index: 0;
}
/* Кадр вписывается в поле по обеим сторонам: ширина не больше поля
   (100cqw) и не больше того, что позволяет высота (100cqh × пропорция).
   Скругление и тёмный фон — на самом кадре: чёрных полей вокруг больше нет.
   Фон всё же нужен — под ним первый кадр до загрузки и полосы у ролика,
   чья пропорция не совпала с проектом (в экспорте он тоже ляжет с полями). */
/* Коробка кадра. Размеры и скругление — здесь, потому что именно она теперь
   рамка фильма; она же и обрезает увеличенную картинку. */
.frame-clip {
  position: relative;
  z-index: 1;
  overflow: hidden;
  aspect-ratio: var(--ar-now);
  width: min(var(--video-box-w), calc(var(--frame-h) * var(--ar-now)));
  background: var(--color-neutral-900);
  border-radius: var(--radius-preview);
}

/* Слой титров лежит ровно на кадре фильма и ничего не ловит: правят их
   в своей плашке, а не тыканьем в букву. */
.frame-text {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 2;
  pointer-events: none;
}

.player-wrap video {
  display: block;
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  /* «cover» стоит ВСЕГДА: режет он или нет, решает пропорция коробки. Пока
     она равна пропорции сцены — не режет ничего. Так переход становится
     обычным изменением размера, а его браузер умеет тянуть плавно —
     в отличие от самого object-fit, который переключается рывком. */
  object-fit: cover;
  object-position: var(--video-pos-x, 50%) var(--video-pos-y, 50%);
  /* Масштаб кадра. Сдвиг перед ним не случайный: он ровно тот, при котором
     итог совпадает с формулой экспорта (кадр − картинка)·доля. Проверено
     числами — см. ROADMAP v4.53. */
  transform-origin: 0 0;
  transform: translate(calc((1 - var(--zoom, 1)) * var(--pos-fx, 0.5) * 100%),
                       calc((1 - var(--zoom, 1)) * var(--pos-fy, 0.5) * 100%))
             scale(var(--zoom, 1));
}

/* Переход включается ТОЛЬКО на время нажатия «заполнить» / «вернуть».
   Постоянный он быть не может: у сцен разные пропорции, и при обычной смене
   сцены — щелчком по ленте или просто при воспроизведении на стыке — превью
   принималось бы «дышать» на каждом переходе.

   object-position едет вместе с размером: без него «вернуть» после того, как
   картинку подвинули, читалось как рывок — коробка ехала плавно, а смещение
   сбрасывалось в центр мгновенно. */
.player-wrap.filling .frame-clip {
  transition: width var(--dur-move) var(--ease),
              aspect-ratio var(--dur-move) var(--ease);
}
.player-wrap.filling video {
  transition: object-position var(--dur-move) var(--ease);
}

/* Пока картинку тянут — переход снимаем: он бы догонял руку с задержкой.
   Правило стоит ПОСЛЕ «filling», чтобы выигрывать при равной силе. */
.player-wrap.dragging video { transition: none; }

/* «Оригинал» (по умолчанию) — кадр не раздувается больше своего размера:
   ролик 640×360 на большом мониторе останется маленьким.
   «На всё поле» — снимаем этот потолок, кадр занимает всю площадь.
   Ни в том, ни в другом случае ничего не обрезается. */
.player-wrap.fill { --video-box-w: min(100cqw, calc(100cqh * var(--video-ar, 1.7778))); }
.player-wrap.fill video {
  width: min(var(--video-box-w), calc(var(--frame-h) * var(--ar-now)));
}

/* Тот же сегментный переключатель, что и «формат кадра» в строке
   просмотра: светлая подложка, карточный радиус, выбранное — акцентом.
   Тёмная полупрозрачная плашка выглядела деталью из чужого интерфейса. */
.fit-toggle {
  position: absolute;
  top: var(--space-3); right: var(--space-3);
  z-index: 3;
  display: flex;
  gap: 4px;
  padding: 4px;
  border-radius: var(--radius-card);
  background: var(--color-surface);
  box-shadow: var(--shadow-sm);
  opacity: 0;
  transition: opacity var(--dur) var(--ease);
}
.player-wrap:hover .fit-toggle,
.fit-toggle:focus-within { opacity: 1; }

/* Подсказка о полях — поверх кадра, внизу. Она про то, что человек видит
   прямо сейчас: полосы по краям, а после «заполнить» — что картинку можно
   двигать. В колонке та же мысль остаётся, поэтому подсказку можно закрыть
   навсегда, ничего не потеряв.

   Без плашки и без подложки: поверх кадра любая подложка выглядит вырезанным
   куском интерфейса и закрывает картинку. Читаемость держим тем же приёмом,
   что и номер сцены на ленте, — белым по тени. Тень двойная: короткая даёт
   контур на светлом кадре, длинная и мягкая притемняет пятно под текстом на
   пёстром. */
.frame-tip {
  position: absolute;
  left: 50%;
  bottom: calc(var(--frame-inset-y) + var(--space-4));
  transform: translateX(-50%);
  z-index: 4;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  max-width: calc(100% - var(--space-8));
  color: #fff;
  /* Тень осталась страховкой: подложка снимает основную задачу, но у самого
     края кадра градиент почти прозрачен. */
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.55);
  font-size: 13px;
  line-height: 1.35;
  /* Появляется быстро, уходит НЕ спеша. Медленное исчезновение — общее
     правило для этой подсказки, а не приём одного случая: она уходит, пока
     человек уже занят кадром, и на краю зрения быстрое исчезновение
     читается как мигание. Поэтому растворяются ВСЕ её уходы — и по крестику,
     и при захвате картинки, и при переходе на сцену без полей. */
  transition: opacity var(--dur) var(--ease);
}

/* Прячем прозрачностью, а видимость снимаем ПОСЛЕ того, как она догорела.
   Состояние своё (`off`), а не общее `.hidden`: у того `display: none
   !important`, и никакое затухание его не перебьёт — элемент просто
   выключается на первом кадре.
   `fading` — тот же уход, но не насовсем: под ним меняется текст, и подсказка
   возвращается уже с новым. Смена на месте читалась бы как опечатка, а не
   как ответ на нажатие. */
.frame-tip.off,
.frame-tip.fading,
.player-wrap.dragging .frame-tip {
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--tip-out) var(--ease), visibility 0s var(--tip-out);
}
.frame-tip.off { visibility: hidden; }

/* Еле заметная подложка под подсказкой: градиент снизу вверх по нижнему краю
   КАДРА. Нужна потому, что подобрать цвет текста по картинке нельзя — под
   узкой полосой внизу бывает что угодно, и кадр к тому же меняется на ходу.
   Градиент решает это раз и навсегда: белый текст читается на любом кадре, а
   сам он в глаза не бросается и не выглядит плашкой.
   Появляется только когда есть что читать, и уходит вместе с подсказкой —
   поэтому привязан к её состоянию, без единой строки JS. */
.player-wrap::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: var(--frame-inset-y);
  transform: translateX(-50%);
  width: var(--video-box-w);
  height: 96px;
  max-height: calc(var(--frame-h) / 2);
  border-radius: 0 0 var(--radius-preview) var(--radius-preview);
  background: linear-gradient(to top, rgba(0, 0, 0, 0.42), rgba(0, 0, 0, 0));
  opacity: 0;
  pointer-events: none;
  z-index: 3;
  transition: opacity var(--tip-out) var(--ease);
}
.player-wrap:not(.dragging):has(.frame-tip:not(.off))::after {
  opacity: 1;
  transition: opacity var(--dur) var(--ease);
}

/* Значок «сцена растянута, картинку можно двигать». Тонкий и в углу: он не
   объясняет, а напоминает — подсказка словами уходит навсегда после первого
   же перетаскивания, а признак того, что картинка живая, остаться должен.
   Живёт по тем же правилам, что и подсказка: цвет по фону, уход плавный,
   на время перетаскивания убирается с глаз. */
.frame-move {
  position: absolute;
  left: calc(var(--frame-inset-x) + var(--space-4));
  bottom: calc(var(--frame-inset-y) + var(--space-4));
  z-index: 4;
  display: grid;
  place-items: center;
  color: #fff;
  opacity: 0.75;
  filter: drop-shadow(0 0 1px rgba(0, 0, 0, 0.55)) drop-shadow(0 1px 3px rgba(0, 0, 0, 0.7));
  /* События оставляем: без них не покажется подпись по наведению. Тянуть
     от самого значка при этом можно — жест начинается на кадре, а значок в
     список накладок-исключений не входит, поэтому курсор повторяет кадр. */
  cursor: grab;
  transition: opacity var(--dur) var(--ease);
}
.player-wrap.dragging .frame-move { cursor: grabbing; }

/* Значок показывает ТУ ОСЬ, по которой двигать и правда можно. Сцена шире
   кадра — лишнее уходит вбок, значит стрелки в стороны (так нарисовано);
   уже кадра — лишнее сверху и снизу, тот же значок поворачивается.
   Поворот — состояние, а не движение, поэтому без перехода. */
.frame-move.axis-y svg { transform: rotate(90deg); }
.frame-move.off,
.player-wrap.dragging .frame-move {
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--tip-out) var(--ease), visibility 0s var(--tip-out);
}
.frame-move.off { visibility: hidden; }

/* Действие — тоже текстом. Красный тут не нужен: на кадре он спорил бы с
   курсором, и вообще подсказка поверх видео не место для яркого пятна.
   Отличаем действие подчёркиванием, как и в колонке. */
.frame-tip-do,
.frame-tip-x {
  flex: none;
  color: #fff;
  text-shadow: inherit;
  border: 1px solid rgba(255, 255, 255, 0.55);
  border-radius: 6px;
  /* Своя тень: белая обводка по белому кадру исчезала бы вовсе. */
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.45);
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.frame-tip-do {
  padding: 4px 10px;
  font: 500 13px/1.35 var(--font-body);
}
.frame-tip-x {
  width: 24px; height: 24px;
  display: grid; place-items: center;
}
.frame-tip-do:hover,
.frame-tip-x:hover { border-color: #fff; background: rgba(255, 255, 255, 0.14); }

/* Под текстом светлая картинка — переворачиваем пару «цвет + тень». Светлым
   или тёмным считаем по тону, уже снятому с первого кадра этой сцены: ещё
   раз щупать картинку не нужно. На чёрной полосе (сцена шире кадра) этот
   класс не ставится вовсе — там белый прав всегда. */
/* Узкий кадр: текст переносим, действие и крестик держим в строке */
@container (max-width: 460px) {
  .frame-tip { flex-wrap: wrap; justify-content: center; text-align: center; }
}

/* Выбранное — светлой плашкой с тенью, без акцента: красный в системе
   принадлежит выбору сцены и первичному действию, а это служебный
   переключатель, к которому обращаются редко. */
.fit-btn {
  padding: 7px 12px;
  border-radius: 8px;
  font: 500 12px/1 var(--font-body);
  color: var(--color-neutral-600);
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.fit-btn:hover:not(.on) { color: var(--color-text); }
.fit-btn.on {
  background: var(--color-bg);
  color: var(--color-text);
  box-shadow: var(--shadow-sm);
}
/* Перебивка лежит поверх основного кадра в той же коробке */
.player-wrap video.overlay-video { z-index: 2; }
.player-wrap video.hidden { display: none !important; }

/* Строка просмотра */

.view-row { flex: none; display: flex; align-items: center; gap: var(--space-4); }

.play-btn {
  width: 56px; height: 56px;
  flex: none;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--color-accent);
  color: var(--color-bg);
  transition: background var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.play-btn:hover { background: var(--color-accent-600); transform: scale(1.04); }
.play-btn:active { transform: scale(0.97); }
/* Треугольник уже нарисован со сдвигом вправо: его рамка стоит на 2 px
   правее середины, а вот центр тяжести — ровно в середине, и глаз считает
   центром именно его. Сверху на это накладывался ещё padding-left: 3px, и
   поправка выходила двойной — значок заметно уезжал вправо. Паузе поправка
   не нужна вовсе, поэтому у неё она и снималась, и стояла она ровно.
   Теперь ничего не двигаем: центр тяжести треугольника отстоит от середины
   кнопки на 0,06 px. */
.play-btn .ic-pause { display: none; }
.play-btn.playing .ic-play { display: none; }
.play-btn.playing .ic-pause { display: block; }

.seek-wrap { flex: 1; display: flex; flex-direction: column; gap: 9px; min-width: 130px; }
.seek-labels {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  font-variant-numeric: tabular-nums;
}

/* 800-й вес Inter Tight в цифрах тяжелее, чем Archivo в макетах, поэтому
   600 и лёгкий трекинг. Сотые меняются каждый кадр — они на ступень
   серее, чтобы не мельтешить рядом с секундами. */
.tc-cur {
  font: 600 15px/1 var(--font-heading);
  letter-spacing: 0.01em;
  color: var(--color-text);
}
.tc-frac { color: var(--color-neutral-600); }
/* Длина секвенции — тем же кеглем, что и позиция, только серым: на 12px
   она читалась как сноска и терялась. */
.tc-total {
  font: 600 15px/1 var(--font-heading);
  letter-spacing: 0.01em;
  color: var(--color-neutral-600);
}

.seek-track {
  position: relative;
  height: 8px;
  background: var(--color-neutral-300);
  border-radius: var(--radius-pill);
  cursor: pointer;
}
.seek-fill {
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 0;
  background: var(--color-accent);
  border-radius: var(--radius-pill);
}
.seek-knob {
  position: absolute;
  left: 0%;
  top: 50%;
  width: 22px; height: 22px;
  margin-left: -11px;
  transform: translateY(-50%);
  border-radius: 50%;
  background: var(--color-accent);
  border: 4px solid var(--color-bg);
  box-shadow: var(--shadow-sm);
}


/* Узкое превью: фигуры формата прячутся, полосе просмотра — всё место */
@container (max-width: 560px) {
}

/* ---------- Рабочая полоса ----------
   Глаголы к выбранной сцене или к позиции курсора. Стоит между превью и
   лентой: и то и другое рядом, рука не уходит с середины экрана.
   Неприменимый инструмент из полосы ИСЧЕЗАЕТ, а не гаснет — на экране нет
   выключенного, а гаснущая кнопка вдобавок сдвигала бы группу, стоящую по
   центру. */

.toolstrip {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  height: 48px;
  padding: 0 var(--space-8);
  background: var(--color-bg);
  border-top: 1px solid var(--color-neutral-300);
}

.tool-btn {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 34px;
  padding: 0 12px;
  border-radius: var(--radius-card);
  color: var(--color-neutral-700);
  font: 500 13px/1 var(--font-body);
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.tool-btn:hover { background: var(--color-surface); color: var(--color-text); }
.tool-btn:active { background: var(--color-neutral-200); }
.tool-btn svg { flex: none; }

.tool-sep { flex: none; width: 1px; height: 20px; background: var(--color-neutral-300); }

/* Окно вопроса: та же карточка, что у экспорта, только уже — текста немного */
.ask-card { max-width: 420px; }
.ask-text { white-space: pre-line; }
/* Указка «смотри сюда»: одна рамка поверх всего, красный пунктир бежит по
   кругу вокруг места, где лежит следующий шаг, когда он не под рукой.
   Единственное непрерывное движение в продукте; период взят из словаря
   (--tip-out), а не придуман. Ниже модальных окон: в окне и так одно. */
.guide {
  position: fixed; left: 0; top: 0; width: 100%; height: 100%;
  pointer-events: none; z-index: 55; overflow: visible;
  /* Уходит плавно, как всё, что лежит поверх кадра (b263): --tip-out, не --dur. */
  transition: opacity var(--tip-out) var(--ease);
}
.guide.off { opacity: 0; }
.guide rect {
  fill: none; stroke: var(--color-accent); stroke-width: 2;
  /* Не в полную силу: указка подсказывает, а не кричит; в полную силу
     красный спорил с главным действием экрана (b250). */
  stroke-opacity: 0.7;
  stroke-dasharray: 7 6; stroke-linecap: round;
  /* Пунктир бежит и мягко дышит (b261, b263): от невидимого до 0.7 и обратно.
     Период дыхания — два --tip-out: это не переход, а цикл, и короче он
     читался бы как мигание. */
  animation: guide-run var(--tip-out) linear infinite,
             guide-pulse calc(var(--tip-out) * 2) ease-in-out infinite;
}
@keyframes guide-run { to { stroke-dashoffset: -13; } }
@keyframes guide-pulse { 0%, 100% { stroke-opacity: 0; } 50% { stroke-opacity: 0.7; } }
@media (prefers-reduced-motion: reduce) { .guide rect { animation: none; } }
/* Состояние выключателя в меню — справа, вторым цветом */
.menu-state { margin-left: auto; font-size: 11px; color: var(--color-neutral-600); }
/* Подпись — своей строкой, переключатель и счётчик — второй: в ширину карточки
   (420) все три в ряд не встают, и перенос был бы случайным, а не задуманным. */
.subs-opts { display: flex; align-items: center; gap: 8px 10px; flex-wrap: wrap; }
.subs-opts-label { flex-basis: 100%; font: 500 12px/1 var(--font-body); color: var(--color-neutral-700); }
/* Карточка окна сама цвета --color-bg, поэтому подложка переключателя здесь
   на ступень темнее (--color-surface) — иначе она сливается с карточкой. */
.ask-seg { display: flex; gap: 2px; padding: 3px; border-radius: 9px; background: var(--color-surface); }
.ask-seg-btn {
  height: 24px; padding: 0 10px; border-radius: 6px;
  color: var(--color-neutral-600);
  font: 500 12px/1 var(--font-body); white-space: nowrap;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.ask-seg-btn:hover:not(.on) { color: var(--color-text); }
.ask-seg-btn.on { background: var(--color-neutral-200); color: var(--color-text); }
.ask-step { display: flex; align-items: center; gap: 2px; padding: 3px; border-radius: 9px; background: var(--color-surface); }
.ask-step-btn {
  width: 24px; height: 24px; border-radius: 6px;
  color: var(--color-neutral-700); font: 500 14px/1 var(--font-body);
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.ask-step-btn:hover { background: var(--color-neutral-200); color: var(--color-text); }
.ask-step-num { min-width: 74px; text-align: center; font: 500 12px/1 var(--font-body); color: var(--color-text); }
/* Вторая настройка — своей парой строк «подпись / переключатель», как первая */
.subs-opts-row { flex-basis: 100%; display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; }
/* Пока идёт распознавание, кнопка становится «Стоп» и отмечена акцентом:
   это единственный способ прервать пятиминутный счёт, и он должен быть виден. */
.tool-btn.busy { color: var(--color-accent); }

/* ---------- Панель текста в колонке (макет «Титры в колонке v2», 3a) ----------
   Классы ttl-* перенесены из макета; отступы, кегли и подложки — оттуда же. */
.ttl-label { font: 400 11px/1 var(--font-body); letter-spacing: 0.1em; color: var(--color-neutral-700); text-transform: uppercase; }
.ttl-card {
  display: flex; flex-direction: column; gap: var(--space-3);
  padding: var(--space-4); border-radius: var(--radius-card); background: var(--color-surface);
}
/* Поле — белая «бумага» с кольцом; растёт до четырёх строк, дальше прокрутка */
.ttl-input {
  display: block; width: 100%; box-sizing: border-box;
  padding: 12px 14px; border: 0; border-radius: 8px;
  background: var(--color-bg); box-shadow: inset 0 0 0 1px var(--color-neutral-300);
  font: 400 15px/1.35 var(--font-body); color: var(--color-text);
  /* Высота — от текста, без прокрутки и потолка (b259): поле растёт, сколько
     строк ни набери. field-sizing считает это сам; где его нет — growInput. */
  resize: none; overflow: hidden; field-sizing: content;
  transition: box-shadow var(--dur) var(--ease);
}
.ttl-input:focus { outline: none; box-shadow: inset 0 0 0 1px var(--color-neutral-800); }
.ttl-input::placeholder { color: var(--color-neutral-600); }
/* Стили — переключатель; в карточке корпус на ступень темнее карточки */
.ttl-seg { display: flex; flex-wrap: wrap; gap: 4px; padding: 4px; border-radius: var(--radius-card); background: var(--color-neutral-200); }
.ttl-seg-opt {
  position: relative; flex: 1 1 auto; padding: 8px 6px; border-radius: 8px;
  font: 500 12px/1 var(--font-body); color: var(--color-neutral-600); text-align: center; white-space: nowrap;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.ttl-seg-opt:hover:not(.on) { color: var(--color-text); }
.ttl-seg-opt.on { background: var(--color-bg); color: var(--color-text); box-shadow: var(--shadow-sm); }
.ttl-seg-opt.saved { padding-right: 18px; }
.ttl-seg-x {
  position: absolute; right: 4px; top: 50%; transform: translateY(-50%);
  width: 12px; height: 12px; font: 500 11px/12px var(--font-body);
  opacity: 0; transition: opacity var(--dur) var(--ease);
}
.ttl-seg-opt.saved:hover .ttl-seg-x { opacity: 0.85; }
/* Ряды «подпись — контрол»: подпись в колонке 64px, контролы с одной вертикали */
.ttl-rows { display: flex; flex-direction: column; }
.ttl-row { display: grid; grid-template-columns: 64px 1fr; align-items: center; min-height: 36px; gap: 10px; }
.ttl-align { display: flex; gap: 2px; padding: 3px; border-radius: 8px; background: var(--color-neutral-200); width: max-content; }
.ttl-align button {
  display: grid; place-items: center; width: 30px; height: 26px; border-radius: 6px;
  color: var(--color-neutral-600);
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.ttl-align button:hover:not(.on) { color: var(--color-text); }
.ttl-align button.on { background: var(--color-bg); color: var(--color-text); box-shadow: var(--shadow-sm); }
/* Шрифт — кнопка с именем и шевроном; select внутри без своей рамки */
.ttl-font {
  display: inline-flex; align-items: center; gap: 6px; width: max-content; height: 30px; padding: 0 10px;
  border-radius: 8px; background: var(--color-bg); box-shadow: inset 0 0 0 1px var(--color-neutral-300);
  color: var(--color-text); cursor: pointer;
  transition: box-shadow var(--dur) var(--ease);
}
.ttl-font:hover { box-shadow: inset 0 0 0 1px var(--color-neutral-400); }
.ttl-font svg { color: var(--color-neutral-600); flex: none; pointer-events: none; }
.ttl-font-select { appearance: none; -webkit-appearance: none; border: 0; background: transparent; padding: 0; font: 500 13px/1 var(--font-body); color: inherit; cursor: pointer; }
.ttl-font-select:focus { outline: none; }
/* Ползунки — как зум на ленте: дорожка, заливка, ручка (.zs-fill/.zs-knob общие) */
.ttl-slide-row { display: flex; align-items: center; gap: 12px; }
.ttl-slider { position: relative; flex: 1; height: 4px; border-radius: var(--radius-pill); background: var(--color-neutral-300); cursor: pointer; touch-action: none; }
.ttl-slider:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--color-surface), 0 0 0 3px var(--color-neutral-800); }
.ttl-slider:hover .zs-knob { transform: translateY(-50%) scale(1.14); }
.ttl-slide-val { font: 500 12px/1 var(--font-body); color: var(--color-neutral-700); font-variant-numeric: tabular-nums; flex: none; min-width: 52px; text-align: right; }
/* Цвет и подложка — одной кнопкой: образец 20px + имя + шеврон; вся палитра в попапе */
.ttl-colorbtn {
  display: inline-flex; align-items: center; gap: 8px; width: max-content; padding: 6px 10px 6px 6px;
  border-radius: 8px; background: var(--color-bg); box-shadow: inset 0 0 0 1px var(--color-neutral-300);
  font: 500 13px/1 var(--font-body); color: var(--color-text);
  transition: box-shadow var(--dur) var(--ease), background var(--dur) var(--ease);
}
.ttl-colorbtn:hover { box-shadow: inset 0 0 0 1px var(--color-neutral-400); }
.ttl-colorbtn svg { color: var(--color-neutral-600); flex: none; transition: transform var(--dur) var(--ease); }
/* Пока попап открыт, кнопка держит нажатое состояние (4b) */
.ttl-colorbtn.on { background: var(--color-neutral-200); box-shadow: inset 0 0 0 1px var(--color-neutral-400); }
.ttl-colorbtn.on svg { transform: rotate(180deg); }
.ttl-chip { width: 20px; height: 20px; border-radius: 5px; flex: none; box-shadow: inset 0 0 0 1px rgba(32,30,29,.14); }
.ttl-chip-none { position: relative; background: var(--color-bg); }
.ttl-chip-none::after { content: ""; position: absolute; left: 3px; right: 3px; top: 50%; height: 2px; background: var(--color-accent); transform: rotate(-45deg); }
/* Хвост: чернильная главная, светлая вторая, мусорка справа. Красного нет —
   он занят главным действием экрана. */
.ttl-note { margin: 0; font: 400 12px/1.35 var(--font-body); color: var(--color-neutral-700); }
.ttl-foot { display: flex; align-items: center; gap: 8px; margin-top: var(--space-2); }
.ttl-btn {
  display: inline-flex; align-items: center; gap: 7px; height: 32px; padding: 0 14px; border-radius: 8px;
  font: 500 13px/1 var(--font-body);
  transition: background var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.ttl-btn-ink { background: var(--color-text); color: var(--color-bg); }
.ttl-btn-ink:hover { background: var(--color-neutral-800); }
.ttl-btn-lite { background: var(--color-bg); color: var(--color-text); box-shadow: inset 0 0 0 1px var(--color-neutral-300); }
.ttl-btn-lite:hover { box-shadow: inset 0 0 0 1px var(--color-neutral-400); }
.ttl-del {
  margin-left: auto; display: grid; place-items: center; width: 32px; height: 32px; border-radius: 8px;
  color: var(--color-neutral-600);
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.ttl-del:hover { background: var(--color-neutral-200); color: var(--color-text); }

/* Попап цвета (2b): готовые цвета, палитра (насыщенность + тон), hex, пипетка.
   Приходит и уходит за --dur — это состояние интерфейса, не содержимое. */
.ttl-pop {
  position: fixed; z-index: 58; width: 236px; padding: 14px; box-sizing: border-box;
  border-radius: var(--radius-card); background: var(--color-bg);
  box-shadow: 0 10px 40px rgba(32,30,29,.22), 0 2px 8px rgba(32,30,29,.10);
  display: flex; flex-direction: column; gap: 12px;
  transition: opacity var(--dur) var(--ease);
}
.ttl-pop.off { opacity: 0; }
.ttl-pop-swatches { display: grid; grid-template-columns: repeat(7, 1fr); gap: 6px; }
.ttl-sw { width: 100%; aspect-ratio: 1; border-radius: 6px; box-shadow: inset 0 0 0 1px rgba(32,30,29,.14); transition: transform var(--dur) var(--ease); }
.ttl-sw:hover { transform: scale(1.1); }
.ttl-sw.on { outline: 2px solid var(--color-text); outline-offset: 2px; }
.ttl-sw-none { position: relative; background: var(--color-bg); }
.ttl-sw-none::after { content: ""; position: absolute; left: 4px; right: 4px; top: 50%; height: 2px; background: var(--color-accent); transform: rotate(-45deg); }
.ttl-sat { position: relative; height: 96px; border-radius: 8px; cursor: crosshair; touch-action: none; }
.ttl-sat-knob { position: absolute; width: 14px; height: 14px; margin: -7px 0 0 -7px; border-radius: 50%; box-shadow: 0 0 0 2px #fff, 0 1px 4px rgba(0,0,0,.4); pointer-events: none; }
.ttl-hue { position: relative; height: 10px; border-radius: var(--radius-pill); background: linear-gradient(to right, #f00, #ff0, #0f0, #0ff, #00f, #f0f, #f00); cursor: pointer; touch-action: none; }
.ttl-hue-knob { position: absolute; top: 50%; width: 16px; height: 16px; transform: translate(-8px, -50%); border-radius: 50%; box-shadow: 0 0 0 2px #fff, 0 1px 4px rgba(0,0,0,.35); pointer-events: none; }
.ttl-pop-foot { display: flex; align-items: center; gap: 8px; }
.ttl-hex {
  flex: 1; min-width: 0; padding: 7px 10px; border: 0; border-radius: 8px;
  background: var(--color-surface); font: 500 13px/1 var(--font-body); color: var(--color-text);
  font-variant-numeric: tabular-nums; letter-spacing: 0.04em;
}
.ttl-hex:focus { outline: none; box-shadow: inset 0 0 0 1px var(--color-neutral-800); }
.ttl-pick {
  display: grid; place-items: center; width: 30px; height: 30px; border-radius: 8px;
  background: var(--color-bg); box-shadow: inset 0 0 0 1px var(--color-neutral-300); color: var(--color-neutral-600);
  transition: box-shadow var(--dur) var(--ease), color var(--dur) var(--ease);
}
.ttl-pick:hover { box-shadow: inset 0 0 0 1px var(--color-neutral-400); color: var(--color-text); }

/* ---------- Экран экспорта (b252, макет «Экран экспорта STYK») ----------
   Экспорт — конец пути, а не всплывающий вопрос: свой экран со своей шапкой.
   Ниже окон-вопросов (60): диалог поверх экрана возможен, экран поверх
   диалога — нет. */
.exp-screen {
  position: fixed; inset: 0; z-index: 50;
  display: flex; flex-direction: column;
  background: var(--color-bg);
}
.exp-screen.hidden { display: none; }
.exp-head { flex: none; display: flex; align-items: center; gap: var(--space-4); height: 64px; padding: 0 var(--space-8); border-bottom: 1px solid var(--color-neutral-300); }
.exp-head-sep { width: 1px; height: 20px; background: var(--color-neutral-300); }
.exp-head-gap { flex: 1; }
.exp-caps { font: 400 11px/1 var(--font-body); letter-spacing: 0.1em; color: var(--color-neutral-700); text-transform: uppercase; }
/* Оба блока — колонка решений и чертёж кадра — стоят ПАРОЙ по центру
   страницы, по обеим осям (b254, просьба пользователя): прижатые к левому
   верху, они оставляли справа и снизу пустое поле в две трети экрана.
   `safe center` — чтобы на низком окне верх не уезжал за край, а прокрутка
   начиналась с начала. */
.exp-body {
  flex: 1; min-height: 0; display: flex;
  /* Не влезли рядом — чертёж переезжает НАД колонку (b255). Перенос делает
     сам флекс: ширина чертежа зависит от пропорций съёмки (293 у 9:16,
     660 у 16:9), и одна точка перелома в медиа-запросе тут врала бы.
     wrap-reverse кладёт первую строку вниз, поэтому перенесённый чертёж
     оказывается сверху, как и просили. Зазор между строками — small. */
  flex-wrap: wrap-reverse;
  gap: var(--space-6) 56px;
  justify-content: safe center; align-content: safe center;
  /* Верх колонки и чертежа — на одной линии (b258). При wrap-reverse
     начало поперечной оси — низ строки, поэтому «верх» тут flex-end. */
  align-items: flex-end;
  padding: var(--space-8) var(--space-8) var(--space-6);
  overflow: auto;
}
/* Во время счёта и в «готово» решений нет — одна плитка по центру,
   чертёж кадра уходит: смотреть на нём уже нечего. */
.exp-screen.centered .exp-preview { display: none; }
/* Колонка решений: до 620, но не шире места — на узком окне ужимается, и
   боковые отступы остаются равными (правило «ширина — от места», b256) */
.exp-col { flex: 0 1 620px; width: 100%; max-width: 620px; min-width: 0; }
.exp-stack { display: flex; flex-direction: column; gap: var(--space-3); }
.exp-name-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3) var(--space-4); }
.exp-name-label { width: 84px; flex: none; }
.exp-field {
  flex: 1 1 200px; min-width: 0; padding: 12px 14px; border: 0; border-radius: var(--radius-control);
  background: var(--color-bg); box-shadow: inset 0 0 0 1px var(--color-neutral-300);
  font: 400 15px/1.35 var(--font-body); color: var(--color-text);
  transition: box-shadow var(--dur) var(--ease);
}
.exp-field:focus { outline: none; box-shadow: inset 0 0 0 1px var(--color-neutral-800); }
.exp-tile { display: flex; flex-direction: column; gap: var(--space-3); padding: var(--space-4); border-radius: var(--radius-card); background: var(--color-surface); }
/* Переключатель: корпус на ступень темнее плитки, выбранное — грунт с тенью */
.exp-seg { display: flex; flex-wrap: wrap; gap: 4px; padding: 4px; border-radius: var(--radius-card); background: var(--color-neutral-200); }
.exp-opt {
  flex: 1 1 auto; display: inline-flex; align-items: center; justify-content: center; gap: 5px;
  padding: 9px 6px; border-radius: var(--radius-control);
  font: 500 12px/1 var(--font-body); color: var(--color-neutral-600); white-space: nowrap;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.exp-opt:hover:not(.on):not(.lock) { color: var(--color-text); }
.exp-opt.on { background: var(--color-bg); color: var(--color-text); box-shadow: var(--shadow-sm); }
.exp-opt.lock { opacity: 0.72; cursor: not-allowed; }
/* Замок Pro — тот же, что был у 4K: тёмная пилюля 9px/700 */
.exp-pro { display: inline-flex; align-items: center; gap: 3px; padding: 2px 5px; border-radius: var(--radius-pill); background: var(--color-neutral-800); color: var(--color-bg); font-size: 9px; font-weight: 700; }
.exp-note { font: 400 12px/1.35 var(--font-body); color: var(--color-neutral-700); }
.exp-cards { display: flex; flex-wrap: wrap; gap: var(--space-3); }
.exp-vcard { flex: 1 1 150px; min-width: 0; display: flex; flex-direction: column; gap: 6px; padding: var(--space-3) var(--space-4); border-radius: var(--radius-card); background: var(--color-surface); }
.exp-vvalue { font: var(--font-heading-weight) 22px/1.1 var(--font-heading); letter-spacing: -0.01em; color: var(--color-text); font-variant-numeric: tabular-nums; }
/* Единственная красная кнопка экрана */
.exp-main {
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  width: 100%; height: 52px; margin-top: var(--space-2);
  border-radius: var(--radius-card); background: var(--color-accent); color: var(--color-bg);
  font: 600 15px/1 var(--font-body);
  transition: background var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.exp-main:hover { background: var(--color-accent-600); box-shadow: var(--shadow-sm); }
/* Рендер и «готово» — те же плитки, только просторнее */
.exp-run { gap: var(--space-4); padding: var(--space-6); }
.exp-run.hidden { display: none; }
.exp-pct { font: var(--font-heading-weight) 44px/1 var(--font-heading); letter-spacing: -0.03em; font-variant-numeric: tabular-nums; }
.exp-elapsed { font: 400 11px/1 var(--font-body); letter-spacing: 0.1em; color: var(--color-neutral-600); font-variant-numeric: tabular-nums; }
.exp-file { font: var(--font-heading-weight) 26px/1.15 var(--font-heading); letter-spacing: -0.02em; color: var(--color-text); }
.exp-done-row { display: flex; align-items: center; gap: var(--space-2); margin-top: var(--space-2); }
.exp-btn-ink { display: inline-flex; align-items: center; gap: 7px; height: 34px; padding: 0 14px; border-radius: var(--radius-control); background: var(--color-text); color: var(--color-bg); font: 500 13px/1 var(--font-body); transition: background var(--dur) var(--ease); }
.exp-btn-ink:hover { background: var(--color-neutral-800); }
.exp-btn-lite { display: inline-flex; align-items: center; gap: 7px; height: 34px; padding: 0 14px; border-radius: var(--radius-control); background: var(--color-bg); color: var(--color-text); font: 500 13px/1 var(--font-body); box-shadow: inset 0 0 0 1px var(--color-neutral-300); transition: box-shadow var(--dur) var(--ease); }
.exp-btn-lite:hover { box-shadow: inset 0 0 0 1px var(--color-neutral-400); }
/* Ширина — по кадру, а не по остатку: иначе пара не центрируется как пара */
.exp-preview { flex: none; max-width: 100%; display: flex; flex-direction: column; align-items: center; gap: var(--space-4); }
/* Кадр — ЖИВОЕ превью редактора (b257): сюда на время экрана переезжают
   #player-wrap и строка транспорта (.view-row). Плеер меряет своё место сам
   (container-type у .player-wrap), поэтому второго расчёта картинки нет. */
.exp-frame { max-width: 100%; display: flex; flex-direction: column; gap: var(--space-3); transition: width var(--dur-move) var(--ease), height var(--dur-move) var(--ease); }
.exp-frame .player-wrap { flex: 1; min-height: 0; width: 100%; }
.exp-frame .view-row { flex: none; }
/* Инструменты кадра на экспорте не нужны — здесь смотрят, а не правят */
.exp-frame #frame-tip, .exp-frame #frame-move, .exp-frame #crop-panel, .exp-frame #fit-toggle { display: none; }
/* Пуск здесь чернильный: красный на экране один — «Экспортировать» */
/* В кадре 9:16 транспорту достаётся ~220px: два таймкода по 15px в них не
   встают и слипаются. Кегль на ступень меньше — влезают с запасом. */
.exp-frame .tc-cur, .exp-frame .tc-total { font-size: 13px; }
.exp-frame .play-btn { background: var(--color-text); }
.exp-frame .play-btn:hover { background: var(--color-neutral-800); }
.exp-hint { flex: none; display: flex; align-items: center; gap: 12px; min-height: 46px; padding: 0 var(--space-8); border-top: 1px solid var(--color-neutral-300); }
/* Полоса хода: красный тут по правилу — это главное действие в работе */
.progress-track { position: relative; height: 7px; border-radius: var(--radius-pill); background: var(--color-neutral-300); overflow: hidden; }
.progress-fill { height: 100%; width: 0; border-radius: var(--radius-pill); background: var(--color-accent); transition: width 240ms var(--ease); }

/* ---------- Титры на ленте ---------- */
.title-seg {
  position: absolute;
  top: 0;
  height: 100%;
  display: flex;
  align-items: center;
  padding: 0 8px;
  border-radius: 6px;
  background: var(--color-neutral-200);
  border: 1px solid var(--color-neutral-300);
  color: var(--color-text);
  font: 500 11px/1 var(--font-body);
  white-space: nowrap;
  overflow: hidden;
  cursor: grab;
  box-sizing: border-box;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.title-seg:hover { background: var(--color-surface); }
.title-seg.on { border-color: var(--color-accent); background: var(--color-bg); }
.title-seg.dragging { cursor: grabbing; opacity: 0.85; }
.title-seg .title-seg-text { overflow: hidden; text-overflow: ellipsis; pointer-events: none; }
/* Пустой титр всё равно должен быть виден и схватываем — иначе он теряется */
.title-seg .title-seg-text:empty::before { content: "текст"; color: var(--color-neutral-600); }
.title-handle {
  position: absolute;
  top: 0; bottom: 0;
  width: 8px;
  cursor: ew-resize;
}
.title-handle-l { left: 0; }
.title-handle-r { right: 0; }

/* Инструмент курсора — переключатель, а не глагол. Поэтому он НЕ исчезает
   вместе с неприменимыми кнопками: режим обязан быть виден всегда, иначе
   человек не знает, что сейчас сделает его нажатие. */
/* Группа лежит на своей подложке — тем же приёмом, что переключатель кадра
   (.fit-toggle). Без неё выбранный инструмент подсвечивался цветом фона самой
   полосы и от невыбранного отличался одной тенью. */
.tool-modes {
  flex: none;
  display: flex;
  gap: 3px;
  padding: 3px;
  border-radius: var(--radius-card);
  background: var(--color-surface);
}
.tool-mode {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 28px;
  border-radius: var(--radius-card);
  color: var(--color-neutral-600);
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.tool-mode:hover:not(.on) { color: var(--color-text); }
/* Выбранный инструмент отмечен так же, как выбранный режим кадра
   (.fit-btn.on): подложка и тень, а не заливка цветом. Красный в живом
   дизайне — единственный акцент (кнопка результата, ползунок времени,
   рамка выделения), и на переключателе он спорил бы с ними за внимание. */
.tool-mode.on { background: var(--color-bg); color: var(--color-text); box-shadow: var(--shadow-sm); }
/* Радиус внутренней кнопки меньше внешнего на толщину поля — иначе углы
   вложенной подложки режут внешние. */
.tool-mode { border-radius: 7px; }

/* В режиме выделения курсор над лентой говорит, что жест теперь другой */
.timeline.selecting, .timeline.selecting .clip,
.tracks-row:has(.timeline.selecting) .track-head,
.workspace:has(.timeline.selecting) .view,
.workspace:has(.timeline.selecting) .toolstrip { cursor: crosshair; }
.workspace:has(.timeline.selecting) .left-col { cursor: default; }

/* Рамка выделения. Пунктир — потому что это не предмет, а намерение: он
   говорит «вот сюда смотрю», и тем же пунктиром нарисована сама кнопка
   инструмента. Заливка почти прозрачная: под рамкой лежит материал, и его
   должно быть видно. */
.marquee {
  position: absolute;
  z-index: 7;
  pointer-events: none;
  border: 1px dashed var(--color-accent);
  border-radius: 4px;
  /* Заливка — тот же красный, но почти прозрачный: под рамкой лежит материал,
     и его должно быть видно. Цвет один, чтобы рамка и её нутро читались как
     одна вещь. */
  background: rgba(236, 48, 19, 0.07); /* --color-accent, 7% */
}

/* Пока идёт уборка пауз, глаголы к отдельной сцене из полосы уходят: панель
   занимает её одна, и правят ею фильм целиком, а не выбранную сцену. */
.toolstrip.pausing .tool-btn,
.toolstrip.pausing .tool-modes,
.toolstrip.pausing .tool-sep { display: none; }

/* Полоса — часть рабочей области, поэтому на узком окне отступы те же, что
   у ленты, иначе края не совпадут по вертикали. */
@media (max-width: 1000px) {
  .toolstrip { padding: 0 var(--space-4); }
  /* Всем глаголам с подписями нужно 1167 px, а на таком окне их и близко нет
     (замер). Оставляем значки: подпись объясняет кнопку в первый раз, а места
     требует всегда. Название остаётся во всплывающей подсказке. */
  .toolstrip .tool-btn { padding: 0 8px; font-size: 0; gap: 0; }
  .toolstrip .tool-btn svg { font-size: 13px; }
}

/* На стартовом экране полосы нет: глаголы без проекта не к чему применять.
   Тем же правилом, что прячет элементы проекта в шапке. */
.topbar:has(~ .workspace > #editor.hidden) ~ .workspace .toolstrip { display: none; }

/* ---------- Нижняя панель: лента времени ---------- */

.bottom-panel {
  flex: none;
  position: relative;
  border-top: 1px solid var(--color-neutral-300);
  background: var(--color-neutral-100);
  /* верхнего отступа нет: всё пространство над сценами — рабочая
     зона перемотки (линейка), клик работает от самой границы панели */
  padding: 0 var(--space-8) 0;
}

.tracks-row {
  display: flex; gap: var(--space-4); align-items: stretch;
  /* Дорожка музыки есть всегда — пустая она показывает вход, а не обещание */
  --extra-track: calc(var(--track-gap) + var(--au-h));
}

.track-heads {
  /* 84 хватало, пока здесь были одни подписи. С выключателем звука
     «ОРИГИНАЛ» упирался в значок вплотную и читался одним пятном. */
  /* 104 хватало, пока рядом с динамиком ничего не стояло. С подписью
     громкости «−4.0» строка упиралась в край. */
  width: 132px;
  flex: none;
  display: flex;
  flex-direction: column;
  padding-top: var(--scrub-h);
}

.track-head {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: flex-start;
  gap: 3px;
  font: var(--font-heading-weight) 11px/1.2 var(--font-heading);
  letter-spacing: 0.1em;
}
.th-sub {
  font: 400 11px/1 var(--font-body);
  letter-spacing: 0;
  color: var(--color-neutral-600);
  font-variant-numeric: tabular-nums;
}
.th-sub:empty { display: none; }
.th-title { height: var(--title-h); color: var(--color-neutral-600); }
.th-gfx { height: var(--gfx-h); margin-top: var(--track-gap); color: var(--color-neutral-600); }
.th-video { height: var(--video-h); margin-top: var(--track-gap); }
.th-orig { height: var(--au-h); margin-top: var(--track-gap); color: var(--color-neutral-600); }

/* Шапка дорожки со звуком теперь не только подпись, но и выключатель, —
   значит строка, а не столбик: подпись слева, действие справа. */
.th-orig, .th-music { flex-direction: row; align-items: center; gap: 6px; }
/* Пустой дорожки-обещания на экране не держим: шапка и тело появляются
   вместе с файлом. */
.th-music { height: var(--au-h); margin-top: var(--track-gap); color: var(--color-neutral-600); }
/* Выключать нечего, пока музыки нет: пустых кнопок на экране не держим.
   Селектор именно .th-music .th-mute — без него правило гасило и динамик
   ОРИГИНАЛА, у которого выключать как раз есть что. */
.tracks-row:not(.has-music) .th-music .th-mute { display: none; }
.th-name { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.th-mute {
  flex: none; margin-left: auto;
  width: 22px; height: 22px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 6px;
  color: var(--color-neutral-600);
  transition: color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.th-mute:hover { color: var(--color-text); background: var(--color-neutral-200); }
/* Выключенный звук — не тревога и не ошибка, поэтому чернила, а не акцент:
   красный в этой системе значит выбор, курсор и главное действие. */
.th-mute[aria-pressed="true"] { color: var(--color-text); }
.th-mute .th-mute-off { display: none; }
.th-mute[aria-pressed="true"] .th-mute-on { display: none; }
.th-mute[aria-pressed="true"] .th-mute-off { display: block; }
/* «звук 23%» под ОРИГИНАЛом, пока считается волна: пунктир на дорожке
   говорит ГДЕ ещё не готово, подпись — сколько осталось ждать. */
.th-wait { color: var(--color-neutral-600); font-variant-numeric: tabular-nums; }
/* «показать звук» — единственное действие в шапке дорожек, поэтому
   подчёркиванием отличаем его от обычной подписи */
.th-action { cursor: pointer; text-decoration: underline; text-underline-offset: 3px;
  text-decoration-color: var(--color-neutral-400); }
.th-action:hover { color: var(--color-text); }

/* Скролл-контейнер ленты */

/* Высота считается по дорожкам плюс запас снизу. Запас = отступ от
   ОРИГИНАЛА (10px) и место под саму полосу прокрутки (7px): без второго
   слагаемого полоса прижималась к дорожке впритык. Запас постоянный,
   чтобы лента не прыгала по высоте при зуме. */
.timeline {
  --tl-scroll-h: 11px; /* реальная высота полосы в Chrome, замерено */
  --tl-gap-bottom: 10px;
  position: relative;
  flex: 1;
  min-width: 0;
  /* Дорожку ТЕКСТ надо считать здесь ТОЖЕ. Забыл при её появлении — и нижние
     11 px дорожки МУЗЫКА оказались срезаны: overflow скрытый, докрутить
     нельзя. Всякая новая дорожка обязана попасть и в смещения, и сюда. */
  height: calc(var(--scrub-h) + var(--title-h) + var(--track-gap) + var(--gfx-h) + var(--track-gap)
             + var(--video-h) + var(--track-gap) + var(--au-h)
             + var(--extra-track) + var(--tl-gap-bottom) + var(--tl-scroll-h));
  /* При зуме ×1 всё влезает по определению, и прокручивать нечего. Полоса
     всё равно появлялась: насечки секунд и курсор на самом правом краю
     торчат за границу на пиксель-два, и браузер считал это переполнением. */
  overflow-x: hidden;
  overflow-y: hidden;
  user-select: none;
  touch-action: none;
  overscroll-behavior-x: contain;
}
.timeline.zoomed { overflow-x: auto; }
.timeline.panning { cursor: grabbing; }
.timeline::-webkit-scrollbar { height: var(--tl-scroll-h); }
.timeline::-webkit-scrollbar-track { background: transparent; }
.timeline::-webkit-scrollbar-thumb { background: var(--color-neutral-400); border-radius: var(--radius-pill);
  border: 3px solid transparent; background-clip: content-box; }
.timeline::-webkit-scrollbar-thumb:hover { background: var(--color-neutral-600); background-clip: content-box; }

.timeline-content { position: relative; width: 100%; height: 100%; min-width: 100%; }

/* Полоса перемотки над сценами (курсор ходит здесь) */

.ruler {
  position: absolute;
  top: 0; left: 0; right: 0;
  height: var(--scrub-h);
  cursor: pointer;
}
.ruler:hover { background: linear-gradient(180deg, transparent 30%, var(--color-neutral-200) 100%); }

/* насечки движка на полосе — приглушённые точки секунд */
.tick { position: absolute; bottom: 2px; width: 1px; pointer-events: none; background: var(--color-neutral-400); }
.tick-h { height: 10px; }
.tick-m { height: 7px; }
.tick-s { height: 4px; opacity: 0.7; }
.tick-label {
  position: absolute;
  bottom: 15px;
  transform: translateX(3px);
  font: 400 9px/1 var(--font-body);
  letter-spacing: 0.02em;
  color: var(--color-neutral-600);
  font-variant-numeric: tabular-nums;
  pointer-events: none;
  white-space: nowrap;
}

/* Дорожка ВИДЕО: блоки сцен */

/* Дорожка ТЕКСТ стоит НАД видео: титр лежит поверх кадра, и на ленте он
   должен быть там же — сверху. Ниже её всё съезжает ровно на её высоту с
   зазором, поэтому смещение считается одним выражением, а не числами по
   местам. */
.title-track {
  position: absolute;
  top: var(--scrub-h);
  left: 0; right: 0;
  height: var(--title-h);
}
/* Пустая дорожка всё равно занимает место — но не молчит: она вход, как и
   пустая дорожка МУЗЫКА. Иначе тридцать два пикселя тратятся ни на что. */
/* Дорожка ГРАФИКА — под ТЕКСТОМ, той же высоты; плашки — те же .title-seg,
   но с бирюзовой меткой: другой инструмент должно быть видно и на ленте. */
.gfx-track {
  position: absolute;
  top: calc(var(--scrub-h) + var(--title-h) + var(--track-gap));
  left: 0; right: 0;
  height: var(--gfx-h);
}
.gfx-track .title-seg { border-left: 3px solid #4fd3c4; }
.gfx-track:empty::before {
  content: "Графика по смыслу речи — кнопка «Графика» в полосе";
  display: flex;
  align-items: center;
  height: 100%;
  padding-left: 8px;
  color: var(--color-neutral-600);
  font: 400 11px/1 var(--font-body);
  pointer-events: none;
}
.title-track:empty::before {
  content: "Текст поверх кадра — кнопка «Текст» в полосе";
  display: flex;
  align-items: center;
  height: 100%;
  padding-left: 8px;
  color: var(--color-neutral-600);
  font: 400 11px/1 var(--font-body);
  pointer-events: none;
}

.clips {
  position: absolute;
  top: calc(var(--scrub-h) + var(--title-h) + var(--track-gap) + var(--gfx-h) + var(--track-gap));
  left: 0; right: 0;
  height: var(--video-h);
}

.clip {
  position: absolute;
  top: 0;
  bottom: 0;
  /* Зазор между сценами сделан прозрачной рамкой справа, а border-radius
     скругляет ВНЕШНИЙ край. Внутренний тогда получает «радиус минус ширина
     рамки» — то есть ноль, и заливка выходит с прямыми углами справа,
     торчащими за скруглённой обводкой выделения. Поэтому справа радиус
     задаём с прибавкой на ширину рамки: внутренний край снова равен
     --radius-track и совпадает с обводкой. */
  border-radius: var(--radius-track)
                 calc(var(--radius-track) + var(--track-gap))
                 calc(var(--radius-track) + var(--track-gap))
                 var(--radius-track);
  background: var(--color-neutral-300);
  background-clip: padding-box;
  border-right: var(--track-gap) solid transparent;
  cursor: grab;
  overflow: visible;
  transition: filter var(--dur) var(--ease), transform var(--dur) var(--ease),
              box-shadow var(--dur) var(--ease);
}

/* Соседи расступаются, открывая щель там, куда встанет сцена. Двигаются
   только два блока у границы — лента не должна ходить ходуном. */
.clip.gap-l { transform: translateX(-10px); }
.clip.gap-r { transform: translateX(10px); }
/* Едет один (у стыка рядом с дыркой от перетаскиваемой сцены) — забирает
   всё расстояние себе, чтобы щель осталась той же ширины */
.clip.gap-l.gap-solo { transform: translateX(-20px); }
.clip.gap-r.gap-solo { transform: translateX(20px); }
/* При «меньше движения» щель остаётся — она несёт смысл, а не украшает.
   Убираем только плавность. */
@media (prefers-reduced-motion: reduce) {
  .clip { transition: none; }
}
.clip:last-of-type { border-right: none; }
.clip:hover { filter: brightness(0.96); }
.clip:active { cursor: grabbing; }

/* внутренний слой: цвет источника + скругление, чтобы зазор был честным */
.clip::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: var(--radius-track);
  background: inherit;
}

/* Цвет сцены. Основной — тон, снятый с первого кадра ролика (--clip-tint,
   ставит оболочка): по нему видно, где какой ролик, ещё до чтения номеров.
   Запасной — системный по номеру источника: он же остаётся, когда в кадре
   почти нет цвета (ночь, туман, чёрно-белое) и брать оттуда нечего. */
/* Запасной цвет ОДИН и нейтральный: пока кадр не прочитан, сцена честно
   бесцветна. Четыре пастели по числу источников были четвёртым источником
   цвета в системе и значили не то, чем сцена окрашена сейчас. */
.clip.src-c0, .clip.src-c1, .clip.src-c2, .clip.src-c3 {
  background-color: var(--clip-tint, var(--color-neutral-300));
}

/* Цвет кадра бывает тёмным, и тёмно-серый номер по нему не читается.
   Класс ставит оболочка, посчитав светлоту с поправкой на насыщенность. */
.clip.dark-tint .clip-num { color: #fff; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.25); }

/* Выбранная сцена: обводка акцентом 3px (внутренняя — не ломает сетку) */
.clip.selected { z-index: 3; }
.clip.selected::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: var(--radius-track);
  /* Чернила, а не акцент: тон сцены берётся из кадра и бывает любым, в том
     числе красноватым, — по такому фону акцент не выделяет. Раньше это
     лечилось светлой подпоркой изнутри для тёмных тонов; подпорка убрана
     вместе с причиной. Заодно курсор остаётся единственным красным на ленте. */
  box-shadow: inset 0 0 0 3px var(--color-text);
  pointer-events: none;
}

/* Превью-кадр сцены: первый кадр в начале блока (ставит plenka.js).
   Ширина фиксированная, но не шире самого блока; правый край кадра
   мягко растворяется в цвет блока. */
/* Кадр и номер прижаты к левому краю ВИДИМОЙ части сцены: --clip-inset движок
   ставит равным тому, насколько начало сцены ушло за экран. На обычном
   масштабе он ноль, и всё стоит как стояло. */
.clip-thumb,
.clip-num { transform: translateX(var(--clip-inset, 0px)); }

.clip-thumb {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 148px;
  max-width: 100%;
  border-radius: var(--radius-track);
  background-size: cover;
  background-position: center;
  pointer-events: none;
  -webkit-mask-image: linear-gradient(90deg, #000 70%, transparent 100%);
  mask-image: linear-gradient(90deg, #000 70%, transparent 100%);
}

.clip.has-thumb .clip-num {
  color: #fff;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.65);
}
.clip.has-thumb.selected .clip-num { color: #fff; }

/* Номер сцены в углу блока (ставит plenka.js) */
.clip-num {
  position: absolute;
  left: 10px;
  top: 8px;
  font: var(--font-heading-weight) 13px/1 var(--font-heading);
  color: var(--color-neutral-800);
  pointer-events: none;
  z-index: 2;
  /* Номер связывает блок с колонкой, а связь нужна ровно тогда, когда сцена
     выбрана. В покое кадр опознаётся кадром — цифра поверх него мешает его
     читать. */
  opacity: 0;
  transition: opacity var(--dur) var(--ease);
}
.clip.selected .clip-num,
.clip:hover .clip-num,
.clip.dragging .clip-num { opacity: 1; }
.clip.selected .clip-num { color: var(--color-text); }

/* Подпись движка (имя+длина) в новой ленте не показывается —
   вся информация о сцене живёт в левой колонке */
.clip-label { display: none; }

/* Ручки обрезки: всегда видимые пилюли на краях выбранной сцены */
.clip-handle {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 14px;
  height: 48px;
  background: var(--color-neutral-400);
  border-radius: 9px;
  border: 2px solid var(--color-bg);
  cursor: ew-resize;
  z-index: 4;
  opacity: 0.75;
  transition: background var(--dur) var(--ease), opacity var(--dur) var(--ease);
}
.clip-handle-l { left: -7px; }
.clip-handle-r { right: 1px; }
.clip:last-of-type .clip-handle-r { right: -7px; }
.clip:hover .clip-handle { opacity: 1; }
.clip.selected .clip-handle { background: var(--color-text); opacity: 1; }
.clip-handle:hover { background: var(--color-neutral-900); }

/* Узкая сцена (< 34px): ручки ужимаются, номер прячем */
.clip.narrow .clip-handle { width: 6px; height: 36px; }
.clip.narrow .clip-handle-l { left: -3px; }
.clip.narrow .clip-handle-r { right: 0; }
.clip.narrow .clip-num { display: none; }

/* Копия удаляемой сцены: живёт ровно столько, сколько закрывается зазор.
   Складывается по горизонтали, оба края приклеены к краям соседей. */
/* Слой, которым копия растворяется в ленте. Лежит НАД кадром и заливкой, но
   под номером сцены (у того z-index 2): номер должен читаться до самого конца.
   Цвет — фон дорожки, а не акцент: красный читается как «ошибка», а удаление
   сцены — обычный шаг монтажа, который к тому же отменяется. Сцена не убита,
   она ушла. */
.clip.ghost .ghost-out {
  position: absolute;
  inset: 0;
  z-index: 1;
  background: var(--color-neutral-100);
  border-radius: inherit;
  opacity: 0;
  pointer-events: none;
}

.clip.ghost {
  z-index: 2;
  pointer-events: none;
  overflow: hidden;
  /* Живёт на слое ленты, а не в дорожке сцен, поэтому положение по вертикали
     задаём сами: линейка сверху плюс высота видеодорожки. */
  top: var(--scrub-h);
  bottom: auto;
  height: var(--video-h);
}

/* Сцена в перетаскивании */
/* Схваченная сцена приподнята: тень и лёгкое увеличение говорят «держу»,
   пока соседи расступаются, показывая, куда она встанет. */
.clip.dragging {
  z-index: 6;
  filter: none;
  /* Схваченная сцена сильно прозрачнее: под ней видно ленту, а значит и то,
     куда целишься. */
  opacity: 0.45;
  /* Подъём, а не увеличение: у длинной сцены масштаб сдвигает края на
     десятки пикселей, и блок будто дёргается. Сдвиг вверх одинаков при
     любой ширине. */
  transform: translateY(-3px);
  box-shadow: 0 12px 28px -8px rgba(32, 30, 29, 0.45);
  cursor: grabbing;
  /* Ни ширину, ни положение здесь не анимируем: и то и другое движок
     считает сам, кадр за кадром, — только так они не расходятся. */
  transition: opacity 180ms var(--ease);
}
.clip.dragging::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: var(--radius-track);
  box-shadow: inset 0 0 0 3px var(--color-text);
}

/* Дорожка ОРИГИНАЛ: отрезки звука под сценами (рисует plenka.js) */

.au-track {
  position: absolute;
  top: calc(var(--scrub-h) + var(--title-h) + var(--track-gap) + var(--gfx-h) + var(--track-gap) + var(--video-h) + var(--track-gap));
  left: 0; right: 0;
  height: var(--au-h);
  pointer-events: none;
}

.au-seg {
  position: absolute;
  top: 0; bottom: 0;
  /* Зазор той же прозрачной рамкой, значит и поправка та же, что у сцены */
  border-radius: var(--radius-track)
                 calc(var(--radius-track) + var(--track-gap))
                 calc(var(--radius-track) + var(--track-gap))
                 var(--radius-track);
  background: var(--color-neutral-200);
  background-clip: padding-box;
  border-right: var(--track-gap) solid transparent;
  overflow: hidden;
  /* Расступается так же плавно, как сцены. У схваченного отрезка плавность
     снимается ниже — он идёт за рукой. */
  transition: transform var(--dur) var(--ease);
}
.au-seg::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: var(--radius-track);
  background: inherit;
}
/* Настоящая огибающая громкости, а не узор: раньше здесь был
   равномерный штриховой паттерн, и он выглядел как волна — новичок
   верил ему и резал мимо. Рисует plenka.js по пикам из js/peaks.js. */
.au-seg-wave {
  position: absolute;
  left: 6px; top: 4px;
  /* canvas — заменяемый элемент: при width:auto браузер берёт его
     собственные 300×150 и не тянет по left/right. Размер только явный. */
  width: calc(100% - 12px);
  height: calc(100% - 8px);
  display: block;
}
.au-seg.selected { background-color: var(--color-neutral-300); }

/* Звук ведёт себя как сцена, к которой принадлежит: та же прозрачность в
   захвате, тот же сдвиг при расступании. Значения повторяют .clip — если
   менять там, менять и здесь. */
.au-seg.dragging { opacity: 0.45; transition: opacity 180ms var(--ease); }
.au-seg.gap-l { transform: translateX(-10px); }
.au-seg.gap-r { transform: translateX(10px); }
.au-seg.gap-l.gap-solo { transform: translateX(-20px); }
.au-seg.gap-r.gap-solo { transform: translateX(20px); }


/* Хвост ленты: «+» добавить видео */

.track-tail { flex: none; display: flex; flex-direction: column; padding-top: var(--scrub-h); }
.add-tile {
  width: 56px;
  height: var(--video-h);
  border-radius: var(--radius-track);
  outline: 2px dashed var(--color-neutral-400);
  outline-offset: -2px;
  display: grid;
  place-items: center;
  color: var(--color-neutral-600);
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease), outline-color var(--dur) var(--ease);
}
.add-tile:hover { background: var(--color-surface); color: var(--color-text); outline-color: var(--color-neutral-600); }

/* Курсор воспроизведения: красная линия с круглой головкой */

.playhead {
  position: absolute;
  top: 0;
  bottom: 6px;
  left: 0;
  width: 3px;
  margin-left: -1.5px;
  background: var(--color-accent);
  border-radius: 2px;
  pointer-events: none;
  z-index: 9;
}
/* Головка курсора: пилюля высотой в линейку — как ручки по краям сцен */
.playhead::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 0;
  transform: translateX(-50%);
  width: 14px;
  height: var(--scrub-h);
  border-radius: 9px;
  background: var(--color-accent);
  border: 2px solid var(--color-bg);
  box-sizing: border-box;
}

/* Подсказка направлений при захвате */

/* Стрелки «куда можно переставить» — ровно по центру видеодорожки.
   Элемент лежит рядом с дорожкой, а не внутри неё, поэтому высоту считаем
   явно: линейка сверху плюс половина дорожки. */
.move-arrows {
  position: absolute;
  top: calc(var(--scrub-h) + var(--video-h) / 2);
  transform: translate(-50%, -50%);
  display: flex;
  align-items: center;
  justify-content: center;
  /* Ширина фиксированная: у крайних сцен стрелка одна, и плашка не должна
     от этого менять размер. */
  width: 72px;
  height: 34px;
  overflow: hidden;
  /* Ширина едет вместе с поворотом значка: развернулись вниз — подложка
     сжимается в кружок. Двусторонней стрелке нужна длина, одиночной нет. */
  transition: width 220ms var(--ease);
  border-radius: var(--radius-pill);
  background: var(--color-neutral-200);
  color: var(--color-text);
  pointer-events: none;
  z-index: 8;
  white-space: pre;
  box-shadow: var(--shadow-sm);
}

/* Значок целится в стык: пока сцена «дома» — стрелки горизонтальные, а как
   только курсор над подсвеченным стыком, они разворачиваются вниз. Верхний
   наконечник при этом гаснет, чтобы осталась одна стрелка В место вставки,
   а не двусторонняя. */
.move-arrows svg { transition: transform 220ms var(--ease); }
.move-arrows .ma-up, .move-arrows .ma-down { transition: opacity 160ms var(--ease); }
/* Крайняя сцена: в одну сторону двигать некуда — этот наконечник не рисуем */
.move-arrows.no-left .ma-up { opacity: 0; }
.move-arrows.no-right .ma-down { opacity: 0; }
/* Целимся в стык: поворот вниз, верхний наконечник гаснет, нижний остаётся
   ВСЕГДА — даже у крайней сцены, иначе стрелка превратится в палку. */
.move-arrows.aim { width: 34px; }
.move-arrows.aim svg { transform: rotate(90deg); }
.move-arrows.aim .ma-up { opacity: 0; }
.move-arrows.aim .ma-down { opacity: 1; }
@media (prefers-reduced-motion: reduce) {
  .move-arrows, .move-arrows svg, .move-arrows .ma-up { transition: none; }
}

/* Бейдж подрезки */

.trim-tip {
  position: absolute;
  transform: translateX(-50%);
  padding: 5px 9px;
  border-radius: 7px;
  background: var(--color-neutral-900);
  color: var(--color-bg);
  font: 600 12px/1.2 var(--font-body);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  pointer-events: none;
  z-index: 10;
  box-shadow: var(--shadow-sm);
}

/* Мультитрек (спит за флагом) — минимальные стили состояния */
.lane { position: absolute; left: 0; right: 0; pointer-events: none; }
.lane-v2-bg { top: 0; height: 50%; border-bottom: 1px dashed var(--color-neutral-400); }
.lane-v1-bg { top: 50%; height: 50%; }
.lane-tag { position: sticky; left: 4px; font: 600 9px/1 var(--font-body); color: var(--color-neutral-600); padding: 2px 5px; }
.clips.two-lanes .clip:not(.ov) { top: calc(50% + 3px); }
.clip.ov { top: 3px; bottom: calc(50% + 3px); }
.clips.drop-v2 .lane-v2-bg, .clips.drop-v1 .lane-v1-bg { background: var(--color-accent-100); }
#export-status { font-weight: 600; }
#export-time { color: var(--color-neutral-400); }
#export-pct { color: var(--color-text); font-weight: 700; }

.progress-track {
  position: relative;
  height: 7px;
  background: var(--color-neutral-800);
  border-radius: var(--radius-pill);
  overflow: hidden;
}
.progress-fill {
  height: 100%;
  width: 0;
  border-radius: var(--radius-pill);
  background: var(--color-accent);
  transition: width 240ms var(--ease);
}

/* ---------- Строка подсказок ---------- */

/* Строка стоит ПО ЦЕНТРУ: у левого края на широком мониторе её просто не
   замечают. Зум при этом остаётся у правого края — он не сообщение, а
   инструмент, и место у него постоянное. Поэтому он вынут из потока, иначе
   тянул бы центр на себя. */
.hintbar {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-4);
  margin-top: var(--space-3);
  padding: var(--space-3) 140px;
  border-top: 1px solid var(--color-neutral-300);
  font-size: 12px;
  min-height: 46px;
}

.hint-chip { font: var(--font-heading-weight) 10px/1 var(--font-heading); letter-spacing: 0.14em; color: var(--color-neutral-600); flex: none; }
.hint-sep { width: 1px; height: 14px; background: var(--color-neutral-300); flex: none; }
.hint-text { color: var(--color-text); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }


/* чип клавиши внутри подсказки (plenka.js оборачивает [C] и т.п.) */
.key-chip {
  display: inline-grid;
  place-items: center;
  min-width: 20px; height: 20px;
  padding: 0 5px;
  margin: 0 2px;
  border-radius: 6px;
  background: var(--color-bg);
  box-shadow: inset 0 0 0 1px var(--color-neutral-400);
  font: var(--font-heading-weight) 10px/1 var(--font-heading);
}

/* Клавиши вынесены из фразы в отдельную зону: в тексте они превращали
   подсказку в перечень, который никто не дочитывает. Максимум две. */
.hint-keys {
  display: flex;
  align-items: center;
  gap: 14px;
  flex: none;
  color: var(--color-neutral-700);
}
.hint-keys:empty { display: none; }
.hint-keys > span { display: flex; align-items: center; gap: 5px; white-space: nowrap; }

/* «Скрыть подсказки» словами занимало 118px полезной строки. Крестик 22px
   говорит то же самое; вернуть подсказки по-прежнему знаком вопроса. */
/* «не сейчас» у сообщения с действием: отказ, а не кнопка. */
.hint-hide { flex: none; color: var(--color-neutral-600); font-size: 12px; }
.hint-hide:hover { color: var(--color-text); }

/* Кнопка действия в строке заимствует вид у плитки КАДРИРОВАНИЕ, но не её
   расположение: там `margin-left: auto` прижимает кнопку к правому краю
   плитки, а здесь он расталкивал строку по краям — текст влево, кнопка
   вправо, и вся мысль переставала читаться как одна. */
.hintbar .crop-btn { margin-left: 0; }

/* Сказать нечего — метка и разделитель уходят вместе с текстом: висеть над
   пустой строкой им незачем. Крестик и зум остаются. */
.hintbar.empty .hint-chip,
.hintbar.empty .hint-sep { display: none; }

/* Сообщение продукта в той же строке: метка чернилами, клавиши на это время
   убраны — мысль должна быть одна. */
.hintbar.msg .hint-chip { color: var(--color-text); }
.hintbar.msg .hint-keys { display: none; }


.zoom-group {
  position: absolute;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  display: flex; align-items: center; gap: 10px; flex: none;
}

/* Ползунок зума: масштаб плавный, без ступеней и без насечек — рука ведёт
   ленту, а не выбирает из четырёх вариантов. Чернила, не акцент: красный на
   ленте занят курсором. */
.zoom-ic { flex: none; display: flex; color: var(--color-neutral-600); }
.zoom-slider {
  position: relative;
  width: 96px; height: 4px;
  flex: none;
  border-radius: var(--radius-pill);
  background: var(--color-neutral-300);
  cursor: pointer;
}
.zs-fill { position: absolute; left: 0; top: 0; bottom: 0; border-radius: var(--radius-pill); background: var(--color-neutral-600); }
.zs-knob {
  position: absolute;
  top: 50%;
  width: 14px; height: 14px;
  margin-left: -7px;
  transform: translateY(-50%);
  border-radius: 50%;
  background: var(--color-text);
  box-shadow: var(--shadow-sm);
  transition: transform var(--dur) var(--ease);
}
.zoom-slider:hover .zs-knob { transform: translateY(-50%) scale(1.14); }

/* ---------- Разное ---------- */

.engine-compat { position: absolute; left: -9999px; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

@media (max-width: 1000px) {
  .left-col { padding-left: var(--space-6); }
  .bottom-panel { padding-left: var(--space-4); padding-right: var(--space-4); }
}

/* ============================================================
   Окно поверх (пока одно — экспорт)

   Модалок в интерфейсе сознательно почти нет: подтверждения делаются
   двойным нажатием. Экспорт — исключение: тут человек принимает решение
   (размер, имя), а не подтверждает уже сделанное, и решение это стоит
   минут ожидания. Такое честнее спросить явно.
   ============================================================ */

.modal {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-6);
}
.modal.hidden { display: none; }

.modal-veil {
  position: absolute;
  inset: 0;
  background: rgba(32, 30, 29, 0.42);
  backdrop-filter: blur(2px);
  animation: veil-in var(--dur) var(--ease);
}

.modal-card {
  position: relative;
  width: 100%;
  max-width: 420px;
  background: var(--color-bg);
  border-radius: var(--radius-preview);
  padding: var(--space-6);
  box-shadow: 0 24px 60px -18px rgba(32, 30, 29, 0.55);
  animation: card-in 200ms var(--ease);
}

@keyframes veil-in { from { opacity: 0; } }
@keyframes card-in {
  from { opacity: 0; transform: translateY(8px) scale(0.98); }
}
@media (prefers-reduced-motion: reduce) {
  .modal-veil, .modal-card { animation: none; }
}

.modal-title {
  font-family: var(--font-heading);
  font-weight: var(--font-heading-weight);
  font-size: 22px;
  letter-spacing: -0.01em;
  margin-bottom: 2px;
}
.modal-sub {
  font-size: 12px;
  color: var(--color-neutral-700);
  margin-bottom: var(--space-6);
  font-variant-numeric: tabular-nums;
}

.field { margin-bottom: var(--space-4); }
.field-label {
  display: block;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-neutral-700);
  margin-bottom: var(--space-2);
}

/* Поле имени: суффикс .mp4 внутри рамки — расширение не редактируется,
   его незачем и показывать как часть текста. */
.field-box {
  display: flex;
  align-items: center;
  gap: 2px;
  background: var(--color-neutral-100);
  border: 1px solid var(--color-neutral-300);
  border-radius: var(--radius-card);
  padding: 0 12px;
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease);
}
/* Фокус подсвечиваем нейтральным, а не акцентом: красный в системе значит
   «выбрано» и «главное действие», и красная рамка вокруг выделенного текста
   читается как ошибка ввода. */
.field-box:focus-within {
  border-color: var(--color-neutral-800);
  background: var(--color-bg);
}
.field-box input {
  flex: 1;
  min-width: 0;
  border: 0;
  background: none;
  padding: 10px 0;
  font-family: var(--font-body);
  font-size: 14px;
  color: var(--color-text);
}
.field-box input:focus { outline: none; }
.field-suffix {
  font-size: 14px;
  color: var(--color-neutral-600);
  flex: none;
}

.modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-2);
  margin-top: var(--space-6);
}

/* ============================================================
   Сохранённые проекты на стартовом экране

   Раньше здесь была одна карточка «есть сохранённый проект». Браузер
   помнит их несколько, и список честнее: человек выбирает, к чему
   вернуться, а не гадает, какой проект был последним.
   ============================================================ */

.dz-projects {
  width: 100%;
  max-width: 560px;
  margin: var(--space-6) auto 0;
  text-align: left;
}
.dz-projects.hidden { display: none; }

.dzp-title {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-neutral-700);
  margin-bottom: var(--space-2);
}

.dzp-list { display: flex; flex-direction: column; gap: 6px; }

.dzp-card {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  padding: 10px 12px;
  text-align: left;
  background: var(--color-bg);
  border: 1px solid var(--color-neutral-300);
  border-radius: var(--radius-card);
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.dzp-card:hover { border-color: var(--color-neutral-400); box-shadow: var(--shadow-sm); }

/* Полоски цветов источников — те же, что в списке файлов внутри проекта:
   по ним проект узнаётся с одного взгляда, ещё до чтения имени */
/* Кадр первой сцены. До открытия проекта цвета источников не значат ничего —
   язык ленты работает только на ленте; кадр отвечает на «что это за фильм»
   раньше, чем прочитано имя. */
.dzp-poster {
  flex: none;
  width: 64px; height: 40px;
  border-radius: 6px;
  background: var(--color-neutral-300) center / cover no-repeat;
}
.dzp-poster-empty { background-color: var(--color-neutral-200); }

.dzp-main { flex: 1; min-width: 0; }
.dzp-name {
  display: block;
  font-size: 14px;
  font-weight: 600;
  color: var(--color-text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.dzp-meta {
  display: block;
  font-size: 11px;
  color: var(--color-neutral-700);
  font-variant-numeric: tabular-nums;
}

.dzp-del {
  flex: none;
  padding: 5px 8px;
  border-radius: 8px;
  font-size: 11px;
  color: var(--color-neutral-600);
  opacity: 0;
  transition: opacity var(--dur) var(--ease), color var(--dur) var(--ease),
              background var(--dur) var(--ease);
}
.dzp-card:hover .dzp-del, .dzp-del:focus-visible { opacity: 1; }
.dzp-del:hover { color: var(--color-accent); background: var(--color-accent-100); }
/* Подтверждение вторым нажатием — модалок в интерфейсе почти нет */
.dzp-del[data-confirm="1"] {
  opacity: 1;
  color: var(--color-bg);
  background: var(--color-accent);
}

/* ============================================================
   Поля сцены и формат фильма

   Поля по бокам мы знаем заранее — из размеров исходника и кадра фильма,
   искать их по картинке не нужно. Поэтому подсказка не всплывает попапом,
   а живёт в колонке рядом со сценой и появляется только тогда, когда поля
   действительно будут.

   Формат фильма отсюда УЕХАЛ в шапку: он свойство фильма, а не выбранной
   сцены. Рядом эти два блока читались как один прибор из двух половин.
   ============================================================ */

/* Замечание с одним действием — строкой, а не панелью с рамкой и кнопкой */

/* Действие в строке текста: подчёркивание вместо кнопки — оно не спорит
   по весу с настоящими кнопками и не просит себе отдельной плашки. */
.link-action {
  flex: none;
  font-size: 12px;
  font-weight: 500;
  color: var(--color-text);
  border-bottom: 1px solid var(--color-neutral-400);
  padding-bottom: 1px;
  transition: border-color var(--dur) var(--ease);
}
.link-action:hover { color: var(--color-text); border-bottom-color: var(--color-text); }


/* Формат фильма в шапке: словами про то, куда выкладывают, а не цифрами */
.proj-frame-wrap { position: relative; display: inline-flex; align-items: baseline; gap: 6px; }
.proj-dot { color: var(--color-neutral-400); }
.proj-frame {
  /* Строчными: в шапке это продолжение фразы «Мой фильм · вертикальный»,
     а не заголовок. В самом списке варианты остаются с большой буквы. */
  text-transform: lowercase;
  font: 500 13px/1 var(--font-body);
  color: var(--color-neutral-600);
  padding: 4px 6px;
  border-radius: 6px;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.proj-frame:hover, .proj-frame[aria-expanded="true"] { background: var(--color-surface); color: var(--color-text); }

.frame-pick-list {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  z-index: 60;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 6px;
  border-radius: var(--radius-card);
  background: var(--color-bg);
  box-shadow: 0 8px 28px rgba(32, 30, 29, 0.16);
  white-space: nowrap;
}
.frame-pick-list.hidden { display: none; }
.fp {
  text-align: left;
  padding: 7px 12px;
  border-radius: 8px;
  font-size: 13px;
  font-weight: 500;
  color: var(--color-neutral-700);
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.fp:hover { background: var(--color-surface); color: var(--color-text); }
.fp[aria-pressed="true"] { background: var(--color-neutral-200); color: var(--color-text); }


/* Пока тянут картинку в превью — курсор и подсказка о том, что она живая */
.player-wrap.fill-frame video { cursor: grab; }
.player-wrap.fill-frame.dragging video { cursor: grabbing; }

/* Линия примагничивания. Тянется от сцен до музыки — так видно, к какому
   именно стыку прилип кусок. Чернила: красный на ленте занят курсором. */
.snap-guide {
  position: absolute;
  top: var(--scrub-h);
  height: calc(var(--title-h) + var(--track-gap) + var(--gfx-h) + var(--track-gap) + var(--video-h) + var(--track-gap)
             + var(--au-h) + var(--extra-track));
  width: 1px;
  background: var(--color-text);
  pointer-events: none;
  z-index: 5;
}

/* ---------- Своя звуковая дорожка ---------- */
/* Один кусок на весь фильм, от его начала. Живёт по тем же правилам, что и
   волна оригинала: абсолютное положение внутри ленты, высота дорожки. */
.music-track {
  position: absolute;
  top: calc(var(--scrub-h) + var(--title-h) + var(--track-gap) + var(--gfx-h) + var(--track-gap) + var(--video-h) + var(--track-gap) + var(--au-h) + var(--track-gap));
  left: 0; right: 0;
  height: var(--au-h);
  pointer-events: none;
}
/* Вход в пустую дорожку. Пропадает, как только файл есть. */
.music-add {
  position: absolute;
  inset: 0;
  display: flex; align-items: center; gap: 7px;
  padding: 0 10px;
  border-radius: var(--radius-track);
  border: 1px dashed var(--color-neutral-400);
  color: var(--color-neutral-600);
  font: 500 12px/1 var(--font-body);
  pointer-events: auto;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease),
              background var(--dur) var(--ease);
}
.music-add:hover { color: var(--color-text); border-color: var(--color-neutral-600); background: var(--color-neutral-200); }
.tracks-row.has-music .music-add { display: none; }
/* Файл над дорожкой — показываем, что бросать можно сюда */
.music-track.drop-on .music-add { color: var(--color-text); border-color: var(--color-text); background: var(--color-neutral-200); }

.music-seg {
  position: absolute;
  top: 0; bottom: 0; left: 0;
  border-radius: var(--radius-track);
  background: var(--color-neutral-200);
  /* Кусок берут рукой, значит он ловит указатель — в отличие от дорожки */
  pointer-events: auto;
  cursor: grab;
  /* Подпись прячется по ширине САМОГО куска, а не окна */
  container-type: inline-size;
}
.music-seg.dragging { cursor: grabbing; opacity: 0.5; }
/* Выделение — чернилами, как у сцены: красный на ленте остаётся один,
   и это курсор. */
.music-seg.selected::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: var(--radius-track);
  box-shadow: inset 0 0 0 3px var(--color-text);
  pointer-events: none;
}
/* Края для подрезки. Видны у выбранного и под наведением — как у сцен. */
.music-handle {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 12px; height: 22px;
  background: var(--color-neutral-400);
  border-radius: 8px;
  border: 2px solid var(--color-bg);
  opacity: 0;
  cursor: ew-resize;
  transition: opacity var(--dur) var(--ease);
}
.music-handle-l { left: -6px; }
.music-handle-r { right: -6px; }
.music-seg:hover .music-handle,
.music-seg.selected .music-handle { opacity: 1; }
.music-seg.selected .music-handle { background: var(--color-text); }
/* Имя файла — единственный способ понять, что за музыка лежит. Поверх
   волны, поэтому подложка под текстом, а не прозрачность. */
/* Узкий кусок именем не подписываем: оно всё равно превратится в многоточие
   и будет только мешать смотреть на волну. */
@container (max-width: 150px) { .music-name { display: none; } }
.music-name {
  position: absolute;
  left: 8px; top: 50%;
  transform: translateY(-50%);
  max-width: calc(100% - 16px);
  padding: 2px 6px;
  border-radius: 5px;
  background: var(--color-bg);
  font: 500 11px/1.2 var(--font-body);
  color: var(--color-neutral-800);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.music-wave {
  position: absolute;
  left: 6px; top: 4px;
  width: calc(100% - 12px);
  height: calc(100% - 8px);
  display: block;
}
/* Заглушённая дорожка не исчезает — она на месте, просто не звучит */
.music-seg.muted { opacity: 0.45; }

/* Проект без сцен — законное состояние: сначала создают проект, потом
   приносят видео. Всё, что рассказывает о ВЫБРАННОЙ сцене, при этом молчит:
   «Сцена 01 из 1» с нулевой длиной — это неправда на экране. */
.left-col.no-scenes .scene-head,
.left-col.no-scenes .scene-name,
.left-col.no-scenes .value-cards,
.left-col.no-scenes #crop-card { display: none; }

/* ---------- Материалы проекта ---------- */
/* Всё видео, которое принесли в проект. Отличие от «ФАЙЛЫ ПРОЕКТА» ниже:
   там сказано, КАК файл использован в фильме, здесь — что он вообще есть,
   и отсюда его кладут на ленту. */
.bin { margin-top: var(--space-4); }
/* Когда колонка доезжает до блока ТЕКСТ (b261), он встаёт не впритык к
   краю, а с воздухом снизу и сверху (b262). */
#tbin { scroll-margin: 20px 0; }
.bin-head { display: flex; align-items: center; gap: var(--space-2); margin-bottom: var(--space-2); }
.bin-add {
  margin-left: auto;
  width: 22px; height: 22px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 6px;
  color: var(--color-neutral-600);
  transition: color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.bin-add:hover { color: var(--color-text); background: var(--color-neutral-200); }

.bin-list { display: flex; flex-direction: column; gap: 6px; }

/* Плашка материала: карточки лежат внутри своей области, а не растворяются
   в колонке. Пустая она не схлопывается — по ней видно, куда бросать файл. */
/* Плашка: прокручивается только список, а кнопка добавления остаётся дном.
   Уехав вместе с карточками, она пропадала из виду ровно тогда, когда файлов
   стало много, — то есть когда нужна чаще всего. */
.bin-box {
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-height: 260px;
  padding: 6px;
  border-radius: var(--radius-card);
  background: var(--color-neutral-200);
}
.bin-scroll { overflow-y: auto; min-height: 0; }
.bin-box.hidden { display: none; }

/* Добавление живёт внутри плашки, а не в её шапке: приносят файлы туда же,
   где они потом лежат. Пунктир — потому что это место под будущее, а не
   очередная карточка. */
.bin-plus {
  flex: none;
  display: flex; align-items: center; justify-content: center; gap: 7px;
  height: 34px;
  border-radius: 8px;
  border: 1px dashed var(--color-neutral-400);
  color: var(--color-neutral-600);
  font: 500 12px/1 var(--font-body);
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease),
              background var(--dur) var(--ease);
}
.bin-plus:hover {
  color: var(--color-text);
  border-color: var(--color-neutral-600);
  background: var(--color-bg);
}

.bin-item {
  display: flex; align-items: center; gap: var(--space-3);
  padding: 5px;
  border-radius: 8px;
  background: var(--color-surface);
  cursor: grab;
  /* Родное перетаскивание картинки мешает нашему: тянут карточку, а браузер
     тянет изображение. */
  user-select: none; -webkit-user-drag: none;
  transition: background var(--dur) var(--ease);
}
.bin-item:hover { background: var(--color-neutral-300); }
.bin-item.dragging { opacity: 0.4; }

.bin-thumb {
  flex: none;
  width: 62px; height: 36px;
  border-radius: 5px;
  background: var(--color-neutral-300);
  overflow: hidden;
  display: block;
}
.bin-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* У звука кадра нет — вместо него кнопка «послушать» на месте кадра */
.bin-thumb-audio {
  display: flex; align-items: center; justify-content: center;
  color: var(--color-neutral-600);
  transition: color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.bin-listen { cursor: pointer; }
.bin-listen:hover { color: var(--color-text); background: var(--color-neutral-400); }
.bin-listen .ic-stop { display: none; }
.bin-item.listening .bin-listen { color: var(--color-accent); }
.bin-item.listening .bin-listen .ic-listen { display: none; }
.bin-item.listening .bin-listen .ic-stop { display: block; }

.bin-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.bin-name {
  font: 500 12px/1.25 var(--font-body);
  color: var(--color-text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.bin-meta {
  font: 400 11px/1 var(--font-body);
  color: var(--color-neutral-700);
  font-variant-numeric: tabular-nums;
}
/* Сколько сцен из этого ролика уже стоит в фильме. Ноль — значит лежит про
   запас, и это не ошибка. */
.bin-used { color: var(--color-neutral-600); }

/* Пустой блок материалов = призыв начать. Кнопка во всю ширину колонки:
   промахнуться мимо единственного действия на экране нельзя. */
.bin-empty { display: flex; flex-direction: column; align-items: stretch; gap: 8px; }
.bin-empty.hidden { display: none; }
.bin-first { width: 100%; justify-content: center; height: 42px; font-size: 14px; font-weight: 600; }
.bin-drop-note {
  text-align: center;
  font: 400 12px/1.35 var(--font-body);
  color: var(--color-neutral-700);
}
/* Файл тащат над окном — показываем, что бросить можно прямо сюда */
.bin-empty.drop-on .bin-first { box-shadow: var(--shadow-sm); }
.bin-empty.drop-on .bin-drop-note { color: var(--color-text); }

.bin-hint {
  margin-top: var(--space-2);
  font: 400 11px/1.35 var(--font-body);
  color: var(--color-neutral-600);
}
.bin-hint.hidden { display: none; }

/* Карточка, летящая за рукой. Живёт поверх всего и указатель не ловит. */
.bin-ghost {
  position: fixed;
  z-index: 60;
  pointer-events: none;
  display: flex; align-items: center; gap: 8px;
  padding: 5px 9px 5px 5px;
  border-radius: 8px;
  background: var(--color-bg);
  box-shadow: 0 10px 26px -8px rgba(32, 30, 29, 0.45);
  font: 500 12px/1 var(--font-body);
  color: var(--color-text);
}
.bin-ghost .bin-thumb { width: 48px; height: 28px; }

/* ---------- Размер и положение кадра ---------- */
/* Панель стоит под кадром, в поле превью: правят ровно то, на что смотрят.
   Кнопка, которая её открывает, живёт в рабочей полосе — вместе с прочими
   инструментами сцены. */
.crop-panel {
  position: absolute;
  left: 50%;
  bottom: 10px;
  transform: translateX(-50%);
  z-index: 6;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: 8px 12px;
  border-radius: var(--radius-card);
  background: var(--color-bg);
  box-shadow: 0 10px 30px -10px rgba(32, 30, 29, 0.45);
  white-space: nowrap;
}
.crop-panel.hidden { display: none; }
.crop-panel-label {
  font: var(--font-heading-weight) 10px/1 var(--font-heading);
  letter-spacing: 0.1em;
  color: var(--color-neutral-600);
}
.crop-zoom { width: 160px; accent-color: var(--color-accent); }
.crop-zoom-val {
  min-width: 42px;
  font: 500 12px/1 var(--font-body);
  color: var(--color-text);
  font-variant-numeric: tabular-nums;
}
.crop-panel-btn { height: 30px; padding: 0 14px; font-size: 12px; }
/* Поле ввода в окне вопроса — по образцу .field-box, только в одну строку */
.ask-input {
  flex: 1; min-width: 180px; height: 30px; padding: 0 10px;
  background: var(--color-neutral-100); border: 1px solid var(--color-neutral-300); border-radius: 8px;
  font: 500 13px/1 var(--font-body); color: var(--color-text);
  transition: border-color var(--dur) var(--ease);
}
.ask-input:focus { outline: none; border-color: var(--color-neutral-800); }

/* Пока титр выбран, его двигают прямо по кадру */
.player-wrap.title-move .frame-clip { cursor: move; }

/* ---------- Убрать паузы ---------- */
/* Панель встаёт НА МЕСТО кнопок в той же рабочей полосе: высота та же,
   раскладка не прыгает. Пока она открыта, остальные глаголы не нужны —
   правят фильм целиком, а не выбранную сцену. */
.pause-panel {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  white-space: nowrap;
}
.pause-panel.hidden { display: none; }
.pause-label {
  font: var(--font-heading-weight) 10px/1 var(--font-heading);
  letter-spacing: 0.1em;
  color: var(--color-neutral-600);
}
.pause-range { width: 150px; accent-color: var(--color-accent); }
/* Место под строку отведено заранее: она меняется на каждом движении
   ползунка, и без своей ширины таскала бы за собой кнопки. */
.pause-stat {
  min-width: 340px;
  font: 500 12px/1 var(--font-body);
  color: var(--color-text);
  font-variant-numeric: tabular-nums;
}
.pause-panel-btn { height: 30px; padding: 0 14px; font-size: 12px; }

/* Пока меняют размер, картинку тянут рукой — курсор об этом и говорит */
.player-wrap.cropping .frame-clip { cursor: grab; }
.player-wrap.cropping.dragging .frame-clip { cursor: grabbing; }

/* ---------- Громкость дорожек ---------- */
/* Ползунок вертикальный и появляется НАД динамиком: громче — выше, тише —
   ниже, как на любом пульте. Ноль ровно посередине — «как в файле». */
/* Место под всё отведено заранее: и динамик, и подпись стоят на фиксированных
   позициях. Иначе подпись меняет ширину на каждом движении ползунка («−0.5» →
   «−12.0» → «выкл» → пусто) и таскает за собой значок. */
.vol-wrap { position: relative; display: flex; align-items: center; gap: 4px; margin-left: auto; flex: none; }
.vol-wrap .th-mute { margin-left: 0; }

/* Всплывашка примыкает к динамику ВПЛОТНУЮ, а зазор делается её же
   прозрачным полем: между кнопкой и ползунком не должно быть дырки, через
   которую курсор «выпадает» и всё закрывается. */
.vol-pop {
  position: absolute;
  bottom: 100%;
  left: 50%;
  transform: translateX(-50%);
  z-index: 12;
  display: none;
  padding-bottom: 8px;
}
.vol-card {
  display: block;
  padding: 8px 6px;
  border-radius: 10px;
  background: var(--color-bg);
  box-shadow: 0 10px 26px -8px rgba(32, 30, 29, 0.45);
}
/* Держим открытым и пока тянут: увели курсор за габарит — ползунок не должен
   исчезать из-под руки. */
.vol-wrap:hover .vol-pop,
.vol-wrap.holding .vol-pop { display: block; }

.vol-range {
  writing-mode: vertical-lr;
  direction: rtl;               /* верх = громче */
  width: 18px;
  height: 96px;
  accent-color: var(--color-accent);
}

/* Насколько отклонились от «как в файле». Красным — потому что это правка
   человека поверх исходника, как и всё остальное, что он тронул. */
.vol-num {
  flex: none;
  width: 34px;              /* «−12.0» — самая длинная надпись */
  font: 500 10px/1 var(--font-body);
  color: var(--color-accent);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
/* Пусто — но место остаётся: убирать его значит двигать соседей.
   Свой класс, а не общий .hidden: тот выключает элемент насовсем. */
.vol-num.off { visibility: hidden; }
