/*
 * Сброс, типографика и примитивы студии.
 *
 * Третьего листа нет намеренно: контролы студии — это её типографика,
 * а не отдельная тема, которую можно поменять. Разложить их по файлу
 * на контрол значило бы получить десяток запросов на один экран (сборщика
 * в проекте нет) ради возможности, которой никто не воспользуется.
 *
 * Числа каркаса берутся из `--vst-lay-*`, а те приезжают из layout.ts —
 * второй раз в CSS они не появляются. Порогов ширины в медиазапросах нет
 * по той же причине: `@media` не умеет `var()`, поэтому режим окна ставит
 * оболочка атрибутом `data-fit` на корне, а CSS смотрит на атрибут.
 */

/* ─── сброс ─────────────────────────────────────────────────────────── */

*, *::before, *::after { box-sizing: border-box; }

html, body { height: 100%; }

body {
  margin: 0;
  background: var(--vst-bg);
  color: var(--vst-fg);
  font-family: var(--vst-font);
  font-size: var(--vst-text);
  line-height: var(--vst-leading);
  -webkit-text-size-adjust: 100%;
}

h1, h2, h3, p, ul, ol, figure { margin: 0; }
ul, ol { padding: 0; list-style: none; }

img, svg, iframe { display: block; max-width: 100%; }

/* Контролы не наследуют шрифт сами — во всех браузерах у них свой,
   и без этой строки поле ввода на macOS оказывается другой гарнитуры. */
button, input, select, textarea { font: inherit; color: inherit; }

button { cursor: pointer; background: none; border: 0; padding: 0; }
button:disabled { cursor: default; }

a { color: var(--vst-accent); text-decoration: none; }
a:hover { color: var(--vst-accent-hover); }

code, kbd, samp { font-family: var(--vst-font-mono); font-size: .92em; }

/* Кольцо фокуса одно на всё приложение. `:focus-visible`, а не `:focus`:
   кольцо после нажатия мышью читается как «залипло» и его начинают гасить
   поштучно, а вместе с ним гаснет и клавиатурный. */
:focus-visible {
  outline: var(--vst-focus-width) solid var(--vst-focus);
  outline-offset: 2px;
  border-radius: var(--vst-radius-s);
}

/* Выделенный текст читается на обеих темах: акцент здесь — перо, и зашитый
   белый на нём в тёмной теме означал исчезновение выделенного значения
   ровно в тот момент, когда его выделили, чтобы прочитать или скопировать. */
::selection { background: var(--vst-accent); color: var(--vst-primary-fg); }

/* ─── типографика ───────────────────────────────────────────────────── */

h1, h2, h3 { font-weight: var(--vst-weight-bold); line-height: var(--vst-leading-tight); letter-spacing: -.015em; }
h1 { font-size: var(--vst-text); font-weight: var(--vst-weight-medium); letter-spacing: 0; }
h2 { font-size: var(--vst-text-xl); }
h3 { font-size: var(--vst-text-m); }

.vst-hero { font-size: var(--vst-text-hero); font-weight: var(--vst-weight-bold); line-height: 1.1; letter-spacing: -.025em; }
.vst-lead { font-size: var(--vst-text-m); line-height: var(--vst-leading-loose); color: var(--vst-fg-2); }
.vst-muted { color: var(--vst-fg-3); }
.vst-mono { font-family: var(--vst-font-mono); font-size: var(--vst-text-xs); color: var(--vst-fg-3); }

/* ─── каркас ────────────────────────────────────────────────────────── */

.vst-app {
  display: flex;
  flex-direction: column;
  height: 100dvh;
  overflow: hidden;
}

.vst-top {
  flex: 0 0 var(--vst-lay-top-bar);
  height: var(--vst-lay-top-bar);
  display: flex;
  align-items: center;
  gap: var(--vst-gap-3);
  padding: 0 var(--vst-gap-3);
  background: var(--vst-top);
  border-bottom: 1px solid var(--vst-line);
}

.vst-top__back { display: flex; align-items: center; gap: var(--vst-gap-1); color: var(--vst-fg-2); }
.vst-top__back:hover { color: var(--vst-fg); }
.vst-top__back[hidden] { display: none; }

.vst-top__mark { width: 16px; height: 16px; border-radius: var(--vst-radius-s); background: var(--vst-fg); }
.vst-top__brand { font-weight: var(--vst-weight-medium); }
.vst-top__sep { width: 1px; height: 18px; background: var(--vst-line); }
/* Сжимается ТЕКСТ, а не органы управления.
 *
 * По умолчанию во флексе ужимаются все, и на узком окне переключатель темы
 * уезжал за край: пропадала кнопка, а не подпись. Кнопка нужна всегда,
 * подпись — обрезается многоточием и остаётся понятной. */
.vst-top__title {
  font-weight: var(--vst-weight-medium);
  white-space: nowrap;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}
.vst-top__sub {
  color: var(--vst-fg-3);
  font-size: var(--vst-text-s);
  white-space: nowrap;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}
.vst-top__gap { flex: 1; }
.vst-top__actions { display: flex; align-items: center; gap: var(--vst-gap-2); flex: none; }

.vst-top__icon {
  flex: none;
  display: grid;
  place-items: center;
  width: 26px; height: 26px;
  border-radius: var(--vst-radius-s);
  color: var(--vst-fg-2);
}
.vst-top__icon:hover { background: var(--vst-surface-2); color: var(--vst-fg); }

/* Узкое окно: марка и название студии уходят первыми — они опознавательные,
   а не рабочие, и на 1024 px их место нужнее адресу страницы. */
[data-fit='refuse'] .vst-top__brand,
[data-fit='refuse'] .vst-top__sep,
[data-fit='narrow'] .vst-top__brand { display: none; }

.vst-host { flex: 1; min-height: 0; overflow: auto; display: flex; flex-direction: column; }
.vst-host:focus { outline: none; }
/* Экран занимает контейнер целиком: у редактора внутри собственная сетка
   на всю высоту, и без этого он схлопывался бы по содержимому. */
.vst-host > .vst-screen { flex: 1; min-height: 0; }

/* ─── сообщения ─────────────────────────────────────────────────────── */

.vst-notes {
  /* Полями, а не сдвигом на половину себя.
   *
   * `translateX(-50%)` считает от СОБСТВЕННОЙ ширины, и на узком окне
   * колонка сжималась до половины экрана: длинная причина отказа читалась
   * по три слова в строке. Теперь ширина ограничена окном, а не половиной. */
  position: fixed;
  left: 0;
  right: 0;
  bottom: var(--vst-gap-5);
  width: fit-content;
  margin-inline: auto;
  max-width: calc(100% - var(--vst-gap-5) * 2);
  z-index: var(--vst-z-note);
  display: flex;
  flex-direction: column;
  gap: var(--vst-gap-2);
  pointer-events: none;
}

.vst-note {
  pointer-events: auto;
  display: flex;
  align-items: center;
  gap: var(--vst-gap-2);
  max-width: 520px;
  padding: var(--vst-gap-2) var(--vst-gap-3);
  background: var(--vst-surface);
  border: 1px solid var(--vst-line);
  border-radius: var(--vst-radius);
  box-shadow: var(--vst-shadow-pop);
  cursor: pointer;
}
.vst-note--warn { border-color: var(--vst-warn-line); color: var(--vst-warn); }

/* ─── плашки ────────────────────────────────────────────────────────── */

.vst-plate {
  max-width: 620px;
  margin: var(--vst-gap-8) auto;
  padding: var(--vst-gap-5);
  display: flex;
  flex-direction: column;
  gap: var(--vst-gap-3);
  align-items: flex-start;
  background: var(--vst-surface);
  border: 1px solid var(--vst-line-quiet);
  border-radius: var(--vst-radius-l);
}
.vst-plate p { color: var(--vst-fg-2); }

.vst-badge {
  display: inline-flex;
  align-items: center;
  padding: 3px 9px;
  background: var(--vst-surface-2);
  border-radius: var(--vst-radius-pill);
  font-size: var(--vst-text-xs);
  color: var(--vst-fg-2);
}

/* Просмотр вместо редактора ниже порога отказа. */
.vst-review { display: flex; flex-direction: column; gap: var(--vst-gap-4); padding-bottom: var(--vst-gap-5); }
.vst-review__frame {
  width: 100%;
  height: 70dvh;
  background: #fff;
  border: 0;
  box-shadow: var(--vst-canvas-edge);
}

.vst-icon { flex: none; }
.vst-icon--spin { animation: vst-spin 700ms linear infinite; }
@keyframes vst-spin { to { transform: rotate(360deg); } }

/* ─── кнопка ────────────────────────────────────────────────────────── */

.vst-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--vst-gap-2);
  height: var(--vst-lay-control-height);
  padding: 0 var(--vst-gap-3);
  border: 1px solid transparent;
  border-radius: var(--vst-radius);
  font-weight: var(--vst-weight-medium);
  white-space: nowrap;
  transition:
    background var(--vst-motion) var(--vst-ease),
    border-color var(--vst-motion) var(--vst-ease),
    color var(--vst-motion) var(--vst-ease),
    opacity var(--vst-motion) var(--vst-ease),
    transform var(--vst-motion-fast) var(--vst-ease);
}
/* Нажатие сжимает кнопку на два процента — приём источника.
   Это единственная отдача, которую даёт кнопка без цвета: в монохроме
   подсветкой «нажато» не покажешь, она совпадает с наведением. */
.vst-btn:active:not(:disabled) { transform: scale(.98); }
.vst-btn__slot:empty { display: none; }
.vst-btn--wide { width: 100%; }
.vst-btn:disabled { opacity: .5; }

.vst-btn--primary { background: var(--vst-primary-bg); color: var(--vst-primary-fg); }
.vst-btn--primary:hover:not(:disabled) { opacity: .85; }

.vst-btn--normal {
  background: var(--vst-surface);
  color: var(--vst-fg);
  border-color: var(--vst-line);
}
.vst-btn--normal:hover:not(:disabled) {
  background: var(--vst-surface-2);
  border-color: var(--vst-line-strong);
}

.vst-btn--quiet { color: var(--vst-fg-2); }
.vst-btn--quiet:hover:not(:disabled) { background: var(--vst-surface-2); color: var(--vst-fg); }

.vst-btn--danger { color: var(--vst-danger); border-color: var(--vst-line); }
.vst-btn--danger:hover:not(:disabled) { background: var(--vst-danger); color: #fff; border-color: transparent; }

/* ─── поля ──────────────────────────────────────────────────────────── */

.vst-field, .vst-para { display: flex; flex-direction: column; gap: var(--vst-gap-1); }

.vst-field__label, .vst-para__label { color: var(--vst-fg-2); font-size: var(--vst-text-s); }

.vst-field__input, .vst-para__input {
  width: 100%;
  padding: 0 var(--vst-gap-3);
  height: var(--vst-lay-control-height);
  background: var(--vst-surface-2);
  color: var(--vst-fg);
  border: 1px solid var(--vst-line);
  border-radius: var(--vst-radius);
  transition: border-color var(--vst-motion) var(--vst-ease);
}
.vst-field__input:hover:not(:disabled),
.vst-para__input:hover:not(:disabled) { border-color: var(--vst-line-strong); }
.vst-para__input {
  height: auto;
  padding: var(--vst-gap-2) var(--vst-gap-3);
  line-height: var(--vst-leading);
  resize: none;
}
.vst-field__input::placeholder, .vst-para__input::placeholder { color: var(--vst-fg-3); }
.vst-field__input:disabled, .vst-para__input:disabled { opacity: .55; }

.vst-field__hint, .vst-para__hint {
  display: flex;
  justify-content: space-between;
  gap: var(--vst-gap-2);
  color: var(--vst-fg-3);
  font-size: var(--vst-text-s);
}
.vst-para__counter { font-family: var(--vst-font-mono); font-size: var(--vst-text-xs); }

/* Ошибка занимает место, только когда она есть: зарезервированная строка
   двигает форму при первом же появлении и выглядит как прыжок вёрстки. */
.vst-field__error, .vst-para__error { color: var(--vst-danger); font-size: var(--vst-text-s); }
.vst-field__error:empty, .vst-para__error:empty { display: none; }
.is-invalid .vst-field__input, .is-invalid .vst-para__input { border-color: var(--vst-danger); }

/* ─── список ────────────────────────────────────────────────────────── */

.vst-list { display: flex; flex-direction: column; gap: 2px; }

.vst-list__row {
  width: 100%;
  display: flex;
  align-items: center;
  gap: var(--vst-gap-3);
  padding: var(--vst-gap-3);
  border: 1px solid transparent;
  border-radius: var(--vst-radius);
  text-align: left;
}
.vst-list__row:hover:not(:disabled) { background: var(--vst-surface); border-color: var(--vst-line-quiet); }
.vst-list__row[aria-current='true'] { background: var(--vst-surface); border-color: var(--vst-line); }
.vst-list__row:disabled { opacity: .5; }

.vst-list__main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.vst-list__title { font-weight: var(--vst-weight-medium); }
.vst-list__note { color: var(--vst-fg-3); font-size: var(--vst-text-s); }
.vst-list__badges { display: flex; flex-wrap: wrap; gap: var(--vst-gap-1); margin-top: var(--vst-gap-1); }
.vst-list__meta { color: var(--vst-fg-3); font-size: var(--vst-text-s); white-space: nowrap; }
.vst-list__empty { padding: var(--vst-gap-5); color: var(--vst-fg-3); text-align: center; }

/* ─── вкладки ───────────────────────────────────────────────────────── */

.vst-tabs {
  display: inline-flex;
  gap: 2px;
  padding: 2px;
  background: var(--vst-surface-2);
  border-radius: var(--vst-radius-s);
}

.vst-tabs__tab {
  height: 24px;
  padding: 0 var(--vst-gap-3);
  border-radius: calc(var(--vst-radius-s) - 2px);
  color: var(--vst-fg-2);
  font-size: var(--vst-text-s);
}
.vst-tabs__tab:hover:not(:disabled) { color: var(--vst-fg); }
.vst-tabs__tab[aria-selected='true'] { background: var(--vst-surface); color: var(--vst-fg); }
.vst-tabs__tab:disabled { opacity: .45; }

/* ─── находка ───────────────────────────────────────────────────────── */

.vst-finding {
  display: flex;
  align-items: flex-start;
  gap: var(--vst-gap-3);
  padding: var(--vst-gap-3) var(--vst-gap-4);
  background: var(--vst-surface);
  border: 1px solid var(--vst-line-quiet);
  border-radius: var(--vst-radius-l);
}
.vst-finding__mark { display: flex; margin-top: 1px; color: var(--vst-fg-3); }
.vst-finding--ok .vst-finding__mark { color: var(--vst-ok); }
.vst-finding--info .vst-finding__mark { color: var(--vst-accent); }
.vst-finding--warn .vst-finding__mark { color: var(--vst-warn); }
.vst-finding--error .vst-finding__mark { color: var(--vst-danger); }
.vst-finding--warn { border-color: var(--vst-warn-line); }
.vst-finding--error { border-color: var(--vst-danger); }

.vst-finding__body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.vst-finding__title { font-weight: var(--vst-weight-medium); }
.vst-finding__note { color: var(--vst-fg-3); font-size: var(--vst-text-s); }
.vst-finding__note:empty { display: none; }
.vst-finding__chips { display: flex; flex-wrap: wrap; gap: var(--vst-gap-1); margin-top: var(--vst-gap-2); }
.vst-finding__action { align-self: flex-start; margin-top: var(--vst-gap-2); color: var(--vst-accent); font-size: var(--vst-text-s); }
.vst-finding__meta { font-family: var(--vst-font-mono); font-size: var(--vst-text-xs); color: var(--vst-fg-3); }

/* ─── прогресс ──────────────────────────────────────────────────────── */

.vst-progress { display: flex; flex-direction: column; gap: var(--vst-gap-2); }
.vst-progress__head { display: flex; justify-content: space-between; gap: var(--vst-gap-2); }
.vst-progress__label { font-weight: var(--vst-weight-medium); }
.vst-progress__count { font-family: var(--vst-font-mono); font-size: var(--vst-text-xs); color: var(--vst-fg-3); }

.vst-progress__track {
  height: 4px;
  background: var(--vst-surface-2);
  border-radius: var(--vst-radius-pill);
  overflow: hidden;
}
.vst-progress__bar {
  height: 100%;
  width: 0;
  background: var(--vst-accent);
  border-radius: inherit;
  transition: width var(--vst-motion) var(--vst-ease);
}
.vst-progress__note { color: var(--vst-fg-3); font-size: var(--vst-text-s); }
.vst-progress__note:empty { display: none; }

.is-indeterminate .vst-progress__bar {
  width: 35%;
  animation: vst-slide 1.4s var(--vst-ease) infinite;
}
@keyframes vst-slide {
  0% { transform: translateX(-100%); }
  100% { transform: translateX(300%); }
}

/* ─── тумблер ───────────────────────────────────────────────────────── */

.vst-toggle {
  display: flex;
  align-items: flex-start;
  gap: var(--vst-gap-3);
  padding: var(--vst-gap-1) 0;
  text-align: left;
}
.vst-toggle__track {
  flex: none;
  position: relative;
  width: 32px; height: 18px;
  margin-top: 2px;
  background: var(--vst-surface-2);
  border: 1px solid var(--vst-line);
  border-radius: var(--vst-radius-pill);
  transition: background var(--vst-motion-fast) var(--vst-ease);
}
.vst-toggle__knob {
  position: absolute;
  top: 2px; left: 2px;
  width: 12px; height: 12px;
  background: var(--vst-fg-3);
  border-radius: 50%;
  transition: transform var(--vst-motion-fast) var(--vst-ease), background var(--vst-motion-fast) var(--vst-ease);
}
.vst-toggle.is-on .vst-toggle__track { background: var(--vst-accent); border-color: transparent; }
.vst-toggle.is-on .vst-toggle__knob { transform: translateX(14px); background: var(--vst-primary-fg); }
.vst-toggle__body { display: flex; flex-direction: column; gap: 2px; }
.vst-toggle__hint { color: var(--vst-fg-3); font-size: var(--vst-text-s); }
.vst-toggle:disabled { opacity: .5; }

/* ─── всплывашка ────────────────────────────────────────────────────── */

.vst-popover {
  position: fixed;
  inset: auto;
  margin: 0;
  z-index: var(--vst-z-popover);
  min-width: 180px;
  max-width: min(420px, calc(100vw - 2 * var(--vst-gap-2)));
  padding: var(--vst-gap-2);
  background: var(--vst-surface);
  color: var(--vst-fg);
  border: 1px solid var(--vst-line);
  border-radius: var(--vst-radius);
  box-shadow: var(--vst-shadow-pop);
}
.vst-popover:not(:popover-open):not(.vst-popover--plain) { display: none; }

/* ─── экраны ────────────────────────────────────────────────────────────
 *
 * Правила лежат здесь, а не в файлах экранов: инструмент, у которого каждый
 * экран несёт свои отступы, разъезжается на третьем экране. Все величины —
 * из tokens.css, литералов быть не должно.
 */

.vst-screen {
  padding: var(--vst-gap-6) var(--vst-gap-6) var(--vst-gap-7);
}

/* Колонка чтения задаётся БЛОКАМ, а не всем детям экрана подряд.
 *
 * Правило `.vst-screen > *` выглядело короче и оказалось ловушкой: редактор —
 * тоже экран, и его холст получал ширину колонки текста. Живой прогон дал
 * серую полосу в триста пикселей вместо холста. Общее правило, которое
 * приходится отменять исключениями, всегда отменяет не только их. */
.vst-state,
.vst-form,
.vst-run__stage,
.vst-screen > p { max-width: 76ch; }

.vst-muted { color: var(--vst-fg-3); }

/* ─── состояния: пусто, ошибка, ворота ──────────────────────────────── */

.vst-state {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--vst-gap-3);
  padding: var(--vst-gap-6);
  border: 1px solid var(--vst-line);
  border-radius: var(--vst-radius-l);
  background: var(--vst-surface);
}
.vst-state h2 { font-size: var(--vst-text-xl); font-weight: var(--vst-weight-bold); margin: 0; }
.vst-state p { margin: 0; line-height: var(--vst-leading-loose); }
.vst-state--bad { border-color: var(--vst-line-strong); }

/* ─── список проектов ───────────────────────────────────────────────── */

.vst-cards {
  display: grid;
  /* От минимальной ширины карточки, а не от числа колонок: на узком окне
   * колонка становится одна сама, без второго набора правил. */
  grid-template-columns: repeat(auto-fill, minmax(min(320px, 100%), 1fr));
  gap: var(--vst-gap-4);
}

.vst-card {
  display: flex;
  flex-direction: column;
  gap: var(--vst-gap-2);
  padding: var(--vst-gap-4);
  border: 1px solid var(--vst-line);
  border-radius: var(--vst-radius-l);
  background: var(--vst-surface);
  transition: border-color var(--vst-motion) var(--vst-ease);
}
.vst-card:hover { border-color: var(--vst-line-strong); }
/* Кнопка выравнивается по ВЕРХУ, а не по середине: имя проекта — это фраза
   человека, и на двух строках «Удалить» съезжает к их середине, повисая
   ни у чего. */
.vst-card__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--vst-gap-2);
}
/* Имя ужимается, кнопка — нет.
 *
 * По умолчанию во флексе ужимаются оба, и длинное имя отжало кнопку до
 * ширины подписи: значок корзины схлопнулся в ноль и пропал ровно у той
 * карточки, где имя длиннее. Выглядело это как разные кнопки у соседних
 * карточек — то есть как сбой, а не как теснота. */
.vst-card__head > .vst-card__open { min-width: 0; }
.vst-card__head > .vst-btn { flex: none; }
/* Имя обрезается на второй строке.
 *
 * Имя проекта — это первая фраза человека о деле, и она бывает длиной
 * в строку прайса. Три строки заголовка ломают ряд карточек по высоте
 * и отжимают вниз то, ради чего в карточку и смотрят: этап и время. */
.vst-card__open {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  font-size: var(--vst-text-l);
  font-weight: var(--vst-weight-medium);
  line-height: var(--vst-leading-tight);
  color: inherit;
  text-decoration: none;
}
.vst-card__open:hover { text-decoration: underline; }
.vst-card__origin { font-size: var(--vst-text-s); }
.vst-card__facts {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--vst-gap-2);
  font-size: var(--vst-text-s);
  color: var(--vst-fg-2);
}

.vst-tag {
  padding: 2px var(--vst-gap-2);
  border-radius: var(--vst-radius-pill);
  background: var(--vst-surface-2);
  color: var(--vst-fg-2);
}
/* Находки — жёлтым, а не акцентом.
 *
 * Акцент стал ахроматическим пером, и метка «3 находки» на нём сравнялась
 * с обычной меткой этапа: то, ради чего человек и смотрит на карточку,
 * перестало отличаться от того, что он и так знает. */
.vst-tag--warn {
  background: var(--vst-warn-bg);
  color: var(--vst-warn);
  border: 1px solid var(--vst-warn-line);
}

/* ─── формы ─────────────────────────────────────────────────────────── */

.vst-form { display: flex; flex-direction: column; align-items: flex-start; gap: var(--vst-gap-4); }
.vst-form > * { width: 100%; }
.vst-form > button { width: auto; }

/* Колонка ввода — 768 px по центру, как поле на главной. */
.vst-intake__column {
  width: 100%;
  max-width: 768px;
  margin: 0 auto;
  padding-top: var(--vst-gap-7);
}

.vst-intake__count { display: block; font-size: var(--vst-text-s); margin-top: calc(-1 * var(--vst-gap-2)); }
.vst-intake__more { margin-top: var(--vst-gap-2); }
.vst-intake__more summary { cursor: pointer; color: var(--vst-fg-2); }
.vst-intake__examples {
  margin-top: var(--vst-gap-6);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--vst-gap-2);
}

.vst-example {
  text-align: left;
  font: inherit;
  color: var(--vst-fg-2);
  background: none;
  border: 1px dashed var(--vst-line);
  border-radius: var(--vst-radius-s);
  padding: var(--vst-gap-2) var(--vst-gap-3);
  cursor: pointer;
}
.vst-example:hover { border-style: solid; color: var(--vst-fg); }

/* ─── лента прогона ─────────────────────────────────────────────────── */

.vst-feed { list-style: none; margin: var(--vst-gap-4) 0 0; padding: 0; display: flex; flex-direction: column; gap: var(--vst-gap-1); }
.vst-feed__row {
  display: grid;
  grid-template-columns: 16px 1fr auto;
  align-items: baseline;
  gap: var(--vst-gap-2);
  padding: var(--vst-gap-1) 0;
  border-bottom: 1px solid var(--vst-line-quiet);
}
.vst-feed__row--warn { color: var(--vst-fg); }
.vst-feed__row--bad { color: var(--vst-fg); background: var(--vst-accent-quiet); }
.vst-feed__row--done { font-weight: var(--vst-weight-medium); }
.vst-feed__text { min-width: 0; overflow-wrap: anywhere; }
.vst-feed--compact { font-size: var(--vst-text-s); max-height: 40vh; overflow: auto; }
.vst-run__stage { font-size: var(--vst-text-l); font-weight: var(--vst-weight-medium); }

/* ─── редактор ──────────────────────────────────────────────────────── */

/* Правило редактора живёт ОДНО и в конце файла: два объявления одного
 * класса — это спор, который выигрывает порядок строк, а не смысл. */
.vst-canvas { overflow: auto; background: var(--vst-canvas-well); }
/* Кромка отделяет лист от подложки. Тень тут не годится: она масштабируется
   вместе со сценой и при 65 % становится тоньше волоса. */
.vst-canvas__stage { display: block; box-shadow: var(--vst-canvas-edge); }
/* Фон кадра — БЕЛЫЙ, а не поверхность инструмента.
 *
 * Пока страница грузится, кадр показывает свой фон. С цветом панели это
 * читается как «холст не открылся», а с белым — как пустая страница,
 * которой она сейчас и станет. */
.vst-canvas__frame { display: block; width: 100%; height: 100%; min-height: 100vh; border: 0; background: #fff; }
.vst-run-panel {
  border-left: 1px solid var(--vst-line);
  background: var(--vst-surface);
  padding: var(--vst-gap-4);
  overflow: auto;
  display: flex; flex-direction: column; gap: var(--vst-gap-3);
}
.vst-run-panel h2 { font-size: var(--vst-text-m); font-weight: var(--vst-weight-bold); margin: 0; }
.vst-run-panel__steps { display: flex; flex-wrap: wrap; gap: var(--vst-gap-2); }
.vst-run-panel__note { font-size: var(--vst-text-s); margin-top: auto; }

.vst-publish__override { margin-top: var(--vst-gap-4); }
.vst-publish__override summary { cursor: pointer; color: var(--vst-fg-2); }

/* ─── дерево ────────────────────────────────────────────────────────── */

/*
 * Высота строки приезжает из layout.ts переменной `--vst-lay-tree-row`
 * и здесь числом не повторяется: на ней стоит вся арифметика виртуализации,
 * и второе число означало бы, что окно рисуемых строк считается не от той
 * высоты, которую строка занимает, — с промахом ровно на разницу.
 */

.vst-tree {
  /* Шаг вложенности. Строка получает только глубину числом в `--vst-depth`;
     величина отступа остаётся здесь, рядом с остальным ритмом. */
  --vst-tree-step: var(--vst-gap-3);

  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  overflow: auto;
  /* Место под полосу прокрутки держится всегда: при виртуализации она
     появляется почти сразу, и её приход сдвигал бы теги всех строк. */
  scrollbar-gutter: stable;
  /* Дерево прокручено до конца — колесо не должно уносить страницу студии. */
  overscroll-behavior: contain;
  background: var(--vst-surface);
}

/* Фокус объявляет полоса курсора, а не кольцо вокруг колонки: кольцо
   на 320 px панели не говорит, ГДЕ курсор, а именно это и нужно знать. */
.vst-tree:focus-visible { outline: none; }

.vst-tree__space { position: relative; }

.vst-tree__row {
  position: absolute;
  inset-inline: 0;
  top: 0;
  height: var(--vst-lay-tree-row);
  display: flex;
  align-items: center;
  gap: var(--vst-gap-1);
  padding-left: calc(var(--vst-gap-2) + var(--vst-depth, 0) * var(--vst-tree-step));
  padding-right: var(--vst-gap-2);
  white-space: nowrap;
  /* Строка режет всё, что не влезло: без этого длинный ключ выталкивает
     тег за край панели и он рисуется поверх соседнего блока. */
  overflow: hidden;
  cursor: default;
  /* Полосы подсветки лежат под строками, но перехватывать клики нельзя
     и им, и незанятым слотам пула — попадание считается по геометрии. */
  user-select: none;
}
/* Слот пула вне окна прячется атрибутом, а `display: flex` выше сильнее
   правила браузера для `[hidden]` — без этой строки скрытая строка видна. */
.vst-tree__row[hidden] { display: none; }

.vst-tree__twisty {
  display: grid;
  place-items: center;
  width: var(--vst-gap-4);
  height: var(--vst-gap-4);
  flex: 0 0 auto;
  color: var(--vst-fg-3);
  cursor: pointer;
}
.vst-tree__twisty:hover { color: var(--vst-fg); }
/* У листа стрелка не убирается, а гасится: убранная сдвигает подпись
   на ширину значка, и одноуровневые строки перестают стоять в колонку. */
.vst-tree__row:not(.vst-tree__row--kids) .vst-tree__twisty { visibility: hidden; }
.vst-tree__row--open .vst-tree__twisty { transform: rotate(90deg); }

.vst-tree__mark { flex: 0 0 auto; color: var(--vst-fg-3); }
.vst-tree__row--filled .vst-tree__mark rect { fill: currentColor; stroke: none; }

/* Имя не ужимается вовсе, а не «ужимается неохотно»: у элемента с
   `overflow: hidden` автоматический минимум равен нулю, поэтому даже
   двухпроцентная доля усадки съедает букву — «Text» превращается в «T…»,
   потому что многоточие занимает место буквы. Половина строки —
   предохранитель для непомерно длинного ключа: он обрежется сам,
   а не вытолкнет тег и точку за край. */
.vst-tree__name {
  flex: 0 0 auto;
  max-width: 50%;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Всю усадку принимает содержимое: обрезанное «Лечение…» остаётся понятным,
   а обрезанное «Sect…» перестаёт отличать секцию от списка. */
.vst-tree__preview {
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  color: var(--vst-fg-3);
}
.vst-tree__gap { flex: 1 1 auto; }

.vst-tree__dot {
  flex: 0 0 auto;
  width: var(--vst-gap-1);
  height: var(--vst-gap-1);
  border-radius: var(--vst-radius-pill);
  /* Тот же токен, что у точки в инспекторе: это ОДИН И ТОТ ЖЕ смысл —
     значение принадлежит человеку. На ахроматическом акценте точка
     сливалась с текстом дерева и переставала что-либо значить. */
  background: var(--vst-dot);
}

.vst-tree__tag {
  flex: 0 0 auto;
  font-size: var(--vst-text-xs);
  color: var(--vst-fg-3);
}

.vst-tree__row--pick .vst-tree__preview,
.vst-tree__row--pick .vst-tree__tag { color: var(--vst-fg-2); }

/* Три полосы вместо классов на строках: смена выделения двигает один
   элемент, а не ищет в DOM две строки, из которых одна уже за окном. */
.vst-tree__band {
  position: absolute;
  inset-inline: 0;
  top: 0;
  height: var(--vst-lay-tree-row);
  pointer-events: none;
}
.vst-tree__band--hover { background: var(--vst-surface-2); }
.vst-tree__band--pick {
  background: var(--vst-accent-quiet);
  box-shadow: inset var(--vst-focus-width) 0 0 var(--vst-accent);
}
/* Курсор клавиатуры гасится прозрачностью, а не `display`: скрытый
   `display` пришлось бы возвращать правилом сильнее, чем `[hidden]`,
   и полоса выезжала бы за последнюю строку. */
.vst-tree__band--cursor {
  opacity: 0;
  outline: var(--vst-focus-width) solid var(--vst-focus);
  outline-offset: calc(-1 * var(--vst-focus-width));
}
.vst-tree:focus-visible .vst-tree__band--cursor { opacity: 1; }

.vst-tree__empty {
  padding: var(--vst-gap-3) var(--vst-gap-2);
  color: var(--vst-fg-3);
}

/* ─── левый рельс и разделы ──────────────────────────────────────────────
 *
 * Раздел 3.3 EDITOR.md и макет `docs/ui/Main.dc.html`: полоса 48 px, значок
 * 32×32, активный — на приподнятой поверхности. Ширина рельса и размер значка
 * приезжают из `LAYOUT` переменными `--vst-lay-*`: второе место, где записано
 * 48, разойдётся с первым, а разъехавшийся рельс двигает холст на два пикселя
 * и ломает арифметику зума.
 */

.vst-rail {
  flex: none;
  width: var(--vst-lay-rail);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: calc(var(--vst-gap-1) / 2);
  padding: var(--vst-gap-2) 0;
  background: var(--vst-top);
  border-right: 1px solid var(--vst-line);
}

.vst-rail__btn {
  display: grid;
  place-items: center;
  width: var(--vst-lay-control-height);
  height: var(--vst-lay-control-height);
  border-radius: var(--vst-radius-s);
  color: var(--vst-fg-3);
}
.vst-rail__btn:hover { color: var(--vst-fg); background: var(--vst-surface-2); }
.vst-rail__btn--on { color: var(--vst-fg); background: var(--vst-surface-2); }
/* Находки красят сам значок, а не цифру поверх него: цифра на 32 px читается
   только вблизи, а цвет виден боковым зрением — за этим он и нужен. */
.vst-rail__btn--flag { color: var(--vst-warn); }
.vst-rail__btn--flag.vst-rail__btn--on { background: var(--vst-warn-bg); }

.vst-rail__spacer { flex: 1; }

/* Взведённый аккорд виден: клавиша, съеденная молча, читается как поломка. */
.vst-rail__pending {
  margin-top: var(--vst-gap-2);
  font-family: var(--vst-font-mono);
  font-size: var(--vst-text-xs);
  color: var(--vst-accent);
}
.vst-rail__pending[hidden] { display: none; }

/* `display: flex` перебивает служебный `display: none` у `[hidden]`,
   поэтому скрытие возвращается явно — иначе закрытая панель остаётся видимой. */
.vst-rail-panel {
  flex: none;
  width: var(--vst-rail-panel-w, var(--vst-lay-left-panel-def));
  display: flex;
  flex-direction: column;
  min-height: 0;
  background: var(--vst-surface);
  border-right: 1px solid var(--vst-line);
  overflow: hidden;
}
.vst-rail-panel[hidden] { display: none; }

/* Ниже 1640 панель ложится ПОВЕРХ холста и не перекладывает его (3.2).
   `fixed`, а не `absolute`: рельс не знает своего родителя и не вправе
   требовать от экрана позиционирующего предка — геометрию он берёт из тех же
   переменных раскладки, из которых собрана верхняя полоса. */
[data-fit='overlay'] .vst-rail-panel,
[data-fit='narrow'] .vst-rail-panel {
  position: fixed;
  left: var(--vst-lay-rail);
  top: var(--vst-lay-top-bar);
  bottom: 0;
  z-index: calc(var(--vst-z-popover) - 1);
  box-shadow: var(--vst-shadow-pop);
}

.vst-panel__head {
  flex: none;
  height: var(--vst-lay-top-bar);
  display: flex;
  align-items: center;
  gap: var(--vst-gap-2);
  padding: 0 var(--vst-gap-2) 0 var(--vst-gap-3);
  border-bottom: 1px solid var(--vst-line);
}
.vst-panel__title { font-size: var(--vst-text); font-weight: var(--vst-weight-medium); letter-spacing: 0; }
.vst-panel__chord {
  margin-right: auto;
  padding: calc(var(--vst-gap-1) / 2) var(--vst-gap-1);
  border-radius: var(--vst-radius-s);
  background: var(--vst-surface-2);
  font-size: var(--vst-text-xs);
  color: var(--vst-fg-3);
}
.vst-panel__close { flex: none; }
/* Подпись остаётся для читалки и уходит с глаз: значок без имени объявляется
   как «кнопка», а имя рядом со значком в полосе на 320 px съедает заголовок. */
.vst-panel__close .vst-btn__label {
  position: absolute;
  width: 1px; height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.vst-panel__body { flex: 1; min-height: 0; overflow: auto; }

.vst-panel {
  display: flex;
  flex-direction: column;
  gap: var(--vst-gap-3);
  padding: var(--vst-gap-3);
  /* `min-height`, а не `height`: раздел с длинным содержимым обязан расти
     и отдавать прокрутку телу панели. Жёсткая высота сжимала бы карточки
     находок до налезания строк друг на друга. */
  min-height: 100%;
}
.vst-panel[hidden] { display: none; }
/* Исключение — «Прогон»: у него прокручивается ЛЕНТА, а кнопки этапов
   и полоса прогресса остаются на месте. Растущая панель уводила бы
   «Остановить» за нижний край ровно тогда, когда она нужна. */
.vst-panel--run { height: 100%; min-height: 0; }

.vst-panel__note {
  font-size: var(--vst-text-s);
  color: var(--vst-fg-3);
  line-height: var(--vst-leading-loose);
}
.vst-panel__note:empty { display: none; }
.vst-panel__row { display: flex; justify-content: flex-end; gap: var(--vst-gap-2); }

.vst-panel__stub { display: flex; flex-direction: column; gap: var(--vst-gap-2); }
.vst-panel__stub-head { font-size: var(--vst-text-s); color: var(--vst-fg); }
.vst-panel__stub-head + p { margin-bottom: var(--vst-gap-2); }
.vst-panel__stub p { font-size: var(--vst-text-s); color: var(--vst-fg-2); line-height: var(--vst-leading-loose); }

/* ─── раздел «Прогон» ───────────────────────────────────────────────── */

.vst-run__steps { display: flex; flex-wrap: wrap; gap: var(--vst-gap-2); }
.vst-feed__mark { display: grid; place-items: center; }
.vst-feed__row--warn .vst-feed__mark { color: var(--vst-warn); }
.vst-feed__row--done .vst-feed__mark { color: var(--vst-ok); }
/* Внутри панели лента занимает остаток высоты, а не 40% экрана: панель уже
   ограничена своей высотой, и второй потолок оставлял бы под лентой пустоту. */
.vst-panel--run .vst-feed { margin-top: 0; flex: 1; min-height: 0; max-height: none; }

/* ─── раздел «Аудит» ────────────────────────────────────────────────── */

.vst-audit { display: flex; flex-direction: column; gap: var(--vst-gap-4); }
.vst-audit__group { display: flex; flex-direction: column; gap: var(--vst-gap-2); }
.vst-audit__head {
  display: flex;
  align-items: center;
  gap: var(--vst-gap-2);
  font-size: var(--vst-text-s);
  color: var(--vst-fg);
}

/* ─── раздел «Тема» ─────────────────────────────────────────────────── */

.vst-theme { display: flex; flex-direction: column; gap: var(--vst-gap-4); }
.vst-theme__group { display: flex; flex-direction: column; gap: var(--vst-gap-2); }
.vst-theme__head { font-size: var(--vst-text-s); color: var(--vst-fg-2); }
.vst-theme__rows { display: flex; flex-direction: column; gap: var(--vst-gap-1); }

.vst-theme__row {
  display: flex;
  align-items: center;
  gap: var(--vst-gap-2);
  min-height: var(--vst-gap-5);
  font-size: var(--vst-text-s);
}
.vst-theme__name { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.vst-theme__marks { display: flex; flex: none; gap: calc(var(--vst-gap-1) / 2); }

.vst-swatch {
  display: block;
  width: var(--vst-gap-4);
  height: var(--vst-gap-4);
  border: 1px solid var(--vst-line);
  border-radius: var(--vst-radius-s);
}

/* Шкала отступов читается глазом: полоса шириной в сам отступ отвечает
   на вопрос «во сколько раз» быстрее, чем десять сравнений чисел подряд.
   Колонка имени фиксирована — иначе полосы начинались бы с разных мест
   и шкала перестала бы быть шкалой. */
.vst-theme__row--space { display: grid; grid-template-columns: var(--vst-gap-6) 1fr auto; }
.vst-theme__bar {
  display: block;
  height: var(--vst-gap-2);
  max-width: 100%;
  border-radius: var(--vst-radius-pill);
  background: var(--vst-accent-quiet);
}

.vst-theme__radii { display: flex; flex-wrap: wrap; gap: var(--vst-gap-3); }
.vst-theme__radius-cell { display: flex; flex-direction: column; align-items: center; gap: var(--vst-gap-1); }
.vst-theme__radius {
  display: block;
  width: var(--vst-gap-7);
  height: var(--vst-gap-7);
  background: var(--vst-surface-2);
  border: 1px solid var(--vst-line-strong);
}

/* ─── мост холста: обводки над страницей ────────────────────────────── */

/* Слой лежит поверх фрейма и не берёт на себя ни одного события: клик обязан
   дойти до страницы, иначе выделять будет нечего. Обрезка своя — узел,
   уехавший прокруткой за край холста, не должен рисоваться поверх панели. */
.vst-canvas-overlay {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}

/* Рамка рисуется `outline`, а не `border`: граница вошла бы ВНУТРЬ коробки
   (`box-sizing: border-box` на всём приложении) и закрыла крайний пиксель
   узла — ровно тот, по которому целятся, двигая отступ. */
.vst-canvas-outline {
  position: absolute;
  top: 0;
  left: 0;
  outline: 1px solid var(--vst-accent);
}
.vst-canvas-outline[hidden] { display: none; }

/* Наведение слабее выделения. Две одинаковые рамки читаются как две
   выделенные вещи, и человек ищет, какую из них он выбрал. */
.vst-canvas-outline--hover {
  outline-color: color-mix(in oklab, var(--vst-accent) 45%, transparent);
}
.vst-canvas-outline--sel { outline-width: var(--vst-focus-width); }

.vst-canvas-outline__chip {
  position: absolute;
  left: 0;
  bottom: 100%;
  padding: 0 var(--vst-gap-1);
  border-radius: var(--vst-radius-s);
  background: var(--vst-accent);
  /* Перо, обратное акценту, а не зашитый белый: акцент в тёмной теме сам
     белый, и подпись на нём исчезала целиком. */
  color: var(--vst-primary-fg);
  font-size: var(--vst-text-xs);
  line-height: var(--vst-leading-loose);
  white-space: nowrap;
}

/* У верхнего края холста над рамкой места нет, и чип уходит внутрь неё:
   срезанный обрезкой слоя чип не отвечает на вопрос, что под курсором. */
.vst-canvas-outline--tight .vst-canvas-outline__chip { bottom: auto; top: 0; }

/* ─── инспектор ─────────────────────────────────────────────────────────
 *
 * Плотность здесь не вкус, а требование: на 320 px ширины и 900 px высоты
 * помещается шапка, семь секций и строка задачи. Отсюда строка свойства
 * высотой в один контрол (`--vst-lay-control-height`) и пары полей в ряд —
 * ровно как на макете `docs/ui/Inspector.dc.html`.
 *
 * Цветом обозначается только состояние: синим — владение человека,
 * янтарным — значение вне шкалы политики и вопрос арбитра, красным —
 * отказ. Ничего декоративного: панель стоит вплотную к чужому дизайну,
 * и каждый лишний цвет читается как часть этого дизайна.
 */

.vst-inspector {
  display: flex;
  flex-direction: column;
  min-height: 0;
  background: var(--vst-surface);
  border-left: 1px solid var(--vst-line);
}

.vst-inspector__body {
  flex: 1 1 auto;
  min-height: 0;
  overflow: auto;
  overscroll-behavior: contain;
  scrollbar-gutter: stable;
  padding: var(--vst-lay-section-pad-y) var(--vst-gap-3);
  display: flex;
  flex-direction: column;
  gap: var(--vst-gap-3);
}

.vst-inspector__note { font-size: var(--vst-text-s); margin: 0; }
.vst-inspector__error { font-size: var(--vst-text-s); margin: 0; color: var(--vst-danger); }

/* Полоса Simple прилипает к низу: факт ручной правки не должен уезжать
   из виду вместе с прокруткой — он объясняет, почему смена темы
   не подействовала на часть значений. */
.vst-inspector__band {
  position: sticky;
  bottom: calc(var(--vst-lay-section-pad-y) * -1);
  margin-top: auto;
  display: flex;
  align-items: center;
  gap: var(--vst-gap-2);
  padding: var(--vst-gap-2) var(--vst-gap-3);
  font-size: var(--vst-text-s);
  color: var(--vst-fg-2);
  background: var(--vst-surface-2);
  border-radius: var(--vst-radius-s);
}
.vst-inspector__band-btn {
  margin-left: auto;
  border: 0;
  background: none;
  padding: 0;
  color: var(--vst-accent);
  font: inherit;
  cursor: pointer;
}

/* ── шапка ─────────────────────────────────────────────────────────── */

.vst-head {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  gap: var(--vst-gap-1);
  padding-bottom: var(--vst-gap-2);
  border-bottom: 1px solid var(--vst-line);
  font-size: var(--vst-text-s);
}

.vst-head__tabs { border-bottom: 1px solid var(--vst-line-quiet); }
.vst-head__tabs .vst-tabs { padding: 0 var(--vst-gap-2); }

/* Пустая строка шапки НЕ занимает места.
 *
 * Когда ничего не выделено, пусты сразу четыре: имя узла, путь предков,
 * ключ и повтор. Вместе они держали сто пикселей пустоты между вкладками
 * и слоем — панель выглядела недогруженной ровно в тот момент, когда она
 * должна объяснять, что делать.
 *
 * Прыжка шапки, которого я боялся раньше, при этом нет: между двумя
 * ВЫДЕЛЕННЫМИ узлами эти строки заполнены обе, а переход «пусто → выделено»
 * и так меняет всю панель. */
.vst-head__identity:empty,
.vst-head__trail:empty,
.vst-head__key:empty { display: none; }

.vst-head__identity,
.vst-head__trail,
.vst-head__key,
.vst-head__layer,
.vst-head__repeat {
  display: flex;
  align-items: center;
  gap: var(--vst-gap-1);
  padding: 0 var(--vst-gap-3);
  min-height: var(--vst-gap-5);
}

.vst-head__role { color: var(--vst-fg); font-weight: var(--vst-weight-medium); }
.vst-head__sep,
.vst-head__tag { color: var(--vst-fg-3); }

.vst-head__trail { flex-wrap: wrap; gap: 0; }
.vst-head__crumb {
  display: inline-flex;
  align-items: center;
  gap: calc(var(--vst-gap-1) / 2);
  border: 0;
  background: none;
  padding: 0 var(--vst-gap-1) 0 0;
  color: var(--vst-fg-3);
  font: inherit;
  cursor: pointer;
}
.vst-head__crumb:hover { color: var(--vst-fg); }

.vst-head__gap { flex: 1 1 auto; }
.vst-head__preview { color: var(--vst-fg-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vst-head__code {
  font-family: var(--vst-font-mono);
  font-size: var(--vst-text-xs);
  color: var(--vst-fg-3);
}

/* Строка «Слой» — единственная строка панели, которая обязана быть видна
   всегда: она отвечает на «куда уедет правка». Отсюда фон, отделяющий
   её от остальных строк шапки. */
.vst-head__layer {
  flex-wrap: wrap;
  gap: var(--vst-gap-2);
  padding-block: var(--vst-gap-1);
  background: var(--vst-surface-2);
}
.vst-head__layer-label { color: var(--vst-fg-2); }

.vst-head__repeat {
  gap: var(--vst-gap-2);
  color: var(--vst-warn);
  background: var(--vst-warn-bg);
  border-block: 1px solid var(--vst-warn-line);
}
.vst-head__repeat[hidden] { display: none; }

/* ── сегменты ──────────────────────────────────────────────────────── */

.vst-seg {
  display: inline-flex;
  gap: 1px;
  padding: 1px;
  background: var(--vst-bg);
  border-radius: var(--vst-radius-s);
}
.vst-seg__btn {
  border: 0;
  background: none;
  padding: var(--vst-gap-1) var(--vst-gap-2);
  border-radius: var(--vst-radius-s);
  color: var(--vst-fg-3);
  font: inherit;
  font-size: var(--vst-text-xs);
  cursor: pointer;
}
.vst-seg__btn:hover:not(:disabled) { color: var(--vst-fg); }
.vst-seg__btn--on { background: var(--vst-surface-2); color: var(--vst-fg); }
.vst-seg__btn:disabled { cursor: default; opacity: .5; }

/* ── секция ────────────────────────────────────────────────────────── */

.vst-sect { display: flex; flex-direction: column; gap: var(--vst-gap-2); }

.vst-sect__head {
  display: flex;
  align-items: center;
  gap: var(--vst-gap-2);
  min-height: var(--vst-gap-5);
  border-top: 1px solid var(--vst-line-quiet);
  padding-top: var(--vst-gap-2);
}
.vst-sect:first-child .vst-sect__head { border-top: 0; padding-top: 0; }

.vst-sect__toggle,
.vst-sect__title {
  display: inline-flex;
  align-items: center;
  gap: var(--vst-gap-1);
  border: 0;
  background: none;
  padding: 0;
  color: var(--vst-fg);
  font: inherit;
  font-weight: var(--vst-weight-medium);
  cursor: pointer;
}
.vst-sect__title { cursor: default; }
.vst-sect__chevron { display: inline-flex; color: var(--vst-fg-3); transition: transform var(--vst-motion-fast) var(--vst-ease); }
.vst-sect__chevron--open { transform: rotate(90deg); }
.vst-sect__gap { flex: 1 1 auto; }

/* «Сбросить» появляется по наведению и только там, где есть что снимать:
   иначе панель несёт одиннадцать ссылок, из которых работают две. */
.vst-sect__reset {
  border: 0;
  background: none;
  padding: 0;
  color: var(--vst-fg-3);
  font: inherit;
  font-size: var(--vst-text-xs);
  cursor: pointer;
  opacity: 0;
  transition: opacity var(--vst-motion-fast) var(--vst-ease);
}
.vst-sect:hover .vst-sect__reset,
.vst-sect__reset:focus-visible { opacity: 1; }
.vst-sect__reset:hover { color: var(--vst-fg); }

.vst-sect__rows {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--vst-lay-control-gap);
  align-items: start;
}

.vst-sect__add {
  font-size: var(--vst-text-xs);
  color: var(--vst-fg-3);
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: calc(var(--vst-gap-1) / 2);
}
.vst-sect__add-btn {
  border: 0;
  background: none;
  padding: 0;
  color: var(--vst-fg-2);
  font: inherit;
  cursor: pointer;
}
.vst-sect__add-btn:hover { color: var(--vst-accent); }
.vst-sect__dotsep { color: var(--vst-line-strong); }

/* ── строка свойства ───────────────────────────────────────────────── */

.vst-prop { display: flex; flex-direction: column; gap: var(--vst-gap-1); min-width: 0; }
.vst-prop--wide,
.vst-prop--adjust,
.vst-prop--warn,
.vst-prop--deny,
.vst-prop--escalate,
.vst-prop--offline { grid-column: 1 / -1; }

.vst-prop__pill {
  display: flex;
  align-items: center;
  gap: var(--vst-gap-1);
  min-height: var(--vst-lay-control-height);
  padding: 0 var(--vst-gap-2);
  background: var(--vst-surface-2);
  border-radius: var(--vst-radius-s);
  font-size: var(--vst-text-s);
}
.vst-prop__name { color: var(--vst-fg-2); white-space: nowrap; }
.vst-prop__gap { flex: 1 1 auto; }
.vst-prop__value { color: var(--vst-fg); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vst-prop__unit { color: var(--vst-fg-3); font-size: var(--vst-text-xs); }
.vst-prop__hint { margin: 0; font-size: var(--vst-text-xs); color: var(--vst-fg-3); }

.vst-prop__input,
.vst-prop__select {
  min-width: 0;
  max-width: 50%;
  border: 0;
  background: none;
  padding: 0;
  color: var(--vst-fg);
  font: inherit;
  text-align: right;
}
.vst-prop__select { max-width: 60%; color: var(--vst-fg); }
.vst-prop__input:disabled,
.vst-prop__select:disabled { color: var(--vst-fg-3); }
.vst-prop__input::placeholder { color: var(--vst-fg-3); }

/* Взведённый контрол: раскрыт из «Добавить», но ничего не задал. Серым —
   потому что значение пока принадлежит политике, и точки рядом нет. */
.vst-prop--armed .vst-prop__input { color: var(--vst-fg-3); }

.vst-prop__swatch {
  flex: 0 0 var(--vst-gap-4);
  width: var(--vst-gap-4);
  height: var(--vst-gap-4);
  border: 1px solid var(--vst-line-strong);
  border-radius: var(--vst-radius-s);
}

.vst-prop__flag {
  border: 0;
  background: var(--vst-bg);
  padding: var(--vst-gap-1) var(--vst-gap-2);
  border-radius: var(--vst-radius-s);
  color: var(--vst-fg-3);
  font: inherit;
  font-size: var(--vst-text-xs);
  cursor: pointer;
}
.vst-prop__flag--on { background: var(--vst-accent-quiet); color: var(--vst-accent); }

/* ── ответ арбитра ─────────────────────────────────────────────────── */

.vst-prop__note {
  margin: 0;
  padding: var(--vst-gap-1) var(--vst-gap-2);
  border-radius: var(--vst-radius-s);
  font-size: var(--vst-text-xs);
  line-height: var(--vst-leading);
}
.vst-prop__note--adjust { color: var(--vst-fg-2); background: var(--vst-surface-2); }
.vst-prop__note--warn { color: var(--vst-warn); background: var(--vst-warn-bg); }
.vst-prop__note--deny { color: var(--vst-danger); background: var(--vst-surface-2); }
.vst-prop__note--escalate {
  color: var(--vst-warn);
  background: var(--vst-warn-bg);
  border: 1px solid var(--vst-warn-line);
}
.vst-prop__notes { margin: var(--vst-gap-1) 0 0; padding-left: var(--vst-gap-4); }
.vst-prop__rule { font-family: var(--vst-font-mono); }
.vst-prop__acts { display: flex; gap: var(--vst-gap-2); margin-top: var(--vst-gap-2); }
.vst-prop__act { font-size: var(--vst-text-xs); }
/* Единственная правка, разрешённая в Simple: снять чужое значение,
   по одному свойству и явно. Ссылкой, а не кнопкой, — она стоит внутри
   фразы и продолжает её. */
.vst-prop__link {
  border: 0;
  background: none;
  padding: 0;
  color: var(--vst-accent);
  font: inherit;
  cursor: pointer;
}
.vst-prop__link:hover { color: var(--vst-accent-hover); }


/* ── владение ──────────────────────────────────────────────────────── */

.vst-own__lines,
.vst-own__none { margin: 0; font-size: var(--vst-text-s); color: var(--vst-fg-2); }
.vst-own__lines p { margin: 0; }
.vst-own__off { color: var(--vst-warn); }
.vst-own__list {
  margin: 0;
  padding-left: var(--vst-gap-4);
  font-size: var(--vst-text-xs);
  color: var(--vst-fg-2);
  max-height: var(--vst-gap-8);
  overflow: auto;
}
.vst-own__acts { display: flex; gap: var(--vst-gap-2); }
.vst-own__reset { align-self: flex-start; }

/* ── маркер владения ───────────────────────────────────────────────── */

/*
 * Место под точку занято ВСЕГДА, даже когда её нет: иначе имена свойств
 * в соседних строках стоят на разных отступах, и колонка перестаёт
 * читаться как колонка.
 */
.vst-dot {
  position: relative;
  flex: 0 0 var(--vst-gap-4);
  width: var(--vst-gap-4);
  height: var(--vst-gap-4);
  border: 0;
  padding: 0;
  background: none;
}
.vst-dot--live { cursor: pointer; }
.vst-dot::before {
  content: '';
  position: absolute;
  inset: 25%;
  border-radius: var(--vst-radius-pill);
}
.vst-dot--user::before,
.vst-dot--ai::before { background: var(--vst-dot); }
/* Полая точка: значение задано, но в ДРУГОМ слое — здесь его нет. */
.vst-dot--elsewhere::before { border: 1px solid var(--vst-dot); }
/* Приглушённая: значение здесь есть, но узкий слой его перебивает. */
.vst-dot--shadowed::before { background: var(--vst-dot); opacity: .45; }
/* Янтарное кольцо: значение вне шкалы политики, поставлено из Tweaks. */
.vst-dot--off::before {
  background: var(--vst-accent);
  box-shadow: 0 0 0 var(--vst-focus-width) var(--vst-warn);
}
.vst-dot--live:hover::before { box-shadow: 0 0 0 var(--vst-focus-width) color-mix(in oklab, var(--vst-dot) 25%, transparent); }

/* ─── редактор целиком ──────────────────────────────────────────────────
 *
 * Четыре колонки: рельс, панель раздела, холст, правая колонка. Панель
 * раздела схлопывается в ноль, когда раздел закрыт, — так холст получает
 * её ширину обратно, а не остаётся с пустой полосой.
 */
.vst-editor {
  display: grid;
  /* Вторая колонка — `auto`, а не переменная.
   *
   * Рельс ставит `--vst-rail-panel-w` НА САМОЙ ПАНЕЛИ, а сетка читала бы её
   * на родителе — переменная от ребёнка родителю не видна, и колонка всегда
   * оставалась нулевой: панель шириной 360 px жила в дорожке шириной ноль
   * и выдавливала холст. `auto` берёт ширину у содержимого, и связь между
   * двумя файлами через одно имя переменной исчезает совсем. */
  grid-template-columns:
    var(--vst-lay-rail)
    auto
    minmax(0, 1fr)
    var(--vst-lay-right-column-def);

  /* Редактор — единственный экран, который НЕ прокручивается целиком:
   * прокручиваются холст, дерево и инспектор по отдельности. Поэтому он
   * отменяет поля и прокрутку `.vst-screen` и берёт ровно высоту окна.
   *
   * Эти три объявления стояли ниже блоком БЕЗ СЕЛЕКТОРА — он потерялся при
   * правке, и браузер молча выбрасывал их целиком. Редактор оставался без
   * высоты, правая колонка вырастала по длине дерева и уезжала за нижний
   * край окна вместе с инспектором. В коде при этом всё выглядело написанным. */
  padding: 0;
  overflow: hidden;
  height: 100%;
}

/*
 * Колонка каждому назначена ЯВНО, а не по порядку в разметке.
 *
 * Панель раздела при закрытом разделе выпадает из потока (`display: none`),
 * и элемент с `display: none` не является элементом сетки вовсе. Оставшиеся
 * трое молча съезжали на дорожку левее: холст оказывался в узкой `auto`,
 * а правая колонка — в широкой `1fr`. На снимке экрана это выглядело как
 * «дерево заняло всё, холст исчез», и наоборот при открытом разделе.
 *
 * Раскладка, зависящая от того, показан ли соседний элемент, — это не сетка,
 * а лотерея.
 */
.vst-editor > .vst-rail { grid-column: 1; }
.vst-editor > .vst-rail-panel { grid-column: 2; }
.vst-editor > .vst-canvas { grid-column: 3; }
.vst-editor > .vst-right { grid-column: 4; }

/* Слой обводок ложится НАД холстом и сам не масштабируется: внутри
 * масштабируемой сцены рамка выделения при 65% стала бы тоньше волоса. */
.vst-canvas { position: relative; }

.vst-right {
  display: grid;
  /* Дерево тянется, инспектор занимает столько, сколько ему нужно снизу.
   * Обратное дало бы дерево в три строки на странице из трёхсот узлов. */
  grid-template-rows: 1fr auto minmax(0, 45%);
  border-left: 1px solid var(--vst-line);
  background: var(--vst-surface);
  min-height: 0;
  overflow: hidden;
}

/* Разделитель — он же ручка ресайза: на референсе тулбар стоит физически
 * между деревом и инспектором, и это требование, а не предложение. */
.vst-right__split {
  height: var(--vst-lay-toolbar);
  border-top: 1px solid var(--vst-line);
  border-bottom: 1px solid var(--vst-line);
  background: var(--vst-surface-2);
  cursor: row-resize;
}

/* Ниже порога правая колонка сворачивается: холсту нужно не меньше 936 px,
 * иначе тело сайта рендерится мельче десяти с половиной пикселей. */
@media (max-width: 1199px) {
  .vst-editor { grid-template-columns: var(--vst-lay-rail) auto minmax(0, 1fr); }
  .vst-right { display: none; }
}

/* ═══ главный экран ══════════════════════════════════════════════════
 *
 * Форма с главного экрана AI-сервиса студии: вопрос по центру, поле под
 * ним, сделанное раньше — ниже. Экран НЕ центрируется по вертикали
 * целиком: начало стоит в верхней трети, а список под ним прокручивается.
 * Полная центровка выглядит хорошо ровно до первого проекта, после чего
 * список уезжает под сгиб и человек не догадывается, что он там есть.
 */

.vst-home {
  display: flex;
  flex-direction: column;
  gap: var(--vst-gap-8);
  padding: var(--vst-gap-8) var(--vst-gap-6);
}

.vst-home__hero {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--vst-gap-3);
  /* Колонка вопроса и поля — 768 px, как у источника. Шире фраза перестаёт
   * читаться одним взглядом, уже — поле становится колодцем. */
  width: 100%;
  max-width: 768px;
  margin: 0 auto;
  padding-top: var(--vst-gap-8);
  text-align: center;
}

.vst-home__title {
  margin: 0;
  font-size: var(--vst-text-hero);
  font-weight: var(--vst-weight-bold);
  line-height: var(--vst-leading-tight);
  letter-spacing: -.02em;
}

.vst-home__sub {
  margin: 0 0 var(--vst-gap-4);
  max-width: 60ch;
  color: var(--vst-fg-3);
  font-size: var(--vst-text-m);
  line-height: var(--vst-leading);
}

.vst-home__ask { width: 100%; }

.vst-home__aside {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--vst-gap-2);
  width: 100%;
}

.vst-home__examples {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--vst-gap-2);
}

/* Пример — кнопка-капсула с обрезанным хвостом: фраза длиной в строку
   развалила бы ряд на три этажа, а короткий огрызок не показывает,
   какой подробности от человека ждут. */
.vst-home__example {
  max-width: 34ch;
  height: auto;
  padding: var(--vst-gap-1) var(--vst-gap-3);
  border-color: var(--vst-line);
  border-radius: var(--vst-radius-pill);
  color: var(--vst-fg-3);
  font-size: var(--vst-text-s);
  font-weight: var(--vst-weight);
}
.vst-home__example .vst-btn__label,
.vst-home__example > span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.vst-home__example:hover:not(:disabled) { color: var(--vst-fg); }

.vst-home__full {
  color: var(--vst-fg-3);
  font-size: var(--vst-text-s);
  text-decoration: none;
}
.vst-home__full:hover { color: var(--vst-fg); text-decoration: underline; }

.vst-home__recent {
  width: 100%;
  max-width: 1120px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: var(--vst-gap-4);
}

.vst-home__h2 {
  margin: 0;
  font-size: var(--vst-text-m);
  font-weight: var(--vst-weight-medium);
  color: var(--vst-fg-2);
}

/* ═══ композитор ═════════════════════════════════════════════════════
 *
 * Рамка у коробки, а не у поля: внутри коробки живёт ещё и подвал
 * с кнопкой, и рамка вокруг одного поля разрезала бы их пополам.
 */

.vst-composer { display: flex; flex-direction: column; gap: var(--vst-gap-2); }

.vst-composer__box {
  display: flex;
  flex-direction: column;
  gap: var(--vst-gap-2);
  padding: var(--vst-gap-3);
  background: var(--vst-surface);
  border: 1px solid var(--vst-line);
  border-radius: var(--vst-radius-xl);
  transition: border-color var(--vst-motion) var(--vst-ease);
  text-align: left;
}
.vst-composer__box:hover { border-color: var(--vst-line-strong); }

/* Кольцо фокуса — у КОРОБКИ, а не у поля внутри.
 *
 * Само поле рамки не имеет, и его собственное кольцо повисло бы внутри
 * коробки вторым прямоугольником. `:focus-within` переносит признак туда,
 * где человек видит границу предмета. */
.vst-composer__box:focus-within {
  border-color: var(--vst-focus);
  box-shadow: 0 0 0 var(--vst-focus-width) var(--vst-accent-quiet);
}

.vst-composer__input {
  width: 100%;
  padding: var(--vst-gap-2);
  background: none;
  border: none;
  color: var(--vst-fg);
  font: inherit;
  font-size: var(--vst-text-m);
  line-height: var(--vst-leading);
  resize: none;
}
.vst-composer__input:focus { outline: none; }
.vst-composer__input::placeholder { color: var(--vst-fg-3); }

.vst-composer__foot {
  display: flex;
  align-items: center;
  gap: var(--vst-gap-3);
  padding-left: var(--vst-gap-2);
}
.vst-composer__hint {
  flex: 1;
  min-width: 0;
  color: var(--vst-fg-3);
  font-size: var(--vst-text-s);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.vst-composer__count {
  color: var(--vst-fg-3);
  font-family: var(--vst-font-mono);
  font-size: var(--vst-text-xs);
}
.vst-composer__count:empty { display: none; }

.vst-composer__error { color: var(--vst-danger); font-size: var(--vst-text-s); text-align: left; }
.vst-composer__error:empty { display: none; }
.vst-composer.is-invalid .vst-composer__box { border-color: var(--vst-danger); }

/* На узком окне подсказка уходит: она объясняет клавиши, которых на
   телефоне нет, и съедает строку у кнопки. */
@media (max-width: 640px) {
  .vst-composer__hint { display: none; }
  .vst-home__title { font-size: var(--vst-text-xl); }
}

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

@keyframes vst-rise {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: none; }
}

.vst-rise { animation: vst-rise 320ms var(--vst-ease) both; }
.vst-rise--1 { animation-delay: 60ms; }
.vst-rise--2 { animation-delay: 120ms; }
.vst-rise--3 { animation-delay: 180ms; }

@media (prefers-reduced-motion: reduce) {
  .vst-rise { animation: none; }
}

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

.vst-publish__column {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--vst-gap-4);
  width: 100%;
  max-width: 768px;
  margin: 0 auto;
  padding-top: var(--vst-gap-6);
}

.vst-publish__h2,
.vst-publish__override h2,
.vst-publish__done h2 {
  margin: 0;
  font-size: var(--vst-text-m);
  font-weight: var(--vst-weight-medium);
  color: var(--vst-fg-2);
}

/* Адрес — самое крупное на экране.
 *
 * Это единственное, что человек обязан прочитать перед необратимым:
 * куда именно уедет сайт. Кегль здесь работает не на красоту, а на то,
 * чтобы его нельзя было пропустить. */
.vst-publish__target {
  width: 100%;
  padding: var(--vst-gap-4);
  border: 1px solid var(--vst-line);
  border-radius: var(--vst-radius-l);
  background: var(--vst-surface);
}
.vst-publish__address { margin-top: var(--vst-gap-2); }
.vst-publish__url {
  font-size: var(--vst-text-l);
  font-family: var(--vst-font-mono);
  word-break: break-all;
}
.vst-publish__off { font-size: var(--vst-text-l); color: var(--vst-warn); }
.vst-publish__note { margin: var(--vst-gap-2) 0 0; font-size: var(--vst-text-s); }

.vst-publish__lead { margin: 0; max-width: 68ch; line-height: var(--vst-leading-loose); }

/* Обход гейта обведён красным и стоит отдельным блоком: он появляется,
   только когда есть что обходить, и обязан выглядеть исключением,
   а не вторым способом сделать то же самое. */
.vst-publish__override {
  display: flex;
  flex-direction: column;
  gap: var(--vst-gap-3);
  width: 100%;
  padding: var(--vst-gap-4);
  border: 1px solid var(--vst-danger);
  border-radius: var(--vst-radius-l);
  background: var(--vst-surface);
}
.vst-publish__override[hidden] { display: none; }
.vst-publish__override h2 { color: var(--vst-danger); }
.vst-publish__override p { margin: 0; max-width: 68ch; line-height: var(--vst-leading); }
/* Обход — того же размера, что обычное действие.
 *
 * Растянутая во всю ширину красная кнопка крупнее главной читается как
 * призыв: глаз идёт к самому большому пятну на экране, а самым большим
 * пятном оказывался обход правила. */
.vst-publish__override .vst-btn { align-self: flex-start; }

.vst-publish__done {
  display: flex;
  flex-direction: column;
  gap: var(--vst-gap-2);
  width: 100%;
  padding: var(--vst-gap-4);
  border: 1px solid var(--vst-ok);
  border-radius: var(--vst-radius-l);
  background: var(--vst-surface);
}
.vst-publish__done[hidden] { display: none; }
.vst-publish__done h2 { color: var(--vst-ok); }
.vst-publish__done p { margin: 0; font-size: var(--vst-text-s); }

/* Ссылка на выложенный сайт — крупная и первая под фокусом: ради неё
   на этот экран и приходили. */
.vst-publish__open {
  display: inline-flex;
  align-items: center;
  gap: var(--vst-gap-2);
  font-size: var(--vst-text-l);
  font-family: var(--vst-font-mono);
  color: var(--vst-fg);
  word-break: break-all;
}
.vst-publish__open:hover { text-decoration: underline; }

/* Лента занимает место, только когда в ней что-то есть: пустая рамка
   на полэкрана до первого нажатия читается как сломанный блок. */
.vst-publish .vst-feed:empty { display: none; }
.vst-publish .vst-feed {
  width: 100%;
  max-height: 40vh;
  overflow: auto;
}

.vst-publish__url--live {
  display: inline-flex;
  align-items: center;
  gap: var(--vst-gap-2);
  color: var(--vst-fg);
  text-decoration: none;
}
.vst-publish__url--live:hover { text-decoration: underline; }

/* Ссылка на живой сайт с карточки проекта: значок и адрес, приглушённо —
   на карточке главное имя, а не адрес. */
.vst-card__live {
  display: inline-flex;
  align-items: center;
  gap: var(--vst-gap-1);
  color: var(--vst-fg-3);
  font-size: var(--vst-text-s);
  text-decoration: none;
}
.vst-card__live:hover { color: var(--vst-fg); text-decoration: underline; }

/* Блок состояния, стоящий прямо на экране, живёт в той же колонке, что
 * главная и публикация.
 *
 * Прижатый к левому верхнему углу чёрного поля, он читается как обломок
 * страницы, которая не дозагрузилась, — особенно на широком мониторе, где
 * справа от него метр пустоты. Внутри списка проектов правило не работает:
 * там блок принадлежит колонке списка, а не экрану. */
/* Ворота — это экран И блок состояния в одном узле, поэтому правило ниже
   (`.vst-screen > .vst-state`) до них не достаёт: они не ребёнок экрана,
   они экран и есть. Без этого поле ввода ключа стоит прижатым к левому
   краю, а справа полметра пустоты. */
.vst-screen.vst-state {
  width: auto;
  max-width: 768px;
  margin: var(--vst-gap-7) auto 0;
  /* Высота по содержимому, а не во весь экран: контейнер тянет своих детей,
     и карточка ворот растягивалась до нижнего края — поле ввода вверху,
     под ним полметра пустой рамки. */
  align-self: flex-start;
  flex: none;
}

.vst-screen > .vst-state {
  width: 100%;
  max-width: 768px;
  margin-inline: auto;
  margin-top: var(--vst-gap-7);
}

/* Уведомление закрывается кликом, и это должно быть ВИДНО.
 *
 * Предупреждение теперь не уходит само, поэтому крестик обязателен: без него
 * человек смотрит на висящее сообщение и не понимает, ждать ли, пока оно
 * пропадёт. Крестик приглушён — он подсказка, а не кнопка, к которой зовут. */
.vst-note { cursor: pointer; }
.vst-note__text { flex: 1; min-width: 0; }
.vst-note__close { flex: none; color: var(--vst-fg-3); }
.vst-note:hover .vst-note__close { color: var(--vst-fg); }
.vst-note:focus-visible {
  outline: var(--vst-focus-width) solid var(--vst-focus);
  outline-offset: 2px;
}

/* Незакончившийся прогон подписан ЖЁЛТЫМ, а не красным: остановка кнопкой
   и отказ этапа — не одно и то же, и красный на собственное решение
   человека читается как обвинение. */
.vst-run__stage--bad { color: var(--vst-warn); }
