/* Редактор монтажа (шаг «Сборка»). Токены и правила — DESIGN_SYSTEM.md; переменные --fb-* объявлены
   в tokens.css, он подключён первым.

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

/* Диалог шире стандартных Mud-размеров: на таймлайне важна длина, а не высота. */
.tl-modal {
    width: min(1560px, 96vw) !important;
    max-width: none !important;
}

/* `minmax(0, 1fr)`, а не `1fr`: минимум строки по умолчанию — её min-content, и схема кадра (у неё
   своя высота) выдавливала бы дорожки. Дорожек шесть, они важнее лишней сотни пикселей у кадра. */
.tl-dialog {
    display: grid;
    grid-template-rows: minmax(0, 1fr) auto;
    gap: 0;
    height: min(880px, 86vh);
    background: var(--fb-bg);
}

/* ---------- верх: материалы | кадр | клип ---------- */

.tl-top {
    display: grid;
    grid-template-columns: 232px 1fr 380px;
    min-height: 0;
    border-bottom: 1px solid var(--fb-line);
}

.tl-rail,
.tl-panel {
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
}

.tl-rail {
    padding: 14px 12px;
    border-right: 1px solid var(--fb-line);
}

.tl-panel {
    padding: 14px 16px;
    border-left: 1px solid var(--fb-line);
}

.tl-section {
    font-family: var(--fb-ui);
    font-size: 9px;
    font-weight: 800;
    letter-spacing: var(--fb-tr-eyebrow);
    text-transform: uppercase;
    color: var(--fb-ink-dim);
}

.tl-hint {
    margin-top: 6px;
    font-size: 11.5px;
    line-height: 1.5;
    color: var(--fb-ink-dim);
}

/* ---------- материалы ---------- */

.tl-source {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    margin-top: 6px;
    padding: 7px 9px;
    border: 1px solid var(--fb-line);
    border-radius: 8px;
    background: var(--fb-grad);
    color: var(--fb-ink);
    font-family: var(--fb-ui);
    font-size: 12.5px;
    text-align: left;
    cursor: grab;
    transition: border-color .12s ease, opacity .15s ease;
}

.tl-source:hover { border-color: var(--fb-primary); }
.tl-source:active { cursor: grabbing; }

/* Материал уже разложен — приглушаем, но оставляем: один источник кладут на таймлайн и дважды. */
.tl-source.is-used { opacity: .45; }

/*
   Субтитры на дорожку не кладут — их нажимают, чтобы открыть оформление. Отсюда курсор указателя
   вместо «схватить» и подсветка выбранной строки: панель справа показывает именно её.
*/
.tl-source.is-picked,
.tl-source[draggable="false"] { cursor: pointer; }

.tl-source.is-picked {
    border-color: var(--fb-primary);
    box-shadow: inset 0 0 0 1px var(--fb-primary);
}

.tl-source-dot {
    flex: none;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--t, var(--fb-t-none));
}

.tl-source-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.tl-source-kind {
    margin-left: auto;
    flex: none;
    font-family: var(--fb-mono);
    font-size: 9.5px;
    color: var(--fb-ink-dim);
}

/* ---------- схема кадра ---------- */

.tl-stage {
    display: grid;
    grid-template-rows: 1fr auto;
    justify-items: center;
    gap: 10px;
    min-height: 0;
    padding: 14px;
    background: var(--fb-canvas);
}

/* Растянутая обёртка с определённой высотой: без неё `height: 100%` кадра не к чему привязать. */
.tl-stage-fit {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
    min-height: 0;
}

/* Утопленная площадка, как превью ноды: это окно в продукт, а не элемент управления.
   Размер задаётся по ведущей стороне, а не через max-width/max-height: `aspect-ratio` у пустого
   блока не даёт собственного размера вовсе, и кадр схлопывался в пару пикселей. Вертикали ведёт
   высота (иначе кадр вылезал бы вниз), горизонтали — ширина (иначе за колонку вбок). */
.tl-frame {
    position: relative;
    border: 1px solid var(--fb-line);
    border-radius: 8px;
    background: var(--fb-screen);
    overflow: hidden;
    touch-action: none;
}

.tl-frame.is-vertical {
    height: min(100%, 440px);
    width: auto;
}

.tl-frame.is-horizontal {
    width: min(100%, 620px);
    height: auto;
}

.tl-frame-empty {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0 24px;
    text-align: center;
    font-family: var(--fb-mono);
    font-size: 10.5px;
    line-height: 1.6;
    color: var(--fb-screen-ink-dim);
}

/* Примерка текста: настоящий кадр из FFmpeg во всю рамку. Событий не ловит — тянуть клип мышью
   по-прежнему нужно за его прямоугольник, который лежит выше по дереву. */
.tl-frame-preview {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: contain;
    pointer-events: none;
}

/* Пока примерка на экране, прямоугольники клипов остаются только рамками: их заливка закрасила бы
   ровно то, ради чего примерку и открыли. */
.tl-frame:has(.tl-frame-preview) .tl-box {
    background: transparent;
}

/* Прямоугольник клипа в кадре. Содержимого у него нет и быть не может — рендера до прогона не
   существует, поэтому показываем имя источника и цвет типа, а не выдуманный кадр. */
.tl-box {
    position: absolute;
    display: flex;
    align-items: flex-start;
    padding: 5px 6px;
    border: 1px solid color-mix(in srgb, var(--t, var(--fb-t-none)) 70%, transparent);
    border-radius: 4px;
    background: color-mix(in srgb, var(--t, var(--fb-t-none)) 12%, transparent);
    font-family: var(--fb-mono);
    font-size: 9.5px;
    color: var(--fb-screen-ink);
    overflow: hidden;
    cursor: move;
}

.tl-box.is-selected {
    border-color: var(--fb-primary);
    box-shadow: var(--fb-ring);
}

.tl-box.is-text {
    align-items: flex-start;
    background: var(--fb-overlay);
    border-style: dashed;
}

/* Ручка размера — только у выделенного: у остальных она была бы шумом на маленькой схеме. */
.tl-box-grip {
    position: absolute;
    right: -5px;
    bottom: -5px;
    width: 11px;
    height: 11px;
    border: 1px solid var(--fb-primary);
    border-radius: 3px;
    background: var(--fb-bg);
    cursor: nwse-resize;
}

.tl-stage-note {
    font-family: var(--fb-mono);
    font-size: 10px;
    color: var(--fb-ink-dim);
}

/* ---------- таймлайн ---------- */

.tl-bottom {
    display: flex;
    flex-direction: column;
    min-height: 0;
    background: var(--fb-canvas);
}

/* Шесть дорожек в высокий попап влезают, в низкий — нет, поэтому прокрутка у таймлайна теперь по
   обеим осям: раньше вертикальная была спрятана, и дорожка просто обрезалась молча. */
.tl-scroll {
    min-height: 0;
    overflow: auto;
    padding: 0 0 10px;
}

/* Точка отсчёта для линии привязки: она идёт через все дорожки, а не внутри одной. */
.tl-grid {
    position: relative;
    min-width: max-content;
}

/* Момент, к которому привязан выбранный клип. Пунктир — тот же «этого ещё нет»/«это не материал,
   а отношение», которым на канвасе рисуется провод в руке. */
.tl-anchor-line {
    position: absolute;
    top: 20px;
    bottom: 0;
    width: 0;
    border-left: 1px dashed var(--fb-primary);
    opacity: .8;
    pointer-events: none;
    z-index: 5;
}

/* Линейка. Числа машинные — моноширинные и тихие. */
.tl-ruler {
    position: relative;
    height: 20px;
    margin-left: var(--head, 92px);
    border-bottom: var(--fb-div);
}

.tl-tick {
    position: absolute;
    bottom: 0;
    width: 1px;
    height: 5px;
    background: var(--fb-wire);
}

.tl-tick.is-major { height: 9px; background: var(--fb-ink-faint); }

.tl-tick-label {
    position: absolute;
    bottom: 9px;
    transform: translateX(-50%);
    font-family: var(--fb-mono);
    font-size: 9.5px;
    color: var(--fb-ink-dim);
    white-space: nowrap;
}

.tl-track {
    display: flex;
    align-items: stretch;
    border-bottom: var(--fb-div);
}

.tl-track-head {
    flex: none;
    width: var(--head, 92px);
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 2px;
    padding: 6px 10px;
    border-right: var(--fb-div);
}

.tl-track-id {
    font-family: var(--fb-mono);
    font-size: 11px;
    color: var(--fb-ink);
}

/* Эталон красится Primary, а не жёлтым: жёлтый в системе значит ровно «ждёт человека» (§2). */
.tl-master {
    align-self: flex-start;
    padding: 1px 5px;
    border-radius: 4px;
    border: 1px solid transparent;
    background: var(--fb-primary-soft);
    color: var(--fb-primary);
    font-family: var(--fb-mono);
    font-size: 9px;
    cursor: default;
}

.tl-master-set {
    align-self: flex-start;
    padding: 1px 5px;
    border: 1px solid var(--fb-line);
    border-radius: 4px;
    background: none;
    color: var(--fb-ink-dim);
    font-family: var(--fb-mono);
    font-size: 9px;
    cursor: pointer;
    transition: border-color .12s ease, color .12s ease;
}

.tl-master-set:hover { border-color: var(--fb-primary); color: var(--fb-ink); }

/* Клипы стоят по абсолютному времени, а не цепочкой во flex: привязка разрешает наложение, а
   цепочка нарисовала бы привязанный клип правее его настоящего места. Отсюда же требование к
   отступам: содержимое дорожки обязано начинаться там же, где нулевая засечка линейки. */
.tl-lane {
    position: relative;
    flex: 1;
    min-width: 320px;
    height: 46px;
    padding: 0;
}

.tl-lane.is-target { background: var(--fb-primary-soft); }

/* Дорожка не принимает этот материал (аудио в видеоряд) — говорим об этом заранее, а не после броска. */
.tl-lane.is-denied { background: var(--fb-danger-soft); }

.tl-lane-empty {
    position: absolute;
    top: 50%;
    left: 10px;
    transform: translateY(-50%);
    font-family: var(--fb-mono);
    font-size: 10px;
    color: var(--fb-ink-dim);
    pointer-events: none;
}

/* ---------- клип ---------- */

.tl-clip {
    position: absolute;
    top: 4px;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 2px;
    height: 38px;
    padding: 5px 8px;
    border: 1px solid color-mix(in srgb, var(--t, var(--fb-t-none)) 55%, var(--fb-line));
    border-radius: 6px;
    background: linear-gradient(180deg,
        color-mix(in srgb, var(--t, var(--fb-t-none)) 22%, var(--fb-surface)),
        var(--fb-surface));
    color: var(--fb-ink);
    text-align: left;
    overflow: hidden;
    cursor: grab;
    transition: box-shadow .15s ease, border-color .12s ease;
}

.tl-clip:active { cursor: grabbing; }

.tl-clip.is-selected {
    border-color: var(--fb-primary);
    box-shadow: var(--fb-ring);
}

.tl-clip.is-error {
    border-color: var(--fb-danger);
    background: linear-gradient(180deg, var(--fb-danger-soft), var(--fb-surface));
}

.tl-clip-name {
    font-family: var(--fb-ui);
    font-size: 11.5px;
    line-height: 1.1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.tl-clip-time {
    font-family: var(--fb-mono);
    font-size: 9.5px;
    color: var(--fb-ink-dim);
    white-space: nowrap;
}

/* Длительность станет известна только в прогоне. Правая кромка растворяется штриховкой — тем же
   «этого ещё нет», которым говорят пунктирный провод в руке и пустой обязательный порт. */
.tl-clip.is-auto::after {
    content: "";
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    width: 34px;
    background:
        linear-gradient(90deg, transparent, var(--fb-canvas-fade)),
        repeating-linear-gradient(135deg,
            color-mix(in srgb, var(--t, var(--fb-t-none)) 26%, transparent) 0 2px,
            transparent 2px 6px);
    pointer-events: none;
}

/* Значок привязки: клип стоит не в свою очередь, а в момент чужого клипа. Мелкий и тихий — это
   пометка о том, откуда взялась позиция, а не элемент управления. */
.tl-clip-anchor {
    position: absolute;
    top: 2px;
    right: 3px;
    font-size: 9px;
    line-height: 1;
    opacity: .75;
    pointer-events: none;
}

/* Пауза перед клипом: пустое место, отчёркнутое от клипа. */
.tl-gap {
    position: absolute;
    top: 4px;
    bottom: 4px;
    border-right: 1px dashed var(--fb-line);
    pointer-events: none;
}

/* Цель для броска «вставить перед этим клипом». Видна только пока над клипом что-то тащат. */
.tl-clip.is-before {
    box-shadow: inset 3px 0 0 var(--fb-primary);
}

/* ---------- подвал ---------- */

.tl-hud {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 8px 16px;
    border-top: 1px solid var(--fb-line);
    font-family: var(--fb-mono);
    font-size: 11px;
    color: var(--fb-ink-dim);
}

.tl-hud .is-error { color: var(--fb-danger); }
.tl-hud .is-warn { color: var(--fb-await); }

@media (max-width: 1240px) {
    .tl-top { grid-template-columns: 200px 1fr 320px; }
}

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

.subs-anchor {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 3px;
    width: 84px;
    margin: 6px 0 2px;
    padding: 3px;
    border: 1px solid var(--fb-line);
    border-radius: 5px;
}

.subs-anchor-cell {
    display: flex;
    align-items: center;
    justify-content: center;
    aspect-ratio: 9 / 14;
    padding: 0;
    border: 0;
    border-radius: 3px;
    background: color-mix(in srgb, var(--fb-ink) 6%, transparent);
    cursor: pointer;
}

.subs-anchor-cell:hover { background: color-mix(in srgb, var(--fb-ink) 14%, transparent); }

.subs-anchor-cell span {
    width: 60%;
    height: 3px;
    border-radius: 2px;
    background: var(--fb-ink-dim);
}

.subs-anchor-cell.is-on { background: color-mix(in srgb, var(--fb-primary) 28%, transparent); }
.subs-anchor-cell.is-on span { background: var(--fb-primary); }
