refactor(labs): переработка панели управления Планиметрии

Было: 13 секций подряд (включая дублирующийся заголовок 'Построения'), 35 кнопок одним сплошным длинным списком, ширина 210px, шрифт .73rem — приходилось много скроллить, инструменты сложно находить.

Стало:
- Ширина 210px → 260px
- Sticky quick-bar сверху с 4 самыми частыми: Выбор / Точка / Отрезок / Круг (фиолетовая подсветка, всегда видна)
- Все остальные инструменты — в 7 collapsible-секциях <details>:
  - Линии (Прямая, Луч)
  - Фигуры (Треугольник, Четырёхугольник, Многоугольник, Параллелограмм, n-угольник + control)
  - Построения (Середина, Пересечение, ⊥ биссектриса, ∠ биссектриса, ∥ прямая, ⊥ прямая, Основание, Касательные, Диагонали, Описанная, Вписанная) — теперь без дублирующегося заголовка
  - Треугольник (Высота, Медиана, Центроид, Ортоцентр, Средняя линия, Фалес)
  - Преобразования (Симметрия, Перенос, Подобие + k-control)
  - Измерения и ГМТ (Длина, Угол, Площадь, ГМТ, Т. на отрезке, Т. на круге)
  - Метки (Штрихи, Дуги, Параллельность)
- Шрифт .73rem → .78rem
- Параметры/Объектов/Очистить/Задачник остались внизу без сворачивания
This commit is contained in:
Maxim Dolgolyov
2026-05-26 18:55:49 +03:00
parent 970276915c
commit 1528d4e46e
2 changed files with 285 additions and 207 deletions
+80
View File
@@ -1945,6 +1945,86 @@ canvas[data-draggable]:active { cursor: grabbing; }
.ptbl-reaction-eq { font-size: .78rem; font-weight: 600; font-family: 'Courier New', monospace; }
.ptbl-reaction-note { font-size: .68rem; color: rgba(255,255,255,0.3); font-style: italic; margin-top: 4px; }
/* ═══════════════════════════════════════════════════════════
GEOMETRY PANEL — modern layout (collapsible)
═══════════════════════════════════════════════════════════ */
.geo-panel-modern {
width: 260px !important;
padding: 10px 10px !important;
gap: 6px !important;
}
.geo-panel-modern .geo-tool-btn {
font-size: .78rem;
padding: 6px 8px;
}
/* sticky quick-access bar */
.geo-quick-bar {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 4px;
padding: 6px;
margin-bottom: 8px;
background: rgba(155,93,229,0.08);
border: 1px solid rgba(155,93,229,0.25);
border-radius: 10px;
position: sticky;
top: 0;
z-index: 5;
}
.geo-quick-bar .geo-tool-btn {
padding: 6px 8px;
background: rgba(255,255,255,0.04);
border-color: rgba(255,255,255,0.12);
font-size: .78rem;
}
/* accordion */
.geo-acc {
border: 1px solid var(--border);
border-radius: 9px;
margin-bottom: 5px;
background: rgba(255,255,255,0.02);
overflow: hidden;
}
.geo-acc > summary {
cursor: pointer;
list-style: none;
padding: 7px 11px 7px 27px;
font-family: 'Unbounded', sans-serif;
font-size: .72rem;
font-weight: 700;
color: var(--text);
letter-spacing: .04em;
text-transform: uppercase;
position: relative;
user-select: none;
transition: background .15s;
}
.geo-acc > summary:hover { background: rgba(255,255,255,0.04); }
.geo-acc > summary::-webkit-details-marker { display: none; }
.geo-acc > summary::before {
content: '';
position: absolute;
left: 11px;
top: 50%;
width: 0;
height: 0;
border-left: 4.5px solid currentColor;
border-top: 3.5px solid transparent;
border-bottom: 3.5px solid transparent;
transform: translateY(-50%);
transition: transform .18s;
opacity: .6;
}
.geo-acc[open] > summary::before {
transform: translateY(-50%) rotate(90deg);
}
.geo-acc-body {
padding: 8px 10px 10px;
border-top: 1px solid var(--border);
}
/* ═══════════════════════════════════════════════════════════
DYNAMICS PANEL — modern layout
═══════════════════════════════════════════════════════════ */
+205 -207
View File
@@ -4252,11 +4252,10 @@
<div class="sim-body-wrap">
<!-- left panel -->
<div class="geo-panel">
<div class="geo-panel geo-panel-modern">
<!-- Tool: select + point -->
<div class="gp-section-title">Инструмент</div>
<div class="geo-tool-grid">
<!-- 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>
Выбор
@@ -4265,226 +4264,225 @@
<svg viewBox="0 0 24 24" fill="none"><circle cx="12" cy="12" r="4" fill="currentColor"/></svg>
Точка
</button>
</div>
<div class="gp-section-title" style="margin-top:4px">Построения</div>
<div class="geo-tool-grid">
<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-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>
<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>
<div class="gp-section-title" style="margin-top:4px">Фигуры</div>
<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>
</div>
<div class="gp-section-title" style="margin-top:4px">Построения</div>
<div class="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-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-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-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-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>
<div class="gp-section-title" style="margin-top:4px">Преобразования</div>
<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-tangent" class="geo-tool-btn geo-tool-wide" 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>
</div>
<div class="gp-section-title" style="margin-top:4px">Элементы треугольника</div>
<div class="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>
</div>
<div class="gp-section-title" style="margin-top:4px">Средняя линия и четырёхугольники</div>
<div class="geo-tool-grid">
<button id="geo-btn-midline" class="geo-tool-btn" 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-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-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-scale" class="geo-tool-btn" 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="gap:6px;padding:2px 0 4px">
<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 class="gp-section-title" style="margin-top:4px">Правильный многоугольник</div>
<div class="geo-tool-grid">
<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 class="geo-ngon-ctrl" id="geo-ngon-ctrl">
<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>
<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>
<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 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>
</div>
</details>
<!-- Thales theorem -->
<div class="gp-section-title" style="margin-top:4px">Теорема Фалеса</div>
<div class="geo-tool-grid">
<button id="geo-btn-thales" class="geo-tool-btn" 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 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>
<!-- Mark tools -->
<div class="gp-section-title" style="margin-top:4px">Метки</div>
<div class="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" 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 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>
<!-- Constrained points for locus -->
<div class="gp-section-title" style="margin-top:4px">Точки на объектах</div>
<div class="geo-tool-grid">
<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 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>
<!-- Measurement + Locus tools -->
<div class="gp-section-title" style="margin-top:4px">Измерения и ГМТ</div>
<div class="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>
</div>
<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>