/* ============================================================= tokens / themes
   Values copied verbatim from the design handoff (dark/light/autumn). */
.app {
  --desk:#070a0e; --canvas:#0c0f15; --panel:#11151c; --panel2:#181d26; --panel3:#1e2530;
  --line:#252c38; --line2:#323b49; --text:#e7edf4; --text2:#aeb8c6; --muted:#6f7b8b;
  --accent:#4c8dff; --accent2:#3567d6; --accent-weak:rgba(76,141,255,0.16);
  --green:#3fb950; --green-weak:rgba(63,185,80,0.20); --red:#f0506e; --red-weak:rgba(240,80,110,0.18); --amber:#d6a338;
  --codebg:#0a0d13; --codetext:#cdd6e4; --gutter:#4a5566;
  --syn-kw:#c678dd; --syn-fn:#61afef; --syn-str:#98c379; --syn-num:#d19a66; --syn-com:#5c6680; --syn-self:#e06c75;
}
.app.theme-light {
  --desk:#e6e4df; --canvas:#f3f4f6; --panel:#ffffff; --panel2:#f5f6f8; --panel3:#eceef2;
  --line:#e4e7ec; --line2:#d4d9e0; --text:#171b22; --text2:#49515d; --muted:#8b93a0;
  --accent:#2f6df6; --accent2:#2057d8; --accent-weak:rgba(47,109,246,0.12);
  --green:#1a9d4b; --green-weak:rgba(26,157,75,0.16); --red:#e5484d; --red-weak:rgba(229,72,77,0.14); --amber:#9a6a00;
  --codebg:#fbfbfd; --codetext:#1f2328; --gutter:#aab1bb;
  --syn-kw:#cf222e; --syn-fn:#6639ba; --syn-str:#0a3069; --syn-num:#0550ae; --syn-com:#6e7781; --syn-self:#953800;
}
.app.theme-autumn {
  --desk:#dcc8a9; --canvas:#efe2cf; --panel:#fbf3e7; --panel2:#f3e7d4; --panel3:#ecdcc4;
  --line:#e2d0b4; --line2:#d2bb98; --text:#3a2b1e; --text2:#6d5740; --muted:#9c876b;
  --accent:#c2521c; --accent2:#9e3f12; --accent-weak:rgba(194,82,28,0.16);
  --green:#6f7d2c; --green-weak:rgba(111,125,44,0.20); --red:#b03a22; --red-weak:rgba(176,58,34,0.15); --amber:#b5791a;
  --codebg:#271c12; --codetext:#ecdcc4; --gutter:#7a6043;
  --syn-kw:#e0813f; --syn-fn:#e0b341; --syn-str:#9aa257; --syn-num:#cf8a4a; --syn-com:#8a755c; --syn-self:#d96a44;
}

/* ============================================================= base */
* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; }
body { font-family: 'IBM Plex Sans', system-ui, sans-serif; }
.mono { font-family: 'IBM Plex Mono', monospace; }
::-webkit-scrollbar { height: 12px; width: 12px; }
::-webkit-scrollbar-thumb { background: rgba(128,128,128,0.35); border-radius: 8px; border: 3px solid transparent; background-clip: content-box; }

@keyframes recpulse { 0%,100% { opacity:1; } 50% { opacity:0.35; } }
@keyframes livepulse { 0% { box-shadow:0 0 0 0 var(--green-weak);} 70% { box-shadow:0 0 0 6px transparent;} 100% { box-shadow:0 0 0 0 transparent;} }

.app {
  /* фикс. высота вьюпорта (не min-height!) — иначе высокая колонка телефона
     растягивает .body и редактор уходит вниз за экран; внутренние области
     (.code-view / .phone-col) скроллятся сами */
  height: 100vh; height: 100dvh; overflow: hidden; display: flex; flex-direction: column;
  background: var(--canvas); color: var(--text);
}

/* ============================================================= shell */
.shell { height:56px; flex:none; display:flex; align-items:center; justify-content:space-between;
  padding:0 18px; background:var(--panel); border-bottom:1px solid var(--line); }
.shell-left { display:flex; align-items:center; gap:16px; height:100%; }
.brand { display:flex; align-items:center; gap:9px; }
.logo { width:27px; height:27px; border-radius:8px; background:linear-gradient(140deg,var(--accent),var(--accent2));
  display:flex; align-items:center; justify-content:center; box-shadow:0 2px 8px -2px var(--accent-weak); }
.logo > span { width:9px; height:9px; border-radius:50%; border:2.5px solid #fff; display:block; }
.wordmark { font-size:15.5px; font-weight:600; letter-spacing:-0.3px; color:var(--text); }
.chip { font-size:10px; font-weight:600; letter-spacing:0.4px; text-transform:uppercase; color:var(--muted);
  border:1px solid var(--line2); border-radius:5px; padding:2px 5px; }
.vdiv { width:1px; height:24px; background:var(--line); }
.tabs { display:flex; gap:2px; height:100%; align-items:stretch; }
.tab { position:relative; display:flex; align-items:center; padding:0 13px; font-size:13.5px; font-weight:500;
  color:var(--muted); cursor:pointer; background:none; border:none; font-family:inherit; }
.tab.active { color:var(--text); font-weight:600; }
.tab .underline { position:absolute; left:13px; right:13px; bottom:0; height:2px; border-radius:2px; background:var(--accent); opacity:0; }
.tab.active .underline { opacity:1; }
.shell-right { display:flex; align-items:center; gap:10px; }
.pill { display:flex; align-items:center; gap:7px; padding:5px 10px; border-radius:8px; background:var(--panel2);
  font-size:12px; color:var(--text2); }
.pill .dot { width:7px; height:7px; border-radius:50%; background:var(--green); box-shadow:0 0 0 3px var(--green-weak); }
.pill .dot.off { background:var(--muted); box-shadow:none; }
.pill .phone-ic { width:9px; height:13px; border:1.5px solid var(--muted); border-radius:2px; }
.pill .num { color:var(--text); } .pill .num-muted { color:var(--muted); }
.theme-switch { display:flex; align-items:center; gap:3px; padding:3px; border-radius:9px; background:var(--panel2); border:1px solid var(--line); }
.swatch { width:20px; height:20px; border-radius:6px; cursor:pointer; box-shadow:inset 0 0 0 1px var(--line2); }
.swatch.active { box-shadow:inset 0 0 0 2px var(--accent); }
.swatch.dark { background:linear-gradient(135deg,#1b2230,#0c0f14); }
.swatch.light { background:linear-gradient(135deg,#ffffff,#e4e7ec); }
.swatch.autumn { background:linear-gradient(135deg,#e58a3c,#7a3b1d); }
.icon-btn { width:30px; height:30px; border-radius:8px; background:var(--panel2); border:1px solid var(--line);
  display:flex; align-items:center; justify-content:center; color:var(--muted); font-size:15px; cursor:pointer; }
.icon-btn:hover { color:var(--text); }
.icon-btn.spin { color:var(--text); pointer-events:none; animation:spin 0.8s linear infinite; }
@keyframes spin { to { transform:rotate(360deg); } }
.avatar { width:30px; height:30px; border-radius:50%; background:linear-gradient(135deg,#7c5cff,#42a5f5);
  color:#fff; display:flex; align-items:center; justify-content:center; font-size:12px; font-weight:600; }

/* ============================================================= generic */
.body { flex:1; display:flex; min-height:0; }
.btn { font-family:inherit; cursor:pointer; border:none; }
.btn:disabled { opacity:.55; cursor:default; }
.ghost { background:var(--panel2); border:1px solid var(--line2); color:var(--text); }
.accent { background:var(--accent); color:#fff; box-shadow:0 4px 12px -4px var(--accent-weak); }

/* ============================================================= panel tab */
.control-col { flex:none; width:432px; border-right:1px solid var(--line); background:var(--panel);
  padding:18px; display:flex; flex-direction:column; gap:14px; overflow-y:auto; }
.control-head { display:flex; align-items:center; justify-content:space-between; }
.control-head .title { font-size:13px; font-weight:700; color:var(--text); }
.badge-accent { font-size:11.5px; font-weight:600; color:var(--accent); background:var(--accent-weak);
  border:1px solid var(--accent); padding:3px 9px; border-radius:7px; }
.preview-wrap { display:flex; justify-content:center; padding:2px 0; }
.phone-body { position:relative; border-radius:26px; background:linear-gradient(155deg,#15151a,#08080a);
  box-shadow:0 16px 40px -16px rgba(0,0,0,0.6), inset 0 0 0 1px rgba(255,255,255,0.05); }
.phone-body .speaker { position:absolute; top:8px; left:50%; transform:translateX(-50%); width:36px; height:4px; border-radius:3px; background:#222227; }
.phone-body .home { position:absolute; bottom:6px; left:50%; transform:translateX(-50%); width:19px; height:19px; border-radius:50%; border:1.5px solid #2a2a30; }
.action-grid { display:grid; grid-template-columns:1fr 1fr; gap:9px; }
.action-btn { height:46px; border-radius:10px; background:var(--panel2); border:1px solid var(--line2);
  display:flex; align-items:center; justify-content:center; gap:8px; font-size:13px; font-weight:500; color:var(--text); cursor:pointer; }
.action-btn .gl { font-size:15px; }
.field { display:flex; flex-direction:column; gap:9px; margin-top:2px; }
.text-input { height:42px; border-radius:10px; border:1px solid var(--line2); background:var(--panel2);
  padding:0 14px; color:var(--text); font-size:13px; font-family:inherit; outline:none; }
.text-input::placeholder { color:var(--muted); }
.text-input-wrap { display:flex; }
.text-input-wrap .text-input { flex:1; width:100%; padding-right:40px; }
.text-hist-btn { position:absolute; right:1px; top:1px; bottom:1px; width:36px; border:none; padding:0;
  background:transparent; color:var(--muted); cursor:pointer; font-size:12px; border-radius:0 10px 10px 0;
  display:flex; align-items:center; justify-content:center; }
.text-hist-btn:hover:not(:disabled) { color:var(--text); background:var(--panel); }
.text-hist-btn:disabled { opacity:.35; cursor:default; }
/* поле ввода стоит внизу прокручиваемой колонки — раскрываем список ВВЕРХ,
   иначе overflow-y колонки его обрежет */
.text-hist-menu { top:auto; bottom:100%; margin-top:0; margin-bottom:6px;
  max-height:280px; overflow:auto; min-width:100%; max-width:340px; }
.text-hist-menu .hist-text { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.text-hist-menu .hist-del { flex:none; color:var(--muted); font-size:15px; line-height:1; }
.text-hist-menu .hist-del:hover { color:#e5484d; }
.send-row { display:flex; gap:9px; }
.send-row .btn { flex:1; height:42px; border-radius:10px; display:flex; align-items:center; justify-content:center; gap:7px; font-size:13px; font-weight:500; }
.send-row .accent { font-size:13.5px; font-weight:600; }
.note { margin-top:auto; font-size:11.5px; color:var(--muted); line-height:1.55; }

.grid-col { flex:1; display:flex; flex-direction:column; min-width:0; }
.grid-toolbar { flex:none; height:52px; display:flex; align-items:center; justify-content:space-between;
  padding:0 20px; border-bottom:1px solid var(--line); }
.grid-toolbar .left { display:flex; align-items:center; gap:14px; }
.checkbox { width:18px; height:18px; border-radius:5px; border:1.5px solid var(--line2); display:flex;
  align-items:center; justify-content:center; color:#fff; font-size:11px; font-weight:700; cursor:pointer; }
.checkbox.on { background:var(--accent); border-color:var(--accent); }
.select-all { display:flex; align-items:center; gap:8px; cursor:pointer; }
.select-all span { font-size:13px; color:var(--text2); font-weight:500; }
.count { font-size:13px; color:var(--muted); }
.count b { color:var(--accent); font-weight:600; }
.dropdown { display:flex; align-items:center; gap:6px; padding:6px 11px; border-radius:8px; background:var(--panel2);
  border:1px solid var(--line); font-size:12.5px; color:var(--text2); cursor:pointer; }
.fps { display:flex; align-items:center; gap:6px; font-size:12px; color:var(--muted); }
.fps .dot { width:7px; height:7px; border-radius:50%; background:var(--green); }

.grid-scroll { flex:1; overflow:auto; padding:18px; }
.grid { display:grid; grid-template-columns:repeat(4, 188px); gap:20px 18px; justify-content:start; }
.device-card { position:relative; width:188px; cursor:pointer; }
.tile { position:relative; width:188px; height:334px; border-radius:13px; overflow:hidden; border:1px solid var(--line); background:#0a0a0c; }
.tile .sel-ring { position:absolute; inset:0; border-radius:13px; border:2.5px solid var(--accent);
  box-shadow:inset 0 0 0 1px var(--accent), 0 0 0 4px var(--accent-weak); pointer-events:none; }
.tile .cb { position:absolute; top:8px; left:8px; width:21px; height:21px; border-radius:6px; display:flex;
  align-items:center; justify-content:center; font-size:12px; font-weight:700; color:#fff; pointer-events:none;
  background:rgba(10,12,16,0.35); border:1.5px solid rgba(255,255,255,0.65); box-shadow:0 1px 3px rgba(0,0,0,0.3); }
.tile .cb.on { background:var(--accent); border-color:var(--accent); }
.tile .status { position:absolute; top:10px; right:9px; width:9px; height:9px; border-radius:50%;
  box-shadow:0 0 0 2px rgba(0,0,0,0.25); }
/* offline = AirPlay/screen lost, but USB control still works → overlay is purely
   visual (click-through) so taps reach the control layer; only its button re-enables. */
.tile .offline { position:absolute; inset:0; background:rgba(8,10,14,0.66); display:flex; flex-direction:column;
  align-items:center; justify-content:center; gap:7px; pointer-events:none; }
.tile .offline .od { width:9px; height:9px; border-radius:50%; background:#d9912b; }
.tile .offline .ol { font-size:12px; color:#c2cad6; font-weight:600; }
.tile .offline .ap-reconnect { margin-top:4px; font-size:11px; font-weight:600; color:#0c0e12; background:#d9912b;
  border:0; border-radius:7px; padding:5px 11px; cursor:pointer; }
.tile .offline .ap-reconnect:hover { background:#e9a43c; }
/* «Восстановить AirPlay» + «Полная перезагрузка» — две равные кнопки в одну строку;
   размеры те же, что у .send-row ниже в этой колонке, чтобы ряды читались одинаково. */
.control-col .ap-btn-row { display:flex; gap:9px; margin-top:10px; }
.control-col .ap-btn-row .btn { flex:1; min-width:0; height:42px; border-radius:10px;
  display:flex; align-items:center; justify-content:center; gap:7px;
  font-size:13px; font-weight:500; white-space:nowrap; }
.caption { display:flex; align-items:center; gap:7px; margin-top:9px; padding:0 2px; }
.caption .name { font-size:12.5px; font-weight:500; color:var(--text2); }
.caption .more { font-size:14px; color:var(--muted); line-height:1; margin-left:auto; }
/* per-phone desk number — compact stepper, edit to renumber (swaps on collision) */
.caption .dev-num { flex:none; width:38px; padding:2px 4px; font-size:12px; font-weight:600; text-align:center;
  color:var(--text2); background:var(--panel2); border:1px solid var(--line); border-radius:6px; }
.caption .dev-num:focus { outline:none; border-color:var(--accent); }

/* ============================================================= constructor tab */
.ctor-toolbar { flex:none; height:54px; display:flex; align-items:center; justify-content:space-between;
  padding:0 18px; border-bottom:1px solid var(--line); gap:10px; }
.ctor-toolbar .grp { display:flex; align-items:center; gap:8px; }
.file-pill { display:flex; align-items:center; gap:8px; padding:7px 12px; border-radius:9px; background:var(--panel2);
  border:1px solid var(--line); font-size:13px; font-weight:600; color:var(--text); cursor:pointer; }
.file-pill .ic { color:var(--accent); }
.tb-btn { display:flex; align-items:center; gap:7px; height:38px; padding:0 13px; border-radius:9px;
  background:var(--panel2); border:1px solid var(--line2); font-size:13px; color:var(--text); cursor:pointer; }
.tb-btn.ghost { background:transparent; border:1px solid var(--line); color:var(--text2); }
.tb-btn.rec.on { background:var(--red-weak); border:1px solid var(--red); color:var(--red); }
.tb-btn.rec.on .dot { width:9px; height:9px; border-radius:50%; background:var(--red); animation:recpulse 1.2s infinite; }
.tb-btn .play { color:var(--green); font-size:11px; }
.tb-btn.disabled { opacity:0.5; pointer-events:none; }
.dev-pill { display:flex; align-items:center; gap:8px; padding:7px 11px; border-radius:9px; background:var(--panel2);
  border:1px solid var(--line); font-size:12.5px; color:var(--text2); cursor:pointer; }
.dev-pill .dot { width:7px; height:7px; border-radius:50%; background:var(--green); }

.phone-col { flex:none; width:472px; background:var(--panel);
  padding:22px; display:flex; flex-direction:column; align-items:center; gap:16px;
  min-height:0; overflow-y:auto; }
.select-banner { align-self:stretch; display:flex; align-items:center; gap:9px; padding:9px 12px; border-radius:9px;
  background:var(--accent-weak); border:1px solid var(--accent); font-size:12px; color:var(--accent); font-weight:500; }
/* мастер записи click_expect: панель сбора исходов (шаг 2) */
.ce-panel { align-self:stretch; display:flex; flex-direction:column; gap:7px; padding:9px 12px; border-radius:9px;
  background:var(--accent-weak); border:1px solid var(--accent); font-size:12px; color:var(--accent); }
.ce-panel .ce-row { display:flex; align-items:center; gap:8px; flex-wrap:wrap; }
.ce-chip { display:inline-flex; align-items:center; gap:6px; padding:2px 8px; border-radius:12px;
  background:var(--panel); border:1px solid var(--accent); color:var(--text); font-weight:500; }
.ce-chip b { color:var(--accent); font-weight:600; }
.ce-lnk { cursor:pointer; color:var(--accent); font-size:11px; }
.ce-lnk.del { color:var(--red); opacity:.8; }
.ce-lnk:hover { text-decoration:underline; }
.ce-fn { width:96px; font-size:11px; padding:1px 5px; border:1px solid var(--accent); border-radius:6px;
  background:var(--panel); color:var(--text); }
.phone-body.lg { padding:20px 12px 38px; border-radius:34px; }
.phone-body.lg .speaker { top:10px; width:50px; height:5px; }
.phone-body.lg .home { bottom:7px; width:25px; height:25px; }
.phone-body.recording { box-shadow:0 0 0 2px var(--red), 0 0 30px -4px var(--red-weak), 0 18px 44px -16px rgba(0,0,0,0.6); }
.btn-row { align-self:stretch; display:flex; flex-wrap:wrap; gap:8px; }
.cbtn { height:38px; padding:0 12px; border-radius:9px; background:var(--panel2); border:1px solid var(--line2);
  display:flex; align-items:center; gap:6px; font-size:12.5px; color:var(--text); cursor:pointer; }
.cbtn.active { background:var(--accent); border:1px solid var(--accent); color:#fff; font-weight:600; }

/* разделитель колонок — тянем, чтобы менять ширину поля с кодом */
.col-resizer { flex:none; width:6px; cursor:col-resize; background:transparent; transition:background .12s;
  border-right:1px solid var(--line); }
.col-resizer:hover, .col-resizer.active { background:var(--accent-weak); border-right-color:var(--accent); }
/* нижний разделитель — тянем вверх, чтобы уменьшить высоту поля с кодом (ниже — пусто) */
.row-resizer { flex:none; height:6px; cursor:row-resize; background:transparent; transition:background .12s;
  border-top:1px solid var(--line); }
.row-resizer:hover, .row-resizer.active { background:var(--accent-weak); border-top-color:var(--accent); }

/* code editor */
.editor { flex:1; min-width:0; display:flex; flex-direction:column; background:var(--codebg); }
.editor-tabs { flex:none; height:42px; display:flex; align-items:center; justify-content:space-between;
  padding:0 8px 0 0; border-bottom:1px solid var(--line); background:var(--codebg); }
.editor-tabs .tabs-l { display:flex; align-items:stretch; height:100%; }
.etab { display:flex; align-items:center; gap:8px; padding:0 16px; font-size:12.5px; color:var(--gutter);
  font-family:'IBM Plex Mono', monospace; border-right:1px solid var(--line); cursor:pointer; }
.etab.active { color:var(--codetext); border-bottom:2px solid var(--accent); }
.etab .ic { color:var(--syn-fn); }
.etab .dirty { width:6px; height:6px; border-radius:50%; background:var(--amber); }
.editor-tools { display:flex; align-items:center; gap:6px; font-size:11.5px; color:var(--gutter); }
.editor-tools span { padding:5px 9px; border-radius:7px; border:1px solid var(--line); cursor:pointer; }
.editor-body { flex:1; min-height:0; position:relative; overflow:hidden; }
/* overlay-редактор: textarea лежит ПОВЕРХ слоя подсветки .edit-hl. Текст самого textarea
   прозрачный (виден только курсор и выделение) — подсветку рисует .edit-hl под ним. */
.code-area { position:absolute; inset:0; width:100%; height:100%; resize:none; border:none; outline:none;
  background:transparent; color:transparent; font-family:'IBM Plex Mono', monospace; font-size:13px;
  line-height:23px; padding:12px 14px 12px 58px; white-space:pre; tab-size:4; caret-color:var(--accent); z-index:2; }
.code-area::selection { background:var(--accent-weak); }
/* слой подсветки под textarea: та же типографика/паддинг, номера строк в 58px-гуттере,
   БЕЗ картинок (высоты строк должны совпадать с textarea) */
.edit-hl { position:absolute; inset:0; overflow:hidden; padding:12px 0; margin:0; z-index:1;
  font-family:'IBM Plex Mono', monospace; font-size:13px; line-height:23px; white-space:pre;
  color:var(--codetext); pointer-events:none; }
.edit-hl .el { line-height:23px; white-space:pre; }
.edit-hl .eg { display:inline-block; width:58px; box-sizing:border-box; padding-right:14px; text-align:right;
  color:var(--gutter); font-size:12.5px; vertical-align:top; user-select:none; }
.edit-hl .es { font-size:13px; }
/* read view (line numbers + syntax). v-show toggles it with the textarea, so it must
   stay interactive: wheel-scroll long code + click to start editing. */
.code-view { position:absolute; inset:0; overflow:auto; padding:12px 0; font-family:'IBM Plex Mono', monospace;
  color:var(--codetext); }
.cl { display:flex; line-height:23px; }
.cl.active { background:var(--accent-weak); }
/* «На всех»: слева у каждой строки рейка с цветными метками устройств, СЕЙЧАС на ней
   (одно — во всю высоту; несколько — вертикальными полосами). Рейка есть у всех строк
   (даже пустая) — чтобы нумерация не «прыгала» при появлении меток. */
.cl .run-rail { width:6px; flex:none; align-self:stretch; display:flex; flex-direction:column;
  gap:1px; padding:2px 0; }
.cl .run-seg { flex:1; min-height:4px; border-radius:2px; }
.cl .gut { width:44px; flex:none; text-align:right; padding-right:14px; color:var(--gutter); font-size:12.5px; }
/* на паузе пошагового прогона НОМЕР строки — кликабельная цель «перенести выполнение сюда»
   (клик по самому коду по-прежнему открывает редактирование) */
.gut.canjump { cursor:pointer; }
.gut.canjump:hover { color:var(--accent); background:var(--accent-weak); outline:1px dashed var(--accent); outline-offset:-1px; }
.cl.active .gut { color:var(--accent); }
.cl .src { flex:1; white-space:pre; font-size:13px; padding-left:0; }
/* легенда параллельного прогона «на всех» — цвет ↔ устройство ↔ где оно сейчас */
.run-legend { display:flex; flex-wrap:wrap; align-items:center; gap:8px; padding:6px 12px;
  border-bottom:1px solid var(--line); background:var(--panel2); font-size:12px; }
.run-legend .rl-title { color:var(--muted); font-weight:600; }
.run-legend .rl-chip { display:inline-flex; align-items:center; gap:5px; padding:2px 9px;
  border-radius:12px; background:var(--panel3); border:1px solid var(--line); }
.run-legend .rl-dot { width:9px; height:9px; border-radius:50%; flex:none; }
.run-legend .rl-state { color:var(--muted); }
.run-legend .st-error { border-color:#e6504d; }
.run-legend .st-done { opacity:.65; }
/* variable bar: persistent self.var/gvar, under the toolbar, above the editor */
.var-bar { display:flex; flex-wrap:wrap; align-items:center; gap:8px 18px; padding:6px 14px;
  border-bottom:1px solid var(--line); background:var(--panel2); font-size:12px; }
.var-bar .vb-toggle { display:inline-flex; align-items:center; gap:5px; cursor:pointer;
  color:var(--muted); font-weight:600; user-select:none; }
.var-bar .vb-toggle:hover { color:var(--text2); }
.var-bar .vb-grp { display:flex; flex-wrap:wrap; align-items:center; gap:6px; }
.var-bar .vb-title { color:var(--muted); font-weight:600; margin-right:2px; }
.var-bar .vb-chip { display:inline-flex; align-items:center; gap:6px; padding:2px 7px 2px 9px;
  border-radius:12px; background:var(--panel3); border:1px solid var(--line); }
.var-bar .vb-name { color:var(--text2); }
.var-bar .vb-name::after { content:"="; color:var(--muted); margin-left:6px; }
.var-bar .vb-val { color:var(--accent); cursor:pointer; min-width:8px; }
.var-bar .vb-val:hover { text-decoration:underline; }
.var-bar .vb-input { width:96px; height:20px; padding:0 5px; border-radius:6px;
  border:1px solid var(--accent); background:var(--panel); color:var(--text); font-size:12px; }
.var-bar .vb-del { color:var(--muted); cursor:pointer; font-size:14px; line-height:1; }
.var-bar .vb-del:hover { color:var(--red); }
.var-bar .vb-add { cursor:pointer; color:var(--accent); border:1px dashed var(--line2);
  border-radius:12px; padding:1px 9px; font-weight:600; }
.var-bar .vb-add:hover { border-color:var(--accent); }
.tok-kw{color:var(--syn-kw);} .tok-fn{color:var(--syn-fn);} .tok-str{color:var(--syn-str);}
.tok-num{color:var(--syn-num);} .tok-com{color:var(--syn-com);} .tok-self{color:var(--syn-self);}
.tmpl-widget { display:inline-flex; flex-wrap:wrap; align-items:center; gap:8px 18px; margin:6px 0 6px 58px; padding:8px 11px;
  background:rgba(127,127,127,0.10); border:1px solid var(--line); border-radius:9px; }
.tmpl-item { display:inline-flex; align-items:center; gap:11px; }
.tmpl-widget img { height:30px; border-radius:7px; border:1px solid var(--line2); display:block; }
.tmpl-widget .meta { font-family:'IBM Plex Mono', monospace; }
.tmpl-widget .meta .n { font-size:12px; color:var(--codetext); }
.tmpl-widget .meta .d { font-size:10.5px; color:var(--gutter); margin-top:2px; }
/* click_expect: подписи «нажать»/«ждать» перед группами картинок + кнопка правки исходов */
.tmpl-label { font-family:'IBM Plex Mono', monospace; font-size:10.5px; text-transform:uppercase;
  letter-spacing:.04em; color:var(--accent); opacity:.8; }
.ce-edit-btn { font-size:11px; color:var(--accent); background:var(--accent-weak); border:1px solid var(--accent);
  border-radius:12px; padding:2px 9px; cursor:pointer; }
.ce-edit-btn:hover { background:var(--accent); color:#fff; }
.caret { color:var(--accent); font-weight:700; animation:recpulse 1s infinite; }
.rec-hint { display:flex; align-items:center; gap:8px; padding:0 0 8px 58px; font-family:'IBM Plex Mono', monospace; font-size:13px; }

/* script output console (self.print) — pinned under the editor body */
.console { flex:none; max-height:170px; display:flex; flex-direction:column; border-top:1px solid var(--line); background:var(--codebg); }
.console-head { flex:none; display:flex; align-items:center; justify-content:space-between;
  padding:5px 12px; font-size:11px; color:var(--gutter); border-bottom:1px solid var(--line); }
.console-clear { cursor:pointer; }
.console-clear:hover { color:var(--text2); }
/* два поля: слева обычный вывод, справа «коллекция окончаний» (Запуск N раз) */
.console-split { flex:1; display:flex; min-height:0; }
.console-body { flex:1; overflow:auto; padding:6px 12px; font-size:12.5px; line-height:18px; color:var(--codetext); }
.console-line { white-space:pre-wrap; word-break:break-word; }
.console-line.err { color:var(--red); }
/* правое поле — сводка окончаний: «GOOD 2 · 3.2 с» по убыванию частоты */
.outcomes { flex:none; width:210px; overflow:auto; padding:6px 10px; }
.outcomes-head { font-size:11px; color:var(--gutter); margin-bottom:4px; }
.outcome { display:flex; align-items:baseline; gap:8px; font-size:12.5px; line-height:19px; }
.outcome .oc-count { flex:none; min-width:20px; text-align:right; font-weight:600; color:var(--green); }
/* «(N)» — сколько окончаний с этой меткой за последний час (рядом с общим числом) */
.outcome .oc-hour { flex:none; margin-left:-4px; font-size:11px; color:var(--muted); }
.outcome .oc-label { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; color:var(--codetext); }
.outcome .oc-avg { flex:none; color:var(--gutter); }
.outcome.err .oc-count { color:var(--red); }
/* «Воспроизведение»: окончания лежат на СВЕТЛОЙ панели, а базовый --codetext подобран
   под тёмный редактор кода (в осенней теме он светло-кремовый → сливался). Здесь берём
   обычный текст панели — контрастен во всех трёх темах. Консоли Конструктора (.outcomes
   на тёмном --codebg) это не касается — там --codetext остаётся правильным. */
.pb-global .oc-label, .pb-history .oc-label { color:var(--text); }
/* поле ввода N в кнопке «N раз» */
.tb-btn.nrun { gap:5px; }
.nrun-input { width:44px; padding:1px 4px; font:inherit; font-size:12px; text-align:center;
  background:var(--codebg); color:var(--text2); border:1px solid var(--line); border-radius:4px; }
.nrun-input::-webkit-inner-spin-button { opacity:.6; }

/* ============================================================= playback tab */
.pb-side { flex:none; width:308px; border-right:1px solid var(--line); background:var(--panel);
  padding:14px; display:flex; flex-direction:column; gap:12px; overflow-y:auto; }
.pb-box { background:var(--panel2); border:1px solid var(--line); border-radius:12px; padding:12px; }
.pb-box-head { font-size:12px; font-weight:700; color:var(--text); margin-bottom:9px;
  display:flex; align-items:center; justify-content:space-between; }
.pb-run-title { font-size:11px; font-weight:500; color:var(--accent); max-width:150px;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.pb-lbl { display:block; font-size:11px; color:var(--muted); margin:6px 0 4px; }
.pb-launch .text-input { width:100%; height:36px; }
.pb-runs { display:flex; align-items:center; gap:12px; }
.pb-chk { display:flex; align-items:center; gap:6px; font-size:12.5px; color:var(--text2); cursor:pointer; }
.pb-indep { margin-top:8px; }
.pb-hint { font-size:11.5px; color:var(--muted); margin:10px 0 8px; }
.pb-hint b { color:var(--accent); }
.pb-go { width:100%; height:40px; border-radius:10px; font-size:13.5px; font-weight:600;
  display:flex; align-items:center; justify-content:center; gap:6px; }
.pb-go.stop { color:var(--red); border-color:var(--red); }

.pb-stats { display:flex; flex-direction:column; }
.pb-stat { display:flex; align-items:baseline; gap:8px; padding:4px 0; border-bottom:1px solid var(--line); }
.pb-stat:last-child { border-bottom:none; }
.pb-stat .k { flex:none; width:66px; font-size:11.5px; color:var(--muted); }
.pb-stat .v { font-size:15px; font-weight:700; color:var(--text); }
.pb-stat .v.bad { color:var(--red); }
.pb-stat .v .dim { font-size:12px; font-weight:500; color:var(--muted); }
.pb-stat .sub { font-size:11px; color:var(--muted); }
.pb-stat .sub.good { color:var(--green); }
.pb-stat .sub.bad { color:var(--red); }

.pb-spark { width:100%; height:34px; margin:8px 0 2px; display:block; }
.pb-spark polyline { fill:none; stroke:var(--green); stroke-width:1.5; vector-effect:non-scaling-stroke; }

.pb-sub-head { font-size:11px; color:var(--gutter); margin:10px 0 4px; }
.pb-empty { font-size:11.5px; color:var(--muted); font-style:italic; }
.pb-counter { display:flex; justify-content:space-between; font-size:12px; color:var(--text2); line-height:19px; }
.pb-counter b { color:var(--accent); }

.pb-hist { padding:6px 0; border-bottom:1px solid var(--line); }
.pb-hist:last-child { border-bottom:none; }
.pb-hist .hh { display:flex; justify-content:space-between; gap:8px; font-size:12px; }
.pb-hist .hh b { color:var(--text); font-weight:600; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.pb-hist .hh span { flex:none; color:var(--muted); font-size:10.5px; }
.pb-hist .hm { font-size:11px; color:var(--muted); margin-top:2px; }
.pb-hist .good { color:var(--green); } .pb-hist .bad { color:var(--red); }

.pb-main { flex:1; display:flex; flex-direction:column; min-width:0; }
.pb-topbar { flex:none; height:52px; display:flex; align-items:center; padding:0 20px;
  border-bottom:1px solid var(--line); font-size:13px; }
.pb-live { display:flex; align-items:center; gap:8px; color:var(--text2); font-weight:600; }
.pb-live .ld { width:9px; height:9px; border-radius:50%; background:var(--green);
  box-shadow:0 0 0 3px var(--accent-weak); animation:pbPulse 1.4s infinite; }
@keyframes pbPulse { 0%,100%{opacity:1;} 50%{opacity:0.35;} }
.pb-done, .pb-idle { color:var(--muted); }
.pb-showall { margin-left:auto; height:30px; padding:0 14px; font-size:12.5px; color:var(--text2);
  background:var(--panel2); border:1px solid var(--line2); border-radius:8px; cursor:pointer; }
.pb-showall:hover { border-color:var(--accent); color:var(--accent); }

.pb-scroll { flex:1; overflow:auto; padding:18px; }
.pb-grid { display:grid; grid-template-columns:repeat(auto-fill, 188px); gap:20px 18px; justify-content:start; }
.pb-dcard { width:188px; }
.pb-dcard.sel { cursor:pointer; }
.pb-badge { position:absolute; top:8px; left:8px; font-size:11px; font-weight:700; color:#fff;
  background:rgba(10,12,16,0.6); border-radius:7px; padding:2px 7px; pointer-events:none; }
.status.ok { background:var(--green); } .status.err { background:var(--red); }
.status.done { background:var(--accent); } .status.idle { background:var(--muted); }

.pb-devstats { margin-top:8px; display:flex; flex-direction:column; gap:4px; }
.pb-drow { display:flex; align-items:center; gap:8px; font-size:12px; min-width:0; }
.pb-drow.name { justify-content:space-between; }
.pb-drow .nm { font-weight:600; color:var(--text2); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.pb-drow .st { flex:none; font-size:11px; font-weight:600; }
.pb-drow .st.ok { color:var(--green); } .pb-drow .st.err { color:var(--red); }
.pb-drow .st.done { color:var(--accent); } .pb-drow .st.idle { color:var(--muted); }
.pb-drow.metrics .good { color:var(--green); } .pb-drow.metrics .bad { color:var(--red); }
.pb-drow.metrics .cyc { color:var(--muted); margin-left:auto; }
.pb-stage { font-size:12px; color:var(--accent); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.pb-line { font-size:11px; color:var(--codetext); background:var(--codebg); border-radius:6px; padding:3px 7px;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-family:monospace; }
.pb-line b { color:var(--gutter); margin-right:5px; }
.pb-err { font-size:11px; color:var(--red); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.pb-mini { display:flex; flex-wrap:wrap; gap:4px; }
.pb-mini .mo { font-size:10.5px; color:var(--text2); background:var(--panel2); border:1px solid var(--line);
  border-radius:5px; padding:1px 5px; }
.pb-mini .mo.err, .pb-mini .mo.bad { color:var(--red); border-color:var(--red); }
/* живой вывод self.print(...) этого телефона — прижат к низу (директива v-stick) */
/* фиксированная высота ровно в 6 строк (6×14.7px + отступы + зазоры), чтобы окно вывода
   не «росло» с 1 до 6 строк по ходу прогона — карточки всегда одной высоты. */
.pb-log { height:104px; overflow-y:auto; display:flex; flex-direction:column; gap:1px;
  background:var(--codebg); border-radius:6px; padding:4px 7px; }
.pb-logline { font-size:10.5px; line-height:1.4; color:var(--codetext); font-family:monospace;
  white-space:pre-wrap; word-break:break-word; }
.pb-shot { margin-top:4px; border:1px solid var(--line2); border-radius:8px; overflow:hidden;
  background:var(--codebg); cursor:pointer; transition:border-color 0.12s; }
.pb-shot:hover { border-color:var(--accent); }
.pb-shot img { display:block; width:100%; height:auto; }

/* кликабельное окончание (открывает ленту проходок) */
.outcome.clickable { cursor:pointer; border-radius:6px; padding:1px 4px; margin:0 -4px;
  transition:background 0.12s; }
.outcome.clickable:hover { background:var(--accent-weak); }
.outcome.clickable:hover .oc-label { color:var(--accent); }
.pb-sub-hint { font-size:9.5px; font-weight:400; color:var(--gutter); text-transform:none; }

/* история: раскрываемая запись с окончаниями */
.pb-hist .hh b { flex:1; }
.pb-hist .hh.clickable { cursor:pointer; }
.pb-hist .hh.clickable:hover b { color:var(--accent); }
.pb-hist .hh .when { flex:none; color:var(--muted); font-size:10.5px; }
.pb-hist .hh .chev { flex:none; color:var(--muted); font-size:10px; width:10px; text-align:center; }
.pb-hist.open .hh .chev { color:var(--accent); }
.pb-hist-oc { margin:6px 0 2px; padding-left:2px; display:flex; flex-direction:column; gap:1px; }

/* ===================================== лента проходок (оверлей поверх вкладки) */
.pb-feed-overlay { position:fixed; inset:0; z-index:60; background:rgba(4,6,10,0.62);
  backdrop-filter:blur(2px); display:flex; align-items:center; justify-content:center; padding:30px; }
.pb-feed { width:min(1160px, 94vw); max-height:90vh; display:flex; flex-direction:column;
  background:var(--panel); border:1px solid var(--line2); border-radius:14px; overflow:hidden;
  box-shadow:0 24px 64px -20px rgba(0,0,0,0.6); }
.pb-feed-head { flex:none; display:flex; align-items:center; gap:12px; padding:13px 18px;
  border-bottom:1px solid var(--line); }
.pb-feed-head .ttl { font-size:13.5px; font-weight:700; color:var(--text); max-width:280px;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.pb-feed-head .oc { font-size:12.5px; font-weight:600; color:var(--green); background:var(--green-weak);
  border-radius:7px; padding:3px 10px; }
.pb-feed-head .oc.err { color:var(--red); background:var(--red-weak); }
.pb-feed-head .oc.bad { color:var(--amber); background:transparent; border:1px solid var(--line2); }
.pb-feed-head .cnt { font-size:11.5px; color:var(--muted); }
.pb-feed-head .x { margin-left:auto; width:30px; height:30px; border-radius:8px; flex:none;
  background:var(--panel2); border:1px solid var(--line2); color:var(--muted); cursor:pointer; font-size:14px; }
.pb-feed-head .x:hover { color:var(--red); border-color:var(--red); }
.pb-feed-msg { padding:40px; text-align:center; color:var(--muted); font-size:13px; }
.pb-feed-list { flex:1; overflow-y:auto; padding:16px; display:flex; flex-direction:column; gap:14px; }

.pb-frame { border:1px solid var(--line); border-left:3px solid var(--green); border-radius:11px;
  background:var(--panel2); padding:12px 14px; }
.pb-frame.err { border-left-color:var(--red); }
.pb-frame.bad { border-left-color:var(--amber); }
.pb-frame-head { display:flex; align-items:baseline; gap:12px; font-size:12px; flex-wrap:wrap; }
.pb-frame-head .ph { font-weight:700; color:var(--text); }
.pb-frame-head .cyc { color:var(--accent); font-weight:600; }
.pb-frame-head .dt { color:var(--text2); font-variant-numeric:tabular-nums; }
.pb-frame-head .dur { margin-left:auto; color:var(--muted); }
/* снимки в ряд — горизонтальный скролл, финальный кадр последним */
.pb-frame-shots { display:flex; gap:8px; margin-top:10px; overflow-x:auto; padding-bottom:6px; }
.pb-frame-shots .shot { flex:none; position:relative; border:1px solid var(--line2); border-radius:8px;
  overflow:hidden; background:var(--codebg); line-height:0; cursor:pointer; transition:border-color 0.12s; }
.pb-frame-shots .shot:hover { border-color:var(--accent); }
.pb-frame-shots .shot img { height:216px; width:auto; display:block; }
/* уголок «открыть полностью» — не перехватывает клик-закрепление (@click.stop в разметке) */
.pb-frame-shots .shot .shot-open { position:absolute; top:5px; right:5px; width:22px; height:22px;
  display:flex; align-items:center; justify-content:center; border-radius:6px; line-height:1;
  font-size:12px; text-decoration:none; color:var(--text); background:rgba(0,0,0,0.55);
  opacity:0; transition:opacity 0.12s; }
.pb-frame-shots .shot:hover .shot-open { opacity:1; }
.pb-frame-shots .shot .shot-open:hover { background:var(--accent); color:#fff; }
.pb-frame-noshot { margin-top:8px; font-size:11px; font-style:italic; color:var(--muted); }
.pb-frame-stop { margin-top:9px; font-size:12px; font-family:monospace; color:var(--codetext);
  background:var(--codebg); border-radius:7px; padding:5px 9px; overflow-x:auto; white-space:nowrap; }
.pb-frame-stop b { color:var(--gutter); margin-right:6px; }
.pb-frame-err { margin-top:7px; font-size:12px; color:var(--red); word-break:break-word; }
/* широкий лог проходки — на всю ширину фрейма, читаемый */
.pb-frame-log { margin-top:9px; max-height:240px; overflow-y:auto; background:var(--codebg);
  border-radius:8px; padding:8px 11px; display:flex; flex-direction:column; gap:1px; }
.pb-frame-log .lg { font-size:12px; line-height:1.5; color:var(--codetext); font-family:monospace;
  white-space:pre-wrap; word-break:break-word; }
.pb-frame-log .lg.dim { color:var(--muted); font-style:italic; }

/* ============================================================= device screen */
.screen { position:relative; width:100%; height:100%; background:#000; overflow:hidden; user-select:none; }
.screen img { width:100%; height:100%; object-fit:cover; display:block; pointer-events:none; }
.screen .nosig { position:absolute; inset:0; display:flex; align-items:center; justify-content:center;
  color:#54606e; font-size:11px; }
.screen .ilayer { position:absolute; inset:0; cursor:crosshair; }
.screen.tappable .ilayer { cursor:pointer; }
.screen .selrect { position:absolute; border:2px solid var(--accent); background:rgba(76,141,255,0.12);
  box-shadow:0 0 0 9999px rgba(8,10,14,0.34); }
.screen .selrect .lbl { position:absolute; top:-23px; left:-1px; background:var(--accent); color:#fff;
  font-size:11px; font-weight:600; padding:2px 8px; border-radius:5px; white-space:nowrap; }
.screen .selrect .h { position:absolute; width:8px; height:8px; background:#fff; border:1.5px solid var(--accent); border-radius:2px; }
.screen .selrect .h.tl{top:-4px;left:-4px;} .screen .selrect .h.tr{top:-4px;right:-4px;}
.screen .selrect .h.bl{bottom:-4px;left:-4px;} .screen .selrect .h.br{bottom:-4px;right:-4px;}
.screen .ripple { position:absolute; width:18px; height:18px; margin:-9px 0 0 -9px; border-radius:50%;
  border:2px solid var(--accent); animation:rippleA 0.5s ease-out forwards; pointer-events:none; }
@keyframes rippleA { from{transform:scale(0.4);opacity:0.9;} to{transform:scale(1.8);opacity:0;} }

/* toast */
.toasts { position:fixed; right:18px; bottom:18px; display:flex; flex-direction:column; gap:8px; z-index:50; }
.toast { padding:10px 14px; border-radius:9px; background:var(--panel2); border:1px solid var(--line2);
  color:var(--text); font-size:12.5px; box-shadow:0 8px 24px -10px rgba(0,0,0,0.5); max-width:340px; }
.toast.err { border-color:var(--red); color:var(--red); background:var(--red-weak); }

/* dialog */
.modal-bg { position:fixed; inset:0; background:rgba(0,0,0,0.5); display:flex; align-items:center; justify-content:center; z-index:60; }
.modal { background:var(--panel); border:1px solid var(--line2); border-radius:14px; padding:20px; width:380px;
  display:flex; flex-direction:column; gap:14px; }
.modal h3 { margin:0; font-size:15px; color:var(--text); }
.modal .row { display:flex; gap:10px; align-items:center; }
.modal .actions { display:flex; gap:9px; justify-content:flex-end; }
.modal .actions .btn { height:38px; padding:0 16px; border-radius:9px; font-size:13px; font-weight:500; }
.modal label { font-size:12.5px; color:var(--text2); display:flex; align-items:center; gap:8px; }
.dropdown-menu { position:absolute; top:100%; left:0; margin-top:6px; background:var(--panel); border:1px solid var(--line2);
  border-radius:9px; padding:6px; min-width:200px; z-index:20; box-shadow:0 12px 30px -12px rgba(0,0,0,0.5); }
.dropdown-menu .item { padding:8px 10px; border-radius:7px; font-size:13px; color:var(--text2); cursor:pointer; display:flex; justify-content:space-between; gap:10px; }
.dropdown-menu .item:hover { background:var(--panel2); color:var(--text); }
.rel { position:relative; }

/* ============================================================= virtual keyboard */
.vkbd { position:fixed; left:0; right:0; bottom:0; z-index:45; background:var(--panel);
  border-top:1px solid var(--line2); box-shadow:0 -10px 30px -12px rgba(0,0,0,0.5);
  padding:8px 12px 14px; display:flex; flex-direction:column; gap:8px; animation:vkbdUp .16s ease-out; }
@keyframes vkbdUp { from { transform:translateY(100%); } to { transform:translateY(0); } }
.vkbd.disabled { opacity:.55; pointer-events:none; }
/* В Конструкторе клавиатура «встроена» в колонку кода в потоке (не fixed): стоит
   между кодом и консолью, поэтому ужимается только код, а левое поле (экран+кнопки)
   и нижний «Вывод скрипта» остаются видимыми. flex:none — клавиатура не сжимается. */
.vkbd.docked { position:static; flex:none; }
/* В Панели клавиатура остаётся зафиксированной снизу, но её левый край сдвинут
   на ширину левой колонки (.control-col = 432px), чтобы не загораживать экран и
   кнопки слева — печать всё равно уходит на выбранные устройства. */
.vkbd.panel { left:432px; }
.vkbd-head { display:flex; align-items:center; justify-content:space-between; padding:0 2px; }
.vkbd-title { font-size:12px; font-weight:600; color:var(--text2); }
.vkbd-x { width:26px; height:26px; border-radius:7px; display:flex; align-items:center; justify-content:center;
  color:var(--muted); font-size:13px; cursor:pointer; background:var(--panel2); border:1px solid var(--line); }
/* палитра команд слева + стойка клавиш справа (переносится под палитру, если узко) */
.vkbd-rows { display:flex; flex-flow:row wrap; gap:12px 16px; justify-content:center; align-items:flex-start;
  max-width:1120px; width:100%; margin:0 auto; }
/* стойка клавиш — прежний вертикальный столбец, теперь отдельный флекс-ребёнок; в
   Панели палитры нет, поэтому стойка просто центрируется одна (как раньше). Базис
   подобран так, чтобы палитра+клавиши влезли в одну строку на обычной ширине поля
   кода; если поле кода узкое — клавиши переносятся под палитру (flex-wrap). */
.vkbd-keys { display:flex; flex-direction:column; gap:7px; flex:1 1 520px; min-width:320px; max-width:720px; width:100%; }
.vkrow { display:flex; gap:6px; justify-content:center; }
.vk { flex:1 1 0; min-width:0; height:42px; padding:0; border-radius:8px; background:var(--panel2);
  border:1px solid var(--line2); color:var(--text); font-family:inherit; font-size:15px; cursor:pointer;
  display:flex; align-items:center; justify-content:center; user-select:none; -webkit-user-select:none; }
.vk:active { background:var(--panel3); }
.vk.wide { flex:1.5 1 0; font-size:13px; color:var(--text2); }
.vk.space { flex:5 1 0; font-size:12px; color:var(--text2); }
.vk.on { background:var(--accent); border-color:var(--accent); color:#fff; }
.vk.mod { flex:1.5 1 0; font-size:13px; color:var(--text2); }
.vkrow.mods { max-width:360px; margin:2px auto 0; }
.vkbd-mod-hint { color:var(--accent); font-weight:600; }
.vkrow.arrows { max-width:260px; margin:2px auto 0; }
/* Палитра команд (только Конструктор): кнопки вставляют строку кода (self.sleep(1) и
   т.п.), а не печатают на телефон. Колонка СЛЕВА от клавиш; высота ограничена (скролл),
   чтобы виджет не рос по вертикали. Панель палитру не передаёт → её тут нет. */
.vk-cmds { display:flex; flex-direction:column; gap:5px; flex:1 1 340px; min-width:240px; max-width:520px;
  max-height:336px; overflow-y:auto; padding-right:12px; border-right:1px solid var(--line); }
.vk-cmds-head { position:sticky; top:0; background:var(--panel); padding-bottom:2px; z-index:1;
  font-size:10px; font-weight:600; letter-spacing:0.4px; text-transform:uppercase; color:var(--muted); }
.vk-cmd-grp { display:flex; flex-wrap:wrap; align-items:center; gap:5px; }
.vk-cmd-title { font-size:11px; color:var(--muted); min-width:86px; }
.vk-cmd { height:28px; padding:0 8px; border-radius:7px; background:var(--panel2); border:1px solid var(--line2);
  color:var(--text); font-family:inherit; font-size:12px; cursor:pointer;
  display:inline-flex; align-items:center; gap:6px; }
.vk-cmd:hover { border-color:var(--accent); }
.vk-cmd:active { background:var(--panel3); }
.vk-cmd b { font-weight:600; white-space:nowrap; }
.vk-cmd code { font-family:'IBM Plex Mono', monospace; font-size:11px; color:var(--muted); }
.action-btn.active { background:var(--accent); border-color:var(--accent); color:#fff; }

/* screen video source toggle + fps textbox (grid toolbar, right side) */
.src-controls { display:flex; align-items:center; gap:10px; }
.src-toggle { display:flex; padding:3px; border-radius:9px; background:var(--panel2); border:1px solid var(--line); }
.src-toggle .seg { font-family:inherit; font-size:12px; font-weight:500; color:var(--muted); cursor:pointer;
  background:none; border:none; padding:5px 11px; border-radius:6px; }
.src-toggle .seg.on { background:var(--accent); color:#fff; }
.fps-field { display:flex; align-items:center; gap:6px; padding:4px 9px; border-radius:8px;
  background:var(--panel2); border:1px solid var(--line); font-size:12px; color:var(--muted); }
.fps-field input { width:46px; height:22px; padding:0 6px; border-radius:6px; background:var(--panel);
  border:1px solid var(--line2); color:var(--text); font-family:inherit; font-size:12px; text-align:center; }
.fps .dot.off { background:var(--muted); }
.ap-restart-btn { font-family:inherit; font-size:12px; font-weight:500; color:var(--text2); cursor:pointer;
  padding:6px 11px; border-radius:8px; background:var(--panel2); border:1px solid var(--line); white-space:nowrap; }
.ap-restart-btn:hover { border-color:var(--accent); color:var(--accent); }
.iface-field { display:flex; align-items:center; gap:6px; padding:4px 9px; border-radius:8px;
  background:var(--panel2); border:1px solid var(--line); font-size:12px; color:var(--muted); }
.iface-field select { height:22px; max-width:190px; border-radius:6px; background:var(--panel);
  border:1px solid var(--line2); color:var(--text); font-family:inherit; font-size:12px; padding:0 4px; }
.ap-router-tag { display:inline-flex; align-items:center; gap:5px; padding:4px 9px; border-radius:8px;
  background:var(--panel2); border:1px solid var(--line); font-size:12px; color:var(--muted); white-space:nowrap; }

/* AirPlay "Привязка" panel: connected phones (info only) + manual device binding */
.bind-col { flex:none; width:300px; border-left:1px solid var(--line); background:var(--panel);
  padding:16px; display:flex; flex-direction:column; gap:12px; overflow-y:auto; }
.bind-head { display:flex; align-items:center; justify-content:space-between; }
.bind-hint { font-size:11.5px; color:var(--muted); line-height:1.55; }
.bind-empty { font-size:12.5px; color:var(--muted); padding:16px; text-align:center;
  border:1px dashed var(--line2); border-radius:10px; }
.bind-card { border:1px solid var(--line); border-radius:10px; padding:10px 11px; background:var(--panel2);
  display:flex; flex-direction:column; gap:7px; }
.bind-card.bound { border-color:var(--accent); }
.bind-card-top { display:flex; align-items:center; gap:7px; font-size:13px; }
.bind-card-top b { font-weight:600; color:var(--text); }
.bind-id { font-size:11px; color:var(--gutter); font-family:'IBM Plex Mono', monospace; }
.bind-ip { color:var(--green); }
.bind-row { display:flex; align-items:center; gap:8px; }
.bind-row .ap-bind { flex:1; height:30px; }
.ap-dot { width:7px; height:7px; border-radius:50%; background:var(--green); flex:none; }
.ap-model { font-size:11px; color:var(--muted); }
.ap-arrow { color:var(--muted); }
.ap-bind { height:24px; border-radius:6px; background:var(--panel); border:1px solid var(--line2);
  color:var(--text); font-family:inherit; font-size:12px; padding:0 4px; }
.caption .ap-tag { font-size:11px; color:var(--accent); font-weight:500; margin-left:6px;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; max-width:130px; }

/* ------------------------------------------------- «Доступ» (remote access) tab */
.access-body { overflow:auto; }
.access-wrap { max-width:820px; margin:0 auto; padding:22px 20px 60px; width:100%; }
.access-head { display:flex; align-items:flex-start; justify-content:space-between; gap:16px; margin-bottom:18px; }
.access-title { font-size:18px; font-weight:600; color:var(--text); }
.access-sub { font-size:12.5px; color:var(--muted); margin-top:4px; max-width:560px; line-height:1.45; }
.access-empty { color:var(--muted); font-size:13px; padding:24px 0; text-align:center; }
.access-card { background:var(--panel); border:1px solid var(--line); border-radius:12px;
  padding:14px 16px; margin-bottom:14px; }
.access-card.disabled { opacity:0.6; }
.access-card-top { display:flex; align-items:center; gap:10px; }
.access-label { flex:1; height:32px; background:var(--panel2); border:1px solid var(--line2);
  border-radius:8px; color:var(--text); font-family:inherit; font-size:14px; font-weight:500; padding:0 10px; }
.access-enabled { display:flex; align-items:center; gap:6px; font-size:12px; color:var(--text2); cursor:pointer; white-space:nowrap; }
.access-del { width:30px; height:30px; border-radius:8px; border:1px solid var(--line2); background:transparent;
  color:var(--muted); cursor:pointer; font-size:13px; }
.access-del:hover { color:var(--red); border-color:var(--red); }
.access-section { margin-top:12px; }
.access-section-title { font-size:11px; text-transform:uppercase; letter-spacing:0.04em; color:var(--muted); margin-bottom:7px; }
.access-caps, .access-devices { display:flex; flex-wrap:wrap; gap:7px; }
.access-devices { margin-top:8px; }
.access-chip { display:inline-flex; align-items:center; gap:6px; padding:5px 10px; border-radius:8px;
  border:1px solid var(--line2); background:var(--panel2); color:var(--text2); font-size:12.5px; cursor:pointer; }
.access-chip input { accent-color:var(--accent); }
.access-all { background:var(--accent-weak); border-color:var(--accent); color:var(--text); }
.access-hint { color:var(--muted); font-size:12px; }
.access-link-row { display:flex; gap:8px; margin-top:14px; }
.access-link { flex:1; height:32px; background:var(--codebg); border:1px solid var(--line2); border-radius:8px;
  color:var(--codetext); font-family:var(--mono, monospace); font-size:12px; padding:0 10px; }

/* ------------------------------------------------------------- «Нет доступа» */
.denied-screen { position:fixed; inset:0; display:flex; align-items:center; justify-content:center; background:var(--desk); }
.denied-box { text-align:center; max-width:380px; padding:0 24px; }
.denied-logo { width:44px; height:44px; border-radius:12px; margin:0 auto 16px;
  background:var(--panel2); border:1px solid var(--line2); display:flex; align-items:center; justify-content:center; }
.denied-logo span { width:16px; height:16px; border-radius:5px; background:var(--red); display:block; }
.denied-title { font-size:20px; font-weight:600; color:var(--text); }
.denied-sub { font-size:13px; color:var(--muted); margin-top:8px; line-height:1.5; }
