Files
Learn_System/frontend/labs-bodies.html
T
Maxim Dolgolyov 24403718bf feat(stereo): C1+C3 — плоскость как сечение + «натуральная величина»
Фаза C раунда «Конструктор» (C2 покрыта Фазой A, C4 отложена).

C1 — любую построенную плоскость можно показать сечением тела: клик по
плоскости в дереве (нормальный режим) → setSectionPlane: заливка
многоугольника + подписи вершин K,L,M… + площадь и периметр в readout-
панели. Удаление плоскости / очистка / смена фигуры сбрасывают сечение.

C3 — «Натуральная величина» сечения (getTrueShape): многоугольник сечения
разворачивается в свою плоскость (ортонормированный базис от нормали) с
сохранением истинных длин → 2D-SVG мини-панель со штриховкой (pattern),
подписями вершин, длинами сторон и S/P. Появляется автоматически при
активном сечении.

- StereoSim: _sectionPlaneId, setSectionPlane, _activeSectionPolygon,
  _sectionVertexLabel, getTrueShape; _drawPlaneObject заливает+подписывает
  активное сечение; getReadout добавляет S/P; getConstructions отдаёт
  sectionId + per-plane section; pickConstructObject в нормальном режиме
  тогглит сечение по плоскости.
- Панель: контейнер #construct-trueshape + подсказка; glue
  _stereoUpdateTrueShape (SVG-рендер) вызывается из _stereoUpdateUI; строки
  плоскостей в дереве всегда кликабельны, тег «(сечение)».

Верификация: node --check OK; headless-смоук 26/26 (квадрат y=2: S=16,P=16;
readout/дерево/тоггл; true-shape длины K,L,M,N=4, площадь=16; сохранение
длин и площади для прямого И наклонного сечения; 2D-shoelace=S; удаление/
очистка/setFigure сбрасывают сечение; dispose); эмодзи/eval/new Function — 0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 17:15:22 +03:00

4464 lines
356 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!-- ── GRAPH sim body ── -->
<div id="sim-graph" class="sim-body-wrap">
<!-- left panel -->
<div class="graph-panel">
<div class="gp-section-title">Функции</div>
<!-- fn 1 -->
<div style="--fn-color:var(--violet)">
<div class="fn-row">
<div class="fn-dot"></div>
<span class="fn-label">y =</span>
<input class="fn-input" id="fn0" placeholder="sin(x)" autocomplete="off" spellcheck="false" oninput="updateFn(0)" />
</div>
<div class="fn-preview" id="fn0-prev"></div>
<div class="fn-err" id="fn0-err">Синтаксическая ошибка</div>
</div>
<!-- fn 2 -->
<div style="--fn-color:var(--cyan)">
<div class="fn-row">
<div class="fn-dot"></div>
<span class="fn-label">y =</span>
<input class="fn-input" id="fn1" placeholder="x^2 - 4" autocomplete="off" spellcheck="false" oninput="updateFn(1)" />
</div>
<div class="fn-preview" id="fn1-prev"></div>
<div class="fn-err" id="fn1-err">Синтаксическая ошибка</div>
</div>
<!-- fn 3 -->
<div style="--fn-color:var(--pink)">
<div class="fn-row">
<div class="fn-dot"></div>
<span class="fn-label">y =</span>
<input class="fn-input" id="fn2" placeholder="tg(x)" autocomplete="off" spellcheck="false" oninput="updateFn(2)" />
</div>
<div class="fn-preview" id="fn2-prev"></div>
<div class="fn-err" id="fn2-err">Синтаксическая ошибка</div>
</div>
<div style="margin-top:8px"></div>
<div class="gp-section-title">Примеры</div>
<div class="gp-preset-group">
<div class="gp-preset-label">Линейные / степенные</div>
<div class="presets-wrap">
<button class="preset-btn" onclick="applyPreset('2x-1')">2x1</button>
<button class="preset-btn" onclick="applyPreset('x^2')"></button>
<button class="preset-btn" onclick="applyPreset('x^2-4')">x²−4</button>
<button class="preset-btn" onclick="applyPreset('x^3-3x')">x³−3x</button>
<button class="preset-btn" onclick="applyPreset('x^4-4x^2+3')">x⁴−4x²+3</button>
</div>
</div>
<div class="gp-preset-group">
<div class="gp-preset-label">Тригонометрия</div>
<div class="presets-wrap">
<button class="preset-btn" onclick="applyPreset('sin(x)')">sin x</button>
<button class="preset-btn" onclick="applyPreset('cos(x)')">cos x</button>
<button class="preset-btn" onclick="applyPreset('tg(x)')">tg x</button>
<button class="preset-btn" onclick="applyPreset('sin(2x)')">sin 2x</button>
<button class="preset-btn" onclick="applyPreset('x*sin(x)')">x·sin x</button>
<button class="preset-btn" onclick="applyPreset('sin(x)/x')">sin(x)/x</button>
</div>
</div>
<div class="gp-preset-group">
<div class="gp-preset-label">Показательные / логарифмы</div>
<div class="presets-wrap">
<button class="preset-btn" onclick="applyPreset('exp(x)')"></button>
<button class="preset-btn" onclick="applyPreset('2^x')"></button>
<button class="preset-btn" onclick="applyPreset('ln(x)')">ln x</button>
<button class="preset-btn" onclick="applyPreset('log(x)')">log x</button>
</div>
</div>
<div class="gp-preset-group">
<div class="gp-preset-label">Прочие</div>
<div class="presets-wrap">
<button class="preset-btn" onclick="applyPreset('sqrt(x)')">√x</button>
<button class="preset-btn" onclick="applyPreset('1/x')">1/x</button>
<button class="preset-btn" onclick="applyPreset('abs(x)')">|x|</button>
<button class="preset-btn" onclick="applyPreset('floor(x)')">⌊x⌋</button>
<button class="preset-btn" onclick="applyPreset('1/(1+exp(-x))')">σ(x)</button>
</div>
</div>
<div style="margin-top:auto;padding-top:14px"></div>
<button class="gp-btn" onclick="clearAll()">
<svg viewBox="0 0 24 24" fill="none"><polyline points="3 6 5 6 21 6"/><path d="M19 6l-1 14H6L5 6"/><path d="M10 11v6"/><path d="M14 11v6"/><path d="M9 6V4h6v2"/></svg>
Очистить всё
</button>
</div>
<!-- canvas area -->
<div class="graph-canvas-outer">
<div class="graph-canvas-wrap">
<canvas id="graph-canvas"></canvas>
</div>
<div class="graph-info-bar" id="graph-info-bar">
<div class="info-coord">
<span class="ic-label">x =</span>
<span class="ic-val" id="info-x"></span>
</div>
<div class="info-fn-val">
<div class="info-fn-dot" style="background:var(--violet);box-shadow:0 0 5px var(--violet)"></div>
<span class="ic-label">y₁ =</span>
<span class="ic-val" id="info-y0"></span>
</div>
<div class="info-fn-val">
<div class="info-fn-dot" style="background:var(--cyan);box-shadow:0 0 5px var(--cyan)"></div>
<span class="ic-label">y₂ =</span>
<span class="ic-val" id="info-y1"></span>
</div>
<div class="info-fn-val">
<div class="info-fn-dot" style="background:var(--pink);box-shadow:0 0 5px var(--pink)"></div>
<span class="ic-label">y₃ =</span>
<span class="ic-val" id="info-y2"></span>
</div>
<div class="info-hint">Скролл — зум · Перетащи — панорама</div>
</div>
</div>
</div><!-- /#sim-graph -->
<!-- ══ ЭЛЕКТРОМАГНИТНЫЕ ПОЛЯ (EMField) ══
replaces sim-mag + sim-coulomb -->
<div id="sim-emfield" class="sim-proj-wrap" style="display:none">
<div class="sim-body-wrap">
<div class="proj-panel" style="width:258px;gap:0">
<!-- Mode tabs -->
<div style="display:flex;gap:4px;margin-bottom:12px">
<button id="em-tab-E" class="mag-mode-btn active" onclick="emSwitchMode('E')" style="flex:1;font-size:.72rem">Электрическое</button>
<button id="em-tab-B" class="mag-mode-btn" onclick="emSwitchMode('B')" style="flex:1;font-size:.72rem">Магнитное</button>
<button id="em-tab-combined" class="mag-mode-btn" onclick="emSwitchMode('combined')" style="flex:1;font-size:.72rem">Комбо</button>
</div>
<!-- E controls -->
<div id="em-ctrl-E">
<div class="gp-section-title" style="margin-bottom:6px">Заряд</div>
<div style="display:flex;gap:6px;margin-bottom:10px">
<button class="mag-mode-btn active" id="em-sign-pos" onclick="emSign(1)" style="flex:1">
<span style="font-size:1.2rem;font-weight:900;color:#EF476F">+</span> Полож.
</button>
<button class="mag-mode-btn" id="em-sign-neg" onclick="emSign(-1)" style="flex:1">
<span style="font-size:1.2rem;font-weight:900;color:#4CC9F0">&#8722;</span> Отриц.
</button>
</div>
<div class="gp-section-title" style="margin-bottom:6px">Слои E</div>
<div style="display:flex;flex-direction:column;gap:5px;margin-bottom:10px">
<label class="tri-layer-row active" onclick="emLayer('E','colormap',this)">
<span class="tri-dot" style="background:linear-gradient(90deg,#EF476F,#9B5DE5,#4CC9F0)"></span>
<span class="tri-layer-name">Карта потенциала</span>
<span class="tri-layer-hint" style="color:rgba(255,255,255,.4)">V</span>
<span class="tri-toggle" style="background:var(--violet)"><span style="display:block;width:12px;height:12px;border-radius:50%;background:#fff;margin:2px;margin-left:14px"></span></span>
</label>
<label class="tri-layer-row active" onclick="emLayer('E','fieldlines',this)">
<span class="tri-dot" style="background:rgba(255,255,255,0.8)"></span>
<span class="tri-layer-name">Линии поля E</span>
<span class="tri-layer-hint" style="color:rgba(255,255,255,.4)">E</span>
<span class="tri-toggle" style="background:var(--violet)"><span style="display:block;width:12px;height:12px;border-radius:50%;background:#fff;margin:2px;margin-left:14px"></span></span>
</label>
<label class="tri-layer-row" onclick="emLayer('E','vectors',this)">
<span class="tri-dot" style="background:rgba(255,255,255,0.4)"></span>
<span class="tri-layer-name">Векторы E</span>
<span class="tri-toggle"><span style="display:block;width:12px;height:12px;border-radius:50%;background:#fff;margin:2px;margin-left:2px"></span></span>
</label>
<label class="tri-layer-row active" onclick="emLayer('E','equipotentials',this)">
<span class="tri-dot" style="background:rgba(255,255,255,0.5)"></span>
<span class="tri-layer-name">Эквипотенциали</span>
<span class="tri-layer-hint" style="color:rgba(255,255,255,.3)">V=const</span>
<span class="tri-toggle" style="background:var(--violet)"><span style="display:block;width:12px;height:12px;border-radius:50%;background:#fff;margin:2px;margin-left:14px"></span></span>
</label>
<label class="tri-layer-row" onclick="emLayer('E','forces',this)">
<span class="tri-dot" style="background:#FFD166;box-shadow:0 0 5px #FFD166"></span>
<span class="tri-layer-name">Силы Кулона</span>
<span class="tri-layer-hint" style="color:#FFD166">F</span>
<span class="tri-toggle"><span style="display:block;width:12px;height:12px;border-radius:50%;background:#fff;margin:2px;margin-left:2px"></span></span>
</label>
</div>
<div class="gp-section-title" style="margin-bottom:6px">Поверхность Гаусса</div>
<label class="tri-layer-row" id="em-gauss-row" onclick="emGaussToggle(this)" style="margin-bottom:6px">
<span class="tri-dot" style="background:#34d399;box-shadow:0 0 5px #34d399"></span>
<span class="tri-layer-name">Поток Гаусса &#934;&#8336;</span>
<span class="tri-layer-hint" style="color:#34d399">&#934;=q/&#949;&#8320;</span>
<span class="tri-toggle"><span style="display:block;width:12px;height:12px;border-radius:50%;background:#fff;margin:2px;margin-left:2px"></span></span>
</label>
<div class="param-block" id="em-gauss-r-block" style="display:none;margin-bottom:10px">
<div class="param-header">
<span class="param-name">Радиус поверхности</span>
<span class="param-val" id="em-gaussR-val">70 пкс</span>
</div>
<input type="range" class="param-slider" id="sl-emGaussR" min="20" max="200" value="70" oninput="emGaussRChange()">
</div>
<div class="gp-section-title" style="margin-bottom:6px">Пресеты E</div>
<div style="display:flex;flex-wrap:wrap;gap:5px;margin-bottom:10px">
<button class="proj-preset-chip" onclick="emPresetE('dipole')">Диполь &#177;</button>
<button class="proj-preset-chip" onclick="emPresetE('equal')">Два + заряда</button>
<button class="proj-preset-chip" onclick="emPresetE('quadrupole')">Квадруполь</button>
<button class="proj-preset-chip" onclick="emPresetE('ring')">Кольцо</button>
</div>
</div><!-- /#em-ctrl-E -->
<!-- B controls -->
<div id="em-ctrl-B" style="display:none">
<div class="gp-section-title" style="margin-bottom:6px">Провод</div>
<div style="display:flex;gap:6px;margin-bottom:10px">
<button class="mag-mode-btn active" id="em-dir-out" onclick="emWireDir('out')" style="flex:1">
<span style="font-size:1.2rem;font-weight:900;color:#06D6E0">&#8226;</span> Ток на нас
</button>
<button class="mag-mode-btn" id="em-dir-in" onclick="emWireDir('in')" style="flex:1">
<span style="font-size:1.1rem;font-weight:900;color:#F15BB5">&#215;</span> Ток от нас
</button>
</div>
<div class="param-block" style="margin-bottom:10px">
<div class="param-header">
<span class="param-name">Сила тока I</span>
<span class="param-val" id="em-curI-val">6 А</span>
</div>
<input type="range" class="param-slider" id="sl-emI" min="1" max="20" value="6" oninput="emCurrentChange()">
</div>
<div class="gp-section-title" style="margin-bottom:6px">Слои B</div>
<div style="display:flex;flex-direction:column;gap:5px;margin-bottom:10px">
<label class="tri-layer-row active" onclick="emLayer('B','colormap',this)">
<span class="tri-dot" style="background:linear-gradient(90deg,#9B5DE5,#06D6E0,#F15BB5)"></span>
<span class="tri-layer-name">Карта поля B</span>
<span class="tri-layer-hint" style="color:rgba(255,255,255,.4)">hue=угол</span>
<span class="tri-toggle" style="background:var(--violet)"><span style="display:block;width:12px;height:12px;border-radius:50%;background:#fff;margin:2px;margin-left:14px"></span></span>
</label>
<label class="tri-layer-row active" onclick="emLayer('B','fieldlines',this)">
<span class="tri-dot" style="background:var(--cyan);box-shadow:0 0 5px var(--cyan)"></span>
<span class="tri-layer-name">Силовые линии B</span>
<span class="tri-layer-hint" style="color:rgba(255,255,255,.4)">+ стрелки</span>
<span class="tri-toggle" style="background:var(--violet)"><span style="display:block;width:12px;height:12px;border-radius:50%;background:#fff;margin:2px;margin-left:14px"></span></span>
</label>
<label class="tri-layer-row" onclick="emLayer('B','vectors',this)">
<span class="tri-dot" style="background:var(--violet);box-shadow:0 0 5px var(--violet)"></span>
<span class="tri-layer-name">Векторное поле B</span>
<span class="tri-toggle"><span style="display:block;width:12px;height:12px;border-radius:50%;background:#fff;margin:2px;margin-left:2px"></span></span>
</label>
</div>
<div class="gp-section-title" style="margin-bottom:6px">Проводник в поле</div>
<label class="tri-layer-row" id="em-cond-row" onclick="emCondToggle(this)" style="margin-bottom:6px">
<span class="tri-dot" style="background:#fbbf24;box-shadow:0 0 5px #fbbf24"></span>
<span class="tri-layer-name">Проводник (Ампер)</span>
<span class="tri-layer-hint" style="color:#fbbf24">F=IL&#215;B</span>
<span class="tri-toggle"></span>
</label>
<div class="param-block" id="em-cond-I-block" style="display:none;margin-bottom:10px">
<div class="param-header">
<span class="param-name">Ток проводника I&#42;</span>
<span class="param-val" id="em-condI-val">8 А</span>
</div>
<input type="range" class="param-slider" id="sl-emCondI" min="1" max="20" value="8" oninput="emCondCurrentChange()">
</div>
<div class="gp-section-title" style="margin-bottom:6px">Магнитный поток</div>
<label class="tri-layer-row" id="em-flux-row" onclick="emFluxToggle(this)" style="margin-bottom:10px">
<span class="tri-dot" style="background:#34d399;box-shadow:0 0 5px #34d399"></span>
<span class="tri-layer-name">Индикатор потока</span>
<span class="tri-layer-hint" style="color:#34d399">&#934;=B&#183;S</span>
<span class="tri-toggle"></span>
</label>
<div class="gp-section-title" style="margin-bottom:6px">ЭДС индукции</div>
<label class="tri-layer-row" id="em-rod-row" onclick="emRodToggle(this)" style="margin-bottom:6px">
<span class="tri-dot" style="background:#f59e0b;box-shadow:0 0 5px #f59e0b"></span>
<span class="tri-layer-name">Движущийся проводник</span>
<span class="tri-layer-hint" style="color:#f59e0b">&#949;=&#8747;vBdl</span>
<span class="tri-toggle"><span style="display:block;width:12px;height:12px;border-radius:50%;background:#fff;margin:2px;margin-left:2px"></span></span>
</label>
<div class="gp-section-title" style="margin-bottom:6px">Пресеты B</div>
<div style="display:flex;flex-wrap:wrap;gap:5px;margin-bottom:10px">
<button class="proj-preset-chip" onclick="emPresetB('single')">Один провод</button>
<button class="proj-preset-chip" onclick="emPresetB('parallel')">Параллельные</button>
<button class="proj-preset-chip" onclick="emPresetB('anti')">Антипарал.</button>
<button class="proj-preset-chip" onclick="emPresetB('solenoid')">Соленоид</button>
<button class="proj-preset-chip" onclick="emPresetB('quadrupole')">Квадруполь</button>
<button class="proj-preset-chip" onclick="emPresetB('ring')">Кольцо</button>
<button class="proj-preset-chip" onclick="emPresetB('toroid')">Тороид</button>
</div>
</div><!-- /#em-ctrl-B -->
<!-- combined extra -->
<div id="em-ctrl-combined" style="display:none">
<div class="gp-section-title" style="margin-bottom:6px">Тип добавляемого</div>
<div style="display:flex;gap:6px;margin-bottom:10px">
<button class="mag-mode-btn active" id="em-add-charge" onclick="emAddTypeSwitch('charge')" style="flex:1;font-size:.72rem">Заряд</button>
<button class="mag-mode-btn" id="em-add-wire" onclick="emAddTypeSwitch('wire')" style="flex:1;font-size:.72rem">Провод</button>
</div>
</div>
<!-- Particle -->
<div class="gp-section-title" style="margin-bottom:6px">Частица</div>
<label class="tri-layer-row" id="em-particle-row" onclick="emParticle(this)" style="margin-bottom:10px">
<span class="tri-dot" style="background:#ffff50;box-shadow:0 0 5px #ffff50"></span>
<span class="tri-layer-name">Заряженная частица</span>
<span class="tri-layer-hint" style="color:#ffff50">Лоренц</span>
<span class="tri-toggle"></span>
</label>
<div style="margin-top:auto;padding-top:6px;display:flex;flex-direction:column;gap:5px">
<div class="tri-stats-grid" style="grid-template-columns:auto 1fr">
<div style="font-size:.68rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--text-3)">Зарядов</div>
<div class="tri-stat-v" id="embar-charges" style="color:#EF476F">0</div>
<div style="font-size:.68rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--text-3)">Проводов</div>
<div class="tri-stat-v" id="embar-wires" style="color:var(--cyan)">0</div>
<div style="font-size:.68rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--text-3)">Курсор |E|</div>
<div class="tri-stat-v" id="embar-curE" style="color:rgba(255,255,255,0.6)">&#8212;</div>
<div style="font-size:.68rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--text-3)">Курсор V</div>
<div class="tri-stat-v" id="embar-curV" style="color:rgba(255,255,255,0.5)">&#8212;</div>
<div style="font-size:.68rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--text-3)">Курсор |B|</div>
<div class="tri-stat-v" id="embar-curB" style="color:var(--cyan)">&#8212;</div>
<div style="font-size:.68rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--text-3)">&#934;&#8336; Гаусса</div>
<div class="tri-stat-v" id="embar-gauss" style="color:#34d399">&#8212;</div>
<div style="font-size:.68rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--text-3)">ЭДС &#949;</div>
<div class="tri-stat-v" id="embar-rod" style="color:#f59e0b">&#8212;</div>
</div>
<div style="font-size:0.68rem;color:var(--text-3);text-align:center;line-height:1.6;margin-top:4px">
Клик &#8212; добавить &nbsp;&#183;&nbsp; ПКМ / 2&#215;клик &#8212; удалить<br>
Перетащи источник для перемещения
</div>
</div>
</div><!-- /.proj-panel -->
<div class="proj-canvas-outer">
<canvas id="emfield-canvas" style="display:block;position:absolute;top:0;left:0;width:100%;height:100%;cursor:crosshair"></canvas>
</div>
</div><!-- /.sim-body-wrap -->
<div class="proj-stats-bar">
<div class="pstat"><div class="pstat-label">Зарядов</div><div class="pstat-val" id="embar-charges-bar" style="color:#EF476F">0</div></div>
<div class="pstat"><div class="pstat-label">Проводов</div><div class="pstat-val" id="embar-wires-bar" style="color:var(--cyan)">0</div></div>
<div class="pstat"><div class="pstat-label">Частица</div><div class="pstat-val" id="embar-particle">выкл</div></div>
<div class="pstat"><div class="pstat-label">|E| курсора</div><div class="pstat-val" id="embar-curE-bar" style="color:#EF476F">&#8212;</div></div>
<div class="pstat"><div class="pstat-label">|B| курсора</div><div class="pstat-val" id="embar-curB-bar" style="color:var(--cyan)">&#8212;</div></div>
<div class="pstat"><div class="pstat-label">Сила Ампера</div><div class="pstat-val" id="embar-ampere" style="color:#fbbf24">&#8212;</div></div>
<div class="pstat"><div class="pstat-label">Поток &#934;</div><div class="pstat-val" id="embar-flux" style="color:#34d399">&#8212;</div></div>
<div class="pstat"><div class="pstat-label">&#934;&#8336; Гаусса</div><div class="pstat-val" id="embar-gauss-bar" style="color:#34d399">&#8212;</div></div>
<div class="pstat"><div class="pstat-label">ЭДС &#949;</div><div class="pstat-val" id="embar-rod-bar" style="color:#f59e0b">&#8212;</div></div>
</div>
</div><!-- /#sim-emfield -->
<!-- ── TRIANGLE sim body ── -->
<div id="sim-tri" class="sim-proj-wrap" style="display:none">
<div class="sim-body-wrap">
<!-- left panel -->
<div class="proj-panel" style="width:240px;gap:0">
<!-- Layer toggles -->
<div class="gp-section-title" style="margin-bottom:10px">Слои</div>
<div style="display:flex;flex-direction:column;gap:5px;margin-bottom:10px">
<label class="tri-layer-row" onclick="triToggle('medians',this)">
<span class="tri-dot" style="background:#22d55e;box-shadow:0 0 5px #22d55e"></span>
<span class="tri-layer-name">Медианы</span>
<span class="tri-layer-hint" style="color:#22d55e">G — центроид</span>
<span class="tri-toggle" id="tl-medians"></span>
</label>
<label class="tri-layer-row" onclick="triToggle('altitudes',this)">
<span class="tri-dot" style="background:#f59e0b;box-shadow:0 0 5px #f59e0b"></span>
<span class="tri-layer-name">Высоты</span>
<span class="tri-layer-hint" style="color:#f59e0b">H — ортоцентр</span>
<span class="tri-toggle" id="tl-altitudes"></span>
</label>
<label class="tri-layer-row" onclick="triToggle('bisectors',this)">
<span class="tri-dot" style="background:#ec4899;box-shadow:0 0 5px #ec4899"></span>
<span class="tri-layer-name">Биссектрисы</span>
<span class="tri-layer-hint" style="color:#ec4899">I — инцентр</span>
<span class="tri-toggle" id="tl-bisectors"></span>
</label>
<label class="tri-layer-row" onclick="triToggle('circumcircle',this)">
<span class="tri-dot" style="background:var(--pink);box-shadow:0 0 5px var(--pink)"></span>
<span class="tri-layer-name">Описанная окружность</span>
<span class="tri-layer-hint" style="color:var(--pink)">O, R</span>
<span class="tri-toggle" id="tl-circumcircle"></span>
</label>
<label class="tri-layer-row" onclick="triToggle('incircle',this)">
<span class="tri-dot" style="background:var(--cyan);box-shadow:0 0 5px var(--cyan)"></span>
<span class="tri-layer-name">Вписанная окружность</span>
<span class="tri-layer-hint" style="color:var(--cyan)">I, r</span>
<span class="tri-toggle" id="tl-incircle"></span>
</label>
<label class="tri-layer-row" onclick="triToggle('eulerLine',this)">
<span class="tri-dot" style="background:rgba(255,255,100,0.8);box-shadow:0 0 5px yellow"></span>
<span class="tri-layer-name">Прямая Эйлера</span>
<span class="tri-layer-hint" style="color:rgba(255,255,100,0.7)">O<svg class="ic" viewBox="0 0 24 24"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg>G<svg class="ic" viewBox="0 0 24 24"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg>H</span>
<span class="tri-toggle" id="tl-eulerLine"></span>
</label>
</div>
<div class="gp-section-title" style="margin-bottom:10px">Теоремы</div>
<div style="display:flex;flex-direction:column;gap:5px;margin-bottom:10px">
<label class="tri-layer-row" onclick="triToggle('sineLaw',this)">
<span class="tri-dot" style="background:#60a5fa;box-shadow:0 0 5px #60a5fa"></span>
<span class="tri-layer-name">Теорема синусов</span>
<span class="tri-layer-hint" style="color:#60a5fa">a/sinA = 2R</span>
<span class="tri-toggle" id="tl-sineLaw"></span>
</label>
<label class="tri-layer-row" onclick="triToggle('cosineLaw',this)">
<span class="tri-dot" style="background:#fbbf24;box-shadow:0 0 5px #fbbf24"></span>
<span class="tri-layer-name">Теорема косинусов</span>
<span class="tri-layer-hint" style="color:#fbbf24">c²=a²+b²−2ab·cosC</span>
<span class="tri-toggle" id="tl-cosineLaw"></span>
</label>
<label class="tri-layer-row" onclick="triToggle('pythagorean',this)">
<span class="tri-dot" style="background:#EF476F;box-shadow:0 0 5px #EF476F"></span>
<span class="tri-layer-name">Теорема Пифагора</span>
<span class="tri-layer-hint" style="color:#EF476F">a²+b² = c²</span>
<span class="tri-toggle" id="tl-pythagorean"></span>
</label>
</div>
<!-- Stats -->
<div class="gp-section-title" style="margin-bottom:8px">Стороны</div>
<div class="tri-stats-grid" style="margin-bottom:10px">
<span class="tri-stat-k" style="color:var(--violet)">a</span><span class="tri-stat-v" id="ts-a"></span>
<span class="tri-stat-k" style="color:var(--cyan)">b</span><span class="tri-stat-v" id="ts-b"></span>
<span class="tri-stat-k" style="color:var(--pink)">c</span><span class="tri-stat-v" id="ts-c"></span>
</div>
<div class="gp-section-title" style="margin-bottom:8px">Углы</div>
<div class="tri-stats-grid" style="margin-bottom:10px">
<span class="tri-stat-k" style="color:var(--violet)">∠A</span><span class="tri-stat-v" id="ts-A"></span>
<span class="tri-stat-k" style="color:var(--cyan)">∠B</span><span class="tri-stat-v" id="ts-B"></span>
<span class="tri-stat-k" style="color:var(--pink)">∠C</span><span class="tri-stat-v" id="ts-C"></span>
</div>
<div class="gp-section-title" style="margin-bottom:8px">Вычисляемые</div>
<div class="tri-stats-grid" style="margin-bottom:10px">
<span class="tri-stat-k">S</span><span class="tri-stat-v" id="ts-S"></span>
<span class="tri-stat-k">P</span><span class="tri-stat-v" id="ts-P"></span>
<span class="tri-stat-k">R</span><span class="tri-stat-v" id="ts-R"></span>
<span class="tri-stat-k">r</span><span class="tri-stat-v" id="ts-r"></span>
</div>
<!-- Type badge -->
<div style="margin-top:auto;padding-top:10px">
<div style="font-size:0.62rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--text-3);margin-bottom:6px">Тип</div>
<div id="ts-type" style="
padding:8px 14px;border-radius:12px;
background:rgba(155,93,229,0.12);border:1.5px solid rgba(155,93,229,0.25);
font-family:'Manrope',sans-serif;font-size:0.82rem;font-weight:700;
color:var(--violet);text-align:center;
"></div>
<div style="margin-top:8px;font-size:0.7rem;color:var(--text-3);text-align:center;line-height:1.5">
Перетащи вершины<br>A, B, C для изменения
</div>
</div>
</div><!-- /.proj-panel -->
<!-- canvas -->
<div class="proj-canvas-outer">
<canvas id="tri-canvas"></canvas>
</div>
</div><!-- /.sim-body-wrap -->
<!-- stats bar -->
<div class="proj-stats-bar">
<div class="pstat">
<div class="pstat-label">Сторона a</div>
<div class="pstat-val" id="tbar-a"></div>
</div>
<div class="pstat">
<div class="pstat-label">Сторона b</div>
<div class="pstat-val" id="tbar-b"></div>
</div>
<div class="pstat">
<div class="pstat-label">Сторона c</div>
<div class="pstat-val" id="tbar-c"></div>
</div>
<div class="pstat">
<div class="pstat-label">Площадь S</div>
<div class="pstat-val" id="tbar-S"></div>
</div>
<div class="pstat">
<div class="pstat-label">Периметр P</div>
<div class="pstat-val" id="tbar-P"></div>
</div>
<div class="pstat">
<div class="pstat-label">R / r</div>
<div class="pstat-val" id="tbar-Rr"></div>
</div>
</div>
</div><!-- /#sim-tri -->
<!-- ══════════════════════════════════════════════
ТРИГОНОМЕТРИЧЕСКАЯ ОКРУЖНОСТЬ
══════════════════════════════════════════════ -->
<div id="sim-trigcircle" class="sim-proj-wrap" style="display:none">
<div class="sim-body-wrap">
<!-- left panel -->
<div class="proj-panel" style="width:240px;gap:0">
<!-- Function toggles -->
<div class="gp-section-title" style="margin-bottom:10px">Отрезки</div>
<div style="display:flex;flex-direction:column;gap:5px;margin-bottom:14px">
<label class="tri-layer-row active" onclick="trigToggle('sin',this)">
<span class="tri-dot" style="background:#EF476F;box-shadow:0 0 5px #EF476F"></span>
<span class="tri-layer-name">sin</span>
<span class="tri-layer-hint" style="color:#EF476F">вертикаль</span>
<span class="tri-toggle" id="trig-tl-sin"></span>
</label>
<label class="tri-layer-row active" onclick="trigToggle('cos',this)">
<span class="tri-dot" style="background:var(--cyan);box-shadow:0 0 5px var(--cyan)"></span>
<span class="tri-layer-name">cos</span>
<span class="tri-layer-hint" style="color:var(--cyan)">горизонталь</span>
<span class="tri-toggle" id="trig-tl-cos"></span>
</label>
<label class="tri-layer-row" onclick="trigToggle('tan',this)">
<span class="tri-dot" style="background:#FFD166;box-shadow:0 0 5px #FFD166"></span>
<span class="tri-layer-name">tg</span>
<span class="tri-layer-hint" style="color:#FFD166">касательная</span>
<span class="tri-toggle" id="trig-tl-tan"></span>
</label>
<label class="tri-layer-row" onclick="trigToggle('cot',this)">
<span class="tri-dot" style="background:#7BF5A4;box-shadow:0 0 5px #7BF5A4"></span>
<span class="tri-layer-name">ctg</span>
<span class="tri-layer-hint" style="color:#7BF5A4">кокасательная</span>
<span class="tri-toggle" id="trig-tl-cot"></span>
</label>
</div>
<!-- Graph function selector -->
<div class="gp-section-title" style="margin-bottom:8px">График</div>
<div style="display:flex;flex-wrap:wrap;gap:5px;margin-bottom:14px">
<button class="trig-fn-btn active" onclick="trigSetGraphFn('sin',this)" style="--fc:#EF476F">sin</button>
<button class="trig-fn-btn" onclick="trigSetGraphFn('cos',this)" style="--fc:#06D6E0">cos</button>
<button class="trig-fn-btn" onclick="trigSetGraphFn('tan',this)" style="--fc:#FFD166">tg</button>
<button class="trig-fn-btn" onclick="trigSetGraphFn('cot',this)" style="--fc:#7BF5A4">ctg</button>
</div>
<!-- Values display -->
<div class="gp-section-title" style="margin-bottom:8px">Значения</div>
<div class="tri-stats-grid" style="margin-bottom:14px">
<span class="tri-stat-k" style="color:#EF476F">sin</span><span class="tri-stat-v" id="trig-v-sin"></span>
<span class="tri-stat-k" style="color:#06D6E0">cos</span><span class="tri-stat-v" id="trig-v-cos"></span>
<span class="tri-stat-k" style="color:#FFD166">tg</span><span class="tri-stat-v" id="trig-v-tan"></span>
<span class="tri-stat-k" style="color:#7BF5A4">ctg</span><span class="tri-stat-v" id="trig-v-cot"></span>
</div>
<!-- Notable angles -->
<div class="gp-section-title" style="margin-bottom:8px">Табличные углы</div>
<div style="display:flex;flex-wrap:wrap;gap:4px;margin-bottom:14px">
<button class="preset-btn" onclick="trigGoTo(0)"></button>
<button class="preset-btn" onclick="trigGoTo(Math.PI/6)">30°</button>
<button class="preset-btn" onclick="trigGoTo(Math.PI/4)">45°</button>
<button class="preset-btn" onclick="trigGoTo(Math.PI/3)">60°</button>
<button class="preset-btn" onclick="trigGoTo(Math.PI/2)">90°</button>
<button class="preset-btn" onclick="trigGoTo(2*Math.PI/3)">120°</button>
<button class="preset-btn" onclick="trigGoTo(Math.PI)">180°</button>
<button class="preset-btn" onclick="trigGoTo(3*Math.PI/2)">270°</button>
</div>
<!-- Angle info -->
<div style="margin-top:auto;padding-top:10px">
<div style="font-size:0.62rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--text-3);margin-bottom:6px">Угол</div>
<div id="trig-angle-badge" style="
padding:10px 14px;border-radius:12px;
background:rgba(155,93,229,0.12);border:1.5px solid rgba(155,93,229,0.25);
font-family:'Manrope',sans-serif;font-size:0.85rem;font-weight:700;
color:var(--violet);text-align:center;line-height:1.6;
">45° = π/4</div>
<div style="margin-top:8px;font-size:0.7rem;color:var(--text-3);text-align:center;line-height:1.5">
Перетащи точку по окружности<br>или выбери табличный угол
</div>
</div>
</div><!-- /.proj-panel -->
<!-- canvas -->
<div class="proj-canvas-outer">
<canvas id="trigcircle-canvas"></canvas>
</div>
</div><!-- /.sim-body-wrap -->
<!-- stats bar -->
<div class="proj-stats-bar">
<div class="pstat">
<div class="pstat-label">Угол</div>
<div class="pstat-val" id="trigbar-angle" style="color:var(--violet)">45°</div>
</div>
<div class="pstat">
<div class="pstat-label">sin</div>
<div class="pstat-val" id="trigbar-sin" style="color:#EF476F"></div>
</div>
<div class="pstat">
<div class="pstat-label">cos</div>
<div class="pstat-val" id="trigbar-cos" style="color:#06D6E0"></div>
</div>
<div class="pstat">
<div class="pstat-label">tg</div>
<div class="pstat-val" id="trigbar-tan" style="color:#FFD166"></div>
</div>
<div class="pstat">
<div class="pstat-label">ctg</div>
<div class="pstat-val" id="trigbar-cot" style="color:#7BF5A4"></div>
</div>
<div class="pstat">
<div class="pstat-label">Четверть</div>
<div class="pstat-val" id="trigbar-quad" style="color:var(--violet)"></div>
</div>
</div>
</div><!-- /#sim-trigcircle -->
<!-- ══════════════════════════════════════════════
ИДЕАЛЬНЫЙ ГАЗ
══════════════════════════════════════════════ -->
<!-- ══════════════════════════════════════════════
МОЛЕКУЛЯРНАЯ ФИЗИКА (газ + броуновское + состояния + диффузия)
══════════════════════════════════════════════ -->
<div id="sim-molphys" class="sim-proj-wrap" style="display:none">
<div class="sim-body-wrap">
<div class="proj-panel" style="width:248px;gap:0">
<!-- Mode selector -->
<div style="display:flex;gap:3px;margin-bottom:12px;padding:3px;background:rgba(255,255,255,0.04);border-radius:10px;border:1px solid var(--border)">
<button class="mag-mode-btn mol-mode active" id="mol-mode-gas" onclick="molMode('gas',this)" style="flex:1;font-size:.63rem;padding:5px 2px">Газ</button>
<button class="mag-mode-btn mol-mode" id="mol-mode-brownian" onclick="molMode('brownian',this)" style="flex:1;font-size:.63rem;padding:5px 2px">Броуновское</button>
<button class="mag-mode-btn mol-mode" id="mol-mode-states" onclick="molMode('states',this)" style="flex:1;font-size:.63rem;padding:5px 2px">Фазы</button>
<button class="mag-mode-btn mol-mode" id="mol-mode-diffusion" onclick="molMode('diffusion',this)" style="flex:1;font-size:.63rem;padding:5px 2px">Диффузия</button>
</div>
<!-- ── Gas panel ── -->
<div id="mol-panel-gas">
<div class="gp-section-title" style="margin-bottom:8px">Параметры газа</div>
<div class="param-block">
<div class="param-header"><span class="param-name">Число молекул N</span><span class="param-val" id="g-N">80</span></div>
<input type="range" class="param-slider" id="sl-gN" min="20" max="200" value="80" oninput="gasNChange()">
</div>
<div class="param-block">
<div class="param-header"><span class="param-name">Температура T</span><span class="param-val" id="g-T">1.0 у.е.</span></div>
<input type="range" class="param-slider" id="sl-gT" min="2" max="30" value="10" oninput="gasTChange()">
</div>
<div class="param-block">
<div class="param-header"><span class="param-name">Поршень (объём)</span><span class="param-val" id="g-piston">100%</span></div>
<input type="range" class="param-slider" id="sl-gPiston" min="30" max="100" value="100" oninput="gasPistonChange()">
</div>
<div style="margin-bottom:10px">
<button class="proj-preset-chip" id="gas-vec-btn" onclick="gasToggleVectors(this)" style="width:100%">Векторы скоростей: Выкл</button>
</div>
<div class="gp-section-title" style="margin-top:4px;margin-bottom:8px">Состояние</div>
<div class="tri-stats-grid" style="grid-template-columns:1fr 1fr;margin-bottom:8px">
<div style="font-size:.68rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--text-3)">Давление P</div>
<div class="tri-stat-v" id="gstat-P" style="text-align:center;color:var(--violet)"></div>
<div style="font-size:.68rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--text-3)">Объём V</div>
<div class="tri-stat-v" id="gstat-V" style="text-align:center;color:var(--cyan)"></div>
<div style="font-size:.68rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--text-3)">PV</div>
<div class="tri-stat-v" id="gstat-PV" style="text-align:center;color:#34d399"></div>
<div style="font-size:.68rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--text-3)">⟨v⟩ средн.</div>
<div class="tri-stat-v" id="gstat-v" style="text-align:center;color:#FFD166"></div>
</div>
<div style="font-size:.65rem;color:var(--text-3);text-align:center;line-height:1.6;margin-top:auto">Стенки светятся по P · Поршень перетащи мышью</div>
</div>
<!-- ── Brownian panel ── -->
<div id="mol-panel-brownian" style="display:none">
<div class="gp-section-title" style="margin-bottom:8px">Параметры</div>
<div class="param-block">
<div class="param-header"><span class="param-name">Молекул газа N</span><span class="param-val" id="br-N">120</span></div>
<input type="range" class="param-slider" id="sl-brN" min="30" max="300" value="120" oninput="brownNChange()">
</div>
<div class="param-block">
<div class="param-header"><span class="param-name">Температура T</span><span class="param-val" id="br-T">1.0 у.е.</span></div>
<input type="range" class="param-slider" id="sl-brT" min="2" max="20" value="10" oninput="brownTChange()">
</div>
<div class="gp-section-title" style="margin-top:10px;margin-bottom:8px">Статистика частицы B</div>
<div class="tri-stats-grid" style="grid-template-columns:1fr 1fr;margin-bottom:8px">
<div style="font-size:.68rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--text-3)">|Δr| смещение</div>
<div class="tri-stat-v" id="brstat-dr" style="text-align:center;color:#FFD166">0</div>
<div style="font-size:.68rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--text-3)">MSD</div>
<div class="tri-stat-v" id="brstat-msd" style="text-align:center;color:var(--violet)">0</div>
<div style="font-size:.68rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--text-3)">Скорость v</div>
<div class="tri-stat-v" id="brstat-v" style="text-align:center;color:var(--cyan)">0</div>
<div style="font-size:.68rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--text-3)">Шагов</div>
<div class="tri-stat-v" id="brstat-steps" style="text-align:center;color:#34d399">0</div>
</div>
<div style="margin-bottom:10px">
<button class="proj-preset-chip" onclick="if(brownSim) brownSim.resetOrigin()" style="width:100%">Сбросить отсчёт (Origin)</button>
</div>
<div style="font-size:.65rem;color:var(--text-3);text-align:center;line-height:1.6;margin-top:auto">График MSD нарастает линейно — закон диффузии</div>
</div>
<!-- ── States panel ── -->
<div id="mol-panel-states" style="display:none">
<div class="gp-section-title" style="margin-bottom:8px">Управление</div>
<div class="param-block">
<div class="param-header"><span class="param-name">Температура T</span><span class="param-val" id="st-T">0.15</span></div>
<input type="range" class="param-slider" id="sl-stT" min="1" max="100" value="15" oninput="statesTChange()">
</div>
<div class="param-block">
<div class="param-header"><span class="param-name">Частиц N</span><span class="param-val" id="st-N">64</span></div>
<input type="range" class="param-slider" id="sl-stN" min="16" max="100" step="4" value="64" oninput="statesNChange()">
</div>
<div style="display:flex;gap:6px;margin-bottom:14px;flex-wrap:wrap">
<button class="proj-preset-chip" onclick="statesPreset(0.05)">Твёрдое</button>
<button class="proj-preset-chip" onclick="statesPreset(0.30)">Жидкость</button>
<button class="proj-preset-chip" onclick="statesPreset(0.75)">Газ</button>
</div>
<button id="states-vec-btn" class="proj-preset-chip" style="margin-bottom:10px;width:100%" onclick="statesToggleVectors(this)">Векторы скоростей: Выкл</button>
<div class="gp-section-title" style="margin-bottom:8px">Фаза и энергия</div>
<div class="tri-stats-grid" style="grid-template-columns:1fr 1fr;margin-bottom:8px">
<div style="font-size:.68rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--text-3)">Фаза</div>
<div class="tri-stat-v" id="ststat-phase" style="text-align:center"></div>
<div style="font-size:.68rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--text-3)">Кин. энергия</div>
<div class="tri-stat-v" id="ststat-KE" style="text-align:center;color:#FFD166"></div>
<div style="font-size:.68rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--text-3)">Пот. энергия</div>
<div class="tri-stat-v" id="ststat-PE" style="text-align:center;color:var(--violet)"></div>
<div style="font-size:.68rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--text-3)">Давление</div>
<div class="tri-stat-v" id="ststat-P" style="text-align:center;color:#EF476F"></div>
</div>
<div style="font-size:.65rem;color:var(--text-3);text-align:center;line-height:1.6;margin-top:auto">LJ потенциал · g(r) — структура · цвет = скорость</div>
</div>
<!-- ── Diffusion panel ── -->
<div id="mol-panel-diffusion" style="display:none">
<div class="gp-section-title" style="margin-bottom:8px">Параметры</div>
<div class="param-block">
<div class="param-header"><span class="param-name">Молекул каждого вида</span><span class="param-val" id="df-N">60</span></div>
<input type="range" class="param-slider" id="sl-dfN" min="20" max="120" value="60" oninput="diffNChange()">
</div>
<div class="param-block">
<div class="param-header"><span class="param-name">Температура T</span><span class="param-val" id="df-T">1.0 у.е.</span></div>
<input type="range" class="param-slider" id="sl-dfT" min="2" max="20" value="10" oninput="diffTChange()">
</div>
<label class="tri-layer-row active" id="df-part-row" onclick="diffPartitionToggle(this)" style="margin-bottom:6px">
<span class="tri-dot" style="background:rgba(255,255,255,0.5)"></span>
<span class="tri-layer-name">Перегородка</span>
<span class="tri-layer-hint" style="color:rgba(255,255,255,.4)"></span>
<span class="tri-toggle" id="df-part-toggle" style="background:var(--violet)"><span style="display:block;width:12px;height:12px;border-radius:50%;background:#fff;margin:2px;margin-left:14px"></span></span>
</label>
<label class="tri-layer-row" id="df-pore-row" onclick="diffPoreToggle(this)" style="margin-bottom:10px">
<span class="tri-dot" style="background:rgba(255,179,71,0.5)"></span>
<span class="tri-layer-name">Пора (щель)</span>
<span class="tri-layer-hint" style="color:rgba(255,255,255,.4)"></span>
<span class="tri-toggle" id="df-pore-toggle" style="background:rgba(255,255,255,0.15)"><span style="display:block;width:12px;height:12px;border-radius:50%;background:#fff;margin:2px;margin-left:2px"></span></span>
</label>
<div class="gp-section-title" style="margin-bottom:8px">Концентрации</div>
<div class="tri-stats-grid" style="grid-template-columns:1fr 1fr;margin-bottom:8px">
<div style="font-size:.68rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--cyan)">Лево A</div>
<div class="tri-stat-v" id="dfstat-LA" style="text-align:center;color:var(--cyan)"></div>
<div style="font-size:.68rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--pink)">Лево B</div>
<div class="tri-stat-v" id="dfstat-LB" style="text-align:center;color:var(--pink)"></div>
<div style="font-size:.68rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--cyan)">Право A</div>
<div class="tri-stat-v" id="dfstat-RA" style="text-align:center;color:var(--cyan)"></div>
<div style="font-size:.68rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--pink)">Право B</div>
<div class="tri-stat-v" id="dfstat-RB" style="text-align:center;color:var(--pink)"></div>
<div style="font-size:.68rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--text-3)">Смешивание</div>
<div class="tri-stat-v" id="dfstat-mix" style="text-align:center;color:#34d399"></div>
</div>
<div style="font-size:.65rem;color:var(--text-3);text-align:center;line-height:1.6;margin-top:auto">A (cyan) — лево · B (розовый) — право</div>
</div>
</div><!-- /.proj-panel -->
<div class="proj-canvas-outer">
<canvas id="gas-canvas" style="display:block;position:absolute;top:0;left:0;width:100%;height:100%"></canvas>
<canvas id="brownian-canvas" style="display:none;position:absolute;top:0;left:0;width:100%;height:100%"></canvas>
<canvas id="states-canvas" style="display:none;position:absolute;top:0;left:0;width:100%;height:100%"></canvas>
<canvas id="diffusion-canvas" style="display:none;position:absolute;top:0;left:0;width:100%;height:100%"></canvas>
</div>
</div><!-- /.sim-body-wrap -->
<div class="proj-stats-bar" id="mol-stats-bar">
<div class="pstat"><div class="pstat-label" id="mpbar-l1"></div><div class="pstat-val" id="mpbar-v1" style="color:var(--cyan)"></div></div>
<div class="pstat"><div class="pstat-label" id="mpbar-l2"></div><div class="pstat-val" id="mpbar-v2" style="color:#FFD166"></div></div>
<div class="pstat"><div class="pstat-label" id="mpbar-l3"></div><div class="pstat-val" id="mpbar-v3" style="color:var(--violet)"></div></div>
<div class="pstat"><div class="pstat-label" id="mpbar-l4"></div><div class="pstat-val" id="mpbar-v4" style="color:#34d399"></div></div>
<div class="pstat"><div class="pstat-label" id="mpbar-l5"></div><div class="pstat-val" id="mpbar-v5"></div></div>
</div>
</div><!-- /#sim-molphys -->
<!-- ══════════════════════════════════════════════
ЗАКОН КУЛОНА
══════════════════════════════════════════════ -->
<!-- sim-coulomb removed: merged into sim-emfield -->
<!-- ══════════════════════════════════════════════
ЭЛЕКТРИЧЕСКИЕ ЦЕПИ
══════════════════════════════════════════════ -->
<div id="sim-circuit" class="sim-proj-wrap" style="display:none">
<div class="sim-body-wrap">
<div class="proj-panel" style="width:240px;gap:0">
<div class="gp-section-title" style="margin-bottom:8px">Инструмент</div>
<div style="display:flex;flex-wrap:wrap;gap:5px;margin-bottom:10px">
<button class="proj-preset-chip circ-tool-btn active" id="ptool-wire" onclick="circTool('wire',this)" data-tool="wire">Провод</button>
<button class="proj-preset-chip circ-tool-btn" id="ptool-resistor" onclick="circTool('resistor',this)" data-tool="resistor">Резистор</button>
<button class="proj-preset-chip circ-tool-btn" id="ptool-battery" onclick="circTool('battery',this)" data-tool="battery">Батарея</button>
<button class="proj-preset-chip circ-tool-btn" id="ptool-capacitor" onclick="circTool('capacitor',this)" data-tool="capacitor">Конденсатор</button>
<button class="proj-preset-chip circ-tool-btn" id="ptool-inductor" onclick="circTool('inductor',this)" data-tool="inductor">Катушка L</button>
<button class="proj-preset-chip circ-tool-btn" id="ptool-diode" onclick="circTool('diode',this)" data-tool="diode">Диод</button>
<button class="proj-preset-chip circ-tool-btn" id="ptool-led" onclick="circTool('led',this)" data-tool="led">LED</button>
<button class="proj-preset-chip circ-tool-btn" id="ptool-ac" onclick="circTool('ac',this)" data-tool="ac">AC источник</button>
<button class="proj-preset-chip circ-tool-btn" id="ptool-switch" onclick="circTool('switch',this)" data-tool="switch">Выключатель</button>
<button class="proj-preset-chip circ-tool-btn" id="ptool-lamp" onclick="circTool('lamp',this)" data-tool="lamp">Лампа</button>
<button class="proj-preset-chip circ-tool-btn" id="ptool-ammeter" onclick="circTool('ammeter',this)" data-tool="ammeter">Амперметр</button>
<button class="proj-preset-chip circ-tool-btn" id="ptool-voltmeter" onclick="circTool('voltmeter',this)" data-tool="voltmeter">Вольтметр</button>
<button class="proj-preset-chip circ-tool-btn" id="ptool-erase" onclick="circTool('erase',this)" data-tool="erase">Ластик</button>
</div>
<div class="gp-section-title" style="margin-bottom:8px">Параметры</div>
<div class="param-block">
<div class="param-header">
<span class="param-name">Сопротивление R</span>
<span class="param-val" id="circ-R-val">10 Ω</span>
</div>
<input type="range" class="param-slider" id="sl-circR" min="1" max="100" value="10" oninput="circRChange()">
</div>
<div class="param-block">
<div class="param-header">
<span class="param-name">Напряжение U</span>
<span class="param-val" id="circ-U-val">9 В</span>
</div>
<input type="range" class="param-slider" id="sl-circU" min="1" max="24" value="9" oninput="circUChange()">
</div>
<div class="param-block">
<div class="param-header">
<span class="param-name">Ёмкость C</span>
<span class="param-val" id="circ-C-val">100 µF</span>
</div>
<input type="range" class="param-slider" id="sl-circC" min="10" max="1000" value="100" step="10" oninput="circCChange()">
</div>
<div class="param-block">
<div class="param-header">
<span class="param-name">Индуктивность L</span>
<span class="param-val" id="circ-L-val">10 мГн</span>
</div>
<input type="range" class="param-slider" id="sl-circL" min="1" max="1000" value="10" step="1" oninput="circLChange()">
</div>
<div class="param-block">
<div class="param-header">
<span class="param-name">Частота AC</span>
<span class="param-val" id="circ-F-val">2 Гц</span>
</div>
<input type="range" class="param-slider" id="sl-circF" min="1" max="20" value="2" oninput="circFChange()">
</div>
<div class="gp-section-title" style="margin-bottom:8px;margin-top:4px">Пресеты</div>
<div style="display:flex;flex-wrap:wrap;gap:5px;margin-bottom:10px">
<button class="proj-preset-chip" onclick="circPreset('serial')">Последовательное</button>
<button class="proj-preset-chip" onclick="circPreset('parallel')">Параллельное</button>
<button class="proj-preset-chip" onclick="circPreset('lamp')">Лампа + выкл</button>
<button class="proj-preset-chip" onclick="circPreset('divider')">Делитель V</button>
<button class="proj-preset-chip" onclick="circPreset('bridge')">Мост Уитстона</button>
<button class="proj-preset-chip" onclick="circPreset('diode')">Диод</button>
<button class="proj-preset-chip" onclick="circPreset('led')">LED</button>
<button class="proj-preset-chip" onclick="circPreset('rc')">RC-цепь</button>
<button class="proj-preset-chip" onclick="circPreset('ac')">AC-цепь</button>
<button class="proj-preset-chip" onclick="circPreset('rlc')">RLC-резонанс</button>
</div>
<div style="margin-top:auto;font-size:0.68rem;color:var(--text-3);text-align:center;line-height:1.7;padding-top:4px">
Тяни узлы для рисования · ПКМ — удалить<br>
2×клик по выключателю — вкл/выкл · Ctrl+Z отмена
</div>
</div><!-- /.proj-panel -->
<div class="proj-canvas-outer">
<canvas id="circuit-canvas" style="display:block;position:absolute;top:0;left:0;width:100%;height:100%;cursor:crosshair"></canvas>
<div id="osc-panel" style="display:none;position:absolute;bottom:8px;right:8px;z-index:10;background:rgba(6,6,22,0.95);border:1px solid rgba(255,255,255,0.12);border-radius:8px;padding:6px">
<div style="font-size:0.7rem;color:rgba(255,255,255,0.45);margin-bottom:4px;text-align:center">Осциллограф</div>
<canvas id="osc-canvas" width="300" height="180" style="display:block;border-radius:4px"></canvas>
</div>
</div>
</div><!-- /.sim-body-wrap -->
<div class="proj-stats-bar">
<div class="pstat"><div class="pstat-label">Компонентов</div><div class="pstat-val" id="cirbar-comps">0</div></div>
<div class="pstat"><div class="pstat-label">Напряжение U</div><div class="pstat-val" id="cirbar-U" style="color:#EF476F"></div></div>
<div class="pstat"><div class="pstat-label">Ток I</div><div class="pstat-val" id="cirbar-I" style="color:#FFD166"></div></div>
<div class="pstat"><div class="pstat-label">Мощность P</div><div class="pstat-val" id="cirbar-P" style="color:#7BF5A4"></div></div>
<div class="pstat"><div class="pstat-label">Статус</div><div class="pstat-val" id="cirbar-status"></div></div>
</div>
</div><!-- /#sim-circuit -->
<!-- ══════════════════════════════════════════════
ЛОГИЧЕСКИЕ СХЕМЫ
══════════════════════════════════════════════ -->
<div id="sim-logic" class="sim-proj-wrap" style="display:none">
<!-- left panel: palette + presets -->
<div class="sim-body-wrap" style="flex-direction:column">
<div style="display:flex;flex:1;min-height:0;overflow:hidden">
<div class="proj-panel" style="width:220px;gap:0;overflow-y:auto">
<div class="gp-section-title" style="margin-bottom:8px">Инструмент</div>
<div style="display:flex;flex-wrap:wrap;gap:5px;margin-bottom:10px">
<button class="proj-preset-chip lgc-tool-btn active" data-tool="select" onclick="logicTool('select',this)">Выбор</button>
<button class="proj-preset-chip lgc-tool-btn" data-tool="INPUT" onclick="logicTool('INPUT',this)">INPUT</button>
<button class="proj-preset-chip lgc-tool-btn" data-tool="CLOCK" onclick="logicTool('CLOCK',this)">CLOCK</button>
<button class="proj-preset-chip lgc-tool-btn" data-tool="OUTPUT" onclick="logicTool('OUTPUT',this)">OUTPUT</button>
<button class="proj-preset-chip lgc-tool-btn" data-tool="AND" onclick="logicTool('AND',this)">AND</button>
<button class="proj-preset-chip lgc-tool-btn" data-tool="OR" onclick="logicTool('OR',this)">OR</button>
<button class="proj-preset-chip lgc-tool-btn" data-tool="NOT" onclick="logicTool('NOT',this)">NOT</button>
<button class="proj-preset-chip lgc-tool-btn" data-tool="XOR" onclick="logicTool('XOR',this)">XOR</button>
<button class="proj-preset-chip lgc-tool-btn" data-tool="NAND" onclick="logicTool('NAND',this)">NAND</button>
<button class="proj-preset-chip lgc-tool-btn" data-tool="NOR" onclick="logicTool('NOR',this)">NOR</button>
<button class="proj-preset-chip lgc-tool-btn" data-tool="XNOR" onclick="logicTool('XNOR',this)">XNOR</button>
<button class="proj-preset-chip lgc-tool-btn" data-tool="BUFFER" onclick="logicTool('BUFFER',this)">BUF</button>
</div>
<div class="gp-section-title" style="margin-bottom:8px;margin-top:4px">Пресеты</div>
<div style="display:flex;flex-direction:column;gap:5px;margin-bottom:10px">
<button class="proj-preset-chip" onclick="logicPreset('half-adder')">Полусумматор</button>
<button class="proj-preset-chip" onclick="logicPreset('full-adder')">Полный сумматор</button>
<button class="proj-preset-chip" onclick="logicPreset('rs-latch')">RS-триггер</button>
<button class="proj-preset-chip" onclick="logicPreset('d-latch')">D-триггер</button>
<button class="proj-preset-chip" onclick="logicPreset('decoder-2to4')">Декодер 2-в-4</button>
<button class="proj-preset-chip" onclick="logicPreset('mux-2to1')">Мультиплексор 2-в-1</button>
<button class="proj-preset-chip" onclick="logicPreset('and-gate')">AND (пример)</button>
</div>
<button class="proj-preset-chip" style="margin-top:auto;background:rgba(239,71,111,0.12);border-color:rgba(239,71,111,0.35);color:#EF476F" onclick="logicClearAll()">Очистить</button>
<div style="margin-top:10px;font-size:0.67rem;color:var(--text-3);text-align:center;line-height:1.7;padding-top:4px">
Клик = добавить элемент<br>
Перетащи выход (кружок) на вход<br>
2×клик по INPUT — переключить 0/1<br>
ПКМ — удалить &nbsp;|&nbsp; Ctrl+Z отмена
</div>
</div><!-- /.proj-panel -->
<div class="proj-canvas-outer" style="flex:1;position:relative">
<canvas id="logic-canvas" style="display:block;position:absolute;top:0;left:0;width:100%;height:100%;cursor:default"></canvas>
</div>
<!-- right: boolean expression panel -->
<div class="proj-panel" style="width:200px;gap:0;overflow-y:auto">
<div class="gp-section-title" style="margin-bottom:8px">Выражение</div>
<div id="logic-expr" style="font-size:0.82rem;color:rgba(255,255,255,0.8);line-height:1.7;word-break:break-all;min-height:40px">
Добавьте OUTPUT для вывода выражения
</div>
</div>
</div><!-- /.flex row -->
<!-- truth table panel (collapsible) -->
<div id="logic-tt-panel" style="max-height:200px;overflow:auto;border-top:1px solid rgba(255,255,255,0.08);padding:8px 12px">
<div style="display:flex;align-items:center;gap:8px;margin-bottom:6px">
<span style="font-size:0.75rem;font-weight:700;color:rgba(255,255,255,0.55);letter-spacing:.08em;text-transform:uppercase">Таблица истинности</span>
<button id="btn-logic-tt" class="zoom-btn active" onclick="logicToggleTable()" style="font-size:0.65rem;padding:2px 7px">скрыть</button>
</div>
<div id="logic-tt-body" style="font-size:0.78rem">
<span style="color:rgba(255,255,255,0.35)">Добавьте INPUT и OUTPUT</span>
</div>
</div>
</div><!-- /.sim-body-wrap -->
</div><!-- /#sim-logic -->
<!-- ══════════════════════════════════════════════
КИНЕТИКА РЕАКЦИЙ
══════════════════════════════════════════════ -->
<!-- ══════════════════════════════════════════════
ХИМИЯ (unified: кинетика + колба + ОВР + ионный обмен)
══════════════════════════════════════════════ -->
<div id="sim-chemistry" class="sim-proj-wrap" style="display:none">
<div class="sim-body-wrap">
<div class="proj-panel" style="width:248px;gap:0">
<!-- Mode selector -->
<div style="display:flex;gap:3px;margin-bottom:12px;padding:3px;background:rgba(255,255,255,0.04);border-radius:10px;border:1px solid var(--border)">
<button class="mag-mode-btn chem-mode active" id="chem-mode-kinetics" onclick="chemMode('kinetics',this)" style="flex:1;font-size:.63rem;padding:5px 2px">Кинетика</button>
<button class="mag-mode-btn chem-mode" id="chem-mode-flask" onclick="chemMode('flask',this)" style="flex:1;font-size:.63rem;padding:5px 2px">Колба</button>
<button class="mag-mode-btn chem-mode" id="chem-mode-redox" onclick="chemMode('redox',this)" style="flex:1;font-size:.63rem;padding:5px 2px">ОВР</button>
<button class="mag-mode-btn chem-mode" id="chem-mode-ionex" onclick="chemMode('ionex',this)" style="flex:1;font-size:.63rem;padding:5px 2px">Ионный</button>
</div>
<!-- ── Kinetics panel ── -->
<div id="chem-panel-kinetics">
<div class="gp-section-title" style="margin-bottom:6px">Параметры</div>
<div class="param-block" style="margin-bottom:7px">
<div class="param-header"><span class="param-name">Молекул N</span><span class="param-val" id="reac-N-val">28</span></div>
<input type="range" class="param-slider" id="sl-reacN" min="5" max="60" value="28" oninput="reacNChange()">
</div>
<div class="param-block" style="margin-bottom:7px">
<div class="param-header"><span class="param-name">Температура T</span><span class="param-val" id="reac-T-val">1.2</span></div>
<input type="range" class="param-slider" id="sl-reacT" min="2" max="40" value="12" oninput="reacTChange()">
</div>
<div class="param-block" style="margin-bottom:7px">
<div class="param-header"><span class="param-name">Энергия активации Ea</span><span class="param-val" id="reac-Ea-val">2.0</span></div>
<input type="range" class="param-slider" id="sl-reacEa" min="5" max="50" value="20" oninput="reacEaChange()">
</div>
<div class="gp-section-title" style="margin-bottom:6px">Режим</div>
<div style="display:flex;flex-direction:column;gap:4px;margin-bottom:8px">
<button class="proj-preset-chip reac-mode-btn active" id="rmode-forward" onclick="reacMode('forward',this)" style="text-align:left"><svg class="ic" viewBox="0 0 24 24"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg> Прямая (A+B<svg class="ic" viewBox="0 0 24 24"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg>C)</button>
<button class="proj-preset-chip reac-mode-btn" id="rmode-reversible" onclick="reacMode('reversible',this)" style="text-align:left">⇌ Обратимая</button>
<button class="proj-preset-chip reac-mode-btn" id="rmode-chain" onclick="reacMode('chain',this)" style="text-align:left"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="display:inline-block;vertical-align:middle"><path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z"/></svg> Цепная</button>
</div>
<div class="gp-section-title" style="margin-bottom:6px">Пресеты</div>
<div style="display:flex;flex-wrap:wrap;gap:5px">
<button class="proj-preset-chip" onclick="reacPreset('simple')">Простая</button>
<button class="proj-preset-chip" onclick="reacPreset('reversible')">Равновесие</button>
<button class="proj-preset-chip" onclick="reacPreset('hot')">Горячая</button>
<button class="proj-preset-chip" onclick="reacPreset('cold')">Холодная</button>
<button class="proj-preset-chip" onclick="reacPreset('chain')">Цепная</button>
</div>
</div><!-- /chem-panel-kinetics -->
<!-- ── Flask panel ── -->
<div id="chem-panel-flask" style="display:none">
<div class="gp-section-title" style="margin-bottom:8px">Металл</div>
<div style="display:flex;flex-wrap:wrap;gap:5px;margin-bottom:10px">
<button class="proj-preset-chip flask-metal-btn active" id="fmetal-Zn" onclick="flaskMetal('Zn',this)">Zn</button>
<button class="proj-preset-chip flask-metal-btn" id="fmetal-Fe" onclick="flaskMetal('Fe',this)">Fe</button>
<button class="proj-preset-chip flask-metal-btn" id="fmetal-Mg" onclick="flaskMetal('Mg',this)">Mg</button>
<button class="proj-preset-chip flask-metal-btn" id="fmetal-Cu" onclick="flaskMetal('Cu',this)">Cu</button>
<button class="proj-preset-chip flask-metal-btn" id="fmetal-Na" onclick="flaskMetal('Na',this)">Na</button>
<button class="proj-preset-chip flask-metal-btn" id="fmetal-Al" onclick="flaskMetal('Al',this)">Al</button>
</div>
<div class="gp-section-title" style="margin-bottom:8px">Реагент</div>
<div style="display:flex;flex-wrap:wrap;gap:5px;margin-bottom:10px">
<button class="proj-preset-chip flask-acid-btn active" id="facid-HCl" onclick="flaskAcid('HCl',this)">HCl</button>
<button class="proj-preset-chip flask-acid-btn" id="facid-H2SO4" onclick="flaskAcid('H2SO4',this)">H₂SO₄</button>
<button class="proj-preset-chip flask-acid-btn" id="facid-H2O" onclick="flaskAcid('H2O',this)">H₂O</button>
</div>
<div class="param-block">
<div class="param-header"><span class="param-name">Концентрация</span><span class="param-val" id="flask-conc-val">35%</span></div>
<input type="range" class="param-slider" id="sl-flask-conc" min="5" max="98" value="35" oninput="flaskConcChange()">
</div>
<div class="param-block">
<div class="param-header"><span class="param-name">Темп. окружения</span><span class="param-val" id="flask-temp-val">20°C</span></div>
<input type="range" class="param-slider" id="sl-flask-temp" min="5" max="80" value="20" oninput="flaskTempChange()">
</div>
<div style="display:flex;gap:6px;margin-bottom:10px;margin-top:2px">
<button class="proj-preset-chip" style="flex:1;background:rgba(239,71,111,0.18);border-color:rgba(239,71,111,0.4)"
onclick="flaskSim && flaskSim.dropMetal()"><svg class="ic" viewBox="0 0 24 24"><line x1="12" y1="5" x2="12" y2="19"/><polyline points="19 12 12 19 5 12"/></svg> Бросить металл</button>
<button class="proj-preset-chip" id="flask-flame-panel" style="flex:0 0 auto"
onclick="flaskToggleFlame()"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="display:inline-block;vertical-align:middle"><path d="M12 2c.5 3.5-1.5 6-1.5 6 1 1.5 3 2 3 5a4 4 0 01-8 0c0-2 .5-3 1.5-4.5C8.5 6.5 7 4.5 7 4.5S9.5 2 12 2z"/></svg></button>
</div>
<div style="font-size:.65rem;color:var(--text-3);text-align:center;line-height:1.7;margin-top:auto;padding-top:4px">
Выбери металл + кислоту<br>H₂ накапливается — поднеси огонь!
</div>
</div><!-- /chem-panel-flask -->
<!-- ── Redox panel ── -->
<div id="chem-panel-redox" style="display:none">
<div class="gp-section-title" style="margin-bottom:8px">Реакция</div>
<div style="display:flex;flex-direction:column;gap:4px;margin-bottom:12px">
<button class="proj-preset-chip redox-rxn-btn active" id="rdxrxn-fe_cu" onclick="redoxRxn('fe_cu',this)" style="text-align:left;font-size:.72rem">Fe + CuSO₄ <svg class="ic" viewBox="0 0 24 24"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg> FeSO₄ + Cu<svg class="ic" viewBox="0 0 24 24"><line x1="12" y1="5" x2="12" y2="19"/><polyline points="19 12 12 19 5 12"/></svg></button>
<button class="proj-preset-chip redox-rxn-btn" id="rdxrxn-zn_hcl" onclick="redoxRxn('zn_hcl',this)" style="text-align:left;font-size:.72rem">Zn + 2HCl <svg class="ic" viewBox="0 0 24 24"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg> ZnCl₂ + H₂<svg class="ic" viewBox="0 0 24 24"><line x1="12" y1="19" x2="12" y2="5"/><polyline points="5 12 12 5 19 12"/></svg></button>
<button class="proj-preset-chip redox-rxn-btn" id="rdxrxn-cl2_ki" onclick="redoxRxn('cl2_ki',this)" style="text-align:left;font-size:.72rem">Cl₂ + 2KI <svg class="ic" viewBox="0 0 24 24"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg> I₂<svg class="ic" viewBox="0 0 24 24"><line x1="12" y1="5" x2="12" y2="19"/><polyline points="19 12 12 19 5 12"/></svg> + 2KCl</button>
<button class="proj-preset-chip redox-rxn-btn" id="rdxrxn-kmno4" onclick="redoxRxn('kmno4',this)" style="text-align:left;font-size:.72rem">KMnO₄ + FeSO₄ (кислая)</button>
<button class="proj-preset-chip redox-rxn-btn" id="rdxrxn-cu_fecl3" onclick="redoxRxn('cu_fecl3',this)" style="text-align:left;font-size:.72rem">Cu + 2FeCl₃ <svg class="ic" viewBox="0 0 24 24"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg> CuCl₂ + 2FeCl₂</button>
</div>
<button class="proj-launch-btn" style="margin-bottom:8px" onclick="redoxStart()"><svg class="ic" viewBox="0 0 24 24"><polygon points="5 3 19 12 5 21 5 3"/></svg> Начать реакцию</button>
<button class="proj-reset-btn" onclick="redoxReset()"><svg class="ic" viewBox="0 0 24 24"><polyline points="1 4 1 10 7 10"/><path d="M3.51 15a9 9 0 1 0 .49-4.12"/></svg> Сброс</button>
<div style="margin-top:auto;padding-top:6px;font-size:.65rem;color:var(--text-3);line-height:1.7;text-align:center">
Синие e⁻ — перенос электронов<br>Цифры — степень окисления
</div>
</div><!-- /chem-panel-redox -->
<!-- ── Ion exchange panel ── -->
<div id="chem-panel-ionex" style="display:none">
<div class="gp-section-title" style="margin-bottom:8px">Реакция</div>
<div style="display:flex;flex-direction:column;gap:4px;margin-bottom:12px">
<button class="proj-preset-chip ionex-rxn-btn active" id="ioxrxn-ba_so4" onclick="ionexRxn('ba_so4',this)" style="text-align:left;font-size:.72rem">BaCl₂ + Na₂SO₄ <svg class="ic" viewBox="0 0 24 24"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg> BaSO₄<svg class="ic" viewBox="0 0 24 24"><line x1="12" y1="5" x2="12" y2="19"/><polyline points="19 12 12 19 5 12"/></svg></button>
<button class="proj-preset-chip ionex-rxn-btn" id="ioxrxn-ag_cl" onclick="ionexRxn('ag_cl',this)" style="text-align:left;font-size:.72rem">AgNO₃ + NaCl <svg class="ic" viewBox="0 0 24 24"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg> AgCl<svg class="ic" viewBox="0 0 24 24"><line x1="12" y1="5" x2="12" y2="19"/><polyline points="19 12 12 19 5 12"/></svg></button>
<button class="proj-preset-chip ionex-rxn-btn" id="ioxrxn-co3_hcl" onclick="ionexRxn('co3_hcl',this)" style="text-align:left;font-size:.72rem">Na₂CO₃ + 2HCl <svg class="ic" viewBox="0 0 24 24"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg> CO₂<svg class="ic" viewBox="0 0 24 24"><line x1="12" y1="19" x2="12" y2="5"/><polyline points="5 12 12 5 19 12"/></svg></button>
<button class="proj-preset-chip ionex-rxn-btn" id="ioxrxn-pb_i" onclick="ionexRxn('pb_i',this)" style="text-align:left;font-size:.72rem">Pb(NO₃)₂ + 2KI <svg class="ic" viewBox="0 0 24 24"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg> PbI₂<svg class="ic" viewBox="0 0 24 24"><line x1="12" y1="5" x2="12" y2="19"/><polyline points="19 12 12 19 5 12"/></svg></button>
<button class="proj-preset-chip ionex-rxn-btn" id="ioxrxn-ca_co3" onclick="ionexRxn('ca_co3',this)" style="text-align:left;font-size:.72rem">CaCl₂ + Na₂CO₃ <svg class="ic" viewBox="0 0 24 24"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg> CaCO₃<svg class="ic" viewBox="0 0 24 24"><line x1="12" y1="5" x2="12" y2="19"/><polyline points="19 12 12 19 5 12"/></svg></button>
</div>
<button class="proj-launch-btn" style="margin-bottom:8px" onclick="ionexStart()"><svg class="ic" viewBox="0 0 24 24"><path d="M9 3h6m-4.5 0v5.5l-4 7.5a1 1 0 0 0 .9 1.5h8.2a1 1 0 0 0 .9-1.5l-4-7.5V3"/></svg> Смешать растворы</button>
<button class="proj-reset-btn" onclick="ionexReset()"><svg class="ic" viewBox="0 0 24 24"><polyline points="1 4 1 10 7 10"/><path d="M3.51 15a9 9 0 1 0 .49-4.12"/></svg> Сброс</button>
<div style="margin-top:auto;padding-top:6px;font-size:.65rem;color:var(--text-3);line-height:1.7;text-align:center">
Яркие ионы = реагируют<br>Тусклые = зрители · <svg class="ic" viewBox="0 0 24 24"><line x1="12" y1="5" x2="12" y2="19"/><polyline points="19 12 12 19 5 12"/></svg> осадок · <svg class="ic" viewBox="0 0 24 24"><line x1="12" y1="19" x2="12" y2="5"/><polyline points="5 12 12 5 19 12"/></svg> газ
</div>
</div><!-- /chem-panel-ionex -->
</div><!-- /.proj-panel -->
<div class="proj-canvas-outer">
<canvas id="reactions-canvas" style="display:block;position:absolute;top:0;left:0;width:100%;height:100%"></canvas>
<canvas id="flask-canvas" style="display:none;position:absolute;top:0;left:0;width:100%;height:100%;cursor:default"></canvas>
<canvas id="redox-canvas" style="display:none;position:absolute;top:0;left:0;width:100%;height:100%;cursor:default"></canvas>
<canvas id="ionexchange-canvas" style="display:none;position:absolute;top:0;left:0;width:100%;height:100%;cursor:default"></canvas>
</div>
</div><!-- /.sim-body-wrap -->
<div class="proj-stats-bar" id="chem-stats-bar">
<div class="pstat"><div class="pstat-label" id="chbar-l1"></div><div class="pstat-val" id="chbar-v1" style="color:var(--cyan)"></div></div>
<div class="pstat"><div class="pstat-label" id="chbar-l2"></div><div class="pstat-val" id="chbar-v2" style="color:#EF476F"></div></div>
<div class="pstat"><div class="pstat-label" id="chbar-l3"></div><div class="pstat-val" id="chbar-v3" style="color:#FFD166"></div></div>
<div class="pstat"><div class="pstat-label" id="chbar-l4"></div><div class="pstat-val" id="chbar-v4"></div></div>
<div class="pstat"><div class="pstat-label" id="chbar-l5"></div><div class="pstat-val" id="chbar-v5" style="color:#7BF5A4"></div></div>
</div>
</div><!-- /#sim-chemistry -->
<!-- ── DYNAMICS sim body (Newton + Sandbox unified) ── -->
<div id="sim-dynamics" class="sim-proj-wrap" style="display:none">
<div class="sim-body-wrap">
<div class="proj-panel dyn-panel-modern" style="width:300px;gap:0">
<!-- ══ Mode selector ══ -->
<div class="dyn-mode-bar">
<button class="mag-mode-btn dyn-mode active" id="dyn-mode-sandbox" onclick="dynMode('sandbox',this)" title="Песочница — свободный режим">Песочница</button>
<button class="mag-mode-btn dyn-mode" id="dyn-mode-law4" onclick="dynMode('law4',this)" title="Классические сцены: Атвуд, Наклон, Качение">Классика</button>
</div>
<div class="dyn-mode-bar" style="margin-bottom:14px">
<button class="mag-mode-btn dyn-mode" id="dyn-mode-law1" onclick="dynMode('law1',this)" title="I закон Ньютона — инерция">I закон</button>
<button class="mag-mode-btn dyn-mode" id="dyn-mode-law2" onclick="dynMode('law2',this)" title="II закон Ньютона — F=ma">II закон</button>
<button class="mag-mode-btn dyn-mode" id="dyn-mode-law3" onclick="dynMode('law3',this)" title="III закон Ньютона — действие=противодействие">III закон</button>
</div>
<!-- ══ Newton controls (shown in law modes) ══ -->
<div id="dyn-newton-panel" style="display:none">
<!-- Scene selector (standard A/B/C — hidden for law 4) -->
<div class="gp-section-title" style="margin-bottom:8px" id="newton-scene-title">Сцена</div>
<div class="dyn-row-4" style="grid-template-columns:1fr 1fr 1fr;margin-bottom:12px" id="newton-scene-row">
<button class="mag-mode-btn nscene-btn active" id="nscn-panel-A" onclick="newtonScene('A',null,this)">A</button>
<button class="mag-mode-btn nscene-btn" id="nscn-panel-B" onclick="newtonScene('B',null,this)">B</button>
<button class="mag-mode-btn nscene-btn" id="nscn-panel-C" onclick="newtonScene('C',null,this)">C</button>
</div>
<!-- Classic scene selector (law 4 only) -->
<div id="newton-classic-panel" style="display:none">
<div class="dyn-row-4" style="grid-template-columns:1fr 1fr 1fr;margin-bottom:10px">
<button class="mag-mode-btn cl-scene-btn active" id="nscn-panel-cl-atwood" data-scene="atwood" onclick="classicScene('atwood')">Атвуд</button>
<button class="mag-mode-btn cl-scene-btn" id="nscn-panel-cl-ramp" data-scene="ramp" onclick="classicScene('ramp')">Наклон</button>
<button class="mag-mode-btn cl-scene-btn" id="nscn-panel-cl-roll" data-scene="roll" onclick="classicScene('roll')">Качение</button>
</div>
<!-- Atwood sub-panel -->
<div id="cl-sub-atwood">
<div class="param-block">
<div class="param-header"><span class="param-name">m₁ (кг)</span><span class="param-val" id="atw-m1-val">5 кг</span></div>
<input type="range" class="param-slider" id="sl-atw-m1" min="1" max="20" value="5" oninput="atwM1Change()">
</div>
<div class="param-block">
<div class="param-header"><span class="param-name">m₂ (кг)</span><span class="param-val" id="atw-m2-val">8 кг</span></div>
<input type="range" class="param-slider" id="sl-atw-m2" min="1" max="20" value="8" oninput="atwM2Change()">
</div>
<div class="gp-section-title" style="margin:4px 0">Блок</div>
<div class="dyn-row-2">
<button class="mag-mode-btn atw-massive-btn active" data-val="false" onclick="atwMassiveToggle(false)">Идеальный</button>
<button class="mag-mode-btn atw-massive-btn" data-val="true" onclick="atwMassiveToggle(true)">Массивный</button>
</div>
</div>
<!-- Ramp sub-panel -->
<div id="cl-sub-ramp" style="display:none">
<div class="param-block">
<div class="param-header"><span class="param-name">Угол α</span><span class="param-val" id="ramp-alpha-val">30°</span></div>
<input type="range" class="param-slider" id="sl-ramp-alpha" min="1" max="89" value="30" oninput="rampAlphaChange()">
</div>
<div class="param-block">
<div class="param-header"><span class="param-name">Масса m (кг)</span><span class="param-val" id="newton-m1-ramp-val">5 кг</span></div>
<input type="range" class="param-slider" id="sl-ramp-mass" min="1" max="20" value="5" oninput="rampMassChange()">
</div>
<div class="param-block">
<div class="param-header"><span class="param-name">Коэфф. трения μ</span><span class="param-val" id="ramp-mu-val">0.20</span></div>
<input type="range" class="param-slider" id="sl-ramp-mu" min="0" max="1.5" step="0.01" value="0.20" oninput="rampMuChange()">
</div>
<div class="param-block">
<div class="param-header"><span class="param-name">Внеш. сила F (Н)</span><span class="param-val" id="ramp-force-val">0 Н</span></div>
<input type="range" class="param-slider" id="sl-ramp-force" min="0" max="80" value="0" oninput="rampForceChange()">
</div>
</div>
<!-- Roll sub-panel -->
<div id="cl-sub-roll" style="display:none">
<div class="param-block">
<div class="param-header"><span class="param-name">Угол α</span><span class="param-val" id="roll-alpha-val">20°</span></div>
<input type="range" class="param-slider" id="sl-roll-alpha" min="5" max="60" value="20" oninput="rollAlphaChange()">
</div>
<div class="gp-section-title" style="margin:4px 0">Режим</div>
<div class="dyn-row-2">
<button class="mag-mode-btn roll-friction-btn active" data-val="false" onclick="rollFrictionToggle(false)">Качение</button>
<button class="mag-mode-btn roll-friction-btn" data-val="true" onclick="rollFrictionToggle(true)">+Трение</button>
</div>
<div style="font-size:.78rem;color:var(--text-2);line-height:1.55;padding:7px 10px;background:rgba(255,255,255,0.035);border-radius:8px;border:1px solid var(--border);margin-bottom:8px">
Шар: a = (5/7)g·sinα<br>
Цилиндр: a = (2/3)g·sinα<br>
Обруч: a = (1/2)g·sinα
</div>
</div>
</div><!-- /#newton-classic-panel -->
<!-- Scene description -->
<div id="newton-scene-desc" style="font-size:.82rem;color:var(--text-2);line-height:1.6;margin-bottom:12px;padding:9px 11px;background:rgba(255,255,255,0.04);border-radius:8px;border:1px solid var(--border)">
Закон инерции: тело движется равномерно при отсутствии сил.
</div>
<!-- Parameter sliders -->
<div id="newton-mu-block" class="param-block">
<div class="param-header"><span class="param-name">Коэфф. трения μ</span><span class="param-val" id="newton-mu-val">0.20</span></div>
<input type="range" class="param-slider" id="sl-newton-mu" min="0" max="1" step="0.01" value="0.20" oninput="newtonMuChange()">
</div>
<div id="newton-mass1-block" class="param-block" style="display:none">
<div class="param-header"><span class="param-name">Масса m₁ (кг)</span><span class="param-val" id="newton-m1-val">5 кг</span></div>
<input type="range" class="param-slider" id="sl-newton-m1" min="1" max="20" value="5" oninput="newtonMass1Change()">
</div>
<div id="newton-mass2-block" class="param-block" style="display:none">
<div class="param-header"><span class="param-name">Масса m₂ (кг)</span><span class="param-val" id="newton-m2-val">5 кг</span></div>
<input type="range" class="param-slider" id="sl-newton-m2" min="1" max="20" value="5" oninput="newtonMass2Change()">
</div>
<div id="newton-force-block" class="param-block" style="display:none">
<div class="param-header"><span class="param-name">Сила F (Н)</span><span class="param-val" id="newton-F-val">20 Н</span></div>
<input type="range" class="param-slider" id="sl-newton-F" min="1" max="60" value="20" oninput="newtonForceChange()">
</div>
<!-- Presets -->
<div class="gp-section-title" style="margin-top:6px">Пресеты</div>
<div id="newton-presets" style="display:flex;flex-wrap:wrap;gap:5px;margin-bottom:10px">
<button class="proj-preset-chip" onclick="newtonPreset('space')">Космос</button>
<button class="proj-preset-chip" onclick="newtonPreset('ice')">Лёд</button>
<button class="proj-preset-chip" onclick="newtonPreset('asphalt')">Асфальт</button>
<button class="proj-preset-chip" onclick="newtonPreset('rubber')">Резина</button>
</div>
<!-- Action -->
<div style="margin-top:auto;padding-top:10px;display:flex;flex-direction:column;gap:6px">
<button class="proj-launch-btn" id="newton-action-main" onclick="newtonAction()">
<span id="newton-action-label"><svg class="ic" viewBox="0 0 24 24"><polygon points="5 3 19 12 5 21 5 3"/></svg> Действие</span>
</button>
<button class="proj-reset-btn" onclick="_resetNewtonScene()">
<svg viewBox="0 0 24 24" width="13" height="13" fill="none" stroke="currentColor" stroke-width="2.2"><path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"/><path d="M3 3v5h5"/></svg>
Сброс сцены
</button>
</div>
<!-- Newton graphs toggle -->
<div style="margin-top:12px;padding-top:10px;border-top:1px solid rgba(255,255,255,0.07)">
<button id="btn-newton-graphs" onclick="newtonToggleGraphs()" style="width:100%;font-size:.82rem;font-weight:700;padding:8px;border-radius:8px;border:1px solid rgba(6,214,224,0.35);background:rgba(6,214,224,0.1);color:#06D6E0;cursor:pointer">Графики x/v/a</button>
</div>
<!-- Energy bars toggle — newton -->
<div class="gp-section-title" style="margin-top:10px">&#1047;&#1072;&#1082;&#1086;&#1085; &#1089;&#1086;&#1093;&#1088;&#1072;&#1085;&#1077;&#1085;&#1080;&#1103; &#1101;&#1085;&#1077;&#1088;&#1075;&#1080;&#1080;</div>
<button id="nwt-energy-btn" class="proj-preset-chip" onclick="dynToggleEnergy()" style="width:100%;font-size:.82rem;text-align:left;display:flex;align-items:center;gap:7px;padding:8px 11px">
<svg class="ic" viewBox="0 0 24 24"><path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z"/></svg>
<span>Энергия: Выкл</span>
</button>
</div><!-- /#dyn-newton-panel -->
<!-- ══ Sandbox controls (shown in sandbox mode) ══ -->
<div id="dyn-sandbox-panel">
<div class="gp-section-title" style="margin-bottom:8px">Инструмент</div>
<div class="dyn-tool-grid">
<button class="mag-mode-btn sb-panel-tool active" id="sbpt-box" onclick="sbTool('box',this)"><svg class="ic" viewBox="0 0 24 24"><rect x="3" y="3" width="18" height="18" rx="2"/></svg> Блок</button>
<button class="mag-mode-btn sb-panel-tool" id="sbpt-ball" onclick="sbTool('ball',this)"><svg class="ic" viewBox="0 0 24 24"><circle cx="12" cy="12" r="8" fill="currentColor" stroke="none"/></svg> Шар</button>
<button class="mag-mode-btn sb-panel-tool" id="sbpt-erase" onclick="sbTool('erase',this)"><svg class="ic" viewBox="0 0 24 24"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg> Ластик</button>
<button class="mag-mode-btn sb-panel-tool" id="sbpt-spring" onclick="sbTool('spring',this)"><svg class="ic" viewBox="0 0 24 24" fill="none"><path d="M3 12 L6 8 L9 16 L12 8 L15 16 L18 8 L21 12"/></svg> Пружина</button>
<button class="mag-mode-btn sb-panel-tool" id="sbpt-rope" onclick="sbTool('rope',this)">— Нить</button>
<button class="mag-mode-btn sb-panel-tool" id="sbpt-anchor" onclick="sbTool('anchor',this)"><svg class="ic" viewBox="0 0 24 24"><path d="M12 2 2 12 12 22 22 12Z"/></svg> Якорь</button>
</div>
<div class="gp-section-title">Режим силы</div>
<div class="dyn-row-2">
<button class="mag-mode-btn sb-fmode active" id="sbfm-constant" onclick="sbForceMode('constant',this)">Постоянная</button>
<button class="mag-mode-btn sb-fmode" id="sbfm-impulse" onclick="sbForceMode('impulse',this)">Импульс</button>
</div>
<div class="param-block">
<div class="param-header"><span class="param-name">Масса нового тела</span><span class="param-val" id="sb-mass-val">5 кг</span></div>
<input type="range" class="param-slider" id="sl-sb-mass" min="1" max="30" value="5" oninput="sbMassChange()">
</div>
<div class="param-block">
<div class="param-header"><span class="param-name">Упругость</span><span class="param-val" id="sb-rest-val">0.65</span></div>
<input type="range" class="param-slider" id="sl-sb-rest" min="0" max="1" step="0.05" value="0.65" oninput="sbRestChange()">
</div>
<div class="param-block" id="sb-spring-block" style="display:none">
<div class="param-header"><span class="param-name">Жёсткость пружины k</span><span class="param-val" id="sb-springk-val">120 Н</span></div>
<input type="range" class="param-slider" id="sl-sb-springk" min="10" max="600" step="10" value="120" oninput="sbSpringKChange()">
</div>
<details class="dyn-acc" open>
<summary>Мир</summary>
<div class="dyn-acc-body">
<div class="dyn-checks">
<label><input type="checkbox" id="sb-gravity" checked onchange="sbWorldToggle()"> Гравитация</label>
<label><input type="checkbox" id="sb-floor" checked onchange="sbWorldToggle()"> Пол</label>
<label><input type="checkbox" id="sb-walls" checked onchange="sbWorldToggle()"> Стенки</label>
<label><input type="checkbox" id="sb-airdrag" onchange="sbWorldToggle()"> Сопротивление воздуха</label>
<label><input type="checkbox" id="sb-ramp" onchange="sbRampToggle()"> Наклонная плоскость</label>
</div>
<div id="sb-ramp-block" style="display:none">
<div class="param-block">
<div class="param-header"><span class="param-name">Угол α</span><span class="param-val" id="sb-angle-val">30°</span></div>
<input type="range" class="param-slider" id="sl-sb-angle" min="5" max="75" value="30" oninput="sbAngleChange()">
</div>
<div class="param-block">
<div class="param-header"><span class="param-name">Трение горки μ</span><span class="param-val" id="sb-rampmu-val">0.20</span></div>
<input type="range" class="param-slider" id="sl-sb-rampmu" min="0" max="1" step="0.01" value="0.20" oninput="sbRampMuChange()">
</div>
<label class="dyn-check-inline"><input type="checkbox" id="sb-decomp" checked onchange="sbDecompToggle()"> Разложение сил</label>
</div>
<div class="param-block">
<div class="param-header"><span class="param-name">Трение пола μ</span><span class="param-val" id="sb-floormu-val">0.30</span></div>
<input type="range" class="param-slider" id="sl-sb-floormu" min="0" max="1" step="0.01" value="0.30" oninput="sbFloorMuChange()">
</div>
</div>
</details>
<details class="dyn-acc">
<summary>Отображение</summary>
<div class="dyn-acc-body">
<div class="dyn-checks">
<label><input type="checkbox" id="sb-forces" checked onchange="sbDisplayToggle()"> Силы</label>
<label><input type="checkbox" id="sb-vel" checked onchange="sbDisplayToggle()"> Скорости</label>
<label><input type="checkbox" id="sb-fbd" onchange="sbDisplayToggle()"> FBD-диаграмма</label>
<label><input type="checkbox" id="sb-energy" checked onchange="sbDisplayToggle()"> Энергия</label>
<label><input type="checkbox" id="sb-trail" checked onchange="sbDisplayToggle()"> Стробоскоп</label>
</div>
</div>
</details>
<details class="dyn-acc">
<summary>Время</summary>
<div class="dyn-acc-body">
<div class="dyn-row-4">
<button class="mag-mode-btn sb-time" onclick="sbTimeScale(0.25,this)">×0.25</button>
<button class="mag-mode-btn sb-time" onclick="sbTimeScale(0.5,this)">×0.5</button>
<button class="mag-mode-btn sb-time active" onclick="sbTimeScale(1,this)">×1</button>
<button class="mag-mode-btn sb-time" onclick="sbTimeScale(2,this)">×2</button>
</div>
</div>
</details>
<details class="dyn-acc" open>
<summary>Пресеты</summary>
<div class="dyn-acc-body">
<div class="dyn-preset-cat">Базовые</div>
<div class="dyn-preset-grp">
<button class="proj-preset-chip" onclick="sbPreset('freefall')">Падение</button>
<button class="proj-preset-chip" onclick="sbPreset('friction')">Трение</button>
<button class="proj-preset-chip" onclick="sbPreset('balance')">Равновесие</button>
<button class="proj-preset-chip" onclick="sbPreset('projectile_angle')">Снаряд 45°</button>
<button class="proj-preset-chip" onclick="sbPreset('circular_motion')">Круговое</button>
</div>
<div class="dyn-preset-cat">Столкновения</div>
<div class="dyn-preset-grp">
<button class="proj-preset-chip" onclick="sbPreset('collision')">Столкновение</button>
<button class="proj-preset-chip" onclick="sbPreset('elastic_collision')">Упругий</button>
<button class="proj-preset-chip" onclick="sbPreset('inelastic_collision')">Неупругий</button>
<button class="proj-preset-chip" onclick="sbPreset('newton_cradle')">Колыбель Ньютона</button>
</div>
<div class="dyn-preset-cat">Пружины и осцилляторы</div>
<div class="dyn-preset-grp">
<button class="proj-preset-chip" onclick="sbPreset('spring_bounce')">Пружина</button>
<button class="proj-preset-chip" onclick="sbPreset('spring_chain')">Цепочка</button>
<button class="proj-preset-chip" onclick="sbPreset('harmonic_oscillator')">Осциллятор</button>
<button class="proj-preset-chip" onclick="sbPreset('coupled_oscillators')">Связанные</button>
</div>
<div class="dyn-preset-cat">Маятники и блоки</div>
<div class="dyn-preset-grp">
<button class="proj-preset-chip" onclick="sbPreset('pendulum')">Маятник</button>
<button class="proj-preset-chip" onclick="sbPreset('double_pendulum')">Двойной маятник</button>
<button class="proj-preset-chip" onclick="sbPreset('atwood')">Атвуд</button>
<button class="proj-preset-chip" onclick="sbPreset('two_body')">Два тела</button>
<button class="proj-preset-chip" onclick="sbPreset('tug')">Перетягивание</button>
</div>
<div class="dyn-preset-cat">Горки и стопки</div>
<div class="dyn-preset-grp">
<button class="proj-preset-chip" onclick="sbPreset('ramp_slide')">Горка</button>
<button class="proj-preset-chip" onclick="sbPreset('ramp_angle')">Крутой спуск</button>
<button class="proj-preset-chip" onclick="sbPreset('ramp_friction')">Трение на горке</button>
<button class="proj-preset-chip" onclick="sbPreset('pulley_ramp')">Горка+блок</button>
<button class="proj-preset-chip" onclick="sbPreset('stacked_boxes')">Стопка</button>
</div>
</div>
</details>
<div style="font-size:.78rem;color:var(--text-2);line-height:1.55;margin-top:14px;padding:9px 11px;background:rgba(255,255,255,0.035);border-radius:8px;border:1px solid var(--border)">
<b style="color:var(--violet);font-size:.78rem;display:block;margin-bottom:4px">Управление</b>
ЛКМ — создать тело · Drag — сила<br>
Shift+drag — импульс · ПКМ — удалить<br>
DblClick — закрепить / открепить<br>
Пружина / Нить — кликни 2 тела
</div>
<!-- Sandbox graphs toggle -->
<div style="margin-top:10px">
<button id="btn-sandbox-graphs" onclick="sandboxToggleGraphs()" style="width:100%;font-size:.82rem;font-weight:700;padding:8px;border-radius:8px;border:1px solid rgba(6,214,224,0.35);background:rgba(6,214,224,0.1);color:#06D6E0;cursor:pointer">Графики тела</button>
</div>
<!-- Energy bars toggle — sandbox -->
<button id="fsb-energy-btn" class="proj-preset-chip" onclick="fsbToggleEnergy()" style="width:100%;font-size:.82rem;text-align:left;display:flex;align-items:center;gap:7px;margin-top:8px;padding:8px 11px">
<svg class="ic" viewBox="0 0 24 24"><path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z"/></svg>
<span>Энергия+: Выкл</span>
</button>
</div><!-- /#dyn-sandbox-panel -->
</div><!-- /.proj-panel -->
<div class="proj-canvas-outer">
<canvas id="newton-canvas" style="display:none;position:absolute;top:0;left:0;width:100%;height:100%;cursor:default"></canvas>
<canvas id="sandbox-canvas" style="display:block;position:absolute;top:0;left:0;width:100%;height:100%;cursor:crosshair"></canvas>
</div>
</div><!-- /.sim-body-wrap -->
<div class="proj-stats-bar" id="dyn-stats-bar">
<div class="pstat"><div class="pstat-label" id="dbar-l1">Тел</div><div class="pstat-val" id="dbar-v1" style="color:var(--cyan)">0</div></div>
<div class="pstat"><div class="pstat-label" id="dbar-l2">KE (Дж)</div><div class="pstat-val" id="dbar-v2" style="color:#4CC9F0">0</div></div>
<div class="pstat"><div class="pstat-label" id="dbar-l3">PE (Дж)</div><div class="pstat-val" id="dbar-v3" style="color:#7BF5A4">0</div></div>
<div class="pstat"><div class="pstat-label" id="dbar-l4">ΣF</div><div class="pstat-val" id="dbar-v4" style="color:#EF476F"></div></div>
<div class="pstat"><div class="pstat-label" id="dbar-l5">Время</div><div class="pstat-val" id="dbar-v5" style="color:#FFD166">0 с</div></div>
</div>
</div><!-- /#sim-dynamics -->
<!-- ── PROJECTILE sim body ── -->
<div id="sim-proj" class="sim-proj-wrap" style="display:none">
<div class="sim-body-wrap">
<!-- controls panel -->
<div class="proj-panel" style="width:240px">
<div class="gp-section-title">Параметры</div>
<div class="param-block">
<div class="param-header">
<span class="param-name">Скорость v₀</span>
<span class="param-val" id="p-v0">20 м/с</span>
</div>
<input type="range" class="param-slider" id="sl-v0" min="1" max="100" value="20" oninput="projParam()">
</div>
<div class="param-block">
<div class="param-header">
<span class="param-name">Угол θ</span>
<span class="param-val" id="p-angle">45°</span>
</div>
<input type="range" class="param-slider" id="sl-angle" min="0" max="90" value="45" oninput="projParam()">
</div>
<div class="param-block">
<div class="param-header">
<span class="param-name">Высота h₀</span>
<span class="param-val" id="p-h0">2 м</span>
</div>
<input type="range" class="param-slider" id="sl-h0" min="0" max="50" value="2" oninput="projParam()">
</div>
<div class="param-block">
<div class="param-header">
<span class="param-name">Сила тяжести g</span>
<span class="param-val" id="p-g">9.81 м/с²</span>
</div>
<input type="range" class="param-slider" id="sl-g" min="1" max="25" step="0.01" value="9.81" oninput="projParam()">
</div>
<!-- Air resistance -->
<div class="gp-section-title" style="margin-top:6px">Сопротивление воздуха</div>
<label class="tri-layer-row" id="drag-row" onclick="projToggleDrag(this)" style="margin-bottom:6px">
<span class="tri-dot" style="background:rgba(239,71,111,0.5)"></span>
<span class="tri-layer-name">Воздух</span>
<span class="tri-toggle" id="drag-toggle" style="background:rgba(255,255,255,0.12)"><span style="display:block;width:12px;height:12px;border-radius:50%;background:#fff;margin:2px;margin-left:2px"></span></span>
</label>
<div id="drag-params" style="display:none">
<div class="param-block">
<div class="param-header">
<span class="param-name">Коэф. Cd</span>
<span class="param-val" id="p-cd">0.30</span>
</div>
<input type="range" class="param-slider" id="sl-cd" min="1" max="100" value="30" oninput="projCdChange()">
</div>
<div class="param-block">
<div class="param-header">
<span class="param-name">Масса тела m</span>
<span class="param-val" id="p-mass">1 кг</span>
</div>
<input type="range" class="param-slider" id="sl-mass" min="1" max="20" value="1" oninput="projMassChange()">
</div>
</div>
<!-- Wind -->
<div class="gp-section-title" style="margin-top:6px">Ветер</div>
<div class="param-block">
<div class="param-header">
<span class="param-name">Скорость ветра</span>
<span class="param-val" id="p-wind">0 м/с</span>
</div>
<input type="range" class="param-slider" id="sl-wind" min="-20" max="20" value="0" step="1" oninput="projWindChange()">
</div>
<!-- Bounce -->
<div class="gp-section-title" style="margin-top:6px">Отскок</div>
<label class="tri-layer-row" id="bounce-row" onclick="projToggleBounce(this)" style="margin-bottom:6px">
<span class="tri-dot" style="background:rgba(123,245,164,0.5)"></span>
<span class="tri-layer-name">Отскок при ударе</span>
<span class="tri-toggle" id="bounce-toggle" style="background:rgba(255,255,255,0.12)"><span style="display:block;width:12px;height:12px;border-radius:50%;background:#fff;margin:2px;margin-left:2px;transition:margin-left .15s"></span></span>
</label>
<div id="bounce-params" style="display:none">
<div class="param-block">
<div class="param-header">
<span class="param-name">Коэф. упругости e</span>
<span class="param-val" id="p-restitution">0.70</span>
</div>
<input type="range" class="param-slider" id="sl-restitution" min="0" max="100" value="70" oninput="projRestitutionChange()">
</div>
</div>
<!-- Parachute -->
<div class="gp-section-title" style="margin-top:6px">Парашют</div>
<label class="tri-layer-row" id="chute-row" onclick="projToggleParachute(this)" style="margin-bottom:6px">
<span class="tri-dot" style="background:rgba(6,214,224,0.5)"></span>
<span class="tri-layer-name">Парашют</span>
<span class="tri-toggle" id="chute-toggle" style="background:rgba(255,255,255,0.12)"><span style="display:block;width:12px;height:12px;border-radius:50%;background:#fff;margin:2px;margin-left:2px;transition:margin-left .15s"></span></span>
</label>
<div id="chute-params" style="display:none">
<div class="param-block">
<div class="param-header">
<span class="param-name">Площадь A</span>
<span class="param-val" id="p-chute-area">1.0 м²</span>
</div>
<input type="range" class="param-slider" id="sl-chute-area" min="1" max="100" value="10" oninput="projChuteAreaChange()">
</div>
<div class="param-block" style="margin-bottom:6px">
<span class="param-name" style="font-size:.68rem">Форма (Cd)</span>
<select id="sel-chute-cd" onchange="projChuteCdChange()" style="width:100%;margin-top:4px;background:#0d0d2a;color:#fff;border:1px solid rgba(255,255,255,.15);border-radius:6px;padding:4px 6px;font-size:.75rem">
<option value="1.5" selected>Парашют (1.5)</option>
<option value="1.05">Куб (1.05)</option>
<option value="0.47">Сфера (0.47)</option>
<option value="0.42">Полусфера (0.42)</option>
<option value="1.17">Плоский диск (1.17)</option>
</select>
</div>
<div class="param-block">
<div class="param-header">
<span class="param-name">Раскрыть на h</span>
<span class="param-val" id="p-chute-height">Сразу</span>
</div>
<input type="range" class="param-slider" id="sl-chute-height" min="0" max="100" value="0" oninput="projChuteHeightChange()">
<div style="font-size:.6rem;color:var(--text-3);margin-top:2px">0 = немедленно, &gt;0 = раскрыть на этой высоте</div>
</div>
</div>
<!-- Ramp -->
<div class="gp-section-title" style="margin-top:6px">Наклонная горка</div>
<label class="tri-layer-row" id="ramp-row" onclick="projToggleRamp(this)" style="margin-bottom:6px">
<span class="tri-dot" style="background:rgba(255,180,50,0.5)"></span>
<span class="tri-layer-name">Старт с горки</span>
<span class="tri-toggle" id="ramp-toggle" style="background:rgba(255,255,255,0.12)"><span style="display:block;width:12px;height:12px;border-radius:50%;background:#fff;margin:2px;margin-left:2px;transition:margin-left .15s"></span></span>
</label>
<div id="ramp-params" style="display:none">
<div class="param-block">
<div class="param-header">
<span class="param-name">Угол горки &alpha;</span>
<span class="param-val" id="p-ramp-angle">30&deg;</span>
</div>
<input type="range" class="param-slider" id="sl-ramp-angle" min="5" max="85" value="30" oninput="projRampChange()">
</div>
<div class="param-block">
<div class="param-header">
<span class="param-name">Длина L</span>
<span class="param-val" id="p-ramp-length">10 м</span>
</div>
<input type="range" class="param-slider" id="sl-ramp-length" min="1" max="50" value="10" oninput="projRampChange()">
</div>
<div class="param-block">
<div class="param-header">
<span class="param-name">Трение &mu;</span>
<span class="param-val" id="p-ramp-mu">0.10</span>
</div>
<input type="range" class="param-slider" id="sl-ramp-mu" min="0" max="80" value="10" oninput="projRampChange()">
<div style="font-size:.6rem;color:var(--text-3);margin-top:2px">v = sqrt(2gL(sin&alpha; &minus; &mu; cos&alpha;))</div>
</div>
</div>
<!-- Planet -->
<div class="gp-section-title" style="margin-top:6px">Планета / гравитация</div>
<div class="param-block" style="margin-bottom:6px">
<select id="sel-planet" onchange="projPlanetChange()" style="width:100%;background:#0d0d2a;color:#fff;border:1px solid rgba(255,255,255,.15);border-radius:6px;padding:4px 6px;font-size:.75rem">
<option value="earth" selected>Земля &mdash; g=9.81</option>
<option value="moon">Луна &mdash; g=1.62</option>
<option value="mars">Марс &mdash; g=3.71</option>
<option value="venus">Венера &mdash; g=8.87</option>
<option value="jupiter">Юпитер &mdash; g=24.79</option>
<option value="mercury">Меркурий &mdash; g=3.7</option>
<option value="saturn">Сатурн &mdash; g=10.44</option>
<option value="uranus">Уран &mdash; g=8.69</option>
<option value="neptune">Нептун &mdash; g=11.15</option>
<option value="pluto">Плутон &mdash; g=0.62</option>
</select>
</div>
<button id="proj-planet-compare-btn" class="proj-preset-chip" onclick="projTogglePlanetCompare()" style="width:100%;text-align:left;display:flex;align-items:center;gap:6px;margin-bottom:4px">
<svg class="ic" viewBox="0 0 24 24"><circle cx="5" cy="12" r="3"/><circle cx="12" cy="5" r="3"/><circle cx="19" cy="19" r="3"/><line x1="5" y1="12" x2="12" y2="5"/><line x1="12" y1="5" x2="19" y2="19"/></svg>
<span>Сравн.планет: Выкл</span>
</button>
<div id="proj-planet-compare-panel" style="display:none;font-size:.65rem;color:rgba(255,255,255,.6);margin-bottom:4px">
<div style="display:flex;gap:4px;flex-direction:column">
<div style="display:flex;align-items:center;gap:6px">
<span style="color:#06D6E0;font-weight:700">1:</span>
<select onchange="projPlanetCompareChange(0,this.value)" style="flex:1;background:#0d0d2a;color:#06D6E0;border:1px solid rgba(6,214,224,.3);border-radius:4px;padding:2px 4px;font-size:.7rem">
<option value="earth" selected>Земля</option><option value="moon">Луна</option><option value="mars">Марс</option><option value="venus">Венера</option><option value="jupiter">Юпитер</option><option value="mercury">Меркурий</option><option value="saturn">Сатурн</option><option value="uranus">Уран</option><option value="neptune">Нептун</option><option value="pluto">Плутон</option>
</select>
</div>
<div style="display:flex;align-items:center;gap:6px">
<span style="color:#7BF5A4;font-weight:700">2:</span>
<select onchange="projPlanetCompareChange(1,this.value)" style="flex:1;background:#0d0d2a;color:#7BF5A4;border:1px solid rgba(123,245,164,.3);border-radius:4px;padding:2px 4px;font-size:.7rem">
<option value="earth">Земля</option><option value="moon" selected>Луна</option><option value="mars">Марс</option><option value="venus">Венера</option><option value="jupiter">Юпитер</option><option value="mercury">Меркурий</option><option value="saturn">Сатурн</option><option value="uranus">Уран</option><option value="neptune">Нептун</option><option value="pluto">Плутон</option>
</select>
</div>
<div style="display:flex;align-items:center;gap:6px">
<span style="color:#F15BB5;font-weight:700">3:</span>
<select onchange="projPlanetCompareChange(2,this.value)" style="flex:1;background:#0d0d2a;color:#F15BB5;border:1px solid rgba(241,91,181,.3);border-radius:4px;padding:2px 4px;font-size:.7rem">
<option value="earth">Земля</option><option value="moon">Луна</option><option value="mars" selected>Марс</option><option value="venus">Венера</option><option value="jupiter">Юпитер</option><option value="mercury">Меркурий</option><option value="saturn">Сатурн</option><option value="uranus">Уран</option><option value="neptune">Нептун</option><option value="pluto">Плутон</option>
</select>
</div>
</div>
</div>
<div class="gp-section-title" style="margin-top:6px">Пресеты</div>
<div style="display:flex;flex-wrap:wrap;gap:6px">
<button class="proj-preset-chip" onclick="projPreset(20,45,0,9.81)">Земля 45°</button>
<button class="proj-preset-chip" onclick="projPreset(20,30,0,9.81)">30°</button>
<button class="proj-preset-chip" onclick="projPreset(20,60,0,9.81)">60°</button>
<button class="proj-preset-chip" onclick="projPreset(20,45,15,9.81)">С высоты</button>
<button class="proj-preset-chip" onclick="projPreset(30,45,0,1.62)">Луна</button>
<button class="proj-preset-chip" onclick="projPreset(30,45,0,3.72)">Марс</button>
<button class="proj-preset-chip" onclick="projPreset(50,45,0,9.81)">Дальний</button>
<button class="proj-preset-chip" onclick="projPreset(20,90,0,9.81)">Вверх</button>
</div>
<!-- Speed -->
<div class="gp-section-title" style="margin-top:8px">Скорость симуляции</div>
<div style="display:flex;gap:5px;margin-bottom:8px">
<button class="mag-mode-btn proj-speed" onclick="projSetSpeed(0.25,this)" style="flex:1;font-size:.68rem">×0.25</button>
<button class="mag-mode-btn proj-speed" onclick="projSetSpeed(0.5,this)" style="flex:1;font-size:.68rem">×0.5</button>
<button class="mag-mode-btn proj-speed active" onclick="projSetSpeed(1,this)" style="flex:1;font-size:.68rem">×1</button>
<button class="mag-mode-btn proj-speed" onclick="projSetSpeed(2,this)" style="flex:1;font-size:.68rem">×2</button>
<button class="mag-mode-btn proj-speed" onclick="projSetSpeed(4,this)" style="flex:1;font-size:.68rem">×4</button>
</div>
<!-- Ghost trails -->
<div class="gp-section-title" style="margin-top:10px">Сравнение</div>
<div style="display:flex;gap:6px;flex-wrap:wrap">
<button class="proj-preset-chip" onclick="projSaveGhost()" style="border-color:rgba(255,214,102,.4);color:#FFD166">Зафиксировать</button>
<button class="proj-preset-chip" onclick="projClearGhosts()" style="border-color:rgba(255,255,255,.15)"><svg class="ic" viewBox="0 0 24 24"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg> Очистить следы</button>
</div>
<div style="font-size:.6rem;color:var(--text-3);margin-top:4px">Сохрани траекторию, измени параметры и сравни</div>
<!-- Feature 1: Target mode -->
<div class="gp-section-title" style="margin-top:10px">Режим целей</div>
<button id="proj-target-btn" class="proj-preset-chip" onclick="projToggleTargetMode()" style="width:100%;text-align:left;display:flex;align-items:center;gap:6px">
<svg class="ic" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><circle cx="12" cy="12" r="6"/><circle cx="12" cy="12" r="2"/></svg>
<span>Режим целей: Выкл</span>
</button>
<div id="proj-target-panel" style="display:none;margin-top:6px">
<button class="proj-preset-chip" onclick="projGenTargets()" style="width:100%;text-align:center">
<svg class="ic" viewBox="0 0 24 24"><path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"/><path d="M3 3v5h5"/></svg>
Новые цели
</button>
<div id="proj-target-hud" style="font-size:.72rem;font-weight:700;color:#FFD166;margin-top:6px;text-align:center">Цели: 0/3 Попыток: 0</div>
</div>
<!-- Energy bars toggle -->
<div class="gp-section-title" style="margin-top:10px">Закон сохранения энергии</div>
<button id="proj-energy-btn" class="proj-preset-chip" onclick="projToggleEnergy()" style="width:100%;text-align:left;display:flex;align-items:center;gap:6px">
<svg class="ic" viewBox="0 0 24 24"><path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z"/></svg>
<span>Энергия: Выкл</span>
</button>
<!-- Feature 2: Graphs toggle -->
<div class="gp-section-title" style="margin-top:10px">Графики</div>
<button id="proj-graphs-btn" class="proj-preset-chip" onclick="projToggleGraphs()" style="width:100%;text-align:left;display:flex;align-items:center;gap:6px">
<svg class="ic" viewBox="0 0 24 24"><polyline points="22 12 18 12 15 21 9 3 6 12 2 12"/></svg>
<span>x(t), y(t), vx(t), vy(t)</span>
</button>
<!-- Feature 3: Dual throw -->
<div class="gp-section-title" style="margin-top:10px">Двойной бросок</div>
<button id="proj-dual-btn" class="proj-preset-chip" onclick="projToggleDual()" style="width:100%;text-align:left;display:flex;align-items:center;gap:6px">
<svg class="ic" viewBox="0 0 24 24"><circle cx="8" cy="18" r="3"/><circle cx="18" cy="6" r="3"/><path d="M8 15V9l10-6"/></svg>
<span>Двойной: Выкл</span>
</button>
<div id="proj-dual-panel" style="display:none;margin-top:6px">
<div style="font-size:.65rem;color:rgba(0,230,255,.8);font-weight:700;margin-bottom:4px">Тело 2 (cyan)</div>
<div class="param-block">
<div class="param-header">
<span class="param-name">Скорость v₀₂</span>
<span class="param-val" id="p2-v0" style="color:#00E6FF">25 м/с</span>
</div>
<input type="range" class="param-slider proj-dual-slider" id="sl-p2-v0" min="1" max="100" value="25" oninput="projP2Param()">
</div>
<div class="param-block">
<div class="param-header">
<span class="param-name">Угол θ₂</span>
<span class="param-val" id="p2-angle" style="color:#00E6FF">30°</span>
</div>
<input type="range" class="param-slider proj-dual-slider" id="sl-p2-angle" min="0" max="90" value="30" oninput="projP2Param()">
</div>
<div class="param-block">
<div class="param-header">
<span class="param-name">Высота h₀₂</span>
<span class="param-val" id="p2-h0" style="color:#00E6FF">0 м</span>
</div>
<input type="range" class="param-slider proj-dual-slider" id="sl-p2-h0" min="0" max="50" value="0" oninput="projP2Param()">
</div>
</div>
<!-- LAUNCH BUTTON -->
<div style="margin-top:auto; padding-top:16px; display:flex; flex-direction:column; gap:8px;">
<button class="proj-launch-btn" id="proj-launch-main" onclick="projPlayPause()">
<svg id="proj-launch-icon" viewBox="0 0 24 24" width="20" height="20" fill="currentColor">
<polygon points="5 3 19 12 5 21 5 3"/>
</svg>
<span id="proj-launch-label">Запустить</span>
</button>
<button class="proj-reset-btn" onclick="pSim && pSim.reset(); _projSyncPlayBtn()">
<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2.2">
<path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"/><path d="M3 3v5h5"/>
</svg>
Сброс
</button>
</div>
</div>
<!-- canvas -->
<div class="proj-canvas-outer">
<canvas id="proj-canvas"></canvas>
</div>
</div><!-- /.sim-body-wrap -->
<!-- graphs panel (Feature 2) -->
<div id="proj-graphs-panel" style="display:none;background:#05050e;border-top:1px solid rgba(255,255,255,.07)">
<canvas id="proj-graphs-canvas" class="proj-graphs-canvas"></canvas>
</div>
<!-- stats bar -->
<div class="proj-stats-bar">
<div class="pstat">
<div class="pstat-label">Дальность</div>
<div class="pstat-val" id="ps-range"></div>
</div>
<div class="pstat">
<div class="pstat-label">Макс. высота</div>
<div class="pstat-val" id="ps-hmax"></div>
</div>
<div class="pstat">
<div class="pstat-label">Время полёта</div>
<div class="pstat-val" id="ps-tf"></div>
</div>
<div class="pstat">
<div class="pstat-label">Скор. удара</div>
<div class="pstat-val" id="ps-vland"></div>
</div>
<div class="pstat">
<div class="pstat-label">Текущее t</div>
<div class="pstat-val" id="ps-t">0.00 с</div>
</div>
<div class="pstat">
<div class="pstat-label">Угол посадки</div>
<div class="pstat-val" id="ps-land-angle"></div>
</div>
<div class="pstat" id="ps-loss-wrap" style="display:none">
<div class="pstat-label">Δ дальность</div>
<div class="pstat-val" id="ps-loss"></div>
</div>
<!-- dual throw stats (Feature 3) -->
<div class="pstat" id="ps-p2-wrap" style="display:none">
<div class="pstat-label" style="color:rgba(0,230,255,.7)">Дальн.&#8202;2</div>
<div class="pstat-val" id="ps-p2-range" style="color:#00E6FF"></div>
</div>
<div class="pstat" id="ps-p2-tf-wrap" style="display:none">
<div class="pstat-label" style="color:rgba(0,230,255,.7)">Время&#8202;2</div>
<div class="pstat-val" id="ps-p2-tf" style="color:#00E6FF"></div>
</div>
</div>
</div><!-- /#sim-proj -->
<!-- ── COLLISION sim body ── -->
<div id="sim-coll" class="sim-proj-wrap" style="display:none">
<div class="sim-body-wrap">
<!-- controls panel -->
<div class="proj-panel" style="width:240px">
<div class="gp-section-title">Параметры</div>
<div class="param-block">
<div class="param-header">
<span class="param-name" style="color:var(--violet)">Масса m₁</span>
<span class="param-val" id="c-m1">4 кг</span>
</div>
<input type="range" class="param-slider" id="sl-m1" min="1" max="20" value="4" oninput="collParam()">
</div>
<div class="param-block">
<div class="param-header">
<span class="param-name" style="color:var(--cyan)">Масса m₂</span>
<span class="param-val" id="c-m2">4 кг</span>
</div>
<input type="range" class="param-slider" id="sl-m2" min="1" max="20" value="4" oninput="collParam()">
</div>
<div class="param-block">
<div class="param-header">
<span class="param-name" style="color:var(--violet)">Скорость v₁</span>
<span class="param-val" id="c-v1">8 м/с</span>
</div>
<input type="range" class="param-slider" id="sl-cv1" min="0" max="30" value="8" oninput="collParam()">
</div>
<div class="param-block">
<div class="param-header">
<span class="param-name" style="color:var(--cyan)">Скорость v₂</span>
<span class="param-val" id="c-v2">8 м/с</span>
</div>
<input type="range" class="param-slider" id="sl-cv2" min="0" max="30" value="8" oninput="collParam()">
</div>
<div class="param-block">
<div class="param-header">
<span class="param-name">Угол v₂</span>
<span class="param-val" id="c-angle"></span>
</div>
<input type="range" class="param-slider" id="sl-cangle" min="-60" max="60" value="0" oninput="collParam()">
</div>
<div class="param-block">
<div class="param-header">
<span class="param-name">Упругость e</span>
<span class="param-val" id="c-e">1.00</span>
</div>
<input type="range" class="param-slider" id="sl-e" min="0" max="1" step="0.01" value="1" oninput="collParam()">
</div>
<div class="param-block">
<div class="param-header">
<span class="param-name"><svg class="ic" viewBox="0 0 24 24"><polygon points="13 19 22 12 13 5 13 19"/><polygon points="2 19 11 12 2 5 2 19"/></svg> Скорость</span>
<span class="param-val" id="c-speed" style="color:var(--cyan)">1.00×</span>
</div>
<input type="range" class="param-slider" id="sl-speed" min="0.1" max="4" step="0.05" value="1"
oninput="collParam()" style="--track-color:#06D6E0">
</div>
<div class="gp-section-title" style="margin-top:6px">Пресеты</div>
<div style="display:flex;flex-wrap:wrap;gap:6px">
<button class="proj-preset-chip" onclick="collPreset(4,4,8,8,0,1)">Упругий 1:1</button>
<button class="proj-preset-chip" onclick="collPreset(4,4,8,8,0,0)">Абс. неупругий</button>
<button class="proj-preset-chip" onclick="collPreset(4,4,8,8,0,0.5)">e = 0.5</button>
<button class="proj-preset-chip" onclick="collPreset(4,4,12,0,0,1)">Бильярд</button>
<button class="proj-preset-chip" onclick="collPreset(2,8,14,0,0,1)">Лёгкий<svg class="ic" viewBox="0 0 24 24"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg>тяжёлый</button>
<button class="proj-preset-chip" onclick="collPreset(8,2,6,0,0,1)">Тяжёлый<svg class="ic" viewBox="0 0 24 24"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg>лёгкий</button>
<button class="proj-preset-chip" onclick="collPreset(2,14,18,0,0,1)">Большая разница</button>
<button class="proj-preset-chip" onclick="collPreset(5,5,8,8,30,1)">Косой 30°</button>
<button class="proj-preset-chip" onclick="collPreset(5,5,8,8,50,0.8)">Скользящий</button>
<button class="proj-preset-chip" onclick="collPreset(6,6,10,10,0,0)">Слипание</button>
</div>
<!-- graphs toggle -->
<div style="margin-top:10px">
<button id="btn-coll-graphs" onclick="collToggleGraphs()" style="width:100%;font-size:.75rem;padding:5px;border-radius:8px;border:1px solid rgba(6,214,224,0.3);background:rgba(6,214,224,0.08);color:#06D6E0;cursor:pointer">&#1043;&#1088;&#1072;&#1092;&#1080;&#1082;&#1080; &#1089;&#1082;&#1086;&#1088;&#1086;&#1089;&#1090;&#1077;&#1081;</button>
</div>
<!-- Energy bars toggle -->
<div class="gp-section-title" style="margin-top:10px">&#1047;&#1072;&#1082;&#1086;&#1085; &#1089;&#1086;&#1093;&#1088;&#1072;&#1085;&#1077;&#1085;&#1080;&#1103; &#1101;&#1085;&#1077;&#1088;&#1075;&#1080;&#1080;</div>
<button id="coll-energy-btn" class="proj-preset-chip" onclick="collToggleEnergy()" style="width:100%;text-align:left;display:flex;align-items:center;gap:6px">
<svg class="ic" viewBox="0 0 24 24"><path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z"/></svg>
<span>&#1069;&#1085;&#1077;&#1088;&#1075;&#1080;&#1103;: &#1042;&#1099;&#1082;&#1083;</span>
</button>
<!-- launch button -->
<div style="margin-top:auto; padding-top:16px; display:flex; flex-direction:column; gap:8px;">
<button class="proj-launch-btn" id="coll-launch-main" onclick="collPlayPause()">
<svg id="coll-launch-icon" viewBox="0 0 24 24" width="20" height="20" fill="currentColor">
<polygon points="5 3 19 12 5 21 5 3"/>
</svg>
<span id="coll-launch-label">Запустить</span>
</button>
<button class="proj-reset-btn" onclick="var _rs=_activeSim&&_activeSim();if(_rs)_rs.reset();_collSyncBtn()">
<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2.2">
<path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"/><path d="M3 3v5h5"/>
</svg>
Сброс
</button>
</div>
</div>
<!-- canvas -->
<div class="proj-canvas-outer">
<canvas id="coll-canvas"></canvas>
</div>
</div><!-- /.sim-body-wrap -->
<!-- stats bar -->
<div class="proj-stats-bar">
<div class="pstat">
<div class="pstat-label">Импульс до</div>
<div class="pstat-val" id="cs-pbefore"></div>
</div>
<div class="pstat">
<div class="pstat-label">Импульс после</div>
<div class="pstat-val" id="cs-pafter"></div>
</div>
<div class="pstat">
<div class="pstat-label">КЭ до</div>
<div class="pstat-val" id="cs-kebefore"></div>
</div>
<div class="pstat">
<div class="pstat-label">КЭ после</div>
<div class="pstat-val" id="cs-keafter"></div>
</div>
<div class="pstat">
<div class="pstat-label">Столкновений</div>
<div class="pstat-val" id="cs-count">0</div>
</div>
</div>
</div><!-- /#sim-coll -->
<!-- ── CRYSTAL sim body ── -->
<div id="sim-crystal" class="sim-body-wrap" style="display:none">
<div class="graph-panel">
<div class="gp-section-title">Тип решётки</div>
<button class="gp-btn crystal-type-btn active" id="crys-nacl" onclick="setCrystal('nacl',this)" style="margin-bottom:6px"><svg class="ic" viewBox="0 0 24 24"><path d="M3 18a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V7H3z"/><path d="M3 7V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v2"/><path d="M12 11v4M10 13h4"/></svg> NaCl (ионная)</button>
<button class="gp-btn crystal-type-btn" id="crys-diamond" onclick="setCrystal('diamond',this)" style="margin-bottom:6px"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="display:inline-block;vertical-align:middle"><path d="M6 3l-3 7 9 11 9-11-3-7H6z"/><path d="M3 10h18"/><path d="M12 21L6 3"/><path d="M12 21l6-18"/></svg> Алмаз (ковалентная)</button>
<button class="gp-btn crystal-type-btn" id="crys-bcc" onclick="setCrystal('bcc',this)" style="margin-bottom:6px">ОЦК (металл)</button>
<button class="gp-btn crystal-type-btn" id="crys-fcc" onclick="setCrystal('fcc',this)" style="margin-bottom:6px">ГЦК (металл)</button>
<div class="gp-section-title" style="margin-top:12px">Управление</div>
<div class="tp-text" style="font-size:0.72rem">Вращение: зажмите и тяните<br>Зум: колёсико мыши</div>
</div>
<div class="graph-canvas-outer">
<div class="graph-canvas-wrap" id="crystal-container"></div>
</div>
</div>
<!-- ── ORBITALS sim body ── -->
<div id="sim-orbitals" class="sim-body-wrap" style="display:none">
<div class="graph-panel">
<div class="gp-section-title">Орбиталь</div>
<button class="gp-btn orbital-mode-btn active" id="orb-s" onclick="setOrbital('s',this)" style="margin-bottom:6px"<span style="display:inline-block;width:10px;height:10px;border-radius:50%;background:#4CC9F0;margin-right:4px"></span>s-орбиталь</button>
<button class="gp-btn orbital-mode-btn" id="orb-p" onclick="setOrbital('p',this)" style="margin-bottom:6px"<span style="display:inline-block;width:10px;height:10px;border-radius:50%;background:#06D6A0;margin-right:4px"></span>p-орбитали</button>
<button class="gp-btn orbital-mode-btn" id="orb-d" onclick="setOrbital('d',this)" style="margin-bottom:6px"<span style="display:inline-block;width:10px;height:10px;border-radius:50%;background:#FFD166;margin-right:4px"></span>d-орбитали</button>
<div class="gp-section-title" style="margin-top:12px">Молекулы</div>
<button class="gp-btn orbital-mode-btn" id="orb-h2" onclick="setOrbital('h2',this)" style="margin-bottom:6px">H₂ (σ-связь)</button>
<button class="gp-btn orbital-mode-btn" id="orb-h2o" onclick="setOrbital('h2o',this)" style="margin-bottom:6px">H₂O (угловая)</button>
<div class="gp-section-title" style="margin-top:12px">Управление</div>
<div class="tp-text" style="font-size:0.72rem">Вращение: зажмите и тяните<br>Зум: колёсико мыши</div>
</div>
<div class="graph-canvas-outer">
<div class="graph-canvas-wrap" id="orbitals-container"></div>
</div>
</div>
<!-- ── CHEM SANDBOX sim body ── -->
<div id="sim-chemsandbox" class="sim-proj-wrap" style="display:none">
<div class="sim-body-wrap">
<div class="proj-panel" style="width:220px;gap:0">
<!-- Category filter -->
<div class="gp-section-title" style="margin-bottom:6px">Реагенты</div>
<div style="display:flex;flex-wrap:wrap;gap:3px;margin-bottom:10px">
<button class="proj-preset-chip reac-mode-btn chemsand-cat active" onclick="chemSandCat('all',this)">Все</button>
<button class="proj-preset-chip reac-mode-btn chemsand-cat" onclick="chemSandCat('acid',this)">Кислоты</button>
<button class="proj-preset-chip reac-mode-btn chemsand-cat" onclick="chemSandCat('base',this)">Основания</button>
<button class="proj-preset-chip reac-mode-btn chemsand-cat" onclick="chemSandCat('salt',this)">Соли</button>
<button class="proj-preset-chip reac-mode-btn chemsand-cat" onclick="chemSandCat('metal',this)">Металлы</button>
<button class="proj-preset-chip reac-mode-btn chemsand-cat" onclick="chemSandCat('indicator',this)">Индикаторы</button>
<button class="proj-preset-chip reac-mode-btn chemsand-cat" onclick="chemSandCat('other',this)">Другое</button>
</div>
<!-- Reagent list -->
<div id="chemsand-reagents" style="display:flex;flex-wrap:wrap;gap:4px;margin-bottom:12px;max-height:180px;overflow-y:auto"></div>
<!-- Presets -->
<div class="gp-section-title" style="margin-bottom:6px">Пресеты</div>
<div style="display:flex;flex-wrap:wrap;gap:4px;margin-bottom:10px">
<button class="proj-preset-chip" onclick="chemSandPreset('neutralization')">Нейтрализация</button>
<button class="proj-preset-chip" onclick="chemSandPreset('gas_evolution')">Газ CO₂</button>
<button class="proj-preset-chip" onclick="chemSandPreset('precipitate')">Осадок AgCl</button>
<button class="proj-preset-chip" onclick="chemSandPreset('displacement')">Замещение Cu</button>
<button class="proj-preset-chip" onclick="chemSandPreset('indicator')">Индикатор</button>
<button class="proj-preset-chip" onclick="chemSandPreset('violent')">Na + H₂O</button>
<button class="proj-preset-chip" onclick="chemSandPreset('yellow_precip')">PbCrO₄<svg class="ic" viewBox="0 0 24 24"><line x1="12" y1="5" x2="12" y2="19"/><polyline points="19 12 12 19 5 12"/></svg></button>
<button class="proj-preset-chip" onclick="chemSandPreset('blue_precip')">Cu(OH)₂<svg class="ic" viewBox="0 0 24 24"><line x1="12" y1="5" x2="12" y2="19"/><polyline points="19 12 12 19 5 12"/></svg></button>
</div>
<!-- Sliders -->
<div class="gp-section-title" style="margin-bottom:4px;margin-top:4px">Условия</div>
<div class="param-block" style="margin-bottom:5px">
<div class="param-header"><span class="param-name" style="font-size:.7rem">Концентрация</span><span class="param-val" id="csand-conc-val" style="font-size:.7rem;min-width:40px">35%</span></div>
<input type="range" class="param-slider" id="sl-csand-conc" min="5" max="95" value="35" oninput="chemSandConcChange()">
</div>
<div class="param-block" style="margin-bottom:5px">
<div class="param-header"><span class="param-name" style="font-size:.7rem">Температура</span><span class="param-val" id="csand-temp-val" style="font-size:.7rem;min-width:40px">20°C</span></div>
<input type="range" class="param-slider" id="sl-csand-temp" min="0" max="100" value="20" oninput="chemSandTempChange()">
</div>
<!-- Quiz mode -->
<div class="pp-group" style="margin-top:8px">
<div class="pp-label" style="font-size:.65rem">Режим</div>
<div style="display:flex;gap:6px;align-items:center">
<button class="proj-preset-chip reac-mode-btn chemsand-mode active" id="csand-mode-free" onclick="chemSandSetMode('free',this)">Свободный</button>
<button class="proj-preset-chip reac-mode-btn chemsand-mode" id="csand-mode-quiz" onclick="chemSandSetMode('quiz',this)">Задания</button>
<span id="csand-quiz-score" style="font-size:.7rem;color:rgba(255,255,255,.4);margin-left:8px"></span>
</div>
<div id="csand-quiz-question" style="display:none;margin-top:6px;padding:6px 10px;border-radius:8px;background:rgba(155,93,229,.10);border:1px solid rgba(155,93,229,.25);font-size:.72rem;color:#C9A0FF;line-height:1.3"></div>
<div id="csand-quiz-result" style="display:none;margin-top:4px;font-size:.72rem;font-weight:700"></div>
<button id="csand-quiz-next" style="display:none;margin-top:4px" class="proj-preset-chip" onclick="chemSandQuizNext()">Следующее задание</button>
</div>
<!-- Hint -->
<div class="tp-text" style="font-size:.65rem;opacity:.4;line-height:1.3">Клик на панели — добавить/убрать · Drag с полки в колбу · ПКМ — сбросить</div>
</div>
<div class="proj-canvas-outer">
<canvas id="chemsandbox-canvas" style="display:block;position:absolute;top:0;left:0;width:100%;height:100%;cursor:default"></canvas>
<!-- equation overlay: shown when reaction fires -->
<div id="chemsand-eq-overlay" class="chemsand-eq-overlay">
<div id="chemsand-eq-type" class="chemsand-eq-type"></div>
<div class="chemsand-eq-row chemsand-eq-row--mol">
<span class="chemsand-eq-label">Молекулярное</span>
<span id="chemsand-eq-mol" class="chemsand-eq-text chemsand-eq-text--mol"></span>
</div>
<div class="chemsand-eq-row chemsand-eq-row--full">
<span class="chemsand-eq-label">Полное ионное</span>
<span id="chemsand-eq-full" class="chemsand-eq-text chemsand-eq-text--full"></span>
</div>
<div class="chemsand-eq-row chemsand-eq-row--net">
<span class="chemsand-eq-label">Сокращённое ионное</span>
<span id="chemsand-eq-net" class="chemsand-eq-text chemsand-eq-text--net"></span>
</div>
</div>
</div>
</div>
<!-- Stats bar -->
<div class="proj-stats-bar" id="chemsand-stats-bar">
<div class="pstat"><div class="pstat-label">В зоне</div><div class="pstat-val" id="csbar-v1" style="color:var(--cyan)">0</div></div>
<div class="pstat"><div class="pstat-label">Тип</div><div class="pstat-val" id="csbar-v3" style="color:#7BF5A4"></div></div>
<div class="pstat"><div class="pstat-label">Уравнение</div><div class="pstat-val" id="csbar-v4" style="color:#EF476F"></div></div>
<div class="pstat"><div class="pstat-label">Сокр. ионное</div><div class="pstat-val" id="csbar-v6" style="color:#9BD4FF"></div></div>
<div class="pstat"><div class="pstat-label">Продукты</div><div class="pstat-val" id="csbar-v5" style="color:#4CC9F0"></div></div>
</div>
</div>
<!-- ── CELL DIVISION sim body ── -->
<div id="sim-celldivision" class="sim-proj-wrap" style="display:none">
<div class="sim-body-wrap">
<div class="proj-panel" style="width:200px;gap:0">
<div class="gp-section-title" style="margin-bottom:6px">Режим</div>
<div style="display:flex;gap:4px;margin-bottom:12px">
<button class="proj-preset-chip reac-mode-btn cd-mode-btn active" onclick="cdSetMode('mitosis',this)">Митоз</button>
<button class="proj-preset-chip reac-mode-btn cd-mode-btn" onclick="cdSetMode('meiosis',this)">Мейоз</button>
</div>
<div class="gp-section-title" style="margin-bottom:6px">Фазы</div>
<div id="cd-phase-dots" style="display:flex;flex-wrap:wrap;gap:4px;margin-bottom:12px"></div>
<div style="display:flex;gap:4px;margin-bottom:12px">
<button class="gp-btn" onclick="cdPrevPhase()" style="flex:1"><svg class="ic" viewBox="0 0 24 24"><polygon points="19 20 9 12 19 4 19 20"/></svg> Назад</button>
<button class="gp-btn" onclick="cdNextPhase()" style="flex:1">Далее <svg class="ic" viewBox="0 0 24 24"><polygon points="5 3 19 12 5 21 5 3"/></svg></button>
</div>
<button class="gp-btn" id="cd-auto-btn" onclick="cdAutoPlay(this)" style="width:100%;margin-bottom:10px"><svg class="ic" viewBox="0 0 24 24"><polygon points="5 3 19 12 5 21 5 3"/></svg> Авто</button>
<div class="pp-hint">Нажми фазу или используй кнопки для пошагового просмотра</div>
</div>
<div class="proj-canvas-outer">
<canvas id="celldiv-canvas" style="display:block;position:absolute;top:0;left:0;width:100%;height:100%"></canvas>
</div>
</div>
<div class="proj-stats-bar" id="cdbar">
<div class="pstat"><div class="pstat-label">Фаза</div><div class="pstat-val" id="cdbar-v1" style="color:#7BF5A4"></div></div>
<div class="pstat"><div class="pstat-label">Хромосомы</div><div class="pstat-val" id="cdbar-v2" style="color:var(--cyan)"></div></div>
<div class="pstat"><div class="pstat-label">ДНК</div><div class="pstat-val" id="cdbar-v3" style="color:#FFD166"></div></div>
<div class="pstat"><div class="pstat-label">Шаг</div><div class="pstat-val" id="cdbar-v4" style="color:#EF476F"></div></div>
<div class="pstat"><div class="pstat-label">Режим</div><div class="pstat-val" id="cdbar-v5" style="color:var(--violet)"></div></div>
</div>
</div>
<!-- ── PHOTOSYNTHESIS sim body ── -->
<div id="sim-photosynthesis" class="sim-proj-wrap" style="display:none">
<div class="sim-body-wrap">
<div class="proj-panel" style="width:200px;gap:0">
<div class="gp-section-title" style="margin-bottom:6px">Процесс</div>
<div style="display:flex;gap:4px;margin-bottom:12px">
<button class="proj-preset-chip reac-mode-btn ps-mode-btn active" onclick="psSetMode('photo',this)">Фотосинтез</button>
<button class="proj-preset-chip reac-mode-btn ps-mode-btn" onclick="psSetMode('resp',this)">Дыхание</button>
</div>
<div class="gp-section-title" style="margin-bottom:4px">Интенсивность света</div>
<div class="sl-row" style="margin-bottom:10px">
<input type="range" id="sl-ps-light" min="0" max="100" value="70" oninput="psLightChange()" style="flex:1">
<span class="sl-val" id="ps-light-val">70%</span>
</div>
<div class="gp-section-title" style="margin-bottom:4px">Концентрация CO₂</div>
<div class="sl-row" style="margin-bottom:10px">
<input type="range" id="sl-ps-co2" min="0" max="100" value="50" oninput="psCO2Change()" style="flex:1">
<span class="sl-val" id="ps-co2-val">50%</span>
</div>
<button class="gp-btn" onclick="psReset()" style="width:100%;margin-top:4px"><svg class="ic" viewBox="0 0 24 24"><polyline points="1 4 1 10 7 10"/><path d="M3.51 15a9 9 0 1 0 .49-4.12"/></svg> Сброс</button>
<div class="pp-hint" style="margin-top:10px">Меняй параметры и наблюдай за скоростью реакций</div>
</div>
<div class="proj-canvas-outer">
<canvas id="photosyn-canvas" style="display:block;position:absolute;top:0;left:0;width:100%;height:100%"></canvas>
</div>
</div>
<div class="proj-stats-bar" id="psbar">
<div class="pstat"><div class="pstat-label">АТФ/с</div><div class="pstat-val" id="psbar-v1" style="color:#FFD166">0</div></div>
<div class="pstat"><div class="pstat-label">O₂ выд.</div><div class="pstat-val" id="psbar-v2" style="color:#7BF5A4">0</div></div>
<div class="pstat"><div class="pstat-label">CO₂ усв.</div><div class="pstat-val" id="psbar-v3" style="color:var(--cyan)">0</div></div>
<div class="pstat"><div class="pstat-label">КПД</div><div class="pstat-val" id="psbar-v4" style="color:#EF476F"></div></div>
<div class="pstat"><div class="pstat-label">Режим</div><div class="pstat-val" id="psbar-v5" style="color:var(--violet)"></div></div>
</div>
</div>
<!-- ── ANGRY BIRDS sim body ── -->
<div id="sim-angrybirds" class="sim-proj-wrap" style="display:none">
<div class="sim-body-wrap">
<div class="proj-panel" style="width:200px;gap:0">
<div class="gp-section-title" style="margin-bottom:6px">Уровень</div>
<div style="display:flex;flex-wrap:wrap;gap:4px;margin-bottom:6px" id="ab-level-btns">
<button class="proj-preset-chip reac-mode-btn ab-lvl-btn active" onclick="abLevel(0,this)">1</button>
<button class="proj-preset-chip reac-mode-btn ab-lvl-btn" onclick="abLevel(1,this)">2</button>
<button class="proj-preset-chip reac-mode-btn ab-lvl-btn" onclick="abLevel(2,this)">3</button>
<button class="proj-preset-chip reac-mode-btn ab-lvl-btn" onclick="abLevel(3,this)">4</button>
<button class="proj-preset-chip reac-mode-btn ab-lvl-btn" onclick="abLevel(4,this)">5</button>
<button class="proj-preset-chip reac-mode-btn ab-lvl-btn" onclick="abLevel(5,this)">6</button>
</div>
<button onclick="angryBirdsRestart()" style="width:100%;padding:6px 10px;border-radius:8px;border:1.5px solid rgba(255,255,255,.15);background:rgba(255,255,255,.06);color:#e0e0e0;font-size:.76rem;font-weight:700;cursor:pointer;margin-bottom:12px" title="Начать уровень заново"><svg class="ic" viewBox="0 0 24 24"><polyline points="1 4 1 10 7 10"/><path d="M3.51 15a9 9 0 1 0 .49-4.12"/></svg> Сначала</button>
<div class="gp-section-title" style="margin-bottom:6px">Планеты</div>
<div style="display:flex;flex-direction:column;gap:5px;margin-bottom:14px">
<div style="display:flex;justify-content:space-between;align-items:center;padding:4px 8px;border-radius:7px;background:rgba(255,255,255,.06)">
<span style="font-size:.75rem;color:#e0e0e0"><svg class="ic" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg> Земля</span><span style="font-size:.72rem;color:var(--cyan);font-weight:700">9.81 м/с²</span>
</div>
<div style="display:flex;justify-content:space-between;align-items:center;padding:4px 8px;border-radius:7px;background:rgba(255,255,255,.06)">
<span style="font-size:.75rem;color:#e0e0e0"><svg class="ic" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10" fill="currentColor" stroke="none"/></svg> Луна</span><span style="font-size:.72rem;color:var(--cyan);font-weight:700">1.62 м/с²</span>
</div>
<div style="display:flex;justify-content:space-between;align-items:center;padding:4px 8px;border-radius:7px;background:rgba(255,255,255,.06)">
<span style="font-size:.75rem;color:#e0e0e0"><svg class="ic" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10" fill="currentColor" stroke="none"/></svg> Марс</span><span style="font-size:.72rem;color:var(--cyan);font-weight:700">3.71 м/с²</span>
</div>
<div style="display:flex;justify-content:space-between;align-items:center;padding:4px 8px;border-radius:7px;background:rgba(255,255,255,.06)">
<span style="font-size:.75rem;color:#e0e0e0"><svg class="ic" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10" fill="currentColor" stroke="none"/></svg> Юпитер</span><span style="font-size:.72rem;color:var(--cyan);font-weight:700">24.8 м/с²</span>
</div>
</div>
<div class="gp-section-title" style="margin-bottom:6px">Птицы</div>
<div style="display:flex;flex-direction:column;gap:5px;margin-bottom:14px">
<div style="display:flex;align-items:center;gap:8px;padding:4px 8px;border-radius:7px;background:rgba(255,255,255,.06)">
<span style="width:14px;height:14px;border-radius:50%;background:#e63946;flex-shrink:0;display:inline-block"></span>
<span style="font-size:.73rem;color:#e0e0e0">Красная — обычная</span>
</div>
<div style="display:flex;align-items:center;gap:8px;padding:4px 8px;border-radius:7px;background:rgba(255,255,255,.06)">
<span style="width:14px;height:14px;border-radius:50%;background:#888;flex-shrink:0;display:inline-block"></span>
<span style="font-size:.73rem;color:#e0e0e0">Тяжёлая — высокий урон</span>
</div>
<div style="display:flex;align-items:center;gap:8px;padding:4px 8px;border-radius:7px;background:rgba(255,255,255,.06)">
<span style="width:14px;height:14px;border-radius:50%;background:#ffd166;flex-shrink:0;display:inline-block"></span>
<span style="font-size:.73rem;color:#e0e0e0">Жёлтая — быстрая</span>
</div>
</div>
<div class="pp-hint">Тяни птицу мышью · отпусти — выстрел</div>
</div>
<div class="proj-canvas-outer">
<canvas id="angrybirds-canvas" style="display:block;position:absolute;top:0;left:0;width:100%;height:100%;cursor:crosshair"></canvas>
</div>
</div>
<div class="proj-stats-bar" id="abbar">
<div class="pstat"><div class="pstat-label">Уровень</div><div class="pstat-val" id="abbar-v1" style="color:var(--cyan)">1</div></div>
<div class="pstat"><div class="pstat-label">Птиц</div><div class="pstat-val" id="abbar-v2" style="color:#ffd166">3</div></div>
<div class="pstat"><div class="pstat-label">Свиней</div><div class="pstat-val" id="abbar-v3" style="color:#7bf5a4">1</div></div>
<div class="pstat"><div class="pstat-label">Очки</div><div class="pstat-val" id="abbar-v4" style="color:#ef476f">0</div></div>
<div class="pstat"><div class="pstat-label">Планета</div><div class="pstat-val" id="abbar-v5" style="color:var(--violet)">Земля <svg class="ic" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg></div></div>
</div>
</div>
<!-- ── QUADRATIC sim body ── -->
<div id="sim-quadratic" class="sim-proj-wrap" style="display:none">
<div class="sim-body-wrap">
<div class="proj-panel" style="width:220px;gap:0">
<div class="gp-section-title" style="margin-bottom:8px">Коэффициенты</div>
<div class="proj-slider-row" style="margin-bottom:10px">
<label style="font-size:.78rem;color:#ccc;width:60px">a = <span id="quad-a-val" style="color:var(--violet);font-weight:700">1</span></label>
<input type="range" id="sl-quad-a" min="-5" max="5" step="0.1" value="1" oninput="quadParam('a',this.value)" style="flex:1">
</div>
<div class="proj-slider-row" style="margin-bottom:10px">
<label style="font-size:.78rem;color:#ccc;width:60px">b = <span id="quad-b-val" style="color:var(--cyan);font-weight:700">0</span></label>
<input type="range" id="sl-quad-b" min="-10" max="10" step="0.1" value="0" oninput="quadParam('b',this.value)" style="flex:1">
</div>
<div class="proj-slider-row" style="margin-bottom:10px">
<label style="font-size:.78rem;color:#ccc;width:60px">c = <span id="quad-c-val" style="color:var(--pink);font-weight:700">-1</span></label>
<input type="range" id="sl-quad-c" min="-10" max="10" step="0.1" value="-1" oninput="quadParam('c',this.value)" style="flex:1">
</div>
<div style="margin-top:8px"></div>
<div class="gp-section-title" style="margin-bottom:6px">Примеры</div>
<div style="display:flex;flex-wrap:wrap;gap:4px;margin-bottom:10px">
<button class="preset-btn" onclick="quadPreset(1,0,-4)">x²−4</button>
<button class="preset-btn" onclick="quadPreset(1,-2,1)">(x1)²</button>
<button class="preset-btn" onclick="quadPreset(1,0,1)">x²+1</button>
<button class="preset-btn" onclick="quadPreset(-1,0,4)">x²+4</button>
<button class="preset-btn" onclick="quadPreset(2,-3,-2)">2x²−3x2</button>
<button class="preset-btn" onclick="quadPreset(0.5,1,-3)">½x²+x3</button>
</div>
<div class="pp-hint">Скролл — зум · Тащи — панорама</div>
</div>
<div class="proj-canvas-outer">
<canvas id="quadratic-canvas"></canvas>
</div>
</div>
<div class="proj-stats-bar" id="quadbar">
<div class="pstat"><div class="pstat-label">Дискриминант</div><div class="pstat-val" id="qbar-v1" style="color:#FFD166"></div></div>
<div class="pstat"><div class="pstat-label">Корни</div><div class="pstat-val" id="qbar-v2" style="color:#EF476F"></div></div>
<div class="pstat"><div class="pstat-label">Вершина</div><div class="pstat-val" id="qbar-v3" style="color:var(--cyan)"></div></div>
<div class="pstat"><div class="pstat-label">Уравнение</div><div class="pstat-val" id="qbar-v4" style="color:var(--violet)"></div></div>
</div>
</div>
<!-- ── NORMAL DISTRIBUTION sim body ── -->
<div id="sim-normaldist" class="sim-proj-wrap" style="display:none">
<div class="sim-body-wrap">
<div class="proj-panel" style="width:220px;gap:0">
<div class="gp-section-title" style="margin-bottom:8px">Параметры</div>
<div class="proj-slider-row" style="margin-bottom:10px">
<label style="font-size:.78rem;color:#ccc;width:60px">μ = <span id="nd-mu-val" style="color:var(--cyan);font-weight:700">0</span></label>
<input type="range" id="sl-nd-mu" min="-5" max="5" step="0.1" value="0" oninput="ndParam('mu',this.value)" style="flex:1">
</div>
<div class="proj-slider-row" style="margin-bottom:10px">
<label style="font-size:.78rem;color:#ccc;width:60px">σ = <span id="nd-sigma-val" style="color:var(--violet);font-weight:700">1</span></label>
<input type="range" id="sl-nd-sigma" min="0.2" max="4" step="0.1" value="1" oninput="ndParam('sigma',this.value)" style="flex:1">
</div>
<div style="margin-top:8px"></div>
<div class="gp-section-title" style="margin-bottom:6px">Закрасить область</div>
<div style="display:flex;flex-wrap:wrap;gap:4px;margin-bottom:10px">
<button class="preset-btn nd-shade-btn active" onclick="ndShade('1s',this)">μ ± 1σ</button>
<button class="preset-btn nd-shade-btn" onclick="ndShade('2s',this)">μ ± 2σ</button>
<button class="preset-btn nd-shade-btn" onclick="ndShade('3s',this)">μ ± 3σ</button>
<button class="preset-btn nd-shade-btn" onclick="ndShade('none',this)">Нет</button>
</div>
<div style="margin-top:8px"></div>
<div class="gp-section-title" style="margin-bottom:6px">Пресеты</div>
<div style="display:flex;flex-wrap:wrap;gap:4px;margin-bottom:10px">
<button class="preset-btn" onclick="ndPreset(0,1)">Стандартное</button>
<button class="preset-btn" onclick="ndPreset(0,0.5)">Узкое σ=0.5</button>
<button class="preset-btn" onclick="ndPreset(0,2)">Широкое σ=2</button>
<button class="preset-btn" onclick="ndPreset(3,1)">Сдвиг μ=3</button>
</div>
<div class="pp-hint">Наведи курсор — Z-score и плотность</div>
</div>
<div class="proj-canvas-outer">
<canvas id="normaldist-canvas"></canvas>
</div>
</div>
<div class="proj-stats-bar" id="ndbar">
<div class="pstat"><div class="pstat-label">μ</div><div class="pstat-val" id="ndbar-v1" style="color:var(--cyan)">0</div></div>
<div class="pstat"><div class="pstat-label">σ</div><div class="pstat-val" id="ndbar-v2" style="color:var(--violet)">1</div></div>
<div class="pstat"><div class="pstat-label">Пик f(μ)</div><div class="pstat-val" id="ndbar-v3" style="color:#FFD166"></div></div>
<div class="pstat"><div class="pstat-label">Область</div><div class="pstat-val" id="ndbar-v4" style="color:#7BF5A4"></div></div>
</div>
</div>
<!-- ── GRAPH TRANSFORM sim body ── -->
<div id="sim-graphtransform" class="sim-proj-wrap" style="display:none">
<div class="sim-body-wrap">
<div class="proj-panel" style="width:230px;gap:0">
<div class="gp-section-title" style="margin-bottom:6px">Базовая функция f(x)</div>
<div style="display:flex;flex-wrap:wrap;gap:4px;margin-bottom:12px">
<button class="preset-btn gt-base-btn active" onclick="gtBase('sin',this)">sin x</button>
<button class="preset-btn gt-base-btn" onclick="gtBase('cos',this)">cos x</button>
<button class="preset-btn gt-base-btn" onclick="gtBase('x^2',this)"></button>
<button class="preset-btn gt-base-btn" onclick="gtBase('x^3',this)"></button>
<button class="preset-btn gt-base-btn" onclick="gtBase('sqrt',this)">√x</button>
<button class="preset-btn gt-base-btn" onclick="gtBase('|x|',this)">|x|</button>
<button class="preset-btn gt-base-btn" onclick="gtBase('1/x',this)">1/x</button>
</div>
<div class="gp-section-title" style="margin-bottom:6px">y = a · f(k·x + b) + c</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:55px">a = <span id="gt-a-val" style="color:var(--violet);font-weight:700">1</span></label>
<input type="range" id="sl-gt-a" min="-3" max="3" step="0.1" value="1" oninput="gtParam('a',this.value)" style="flex:1">
</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:55px">k = <span id="gt-k-val" style="color:var(--cyan);font-weight:700">1</span></label>
<input type="range" id="sl-gt-k" min="-3" max="3" step="0.1" value="1" oninput="gtParam('k',this.value)" style="flex:1">
</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:55px">b = <span id="gt-b-val" style="color:#FFD166;font-weight:700">0</span></label>
<input type="range" id="sl-gt-b" min="-5" max="5" step="0.1" value="0" oninput="gtParam('b',this.value)" style="flex:1">
</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:55px">c = <span id="gt-c-val" style="color:#EF476F;font-weight:700">0</span></label>
<input type="range" id="sl-gt-c" min="-5" max="5" step="0.1" value="0" oninput="gtParam('c',this.value)" style="flex:1">
</div>
<div style="margin-top:8px"></div>
<div class="gp-section-title" style="margin-bottom:6px">Эффекты</div>
<div style="display:flex;flex-wrap:wrap;gap:4px;margin-bottom:8px">
<button class="preset-btn" onclick="gtEffect(2,1,0,0)">Растяжение <svg class="ic" viewBox="0 0 24 24"><line x1="12" y1="21" x2="12" y2="3"/><polyline points="7 8 12 3 17 8"/><polyline points="17 16 12 21 7 16"/></svg></button>
<button class="preset-btn" onclick="gtEffect(1,2,0,0)">Сжатие <svg class="ic" viewBox="0 0 24 24"><line x1="3" y1="12" x2="21" y2="12"/><polyline points="8 17 3 12 8 7"/><polyline points="16 7 21 12 16 17"/></svg></button>
<button class="preset-btn" onclick="gtEffect(-1,1,0,0)">Отражение <svg class="ic" viewBox="0 0 24 24"><line x1="12" y1="21" x2="12" y2="3"/><polyline points="7 8 12 3 17 8"/><polyline points="17 16 12 21 7 16"/></svg></button>
<button class="preset-btn" onclick="gtEffect(1,-1,0,0)">Отражение <svg class="ic" viewBox="0 0 24 24"><line x1="3" y1="12" x2="21" y2="12"/><polyline points="8 17 3 12 8 7"/><polyline points="16 7 21 12 16 17"/></svg></button>
<button class="preset-btn" onclick="gtEffect(1,1,2,0)">Сдвиг <svg class="ic" viewBox="0 0 24 24"><line x1="19" y1="12" x2="5" y2="12"/><polyline points="12 19 5 12 12 5"/></svg></button>
<button class="preset-btn" onclick="gtEffect(1,1,0,3)">Сдвиг <svg class="ic" viewBox="0 0 24 24"><line x1="12" y1="19" x2="12" y2="5"/><polyline points="5 12 12 5 19 12"/></svg></button>
</div>
<button class="preset-btn" onclick="gtEffect(1,1,0,0)" style="width:100%;margin-top:4px">Сброс</button>
<div class="pp-hint">Скролл — зум · Тащи — панорама</div>
</div>
<div class="proj-canvas-outer">
<canvas id="graphtransform-canvas"></canvas>
</div>
</div>
<div class="proj-stats-bar" id="gtbar">
<div class="pstat"><div class="pstat-label">f(x)</div><div class="pstat-val" id="gtbar-v1" style="color:var(--cyan)">sin(x)</div></div>
<div class="pstat"><div class="pstat-label">a</div><div class="pstat-val" id="gtbar-v2" style="color:var(--violet)">1</div></div>
<div class="pstat"><div class="pstat-label">k</div><div class="pstat-val" id="gtbar-v3" style="color:var(--cyan)">1</div></div>
<div class="pstat"><div class="pstat-label">b</div><div class="pstat-val" id="gtbar-v4" style="color:#FFD166">0</div></div>
<div class="pstat"><div class="pstat-label">c</div><div class="pstat-val" id="gtbar-v5" style="color:#EF476F">0</div></div>
</div>
</div>
<!-- ── PENDULUM sim body ── -->
<div id="sim-pendulum" class="sim-proj-wrap" style="display:none">
<!-- mode bar -->
<div style="display:flex;gap:4px;padding:6px 12px;background:rgba(22,22,38,0.8);flex-wrap:wrap;border-bottom:1px solid rgba(255,255,255,0.07)">
<button class="pend-mode-btn active" data-mode="math" onclick="pendSetMode('math')" style="font-size:.72rem;padding:3px 10px;border-radius:14px;border:1px solid rgba(255,255,255,0.15);background:rgba(155,93,229,0.2);color:#ccc;cursor:pointer">&#1052;&#1072;&#1090;&#1077;&#1084;&#1072;&#1090;.</button>
<button class="pend-mode-btn" data-mode="double" onclick="pendSetMode('double')" style="font-size:.72rem;padding:3px 10px;border-radius:14px;border:1px solid rgba(255,255,255,0.15);background:rgba(22,22,38,0.6);color:#ccc;cursor:pointer">&#1044;&#1074;&#1086;&#1081;&#1085;&#1086;&#1081;</button>
<button class="pend-mode-btn" data-mode="coupled" onclick="pendSetMode('coupled')" style="font-size:.72rem;padding:3px 10px;border-radius:14px;border:1px solid rgba(255,255,255,0.15);background:rgba(22,22,38,0.6);color:#ccc;cursor:pointer">&#1057;&#1074;&#1103;&#1079;&#1072;&#1085;&#1085;&#1099;&#1077;</button>
<button class="pend-mode-btn" data-mode="spring" onclick="pendSetMode('spring')" style="font-size:.72rem;padding:3px 10px;border-radius:14px;border:1px solid rgba(255,255,255,0.15);background:rgba(22,22,38,0.6);color:#ccc;cursor:pointer">&#1055;&#1088;&#1091;&#1078;&#1080;&#1085;&#1085;&#1099;&#1081;</button>
<button class="pend-mode-btn" data-mode="physical" onclick="pendSetMode('physical')" style="font-size:.72rem;padding:3px 10px;border-radius:14px;border:1px solid rgba(255,255,255,0.15);background:rgba(22,22,38,0.6);color:#ccc;cursor:pointer">&#1060;&#1080;&#1079;&#1080;&#1095;.</button>
<button class="pend-mode-btn" data-mode="foucault" onclick="pendSetMode('foucault')" style="font-size:.72rem;padding:3px 10px;border-radius:14px;border:1px solid rgba(255,255,255,0.15);background:rgba(22,22,38,0.6);color:#ccc;cursor:pointer">&#1060;&#1091;&#1082;&#1086;</button>
<button class="pend-mode-btn" data-mode="resonance" onclick="pendSetMode('resonance')" style="font-size:.72rem;padding:3px 10px;border-radius:14px;border:1px solid rgba(255,255,255,0.15);background:rgba(22,22,38,0.6);color:#ccc;cursor:pointer">&#1056;&#1077;&#1079;&#1086;&#1085;&#1072;&#1085;&#1089;</button>
<button id="btn-pend-phase" onclick="pendTogglePhase()" style="font-size:.72rem;padding:3px 10px;border-radius:14px;border:1px solid rgba(255,255,255,0.15);background:rgba(22,22,38,0.6);color:#ccc;cursor:pointer;margin-left:auto">&#1060;&#1072;&#1079;. &#1087;&#1086;&#1088;&#1090;&#1088;&#1077;&#1090;</button>
<button id="btn-pend-graphs" onclick="pendToggleGraphs()" style="font-size:.72rem;padding:3px 10px;border-radius:14px;border:1px solid rgba(6,214,224,0.3);background:rgba(6,214,224,0.08);color:#06D6E0;cursor:pointer">&#1043;&#1088;&#1072;&#1092;&#1080;&#1082;&#1080;</button>
</div>
<div class="sim-body-wrap">
<div class="proj-panel" style="width:230px;gap:0;overflow-y:auto;max-height:100%">
<!-- MATH params -->
<div class="pend-params" data-mode="math">
<div class="gp-section-title" style="margin-bottom:8px">&#1052;&#1072;&#1090;&#1077;&#1084;&#1072;&#1090;&#1080;&#1095;. &#1084;&#1072;&#1103;&#1090;&#1085;&#1080;&#1082;</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:55px">&#952; = <span id="pend-theta-val" style="color:var(--violet);font-weight:700">45</span>&#176;</label>
<input type="range" id="sl-pend-theta" min="5" max="170" step="1" value="45" oninput="pendParam('theta',this.value)" style="flex:1">
</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:55px">L = <span id="pend-L-val" style="color:var(--cyan);font-weight:700">200</span></label>
<input type="range" id="sl-pend-L" min="60" max="300" step="5" value="200" oninput="pendParam('L',this.value)" style="flex:1">
</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:55px">g = <span id="pend-g-val" style="color:#FFD166;font-weight:700">9.81</span></label>
<input type="range" id="sl-pend-g" min="1" max="25" step="0.1" value="9.81" oninput="pendParam('g',this.value)" style="flex:1">
</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:70px">&#1047;&#1072;&#1090;&#1091;&#1093;. <span id="pend-damp-val" style="color:#EF476F;font-weight:700">0</span></label>
<input type="range" id="sl-pend-damp" min="0" max="2" step="0.05" value="0" oninput="pendParam('damping',this.value)" style="flex:1">
</div>
<div class="gp-section-title" style="margin-bottom:6px;margin-top:8px">&#1055;&#1088;&#1077;&#1089;&#1077;&#1090;&#1099;</div>
<div style="display:flex;flex-wrap:wrap;gap:4px;margin-bottom:8px">
<button class="preset-btn" onclick="pendPreset(45,200,9.81,0)">&#1047;&#1077;&#1084;&#1083;&#1103;</button>
<button class="preset-btn" onclick="pendPreset(45,200,1.62,0)">&#1051;&#1091;&#1085;&#1072;</button>
<button class="preset-btn" onclick="pendPreset(170,200,9.81,0)">&#1041;&#1086;&#1083;&#1100;&#1096;&#1086;&#1081; &#952;</button>
<button class="preset-btn" onclick="pendPreset(45,200,9.81,0.5)">&#1047;&#1072;&#1090;&#1091;&#1093;&#1072;&#1085;&#1080;&#1077;</button>
</div>
<div class="pp-hint">&#1058;&#1072;&#1097;&#1080; &#1075;&#1088;&#1091;&#1079;&#1080;&#1082; &#1084;&#1099;&#1096;&#1100;&#1102; &#1076;&#1083;&#1103; &#1091;&#1089;&#1090;&#1072;&#1085;&#1086;&#1074;&#1082;&#1080; &#1091;&#1075;&#1083;&#1072;</div>
</div>
<!-- DOUBLE params -->
<div class="pend-params" data-mode="double" style="display:none">
<div class="gp-section-title" style="margin-bottom:8px">&#1044;&#1074;&#1086;&#1081;&#1085;&#1086;&#1081; &#1084;&#1072;&#1103;&#1090;&#1085;&#1080;&#1082;</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:65px">L1 = <span id="pend-d-L1-val" style="color:var(--cyan);font-weight:700">130</span></label>
<input type="range" min="50" max="200" step="5" value="130" oninput="pendDoubleParam('L1',this.value)" style="flex:1">
</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:65px">L2 = <span id="pend-d-L2-val" style="color:var(--cyan);font-weight:700">100</span></label>
<input type="range" min="50" max="200" step="5" value="100" oninput="pendDoubleParam('L2',this.value)" style="flex:1">
</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:65px">m1 = <span id="pend-d-m1-val" style="color:#FFD166;font-weight:700">1.5</span></label>
<input type="range" min="0.5" max="4" step="0.1" value="1.5" oninput="pendDoubleParam('m1',this.value)" style="flex:1">
</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:65px">m2 = <span id="pend-d-m2-val" style="color:#FFD166;font-weight:700">1.0</span></label>
<input type="range" min="0.5" max="4" step="0.1" value="1.0" oninput="pendDoubleParam('m2',this.value)" style="flex:1">
</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:65px">&#952;1 = <span id="pend-d-th1-val" style="color:var(--violet);font-weight:700">108</span>&#176;</label>
<input type="range" min="10" max="170" step="1" value="108" oninput="pendDoubleParam('th1',this.value)" style="flex:1">
</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:65px">&#952;2 = <span id="pend-d-th2-val" style="color:var(--violet);font-weight:700">72</span>&#176;</label>
<input type="range" min="10" max="170" step="1" value="72" oninput="pendDoubleParam('th2',this.value)" style="flex:1">
</div>
<button id="btn-pend-ghost" onclick="pendToggleGhost()" style="width:100%;margin-top:6px;font-size:.75rem;padding:5px;border-radius:8px;border:1px solid rgba(239,71,111,0.4);background:rgba(239,71,111,0.1);color:#EF476F;cursor:pointer">&#1057;&#1088;&#1072;&#1074;&#1085;&#1080;&#1090;&#1100; &#1090;&#1088;&#1072;&#1077;&#1082;&#1090;&#1086;&#1088;&#1080;&#1080; (&#1093;&#1072;&#1086;&#1089;)</button>
<div class="pp-hint" style="margin-top:6px">&#1063;&#1091;&#1074;&#1089;&#1090;&#1074;&#1080;&#1090;&#1077;&#1083;&#1100;&#1085;&#1086;&#1089;&#1090;&#1100; &#1082; &#1085;&#1072;&#1095;. &#1091;&#1089;&#1083;&#1086;&#1074;&#1080;&#1103;&#1084; (+0.001 &#1088;&#1072;&#1076;)</div>
</div>
<!-- COUPLED params -->
<div class="pend-params" data-mode="coupled" style="display:none">
<div class="gp-section-title" style="margin-bottom:8px">&#1057;&#1074;&#1103;&#1079;&#1072;&#1085;&#1085;&#1099;&#1077; &#1084;&#1072;&#1103;&#1090;&#1085;&#1080;&#1082;&#1080;</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:65px">L = <span id="pend-cp-L-val" style="color:var(--cyan);font-weight:700">160</span></label>
<input type="range" min="80" max="260" step="5" value="160" oninput="pendCoupledParam('L',this.value)" style="flex:1">
</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:65px">k = <span id="pend-cp-k-val" style="color:#FFD166;font-weight:700">0.30</span></label>
<input type="range" min="0.01" max="2" step="0.01" value="0.3" oninput="pendCoupledParam('k',this.value)" style="flex:1">
</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:65px">&#952;1 = <span id="pend-cp-th1-val" style="color:var(--violet);font-weight:700">36</span>&#176;</label>
<input type="range" min="5" max="90" step="1" value="36" oninput="pendCoupledParam('th1',this.value)" style="flex:1">
</div>
<div class="pp-hint">&#952;2=0: &#1101;&#1085;&#1077;&#1088;&#1075;&#1080;&#1103; &#1087;&#1077;&#1088;&#1077;&#1082;&#1072;&#1095;&#1080;&#1074;&#1072;&#1077;&#1090;&#1089;&#1103; &#1086;&#1090; &#1084;&#1072;&#1103;&#1090;&#1085;&#1080;&#1082;&#1072; 1 &#1082; &#1084;&#1072;&#1103;&#1090;&#1085;&#1080;&#1082;&#1091; 2 &#1080; &#1086;&#1073;&#1088;&#1072;&#1090;&#1085;&#1086;</div>
</div>
<!-- SPRING params -->
<div class="pend-params" data-mode="spring" style="display:none">
<div class="gp-section-title" style="margin-bottom:8px">&#1055;&#1088;&#1091;&#1078;&#1080;&#1085;&#1085;&#1099;&#1081; &#1084;&#1072;&#1103;&#1090;&#1085;&#1080;&#1082;</div>
<div style="display:flex;gap:4px;margin-bottom:10px">
<button class="sp-mode-btn active" data-m="vert" onclick="pendSpringMode('vert')" style="flex:1;font-size:.72rem;padding:4px;border-radius:8px;border:1px solid rgba(255,255,255,0.15);background:rgba(6,214,224,0.15);color:#06D6E0;cursor:pointer">&#1042;&#1077;&#1088;&#1090;&#1080;&#1082;.</button>
<button class="sp-mode-btn" data-m="horiz" onclick="pendSpringMode('horiz')" style="flex:1;font-size:.72rem;padding:4px;border-radius:8px;border:1px solid rgba(255,255,255,0.15);background:rgba(22,22,38,0.6);color:#ccc;cursor:pointer">&#1043;&#1086;&#1088;&#1080;&#1079;&#1086;&#1085;&#1090;.</button>
</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:65px">k = <span id="pend-sp-k-val" style="color:#FFD166;font-weight:700">20</span></label>
<input type="range" min="1" max="100" step="1" value="20" oninput="pendSpringParam('k',this.value)" style="flex:1">
</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:65px">m = <span id="pend-sp-m-val" style="color:var(--violet);font-weight:700">1</span> &#1082;&#1075;</label>
<input type="range" min="0.1" max="5" step="0.1" value="1" oninput="pendSpringParam('m',this.value)" style="flex:1">
</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:65px">x0 = <span id="pend-sp-x0-val" style="color:#EF476F;font-weight:700">8</span> &#1089;&#1084;</label>
<input type="range" min="1" max="20" step="0.5" value="8" oninput="pendSpringParam('x0',this.value)" style="flex:1">
</div>
<div class="pp-hint">T = 2&#960;&#8730;(m/k) &#1085;&#1077; &#1079;&#1072;&#1074;&#1080;&#1089;&#1080;&#1090; &#1086;&#1090; g (&#1075;&#1086;&#1088;&#1080;&#1079;&#1086;&#1085;&#1090;.)</div>
</div>
<!-- PHYSICAL params -->
<div class="pend-params" data-mode="physical" style="display:none">
<div class="gp-section-title" style="margin-bottom:8px">&#1060;&#1080;&#1079;&#1080;&#1095;&#1077;&#1089;&#1082;&#1080;&#1081; &#1084;&#1072;&#1103;&#1090;&#1085;&#1080;&#1082;</div>
<div style="display:flex;flex-wrap:wrap;gap:3px;margin-bottom:10px">
<button class="ph-shape-btn active" data-s="rod" onclick="pendPhysShape('rod')" style="font-size:.72rem;padding:3px 8px;border-radius:8px;border:1px solid rgba(155,93,229,0.4);background:rgba(155,93,229,0.15);color:#9B5DE5;cursor:pointer">&#1057;&#1090;&#1077;&#1088;&#1078;&#1077;&#1085;&#1100;</button>
<button class="ph-shape-btn" data-s="hoop" onclick="pendPhysShape('hoop')" style="font-size:.72rem;padding:3px 8px;border-radius:8px;border:1px solid rgba(255,255,255,0.15);background:rgba(22,22,38,0.6);color:#ccc;cursor:pointer">&#1054;&#1073;&#1088;&#1091;&#1095;</button>
<button class="ph-shape-btn" data-s="disk" onclick="pendPhysShape('disk')" style="font-size:.72rem;padding:3px 8px;border-radius:8px;border:1px solid rgba(255,255,255,0.15);background:rgba(22,22,38,0.6);color:#ccc;cursor:pointer">&#1044;&#1080;&#1089;&#1082;</button>
<button class="ph-shape-btn" data-s="rect" onclick="pendPhysShape('rect')" style="font-size:.72rem;padding:3px 8px;border-radius:8px;border:1px solid rgba(255,255,255,0.15);background:rgba(22,22,38,0.6);color:#ccc;cursor:pointer">&#1055;&#1088;&#1103;&#1084;&#1086;&#1091;&#1075;.</button>
</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:65px">L = <span id="pend-ph-L-val" style="color:var(--cyan);font-weight:700">200</span></label>
<input type="range" min="60" max="260" step="5" value="200" oninput="pendPhysParam('L',this.value)" style="flex:1">
</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:65px">&#952; = <span id="pend-ph-theta-val" style="color:var(--violet);font-weight:700">36</span>&#176;</label>
<input type="range" min="5" max="120" step="1" value="36" oninput="pendPhysParam('theta',this.value)" style="flex:1">
</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:65px">&#1047;&#1072;&#1090;&#1091;&#1093;. <span id="pend-ph-damping-val" style="color:#EF476F;font-weight:700">0</span></label>
<input type="range" min="0" max="1" step="0.02" value="0" oninput="pendPhysParam('damping',this.value)" style="flex:1">
</div>
<div class="pp-hint">T &#1079;&#1072;&#1074;&#1080;&#1089;&#1080;&#1090; &#1086;&#1090; &#1084;&#1086;&#1084;&#1077;&#1085;&#1090;&#1072; &#1080;&#1085;&#1077;&#1088;&#1094;&#1080;&#1080; I &#1080; &#1088;&#1072;&#1089;&#1089;&#1090;. &#1076;&#1086; &#1094;.&#1090;. d</div>
</div>
<!-- FOUCAULT params -->
<div class="pend-params" data-mode="foucault" style="display:none">
<div class="gp-section-title" style="margin-bottom:8px">&#1052;&#1072;&#1103;&#1090;&#1085;&#1080;&#1082; &#1060;&#1091;&#1082;&#1086;</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:65px">&#966; = <span id="pend-fc-phi-val" style="color:#FFD166;font-weight:700">45</span>&#176;</label>
<input type="range" min="1" max="90" step="1" value="45" oninput="pendFoucaultParam('phi',this.value)" style="flex:1">
</div>
<div class="pp-hint">&#1042;&#1080;&#1076; &#1089;&#1074;&#1077;&#1088;&#1093;&#1091;. &#1055;&#1083;&#1086;&#1089;&#1082;&#1086;&#1089;&#1090;&#1100; &#1082;&#1072;&#1095;&#1072;&#1085;&#1080;&#1081; &#1074;&#1088;&#1072;&#1097;&#1072;&#1077;&#1090;&#1089;&#1; &#1080;&#1079;-&#1079;&#1072; &#1074;&#1088;&#1072;&#1097;&#1077;&#1085;&#1080;&#1103; &#1047;&#1077;&#1084;&#1083;&#1080;. T = 24 &#1095; / sin(&#966;)</div>
<div class="pp-hint" style="color:#FFD166;margin-top:4px">&#1055;&#1086;&#1083;&#1102;&#1089; (90&#176;): &#1086;&#1073;&#1086;&#1088;&#1086;&#1090; &#1079;&#1072; 24 &#1095;. &#1069;&#1082;&#1074;&#1072;&#1090;&#1086;&#1088;: &#1087;&#1086;&#1095;&#1090;&#1080; &#1085;&#1077; &#1074;&#1088;&#1072;&#1097;&#1072;&#1077;&#1090;&#1089;&#1103;.</div>
</div>
<!-- RESONANCE params -->
<div class="pend-params" data-mode="resonance" style="display:none">
<div class="gp-section-title" style="margin-bottom:8px">&#1056;&#1077;&#1079;&#1086;&#1085;&#1072;&#1085;&#1089;</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:70px">&#969; = <span id="pend-rs-dOmega-val" style="color:#EF476F;font-weight:700">1.50</span></label>
<input type="range" min="0.1" max="6" step="0.05" value="1.5" oninput="pendResonanceParam('dOmega',this.value)" style="flex:1">
</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:70px">F0 = <span id="pend-rs-F0-val" style="color:#FFD166;font-weight:700">0.80</span></label>
<input type="range" min="0.1" max="3" step="0.05" value="0.8" oninput="pendResonanceParam('F0',this.value)" style="flex:1">
</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:70px">&#947; = <span id="pend-rs-gamma-val" style="color:var(--cyan);font-weight:700">0.30</span></label>
<input type="range" min="0.01" max="2" step="0.01" value="0.3" oninput="pendResonanceParam('gamma',this.value)" style="flex:1">
</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:70px">L = <span id="pend-rs-L-val" style="color:var(--violet);font-weight:700">180</span></label>
<input type="range" min="60" max="300" step="5" value="180" oninput="pendResonanceParam('L',this.value)" style="flex:1">
</div>
<div class="pp-hint">&#1050;&#1088;&#1072;&#1089;&#1085;&#1072;&#1103; &#1089;&#1090;&#1088;&#1077;&#1083;&#1082;&#1072;&#1074;&#1099;&#1085;&#1091;&#1078;&#1076;&#1072;&#1102;&#1097;&#1072;&#1103; &#1089;&#1080;&#1083;&#1072;. &#1055;&#1080;&#1082; &#1087;&#1088;&#1080; &#969; &#8776; &#969;&#8320;.</div>
</div>
<!-- Energy bars toggle (shared across all pendulum modes) -->
<div class="gp-section-title" style="margin-top:10px">&#1047;&#1072;&#1082;&#1086;&#1085; &#1089;&#1086;&#1093;&#1088;&#1072;&#1085;&#1077;&#1085;&#1080;&#1103; &#1101;&#1085;&#1077;&#1088;&#1075;&#1080;&#1080;</div>
<button id="pend-energy-btn" class="proj-preset-chip" onclick="pendToggleEnergy()" style="width:100%;text-align:left;display:flex;align-items:center;gap:6px">
<svg class="ic" viewBox="0 0 24 24"><path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z"/></svg>
<span>&#1069;&#1085;&#1077;&#1088;&#1075;&#1080;&#1103;: &#1042;&#1099;&#1082;&#1083;</span>
</button>
</div>
<div class="proj-canvas-outer">
<canvas id="pendulum-canvas"></canvas>
</div>
</div>
<div class="proj-stats-bar" id="pendbar">
<div class="pstat"><div class="pstat-label">&#1059;&#1075;&#1086;&#1083; / &#1082;&#1086;&#1086;&#1088;&#1076;.</div><div class="pstat-val" id="pendbar-v1" style="color:var(--violet)">45&#176;</div></div>
<div class="pstat"><div class="pstat-label">&#969;</div><div class="pstat-val" id="pendbar-v2" style="color:var(--cyan)">0</div></div>
<div class="pstat"><div class="pstat-label">&#1055;&#1077;&#1088;&#1080;&#1086;&#1076; T</div><div class="pstat-val" id="pendbar-v3" style="color:#FFD166"></div></div>
<div class="pstat"><div class="pstat-label">&#1056;&#1077;&#1078;&#1080;&#1084;</div><div class="pstat-val" id="pendbar-v4" style="color:#EF476F"></div></div>
</div>
</div>
<!-- ── EQUILIBRIUM sim body ── -->
<div id="sim-equilibrium" class="sim-proj-wrap" style="display:none">
<div class="sim-body-wrap">
<div class="proj-panel" style="width:220px;gap:0">
<div class="gp-section-title" style="margin-bottom:8px">Параметры</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:55px">T = <span id="eq-T-val" style="color:#FFD166;font-weight:700">300</span> K</label>
<input type="range" id="sl-eq-T" min="200" max="500" step="10" value="300" oninput="eqParam('T',this.value)" style="flex:1">
</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:55px">Ea<svg class="ic" viewBox="0 0 24 24"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg> <span id="eq-Eaf-val" style="color:#7BF5A4;font-weight:700">50</span></label>
<input type="range" id="sl-eq-Eaf" min="20" max="80" step="1" value="50" oninput="eqParam('Ea_f',this.value)" style="flex:1">
</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:55px">Ea<svg class="ic" viewBox="0 0 24 24"><line x1="19" y1="12" x2="5" y2="12"/><polyline points="12 19 5 12 12 5"/></svg> <span id="eq-Ear-val" style="color:#EF476F;font-weight:700">55</span></label>
<input type="range" id="sl-eq-Ear" min="20" max="80" step="1" value="55" oninput="eqParam('Ea_r',this.value)" style="flex:1">
</div>
<div style="margin-top:8px"></div>
<div class="gp-section-title" style="margin-bottom:6px">Пресеты</div>
<div style="display:flex;flex-wrap:wrap;gap:4px;margin-bottom:8px">
<button class="preset-btn" onclick="eqPreset('default')">По умолч.</button>
<button class="preset-btn" onclick="eqPreset('exothermic')">Экзо</button>
<button class="preset-btn" onclick="eqPreset('endothermic')">Эндо</button>
<button class="preset-btn" onclick="eqPreset('excess_A')">Избыток A</button>
</div>
<div class="pp-hint">A + B ⇌ C + D — принцип Ле Шателье</div>
</div>
<div class="proj-canvas-outer">
<canvas id="equilibrium-canvas"></canvas>
</div>
</div>
<div class="proj-stats-bar" id="eqbar">
<div class="pstat"><div class="pstat-label">Keq</div><div class="pstat-val" id="eqbar-v1" style="color:#7BF5A4"></div></div>
<div class="pstat"><div class="pstat-label">Q</div><div class="pstat-val" id="eqbar-v2" style="color:#FFD166"></div></div>
<div class="pstat"><div class="pstat-label">Направление</div><div class="pstat-val" id="eqbar-v3" style="color:var(--cyan)"></div></div>
<div class="pstat"><div class="pstat-label">A|B|C|D</div><div class="pstat-val" id="eqbar-v4" style="color:var(--violet)"></div></div>
</div>
</div>
<!-- ── OPTICSBENCH sim body ── -->
<div id="sim-opticsbench" class="sim-proj-wrap" style="display:none;flex-direction:column">
<!-- Tab bar -->
<div style="display:flex;gap:0;border-bottom:1px solid #2a2a3e;background:#12121e;flex-shrink:0">
<button id="ob-tab-lens" onclick="obSwitchMode('lens')" class="ob-tab active" style="flex:1;padding:8px 0;border:none;background:transparent;color:#ccc;font-size:.78rem;font-weight:600;cursor:pointer;border-bottom:2px solid transparent;transition:all .15s">Тонкая линза</button>
<button id="ob-tab-mirror" onclick="obSwitchMode('mirror')" class="ob-tab" style="flex:1;padding:8px 0;border:none;background:transparent;color:#ccc;font-size:.78rem;font-weight:600;cursor:pointer;border-bottom:2px solid transparent;transition:all .15s">Зеркала</button>
<button id="ob-tab-refraction" onclick="obSwitchMode('refraction')" class="ob-tab" style="flex:1;padding:8px 0;border:none;background:transparent;color:#ccc;font-size:.78rem;font-weight:600;cursor:pointer;border-bottom:2px solid transparent;transition:all .15s">Преломление</button>
<button id="ob-tab-freebuild" onclick="obSwitchMode('freebuild')" class="ob-tab" style="flex:1;padding:8px 0;border:none;background:transparent;color:#ccc;font-size:.78rem;font-weight:600;cursor:pointer;border-bottom:2px solid transparent;transition:all .15s">Конструктор</button>
<button id="ob-tab-prism" onclick="obSwitchMode('prism')" class="ob-tab" style="flex:1;padding:8px 0;border:none;background:transparent;color:#ccc;font-size:.78rem;font-weight:600;cursor:pointer;border-bottom:2px solid transparent;transition:all .15s">Призма</button>
<button id="ob-tab-interf" onclick="obSwitchMode('interf')" class="ob-tab" style="flex:1;padding:8px 0;border:none;background:transparent;color:#ccc;font-size:.78rem;font-weight:600;cursor:pointer;border-bottom:2px solid transparent;transition:all .15s">Интерференция</button>
<button id="ob-tab-waves" onclick="obSwitchMode('waves')" class="ob-tab" style="flex:1;padding:8px 0;border:none;background:transparent;color:#ccc;font-size:.78rem;font-weight:600;cursor:pointer;border-bottom:2px solid transparent;transition:all .15s">Волны</button>
</div>
<!-- ── Wavelength slider bar (global) ── -->
<div id="ob-wavelength-bar" style="display:flex;align-items:center;gap:8px;padding:5px 10px;background:#0c0c1a;border-bottom:1px solid #1a1a30;flex-shrink:0">
<span style="font-size:.72rem;color:#aaa;font-weight:600;white-space:nowrap;flex-shrink:0">&#955; =</span>
<div id="ob-wl-slider-row" style="display:flex;align-items:center;gap:6px;flex:1;max-width:280px">
<span style="font-size:.68rem;color:#8080ff">380</span>
<input type="range" id="sl-ob-wavelength" min="380" max="780" step="5" value="550"
oninput="obSetWavelength(this.value)"
style="flex:1;accent-color:var(--violet)">
<span style="font-size:.68rem;color:#ff6060">780</span>
</div>
<span id="ob-wl-val" style="font-size:.75rem;font-weight:700;min-width:52px;color:#FFFFFF">550 нм</span>
<label style="display:flex;align-items:center;gap:4px;font-size:.72rem;color:#ccc;cursor:pointer;flex-shrink:0;white-space:nowrap">
<input type="checkbox" id="ob-white-toggle" onchange="obToggleWhiteLight(this.checked)">
Белый свет
</label>
</div>
<!-- ── Готовые сцены / Instruments preset bar ── -->
<div id="ob-presets-bar" style="display:flex;align-items:center;gap:6px;padding:6px 10px;background:#0f0f1c;border-bottom:1px solid #1e1e32;flex-shrink:0;flex-wrap:wrap">
<span style="font-size:.72rem;color:#666;font-weight:600;white-space:nowrap;flex-shrink:0">Приборы:</span>
<button class="ob-preset-chip" data-preset="magnifier" onclick="obLoadPreset('magnifier')" title="Лупа: d &lt; f, мнимое увеличение">Лупа</button>
<button class="ob-preset-chip" data-preset="microscope" onclick="obLoadPreset('microscope')" title="Микроскоп: объектив f=10, d=14">Микроскоп</button>
<button class="ob-preset-chip" data-preset="keplerian" onclick="obLoadPreset('keplerian')" title="Телескоп Кеплера: fуб=200, fок=30">Тел. Кеплера</button>
<button class="ob-preset-chip" data-preset="galilean" onclick="obLoadPreset('galilean')" title="Телескоп Галилея: fок=-40">Тел. Галилея</button>
<button class="ob-preset-chip" data-preset="camera" onclick="obLoadPreset('camera')" title="Камера/Глаз: f=40, d=120">Камера</button>
<button class="ob-preset-chip" data-preset="periscope" onclick="obLoadPreset('periscope')" title="Перископ: плоское зеркало 45°">Перископ</button>
<button class="ob-preset-chip" data-preset="projector" onclick="obLoadPreset('projector')" title="Слайд-проектор: f=80, d=100">Проектор</button>
<button class="ob-preset-chip" data-preset="fiber" onclick="obLoadPreset('fiber')" title="Световод: ПВО, n=1.5 → n=1">Световод</button>
<button class="ob-preset-chip" data-preset="spoon" onclick="obLoadPreset('spoon')" title="Ложка в воде: преломление на границе">Ложка в воде</button>
<button class="ob-preset-chip ob-preset-clear" onclick="obClearPreset()" title="Вернуть начальные настройки" style="margin-left:auto">Очистить</button>
</div>
<!-- ── Эффекты panel (collapsible) ── -->
<details id="ob-fx-panel" class="ob-fx-panel">
<summary class="ob-fx-summary">
<svg class="ic" viewBox="0 0 16 16" width="12" height="12"><path d="M8 1a7 7 0 1 0 0 14A7 7 0 0 0 8 1zm0 2a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3zm0 4.5c1.7 0 3.2.85 4.1 2.15a5 5 0 0 1-8.2 0C4.8 8.35 6.3 7.5 8 7.5z"/></svg>
Эффекты
</summary>
<div class="ob-fx-row">
<label class="ob-fx-label">
<input type="checkbox" id="obfx-wavefronts" onchange="obFXToggle('wavefronts',this.checked)">
Волновые фронты вдоль лучей
</label>
<label class="ob-fx-label">
<input type="checkbox" id="obfx-mist" onchange="obFXToggle('mist',this.checked)">
Туман
</label>
<label class="ob-fx-label">
<input type="checkbox" id="obfx-flare" onchange="obFXToggle('flare',this.checked)">
Lens flare
</label>
<label class="ob-fx-label">
<input type="checkbox" id="obfx-huygens" onchange="obFXToggle('huygens',this.checked)">
Конструкция Гюйгенса
</label>
<label class="ob-fx-label">
<input type="checkbox" id="obfx-caustics" onchange="obFXToggle('caustics',this.checked)">
Каустики
</label>
</div>
</details>
<!-- Body row: control panels + shared canvas -->
<div style="display:flex;flex:1;min-height:0;overflow:hidden">
<!-- ── Lens control panel ── -->
<div id="ob-ctrl-lens" class="proj-panel" style="width:220px;gap:0;flex-shrink:0">
<div class="gp-section-title" style="margin-bottom:8px">Параметры</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:55px">f = <span id="lens-f-val" style="color:var(--cyan);font-weight:700">100</span></label>
<input type="range" id="sl-lens-f" min="-200" max="200" step="5" value="100" oninput="lensParam('f',this.value)" style="flex:1">
</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:55px">d = <span id="lens-d-val" style="color:var(--violet);font-weight:700">200</span></label>
<input type="range" id="sl-lens-d" min="30" max="400" step="5" value="200" oninput="lensParam('d',this.value)" style="flex:1">
</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:55px">h = <span id="lens-h-val" style="color:#EF476F;font-weight:700">50</span></label>
<input type="range" id="sl-lens-h" min="20" max="80" step="2" value="50" oninput="lensParam('h',this.value)" style="flex:1">
</div>
<div style="margin-top:8px"></div>
<div class="gp-section-title" style="margin-bottom:6px">Пресеты</div>
<div style="display:flex;flex-wrap:wrap;gap:4px;margin-bottom:8px">
<button class="preset-btn" onclick="lensPreset(100,200,50)">Собирающая</button>
<button class="preset-btn" onclick="lensPreset(-100,200,50)">Рассеивающая</button>
<button class="preset-btn" onclick="lensPreset(100,100,50)">d = f</button>
<button class="preset-btn" onclick="lensPreset(100,60,50)">d &lt; f</button>
</div>
<div class="pp-hint">Тащи стрелку-предмет или фокус мышью</div>
<div style="margin-top:8px"></div>
<!-- Feature 1: animated ray buttons -->
<div style="display:flex;gap:4px;margin-bottom:8px">
<button onclick="if(lensSim)lensSim.buildRays()" style="flex:1;padding:5px 0;border-radius:6px;border:none;background:linear-gradient(135deg,#06D6E0,#9B5DE5);color:#fff;font-size:.72rem;font-weight:700;cursor:pointer">Построить лучи</button>
<button onclick="if(lensSim)lensSim.resetRays()" style="padding:5px 9px;border-radius:6px;border:1px solid #333;background:#1a1a2e;color:#888;font-size:.78rem;cursor:pointer" title="Сбросить лучи">&#8634;</button>
</div>
<!-- Feature 3: lens-maker toggle -->
<div style="margin-bottom:6px">
<label style="display:flex;align-items:center;gap:6px;font-size:.72rem;color:#ccc;cursor:pointer">
<input type="checkbox" id="ltog-lensmaker" onchange="lensToggleLM(this.checked)">
Подробный (R1/R2/n)
</label>
</div>
<!-- LM sliders (hidden by default) -->
<div id="ob-lm-sliders" style="display:none">
<div class="proj-slider-row" style="margin-bottom:6px">
<label style="font-size:.72rem;color:#ccc;width:60px">R1 = <span id="lm-r1-val" style="color:#FFD166;font-weight:700">200</span></label>
<input type="range" id="sl-lm-r1" min="-300" max="300" step="5" value="200" oninput="lensLMParam('R1',this.value)" style="flex:1">
</div>
<div class="proj-slider-row" style="margin-bottom:6px">
<label style="font-size:.72rem;color:#ccc;width:60px">R2 = <span id="lm-r2-val" style="color:#FFD166;font-weight:700">-200</span></label>
<input type="range" id="sl-lm-r2" min="-300" max="300" step="5" value="-200" oninput="lensLMParam('R2',this.value)" style="flex:1">
</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.72rem;color:#ccc;width:60px">n = <span id="lm-n-val" style="color:#9B5DE5;font-weight:700">1.50</span></label>
<input type="range" id="sl-lm-n" min="1.3" max="2.4" step="0.05" value="1.5" oninput="lensLMParam('n',this.value)" style="flex:1">
</div>
<div style="font-size:.68rem;color:#888;margin-bottom:6px">f = 1/((n-1)*(1/R1 - 1/R2))</div>
</div>
<div style="margin-top:0"></div>
<div class="gp-section-title" style="margin-bottom:6px">Аберрации</div>
<div style="display:flex;flex-direction:column;gap:4px;margin-bottom:8px">
<label style="display:flex;align-items:center;gap:4px;font-size:.72rem;color:#ccc;cursor:pointer"><input type="checkbox" id="ltog-spherical" onchange="lensAberration('spherical',this.checked)"> Сферическая</label>
<label style="display:flex;align-items:center;gap:4px;font-size:.72rem;color:#ccc;cursor:pointer"><input type="checkbox" id="ltog-chromatic" onchange="lensAberration('chromatic',this.checked)"> Хроматическая</label>
</div>
</div>
<!-- ── Mirror control panel ── -->
<div id="ob-ctrl-mirror" class="proj-panel" style="width:264px;gap:0;flex-shrink:0;display:none">
<div class="gp-section-title" style="margin-bottom:8px">Тип зеркала</div>
<div style="display:flex;flex-wrap:wrap;gap:4px;margin-bottom:10px">
<button class="preset-btn mirror-type-btn" id="mtype-flat" onclick="mirrorType('flat',this)" style="font-size:.72rem">Плоское</button>
<button class="preset-btn mirror-type-btn active" id="mtype-concave" onclick="mirrorType('concave',this)" style="font-size:.72rem">Вогнутое</button>
<button class="preset-btn mirror-type-btn" id="mtype-convex" onclick="mirrorType('convex',this)" style="font-size:.72rem">Выпуклое</button>
</div>
<div class="gp-section-title" style="margin-bottom:8px">Параметры</div>
<div class="proj-slider-row" style="margin-bottom:8px" id="mirror-f-row">
<label style="font-size:.78rem;color:#ccc;width:60px">f = <span id="mirror-f-val" style="color:var(--cyan);font-weight:700">120</span></label>
<input type="range" id="sl-mirror-f" min="30" max="300" step="5" value="120" oninput="mirrorParam('f',this.value)" style="flex:1">
</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:60px">d = <span id="mirror-d-val" style="color:var(--violet);font-weight:700">240</span></label>
<input type="range" id="sl-mirror-d" min="30" max="500" step="5" value="240" oninput="mirrorParam('d',this.value)" style="flex:1">
</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:60px">h = <span id="mirror-h-val" style="color:#EF476F;font-weight:700">60</span></label>
<input type="range" id="sl-mirror-h" min="20" max="80" step="2" value="60" oninput="mirrorParam('h',this.value)" style="flex:1">
</div>
<div style="display:flex;gap:6px;margin-top:8px;margin-bottom:8px;align-items:center">
<button id="mirror-play-btn" onclick="mirrorTogglePlay(this)" style="flex:1;padding:6px 0;border-radius:8px;border:none;background:linear-gradient(135deg,var(--cyan),var(--violet));color:#fff;font-size:.78rem;font-weight:700;cursor:pointer">&#9654; Анимация</button>
<div style="display:flex;flex-direction:column;align-items:center;gap:2px">
<span style="font-size:.62rem;color:#888">скорость</span>
<select id="mirror-speed-sel" onchange="mirrorSetSpeed(this.value)" style="background:#1a1a2e;color:#ccc;border:1px solid #333;border-radius:4px;font-size:.7rem;padding:2px 4px">
<option value="0.25">&#215;&#188;</option><option value="0.5">&#215;&#189;</option>
<option value="1" selected>&#215;1</option><option value="2">&#215;2</option>
</select>
</div>
</div>
<div style="display:flex;gap:4px;margin-bottom:10px">
<button onclick="mirrorStepNext()" style="flex:1;padding:5px 0;border-radius:6px;border:1px solid #333;background:#1a1a2e;color:#7BF5A4;font-size:.73rem;cursor:pointer" title="Показать следующий луч">&#9312; Пошагово</button>
<button onclick="mirrorStepReset()" style="padding:5px 9px;border-radius:6px;border:1px solid #333;background:#1a1a2e;color:#888;font-size:.78rem;cursor:pointer" title="Показать все лучи">&#8634;</button>
</div>
<!-- Feature 2: R-slider + parabolic toggle -->
<div style="margin-bottom:6px">
<label style="display:flex;align-items:center;gap:6px;font-size:.72rem;color:#ccc;cursor:pointer">
<input type="checkbox" id="mtog-useR" onchange="mirrorToggleR(this.checked)">
Радиус R (непрерывный)
</label>
</div>
<div id="ob-mirror-R-row" class="proj-slider-row" style="margin-bottom:6px;display:none">
<label style="font-size:.72rem;color:#ccc;width:60px">R = <span id="mirror-R-val" style="color:var(--cyan);font-weight:700">240</span></label>
<input type="range" id="sl-mirror-R" min="-250" max="250" step="5" value="240" oninput="mirrorRParam(this.value)" style="flex:1">
</div>
<div style="display:flex;gap:4px;margin-bottom:8px">
<button id="mirror-parab-btn" onclick="mirrorToggleParabolic(this)" style="flex:1;padding:5px 0;border-radius:6px;border:1px solid #333;background:#1a1a2e;color:#888;font-size:.72rem;cursor:pointer">Сферическое</button>
</div>
<div class="gp-section-title" style="margin-bottom:6px">Отображение</div>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:3px 10px;margin-bottom:10px">
<label style="display:flex;align-items:center;gap:4px;font-size:.72rem;color:#ccc;cursor:pointer"><input type="checkbox" id="mtog-normals" checked onchange="mirrorToggle('normals',this.checked)"> Нормали</label>
<label style="display:flex;align-items:center;gap:4px;font-size:.72rem;color:#ccc;cursor:pointer"><input type="checkbox" id="mtog-dims" checked onchange="mirrorToggle('dims',this.checked)"> Размеры</label>
<label style="display:flex;align-items:center;gap:4px;font-size:.72rem;color:#ccc;cursor:pointer"><input type="checkbox" id="mtog-angles" checked onchange="mirrorToggle('angles',this.checked)"> Углы &#952;</label>
<label style="display:flex;align-items:center;gap:4px;font-size:.72rem;color:#ccc;cursor:pointer"><input type="checkbox" id="mtog-photons" checked onchange="mirrorToggle('photons',this.checked)"> Фотоны</label>
<label style="display:flex;align-items:center;gap:4px;font-size:.72rem;color:#ccc;cursor:pointer"><input type="checkbox" id="mtog-grid" onchange="mirrorToggle('grid',this.checked)"> Сетка</label>
<label style="display:flex;align-items:center;gap:4px;font-size:.72rem;color:#ccc;cursor:pointer"><input type="checkbox" id="mtog-zones" checked onchange="mirrorToggle('zones',this.checked)"> Зоны</label>
<label style="display:flex;align-items:center;gap:4px;font-size:.72rem;color:#ccc;cursor:pointer;grid-column:span 2"><input type="checkbox" id="mtog-point" onchange="mirrorSetPointMode(this.checked)"> Точечный объект</label>
<label style="display:flex;align-items:center;gap:4px;font-size:.72rem;color:#FF6B6B;cursor:pointer;grid-column:span 2"><input type="checkbox" id="mtog-spherical" onchange="mirrorAberration(this.checked)"> Сферич. аберрация</label>
</div>
<button onclick="if(mirrorSim)mirrorSim.exportPng()" style="width:100%;padding:5px 0;border-radius:6px;border:1px solid #333;background:#1a1a2e;color:#888;font-size:.72rem;cursor:pointer;margin-bottom:8px"><svg class="ic" viewBox="0 0 24 24"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg> Экспорт PNG</button>
<div class="gp-section-title" style="margin-bottom:6px">Пресеты</div>
<div style="display:flex;flex-wrap:wrap;gap:4px;margin-bottom:8px">
<button class="preset-btn" onclick="mirrorPreset('flat')">Плоское</button>
<button class="preset-btn" onclick="mirrorPreset('far')">d &gt; 2f</button>
<button class="preset-btn" onclick="mirrorPreset('2f')">d = 2f</button>
<button class="preset-btn" onclick="mirrorPreset('between')">f &lt; d &lt; 2f</button>
<button class="preset-btn" onclick="mirrorPreset('near')">d &lt; f</button>
<button class="preset-btn" onclick="mirrorPreset('convex')">Выпуклое</button>
</div>
<div class="pp-hint">Тащи предмет, фокус или изображение мышью</div>
</div>
<!-- ── Refraction control panel ── -->
<div id="ob-ctrl-refraction" class="proj-panel" style="width:220px;gap:0;flex-shrink:0;display:none">
<div class="gp-section-title" style="margin-bottom:8px">Параметры</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:55px">n&#8321; = <span id="refr-n1-val" style="color:var(--violet);font-weight:700">1.00</span></label>
<input type="range" id="sl-refr-n1" min="1" max="2.5" step="0.01" value="1" oninput="refrParam('n1',this.value)" style="flex:1">
</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:55px">n&#8322; = <span id="refr-n2-val" style="color:var(--cyan);font-weight:700">1.50</span></label>
<input type="range" id="sl-refr-n2" min="1" max="2.5" step="0.01" value="1.5" oninput="refrParam('n2',this.value)" style="flex:1">
</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:55px">&#952; = <span id="refr-angle-val" style="color:#FFD166;font-weight:700">30</span>&#176;</label>
<input type="range" id="sl-refr-angle" min="0" max="89" step="1" value="30" oninput="refrParam('angle',this.value)" style="flex:1">
</div>
<div style="margin-top:8px"></div>
<label style="display:flex;align-items:center;gap:6px;font-size:.72rem;color:#ccc;cursor:pointer;margin-bottom:8px">
<input type="checkbox" id="refr-dispersion-toggle" onchange="refrDispersion(this.checked)">
Дисперсия (7 цветов)
</label>
<div class="gp-section-title" style="margin-bottom:6px">Пресеты</div>
<div style="display:flex;flex-wrap:wrap;gap:4px;margin-bottom:8px">
<button class="preset-btn" onclick="refrPreset(1,1.5,30)">Воздух&#8594;Стекло</button>
<button class="preset-btn" onclick="refrPreset(1.5,1,30)">Стекло&#8594;Воздух</button>
<button class="preset-btn" onclick="refrPreset(1.33,1.5,30)">Вода&#8594;Стекло</button>
<button class="preset-btn" onclick="refrPreset(1,2.42,45)">Алмаз</button>
</div>
<div class="pp-hint">Тащи луч мышью для изменения угла</div>
</div>
<!-- ── Prism control panel ── -->
<div id="ob-ctrl-prism" class="proj-panel" style="width:220px;gap:0;flex-shrink:0;display:none">
<div class="gp-section-title" style="margin-bottom:8px">Параметры призмы</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:55px">n = <span id="prism-n0-val" style="color:#64b4ff;font-weight:700">1.50</span></label>
<input type="range" id="sl-prism-n0" min="1.3" max="2.4" step="0.01" value="1.5" oninput="prismParam('n0',this.value)" style="flex:1">
</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:65px">&#952;&#1074;&#1093; = <span id="prism-inc-val" style="color:#FFD166;font-weight:700">30</span>&#176;</label>
<input type="range" id="sl-prism-inc" min="0" max="75" step="1" value="30" oninput="prismParam('incAngle',this.value)" style="flex:1">
</div>
<div class="pp-hint" style="margin-bottom:8px">Тащи призму мышью: ← → вращение, &#8597; угол луча</div>
<div class="gp-section-title" style="margin-bottom:6px">Свет</div>
<div style="display:flex;gap:5px;margin-bottom:10px">
<button class="preset-btn active" id="ob-prism-white-btn" onclick="prismToggleWhite(true,this)" style="flex:1">Белый</button>
<button class="preset-btn" id="ob-prism-mono-btn" onclick="prismToggleWhite(false,this)" style="flex:1">Моно</button>
</div>
<div class="gp-section-title" style="margin-bottom:6px">Пресеты</div>
<div style="display:flex;flex-wrap:wrap;gap:4px;margin-bottom:8px">
<button class="preset-btn" onclick="prismPreset(1.5,30)">Стекло (n=1.5)</button>
<button class="preset-btn" onclick="prismPreset(1.7,40)">Флинт (n=1.7)</button>
<button class="preset-btn" onclick="prismPreset(2.42,45)">Алмаз (n=2.42)</button>
</div>
</div>
<!-- ── Free-build multi-lens control panel (Agent OB-A3) ── -->
<div id="ob-ctrl-freebuild" class="proj-panel" style="width:230px;gap:0;flex-shrink:0;display:none;overflow-y:auto">
<div class="gp-section-title" style="margin-bottom:6px">Добавить элемент</div>
<div style="display:flex;flex-wrap:wrap;gap:4px;margin-bottom:8px">
<button class="preset-btn" style="font-size:.68rem" onclick="benchAdd('lens')">+ Линза</button>
<button class="preset-btn" style="font-size:.68rem" onclick="benchAdd('mirror')">+ Зеркало</button>
<button class="preset-btn" style="font-size:.68rem" onclick="benchAdd('aperture')">+ Диафрагма</button>
<button class="preset-btn" style="font-size:.68rem" onclick="benchAdd('screen')">+ Экран</button>
<button class="preset-btn" style="font-size:.68rem" onclick="benchAdd('prism')">+ Призма</button>
<button class="preset-btn" style="font-size:.68rem" onclick="benchAdd('interface')">+ Граница</button>
<button class="preset-btn" style="font-size:.68rem" onclick="benchAdd('slab')">+ Пластина</button>
</div>
<div class="gp-section-title" style="margin-bottom:6px">Схема</div>
<div id="bench-list" style="display:flex;flex-wrap:wrap;gap:3px;margin-bottom:8px"></div>
<div id="bench-props" style="margin-bottom:8px"></div>
<div class="gp-section-title" style="margin-bottom:6px">Системы</div>
<div style="display:flex;flex-wrap:wrap;gap:4px;margin-bottom:6px">
<button class="preset-btn" style="font-size:.68rem" onclick="benchPreset('microscope')">Микроскоп</button>
<button class="preset-btn" style="font-size:.68rem" onclick="benchPreset('telescope')">Телескоп</button>
<button class="preset-btn" style="font-size:.68rem" onclick="benchPreset('projector')">Проектор</button>
<button class="preset-btn" style="font-size:.68rem" onclick="benchPreset('folded')">Зеркальная</button>
</div>
<div style="display:flex;gap:4px;margin-bottom:6px">
<button class="preset-btn" style="flex:1" onclick="benchClear()">Очистить</button>
<button class="preset-btn" style="flex:1" onclick="benchExportPng()">Снимок PNG</button>
</div>
<div class="pp-hint">Тащи элементы и источник по оси. Клик — выбрать и настроить. λ и «Белый свет» — сверху.</div>
</div>
<!-- ── Interference control panel (Agent C) ── -->
<div id="ob-ctrl-interf" class="proj-panel" style="width:240px;gap:0;flex-shrink:0;display:none">
<!-- Sub-mode buttons -->
<div class="gp-section-title" style="margin-bottom:6px">Эксперимент</div>
<div style="display:flex;gap:3px;margin-bottom:10px;flex-wrap:wrap">
<button id="if-sub-newton" class="preset-btn active" onclick="ifSwitchSub('newton')" style="font-size:.7rem;flex:1">Кольца Ньютона</button>
<button id="if-sub-thinfilm" class="preset-btn" onclick="ifSwitchSub('thinfilm')" style="font-size:.7rem;flex:1">Тонкая плёнка</button>
<button id="if-sub-polarization" class="preset-btn" onclick="ifSwitchSub('polarization')" style="font-size:.7rem;flex:1">Поляризация</button>
</div>
<!-- Newton rings controls -->
<div id="if-ctrl-newton">
<div class="gp-section-title" style="margin-bottom:6px">Кольца Ньютона</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:65px">R = <span id="if-newton-r-val" style="color:var(--cyan);font-weight:700">200</span> мм</label>
<input type="range" id="sl-if-newton-r" min="50" max="500" step="10" value="200" oninput="ifNewtParam('R',this.value)" style="flex:1">
</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:65px">n = <span id="if-newton-n-val" style="color:#FFD166;font-weight:700">12</span></label>
<input type="range" id="sl-if-newton-n" min="4" max="20" step="1" value="12" oninput="ifNewtParam('nmax',this.value)" style="flex:1">
</div>
<div class="pp-hint">r_n(dark) = sqrt(n*lambda*R)</div>
</div>
<!-- Thin film controls -->
<div id="if-ctrl-thinfilm" style="display:none">
<div class="gp-section-title" style="margin-bottom:6px">Тонкая плёнка</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:60px">t = <span id="if-tf-t-val" style="color:var(--cyan);font-weight:700">400</span></label>
<input type="range" id="sl-if-tf-t" min="50" max="2000" step="10" value="400" oninput="ifThinFilmParam('t',this.value)" style="flex:1">
</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:60px">n = <span id="if-tf-n-val" style="color:#FFD166;font-weight:700">1.33</span></label>
<input type="range" id="sl-if-tf-n" min="1.0" max="2.5" step="0.01" value="1.33" oninput="ifThinFilmParam('n',this.value)" style="flex:1">
</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:60px">&#952; = <span id="if-tf-th-val" style="color:#EF476F;font-weight:700">0</span>&#176;</label>
<input type="range" id="sl-if-tf-th" min="0" max="60" step="1" value="0" oninput="ifThinFilmParam('theta',this.value)" style="flex:1">
</div>
<div class="gp-section-title" style="margin-bottom:4px">Пресет</div>
<div style="display:flex;flex-wrap:wrap;gap:3px;margin-bottom:6px">
<button class="preset-btn" onclick="ifThinFilmPreset('soap')" style="font-size:.68rem">Мыльная n=1.33</button>
<button class="preset-btn" onclick="ifThinFilmPreset('oil')" style="font-size:.68rem">Масло n=1.50</button>
<button class="preset-btn" onclick="ifThinFilmPreset('coating')" style="font-size:.68rem">Покрытие n=1.38</button>
</div>
<div class="pp-hint">2nt&#183;cos&#952;r = (m+0.5)&#955; — максимум</div>
</div>
<!-- Polarization controls -->
<div id="if-ctrl-polarization" style="display:none">
<div class="gp-section-title" style="margin-bottom:6px">Поляризация (Малюс)</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:60px">&#952; = <span id="if-pol-th-val" style="color:var(--cyan);font-weight:700">45</span>&#176;</label>
<input type="range" id="sl-if-pol-th" min="0" max="90" step="1" value="45" oninput="ifPolParam('theta',this.value)" style="flex:1">
</div>
<div style="margin-bottom:8px">
<label style="font-size:.72rem;color:#ccc;display:flex;align-items:center;gap:6px;cursor:pointer">
<input type="radio" name="if-pol-src" value="unpolarized" checked onchange="ifPolSrc(this.value)" style="accent-color:var(--violet)">
Неполяризованный
</label>
<label style="font-size:.72rem;color:#ccc;display:flex;align-items:center;gap:6px;cursor:pointer;margin-top:4px">
<input type="radio" name="if-pol-src" value="polarized" onchange="ifPolSrc(this.value)" style="accent-color:var(--violet)">
Поляризованный
</label>
</div>
<div class="pp-hint">I = I&#8320;&#183;cos&#178;(&#952;)</div>
</div>
</div>
<!-- ── Waves (diffraction) control panel (Agent B1) ── -->
<div id="ob-ctrl-waves" class="proj-panel" style="width:230px;gap:0;flex-shrink:0;display:none">
<div class="gp-section-title" style="margin-bottom:8px">Опыт</div>
<div style="display:flex;gap:3px;margin-bottom:10px">
<button id="diffr-sub-young" onclick="diffrSwitchSub('young')" class="preset-btn active" style="flex:1;font-size:.7rem">Юнг</button>
<button id="diffr-sub-single" onclick="diffrSwitchSub('single')" class="preset-btn" style="flex:1;font-size:.7rem">Однощелевая</button>
<button id="diffr-sub-grating" onclick="diffrSwitchSub('grating')" class="preset-btn" style="flex:1;font-size:.7rem">Решётка</button>
</div>
<!-- Young sliders -->
<div id="ob-diffr-young-params">
<div class="gp-section-title" style="margin-bottom:6px">Параметры (Юнг)</div>
<div class="proj-slider-row" style="margin-bottom:6px">
<label style="font-size:.75rem;color:#ccc;width:72px">d = <span id="diffr-d-young-val" style="color:var(--cyan);font-weight:700">40</span> мкм</label>
<input type="range" id="sl-diffr-d-young" min="10" max="100" step="1" value="40"
oninput="diffrParam('d_young',this.value)" style="flex:1">
</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.75rem;color:#ccc;width:72px">L = <span id="diffr-L-young-val" style="color:var(--violet);font-weight:700">1.0</span> м</label>
<input type="range" id="sl-diffr-L-young" min="5" max="20" step="1" value="10"
oninput="diffrParam('L_young',this.value/10)" style="flex:1">
</div>
</div>
<!-- Single-slit sliders -->
<div id="ob-diffr-single-params" style="display:none">
<div class="gp-section-title" style="margin-bottom:6px">Параметры (Однощелевая)</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.75rem;color:#ccc;width:72px">a = <span id="diffr-a-single-val" style="color:#FFD166;font-weight:700">80</span> мкм</label>
<input type="range" id="sl-diffr-a-single" min="10" max="200" step="5" value="80"
oninput="diffrParam('a_single',this.value)" style="flex:1">
</div>
</div>
<!-- Grating sliders -->
<div id="ob-diffr-grating-params" style="display:none">
<div class="gp-section-title" style="margin-bottom:6px">Параметры (Решётка)</div>
<div class="proj-slider-row" style="margin-bottom:6px">
<label style="font-size:.75rem;color:#ccc;width:72px">N = <span id="diffr-N-grating-val" style="color:#7BF5A4;font-weight:700">10</span></label>
<input type="range" id="sl-diffr-N-grating" min="2" max="100" step="1" value="10"
oninput="diffrParam('N_grating',this.value)" style="flex:1">
</div>
<div class="proj-slider-row" style="margin-bottom:6px">
<label style="font-size:.75rem;color:#ccc;width:72px">d = <span id="diffr-d-grating-val" style="color:var(--cyan);font-weight:700">2.0</span> мкм</label>
<input type="range" id="sl-diffr-d-grating" min="5" max="50" step="1" value="20"
oninput="diffrParam('d_grating',this.value/10)" style="flex:1">
</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.75rem;color:#ccc;width:72px">a = <span id="diffr-a-grating-val" style="color:#FFD166;font-weight:700">0.5</span> мкм</label>
<input type="range" id="sl-diffr-a-grating" min="1" max="30" step="1" value="5"
oninput="diffrParam('a_grating',this.value/10)" style="flex:1">
</div>
</div>
<div style="margin-top:4px"></div>
<button onclick="diffrReset()" style="width:100%;padding:5px 0;border-radius:6px;border:1px solid #333;background:#1a1a2e;color:#888;font-size:.72rem;cursor:pointer;margin-bottom:8px">Сброс</button>
<div class="pp-hint">&#955; берётся из глобального ползунка</div>
</div>
<!-- ── Shared canvas area (all 6 canvases stacked) ── -->
<div class="proj-canvas-outer" style="position:relative;flex:1;min-width:0">
<canvas id="ob-lens-canvas" style="position:absolute;top:0;left:0;width:100%;height:100%"></canvas>
<canvas id="ob-mirror-canvas" style="position:absolute;top:0;left:0;width:100%;height:100%;display:none"></canvas>
<canvas id="ob-refr-canvas" style="position:absolute;top:0;left:0;width:100%;height:100%;display:none"></canvas>
<canvas id="ob-prism-canvas" style="position:absolute;top:0;left:0;width:100%;height:100%;display:none"></canvas>
<canvas id="ob-free-canvas" style="position:absolute;top:0;left:0;width:100%;height:100%;display:none"></canvas>
<canvas id="ob-waves-canvas" style="position:absolute;top:0;left:0;width:100%;height:100%;display:none"></canvas>
<canvas id="ob-interf-canvas" style="position:absolute;top:0;left:0;width:100%;height:100%;display:none"></canvas>
</div>
</div>
<!-- Spectrometer panel (shown only in prism mode) -->
<div id="ob-spectrometer-panel" style="display:none;flex-shrink:0;padding:6px 10px 4px;background:#0a0a16;border-top:1px solid #1a1a30">
<div style="display:flex;align-items:center;gap:8px;margin-bottom:4px">
<span style="font-size:.72rem;color:#888;font-weight:600">Спектрометр</span>
<span style="font-size:.68rem;color:#555">380780 нм</span>
</div>
<canvas id="ob-spectrometer-canvas" style="width:100%;height:56px;display:block;border-radius:4px"></canvas>
</div>
<!-- Stats bar -->
<div class="proj-stats-bar" id="ob-statsbar" style="padding:0">
<div id="ob-stats-lens" style="display:flex;flex:1;gap:0">
<div class="pstat"><div class="pstat-label">f</div><div class="pstat-val" id="lensbar-v1" style="color:var(--cyan)">100</div></div>
<div class="pstat"><div class="pstat-label">d&#8217;</div><div class="pstat-val" id="lensbar-v2" style="color:#EF476F">&#8212;</div></div>
<div class="pstat"><div class="pstat-label">M</div><div class="pstat-val" id="lensbar-v3" style="color:#FFD166">&#8212;</div></div>
<div class="pstat"><div class="pstat-label">Тип</div><div class="pstat-val" id="lensbar-v4" style="color:var(--violet)">&#8212;</div></div>
</div>
<div id="ob-stats-mirror" style="display:none;flex:1;gap:0">
<div class="pstat"><div class="pstat-label">f</div><div class="pstat-val" id="mirrorbar-v1" style="color:var(--cyan)">120</div></div>
<div class="pstat"><div class="pstat-label">d</div><div class="pstat-val" id="mirrorbar-v5" style="color:var(--violet)">240</div></div>
<div class="pstat"><div class="pstat-label">d&#8217;</div><div class="pstat-val" id="mirrorbar-v2" style="color:#EF476F">&#8212;</div></div>
<div class="pstat"><div class="pstat-label">M</div><div class="pstat-val" id="mirrorbar-v3" style="color:#FFD166">&#8212;</div></div>
<div class="pstat"><div class="pstat-label">Тип изобр.</div><div class="pstat-val" id="mirrorbar-v4" style="color:var(--violet)">&#8212;</div></div>
</div>
<div id="ob-stats-refr" style="display:none;flex:1;gap:0">
<div class="pstat"><div class="pstat-label">&#952;&#8321;</div><div class="pstat-val" id="refrbar-v1" style="color:var(--violet)">30&#176;</div></div>
<div class="pstat"><div class="pstat-label">&#952;&#8322;</div><div class="pstat-val" id="refrbar-v2" style="color:var(--cyan)">&#8212;</div></div>
<div class="pstat"><div class="pstat-label">Крит. угол</div><div class="pstat-val" id="refrbar-v3" style="color:#FFD166">&#8212;</div></div>
<div class="pstat"><div class="pstat-label">ПВО</div><div class="pstat-val" id="refrbar-v4" style="color:#EF476F">Нет</div></div>
</div>
<div id="ob-stats-freebuild" style="display:none;flex:1;gap:0">
<div class="pstat"><div class="pstat-label">&#915; общ.</div><div class="pstat-val" id="freebar-mag" style="color:#FFD166">&#8212;</div></div>
<div class="pstat"><div class="pstat-label">F сист.</div><div class="pstat-val" id="freebar-sys" style="color:var(--cyan)">&#8212;</div></div>
</div>
<div id="ob-stats-prism" style="display:none;flex:1;gap:0">
<div class="pstat"><div class="pstat-label">A</div><div class="pstat-val" style="color:#64b4ff">60&#176;</div></div>
<div class="pstat"><div class="pstat-label">n(550)</div><div class="pstat-val" id="prismbar-n" style="color:#64b4ff">1.50</div></div>
<div class="pstat"><div class="pstat-label">&#955;</div><div class="pstat-val" id="prismbar-wl" style="color:#FFFFFF">550 нм</div></div>
<div class="pstat"><div class="pstat-label">Режим</div><div class="pstat-val" id="prismbar-mode" style="color:#aaa">Моно</div></div>
</div>
<div id="ob-stats-interf" style="display:none;flex:1;gap:0">
<div class="pstat"><div class="pstat-label">Режим</div><div class="pstat-val" id="ifbar-sub" style="color:var(--cyan)">Кольца</div></div>
<div class="pstat"><div class="pstat-label">&#955;</div><div class="pstat-val" id="ifbar-wl" style="color:#FFFFFF">550 нм</div></div>
</div>
<div id="ob-stats-waves" style="display:none;flex:1;gap:0">
<div class="pstat"><div class="pstat-label">Опыт</div><div class="pstat-val" id="diffbar-sub" style="color:var(--cyan)">Юнг</div></div>
<div class="pstat"><div class="pstat-label">&#955;</div><div class="pstat-val" id="diffbar-wl" style="color:#FFFFFF">550 нм</div></div>
<div class="pstat" style="flex:2"><div class="pstat-label">Результат</div><div class="pstat-val" id="diffbar-info" style="color:#FFD166;font-size:.72rem">&#8212;</div></div>
</div>
</div>
</div>
<!-- ── ISOPROCESS sim body ── -->
<div id="sim-isoprocess" class="sim-proj-wrap" style="display:none">
<div class="sim-body-wrap">
<div class="proj-panel" style="width:220px;gap:0">
<div class="gp-section-title" style="margin-bottom:8px">Процесс</div>
<div style="display:flex;flex-wrap:wrap;gap:4px;margin-bottom:10px">
<button class="preset-btn iso-proc-btn active" id="iproc-isothermal" onclick="isoProc('isothermal',this)" style="font-size:.72rem">Изотерма</button>
<button class="preset-btn iso-proc-btn" id="iproc-isochoric" onclick="isoProc('isochoric',this)" style="font-size:.72rem">Изохора</button>
<button class="preset-btn iso-proc-btn" id="iproc-isobaric" onclick="isoProc('isobaric',this)" style="font-size:.72rem">Изобара</button>
<button class="preset-btn iso-proc-btn" id="iproc-adiabatic" onclick="isoProc('adiabatic',this)" style="font-size:.72rem">Адиабата</button>
</div>
<div class="gp-section-title" style="margin-bottom:6px">Газ γ</div>
<div style="display:flex;gap:4px;margin-bottom:10px">
<button class="preset-btn iso-gamma-btn" id="igamma-14" onclick="isoGamma(1.4,this)" style="font-size:.72rem">Двухат. 1.4</button>
<button class="preset-btn iso-gamma-btn active" id="igamma-167" onclick="isoGamma(1.667,this)" style="font-size:.72rem">Одноат. 5/3</button>
</div>
<div class="gp-section-title" style="margin-bottom:8px">Начальное состояние</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:70px">P₁ = <span id="iso-p1-val" style="color:var(--violet);font-weight:700">3.0</span></label>
<input type="range" id="sl-iso-p1" min="0.5" max="8" step="0.1" value="3.0" oninput="isoParam('P1',this.value)" style="flex:1">
</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:70px">V₁ = <span id="iso-v1-val" style="color:var(--violet);font-weight:700">10</span></label>
<input type="range" id="sl-iso-v1" min="2" max="28" step="1" value="10" oninput="isoParam('V1',this.value)" style="flex:1">
</div>
<div class="gp-section-title" style="margin-bottom:8px">Конечное состояние</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:70px;white-space:nowrap">Сжат./расш.</label>
<input type="range" id="sl-iso-ratio" min="0.01" max="0.99" step="0.01" value="0.5" oninput="isoRatio(this.value)" style="flex:1">
</div>
<div style="margin-top:6px"></div>
<div class="gp-section-title" style="margin-bottom:6px">Пресеты</div>
<div style="display:flex;flex-wrap:wrap;gap:4px;margin-bottom:8px">
<button class="preset-btn" onclick="isoPreset('iso_expand')">Изотерма расш.</button>
<button class="preset-btn" onclick="isoPreset('iso_comp')">Изотерма сжат.</button>
<button class="preset-btn" onclick="isoPreset('heat_iso')">Изохора нагрев</button>
<button class="preset-btn" onclick="isoPreset('adiab_exp')">Адиабата расш.</button>
</div>
<div class="pp-hint">Тащи точки 1 и 2 по диаграмме</div>
</div>
<div class="proj-canvas-outer">
<canvas id="isoprocess-canvas"></canvas>
</div>
</div>
<div class="proj-stats-bar" id="isobar">
<div class="pstat"><div class="pstat-label">T₁, K</div><div class="pstat-val" id="isobar-t1" style="color:var(--violet)"></div></div>
<div class="pstat"><div class="pstat-label">T₂, K</div><div class="pstat-val" id="isobar-t2" style="color:var(--cyan)"></div></div>
<div class="pstat"><div class="pstat-label">W, Дж</div><div class="pstat-val" id="isobar-w" style="color:#7BF5A4"></div></div>
<div class="pstat"><div class="pstat-label">Q, Дж</div><div class="pstat-val" id="isobar-q" style="color:#FFD166"></div></div>
<div class="pstat"><div class="pstat-label">ΔU, Дж</div><div class="pstat-val" id="isobar-du" style="color:#EF476F"></div></div>
</div>
</div>
<!-- ── TITRATION sim body ── -->
<div id="sim-titration" class="sim-proj-wrap" style="display:none">
<div class="sim-body-wrap">
<div class="proj-panel" style="width:220px;gap:0">
<div class="gp-section-title" style="margin-bottom:8px">Параметры</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:75px">C(кисл) <span id="titr-ac-val" style="color:#EF476F;font-weight:700">0.10</span> М</label>
<input type="range" id="sl-titr-ac" min="0.05" max="1" step="0.05" value="0.1" oninput="titrParam('acidConc',this.value)" style="flex:1">
</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:75px">C(осн) <span id="titr-bc-val" style="color:var(--violet);font-weight:700">0.10</span> М</label>
<input type="range" id="sl-titr-bc" min="0.05" max="1" step="0.05" value="0.1" oninput="titrParam('baseConc',this.value)" style="flex:1">
</div>
<div class="proj-slider-row" style="margin-bottom:8px">
<label style="font-size:.78rem;color:#ccc;width:75px">V(кисл) <span id="titr-vol-val" style="color:var(--cyan);font-weight:700">50</span> мл</label>
<input type="range" id="sl-titr-vol" min="25" max="100" step="5" value="50" oninput="titrParam('acidVol',this.value)" style="flex:1">
</div>
<div style="margin-top:4px;margin-bottom:8px">
<div class="gp-section-title" style="margin-bottom:4px">Индикатор</div>
<div style="display:flex;flex-wrap:wrap;gap:4px">
<button class="preset-btn titr-ind-btn active" onclick="titrIndicator('phenolphthalein',this)" style="font-size:.72rem">Фенолф.</button>
<button class="preset-btn titr-ind-btn" onclick="titrIndicator('methyl_orange',this)" style="font-size:.72rem">Метилор.</button>
<button class="preset-btn titr-ind-btn" onclick="titrIndicator('litmus',this)" style="font-size:.72rem">Лакмус</button>
</div>
</div>
<div class="gp-section-title" style="margin-bottom:6px">Пресеты</div>
<div style="display:flex;flex-wrap:wrap;gap:4px;margin-bottom:8px">
<button class="preset-btn" onclick="titrPreset('strong_strong')">HCl+NaOH</button>
<button class="preset-btn" onclick="titrPreset('weak_strong')">CH₃COOH</button>
<button class="preset-btn" onclick="titrPreset('concentrated')">Конц.</button>
</div>
<div class="pp-hint">Нажми <svg class="ic" viewBox="0 0 24 24"><polygon points="5 3 19 12 5 21 5 3"/></svg> — основание добавляется каплями</div>
</div>
<div class="proj-canvas-outer">
<canvas id="titration-canvas"></canvas>
</div>
</div>
<div class="proj-stats-bar" id="titrbar">
<div class="pstat"><div class="pstat-label">pH</div><div class="pstat-val" id="titrbar-v1" style="color:#EF476F"></div></div>
<div class="pstat"><div class="pstat-label">Добавлено</div><div class="pstat-val" id="titrbar-v2" style="color:var(--violet)">0.0 мл</div></div>
<div class="pstat"><div class="pstat-label">Точка экв.</div><div class="pstat-val" id="titrbar-v3" style="color:var(--cyan)"></div></div>
<div class="pstat"><div class="pstat-label">Тип</div><div class="pstat-val" id="titrbar-v4" style="color:#FFD166"></div></div>
</div>
</div>
<!-- ── PROBABILITY sim body ── -->
<div id="sim-probability" class="sim-proj-wrap" style="display:none">
<div class="sim-body-wrap">
<div class="proj-panel" style="width:220px;gap:0">
<div class="gp-section-title" style="margin-bottom:8px">Режим</div>
<div style="display:flex;flex-wrap:wrap;gap:4px;margin-bottom:10px">
<button class="preset-btn prob-mode-btn active" onclick="probMode('coin',this)">Монета</button>
<button class="preset-btn prob-mode-btn" onclick="probMode('dice',this)">Кубик</button>
<button class="preset-btn prob-mode-btn" onclick="probMode('dice2',this)">2 кубика</button>
</div>
<div class="gp-section-title" style="margin-bottom:6px">Пресеты</div>
<div style="display:flex;flex-wrap:wrap;gap:4px;margin-bottom:8px">
<button class="preset-btn" onclick="probPreset('coin',100)">100 бросков</button>
<button class="preset-btn" onclick="probPreset('coin',1000)">1000</button>
<button class="preset-btn" onclick="probPreset('dice',100)">Кубик ×100</button>
<button class="preset-btn" onclick="probPreset('dice2',500)">2 куб. ×500</button>
</div>
<div class="pp-hint">Нажми <svg class="ic" viewBox="0 0 24 24"><polygon points="5 3 19 12 5 21 5 3"/></svg> — броски идут автоматически</div>
</div>
<div class="proj-canvas-outer">
<canvas id="probability-canvas"></canvas>
</div>
</div>
<div class="proj-stats-bar" id="probbar">
<div class="pstat"><div class="pstat-label">Бросков</div><div class="pstat-val" id="probbar-v1" style="color:var(--violet)">0</div></div>
<div class="pstat"><div class="pstat-label">Макс. отклон.</div><div class="pstat-val" id="probbar-v2" style="color:#EF476F"></div></div>
<div class="pstat"><div class="pstat-label">χ²</div><div class="pstat-val" id="probbar-v3" style="color:var(--cyan)"></div></div>
<div class="pstat"><div class="pstat-label">Режим</div><div class="pstat-val" id="probbar-v4" style="color:#FFD166">Монета</div></div>
</div>
</div>
<!-- ── BOHR ATOM sim body ── -->
<div id="sim-bohratom" class="sim-proj-wrap" style="display:none">
<div class="sim-body-wrap">
<div class="proj-panel" style="width:220px;gap:0">
<div class="gp-section-title" style="margin-bottom:8px">Уровень</div>
<div style="display:flex;flex-wrap:wrap;gap:4px;margin-bottom:10px">
<button class="preset-btn" onclick="bohrLevel(1)">n=1</button>
<button class="preset-btn" onclick="bohrLevel(2)">n=2</button>
<button class="preset-btn" onclick="bohrLevel(3)">n=3</button>
<button class="preset-btn" onclick="bohrLevel(4)">n=4</button>
<button class="preset-btn" onclick="bohrLevel(5)">n=5</button>
<button class="preset-btn" onclick="bohrLevel(6)">n=6</button>
</div>
<div class="gp-section-title" style="margin-bottom:6px">Переходы</div>
<div style="display:flex;flex-wrap:wrap;gap:4px;margin-bottom:8px">
<button class="preset-btn" onclick="bohrTransition(2,1)">2<svg class="ic" viewBox="0 0 24 24"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg>1 (УФ)</button>
<button class="preset-btn" onclick="bohrTransition(3,2)">3<svg class="ic" viewBox="0 0 24 24"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg>2 (красн.)</button>
<button class="preset-btn" onclick="bohrTransition(4,2)">4<svg class="ic" viewBox="0 0 24 24"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg>2 (голуб.)</button>
<button class="preset-btn" onclick="bohrTransition(4,3)">4<svg class="ic" viewBox="0 0 24 24"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg>3 (ИК)</button>
<button class="preset-btn" onclick="bohrTransition(1,3)">1<svg class="ic" viewBox="0 0 24 24"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg>3 (поглощ.)</button>
</div>
<div class="pp-hint">Кликни на уровень для перехода электрона</div>
</div>
<div class="proj-canvas-outer">
<canvas id="bohratom-canvas"></canvas>
</div>
</div>
<div class="proj-stats-bar" id="bohrbar">
<div class="pstat"><div class="pstat-label">Уровень n</div><div class="pstat-val" id="bohrbar-v1" style="color:var(--violet)">1</div></div>
<div class="pstat"><div class="pstat-label">E (эВ)</div><div class="pstat-val" id="bohrbar-v2" style="color:var(--cyan)">-13.6</div></div>
<div class="pstat"><div class="pstat-label">λ (нм)</div><div class="pstat-val" id="bohrbar-v3" style="color:#FFD166"></div></div>
<div class="pstat"><div class="pstat-label">Серия</div><div class="pstat-val" id="bohrbar-v4" style="color:#EF476F"></div></div>
</div>
</div>
<!-- ── ELECTROLYSIS sim body ── -->
<div id="sim-electrolysis" class="sim-proj-wrap" style="display:none">
<div class="sim-body-wrap">
<div class="proj-panel elec-panel-modern" style="width:280px;gap:0;overflow-y:auto">
<!-- Квик-бар -->
<div class="elec-quick-bar">
<button class="mag-mode-btn" onclick="elecSim?.playing ? elecSim.pause() : elecSim?.play(); this.textContent=elecSim?.playing?'Пауза':'Старт'">Старт</button>
<button class="mag-mode-btn" onclick="elecSim?.reset(); document.querySelector('.elec-quick-bar .mag-mode-btn').textContent='Старт'">Сброс</button>
</div>
<!-- Напряжение — всегда видно -->
<div class="param-block" style="margin:8px 0 4px">
<div class="param-header">
<span class="param-name">U (В)</span>
<span class="param-val" id="elec-V-val" style="color:#FFD166;font-weight:700">6.0</span>
</div>
<input type="range" id="sl-elec-V" class="param-slider" min="1" max="12" step="0.5" value="6" oninput="elecParam('voltage',this.value)">
</div>
<!-- Электролиты -->
<details class="elec-acc" open>
<summary>Электролит</summary>
<div class="elec-acc-body">
<div style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:5px">
<button class="mag-mode-btn elec-type-btn active" onclick="elecPreset('nacl',this)">NaCl</button>
<button class="mag-mode-btn elec-type-btn" onclick="elecPreset('cuso4',this)">CuSO₄</button>
<button class="mag-mode-btn elec-type-btn" onclick="elecPreset('h2so4',this)">H₂SO₄</button>
<button class="mag-mode-btn elec-type-btn" onclick="elecPreset('ki',this)">KI</button>
<button class="mag-mode-btn elec-type-btn" onclick="elecPreset('znso4',this)">ZnSO₄</button>
<button class="mag-mode-btn elec-type-btn" onclick="elecPreset('agno3',this)">AgNO₃</button>
</div>
</div>
</details>
<!-- Скорость -->
<details class="elec-acc">
<summary>Скорость</summary>
<div class="elec-acc-body">
<div style="display:grid;grid-template-columns:1fr 1fr 1fr 1fr;gap:5px">
<button class="mag-mode-btn elec-speed-btn" onclick="elecSpeed(0.5,this)">&times;0.5</button>
<button class="mag-mode-btn elec-speed-btn active" onclick="elecSpeed(1,this)">&times;1</button>
<button class="mag-mode-btn elec-speed-btn" onclick="elecSpeed(2,this)">&times;2</button>
<button class="mag-mode-btn elec-speed-btn" onclick="elecSpeed(5,this)">&times;5</button>
</div>
</div>
</details>
<!-- Отображение -->
<details class="elec-acc">
<summary>Отображение</summary>
<div class="elec-acc-body">
<div class="dyn-checks">
<label>
<input type="checkbox" id="elec-chk-electrons" checked onchange="elecToggle('electrons',this.checked)">
Электроны в цепи
</label>
<label>
<input type="checkbox" id="elec-chk-ions" checked onchange="elecToggle('ions',this.checked)">
Ионы
</label>
<label>
<input type="checkbox" id="elec-chk-bubbles" checked onchange="elecToggle('bubbles',this.checked)">
Пузыри
</label>
<label>
<input type="checkbox" id="elec-chk-graphs" onchange="elecToggle('graphs',this.checked)">
Графики m(t) / V(t)
</label>
</div>
</div>
</details>
<!-- Уравнения -->
<details class="elec-acc" open>
<summary>Уравнения</summary>
<div class="elec-acc-body">
<div style="margin-bottom:5px">
<div style="font-size:.72rem;color:rgba(6,214,224,0.7);margin-bottom:3px">Катод ():</div>
<div id="elec-eq-cathode" style="font-size:.80rem;color:rgba(255,255,255,0.88);line-height:1.4">2H₂O + 2e⁻ → H₂ + 2OH⁻</div>
</div>
<div>
<div style="font-size:.72rem;color:rgba(239,71,111,0.7);margin-bottom:3px">Анод (+):</div>
<div id="elec-eq-anode" style="font-size:.80rem;color:rgba(255,255,255,0.88);line-height:1.4">2Cl⁻ 2e⁻ → Cl₂</div>
</div>
</div>
</details>
</div>
<div class="proj-canvas-outer">
<canvas id="electrolysis-canvas"></canvas>
</div>
</div>
<div class="proj-stats-bar" id="elecbar">
<div class="pstat"><div class="pstat-label">I (А)</div><div class="pstat-val" id="elecbar-v1" style="color:#FFD166"></div></div>
<div class="pstat"><div class="pstat-label">Масса</div><div class="pstat-val" id="elecbar-v2" style="color:var(--violet)"></div></div>
<div class="pstat"><div class="pstat-label">Газ (мл)</div><div class="pstat-val" id="elecbar-v3" style="color:var(--cyan)"></div></div>
<div class="pstat"><div class="pstat-label">Время</div><div class="pstat-val" id="elecbar-v4" style="color:#EF476F">0 с</div></div>
<div class="pstat"><div class="pstat-label">Q (Кл)</div><div class="pstat-val" id="elecbar-v5" style="color:#9B5DE5"></div></div>
<div class="pstat"><div class="pstat-label">e⁻ (шт)</div><div class="pstat-val" id="elecbar-v6" style="color:rgba(200,220,255,0.8)"></div></div>
</div>
</div>
<!-- ── RACE sim body ── -->
<div id="sim-race" class="sim-proj-wrap race-sim-host" style="display:none">
<div id="race-wrap" style="width:100%;height:100%;display:flex;flex-direction:column"></div>
</div>
<!-- ── WAVES sim body ── -->
<div id="sim-waves" class="sim-proj-wrap" style="display:none">
<div class="sim-body-wrap">
<div class="proj-panel" style="width:228px;gap:0;overflow-y:auto">
<!-- Mode selector -->
<div class="gp-section-title" style="margin-bottom:6px">Режим</div>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:4px;margin-bottom:12px">
<button class="wave-mode-btn active" onclick="wavesMode('transverse',this)">Поперечная</button>
<button class="wave-mode-btn" onclick="wavesMode('longitudinal',this)">Продольная</button>
<button class="wave-mode-btn" onclick="wavesMode('superposition',this)">Суперпозиция</button>
<button class="wave-mode-btn" onclick="wavesMode('standing',this)">Стоячая</button>
<button class="wave-mode-btn" onclick="wavesMode('doppler',this)">Доплер</button>
<button class="wave-mode-btn" onclick="wavesMode('beats',this)">Биения</button>
<button class="wave-mode-btn" onclick="wavesMode('spectrum',this)" style="grid-column:span 2">Спектр (ДПФ)</button>
</div>
<!-- Wave 1 -->
<div class="gp-section-title" style="margin-bottom:6px">Волна 1</div>
<div class="param-block">
<div class="param-header">
<span class="param-name">Амплитуда A₁</span>
<span class="param-val" id="waves-A1-val" style="color:var(--violet)">50</span>
</div>
<input type="range" id="sl-waves-A1" class="param-slider" min="10" max="90" step="2" value="50" oninput="wavesParam('A1',this.value)">
</div>
<div class="param-block">
<div class="param-header">
<span class="param-name">Частота f₁</span>
<span class="param-val" id="waves-f1-val" style="color:var(--violet)">1.0 Гц</span>
</div>
<input type="range" id="sl-waves-f1" class="param-slider" min="0.3" max="4" step="0.1" value="1.0" oninput="wavesParam('f1',this.value)">
</div>
<div class="param-block">
<div class="param-header">
<span class="param-name">Фаза φ₁</span>
<span class="param-val" id="waves-phi1-val" style="color:var(--violet)">0</span>
</div>
<input type="range" id="sl-waves-phi1" class="param-slider" min="0" max="6.28" step="0.1" value="0" oninput="wavesParam('phi1',this.value)">
</div>
<!-- Wave 2 (superposition only) -->
<div id="waves-w2-section" style="display:none">
<div class="gp-section-title" style="margin-top:4px;margin-bottom:6px">Волна 2</div>
<div class="param-block">
<div class="param-header">
<span class="param-name">Амплитуда A₂</span>
<span class="param-val" id="waves-A2-val" style="color:var(--cyan)">40</span>
</div>
<input type="range" id="sl-waves-A2" class="param-slider" min="10" max="90" step="2" value="40" oninput="wavesParam('A2',this.value)">
</div>
<div class="param-block">
<div class="param-header">
<span class="param-name">Частота f₂</span>
<span class="param-val" id="waves-f2-val" style="color:var(--cyan)">1.5 Гц</span>
</div>
<input type="range" id="sl-waves-f2" class="param-slider" min="0.3" max="4" step="0.1" value="1.5" oninput="wavesParam('f2',this.value)">
</div>
<div class="param-block">
<div class="param-header">
<span class="param-name">Фаза φ₂</span>
<span class="param-val" id="waves-phi2-val" style="color:var(--cyan)">0</span>
</div>
<input type="range" id="sl-waves-phi2" class="param-slider" min="0" max="6.28" step="0.1" value="0" oninput="wavesParam('phi2',this.value)">
</div>
<div class="pp-hint" style="margin-bottom:8px">φ₂=0: конструктивная · φ₂=π: деструктивная интерференция</div>
</div>
<!-- Standing wave harmonics -->
<div id="waves-n-section" style="display:none">
<div class="gp-section-title" style="margin-top:4px;margin-bottom:6px">Гармоника n</div>
<div style="display:flex;flex-wrap:wrap;gap:4px;margin-bottom:10px">
<button class="preset-btn wave-n-btn active" onclick="wavesN(1,this)">n=1</button>
<button class="preset-btn wave-n-btn" onclick="wavesN(2,this)">n=2</button>
<button class="preset-btn wave-n-btn" onclick="wavesN(3,this)">n=3</button>
<button class="preset-btn wave-n-btn" onclick="wavesN(4,this)">n=4</button>
<button class="preset-btn wave-n-btn" onclick="wavesN(5,this)">n=5</button>
</div>
</div>
<!-- Doppler controls -->
<div id="waves-doppler-section" style="display:none">
<div class="gp-section-title" style="margin-top:4px;margin-bottom:6px">Эффект Доплера</div>
<div class="param-block">
<div class="param-header">
<span class="param-name">Скорость источника v<sub>s</sub></span>
<span class="param-val" id="waves-dopVs-val" style="color:var(--gold)">0.35c</span>
</div>
<input type="range" id="sl-waves-dopVs" class="param-slider" min="0" max="1.8" step="0.05" value="0.35" oninput="wavesParam('dopVs',this.value)" style="accent-color:#FFD166">
</div>
<div class="param-block">
<div class="param-header">
<span class="param-name">Частота источника f₀</span>
<span class="param-val" id="waves-f1-dop-val" style="color:var(--violet)"></span>
</div>
<input type="range" id="sl-waves-f1-dop" class="param-slider" min="0.3" max="4" step="0.1" value="1.0" oninput="wavesParam('f1',this.value)">
</div>
<div class="pp-hint" style="margin-bottom:8px">S — источник (перетащи), O — наблюдатель (перетащи)</div>
</div>
<!-- Beats controls -->
<div id="waves-beats-section" style="display:none">
<div class="gp-section-title" style="margin-top:4px;margin-bottom:6px">Биения</div>
<div class="param-block">
<div class="param-header">
<span class="param-name">Частота f₁</span>
<span class="param-val" id="waves-beatsF1-val" style="color:var(--violet)">440 Гц</span>
</div>
<input type="range" id="sl-waves-beatsF1" class="param-slider" min="100" max="1000" step="1" value="440" oninput="wavesParam('beatsF1',this.value)">
</div>
<div class="param-block">
<div class="param-header">
<span class="param-name">Частота f₂</span>
<span class="param-val" id="waves-beatsF2-val" style="color:var(--cyan)">444 Гц</span>
</div>
<input type="range" id="sl-waves-beatsF2" class="param-slider" min="100" max="1000" step="1" value="444" oninput="wavesParam('beatsF2',this.value)">
</div>
<div class="pp-hint" style="margin-bottom:8px">f<sub>бие</sub> = |f₁ − f₂|, огибающая — золотая кривая</div>
</div>
<!-- Spectrum controls -->
<div id="waves-spectrum-section" style="display:none">
<div class="gp-section-title" style="margin-top:4px;margin-bottom:6px">Спектр (ДПФ)</div>
<div class="param-block">
<div class="param-header">
<span class="param-name">Гармоника для добавления</span>
<span class="param-val" id="waves-specNewF-val" style="color:var(--pink)">5 Гц</span>
</div>
<input type="range" id="sl-waves-specNewF" class="param-slider" min="1" max="50" step="1" value="5" oninput="wavesParam('specNewF',this.value)" style="accent-color:var(--pink)">
</div>
<div style="display:flex;gap:6px;margin-bottom:8px">
<button class="preset-btn" onclick="wavesSpecAdd()" style="flex:1">Добавить гармонику</button>
<button class="preset-btn" onclick="wavesSpecClear()" style="flex:1;color:var(--pink)">Очистить</button>
</div>
<div class="pp-hint" style="margin-bottom:8px">ДПФ N=256, fs=100 Гц. Пики подписаны в Гц.</div>
</div>
<!-- Presets -->
<div class="gp-section-title" style="margin-top:4px;margin-bottom:6px">Пресеты</div>
<div style="display:flex;flex-wrap:wrap;gap:4px;margin-bottom:10px">
<button class="preset-btn" onclick="wavesPreset('constructive')">Конструктивная</button>
<button class="preset-btn" onclick="wavesPreset('destructive')">Деструктивная</button>
<button class="preset-btn" onclick="wavesPreset('beats')">Биения</button>
</div>
<!-- Speed -->
<div class="param-block" style="margin-top:4px">
<div class="param-header">
<span class="param-name">Скорость анимации</span>
<span class="param-val" id="waves-speed-val" style="color:#FFD166">×2.0</span>
</div>
<input type="range" id="sl-waves-speed" class="param-slider" min="0.3" max="5" step="0.1" value="2.0" oninput="wavesParam('speed',this.value)" style="accent-color:#FFD166">
</div>
<div class="pp-hint" style="margin-top:10px">v = λ·f — основное волновое уравнение</div>
</div>
<div class="proj-canvas-outer">
<canvas id="waves-canvas"></canvas>
</div>
</div>
<div class="proj-stats-bar" id="wavesbar">
<div class="pstat"><div class="pstat-label">T (с)</div><div class="pstat-val" id="wavesbar-T" style="color:var(--violet)"></div></div>
<div class="pstat"><div class="pstat-label">λ (px)</div><div class="pstat-val" id="wavesbar-lam" style="color:var(--cyan)"></div></div>
<div class="pstat"><div class="pstat-label">v (px/с)</div><div class="pstat-val" id="wavesbar-v" style="color:#FFD166"></div></div>
<div class="pstat"><div class="pstat-label">f (Гц)</div><div class="pstat-val" id="wavesbar-f" style="color:var(--pink)"></div></div>
</div>
</div>
<!-- ── STEREO sim body ── -->
<div id="sim-stereo" class="sim-body-wrap" style="display:none">
<div class="stereo-panel">
<!-- ── Фигуры ── -->
<div class="gp-section-title" style="margin-bottom:6px">Многогранники</div>
<div class="stereo-fig-grid">
<button class="st-fig-btn stereo-fig-btn active" onclick="setStereoFigure('cube',this)" title="Куб">
<svg viewBox="0 0 24 24"><rect x="3" y="7" width="12" height="12"/><path d="M3 7l4-4h12v12l-4 4"/><path d="M15 3v12M3 19l4-4"/></svg>Куб
</button>
<button class="st-fig-btn stereo-fig-btn" onclick="setStereoFigure('parallelepiped',this)" title="Прямоугольный параллелепипед">
<svg viewBox="0 0 24 24"><rect x="2" y="8" width="13" height="11"/><path d="M2 8l4-5h13v11l-4 5"/><path d="M15 3v11M2 19l4-5"/></svg>Параллел.
</button>
<button class="st-fig-btn stereo-fig-btn" onclick="setStereoFigure('prism',this)" title="Правильная призма">
<svg viewBox="0 0 24 24"><polygon points="12,3 3,8 3,19 12,21 21,19 21,8"/><line x1="12" y1="3" x2="12" y2="21"/></svg>Призма
</button>
<button class="st-fig-btn stereo-fig-btn" onclick="setStereoFigure('pyramid',this)" title="Правильная пирамида">
<svg viewBox="0 0 24 24"><polygon points="12,2 22,20 2,20"/><line x1="12" y1="2" x2="12" y2="20"/></svg>Пирамида
</button>
<button class="st-fig-btn stereo-fig-btn" onclick="setStereoFigure('truncpyramid',this)" title="Усечённая пирамида">
<svg viewBox="0 0 24 24"><polygon points="6,6 18,6 22,20 2,20"/><line x1="9" y1="6" x2="4" y2="20"/><line x1="15" y1="6" x2="20" y2="20"/></svg>Усеч. пир.
</button>
<button class="st-fig-btn stereo-fig-btn" onclick="setStereoFigure('tetrahedron',this)" title="Правильный тетраэдр">
<svg viewBox="0 0 24 24"><polygon points="12,2 22,20 2,20"/><line x1="12" y1="2" x2="12" y2="20"/><line x1="2" y1="20" x2="12" y2="14"/><line x1="22" y1="20" x2="12" y2="14"/></svg>Тетраэдр
</button>
</div>
<div class="gp-section-title" style="margin-top:6px;margin-bottom:6px">Правильные многогранники</div>
<div class="stereo-fig-grid">
<button class="st-fig-btn stereo-fig-btn" onclick="setStereoFigure('octahedron',this)" title="Правильный октаэдр">
<svg viewBox="0 0 24 24"><polygon points="12,2 22,12 12,22 2,12"/><line x1="12" y1="2" x2="2" y2="12"/><line x1="12" y1="2" x2="22" y2="12"/><line x1="2" y1="12" x2="12" y2="22"/><line x1="22" y1="12" x2="12" y2="22"/></svg>Октаэдр
</button>
<button class="st-fig-btn stereo-fig-btn" onclick="setStereoFigure('icosahedron',this)" title="Правильный икосаэдр">
<svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><polygon points="12,3 20,8 18,17 6,17 4,8"/><line x1="12" y1="3" x2="12" y2="21"/></svg>Икосаэдр
</button>
<button class="st-fig-btn stereo-fig-btn st-fig-btn-wide" onclick="setStereoFigure('dodecahedron',this)" title="Правильный додекаэдр">
<svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="9" stroke-dasharray="4,2"/><polygon points="12,2 20,8 17,17 7,17 4,8"/></svg>Додекаэдр
</button>
</div>
<div class="gp-section-title" style="margin-top:6px;margin-bottom:6px">Тела вращения</div>
<div class="stereo-fig-grid">
<button class="st-fig-btn stereo-fig-btn" onclick="setStereoFigure('cylinder',this)" title="Цилиндр">
<svg viewBox="0 0 24 24"><ellipse cx="12" cy="5" rx="9" ry="3"/><ellipse cx="12" cy="19" rx="9" ry="3"/><line x1="3" y1="5" x2="3" y2="19"/><line x1="21" y1="5" x2="21" y2="19"/></svg>Цилиндр
</button>
<button class="st-fig-btn stereo-fig-btn" onclick="setStereoFigure('cone',this)" title="Конус">
<svg viewBox="0 0 24 24"><ellipse cx="12" cy="19" rx="9" ry="3"/><line x1="3" y1="19" x2="12" y2="4"/><line x1="21" y1="19" x2="12" y2="4"/></svg>Конус
</button>
<button class="st-fig-btn stereo-fig-btn" onclick="setStereoFigure('trunccone',this)" title="Усечённый конус">
<svg viewBox="0 0 24 24"><ellipse cx="12" cy="18" rx="9" ry="3"/><ellipse cx="12" cy="7" rx="5" ry="2"/><line x1="3" y1="18" x2="7" y2="7"/><line x1="21" y1="18" x2="17" y2="7"/></svg>Усеч. конус
</button>
<button class="st-fig-btn stereo-fig-btn" onclick="setStereoFigure('sphere',this)" title="Шар">
<svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><ellipse cx="12" cy="12" rx="9" ry="3"/></svg>Шар
</button>
</div>
<!-- ── Параметры ── -->
<div class="gp-section-title" style="margin-top:8px;margin-bottom:6px">Параметры</div>
<div id="stereo-params">
<div class="stereo-sl-row" id="sp-a-row">
<label>Сторона <b>a</b> <span id="sp-a-val">4</span></label>
<input type="range" id="sl-sp-a" min="1" max="10" step="0.5" value="4" oninput="stereoParamChange('a',this.value)">
</div>
<div class="stereo-sl-row" id="sp-b-row" style="display:none">
<label>Сторона <b>b</b> <span id="sp-b-val">3</span></label>
<input type="range" id="sl-sp-b" min="1" max="10" step="0.5" value="3" oninput="stereoParamChange('b',this.value)">
</div>
<div class="stereo-sl-row" id="sp-c-row" style="display:none">
<label>Сторона <b>c</b> <span id="sp-c-val">5</span></label>
<input type="range" id="sl-sp-c" min="1" max="10" step="0.5" value="5" oninput="stereoParamChange('c',this.value)">
</div>
<div class="stereo-sl-row" id="sp-h-row" style="display:none">
<label>Высота <b>h</b> <span id="sp-h-val">5</span></label>
<input type="range" id="sl-sp-h" min="1" max="12" step="0.5" value="5" oninput="stereoParamChange('h',this.value)">
</div>
<div class="stereo-sl-row" id="sp-r-row" style="display:none">
<label>Радиус <b>r</b> <span id="sp-r-val">2</span></label>
<input type="range" id="sl-sp-r" min="0.5" max="8" step="0.5" value="2" oninput="stereoParamChange('r',this.value)">
</div>
<div class="stereo-sl-row" id="sp-R-row" style="display:none">
<label>Радиус осн. <b>R</b> <span id="sp-R-val">3</span></label>
<input type="range" id="sl-sp-R" min="0.5" max="8" step="0.5" value="3" oninput="stereoParamChange('R',this.value)">
</div>
<div class="stereo-sl-row" id="sp-n-row" style="display:none">
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:4px">
<span style="font-size:0.72rem;color:var(--text-2)">Граней основания <b>n</b></span>
<div class="st-n-ctrl">
<button class="st-n-btn" onclick="stereoNChange(-1)"><svg viewBox="0 0 16 16" fill="none"><line x1="3" y1="8" x2="13" y2="8" stroke-width="2" stroke-linecap="round"/></svg></button>
<span class="st-n-val" id="sp-n-val">4</span>
<button class="st-n-btn" onclick="stereoNChange(+1)"><svg viewBox="0 0 16 16" fill="none"><line x1="8" y1="3" x2="8" y2="13" stroke-width="2" stroke-linecap="round"/><line x1="3" y1="8" x2="13" y2="8" stroke-width="2" stroke-linecap="round"/></svg></button>
</div>
</div>
</div>
</div>
<div class="stereo-sl-row" style="margin-top:2px">
<label>Прозрачность <span id="sp-opacity-val">0.3</span></label>
<input type="range" id="sl-sp-opacity" min="0" max="1" step="0.05" value="0.3" oninput="stereoOpacityChange(this.value)">
</div>
<!-- ── Отображение ── -->
<div class="gp-section-title" style="margin-top:8px;margin-bottom:4px">Отображение</div>
<div onclick="stereoToggleSt('edges',this.querySelector('.st-toggle'))" class="st-toggle-row">
<span class="st-toggle-label"><svg viewBox="0 0 24 24"><rect x="3" y="3" width="18" height="18"/></svg>Рёбра</span>
<div class="st-toggle on" id="stg-edges"></div>
</div>
<div onclick="stereoToggleSt('vertices',this.querySelector('.st-toggle'))" class="st-toggle-row">
<span class="st-toggle-label"><svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="4" fill="currentColor"/></svg>Вершины</span>
<div class="st-toggle on" id="stg-vertices"></div>
</div>
<div onclick="stereoToggleSt('labels',this.querySelector('.st-toggle'))" class="st-toggle-row">
<span class="st-toggle-label"><svg viewBox="0 0 24 24"><path d="M4 7h16M4 12h10M4 17h7"/></svg>Подписи</span>
<div class="st-toggle on" id="stg-labels"></div>
</div>
<div onclick="stereoToggleSt('axes',this.querySelector('.st-toggle'))" class="st-toggle-row">
<span class="st-toggle-label"><svg viewBox="0 0 24 24"><line x1="2" y1="12" x2="22" y2="12"/><line x1="12" y1="2" x2="12" y2="22"/></svg>Оси</span>
<div class="st-toggle on" id="stg-axes"></div>
</div>
<div onclick="stereoToggleSt('grid',this.querySelector('.st-toggle'))" class="st-toggle-row">
<span class="st-toggle-label"><svg viewBox="0 0 24 24"><rect x="3" y="3" width="18" height="18"/><line x1="3" y1="9" x2="21" y2="9"/><line x1="3" y1="15" x2="21" y2="15"/><line x1="9" y1="3" x2="9" y2="21"/><line x1="15" y1="3" x2="15" y2="21"/></svg>Сетка</span>
<div class="st-toggle on" id="stg-grid"></div>
</div>
<!-- ── Элементы фигуры ── -->
<div class="gp-section-title" style="margin-top:8px;margin-bottom:4px">Элементы</div>
<div onclick="stereoToggleElem('height',this.querySelector('.st-toggle'))" class="st-toggle-row">
<span class="st-toggle-label"><svg viewBox="0 0 24 24"><line x1="12" y1="3" x2="12" y2="21" stroke-dasharray="4,2"/><line x1="9" y1="21" x2="15" y2="21"/></svg>Высота</span>
<div class="st-toggle" id="stg-height"></div>
</div>
<div onclick="stereoToggleElem('apothem',this.querySelector('.st-toggle'))" class="st-toggle-row">
<span class="st-toggle-label"><svg viewBox="0 0 24 24"><line x1="12" y1="5" x2="12" y2="19"/><line x1="6" y1="19" x2="18" y2="19"/></svg>Апофема</span>
<div class="st-toggle" id="stg-apothem"></div>
</div>
<div onclick="stereoToggleElem('diagonals',this.querySelector('.st-toggle'))" class="st-toggle-row">
<span class="st-toggle-label"><svg viewBox="0 0 24 24"><rect x="3" y="3" width="18" height="18"/><line x1="3" y1="3" x2="21" y2="21" stroke-dasharray="4,2"/><line x1="21" y1="3" x2="3" y2="21" stroke-dasharray="4,2"/></svg>Диагонали</span>
<div class="st-toggle" id="stg-diagonals"></div>
</div>
<div onclick="stereoToggleElem('midpoints',this.querySelector('.st-toggle'))" class="st-toggle-row">
<span class="st-toggle-label"><svg viewBox="0 0 24 24"><line x1="3" y1="12" x2="21" y2="12"/><circle cx="12" cy="12" r="3" fill="currentColor"/></svg>Середины рёбер</span>
<div class="st-toggle" id="stg-midpoints"></div>
</div>
<div onclick="stereoToggleElem('inscribed',this.querySelector('.st-toggle'))" class="st-toggle-row">
<span class="st-toggle-label"><svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="5" stroke-dasharray="3,2"/><rect x="3" y="3" width="18" height="18"/></svg>Вписанная сфера</span>
<div class="st-toggle" id="stg-inscribed"></div>
</div>
<div onclick="stereoToggleElem('circumscribed',this.querySelector('.st-toggle'))" class="st-toggle-row">
<span class="st-toggle-label"><svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="9" stroke-dasharray="4,2"/><polygon points="6,18 18,18 12,6"/></svg>Описанная сфера</span>
<div class="st-toggle" id="stg-circumscribed"></div>
</div>
<div onclick="stereoToggleElem('edgelengths',this.querySelector('.st-toggle'))" class="st-toggle-row">
<span class="st-toggle-label"><svg viewBox="0 0 24 24"><line x1="4" y1="12" x2="20" y2="12"/><line x1="4" y1="9" x2="4" y2="15"/><line x1="20" y1="9" x2="20" y2="15"/></svg>Длины рёбер</span>
<div class="st-toggle" id="stg-edgelengths"></div>
</div>
<div id="sect-area-display" style="font-size:0.7rem;color:var(--cyan);margin-top:2px;display:none"></div>
<div id="sphere-radius-info" style="font-size:0.7rem;color:#F59E0B;margin-top:2px;display:none"></div>
<!-- ── Сечение ── -->
<div class="gp-section-title" style="margin-top:8px;margin-bottom:6px">Сечение</div>
<div class="st-tool-grid" style="margin-bottom:4px">
<button class="st-tool-btn stereo-sect-btn st-tool-btn-wide" id="sect-toggle" onclick="stereoSectionToggle(this)">
<svg viewBox="0 0 24 24"><path d="M3 12h18M12 3v18" stroke-dasharray="4,2"/></svg>Показать сечение
</button>
<button class="st-tool-btn stereo-sect-type active" data-type="horizontal" onclick="stereoSectionType('horizontal',this)">
<svg viewBox="0 0 24 24"><line x1="3" y1="12" x2="21" y2="12"/></svg>Горизонт.
</button>
<button class="st-tool-btn stereo-sect-type" data-type="diagonal" onclick="stereoSectionType('diagonal',this)">
<svg viewBox="0 0 24 24"><line x1="4" y1="18" x2="20" y2="6"/></svg>Диагональ
</button>
<button class="st-tool-btn stereo-sect-type st-tool-btn-wide" data-type="custom" onclick="stereoSectionType('custom',this)">
<svg viewBox="0 0 24 24"><circle cx="5" cy="19" r="2" fill="currentColor"/><circle cx="12" cy="5" r="2" fill="currentColor"/><circle cx="19" cy="15" r="2" fill="currentColor"/><polyline points="5,19 12,5 19,15 5,19"/></svg>По 3+ точкам
</button>
</div>
<div class="stereo-sl-row">
<label>Высота <span id="sp-sect-val">50%</span></label>
<input type="range" id="sl-sp-sect" min="0" max="100" step="1" value="50" oninput="stereoSectionHeight(this.value)">
</div>
<div class="stereo-sl-row" id="sp-angle-row" style="display:none">
<label>Наклон <span id="sp-angle-val">50%</span></label>
<input type="range" id="sl-sp-angle" min="0" max="100" step="1" value="50" oninput="stereoSectionAngle(this.value)">
</div>
<!-- ── Инструменты ── -->
<div class="gp-section-title" style="margin-top:8px;margin-bottom:6px">Инструменты</div>
<div class="st-tool-grid">
<button class="st-tool-btn" id="stereo-point-btn" onclick="stereoPointMode(this)" title="Поставить точку на ребро">
<svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="4" fill="currentColor"/><line x1="3" y1="12" x2="21" y2="12"/></svg>Точка
</button>
<button class="st-tool-btn" id="stereo-connect-btn" onclick="stereoConnectMode(this)" title="Соединить две точки отрезком">
<svg viewBox="0 0 24 24"><circle cx="5" cy="19" r="2.5" fill="currentColor"/><circle cx="19" cy="5" r="2.5" fill="currentColor"/><line x1="5" y1="19" x2="19" y2="5" stroke-dasharray="4,2"/></svg>Соединить
</button>
<button class="st-tool-btn" id="stereo-measure-btn" onclick="stereoMeasure(this)" title="Измерить расстояние между двумя точками">
<svg viewBox="0 0 24 24"><line x1="4" y1="12" x2="20" y2="12"/><line x1="4" y1="9" x2="4" y2="15"/><line x1="20" y1="9" x2="20" y2="15"/></svg>Измерение
</button>
<button class="st-tool-btn" id="stereo-unfold-btn" onclick="stereoUnfold(this)" title="Развернуть в сетку">
<svg viewBox="0 0 24 24"><rect x="3" y="10" width="18" height="11"/><path d="M8 10V6a4 4 0 0 1 8 0v4"/></svg>Развёртка
</button>
</div>
<div class="st-action-grid" style="margin-top:3px">
<button class="st-action-btn" onclick="stereoUndoPoint()">Удалить точку</button>
<button class="st-action-btn" onclick="stereoClearPoints()">Очист. точки</button>
<button class="st-action-btn" onclick="stereoMeasureUndo()">Удалить изм.</button>
<button class="st-action-btn" onclick="stereoMeasureClear()">Очист. изм.</button>
</div>
<div id="points-info" style="font-size:0.65rem;color:rgba(255,255,255,0.4);margin-top:2px"></div>
<!-- ── Построения (прямые / плоскости) ── -->
<div class="gp-section-title" style="margin-top:8px;margin-bottom:6px">Построения</div>
<div class="st-tool-grid">
<button class="st-tool-btn" id="stereo-line-btn" onclick="stereoLineMode(this)" title="Прямая через 2 точки — кликните две вершины или точки">
<svg viewBox="0 0 24 24"><line x1="3" y1="21" x2="21" y2="3"/><circle cx="6" cy="18" r="2" fill="currentColor"/><circle cx="18" cy="6" r="2" fill="currentColor"/></svg>Прямая
</button>
<button class="st-tool-btn" id="stereo-plane-btn" onclick="stereoPlaneMode(this)" title="Плоскость через 3 точки — кликните три вершины или точки">
<svg viewBox="0 0 24 24"><polygon points="3,16 13,20 21,8 11,4" fill="none"/><circle cx="3" cy="16" r="1.8" fill="currentColor"/><circle cx="21" cy="8" r="1.8" fill="currentColor"/><circle cx="11" cy="4" r="1.8" fill="currentColor"/></svg>Плоскость
</button>
<button class="st-tool-btn st-tool-btn-wide" id="stereo-intersect-btn" onclick="stereoIntersectMode(this)" title="Пересечение: выберите 2 объекта в списке (прямая∩плоскость → точка, плоскость∩плоскость → прямая)">
<svg viewBox="0 0 24 24"><line x1="3" y1="7" x2="21" y2="17"/><line x1="3" y1="17" x2="21" y2="7"/><circle cx="12" cy="12" r="2.4" fill="currentColor"/></svg>Пересечение
</button>
</div>
<div class="st-tool-grid" style="margin-top:3px">
<button class="st-tool-btn" id="stereo-rel-lpar-btn" onclick="stereoRelMode('lpar',this)" title="Прямая, параллельная выбранной прямой, через точку">
<svg viewBox="0 0 24 24"><line x1="4" y1="8" x2="20" y2="6"/><line x1="4" y1="18" x2="20" y2="16"/></svg>∥ прямая
</button>
<button class="st-tool-btn" id="stereo-rel-lperp-btn" onclick="stereoRelMode('lperp',this)" title="Прямая, перпендикулярная выбранной плоскости, через точку">
<svg viewBox="0 0 24 24"><ellipse cx="12" cy="17" rx="9" ry="3" fill="none"/><line x1="12" y1="3" x2="12" y2="17"/><path d="M12 14 L15 14 L15 17" fill="none"/></svg>⟂ прямая
</button>
<button class="st-tool-btn" id="stereo-rel-ppar-btn" onclick="stereoRelMode('ppar',this)" title="Плоскость, параллельная выбранной плоскости, через точку">
<svg viewBox="0 0 24 24"><polygon points="3,11 12,14 21,6 12,3" fill="none"/><polygon points="3,18 12,21 21,13 12,10" fill="none"/></svg>∥ плоск.
</button>
<button class="st-tool-btn" id="stereo-rel-pperp-btn" onclick="stereoRelMode('pperp',this)" title="Плоскость, перпендикулярная выбранной прямой, через точку">
<svg viewBox="0 0 24 24"><polygon points="3,14 12,17 21,9 12,6" fill="none"/><line x1="12" y1="2" x2="12" y2="21"/></svg>⟂ плоск.
</button>
</div>
<div class="st-action-grid" style="margin-top:3px">
<button class="st-action-btn" onclick="stereoConstructHistUndo()" title="Отменить (Ctrl+Z)">Отменить</button>
<button class="st-action-btn" onclick="stereoConstructHistRedo()" title="Вернуть (Ctrl+Shift+Z)">Вернуть</button>
</div>
<div class="st-action-grid" style="margin-top:3px">
<button class="st-action-btn" onclick="stereoConstructUndo()">Удалить последнее</button>
<button class="st-action-btn" onclick="stereoConstructClear()">Очистить</button>
</div>
<div id="construct-hint" style="font-size:0.63rem;color:rgba(255,255,255,0.38);margin-top:3px;line-height:1.4"></div>
<div style="font-size:0.6rem;color:rgba(255,255,255,0.3);margin-top:2px;line-height:1.35">Клик по плоскости в списке — показать её сечением (заливка, площадь, периметр, натуральная величина).</div>
<div id="construct-list" style="font-size:0.7rem;margin-top:4px;line-height:1.6"></div>
<div id="construct-trueshape" style="display:none;margin-top:6px;background:rgba(6,214,224,0.05);border:1px solid rgba(6,214,224,0.18);border-radius:8px;padding:6px"></div>
<!-- ── Метки рёбер ── -->
<div class="gp-section-title" style="margin-top:8px;margin-bottom:6px">Метки рёбер</div>
<div class="st-tool-grid">
<button class="st-tool-btn" id="stereo-mark-tick-btn" onclick="stereoMarkMode('ticks',this)" title="Засечки равных рёбер — кликните ребро (до 3 штрихов)">
<svg viewBox="0 0 24 24"><line x1="5" y1="19" x2="19" y2="5"/><line x1="9" y1="9" x2="11" y2="11"/><line x1="13" y1="13" x2="15" y2="15"/></svg>Засечки =
</button>
<button class="st-tool-btn" id="stereo-mark-par-btn" onclick="stereoMarkMode('parallel',this)" title="Метки параллельных рёбер — кликните ребро">
<svg viewBox="0 0 24 24"><line x1="3" y1="8" x2="21" y2="8"/><line x1="3" y1="16" x2="21" y2="16"/><polyline points="15 5 18 8 15 11"/><polyline points="15 13 18 16 15 19"/></svg>Паралл. →
</button>
</div>
<div class="st-action-grid" style="margin-top:3px">
<button class="st-action-btn st-tool-btn-wide" onclick="stereoMarkClear()" style="grid-column:span 2">Очистить метки</button>
</div>
<!-- ── Производные точки ── -->
<div class="gp-section-title" style="margin-top:8px;margin-bottom:6px">Производные точки</div>
<div class="st-tool-grid">
<button class="st-tool-btn" id="stereo-derive-mid-btn" onclick="stereoDerive('midpoint',this)" title="Середина ребра — кликните ребро">
<svg viewBox="0 0 24 24"><line x1="3" y1="12" x2="21" y2="12"/><circle cx="12" cy="12" r="3.5" fill="currentColor"/></svg>Сер. ребра
</button>
<button class="st-tool-btn" id="stereo-derive-fc-btn" onclick="stereoDerive('face_centroid',this)" title="Центр грани — кликните грань">
<svg viewBox="0 0 24 24"><polygon points="12,3 21,21 3,21"/><circle cx="12" cy="15" r="2.5" fill="currentColor"/></svg>Центр грани
</button>
<button class="st-tool-btn" id="stereo-derive-alt-btn" onclick="stereoDerive('alt_foot',this)" title="Основание высоты: вершина → ребро">
<svg viewBox="0 0 24 24"><line x1="3" y1="20" x2="21" y2="20"/><line x1="10" y1="4" x2="10" y2="20" stroke-dasharray="4,2"/><path d="M10 20 L13 20 L13 17" fill="none"/></svg>Осн. высоты
</button>
<button class="st-tool-btn" id="stereo-derive-cen-btn" onclick="stereoDerive('solid_centroid',this)" title="Центроид тела — точка G">
<svg viewBox="0 0 24 24"><rect x="3" y="3" width="18" height="18"/><circle cx="12" cy="12" r="3" fill="currentColor"/><line x1="3" y1="3" x2="21" y2="21" stroke-dasharray="4,2" opacity=".4"/><line x1="21" y1="3" x2="3" y2="21" stroke-dasharray="4,2" opacity=".4"/></svg>Центроид G
</button>
</div>
<div class="st-action-grid" style="margin-top:3px">
<button class="st-action-btn" onclick="stereoDeriveUndo()">Удалить послед.</button>
<button class="st-action-btn" onclick="stereoDeriveClear()">Очистить</button>
</div>
<!-- ── Углы и расстояния ── -->
<div class="gp-section-title" style="margin-top:8px;margin-bottom:6px">Углы и расстояния</div>
<div class="st-tool-grid">
<button class="st-tool-btn" id="stereo-angle-edge-btn" onclick="stereoAngleMode('edge',this)" title="Угол между рёбрами: 3 точки A-B-C">
<svg viewBox="0 0 24 24"><line x1="12" y1="19" x2="4" y2="5"/><line x1="12" y1="19" x2="20" y2="6"/><path d="M7 16 Q12 13 17 15" fill="none" stroke-dasharray="3,2"/></svg>∠ рёбер
</button>
<button class="st-tool-btn" id="stereo-angle-lp-btn" onclick="stereoAngleMode('linePlane',this)" title="Угол прямой к плоскости: 2 точки → грань">
<svg viewBox="0 0 24 24"><line x1="4" y1="20" x2="20" y2="4"/><ellipse cx="12" cy="18" rx="9" ry="3" fill="none" opacity=".6"/></svg>∠ пр.–пл.
</button>
<button class="st-tool-btn" id="stereo-angle-dih-btn" onclick="stereoAngleMode('dihedral',this)" title="Двугранный угол: 2 точки общего ребра">
<svg viewBox="0 0 24 24"><line x1="12" y1="3" x2="12" y2="21"/><line x1="3" y1="12" x2="12" y2="21"/><line x1="21" y1="7" x2="12" y2="21"/></svg>∠ двугр.
</button>
<button class="st-tool-btn" id="stereo-angle-pp-btn" onclick="stereoAngleMode('pointPlane',this)" title="Расстояние точка–плоскость">
<svg viewBox="0 0 24 24"><ellipse cx="12" cy="18" rx="9" ry="3" fill="none"/><line x1="12" y1="5" x2="12" y2="18" stroke-dasharray="3,2"/><circle cx="12" cy="5" r="2.5" fill="currentColor"/></svg>d(т→пл)
</button>
<button class="st-tool-btn st-tool-btn-wide" id="stereo-angle-skew-btn" onclick="stereoAngleMode('skewLines',this)" title="Угол и расстояние скрещивающихся прямых: P1,P2→P3,P4">
<svg viewBox="0 0 24 24"><line x1="3" y1="6" x2="21" y2="12"/><line x1="3" y1="18" x2="21" y2="12" opacity=".5"/><circle cx="12" cy="9" r="2" fill="currentColor"/></svg>∠ скрещивающихся прямых
</button>
</div>
<div class="st-action-grid" style="margin-top:3px">
<button class="st-action-btn" style="grid-column:span 2" onclick="stereoAngleClear()">Очистить углы</button>
</div>
<div id="angle-hint" style="font-size:0.63rem;color:rgba(255,255,255,0.38);margin-top:3px;line-height:1.4"></div>
<!-- ── Сечение через 3 точки ── -->
<div class="gp-section-title" style="margin-top:8px;margin-bottom:6px">Сечение через 3 точки</div>
<div class="st-tool-grid" style="margin-bottom:4px">
<button class="st-tool-btn st-tool-btn-wide" id="stereo-sect3p-btn" onclick="stereoSection3P(this)" title="Выбрать 3 точки — построить сечение">
<svg viewBox="0 0 24 24"><circle cx="5" cy="19" r="2.5" fill="currentColor"/><circle cx="12" cy="4" r="2.5" fill="currentColor"/><circle cx="19" cy="14" r="2.5" fill="currentColor"/><polyline points="5,19 12,4 19,14 5,19" fill="none" stroke-dasharray="3,2"/></svg>Сечение через 3 точки
</button>
</div>
<div class="st-action-grid" style="margin-top:3px">
<button class="st-action-btn" onclick="stereoSection3PClear()" style="grid-column:span 2">Сбросить сечение</button>
</div>
<div id="sect3p-hint" style="font-size:0.63rem;color:rgba(255,255,255,0.38);margin-top:3px;line-height:1.4"></div>
<div id="sect3p-info" style="font-size:0.7rem;margin-top:4px;line-height:1.6"></div>
<div class="st-toggle-row" style="margin-top:4px" onclick="stereoSection3PStepBy(this.querySelector('.st-toggle'))">
<span class="st-toggle-label"><svg viewBox="0 0 24 24"><line x1="4" y1="12" x2="20" y2="12"/><polyline points="13 5 20 12 13 19"/></svg>Пошагово</span>
<div class="st-toggle" id="stg-sect3p-step"></div>
</div>
<div class="st-action-grid" style="margin-top:3px">
<button class="st-action-btn" onclick="stereoSection3PPrevStep()">Назад</button>
<button class="st-action-btn" onclick="stereoSection3PNextStep()">Вперёд</button>
</div>
<!-- ── Формулы ── -->
<div class="gp-section-title" style="margin-top:8px;margin-bottom:4px">Формулы</div>
<div id="stereo-formulas" style="font-size:0.72rem;color:rgba(255,255,255,0.7);line-height:1.5;margin-bottom:6px"></div>
</div>
<div class="graph-canvas-outer" style="position:relative">
<div class="graph-canvas-wrap" id="stereo-container"></div>
<!-- ── view controls overlay ── -->
<div class="st-view-toolbar">
<div class="st-view-group" role="group" aria-label="Ракурс">
<button class="st-view-preset active" onclick="stereoPreset('iso',this)" title="Изометрия">Изо</button>
<button class="st-view-preset" onclick="stereoPreset('front',this)" title="Вид спереди">Спер.</button>
<button class="st-view-preset" onclick="stereoPreset('side',this)" title="Вид сбоку">Сбоку</button>
<button class="st-view-preset" onclick="stereoPreset('top',this)" title="Вид сверху">Сверху</button>
</div>
<div class="st-view-group" role="group" aria-label="Действия с видом">
<button class="st-view-btn" onclick="stereoResetView()" title="Сбросить вид" aria-label="Сбросить вид">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12a9 9 0 1 0 3-6.7L3 8"/><path d="M3 3v5h5"/></svg>
</button>
<button class="st-view-btn active" id="st-spin-btn" onclick="stereoToggleSpin(this)" title="Авто-вращение" aria-label="Авто-вращение" aria-pressed="true">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-2.6-6.3"/><path d="M21 4v5h-5"/></svg>
</button>
<button class="st-view-btn" onclick="stereoFullscreen()" title="Во весь экран" aria-label="Во весь экран">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M8 3H5a2 2 0 0 0-2 2v3M21 8V5a2 2 0 0 0-2-2h-3M16 21h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3"/></svg>
</button>
<button class="st-view-btn" onclick="stereoScreenshot()" title="Снимок PNG" aria-label="Снимок PNG">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z"/><circle cx="12" cy="13" r="4"/></svg>
</button>
</div>
</div>
<!-- ── live section/measure readout ── -->
<div class="st-readout" id="stereo-readout" style="display:none" aria-live="polite"></div>
</div>
</div>
<!-- stats bar for stereo -->
<div class="proj-stats-bar" id="stereo-stats" style="display:none">
<div class="pstat"><div class="pstat-label">Объём</div><div class="pstat-val" id="stbar-vol"></div></div>
<div class="pstat"><div class="pstat-label">Полная S</div><div class="pstat-val" id="stbar-area"></div></div>
<div class="pstat"><div class="pstat-label">Бок. S</div><div class="pstat-val" id="stbar-side"></div></div>
<div class="pstat"><div class="pstat-label">Высота</div><div class="pstat-val" id="stbar-h"></div></div>
<div class="pstat"><div class="pstat-label">Диагональ</div><div class="pstat-val" id="stbar-d"></div></div>
</div>
<!-- ── HYDROSTATICS sim body ── -->
<div id="sim-hydro" class="sim-proj-wrap" style="display:none">
<div class="sim-body-wrap">
<!-- left panel -->
<div class="proj-panel" style="width:230px;gap:0;overflow-y:auto">
<div class="gp-section-title" style="margin-bottom:8px">Параметры</div>
<!-- liquid -->
<div style="margin-bottom:10px">
<div style="font-size:.72rem;color:rgba(255,255,255,.4);margin-bottom:4px">Жидкость</div>
<select onchange="hydroSim&&hydroSim.setLiquid(this.value);document.getElementById('hydro-liq-sel').value=this.value" style="width:100%;background:#1a1030;color:#f0e8ff;border:1px solid rgba(255,255,255,.12);border-radius:8px;padding:5px 8px;font-size:.78rem">
<option value="water">Вода (1000 кг/м³)</option>
<option value="saltwater">Солёная вода (1030)</option>
<option value="oil">Масло (900)</option>
<option value="alcohol">Спирт (790)</option>
<option value="glycerin">Глицерин (1260)</option>
<option value="mercury">Ртуть (13600)</option>
</select>
</div>
<!-- material (Archimedes only) -->
<div id="hydro-panel-mat" style="margin-bottom:10px;display:none">
<div style="font-size:.72rem;color:rgba(255,255,255,.4);margin-bottom:4px">Материал тела</div>
<select onchange="hydroSim&&hydroSim.setMaterial(this.value)" style="width:100%;background:#1a1030;color:#f0e8ff;border:1px solid rgba(255,255,255,.12);border-radius:8px;padding:5px 8px;font-size:.78rem">
<option value="styrofoam">Пенопласт (30 кг/м³)</option>
<option value="cork">Пробка (120)</option>
<option value="wood">Дерево (500)</option>
<option value="ice">Лёд (900)</option>
<option value="plastic">Пластик (1100)</option>
<option value="glass">Стекло (2500)</option>
<option value="aluminum">Алюминий (2700)</option>
<option value="iron">Железо (7800)</option>
<option value="gold">Золото (19300)</option>
</select>
<div style="display:flex;gap:5px;margin-top:6px">
<button class="gp-btn" onclick="hydroSim&&hydroSim.addBody()" style="flex:1">+ Тело</button>
<button class="gp-btn" onclick="hydroSim&&hydroSim.clearBodies()" style="flex:1">Очистить</button>
</div>
</div>
<!-- contact angle (surface tension) -->
<div id="hydro-panel-theta" style="margin-bottom:10px;display:none">
<div style="display:flex;justify-content:space-between;font-size:.72rem;color:rgba(255,255,255,.4);margin-bottom:4px">
<span>Краевой угол θ</span>
<span id="hydro-theta-lbl" style="color:var(--violet)">20°</span>
</div>
<input type="range" min="0" max="160" value="20" step="5" style="width:100%;accent-color:var(--violet)" oninput="hydroSim&&hydroSim.setContactAngle(+this.value);document.getElementById('hydro-theta-lbl').textContent=this.value+'\u00B0';document.getElementById('hydro-theta-val').textContent=this.value+'\u00B0';document.querySelector('#hydro-surf-ctrl input[type=range]').value=this.value">
<div style="display:flex;justify-content:space-between;font-size:.65rem;color:rgba(255,255,255,.25);margin-top:2px">
<span>Смачивание</span><span>Несмачивание</span>
</div>
<div style="margin-top:6px">
<button class="gp-btn" id="hydro-surf-toggle-panel" onclick="hydroToggleSurface()" style="width:100%">Капилляры</button>
</div>
</div>
<!-- communicating vessels -->
<div id="hydro-panel-comm" style="margin-bottom:10px;display:none">
<div style="font-size:.72rem;color:rgba(255,255,255,.4);margin-bottom:4px">Сосудов</div>
<div style="display:flex;gap:5px">
<button class="gp-btn hydro-nv active" onclick="hydroSetVessels(2,this)" style="flex:1">2</button>
<button class="gp-btn hydro-nv" onclick="hydroSetVessels(3,this)" style="flex:1">3</button>
<button class="gp-btn hydro-nv" onclick="hydroSetVessels(4,this)" style="flex:1">4</button>
</div>
<div style="margin-top:8px">
<button class="gp-btn" id="hydro-valve-panel-btn" onclick="hydroToggleValve()" style="width:100%;color:#06D6A0;border-color:rgba(6,214,160,.3)">Кран: открыт</button>
</div>
<div style="margin-top:6px;display:flex;gap:5px">
<button class="gp-btn" onclick="hydroSim&&hydroSim.addLiquid(0)" style="flex:1">+ Жидкость</button>
<button class="gp-btn" onclick="hydroSim&&hydroSim.removeLiquid()" style="flex:1">- Жидкость</button>
</div>
</div>
<!-- formula display -->
<div class="gp-section-title" style="margin-top:4px;margin-bottom:6px">Формулы</div>
<div id="hydro-formulas" style="font-size:.72rem;font-family:'JetBrains Mono',monospace;color:rgba(255,255,255,.6);line-height:1.7;background:rgba(255,255,255,.03);border-radius:8px;padding:8px 10px;min-height:80px"></div>
<!-- result badge -->
<div id="hydro-result" style="margin-top:8px;font-size:.82rem;font-weight:700;text-align:center;padding:8px;border-radius:8px;display:none"></div>
<!-- hydrostatics graphs toggle (Archimedes mode) -->
<div id="hydro-graphs-row" style="margin-top:8px;display:none">
<button id="btn-hydro-graphs" onclick="hydroToggleGraphs()" style="width:100%;font-size:.75rem;padding:5px;border-radius:8px;border:1px solid rgba(6,214,224,0.3);background:rgba(6,214,224,0.08);color:#06D6E0;cursor:pointer">&#1043;&#1088;&#1072;&#1092;&#1080;&#1082; &#1087;&#1086;&#1075;&#1088;&#1091;&#1078;&#1077;&#1085;&#1080;&#1103;</button>
</div>
</div><!-- /.proj-panel -->
<!-- canvas area -->
<div style="flex:1;min-width:0;position:relative" id="hydro-canvas-wrap">
<canvas id="hydro-canvas" style="width:100%;height:100%;display:block"></canvas>
</div>
</div><!-- /.sim-body-wrap -->
</div><!-- /#sim-hydro -->
<!-- ══════════════════════════════════════════════
РАДИОАКТИВНЫЙ РАСПАД
══════════════════════════════════════════════ -->
<div id="sim-radioactive" class="sim-proj-wrap" style="display:none">
<div class="sim-body-wrap">
<!-- left panel: controls -->
<div class="proj-panel" style="width:228px;gap:0;overflow-y:auto">
<div class="gp-section-title" style="margin-bottom:6px">Изотоп</div>
<select id="rd-isotope-sel" onchange="radioactiveIsotope(this.value)"
style="width:100%;background:#1a1a2e;color:#ccc;border:1px solid rgba(255,255,255,0.15);border-radius:6px;padding:5px 8px;font-size:.82rem;margin-bottom:10px;cursor:pointer">
<option value="C-14">¹⁴C — углерод (T½ = 5730 лет)</option>
<option value="I-131">¹³¹I — йод (T½ = 8.0 сут)</option>
<option value="Cs-137">¹³⁷Cs — цезий (T½ = 30.2 г)</option>
<option value="Ra-226">²²⁶Ra — радий → цепочка</option>
<option value="K-40">⁴⁰K — калий (T½ = 1.25·10⁹ г)</option>
<option value="U-238">²³⁸U → цепочка → ²⁰⁶Pb</option>
<option value="U-235">²³⁵U → цепочка → ²⁰⁷Pb</option>
</select>
<div class="gp-section-title" style="margin-bottom:6px">Начальное N₀</div>
<div class="param-block">
<div class="param-header">
<span class="param-name">Частиц</span>
<span class="param-val" id="rd-n0-val" style="color:var(--violet)">500</span>
</div>
<input type="range" id="sl-rd-n0" class="param-slider" min="50" max="2000" step="50" value="500"
oninput="radioactiveN0(this.value)">
</div>
<div class="gp-section-title" style="margin-top:4px;margin-bottom:6px">Скорость симуляции</div>
<div class="param-block">
<div class="param-header">
<span class="param-name">Масштаб</span>
<span class="param-val" id="rd-speed-val" style="color:var(--cyan)">×10</span>
</div>
<input type="range" id="sl-rd-speed" class="param-slider" min="1" max="1000" step="1" value="10"
oninput="radioactiveSpeed(this.value)">
</div>
<div style="display:flex;gap:6px;margin-top:8px;flex-wrap:wrap">
<button id="rd-play-btn" class="preset-btn" onclick="radioactivePlay()" style="flex:1;min-width:70px">Старт</button>
<button class="preset-btn" onclick="radioactiveReset()" style="flex:1;min-width:70px">Сброс</button>
</div>
<!-- Dating mode -->
<div style="margin-top:16px;border-top:1px solid rgba(255,255,255,0.08);padding-top:12px">
<div class="gp-section-title" style="margin-bottom:6px">Радиоуглеродное датирование</div>
<div class="param-block">
<div class="param-header">
<span class="param-name">Осталось ¹⁴C</span>
<span class="param-val" id="rd-dating-pct-val" style="color:#FFD166">50% осталось</span>
</div>
<input type="range" id="sl-rd-dating" class="param-slider" min="1" max="99" step="1" value="50"
oninput="radioactiveDating(this.value)">
</div>
<div id="rd-dating-result" style="font-size:.8rem;color:var(--cyan);text-align:center;margin-top:4px"></div>
<div class="pp-hint">Только для ¹⁴C — другие изотопы игнорируют</div>
</div>
</div><!-- /.proj-panel -->
<!-- particle canvas -->
<div class="proj-canvas-outer" style="flex:1;min-width:0">
<canvas id="radioactive-canvas"></canvas>
</div>
<!-- graph canvas -->
<div class="proj-canvas-outer" style="width:280px;flex-shrink:0">
<canvas id="radioactive-graph"></canvas>
</div>
</div><!-- /.sim-body-wrap -->
<!-- HUD bar -->
<div class="proj-stats-bar" id="rd-hud">
<div class="pstat">
<div class="pstat-label">Прошло периодов</div>
<div class="pstat-val" id="rd-hud-periods" style="color:var(--violet)">0 T½</div>
</div>
<div class="pstat">
<div class="pstat-label">Распалось</div>
<div class="pstat-val" id="rd-hud-decayed" style="color:#EF476F">0%</div>
</div>
<div class="pstat">
<div class="pstat-label">Активность</div>
<div class="pstat-val" id="rd-hud-activity" style="color:var(--cyan)">0 Бк</div>
</div>
</div>
</div><!-- /#sim-radioactive -->
<!-- ══════════════════════════════════════════════
ПЛАНИМЕТРИЯ
══════════════════════════════════════════════ -->
<div id="sim-geometry" class="sim-proj-wrap" style="display:none">
<div class="sim-body-wrap">
<!-- left panel -->
<div class="geo-panel geo-panel-modern">
<!-- Quick-access bar: most-used tools always visible -->
<div class="geo-quick-bar">
<button id="geo-btn-select" class="geo-tool-btn active" onclick="geoSetTool('select',this)" title="Выделить / переместить (Esc)">
<svg viewBox="0 0 24 24" fill="none"><path d="M5 3l14 9-7 1-4 7z" stroke-width="2"/></svg>
Выбор
</button>
<button id="geo-btn-point" class="geo-tool-btn" onclick="geoSetTool('point',this)" title="Поставить точку">
<svg viewBox="0 0 24 24" fill="none"><circle cx="12" cy="12" r="4" fill="currentColor"/></svg>
Точка
</button>
<button id="geo-btn-segment" class="geo-tool-btn" onclick="geoSetTool('segment',this)" title="Отрезок — 2 точки">
<svg viewBox="0 0 24 24" fill="none"><line x1="4" y1="20" x2="20" y2="4" stroke-width="2.5"/><circle cx="4" cy="20" r="2.5" fill="currentColor"/><circle cx="20" cy="4" r="2.5" fill="currentColor"/></svg>
Отрезок
</button>
<button id="geo-btn-circle" class="geo-tool-btn" onclick="geoSetTool('circle',this)" title="Окружность — центр + радиус">
<svg viewBox="0 0 24 24" fill="none"><circle cx="12" cy="12" r="8" stroke-width="2"/><circle cx="12" cy="12" r="2" fill="currentColor"/></svg>
Круг
</button>
</div>
<details class="geo-acc">
<summary>Линии</summary>
<div class="geo-acc-body geo-tool-grid">
<button id="geo-btn-line" class="geo-tool-btn" onclick="geoSetTool('line',this)" title="Прямая — 2 точки">
<svg viewBox="0 0 24 24" fill="none"><line x1="2" y1="22" x2="22" y2="2" stroke-width="2" stroke-dasharray="3,2"/></svg>
Прямая
</button>
<button id="geo-btn-ray" class="geo-tool-btn" onclick="geoSetTool('ray',this)" title="Луч — начало + направление">
<svg viewBox="0 0 24 24" fill="none"><line x1="4" y1="20" x2="22" y2="4" stroke-width="2"/><polyline points="17 4 22 4 22 9" stroke-width="2"/><circle cx="4" cy="20" r="2.5" fill="currentColor"/></svg>
Луч
</button>
</div>
</details>
<details class="geo-acc">
<summary>Фигуры</summary>
<div class="geo-acc-body">
<div class="geo-tool-grid">
<button id="geo-btn-triangle" class="geo-tool-btn" onclick="geoSetTool('triangle',this)" title="Треугольник — 3 точки">
<svg viewBox="0 0 24 24" fill="none"><polygon points="12,3 22,21 2,21" stroke-width="2"/></svg>
Треуг.
</button>
<button id="geo-btn-quad" class="geo-tool-btn" onclick="geoSetTool('quad',this)" title="Четырёхугольник — 4 точки">
<svg viewBox="0 0 24 24" fill="none"><polygon points="3,6 21,4 20,19 4,20" stroke-width="2"/></svg>
Четырёх.
</button>
<button id="geo-btn-polygon" class="geo-tool-btn geo-tool-wide" onclick="geoSetTool('polygon',this)" title="Многоугольник — N точек, Enter/двойной клик для завершения">
<svg viewBox="0 0 24 24" fill="none"><polygon points="12,2 22,8 19,21 5,21 2,8" stroke-width="2"/></svg>
Многоугольник
</button>
<button id="geo-btn-parallelogram" class="geo-tool-btn" onclick="geoSetTool('parallelogram',this)" title="Параллелограмм — 3 точки A, B, C → вычисляет D">
<svg viewBox="0 0 24 24" fill="none"><polygon points="6,19 3,5 18,5 21,19" stroke-width="1.5" fill="none"/></svg>
Парал-мм
</button>
<button id="geo-btn-ngon" class="geo-tool-btn" onclick="geoSetTool('ngon',this)" title="Правильный n-угольник — клик центр, клик вершина">
<svg viewBox="0 0 24 24" fill="none"><polygon points="12,3 20.2,8.5 17.3,18 6.7,18 3.8,8.5" stroke-width="1.5" fill="none"/></svg>
n-уг.
</button>
</div>
<div class="geo-ngon-ctrl" id="geo-ngon-ctrl" style="margin-top:6px">
<span style="font-size:11px;opacity:.7">N =</span>
<button class="geo-ngon-btn" onclick="geoNgonN(-1)">
<svg viewBox="0 0 16 16" fill="none"><line x1="3" y1="8" x2="13" y2="8" stroke-width="2" stroke-linecap="round"/></svg>
</button>
<span id="geo-ngon-n">6</span>
<button class="geo-ngon-btn" onclick="geoNgonN(+1)">
<svg viewBox="0 0 16 16" fill="none"><line x1="8" y1="3" x2="8" y2="13" stroke-width="2" stroke-linecap="round"/><line x1="3" y1="8" x2="13" y2="8" stroke-width="2" stroke-linecap="round"/></svg>
</button>
</div>
</div>
</details>
<details class="geo-acc">
<summary>Построения</summary>
<div class="geo-acc-body geo-tool-grid">
<button id="geo-btn-midpoint" class="geo-tool-btn" onclick="geoSetTool('midpoint',this)" title="Середина отрезка — 2 точки">
<svg viewBox="0 0 24 24" fill="none"><line x1="3" y1="12" x2="21" y2="12" stroke-width="2"/><circle cx="12" cy="12" r="3.5" fill="currentColor"/></svg>
Середина
</button>
<button id="geo-btn-intersect" class="geo-tool-btn" onclick="geoSetTool('intersect',this)" title="Точка пересечения — клик на две прямые">
<svg viewBox="0 0 24 24" fill="none"><line x1="4" y1="20" x2="20" y2="4" stroke-width="2"/><line x1="4" y1="4" x2="20" y2="20" stroke-width="2"/><circle cx="12" cy="12" r="3.5" fill="currentColor"/></svg>
Пересеч.
</button>
<button id="geo-btn-perpbisect" class="geo-tool-btn" onclick="geoSetTool('perpbisect',this)" title="Серединный перпендикуляр — 2 точки">
<svg viewBox="0 0 24 24" fill="none"><line x1="4" y1="18" x2="20" y2="6" stroke-width="2"/><line x1="12" y1="2" x2="12" y2="22" stroke-width="1.5" stroke-dasharray="3,2"/><circle cx="12" cy="12" r="2.5" fill="currentColor"/></svg>
⊥ биссект.
</button>
<button id="geo-btn-anglebisect" class="geo-tool-btn" onclick="geoSetTool('anglebisect',this)" title="Биссектриса угла — 3 точки: A, вершина, B">
<svg viewBox="0 0 24 24" fill="none"><polyline points="4,20 12,4 20,20" stroke-width="2"/><line x1="12" y1="4" x2="12" y2="20" stroke-width="1.5" stroke-dasharray="3,2"/></svg>
∠ биссект.
</button>
<button id="geo-btn-parallel" class="geo-tool-btn" onclick="geoSetTool('parallel',this)" title="Параллельная прямая — клик на линию, затем на точку">
<svg viewBox="0 0 24 24" fill="none"><line x1="3" y1="8" x2="21" y2="8" stroke-width="2"/><line x1="3" y1="16" x2="21" y2="16" stroke-width="2" opacity=".5" stroke-dasharray="4,3"/></svg>
∥ прямая
</button>
<button id="geo-btn-perpendicular" class="geo-tool-btn" onclick="geoSetTool('perpendicular',this)" title="Перпендикулярная прямая — клик на линию, затем на точку">
<svg viewBox="0 0 24 24" fill="none"><line x1="3" y1="12" x2="21" y2="12" stroke-width="2"/><line x1="12" y1="4" x2="12" y2="20" stroke-width="2" opacity=".5" stroke-dasharray="4,3"/></svg>
⊥ прямая
</button>
<button id="geo-btn-foot" class="geo-tool-btn" onclick="geoSetTool('foot',this)" title="Основание перпендикуляра — клик на прямую, затем на точку">
<svg viewBox="0 0 24 24" fill="none"><line x1="3" y1="18" x2="21" y2="18" stroke-width="2"/><line x1="12" y1="18" x2="12" y2="4" stroke-width="1.5" stroke-dasharray="3,2"/><path d="M12 18 L15 18 L15 15" stroke-width="1.5" fill="none"/><circle cx="12" cy="4" r="2.5" fill="currentColor"/></svg>
Основание
</button>
<button id="geo-btn-tangent" class="geo-tool-btn" onclick="geoSetTool('tangent',this)" title="Касательные из точки к окружности — клик на окружность, затем на точку">
<svg viewBox="0 0 24 24" fill="none"><circle cx="12" cy="12" r="7" stroke-width="1.5"/><line x1="4" y1="4" x2="19" y2="12" stroke-width="1.5" stroke-dasharray="4,3"/><line x1="4" y1="20" x2="19" y2="12" stroke-width="1.5" stroke-dasharray="4,3"/><circle cx="4" cy="12" r="2.5" fill="currentColor"/></svg>
Касат.
</button>
<button id="geo-btn-diagonal" class="geo-tool-btn" onclick="geoSetTool('diagonal',this)" title="Диагонали — клик внутри многоугольника (4+ вершин)">
<svg viewBox="0 0 24 24" fill="none"><rect x="3" y="3" width="18" height="18" stroke-width="1.5" fill="none"/><line x1="3" y1="3" x2="21" y2="21" stroke-width="1.5" stroke-dasharray="4,2"/><line x1="21" y1="3" x2="3" y2="21" stroke-width="1.5" stroke-dasharray="4,2"/></svg>
Диагонали
</button>
<button id="geo-btn-circumcircle" class="geo-tool-btn geo-tool-wide" onclick="geoSetTool('circumcircle',this)" title="Описанная окружность — 3 точки треугольника">
<svg viewBox="0 0 24 24" fill="none"><circle cx="12" cy="12" r="9" stroke-width="1.5" stroke-dasharray="4,3"/><polygon points="6,18 18,18 12,6" stroke-width="1.5" fill="none"/></svg>
Описанная
</button>
<button id="geo-btn-incircle" class="geo-tool-btn geo-tool-wide" onclick="geoSetTool('incircle',this)" title="Вписанная окружность — 3 точки треугольника">
<svg viewBox="0 0 24 24" fill="none"><polygon points="4,20 20,20 12,4" stroke-width="1.5" fill="none"/><circle cx="12" cy="15" r="5" stroke-width="1.5" stroke-dasharray="4,3"/></svg>
Вписанная
</button>
</div>
</details>
<details class="geo-acc">
<summary>Треугольник</summary>
<div class="geo-acc-body geo-tool-grid">
<button id="geo-btn-altitude" class="geo-tool-btn" onclick="geoSetTool('altitude',this)" title="Высота — клик на сторону, затем на вершину">
<svg viewBox="0 0 24 24" fill="none"><line x1="3" y1="20" x2="21" y2="20" stroke-width="1.5"/><line x1="10" y1="4" x2="10" y2="20" stroke-width="1.5" stroke-dasharray="4,3"/><rect x="10" y="14" width="4" height="4" stroke-width="1.2"/><polygon points="10,4 3,20 21,20" stroke-width="1.5" fill="none"/></svg>
Высота
</button>
<button id="geo-btn-median" class="geo-tool-btn" onclick="geoSetTool('median',this)" title="Медиана — клик вершина A, B, C">
<svg viewBox="0 0 24 24" fill="none"><polygon points="12,3 3,20 21,20" stroke-width="1.5" fill="none"/><line x1="12" y1="3" x2="12" y2="20" stroke-width="1.5"/><circle cx="12" cy="20" r="2.5" fill="currentColor"/></svg>
Медиана
</button>
<button id="geo-btn-centroid" class="geo-tool-btn" onclick="geoSetTool('centroid',this)" title="Центроид — 3 точки треугольника, строит 3 медианы">
<svg viewBox="0 0 24 24" fill="none"><polygon points="12,3 3,20 21,20" stroke-width="1.5" fill="none"/><line x1="12" y1="3" x2="12" y2="20" stroke-width="1.2" opacity=".6"/><line x1="3" y1="20" x2="16.5" y2="11.5" stroke-width="1.2" opacity=".6"/><line x1="21" y1="20" x2="7.5" y2="11.5" stroke-width="1.2" opacity=".6"/><circle cx="12" cy="14.3" r="2.5" fill="currentColor"/></svg>
Центроид
</button>
<button id="geo-btn-orthocenter" class="geo-tool-btn" onclick="geoSetTool('orthocenter',this)" title="Ортоцентр — 3 точки треугольника, строит 3 высоты">
<svg viewBox="0 0 24 24" fill="none"><polygon points="12,3 3,20 21,20" stroke-width="1.5" fill="none"/><line x1="12" y1="3" x2="12" y2="20" stroke-width="1.2" stroke-dasharray="3,2" opacity=".6"/><line x1="3" y1="20" x2="16" y2="12" stroke-width="1.2" stroke-dasharray="3,2" opacity=".6"/><line x1="21" y1="20" x2="8" y2="12" stroke-width="1.2" stroke-dasharray="3,2" opacity=".6"/><circle cx="12" cy="14" r="2.5" fill="currentColor"/></svg>
Ортоцентр
</button>
<button id="geo-btn-midline" class="geo-tool-btn geo-tool-wide" onclick="geoSetTool('midline',this)" title="Средняя линия треугольника — 3 вершины A, B, C">
<svg viewBox="0 0 24 24" fill="none"><polygon points="12,3 3,20 21,20" stroke-width="1.5" fill="none"/><line x1="7.5" y1="11.5" x2="16.5" y2="11.5" stroke-width="2"/><circle cx="7.5" cy="11.5" r="2" fill="currentColor"/><circle cx="16.5" cy="11.5" r="2" fill="currentColor"/></svg>
Средняя линия
</button>
<button id="geo-btn-thales" class="geo-tool-btn geo-tool-wide" onclick="geoSetTool('thales',this)" title="Теорема Фалеса — клик O, затем A, затем B → A&#39;B&#39; ∥ AB">
<svg viewBox="0 0 24 24" fill="none"><circle cx="4" cy="20" r="2" fill="currentColor"/><line x1="4" y1="20" x2="22" y2="4" stroke-width="1.5"/><line x1="4" y1="20" x2="22" y2="12" stroke-width="1.5"/><line x1="10" y1="15" x2="13" y2="12" stroke-width="2" stroke-dasharray="0"/><line x1="17" y1="9" x2="20" y2="7" stroke-width="2" opacity=".6"/></svg>
Фалес
</button>
</div>
</details>
<details class="geo-acc">
<summary>Преобразования</summary>
<div class="geo-acc-body">
<div class="geo-tool-grid">
<button id="geo-btn-reflect" class="geo-tool-btn" onclick="geoSetTool('reflect',this)" title="Симметрия точки относительно прямой — клик на ось, затем на точку">
<svg viewBox="0 0 24 24" fill="none"><line x1="12" y1="2" x2="12" y2="22" stroke-width="1.5" stroke-dasharray="3,2"/><circle cx="6" cy="12" r="3" stroke-width="1.5"/><circle cx="18" cy="12" r="2.5" stroke-width="1.5" opacity=".5"/><line x1="9" y1="12" x2="15" y2="12" stroke-width="1" opacity=".6"/></svg>
Симметрия
</button>
<button id="geo-btn-translate" class="geo-tool-btn" onclick="geoSetTool('translate',this)" title="Параллельный перенос — вектор AB, затем точка P">
<svg viewBox="0 0 24 24" fill="none"><circle cx="6" cy="18" r="2.5" stroke-width="1.5"/><circle cx="18" cy="6" r="2.5" stroke-width="1.5"/><line x1="6" y1="18" x2="18" y2="6" stroke-width="1.5" marker-end="url(#arrow)"/><circle cx="14" cy="18" r="2.5" stroke-width="1.5" opacity=".4"/><circle cx="21" cy="9" r="2" stroke-width="1.5" stroke-dasharray="3,2"/></svg>
Перенос
</button>
<button id="geo-btn-scale" class="geo-tool-btn geo-tool-wide" onclick="geoSetTool('scale',this)" title="Подобие (гомотетия) — клик центр O, затем клик точку P → P&#39; = O + k·(P O)">
<svg viewBox="0 0 24 24" fill="none"><circle cx="12" cy="12" r="2" fill="currentColor"/><line x1="12" y1="12" x2="20" y2="6" stroke-width="1.5"/><circle cx="20" cy="6" r="2.5" stroke-width="1.5"/><line x1="12" y1="12" x2="17" y2="18" stroke-width="1.5" stroke-dasharray="3,2"/><circle cx="17" cy="18" r="2.5" stroke-width="1.5" stroke-dasharray="3,2"/></svg>
Подобие
</button>
</div>
<div class="geo-ngon-ctrl" id="geo-scale-ctrl" style="margin-top:6px">
<span style="font-size:11px;opacity:.7">k =</span>
<button class="geo-ngon-btn" onclick="geoScaleK(-0.5)">
<svg viewBox="0 0 16 16" fill="none"><line x1="3" y1="8" x2="13" y2="8" stroke-width="2" stroke-linecap="round"/></svg>
</button>
<span id="geo-scale-k">2</span>
<button class="geo-ngon-btn" onclick="geoScaleK(+0.5)">
<svg viewBox="0 0 16 16" fill="none"><line x1="8" y1="3" x2="8" y2="13" stroke-width="2" stroke-linecap="round"/><line x1="3" y1="8" x2="13" y2="8" stroke-width="2" stroke-linecap="round"/></svg>
</button>
</div>
</div>
</details>
<details class="geo-acc">
<summary>Измерения и ГМТ</summary>
<div class="geo-acc-body geo-tool-grid">
<button id="geo-btn-measure_length" class="geo-tool-btn" onclick="geoSetTool('measure_length',this)" title="Длина отрезка — кликни на отрезок, получишь живой чип">
<svg viewBox="0 0 24 24" fill="none"><line x1="3" y1="12" x2="21" y2="12" stroke-width="2"/><line x1="3" y1="8" x2="3" y2="16" stroke-width="2" stroke-linecap="round"/><line x1="21" y1="8" x2="21" y2="16" stroke-width="2" stroke-linecap="round"/></svg>
Длина
</button>
<button id="geo-btn-measure_angle" class="geo-tool-btn" onclick="geoSetTool('measure_angle',this)" title="Угол — 3 клика: точка A, вершина, точка B">
<svg viewBox="0 0 24 24" fill="none"><path d="M3 20 L20 20" stroke-width="2" stroke-linecap="round"/><path d="M3 20 L14 6" stroke-width="2" stroke-linecap="round"/><path d="M7 20 A10 10 0 0 1 11.5 12" stroke-width="1.5" fill="none"/></svg>
Угол
</button>
<button id="geo-btn-measure_area" class="geo-tool-btn" onclick="geoSetTool('measure_area',this)" title="Площадь многоугольника — кликни на полигон">
<svg viewBox="0 0 24 24" fill="none"><polygon points="12,3 21,9 18,20 6,20 3,9" stroke-width="2" fill="none"/></svg>
Площадь
</button>
<button id="geo-btn-locus" class="geo-tool-btn" onclick="geoSetTool('locus',this)" title="ГМТ — выбери точку-мовер (on_segment/on_circle), затем целевую точку">
<svg viewBox="0 0 24 24" fill="none"><path d="M4 20 Q8 4 12 12 Q16 20 20 6" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/><circle cx="8" cy="14" r="2" fill="currentColor"/></svg>
ГМТ
</button>
<button id="geo-btn-point_on_segment" class="geo-tool-btn" onclick="geoSetTool('point_on_segment',this)" title="Точка на отрезке — кликни на отрезок, получишь скользящую точку">
<svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="3" y1="20" x2="21" y2="4"/><circle cx="12" cy="12" r="3" fill="currentColor" stroke="none"/></svg>
Т. на отрезке
</button>
<button id="geo-btn-point_on_circle" class="geo-tool-btn" onclick="geoSetTool('point_on_circle',this)" title="Точка на окружности — кликни на окружность, получишь скользящую точку">
<svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><circle cx="12" cy="3" r="2.5" fill="currentColor" stroke="none"/></svg>
Т. на круге
</button>
</div>
</details>
<details class="geo-acc">
<summary>Метки</summary>
<div class="geo-acc-body geo-tool-grid">
<button id="geo-btn-tick" class="geo-tool-btn" onclick="geoSetTool('tick',this)" title="Метки равных сторон — клик на отрезок или сторону (1–3 штриха)">
<svg viewBox="0 0 24 24" fill="none"><line x1="3" y1="20" x2="21" y2="4" stroke-width="1.5"/><line x1="11" y1="7" x2="8" y2="11" stroke-width="2" stroke-linecap="round"/><line x1="13" y1="9" x2="10" y2="13" stroke-width="2" stroke-linecap="round"/></svg>
Штрихи
</button>
<button id="geo-btn-arcmark" class="geo-tool-btn" onclick="geoSetTool('arcmark',this)" title="Метки равных углов — клик на вершину полигона (1–3 дуги)">
<svg viewBox="0 0 24 24" fill="none"><path d="M4 20 L20 20 L20 4" stroke-width="1.5" fill="none"/><path d="M8 20 A12 12 0 0 1 20 8" stroke-width="1.5" fill="none"/><path d="M11 20 A9 9 0 0 1 20 11" stroke-width="1.5" fill="none"/></svg>
Дуги
</button>
<button id="geo-btn-parallelmark" class="geo-tool-btn geo-tool-wide" onclick="geoSetTool('parallelmark',this)" title="Метки параллельных сторон — клик на отрезок (1–2 стрелки)">
<svg viewBox="0 0 24 24" fill="none"><line x1="3" y1="8" x2="21" y2="8" stroke-width="1.5"/><polyline points="9,5 13,8 9,11" stroke-width="1.8" fill="none" stroke-linecap="round" stroke-linejoin="round"/><line x1="3" y1="16" x2="21" y2="16" stroke-width="1.5"/><polyline points="9,13 13,16 9,19" stroke-width="1.8" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg>
Параллельность
</button>
</div>
</details>
<!-- Display options -->
<div class="gp-section-title" style="margin-top:6px">Параметры</div>
<label class="geo-toggle-row" onclick="geoToggle('showGrid',this)">
<span class="geo-toggle-label">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor"><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/></svg>
Сетка
</span>
<div class="geo-toggle on" id="geo-tog-showGrid"></div>
</label>
<label class="geo-toggle-row" onclick="geoToggle('showAxes',this)">
<span class="geo-toggle-label">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor"><line x1="12" y1="20" x2="12" y2="4"/><line x1="4" y1="12" x2="20" y2="12"/></svg>
Оси
</span>
<div class="geo-toggle on" id="geo-tog-showAxes"></div>
</label>
<label class="geo-toggle-row" onclick="geoToggle('showLabels',this)">
<span class="geo-toggle-label">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor"><path d="M12 20h9"/><path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z"/></svg>
Метки
</span>
<div class="geo-toggle on" id="geo-tog-showLabels"></div>
</label>
<label class="geo-toggle-row" onclick="geoToggle('showLengths',this)">
<span class="geo-toggle-label">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor"><line x1="4" y1="12" x2="20" y2="12"/><line x1="4" y1="8" x2="4" y2="16"/><line x1="20" y1="8" x2="20" y2="16"/></svg>
Длины
</span>
<div class="geo-toggle" id="geo-tog-showLengths"></div>
</label>
<label class="geo-toggle-row" onclick="geoToggle('showAngles',this)">
<span class="geo-toggle-label">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor"><path d="M3 20 L20 20 L20 4"/><path d="M7 20 A13 13 0 0 1 20 9"/></svg>
Углы
</span>
<div class="geo-toggle" id="geo-tog-showAngles"></div>
</label>
<!-- Stats -->
<div class="gp-section-title" style="margin-top:6px">Объектов</div>
<div style="display:flex;flex-direction:column;gap:0">
<div class="geo-stat-row"><span>Точки</span><b id="geo-st-pts">0</b></div>
<div class="geo-stat-row"><span>Отрезки</span><b id="geo-st-segs">0</b></div>
<div class="geo-stat-row"><span>Окружности</span><b id="geo-st-circs">0</b></div>
<div class="geo-stat-row"><span>Многоугольники</span><b id="geo-st-polys">0</b></div>
<div class="geo-stat-row"><span>Построения</span><b id="geo-st-constr">0</b></div>
</div>
<!-- Actions -->
<div style="margin-top:auto;padding-top:8px;display:flex;flex-direction:column;gap:4px">
<button class="gp-btn" onclick="geomSim&&geomSim.reset()" title="Очистить всё">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="3 6 5 6 21 6"/><path d="M19 6l-1 14H6L5 6"/></svg>
Очистить
</button>
<button class="geo-challenge-toggle" id="geo-chall-toggle-btn" onclick="geoToggleChallengePanel()" title="Открыть задачник">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 11l3 3L22 4"/><path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"/></svg>
Задачник
<span class="chall-count" id="geo-chall-count">0/5</span>
</button>
</div>
</div><!-- /.geo-panel -->
<!-- canvas area -->
<div class="geo-canvas-outer">
<canvas id="geo-canvas"></canvas>
<div class="geo-hint-bar" id="geo-hint">Кликни для добавления точки</div>
<div class="geo-del-confirm" id="geo-del-confirm">
<span id="geo-del-msg"></span>
<button class="geo-del-btn geo-del-btn-soft" id="geo-del-soft">Только этот</button>
<button class="geo-del-btn geo-del-btn-hard" id="geo-del-hard">Со всеми зависимыми</button>
<button class="geo-del-btn geo-del-btn-cancel" id="geo-del-cancel">Отмена</button>
</div>
<!-- Challenge panel (slides in from right) -->
<div class="geo-challenge-panel" id="geo-challenge-panel">
<div class="geo-chall-header">
<span class="geo-chall-header-title">Задачник</span>
<button class="geo-chall-close" onclick="geoToggleChallengePanel()">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
</button>
</div>
<div class="geo-chall-list" id="geo-chall-list">
<!-- Populated by JS -->
</div>
</div>
</div>
</div><!-- /.sim-body-wrap -->
</div><!-- /#sim-geometry -->
<!-- ── STOICHIOMETRY sim body ── -->
<div id="sim-stoichiometry" class="sim-proj-wrap" style="display:none">
<div id="stoichiometry-wrap" style="flex:1;min-height:0;overflow:hidden;"></div>
</div>
<!-- ── QUALANALYSIS sim body ── -->
<div id="sim-qualanalysis" class="sim-proj-wrap" style="display:none">
<div id="qualanalysis-wrap" style="flex:1;min-height:0;overflow:hidden;"></div>
</div>
<!-- ── ORGANIC CHEMISTRY sim body ── -->
<div id="sim-organic" class="sim-proj-wrap" style="display:none;flex:1;min-height:0;overflow:hidden;"></div>
<!-- ── HEAT ENGINE sim body ── -->
<div id="sim-heatengine" class="sim-proj-wrap" style="display:none">
<div class="sim-body-wrap" style="flex-direction:column">
<!-- top: two canvases side by side -->
<div style="display:flex;flex:1;min-height:0;gap:0">
<!-- left: PV diagram -->
<div class="proj-canvas-outer" style="flex:1">
<canvas id="he-pv-canvas"></canvas>
</div>
<!-- right: piston animation -->
<div class="proj-canvas-outer" style="width:220px;border-left:1px solid var(--border)">
<canvas id="he-piston-canvas"></canvas>
</div>
</div>
<!-- bottom: control panel -->
<div style="display:flex;gap:12px;padding:10px 14px;border-top:1px solid var(--border);flex-wrap:wrap;align-items:flex-start;background:rgba(255,255,255,0.015)">
<!-- cycle selector -->
<div style="display:flex;flex-direction:column;gap:4px;min-width:140px">
<div class="gp-section-title" style="margin-bottom:4px">Цикл</div>
<div style="display:flex;flex-wrap:wrap;gap:3px">
<button class="preset-btn he-cycle-btn active" onclick="heSetCycle('carnot',this)" style="font-size:.72rem">Карно</button>
<button class="preset-btn he-cycle-btn" onclick="heSetCycle('otto',this)" style="font-size:.72rem">Отто</button>
<button class="preset-btn he-cycle-btn" onclick="heSetCycle('diesel',this)" style="font-size:.72rem">Дизель</button>
<button class="preset-btn he-cycle-btn" onclick="heSetCycle('brayton',this)" style="font-size:.72rem">Брайтон</button>
</div>
</div>
<!-- sliders -->
<div style="display:flex;flex-direction:column;gap:6px;flex:1;min-width:180px">
<div class="gp-section-title" style="margin-bottom:2px">Параметры</div>
<div class="proj-slider-row">
<label style="font-size:.78rem;color:#ccc;width:90px">T<sub>гор</sub> = <span id="he-th-val" style="color:#EF476F;font-weight:700">800</span> K</label>
<input type="range" id="sl-he-th" min="300" max="1500" step="10" value="800" oninput="heParam('Th',this.value)" style="flex:1">
</div>
<div class="proj-slider-row">
<label style="font-size:.78rem;color:#ccc;width:90px">T<sub>хол</sub> = <span id="he-tc-val" style="color:#06D6E0;font-weight:700">300</span> K</label>
<input type="range" id="sl-he-tc" min="200" max="500" step="10" value="300" oninput="heParam('Tc',this.value)" style="flex:1">
</div>
<div class="proj-slider-row" id="he-cr-row" style="display:none">
<label style="font-size:.78rem;color:#ccc;width:90px">r<sub>сж</sub> = <span id="he-cr-val" style="color:#FFD166;font-weight:700">8</span></label>
<input type="range" id="sl-he-cr" min="2" max="20" step="1" value="8" oninput="heParam('cr',this.value)" style="flex:1">
</div>
</div>
<!-- buttons -->
<div style="display:flex;flex-direction:column;gap:5px;min-width:120px">
<div class="gp-section-title" style="margin-bottom:2px">Управление</div>
<div style="display:flex;gap:4px">
<button onclick="heStart()" style="flex:1;padding:6px 0;border-radius:7px;border:none;background:linear-gradient(135deg,#EF476F,#9B5DE5);color:#fff;font-size:.78rem;font-weight:700;cursor:pointer" title="Старт">
<svg class="ic" viewBox="0 0 24 24"><polygon points="5 3 19 12 5 21 5 3"/></svg>
</button>
<button onclick="hePause()" style="flex:1;padding:6px 0;border-radius:7px;border:1px solid #444;background:#1a1a2e;color:#ccc;font-size:.78rem;cursor:pointer" title="Пауза">
<svg class="ic" viewBox="0 0 24 24"><rect x="6" y="4" width="4" height="16"/><rect x="14" y="4" width="4" height="16"/></svg>
</button>
<button onclick="heStep()" style="flex:1;padding:6px 0;border-radius:7px;border:1px solid #444;background:#1a1a2e;color:#ccc;font-size:.78rem;cursor:pointer" title="Шаг">
<svg class="ic" viewBox="0 0 24 24"><polygon points="5 4 15 12 5 20 5 4"/><line x1="19" y1="5" x2="19" y2="19"/></svg>
</button>
<button onclick="heReset()" style="flex:1;padding:6px 0;border-radius:7px;border:1px solid #444;background:#1a1a2e;color:#888;font-size:.78rem;cursor:pointer" title="Сброс">
<svg class="ic" viewBox="0 0 24 24"><polyline points="1 4 1 10 7 10"/><path d="M3.51 15a9 9 0 1 0 .49-3.5"/></svg>
</button>
</div>
</div>
</div><!-- /controls -->
</div><!-- /.sim-body-wrap -->
<!-- stats bar -->
<div class="proj-stats-bar">
<div class="pstat"><div class="pstat-label">T<sub>гор</sub></div><div class="pstat-val" id="hebar-th" style="color:#EF476F">800 K</div></div>
<div class="pstat"><div class="pstat-label">T<sub>хол</sub></div><div class="pstat-val" id="hebar-tc" style="color:#06D6E0">300 K</div></div>
<div class="pstat"><div class="pstat-label">η</div><div class="pstat-val" id="hebar-eta" style="color:#7BF5A4">—%</div></div>
<div class="pstat"><div class="pstat-label">Q<sub>гор</sub>, Дж</div><div class="pstat-val" id="hebar-qh" style="color:#FFD166"></div></div>
<div class="pstat"><div class="pstat-label">Q<sub>хол</sub>, Дж</div><div class="pstat-val" id="hebar-qc" style="color:var(--cyan)"></div></div>
<div class="pstat"><div class="pstat-label">W, Дж</div><div class="pstat-val" id="hebar-w" style="color:var(--violet)"></div></div>
</div>
</div><!-- /#sim-heatengine -->
<!-- ── PERIODIC TABLE sim body ── -->
<div id="sim-periodic" class="sim-proj-wrap" style="display:none">
<div id="periodic-wrap" style="flex:1;min-height:0;overflow:hidden;"></div>
</div>
<!-- ── SOLUTIONS sim body ── -->
<div id="sim-solutions" class="sim-proj-wrap" style="display:none">
<div id="solutions-wrap" style="flex:1;min-height:0;overflow:hidden;"></div>
</div>