/* ContentFactory — оформление диспетчерской.
   Направление: производственный пульт. Графит, янтарный акцент, крупная типографика. */
:root{
  --bg:#0d0e10; --bg-card:#16181c; --bg-sunk:#111316; --line:#24272d; --line-soft:#1d2026;
  --ink:#f2f0ec; --ink-dim:#8b9099; --ink-faint:#5c626d;
  --amber:#ffab2e; --amber-deep:#c97f14; --green:#4ade80; --red:#ff5a5a;
}
*{box-sizing:border-box;margin:0;padding:0}
body{
  background:var(--bg);color:var(--ink);
  font-family:'Onest',system-ui,sans-serif;font-weight:300;font-size:15px;line-height:1.55;
  min-height:100vh;-webkit-font-smoothing:antialiased;
  background-image:
    radial-gradient(1000px 560px at 82% -10%,rgba(255,171,46,.075),transparent 62%),
    radial-gradient(760px 460px at 2% 108%,rgba(255,171,46,.03),transparent 66%);
  background-attachment:fixed;
}
body::after{content:'';position:fixed;inset:0;pointer-events:none;z-index:99;opacity:.2;
  background-image:repeating-linear-gradient(0deg,rgba(255,255,255,.022) 0 1px,transparent 1px 3px)}
a{color:inherit}
/* Спрятанное спрятано. Браузер скрывает [hidden] правилом display:none, и любой
   наш `display:flex` по классу его перебивает: форма правки, скрытая у клипа,
   осталась на месте и предлагала переделать словами то, что переделывается
   только новым заказом. */
[hidden]{display:none!important}

/* Вся панель крупнее на 10 %.
   Размеры в этом файле заданы в пикселях, поэтому корневой font-size их не
   двигает: масштабируется весь слой целиком. Zoom, а не transform: transform
   не меняет поток и оставил бы полосы прокрутки от прежнего размера. */
.shell{zoom:1.1}

/* Горизонтальной шапки нет: её место занял постоянный боковой столбец со всеми
   разделами. Правила для неё убраны — мёртвый CSS переживает вёрстку и потом
   молча влияет на новые классы с теми же именами. */
.dot{width:7px;height:7px;border-radius:50%;background:var(--green);animation:beat 2.6s infinite}
.dot.bad{background:var(--red)}
@keyframes beat{0%{box-shadow:0 0 0 0 rgba(74,222,128,.5)}70%{box-shadow:0 0 0 9px rgba(74,222,128,0)}100%{box-shadow:0 0 0 0 rgba(74,222,128,0)}}

/* ── кнопки ── */
/* Базовый вид задан здесь, а не только у btn-primary/btn-ghost: кнопка без
   модификатора доставалась браузеру, и он рисовал её белой прямоугольной
   кляксой посреди графитовой панели. Своего вида у «просто кнопки» не было
   вовсе — а таких в разделе «Замысел» половина. */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:9px;cursor:pointer;
  font-family:'Onest',sans-serif;font-size:14px;font-weight:500;letter-spacing:-.01em;
  padding:11px 20px;border-radius:10px;text-decoration:none;
  background:var(--bg-sunk);color:var(--ink);border:1px solid var(--line);
  transition:transform .16s,box-shadow .16s,background .16s,border-color .16s}
.btn:hover{border-color:var(--amber-deep)}
.btn-primary,.btn-ghost{border-color:transparent}
.btn-primary{background:var(--amber);color:#20160a;box-shadow:0 6px 22px rgba(255,171,46,.18)}
.btn-primary:hover{transform:translateY(-1px);box-shadow:0 9px 28px rgba(255,171,46,.28)}
.btn-ghost{background:transparent;color:var(--ink-dim);border:1px solid var(--line)}
.btn-ghost:hover{color:var(--ink);border-color:var(--ink-faint)}
.btn[disabled]{opacity:.4;cursor:not-allowed;transform:none;box-shadow:none}

/* ── сетка доски ── */
.grid{display:grid;grid-template-columns:minmax(0,1fr) 330px;gap:22px;align-items:stretch}
.col{display:flex;flex-direction:column;gap:22px;animation:rise .5s cubic-bezier(.2,.7,.3,1) both}
.col.side{align-self:start;animation-delay:.08s}
.panel.grow{flex:1;display:flex;flex-direction:column}
.panel.grow .empty{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center}
@keyframes rise{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}

.panel{background:var(--bg-card);border:1px solid var(--line-soft);border-radius:15px;overflow:hidden}
.panel-head{display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:15px 20px;border-bottom:1px solid var(--line-soft)}
.panel-head h2{font-family:'Unbounded',sans-serif;font-weight:600;font-size:12px;
  letter-spacing:.13em;text-transform:uppercase;color:var(--ink-dim)}
.panel-head .hint{font-family:'JetBrains Mono',monospace;font-size:11.5px;color:var(--ink-faint)}
.panel-body{padding:22px}

/* ── следующий шаг ── */
.next{position:relative;border:1px solid var(--line);border-radius:15px;overflow:hidden;
  background:linear-gradient(122deg,#1c1e23 0%,#141619 62%)}
.next::before{content:'';position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--amber)}
.next-in{padding:26px 30px;display:flex;align-items:center;justify-content:space-between;gap:28px}
.next .lbl{font-family:'JetBrains Mono',monospace;font-size:11px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--amber-deep);margin-bottom:11px}
.next h3{font-family:'Unbounded',sans-serif;font-weight:600;font-size:21px;
  letter-spacing:-.015em;margin-bottom:9px}
.next p{color:var(--ink-dim);font-size:14.5px;max-width:60ch}
.next .act{display:flex;flex-direction:column;gap:9px;flex:none;min-width:210px}

/* ── конвейер ── */
.flow{display:flex;align-items:stretch;gap:0}
.node{flex:1;padding:14px 12px 15px;border-radius:11px;background:var(--bg-sunk);
  border:1px solid transparent;transition:border-color .2s,background .2s;min-width:0}
.node:hover{border-color:var(--line);background:#14171b}
.node .n{font-family:'JetBrains Mono',monospace;font-size:10.5px;color:var(--ink-faint);
  display:block;margin-bottom:6px}
.node .t{font-size:13.5px;font-weight:500;letter-spacing:-.01em}
.node .s{font-size:11.5px;color:var(--ink-faint);margin-top:3px;line-height:1.35}
.node.idle .t{color:var(--ink-dim)}
.arrow{flex:none;width:22px;display:flex;align-items:center;justify-content:center;color:var(--line)}
.arrow svg{width:11px;height:11px}

/* ── пустые состояния ── */
.empty{text-align:center;padding:34px 24px}
.empty .ic{width:52px;height:52px;margin:0 auto 16px;border-radius:14px;background:var(--bg-sunk);
  border:1px solid var(--line-soft);display:flex;align-items:center;justify-content:center;
  font-size:22px;color:var(--ink-faint)}
.empty h4{font-family:'Unbounded',sans-serif;font-weight:400;font-size:15px;margin-bottom:7px}
.empty p{color:var(--ink-faint);font-size:13.5px;max-width:46ch;margin:0 auto 18px}
.empty .btn{margin:0 auto}

/* ── списки ── */
.rows{display:flex;flex-direction:column}
.row{display:flex;align-items:center;gap:12px;padding:12px 20px;
  border-bottom:1px solid var(--line-soft);transition:background .18s}
.row:last-child{border-bottom:0}
.row:hover{background:rgba(255,255,255,.014)}
.led{width:8px;height:8px;border-radius:50%;flex:none}
.up .led{background:var(--green);box-shadow:0 0 10px rgba(74,222,128,.45)}
.down .led{background:var(--red);box-shadow:0 0 10px rgba(255,90,90,.4)}
.row .nm{font-size:14px;flex:1;min-width:0;letter-spacing:-.01em;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.row .st{font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--ink-faint);flex:none}
.down .st{color:#cf7b80}

.lang-row{display:flex;flex-direction:column;gap:5px;padding:13px 20px;
  border-bottom:1px solid var(--line-soft)}
.lang-row:last-child{border-bottom:0}
.lang-main{display:flex;align-items:center;justify-content:space-between;gap:10px}
.lang-row .code{font-family:'Unbounded',sans-serif;font-weight:600;font-size:14px;letter-spacing:-.01em}
.lang-row .voice{font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--ink-faint)}
.chip{font-family:'JetBrains Mono',monospace;font-size:10px;letter-spacing:.05em;
  padding:3px 8px;border-radius:20px;background:rgba(139,144,153,.11);color:var(--ink-dim);flex:none}

.road{display:flex;align-items:center;gap:11px;padding:9px 20px;font-size:13.5px;color:var(--ink-faint)}
.road .mark{font-family:'JetBrains Mono',monospace;font-size:12px;width:12px;flex:none;text-align:center}
.road.done{color:var(--ink-dim)}
.road.done .mark{color:var(--green)}
.road.cur{color:var(--ink);font-weight:500;background:rgba(255,171,46,.05)}
.road.cur .mark{color:var(--amber)}

/* ── формы ── */
.field{margin-bottom:20px}
.field label{display:block;font-size:13.5px;font-weight:500;margin-bottom:6px;letter-spacing:-.01em}
.field .note{font-size:12.5px;color:var(--ink-faint);margin-bottom:9px}
/* Виды полей перечислены явно, но списком: пока стояло только `type=text`, поле
   пароля и числовое поле выпадали из оформления и выглядели сломанными — белые
   прямоугольники посреди тёмной формы (подключение витрины, 01.08.2026). */
input[type=text],input[type=password],input[type=number],input[type=datetime-local],
input[type=url],input[type=email],textarea,select{
  width:100%;background:var(--bg-sunk);border:1px solid var(--line);border-radius:10px;
  padding:12px 14px;color:var(--ink);font-family:'Onest',sans-serif;font-size:14.5px;
  font-weight:300;transition:border-color .18s,background .18s}
input[type=text]:focus,input[type=password]:focus,input[type=number]:focus,
input[type=datetime-local]:focus,input[type=url]:focus,input[type=email]:focus,
textarea:focus,select:focus{
  outline:0;border-color:var(--amber-deep);background:#14171b}
textarea{min-height:110px;resize:vertical;line-height:1.6}
.picks{display:flex;flex-wrap:wrap;gap:10px}
.pick{display:flex;align-items:center;gap:13px;padding:12px 17px;border-radius:11px;
  background:var(--bg-sunk);border:1px solid var(--line);cursor:pointer;
  transition:border-color .18s,background .18s}
.pick:hover{border-color:var(--ink-faint)}
.pick input{accent-color:var(--amber);width:16px;height:16px;cursor:pointer;flex:none}
.pick:has(input:checked){border-color:var(--amber-deep);background:rgba(255,171,46,.06)}
.pick .pn{font-size:14px}
.pick .pv{font-family:'JetBrains Mono',monospace;font-size:10px;color:var(--ink-dim);letter-spacing:.05em;padding:3px 7px;border-radius:20px;background:rgba(139,144,153,.13);margin-left:2px}
.form-act{display:flex;gap:11px;align-items:center;padding-top:6px}
.form-act.center{justify-content:center}

/* ── страница настройки ── */
.state{display:flex;align-items:center;gap:12px;padding:15px 20px;border-radius:12px;
  background:var(--bg-sunk);border:1px solid var(--line-soft);margin-bottom:22px}
.state .nm{flex:1;font-size:14.5px}
.steps{counter-reset:s;list-style:none}
.steps li{counter-increment:s;position:relative;padding:0 0 16px 40px;font-size:14.5px;
  color:var(--ink-dim);line-height:1.6}
.steps li::before{content:counter(s);position:absolute;left:0;top:1px;width:25px;height:25px;
  border-radius:8px;background:var(--bg-sunk);border:1px solid var(--line);
  font-family:'JetBrains Mono',monospace;font-size:11.5px;color:var(--amber);
  display:flex;align-items:center;justify-content:center}
.steps li b{color:var(--ink);font-weight:500}
code{font-family:'JetBrains Mono',monospace;font-size:12.5px;color:var(--amber);
  background:rgba(255,171,46,.08);padding:2px 7px;border-radius:5px}
.msg{border-radius:12px;padding:14px 18px;margin-bottom:22px;font-size:14px}
.msg.err{border:1px solid #63262a;background:rgba(255,90,90,.08);color:#ffb3b3}
.msg.ok{border:1px solid #276b41;background:rgba(74,222,128,.08);color:#a9edc4}

.maint{border:1px solid var(--amber-deep);background:rgba(255,171,46,.07);border-radius:13px;
  padding:15px 19px;margin-bottom:22px;display:flex;gap:12px;align-items:flex-start;font-size:14px}
.maint b{font-weight:600;color:var(--amber)}
footer{margin-top:26px;padding-top:16px;border-top:1px solid var(--line-soft);
  display:flex;justify-content:space-between;font-family:'JetBrains Mono',monospace;
  font-size:11px;color:var(--ink-faint)}
p.lede{color:var(--ink-dim);font-size:15px;max-width:70ch;margin-bottom:26px}

@media(max-width:1150px){.grid{grid-template-columns:1fr}
  .flow{flex-wrap:wrap;gap:8px}.node{flex:1 1 140px}.arrow{display:none}}
@media(max-width:680px){
  .next-in{flex-direction:column;align-items:flex-start;gap:20px}
  .next .act{width:100%;min-width:0}
  .facts{grid-template-columns:repeat(2,minmax(0,1fr))}
  .version{flex-direction:column;align-items:stretch;gap:14px}
  .version-act{align-items:stretch}
  .version-act .btn{width:100%}}

/* ── сценарий с языковыми версиями ── */
.script{display:block;text-decoration:none;padding:18px 20px;
  border-bottom:1px solid var(--line-soft);transition:background .16s}
.script:hover{background:rgba(255,255,255,.02)}
.script:hover .script-name{color:var(--amber)}
.script:last-child{border-bottom:0}
.script-top{display:flex;align-items:center;justify-content:space-between;gap:14px;margin-bottom:13px}
.script-name{font-size:15.5px;font-weight:500;letter-spacing:-.01em}
.vers{display:grid;grid-template-columns:repeat(auto-fill,minmax(158px,1fr));gap:9px}
.ver{display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding:10px 13px;border-radius:10px;background:var(--bg-sunk);
  border:1px solid var(--line-soft);transition:border-color .18s}
.ver:hover{border-color:var(--line)}
.ver.ok{border-color:rgba(74,222,128,.28);background:rgba(74,222,128,.05)}
.ver .vl{font-size:13.5px;font-weight:400}
.ver .vs{font-family:'JetBrains Mono',monospace;font-size:10.5px;color:var(--ink-faint)}
.ver.ok .vs{color:var(--green)}

/* ── каркас с боковым меню ── */
.shell{display:grid;grid-template-columns:246px minmax(0,1fr);min-height:100vh}
.sidebar{position:sticky;top:0;align-self:start;height:100vh;display:flex;flex-direction:column;
  background:#101215;border-right:1px solid var(--line);padding:24px 0 18px}
.sb-brand{padding:0 22px 22px;border-bottom:1px solid var(--line-soft);margin-bottom:18px;
  text-decoration:none;display:block}
.sb-brand h1{font-family:'Unbounded',sans-serif;font-weight:800;font-size:18px;letter-spacing:-.02em}
.sb-brand h1 span{color:var(--amber)}
.sb-brand .sub{font-size:10.5px;color:var(--ink-faint);letter-spacing:.16em;
  text-transform:uppercase;margin-top:5px}
.sb-group{padding:0 12px;margin-bottom:20px}
.sb-title{font-family:'JetBrains Mono',monospace;font-size:10px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--ink-faint);padding:0 10px 9px}
.sb-link{display:flex;align-items:center;gap:11px;padding:9px 11px;border-radius:9px;
  text-decoration:none;color:var(--ink-dim);font-size:14px;transition:background .16s,color .16s;
  margin-bottom:2px}
.sb-link:hover{background:rgba(255,255,255,.035);color:var(--ink)}
.sb-link.on{background:rgba(255,171,46,.1);color:var(--ink);font-weight:500}
.sb-link.on .ico{color:var(--amber)}
.sb-link .ico{width:17px;flex:none;text-align:center;font-size:13px;color:var(--ink-faint)}
.sb-link .cnt{margin-left:auto;font-family:'JetBrains Mono',monospace;font-size:10.5px;
  color:var(--ink-faint);background:rgba(139,144,153,.12);padding:2px 7px;border-radius:20px}
.sb-foot{margin-top:auto;padding:16px 22px 0;border-top:1px solid var(--line-soft)}
.sb-stat{display:flex;align-items:baseline;justify-content:space-between;margin-bottom:9px;
  text-decoration:none;color:inherit;border-radius:8px;transition:background .15s}
.sb-stat:hover{background:rgba(255,255,255,.05)}
.sb-stat .v{font-family:'Unbounded',sans-serif;font-weight:600;font-size:16px}
.sb-stat .k{font-size:11.5px;color:var(--ink-faint)}

/* Раздел «Затраты»: итоги сверху, под ними три разреза одного журнала. Доля
   показана полоской — длину глаз читает быстрее, чем проценты. */
.sum-top{display:flex;gap:14px;flex-wrap:wrap}
.sum-card{flex:1 1 160px;background:var(--bg-card);border:1px solid var(--line-soft);
  border-radius:14px;padding:16px 18px;display:flex;flex-direction:column;gap:4px}
.sum-card.big{flex:1 1 240px;border-color:rgba(255,179,0,.35)}
.sum-k{font-size:11.5px;color:var(--ink-faint);letter-spacing:.02em}
.sum-v{font-family:'Unbounded',sans-serif;font-weight:600;font-size:26px}
.sum-card.big .sum-v{color:var(--amber)}
.sum-note{font-family:'JetBrains Mono',monospace;font-size:10.5px;color:var(--ink-faint)}
.cost{display:flex;align-items:center;gap:14px;padding:12px 20px;
  border-top:1px solid var(--line-soft);text-decoration:none;color:inherit}
.cost:first-child{border-top:0}
.cost.link:hover{background:rgba(255,255,255,.03)}
.cost-main{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;gap:2px}
.cost-title{font-size:14px;font-weight:500;letter-spacing:-.01em}
.cost-note{font-size:11.5px;color:var(--ink-faint);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cost-bar{flex:0 0 120px;height:4px;border-radius:99px;background:rgba(255,255,255,.07);overflow:hidden}
.cost-bar i{display:block;height:100%;background:var(--amber);border-radius:99px}
.cost-count,.cost-when{flex:none;font-size:10.5px;color:var(--ink-faint)}
.cost-count{min-width:44px;text-align:right}
.cost-when{min-width:62px;text-align:right}
.cost-sum{flex:none;min-width:72px;text-align:right;font-size:13px;color:var(--ink)}
.cost-sum.zero{color:var(--ink-faint)}
.cost.free .cost-bar{opacity:.35}
.cost.entry .cost-bar{display:none}
.sb-sys{display:flex;align-items:center;gap:8px;font-family:'JetBrains Mono',monospace;
  font-size:10.5px;color:var(--ink-faint)}
/* Ширина рабочей области ограничена.
   На широком мониторе (2000 px и больше) страница расползалась: строка текста
   тянулась через весь экран, а состояние и время уезжали к правому краю так,
   что глазу было не связать их со строкой, к которой они относятся. Предел
   выбран под самую широкую таблицу панели, а не «на глаз»: дальше растёт пустота,
   а не польза. */
.main{min-width:0;padding:24px 30px 40px}
.main > *{max-width:1320px}
.main-head{display:flex;align-items:flex-end;justify-content:space-between;gap:20px;
  padding-bottom:18px;border-bottom:1px solid var(--line);margin-bottom:24px;flex-wrap:wrap}
.main-head h2{font-family:'Unbounded',sans-serif;font-weight:600;font-size:23px;letter-spacing:-.02em}
.main-head .sub{color:var(--ink-faint);font-size:13.5px;margin-top:5px}
.main.narrow{max-width:900px}
@media(max-width:1000px){.shell{grid-template-columns:1fr}
  .sidebar{position:static;height:auto;flex-direction:row;flex-wrap:wrap;align-items:center;
    gap:10px;padding:16px;border-right:0;border-bottom:1px solid var(--line)}
  .sb-brand{border:0;margin:0;padding:0 12px 0 6px}
  .sb-group{margin:0;padding:0;display:flex;gap:6px;flex-wrap:wrap}
  .sb-title{display:none}.sb-foot{margin:0;border:0;padding:0 6px}
  .main{padding:20px 16px 32px}}
.sb-link .cnt.alert{background:rgba(255,90,90,.16);color:#ff8f8f}

/* ── узлы конвейера: состояние видно цветом, а не подписью ── */
.node.later{opacity:.45}
.node.later .t{color:var(--ink-faint)}
.node.wait .t{color:var(--ink-dim)}
.node.done{border-color:rgba(74,222,128,.3);background:rgba(74,222,128,.05)}
.node.done .s{color:var(--green)}
.node.active{border-color:var(--amber-deep);background:rgba(255,171,46,.08)}
.node.active .s{color:var(--amber)}
.node.active .n{color:var(--amber)}
/* «Спросить не у кого» — не то же самое, что «ещё не делали»: узел с непрочитанными
   данными штрихуется, чтобы его нельзя было принять за пустую стадию. */
.node.unknown{border-style:dashed}
.node.unknown .t{color:var(--ink-dim)}
.node.unknown .s{color:var(--ink-faint);font-style:italic}

/* ── языковая версия: слева состояние, справа единственное действие ── */
.version{display:flex;align-items:center;justify-content:space-between;gap:20px;
  padding:16px 20px;border-bottom:1px solid var(--line-soft);text-decoration:none;
  transition:background .16s}
.version:last-child{border-bottom:0}
a.version:hover{background:rgba(255,255,255,.02)}
.version-main{min-width:0;flex:1}
.version-name{font-size:15.5px;font-weight:500;letter-spacing:-.01em;
  display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.version-name .tier{font-family:'JetBrains Mono',monospace;font-size:10px;
  color:var(--ink-faint);background:rgba(139,144,153,.12);padding:2px 7px;border-radius:20px}
.version-note{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-top:6px}
.version-note .dim{font-size:12.5px;color:var(--ink-faint)}
.version-file{display:flex;gap:14px;margin-top:8px;font-family:'JetBrains Mono',monospace;
  font-size:11px;color:var(--ink-faint)}
.version-err{margin-top:7px;font-size:12.5px;color:#cf7b80;max-width:70ch}
/* Предупреждение отличается от ошибки: ролик ещё не собирали, но уже видно, что
   он не соберётся. Янтарный, а не красный — это не поломка, а работа для автора. */
.version-warn{margin-top:7px;font-size:12.5px;color:var(--amber);max-width:70ch}
/* Выход из отказа. Причина без него — это тупик: владелец читает «озвучка не
   прошла проверку» и остаётся с ней один на один. */
.version-why{display:inline-block;margin-top:5px;font-size:12px;color:var(--amber);
  text-decoration:none;border-bottom:1px dotted rgba(255,171,46,.5)}
.version-why:hover{border-bottom-style:solid}
/* Голос и доля распознавания: не отметка «озвучено», а измерение. */
.version-voice{display:block;margin-top:7px;font-size:12.5px;color:var(--ink-dim);
  text-decoration:none}
a.version-voice:hover{color:var(--ink)}
/* Паспорт сценария: состояние, дата и язык оригинала одной строкой над воротами. */
.script-meta{display:flex;align-items:center;gap:14px;flex-wrap:wrap;margin-bottom:14px;
  font-size:12.5px;color:var(--ink-faint)}
/* Ворота утверждения: главное решение владельца по сценарию, поэтому стоят
   выше цифр и заметны в обоих состояниях. */
.gate{display:flex;align-items:center;justify-content:space-between;gap:20px;
  padding:16px 20px;margin-bottom:16px;border-radius:12px;
  border:1px solid rgba(255,171,46,.35);background:rgba(255,171,46,.06)}
.gate-ok{border-color:rgba(74,222,128,.3);background:rgba(74,222,128,.05)}
.gate-text{display:flex;flex-direction:column;gap:4px}
.gate-text b{font-size:14.5px}
.gate-text span{font-size:12.5px;color:var(--ink-dim);max-width:80ch}
.version-act{flex:none;display:flex;flex-direction:column;align-items:flex-end;gap:7px;min-width:190px}
.version-act .dim{font-size:12.5px;color:var(--ink-faint)}
.version.ok{background:rgba(74,222,128,.035)}
.version.busy{background:rgba(255,171,46,.05)}

/* Состояние версии словом: цвет повторяет смысл, чтобы его было видно боковым
   зрением. Имя намеренно своё: класс .state уже занят карточкой состояния системы
   на странице настройки, и одинаковая специфичность ломала ту карточку. */
.version-state{font-family:'JetBrains Mono',monospace;font-size:10.5px;letter-spacing:.05em;
  padding:3px 9px;border-radius:20px;background:rgba(139,144,153,.13);color:var(--ink-dim)}
.version-state.s-ready{background:rgba(74,222,128,.14);color:var(--green)}
.version-state.s-failed{background:rgba(255,90,90,.14);color:#ff8f8f}
.version-state.s-rendering,.version-state.s-qa,.version-state.s-voicing,.version-state.s-localizing{
  background:rgba(255,171,46,.14);color:var(--amber)}
.version-state.s-blocked{background:rgba(139,144,153,.1);color:var(--ink-faint)}

/* ── ход сборки ── */
.progress{width:100%;display:flex;flex-direction:column;align-items:flex-end;gap:6px}
.bar{width:100%;height:6px;border-radius:20px;background:var(--bg-sunk);
  border:1px solid var(--line-soft);overflow:hidden}
.bar i{display:block;height:100%;background:var(--amber);border-radius:20px;
  transition:width .5s cubic-bezier(.2,.7,.3,1);box-shadow:0 0 12px rgba(255,171,46,.5)}
.pstage{font-family:'JetBrains Mono',monospace;font-size:10.5px;color:var(--amber)}
.panel.live{border-color:var(--amber-deep)}
.build{display:block;text-decoration:none;padding:15px 20px;
  border-bottom:1px solid var(--line-soft)}
.build:last-child{border-bottom:0}
.build-top{display:flex;align-items:center;justify-content:space-between;gap:14px;margin-bottom:10px}
.build-name{font-size:14.5px;font-weight:500}
.build-stage{font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--amber)}

/* ── короткие факты о сценарии ── */
.facts{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:12px;margin-bottom:22px}
.fact{background:var(--bg-card);border:1px solid var(--line-soft);border-radius:12px;
  padding:15px 17px;display:flex;flex-direction:column;gap:3px}
.fact .fv{font-family:'Unbounded',sans-serif;font-weight:600;font-size:19px;letter-spacing:-.02em}
.fact .fk{font-size:12px;color:var(--ink-faint)}

/* ── раскадровка ── */
.scene{display:flex;gap:16px;padding:14px 20px;border-bottom:1px solid var(--line-soft)}
.scene:last-child{border-bottom:0}
.scene-num{flex:none;width:28px;height:28px;border-radius:9px;background:var(--bg-sunk);
  border:1px solid var(--line-soft);display:flex;align-items:center;justify-content:center;
  font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--ink-faint)}
.scene-body{min-width:0;flex:1}
.scene-top{display:flex;align-items:baseline;gap:12px;justify-content:space-between}
.scene-name{font-size:14.5px;font-weight:500;letter-spacing:-.01em}
.scene-top .dim{font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--ink-faint)}
/* ── выбор языка ──
   Плюс стоит там же, где языковые версии: язык добавляют, глядя на то, что уже есть. */
.lang-add{display:flex;align-items:center;gap:11px;padding:14px 20px}
/* Плюс — квадрат со знаком посередине. Без своей раскладки знак прижимался к
   левому верхнему углу квадрата: у полноширинного «＋» своя ширина и своя
   базовая линия, и строчный поток ставит его куда придётся. */
.btn-plus{width:34px;height:34px;flex:none;border-radius:11px;cursor:pointer;
  display:grid;place-items:center;
  background:var(--bg-sunk);border:1px dashed var(--line);color:var(--ink-dim);
  font-size:17px;line-height:1;transition:border-color .15s,color .15s}
.btn-plus:hover{border-color:var(--amber);color:var(--amber);border-style:solid}
/* margin:auto возвращает окну середину экрана: глобальный сброс отступов в начале
   файла гасит собственный margin диалога, и без этой строки оно липнет к левому
   верхнему углу. */
.picker{width:min(560px,94vw);max-height:82vh;padding:0;margin:auto;border:1px solid var(--line);
  border-radius:16px;background:var(--bg-card);color:var(--ink);overflow:hidden}
.picker::backdrop{background:rgba(5,6,8,.72)}
.picker-head{display:flex;gap:10px;padding:16px;border-bottom:1px solid var(--line-soft)}
.picker-head input{flex:1;min-width:0;padding:11px 14px;border-radius:11px;font-size:14px;
  background:var(--bg-sunk);border:1px solid var(--line);color:var(--ink);font-family:inherit}
.picker-head input:focus{outline:none;border-color:var(--amber)}
.picker-list{overflow-y:auto;max-height:calc(82vh - 74px);padding-bottom:10px}
.picker-title{font-family:'JetBrains Mono',monospace;font-size:10px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--ink-faint);padding:14px 18px 7px}
.picker-row button{display:flex;align-items:center;gap:12px;width:100%;padding:9px 18px;
  background:none;border:0;cursor:pointer;color:inherit;font-family:inherit;text-align:left}
.picker-row button:hover:not(:disabled){background:rgba(255,171,46,.07)}
.picker-row button:disabled{cursor:default;opacity:.45}
/* Флаги — эмодзи, а Windows их не рисует: система показывает вместо флага пару букв
   («US», «RU»). Шрифт Noto Color Emoji подключён в шапке страницы именно ради этого. */
.flag{font-family:'Noto Color Emoji',sans-serif;font-size:19px;line-height:1;flex:none;width:28px}
.picker-name{flex:1;min-width:0;font-size:14px;display:flex;flex-direction:column;gap:1px}
.picker-name i{font-style:normal;font-size:11.5px;color:var(--ink-faint)}
.picker-note{flex:none;font-size:10.5px;color:var(--ink-faint);padding:2px 8px;border-radius:20px;
  background:rgba(139,144,153,.12)}
.picker-act{flex:none;font-size:11.5px;color:var(--amber)}
.picker-row button:disabled .picker-act{color:var(--ink-faint)}
.picker-none{padding:26px 18px;text-align:center;color:var(--ink-faint);font-size:13.5px}

/* Раскадровка показывает содержание, а не форму: что говорит диктор и что написано
   в кадре. Имена ячеек и пределы символов нужны автору текста, а не тому, кто
   утверждает сценарий, поэтому предел появляется только у подошедшей к нему строки. */
.scene-say{margin-top:7px;color:var(--ink);font-size:14px;line-height:1.5;
  padding-left:11px;border-left:2px solid var(--amber-deep)}
.slot-row{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;margin-top:7px}
.slot-note{flex:none;min-width:150px;font-size:11.5px;color:var(--ink-faint)}
.slot-text{display:flex;flex-direction:column;gap:2px;min-width:0;font-size:13.5px;color:var(--ink-dim)}
.slot-lim{font-family:'JetBrains Mono',monospace;font-size:10.5px;color:var(--ink-faint);
  padding:2px 7px;border-radius:20px;background:rgba(139,144,153,.1)}
.slot-lim.tight{color:var(--amber);background:rgba(255,171,46,.12)}
.mono{font-family:'JetBrains Mono',monospace}
.msg.warn{border:1px solid var(--amber-deep);background:rgba(255,171,46,.07);color:#ffd79a}

/* ── просмотр готового ролика ── */
/* Ролик вертикальный, поэтому превью узкое и высокое. Первый кадр — обложка
   по построению, поэтому постер отдельно не нужен: браузер покажет её сам. */
.preview{flex:none;width:104px}
.preview .shot{width:104px;height:185px}

/* ── журнал работ ── */
.job{padding:11px 20px;border-bottom:1px solid var(--line-soft)}
.job:last-child{border-bottom:0}
.job-top{display:flex;align-items:baseline;justify-content:space-between;gap:10px}
.job-stage{font-size:13.5px;font-weight:500;letter-spacing:-.01em}
.job-when{font-family:'JetBrains Mono',monospace;font-size:10.5px;color:var(--ink-faint)}
.job-sub{display:flex;align-items:baseline;justify-content:space-between;gap:10px;margin-top:3px;
  font-size:12px;color:var(--ink-faint)}
/* Номер попытки: видно, что стадию переделывали, — озвучка переозвучивается другим
   голосом, когда распознавание не сошлось с текстом. */
.job-try{font-family:'JetBrains Mono',monospace;font-size:10px;font-style:normal;
  color:var(--amber);background:rgba(255,171,46,.12);padding:2px 7px;border-radius:20px;
  margin-left:8px;vertical-align:middle}
.job-status{font-family:'JetBrains Mono',monospace;font-size:10.5px}
.job-status.ok{color:var(--green)}
.job.bad .job-status{color:#ff8f8f}
.job-err{margin-top:5px;font-size:12px;color:#cf7b80}
/* История попыток. Свёрнута намеренно: в журнале важно «чем кончилось», а «почему
   понадобился третий раз» спрашивают отдельно — и тогда разворачивают. */
.job-tries{margin-top:6px}
.job-tries>summary{display:inline-block;cursor:pointer;font-size:11px;color:var(--ink-faint);
  list-style:none;padding:2px 9px;border:1px solid var(--line-soft);border-radius:20px}
.job-tries>summary::-webkit-details-marker{display:none}
.job-tries>summary:hover{color:var(--ink);border-color:var(--line)}
.job-tries[open]>summary{margin-bottom:6px}
.job-try-row{display:flex;align-items:baseline;gap:9px;flex-wrap:wrap;padding:4px 0 4px 11px;
  border-left:2px solid var(--line-soft);font-size:11.5px;color:var(--ink-faint)}
.job-try-row.bad{border-left-color:#7a3a3f}
.job-try-no{font-family:'JetBrains Mono',monospace;font-size:10.5px;color:var(--ink-faint)}
.job-try-state{font-family:'JetBrains Mono',monospace;font-size:10.5px;color:#ff8f8f}
.job-try-state.ok{color:var(--green)}
.job-try-when{font-family:'JetBrains Mono',monospace;font-size:10px;color:var(--ink-faint)}
.job-try-err{flex:1 1 100%;color:#cf7b80}

/* ── отбор голосов ──
   Строка голоса: слева номер попытки, в середине имя и линейка, справа плеер и
   единственное действие. Номер, а не просто галочка: порядок отметок — это порядок,
   в котором фабрика перебирает голоса при браке дорожки, и он должен быть виден. */
.voice-row{display:flex;align-items:center;gap:16px;padding:12px 20px;
  border-bottom:1px solid var(--line-soft);transition:background .16s}
.voice-row:last-child{border-bottom:0}
.voice-row:hover{background:rgba(255,255,255,.015)}
.voice-row.on{background:rgba(255,171,46,.05)}
.voice-mark{display:flex;align-items:center;gap:9px;flex:none;cursor:pointer}
.voice-mark input{accent-color:var(--amber);width:17px;height:17px;cursor:pointer}
.voice-order{width:20px;font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--amber)}
.voice-main{flex:1;min-width:0}
.voice-name{font-size:14.5px;font-weight:500;letter-spacing:-.01em;display:flex;
  align-items:center;gap:9px;flex-wrap:wrap}
.chip.prem{background:rgba(255,171,46,.14);color:var(--amber)}
.voice-sub{display:flex;gap:12px;flex-wrap:wrap;margin-top:3px;
  font-size:11.5px;color:var(--ink-faint)}
/* Место под плеер держится всегда, даже пока пробы нет: строки голосов идут одна
   под другой, и кнопка, прыгающая влево-вправо от того, озвучен ли голос, мешает
   вести взглядом по списку из сорока строк. */
.voice-act{flex:none;display:flex;align-items:center;gap:12px}
.voice-act .voice-player{width:232px}
.voice-act .btn{padding:9px 15px;min-width:150px}

/* Общий список языков: строка ведёт на отбор голосов. */
.lang-list{max-height:520px;overflow-y:auto}
.lang-line{display:flex;align-items:center;gap:12px;padding:10px 20px;text-decoration:none;
  border-bottom:1px solid var(--line-soft);transition:background .16s}
.lang-line:last-of-type{border-bottom:0}
.lang-line:hover{background:rgba(255,171,46,.06)}
.lang-names{flex:1;min-width:0;font-size:14px;display:flex;flex-direction:column;gap:1px}
.lang-names i{font-style:normal;font-size:11.5px;color:var(--ink-faint)}
.lang-voice{flex:none;font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--ink-dim)}
.lang-voice i{font-style:normal;color:var(--ink-faint)}
.lang-voice.none{color:var(--ink-faint)}
a.lang-row{text-decoration:none}
a.lang-row:hover{background:rgba(255,255,255,.02)}
a.lang-row:hover .code{color:var(--amber)}
input[type=search]{width:100%;background:var(--bg-sunk);border:1px solid var(--line);
  border-radius:10px;padding:11px 14px;color:var(--ink);font-family:'Onest',sans-serif;
  font-size:14px;font-weight:300}
input[type=search]:focus{outline:0;border-color:var(--amber-deep)}

@media(max-width:680px){
  .voice-row{flex-wrap:wrap}
  .voice-act{width:100%;justify-content:space-between}
  .voice-act .voice-player{width:auto;flex:1}}

/* ── миниатюра ролика со своими элементами управления ──
   Браузерная панель <video controls> поверх маленькой миниатюры занимает её почти
   целиком. Свои элементы: кнопка по центру, тонкая полоса хода внизу, показ по
   наведению. Размер задаёт хозяин миниатюры — в сетке это плитка, в строке версии
   узкий столбик, а сама миниатюра одна и та же. */
.shot{position:relative;aspect-ratio:9/16;background:#05070a;overflow:hidden;border-radius:11px;
  border:1px solid var(--line-soft);display:flex;align-items:center;justify-content:center;
  flex:none}
.shot video{width:100%;height:100%;object-fit:cover;display:block}
/* Слой «смотреть крупно» — отдельный от самого кадра, и это не украшение.
   Кнопкой был весь кадр, а в разделе клипов внутри него лежали галочка «в ролик»
   и переключатель версий: кнопка внутри кнопки. Мышь спасало гашение всплытия, а
   Enter и Пробел на галочке доходили до кадра и открывали окно просмотра вместо
   отметки. Теперь слой лежит НИЖЕ галочки и таблеток (у них z-index 3), и до него
   их нажатия просто не доходят. */
.shot-open{position:absolute;inset:0;z-index:1;display:block;cursor:pointer;
  text-decoration:none;color:inherit}
/* Обводка внутрь: кадр обрезает всё, что вылезает за его край, и обычная рамка
   focus-visible снаружи была бы срезана вместе с отступом. */
.shot-open:focus-visible{outline:2px solid var(--amber);outline-offset:-4px}
.shot-off{cursor:default;border-style:dashed;border-color:var(--line);background:var(--bg-sunk)}
.shot-empty{font-family:'JetBrains Mono',monospace;font-size:10.5px;color:var(--ink-faint);
  text-align:center;padding:0 6px}
/* Пустое место под ролик — не дыра в сетке: значок показывает, что кадра ещё нет,
   а не что плитка сломалась. */
.shot-off .shot-empty::before{content:'▤';display:block;font-size:22px;line-height:1;
  color:var(--line);margin-bottom:8px}
.tile.busy .shot-empty{color:var(--amber);font-size:17px}
.shot-play{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
  width:38px;height:38px;border-radius:99px;background:rgba(4,7,12,.62);
  border:1px solid rgba(255,255,255,.22);color:#fff;display:flex;align-items:center;
  justify-content:center;font-size:12px;padding-left:2px;backdrop-filter:blur(6px);
  transition:opacity .18s,transform .18s,background .18s}
.shot:hover .shot-play{background:rgba(255,171,46,.9);color:#20160a;border-color:transparent;
  transform:translate(-50%,-50%) scale(1.08)}
/* Перемотка миниатюры: узкая полоса у нижнего края под лёгким размытием, в ней шкала
   хода. Появляется вместе с показом по наведению — у стоящего кадра ей нечего
   показывать. Перематывает само движение мыши: нажимать, чтобы посмотреть нужный
   кусок, на миниатюре незачем.

   Десятая часть кадра, а не четверть: размытие закрывает картинку, ради которой
   владелец на неё и смотрит. Шкала лежит в самом низу этой полосы, и на неё хватает
   с запасом. */
.shot-scrub{position:absolute;left:0;right:0;bottom:0;height:10%;
  opacity:0;transition:opacity .18s;
  -webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);
  background:linear-gradient(rgba(4,7,12,0),rgba(4,7,12,.5))}
.shot:hover .shot-scrub{opacity:1}
.shot-track{position:absolute;left:9px;right:9px;bottom:9px;height:3px;border-radius:99px;
  background:rgba(255,255,255,.26);overflow:hidden}
.shot-track i{display:block;height:100%;width:0;background:#fff;border-radius:99px}
.shot-off .shot-scrub{display:none}
/* Полоса хода поверх слоя просмотра: слой прозрачный и лежит выше по порядку
   рисования, а полосу видеть надо. Осталась у клипов: там миниатюра переключает
   версии, и перемотка спорила бы с этим нажатием. */
.shot-bar{position:absolute;left:0;right:0;bottom:0;height:3px;z-index:2;
  background:rgba(255,255,255,.14)}
.shot-bar i{display:block;height:100%;width:0;background:var(--amber);transition:width .2s linear}
/* У клипа полоса лежит в разметке всегда — версии переключаются на месте, и
   искать её потом негде. Но показывать ей нечего, пока кадра нет: светлая черта
   под надписью «не вышло» читается как остаток чужого показа. */
.shot-off .shot-bar{display:none}

/* ── сетка готовых роликов ── */
/* Фабрика делает видео: первое, что нужно увидеть, — кадр. Собранное и несобранное
   стоят рядом, поэтому за один взгляд видно, сколько работы осталось. */
.tiles{display:grid;grid-template-columns:repeat(auto-fill,minmax(158px,1fr));gap:15px}
.tile{display:flex;flex-direction:column;border-radius:14px;
  background:var(--bg-card);border:1px solid var(--line-soft);overflow:hidden;
  transition:border-color .18s,transform .18s}
.tile:hover{border-color:var(--line);transform:translateY(-2px)}
.tile.ok{border-color:rgba(74,222,128,.28)}
.tile.busy{border-color:var(--amber-deep)}
.tile .shot{border:0;border-radius:0;width:100%}
.tile-body{padding:11px 13px 13px;display:flex;flex-direction:column;gap:5px}
.tile-name{font-size:13.5px;line-height:1.3;letter-spacing:-.01em;color:var(--ink);
  text-decoration:none;font-weight:500}
.tile-name:hover{color:var(--amber)}
.tile-lang{font-size:12px;color:var(--ink-faint)}
/* Дата заведения версии — самая тихая строка карточки: она нужна, чтобы отличить
   вчерашнее от майского, но спорить с состоянием и длительностью ей незачем. */
.tile-when{font-size:11px;color:var(--ink-faint);opacity:.75}
.tile-meta{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:2px}
.tile-meta .mono{font-size:10.5px;color:var(--ink-faint)}

/* ── карточка нейроклипа ──
   Главное в ней — кадр, а не текст. Описание сценки, напечатанное целиком,
   растягивало карточку на весь экран и превращало библиотеку в столбец
   английского текста: шесть клипов занимали страницу, а понять по ним, что за
   сценка, было нельзя. Поэтому описание живёт в трёх видах: две строки в
   карточке, целиком в подсказке по наведению и целиком в карточке по нажатию. */
.tiles.clips{grid-template-columns:repeat(auto-fill,minmax(186px,1fr));align-items:start}
.tile.clip .tile-body{gap:6px}
.cdesc summary{list-style:none;cursor:pointer;display:block}
.cdesc summary::-webkit-details-marker{display:none}
.cdesc summary:focus-visible{outline:2px solid var(--amber);outline-offset:3px;border-radius:6px}
.cdesc-short{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;
  font-size:12px;line-height:1.42;color:var(--ink-dim);transition:color .15s}
.cdesc summary:hover .cdesc-short{color:var(--ink)}
.cdesc-more{display:block;margin-top:3px;font-style:normal;
  font-size:10.5px;letter-spacing:.02em;color:var(--ink-faint);transition:color .15s}
.cdesc summary:hover .cdesc-more{color:var(--amber)}
.cdesc[open] .cdesc-short{display:none}
.cdesc[open] .cdesc-more{font-size:0}
.cdesc[open] .cdesc-more::after{content:'свернуть';font-size:10.5px}
.cdesc-full,.cdesc-en{display:none}
.cdesc[open] .cdesc-full{display:block;font-size:12px;line-height:1.45;color:var(--ink)}
.cdesc[open] .cdesc-en{display:block;margin-top:7px;font-size:11px;line-height:1.4;
  color:var(--ink-faint)}
.cdesc-en i{display:block;font-style:normal;font-size:9px;letter-spacing:.1em;
  text-transform:uppercase;color:var(--ink-faint);opacity:.75;margin-bottom:2px}
/* Действия — строкой мелких ссылок, а не двумя кнопками в рамках: они нужны раз
   в месяц, а места занимали больше, чем само описание сценки. */
.clip-acts{display:flex;align-items:center;gap:14px;flex-wrap:wrap;margin-top:4px}
.clip-acts .lb-link{flex:none;padding:0;border:0;border-radius:0;text-align:left;
  font-size:11px;color:var(--ink-faint)}
.clip-acts .lb-link:hover{color:var(--amber);border-color:transparent}

/* Подсказка с полным текстом. Своя, а не браузерная: `title` появляется через
   секунду, рисуется системой чужим шрифтом и не умеет абзаца — а показывать надо
   именно абзац, ради которого карточка и осталась компактной. */
.tiptext{position:fixed;z-index:60;max-width:320px;padding:11px 13px;border-radius:12px;
  background:#1b1e23;border:1px solid var(--line);box-shadow:0 20px 44px rgba(0,0,0,.55);
  font-size:12.5px;line-height:1.5;color:var(--ink);pointer-events:none}

/* Вид «списком»: та же плитка, положенная набок. Отдельной вёрстки нет нарочно —
   две разметки одного списка расходятся на первой же правке. */
.tiles.list{display:flex;flex-direction:column;gap:0;
  background:var(--bg-card);border:1px solid var(--line-soft);border-radius:15px;overflow:hidden}
.tiles.list .tile{flex-direction:row;align-items:center;gap:15px;border:0;border-radius:0;
  border-bottom:1px solid var(--line-soft);padding:9px 18px;background:none;transform:none}
.tiles.list .tile:last-child{border-bottom:0}
.tiles.list .tile:hover{background:rgba(255,255,255,.02)}
.tiles.list .shot{width:38px;height:68px;border-radius:7px;border:1px solid var(--line-soft)}
.tiles.list .shot-play{width:22px;height:22px;font-size:8px}
.tiles.list .shot-empty{font-size:0}
.tiles.list .tile-body{flex:1;min-width:0;padding:0;flex-direction:row;align-items:center;
  gap:16px;flex-wrap:nowrap}
.tiles.list .tile-name{flex:1;min-width:0;font-size:14.5px;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
/* Столбцы стоят на своих местах: язык и состояние выстроены в ряд, иначе взгляд
   ищет их заново в каждой строке. */
.tiles.list .tile-lang{flex:none;width:96px}
.tiles.list .tile-meta{margin:0;flex:none;width:250px;justify-content:flex-end;flex-wrap:nowrap}
/* Дата — такой же столбец, как язык и состояние. Без своей ширины она встаёт в
   строку резиновой и толкает соседей, из-за чего столбцы перестают совпадать
   между строками — а ради их совпадения список и сделан. */
.tiles.list .tile-when{flex:none;width:86px;text-align:right}

/* ── панель над списком: отбор слева, вид справа ── */
.listbar{display:flex;align-items:center;gap:14px;flex-wrap:wrap;margin-bottom:18px}
.segs{display:flex;gap:4px;padding:4px;border-radius:12px;background:var(--bg-sunk);
  border:1px solid var(--line-soft)}
.seg{display:flex;align-items:center;gap:7px;padding:7px 13px;border-radius:9px;
  text-decoration:none;color:var(--ink-dim);font-size:13.5px;transition:background .16s,color .16s}
.seg:hover{color:var(--ink);background:rgba(255,255,255,.04)}
.seg.on{background:rgba(255,171,46,.13);color:var(--ink);font-weight:500}
.seg i{font-style:normal;font-family:'JetBrains Mono',monospace;font-size:10.5px;
  color:var(--ink-faint);background:rgba(139,144,153,.14);padding:1px 7px;border-radius:20px}
.seg.on i{color:var(--amber);background:rgba(255,171,46,.15)}
.langsel{display:flex;align-items:center;gap:8px}
.langsel select{width:auto;min-width:170px;padding:9px 12px;font-size:13.5px}
.langsel .btn{padding:9px 15px}
.listbar-right{margin-left:auto;display:flex;align-items:center;gap:14px}
.listbar-count{font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--ink-faint)}
.reset{font-size:13px;color:var(--amber);text-decoration:none;border-bottom:1px dashed rgba(255,171,46,.4)}
.reset:hover{color:#ffc266}
.viewsw{display:flex;gap:3px;padding:3px;border-radius:11px;background:var(--bg-sunk);
  border:1px solid var(--line-soft)}
.vw{width:34px;height:30px;border-radius:8px;display:flex;align-items:center;justify-content:center;
  text-decoration:none;color:var(--ink-faint);font-size:14px;transition:background .16s,color .16s}
.vw:hover{color:var(--ink);background:rgba(255,255,255,.04)}
.vw.on{background:rgba(255,171,46,.13);color:var(--amber)}

/* ── окно просмотра ролика ──
   margin:auto возвращает окну середину экрана: глобальный сброс отступов в начале
   файла гасит собственный margin диалога. */
/* Ширину окна задаёт сам ролик, а не круглое число: он вертикальный, и окно с
   запасом по бокам оставляло бы широкие чёрные поля вместо кадра. */
.lightbox{width:min(772px,94vw);max-height:94vh;padding:0;margin:auto;
  border:1px solid var(--line);border-radius:18px;background:var(--bg-card);color:var(--ink);
  overflow:hidden;position:relative}
.lightbox::backdrop{background:rgba(5,6,8,.82);backdrop-filter:blur(3px)}
.lb-body{display:grid;grid-template-columns:minmax(0,1fr) 330px}
.lb-stage{background:#05070a;height:min(78vh,760px);display:flex;
  align-items:center;justify-content:center;position:relative}
.lb-stage video{width:100%;height:100%;object-fit:contain;display:block;background:#05070a;cursor:pointer}
.lb-side{padding:20px 22px;display:flex;flex-direction:column;gap:11px;overflow-y:auto;
  border-left:1px solid var(--line-soft)}
/* Место под крестик: он стоит в том же углу, что и заголовок. */
.lb-side h3{font-family:'Unbounded',sans-serif;font-weight:600;font-size:17px;letter-spacing:-.02em;
  padding-right:42px}
/* Язык, длительность и размер — одной строкой. Двумя плитками они занимали пятую
   часть высоты окна ради двух чисел, которые смотрят раз в сеанс. */
.lb-meta{display:flex;flex-wrap:wrap;align-items:center;gap:7px;font-size:12.5px;color:var(--ink-dim)}
.lb-lang{color:var(--amber)}
.lb-dot{color:var(--ink-faint)}
/* Кнопки-ссылки вместо двух широких кнопок: они нужны редко, а место под правку —
   каждый раз. */
.lb-act{display:flex;gap:8px;flex-wrap:wrap}
/* Подписи в одну строку: «Проект Flow», перенесённый на вторую, поднимал ряд
   кнопок вдвое и ломал его высоту. */
.lb-act .lb-link{white-space:nowrap;padding:7px 9px;font-size:12px}
/* Фон объявлен прозрачным намеренно: этот же класс носят и ссылки, и кнопки,
   а кнопке без фона браузер рисует свой — светлую кляксу на графите. */
.lb-link{flex:1;text-align:center;text-decoration:none;font-size:12.5px;color:var(--ink-dim);
  background:transparent;font-family:'Onest',sans-serif;cursor:pointer;
  border:1px solid var(--line);border-radius:9px;padding:7px 10px;
  transition:color .15s,border-color .15s}
.lb-link:hover{color:var(--amber);border-color:var(--amber-deep)}
/* Описание сценки в окне просмотра. У клипа правки словами нет, и без описания
   правая половина окна оставалась чёрной пустотой рядом с кадром. */
.lb-note{margin-top:14px;font-size:13px;line-height:1.55;color:var(--ink-dim)}
.lb-close{position:absolute;right:12px;top:12px;z-index:3}
.lb-close button{width:34px;height:34px;border-radius:99px;cursor:pointer;font-size:13px;
  background:rgba(4,7,12,.6);border:1px solid rgba(255,255,255,.16);color:var(--ink);
  backdrop-filter:blur(6px)}
.lb-close button:hover{background:rgba(255,90,90,.75);border-color:transparent}

/* ── свой плеер ──
   Браузерная панель мелкая и чужая по виду, а скорость воспроизведения спрятана
   в меню из трёх точек — при просмотре ролика на проверку она нужна чаще всего.
   Поэтому все органы управления свои: кнопки крупные, скорость на виду, громкость
   и скорость раскрываются наведением. */
.lb-big{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
  width:74px;height:74px;border-radius:99px;border:1px solid rgba(255,255,255,.2);
  background:rgba(8,10,14,.55);backdrop-filter:blur(8px);color:var(--ink);
  display:flex;align-items:center;justify-content:center;
  cursor:pointer;z-index:2;transition:opacity .2s,transform .2s,background .2s,color .2s}
.lb-big svg{width:28px;height:28px;fill:currentColor;margin-left:3px}
.lb-big:hover{background:rgba(255,171,46,.9);color:#20160a;border-color:transparent}
.lb-stage.playing .lb-big{opacity:0;pointer-events:none;transform:translate(-50%,-50%) scale(.85)}

.lb-ctl{position:absolute;left:0;right:0;bottom:0;z-index:2;padding:26px 14px 12px;
  display:flex;flex-direction:column;gap:9px;
  background:linear-gradient(to top,rgba(4,6,9,.92),rgba(4,6,9,.55) 55%,transparent);
  opacity:0;transition:opacity .18s}
.lb-stage:hover .lb-ctl,.lb-stage:focus-within .lb-ctl,
.lb-stage:not(.playing) .lb-ctl{opacity:1}

/* Полоса перемотки толще браузерной: в неё целятся указателем, и три пикселя
   промахиваются. */
.lb-seek{position:relative;height:6px;border-radius:99px;background:rgba(255,255,255,.18);
  cursor:pointer;flex:none}
.lb-seek::before{content:'';position:absolute;left:0;right:0;top:-9px;bottom:-9px}
.lb-seek i{position:absolute;left:0;top:0;bottom:0;width:0;border-radius:99px;background:var(--amber)}
.lb-seek b{position:absolute;top:50%;left:0;width:14px;height:14px;border-radius:99px;
  background:var(--amber);transform:translate(-50%,-50%);box-shadow:0 2px 8px rgba(0,0,0,.5);
  opacity:0;transition:opacity .15s}
.lb-seek:hover b,.lb-seek:focus-visible b{opacity:1}
.lb-seek:focus-visible{outline:2px solid var(--amber);outline-offset:4px}

.lb-row{display:flex;align-items:center;gap:6px}
.lb-gap{flex:1}
.lb-btn{width:38px;height:38px;border-radius:10px;border:1px solid transparent;cursor:pointer;
  background:transparent;color:var(--ink);font-size:15px;line-height:1;
  display:inline-flex;align-items:center;justify-content:center;
  transition:background .15s,color .15s,border-color .15s}
.lb-btn:hover{background:rgba(255,255,255,.1)}
.lb-btn svg{width:20px;height:20px;fill:currentColor}
/* Показ и пауза — два значка в одной кнопке: класс на сцене решает, какой видно. */
.lb-btn .i-pause,.lb-stage.playing .lb-btn .i-play{display:none}
.lb-stage.playing .lb-btn .i-pause{display:block}
/* Громкость: волны гаснут по мере убавления, крестик появляется только в тишине. */
.lb-btn.vol .i-cross{display:none}
.lb-btn.vol.low .i-wave2{display:none}
.lb-btn.vol.off .i-wave1,.lb-btn.vol.off .i-wave2{display:none}
.lb-btn.vol.off .i-cross{display:block}
/* Ширина кнопки скорости постоянная, а не по тексту. «1×» и «1,25×» разной длины,
   от них ехала вся строка кнопок, а вместе с ней и меню, привязанное к середине
   кнопки: бегунок уползал из-под указателя ровно в тот миг, когда им двигали, и
   поймать нужное значение было нельзя. */
.lb-btn.wide{width:64px;padding:0 6px;font-family:'JetBrains Mono',monospace;
  font-size:12.5px;font-weight:500}
.lb-btn.hot{color:var(--amber);border-color:rgba(255,171,46,.4);background:rgba(255,171,46,.12)}
.lb-time{font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--ink-dim);
  padding:0 6px;white-space:nowrap}
.lb-time b{color:var(--ink);font-weight:500}

/* Всплывающая настройка.
   Панель вырастает прямо из кнопки и вплотную к ней: зазор между ними указатель
   пересекал по воздуху, и настройка закрывалась от одного пикселя мимо. Мостик
   (::before) остаётся страховкой на случай тени и скруглений, но теперь он широкий:
   промах по горизонтали тоже не должен закрывать панель. */
.lb-pin{position:relative}
.lb-pop{position:absolute;bottom:100%;left:50%;transform:translateX(-50%) scale(.96);
  transform-origin:50% 100%;
  background:rgba(14,16,20,.97);border:1px solid var(--line);border-radius:12px;
  box-shadow:0 14px 40px rgba(0,0,0,.55);padding:10px;
  opacity:0;pointer-events:none;transition:opacity .14s,transform .14s}
.lb-pop::before{content:'';position:absolute;left:-14px;right:-14px;top:-10px;bottom:-10px;
  z-index:-1}
.lb-pin:hover .lb-pop,.lb-pin:focus-within .lb-pop,.lb-pin.open .lb-pop{
  opacity:1;pointer-events:auto;transform:translateX(-50%) scale(1)}
.lb-pop-rate{width:186px;margin-bottom:6px}
.lb-quick{display:grid;grid-template-columns:1fr 1fr 1fr;gap:5px;margin-bottom:9px}
.lb-quick button{border:1px solid var(--line);background:transparent;color:var(--ink-dim);
  border-radius:8px;padding:6px 0;cursor:pointer;font-family:'JetBrains Mono',monospace;
  font-size:11.5px;transition:color .13s,border-color .13s,background .13s}
.lb-quick button:hover{color:var(--ink);border-color:var(--ink-faint)}
.lb-quick button.on{background:var(--amber);color:#20160a;border-color:transparent}

/* Бегунок свой: браузерный по умолчанию разный в каждом браузере и не совпадает
   ни с одним другим элементом панели. */
/* Хватать бегунок надо не за пятипиксельную нитку: сама дорожка нарисована фоном,
   а элемент вчетверо выше её — промах по вертикали больше не проходит мимо. */
.lb-range{-webkit-appearance:none;appearance:none;width:100%;height:20px;border-radius:99px;
  background:linear-gradient(rgba(255,255,255,.18),rgba(255,255,255,.18)) center/100% 5px no-repeat;
  outline:none;cursor:pointer}
.lb-range::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:15px;height:15px;
  border-radius:99px;background:var(--amber);border:0;box-shadow:0 2px 7px rgba(0,0,0,.5)}
.lb-range::-moz-range-thumb{width:15px;height:15px;border-radius:99px;background:var(--amber);
  border:0;box-shadow:0 2px 7px rgba(0,0,0,.5)}
/* Громкость — не отдельная коробка над кнопкой, а её продолжение вверх: та же
   ширина, общий фон, скругление только сверху. Кнопка при этом становится
   основанием колонны. Так указатель идёт от динамика к бегунку по сплошной
   поверхности и ничего не теряет по дороге. */
.lb-pop-vol{width:38px;padding:13px 0 9px;border-radius:11px 11px 0 0;border-bottom:0;
  background:rgba(32,35,42,.98);box-shadow:0 -10px 26px rgba(0,0,0,.45)}
.lb-pop-vol::before{left:-12px;right:-12px;top:-12px;bottom:-4px}
.lb-range.vert{writing-mode:vertical-lr;direction:rtl;width:22px;height:96px;display:block;margin:0 auto;
  background:linear-gradient(rgba(255,255,255,.18),rgba(255,255,255,.18)) center/5px 100% no-repeat}
#lb-vol-pin:hover .lb-btn.vol,#lb-vol-pin:focus-within .lb-btn.vol{
  background:rgba(32,35,42,.98);border-color:var(--line);border-top-color:transparent;
  border-radius:0 0 10px 10px}

/* ── языковые версии плитками ──
   Строка во всю ширину растягивала вертикальный кадр 9:16 на полтора экрана
   пустоты справа: занять это место рядом с ним нечем. В плитке всё про версию
   лежит под её же кадром, и версии видно разом. */
/* Плитка лежит поперёк: кадр 9:16 в полную ширину плитки давал бы башню в пол-экрана
   высотой, и трёх версий разом было бы не видно. Превью узкое и слева, всё
   остальное — справа от него. */
.vtiles{display:grid;grid-template-columns:repeat(auto-fill,minmax(310px,1fr));
  gap:14px;padding:16px 20px}
.vtile{background:var(--bg-sunk);border:1px solid var(--line-soft);border-radius:14px;
  overflow:hidden;display:flex;gap:12px;padding:12px;transition:border-color .15s;
  text-align:left}
.vtile.ok{border-color:rgba(74,222,128,.22)}
.vtile.busy{border-color:rgba(255,171,46,.3)}
.vtile .shot{flex:none;width:92px;border-radius:9px;border:1px solid var(--line-soft)}
.vtile .shot-play{width:26px;height:26px;font-size:9px}
.vtile .shot-empty{font-size:9px}
.vtile-body{flex:1;display:flex;flex-direction:column;gap:8px;min-width:0}
.vtile-top{display:flex;align-items:baseline;gap:8px;justify-content:space-between}
.vtile-name{font-size:15px;font-weight:500;letter-spacing:-.01em}
.vtile-top .tier{font-family:'JetBrains Mono',monospace;font-size:10px;color:var(--ink-faint)}
.vtile-state{display:flex;align-items:center;gap:8px;flex-wrap:wrap;
  font-family:'JetBrains Mono',monospace;font-size:10.5px;color:var(--ink-faint)}
.vtile .btn{width:100%}
.vtile .fix-drop summary{text-align:left}
.vtile .fix-drop form{width:100%}
.vtile-add{border-style:dashed;cursor:pointer;align-items:center;justify-content:center;
  gap:10px;padding:26px 12px;color:var(--ink-dim);font-family:'Onest',sans-serif;
  font-size:13.5px;background:transparent;min-height:132px}
.vtile-add:hover{border-color:var(--amber-deep);color:var(--amber)}

/* ── раскадровка лентой кадров ──
   Сцены идут одна за другой во времени, и читать их проще, когда они и лежат
   одна за другой. Столбец во всю ширину заодно оставлял полтора экрана пустоты
   справа, занять которую нечем.

   Два вида текста нарочно не похожи друг на друга: то, что ЗВУЧИТ (речь диктора,
   она же субтитры), и то, что НАПИСАНО В КАДРЕ. Пока они шли одинаковыми
   строчками, отличить их можно было только по подписи слева. */
/* Выбор языка раскадровки — именно выбор, а не подпись в углу. Серыми таблетками
   с надписью «текст версии» его не замечали и правили русский текст, думая, что
   правят китайский. */
.story-lang{display:flex;align-items:center;gap:7px;flex-wrap:wrap;
  background:var(--bg-sunk);border:1px solid var(--line-soft);border-radius:11px;
  padding:5px 7px}
.story-lang-title{font-family:'JetBrains Mono',monospace;font-size:9.5px;
  letter-spacing:.14em;text-transform:uppercase;color:var(--ink-faint);padding:0 5px}
.story-lang .seg{font-size:13px;padding:6px 13px;border-radius:8px;text-decoration:none;
  color:var(--ink-dim);border:1px solid transparent;transition:color .14s,background .14s}
.story-lang .seg:hover{color:var(--ink);background:rgba(255,255,255,.04)}
.story-lang .seg.on{background:var(--amber);color:#20160a;border-color:transparent;
  font-weight:500}
/* Лента тянется мышью: полоса прокрутки под длинной панелью — отдельное
   путешествие курсором, и владелец пробовал тащить саму ленту. */
.strip{display:flex;gap:14px;padding:16px 20px;overflow-x:auto;scroll-snap-type:x proximity;
  cursor:grab}
.strip.dragging{cursor:grabbing;scroll-snap-type:none;user-select:none}
/* Внутри кадра курсор обычный: поля набирают, кнопки нажимают. Рука-«захват»
   только там, где лента действительно тянется. */
.strip textarea,.strip input{cursor:text}
.strip button,.strip .btn,.strip a,.strip label{cursor:pointer}
.frame{flex:none;width:290px;scroll-snap-align:start;background:var(--bg-sunk);
  border:1px solid var(--line-soft);border-radius:14px;padding:13px;
  display:flex;flex-direction:column;gap:9px}
.frame-top{display:flex;align-items:center;gap:9px}
.frame-num{flex:none;width:24px;height:24px;border-radius:8px;background:var(--bg-card);
  border:1px solid var(--line);display:flex;align-items:center;justify-content:center;
  font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--ink-dim)}
.frame-name{flex:1;font-size:14px;font-weight:500;letter-spacing:-.01em;min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.frame-sec{font-family:'JetBrains Mono',monospace;font-size:10.5px;color:var(--ink-faint)}
/* Подпись вида текста — это разделитель, а не украшение: по ней сразу видно,
   читает диктор эту строку или она нарисована в кадре. */
.frame-kind{display:flex;align-items:center;gap:7px;font-family:'JetBrains Mono',monospace;
  font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;margin-top:3px}
.frame-kind::before{content:'';width:3px;height:12px;border-radius:2px}
.frame-kind.say{color:#7fd4ff}
.frame-kind.say::before{background:#7fd4ff}
.frame-kind.screen{color:var(--amber)}
.frame-kind.screen::before{background:var(--amber)}
.frame textarea{width:100%;background:var(--bg-card);color:var(--ink);
  border:1px solid var(--line);border-radius:9px;padding:8px 10px;resize:vertical;
  font-family:'Onest',sans-serif;font-size:13.5px;line-height:1.5}
.frame textarea:focus{outline:none;border-color:var(--amber-deep)}
.frame-say{border-left:3px solid #7fd4ff !important}
.frame-screen{border-left:3px solid var(--amber) !important;
  font-family:'JetBrains Mono',monospace;font-size:12.5px}
.frame-screen.over{border-color:var(--red);background:rgba(255,90,90,.06)}
.frame-slot{display:flex;flex-direction:column;gap:4px}
.frame-slot-top{display:flex;align-items:baseline;gap:8px;justify-content:space-between}
/* Пояснение ужимается, предел — нет: перенесённый на две строки, он наезжал на
   поле ввода и читался как часть текста кадра. */
.frame-slot-top .slot-note{flex:1;min-width:0;font-size:11px;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
.frame-slot-top .slot-lim{flex:none;white-space:nowrap}
.frame-clip{font-size:11.5px;color:var(--ink-faint)}
.frame-act{display:flex;gap:7px;margin-top:auto;padding-top:4px}
.frame-act .btn{flex:1;padding:8px 10px;font-size:12.5px}

/* ── правка словами ── */
/* Поле «что переделать» одинаково везде: на странице сценария, у отдельной версии и
   в окне просмотра. */
.panel-body.two{display:grid;grid-template-columns:1fr 1fr;gap:26px}
.fix textarea{min-height:88px}
/* В окне просмотра поле правки занимает всё, что осталось: это главное, ради чего
   окно открывают второй раз. */
.fix-tall{flex:1;display:flex;flex-direction:column;gap:9px;min-height:0}
.fix-tall textarea{flex:1;min-height:120px;resize:none}
.fix-warn{margin-top:9px;font-size:12px;line-height:1.5;color:var(--amber);
  background:rgba(255,171,46,.07);border:1px solid rgba(255,171,46,.25);
  border-radius:10px;padding:9px 12px}

/* ── снимки к правке ──
   Номер снимка совпадает с тем, под каким он уедет модели: щелчок по подписи
   вставляет «Image N» в текст, чтобы номер не набирали руками и не путали. */
.shots{display:flex;flex-direction:column;gap:8px}
.shots-list{display:flex;flex-wrap:wrap;gap:8px}
.shots.has .shots-list{margin-bottom:2px}
.shots-item{position:relative;width:74px}
.shots-item img{width:74px;height:74px;object-fit:cover;border-radius:9px;display:block;
  border:1px solid var(--line);background:var(--bg-sunk)}
.shots-tag{display:block;width:100%;margin-top:4px;border:0;background:transparent;cursor:pointer;
  font-family:'JetBrains Mono',monospace;font-size:10px;color:var(--ink-faint);
  transition:color .13s}
.shots-tag:hover{color:var(--amber)}
.shots-kill{position:absolute;right:-5px;top:-5px;width:20px;height:20px;border-radius:99px;
  border:1px solid var(--line);background:var(--bg-card);color:var(--ink-dim);
  font-size:9px;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center}
.shots-kill:hover{background:var(--red);color:#fff;border-color:transparent}
.shots-bar{display:flex;align-items:center;gap:9px;flex-wrap:wrap}
.shots-add{border:1px dashed var(--line);background:transparent;color:var(--ink-dim);
  border-radius:9px;padding:6px 12px;cursor:pointer;font-family:'Onest',sans-serif;font-size:12.5px;
  transition:color .13s,border-color .13s}
.shots-add:hover{color:var(--amber);border-color:var(--amber-deep)}
.shots-hint{font-size:11.5px;color:var(--ink-faint)}
.shots.over .shots-add{color:var(--amber);border-color:var(--amber);border-style:solid}

/* ── решения ──
   Карточка вопроса: что не так, и две кнопки под два честных ответа. Список причин
   без кнопок был бы тем же отказом стадии, только в другом месте. */
.deci{padding:16px 20px;border-bottom:1px solid var(--line-soft);display:flex;
  flex-direction:column;gap:9px}
.deci:last-child{border-bottom:0}
.deci-top{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.deci-script{font-weight:500;text-decoration:none}
.deci-script:hover{color:var(--amber)}
.deci-lang{font-size:12.5px;color:var(--amber)}
.deci-over{font-family:'JetBrains Mono',monospace;font-size:11.5px;color:#20160a;
  background:var(--amber);border-radius:99px;padding:2px 9px}
.deci-ready{font-size:11.5px;color:var(--ink-faint)}
.deci-problem{font-size:13.5px;color:var(--ink-dim);line-height:1.55;max-width:70ch}
.deci-acts{display:flex;align-items:center;gap:9px;flex-wrap:wrap}
.deci-acts .btn{padding:9px 16px;font-size:13px}
.deci-lead{margin-bottom:18px;padding:14px 18px;border-radius:12px;font-size:13.5px;
  line-height:1.6;color:var(--ink-dim);max-width:86ch;
  background:var(--bg-sunk);border:1px solid var(--line-soft)}
.deci-lead b{color:var(--ink);font-weight:500}
.fix-drop{width:100%}
.fix-drop summary{cursor:pointer;font-size:12.5px;color:var(--ink-dim);list-style:none;
  text-align:right;padding:3px 0;transition:color .15s}
.fix-drop summary::-webkit-details-marker{display:none}
.fix-drop summary::before{content:'↺ ';color:var(--ink-faint)}
.fix-drop summary:hover{color:var(--amber)}
.fix-drop[open] summary{color:var(--amber)}
.fix-drop form{margin-top:9px;display:flex;flex-direction:column;gap:9px;
  width:min(360px,72vw);text-align:left}
.fix-drop textarea{min-height:64px;font-size:13.5px}

/* Снимки в ленте правок: видно не только то, что владелец написал, но и то, на что
   он показывал пальцем. */
.rev-shots{display:flex;flex-wrap:wrap;gap:7px;margin-top:8px}
.rev-shot{position:relative;display:block;text-decoration:none}
.rev-shot img{width:64px;height:64px;object-fit:cover;border-radius:8px;display:block;
  border:1px solid var(--line);background:var(--bg-sunk)}
.rev-shot i{display:block;margin-top:3px;font-style:normal;text-align:center;
  font-family:'JetBrains Mono',monospace;font-size:9.5px;color:var(--ink-faint)}
.rev-shot:hover img{border-color:var(--amber-deep)}

.rev-head{font-family:'JetBrains Mono',monospace;font-size:10px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--ink-faint);padding:14px 20px 8px;
  border-top:1px solid var(--line-soft)}
/* Строка правки: сверху состояние и к чему относится, ниже — сами слова владельца. */
.rev{padding:13px 20px;border-bottom:1px solid var(--line-soft)}
.rev:last-child{border-bottom:0}
.rev.fresh{background:rgba(255,171,46,.05)}
.rev-top{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.rev-what{font-size:13px;color:var(--ink-dim)}
.rev-script{font-size:13px;color:var(--ink);text-decoration:none;border-bottom:1px solid var(--line)}
.rev-script:hover{color:var(--amber);border-color:var(--amber-deep)}
.rev-new{font-family:'JetBrains Mono',monospace;font-size:10px;letter-spacing:.05em;
  color:#20160a;background:var(--amber);padding:2px 8px;border-radius:20px}
.rev-when{margin-left:auto;font-family:'JetBrains Mono',monospace;font-size:10.5px;color:var(--ink-faint)}
.rev-prompt{margin-top:7px;font-size:14px;line-height:1.5;padding-left:11px;
  border-left:2px solid var(--line)}
.rev.fresh .rev-prompt{border-left-color:var(--amber-deep)}
.rev-note{margin-top:6px;font-size:12.5px;color:var(--ink-faint)}
.version-state.s-done{background:rgba(74,222,128,.14);color:var(--green)}
.version-state.s-working{background:rgba(255,171,46,.14);color:var(--amber)}

@media(max-width:900px){
  .lightbox{width:94vw}
  .lb-body{grid-template-columns:1fr}
  .lb-stage{height:46vh}
  .lb-side{border-left:0;border-top:1px solid var(--line-soft)}
  .panel-body.two{grid-template-columns:1fr;gap:20px}}
@media(max-width:680px){
  .listbar{gap:10px}
  .listbar-right{margin-left:0;width:100%;justify-content:space-between}
  .langsel{width:100%}
  .langsel select{flex:1;min-width:0}
  .segs{width:100%}
  .seg{flex:1;justify-content:center}
  .fix-drop summary{text-align:left}
  .fix-drop form{width:100%}
  .tiles.list .tile-name{min-width:0}}

/* Убрать язык. Кнопка нарочно тихая: она нужна раз в жизни сценария и стоит рядом
   с действиями, которые нужны постоянно. Показывается только у пустой версии. */
.version-drop{margin-top:7px}
.version-drop-btn{border:0;background:transparent;color:var(--ink-faint);cursor:pointer;
  font-size:11.5px;padding:2px 0;text-decoration:underline;text-decoration-style:dotted}
.version-drop-btn:hover{color:#cf7b80}

/* ── раздел «Замысел» ──────────────────────────────────────────────────────
   Он появился позже остальных и жил без единой строки оформления: таблицы шли
   голым HTML, заголовки панелей не находили правил (в разметке h3, а стиль был
   написан на h2), карточки идей рисовались абзацами подряд. Отсюда и вид.   */

.panel-head h3{font-family:'Unbounded',sans-serif;font-weight:600;font-size:12px;
  letter-spacing:.13em;text-transform:uppercase;color:var(--ink-dim)}

/* Формы раздела: метка сверху, поле под ней, кнопка отдельной строкой. */
.panel > .form{display:flex;flex-direction:column;gap:14px;padding:20px}
.panel > .form + .form{border-top:1px solid var(--line-soft)}
/* Поле не тянется во всю ширину панели: строка длиной в монитор нечитаема, а
   правят здесь названия и пару фраз, а не документы. Описание продукта — то же
   поле, просто выше. */
.panel > .form label{display:flex;flex-direction:column;gap:6px;max-width:860px;
  font-size:13.5px;font-weight:500;letter-spacing:-.01em}
.panel > .form .in{font-size:14.5px}
.panel > .form textarea.in{min-height:auto}
.panel > .form .btn{align-self:flex-start}
.panel > .form .btn:disabled{opacity:.45;cursor:default;border-color:var(--line)}
.panel > .form .btn:disabled:hover{border-color:var(--line)}
/* Ссылка-кнопка внутри формы раздела: она задумана как второстепенное действие
   рядом с полями, а общий .lb-link тянется во всю ширину (он живёт в подвале
   карточки ролика, где кнопок несколько и они делят строку поровну). */
.panel > .form .lb-link{flex:none;align-self:flex-start;padding:9px 16px}
/* Кнопка отбора стоит в форме без класса .form — таблица с галочками.
   Форма именно СВОЯ У ПАНЕЛИ (`>`), а не любая вложенная. Пока связь была
   свободной, отступ доставался каждой кнопке, лежащей в форме где угодно внутри
   панели, — в том числе «Собрать ролик» в плитке языковой версии. Там кнопка
   растянута во всю ширину плитки, и 20 пикселей сбоку выносили её за край:
   плитка обрезает всё лишнее, и владелец видел кнопку, уползающую под рамку. */
.panel > form > .btn{margin:0 20px 20px}

/* ── таблицы раздела ── */
.tbl{width:100%;border-collapse:collapse;font-size:14px}
.tbl th{padding:11px 20px;text-align:left;font-family:'JetBrains Mono',monospace;
  font-size:10.5px;letter-spacing:.09em;text-transform:uppercase;color:var(--ink-faint);
  font-weight:400;border-bottom:1px solid var(--line-soft);background:var(--bg-sunk)}
.tbl td{padding:14px 20px;vertical-align:top;border-bottom:1px solid var(--line-soft)}
.tbl tbody tr:last-child td{border-bottom:0}
.tbl tbody tr:hover{background:rgba(255,255,255,.014)}
.tbl .hint{margin-top:4px}
.tbl-foot{padding:10px 20px;border-top:1px solid var(--line-soft)}
.acts{display:flex;flex-wrap:wrap;gap:10px;align-items:center;justify-content:flex-end}

/* Колонки списка прогонов: вопрос тянется, остальное — по содержимому.
   Иначе состояние и время уезжали к правому краю, а причина отказа
   растягивала строку на пол-экрана. */
/* Первая колонка забирает остаток ширины, остальные — по содержимому.
   Отдельной колонки действий нет намеренно: она пуста, пока ни один прогон не
   закончился отчётом, и оставляла справа полосу пустоты в четверть таблицы.
   Кнопки живут под вопросом — там, где написано, к чему они относятся. */
.runs td:first-child,.runs th:first-child{width:auto}
.runs .c-state{width:1%;white-space:nowrap;padding-right:26px}
.runs .c-when{width:1%;white-space:nowrap;color:var(--ink-dim);font-size:12.5px;text-align:right}
.run-acts{display:flex;gap:9px;margin-top:11px}
.run-acts .lb-link{flex:none;padding:6px 14px}
.run-q{font-weight:400}
.run-why{margin-top:6px;font-size:12.5px;color:#cf7b80;max-width:86ch}
.run-more{margin-top:7px}
.run-more summary{cursor:pointer;font-family:'JetBrains Mono',monospace;font-size:10.5px;
  letter-spacing:.05em;color:var(--ink-faint);list-style:none}
.run-more summary::-webkit-details-marker{display:none}
.run-more summary::before{content:'▸ ';color:var(--ink-faint)}
.run-more[open] summary::before{content:'▾ '}
.run-more summary:hover{color:var(--ink-dim)}
.run-more pre{margin-top:8px;padding:12px 14px;border-radius:10px;background:var(--bg-sunk);
  border:1px solid var(--line-soft);font-family:'JetBrains Mono',monospace;font-size:11px;
  line-height:1.65;color:var(--ink-dim);white-space:pre-wrap;word-break:break-word;
  max-height:220px;overflow:auto}

/* Колонки списка болей. Доли, а не «как получится»: без них боль занимала всю
   строку, а зацепка и адресат прижимались к правому краю экрана — глазом их
   было не связать с той болью, к которой они относятся. */
.pains{table-layout:fixed}
.pains .c-pick{width:46px;padding-right:0}
.pains .c-pick input[type=checkbox]{accent-color:var(--amber);width:16px;height:16px;cursor:pointer}
.pains .pain{width:42%}
.pains .c-hook{width:30%;color:var(--ink-dim)}
.pains .c-who{width:28%;color:var(--ink-dim);font-size:13.5px}

/* ── карточки идей ── */
.idea{padding:18px 20px;border-bottom:1px solid var(--line-soft)}
.idea:last-child{border-bottom:0}
.idea-head{display:flex;align-items:center;gap:11px;flex-wrap:wrap}
.idea-head b{font-family:'Unbounded',sans-serif;font-weight:600;font-size:15px;letter-spacing:-.01em}
.idea-head .mono{margin-left:auto;font-family:'JetBrains Mono',monospace;
  font-size:11px;color:var(--ink-faint)}
/* Ссылка на сценарий — метка рядом с датой, а не полоса во всю строку:
   общий .lb-link тянется (flex:1), потому что живёт в подвале карточки ролика,
   где кнопок несколько и они делят строку поровну. */
.idea-head .lb-link{flex:none;padding:5px 13px}
.idea-hook{margin-top:8px;font-size:14.5px;color:var(--ink)}
.idea > .hint{margin-top:5px}
.idea-beats{margin:13px 0 0;padding:13px 16px 13px 34px;border-radius:11px;
  background:var(--bg-sunk);border:1px solid var(--line-soft);
  display:flex;flex-direction:column;gap:5px;font-size:13.5px;color:var(--ink-dim)}
.idea-beats li::marker{color:var(--ink-faint);font-family:'JetBrains Mono',monospace;font-size:11px}
.idea-payoff{margin-top:11px;font-size:13.5px;color:var(--ink-dim);
  padding-left:13px;border-left:2px solid var(--amber-deep)}
.idea-acts{display:flex;align-items:center;gap:14px;flex-wrap:wrap;margin-top:15px}
.idea-rework{display:flex;align-items:center;gap:9px;margin-left:auto}
.idea-rework .in{width:230px;padding:9px 12px;font-size:13px}

/* Основание боли («знание владельца», цитата из отчёта) — подпись, а не вторая
   строка самой боли: без своего вида она читалась как продолжение текста. */
.pains .pain .hint{margin-top:7px;font-size:12px;color:var(--ink-faint);
  font-family:'JetBrains Mono',monospace;letter-spacing:.02em}

/* Подвал таблицы — служебная строка, а не содержимое. */
.tbl-foot{font-family:'JetBrains Mono',monospace;font-size:11px;
  letter-spacing:.04em;color:var(--ink-faint)}

/* Форма отбора и форма «своя боль» — разные действия, и между ними нужна
   граница: без неё кнопка «Сохранить отбор» выглядела частью следующей формы. */
.panel > form:not(.form) > .btn{margin:16px 20px 20px}
.panel > form:not(.form) + .form{border-top:1px solid var(--line-soft)}

/* Номер шага в заголовке панели.
   Раздел — это путь: продукт, исследование, боли, идеи. Панели шли подряд, и
   порядок читался только из текста; номер показывает его сразу и отвечает на
   вопрос «с чего начать», который на пустой странице задаёт каждый. */
.panel-head h3{display:flex;align-items:center;gap:11px}
.step{display:inline-flex;align-items:center;justify-content:center;
  width:21px;height:21px;border-radius:50%;flex:none;
  font-family:'JetBrains Mono',monospace;font-size:11px;font-style:normal;
  letter-spacing:0;color:var(--amber);background:rgba(255,171,46,.12);
  border:1px solid rgba(255,171,46,.28)}

/* ── витрина для тех, кто пришёл снаружи ──
   У страницы входа свой каркас: бокового столбца с разделами и счётчиками работ
   на ней нет. Показывать постороннему, сколько у владельца сценариев в работе,
   незачем, а голая форма с одной кнопкой не отвечала на вопрос «куда я попал».
   Ширина ограничена содержимым, а не окном: строка текста длиннее 70 знаков
   читается тяжело, и на широком мониторе витрина расползалась во всю ширину. */
.lp{max-width:1060px;margin:0 auto;padding:34px 26px 60px}
.lp-top{display:flex;align-items:center;justify-content:space-between;gap:20px;
  padding-bottom:26px;border-bottom:1px solid var(--line-soft)}
.lp-brand{display:flex;align-items:center;gap:13px}
.lp-brand img{display:block;width:52px;height:52px;border-radius:12px}
.lp-brand em{font-family:'JetBrains Mono',monospace;font-style:normal;
  font-weight:400;font-size:10px;letter-spacing:.16em;text-transform:uppercase;
  color:var(--ink-faint);margin-top:3px}

.lp-hero{padding:58px 0 46px;max-width:760px}
.lp-tag{display:inline-block;font-family:'JetBrains Mono',monospace;font-size:11px;
  letter-spacing:.14em;text-transform:uppercase;color:var(--amber);
  background:rgba(255,171,46,.1);border:1px solid rgba(255,171,46,.24);
  border-radius:99px;padding:5px 13px;margin-bottom:22px}
.lp-hero h1{font-family:'Unbounded',sans-serif;font-weight:600;font-size:41px;
  line-height:1.16;letter-spacing:-.03em}
.lp-hero h1 span{color:var(--amber)}
.lp-lede{margin-top:20px;font-size:17px;line-height:1.62;color:var(--ink-dim);max-width:660px}
.lp-cta{margin-top:32px;display:flex;align-items:center;gap:18px;flex-wrap:wrap}
.btn-lg{font-size:15px;padding:14px 26px}
.lp-note{font-size:13px;color:var(--ink-faint)}
.lp-warn{margin-top:30px;padding:15px 18px;border-radius:11px;font-size:14px;
  color:var(--ink);background:rgba(255,90,90,.09);border:1px solid rgba(255,90,90,.3)}

/* Четыре шага конвейера. Сетка сама решает, сколько столбцов влезло: на телефоне
   один, на мониторе четыре — без запросов ширины под каждый размер экрана. */
.lp-steps{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(224px,1fr));
  margin-bottom:56px}
.lp-steps article{background:var(--bg-card);border:1px solid var(--line);
  border-radius:14px;padding:20px 20px 22px}
.lp-steps b{font-family:'JetBrains Mono',monospace;font-size:11px;letter-spacing:.1em;
  color:var(--amber);font-weight:500}
.lp-steps h3{font-family:'Unbounded',sans-serif;font-weight:600;font-size:17px;
  letter-spacing:-.02em;margin:8px 0 9px}
.lp-steps p{font-size:14px;line-height:1.58;color:var(--ink-dim)}

/* Снимки панели. Тень и рамка нужны затем, чтобы тёмный снимок не сливался с
   тёмной страницей: без них картинка выглядит дырой в фоне. */
.lp-shots{display:grid;gap:34px}
.lp-shots figure{margin:0}
.lp-shots img{display:block;width:100%;height:auto;border-radius:13px;
  border:1px solid var(--line);box-shadow:0 18px 44px rgba(0,0,0,.45)}
.lp-shots figcaption{margin-top:13px;font-size:14px;color:var(--ink-dim);max-width:700px}
.lp-shots figcaption b{color:var(--ink);font-weight:500}

.lp-foot{margin-top:56px;padding-top:22px;border-top:1px solid var(--line-soft);
  display:flex;justify-content:space-between;gap:16px;flex-wrap:wrap;
  font-family:'JetBrains Mono',monospace;font-size:11px;letter-spacing:.04em;
  color:var(--ink-faint)}

@media (max-width:640px){
  .lp-hero{padding:38px 0 32px}
  .lp-hero h1{font-size:29px}
  .lp-top{flex-direction:column;align-items:flex-start;gap:14px}
}

/* Выход из панели. Виден только тому, кто входил: за столом владельца входа нет,
   и кнопка, которая ничего не делает, — это обещание действия, которого нет. */
.sb-out{display:flex;align-items:center;justify-content:space-between;gap:10px;
  margin-top:11px;padding-top:11px;border-top:1px solid var(--line-soft)}
.sb-out span{font-family:'JetBrains Mono',monospace;font-size:10px;letter-spacing:.04em;
  color:var(--ink-faint);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sb-out-btn{flex:none;cursor:pointer;font-family:'Onest',sans-serif;font-size:11px;
  color:var(--ink-dim);background:transparent;border:1px solid var(--line);
  border-radius:7px;padding:4px 10px;transition:color .16s,border-color .16s}
.sb-out-btn:hover{color:var(--ink);border-color:var(--amber-deep)}

/* Библиотека музыки. Карточка строкой, а не плиткой: у трека нет картинки, и
   плитка с пустым квадратом вместо обложки выглядит как незагрузившийся клип.
   Проигрыватель браузерный — слушать надо здесь, «готово» у музыки решают уши. */
.tracks{display:flex;flex-direction:column}
.track{padding:16px 20px;border-top:1px solid var(--line-soft)}
.track:first-child{border-top:none}
.track-head{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:10px}
.track-name{font-family:'Unbounded',sans-serif;font-weight:400;font-size:14px;
  margin-right:auto}
.track-head .dim{font-family:'JetBrains Mono',monospace;font-size:10.5px;
  letter-spacing:.04em;color:var(--ink-faint)}
.track-play{width:100%;margin-bottom:10px}

/* ── свой проигрыватель звука ──
   Браузерная панель <audio controls> в графитовом пульте выглядит наклейкой из
   чужой системы: у каждого браузера она своя, кнопки мелкие, а нужное — послушать
   три секунды — спрятано среди скачивания и меню из трёх точек. */
.ap{display:flex;align-items:center;gap:11px;padding:7px 11px;border-radius:10px;
  background:var(--bg-sunk);border:1px solid var(--line-soft);min-width:0}
/* Кнопка показа — ссылка на сам файл (без сценария она его просто откроет),
   поэтому подчёркивание снимается явно. */
.ap-play{flex:none;width:30px;height:30px;border-radius:50%;cursor:pointer;
  display:grid;place-items:center;border:1px solid var(--line);text-decoration:none;
  background:rgba(255,255,255,.04);color:var(--ink);transition:background .16s,border-color .16s}
.ap-play:focus-visible{outline:2px solid var(--amber);outline-offset:2px}
.ap-play:hover{border-color:var(--amber-deep);background:rgba(255,171,46,.12);color:var(--amber)}
.ap-play svg{width:13px;height:13px;fill:currentColor}
.ap-play .i-play{margin-left:2px}
.ap-play .i-pause,.ap.playing .ap-play .i-play{display:none}
.ap.playing .ap-play .i-pause{display:block}
.ap.playing .ap-play{border-color:var(--amber-deep);color:var(--amber)}
.ap-seek{flex:1;min-width:40px;height:5px;border-radius:3px;cursor:pointer;
  background:rgba(255,255,255,.1);position:relative}
.ap-seek i{display:block;height:100%;width:0;border-radius:3px;background:var(--amber)}
.ap-seek:focus-visible{outline:2px solid var(--amber);outline-offset:3px}
.ap-time{flex:none;font-family:'JetBrains Mono',monospace;font-size:10.5px;
  letter-spacing:.03em;color:var(--ink-faint)}
.ap-time b{color:var(--ink-dim);font-weight:400}
.ap.bad{border-color:rgba(255,90,90,.35)}

/* ── разбор озвучки версии ──
   Страница отвечает на вопрос «что делать дальше», поэтому выходы стоят наверху,
   а сравнение написанного с услышанным — под ними. */
.check-acts{display:flex;align-items:center;gap:11px;flex-wrap:wrap}
.take{padding:14px 20px;border-top:1px solid var(--line-soft);
  display:flex;flex-direction:column;gap:9px}
.take:first-child{border-top:0}
.take-top{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.take-num{flex:none;width:22px;height:22px;border-radius:7px;display:grid;place-items:center;
  background:var(--bg-sunk);border:1px solid var(--line-soft);
  font-family:'JetBrains Mono',monospace;font-size:10.5px;color:var(--ink-faint)}
/* Сохранённая дорожка прошлого прогона: слово вместо номера, поэтому кружок под
   цифру ей узок. */
.take-num.kept{width:auto;padding:0 8px;letter-spacing:.02em}
.take-voice{font-size:14.5px;font-weight:500;letter-spacing:-.01em}
.take-ratio{font-family:'JetBrains Mono',monospace;font-size:10.5px;color:var(--ink-dim)}
.take-ratio.bad{color:#cf7b80}
.take-meta{margin-left:auto;font-size:10.5px;color:var(--ink-faint)}
.take-note{font-size:12.5px;line-height:1.6;color:#cf7b80;
  border-left:2px solid rgba(255,90,90,.35);padding-left:11px}
.take-noaudio{font-size:12.5px;color:var(--ink-faint)}
.take-kept{font-size:12.5px;line-height:1.6;color:var(--ink-dim);
  border-left:2px solid var(--line-soft);padding-left:11px}
.take.ok .take-voice{color:var(--green)}

/* Сравнение фраз: слева написанное, справа услышанное. Совпавшие строки гасятся —
   искать глазами надо расхождения, а не читать заново весь текст. */
.cmp{display:grid;grid-template-columns:26px minmax(0,1fr) minmax(0,1fr);gap:14px;
  padding:12px 20px;border-top:1px solid var(--line-soft);align-items:start}
.cmp:first-child{border-top:0}
.cmp-num{font-family:'JetBrains Mono',monospace;font-size:10.5px;color:var(--ink-faint);
  padding-top:3px}
.cmp-said{font-size:14px;line-height:1.55}
.cmp-heard{font-size:14px;line-height:1.55;color:var(--ink-dim)}
.cmp-heard i{color:#cf7b80;font-style:normal}
.cmp.same .cmp-said,.cmp.same .cmp-heard{color:var(--ink-faint)}
.cmp:not(.same) .cmp-heard{color:var(--amber)}
.cmp-foot{padding:12px 20px;border-top:1px solid var(--line-soft);
  font-size:12px;color:var(--ink-faint)}

/* ── живая озвучка образцов ──
   Нажатие не перезагружает страницу: кнопка крутит спиннер, готовая проба
   появляется плеером в своей же строке. Перезагрузка здесь сбрасывала и
   прокрутку, и прослушивание на середине. */
.say-spin{display:none;width:13px;height:13px;flex:none;border-radius:50%;
  border:2px solid rgba(255,255,255,.25);border-top-color:var(--amber);
  animation:spin .7s linear infinite}
.say-one.working .say-spin,.say-all.working .say-spin{display:block}
@keyframes spin{to{transform:rotate(360deg)}}
.say-msg{margin-top:12px;font-size:13px;color:var(--ink-dim)}
.say-msg.ok{color:var(--green)}
.say-msg.bad{color:#cf7b80}
/* Ширину плееру задаёт его место (в строке голоса — 232 px), а не он сам.
   Общий flex:1 её перебивал, и столбец плееров в списке из сорока четырёх строк
   получался неровным. Растягивание оставлено только узкому экрану — там место
   под плеер меряется остатком строки. */
.voice-player{min-width:0;display:flex}
.voice-player .ap{flex:1;min-width:0}

/* ── библиотека клипов: дерево слева, карточки справа ──
   Свалить всё в одну ленту нельзя: клипов десятки, они принадлежат разным
   сценариям и разным продуктам, и по куче миниатюр не понять, что для чего. */
.clips-shell{display:grid;grid-template-columns:246px minmax(0,1fr);gap:20px;align-items:start}
.clip-tree{position:sticky;top:22px;background:var(--bg-card);border:1px solid var(--line-soft);
  border-radius:14px;padding:8px;display:flex;flex-direction:column;gap:2px;
  max-height:calc(100vh - 60px);overflow-y:auto}
.clip-branch,.clip-leaf{display:flex;align-items:center;gap:9px;
  padding:8px 10px;border-radius:9px;text-decoration:none;cursor:pointer;
  font-size:13.5px;color:var(--ink-dim);transition:background .14s,color .14s}
/* Продукт: слева заметная кнопка раскрытия, справа — сама ссылка на его клипы.
   Пока это была одна строка, нажатие только складывало список, и посмотреть
   продукт целиком было нельзя. */
.clip-product{gap:4px;padding:4px 6px 4px 4px}
.clip-branch-link{flex:1;min-width:0;display:flex;align-items:center;gap:9px;
  padding:5px 6px;border-radius:8px;text-decoration:none;color:inherit;
  font-family:'Unbounded',sans-serif;font-weight:400;font-size:11.5px;
  letter-spacing:.06em;text-transform:uppercase}
.clip-toggle{flex:none;width:22px;height:22px;border-radius:7px;cursor:pointer;
  display:grid;place-items:center;font-size:13px;line-height:1;
  background:rgba(255,255,255,.05);border:1px solid var(--line);color:var(--ink-dim);
  transition:background .14s,color .14s,border-color .14s}
.clip-toggle:hover{border-color:var(--amber-deep);color:var(--amber)}
.clip-toggle::before{content:'+';font-size:14px;font-family:'JetBrains Mono',monospace}
.clip-node.open > .clip-branch > .clip-toggle::before{content:'−'}
.clip-kids{display:flex;flex-direction:column;gap:2px}
.clip-node:not(.open) .clip-kids{display:none}
.clip-branch:hover,.clip-leaf:hover{background:rgba(255,255,255,.03);color:var(--ink)}
.clip-branch.on,.clip-leaf.on{background:rgba(255,171,46,.11);color:var(--amber)}
.clip-leaf{padding-left:34px;font-size:13px}
.clip-branch-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.clip-tree .cnt{flex:none;font-family:'JetBrains Mono',monospace;font-size:10.5px;
  color:var(--ink-faint);background:rgba(255,255,255,.05);border-radius:6px;padding:1px 6px}
.clip-branch.on .cnt,.clip-leaf.on .cnt{background:rgba(255,171,46,.16);color:var(--amber)}
.clip-main-head{display:flex;align-items:baseline;gap:14px;flex-wrap:wrap;margin-bottom:14px}
.clip-main-head h3{font-family:'Unbounded',sans-serif;font-weight:600;font-size:15px;
  letter-spacing:-.01em}

/* Переключатель версий и галочка живут поверх кадра: версии сравнивают глазами,
   и уводить для этого взгляд из-под картинки незачем. Слой z-index здесь несущий,
   а не косметический: он и есть то, что отделяет отметку от просмотра — слой
   «смотреть крупно» лежит ниже (z-index 1), и нажатия сюда до него не доходят. */
.ver-pills{position:absolute;left:8px;bottom:8px;display:flex;gap:5px;z-index:3}
.ver-pill{position:relative;width:23px;height:23px;border-radius:7px;cursor:pointer;
  font-family:'JetBrains Mono',monospace;font-size:11px;line-height:1;
  background:rgba(8,10,13,.72);color:var(--ink-dim);border:1px solid rgba(255,255,255,.16);
  backdrop-filter:blur(3px);transition:background .14s,color .14s,border-color .14s}
.ver-pill:hover{color:var(--ink);border-color:var(--ink-faint)}
.ver-pill.on{background:var(--amber);color:#20160a;border-color:transparent}
/* Точка у номера версии — метка «эта в ролике». Она в углу самой кнопки, а не
   поверх цифры: `position:relative` здесь обязателен, иначе точка считает своим
   началом кадр и садится на цифру соседней версии. */
.ver-pill.picked::after{content:'';position:absolute;right:-2px;top:-2px;width:6px;height:6px;
  border-radius:50%;background:var(--green);border:1px solid var(--bg)}
.clip-pick{position:absolute;right:8px;top:8px;z-index:3}
.clip-pick button{width:27px;height:27px;border-radius:50%;cursor:pointer;font-size:13px;
  line-height:1;background:rgba(8,10,13,.72);color:var(--ink-faint);
  border:1px solid rgba(255,255,255,.18);backdrop-filter:blur(3px);
  transition:background .14s,color .14s,border-color .14s}
.clip-pick button:hover{color:var(--ink);border-color:var(--green)}
.clip-pick button.on{background:var(--green);color:#08210f;border-color:transparent}
.clip-pick button[disabled]{opacity:.35;cursor:not-allowed}

/* Пересоздание: поле с заданием генератору спрятано под кнопку — открытая форма
   у каждой карточки превратила бы библиотеку в анкету. */
.clip-again{margin-top:6px}
.clip-again summary{cursor:pointer;list-style:none;font-size:12px;color:var(--amber);
  padding:3px 0}
.clip-again summary::-webkit-details-marker{display:none}
.clip-again summary:hover{color:var(--ink)}
.clip-again form{display:flex;flex-direction:column;gap:8px;margin-top:8px}
.clip-again textarea{background:var(--bg);border:1px solid var(--line);border-radius:9px;
  padding:9px 11px;color:var(--ink);font-family:'JetBrains Mono',monospace;font-size:11px;
  line-height:1.6;resize:vertical}
.clip-again textarea:focus{outline:0;border-color:var(--amber-deep)}
.clip-again .btn{width:100%;padding:8px 14px;font-size:13px}
.clip-again .note{font-size:11.5px;color:var(--ink-faint);line-height:1.5}

@media(max-width:900px){
  .clips-shell{grid-template-columns:minmax(0,1fr)}
  .clip-tree{position:static;max-height:none}}

/* Предложение пересобрать ролики после смены клипа. Отметка меняет то, что уйдёт
   в следующую сборку, а готовые файлы собраны с прежним клипом — молчать об этом
   значит дать владельцу уйти с мыслью, что дело сделано. */
.gate.rebuild{margin-bottom:18px}
.rebuild-lang{font-style:normal;color:var(--ink)}
.rebuild-lang.dim{color:var(--ink-faint)}

/* Правило отбора стоит НАД списком голосов: под сорока четырьмя строками его
   никто не читает, а решает оно, каким голосом заговорит язык. */
.pick-rule{padding:12px 20px;border-bottom:1px solid var(--line-soft);
  font-size:12.5px;line-height:1.6;color:var(--ink-dim)}
.pick-rule b{color:var(--ink);font-weight:500}
#pick-state.ok{color:var(--green)}
#pick-state.bad{color:#cf7b80}
/* Кнопка «Сохранить отбор» не нужна ровно до тех пор, пока отбор сохраняется сам.
   Признак живёт на форме, а не флагом на кнопке: «сохраняется само» и «кнопки не
   видно» — одно знание, и в двух местах оно расходилось. Прежде флаг ставился при
   загрузке и не снимался никогда, поэтому отказ автосохранения оставлял владельца
   без выхода: красная строка есть, кнопки нет, а обновление страницы стирает
   расставленные галочки. Отвалилось само — сценарий снимает класс, кнопка
   возвращается. Без сценария класса нет вовсе, и кнопка на месте с самого начала. */
.live #pick-save{display:none}
/* Вид оплаты в разрезе затрат: деньги, кредиты подписки, бесплатно. */
.cost-kind{flex:none;min-width:118px;text-align:right;font-size:10.5px;color:var(--ink-faint);
  font-family:'JetBrains Mono',monospace}
.cost.credit .cost-bar i{background:var(--ink-faint)}

/* ── раздача: витрина покрытия, отправка, витрины ── */

/* Витрина «ролик × площадка». Таблица, а не карточки: вопрос владельца звучит
   «что уже разошлось, а что лежит без дела», и ответ на него читается взглядом
   по строке — при карточках его пришлось бы собирать по кусочкам. */
.cov-bar{display:flex;gap:10px;flex-wrap:wrap;padding:14px 20px;align-items:center;
  border-bottom:1px solid var(--line-soft)}
.cov-sel{width:auto;max-width:190px;padding:8px 12px;font-size:13px}
.cov-sel.wide{max-width:250px}
/* Столбцов может стать десять и больше: горизонтальную прокрутку берёт на себя
   таблица, а не страница — иначе уезжает и боковое меню. */
.cov-wrap{overflow-x:auto}
.cov{width:100%;border-collapse:collapse}
.cov th{font-family:'JetBrains Mono',monospace;font-size:10.5px;color:var(--ink-faint);
  font-weight:400;text-align:center;padding:10px 6px;letter-spacing:.04em;white-space:nowrap}
.cov th.first{text-align:left;padding-left:20px}
.cov td{padding:9px 6px;text-align:center;border-top:1px solid var(--line-soft)}
.cov td.first{text-align:left;padding-left:20px}
.cov tr:hover td{background:rgba(255,255,255,.02)}
.cov-name{font-size:13.5px;font-weight:500;color:var(--ink);text-decoration:none;display:block}
.cov-name:hover{color:var(--amber)}
.cov-sub{font-size:11px;color:var(--ink-faint)}
.cov input[type=checkbox]{accent-color:var(--amber);width:15px;height:15px;cursor:pointer}

/* Четыре вида клетки: ушло, идёт, не ушло, не отправляли. Пустая клетка отличается
   от отказа намеренно — «не пробовали» и «попробовали и не вышло» требуют разных
   действий владельца. */
.mark{display:inline-grid;place-items:center;width:24px;height:24px;border-radius:8px;
  font-size:12px;border:1px solid transparent;text-decoration:none}
.mark.ok{background:rgba(60,200,120,.12);color:var(--green);border-color:rgba(60,200,120,.25)}
.mark.ok:hover{background:rgba(60,200,120,.2)}
.mark.wait{background:rgba(255,179,0,.10);color:var(--amber);border-color:rgba(255,179,0,.28)}
.mark.bad{background:rgba(207,123,128,.12);color:#cf7b80;border-color:rgba(207,123,128,.3)}
.mark.none{color:var(--ink-faint);border-color:var(--line-soft);opacity:.5}

/* Строка витрины в списке аккаунтов и площадок. */
.acc{display:flex;align-items:center;gap:12px;padding:11px 20px;border-top:1px solid var(--line-soft)}
.acc:first-child{border-top:0}
.acc-net{flex:0 0 108px;font-size:12.5px;color:var(--ink-dim)}
.acc-name{flex:1 1 auto;font-size:13.5px;font-weight:500;display:flex;align-items:baseline;gap:9px}
.acc-target{font-family:'JetBrains Mono',monospace;font-size:10.5px;color:var(--ink-faint);font-weight:400}
.acc-lang{flex:0 0 100px;font-size:11.5px;color:var(--ink-faint)}
.acc-limit{flex:0 0 200px;font-family:'JetBrains Mono',monospace;font-size:10.5px;color:var(--ink-faint)}
.acc-state{flex:0 0 118px;text-align:right}
/* Пояснение под строкой: «вход по кукам — риск блокировки», чего не хватает для
   официального доступа. Пометка обязана быть видна, а не жить в подсказке. */
.acc-note{padding:0 20px 11px 140px;font-size:12px;color:var(--ink-faint);line-height:1.55}
.plat-access{flex:0 0 250px;font-size:12px}
.plat-access.ok{color:var(--green)}
.plat-access.warn{color:var(--amber)}
.plat-access.none{color:var(--ink-faint)}

/* Экран отправки: слева текст поста, справа витрины. */
.send-body{display:flex;gap:26px;flex-wrap:wrap;padding:18px 20px}
.send-col{flex:1 1 330px;min-width:0}
.send-col .field:last-child{margin-bottom:0}
.send-trouble{padding:16px 20px;color:#cf7b80;font-size:13.5px}
/* Счётчик знаков под полем: предел площадки виден ДО отправки, а не в отказе. */
.cap-note{font-family:'JetBrains Mono',monospace;font-size:10.5px;color:var(--ink-faint);margin-top:6px}
.send-when{display:flex;gap:14px;flex-wrap:wrap;margin-top:14px;align-items:center}
.send-when input[type=datetime-local]{width:auto;max-width:230px}
.send-when .note{font-size:12.5px;color:var(--ink-faint)}
input.num{width:72px;display:inline-block;padding:7px 10px;font-size:13px}
/* Витрина, в которую уже уходило: отметка снята, и сказано почему. */
.pick.off{opacity:.55}
/* Ссылка на страницу, где выдают значение поля. Стоит внутри подсказки, а не
   отдельной строкой: это часть объяснения, а не самостоятельное действие. */
.field-link{display:inline-block;margin-left:6px;color:var(--amber);text-decoration:none;
  border-bottom:1px dashed rgba(255,171,46,.4)}
.field-link:hover{border-bottom-color:var(--amber)}
