*,*::before,*::after{box-sizing:border-box}
:root{
  --bg:#0b0e14;--panel:#11151f;--card:#0d1119;--border:#232a38;
  --text:#cfd6e4;--muted:#67718a;--input:#0d1119;--btn:#1c2433;--btnh:#243049;
  --accent:#2962ff;--accent-hover:#1e53e5;--accent-soft:rgba(41,98,255,0.12);
  --green:#26a69a;--red:#ef5350;--orange:#ff9800;--purple:#9c27b0;--yellow:#f0b90b;
  --radius:8px;--radius-sm:4px;--radius-lg:12px;
  --panel-width:340px;--font-base:13px;--font-small:11px;--font-tiny:10px;
  --axis-x:26px;--col-w:76px;
}
body.light{
  --bg:#eef1f5;--panel:#fff;--card:#f7f8fa;--border:#d8dde6;
  --text:#1c2330;--muted:#667085;--input:#fff;--btn:#e7ebf2;--btnh:#d9dfea;
}
html,body{margin:0;height:100%;width:100%;background:var(--bg);color:var(--text);font:var(--font-base)/1.4 system-ui,Arial;overflow:hidden}
button{font-family:inherit;font-size:inherit;color:inherit;background:none;border:none;cursor:pointer}
input,select,textarea{font-family:inherit;font-size:inherit;color:var(--text);background:var(--input);border:1px solid var(--border);border-radius:var(--radius-sm);padding:3px 6px;outline:none}
input:focus,select:focus{border-color:var(--accent)}
input[type=color]{padding:0;height:24px;cursor:pointer;background:transparent}
input[type=range]{accent-color:var(--accent)}
input[type=checkbox]{accent-color:var(--accent);cursor:pointer}
::-webkit-scrollbar{width:6px;height:6px}
::-webkit-scrollbar-track{background:transparent}
::-webkit-scrollbar-thumb{background:var(--border);border-radius:3px}

/* AUTH */
#authOverlay{position:fixed;inset:0;background:var(--bg);z-index:9999;display:flex;flex-direction:column;align-items:center;justify-content:center}
#authOverlay .auth-box{background:var(--panel);padding:12px;padding-bottom:6px;border-radius:var(--radius-lg);border:1px solid var(--border);width:min(320px,calc(100vw - 24px));max-height:calc(100vh - 24px);max-height:calc(100dvh - 24px);overflow:auto}
#authOverlay input{width:100%;margin-bottom:12px;padding:10px}
#authOverlay .auth-btn{width:100%;padding:10px;background:var(--accent);color:#fff;border:none;border-radius:var(--radius-sm);cursor:pointer;font-weight:bold;font-size:14px}
#authOverlay .auth-btn:hover{background:var(--accent-hover)}
#authOverlay .auth-actions{display:flex;gap:8px}
#authOverlay .auth-actions .auth-btn{flex:1;width:auto;text-align:center;text-decoration:none}
#authOverlay .auth-error{color:var(--red);font-size:12px;margin-top:8px;text-align:center}
/* пустой p ошибки не должен добавлять отступ: иначе фон снизу до кнопок больше половинного padding */
#authOverlay .auth-error:empty{margin-top:0}
#authOverlay .auth-link{display:block;text-align:center;margin-top:16px;color:var(--muted);font-size:11px;text-decoration:none}

/* ============================================
   Приветственный экран (body.kiosk)
   ============================================
   Класс ставит ui/welcome.js только после успешного ответа /api/public/welcome.
   Пока экрана нет или запрос не прошёл, оверлей остаётся прежним — непрозрачным
   и центрированным, поэтому падение сервера не оставляет гостя на пустом фоне.

   Два момента принципиальны:
   1. pointer-events:none на самом оверлее и auto на форме. Без этого fixed-оверлей
      на inset:0 перехватывал бы мышь целиком, и зум с панорамой графика не работали.
   2. Форма поднята наверх (flex-start + отступ), а не центрирована: по центру она
      закрыла бы ровно ту часть графика, которую видно лучше всего. Градиент сверху
      держит её читаемой на свечах. */
body.kiosk #authOverlay{background:linear-gradient(180deg,rgba(8,10,14,.94) 0%,rgba(8,10,14,.74) 24%,rgba(8,10,14,.18) 52%,rgba(8,10,14,0) 76%);justify-content:flex-start;padding-top:5vh;pointer-events:none}
body.kiosk #authOverlay .auth-box{pointer-events:auto;box-shadow:0 10px 32px rgba(0,0,0,.6)}
/* Обвязка приложения гостю не видна: ни настроек, ни дерева объектов, ни подсказок.
   !important нужен потому, что видимость части этих элементов переключается инлайново
   из ui/settings.js (#panelOn) и ui/ribbon.js, а инлайн-стиль сильнее селектора. */
body.kiosk #ribbon,
body.kiosk #panel,
body.kiosk #panelCollapse,
body.kiosk #togglePanel,
body.kiosk #hint,
body.kiosk #statusbar{display:none !important}
/* Подсказка про жесты всё же нужна, но своя: оси остались, а редактирования нет. */
body.kiosk #leftcol::before{content:"колесо и ПКМ-drag — зум · ЛКМ-drag — перемещение";display:block;padding:3px 8px;font-size:10px;color:var(--muted);border-bottom:1px solid var(--border)}

/* ============================================
   Вкладка статистики (видна только админу)
   ============================================
   Ограничение по высоте обязательно: лента не резиновая, а таблицы источников и
   входов могут быть длинными. Без own-скролла вкладка распёрла бы всю ленту и
   уехала бы за экран. Fallback у var() на случай, если переменная темы не задана. */
#statsOut{max-height:52vh;overflow:auto;font-size:11px;padding:2px 0}
.stats-cards{display:flex;flex-wrap:wrap;gap:4px;margin-bottom:6px}
.stats-card{flex:1 1 74px;min-width:74px;padding:4px 6px;border:1px solid var(--border,#2a2f38);border-radius:3px;text-align:center}
.stats-card b{display:block;font-size:13px;color:var(--text,#dfe4ea)}
.stats-card span{font-size:9px;color:var(--muted,#8b949e)}
#rib-stats h4{margin:8px 0 3px;font-size:10px;text-transform:uppercase;letter-spacing:.04em;color:var(--muted,#8b949e)}
.stats-table{width:100%;border-collapse:collapse}
.stats-table td{padding:1px 4px;border-bottom:1px solid var(--border,#2a2f38);vertical-align:top;word-break:break-all}
.stats-table td:not(:first-child){text-align:right;white-space:nowrap;color:var(--muted,#8b949e)}
.stats-empty{padding:6px 4px;color:var(--muted,#8b949e);font-style:italic}

/* APP */
#app{display:none;flex-direction:column;height:100vh;width:100vw}

/* RIBBON */
.ribbon{background:var(--panel);border-bottom:1px solid var(--border);user-select:none;flex-shrink:0}
.ribbon-tabs{display:flex;align-items:stretch;height:36px;padding:0 8px}
.ribbon-tab{padding:0 14px;font-size:12px;font-weight:500;color:var(--muted);display:flex;align-items:center;gap:5px;border-bottom:2px solid transparent;transition:all .2s;white-space:nowrap}
.ribbon-tab:hover{color:var(--text);background:var(--btnh)}
.ribbon-tab.active{color:var(--accent);border-bottom-color:var(--accent);background:var(--accent-soft)}
.ribbon-collapse{margin-left:auto;padding:0 10px;color:var(--muted);display:flex;align-items:center;justify-content:center;border-radius:var(--radius-sm)}
.ribbon-collapse:hover{color:var(--text);background:var(--btnh)}
.ribbon-collapse svg{width:14px;height:14px;transition:transform .25s}
.ribbon-collapse.collapsed svg{transform:rotate(180deg)}
.ribbon-content{height:0;overflow:hidden;background:var(--panel);border-bottom:1px solid var(--border);transition:height .28s cubic-bezier(.4,0,.2,1)}
.ribbon-content.open{height:90px}
.ribbon-inner{display:flex;align-items:center;padding:8px 14px;gap:8px;height:90px;overflow-x:auto}
/* лента «Вид»: секция настроек (тема, сетка, магнит, подсветка точек) */
#rib-view.open{height:auto;max-height:min(52vh,440px)}
#rib-view .ribbon-inner{height:auto;max-height:inherit;align-items:flex-start;overflow-y:auto}
#viewSettingsBox{width:340px;flex:0 0 auto;margin:0}
#rib-view label{display:flex;justify-content:space-between;align-items:center;gap:8px;margin:4px 0;font-size:var(--font-small);color:var(--muted)}
#rib-view input[type=number]{width:100px}
#rib-view hr{border:none;border-top:1px solid var(--border);margin:8px 0}
.ribbon-group{display:flex;flex-direction:column;align-items:center;gap:4px;padding:0 12px;border-right:1px solid var(--border);flex-shrink:0}
.ribbon-group:last-child{border-right:none}
.ribbon-group-label{font-size:9px;color:var(--muted);text-transform:uppercase;letter-spacing:.5px;margin-top:auto;white-space:nowrap}
.ribbon-group-items{display:flex;align-items:center;gap:4px;flex-wrap:wrap;justify-content:center}
.rib-btn{display:flex;flex-direction:column;align-items:center;gap:2px;padding:5px 7px;border-radius:var(--radius-sm);min-width:48px;transition:all .15s;font-size:10px;color:var(--muted)}
.rib-btn:hover{background:var(--btnh);color:var(--text)}
.rib-btn.active{background:var(--accent-soft);color:var(--accent)}
.rib-btn svg{width:18px;height:18px}
.rib-btn span{white-space:nowrap}
.tf-btn{padding:3px 8px;border-radius:var(--radius-sm);font-size:11px;color:var(--muted);transition:all .15s;font-weight:500}
.tf-btn:hover{color:var(--text);background:var(--btnh)}
.tf-btn.active{color:var(--accent);background:var(--accent-soft)}

/* MAIN AREA */
.main-area{display:flex;flex:1;min-height:0}
#leftcol{flex:1;display:flex;flex-direction:column;min-width:0;min-height:0;overflow:hidden}
#hint{padding:2px 10px;font-size:var(--font-tiny);color:var(--muted);background:var(--card);border-bottom:1px solid var(--border);white-space:nowrap;overflow:hidden;flex-shrink:0}
#wrap{flex:1;position:relative;min-height:0;overflow:hidden}
/* touch-action:none обязателен: без него браузер на жесте pinch вместо нашего зума
   масштабирует страницу целиком, а одиночный палец тянет скролл вместо панорамы. */
#chart{position:absolute;inset:0;cursor:crosshair;touch-action:none}
/* Пилюля подсказки жестов: pointer-events:none обязателен, иначе подсказка перехватывала
   бы касания внизу экрана и ломала панораму в том месте, где её читают. z-index выше
   #authOverlay (9999): на узком экране форма входа растягивается почти во всю высоту и
   накрывала подсказку своим слоем — владелец видел это как «текст не на верхнем слое». */
#welcomeHint{position:fixed;left:50%;transform:translateX(-50%);bottom:10px;z-index:10000;padding:5px 12px;border-radius:999px;background:rgba(10,14,20,.55);color:#eaffff;font-size:var(--font-small);pointer-events:none;white-space:nowrap}
#statusbar{padding:4px 10px;background:var(--panel);border-top:1px solid var(--border);font-family:ui-monospace,Consolas,monospace;font-size:var(--font-small);color:var(--muted);white-space:nowrap;overflow:hidden;flex-shrink:0;line-height:1.6}

/* PANEL TABS */
#panel-tabs{display:flex;border-bottom:1px solid var(--border);flex-shrink:0}
.ptab{flex:1;padding:7px 8px;text-align:center;font-size:11px;font-weight:500;color:var(--muted);border:none;background:transparent;cursor:pointer;border-bottom:2px solid transparent;transition:all var(--transition)}
.ptab:hover{color:var(--text);background:var(--btnh)}
.ptab.active{color:var(--accent);border-bottom-color:var(--accent);background:var(--accent-soft)}

/* RIGHT PANEL — KEY FIX */
#panel{
  width:var(--panel-width);
  max-width:35vw;
  min-width:280px;
  background:var(--panel);
  border-left:1px solid var(--border);
  flex-shrink:0;
  display:flex;
  flex-direction:column;
  overflow:hidden;
}
#panel-scroll{
  flex:1;
  overflow-y:auto;
  overflow-x:hidden;
  padding:10px;
  scrollbar-width:thin;
}
#panel-scroll::-webkit-scrollbar{width:6px}
#panel-scroll::-webkit-scrollbar-track{background:transparent}
#panel-scroll::-webkit-scrollbar-thumb{background:var(--border);border-radius:3px}
#panel-scroll::-webkit-scrollbar-thumb:hover{background:var(--muted)}

#panel label{display:flex;justify-content:space-between;align-items:center;gap:8px;margin:4px 0;font-size:var(--font-small);color:var(--muted)}
#panel input[type=number]{width:100px}
#panel select{width:100%}
#panel .row{display:flex;gap:6px;margin:6px 0}
#panel .row button{flex:1}
#panel hr{border:none;border-top:1px solid var(--border);margin:8px 0}
details{margin:5px 0;border:1px solid var(--border);border-radius:6px;padding:5px 8px;background:var(--card)}
summary{cursor:pointer;font-size:var(--font-base);color:var(--text);outline:none}
button.panel-btn{background:var(--btn);color:var(--text);border:1px solid var(--border);border-radius:var(--radius-sm);padding:4px 10px;cursor:pointer;white-space:nowrap}
button.panel-btn:hover{background:var(--btnh)}
button.panel-btn.active{background:#0e4d64;border-color:#00e5ff;color:#eaffff}
button.panel-btn.feed-active{background:#006400;border-color:#00ff00;color:#00ff00;animation:feedPulse 1s ease-in-out infinite}
button.panel-btn.debug-active{background:#8b0000;border-color:#ff0000;color:#ff0000}
@keyframes feedPulse{0%,100%{opacity:1}50%{opacity:.7}}

/* TF ROW */
.tfrow{display:flex;gap:5px;align-items:center;font-size:var(--font-small);flex-wrap:wrap;padding:4px 5px;border-bottom:1px solid var(--border)}
.tfrow:last-child{border-bottom:none}
.tfrow .dot{width:10px;height:10px;border-radius:50%;flex-shrink:0}
.tfrow b{width:38px}
.tfrow label{margin:0;gap:3px;font-size:var(--font-tiny);justify-content:flex-start;color:var(--muted)}
.tfrow .mainRadio{accent-color:#00e5ff}
.tfrow.active{background:rgba(0,229,255,.06)}

/* ZZ GRID */
.zzgrid{display:grid;grid-template-columns:1fr 1fr;gap:3px 8px;font-size:var(--font-tiny);color:var(--muted)}
.zzgrid label{margin:2px 0;font-size:var(--font-tiny)}

/* HIER INFO */
.hierLevelInfo{margin:3px 0;padding:4px 8px;background:rgba(255,255,255,.03);border-radius:4px;border:1px solid transparent}
.hierLevelInfo[open]{border-color:#2b3a55}
.hierLevelInfo .angleInfo{font-size:var(--font-tiny);color:var(--muted);font-family:ui-monospace,monospace;margin-top:3px;line-height:1.5}
.zlineChecks{display:flex;gap:10px;margin-top:4px;align-items:center;flex-wrap:wrap}
.zlineChecks label{margin:0;gap:4px;font-size:var(--font-tiny);color:#ffd700;font-weight:600;justify-content:flex-start}
.zlineChecks label.mode{color:#9ad0ff}
.zlineChecks label.coeff{color:#7ee787}
.zlineChecks label.gann{color:#ffa500}
.zlineChecks label.gsq{color:#00ff88}
.statsBlock{font-size:9px;color:#7ee787;margin:2px 0 4px;padding:3px 6px;background:rgba(126,231,135,.06);border-radius:4px;line-height:1.5}
.statsBlock b{color:#9ad0ff}

/* SNAP POINTS */
.snap-points-list{max-height:300px;overflow-y:auto;font-size:10px;font-family:ui-monospace,monospace;margin-top:10px}
.snap-point-item{padding:6px 8px;margin:3px 0;background:var(--card);border-radius:4px;cursor:pointer;border-left:3px solid var(--highlight-color,#ff0000);transition:background .2s}
.snap-point-item:hover{background:var(--btnh)}
.snap-point-item .point-type{color:var(--highlight-color,#ff0000);font-weight:bold;font-size:11px}
.snap-point-item .point-coords{color:var(--muted);font-size:9px}
.snap-point-item .point-screen{color:#00e5ff;font-size:9px;margin-top:1px}

/* LINE RATIO */
.lineRatioBlock{margin:4px 0;font-size:var(--font-small)}
.ratioValue{color:#7ee787;font-weight:600;font-family:ui-monospace,monospace}

/* OBJECT TREE */
.obj-group{margin-bottom:4px}
.obj-group-header{display:flex;align-items:center;gap:5px;padding:4px 6px;border-radius:var(--radius-sm);cursor:pointer;font-size:11px;font-weight:600;color:var(--text);transition:background .1s;user-select:none}
.obj-group-header:hover{background:var(--btnh)}
.obj-group-header .chevron{width:10px;height:10px;transition:transform .2s;color:var(--muted);flex-shrink:0}
.obj-group-header.collapsed .chevron{transform:rotate(-90deg)}
.obj-group-header .count{margin-left:auto;font-size:9px;color:var(--muted);background:var(--btn);padding:1px 5px;border-radius:8px}
/* Заголовок связки разнотипных объектов внутри секции «Группы»: тише и с отступом, чтобы
   секция читалась как контейнер, а не как ещё одна типовая группа. */
.obj-group-sub{font-weight:500;padding-left:14px}
.obj-group-items{overflow:hidden;transition:max-height .25s}
.obj-group-items.collapsed{max-height:0!important}
.obj-item{display:flex;align-items:center;gap:4px;padding:3px 6px 3px 18px;border-radius:var(--radius-sm);cursor:pointer;font-size:11px;color:var(--text);transition:background .1s;border-left:2px solid transparent}
.obj-item:hover{background:var(--btnh)}
.obj-item.selected{background:var(--accent-soft);color:var(--accent);border-left-color:var(--accent)}
/* Множественное выделение (ctrl+клик по строкам для сборки группы). Рамка, а не фон: фон
   уже занят состоянием .selected, и две подсветки одним приёмом не отличили бы «объект выбран
   для правки свойств» от «объект отмечен в группу». Пунктир читается как временное состояние. */
.obj-item-multi{outline:1px dashed var(--accent);outline-offset:-1px}
/* Член группы разнотипных объектов: дополнительный отступ показывает подчинение её строке. */
.obj-item-nested{padding-left:30px}
/* Планка с кнопкой «Группировать выделенное»: видна только при непустом выделении. */
.obj-multi-bar{display:flex;gap:4px;margin-bottom:6px}
.obj-item .obj-icon{width:12px;height:12px;flex-shrink:0;display:flex;align-items:center;justify-content:center;font-size:10px}
.obj-item .obj-name{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.obj-item .obj-actions{display:flex;gap:1px;opacity:0;transition:opacity .15s}
.obj-item:hover .obj-actions{opacity:1}
.obj-act{width:18px;height:18px;display:flex;align-items:center;justify-content:center;border-radius:3px;color:var(--muted);font-size:9px;cursor:pointer}
.obj-act:hover{background:var(--btnh);color:var(--text)}
.obj-act.del{color:var(--red)}
.obj-act.del:hover{background:rgba(239,83,80,.15)}

/* OBJECT PROPERTIES */
.prop-section{margin-bottom:10px}
.prop-section-title{font-size:10px;color:var(--accent);text-transform:uppercase;letter-spacing:.5px;margin-bottom:6px;font-weight:600;padding-bottom:4px;border-bottom:1px solid var(--border)}
.prop-row{display:flex;align-items:center;justify-content:space-between;padding:3px 0;gap:6px}
.prop-label{font-size:11px;color:var(--muted);flex-shrink:0}
.prop-val{display:flex;align-items:center;gap:4px}
.prop-val input[type=color]{width:28px;height:20px;padding:0;border:1px solid var(--border);border-radius:3px;cursor:pointer;background:transparent}
.prop-val input[type=number]{width:60px;padding:2px 4px;font-size:11px}
.prop-val input[type=text]{width:100px;padding:2px 4px;font-size:11px}
.prop-val select{padding:2px 4px;font-size:11px}
.prop-actions{display:flex;gap:4px;margin-top:8px;padding-top:6px;border-top:1px solid var(--border)}
.prop-btn{flex:1;padding:4px;border:1px solid var(--border);background:var(--btn);color:var(--text);border-radius:var(--radius-sm);cursor:pointer;font-size:10px;text-align:center}
.prop-btn:hover{background:var(--btnh)}
.prop-btn.danger{color:var(--red);border-color:rgba(239,83,80,.3)}
.prop-btn.danger:hover{background:rgba(239,83,80,.1)}

/* PLANETARY STEPS — список групп и их линий в панели */
.panel-btn.danger{color:var(--red);border-color:rgba(239,83,80,.3)}
.panel-btn.danger:hover{background:rgba(239,83,80,.1)}
.psGroup{margin:5px 0;border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--card);overflow:hidden}
.psGroupHead{display:flex;align-items:center;gap:5px;padding:5px 7px;cursor:pointer;user-select:none}
.psGroupHead:hover{background:var(--btnh)}
.psGroupHead .groupArrow{font-size:9px;color:var(--muted);width:9px;transition:transform .15s}
.psGroup.collapsed .groupArrow{transform:rotate(-90deg)}
.psGroup.collapsed .psGroupBody{display:none}
.psGroupHead .groupTitle{flex:1;min-width:0;font:11px ui-monospace,Consolas,monospace;color:var(--text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.psGroupHead .groupCount{font-size:10px;color:var(--muted)}
.psGroupHead .groupDelBtn,.psDelBtn{background:none;border:1px solid var(--border);border-radius:3px;color:var(--muted);cursor:pointer;font-size:10px;padding:1px 5px;flex-shrink:0}
.psGroupHead .groupDelBtn:hover,.psDelBtn:hover{color:var(--red);border-color:rgba(239,83,80,.4)}
.psGroupBody{padding:3px 5px;border-top:1px solid var(--border)}
.psItem{display:flex;gap:5px;align-items:center;padding:3px 4px;margin:2px 0;border-radius:3px;font:11px ui-monospace,Consolas,monospace}
.psItem:hover{background:var(--btn)}
.psItem .psInfo{flex:1;min-width:0;line-height:1.35}
.psItem .psInfo .psTime{color:var(--text)}
.psItem .psInfo .psMeta{font-size:10px;color:var(--muted)}
.psCoeffBadge{display:inline-block;padding:1px 5px;border-radius:3px;color:#fff;font-size:10px;font-weight:700;white-space:nowrap}
.psEmpty{padding:8px;font-size:11px;color:var(--muted);text-align:center;font-style:italic}

/* FIBONACCI — списки панели: сетки, уровни и активные зоны.
   Имена классов пришли из прототипа (add/onepagehtml/fibonacci retracements.html): строки
   списков строит кодом ui/fib.js, поэтому в разметке index.html стоят только пустые
   контейнеры .grids-list/.fib-levels/.az-list.
   Цвета — переменные проекта вместо литералов песочницы (#3a1f1f/#6b2a2a/#ff6b6b): крестик
   удаления читается так же, как .obj-act.del в дереве объектов, и переживает смену темы
   (body.light), где тёмно-бордовый фон стал бы чёрным пятном. */
.fib-levels,.az-list,.grids-list{max-height:180px;overflow-y:auto;border:1px solid var(--border);border-radius:var(--radius-sm);padding:4px;margin:4px 0;background:var(--card)}
.list-item{display:flex;align-items:center;gap:4px;padding:2px 4px;font-size:var(--font-tiny);margin-bottom:2px}
.list-item input[type=checkbox]{margin:0}
.list-item .lbl{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* Образец линии: цветной прямоугольник рядом с подписью уровня или зоны — тот же приём,
   что цветная точка в строке дерева объектов: цвет уровня виден ещё до его отрисовки. */
.list-item .line-sample{width:20px;height:2px;display:inline-block;flex-shrink:0}
.list-item .del-btn{background:var(--btn);border:1px solid var(--border);color:var(--red);border-radius:3px;padding:0 5px;font-size:var(--font-tiny);cursor:pointer;margin-left:2px;flex-shrink:0}
.list-item .del-btn:hover{background:rgba(239,83,80,.15);border-color:rgba(239,83,80,.4)}
/* Пустой список: подпись вместо строк, иначе контейнер с границей выглядел бы сломанным. */
.list-empty{padding:4px;text-align:center;color:var(--muted);font-size:var(--font-tiny)}

/* СКРЫТИЕ ПРАВОЙ ПАНЕЛИ */
/* position:relative нужен только как якорь для абсолютно позиционированной кнопки;
   отдельным правилом, чтобы не переписывать основной блок #panel. */
#panel{position:relative}
/* Свёрнутая панель сжимается в рейку, а не в ноль: кнопка должна остаться кликабельной,
   иначе развернуть панель будет нечем. Вкладки и прокручиваемая область скрываются, а
   overflow:hidden у #panel уже есть, поэтому содержимое не вылезает. */
#panel.collapsed{width:20px;min-width:20px;max-width:20px}
#panel.collapsed #panel-tabs,#panel.collapsed #panel-scroll{display:none}
#panelCollapse{position:absolute;left:0;top:0;bottom:0;width:20px;padding:0;border:none;border-right:1px solid var(--border);background:transparent;color:var(--muted);cursor:pointer;font-size:13px;line-height:1;z-index:2;display:flex;align-items:center;justify-content:center}
#panelCollapse:hover{background:var(--btnh);color:var(--text)}
/* Стрелка смотрит в сторону действия: › когда панель можно скрыть, ‹ когда развернуть. */
#panel.collapsed #panelCollapse{border-right:none}

/* ЧЕРТЁЖНЫЕ ВЕБ-ШРИФТЫ (необязательно)
   В frontend/fonts/ лежит только README, шрифтовых файлов нет, и @font-face намеренно
   закомментированы: объявление с несуществующим url() дало бы 404 на каждой загрузке
   страницы и шум в консоли, а пользы никакой — canvas при недоступном шрифте молча
   рисует запасным.

   Чтобы включить: положить .woff2 в frontend/fonts/ и раскомментировать нужный блок,
   подставив реальное имя файла. Имя семейства в src и в font-family должно совпадать
   со значением поля «Имя веб-шрифта» в панели (txtWebfont) — именно его подставляет
   canvasFont() в stroke-font.js. Подробности — frontend/fonts/README.md.

   Лицензия: большинство чертёжных шрифтов (GOST type A/B, ISOCP) распространяются вместе
   с САПР и не являются свободными. Прежде чем класть файл в репозиторий, убедиться, что
   его лицензия это позволяет; иначе шрифт должен оставаться вне git.

@font-face{
  font-family:"GOST type A";
  src:url("../fonts/gost-type-a.woff2") format("woff2");
  font-weight:normal; font-style:normal; font-display:swap;
}
@font-face{
  font-family:"GOST type B";
  src:url("../fonts/gost-type-b.woff2") format("woff2");
  font-weight:normal; font-style:normal; font-display:swap;
}
*/

/* MOBILE */
#togglePanel{display:none;position:absolute;top:10px;right:10px;z-index:101;background:var(--btn);border:1px solid var(--border);border-radius:6px;width:36px;height:36px;align-items:center;justify-content:center;cursor:pointer;font-size:18px;padding:0}
#togglePanel:hover{background:var(--btnh)}
@media(max-width:767px){
  :root{--panel-width:min(320px,85vw)}
  #panel{position:absolute;right:0;top:0;bottom:0;z-index:100;box-shadow:-4px 0 12px rgba(0,0,0,.5);transform:translateX(100%);max-width:none}
  #panel.open{transform:translateX(0)}
  #togglePanel{display:flex!important}
}
@media(max-width:480px){
  :root{--font-base:11px;--axis-x:20px;--col-w:52px}
  .ribbon-inner{padding:4px 8px;gap:4px}
  .rib-btn{padding:4px 5px;min-width:40px}
}
