:root{
  --bg:#0e1113; --panel:#161a1d; --panel2:#1d2226; --line:#2a3136;
  --txt:#c8d2d6; --dim:#929fa7; --acc:#e0b23c; --acc2:#4ec9b0;
  --t-sig:#4ec9b0; --t-num:#e0b23c; --t-spec:#c586c0; --t-img:#569cd6;
  --t-txt:#d18ad1; --t-blk:#7fd17f; --t-bands:#5fb8d1; --t-rec:#e0875f; --t-trk:#e07fb0; --t-iq:#b4d455; --t-vid:#e6d36a; --t-rtc:#6fd0c0; --t-bin:#e0b050; --err:#e05c5c;
  /* цвета пинов по типам: 14 разных оттенков, по кругу */
  --p-rec:#da7a62; --p-val:#daa262; --p-num:#dabe62; --p-vid:#d6da62; --p-iq:#aeda62; --p-blk:#62da66; --p-sig:#62dabe; --p-rtc:#62c2da; --p-img:#6292da; --p-bands:#6262da; --p-spec:#9a62da; --p-txt:#d262da; --p-trk:#da62a2; --p-song:#e0875f; --p-bin:#da6272;
  /* --grid/--axis — сетка/подписи осей на canvas.view. Тот canvas всегда на тёмном --screen
     (см. ниже — --screen НЕ переопределён в светлой теме, экран прибора тёмный в обеих темах),
     так что и эти двое — не по теме, а константа, как --screen/--screen-fg сами; если сделать
     их светлыми в светлой теме, сетка станет ярче на том же тёмном фоне, а не тише, как задумано. */
  --grid:#1e2529; --axis:#6c7a80;
  /* --scr-panel/--scr-hi — тот же случай: заливка-«подложка»/яркий highlight-акцент поверх
     canvas.view, тоже всегда на тёмном --screen, тоже не по теме */
  --scr-panel:#1d2226; --scr-hi:#ffffff;
  --scr-txt:#c8d2d6; --scr-ok:#7dff9a; --scr-warn:#ffd84a; --scr-bad:#ff5c5c;
  --hi:#ffffff; --scrim:#0009;
  --note-bg:#1c1a14; --note-head:#241f14; --note-line:#3a3320;
  --canvas:#07090a; --screen:#0a0d0e; --screen-fg:#4ec9b0; --pin:13px; --pov:8px;
  --mono:ui-monospace,"SF Mono",Menlo,Consolas,monospace;
}
/* светлая системная тема — для читаемости на солнце */
@media (prefers-color-scheme: light){
  :root{
    --bg:#eef0f2; --panel:#ffffff; --panel2:#e6e9ec; --line:#c7ccd1;
    --txt:#1c2226; --dim:#5c6670; --acc:#a8720f; --acc2:#0f9488;
    --t-sig:#0f9488; --t-num:#a8720f; --t-spec:#9333ea; --t-img:#2563eb;
    --t-txt:#a83fa8; --t-blk:#2f9e4f; --t-bands:#1b7f96; --t-rec:#b8541f; --t-trk:#b83d7c; --t-iq:#5f8a0e; --t-vid:#8a7a0a; --t-rtc:#1d8a78; --t-bin:#a9770f; --err:#c23b3b;
    --p-rec:#a33114; --p-val:#a36114; --p-num:#a38214; --p-vid:#9fa314; --p-iq:#6fa314; --p-blk:#14a319; --p-sig:#14a382; --p-rtc:#1487a3; --p-img:#144da3; --p-bands:#1414a3; --p-spec:#5714a3; --p-txt:#9a14a3; --p-trk:#a31461; --p-song:#b8541f; --p-bin:#a31427;
    --hi:#000000; --scrim:#0004;
    --canvas:#d3d9df;
    --screen:#f3f5f7; --screen-fg:#0b7c72; --grid:#dde2e6; --axis:#68737b; --scr-panel:#e4e8eb; --scr-hi:#111111;
    --scr-txt:#2b343a; --scr-ok:#1a9a45; --scr-warn:#a87400; --scr-bad:#d03030;
    --note-bg:#fff8e1; --note-head:#fbecc3; --note-line:#e3cf95;
  }
}
*{box-sizing:border-box}
:root{--barh:44px}
html,body{margin:0;height:100%;overflow:hidden;background:var(--bg);color:var(--txt);
  font:12px/1.4 var(--mono);-webkit-font-smoothing:antialiased;overscroll-behavior:none;
  -webkit-tap-highlight-color:transparent;-webkit-text-size-adjust:100%}
button,select,input{font:inherit;color:inherit}
#app{display:flex;height:100%;padding:env(safe-area-inset-top) env(safe-area-inset-right) 0 env(safe-area-inset-left)}

/* ---- палитра ---- */
#side{width:235px;flex:0 0 235px;background:var(--panel);border-right:1px solid var(--line);
  display:flex;flex-direction:column;overflow:hidden}
#side h1{margin:0;padding:0 12px;height:var(--barh);line-height:1;display:flex;align-items:center;flex:none;font-size:12px;letter-spacing:.06em;font-weight:600;
  color:var(--txt);border-bottom:1px solid var(--line)}
#side h1 small{display:block;color:var(--dim);font-size:10px;margin-top:4px}
/* табы — как вкладки тайлов: активная слита с телом, акцентная черта сверху */
#sideTabs{display:flex;flex:none;align-items:stretch;min-height:24px;background:var(--panel2);border-bottom:1px solid var(--line)}
#sideTabs button{flex:1;background:none;border:0;border-radius:0;margin-bottom:-1px;padding:0 9px;cursor:pointer;
  color:var(--dim);font:11px var(--mono)}
#sideTabs button:hover{color:var(--txt);background:var(--panel)}
#sideTabs button.on{color:var(--hi,var(--txt));background:var(--panel);
  box-shadow:inset 0 2px 0 var(--acc),inset 1px 0 0 var(--line),inset -1px 0 0 var(--line)}
@media (pointer:coarse){ #sideTabs{min-height:34px} #sideTabs button{font-size:12px} }
.sidepanel{display:none;flex-direction:column;overflow:hidden;flex:1;min-height:0}
.sidepanel.on{display:flex}
#patchTools{display:flex;gap:5px;padding:8px;border-bottom:1px solid var(--line)}
#patchSearch{width:100%;min-width:0;background:var(--bg);border:1px solid var(--line);
  border-radius:3px;padding:7px 8px;outline:none}
#patchSearch:focus{border-color:var(--acc)}
#patchTools button{flex:0 0 34px;background:none;border:0;
  border-radius:3px;cursor:pointer;color:var(--dim);font-size:15px;line-height:1}
#patchTools button:hover{background:var(--panel2);color:var(--txt)}
#patchList{overflow:auto;flex:1;padding:6px 0 20px;background:var(--bg)}
#patchList .pitem.on{background:var(--panel2);border-left-color:var(--acc)}
#palette{overflow:auto;overscroll-behavior:contain;flex:1;padding:0 0 20px;background:var(--bg)}
#palette .pcat:first-child{margin-top:6px}
#paletteTools{display:flex;gap:5px;padding:8px;border-bottom:1px solid var(--line);background:var(--panel);
  position:relative;z-index:1}
#paletteSearch{width:100%;min-width:0;background:var(--bg);border:1px solid var(--line);
  border-radius:3px;padding:7px 8px;outline:none}
#paletteSearch:focus{border-color:var(--acc)}
#palette.empty:after,#patchList.empty:after{content:'Nothing found';display:block;padding:18px 12px;color:var(--dim)}
.pcat summary{display:flex;align-items:center;gap:7px;padding:7px 12px 5px;
  color:var(--dim);font-size:9px;letter-spacing:.1em;text-transform:uppercase;cursor:pointer;
  list-style:none;user-select:none;
  position:sticky;top:0;z-index:1;background:var(--bg)}
.pcat summary::-webkit-details-marker{display:none}
.pcat summary::before{content:'▸';flex:none;font-size:8px;transition:transform .12s}
.pcat[open] summary::before{transform:rotate(90deg)}
.pcat summary:hover{color:var(--txt)}
.pcat summary .cnt{margin-left:auto;color:var(--dim);font-size:9px;opacity:.7}
.pcat[open]{padding-bottom:6px}
.pitem{display:flex;align-items:center;width:100%;text-align:left;background:none;line-height:1.2;
  border:0;padding:3px 12px 3px 20px;cursor:grab;color:var(--txt);border-left:2px solid transparent}
.pitem:hover{background:var(--panel2);border-left-color:var(--acc)}
.pitem.dragging{opacity:.4}
#canvas.dropok{outline:2px dashed var(--acc);outline-offset:-2px}
.pitem .ptxt{flex:1;min-width:0;display:flex;flex-direction:column;gap:0}
.pitem{position:relative}
.pitem .pins,.pitem .pdel{display:none;position:absolute;top:50%;transform:translateY(-50%);padding:1px 5px;border-radius:3px;
  background:var(--panel2);color:var(--dim);font-size:11px;line-height:1.2;cursor:pointer}
.pitem .pdel{right:6px}
.pitem .pins{right:28px}
.pitem:hover .pins,.pitem:hover .pdel{display:block}
.pitem .pstar{display:none;position:absolute;top:50%;transform:translateY(-50%);right:50px;padding:1px 5px;border-radius:3px;color:var(--dim)}
.pitem:hover .pstar,.pitem .pstar.on{display:block}
.pitem .pstar.on{color:var(--acc)}
.pitem .pstar:hover{color:var(--acc);background:var(--bg)}
.pitem .pins:hover,.pitem .pdel:hover{color:var(--txt);background:var(--bg)}
#patchList .pitem:hover .ptxt{padding-right:46px}
#patchList .pitem{padding-top:3px;padding-bottom:3px}
#patchList .pitem.insub{padding-left:28px;background-image:linear-gradient(var(--line),var(--line));background-repeat:no-repeat;background-size:1px 100%;background-position:15px 0}
#patchList .ptxt b{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pitem b{font-weight:400;overflow-wrap:anywhere}
.pitem i{font-style:normal;color:var(--dim);font-size:9px}
.pitem .prow{display:flex;align-items:baseline;flex-wrap:wrap;gap:0 8px}
.pitem .pio{display:flex;flex-wrap:wrap;align-items:center;gap:4px;margin-left:auto}
.pitem .pio .grp{display:flex;align-items:center;gap:3px;font-size:8px;
  color:var(--dim);text-transform:uppercase;letter-spacing:.03em}
.pitem .pio .pin{width:5px;height:5px;border-radius:50%;flex:0 0 5px}
.pitem .pio .arr{color:var(--dim);font-size:8px}

/* тонкие скроллбары в тон интерфейсу — везде (списки узлов, панели тайлов, textarea, readout…) */
*{scrollbar-width:thin;scrollbar-color:var(--line) transparent}
::-webkit-scrollbar{width:8px;height:8px}
::-webkit-scrollbar-track,::-webkit-scrollbar-corner{background:transparent}
::-webkit-scrollbar-thumb{background:var(--line);border-radius:4px;border:2px solid transparent;background-clip:padding-box}
::-webkit-scrollbar-thumb:hover{background-color:var(--dim)}

/* ---- рабочая область ---- */
#main{flex:1;display:flex;flex-direction:column;min-width:0}
#bar{display:flex;gap:6px;align-items:center;padding:0 8px;min-height:var(--barh);flex:none;background:var(--panel);
  border-bottom:1px solid var(--line);flex-wrap:wrap}
#bar .sep{width:1px;height:20px;background:var(--line);margin:0 2px}
#bar button{background:none;border:0;padding:5px 10px;
  border-radius:3px;cursor:pointer}
#bar button:hover{background:var(--panel2);color:var(--hi)}
#bar button:active{background:var(--line)}
#bar button:disabled{opacity:.35;pointer-events:none}
#bar button.on{color:var(--acc)}
#bar button:focus-visible,#patchTools button:focus-visible{outline:1px solid var(--acc);outline-offset:-1px}
#bar .sp{flex:1}
body.noedit #bar .ed{display:none}
@media (min-width:821px) and (pointer:fine){
  #bar #menu{position:fixed;left:0;top:0;z-index:12;width:var(--barh);height:calc(var(--barh) - 1px);padding:0;border-radius:0}
  #side h1{padding-left:var(--barh)}
  #side.collapsed~#main #bar{padding-left:var(--barh)}
}
.i{width:16px;height:16px;display:block;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round;pointer-events:none}
#bar button:has(.i),#patchTools button:has(.i){display:inline-flex;align-items:center;justify-content:center}
#bar button:has(.i){padding:5px 8px}
#stat{color:var(--dim);font-size:11px;flex:0 1 40ch;min-width:0;text-align:right;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;contain:layout paint}
#stat.warn{color:var(--acc)}
#stat.crit{color:#e05c5c;font-weight:600}

#canvas{flex:1;position:relative;overflow:hidden;cursor:grab;touch-action:none;background:var(--canvas)}
#side.collapsed{display:none}
/* ---- дашборд: тайловая раскладка закреплённых (📌) узлов, дерево произвольных сплитов (как в tiling WM) ---- */
#dashGrid{display:none;width:100%;height:100%;overflow:hidden;box-sizing:border-box}
#dashGrid>*{width:100%;height:100%}
#canvas.dashboard{overflow:hidden;background:none}
#canvas.dashboard:not(.graphOn){cursor:default;touch-action:none}
/* панель «граф модулей»: сквозь прозрачную панель виден и работает обычный холст под сеткой */
#canvas.graphOn #content,#canvas.graphOn #wires{display:block}
#canvas.graphOn #dashGrid{position:relative;z-index:1;pointer-events:none}
#canvas.graphOn .dash-pane:not(.graph),#canvas.graphOn .dash-tools,#canvas.graphOn .dash-resizer{pointer-events:auto}
.dash-pane.graph{background:none;outline:1px solid var(--line);outline-offset:-1px}
.dash-pane.graph>.dash-body{overflow:hidden}
.node.ghost{opacity:.75;border-style:dashed}
.node.ghost .ghostNote{color:var(--dim);font-size:11px;padding:4px 0}
#canvas.dashboard:not(.graphOn) #content,#canvas.dashboard:not(.graphOn) #wires{display:none}
#canvas.dashboard #dashGrid{display:flex}
.dash-split{display:flex;width:100%;height:100%;min-width:0;min-height:0}
.dash-split.row{flex-direction:row;gap:0}
.dash-split.col{flex-direction:column;gap:0}              /* gap:0 — иначе общий .col (gap:10px) даёт зазоры */
/* разделитель — линия в 1px без зазора; зона захвата шире за счёт ::before поверх соседних панелей */
.dash-resizer{flex:none;position:relative;background:var(--line);z-index:3;touch-action:none}
.dash-resizer::before{content:'';position:absolute;inset:0}
.dash-split.row>.dash-resizer{width:3px;cursor:col-resize}
.dash-split.col>.dash-resizer{height:3px;cursor:row-resize}
.dash-split.row>.dash-resizer::before{left:-3px;right:-3px}
.dash-split.col>.dash-resizer::before{top:-3px;bottom:-3px}
@media (pointer:coarse){
  .dash-split.row>.dash-resizer::before{left:-9px;right:-9px}
  .dash-split.col>.dash-resizer::before{top:-9px;bottom:-9px}
}
.dash-resizer:hover,.dash-resizer.active{background:var(--acc);box-shadow:0 0 0 1px var(--acc)}
.dash-pane{position:relative;display:flex;flex-direction:column;min-width:0;min-height:0;background:var(--panel);overflow:hidden}
.dash-tools{flex:none;position:relative;z-index:4;display:flex;align-items:stretch;gap:0;padding:0;min-height:24px;
  background:var(--panel2);container-type:inline-size}
/* кнопки действий — без рамок и приглушены, ярче при наведении на панель */
.dash-tools button{flex:none;background:none;border:0;border-radius:0;color:var(--dim);
  cursor:pointer;font-size:12px;padding:0 7px;line-height:1.5}
.dash-tools button:hover{color:var(--acc)}
.dash-tools button.on{color:var(--acc)}
.dash-acts{flex:none;display:flex;align-items:stretch;opacity:.45;transition:opacity .12s}
.dash-pane:hover .dash-acts,.dash-tools.acts .dash-acts{opacity:1}
/* вкладки: активная — селект модуля, слита с телом панели, акцентная черта сверху; остальные — тусклый текст */
.dash-tabs{flex:1 1 auto;min-width:0;display:flex;align-items:stretch;overflow-x:auto;scrollbar-width:none;touch-action:pan-x}
@media (pointer:coarse){ .dash-tools{touch-action:none} .dash-tools .dash-tabs.ovf{touch-action:pan-x} }
.dash-tabs::-webkit-scrollbar{display:none}
.dash-tools select.dash-pick{flex:0 1 auto;min-width:5em;max-width:100%;-webkit-appearance:none;appearance:none;
  border:0;border-radius:0;margin-bottom:-1px;color:var(--hi,var(--txt));font:11px var(--mono);padding:0 20px 0 9px;cursor:pointer;
  box-shadow:inset 0 2px 0 var(--acc),inset 1px 0 0 var(--line),inset -1px 0 0 var(--line);
  background:linear-gradient(45deg,transparent 50%,var(--dim) 50%) right 11px center/4px 4px no-repeat,
    linear-gradient(135deg,var(--dim) 50%,transparent 50%) right 7px center/4px 4px no-repeat,var(--panel)}
.dash-tools .dash-tab{max-width:10em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font:11px var(--mono);padding:0 9px}
.dash-tools .dash-tab:hover{color:var(--txt);background:var(--panel)}
.dash-tools .dash-tadd{padding:0 8px;opacity:.6}
.dash-tools .dash-tadd:hover{opacity:1}
/* мышь: управление тайлом скрыто, пока курсор не над ним; над тайлом — полупрозрачно, над шапкой — полностью */
@media (hover:hover) and (pointer:fine){
  .dash-acts,.dash-tools .dash-tadd{opacity:0}
  .dash-pane:hover .dash-acts,.dash-pane:hover .dash-tadd{opacity:.45}
  .dash-tools:hover .dash-acts,.dash-tools:hover .dash-tadd,.dash-tools:focus-within .dash-acts,.dash-tools:focus-within .dash-tadd{opacity:1}
}
.dash-tools .dash-more{display:none}
/* развёрнутая панель: акцентная черта под шапкой */
.dash-pane.max>.dash-tools{box-shadow:inset 0 -2px 0 var(--acc)}
/* узкая панель и тач: действия под «⋯», выпадают столбиком */
@container (max-width:300px){
  .dash-tools .dash-more{display:block}
  .dash-tools select.dash-pick{min-width:4em}
  .dash-acts{display:none;position:absolute;right:2px;top:100%;z-index:6;flex-direction:column;gap:2px;padding:3px;
    background:var(--panel2);border:1px solid var(--line);border-radius:3px;box-shadow:0 4px 14px rgba(0,0,0,.35)}
  .dash-tools.acts .dash-acts{display:flex}
  .dash-acts button{padding:6px 12px}
}
@media (hover:none){
  .dash-tools .dash-more{display:block}
  .dash-acts{display:none;position:absolute;right:2px;top:100%;z-index:6;flex-direction:column;gap:2px;padding:3px;opacity:1;
    background:var(--panel2);border:1px solid var(--line);border-radius:3px;box-shadow:0 4px 14px rgba(0,0,0,.35)}
  .dash-tools.acts .dash-acts{display:flex}
  .dash-acts button{padding:8px 14px}
}
@media (pointer:coarse){
  .dash-tools{min-height:34px}
  .dash-tools button{font-size:14px;padding:0 11px}
  .dash-tools .dash-tab{font-size:12px;padding:0 11px}
  .dash-tools select.dash-pick{font-size:12px}
}
/* страницы тайлов — рядом с ▦, только в режиме тайлов */
/* страницы — одна сегментированная группа, активная залита акцентом (#bar button.on) */
#dashPages{display:none;gap:0;align-items:center}
#dashPages.on{display:flex;flex:0 0 auto}
#bar #dashPages .dpg{padding:5px 8px;min-width:28px;font:12px var(--mono);border-radius:0;margin-left:-1px}
#bar #dashPages .dpg:first-child{border-radius:3px 0 0 3px;margin-left:0}
#bar #dashPages .dpg:last-child{border-radius:0 3px 3px 0}
#bar #dashPages .dpg:only-child{border-radius:3px}
#bar #dashPages .dpg.add{color:var(--dim)}
.dash-menu{position:fixed;z-index:30;display:flex;flex-direction:column;min-width:150px;padding:4px;
  background:var(--panel2);border:1px solid var(--line);border-radius:6px;box-shadow:0 6px 24px rgba(0,0,0,.4)}
.dash-menu button{background:none;border:0;color:var(--txt);text-align:left;padding:7px 10px;border-radius:4px;cursor:pointer;font-size:13px}
.dash-menu button:hover:not(:disabled){background:var(--panel);color:var(--acc)}
.dash-menu button:disabled{color:var(--dim);opacity:.5;cursor:default}
@media (pointer:coarse){
  .dash-menu button{padding:11px 12px;font-size:14px}
  #bar #dashPages .dpg{padding:8px 11px}
}
/* ⛶ — в панели только основная канва узла, без заголовка и контролов */
.dash-tools .dash-bare{opacity:.75}
.dash-tools .dash-bare:hover,.dash-tools .dash-bare.on{opacity:1}
.dash-pane.bare .node,.dash-pane.bare .nbody,.dash-pane.bare .dash-body{background:none;border-radius:0}
.dash-pane.bare canvas.view{margin:0;border-radius:0}
.dash-pane.bare :focus,.dash-pane.bare :focus-visible{outline:none}
.dash-pane.bare>.dash-rail{display:none!important}
.dash-pane.bare.scroll>.dash-body{padding-right:0}
.dash-pane.bare .node .io3>.mid{padding:0}
.dash-pane.bare .node .io3>.mid>:not(canvas.view.main):not(.tbl-ui):not(.chat):not(.sa-ov):not(.geo-ov):not(.vp){display:none!important}
.dash-body .vp-stage{flex:1 1 0;aspect-ratio:auto;min-height:0}
.dash-pane.bare .vp-src{display:none}
.dash-pane.bare .tbl-ui>:not(.tbl-list){display:none!important}
.dash-pane.bare .dash-body{overflow:hidden}
.dash-body{flex:1 1 auto;min-height:0;overflow:auto}
/* в тайлах заголовок узла не нужен: имя уже в селекте панели, кнопки заголовка тут бессмысленны */
.dash-body .node>.nhead{display:none}
.dash-body .node.folded .nbody{display:block}
/* тач: нативный скроллбар на мобилке не тащится, а свайп съедают слайдеры/канвы — своя широкая полоса */
.dash-rail{display:none;position:absolute;right:0;bottom:0;width:22px;z-index:2;
  background:var(--panel2);border-left:1px solid var(--line);touch-action:none}
.dash-rail>i{position:absolute;left:3px;right:3px;min-height:36px;border-radius:8px;background:var(--line)}
.dash-rail.active>i{background:var(--acc)}
@media (pointer:coarse){
  .dash-pane.scroll>.dash-rail{display:block}
  .dash-pane.scroll>.dash-body{padding-right:22px;scrollbar-width:none}
  .dash-pane.scroll>.dash-body::-webkit-scrollbar{display:none}
}
.dash-body .node{position:static!important;width:100%!important;height:100%!important;
  max-width:none!important;box-shadow:none;transform:none!important}
.dash-body .node .io3>.col{display:none}
.dash-body .node .rz{display:none}
.dash-body .node.sel{box-shadow:none}
/* в панели: контролы переносятся по ширине (сколько колонок влезет), крупные блоки — на всю
   ширину; высоту основной канвы/списка до низа панели выставляет dashFit() (core-graph.js) */
.dash-body .node .io3>.mid,.dash-body .node .io3>.mid>.advWrap:not([hidden]){display:flex;flex-wrap:wrap;
  align-content:flex-start;gap:10px 16px}
.dash-body .node .io3>.mid>*,.dash-body .node .io3>.mid>.advWrap>*{flex:1 1 100%;min-width:0}
.dash-body .node .io3>.mid>.prm:not(.advToggle),.dash-body .node .io3>.mid>.advWrap>.prm{flex:1 1 240px}
.dash-empty{display:flex;align-items:center;justify-content:center;
  width:100%;height:100%;padding:10px;box-sizing:border-box;color:var(--dim);font-size:12px;text-align:center}
#scrim{display:none;position:fixed;inset:0;background:var(--scrim);z-index:9}
#toast{position:fixed;top:14px;left:50%;transform:translate(-50%,-8px);z-index:20;
  background:var(--panel2);border:1px solid var(--acc);color:var(--txt);
  padding:6px 14px;border-radius:6px;font-size:12px;white-space:nowrap;
  opacity:0;pointer-events:none;transition:opacity .15s ease,transform .15s ease}
#updBar{position:fixed;left:50%;bottom:14px;transform:translateX(-50%);z-index:90;display:flex;align-items:center;gap:10px;max-width:92vw;padding:8px 12px;background:var(--panel2);color:var(--txt);border:1px solid var(--acc);border-radius:6px;font:13px system-ui,sans-serif;box-shadow:0 2px 10px #0006}
#updBar button{background:var(--acc);color:var(--bg);border:0;border-radius:3px;padding:4px 10px;font:inherit;cursor:pointer}
#updBar i{font-style:normal;cursor:pointer;color:var(--dim);padding:0 2px}
#toast.show{opacity:1;transform:translate(-50%,0)}

@media (max-width:820px), (pointer:coarse){
  :root{--pin:17px}
  #menu{display:inline-block}
  #side{position:fixed;left:0;right:0;top:auto;bottom:0;z-index:10;width:auto;max-width:none;
    height:70vh;max-height:70vh;border-right:0;border-top:1px solid var(--line);
    border-radius:14px 14px 0 0;transform:translateY(102%);transition:transform .18s ease}
  #side.open{transform:none}
  #side.collapsed{display:flex}                       /* на телефоне сайдбар — выезжающая шторка, не сворачиваем */
  #side::before{content:'';display:block;flex:0 0 auto;width:36px;height:4px;border-radius:2px;
    background:var(--line);margin:8px auto 2px}
  #scrim.open{display:block}
  #main{flex-direction:column}
  /* внизу — зазор под жест «домой»: статус лежит в нём (fixed), чтобы свайп по панели не сворачивал приложение */
  #bar{order:2;flex-wrap:nowrap;overflow-x:auto;gap:5px;padding:7px;padding-bottom:calc(26px + env(safe-area-inset-bottom));
    scrollbar-width:none;border-bottom:0;border-top:1px solid var(--line)}
  #canvas{order:1}
  #bar::-webkit-scrollbar{display:none}
  #bar button{flex:0 0 auto;padding:8px 11px}
  #bar .sp{display:none}
  #stat{position:fixed;left:0;right:0;bottom:env(safe-area-inset-bottom);height:20px;line-height:20px;padding:0 24px;
    text-align:center;font-size:10px;z-index:1;pointer-events:none;flex:none}
  .pitem{padding:8px 12px 8px 20px}
  /* на тач-устройствах hover недоступен — держим крестик крупнее и заметным всегда */
  .pitem .pins,.pitem .pdel,.pitem .pstar{display:block;position:static;transform:none;margin-left:2px;padding:6px 10px;font-size:14px;background:none}
  #patchList .pitem:hover .ptxt{padding-right:0}
  .prm{flex-wrap:wrap;gap:2px}
  .prm label{flex:1 0 100%;font-size:10px}
  .prm input[type=range]{height:40px;flex:1 1 60%}
  .prm .val{flex:0 0 52px;padding:3px 0}
  .prm input[type=checkbox]{width:19px;height:19px}
  .prm input[type=checkbox]:checked::after{left:5px;top:2px;width:5px;height:10px}
  .slidernum{height:34px}
  .slidernum input[type=number]{font-size:14px}
  .nhead{padding:8px}
  .nhead .x{padding:0 6px;font-size:14px}
  .nhead .ren,.nhead .rst,.nhead .xpd,.nhead .hlp{padding:0 6px;font-size:13px}
  .rz-r,.rz-l{width:14px}
  .rz-r{right:-10px}
  .rz-l{left:-10px}
  .rz-b{height:14px;bottom:-10px}
  .rz-br,.rz-bl{width:24px;height:24px;bottom:-10px}
  .rz-br{right:-10px}
  .rz-bl{left:-10px}
}
/* ---- мобильный UX: карточки не выходят за ширину экрана ---- */
@media (max-width:600px){
  #canvas #content .node{min-width:0}
  #canvas #content .node .mid{padding-left:7px;padding-right:7px}
}
#canvas.grab{cursor:grabbing}
#content{position:absolute;left:0;top:0;transform-origin:0 0}
#wires{position:absolute;left:-8000px;top:-8000px;width:16000px;height:16000px;overflow:visible;pointer-events:none}
#wires path{pointer-events:stroke}
/* провода притушены в состоянии покоя — плотный граф не превращается в сплошной цветной тангл;
   при наведении (.hv) провод становится ярче и толще.
   hit-путь тоже сюда попадает, но у него stroke:transparent — opacity на нём не видна */
#wires path{opacity:.55;transition:opacity .12s}
#wires path.hv{opacity:1;stroke-width:2.6}
#wires path.hl{opacity:1;stroke-width:2.2}
#wires.hasSel path:not(.hl):not(.hv):not(.whit){opacity:.3}
@media (pointer:coarse){ #wires path.whit{stroke-width:20px} }   /* палец шире курсора */
/* свободный пин притушен; концы наведённого провода — в кольце */
.port:not(.wired) .pin{opacity:.7}
.port.lit .pin,.port:hover .pin{opacity:1}
.port.hot .pin{box-shadow:0 0 0 3px var(--acc)}
/* длинные колонки пинов: свёрнутые лишние (подключённые видны) и кнопка «+N» */
.col.collapsed:not(.open) .port.extra:not(.wired){display:none}
.pmore{position:relative;height:var(--pin);width:var(--pov);flex:none;pointer-events:auto;cursor:pointer}
.pmore span{position:absolute;top:50%;transform:translateY(-50%);min-width:var(--pin);height:var(--pin);box-sizing:border-box;
  padding:0 6px;display:flex;align-items:center;justify-content:center;border-radius:999px;font-size:9px;font-weight:600;
  background:var(--panel2);color:var(--dim);white-space:nowrap}
.col:not(.o) .pmore span{right:0}
.col.o .pmore span{left:0}

/* ---- узел ---- */
.node{position:absolute;left:0;top:0;width:212px;background:var(--panel);
  border-radius:3px;user-select:none;isolation:isolate;box-shadow:0 0 0 1px var(--line),0 2px 8px #0006}
/* ---- карточная вёрстка узлов ----
   Порты выведены из потока (position:absolute) и не отжимают контент —
   .mid занимает всю высоту от заголовка до низа, точки просто плавают поверх. */
  #canvas #content .node .io3{position:relative;container:nio/inline-size}
  #canvas #content .node .io3>.col{
    position:absolute;top:10px;bottom:10px;left:0;width:var(--pov);
    max-width:none;min-height:0;flex-direction:column;justify-content:flex-start;
    gap:10px;padding:0;background:none;border:0;overflow:visible;pointer-events:none;z-index:3}   /* выше .rz: пин важнее ресайза */
  #canvas #content .node .io3>.col.o{
    left:auto;right:0;justify-content:flex-start}
  /* колонки по ширине узла: 2 на узком, до 4 на широком (см. @container nio ниже) */
  #canvas #content .node .io3>.mid{display:grid;
    grid-template-columns:repeat(2,minmax(0,1fr));gap:11px 10px;padding:10px 14px}
  #canvas #content .node .io3>.mid>.prm.wide,
  #canvas #content .node .io3>.mid>canvas.view,
  #canvas #content .node .io3>.mid>.readout,
  #canvas #content .node .io3>.mid>.copy,
  #canvas #content .node .io3>.mid>.swatch,
  #canvas #content .node .io3>.mid>.graphview,
  #canvas #content .node .io3>.mid>.chat,
  #canvas #content .node .io3>.mid>.wa,
  #canvas #content .node .io3>.mid>.vp,
  #canvas #content .node .io3>.mid>.pl,
  #canvas #content .node .io3>.mid>.ml,
  #canvas #content .node .io3>.mid>.eq10,
  #canvas #content .node .io3>.mid>.rds-ui,
  #canvas #content .node .io3>.mid>.ng,
  #canvas #content .node .io3>.mid>.fm,
  #canvas #content .node .io3>.mid>.rtc-media,
  #canvas #content .node .io3>.mid>.advWrap{grid-column:1/-1}
  #canvas #content .node .io3>.mid>.advWrap:not([hidden]){
    display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:11px 10px}
  #canvas #content .node .io3>.mid>.advWrap>.prm.wide{grid-column:1/-1}
  /* свёрнутый advanced — обычная ячейка, а не отдельная строка */
  #canvas #content .node .io3>.mid>.prm.wide.advToggle{grid-column:auto;align-self:center}
  /* на широком узле ряды галочек/ручек занимают 2 ячейки, кнопки — одну, а не всю строку */
  @container nio (min-width:480px){
    #canvas #content .node .io3>.mid,#canvas #content .node .io3>.mid>.advWrap:not([hidden]){
      grid-template-columns:repeat(3,minmax(0,1fr))}
  }
  @container nio (min-width:640px){
    #canvas #content .node .io3>.mid,#canvas #content .node .io3>.mid>.advWrap:not([hidden]){
      grid-template-columns:repeat(4,minmax(0,1fr))}
    #canvas #content .node .io3>.mid>.prm.wide:is(.checkrow,.knobrow),
    #canvas #content .node .io3>.mid>.advWrap>.prm.wide:is(.checkrow,.knobrow){grid-column:span 2}
    #canvas #content .node .io3>.mid>.prm.wide.btnrow{grid-column:auto;align-self:start}
  }
  #canvas #content .node .io3>.mid>.prm{min-width:0}
  #canvas #content .node .io3>.mid>.prm:not(.prmrows) label{flex-basis:46px}
  /* В спектроанализаторе чекбоксы занимают свободную ячейку
     напротив «доли спектра», а не переносятся на следующую строку. */
  #canvas #content .node[data-type="sa"] .io3>.mid>.prm.wide.checkrow{
    grid-column:auto}
  /* В «Микрофоне» выбор устройства и соответствующая кнопка стоят парой. */
  #canvas #content .node[data-type="mic"] .io3>.mid>.prm.mic-button{
    grid-column:auto}
.node.sel{box-shadow:0 0 0 1px var(--acc)}
.node.note{background:var(--note-bg)}
.node.note .nhead{background:var(--note-bg)}
#sel{position:absolute;border:1px solid var(--acc);background:#e0b23c18;pointer-events:none;display:none}
.nhead{display:flex;align-items:center;gap:6px;padding:5px 7px;cursor:move;user-select:none;-webkit-user-select:none;
  background:var(--panel);border-radius:3px 3px 0 0;box-shadow:inset 0 2px 0 var(--cat,var(--dim))}
.nhead .ttl{flex:1;font-size:11px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.nhead .x,.nhead .ren,.nhead .rst,.nhead .xpd,.nhead .hlp{cursor:pointer;color:var(--dim);padding:0 2px}
.nhead .ren,.nhead .rst,.nhead .xpd,.nhead .hlp{font-size:10px;opacity:.5}
@media (hover:hover){   /* кнопки шапки — только у наведённого/выделенного узла; на тач-экране остаются */
  #content .node:not(:hover):not(.sel) .nhead :is(.x,.ren,.rst,.xpd,.hlp){visibility:hidden}
}
.nhead .ren:hover,.nhead .rst:hover,.nhead .xpd:hover,.nhead .hlp:hover{color:var(--acc);opacity:1}
.nhead .x:hover{color:#e05c5c}
.nbody{padding:0}
.io{display:flex;justify-content:space-between;gap:8px}
.io3{display:flex;gap:0;align-items:stretch;margin:0}
.io3 .col:empty{display:none}
.mid{flex:1;min-width:0;padding:9px 13px 10px}
.node.folded .nbody{display:none}
.node.folded{width:auto!important;min-width:150px}
.node.folded .nhead{border-bottom:0;border-radius:3px}
.node.folded .rz{display:none}
/* точка: кружок с инициалами; полное имя — при наведении / выделении */
#content .node.lod-dot{width:34px!important;height:34px!important;min-width:0;border-radius:50%;
  box-shadow:0 0 0 2px var(--cat,var(--dim)),0 2px 8px #0006}
#content .node.lod-dot .nbody,#content .node.lod-dot .nhead .x,#content .node.lod-dot .nhead .ren,#content .node.lod-dot .nhead .rst,#content .node.lod-dot .rz{display:none}
#content .node.lod-dot .nhead{height:100%;padding:0;border-radius:50%;box-shadow:none;justify-content:center}
#content .node.lod-dot .nhead .ttl{flex:none;font-size:0}
#content .node.lod-dot .nhead .ttl::before{content:attr(data-ini);font-size:11px;font-weight:600}
#content .node.lod-dot::after{content:attr(data-title);position:absolute;top:100%;left:50%;transform:translateX(-50%);
  margin-top:3px;font-size:10px;white-space:nowrap;color:var(--dim);background:var(--panel);padding:1px 5px;border-radius:3px;
  pointer-events:none;opacity:0}
@media (pointer:coarse){ #content .node.lod-dot{width:44px!important;height:44px!important} }
#content .node.lod-dot.sel{box-shadow:0 0 0 2px var(--acc)}
#content .node.lod-dot:hover::after,#content .node.lod-dot.sel::after{opacity:1}
.seg{display:flex;gap:3px;flex:1;min-width:0}
.seg button{flex:1;min-width:0;padding:3px 0;background:var(--bg);border:1px solid var(--line);
  border-radius:3px;cursor:pointer;font-size:10px;color:var(--dim)}
.seg button.on{background:var(--acc);border-color:var(--acc);color:#111;font-weight:600}
.seg button:hover{border-color:var(--acc)}
.col{display:flex;flex-direction:column;gap:10px;min-width:0}
.col.o{align-items:stretch}
.port{position:relative;height:var(--pin);width:var(--pov);cursor:crosshair;
  pointer-events:auto;flex:none}
.port .pin{position:absolute;top:50%;transform:translateY(-50%);
  min-width:var(--pin);height:var(--pin);box-sizing:border-box;padding:0 6px;
  display:flex;align-items:center;justify-content:center;border-radius:999px;flex:none;
  font-size:9px;font-weight:600;color:#111;white-space:nowrap}
/* тап-зона шире видимой точки (на мобильном пин мал для пальца) */
.port .pin::before{content:'';position:absolute;inset:-6px}
.col:not(.o) .port .pin{right:0}   /* контейнер сам шириной --pov у края узла — точка просто у его дальней стороны */
.col.o .port .pin{left:0}
.port:hover .pin{box-shadow:0 0 0 1px var(--acc)}
.port.lit .pin{box-shadow:0 0 0 3px var(--acc)}
.prm input[type=range]{flex:1;min-width:0;height:32px;accent-color:var(--acc);background:none;
  cursor:pointer;touch-action:none}
.prm input[type=range]::-webkit-slider-runnable-track{height:5px;background:var(--line);border-radius:3px}
.prm input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;width:20px;height:20px;
  margin-top:-7.5px;border:2px solid var(--acc);border-radius:50%;background:var(--panel2)}
.prm input[type=range]::-moz-range-track{height:5px;background:var(--line);border-radius:3px}
.prm input[type=range]::-moz-range-progress{height:5px;background:var(--acc);border-radius:3px}
.prm input[type=range]::-moz-range-thumb{width:16px;height:16px;border:2px solid var(--acc);
  border-radius:50%;background:var(--panel2)}
.prm textarea{width:100%;min-height:120px;resize:vertical;background:var(--bg);
  border:1px solid transparent;border-radius:3px;padding:4px 5px;font:11px/1.45 var(--mono);
  color:var(--txt);white-space:pre;overflow:auto}
.prm textarea:focus{outline:none;border-color:var(--acc)}
.prm .code{position:relative;display:flex;width:100%}
.prm .code pre{position:absolute;inset:0;margin:0;padding:4px 5px;border:1px solid transparent;border-radius:3px;
  background:var(--bg);font:11px/1.45 var(--mono);color:var(--txt);white-space:pre;overflow:hidden;pointer-events:none}
.prm .code pre code{font:inherit}
.prm .code pre+textarea{position:relative;background:transparent;color:transparent;caret-color:var(--txt)}
.prm .code pre+textarea::selection{background:#4a6a9a88;color:transparent}
.hl-c{color:#6c7a80}.hl-s{color:#7fd17f}.hl-n{color:#e0875f}.hl-k{color:#c586c0}
.prm select,.prm input[type=number],.prm input[type=text]{height:26px;line-height:20px}
.prm input[type=number]{flex:0 1 92px;min-width:92px;width:92px;
  font-variant-numeric:tabular-nums}
.prm input[type=number]:focus{outline:none;border-color:var(--acc)}
.prm .val{flex:0 0 44px;text-align:right;font-size:10px;color:var(--txt);cursor:text}
.prm .val:hover{color:var(--hi)}
.prm .val input{width:52px;background:var(--bg);border:1px solid var(--acc);border-radius:3px;
  padding:1px 3px;text-align:right;font-size:10px;color:var(--hi)}
/* Material-подобная подпись: label лежит прямо на верхней границе поля. */
.prm{display:flex;flex-direction:column;align-items:stretch;gap:0;margin-top:2px;padding-top:3px;
  position:relative;align-self:start}
/* единая линия-подложка под label для всех типов полей, не только текстовых */
.prm:not(.wide){min-height:26px;border-bottom:1px solid var(--line)}
.prm:not(.wide):has(>input[type=checkbox]){border-bottom:0}   /* галочкам подчёркивание ни к чему */
.prm:not(.wide):has(.slidernum){border-bottom:0}
.prm:not(.wide):has(>input[type=number]){border-bottom:0}
.prm:not(.wide):has(>select){border-bottom:0}
  /* у числовых полей вместо подчёркивания — заливка на самом поле */
.prm:focus-within:not(.wide){border-bottom-color:var(--acc)}
.prm label{display:block;flex:none;min-height:0;width:max-content;max-width:calc(100% - 8px);
  position:absolute;left:0;top:-.9em;padding:0;margin:0;
  background:none;color:var(--dim);font-size:9px;line-height:1.1;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.prm input[type=text]{
  width:100%;min-width:0;height:26px;flex:1 1 auto;border:0;
  border-radius:0;padding:2px 0;background:transparent}
.prm select,.prm input[type=number]{width:100%;min-width:0;height:26px;flex:1 1 auto;border:0;
  border-radius:3px;padding:2px 6px;background:var(--bg)}
.slidernum{position:relative;width:100%;height:26px;display:flex;align-items:center;
  overflow:hidden;cursor:ew-resize;user-select:none;touch-action:none;
  background:var(--bg);border-radius:3px;padding:2px 6px}
.slidernum .sn-fill{position:absolute;left:0;top:0;bottom:0;background:var(--acc);
  opacity:.16;pointer-events:none}
.slidernum:hover .sn-fill{opacity:.26}
.slidernum .sn-val{position:relative;z-index:1;font-variant-numeric:tabular-nums;
  pointer-events:none;white-space:nowrap}
.slidernum input[type=number]{position:absolute;inset:0;z-index:2;width:100%;height:100%;
  border:0;border-radius:3px;background:var(--bg);padding:2px 6px;cursor:text}
.range2{display:flex;align-items:center;gap:4px;width:100%}
.range2 .slidernum{width:auto;flex:1;min-width:0}
.range2 .r2dash{flex:none;color:var(--dim);font-size:11px}
.prm select:focus,.prm input[type=number]:focus,.prm input[type=text]:focus{
  outline:none;box-shadow:none}
/* чекбокс — не отдельное плавающее поле, а строка «галочка + подпись» */
.prm:has(>input[type=checkbox]){flex-direction:row;align-items:center;gap:6px;
  min-height:29px}
.prm:has(>input[type=checkbox]) label{position:static;order:2;top:auto;left:auto;
  max-width:none;color:var(--txt);font-size:10px}
.prm input[type=checkbox]{appearance:none;-webkit-appearance:none;order:1;flex:none;
  width:15px;height:15px;margin:0;border:1px solid var(--line);border-radius:3px;
  background:var(--bg);cursor:pointer;position:relative}
.prm input[type=checkbox]:hover{border-color:var(--acc)}
.prm input[type=checkbox]:checked{background:var(--acc);border-color:var(--acc)}
.prm input[type=checkbox]:checked::after{content:'';position:absolute;left:4px;top:1px;
  width:4px;height:8px;border:solid #111;border-width:0 2px 2px 0;transform:rotate(45deg)}
.prm input[type=checkbox]:focus-visible{outline:none;border-color:var(--acc)}
/* общий ряд для всех галочек узла — не растягиваются на всю колонку, идут подряд и переносятся при нехватке места */
.prm.wide.checkrow{display:flex;flex-direction:row;flex-wrap:wrap;align-items:center;
  justify-content:flex-start;column-gap:18px;row-gap:8px}
.checkrow>.prm{width:auto;flex:0 0 auto;min-height:0;padding-top:0;margin-top:0;align-self:auto}
/* поле перебито проводом на одноимённый вход — гасим и блокируем, крутить его сейчас бессмысленно */
.prm.linked label,.prm.linked .slidernum,.prm.linked select,.prm.linked input,.prm.linked .seg{opacity:.45}
.prm.linked:not(.wide){border-bottom-color:var(--acc2)}
.prm.linked .slidernum,.prm.linked select,.prm.linked input,.prm.linked .seg{pointer-events:none}
.slidernum.linked .sn-fill,.slidernum.linked .sn-val{opacity:.45}
.slidernum.linked{pointer-events:none}
.prm.wide{display:block}
/* Пин контрола (число/галочка без явного ins/outs в модуле) — тот же .port, что и у обычных
   пинов, в той же колонке (слева вход, справа выход — провод всегда в привычном месте), просто
   схлопнут в 0, пока ничего не подключено, чтобы не есть место у свободных параметров. */
.port.ctrl:not(.wired){display:none}
.prm.wide label{margin-bottom:.5em}
.checkrow>.prm label{margin-bottom:0}
.node .io3>.mid{row-gap:11px}
.prm button{width:100%;background:var(--panel2);border:1px solid var(--line);padding:4px;
  border-radius:3px;cursor:pointer}
.prm button:hover{border-color:var(--acc)}
.btnrow{display:flex;gap:6px}
/* кнопки — тот же отступ сверху, что у ламп/холстов/readout (5px) */
.prm.wide.btnrow{margin-top:5px;padding-top:0}
.btnrow button{flex:1 1 0;width:auto;min-width:0;white-space:normal;
  font-size:10px;line-height:1.25}
/* ряд ручек (range с knob:true): подпись под ручкой, число внутри */
.prm.wide.knobrow{display:flex;flex-direction:row;flex-wrap:wrap;gap:6px 10px;align-items:flex-start}
.knobrow>.prm.kn{flex:0 0 52px;width:52px;min-height:0;margin:0;padding:0;align-items:center;gap:1px}
.knobrow>.prm.kn label{position:static;order:2;width:100%;max-width:none;margin:0;text-align:center;
  white-space:normal;line-height:1.15;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}
.slidernum.kn{width:44px;height:44px;padding:0;background:none;border-radius:50%;cursor:ns-resize;
  justify-content:center;overflow:visible}
.slidernum.kn .sn-fill{display:none}
.slidernum.kn .kn-svg{position:absolute;inset:0;width:100%;height:100%;pointer-events:none}
.slidernum.kn .kn-track,.slidernum.kn .kn-val{fill:none;stroke-width:4;stroke-linecap:round}
.slidernum.kn .kn-track{stroke:var(--line)}
.slidernum.kn .kn-val{stroke:var(--acc)}
.slidernum.kn:hover .kn-track{stroke:var(--dim)}
.slidernum.kn .sn-val{font-size:9px}
.slidernum.kn input[type=number]{inset:12px -10px auto;width:auto;height:20px;font-size:10px;
  padding:0 3px;text-align:center;border:1px solid var(--acc)}
.prm.linked .slidernum.kn{opacity:.45}
/* строки «подпись — значение» (renderParamRows): подпись слева, значение справа, у чисел — заливка
   положения во всю строку; сетка до 4 колонок, каждая не уже 140px */
.prm.wide.prmrows{display:grid;grid-template-columns:repeat(auto-fill,minmax(max(140px,calc((100% - 36px)/4)),1fr));
  gap:2px 12px}
.prmrows>.prm.pr{position:relative;display:flex;flex-direction:row;align-items:center;gap:6px;height:22px;
  min-height:0;margin:0;padding:0 6px;border:0;border-radius:3px;background:var(--bg);overflow:hidden}
.prmrows>.prm.pr:hover{box-shadow:inset 0 0 0 1px var(--line)}
.prmrows>.prm.pr label{position:relative;z-index:1;order:0;top:auto;left:auto;flex:1 1 auto;min-width:0;
  width:auto;max-width:none;margin:0;color:var(--dim);font-size:10px;line-height:1;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;pointer-events:none}
/* число: вся строка — slidernum (тащить/колесо/клик — ввод) */
.prmrows>.prm.pr-range{padding:0}
.prmrows>.pr-range .slidernum{height:22px;padding:0 6px;gap:6px;background:none;border-radius:3px}
.prmrows>.pr :is(label){flex:0 1 auto}
.prmrows>.pr-range .sn-val{flex:none;margin-left:auto;font-size:11px;color:var(--txt)}
.prmrows>.pr-select label{max-width:55%}              /* значение select лежит поверх правых 45% */
.prmrows>.pr-range .slidernum input[type=number]{text-align:right;font-size:11px}
/* выбор: прозрачный select на всю строку, значение справа */
.prmrows>.pr-select select{position:absolute;inset:0;width:100%;height:100%;margin:0;padding:0 16px 0 55%;
  appearance:none;-webkit-appearance:none;background:none;border:0;border-radius:3px;cursor:pointer;
  color:var(--txt);font-size:11px;text-align:right;text-align-last:right;text-overflow:ellipsis}
.prmrows>.pr-select select option{background:var(--panel);text-align:left}
.prmrows>.pr-select::after{content:'▾';position:absolute;right:6px;font-size:9px;color:var(--dim);pointer-events:none}
/* галочка: прозрачный чекбокс на всю строку, справа — on/off и точка у края (как ▾ у select) */
.prmrows>.pr-check input[type=checkbox]{position:absolute;inset:0;width:100%;height:100%;margin:0;
  border:0;border-radius:3px;background:none;opacity:0;cursor:pointer}
.prmrows>.pr-check label{color:var(--dim)}
.prmrows>.pr-check::after{content:'off';flex:none;margin-left:auto;font-size:11px;color:var(--dim);pointer-events:none}
.prmrows>.pr-check::before{content:'';order:3;flex:none;width:7px;height:7px;border-radius:50%;
  background:var(--line);pointer-events:none}
.prmrows>.pr-check:has(>input:checked)::after{content:'on';color:var(--acc)}
.prmrows>.pr-check:has(>input:checked)::before{background:var(--acc);box-shadow:0 0 4px var(--acc)}
/* диапазон: подпись, справа «от — до» — две половинки-slidernum со своей заливкой */
.prmrows>.prm.pr-range2{padding:0 2px 0 6px}
.prmrows>.pr-range2 .range2{flex:0 1 auto;width:auto;min-width:0;margin-left:auto;height:22px;gap:0}
.prmrows>.pr-range2 .range2 .slidernum{flex:0 1 90px;width:auto;min-width:40px;height:18px;padding:0 6px;
  background:var(--panel2);border-radius:3px;justify-content:flex-end;box-shadow:inset 0 0 0 1px var(--line)}
.prmrows>.pr-range2 .range2 .slidernum:hover{box-shadow:inset 0 0 0 1px var(--acc)}
.prmrows>.pr-range2 .sn-val{font-size:11px;color:var(--txt)}
.prmrows>.pr-range2 .slidernum input[type=number]{text-align:right;font-size:11px}
.prmrows>.pr-range2 .r2dash{padding:0 2px;font-size:10px}
/* при 2+ колонках, пока ячейки уже ~220px, длинной строке (подпись + значение, см. pr-long) — 2 ячейки */
@container nio (min-width:320px) and (max-width:943px){ .prmrows>.pr-long{grid-column:span 2} }
/* единица (хвост подписи «…, Hz») — тусклым текстом после значения */
.prmrows .pr-unit{position:relative;z-index:1;flex:none;margin-left:-3px;font-size:10px;color:var(--dim);pointer-events:none}
/* выбор из двух переключается кликом */
.prmrows>.pr-select.pr-two::after{content:'⇄'}
/* параметр ведёт провод — бирюзовая полоска слева (вместо одной бледности) */
.prmrows>.prm.pr.linked{box-shadow:inset 3px 0 0 var(--acc2)}
.prmrows>.pr-range2 .slidernum.linked{box-shadow:inset 0 0 0 1px var(--acc2)}
/* поля ввода — справа, без рамки */
.prmrows>:is(.pr-num,.pr-text) input{flex:1 1 50%;width:auto;min-width:0;height:20px;padding:0;border:0;
  background:none;text-align:right;font-size:11px;color:var(--txt)}
.prm.wide.pr-btns{display:flex;flex-direction:row;flex-wrap:wrap;gap:3px}
.pr-btns button{flex:1 1 auto;width:auto;min-width:0;height:22px;padding:0 8px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* строки идут плотнее обычных полей (у тех подпись висит над полем) */
#canvas #content .node .io3>.mid>:is(.pr-btns,.prmrows)+:is(.pr-btns,.prmrows,.advToggle){margin-top:-6px}
@media (pointer:coarse){
  .prmrows>.prm.pr,.prmrows>.pr-range .slidernum,.pr-btns button{height:32px}
}
.advToggle{white-space:nowrap;cursor:pointer;color:var(--dim);font-size:10px;user-select:none;margin-top:2px}
.advToggle:hover{color:var(--txt)}
.advWrap{row-gap:11px}
/* группы параметров (renderParamGroups): сворачиваемая секция с заголовком */
.prm.wide.pgrp{display:block;padding:0;margin:0;background:none;border:0;min-width:0}
.pgh{display:flex;align-items:center;gap:6px;min-height:18px;padding:2px 0;cursor:pointer;user-select:none;
  font-size:10px;letter-spacing:.05em;text-transform:uppercase;color:var(--dim);border-bottom:1px solid var(--line)}
.pgh:hover{color:var(--txt)}
.pgn{margin-left:auto;font-size:9px;opacity:.7;letter-spacing:0}
.pgb{display:flex;flex-direction:column;gap:3px;padding-top:5px}
.pgb[hidden]{display:none}
.pgb>.prm.wide{margin:0;align-self:stretch}
.pgb>.prm.wide.prmrows{grid-template-columns:repeat(auto-fill,minmax(max(168px,calc((100% - 36px)/4)),1fr))}
.pgrp.closed .pgh{border-bottom-color:transparent}
.dash-body .node .io3>.mid>.prm.wide.pgrp{flex:1 1 100%}
@media (pointer:coarse){ .pgh{min-height:30px} }
/* списки (таблица, закладки, диапазоны): в тайле список идёт первым и занимает всю высоту, настройки — под ним */
.dash-body .node .io3>.mid>:is(.tbl-ui,.bm-ui,.bp-ui){order:-1}
/* режим «только главное» в тайле: остаются строки .pri, группы без них и advanced прячутся */
.dash-pane.compact :is(.advToggle,.advWrap,.pgh,.pr-btns){display:none}
.dash-pane.compact .pgrp:not(:has(.pri)){display:none}
.dash-pane.compact .pgb,.dash-pane.compact .pgb[hidden]{display:flex}
.dash-pane.compact .pgb .prm.pr:not(.pri){display:none}
.dash-pane.compact .pgb{padding-top:0}
.prm input[type=file]{width:100%;font-size:10px;color:var(--dim)}
canvas.view{display:block;width:100%;background:var(--screen);
  border-radius:3px;margin-top:5px;cursor:default}
/* мелкий шрифт и перенос по словам (до 6 строк) — длинные статусы не обрезаются многоточием */
.readout{contain:layout;margin-top:5px;padding:5px 6px;background:var(--screen);
  border-radius:3px;font-size:10px;line-height:1.35;color:var(--screen-fg);text-align:center;overflow:hidden;
  white-space:normal;overflow-wrap:anywhere;max-height:calc(6 * 1.35em + 10px);user-select:text;cursor:pointer}
.readout.copied{outline:1px solid var(--acc)}
/* невидимые зоны ресайза снаружи рамки модуля — порты на краях остаются кликабельными */
.rz{position:absolute;z-index:2;touch-action:none}
.rz-r{right:-6px;top:28px;bottom:10px;width:6px;cursor:ew-resize}
.rz-l{left:-6px;top:28px;bottom:10px;width:6px;cursor:ew-resize}
.rz-b{left:10px;right:10px;bottom:-6px;height:6px;cursor:ns-resize}
.rz-br{right:-6px;bottom:-6px;width:16px;height:16px;cursor:nwse-resize}
.rz-bl{left:-6px;bottom:-6px;width:16px;height:16px;cursor:nesw-resize}
.rz:hover{background:var(--acc);opacity:.6}
canvas.view.pick{cursor:crosshair}
.nhead .fsb{cursor:pointer;color:var(--dim);padding:0 2px;font-size:10px;opacity:.5}
.nhead .fsb:hover{color:var(--acc);opacity:1}
.nhead .pipb{cursor:pointer;color:var(--dim);padding:0 2px;font-size:10px;opacity:.5}
.nhead .pipb:hover{color:var(--acc);opacity:1}
.nhead .wpb{cursor:pointer;color:var(--dim);padding:0 2px;font-size:10px;opacity:.5}
.nhead .wpb:hover{color:var(--acc);opacity:1}
.nhead .flb{cursor:pointer;color:var(--dim);padding:0 2px;font-size:10px;opacity:.5}
.nhead .flb:hover{color:var(--acc);opacity:1}
canvas.view:fullscreen{width:100%!important;height:100%!important;margin:0;border-radius:0;background:#000}
canvas.view.fs-fb{position:fixed!important;inset:0;width:100vw!important;height:100vh!important;z-index:300;margin:0;border-radius:0;background:#000}
.readout.tall{font-size:12px;text-align:left;white-space:pre-wrap;word-break:break-word;
  height:96px;max-height:none;overflow:auto;line-height:1.5;color:var(--txt);resize:vertical}
.copy{width:100%;margin-top:4px;background:var(--panel2);border:1px solid var(--line);
  border-radius:3px;padding:3px;cursor:pointer;color:var(--dim);font-size:10px}
.copy:hover{border-color:var(--acc);color:var(--txt)}
.swatch{margin-top:5px;height:44px;border-radius:3px}
#settings.on{color:var(--acc)}
#setPanel{position:fixed;z-index:60;max-height:calc(100vh - 70px);overflow-y:auto;overscroll-behavior:contain;padding:10px;display:flex;flex-direction:row;gap:0;background:var(--panel);border:1px solid var(--line);border-radius:6px;box-shadow:0 6px 24px rgba(0,0,0,.35);font-size:12px;color:var(--txt)}
#setPanel[hidden]{display:none}
#setTabs{display:flex;flex-direction:column;gap:2px;min-width:96px;border-right:1px solid var(--line);padding-right:8px;margin-right:10px;align-self:flex-start}
#setTabs button{text-align:left;white-space:nowrap;border-color:transparent;background:transparent}
#setTabs button.on{color:var(--acc);border-color:var(--acc)}
#setBody{flex:1;min-width:0;display:flex;flex-direction:column;gap:8px}
#setBody>section{display:flex;flex-direction:column;gap:8px;min-width:280px}
#setBody>section[hidden]{display:none}
#setPanel label{display:flex;align-items:center;justify-content:space-between;gap:10px}
#setPanel label span{color:var(--dim)}
#setPanel button{background:var(--panel2);color:var(--txt);border:1px solid var(--line);border-radius:3px;padding:5px 8px;font:inherit;cursor:pointer}
#setPanel select,#setPanel input{background:var(--panel2);color:var(--txt);border:1px solid var(--line);border-radius:3px;padding:5px 6px;font:inherit;min-width:0}
#setPanel input{flex:1;max-width:190px}
#setPanel select{cursor:pointer}
#setPanel select:focus-visible,#setPanel input:focus{outline:1px solid var(--acc);outline-offset:-1px}
#setPanel p{margin:0;color:var(--dim);font-size:11px;line-height:1.4}
#setPanel code{font:11px var(--mono)}
/* выбор устройства в параметре узла: список из Settings → Devices или свой адрес */
.devpick{display:flex;flex-direction:column;gap:3px;flex:1;min-width:0;align-items:stretch}
/* учётка в узле: список + правка, форма на всю ширину узла (поля крупнее, подписи слева, с отступом от пинов) */
.prm.pr-cred{flex-wrap:wrap}
.prm.pr-cred>.credform{flex:1 0 100%;order:3}
.credpick{display:flex;flex-direction:column;gap:6px;flex:1;min-width:0;align-items:stretch}
.credpick .cr-top{display:flex;gap:6px;align-items:center}
.credpick .cr-top select{flex:1 1 auto;min-width:0;width:auto;height:24px;padding:0 6px;border:0;border-radius:3px;background:var(--panel2);box-shadow:inset 0 0 0 1px var(--line);color:var(--txt);font-size:12px;text-overflow:ellipsis}
.credpick .cr-edit{flex:none;height:24px;padding:0 9px;font-size:13px}
.credform{display:grid;grid-template-columns:max-content minmax(0,1fr);gap:8px 12px;align-items:center;padding:12px 14px;margin:4px 8px 6px;background:var(--panel2);border:1px solid var(--line);border-radius:6px;box-sizing:border-box;min-width:0}
.credform[hidden]{display:none}
.credform label{font-size:11px;color:var(--dim);white-space:normal;overflow:visible;text-overflow:clip;height:auto;width:auto;max-width:none;flex:none}
.credform [hidden]{display:none!important}
.credform input[type=text],.credform select{width:100%;min-width:0;box-sizing:border-box;height:28px;padding:2px 8px;border:0;border-radius:4px;background:var(--panel);box-shadow:inset 0 0 0 1px var(--line);color:var(--txt);font-size:13px}
.credform input:focus,.credform select:focus{outline:none;box-shadow:inset 0 0 0 1px var(--acc)}
.credform input[readonly]{opacity:.65}
.credform .cr-wide{grid-column:1/-1}
.credform .cr-reg{display:flex;gap:8px;align-items:flex-start;line-height:1.4;color:var(--txt);font-size:12px}
.credform .cr-reg span{white-space:normal;min-width:0}
.credform .cr-reg input[type=checkbox]{margin-top:1px;flex:none;order:0;width:16px;height:16px;border:1px solid var(--dim);background:var(--panel)}
.credform .cr-reg input[type=checkbox]:checked{background:var(--acc);border-color:var(--acc)}
.credform .cr-btns{display:flex;gap:8px;justify-content:flex-end}
.credform .cr-btns button{height:28px;padding:0 14px;font-size:12px}
.credform .cr-del{margin-right:auto;color:var(--err,#e05c5c)}
.credform .cr-res{font-size:11px;color:#d9822b;min-height:0}
.credform .cr-res:empty{display:none}
.devpick select,.devpick input{width:100%;min-width:0;box-sizing:border-box;text-overflow:ellipsis}
.devpick input[hidden],.devpick select[hidden]{display:none}
.devpick select.warn{outline:1px solid #d9822b}
/* в строках параметров узла: подпись слева, выбор устройства справа в той же строке; свой адрес — поле рядом, во всю ширину строки */
.prmrows>.prm.pr.pr-dev{grid-column:1/-1;height:auto;min-height:22px;overflow:visible}
.prmrows>.pr-dev .devpick{flex-direction:row;align-items:center;gap:6px}
.prmrows>.pr-dev .devpick select{flex:1 1 auto;width:auto;height:22px;margin:0;padding:0 12px 0 0;border:0;border-radius:3px;background:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='5'%3E%3Cpath d='M0 0h8L4 5z' fill='%23888'/%3E%3C/svg%3E") no-repeat right 1px center;
  appearance:none;-webkit-appearance:none;color:var(--txt);font-size:11px;text-align:right;text-align-last:right;cursor:pointer}
.prmrows>.pr-dev .devpick select option{background:var(--panel);text-align:left}
.prmrows>.pr-dev .devpick select.warn{outline:0;color:#d9822b}
.prmrows>.pr-dev .devpick select:has(~input:not([hidden])){flex:0 1 auto;max-width:45%}
.prmrows>.pr-dev .devpick input{flex:1 1 0;width:auto;height:18px;padding:0 6px;border:0;border-radius:3px;background:var(--panel2);box-shadow:inset 0 0 0 1px var(--line);color:var(--txt);font-size:11px}
.prmrows>.pr-dev .devpick input:only-child{text-align:right}
#gwBox,#crBox{display:flex;flex-direction:column;gap:6px;border-top:1px solid var(--line);padding-top:8px}
#gwBox .gwHead,#crBox .gwHead{display:flex;align-items:center;justify-content:space-between;color:var(--dim)}
#gwBox .gwList,#crBox .crList{display:flex;flex-direction:column;gap:8px}
#gwBox .gwRow,#crBox .gwRow{display:flex;flex-direction:column;gap:4px;padding:6px;border:1px solid var(--line);border-radius:4px}
#gwBox .gwTop,#crBox .gwTop{display:flex;gap:6px}
#gwBox .gwTop input,#crBox .gwTop input{flex:1;max-width:none}
#gwBox .gwTok,#crBox .gwTok{-webkit-text-security:disc;text-security:disc}
#gwBox .gwRow>input,#crBox .gwRow>input{max-width:none;width:100%;box-sizing:border-box}
#gwBox .gwCert summary{cursor:pointer;color:var(--dim)}
#gwBox .gwCert{display:flex;flex-direction:column;gap:6px}
#gwBox .gwCert[open]>*{margin-top:6px}
#gwBox .gwCert input{max-width:none;width:100%;box-sizing:border-box}
#gwBox .gwCert select{max-width:none;width:100%;box-sizing:border-box}
#gwBox .gwCertBtns{display:flex;gap:6px}
#gwBox .gwCertRes{display:flex;flex-direction:column;gap:3px;font-size:11px;word-break:break-word}
#gwBox .gwCertRes a{color:var(--acc)}
#gwBox .gwRes,#crBox .gwRes{font-size:11px;color:var(--dim);min-height:1em;word-break:break-word}


/* ---- аудиоредактор клипов (modules/audioeditor.js) ---- */
.aed{position:fixed;inset:0;z-index:50;display:flex;flex-direction:column;background:var(--bg);
  padding:env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
  user-select:none;-webkit-user-select:none}
.aed-head{display:flex;align-items:center;gap:6px;padding:6px 8px;background:var(--panel);border-bottom:1px solid var(--line)}
.aed-name{flex:1;min-width:60px;background:var(--bg);border:1px solid var(--line);border-radius:3px;padding:6px 8px;outline:none}
.aed-name:focus{border-color:var(--acc)}
.aed-info{color:var(--dim);font-size:11px;white-space:nowrap}
.aed-over{display:block;width:100%;height:34px;flex:none;touch-action:none;cursor:pointer;border-bottom:1px solid var(--line)}
.aed-main{flex:1;min-height:120px;position:relative;overflow:hidden}
.aed-cv{position:absolute;inset:0;width:100%;height:100%;display:block;touch-action:none;cursor:text}
.aed-stat{display:flex;gap:10px;justify-content:space-between;padding:4px 8px;font-size:11px;color:var(--dim);
  background:var(--panel);border-top:1px solid var(--line);white-space:nowrap;overflow:hidden;font-variant-numeric:tabular-nums}
.aed-stat span{overflow:hidden;text-overflow:ellipsis}
.aed-bar{background:var(--panel);border-top:1px solid var(--line);padding:4px 6px 6px}
.aed-row{display:flex;gap:4px;align-items:center;padding:2px 0}
.aed-bar .aed-row{overflow-x:auto;scrollbar-width:thin}
.aed-tr>:first-child{margin-left:auto}
.aed-tr>:last-child{margin-right:auto}   /* центр без обрезки при переполнении */
.aed-sp{flex:1}
.aed-b{flex:none;min-width:38px;height:36px;padding:0 10px;background:var(--panel2);border:1px solid var(--line);
  border-radius:4px;color:var(--txt);cursor:pointer;white-space:nowrap;font-size:12px}
.aed-b:hover:not(:disabled){border-color:var(--acc)}
.aed-b:disabled{opacity:.35;cursor:default}
.aed-b.on{background:var(--acc);border-color:var(--acc);color:#111}
.aed-b.aed-pri{border-color:var(--acc2);color:var(--acc2)}
.aed-play{min-width:52px;font-size:15px}
.aed-sheet{display:none;flex-direction:column;gap:6px;padding:8px;background:var(--panel);border-top:1px solid var(--line)}
.aed-sheet.on{display:flex}
.aed-sheet .aed-row{flex-wrap:wrap}
.aed-nrinfo{color:var(--dim);font-size:11px}
.aed-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(170px,1fr));gap:6px 12px}
.aed-grid label{display:flex;flex-direction:column;gap:2px;font-size:10px;color:var(--dim);position:relative}
.aed-grid label b{position:absolute;right:0;top:0;font-weight:normal;color:var(--txt)}
.aed-grid input[type=range]{width:100%;accent-color:var(--acc);height:26px}
.aed-grid select{height:30px;background:var(--bg);border:1px solid var(--line);border-radius:3px}
.aed-chk{display:flex;align-items:center;gap:6px;font-size:11px}
@media (max-width:600px){
  .aed-info{display:none}
  .aed-b{min-width:42px;height:40px;padding:0 9px}
  .aed-hov{display:none}
}
/* выбор модуля на холсте (двойной клик / «+» панели графа) */
.modpick{position:fixed;z-index:30;display:flex;flex-direction:column;background:var(--panel);
  border:1px solid var(--acc);border-radius:4px;box-shadow:0 6px 24px rgba(0,0,0,.35);overflow:hidden}
.modpick input{flex:none;margin:6px;padding:5px 7px;background:var(--panel2);color:var(--txt);
  border:1px solid var(--line);border-radius:3px;font-size:12px;outline:none}
.modpick input:focus{border-color:var(--acc)}
.modpick .mp-list{flex:1 1 auto;min-height:0;overflow:auto;padding:0 4px 6px}
.modpick .mp-cat{padding:6px 6px 2px;color:var(--dim);font-size:10px;text-transform:uppercase;letter-spacing:.05em}
.modpick .mp-item{display:flex;align-items:center;gap:6px;width:100%;padding:4px 6px;background:none;border:0;
  border-radius:3px;color:var(--txt);font-size:12px;text-align:left;cursor:pointer}
/* пункт в два ряда: имя на всю ширину, ниже — типы портов */
.modpick .mp-item .mp-t{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;gap:1px}
.modpick .mp-item b{font-weight:500;line-height:1.2;white-space:normal;overflow:hidden;overflow-wrap:anywhere;max-height:2.4em}
.modpick .mp-item .mp-sub{display:flex;align-items:center;min-height:11px;line-height:1.1;font-size:9px;overflow:hidden}
.modpick .mp-item .mp-sub .pio{flex-wrap:wrap;gap:1px 6px}
.modpick .mp-item .dot{flex:none;width:7px;height:7px;border-radius:50%}
.modpick .mp-item .pio{flex:none;display:flex;align-items:center;gap:4px;color:var(--dim)}
.modpick .mp-item .pio .grp{display:flex;align-items:center;gap:2px;font-size:8px}
.modpick .mp-item .pio .pin{width:5px;height:5px;border-radius:50%}
.modpick .mp-item .pio .arr{font-style:normal;font-size:9px}
.modpick .mp-item.on,.modpick .mp-item:hover{background:var(--panel2);color:var(--acc)}
@media (pointer:coarse){ .modpick .mp-item{padding:9px 8px;font-size:13px} }

/* ---- трекер (modules/tracker*.js); кнопки/шапка — от редактора семплов (.aed-*) ---- */
.trk{position:fixed;inset:0;z-index:49;display:flex;flex-direction:column;background:var(--bg);
  padding:env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left)}
.trk-top{display:flex;align-items:flex-start;gap:6px;padding:4px 6px 0;background:var(--panel);border-bottom:1px solid var(--line)}
.trk-top>.trk-close{margin-top:2px}
.trk-top>.trk-panel{flex:1;min-width:0}
.trk-head{overflow-x:auto;scrollbar-width:thin}
.trk-head .aed-name{min-width:110px;flex:1}
.trk-center{flex:1;min-width:0;display:flex;flex-direction:column}
.trk-panel{min-width:0;min-height:0;display:flex;flex-direction:column;gap:6px}
.trk-p-pat{flex:1;gap:0}
.trk-p-pat .trk-main{min-height:120px}
.trk-pane>.trk-p-ins{flex:1 1 40%}
.trk-p-seq .trk-ords{flex:1}
.trk-extnote{font-size:11px;color:var(--t-trk);padding:4px 0}
.trk-extnote[hidden]{display:none}
/* узел-тайл: панель на всю высоту узла / тайла дашборда */
.trk-tile{grid-column:1/-1;width:100%;min-width:0;display:flex;flex-direction:column;overflow:auto;
  background:var(--panel);border-radius:3px;font-size:12px}
.trk-tile>.trk-panel{flex:1;padding:4px}
.trk-tile>.trk-p-pat{padding:0}
.trk-tile>.trk-p-bar{gap:0}
.trk-tile .trk-head,.trk-tile .trk-tr{flex-wrap:wrap}
.trk-empty{padding:12px;color:var(--dim);font-size:11px}
.trk-mix{display:flex;gap:4px;overflow-x:auto;height:100%;min-height:150px}
.trk-strip{display:flex;flex-direction:column;align-items:center;gap:4px;width:52px;flex:none;padding:4px 2px;
  background:var(--panel2);border:1px solid var(--line);border-radius:3px}
.trk-strip b{font-size:11px}
.trk-strip .aed-b{min-width:34px;height:26px;padding:0}
.trk-strip input[type=range]{width:46px;accent-color:var(--acc)}
.trk-strip input[data-f=vol]{writing-mode:vertical-lr;direction:rtl;height:70px;width:22px;flex:1}
.trk-vu{display:block;width:8px;height:40px;background:var(--bg);border-radius:2px;position:relative;overflow:hidden}
.trk-vu>i{position:absolute;left:0;right:0;bottom:0;background:var(--acc2)}
.trk-tr{padding:2px 0 4px;overflow-x:auto;scrollbar-width:thin}
.trk-lab{color:var(--dim);font-size:10px;margin-left:6px}
.trk-oct,.trk-step{min-width:18px;text-align:center;font-weight:normal}
.trk-pos{margin-left:auto;padding:0 6px;color:var(--dim);font-size:11px;white-space:nowrap}
.trk-body{flex:1;min-height:0;display:flex}
.trk-main{flex:1;min-width:0;position:relative;overflow:hidden}
.trk-cv{position:absolute;inset:0;width:100%;height:100%;display:block;touch-action:none;cursor:text}
.trk-side{width:340px;flex:none;display:flex;flex-direction:column;min-height:0;background:var(--panel);border-left:1px solid var(--line)}
.trk-tabs{display:flex;border-bottom:1px solid var(--line)}
.trk-tab{flex:1;height:34px;background:none;border:0;border-bottom:2px solid transparent;color:var(--dim);cursor:pointer}
.trk-tab.on{color:var(--txt);border-bottom-color:var(--acc)}
.trk-pane{display:none;flex:1;min-height:0;flex-direction:column;gap:6px;padding:6px;overflow:auto}
.trk-pane.on{display:flex}
.trk-grid{display:grid;grid-template-columns:1fr 1fr;gap:6px}
.trk-grid label{display:flex;flex-direction:column;gap:2px;font-size:10px;color:var(--dim)}
.trk-grid input,.trk-grid select{height:30px;min-width:0;padding:0 6px;background:var(--bg);border:1px solid var(--line);border-radius:3px}
.trk-ords{display:grid;grid-template-columns:repeat(auto-fill,minmax(62px,1fr));gap:3px;align-content:start;overflow:auto;min-height:60px}
.trk-ord{display:flex;justify-content:space-between;gap:4px;padding:5px 6px;background:var(--panel2);border:1px solid var(--line);border-radius:3px;cursor:pointer}
.trk-ord span{color:var(--dim)}
.trk-ord.pl{background:rgba(78,201,176,.25)}
.trk-ord.on{border-color:var(--acc)}
.trk-slist{flex:1 1 45%;min-height:100px;overflow:auto;background:var(--bg);border:1px solid var(--line);border-radius:3px}
.trk-si{display:flex;gap:6px;padding:3px 6px;cursor:pointer;border-bottom:1px solid var(--panel2)}
.trk-si span:first-child{color:var(--dim)}
.trk-si .trk-sn{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.trk-si.empty{color:var(--dim)}
.trk-si.on{background:var(--panel2);color:var(--acc)}
.trk-sed{display:flex;flex-direction:column;gap:6px}
.trk-wave{width:100%;height:96px;flex:none;border-radius:3px;touch-action:none;cursor:ew-resize}
.trk-wrap{flex-wrap:wrap}
.trk-sinfo{font-size:10px;color:var(--dim)}
.trk-piano{display:grid;grid-template-columns:repeat(12,1fr);gap:2px}
.trk-letters{grid-template-columns:repeat(10,1fr)}
.trk-chk{flex-direction:row!important;align-items:center;gap:6px!important;font-size:11px!important;color:var(--txt)!important}
.trk-xi,.trk-xe{display:flex;flex-direction:column;gap:6px}
.trk-xi[hidden],.trk-xe[hidden],.trk-grid [hidden],.trk-hex[hidden]{display:none}
.trk-xs{display:flex;gap:3px;flex-wrap:wrap}
.trk-xs .aed-b{min-width:30px;height:30px;padding:0 6px}
.trk-map{width:100%;height:44px;flex:none;border-radius:3px;touch-action:none;cursor:pointer}
.trk-env{width:100%;height:120px;flex:none;border-radius:3px;touch-action:none;cursor:crosshair}
.trk-add{color:var(--acc2)}
select.aed-b{padding:0 6px}
.trk-hex{display:grid;grid-template-columns:repeat(8,1fr);gap:2px}
.trk-kb{display:grid;grid-template-columns:repeat(4,1fr);gap:2px}
.trk-pk,.trk-k{height:40px;padding:0;background:var(--panel2);border:1px solid var(--line);border-radius:3px;cursor:pointer;font-size:11px}
.trk-pk.blk{background:var(--bg);color:var(--dim)}
.trk-pk:active,.trk-k:active{border-color:var(--acc)}
@media (max-width:820px){
  .trk-body{flex-direction:column}
  .trk-side{width:auto;height:44%;border-left:0;border-top:1px solid var(--line)}
  .trk-pk{height:46px}
}

#boot{position:fixed;inset:0;z-index:100;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;background:var(--bg);color:var(--txt);font:14px system-ui,sans-serif}
#bootBar{width:min(240px,60vw);height:4px;background:var(--line);border-radius:2px;overflow:hidden}
#bootBar i{display:block;height:100%;width:0;background:var(--acc);transition:width .1s}
#bootCur{font:12px var(--mono);color:var(--acc);min-height:1.2em;max-width:90vw;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
#boot.err{color:var(--err)}
#net{color:var(--acc);font-size:11px;font-weight:600}
#errBadge{color:var(--err);font-size:11px;font-weight:600;white-space:nowrap}
#errBadge[hidden]{display:none}
#errPanel{position:fixed;z-index:90;left:50%;top:50%;transform:translate(-50%,-50%);width:min(640px,94vw);max-height:80vh;display:flex;flex-direction:column;background:var(--panel);color:var(--txt);border:1px solid var(--line);border-radius:6px;box-shadow:0 6px 24px rgba(0,0,0,.45);font-size:12px}
#errPanel .ep-head{display:flex;align-items:center;gap:10px;padding:8px 10px;border-bottom:1px solid var(--line)}
#errPanel .ep-v{flex:1;color:var(--dim);font:11px var(--mono)}
#errPanel .ep-list{flex:1;overflow:auto;padding:6px 10px}
#errPanel .ep-foot{display:flex;gap:8px;padding:8px 10px;border-top:1px solid var(--line)}
#errPanel .ee{padding:4px 0;border-bottom:1px solid var(--line)}
#errPanel .ee.old{opacity:.6}
#errPanel .ee summary{cursor:pointer;color:var(--err);overflow-wrap:anywhere}
#errPanel .ee-meta{color:var(--dim);font:10px var(--mono);margin-top:2px;overflow-wrap:anywhere}
#errPanel pre{margin:4px 0 0;font:10px var(--mono);white-space:pre-wrap;overflow-wrap:anywhere;color:var(--dim)}
#errPanel .ee-empty{color:var(--dim);padding:8px 0}
#errPanel button,#bootRep{background:var(--panel2);color:var(--txt);border:1px solid var(--line);border-radius:3px;padding:4px 10px;font:12px system-ui,sans-serif;cursor:pointer}
#bootRep{margin-top:6px}

/* значок модуля: инициалы, цвет — группа, форма — роль: круг = источник, квадрат = обработка, шестиугольник = приёмник */
.mi{flex:none;display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;margin-right:7px;
  font:600 9px/1 var(--mono,monospace);color:#111;background:var(--c,var(--dim));border-radius:5px}
.mi[data-role=source]{border-radius:50%}
.mi[data-role=proc]{border-radius:3px}
.mi[data-role=sink]{border-radius:0;clip-path:polygon(25% 3%,75% 3%,100% 50%,75% 97%,25% 97%,0 50%)}
.pcat summary .gdot{flex:none;width:8px;height:8px;border-radius:50%;background:var(--c)}
.psub{padding:6px 12px 1px 20px;color:var(--dim);font-size:9px;text-transform:uppercase;letter-spacing:.06em}
#palLegend{display:flex;gap:10px;padding:6px 12px;color:var(--dim);font-size:10px;border-top:1px solid var(--line)}
#palLegend .mi{width:12px;height:12px;margin:0 3px 0 0;font-size:0;vertical-align:middle;background:var(--dim)}
.pitem .mi{width:16px;height:16px;margin:0 8px 0 -8px;font-size:7px;border-radius:4px}
.pitem .mi[data-role=source]{border-radius:50%}
.pitem .mi[data-role=proc]{border-radius:3px}
.pitem .pio{display:none}
.pitem:hover .pio{display:flex}
.pitem .prow i{opacity:.7}
.modpick .mp-item .mi{width:18px;height:18px;margin-right:0;font-size:8px}
.modpick .mp-from{display:flex;align-items:center;gap:5px;padding:6px 8px 0;color:var(--dim);font-size:10px}
.modpick .mp-from .pin{width:7px;height:7px;border-radius:50%}
.modpick .mp-from i{font-style:normal;color:var(--txt)}
.modpick .mp-item .mp-port{flex:none;font-style:normal;font-size:9px;color:var(--dim)}
.graphview{width:100%;height:280px;min-height:120px;resize:vertical;overflow:hidden;background:var(--bg);border:1px solid var(--line);border-radius:3px}
.entcard{width:100%;height:280px;min-height:120px;display:flex;flex-direction:column;background:var(--bg);border:1px solid var(--line);border-radius:3px;overflow:hidden;font-size:11px}
.ec-bar{display:flex;gap:4px;padding:3px;border-bottom:1px solid var(--line)}
.ec-q{flex:1;min-width:0}
.ec-body{flex:1;overflow:auto;padding:5px 6px;user-select:text}
.ec-title{font-size:13px;font-weight:600}
.ec-type{margin-left:6px;font-size:10px;font-weight:400;color:var(--acc2);border:1px solid var(--line);border-radius:3px;padding:0 4px}
.ec-id,.ec-dim{color:var(--dim);margin-top:1px}
.ec-attrs{display:grid;grid-template-columns:auto 1fr;gap:1px 8px;margin:5px 0}
.ec-k{color:var(--dim)}
.ec-v{word-break:break-all}
.ec-h{margin:7px 0 2px;color:var(--dim)}
.ec-chips{display:flex;flex-wrap:wrap;gap:3px}
.ec-chip,.ec-pick{cursor:pointer;background:var(--panel2);border:1px solid var(--line);border-radius:3px;padding:1px 5px}
.ec-chip:hover,.ec-pick:hover{border-color:var(--acc)}
.ec-pick{display:block;margin-bottom:2px}
.ec-more{color:var(--dim);padding:1px 3px}
.chat{display:flex;flex-direction:column;gap:4px;width:100%;min-height:0}
.chat-log{flex:1 1 160px;min-height:60px;overflow:auto;background:var(--bg);border:1px solid var(--line);border-radius:3px;padding:4px 6px;font:11px/1.45 var(--mono)}
.chat-msg{white-space:pre-wrap;overflow-wrap:anywhere;padding:1px 0;font:inherit}
.chat-msg.chat-in{color:var(--txt)}
.chat-msg.chat-out{color:var(--acc2);text-align:right}
.chat-t{color:var(--dim);margin-right:6px}
.chat-bar{display:flex;gap:10px;overflow-x:auto;flex:0 0 auto;padding:2px 2px 4px}
.chat-p{display:flex;flex-direction:column;align-items:center;gap:2px;flex:none;max-width:56px;font-size:9px;color:var(--dim)}
.chat-p span{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.chat-msg.chat-grp{display:flex;gap:6px;align-items:flex-start;padding:3px 0;white-space:normal}
.chat-msg.chat-grp.chat-out{flex-direction:row-reverse;text-align:right}
.chat-b{min-width:0;white-space:pre-wrap;overflow-wrap:anywhere}
.chat-n{font-size:10px;color:var(--acc2)}
.chat-sub{margin-left:38px}
.chat-sub .chat-n{display:none}
.chat-typ{flex:0 0 auto;font-size:10px;color:var(--acc2);font-style:italic;min-height:14px}
.chat-row{display:flex;gap:4px;flex:0 0 auto}
/* Chat: режим conversations */
.chat.cv{gap:6px}
.cv-head{display:flex;align-items:center;gap:8px;flex:0 0 auto}
.cv-title{flex:1;min-width:0;font-weight:600;font-size:13px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cv-head button{height:26px;padding:0 10px;background:var(--panel2);border:1px solid var(--line);border-radius:3px;cursor:pointer;font-size:12px}
.cv-head button:hover{border-color:var(--acc)}
.cv-filters{display:flex;flex-wrap:wrap;gap:6px;flex:0 0 auto}
.cv-filters[hidden]{display:none}
.cv-filters input[type=text]{flex:1 1 140px;min-width:0;height:26px;border:1px solid var(--line);border-radius:3px;padding:2px 8px;background:var(--bg);color:var(--txt);font-size:12px}
.cv-filters select{flex:1 1 110px;min-width:0;height:26px;font-size:12px}
.cv-un{display:flex;align-items:center;gap:4px;font-size:12px;color:var(--dim);white-space:nowrap}
.cv-body{flex:1 1 240px;min-height:120px;overflow:auto;background:var(--bg);border:1px solid var(--line);border-radius:4px;padding:6px;display:flex;flex-direction:column;gap:2px}
.cv-empty{margin:auto;color:var(--dim);font-size:12px;text-align:center;padding:16px;max-width:240px}
.cv-conv{display:flex;align-items:center;gap:10px;padding:8px 6px;border-radius:6px;cursor:pointer;border-bottom:1px solid color-mix(in srgb,var(--line) 40%,transparent)}
.cv-conv:hover{background:color-mix(in srgb,var(--acc2) 12%,transparent)}
.cv-cmid{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.cv-ct{display:flex;align-items:baseline;gap:6px;min-width:0}
.cv-ctitle{font-weight:600;font-size:13px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cv-proto{font-size:10px;color:var(--dim);flex:none}
.cv-prev{font-size:12px;color:var(--dim);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cv-conv.unread .cv-prev{color:var(--txt)}
.cv-side{display:flex;flex-direction:column;align-items:flex-end;gap:4px;flex:none}
.cv-when{font-size:10px;color:var(--dim)}
.cv-badge{min-width:18px;height:18px;padding:0 5px;box-sizing:border-box;border-radius:9px;background:var(--acc);color:#fff;font-size:11px;line-height:18px;text-align:center}
.cv-day{align-self:center;margin:8px 0 4px;padding:1px 10px;border-radius:10px;background:var(--panel2);color:var(--dim);font-size:10px}
.cv-msg{display:flex;margin-top:6px}
.cv-msg.run{margin-top:1px}
.cv-msg.out{justify-content:flex-end}
.cv-bub{max-width:86%;padding:5px 9px 3px;border-radius:12px;background:var(--panel2);font-size:13px;line-height:1.4;min-width:0;overflow-wrap:anywhere}
.cv-msg.out .cv-bub{background:color-mix(in srgb,var(--acc) 30%,var(--panel2))}
.cv-who{font-size:11px;font-weight:600;color:var(--acc2);cursor:pointer;margin-bottom:1px}
.cv-who:hover{text-decoration:underline}
.cv-subj{font-size:11px;color:var(--dim);margin-bottom:2px}
.cv-text{white-space:pre-wrap}
.cv-text code,.cv-bub code{font-family:var(--mono);font-size:12px;background:rgba(0,0,0,.25);border-radius:3px;padding:0 4px}
.cv-text s{opacity:.7}
.chat-a{color:var(--acc2)}
.cv-atts{font-size:11px;color:var(--acc2);margin-top:2px}
.cv-foot{display:flex;align-items:center;justify-content:flex-end;gap:6px;margin-top:1px;min-height:14px}
.cv-time{font-size:10px;color:var(--dim)}
.cv-st{font-size:10px;color:var(--acc2)}
.cv-st.wait{color:var(--dim)}
.cv-st.rd{color:#4fc3f7}
.cv-st.bad{color:#e0a030}
.cv-re{border:0;background:none;color:var(--dim);cursor:pointer;font-size:12px;padding:0 2px;opacity:.35}
.cv-msg:hover .cv-re,.cv-re:focus{opacity:1;color:var(--acc2)}
.cv-thr{margin:6px 0 2px;border-left:2px solid var(--acc2);padding-left:6px;display:flex;flex-direction:column;gap:2px}
.cv-thr-h{font-size:11px;color:var(--acc2);cursor:pointer;user-select:none}
.cv-hit{padding:6px;border-bottom:1px solid color-mix(in srgb,var(--line) 40%,transparent);cursor:pointer;border-radius:4px}
.cv-hit:hover{background:color-mix(in srgb,var(--acc2) 12%,transparent)}
.cv-hit-h{font-size:10px;color:var(--dim);margin-bottom:2px}
.cv-text.gone{font-style:italic;color:var(--dim)}
.cv-edited{font-size:10px;color:var(--dim);font-style:italic}
.cv-rx{display:flex;flex-wrap:wrap;gap:4px;margin-top:4px}
.cv-chip{height:20px;padding:0 7px;border-radius:10px;border:1px solid var(--line);background:var(--bg);color:var(--txt);font-size:12px;line-height:18px;cursor:pointer}
.cv-chip.mine{border-color:var(--acc);background:color-mix(in srgb,var(--acc) 28%,var(--bg))}
.cv-chip:disabled{cursor:default;opacity:.85}
.cv-pick{display:flex;gap:2px;margin-top:4px;padding:2px;border-radius:12px;background:var(--bg);border:1px solid var(--line);width:max-content;max-width:100%;flex-wrap:wrap}
.cv-pick button{border:0;background:none;cursor:pointer;font-size:16px;line-height:22px;width:28px;height:26px;border-radius:50%}
.cv-pick button:hover{background:var(--panel2)}
.cv-hint{font-size:11px;color:#d9822b;flex:0 0 auto}
.cv-hint[hidden]{display:none}
.cv-reply{display:flex;align-items:center;gap:6px;font-size:11px;color:var(--acc2);padding:2px 6px;border-left:2px solid var(--acc2);background:var(--panel2);border-radius:0 4px 4px 0;flex:0 0 auto}
.cv-reply[hidden]{display:none}
.cv-reply span{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cv-reply button{border:0;background:none;color:var(--dim);cursor:pointer}
.chat.cv .chat-row[hidden]{display:none}

.chat-row input{flex:1;min-width:0;height:26px;border:1px solid var(--line);border-radius:3px;padding:2px 6px;background:var(--bg);color:var(--txt)}
.chat-row input:focus{outline:none;border-color:var(--acc)}
.chat-row button{flex:0 0 auto;height:26px;padding:2px 12px;background:var(--panel2);border:1px solid var(--line);border-radius:3px;cursor:pointer}
.chat-row button:hover{border-color:var(--acc)}
/* RDS Display: цвета — токены экрана прибора; ширина — @container, высота — data-h (см. modules/rds.js) */
.rds-ui{--rd:var(--axis);--rl:var(--grid);container:rds/inline-size;display:flex;flex-direction:column;gap:6px;width:100%;
  height:300px;min-height:100px;resize:vertical;overflow:hidden;padding:8px 10px;border-radius:4px;
  background:var(--screen);color:var(--txt);font:11px/1.4 var(--mono)}
.rds-head{display:flex;flex-wrap:wrap;align-items:center;gap:4px 12px;flex:0 0 auto}
.rds-ps{font-size:clamp(20px,10cqw,54px);line-height:1.05;letter-spacing:.06em;white-space:pre;color:var(--screen-fg)}
.rds-side{flex:1 1 110px;min-width:0;display:flex;flex-direction:column;gap:1px}
.rds-pi b{font-size:15px;color:var(--acc);font-weight:600}
.rds-pi span{color:var(--screen-fg);font-size:13px}
.rds-sub{color:var(--rd);overflow-wrap:anywhere}
.rds-q{display:flex;align-items:center;gap:6px;color:var(--rd);font-size:10px}
.rds-q .trk{flex:0 1 90px;height:5px;border-radius:3px;background:var(--rl);overflow:hidden}
.rds-q i{display:block;height:100%;width:0;background:var(--t-blk);transition:width .4s}
.rds-q i.y{background:var(--acc)}
.rds-q i.r{background:var(--err)}
.rds-flags{display:flex;flex-wrap:wrap;gap:4px;flex:0 0 auto}
.rds-chip{display:inline-block;padding:1px 7px;border:1px solid var(--rl);border-radius:9px;color:var(--rd);font-size:10px;letter-spacing:.04em;white-space:nowrap}
.rds-chip.on{color:var(--screen);background:var(--screen-fg);border-color:var(--screen-fg)}
.rds-chip.off{opacity:.55}
.rds-chip.unk{opacity:.35;border-style:dashed}
.rds-st .rds-chip{cursor:pointer}
.rds-body{flex:1 1 auto;min-height:0;overflow:auto;display:flex;flex-direction:column;gap:9px;padding-right:2px}
.rds-rt{font-size:13px;color:var(--scr-hi);overflow-wrap:anywhere;min-height:1.4em}
.rds-np{color:var(--acc);font-size:12px;overflow-wrap:anywhere}
.rds-cards{display:grid;grid-template-columns:minmax(0,1fr);gap:7px 12px}
.rds-card{display:flex;flex-direction:column;min-width:0;padding-left:7px;border-left:2px solid var(--rl)}
.rds-k{color:var(--rd);font-size:9px;text-transform:uppercase;letter-spacing:.07em}
.rds-v{font-size:12px;color:var(--scr-hi);overflow-wrap:anywhere}
.rds-s{color:var(--rd);font-size:10px}
.rds-wide{display:none}
.rds-sec h4{margin:0 0 3px;font:600 9px var(--mono);text-transform:uppercase;letter-spacing:.07em;color:var(--rd)}
.rds-chips{display:flex;flex-wrap:wrap;gap:3px}
.rds-eonrow{display:flex;gap:8px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.rds-eonrow b{color:var(--screen-fg);font-weight:600}
.rds-eonrow span{color:var(--rd);overflow:hidden;text-overflow:ellipsis}
.rds-grp{display:grid;grid-template-columns:repeat(16,minmax(0,1fr));gap:2px;height:48px}
.rds-gc{display:flex;flex-direction:column;align-items:stretch;gap:1px;font-size:8px;color:var(--rd);text-align:center}
.rds-gb{flex:1;display:flex;align-items:flex-end;gap:1px}
.rds-gb i{flex:1;min-height:1px;background:var(--screen-fg)}
.rds-gb i.b{background:var(--acc)}
.rds-gc.z i{opacity:.2}
.rds-st{display:flex;flex-wrap:wrap;gap:4px}
.rds-stale .rds-ps,.rds-stale .rds-rt,.rds-stale .rds-np{opacity:.4}
.rds-none .rds-ps{opacity:.3}
@container rds (max-width:259px){
  .rds-flags .rds-chip:nth-child(n+4){display:none}
  .rds-sub{white-space:normal}
}
@container rds (min-width:300px){
  .rds-cards{grid-template-columns:repeat(2,minmax(0,1fr))}
  .rds-wide{display:grid;grid-template-columns:minmax(0,1fr);gap:9px}
}
@container rds (min-width:520px){
  .rds-cards{grid-template-columns:repeat(3,minmax(0,1fr))}
  .rds-wide{grid-template-columns:repeat(2,minmax(0,1fr))}
  .rds-sec[data-s=grp]{grid-column:1/-1}
}
@container rds (min-width:760px){
  .rds-cards{grid-template-columns:repeat(5,minmax(0,1fr))}
  .rds-wide{grid-template-columns:repeat(3,minmax(0,1fr))}
}
/* низкая плитка: название станции и одна строка радиотекста */
.rds-ui[data-h=s]{padding:5px 8px;gap:3px}
.rds-ui[data-h=s] .rds-flags,.rds-ui[data-h=s] .rds-q,.rds-ui[data-h=s] .rds-sub{display:none}
.rds-ui[data-h=s] .rds-ps{font-size:clamp(16px,7cqw,32px)}
.rds-ui[data-h=s] .rds-body>:not(.rds-rt){display:none}
.rds-ui[data-h=s] .rds-rt{font-size:11px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
#power.on{color:var(--acc)}
#powerPanel{position:fixed;right:8px;bottom:8px;z-index:60;width:230px;padding:8px;background:var(--panel,#1b1d22);border:1px solid var(--line,#333);border-radius:6px;font-size:11px;color:var(--dim)}
#powerPanel .pp-h{display:flex;justify-content:space-between;align-items:center;margin-bottom:4px;color:var(--text,#ddd)}
#powerPanel .pp-r{display:flex;justify-content:space-between;gap:8px;padding:1px 0;cursor:pointer}
#powerPanel .pp-r.off{opacity:.45;text-decoration:line-through}
#powerPanel .pp-f{margin-top:4px;opacity:.7}
.pbadge{position:absolute;right:4px;top:-14px;font-size:10px;color:var(--acc);pointer-events:none}
.pbadge:empty{display:none}
.ng{display:flex;flex-direction:column;gap:6px;width:100%;min-height:0}
.ng-bar{display:flex;gap:4px;align-items:center;flex-wrap:wrap}
.ng-st{flex:1 1 140px;color:var(--dim);font:11px/1.35 var(--mono)}
.ng-bar button{height:24px;padding:2px 10px;background:var(--panel2);border:1px solid var(--line);border-radius:3px;cursor:pointer}
.ng-bar button:hover{border-color:var(--acc)}
.ng-bd{display:flex;gap:10px;flex-wrap:wrap;justify-content:center}
.ng-bw{flex:1 1 150px;min-width:0;max-width:300px}
.ng-cap{color:var(--dim);font:10px var(--mono);margin-bottom:2px}
.ng-g{display:grid;gap:2px;width:100%;max-width:300px}
.ng-c{aspect-ratio:1;display:flex;align-items:center;justify-content:center;background:var(--bg);border:1px solid var(--line);border-radius:2px;font:bold 15px var(--mono);cursor:pointer;user-select:none}
.ng-c:hover{border-color:var(--acc)}
.ng-c.p1,.ng-c.hit{color:var(--acc)}
.ng-c.p2{color:var(--acc2)}
.ng-c.hit{color:var(--err)}
.ng-c.miss{color:var(--dim)}
.ng-c.ship{background:var(--panel2);border-color:var(--dim)}
.ng-c.win{border-color:var(--hi);box-shadow:inset 0 0 0 1px var(--hi)}
.ng-disc{border-radius:50%}
.ng-disc.f1{background:var(--acc);border-color:var(--acc)}
.ng-disc.f2{background:var(--acc2);border-color:var(--acc2)}
.ng-disc.last{box-shadow:inset 0 0 0 2px var(--bg)}
.ng-c.hint::after{content:'';width:30%;height:30%;border-radius:50%;background:var(--dim);opacity:.5}

/* ---- Table (modules/table.js): список, правка панелью снизу, меню действий ---- */
.tbl-ui{position:relative;display:flex;flex-direction:column;gap:4px;font-size:11px;color:var(--txt);box-sizing:border-box;
  overflow:hidden;grid-column:1/-1;width:100%;min-width:0}
.tbl-head,.tbl-bar,.tbl-acts{display:flex;gap:4px;align-items:center;flex:none;min-width:0}
.tbl-ui .tbl-pick{flex:1;min-width:0;height:28px;background:var(--bg);border:1px solid var(--line);border-radius:3px;
  color:var(--txt);padding:0 6px;font-size:12px;text-align:left;cursor:pointer;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tbl-ui .tbl-pick:hover{border-color:var(--acc)}
.tbl-ui .tbl-btn{background:var(--panel2);border:1px solid var(--line);color:var(--txt);padding:0 9px;border-radius:3px;
  cursor:pointer;font-size:12px;height:28px;white-space:nowrap;flex:none}
.tbl-ui .tbl-btn:hover{border-color:var(--acc)}
.tbl-ui .tbl-btn.on{color:var(--acc);border-color:var(--acc)}
.tbl-ui .tbl-btn.pri{border-color:var(--acc2);color:var(--acc2)}
.tbl-ui .tbl-chk{display:flex;align-items:center;gap:3px;color:var(--dim);font-size:10px;white-space:nowrap;cursor:pointer;flex:none}
.tbl-ui input[type=checkbox]{margin:0;accent-color:var(--acc2)}
.tbl-ui .tbl-filter.bad{border-color:var(--err)}
.tbl-ui .tbl-filter{flex:1;min-width:0;height:26px;background:var(--bg);border:1px solid var(--line);color:var(--txt);
  font-size:11px;padding:0 6px;border-radius:3px}
.tbl-ui .tbl-count{color:var(--dim);font-size:10px;white-space:nowrap}
.tbl-ui .tbl-bar{flex-wrap:wrap}
.tbl-ui .tbl-bar .tbl-filter{flex:1 1 90px}
.tbl-ui .tbl-bar .tbl-count{flex:none}
.tbl-ui .tbl-viewb .i{width:14px;height:14px}
.tbl-ui .tbl-bar .tbl-btn{height:26px;padding:0 7px}
.tbl-ui [hidden]{display:none!important}
.tbl-list{position:relative;flex:1;min-height:0;overflow-y:auto;border:1px solid var(--line);border-radius:3px;background:var(--bg)}
.tbl-row{display:flex;align-items:center;gap:6px;padding:4px 6px;cursor:pointer;border-bottom:1px solid var(--line);min-width:0}
.tbl-row.on{background:color-mix(in srgb,var(--acc2) 20%,transparent)}
.tbl-row.edit{box-shadow:inset 2px 0 0 var(--acc)}
.tbl-rname{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tbl-rval{color:var(--acc2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:55%}
.tbl-ico{cursor:pointer;color:var(--dim);flex:none;padding:0 3px}
.tbl-ico:hover{color:var(--acc)}
.tbl-ico.warn{color:var(--acc)}
.tbl-empty{padding:12px;text-align:center;color:var(--dim)}
.tbl-empty.sm{padding:4px;font-size:10px}
.tbl-edit{position:absolute;left:0;right:0;bottom:0;z-index:15;max-height:62%;display:flex;flex-direction:column;
  background:var(--panel);border:1px solid var(--acc);border-radius:4px;box-shadow:0 -4px 14px #0006}
.tbl-edit .te-h{display:flex;gap:6px;align-items:center;padding:4px 6px;border-bottom:1px solid var(--line);flex:none}
.tbl-edit .te-t{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dim)}
.tbl-edit .tbl-btn{height:26px}
.tbl-form{overflow-y:auto;padding:6px;display:grid;grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:6px 8px}
.tbl-form label{display:flex;flex-direction:column;gap:1px;font-size:9px;color:var(--dim);min-width:0}
.tbl-form label.wide{grid-column:1/-1}
.tbl-form input,.tbl-form select{min-width:0;height:26px;background:var(--bg);border:1px solid var(--line);color:var(--txt);
  font-size:12px;padding:0 5px;border-radius:3px}
.tbl-form input:focus,.tbl-form select:focus{outline:none;border-color:var(--acc)}
.tbl-form input[type=color]{padding:0;width:48px}
.tbl-form .tf-bar{display:flex;gap:4px;align-items:center;flex-wrap:wrap;font-size:10px;color:var(--txt)}
.tbl-form .tf-bar button{background:var(--panel2);border:1px solid var(--line);color:var(--txt);border-radius:3px;cursor:pointer;
  padding:2px 7px;font-size:11px}
.tbl-menu{position:absolute;z-index:20;left:0;right:0;top:32px;max-height:75%;overflow-y:auto;background:var(--panel);
  border:1px solid var(--line);border-radius:4px;box-shadow:0 4px 14px #0007}
.tbl-menu .tp-q{position:sticky;top:0;z-index:1;box-sizing:border-box;width:100%;height:28px;background:var(--bg);border:0;border-bottom:1px solid var(--line);color:var(--txt);padding:0 8px;font-size:12px;outline:none}
.tbl-menu .tm-s{padding:4px 10px;border-bottom:0}
.tbl-menu .tm-i.act{color:var(--acc2)}
.tbl-menu .tm-i.hi{background:color-mix(in srgb,var(--acc2) 20%,transparent)}
.tbl-menu .tm-none{padding:8px 10px}
.tbl-menu .tp-top{display:flex;gap:10px;align-items:center;padding:3px 10px;background:var(--panel2);border-bottom:1px solid var(--line);color:var(--dim);font-size:10px}
.tbl-menu .tp-cnt{flex:1}
.tbl-menu .tp-none{cursor:pointer}
.tbl-menu .tp-none:hover{color:var(--acc)}
.tbl-menu .tm-h{display:flex;align-items:center;gap:6px}
.tbl-menu .tp-dir{cursor:pointer}
.tbl-menu .tp-dir:hover{background:color-mix(in srgb,var(--acc2) 12%,var(--panel2))}
.tbl-menu .tp-car{width:9px;color:var(--dim);flex:none}
.tbl-menu .tp-gn{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis}
.tbl-menu .tp-n{color:var(--dim);font-size:9px}
.tbl-menu .tm-s{display:flex;align-items:center;gap:6px}
.tbl-menu .tp-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis}
.tbl-menu .tp-cb{margin:0;width:15px;height:15px;accent-color:var(--acc2);cursor:pointer;flex:none}
.tbl-menu .tm-h{padding:5px 10px 2px;font-size:9px;color:var(--dim);letter-spacing:.06em;text-transform:uppercase;background:var(--panel2)}
.tbl-menu .tm-i{padding:7px 10px;cursor:pointer;border-bottom:1px solid var(--line)}
.tbl-menu .tm-i:hover{background:color-mix(in srgb,var(--acc2) 20%,transparent)}
.tbl-menu .tm-d{color:var(--dim);font-size:9px;white-space:normal}
.tbl-menu .tm-c{color:var(--acc2);font-size:9px;white-space:normal}

.fm{position:relative;display:flex;flex-direction:column;gap:4px;width:100%;height:100%;min-height:120px;font:11px var(--mono)}
.fm button{background:var(--panel2);border:1px solid var(--line);border-radius:3px;color:var(--txt);cursor:pointer;padding:2px 6px;font:inherit}
.fm button:hover{border-color:var(--acc)}
.fm-bar{display:flex;gap:4px;flex:0 0 auto;flex-wrap:wrap}
.fm-off{flex:0 0 auto;display:flex;flex-direction:column;gap:4px;padding:4px 6px;border:1px solid var(--line);border-radius:3px;background:var(--panel2)}
.fm-off[hidden]{display:none}
.fm-crumbs{flex:0 0 auto;color:var(--dim)}
.fm-crumbs button{border:0;background:none;padding:0 2px;color:var(--acc2)}
.fm-list{flex:1 1 120px;min-height:60px;overflow:auto;background:var(--bg);border:1px solid var(--line);border-radius:3px}
.fm-row{display:flex;align-items:center;gap:5px;padding:2px 6px;min-height:28px;cursor:pointer;border-bottom:1px solid var(--line)}
.fm-q{flex:1 1 80px;min-width:60px}
.fm-bar select,.fm-q{background:var(--bg);color:var(--txt);border:1px solid var(--line);border-radius:3px;font:inherit}
.fm-bar button.on{border-color:var(--acc);color:var(--acc)}
.fm-row.mark{background:var(--panel2);outline:1px solid var(--acc)}
.fm-row input[type=checkbox]{flex:0 0 auto;margin:0}
.fm-sys{color:var(--acc2)}
.fm-prev{flex:0 0 auto;display:flex;align-items:center;gap:6px;flex-wrap:wrap;max-height:90px;overflow:auto;font-size:10px;color:var(--dim);border:1px solid var(--line);border-radius:3px;padding:3px 5px}
.fm-prev img{max-height:70px;max-width:100%;border-radius:2px}
.fm-prev pre{margin:0;white-space:pre-wrap;word-break:break-all;max-height:80px;overflow:hidden;color:var(--txt);font:inherit;font-family:monospace}
.fm-prev canvas{color:var(--acc2)}
.fm-prev video{max-height:80px;max-width:100%}
.fm-prev audio{height:28px;max-width:100%}
.fm-seek{flex:1 1 80px;min-width:60px;accent-color:var(--acc2)}
.dsp-toast{position:absolute;left:6px;right:6px;bottom:6px;z-index:20;background:var(--panel2);border:1px solid var(--acc);border-radius:4px;padding:4px 8px;font-size:11px;display:flex;align-items:center;gap:8px}
.dsp-toast button{color:var(--acc);background:none;border:0;cursor:pointer;font:inherit}
.fm-bar button:disabled{opacity:.4;cursor:default}
.fm-row.sel{background:var(--panel2)}
.fm-row.over{background:var(--panel2);outline:1px solid var(--acc)}
.fm-row button{flex:0 0 auto;padding:0 5px;color:var(--dim);border-color:transparent;background:none}
.fm-name{flex:1;min-width:30px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.fm-size{flex:0 0 auto;color:var(--acc);font-size:10px}
.fm-th{flex:0 0 36px;width:36px;height:22px;display:flex;align-items:center;justify-content:center;color:var(--acc);overflow:hidden}
.fm-th img{max-width:36px;max-height:22px;object-fit:cover}
.fm-th canvas{width:36px;height:18px}
.fm-aud{min-height:44px;padding:4px 8px;gap:8px;border-left:3px solid transparent}
.fm-aud:hover{background:color-mix(in srgb,var(--acc2) 8%,transparent)}
.fm-aud.sel{border-left-color:var(--acc2);background:color-mix(in srgb,var(--acc2) 14%,var(--panel2))}
.fm-aud .fm-th{flex:0 0 72px;width:72px;height:30px;background:var(--panel);border:1px solid var(--line);border-radius:4px;color:var(--acc2)}
.fm-aud .fm-th canvas{width:72px;height:28px}
.fm-main{flex:1;min-width:30px;display:flex;flex-direction:column;gap:1px}
.fm-main .fm-name{flex:none;font-size:12px}
.fm-sub{color:var(--dim);font-size:10px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.fm-aud .fm-size{padding:1px 6px;border-radius:9px;background:var(--panel2);border:1px solid var(--line);color:var(--acc2)}
.fm-empty{padding:12px;text-align:center;color:var(--dim)}
.fm-info{flex:0 0 auto;color:var(--dim);font-size:10px}
.fm-disk{flex:0 0 auto;display:flex;flex-direction:column;gap:2px;color:var(--dim);font-size:10px}
.fm-meter{height:5px;background:var(--bg);border:1px solid var(--line);border-radius:3px;overflow:hidden}
.fm-meter i{display:block;height:100%;background:var(--acc)}
.fm-meter.warn i{background:var(--err,#e5534b)}
.fm-ov{position:fixed;inset:0;z-index:300;background:var(--scrim);display:flex;align-items:center;justify-content:center}
.fm-pick{background:var(--panel);color:var(--txt);border:1px solid var(--line);border-radius:6px;padding:12px;display:flex;flex-direction:column;gap:4px;max-width:92vw;max-height:80vh;overflow:auto;font:12px var(--mono)}
.fm-pick button{text-align:left;background:var(--panel2);border:1px solid var(--line);border-radius:3px;color:var(--txt);padding:6px 10px;cursor:pointer;font:inherit}

.rtc-media{position:relative;width:100%;background:#000;border:1px solid var(--line);border-radius:3px;min-height:40px}
.rtc-rv{display:block;width:100%;max-height:260px;object-fit:contain;background:#000}
.rtc-lv{position:absolute;right:4px;bottom:4px;width:30%;max-height:30%;object-fit:cover;border:1px solid var(--line);border-radius:3px;background:#000}
.fm-row.armed{background:var(--panel2)}

/* ---- HEX Structure (modules/hex.js): дамп с подсветкой полей, дерево полей, правка ---- */
.hx-ui{display:flex;flex-direction:column;gap:4px;font-size:11px;color:var(--txt);box-sizing:border-box;overflow:hidden;
  grid-column:1/-1;width:100%;min-width:0}
.hx-bar{display:flex;gap:4px;align-items:center;flex:none;min-width:0}
.hx-info{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dim,#889)}
.hx-info.bad{color:var(--err)}
.hx-btn{background:var(--panel2);border:1px solid var(--line);color:var(--txt);padding:0 8px;border-radius:3px;cursor:pointer;font-size:10px;height:20px}
.hx-btn:hover{border-color:var(--acc)}
.hx-dump{contain:layout style;flex:none;max-height:42%;min-height:40px;overflow:auto;background:var(--screen,var(--bg));border:1px solid var(--line);
  border-radius:3px;padding:3px 4px;font:11px/1.45 ui-monospace,Menlo,Consolas,monospace;outline:none;white-space:nowrap}
.hx-dump:focus{border-color:var(--acc)}
.hx-row{display:flex;gap:8px}
.hx-off{color:#778;user-select:none}
.hx-hex b{font-weight:400;padding:0 1px;border-radius:2px;cursor:pointer;display:inline-block;min-width:1.7em;text-align:center}
.hx-asc{color:#99a}
.hx-asc i{font-style:normal;cursor:pointer;display:inline-block;min-width:.6em;text-align:center}
.hx-x{color:#667}
.hx-err{background:rgba(224,92,92,.35)}
.hx-pad{background:rgba(128,128,128,.18)}
.hx-c0{background:rgba(95,184,209,.28)} .hx-c1{background:rgba(224,135,95,.28)} .hx-c2{background:rgba(127,209,127,.26)}
.hx-c3{background:rgba(209,138,209,.28)} .hx-c4{background:rgba(224,176,80,.28)} .hx-c5{background:rgba(111,208,192,.28)}
.hx-c6{background:rgba(224,127,176,.28)} .hx-c7{background:rgba(180,212,85,.26)}
.hx-in{outline:1px solid var(--acc);outline-offset:-1px}
.hx-cur{box-shadow:0 0 0 1px var(--acc)}
.hx-empty{color:#889;padding:4px}
.hx-tree{contain:layout style;flex:1;min-height:40px;overflow:auto;border:1px solid var(--line);border-radius:3px;background:var(--bg)}
.hx-f{display:flex;gap:6px;align-items:baseline;padding:1px 4px;cursor:pointer;white-space:nowrap}
.hx-f:hover{background:var(--panel2)}
.hx-f.on{background:rgba(95,184,209,.18)}
.hx-f.bad .hx-val{color:var(--err)}
.hx-f s{width:8px;height:8px;border-radius:2px;flex:none;align-self:center}
.hx-n{min-width:60px;flex:none}
.hx-o{color:#778;min-width:28px;flex:none;font-size:10px}
.hx-val{overflow:hidden;text-overflow:ellipsis;font-family:ui-monospace,Menlo,Consolas,monospace}
.hx-val.ed:hover{text-decoration:underline dotted}
.hx-val u{text-decoration:none;color:#889;margin-left:4px}
.hx-val em{color:var(--err);font-style:normal;margin-left:4px}
.hx-edit,.hx-line{min-width:0;width:100%;box-sizing:border-box;background:var(--bg);border:1px solid var(--line);color:var(--txt);
  font:11px ui-monospace,Menlo,Consolas,monospace;padding:2px 4px;flex:none}
.hx-edit{width:12em}

/* ⛶ в заголовке узла: параметры скрыты, канва / список на весь модуль (core-graph.js, xpandNode) */
.nhead .xpd.on{color:var(--acc);opacity:1}
.node.xp{display:flex;flex-direction:column}
#canvas #content .node.xp .nbody{flex:1 1 0;min-height:0;display:flex;flex-direction:column}
#canvas #content .node.xp .io3{flex:1 1 0;min-height:0}
#canvas #content .node.xp .io3>.mid{flex:1 1 0;min-height:0;min-width:0;display:flex!important;flex-direction:column;padding:0;margin:0}
#canvas #content .node.xp .io3>.mid>:not(canvas.view.main):not(.tbl-ui):not(.chat):not(.sa-ov):not(.vp){display:none!important}
#canvas #content .node.xp .io3>.mid>.vp{flex:1 1 0;min-height:0}
.node.xp .vp-stage{flex:1 1 0;aspect-ratio:auto;min-height:0}
.node.xp .vp-src{display:none}
#canvas #content .node.xp canvas.view.main{flex:1 1 0;min-height:0;width:100%!important;height:auto!important;aspect-ratio:auto;margin:0;border-radius:0}
.node.xp .tbl-ui{flex:1 1 0;min-height:0;height:auto!important;padding:4px}
.node.xp .tbl-ui>:not(.tbl-list){display:none!important}
.node.xp .chat{flex:1 1 0;min-height:0;padding:4px}
.node.xp .chat-log{flex:1 1 0;resize:none}
/* Table: сетка колонок (Wireshark-like), панель вида */
.tbl-list.grid{overflow:auto}
.tbl-row{background:var(--rb,transparent)}
.tbl-list:not(.cards):not(.icons) .tbl-row{height:var(--rh,auto);overflow:hidden;box-sizing:border-box}
.tbl-sp{flex:none;pointer-events:none}
.tbl-list.grid .tbl-row,.tbl-list.grid .tbl-hd{display:grid;grid-template-columns:var(--tc);gap:0;align-items:stretch;width:max-content;min-width:100%;box-sizing:border-box;font-size:11px}
.tbl-list.grid .tbl-row{padding:0;border-bottom:1px solid color-mix(in srgb,var(--line) 50%,transparent);font-variant-numeric:tabular-nums}
.tbl-list.grid .tbl-row.on{background:color-mix(in srgb,var(--acc2) 32%,var(--rb,transparent))}
.tbl-hd{position:sticky;top:0;z-index:1;padding:0;background:var(--panel2);border-bottom:1px solid var(--line);color:var(--dim)}
.tbl-list.grid .tbl-row>*,.tbl-hd>*{padding:2px 5px;border-right:1px solid color-mix(in srgb,var(--txt) 12%,transparent);box-sizing:border-box;min-width:0}
.tbl-list.grid .tbl-row>:last-child,.tbl-hd>:last-child{border-right:0}
.tbl-hd>span,.tbl-c{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tbl-c.r{text-align:right}
.tbl-no{color:var(--dim);font-size:10px;text-align:right}
.tc-bar{position:relative;display:block;width:100%;box-sizing:border-box;height:14px;line-height:14px;border-radius:3px;background:color-mix(in srgb,var(--txt) 10%,transparent);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--txt) 25%,transparent);overflow:hidden}
.tc-bar i{position:absolute;left:0;top:0;bottom:0;background:color-mix(in srgb,var(--txt) 38%,transparent)}
.tc-bar b{position:relative;display:block;padding:0 3px;font-weight:normal;font-size:10px;text-align:right;overflow:hidden;white-space:nowrap}
.tbl-c.tbl-bar{padding-top:3px;padding-bottom:3px}
.tbl-dev{width:15px;height:15px;margin-right:5px;vertical-align:-3px;border-radius:50%;flex-shrink:0}
.tbl-sw{display:inline-block;width:9px;height:9px;border-radius:2px;margin-right:4px;vertical-align:-1px}
.tbl-tail{display:flex;justify-content:flex-end}
.tbl-view{position:absolute;left:0;right:0;top:32px;z-index:13;max-height:80%;overflow-y:auto;border:1px solid var(--acc);border-radius:4px;
  background:var(--panel);padding:4px 6px;display:flex;flex-direction:column;gap:3px}
.tbl-view .tv-top{display:flex;gap:8px;align-items:center;position:sticky;top:-4px;background:var(--panel);padding:2px 0;z-index:1}
.tbl-view .tv-ttl{flex:1}
.tbl-view .tv-x,.tbl-view .tv-mv{cursor:pointer;color:var(--dim);padding:0 3px}
.tbl-view .tv-x:hover,.tbl-view .tv-mv:hover{color:var(--acc)}
.tbl-view .tv-sec{margin-top:4px;font-size:9px;color:var(--dim);letter-spacing:.06em;text-transform:uppercase}
.tbl-view .tv-col,.tbl-view .tv-rule,.tbl-view .tv-acts{display:flex;align-items:center;gap:5px;min-width:0;flex-wrap:wrap}
.tbl-view .tv-ren{cursor:text}
.tbl-view .tv-more{display:flex;align-items:center;gap:5px;flex-wrap:wrap;padding:0 0 3px 22px}
.tbl-view .tv-fold{cursor:pointer}
.tbl-view .tv-col[draggable=true]{cursor:grab}
.tbl-view .tv-col.over{outline:1px solid var(--acc)}
.tbl-view .tv-ren:hover{color:var(--acc)}
.tbl-view .tv-col.off .tv-name{color:var(--dim);text-decoration:line-through}
.tbl-view .tv-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tbl-view .tv-lbl{color:var(--dim);font-size:10px}
.tbl-view input[type=checkbox]{margin:0;accent-color:var(--acc2)}
.tbl-view select,.tbl-view input:not([type=checkbox]):not([type=color]){min-width:0;height:22px;background:var(--bg);border:1px solid var(--line);color:var(--txt);font-size:10px;padding:0 3px;border-radius:3px}
.tbl-view .tv-w{width:52px}
.tbl-view .tv-q{flex:1}
.tbl-view input[type=color]{width:30px;height:22px;padding:0;border:1px solid var(--line);background:none}
.tbl-view [hidden]{display:none!important}
.tbl-view .tv-bar{flex-wrap:nowrap}
.tbl-view .tv-f{border:1px solid var(--line);border-radius:3px;padding:2px 5px;background:var(--panel)}
.tbl-view .tv-f.open{border-color:var(--acc)}
.tbl-view .tv-f .tv-more{display:flex;flex-direction:column;align-items:stretch;gap:3px;padding:3px 0 2px;margin-top:3px;border-top:1px dashed var(--line)}
.tbl-view .tv-line,.tbl-view .tv-grid{display:grid;grid-template-columns:62px minmax(0,1fr);gap:3px 6px;align-items:center}
.tbl-view .tv-grid{padding:4px 5px}
.tbl-view .tv-line>.tv-lbl,.tbl-view .tv-grid>.tv-lbl{text-align:right}
.tbl-view .tv-ctl{display:flex;align-items:center;gap:3px 8px;flex-wrap:wrap;min-width:0}
.tbl-view .tv-ctl .tv-q{flex:1 1 110px}
.tbl-view .tv-f>.tv-col .tv-name{flex:0 0 78px}
.tbl-view .tv-f>.tv-col select{flex:1 1 70px}
.tbl-view .tv-ctl>span>input[type=checkbox]{margin-right:3px;vertical-align:middle}
.tbl-view .tv-chip{font-size:9px;line-height:14px;color:var(--acc2);border:1px solid var(--line);border-radius:3px;padding:0 3px;cursor:default}

/* Table: полосы прокрутки списка заметны (общие — цвета линии на светлом фоне почти не видно) */
.tbl-list:focus{outline:none;border-color:var(--acc)}
.tbl-list{scrollbar-width:auto;scrollbar-color:var(--dim) var(--panel2)}
.tbl-list::-webkit-scrollbar{width:12px;height:12px}
.tbl-list::-webkit-scrollbar-track,.tbl-list::-webkit-scrollbar-corner{background:var(--panel2)}
.tbl-list::-webkit-scrollbar-thumb{background:var(--dim);border:2px solid var(--panel2);border-radius:6px;background-clip:padding-box}

/* GSM: лог в ячейке тайла не прыгает (modules/gsm.js, gsmReadout) */
.readout.gsm-ro{display:flex;flex-direction:column;overflow:hidden;gap:3px}
.gsm-ro .gsm-st{flex:none;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--acc)}
.gsm-ro .gsm-lg{flex:1;min-height:0;overflow:auto;white-space:pre-wrap;word-break:break-word}
/* Спектроанализатор в тайле: контролы сверху, канва до низа ячейки; в режиме «только главное» (▤) канва сверху, главные контролы под ней */
.dash-pane.compact .dash-body .node[data-type="sa"] .io3>.mid>canvas.view.main{order:-1;margin-top:0}

.wa,.pl,.eq10{accent-color:var(--acc);display:flex;flex-direction:column;gap:4px;width:100%;min-height:0;outline:none}
.wa-lcd{display:flex;gap:10px;align-items:center;padding:6px 10px;background:var(--screen);border:1px solid var(--line);border-radius:4px}
.wa-clock{display:flex;align-items:center;gap:6px;flex:none}
.wa-st{color:var(--dim);display:flex}.wa-st .i{width:12px;height:12px;fill:currentColor;stroke:none}
.wa-time{font:600 28px/1 var(--mono);color:var(--screen-fg);cursor:pointer;user-select:none;letter-spacing:.02em}
.wa-inf{min-width:0;flex:1;display:flex;flex-direction:column;gap:3px}
.wa-title{font:12px/1.3 var(--mono);color:var(--screen-fg);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.wa-title.bad{color:var(--err)}
.wa-badges{display:flex;gap:8px;font:10px/1.2 var(--mono);color:var(--dim)}
.wa-badges .on{color:var(--acc2)}
.wa-seek{width:100%;margin:0}
.wa-row{display:flex;gap:6px;align-items:center;flex-wrap:wrap}
.wa-main{justify-content:space-between}
.wa-tr,.wa-tg{display:flex;gap:2px}
.wa-tr button:last-child{margin-left:6px}
.wa-sl label{display:flex;align-items:center;gap:4px;flex:1 1 90px;min-width:70px;color:var(--dim)}
.wa-sl label input{flex:1;min-width:0}
.wa button,.pl button,.eq10 button{display:inline-flex;align-items:center;justify-content:center;gap:4px;height:26px;min-width:28px;padding:0 6px;background:var(--panel2);border:1px solid var(--line);border-radius:4px;cursor:pointer;color:var(--txt);font:11px var(--mono)}
.wa button .i,.pl button .i{width:14px;height:14px}
.wa button[data-a=play] .i{fill:currentColor}
.wa button:hover,.pl button:hover,.eq10 button:hover{border-color:var(--acc)}
.wa button.on,.pl button.on{border-color:var(--acc);color:var(--acc)}
.wa-foot{flex:none}
.wa-foot button{padding:0 8px}
.wa-foot select{max-width:110px;height:26px;min-width:0;background:var(--panel2);color:var(--txt);border:1px solid var(--line);border-radius:4px;font:11px var(--mono)}
.pl-head{flex:none}
.wa-cnt{margin-left:auto;font:10px var(--mono);color:var(--dim)}
.wa-pl{flex:1 1 120px;min-height:60px;overflow:auto;background:var(--screen);border:1px solid var(--line);border-radius:4px;font:11px/1.55 var(--mono)}
.wa-it{display:flex;gap:6px;padding:0 6px;cursor:pointer;color:var(--screen-fg)}
.wa-it:hover{background:var(--panel2)}
.wa-it.cur{color:var(--acc);font-weight:600}
.wa-it.bad{color:var(--err)}
.wa-it .n{flex:none;min-width:2.2em;text-align:right;color:var(--dim)}
.wa-it .t{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.wa-it .d{flex:none;color:var(--dim)}
.wa-it .x{display:none;height:auto;min-width:0;padding:0 4px;border:0;background:none}
.wa-it:hover .x{display:inline}
.ml{display:flex;flex-direction:column;width:100%;min-height:0;outline:none}
.ml-tree{flex:1 1 120px;min-height:60px;overflow:auto;background:var(--screen);border:1px solid var(--line);border-radius:4px;font:11px/1.6 var(--mono)}
.ml-row{display:flex;gap:4px;padding-right:6px;cursor:pointer;color:var(--screen-fg);user-select:none}
.ml-row:hover{background:var(--panel2)}
.ml-row.sel{color:var(--acc);font-weight:600}
.ml-row .tg{flex:none;width:1.2em;color:var(--dim)}
.ml-row .t{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ml-row .c{flex:none;color:var(--dim)}
.eq-top{display:flex;gap:6px;align-items:center}
.eq-top select{flex:1;min-width:0;height:26px;background:var(--panel2);color:var(--txt);border:1px solid var(--line);border-radius:4px;font:11px var(--mono)}
.eq10 button.on{border-color:var(--acc);color:var(--acc)}
.eq-cv{width:100%;height:40px;background:var(--screen);border:1px solid var(--line);border-radius:4px}
.eq-sl{display:flex;gap:2px;flex:1;min-height:90px}
.eq-c{display:flex;flex-direction:column;align-items:center;flex:1;gap:2px;min-width:0;font:9px var(--mono);color:var(--dim)}
.eq-v{writing-mode:vertical-lr;direction:rtl;flex:1;width:18px;margin:0;min-height:60px}
.wa-pick{background:var(--panel);color:var(--txt);border:1px solid var(--line);border-radius:6px;padding:10px;display:flex;flex-direction:column;gap:6px;width:min(480px,92vw);height:min(520px,80vh);font:12px var(--mono)}
.wa-pick-fm{flex:1;min-height:0;display:flex}
.wa-pick .fm{flex:1;min-height:0}

/* Signal Analyzer (sigLab) */
.sl-ui{display:flex;flex-direction:column;gap:4px;font-size:11px;color:var(--txt);box-sizing:border-box;overflow:hidden;grid-column:1/-1;width:100%;min-width:0;margin-top:4px}
.sl-bar{display:flex;gap:4px;align-items:center;flex:none;min-width:0}
.sl-info{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dim)}
.sl-fm{display:flex;gap:2px}
.sl-btn{background:var(--panel2);border:1px solid var(--line);color:var(--txt);padding:0 8px;border-radius:3px;cursor:pointer;font-size:10px;height:20px}
.sl-btn:hover,.sl-btn.on{border-color:var(--acc)}
.sl-btn.on{color:var(--acc)}
.sl-rng{display:flex;gap:4px;align-items:center;flex:none;flex-wrap:wrap;color:var(--dim)}
.sl-rng:empty{display:none}
.sl-rbits{width:52px;height:20px;background:var(--panel2);border:1px solid var(--line);border-radius:3px;padding:0 4px}
.sl-tbl{flex:1;min-height:60px;overflow:auto;background:var(--screen);border:1px solid var(--line);border-radius:3px;font:11px/1.45 var(--mono);color:var(--scr-txt,var(--txt));outline:none}
.sl-tbl:focus{border-color:var(--acc)}
.sl-row{display:flex;gap:8px;padding:0 4px;white-space:pre;cursor:pointer;border-left:3px solid var(--c,transparent);min-width:max-content}
.sl-row:hover{background:var(--panel2)}
.sl-row.on{background:rgba(95,184,209,.14)}
.sl-ruler{color:#778;cursor:default;position:sticky;top:0;background:var(--screen);border-left-color:transparent;z-index:1}
.sl-ruler:hover{background:var(--screen)}
.sl-id{flex:none;min-width:30px;color:var(--c,var(--dim));font-weight:600}
.sl-t{flex:none;min-width:62px;color:#778}
.sl-n{flex:none;min-width:44px;color:#889}
.sl-dt i{font-style:normal}
.sl-d0{opacity:.45}
.sl-d1{opacity:1}
.sl-row.on .sl-dt i{cursor:pointer}
.sl-dt i.sel{outline:1px solid var(--acc);outline-offset:-1px;background:rgba(224,178,60,.3)}
.sl-l0{background:rgba(95,184,209,.30)} .sl-l1{background:rgba(224,135,95,.30)} .sl-l2{background:rgba(127,209,127,.28)} .sl-l3{background:rgba(209,138,209,.30)}
.sl-l4{background:rgba(224,176,80,.30)} .sl-l5{background:rgba(111,208,192,.30)} .sl-l6{background:rgba(224,127,176,.30)} .sl-l7{background:rgba(180,212,85,.28)}
.sl-dt i.sl-sy{border-bottom:2px solid var(--acc)}
.sl-empty{padding:6px;color:#889}
.sl-sel{flex:none;min-height:14px;color:var(--dim);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.sl-lab{display:flex;flex-wrap:wrap;gap:4px;align-items:center;flex:none}
.sl-lab:empty{display:none}
.sl-new{display:flex;gap:4px;align-items:center}
.sl-name{width:110px;height:20px;background:var(--panel2);border:1px solid var(--line);border-radius:3px;padding:0 4px}
.sl-chip{border:1px solid var(--c,var(--line));border-radius:3px;padding:0 5px;cursor:pointer;background:var(--panel2)}
.sl-chip i{font-style:normal;color:var(--dim)}
.sl-chip b{cursor:pointer;color:var(--dim);font-weight:400;padding-left:2px}
.sl-chip b:hover{color:var(--err)}

/* ?readonly-tiles: только тайлы, без панелей и правки раскладки */
body.rotiles #side,body.rotiles #bar,body.rotiles #scrim,body.rotiles #dashPages,body.rotiles .dash-tools,body.rotiles .dash-resizer,body.rotiles .dash-rail,body.rotiles .dash-pane.graph{display:none!important}

/* Аватарки, статус «онлайн», «печатает» (Table: список с иконками, Chat) */
.av-w{position:relative;flex:none;width:var(--av,32px);height:var(--av,32px)}
.av{display:flex;align-items:center;justify-content:center;width:100%;height:100%;border-radius:50%;overflow:hidden;background:var(--panel2);font-size:calc(var(--av,32px)*.45);line-height:1;color:#fff}
.av img{width:100%;height:100%;object-fit:cover;display:block}
.av.none{background:hsl(var(--h) 38% 34%)}
.av-dot{position:absolute;right:-1px;bottom:-1px;width:28%;height:28%;min-width:8px;min-height:8px;border-radius:50%;border:2px solid var(--panel);box-sizing:border-box;background:var(--dim)}
.av-dot.st-online{background:#3fb950}
.av-dot.st-away{background:#e0b23c}
.av-dot.st-busy{background:#e05c5c}
.tc-typing{display:inline-flex;gap:2px;align-items:center;vertical-align:middle;margin-right:4px}
.tc-typing i{width:4px;height:4px;border-radius:50%;background:var(--acc2);animation:tc-blink 1.2s infinite both}
.tc-typing i:nth-child(2){animation-delay:.2s}
.tc-typing i:nth-child(3){animation-delay:.4s}
@keyframes tc-blink{0%,80%,100%{opacity:.2}40%{opacity:1}}
.tbl-list.icons{display:flex;flex-direction:column;align-content:start}
.tbl-irow{gap:10px;padding:var(--tk-rowpad,6px 8px);position:relative;border-bottom-color:var(--tk-sep,var(--line))}
.tbl-irow .av-w{--av:var(--tk-av,38px)}
.ir-body{flex:1;min-width:0;display:flex;flex-direction:column;gap:1px}
.ir-t{font-size:var(--tk-tfs,inherit);font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ir-s{font-size:var(--tk-sfs,10px);color:var(--dim);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ir-s.typ{color:var(--acc2);font-style:italic}
.tbl-irow .tc-tail{position:static;background:none}

/* Table: карточки, карточка записи, связи */
.tbl-list.cards{display:grid;grid-template-columns:repeat(auto-fill,minmax(var(--tk-min,150px),1fr));grid-auto-rows:max-content;gap:var(--tk-gap,6px);padding:6px;align-content:start}
.tbl-card{flex-direction:column;align-items:stretch;gap:0;padding:0;border:1px solid var(--tk-bd,var(--line));border-radius:var(--tk-r,6px);overflow:hidden;position:relative;background:var(--rb,var(--tk-bg,var(--panel)));box-shadow:var(--tk-sh,none)}
.tbl-card.on{outline:1px solid var(--acc2)}
.tc-cover{position:relative;flex:none;width:100%;aspect-ratio:4/3;background:var(--panel2);overflow:hidden;display:flex;align-items:center;justify-content:center}
.tc-cover img{width:100%;height:100%;object-fit:cover;display:block}
.tc-cover.none{font-size:34px;color:#fff;background:hsl(var(--h) 38% 34%)}
.tc-n{position:absolute;right:3px;bottom:3px;background:rgba(0,0,0,.6);color:#fff;border-radius:3px;padding:0 4px;font-size:10px}
.tc-body{padding:var(--tk-pad,4px 6px 6px);display:flex;flex-direction:column;gap:1px;min-width:0}
.tc-t{font-size:var(--tk-tfs,inherit);font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tc-l{display:flex;gap:4px;font-size:10px;min-width:0;align-items:baseline}
.tc-k{color:var(--dim);font-size:9px;flex:none}
.tc-v{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tc-v.pre{white-space:pre-wrap}
.tc-ln{flex-wrap:wrap;gap:1px 8px;font-size:11px}
.tc-file{color:var(--acc2);cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}
.tc-file:hover{text-decoration:underline}
.tc-prev{max-width:100%;max-height:160px;display:block;margin-top:2px;border-radius:3px}
.tc-back-btn{background:var(--panel2);border:1px solid var(--acc2);color:var(--acc2)}
.tbl-view .tv-lay{display:flex;align-items:center;gap:4px;min-width:0;flex-wrap:wrap}
.tbl-view .tv-lay .tc-chip{color:var(--txt);cursor:pointer}
.tbl-view .tv-lay .tc-chip:hover{border-color:var(--bad,#e05c5c);text-decoration:line-through}
.tc-tail{position:absolute;top:2px;right:2px;display:flex;background:rgba(0,0,0,.45);border-radius:4px}
.tc-chips{display:flex;flex-wrap:wrap;gap:3px;min-width:0}
.tc-chip{background:var(--panel2);border:1px solid var(--line);border-radius:10px;padding:0 6px;font-size:10px;color:var(--acc2);cursor:pointer;white-space:nowrap;max-width:100%;overflow:hidden;text-overflow:ellipsis}
.tc-chip:hover{border-color:var(--acc2)}
.tc-links{white-space:normal}
.tc-lnk{color:var(--acc2);text-decoration:none;margin-right:8px;white-space:nowrap}
.tc-lnk:hover{text-decoration:underline}
.tc-detail .tc-gal{display:flex;flex-direction:column;gap:4px}
.tc-big{width:100%;max-height:220px;object-fit:contain;background:var(--bg);border-radius:4px;cursor:zoom-in}
.tc-thumbs{display:flex;gap:4px;overflow-x:auto}
.tc-thumbs img{height:44px;width:58px;object-fit:cover;border-radius:3px;cursor:pointer;flex:none}
.tc-title{font-size:15px;font-weight:600}
.tc-f{display:flex;flex-direction:column;gap:1px;min-width:0;font-size:12px}
.tc-nav,.tc-back{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.tc-nav button{padding:0 9px}
.tbl-view .tv-refs{display:flex;align-items:center;gap:5px;flex-wrap:wrap;width:100%}

/* уважаем системную настройку «меньше движения»: без анимаций и плавных переходов */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important;scroll-behavior:auto!important}
}

/* узлы холста вне экрана не раскладываются и не рисуются (см. cvArm в core-graph.js).
   Только тело узла (.mid): paint-containment обрезает и клики, а пины торчат за рамку узла — в соседних колонках, вне .mid, их он не трогает */
#canvas #content .node.cvis .io3>.mid{content-visibility:auto;overflow-clip-margin:80px;contain-intrinsic-size:auto 200px auto 60px}

/* ============ Studio (DAW) ============ */
.stu{color:var(--txt);font-size:12px;user-select:none}
.stu-tile{grid-column:1/-1;width:100%;min-width:0;display:flex;flex-direction:column;overflow:hidden;background:var(--bg)}
.stu-tile>.stu-p-rack{display:flex;flex-direction:column;background:var(--panel);min-height:0}
.stu-p-roll,.stu-p-list{display:flex;flex-direction:column;flex:1;min-height:0;min-width:0}
.stu-p-mix{display:flex;flex-direction:row;flex:1;min-height:0}
.stu-p-inst{display:flex;flex-direction:column;overflow:auto;flex:1;min-height:0}
.stu-rack>.stu-p-rack{flex:1}
.stu-tile .stu-top{flex-wrap:wrap;align-content:flex-start;overflow:auto}
.stu button,.stu select,.stu input{font:inherit;color:inherit}
.stu-top{display:flex;align-items:center;gap:6px;padding:5px 8px;background:var(--panel);border-bottom:1px solid var(--line);overflow-x:auto;flex:0 0 auto;scrollbar-width:thin}
.stu-b{background:var(--panel2);border:1px solid var(--line);border-radius:4px;padding:4px 9px;cursor:pointer;white-space:nowrap;min-height:26px}
.stu-b:hover{border-color:var(--dim)} .stu-b.on{background:var(--acc);color:#111;border-color:var(--acc)}
.stu-play{min-width:36px;font-size:14px} .stu-recb.on{background:#d33;border-color:#d33;color:#fff}
.stu-sep{width:1px;align-self:stretch;background:var(--line);margin:0 2px;flex:0 0 1px} .stu-fill{flex:1}
.stu-time{font:600 15px var(--mono);background:var(--screen);color:var(--screen-fg);padding:3px 8px;border-radius:4px;min-width:84px;text-align:center}
.stu-f{display:flex;align-items:center;gap:4px;white-space:nowrap;color:var(--dim)}
.stu-f input[type=number]{width:56px} .stu-f input[type=range]{width:70px}
.stu select,.stu input[type=number]{background:var(--panel2);border:1px solid var(--line);border-radius:4px;padding:3px}
.stu-master{border:1px solid var(--line);border-radius:3px;flex:0 0 auto} .stu-stat{color:var(--dim);min-width:70px;white-space:nowrap}
.stu-main{flex:1;display:flex;min-height:0}
.stu-rack{flex:0 0 auto;width:min(640px,50vw);display:flex;flex-direction:column;border-right:1px solid var(--line);background:var(--panel);min-width:0}
.stu-rack-in{flex:1;overflow:auto;padding:4px}
.stu-rack-add{padding:6px;border-top:1px solid var(--line)}
.stu-ch{display:flex;align-items:stretch;gap:6px;margin-bottom:3px;background:var(--panel2);border:1px solid transparent;border-radius:4px;padding:3px;min-width:min-content}
.stu-ch.sel{border-color:var(--acc)} .stu-ch.mute .stu-steps{opacity:.4}
.stu-chh{display:flex;align-items:center;gap:4px;flex:0 0 auto;position:sticky;left:0;background:inherit;z-index:1}
.stu-led{width:14px;height:14px;border-radius:50%;border:1px solid #0008;background:#333;cursor:pointer;padding:0;flex:0 0 14px}
.stu-led.on{background:var(--c,var(--t-blk));box-shadow:0 0 6px var(--c,var(--t-blk))}
.stu-chn{width:84px;text-align:left;background:var(--bg);border:1px solid var(--line);border-radius:3px;padding:4px 6px;cursor:pointer;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.stu-s,.stu-mini,.stu-pr{background:var(--bg);border:1px solid var(--line);border-radius:3px;cursor:pointer;padding:1px 5px;min-width:20px}
.stu-s.on{background:var(--acc2);color:#111} .stu-mixsel{width:42px;padding:2px}
.stu-steps{display:flex;gap:2px;align-items:center;flex:1 0 auto}
.stu-st{width:21px;height:28px;background:#2a3238;border-radius:3px;cursor:pointer;flex:0 0 21px;border:1px solid #0006}
.stu-st.alt{background:#343e45} .stu-st.on{background:var(--c,var(--acc));box-shadow:inset 0 0 0 1px #fff3} .stu-st.cur{outline:2px solid #fff;outline-offset:-2px}
.stu-st:nth-child(4n+1){margin-left:4px}
.stu-work{flex:1;display:flex;flex-direction:column;min-width:0}
.stu-rt,.stu-lt{display:flex;align-items:center;gap:8px;padding:5px 8px;background:var(--panel);border-bottom:1px solid var(--line);overflow-x:auto;scrollbar-width:thin;flex:0 0 auto}
.stu-lb{flex:1;display:flex;min-height:0}
.stu-pal{flex:0 0 120px;overflow:auto;background:var(--panel);border-right:1px solid var(--line);padding:6px;display:flex;flex-direction:column;gap:4px}
.stu-pal h4{margin:0 0 2px;color:var(--dim);font-weight:500}
.stu-pb{text-align:left;background:var(--panel2);border:1px solid var(--line);border-left:5px solid var(--c);border-radius:3px;padding:5px 6px;cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.stu-pb.on{background:var(--c);color:#111;font-weight:600}
.stu-cw{flex:1;min-height:0;min-width:0;position:relative;overflow:hidden} .stu-cw canvas{position:absolute;left:0;top:0;touch-action:none}
.stu-dim{color:var(--dim)} .stu-grp-t{color:var(--dim)}
.stu-empty{padding:30px;color:var(--dim)}
/* микшер */
.stu-strips{flex:1;display:flex;gap:3px;overflow:auto;padding:6px;align-items:flex-start;min-width:0}
.stu-strip{flex:0 0 78px;background:var(--panel2);border:1px solid var(--line);border-radius:4px;padding:4px;display:flex;flex-direction:column;align-items:center;gap:4px;cursor:pointer}
.stu-strip.sel{border-color:var(--acc)} .stu-strip.master{flex-basis:90px;background:var(--panel)}
.stu-sn{width:100%;text-align:center;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.stu-sfx{width:100%;min-height:34px;font-size:10px;line-height:1.25;overflow:hidden}
.stu-sfx i{display:block;font-style:normal;color:var(--dim);white-space:nowrap;overflow:hidden;text-overflow:ellipsis} .stu-sfx i.on{color:var(--acc2)} .stu-sfx i.none{opacity:.4}
.stu-fad{touch-action:none;cursor:ns-resize;border-radius:3px} .stu-ms{display:flex;gap:3px} .stu-sno{color:var(--dim);font-size:10px}
.stu-fxp{flex:0 0 320px;overflow:auto;border-left:1px solid var(--line);background:var(--panel);padding:8px}
.stu-fxp h3{margin:2px 0 6px;font-size:12px;color:var(--dim);font-weight:600}
.stu-slot{display:flex;align-items:center;gap:4px;padding:3px 5px;margin-bottom:2px;background:var(--panel2);border:1px solid var(--line);border-radius:3px;cursor:pointer}
.stu-slot.sel{border-color:var(--acc)} .stu-slot.empty{opacity:.55} .stu-slot .n{flex:1}
.stu-sends{display:flex;flex-wrap:wrap;gap:6px;align-items:flex-end;margin-bottom:6px}
/* ручки */
.stu-params{display:flex;flex-wrap:wrap;gap:8px;padding:8px}
.stu-grp{background:var(--panel2);border:1px solid var(--line);border-radius:5px;padding:4px 8px 6px}
.stu-grp h4{margin:0 0 4px;font-size:10px;letter-spacing:.06em;color:var(--dim);text-transform:uppercase;font-weight:500}
.stu-knobs{display:flex;flex-wrap:wrap;gap:6px;align-items:flex-end}
.stu-knob{display:flex;flex-direction:column;align-items:center;width:52px;cursor:ns-resize;touch-action:none}
.stu-knob.sm{width:40px} .stu-knob canvas{display:block}
.stu-kl{font-size:10px;color:var(--dim);text-align:center;white-space:nowrap;overflow:hidden;max-width:100%} .stu-kv{font:10px var(--mono);color:var(--txt);height:12px}
.stu-knob.on .stu-kv{color:var(--acc)}
.stu-sel{display:flex;flex-direction:column;align-items:center;gap:2px;width:70px} .stu-sel select{width:68px}
.stu-chk{background:var(--bg);border:1px solid var(--line);border-radius:3px;padding:4px 8px;cursor:pointer;align-self:center} .stu-chk.on{background:var(--acc);color:#111}
.stu-ihead{display:flex;align-items:center;gap:10px;padding:8px;background:var(--panel);border-bottom:1px solid var(--line);flex:0 0 auto}
.stu-ihead i{color:var(--dim);font-weight:400;font-style:normal;margin-left:4px}
.stu-env{margin:8px;border:1px solid var(--line);border-radius:4px;max-width:calc(100% - 16px);flex:0 0 auto}
.stu-menu{font:12px/1.3 system-ui,sans-serif;color:var(--txt);position:fixed;z-index:60;background:var(--panel);border:1px solid var(--line);border-radius:5px;padding:3px;box-shadow:0 6px 24px #0008;max-height:70vh;overflow:auto;min-width:170px}
.stu-menu button{font:inherit;color:inherit;display:block;width:100%;text-align:left;background:transparent;border:none;padding:6px 10px;cursor:pointer;border-radius:3px}
.stu-menu button:hover{background:var(--panel2)} .stu-menu button:disabled{opacity:.4} .stu-menu .sep{height:1px;background:var(--line);margin:3px 0}

.stu-knob.sm{width:30px} .stu-knob.sm .stu-kl,.stu-knob.sm .stu-kv{display:none} .stu-knob.sm.on .stu-kv{display:block;position:absolute;margin-top:-14px;background:var(--panel);padding:0 3px;border-radius:3px;z-index:3}
.stu-knob.sm{position:relative}
.stu-chn{width:76px}

/* самостоятельные узлы Studio (Drum Machine, Piano Roll, Playlist, Mixer) */
.stu-lite{display:flex;flex-direction:column;background:var(--bg)}
.stu-lite .stu-mixsel,.stu-lite .stu-pr{display:none}
.stu-lite>.stu-lite .stu-p-rack{overflow:auto;flex:1 1 55%}
.stu-lite .stu-p-inst{flex:1 1 45%}
.stu-scn{width:62px;background:var(--bg);border:1px solid var(--line);border-radius:3px;padding:2px 4px;font-size:10px;text-align:center}

.stu-song{display:flex;flex-direction:column;background:var(--bg);overflow:auto}
.stu-sgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:8px;padding:8px}
.stu-scol{background:var(--panel2);border:1px solid var(--line);border-radius:5px;padding:6px 8px;min-width:0}
.stu-scol h4{margin:0 0 4px;font-size:10px;letter-spacing:.06em;color:var(--dim);text-transform:uppercase;font-weight:500}
.stu-srow{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;padding:1px 0}
.stu-snote{padding:4px 10px 8px;font-size:11px}

/* справка (modules/help.js) */
#helpPanel{position:fixed;z-index:70;top:0;right:0;bottom:0;width:min(560px,100vw);display:flex;flex-direction:column;background:var(--panel);border-left:1px solid var(--line);box-shadow:-6px 0 24px rgba(0,0,0,.25);color:var(--txt);font-size:13px}
#helpPanel[hidden]{display:none}
#helpPanel .hp-bar{display:flex;gap:6px;padding:8px;border-bottom:1px solid var(--line);align-items:center}
#helpPanel .hp-q{flex:1;min-width:0;background:var(--bg);border:1px solid var(--line);color:var(--txt);padding:5px 8px;border-radius:4px;font-size:13px}
#helpPanel .hp-b,#helpPanel .hp-btn{background:var(--panel2);border:1px solid var(--line);color:var(--txt);border-radius:4px;cursor:pointer;padding:3px 9px}
#helpPanel .hp-b:disabled{opacity:.4;cursor:default}
#helpPanel .hp-body{flex:1;overflow:auto;padding:10px 14px 24px;line-height:1.5;user-select:text;-webkit-user-select:text}
#helpPanel h2{margin:4px 0 8px;font-size:18px} #helpPanel h3{margin:14px 0 6px;font-size:14px}
#helpPanel .hp-md h1{font-size:19px;margin:4px 0 10px} #helpPanel .hp-md h2{font-size:16px;margin:16px 0 6px} #helpPanel .hp-md h3{font-size:14px}
#helpPanel .hp-gh{color:var(--dim);text-transform:uppercase;font-size:11px;letter-spacing:.06em}
#helpPanel .hp-dim{color:var(--dim)}
#helpPanel .hp-meta{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-bottom:8px;color:var(--dim)}
#helpPanel .hp-list{display:flex;flex-direction:column;gap:3px}
#helpPanel .hp-item{display:flex;flex-direction:column;align-items:flex-start;text-align:left;background:var(--panel2);border:1px solid var(--line);color:var(--txt);border-radius:4px;padding:5px 9px;cursor:pointer}
#helpPanel .hp-item span{color:var(--dim);font-size:11px;font-weight:400}
#helpPanel .hp-item:hover,#helpPanel .hp-b:hover,#helpPanel .hp-btn:hover{border-color:var(--acc)}
#helpPanel .hp-sel{margin-bottom:8px;border-color:var(--acc)}
#helpPanel code{background:var(--bg);padding:0 4px;border-radius:3px;font-size:12px}
#helpPanel pre{background:var(--bg);padding:8px;border-radius:4px;overflow:auto}
#helpPanel a{color:var(--acc)}
#helpPanel table{border-collapse:collapse;width:100%;margin:6px 0;font-size:12px}
#helpPanel td,#helpPanel th{border:1px solid var(--line);padding:3px 6px;vertical-align:top;text-align:left}
#helpPanel blockquote{margin:6px 0;padding:0 10px;border-left:3px solid var(--line);color:var(--dim)}
#helpPanel .hp-body{font-family:system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;font-size:14px;line-height:1.65}
#helpPanel .hp-md p{margin:.55em 0} #helpPanel .hp-md li{margin:.3em 0} #helpPanel .hp-md ul,#helpPanel .hp-md ol{padding-left:1.3em}
#helpPanel code,#helpPanel pre{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12px}
#helpPanel .hp-more{margin-top:6px;padding-left:10px;border-left:2px solid var(--line)}
#helpPanel .hp-sum{font-size:14px}
#helpPanel .hp-btn{margin:4px 0}

/* рисованные иконки в шапке узла и панелях дашборда (ico() в core-graph.js) */
.nhead :is(.x,.ren,.rst,.xpd,.hlp,.fsb,.pipb,.wpb,.flb){display:inline-flex;align-items:center}
.nhead :is(.x,.ren,.rst,.xpd,.hlp,.fsb,.pipb,.wpb,.flb) .i{width:12px;height:12px}
.dash-tools button{display:inline-flex;align-items:center}
.dash-tools button .i{width:14px;height:14px}
@media (pointer:coarse){
  .nhead :is(.x,.ren,.rst,.xpd,.hlp,.fsb,.pipb,.wpb,.flb) .i{width:18px;height:18px}
  .dash-tools button .i{width:18px;height:18px}
}
/* Video Player */
.vp{display:flex;flex-direction:column;gap:4px;width:100%;height:100%;min-height:0;outline:none;accent-color:var(--acc)}
.vp-stage{position:relative;flex:none;width:100%;aspect-ratio:16/9;min-height:80px;background:#000;border-radius:4px;overflow:hidden}
.vp-stage:fullscreen{aspect-ratio:auto}
.vp-stage video{width:100%;height:100%;object-fit:contain;display:block}
.vp-stage.drop{outline:2px dashed var(--accent,#6cf);outline-offset:-4px}
.vp-tap{position:absolute;top:50%;transform:translateY(-50%);padding:8px 12px;border-radius:18px;font:13px/1 var(--mono);color:#fff;background:rgba(0,0,0,.55);pointer-events:none;opacity:0;transition:opacity .15s}
.vp-tap.on{opacity:1}
.vp-tap.back{left:12%}
.vp-tap.fwd{right:12%}
.vp-msg{position:absolute;left:0;right:0;bottom:0;padding:4px 8px;font:11px/1.3 var(--mono);color:#fff;background:rgba(0,0,0,.6);white-space:pre-wrap;pointer-events:none}
.vp-bar{display:flex;align-items:center;gap:4px;flex:none}
.vp button,.vp select{height:26px;min-width:0;padding:0 6px;background:var(--panel2);border:1px solid var(--line);border-radius:4px;color:var(--txt);font:11px var(--mono)}
.vp button{min-width:28px;cursor:pointer}
.vp button:hover,.vp select:hover{border-color:var(--acc)}
.vp select option,.vp select optgroup{background:var(--panel2);color:var(--txt)}
.vp-seek{flex:1;min-width:40px}
.vp-time{font:11px/1 var(--mono);color:var(--dim);white-space:nowrap}
.vp-speed,.vp-q{flex:none}
.vp-src{flex:none;width:100%}
/* Video Player: на весь экран — картинка и панель управления (в т.ч. в запасном режиме без Fullscreen API) */
.vp.fs-fb{position:fixed!important;inset:0;width:100vw!important;height:100vh!important;z-index:300;background:#000;margin:0;padding:6px;box-sizing:border-box}
.vp:fullscreen{background:#000;padding:6px;box-sizing:border-box}
.vp:fullscreen .vp-stage,.vp.fs-fb .vp-stage{flex:1 1 0;aspect-ratio:auto;min-height:0}

/* ---- подсказка на пустом канвасе ---- */
#cvHint{position:absolute;left:50%;top:36%;transform:translate(-50%,-50%);text-align:center;pointer-events:none;z-index:1;color:var(--dim);font-size:12px;line-height:1.6}
#cvHint b{display:block;color:var(--txt);font-size:16px;margin-bottom:6px;font-weight:600}
#cvHint kbd{font:inherit;color:var(--acc)}
/* ---- командная палитра (Ctrl+K) ---- */
#cmdk{position:fixed;left:50%;top:10%;transform:translateX(-50%);width:min(540px,94vw);z-index:120;background:var(--panel);border:1px solid var(--line);border-radius:8px;box-shadow:0 10px 40px rgba(0,0,0,.55);overflow:hidden}
#cmdk input{width:100%;box-sizing:border-box;padding:10px 12px;border:none;border-bottom:1px solid var(--line);background:var(--panel2);color:var(--txt);font-size:14px;outline:none}
.cmdk-list{max-height:52vh;overflow-y:auto}
.cmdk-row{display:flex;gap:8px;align-items:baseline;width:100%;padding:7px 12px;background:none;border:none;border-bottom:1px solid var(--line);color:var(--txt);font-size:13px;text-align:left;cursor:pointer}
.cmdk-row:last-child{border-bottom:none}
.cmdk-row.on,.cmdk-row:hover{background:var(--panel2)}
.cmdk-kind{flex:none;font-size:9px;text-transform:uppercase;letter-spacing:.5px;color:var(--dim);min-width:44px}
.cmdk-row.on .cmdk-kind{color:var(--acc)}
.cmdk-dim{margin-left:auto;font-size:11px;color:var(--dim)}
.cmdk-step{display:flex;gap:8px;align-items:baseline;padding:6px 12px;font-size:13px;border-bottom:1px solid var(--line)}
.cmdk-step .cmdk-kind{text-align:right}
.cmdk-step b{font-weight:600}
.cmdk-step b:first-of-type{color:var(--dim);font-weight:400}
.cmdk-arrow{color:var(--acc)}
.cmdk-bad{color:#d66;font-size:12px}
.cmdk-hint{padding:8px 12px;font-size:11px;color:var(--dim)}
/* превью цепочки из командной палитры — полупрозрачное, до Enter */
#content .node.cmdk-ghost{opacity:.55}
#wires path.cmdk-ghost{opacity:.45}
/* Command Templates: кнопка ▶ под каждой командой */
.cmds-ui{display:flex;flex-direction:column;gap:3px;padding:3px 0;width:100%;min-width:0}
.cmds-row{display:flex;align-items:center;gap:6px;min-width:0}
.cmds-row button{flex:none;width:22px;height:18px;padding:0;font-size:9px;line-height:1;cursor:pointer;background:var(--panel2);border:1px solid var(--line);border-radius:3px;color:var(--txt)}
.cmds-row button:hover{border-color:var(--acc)}
.cmds-tpl{font:10px var(--mono);color:var(--dim);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
