/* ============================================================
   СПЕКТР UI · spektr-ui.css · v2.0
   Дизайн-система «Телеметрия» — продакшн-пакет.
   Чистый CSS, без сборки. Ни одного внешнего ресурса.
   Префикс всех классов: v-
   Темы: светлая по умолчанию, тёмная — целиком через
   prefers-color-scheme. color-scheme: light dark.
   ============================================================

   ВНИМАНИЕ: это КОПИЯ поставки, и в ней есть НАШИ правки. При
   обновлении пакета их надо нанести заново — иначе вернутся
   дефекты, ради которых они сделаны. Правок ровно две:

   1. УДАЛЕНО правило `.v-hidden{display:none !important}`.
      У нас класс с таким именем означает ДРУГОЕ: `visibility:
      hidden` для <video> и <img> — элемент невидим, но место
      занято и декодер жив (см. docs/FRONTEND.md §1). Правило
      пакета с !important перебивало наше при любом порядке
      файлов и молча меняло поведение плеера и стены.
      Проверено: сам пакет этот класс нигде не использует —
      только его демо-страница, которую мы не подключаем.

   2. СЛИТЫ два объявления `.v-app` в одно. В поставке класс
      описан дважды (база и фон-градиент ниже по файлу), и
      tools/csscheck.py справедливо считал это повтором.
      Порядок деклараций сохранён, поведение не изменилось.
   ============================================================ */

/* ------------------------------------------------------------
   1. ТОКЕНЫ · светлая тема (по умолчанию)
   ------------------------------------------------------------ */
:root{
  color-scheme: light dark;

  /* Шрифты: только системные */
  --v-f-ui:-apple-system,BlinkMacSystemFont,"SF Pro Text","Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
  --v-f-display:-apple-system,BlinkMacSystemFont,"SF Pro Display","Segoe UI",Roboto,sans-serif;
  --v-f-mono:ui-monospace,"SF Mono","Roboto Mono","Cascadia Mono",Menlo,monospace;

  /* Поверхности. Холст нарочно темнее карточек:
     белому стеклу нужен контраст, иначе блик и blur не читаются */
  --v-bg:#B7C1D1;
  --v-surface:#F2F5FA;
  --v-surface-2:#DCE2EC;
  --v-video:#000000;             /* холст видео — всегда чёрный */
  --v-sep:rgba(16,20,30,.12);
  --v-line:rgba(16,20,30,.20);

  /* Текст */
  --v-t1:#171B24;
  --v-t2:rgba(23,27,36,.64);
  --v-t3:rgba(23,27,36,.42);
  --v-on-tint:#FFFFFF;

  /* Акцент действий */
  --v-tint:#3E63D8;
  --v-tint-dim:rgba(62,99,216,.14);

  /* Живой поток (только транслируемому сейчас) */
  --v-live-a:#2F7BFF;
  --v-live-b:#00A9CF;
  --v-live:linear-gradient(90deg,var(--v-live-a),var(--v-live-b));
  --v-live-text:#0678A5;
  --v-live-glow:0 0 10px rgba(0,169,207,.35),0 0 24px rgba(47,123,255,.18);

  /* Семантика */
  --v-ok:#1E9E5C;      --v-ok-dim:rgba(30,158,92,.13);
  --v-warn:#B77400;    --v-warn-dim:rgba(199,133,10,.15);
  --v-danger:#D8362C;  --v-danger-dim:rgba(216,54,44,.12);
  --v-danger-glow:0 0 8px rgba(216,54,44,.4);

  /* Стекло: в обеих темах один материал — дымчатый, как в тёмной.
     Текст на стекле всегда светлый: --v-glass-t1/t2 */
  --v-glass:rgba(21,25,34,.55);
  --v-glass-thick:rgba(17,20,28,.78);
  --v-glass-t1:#F2F3F7;
  --v-glass-t2:rgba(238,241,248,.66);
  --v-blur:saturate(160%) blur(18px);

  /* Геометрия */
  --v-r-chip:999px;
  --v-r-control:999px;
  --v-r-cell:12px;
  --v-r-card:16px;
  --v-r-sheet:22px;

  /* Отступы (4pt) */
  --v-sp-1:4px; --v-sp-2:8px; --v-sp-3:12px; --v-sp-4:16px;
  --v-sp-5:20px; --v-sp-6:24px; --v-sp-8:32px;

  /* Движение и касания */
  --v-ease:cubic-bezier(.25,.1,.25,1);
  --v-dur-fast:120ms; --v-dur:220ms; --v-dur-slow:360ms;
  --v-touch:44px;

  --v-rim-card:inset 0 1px 0 rgba(255,255,255,.8);
  --v-shadow:0 6px 20px rgba(16,20,30,.14);
  --v-shadow-sheet:0 -10px 36px rgba(16,20,30,.22);

  /* Жидкое стекло: ободок-блик и верхний глянец */
  --v-rim:inset 0 1px 0 rgba(255,255,255,.14),inset 0 0 0 1px rgba(255,255,255,.05);
  --v-sheen:linear-gradient(rgba(255,255,255,.07),rgba(255,255,255,0) 48%);
  --v-glass-bright:saturate(160%) blur(20px) brightness(1.05);
}

/* ------------------------------------------------------------
   1a. ТОКЕНЫ · тёмная тема — целиком через prefers-color-scheme
   ------------------------------------------------------------ */
@media (prefers-color-scheme: dark){
  :root{
    --v-bg:#14171F;
    --v-surface:#1D212B;
    --v-surface-2:#272C39;
    --v-sep:rgba(255,255,255,.09);
    --v-line:rgba(255,255,255,.16);

    --v-t1:#F2F3F7;
    --v-t2:rgba(238,241,248,.66);
    --v-t3:rgba(238,241,248,.42);

    --v-tint:#4D7CFE;
    --v-tint-dim:rgba(77,124,254,.16);

    --v-live-a:#3D8BFF;
    --v-live-b:#00D4FF;
    --v-live-text:#5FC9FF;
    --v-live-glow:0 0 12px rgba(0,190,255,.4),0 0 28px rgba(61,139,255,.2);

    --v-ok:#34C77B;      --v-ok-dim:rgba(52,199,123,.14);
    --v-warn:#FF9F0A;    --v-warn-dim:rgba(255,159,10,.14);
    --v-danger:#FF453A;  --v-danger-dim:rgba(255,69,58,.14);
    --v-danger-glow:0 0 10px rgba(255,69,58,.5);

    --v-glass:rgba(20,23,31,.62);
    --v-glass-thick:rgba(16,19,26,.82);

    --v-shadow:0 8px 24px rgba(0,0,0,.35);
    --v-shadow-sheet:0 -10px 40px rgba(0,0,0,.5);

    --v-rim-card:var(--v-rim);
    --v-sheen:linear-gradient(rgba(255,255,255,.07),rgba(255,255,255,0) 48%);
    --v-glass-bright:saturate(160%) blur(20px) brightness(1.07);
  }
}

/* ------------------------------------------------------------
   2. БАЗА И УТИЛИТЫ
   ------------------------------------------------------------ */
.v-app,
.v-app *,
.v-app *::before,
.v-app *::after{box-sizing:border-box}

.v-app{
  /* НАША ПРАВКА 2: сюда слито второе объявление .v-app, которое в
     поставке стоит ниже по файлу (светлый холст с вертикальным
     светом). Порядок деклараций сохранён — фон-градиент идёт
     после сплошного фона и по-прежнему его перекрывает. */
  background:var(--v-bg);
  background:radial-gradient(120% 90% at 50% -10%,color-mix(in srgb,var(--v-bg) 82%,#fff) 0%,var(--v-bg) 55%,color-mix(in srgb,var(--v-bg) 88%,#0a1220) 100%);
  color:var(--v-t1);
  font-family:var(--v-f-ui);
  font-size:15px; line-height:1.5;
  -webkit-font-smoothing:antialiased;
  /* Безопасные зоны: без этого интерфейс уезжает под чёлку */
  padding-top:env(safe-area-inset-top);
  padding-left:env(safe-area-inset-left);
  padding-right:env(safe-area-inset-right);
  padding-bottom:env(safe-area-inset-bottom);
}
.v-mono{font-family:var(--v-f-mono);font-variant-numeric:tabular-nums}

/* НАША ПРАВКА 1: здесь в поставке стоит
   `.v-hidden, video.v-hidden, img.v-hidden{display:none !important}`.
   Удалено намеренно — у нас это имя означает `visibility: hidden`
   (место занято, декодер жив), см. шапку файла и docs/FRONTEND.md §1.
   Наше правило живёт в app.css. Для скрытия НЕ медиа-элементов в новой
   разметке пользуйтесь атрибутом `hidden`, а не этим классом. */

/* Скрыто визуально, доступно скринридеру */
.v-sr{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}

:where(.v-app) :focus-visible{outline:2px solid var(--v-tint);outline-offset:2px;border-radius:var(--v-r-cell)}

/* Анимации должны уметь выключаться */
@media (prefers-reduced-motion: reduce){
  .v-app *,
  .v-app *::before,
  .v-app *::after{animation:none !important;transition:none !important}
}

/* Амбиентный свет под стеклом. Кладётся первым ребёнком .v-app:
   <div class="v-ambient"><i></i><i></i><i></i></div> */
.v-ambient{position:fixed;inset:0;z-index:-1;overflow:hidden;pointer-events:none}
.v-ambient i{position:absolute;border-radius:50%;filter:blur(90px);opacity:.8}
.v-ambient i:nth-child(1){width:620px;height:620px;left:-160px;top:-140px;background:radial-gradient(circle,rgba(62,120,255,.30),transparent 68%)}
.v-ambient i:nth-child(2){width:680px;height:680px;right:-200px;top:30%;background:radial-gradient(circle,rgba(0,180,220,.22),transparent 68%)}
.v-ambient i:nth-child(3){width:520px;height:520px;left:22%;bottom:-220px;background:radial-gradient(circle,rgba(122,92,255,.18),transparent 68%)}
@media (prefers-color-scheme: dark){
  .v-ambient i{opacity:.5}
}
/* Светлый холст: лёгкий вертикальный свет, как в гайде.
   НАША ПРАВКА 2: объявление перенесено в основное правило .v-app выше. */

@keyframes v-pulse{0%,100%{opacity:1}50%{opacity:.25}}
@keyframes v-in{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}

/* ------------------------------------------------------------
   3. КАРТОЧКА
   ------------------------------------------------------------ */
.v-card{
  background:var(--v-surface);
  border:1px solid var(--v-sep);
  border-radius:var(--v-r-card);
  box-shadow:var(--v-rim-card),var(--v-shadow);
}
.v-card--pad{padding:var(--v-sp-4) var(--v-sp-5)}
.v-card--glass{
  color:var(--v-glass-t1);
  background:var(--v-sheen),var(--v-glass);
  backdrop-filter:var(--v-glass-bright);
  -webkit-backdrop-filter:var(--v-glass-bright);
  box-shadow:var(--v-rim),var(--v-shadow);
  border-color:transparent;
}

/* ------------------------------------------------------------
   4. ПЛИТКА КАМЕРЫ С ВИДЕО
   Пропорция контейнера ставится ИЗ JS по реальным
   videoWidth/videoHeight: el.style.setProperty('--v-ar','1920/1080').
   Жёсткие 16:9 давали до сотни пикселей чёрных полей.
   ------------------------------------------------------------ */
.v-cam{
  position:relative;
  aspect-ratio:var(--v-ar, 16/9);   /* 16/9 — только фолбэк до метаданных */
  border-radius:var(--v-r-card);
  overflow:hidden;
  background:var(--v-video);
  border:1px solid var(--v-sep);
  /* Намеренно: жесты прокрутки работают, pinch-zoom по видео — нет */
  touch-action:pan-x pan-y;
  user-select:none;
  -webkit-user-select:none;
}
.v-cam__media{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;background:var(--v-video)}
.v-cam__media--cover{object-fit:cover}

.v-cam__top{position:absolute;top:var(--v-sp-2);left:var(--v-sp-2);right:var(--v-sp-2);display:flex;justify-content:space-between;align-items:center;gap:var(--v-sp-2);z-index:2}
.v-cam__bar{
  position:absolute;left:var(--v-sp-2);right:var(--v-sp-2);bottom:var(--v-sp-2);z-index:2;
  display:flex;align-items:center;justify-content:space-between;gap:var(--v-sp-3);
  background:var(--v-sheen),var(--v-glass);
  backdrop-filter:var(--v-glass-bright);-webkit-backdrop-filter:var(--v-glass-bright);
  border:1px solid transparent;
  border-radius:var(--v-r-cell);
  padding:7px 12px;min-height:38px;
  box-shadow:var(--v-rim);
}
.v-cam__name{font-size:13px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--v-glass-t1)}
.v-cam__meta{font-family:var(--v-f-mono);font-variant-numeric:tabular-nums;font-size:11px;color:var(--v-glass-t2);flex-shrink:0}

/* Камера в эфире: градиентная рамка потока */
.v-cam--live{
  border-color:transparent;
  background:linear-gradient(var(--v-video),var(--v-video)) padding-box,var(--v-live) border-box;
  box-shadow:var(--v-live-glow);
}
/* Офлайн: вуаль вместо чёрного прямоугольника */
.v-cam__veil{
  position:absolute;inset:0;z-index:1;
  display:flex;flex-direction:column;gap:4px;align-items:center;justify-content:center;
  background:color-mix(in srgb,var(--v-video) 55%, transparent);
  backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);
  color:#EDF0F6;font-size:13px;font-weight:600;
}
.v-cam__veil .v-mono{font-size:11px;color:rgba(237,240,246,.55)}

/* ------------------------------------------------------------
   5. ЧИП СТАТУСА
   ------------------------------------------------------------ */
.v-chip{
  display:inline-flex;align-items:center;gap:6px;
  font-family:var(--v-f-mono);font-size:11px;font-weight:700;letter-spacing:.06em;
  padding:4px 10px;border-radius:var(--v-r-chip);
  color:var(--v-t2);background:var(--v-surface-2);
}
.v-chip::before{content:"";width:6px;height:6px;border-radius:50%;background:currentColor;flex-shrink:0}
.v-chip--ok{color:var(--v-ok);background:var(--v-ok-dim)}
.v-chip--warn{color:var(--v-warn);background:var(--v-warn-dim)}
.v-chip--danger{color:var(--v-danger);background:var(--v-danger-dim)}
.v-chip--off{color:var(--v-t3)}
.v-chip--live{color:#fff;background:var(--v-live);box-shadow:var(--v-live-glow)}
.v-chip--live::before{background:#fff;animation:v-pulse 1.4s infinite}
.v-chip--rec{color:var(--v-danger);background:var(--v-danger-dim)}
.v-chip--rec::before{box-shadow:var(--v-danger-glow);animation:v-pulse 1.4s infinite}
.v-chip--plain::before{display:none}

/* ------------------------------------------------------------
   6. КНОПКИ: обычная, основная, опасная, призрачная, малая
   ------------------------------------------------------------ */
.v-btn{
  box-shadow:var(--v-rim);
  font-family:var(--v-f-ui);font-weight:600;font-size:15px;
  min-height:var(--v-touch);padding:0 var(--v-sp-5);
  border-radius:var(--v-r-control);
  border:1px solid transparent;cursor:pointer;
  display:inline-flex;align-items:center;justify-content:center;gap:8px;
  background:var(--v-surface-2);color:var(--v-t1);
  transition:transform var(--v-dur-fast) var(--v-ease),background var(--v-dur-fast),border-color var(--v-dur-fast);
}
.v-btn:hover{background:color-mix(in srgb,var(--v-surface-2) 80%,var(--v-t1) 8%)}
.v-btn:active{transform:scale(.97)}
.v-btn:disabled{opacity:.4;cursor:default;transform:none}
.v-btn--primary{background:linear-gradient(rgba(255,255,255,.22),rgba(255,255,255,0) 55%),var(--v-tint);color:var(--v-on-tint);box-shadow:var(--v-rim),0 4px 14px color-mix(in srgb,var(--v-tint) 30%,transparent)}
.v-btn--primary:hover{background:color-mix(in srgb,var(--v-tint) 88%,#000 8%)}
.v-btn--danger{background:var(--v-danger-dim);color:var(--v-danger)}
.v-btn--danger:hover{background:color-mix(in srgb,var(--v-danger-dim) 70%,var(--v-danger) 12%)}
.v-btn--ghost{background:transparent;border-color:var(--v-line);box-shadow:none}
.v-btn--ghost:hover{background:var(--v-surface-2)}
.v-btn--sm{min-height:32px;font-size:13px;padding:0 var(--v-sp-3)}

/* ------------------------------------------------------------
   7. ПЕРЕКЛЮЧАТЕЛЬ
   ------------------------------------------------------------ */
.v-switch{position:relative;display:inline-flex;align-items:center;gap:10px;cursor:pointer;min-height:var(--v-touch);font-size:14px}
.v-switch input{position:absolute;opacity:0;width:0;height:0}
.v-switch__track{
  width:48px;height:28px;border-radius:999px;flex-shrink:0;position:relative;
  background:var(--v-surface-2);border:1px solid var(--v-line);
  transition:background var(--v-dur) var(--v-ease),border-color var(--v-dur);
}
.v-switch__track::after{
  content:"";position:absolute;top:2px;left:2px;width:22px;height:22px;border-radius:50%;
  background:#fff;box-shadow:0 2px 5px rgba(0,0,0,.3);
  transition:transform var(--v-dur) var(--v-ease);
}
.v-switch input:checked + .v-switch__track{background:var(--v-ok);border-color:transparent}
.v-switch input:checked + .v-switch__track::after{transform:translateX(20px)}
.v-switch input:focus-visible + .v-switch__track{outline:2px solid var(--v-tint);outline-offset:2px}

/* ------------------------------------------------------------
   8. СЕГМЕНТИРОВАННЫЙ КОНТРОЛ
   ------------------------------------------------------------ */
.v-seg{
  display:inline-grid;grid-auto-flow:column;grid-auto-columns:1fr;gap:2px;
  background:var(--v-surface-2);border:1px solid var(--v-sep);
  border-radius:999px;padding:3px;box-shadow:var(--v-rim);
}
.v-seg__btn{
  font-family:var(--v-f-ui);font-size:13px;font-weight:600;color:var(--v-t2);
  background:transparent;border:none;border-radius:999px;
  padding:7px 16px;min-width:72px;cursor:pointer;
  transition:background var(--v-dur-fast),color var(--v-dur-fast),transform var(--v-dur-fast);
}
.v-seg__btn:active{transform:scale(.96)}
.v-seg__btn.v-on,
.v-seg__btn[aria-selected="true"]{
  background:var(--v-sheen),var(--v-surface);color:var(--v-t1);
  box-shadow:var(--v-rim),0 1px 4px rgba(0,0,0,.18);
}

/* ------------------------------------------------------------
   9. ЧЕКБОКС
   ------------------------------------------------------------ */
.v-check{display:inline-flex;align-items:center;gap:10px;cursor:pointer;font-size:14px;min-height:var(--v-touch)}
.v-check input{position:absolute;opacity:0;width:0;height:0}
.v-check__box{
  width:20px;height:20px;border-radius:6px;flex-shrink:0;
  border:1.5px solid var(--v-line);background:var(--v-surface);
  display:grid;place-items:center;
  transition:background var(--v-dur-fast),border-color var(--v-dur-fast);
}
.v-check__box::after{
  content:"";width:10px;height:6px;
  border-left:2px solid #fff;border-bottom:2px solid #fff;
  transform:rotate(-45deg) translate(1px,-1px) scale(0);
  transition:transform var(--v-dur-fast) var(--v-ease);
}
.v-check input:checked + .v-check__box{background:var(--v-tint);border-color:var(--v-tint)}
.v-check input:checked + .v-check__box::after{transform:rotate(-45deg) translate(1px,-1px) scale(1)}
.v-check input:disabled + .v-check__box{opacity:.4}
.v-check input:focus-visible + .v-check__box{outline:2px solid var(--v-tint);outline-offset:2px}

/* ------------------------------------------------------------
   10. ПОЛЯ ВВОДА И СПИСКИ
   ------------------------------------------------------------ */
.v-field{display:flex;flex-direction:column;gap:6px}
.v-label{font-size:13px;font-weight:600;color:var(--v-t2)}
.v-input{
  width:100%;min-width:0;min-height:var(--v-touch);
  font-family:var(--v-f-ui);font-size:16px; /* 16px — iOS не зумит поле */
  color:var(--v-t1);background:var(--v-surface);
  border:1px solid var(--v-line);border-radius:var(--v-r-control);
  padding:10px 16px;
  transition:border-color var(--v-dur-fast),box-shadow var(--v-dur-fast);
}
.v-input::placeholder{color:var(--v-t3)}
.v-input:focus{outline:none;border-color:var(--v-tint);box-shadow:0 0 0 3px var(--v-tint-dim)}
.v-input--mono{font-family:var(--v-f-mono);font-size:14px}
.v-input--error{border-color:var(--v-danger)}
textarea.v-input{min-height:88px;border-radius:var(--v-r-cell);resize:vertical}
.v-hint{font-size:12px;color:var(--v-t3)}
.v-hint--error{color:var(--v-danger)}

.v-list{background:var(--v-surface);border:1px solid var(--v-sep);border-radius:var(--v-r-card);overflow:hidden;min-width:0;box-shadow:var(--v-rim),var(--v-shadow)}
.v-list__item{
  display:flex;align-items:center;gap:var(--v-sp-3);
  min-height:var(--v-touch);padding:var(--v-sp-2) var(--v-sp-4);
  border-bottom:1px solid var(--v-sep);font-size:14px;
  transition:background var(--v-dur-fast);
}
.v-list__item:last-child{border-bottom:0}
.v-list__item[role="button"],
a.v-list__item{cursor:pointer;color:inherit;text-decoration:none}
.v-list__item[role="button"]:active,
a.v-list__item:active{background:var(--v-surface-2)}
.v-list__value{margin-left:auto;color:var(--v-t2);font-size:13px;display:flex;align-items:center;gap:8px;flex-shrink:0}
.v-list__chevron{color:var(--v-t3)}

/* ------------------------------------------------------------
   10a. КАСТОМНЫЙ СЕЛЕКТ
   Кнопка-комбобокс + листбокс на дымчатом стекле.
   Клавиатура и ARIA — в spektr-ui.js (SpektrUI.select).
   <div class="v-select">
     <button class="v-select__btn" role="combobox">…</button>
     <ul class="v-select__menu" role="listbox" hidden>
       <li class="v-select__opt" role="option" data-value="…">…</li>
   ------------------------------------------------------------ */
.v-select{position:relative;display:inline-block;min-width:220px;max-width:100%}
.v-select--block{display:block;width:100%}
.v-select__btn{
  width:100%;min-height:var(--v-touch);
  display:flex;align-items:center;justify-content:space-between;gap:var(--v-sp-3);
  font-family:var(--v-f-ui);font-size:16px;color:var(--v-t1);text-align:left;
  background:var(--v-surface);border:1px solid var(--v-line);
  border-radius:var(--v-r-control);padding:10px 16px;cursor:pointer;
  transition:border-color var(--v-dur-fast),box-shadow var(--v-dur-fast);
}
.v-select__btn:focus-visible,
.v-select.v-open .v-select__btn{outline:none;border-color:var(--v-tint);box-shadow:0 0 0 3px var(--v-tint-dim)}
.v-select__btn:disabled{opacity:.4;cursor:default}
.v-select__value{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.v-select__value.v-placeholder{color:var(--v-t3)}
/* Шеврон: чистый CSS, без url() */
.v-select__chevron{
  width:9px;height:9px;flex:none;margin-top:-3px;
  border-right:1.8px solid var(--v-t3);border-bottom:1.8px solid var(--v-t3);
  transform:rotate(45deg);
  transition:transform var(--v-dur) var(--v-ease),margin var(--v-dur) var(--v-ease);
}
.v-select.v-open .v-select__chevron{transform:rotate(225deg);margin-top:4px}

.v-select__menu{
  /* Координаты и ширину ставит JS при открытии (fixed):
     меню не обрезается контейнерами и переворачивается вверх,
     когда снизу нет места */
  position:fixed;z-index:80;
  margin:0;padding:6px;list-style:none;
  max-height:280px;overflow:auto;overscroll-behavior:contain;
  color:var(--v-glass-t1);
  background:var(--v-sheen),var(--v-glass-thick);
  backdrop-filter:var(--v-glass-bright);-webkit-backdrop-filter:var(--v-glass-bright);
  border:1px solid var(--v-line);border-radius:var(--v-r-cell);
  box-shadow:var(--v-rim),var(--v-shadow);
  animation:v-in var(--v-dur-fast) var(--v-ease);
}
.v-select__menu[hidden]{display:none}
.v-select__search{position:sticky;top:-6px;margin:-6px -6px 6px;padding:6px;background:inherit;backdrop-filter:inherit;-webkit-backdrop-filter:inherit;border-bottom:1px solid var(--v-line)}
.v-select__search .v-input{min-height:36px;font-size:14px;padding:7px 14px;background:rgba(10,13,18,.4);color:var(--v-glass-t1);border-color:var(--v-line)}
.v-select__search .v-input::placeholder{color:var(--v-glass-t2)}
.v-select__none{padding:10px 12px;font-size:13px;color:var(--v-glass-t2)}
.v-select__opt{
  position:relative;display:flex;align-items:center;gap:10px;
  min-height:38px;padding:8px 12px 8px 34px;
  font-size:14px;border-radius:8px;cursor:pointer;
}
.v-select__opt:hover,
.v-select__opt.v-hl{background:rgba(255,255,255,.09)}
.v-select__opt.v-on{color:var(--v-live-text)}
/* Галочка выбранного: тоже чистый CSS */
.v-select__opt.v-on::before{
  content:"";position:absolute;left:12px;top:50%;
  width:10px;height:5.5px;margin-top:-4.5px;
  border-left:2px solid currentColor;border-bottom:2px solid currentColor;
  transform:rotate(-45deg);
}
.v-select__opt[aria-disabled="true"]{opacity:.4;cursor:default}
.v-select__opt[aria-disabled="true"]:hover{background:none}
.v-select__hint{display:block;font-size:11.5px;color:var(--v-glass-t2)}
.v-select__opt.v-on .v-select__hint{color:currentColor;opacity:.75}

/* ------------------------------------------------------------
   11. МОДАЛЬНОЕ ОКНО С «ГРАБЕРОМ» (шторка)
   ------------------------------------------------------------ */
.v-sheet{position:fixed;inset:0;z-index:90;display:none}
.v-sheet.v-open{display:block}
.v-sheet__backdrop{
  position:absolute;inset:0;
  background:rgba(10,13,20,.45);
  backdrop-filter:blur(4px);-webkit-backdrop-filter:blur(4px);
}
.v-sheet__panel{
  color:var(--v-glass-t1);
  position:absolute;left:0;right:0;bottom:0;
  max-height:calc(100% - 48px - env(safe-area-inset-top));
  overflow:auto;
  background:var(--v-sheen),var(--v-glass-thick);
  backdrop-filter:var(--v-glass-bright);-webkit-backdrop-filter:var(--v-glass-bright);
  border-radius:var(--v-r-sheet) var(--v-r-sheet) 0 0;
  border-top:1px solid var(--v-line);
  box-shadow:var(--v-rim),var(--v-shadow-sheet);
  padding:var(--v-sp-2) var(--v-sp-5) calc(var(--v-sp-5) + env(safe-area-inset-bottom));
  animation:v-in var(--v-dur-slow) var(--v-ease);
  touch-action:none;
}
.v-sheet__grabber{
  width:38px;height:5px;border-radius:999px;
  background:var(--v-glass-t2);opacity:.6;
  margin:6px auto 14px;cursor:grab;
}
.v-sheet__title{font-family:var(--v-f-display);font-weight:700;font-size:17px;margin-bottom:4px}
.v-sheet__text{font-size:13px;color:var(--v-glass-t2);margin-bottom:var(--v-sp-4)}

/* ------------------------------------------------------------
   12. ВКЛАДКИ
   ------------------------------------------------------------ */
.v-tabs{display:flex;gap:var(--v-sp-2);border-bottom:1px solid var(--v-sep);overflow-x:auto;overflow-y:hidden}
.v-tab{
  position:relative;font-family:var(--v-f-ui);font-size:14px;font-weight:600;color:var(--v-t2);
  background:none;border:none;cursor:pointer;
  padding:10px 14px;min-height:var(--v-touch);white-space:nowrap;
  transition:color var(--v-dur-fast);
}
.v-tab:hover{color:var(--v-t1)}
.v-tab.v-on,
.v-tab[aria-selected="true"]{color:var(--v-t1)}
.v-tab.v-on::after,
.v-tab[aria-selected="true"]::after{
  content:"";position:absolute;left:12px;right:12px;bottom:-1px;height:2px;
  border-radius:2px;background:var(--v-live);
}
.v-tabpanel[hidden]{display:none}

/* ------------------------------------------------------------
   13. ТАБЛИЦА
   ------------------------------------------------------------ */
.v-table{width:100%;border-collapse:collapse;font-size:14px;background:var(--v-surface);border:1px solid var(--v-sep);border-radius:var(--v-r-card);overflow:hidden}
.v-table th{
  font-family:var(--v-f-mono);font-size:11px;letter-spacing:.07em;text-transform:uppercase;
  color:var(--v-t3);text-align:left;font-weight:600;
  padding:var(--v-sp-3) var(--v-sp-4);border-bottom:1px solid var(--v-line);
}
.v-table td{padding:var(--v-sp-3) var(--v-sp-4);border-bottom:1px solid var(--v-sep)}
.v-table tbody tr:last-child td{border-bottom:0}
.v-table tbody tr:hover{background:var(--v-surface-2)}
.v-table .v-mono{font-size:12.5px;color:var(--v-t2)}

/* ------------------------------------------------------------
   14. ВСПЛЫВАЮЩИЕ УВЕДОМЛЕНИЯ (тосты)
   ------------------------------------------------------------ */
.v-toaster{
  position:fixed;z-index:100;
  left:var(--v-sp-4);right:var(--v-sp-4);
  bottom:calc(var(--v-sp-4) + env(safe-area-inset-bottom));
  display:flex;flex-direction:column;gap:var(--v-sp-2);
  pointer-events:none;
}
@media (min-width:640px){.v-toaster{left:auto;width:360px}}
.v-toast{
  color:var(--v-glass-t1);
  pointer-events:auto;
  display:flex;align-items:center;gap:var(--v-sp-3);
  background:var(--v-sheen),var(--v-glass-thick);
  backdrop-filter:var(--v-glass-bright);-webkit-backdrop-filter:var(--v-glass-bright);
  border:1px solid var(--v-line);
  border-left:3px solid var(--v-t3);
  border-radius:var(--v-r-cell);
  padding:var(--v-sp-3) var(--v-sp-4);
  font-size:14px;box-shadow:var(--v-shadow);
  animation:v-in var(--v-dur) var(--v-ease);
}
.v-toast--ok{border-left-color:var(--v-ok)}
.v-toast--warn{border-left-color:var(--v-warn)}
.v-toast--danger{border-left-color:var(--v-danger)}
.v-toast__close{margin-left:auto;background:none;border:none;color:var(--v-glass-t2);cursor:pointer;font-size:15px;padding:4px}

/* ------------------------------------------------------------
   15. ШКАЛА АРХИВА (таймлайн)
   ------------------------------------------------------------ */
.v-timeline{
  position:relative;height:64px;user-select:none;-webkit-user-select:none;
  touch-action:pan-x pan-y;cursor:crosshair;
}
.v-timeline__density{position:absolute;inset:12px 0 22px;display:flex;align-items:flex-end;gap:1px}
.v-timeline__density i{flex:1;min-height:2px;border-radius:1px;background:color-mix(in srgb,var(--v-t1) 14%,transparent)}
.v-timeline__density i.v-hot{background:color-mix(in srgb,var(--v-warn) 65%,transparent)}
.v-timeline__density i.v-alarm{background:color-mix(in srgb,var(--v-danger) 80%,transparent)}
.v-timeline__ticks{position:absolute;left:0;right:0;bottom:0;height:18px;display:flex;justify-content:space-between;font-family:var(--v-f-mono);font-size:10px;color:var(--v-t3)}
.v-timeline__playhead{
  position:absolute;top:4px;bottom:16px;width:2px;left:0;
  background:var(--v-live);box-shadow:var(--v-live-glow);border-radius:2px;
  pointer-events:none;
}
.v-timeline__playhead::after{
  content:"";position:absolute;top:-5px;left:50%;transform:translateX(-50%);
  width:10px;height:10px;border-radius:50%;background:var(--v-live-b);box-shadow:var(--v-live-glow);
}
.v-timeline__cursor{font-family:var(--v-f-mono);font-variant-numeric:tabular-nums;font-size:13px;color:var(--v-live-text)}

/* ------------------------------------------------------------
   16. СЕТКА СТЕНЫ ЭКРАНОВ
   ------------------------------------------------------------ */
.v-wall{
  display:grid;gap:6px;padding:6px;
  background:var(--v-video);
  border:1px solid var(--v-sep);border-radius:var(--v-r-card);
  aspect-ratio:16/9;
}
.v-wall[data-layout="1"]{grid-template:1fr / 1fr}
.v-wall[data-layout="4"]{grid-template:1fr 1fr / 1fr 1fr}
.v-wall[data-layout="9"]{grid-template:repeat(3,1fr) / repeat(3,1fr)}
.v-wall[data-layout="main"]{grid-template:repeat(3,1fr) / 2fr 1fr}
.v-wall[data-layout="main"] .v-wall__cell:first-child{grid-row:1 / 4}
.v-wall__cell{position:relative;border-radius:6px;overflow:hidden;background:var(--v-video);min-height:0}
.v-wall__cell .v-cam__media{position:absolute}
.v-wall__label{
  position:absolute;left:8px;bottom:6px;z-index:1;
  font-family:var(--v-f-mono);font-size:10px;color:rgba(237,240,246,.8);
  text-shadow:0 1px 2px rgba(0,0,0,.8);
}

/* ------------------------------------------------------------
   17. РЕДАКТОР ЗОН ПОВЕРХ СНИМКА
   Тяга по пустому месту — новая зона; за тело — перенос;
   за угловые ручки — размер; двойной клик — удаление (JS).
   ------------------------------------------------------------ */
.v-zones{
  position:relative;overflow:hidden;
  border-radius:var(--v-r-card);border:1px solid var(--v-sep);
  background:var(--v-video);
  aspect-ratio:var(--v-ar,16/9);
  touch-action:pan-x pan-y;      /* намеренно: без pinch-zoom по кадру */
  user-select:none;-webkit-user-select:none;
  cursor:crosshair;
}
.v-zones__snap{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;pointer-events:none}
.v-zone{
  position:absolute;
  border:1.5px dashed var(--v-danger);
  background:color-mix(in srgb,var(--v-danger) 10%,transparent);
  border-radius:3px;cursor:move;
}
.v-zone.v-active{box-shadow:var(--v-danger-glow)}
.v-zone__label{
  position:absolute;top:-22px;left:-2px;white-space:nowrap;
  font-family:var(--v-f-mono);font-size:10px;font-weight:700;letter-spacing:.05em;
  background:var(--v-danger);color:#fff;padding:2px 7px;border-radius:3px;
  pointer-events:none;
}
.v-zone__h{
  position:absolute;width:12px;height:12px;
  background:var(--v-danger);border:2px solid #fff;border-radius:3px;
  box-sizing:border-box;
}
.v-zone__h--nw{left:-6px;top:-6px;cursor:nwse-resize}
.v-zone__h--ne{right:-6px;top:-6px;cursor:nesw-resize}
.v-zone__h--sw{left:-6px;bottom:-6px;cursor:nesw-resize}
.v-zone__h--se{right:-6px;bottom:-6px;cursor:nwse-resize}


/* ------------------------------------------------------------
   20. ОБОЛОЧКА РАЗДЕЛА: НАВИГАЦИЯ + ПАНЕЛЬ (из гайда §45)
   <div class="v-shell">
     <nav class="v-shell__nav">
       <button class="v-shell__link v-on" data-pane="cams">…
         <span class="v-badge v-badge--warn">3</span></button>
     <div class="v-shell__pane v-on" data-pane="cams">…
   На узких экранах навигация — горизонтальная лента.
   ------------------------------------------------------------ */
.v-shell{display:grid;grid-template-columns:232px 1fr;min-height:400px;overflow:hidden}
.v-shell__nav{border-right:1px solid var(--v-sep);padding:var(--v-sp-2);display:flex;flex-direction:column;gap:2px;overflow-y:auto}
.v-shell__link{
  display:flex;align-items:center;gap:10px;
  font-family:var(--v-f-ui);font-size:14px;font-weight:500;color:var(--v-t2);
  background:none;border:none;border-radius:10px;
  padding:9px 11px;min-height:40px;cursor:pointer;text-align:left;
  transition:background var(--v-dur-fast),color var(--v-dur-fast);
}
.v-shell__link:hover{background:color-mix(in srgb,var(--v-t1) 6%,transparent)}
.v-shell__link.v-on{background:color-mix(in srgb,var(--v-t1) 10%,transparent);color:var(--v-t1);box-shadow:var(--v-rim-card)}
.v-shell__icon{width:24px;height:24px;border-radius:7px;display:grid;place-items:center;flex:none;color:#fff;font-size:12px}
.v-shell__pane{display:none;padding:var(--v-sp-4) var(--v-sp-5);overflow-y:auto;min-width:0}
.v-shell__pane.v-on{display:block;animation:v-in var(--v-dur) var(--v-ease)}
@media(max-width:660px){
  .v-shell{grid-template-columns:1fr;min-height:0}
  .v-shell__nav{flex-direction:row;overflow-x:auto;border-right:0;border-bottom:1px solid var(--v-sep)}
  .v-shell__link{flex:none}
}

/* Счётчик у пункта навигации (недочёты, тревоги) */
.v-badge{
  margin-left:auto;flex:none;min-width:20px;height:20px;padding:0 6px;
  display:inline-grid;place-items:center;
  font-family:var(--v-f-mono);font-size:11px;font-weight:700;
  border-radius:999px;color:var(--v-t2);background:var(--v-surface-2);
}
.v-badge--warn{color:var(--v-warn);background:var(--v-warn-dim)}
.v-badge--danger{color:#fff;background:var(--v-danger)}

/* ------------------------------------------------------------
   21. СТРОКА СПИСКА В ДВЕ СТРОКИ
   Название + пояснение под ним — самое ценное в настройках.
   ------------------------------------------------------------ */
.v-list__text{display:flex;flex-direction:column;gap:2px;min-width:0;padding:4px 0}
.v-list__title{font-size:14px;font-weight:500;color:var(--v-t1)}
.v-list__sub{font-size:12.5px;line-height:1.4;color:var(--v-t3)}

/* ------------------------------------------------------------
   22. ЗАГРУЗКА: СПИННЕР И СКЕЛЕТ
   Скелет мерцает; prefers-reduced-motion гасит анимацию,
   остаётся статичная заглушка.
   ------------------------------------------------------------ */
.v-spinner{
  width:22px;height:22px;flex:none;border-radius:50%;
  border:2.5px solid color-mix(in srgb,var(--v-t1) 15%,transparent);
  border-top-color:var(--v-tint);
  animation:v-spin .7s linear infinite;
}
.v-spinner--lg{width:32px;height:32px}
@keyframes v-spin{to{transform:rotate(360deg)}}
.v-skeleton{
  position:relative;overflow:hidden;border-radius:8px;
  background:color-mix(in srgb,var(--v-t1) 9%,transparent);
}
.v-skeleton::after{
  content:"";position:absolute;inset:0;transform:translateX(-100%);
  background:linear-gradient(90deg,transparent,color-mix(in srgb,var(--v-t1) 8%,transparent),transparent);
  animation:v-shimmer 1.4s infinite;
}
@keyframes v-shimmer{to{transform:translateX(100%)}}
.v-skeleton--text{height:13px;border-radius:6px}
.v-skeleton--title{height:18px;width:40%;border-radius:6px}
.v-skeleton--block{aspect-ratio:16/9;border-radius:var(--v-r-cell)}

/* ------------------------------------------------------------
   23. МЕТРИКИ И ПОЛОСЫ ЗАНЯТОСТИ (из гайда §9/§19)
   ------------------------------------------------------------ */
.v-metric{display:flex;flex-direction:column;gap:2px;min-width:0}
.v-metric__label{font-size:11px;font-weight:600;letter-spacing:.05em;text-transform:uppercase;color:var(--v-t3)}
.v-metric__value{font-family:var(--v-f-mono);font-variant-numeric:tabular-nums;font-weight:600;font-size:26px;color:var(--v-t1)}
.v-metric__value small{font-size:13px;font-weight:400;color:var(--v-t2)}
.v-metric__delta{font-size:12px;color:var(--v-t2)}
.v-metric__delta.v-up{color:var(--v-ok)}
.v-metric__delta.v-down{color:var(--v-danger)}
.v-bar{height:6px;border-radius:3px;background:color-mix(in srgb,var(--v-t1) 10%,transparent);overflow:hidden}
.v-bar i{display:block;height:100%;border-radius:3px;background:var(--v-live);transition:width var(--v-dur-slow) var(--v-ease)}
.v-bar--warn i{background:var(--v-warn)}
.v-bar--danger i{background:var(--v-danger)}
.v-bar--lg{height:10px;border-radius:4px}

/* ------------------------------------------------------------
   24. ТАБЛИЦА НА УЗКОМ ЭКРАНЕ
   .v-table--stack: до 640px строки складываются в карточки,
   подпись колонки берётся из data-label ячейки.
   ------------------------------------------------------------ */
@media(max-width:640px){
  .v-table--stack thead{display:none}
  .v-table--stack tbody tr{display:block;padding:6px 0;border-bottom:1px solid var(--v-sep)}
  .v-table--stack tbody tr:last-child{border-bottom:0}
  .v-table--stack td{
    display:flex;justify-content:space-between;align-items:center;gap:var(--v-sp-3);
    border:0;padding:5px var(--v-sp-4);text-align:right;
  }
  .v-table--stack td::before{
    content:attr(data-label);
    font-family:var(--v-f-mono);font-size:10.5px;letter-spacing:.06em;text-transform:uppercase;
    color:var(--v-t3);text-align:left;
  }
}

/* ------------------------------------------------------------
   25. ЖУРНАЛ С УРОВНЯМИ (info · ok · warn · error · crit)
   Текст обязательно выделяется: оператор копирует строки.
   ------------------------------------------------------------ */
.v-log{
  background:#0B0E14;border:1px solid var(--v-sep);border-radius:var(--v-r-cell);
  font-family:var(--v-f-mono);font-size:12.5px;line-height:1.5;
  padding:var(--v-sp-3) 0;overflow:auto;
  user-select:text;-webkit-user-select:text;   /* намеренно: копирование строк */
}
.v-log__line{display:grid;grid-template-columns:72px 92px 1fr;gap:var(--v-sp-3);padding:2px var(--v-sp-4)}
.v-log__ts{color:rgba(238,241,248,.4)}
.v-log__src{color:#5FC9FF}
.v-log__msg{color:rgba(238,241,248,.75);word-break:break-word}
.v-log__line--ok .v-log__msg{color:#34C77B}
.v-log__line--warn .v-log__msg{color:#FF9F0A}
.v-log__line--error .v-log__msg{color:#FF6B61}
.v-log__line--crit{background:rgba(255,69,58,.12)}
.v-log__line--crit .v-log__msg{color:#FF453A;font-weight:700}
@media(max-width:520px){.v-log__line{grid-template-columns:64px 1fr}.v-log__src{display:none}}

/* ------------------------------------------------------------
   26. КНОПКА С УДЕРЖАНИЕМ (из гайда §16)
   Для действий, рвущих живые просмотры и записи.
   ------------------------------------------------------------ */
.v-hold{
  position:relative;overflow:hidden;width:100%;min-height:var(--v-touch);
  font-family:var(--v-f-ui);font-weight:600;font-size:14px;color:var(--v-t1);
  background:var(--v-surface-2);border:1px solid var(--v-line);border-radius:var(--v-r-control);
  cursor:pointer;user-select:none;-webkit-user-select:none;touch-action:none;
  box-shadow:var(--v-rim);
}
.v-hold__fill{position:absolute;inset:0;width:0;background:var(--v-tint);opacity:.9}
.v-hold--danger .v-hold__fill{background:var(--v-danger)}
.v-hold__label{position:relative;z-index:1;padding:0 var(--v-sp-4)}
.v-hold.v-done{background:var(--v-ok);border-color:transparent;color:#fff}
.v-hold.v-done .v-hold__fill{display:none}

/* ------------------------------------------------------------
   27. БАННЕР СОСТОЯНИЯ (сеть/система, из гайда §23)
   ------------------------------------------------------------ */
.v-banner{
  display:flex;align-items:center;gap:var(--v-sp-3);
  border:1px solid var(--v-sep);border-radius:var(--v-r-cell);
  padding:var(--v-sp-3) var(--v-sp-4);font-size:13.5px;
  background:var(--v-surface);color:var(--v-t2);box-shadow:var(--v-rim-card);
}
.v-banner::before{content:"";width:8px;height:8px;border-radius:50%;background:currentColor;flex:none}
.v-banner--ok{background:var(--v-ok-dim);border-color:color-mix(in srgb,var(--v-ok) 30%,transparent);color:var(--v-ok)}
.v-banner--warn{background:var(--v-warn-dim);border-color:color-mix(in srgb,var(--v-warn) 30%,transparent);color:var(--v-warn)}
.v-banner--danger{background:var(--v-danger-dim);border-color:color-mix(in srgb,var(--v-danger) 30%,transparent);color:var(--v-danger)}
.v-banner--offline::before{animation:v-pulse 1.6s infinite}
.v-banner__aside{margin-left:auto;font-family:var(--v-f-mono);font-size:11px;flex:none}

/* ------------------------------------------------------------
   28. МЕЛКИЕ ПРИМИТИВЫ ИЗ ГАЙДА
   ------------------------------------------------------------ */
/* Клавиша */
.v-kbd{
  font-family:var(--v-f-mono);font-size:11.5px;color:var(--v-t1);
  border:1px solid var(--v-line);border-bottom-width:2px;border-radius:6px;
  padding:2px 8px;background:var(--v-surface-2);
}
/* Аватар */
.v-avatar{
  position:relative;width:34px;height:34px;border-radius:10px;flex:none;
  display:grid;place-items:center;
  background:var(--v-surface-2);color:var(--v-tint);
  font-size:12px;font-weight:700;
}
.v-avatar--sm{width:26px;height:26px;font-size:10px;border-radius:8px}
.v-avatar--lg{width:46px;height:46px;font-size:15px;border-radius:13px}
.v-avatar--on::after{
  content:"";position:absolute;right:-2px;bottom:-2px;width:9px;height:9px;
  border-radius:50%;background:var(--v-ok);border:2px solid var(--v-surface);
}
/* Госномер */
.v-plate{
  display:inline-block;font-family:var(--v-f-mono);font-weight:700;font-size:12.5px;
  background:#fff;color:#000;border:1.5px solid #000;border-radius:4px;
  padding:2px 8px;box-shadow:0 0 0 1.5px #fff;letter-spacing:.04em;
}
/* Выбираемая карточка (профили, тарифы) */
.v-card--pick{cursor:pointer;transition:border-color var(--v-dur-fast),box-shadow var(--v-dur-fast)}
.v-card--pick.v-on{
  border-color:color-mix(in srgb,var(--v-live-b) 60%,transparent);
  box-shadow:var(--v-rim-card),0 0 14px color-mix(in srgb,var(--v-live-b) 25%,transparent);
}

/* ------------------------------------------------------------
   29. СРАВНЕНИЕ КАДРОВ (шторка «было/стало», из гайда §20)
   ------------------------------------------------------------ */
.v-compare{
  position:relative;overflow:hidden;
  border-radius:var(--v-r-card);border:1px solid var(--v-sep);
  aspect-ratio:var(--v-ar,16/9);background:var(--v-video);
  touch-action:pan-y;user-select:none;-webkit-user-select:none;cursor:ew-resize;
}
.v-compare__a,.v-compare__b{position:absolute;inset:0}
.v-compare__b{clip-path:inset(0 0 0 50%)}
.v-compare__divider{
  position:absolute;top:0;bottom:0;left:50%;width:2px;
  background:var(--v-live);box-shadow:var(--v-live-glow);pointer-events:none;
}
.v-compare__label{
  position:absolute;top:8px;z-index:1;
  font-family:var(--v-f-mono);font-size:10px;color:rgba(237,240,246,.85);
  background:rgba(0,0,0,.55);padding:2px 8px;border-radius:4px;
}

/* ------------------------------------------------------------
   30. СПАРКЛАЙН И ТЕПЛОВАЯ СЕТКА
   Спарклайн рисует JS (SpektrUI.spark) — без градиентных defs,
   чистый currentColor. Сетка красится drag-ом (SpektrUI.paint).
   ------------------------------------------------------------ */
.v-spark{display:block;color:var(--v-live-b)}
.v-spark polyline{fill:none;stroke:currentColor;stroke-width:1.6;stroke-linejoin:round}
.v-spark polygon{fill:color-mix(in srgb,currentColor 18%,transparent);stroke:none}
.v-grid{display:grid;gap:2px;user-select:none;-webkit-user-select:none}
.v-grid--paint{touch-action:none;cursor:pointer}
.v-grid__cell{aspect-ratio:1;border-radius:2.5px;background:color-mix(in srgb,var(--v-t1) 9%,transparent)}
.v-grid__cell.v-on{background:color-mix(in srgb,var(--v-live-b) 50%,transparent);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--v-live-b) 35%,transparent)}
.v-grid__label{font-family:var(--v-f-mono);font-size:9.5px;color:var(--v-t3);align-self:center}

/* ------------------------------------------------------------
   31. КОД ПОДТВЕРЖДЕНИЯ (OTP, из гайда §47)
   ------------------------------------------------------------ */
.v-otp{display:flex;gap:8px;justify-content:center}
.v-otp input{
  width:42px;height:50px;text-align:center;
  font-family:var(--v-f-mono);font-size:20px;color:var(--v-t1);
  background:var(--v-surface);border:1px solid var(--v-line);border-radius:12px;
  transition:border-color var(--v-dur-fast),box-shadow var(--v-dur-fast);
}
.v-otp input:focus{outline:none;border-color:var(--v-live-b);box-shadow:0 0 0 3px color-mix(in srgb,var(--v-live-b) 18%,transparent)}

/* ------------------------------------------------------------
   32. ПАЛИТРА ПОИСКА ⌘K (из гайда §15)
   Глобальную горячую клавишу вешает приложение.
   ------------------------------------------------------------ */
.v-palette{
  width:min(620px,94vw);border-radius:var(--v-r-card);overflow:hidden;
  color:var(--v-glass-t1);
  background:var(--v-sheen),var(--v-glass-thick);
  backdrop-filter:var(--v-glass-bright);-webkit-backdrop-filter:var(--v-glass-bright);
  border:1px solid var(--v-line);box-shadow:var(--v-rim),var(--v-shadow-sheet);
}
.v-palette__input{display:flex;align-items:center;gap:var(--v-sp-3);padding:var(--v-sp-3) var(--v-sp-4);border-bottom:1px solid var(--v-line)}
.v-palette__input input{flex:1;min-width:0;background:none;border:none;outline:none;font-family:var(--v-f-ui);font-size:16px;color:var(--v-glass-t1)}
.v-palette__input input::placeholder{color:var(--v-glass-t2)}
.v-palette__row{
  display:flex;align-items:center;gap:var(--v-sp-3);
  margin:0 var(--v-sp-2);padding:9px var(--v-sp-3);
  border-radius:10px;font-size:14px;cursor:pointer;
}
.v-palette__row:first-of-type{margin-top:var(--v-sp-2)}
.v-palette__row:last-of-type{margin-bottom:var(--v-sp-2)}
.v-palette__row:hover,.v-palette__row.v-hl{background:rgba(255,255,255,.09)}
.v-palette__key{margin-left:auto;font-family:var(--v-f-mono);font-size:11px;color:var(--v-glass-t2)}

/* ------------------------------------------------------------
   33. PTZ-ДЖОЙСТИК (из гайда §12)
   ------------------------------------------------------------ */
.v-ptz{
  position:relative;width:140px;height:140px;flex:none;border-radius:50%;
  background:radial-gradient(circle at 50% 42%,var(--v-surface-2),var(--v-surface) 72%);
  border:1px solid var(--v-line);box-shadow:var(--v-rim-card);
  touch-action:none;user-select:none;-webkit-user-select:none;
}
.v-ptz__knob{
  position:absolute;left:50%;top:50%;width:46px;height:46px;margin:-23px 0 0 -23px;
  border-radius:50%;cursor:grab;
  background:linear-gradient(150deg,var(--v-surface),var(--v-surface-2));
  border:1px solid var(--v-line);box-shadow:var(--v-shadow);
  display:grid;place-items:center;
}
.v-ptz__knob::after{content:"";width:7px;height:7px;border-radius:50%;background:var(--v-live-b)}
.v-ptz.v-active .v-ptz__knob{box-shadow:var(--v-live-glow)}

/* ------------------------------------------------------------
   34. ДИАПАЗОН НА ШКАЛЕ АРХИВА (экспорт клипа, из гайда §8)
   ------------------------------------------------------------ */
.v-timeline__range{
  position:absolute;top:4px;bottom:16px;left:30%;width:25%;
  background:color-mix(in srgb,var(--v-live-b) 12%,transparent);
  border-left:2px solid var(--v-live-b);border-right:2px solid var(--v-live-b);
}
.v-timeline__grip{
  position:absolute;top:50%;width:16px;height:28px;transform:translate(-50%,-50%);
  display:grid;place-items:center;cursor:ew-resize;pointer-events:all;
}
.v-timeline__grip::after{content:"";width:5px;height:16px;border-radius:2px;background:var(--v-live-b)}
.v-timeline__grip--a{left:0}
.v-timeline__grip--b{left:100%}

/* ------------------------------------------------------------
   35. МОДИФИКАТОРЫ РАЗМЕЩЕНИЯ
   ------------------------------------------------------------ */
/* Тосты сверху — когда снизу плавающий таб-бар */
.v-toaster--top{
  top:calc(var(--v-sp-4) + env(safe-area-inset-top));bottom:auto;
}
/* Шторка по центру на десктопе (диалог) */
@media(min-width:761px){
  .v-sheet--dialog .v-sheet__panel{
    left:50%;right:auto;bottom:auto;top:50%;
    transform:translate(-50%,-50%);
    width:min(540px,92vw);max-height:min(78vh,720px);
    border-radius:var(--v-r-card);border:1px solid var(--v-line);
  }
  .v-sheet--dialog .v-sheet__grabber{display:none}
}
/* ------------------------------------------------------------
   19. ИКОНКИ
   Спрайт spektr-icons.svg (84 символа, id="v-ic-*").
   Для file:// вставляйте спрайт инлайном в начало <body>.
   <svg class="v-icon"><use href="#v-ic-camera"/></svg>
   ------------------------------------------------------------ */
.v-icon{
  width:20px;height:20px;flex:none;
  fill:none;stroke:currentColor;stroke-width:1.8;
  stroke-linecap:round;stroke-linejoin:round;
  vertical-align:-4px;
}
.v-icon--sm{width:16px;height:16px;stroke-width:2}
.v-icon--lg{width:24px;height:24px;stroke-width:1.6}

/* ------------------------------------------------------------
   18. ПУСТОЕ СОСТОЯНИЕ
   ------------------------------------------------------------ */
.v-empty{
  border:1px dashed var(--v-line);border-radius:var(--v-r-card);
  padding:var(--v-sp-8) var(--v-sp-6);text-align:center;color:var(--v-t2);
}
.v-empty__title{display:block;color:var(--v-t1);font-size:15px;font-weight:600;margin-bottom:var(--v-sp-1)}
.v-empty__text{font-size:14px;max-width:420px;margin:0 auto var(--v-sp-4)}
