feat(stereo): сворачиваемый аккордеон панели управления (UX)

Панель за фазы A–C разрослась до ~14 всегда-раскрытых секций (длинный
скролл, тяжело ориентироваться). Сделал её удобнее:

- _stereoInitPanel() (вызов из _openStereo, идемпотентно) оборачивает
  контролы каждой секции в .st-acc-body; заголовки .gp-section-title →
  кликабельные .st-acc-hdr с шевроном; состояние секций в localStorage.
- Тройку фигурных секций (Многогранники/Правильные/Тела вращения) слил в
  одну «Фигуры» (под-метки .st-sublabel). По умолчанию открыты «Фигуры» и
  «Параметры», остальное свёрнуто.
- Кнопки «Развернуть всё / Свернуть всё» (stereoAccAll), клавиатура
  (Enter/Space на заголовке), role=button/tabindex.
- Только раскладка: ни один контрол/обработчик не изменён (узлы лишь
  перемещены в тело секции). Затронуты stereo.js + lab.css.

Верификация: node --check OK; headless DOM-смоук (мини-DOM + реальный
stereo.js в vm) 22/22: 12 сворачиваемых секций, тройка фигур слита (2
под-метки внутри «Фигуры»), пары заголовок→тело, дефолт-открытие,
тоггл+персист, развернуть/свернуть всё, идемпотентная переинициализация,
ни одна строка контролов не потеряна. Эмодзи/eval/new Function — 0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Maxim Dolgolyov
2026-06-17 17:48:08 +03:00
parent 9547a20875
commit 601f584181
3 changed files with 112 additions and 0 deletions
+25
View File
@@ -388,6 +388,31 @@
border-color: var(--violet) !important; color: var(--violet) !important; background: rgba(155,93,229,.12) !important;
}
/* ── stereo panel: collapsible accordion (UX) ── */
.stereo-panel .st-acc-toolbar { display: flex; gap: 6px; margin: 0 0 8px; }
.stereo-panel .st-acc-toolbar button {
flex: 1; padding: 5px 6px; border-radius: 8px; border: 1px solid var(--border);
background: transparent; color: var(--text-3);
font-family: 'Manrope', sans-serif; font-size: .62rem; font-weight: 700;
cursor: pointer; transition: all .12s;
}
.stereo-panel .st-acc-toolbar button:hover {
color: var(--violet); border-color: rgba(155,93,229,.4); background: rgba(155,93,229,.06);
}
.stereo-panel .st-acc-hdr {
cursor: pointer; justify-content: space-between; user-select: none;
margin: 3px 0; padding: 8px 8px; border-radius: 9px;
background: rgba(255,255,255,.025); transition: background .12s, color .12s;
}
.stereo-panel .st-acc-hdr::after { display: none; } /* drop the divider line */
.stereo-panel .st-acc-hdr:hover { background: rgba(155,93,229,.09); color: var(--violet); }
.stereo-panel .st-acc-hdr.open { color: var(--text-2); background: rgba(155,93,229,.06); }
.stereo-panel .st-acc-chev { display: flex; align-items: center; opacity: .6; transition: transform .18s; }
.stereo-panel .st-acc-chev svg { width: 13px; height: 13px; stroke: currentColor; stroke-width: 2.5; fill: none; }
.stereo-panel .st-acc-hdr.open .st-acc-chev { transform: rotate(180deg); }
.stereo-panel .st-acc-body { margin: 0 0 8px; padding: 0 1px; }
.stereo-panel .st-sublabel { opacity: .8; margin: 8px 0 6px; }
.gp-preset-group { margin-bottom: 8px; }
.gp-preset-label {
font-size: 0.68rem; font-weight: 700; text-transform: uppercase;