// Auto-extracted from frontend/textbooks/physics_9.html (legacy monolith).
// Wrapped in IIFE — avoids collisions with chapter inline JS (STATE, PARAS, etc.).
// All upd*/draw*/init*/start*/lab*/check*/toggle* functions + TASKS_PN arrays
// are explicitly attached to window at the end.
// eslint-disable

(function(){
"use strict";

// ══════════════════════════════════════════════
//  ПУЛЫ ЗАДАЧ
// ══════════════════════════════════════════════

const TASKS_P31 = [
  {
    q: "Тело массой $m = 2\\,\\text{кг}$ движется со скоростью $v = 5\\,\\text{м/с}$. Найдите модуль импульса тела.",
    hint: "Используйте формулу $p = mv$.",
    unit: "кг·м/с", a: 10,
    ex: "$p = mv = 2\\,\\text{кг} \\cdot 5\\,\\text{м/с} = 10\\,\\text{кг}{\\cdot}\\text{м/с}$"
  },
  {
    q: "Мяч массой $m = 0{,}5\\,\\text{кг}$ движется со скоростью $v = 8\\,\\text{м/с}$. Найдите его импульс.",
    hint: "$p = mv$",
    unit: "кг·м/с", a: 4,
    ex: "$p = 0{,}5 \\cdot 8 = 4\\,\\text{кг}{\\cdot}\\text{м/с}$"
  },
  {
    q: "Человек массой $m = 70\\,\\text{кг}$ идёт со скоростью $v = 3\\,\\text{м/с}$. Найдите его импульс.",
    hint: "$p = mv$",
    unit: "кг·м/с", a: 210,
    ex: "$p = 70 \\cdot 3 = 210\\,\\text{кг}{\\cdot}\\text{м/с}$"
  },
  {
    q: "Тело массой $m = 4\\,\\text{кг}$ имеет импульс $p = 12\\,\\text{кг}{\\cdot}\\text{м/с}$. Найдите скорость тела.",
    hint: "Из $p = mv$ выразите $v = p/m$.",
    unit: "м/с", a: 3,
    ex: "$v = \\dfrac{p}{m} = \\dfrac{12}{4} = 3\\,\\text{м/с}$"
  },
  {
    q: "Тело движется со скоростью $v = 5\\,\\text{м/с}$ и имеет импульс $p = 20\\,\\text{кг}{\\cdot}\\text{м/с}$. Найдите массу тела.",
    hint: "$m = p/v$",
    unit: "кг", a: 4,
    ex: "$m = \\dfrac{p}{v} = \\dfrac{20}{5} = 4\\,\\text{кг}$"
  },
  {
    q: "На тело действует постоянная сила $F = 20\\,\\text{Н}$ в течение $\\Delta t = 3\\,\\text{с}$. Найдите изменение импульса тела.",
    hint: "$\\Delta p = F\\,\\Delta t$",
    unit: "кг·м/с", a: 60,
    ex: "$\\Delta p = F\\,\\Delta t = 20 \\cdot 3 = 60\\,\\text{кг}{\\cdot}\\text{м/с}$"
  },
  {
    q: "Пуля при выстреле испытывает силу $F = 500\\,\\text{Н}$ в течение $\\Delta t = 0{,}1\\,\\text{с}$. Найдите импульс силы.",
    hint: "Импульс силы = $F\\,\\Delta t$.",
    unit: "Н·с", a: 50,
    ex: "$F\\,\\Delta t = 500 \\cdot 0{,}1 = 50\\,\\text{Н}{\\cdot}\\text{с}$"
  },
  {
    q: "Импульс тела изменился на $\\Delta p = 200\\,\\text{кг}{\\cdot}\\text{м/с}$ за время $\\Delta t = 4\\,\\text{с}$. Найдите действующую силу.",
    hint: "$F = \\Delta p / \\Delta t$",
    unit: "Н", a: 50,
    ex: "$F = \\dfrac{\\Delta p}{\\Delta t} = \\dfrac{200}{4} = 50\\,\\text{Н}$"
  },
  {
    q: "Мяч массой $m = 0{,}2\\,\\text{кг}$ падает с высоты $h = 5\\,\\text{м}$ и упруго отскакивает от пола ($g = 10\\,\\text{м/с}^2$). Найдите модуль изменения импульса при ударе.",
    hint: "$v = \\sqrt{2gh}$; при упругом отскоке $|\\Delta p| = 2mv$.",
    unit: "кг·м/с", a: 4,
    ex: "$v = \\sqrt{2\\cdot10\\cdot5} = 10\\,\\text{м/с}$; $|\\Delta p| = 2 \\cdot 0{,}2 \\cdot 10 = 4\\,\\text{кг}{\\cdot}\\text{м/с}$"
  },
  {
    q: "Автомобиль массой $m = 800\\,\\text{кг}$ движется со скоростью $v = 10\\,\\text{м/с}$ и тормозит до остановки. Найдите модуль изменения импульса.",
    hint: "$|\\Delta p| = m|\\Delta v| = m \\cdot v$",
    unit: "кг·м/с", a: 8000,
    ex: "$|\\Delta p| = 800 \\cdot 10 = 8000\\,\\text{кг}{\\cdot}\\text{м/с}$"
  },
  {
    q: "Тело массой $m = 4\\,\\text{кг}$ разгоняется с $v_0 = 2\\,\\text{м/с}$ до $v_1 = 8\\,\\text{м/с}$ за $\\Delta t = 3\\,\\text{с}$. Найдите действующую силу.",
    hint: "$F = m\\,\\Delta v / \\Delta t$",
    unit: "Н", a: 8,
    ex: "$F = \\dfrac{m\\,\\Delta v}{\\Delta t} = \\dfrac{4 \\cdot 6}{3} = 8\\,\\text{Н}$"
  },
  {
    q: "Камень массой $m = 0{,}01\\,\\text{кг}$ летит со скоростью $v = 20\\,\\text{м/с}$ и застревает в стене (останавливается). Найдите модуль его изменения импульса.",
    hint: "$|\\Delta p| = mv - 0 = mv$",
    unit: "кг·м/с", a: 0.2,
    ex: "$|\\Delta p| = mv = 0{,}01 \\cdot 20 = 0{,}2\\,\\text{кг}{\\cdot}\\text{м/с}$"
  },
];

const TASKS_P32 = [
  {
    q: "Тело массой $m_1 = 3\\,\\text{кг}$ движется со скоростью $v_1 = 4\\,\\text{м/с}$ и наталкивается на покоящееся тело массой $m_2 = 9\\,\\text{кг}$. Абсолютно неупругий удар. Найдите скорость тел после удара.",
    hint: "$m_1 v_1 = (m_1+m_2)v$",
    unit: "м/с", a: 1,
    ex: "$v = \\dfrac{m_1 v_1}{m_1+m_2} = \\dfrac{3 \\cdot 4}{12} = 1\\,\\text{м/с}$"
  },
  {
    q: "Тело массой $m_1 = 4\\,\\text{кг}$ ($v_1 = 6\\,\\text{м/с}$) ударяет по покоящемуся телу $m_2 = 2\\,\\text{кг}$. Абсолютно неупругий удар. Скорость после удара?",
    hint: "$m_1 v_1 = (m_1+m_2)v$",
    unit: "м/с", a: 4,
    ex: "$v = \\dfrac{4 \\cdot 6}{6} = 4\\,\\text{м/с}$"
  },
  {
    q: "Два одинаковых тела по $m = 5\\,\\text{кг}$ движутся навстречу с одинаковыми скоростями $v = 4\\,\\text{м/с}$. Абсолютно неупругий удар. Скорость после удара?",
    hint: "Векторы импульсов равны и противоположны.",
    unit: "м/с", a: 0,
    ex: "$m \\cdot v - m \\cdot v = 2m \\cdot v_{\\text{после}} \\Rightarrow v_{\\text{после}} = 0\\,\\text{м/с}$"
  },
  {
    q: "Тела массами $m_1 = 6\\,\\text{кг}$ ($v_1 = 3\\,\\text{м/с}$) и $m_2 = 4\\,\\text{кг}$ ($v_2 = 3\\,\\text{м/с}$ навстречу) сталкиваются абсолютно неупруго. Скорость после удара?",
    hint: "Оси: $v_1 > 0$, $v_2 < 0$. Применить ЗСИ.",
    unit: "м/с", a: 0.6,
    ex: "$v = \\dfrac{6\\cdot3 - 4\\cdot3}{6+4} = \\dfrac{18-12}{10} = 0{,}6\\,\\text{м/с}$"
  },
  {
    q: "Пушка массой $M = 200\\,\\text{кг}$ неподвижно стоит на платформе. Снаряд массой $m = 4\\,\\text{кг}$ вылетает со скоростью $v = 500\\,\\text{м/с}$. Найдите скорость отката пушки с платформой.",
    hint: "До выстрела система покоилась: $p = 0$. $0 = mv + Mv_1$.",
    unit: "м/с", a: 10,
    ex: "$v_1 = \\dfrac{mv}{M} = \\dfrac{4 \\cdot 500}{200} = 10\\,\\text{м/с}$"
  },
  {
    q: "Два конькобёжца стоят на льду неподвижно. Масса первого $m_1 = 50\\,\\text{кг}$, второго $m_2 = 30\\,\\text{кг}$. Они отталкиваются, и первый приобретает скорость $v_1 = 0{,}6\\,\\text{м/с}$. Найдите скорость второго.",
    hint: "$p_0 = 0$: $m_1 v_1 + m_2 v_2 = 0$.",
    unit: "м/с", a: 1,
    ex: "$v_2 = \\dfrac{m_1 v_1}{m_2} = \\dfrac{50 \\cdot 0{,}6}{30} = 1\\,\\text{м/с}$"
  },
  {
    q: "Лодка с мальчиком ($m_1{+}m_2 = 140\\,\\text{кг}$) движется со скоростью $v_0 = 1{,}5\\,\\text{м/с}$. Мальчик ($m_2 = 40\\,\\text{кг}$) прыгает вперёд (в направлении движения) со скоростью $v_2 = 2{,}0\\,\\text{м/с}$ (от берега). Найдите скорость лодки после прыжка.",
    hint: "$(m_1+m_2)v_0 = m_1 v_1 + m_2 v_2$, масса лодки $m_1=100\\,\\text{кг}$.",
    unit: "м/с", a: 1.3,
    ex: "$v_1 = \\dfrac{140\\cdot1{,}5 - 40\\cdot2{,}0}{100} = \\dfrac{210-80}{100} = 1{,}3\\,\\text{м/с}$"
  },
  {
    q: "Орудие с платформой ($M = 200\\,\\text{кг}$) неподвижно. Снаряд $m = 10\\,\\text{кг}$ вылетает со скоростью $v = 300\\,\\text{м/с}$. Найдите скорость отката орудия с платформой.",
    hint: "$0 = mv + Mv_1$",
    unit: "м/с", a: 15,
    ex: "$v_1 = \\dfrac{mv}{M} = \\dfrac{10\\cdot300}{200} = 15\\,\\text{м/с}$"
  },
  {
    q: "Ракета стартует с нуля. После сгорания топлива масса ракеты $m_1 = 75\\,\\text{кг}$, масса выброшенных газов $m_2 = 25\\,\\text{кг}$, скорость газов $v_2 = 300\\,\\text{м/с}$ (назад). Найдите скорость ракеты.",
    hint: "$p_0 = 0$: $m_1 v_1 = m_2 v_2$.",
    unit: "м/с", a: 100,
    ex: "$v_1 = \\dfrac{m_2 v_2}{m_1} = \\dfrac{25 \\cdot 300}{75} = 100\\,\\text{м/с}$"
  },
  {
    q: "Две тележки сталкиваются: $m_1 = 6\\,\\text{кг}$, $v_1 = 4\\,\\text{м/с}$; $m_2 = 2\\,\\text{кг}$, $v_2 = 2\\,\\text{м/с}$ (навстречу). Абсолютно неупругий удар. Скорость после удара?",
    hint: "Ось $Ox$ — вдоль $v_1$. ЗСИ в проекции.",
    unit: "м/с", a: 2.5,
    ex: "$v = \\dfrac{6\\cdot4 - 2\\cdot2}{6+2} = \\dfrac{24-4}{8} = 2{,}5\\,\\text{м/с}$"
  },
  {
    q: "Человек стоит на тележке. Суммарная масса системы $70\\,\\text{кг}$ (масса камня $10\\,\\text{кг}$ входит). Из покоя человек бросает камень со скоростью $v = 6\\,\\text{м/с}$. Найдите скорость тележки с человеком после броска.",
    hint: "$p_0=0$: $m_{\\text{кам}}v + m_{\\text{чел+тел}}v_1 = 0$.",
    unit: "м/с", a: 1,
    ex: "$v_1 = \\dfrac{10\\cdot6}{60} = 1\\,\\text{м/с}$ (в сторону, обратную броску)"
  },
  {
    q: "Вагон массой $m_1 = 20\\,\\text{т}$ движется со скоростью $v_1 = 0{,}3\\,\\text{м/с}$ и сцепляется с неподвижным вагоном $m_2 = 10\\,\\text{т}$. Найдите скорость вагонов после сцепки.",
    hint: "Абсолютно неупругий удар. $m_1 v_1 = (m_1+m_2)v$.",
    unit: "м/с", a: 0.2,
    ex: "$v = \\dfrac{20 \\cdot 0{,}3}{30} = 0{,}2\\,\\text{м/с}$"
  },
];

const TASKS_HARD = [
  // ── §31 ──────────────────────────────────────────
  {
    para: "§31",
    q: "Шайба массой $m = 0{,}2\\,\\text{кг}$ летит со скоростью $v_1 = 6\\,\\text{м/с}$ и ударяется о борт, отскакивая в обратном направлении со скоростью $v_2 = 4\\,\\text{м/с}$. Время удара $\\Delta t = 0{,}01\\,\\text{с}$. Найдите среднюю силу борта на шайбу.",
    hint: "$|\\Delta p| = m(v_1+v_2)$, затем $F = |\\Delta p|/\\Delta t$.",
    unit: "Н", a: 200,
    ex: "$F = \\dfrac{m(v_1+v_2)}{\\Delta t} = \\dfrac{0{,}2\\cdot10}{0{,}01} = 200\\,\\text{Н}$"
  },
  {
    para: "§31",
    q: "Автомобиль массой $m = 1200\\,\\text{кг}$ тормозит: скорость уменьшается с $v_0 = 20\\,\\text{м/с}$ до $v = 8\\,\\text{м/с}$ за $t = 6\\,\\text{с}$. Найдите силу торможения.",
    hint: "$F = m|\\Delta v|/\\Delta t$.",
    unit: "Н", a: 2400,
    ex: "$F = \\dfrac{m(v_0-v)}{t} = \\dfrac{1200\\cdot12}{6} = 2400\\,\\text{Н}$"
  },
  {
    para: "§31",
    q: "Молоток массой $m = 2\\,\\text{кг}$ ударяет по гвоздю со скоростью $v = 8\\,\\text{м/с}$ и останавливается за $\\Delta t = 0{,}004\\,\\text{с}$. Найдите среднюю силу удара.",
    hint: "$F = mv/\\Delta t$.",
    unit: "Н", a: 4000,
    ex: "$F = \\dfrac{mv}{\\Delta t} = \\dfrac{2\\cdot8}{0{,}004} = 4000\\,\\text{Н}$"
  },
  {
    para: "§31",
    q: "Мяч массой $m = 0{,}4\\,\\text{кг}$ падает с высоты $h_1 = 3{,}2\\,\\text{м}$ и отскакивает до высоты $h_2 = 0{,}8\\,\\text{м}$, $g = 10\\,\\text{м/с}^2$. Найдите модуль изменения импульса при ударе.",
    hint: "$v_1 = \\sqrt{2gh_1}$, $v_2 = \\sqrt{2gh_2}$; $|\\Delta p| = m(v_1+v_2)$.",
    unit: "кг·м/с", a: 4.8,
    ex: "$v_1=8\\,\\text{м/с}$; $v_2=4\\,\\text{м/с}$; $|\\Delta p|=0{,}4\\cdot12=4{,}8\\,\\text{кг}{\\cdot}\\text{м/с}$"
  },
  {
    para: "§31",
    q: "Тело массой $m = 5\\,\\text{кг}$ движется со скоростью $v_0 = 2\\,\\text{м/с}$. На него действует сила $F = 15\\,\\text{Н}$ в направлении движения в течение $t = 4\\,\\text{с}$. Найдите конечную скорость тела.",
    hint: "$\\Delta p = Ft$; $v = v_0 + Ft/m$.",
    unit: "м/с", a: 14,
    ex: "$v = 2 + \\dfrac{15\\cdot4}{5} = 2+12 = 14\\,\\text{м/с}$"
  },
  // ── §32 ──────────────────────────────────────────
  {
    para: "§32",
    q: "Пуля массой $m = 0{,}01\\,\\text{кг}$ летит со скоростью $v = 400\\,\\text{м/с}$ и застревает в деревянном брусе массой $M = 3{,}99\\,\\text{кг}$. Найдите скорость бруса с пулей после удара.",
    hint: "Абсолютно неупругий удар: $mv = (m+M)V$.",
    unit: "м/с", a: 1,
    ex: "$V = \\dfrac{mv}{m+M} = \\dfrac{0{,}01\\cdot400}{4{,}00} = 1\\,\\text{м/с}$"
  },
  {
    para: "§32",
    q: "Ружьё массой $M = 3\\,\\text{кг}$ выстреливает пулю массой $m = 0{,}02\\,\\text{кг}$ со скоростью $v = 600\\,\\text{м/с}$. Найдите скорость отдачи ружья.",
    hint: "До выстрела система покоилась: $0 = MV + mv$.",
    unit: "м/с", a: 4,
    ex: "$V = \\dfrac{mv}{M} = \\dfrac{0{,}02\\cdot600}{3} = 4\\,\\text{м/с}$"
  },
  {
    para: "§32",
    q: "Снаряд массой $m = 0{,}5\\,\\text{кг}$ покоится и разрывается на два осколка. Осколок $m_1 = 0{,}3\\,\\text{кг}$ летит вправо со скоростью $v_1 = 200\\,\\text{м/с}$. Найдите скорость второго осколка ($m_2 = 0{,}2\\,\\text{кг}$).",
    hint: "$p_0 = 0$: $m_1 v_1 + m_2 v_2 = 0$.",
    unit: "м/с", a: 300,
    ex: "$v_2 = \\dfrac{m_1 v_1}{m_2} = \\dfrac{0{,}3\\cdot200}{0{,}2} = 300\\,\\text{м/с}$ (влево)"
  },
  {
    para: "§32",
    q: "Вагон $m_1 = 20\\,\\text{т}$, $v_1 = 2\\,\\text{м/с}$ догоняет вагон $m_2 = 30\\,\\text{т}$, $v_2 = 1\\,\\text{м/с}$ (в том же направлении). После сцепки найдите скорость вагонов.",
    hint: "$m_1 v_1 + m_2 v_2 = (m_1+m_2)v$.",
    unit: "м/с", a: 1.4,
    ex: "$v = \\dfrac{20\\cdot2+30\\cdot1}{50} = \\dfrac{70}{50} = 1{,}4\\,\\text{м/с}$"
  },
  {
    para: "§32",
    q: "Лодка ($m_1 = 120\\,\\text{кг}$) с человеком ($m_2 = 60\\,\\text{кг}$) движется со скоростью $v_0 = 2\\,\\text{м/с}$. Человек прыгает вперёд со скоростью $v_2 = 4\\,\\text{м/с}$ относительно берега. Найдите скорость лодки после прыжка.",
    hint: "$(m_1+m_2)v_0 = m_1 v_1 + m_2 v_2$.",
    unit: "м/с", a: 1,
    ex: "$v_1 = \\dfrac{180\\cdot2 - 60\\cdot4}{120} = \\dfrac{120}{120} = 1\\,\\text{м/с}$"
  },
  {
    para: "§32",
    q: "Тележки сталкиваются: $m_1 = 5\\,\\text{кг}$, $v_1 = 4\\,\\text{м/с}$; $m_2 = 3\\,\\text{кг}$, $v_2 = 6\\,\\text{м/с}$ навстречу. Абсолютно неупругий удар. Найдите скорость после удара.",
    hint: "Ось — вдоль $v_1$. $m_1 v_1 - m_2 v_2 = (m_1+m_2)v$.",
    unit: "м/с", a: 0.25,
    ex: "$v = \\dfrac{5\\cdot4 - 3\\cdot6}{8} = \\dfrac{2}{8} = 0{,}25\\,\\text{м/с}$"
  },
  {
    para: "§32",
    q: "Два конькобёжца стоят неподвижно и отталкиваются. $m_1 = 60\\,\\text{кг}$, $m_2 = 40\\,\\text{кг}$. Второй приобрёл скорость $v_2 = 3\\,\\text{м/с}$. Найдите скорость первого.",
    hint: "$p_0 = 0$: $m_1 v_1 + m_2 v_2 = 0$.",
    unit: "м/с", a: 2,
    ex: "$v_1 = \\dfrac{m_2 v_2}{m_1} = \\dfrac{40\\cdot3}{60} = 2\\,\\text{м/с}$"
  },
  // ── §33 ──────────────────────────────────────────
  {
    para: "§33",
    q: "Шкаф массой $m = 100\\,\\text{кг}$ перемещают по полу на расстояние $l = 3{,}0\\,\\text{м}$. Коэффициент трения скольжения $\\mu = 0{,}20$, $g = 10\\,\\text{м/с}^2$. Найдите минимальную работу, необходимую для этого перемещения.",
    hint: "При минимальной работе тело движется равномерно: $F = F_{\\text{тр}} = \\mu mg$; $A = Fl$.",
    unit: "Дж", a: 600,
    ex: "$F = 0{,}20 \\cdot 100 \\cdot 10 = 200\\,\\text{Н}$; $A = 200 \\cdot 3 = 600\\,\\text{Дж}$"
  },
  {
    para: "§33",
    q: "Автомобиль массой $m = 2000\\,\\text{кг}$ равномерно поднимается в гору под углом $\\alpha = 30°$ ($\\sin 30° = 0{,}5$) со скоростью $v = 10\\,\\text{м/с}$, $g = 10\\,\\text{м/с}^2$. Найдите мощность двигателя (сопротивление не учитывать).",
    hint: "При равномерном движении $F = mg\\sin\\alpha$; $P = Fv$.",
    unit: "Вт", a: 100000,
    ex: "$F = 2000\\cdot10\\cdot0{,}5 = 10000\\,\\text{Н}$; $P = 10000\\cdot10 = 100000\\,\\text{Вт} = 100\\,\\text{кВт}$"
  },
  {
    para: "§33",
    q: "Кабину лифта массой $m = 400\\,\\text{кг}$ поднимают на высоту $h = 15\\,\\text{м}$ с ускорением $a = 0{,}60\\,\\text{м/с}^2$ вверх, $g = 10\\,\\text{м/с}^2$. Найдите работу силы натяжения троса.",
    hint: "Сила натяжения: $T = m(g+a)$; $A = Th$.",
    unit: "Дж", a: 63600,
    ex: "$T = 400\\cdot10{,}6 = 4240\\,\\text{Н}$; $A = 4240\\cdot15 = 63600\\,\\text{Дж}$"
  },
  // ── §34 ──────────────────────────────────────────
  {
    para: "§34",
    q: "Пружина жёсткостью $k = 200\\,\\text{Н/м}$ накоплена потенциальная энергия $E_\\text{п} = 0{,}25\\,\\text{Дж}$. Найдите деформацию пружины.",
    hint: "$E_\\text{п} = kx^2/2 \\Rightarrow x = \\sqrt{2E_\\text{п}/k}$",
    unit: "м", a: 0.05,
    ex: "$x = \\sqrt{2\\cdot0{,}25/200} = \\sqrt{0{,}0025} = 0{,}05\\,\\text{м}$"
  },
  {
    para: "§34",
    q: "Тело массой $m = 3\\,\\text{кг}$ опустилось с высоты $h_1 = 8\\,\\text{м}$ до $h_2 = 2\\,\\text{м}$, $g = 10\\,\\text{м/с}^2$. Найдите работу силы тяжести.",
    hint: "$A = mg(h_1 - h_2)$",
    unit: "Дж", a: 180,
    ex: "$A = 3\\cdot10\\cdot(8-2) = 3\\cdot10\\cdot6 = 180\\,\\text{Дж}$"
  },
  {
    para: "§34",
    q: "Два тела: $m_1 = 2\\,\\text{кг}$ на высоте $h_1 = 10\\,\\text{м}$ и $m_2 = 3\\,\\text{кг}$ на высоте $h_2 = 4\\,\\text{м}$, $g = 10\\,\\text{м/с}^2$. Найдите суммарную потенциальную энергию системы тел.",
    hint: "$E_\\text{п} = m_1 g h_1 + m_2 g h_2$",
    unit: "Дж", a: 320,
    ex: "$E_\\text{п} = 2\\cdot10\\cdot10 + 3\\cdot10\\cdot4 = 200+120 = 320\\,\\text{Дж}$"
  },
  // ── §35 ──────────────────────────────────────────
  {
    para: "§35",
    q: "Автомобиль массой $m = 1200\\,\\text{кг}$ разгоняется с нуля до $v = 20\\,\\text{м/с}$. Сила тяги $F = 6000\\,\\text{Н}$. Найдите расстояние разгона (пренебречь трением).",
    hint: "По теореме о $E_\\text{к}$: $A = \\Delta E_\\text{к} = mv^2/2$; $s = A/F$.",
    unit: "м", a: 40,
    ex: "$A = \\dfrac{1200 \\cdot 400}{2} = 240\\,000\\,\\text{Дж}$; $s = \\dfrac{240\\,000}{6000} = 40\\,\\text{м}$"
  },
  {
    para: "§35",
    q: "Тело массой $m = 2\\,\\text{кг}$ движется со скоростью $v_0 = 6\\,\\text{м/с}$. Сила трения $F_\\text{тр} = 4\\,\\text{Н}$ действует на пути $s = 5\\,\\text{м}$. Найдите скорость тела в конце пути.",
    hint: "$E_{\\text{к}2} = E_{\\text{к}1} + A_\\text{тр}$; $A_\\text{тр} = -F_\\text{тр} \\cdot s$.",
    unit: "м/с", a: 4,
    ex: "$E_{\\text{к}1} = 2\\cdot36/2 = 36\\,\\text{Дж}$; $A_\\text{тр} = -20\\,\\text{Дж}$; $E_{\\text{к}2} = 16\\,\\text{Дж}$; $v = \\sqrt{2\\cdot16/2} = 4\\,\\text{м/с}$"
  },
  {
    para: "§35",
    q: "Тело движется равномерно. Чему равна работа результирующей всех сил, действующих на него?",
    opts: [
      "$A = mv^2$",
      "$A = mv^2/2$",
      "$A = 0$, так как $\\Delta E_\\text{к} = 0$",
      "$A = mgh$"
    ],
    a: 2,
    ex: "Равномерное движение → $v = \\text{const}$ → $E_\\text{к} = \\text{const}$ → $\\Delta E_\\text{к} = 0$ → $A_\\text{рез} = 0$."
  },
  {
    para: "§35",
    q: "На тело массой $m = 8\\,\\text{кг}$ действуют: сила тяги $F_1 = 50\\,\\text{Н}$ и сила трения $F_2 = 10\\,\\text{Н}$ (противоположна движению). Тело прошло путь $s = 10\\,\\text{м}$ из состояния покоя. Найдите скорость тела.",
    hint: "$A_\\text{рез} = (F_1 - F_2)\\,s = \\Delta E_\\text{к}$; затем $v = \\sqrt{2E_\\text{к}/m}$.",
    unit: "м/с", a: 10,
    ex: "$A_\\text{рез} = (50-10)\\cdot10 = 400\\,\\text{Дж}$; $v = \\sqrt{\\dfrac{2\\cdot400}{8}} = \\sqrt{100} = 10\\,\\text{м/с}$"
  },
  {
    para: "§35",
    q: "Тело массой $m = 2\\,\\text{кг}$ тормозит с $v_0 = 15\\,\\text{м/с}$ до $v = 5\\,\\text{м/с}$ на пути $s = 20\\,\\text{м}$. Найдите силу торможения.",
    hint: "$A_\\text{тр} = \\Delta E_\\text{к} = mv^2/2 - mv_0^2/2$; $F = |A_\\text{тр}|/s$.",
    unit: "Н", a: 10,
    ex: "$\\Delta E_\\text{к} = \\dfrac{2\\cdot25}{2} - \\dfrac{2\\cdot225}{2} = 25 - 225 = -200\\,\\text{Дж}$; $F = 200/20 = 10\\,\\text{Н}$"
  },
  {
    para: "§35",
    q: "Шарик массой $m = 0{,}2\\,\\text{кг}$ бросают вертикально вверх с $v_0 = 10\\,\\text{м/с}$ с высоты $h_0 = 5\\,\\text{м}$ над землёй. $g = 10\\,\\text{м/с}^2$. Найдите механическую энергию шарика относительно земли в начальный момент.",
    hint: "$E_\\text{мех} = mv_0^2/2 + mgh_0$",
    unit: "Дж", a: 20,
    ex: "$E_\\text{мех} = \\dfrac{0{,}2\\cdot100}{2} + 0{,}2\\cdot10\\cdot5 = 10 + 10 = 20\\,\\text{Дж}$"
  },
  {
    para: "§35",
    q: "В какой точке траектории тела, брошенного без сопротивления воздуха, механическая энергия максимальна?",
    opts: [
      "В начальной точке броска",
      "В высшей точке траектории",
      "В конечной точке",
      "Механическая энергия одинакова во всех точках (без трения)"
    ],
    a: 3,
    ex: "Без трения воздуха работают только консервативные силы, поэтому $E_\\text{мех} = \\text{const}$ — одинакова в любой точке траектории."
  },
  // ── §36 ──────────────────────────────────────────
  {
    para: "§36",
    q: "Маятник отклонили так, что шарик поднялся на высоту $h = 0{,}45\\,\\text{м}$ над нижней точкой. $g = 10\\,\\text{м/с}^2$. Без трения. Найдите скорость шарика в нижней точке.",
    hint: "$mgh = mv^2/2 \\Rightarrow v = \\sqrt{2gh}$",
    unit: "м/с", a: 3,
    ex: "$v = \\sqrt{2 \\cdot 10 \\cdot 0{,}45} = \\sqrt{9} = 3\\,\\text{м/с}$"
  },
  {
    para: "§36",
    q: "Тело массой $m = 2\\,\\text{кг}$ брошено горизонтально с высоты $h = 8\\,\\text{м}$ со скоростью $v_0 = 6\\,\\text{м/с}$. $g = 10\\,\\text{м/с}^2$. Без трения. Найдите скорость тела у земли.",
    hint: "ЗСЭ: $mv_0^2/2 + mgh = mv^2/2 \\Rightarrow v^2 = v_0^2 + 2gh$",
    unit: "м/с", a: 14,
    ex: "$v^2 = 36 + 2\\cdot10\\cdot8 = 36 + 160 = 196 \\Rightarrow v = 14\\,\\text{м/с}$"
  },
  {
    para: "§36",
    q: "Пружину жёсткостью $k = 2000\\,\\text{Н/м}$ сжали на $x = 0{,}1\\,\\text{м}$. Отпустили шарик массой $m = 0{,}2\\,\\text{кг}$, который полетел вертикально вверх. $g = 10\\,\\text{м/с}^2$. Найдите максимальную высоту.",
    hint: "$E_\\text{п(пружина)} = kx^2/2 = mgh$",
    unit: "м", a: 5,
    ex: "$kx^2/2 = 2000 \\cdot 0{,}01/2 = 10\\,\\text{Дж}$; $h = \\dfrac{10}{0{,}2 \\cdot 10} = 5\\,\\text{м}$"
  },
  {
    para: "§36",
    q: "Пружину жёсткостью $k = 1000\\,\\text{Н/м}$ сжали на $x = 0{,}1\\,\\text{м}$ и отпустили тело массой $m = 1\\,\\text{кг}$ на горизонтальной поверхности. На участке трения совершена работа $A_\\text{тр} = -3\\,\\text{Дж}$. Найдите скорость тела после участка трения.",
    hint: "$E_\\text{п(пружина)} + A_\\text{тр} = mv^2/2$",
    unit: "м/с", a: 2,
    ex: "$E_\\text{п} = 1000\\cdot0{,}01/2 = 5\\,\\text{Дж}$; $E_\\text{к} = 5 - 3 = 2\\,\\text{Дж}$; $v = \\sqrt{2\\cdot2/1} = 2\\,\\text{м/с}$"
  },
  {
    para: "§36",
    q: "Велосипедист с велосипедом (масса $m = 80\\,\\text{кг}$) съезжает с горки высотой $h = 5\\,\\text{м}$. У основания скорость $v = 8\\,\\text{м/с}$. $g = 10\\,\\text{м/с}^2$. Найдите потери механической энергии на трение.",
    hint: "Потери $= E_{\\text{мех}1} - E_{\\text{мех}2} = mgh - mv^2/2$",
    unit: "Дж", a: 1440,
    ex: "$E_{\\text{мех}1} = 80\\cdot10\\cdot5 = 4000\\,\\text{Дж}$; $E_{\\text{мех}2} = 80\\cdot64/2 = 2560\\,\\text{Дж}$; потери $= 1440\\,\\text{Дж}$"
  },
  {
    para: "§36",
    q: "Тело бросают вертикально вверх с $v_0 = 10\\,\\text{м/с}$. Без трения, $g = 10\\,\\text{м/с}^2$. На какой высоте скорость тела равна $6\\,\\text{м/с}$?",
    hint: "ЗСЭ: $mv_0^2/2 = mv^2/2 + mgh \\Rightarrow h = (v_0^2 - v^2)/(2g)$",
    unit: "м", a: 3.2,
    ex: "$h = \\dfrac{100 - 36}{20} = \\dfrac{64}{20} = 3{,}2\\,\\text{м}$"
  },
  {
    para: "§36",
    q: "Мяч бросают вертикально вверх и ловят на той же высоте. Что можно утверждать о скоростях броска и поимки? (сопротивление воздуха не учитывать)",
    opts: [
      "Скорость при поимке больше — тело ускорялось при падении",
      "Скорость при поимке меньше — тело потеряло энергию",
      "Скорости равны по модулю, так как $E_\\text{мех} = \\text{const}$",
      "Зависит от высоты броска"
    ],
    a: 2,
    ex: "Без трения $E_\\text{мех} = \\text{const}$. На одной высоте $E_\\text{п}$ одинакова, значит $E_\\text{к}$ — тоже одинакова, поэтому $v = v_0$ по модулю."
  },
];

// ══ §33 Механическая работа. Мощность ══
const TASKS_P33 = [
  {
    q: "Сила $F = 100\\,\\text{Н}$ действует вдоль перемещения $\\Delta r = 5\\,\\text{м}$ ($\\alpha = 0°$). Найдите работу силы.",
    hint: "$A = F\\Delta r\\cos\\alpha$, $\\cos 0° = 1$",
    unit: "Дж", a: 500,
    ex: "$A = 100 \\cdot 5 \\cdot 1 = 500\\,\\text{Дж}$"
  },
  {
    q: "Тело тянут под углом $\\alpha = 60°$ к горизонту силой $F = 80\\,\\text{Н}$. Перемещение $\\Delta r = 10\\,\\text{м}$. Найдите работу силы.",
    hint: "$A = F\\Delta r\\cos\\alpha$, $\\cos 60° = 0{,}5$",
    unit: "Дж", a: 400,
    ex: "$A = 80 \\cdot 10 \\cdot 0{,}5 = 400\\,\\text{Дж}$"
  },
  {
    q: "Тело массой $m = 50\\,\\text{кг}$ подняли на высоту $h = 3\\,\\text{м}$, $g = 10\\,\\text{м/с}^2$. Найдите работу по подъёму.",
    hint: "$A = mgh$",
    unit: "Дж", a: 1500,
    ex: "$A = 50 \\cdot 10 \\cdot 3 = 1500\\,\\text{Дж}$"
  },
  {
    q: "Пружину жёсткостью $k = 400\\,\\text{Н/м}$ сжали на $x = 0{,}1\\,\\text{м}$. Найдите работу внешней силы.",
    hint: "$A = kx^2/2$",
    unit: "Дж", a: 2,
    ex: "$A = 400 \\cdot 0{,}01 / 2 = 2\\,\\text{Дж}$"
  },
  {
    q: "За время $\\Delta t = 2\\,\\text{с}$ совершена работа $A = 600\\,\\text{Дж}$. Найдите мощность.",
    hint: "$P = A/\\Delta t$",
    unit: "Вт", a: 300,
    ex: "$P = 600/2 = 300\\,\\text{Вт}$"
  },
  {
    q: "Двигатель тянет тело с силой $F = 500\\,\\text{Н}$ со скоростью $v = 20\\,\\text{м/с}$ (сила вдоль движения). Найдите мощность.",
    hint: "$P = Fv$",
    unit: "Вт", a: 10000,
    ex: "$P = 500 \\cdot 20 = 10000\\,\\text{Вт} = 10\\,\\text{кВт}$"
  },
  {
    q: "Кран поднимает поддон с кирпичами массой $m = 800\\,\\text{кг}$ на высоту $h = 9 \\cdot 3{,}5 = 31{,}5\\,\\text{м}$ (9 этажей), $g = 10\\,\\text{м/с}^2$. Найдите работу силы натяжения троса.",
    hint: "$A = mgh$",
    unit: "Дж", a: 252000,
    ex: "$A = 800 \\cdot 10 \\cdot 31{,}5 = 252\\,000\\,\\text{Дж} = 252\\,\\text{кДж}$"
  },
  {
    q: "Найдите силу тяги двигателя, если при скорости $v = 15\\,\\text{м/с}$ мощность $P = 45\\,\\text{кВт} = 45000\\,\\text{Вт}$.",
    hint: "$F = P/v$",
    unit: "Н", a: 3000,
    ex: "$F = P/v = 45000/15 = 3000\\,\\text{Н}$"
  },
  {
    q: "При каком угле между силой и перемещением работа силы отрицательна?",
    opts: [
      "При $\\alpha = 0°$",
      "При $\\alpha = 45°$",
      "При $\\alpha = 90°$",
      "При $\\alpha = 120°$"
    ],
    a: 3,
    ex: "При $\\alpha > 90°$ имеем $\\cos\\alpha < 0$, поэтому $A = F\\Delta r\\cos\\alpha < 0$."
  },
  {
    q: "Какую работу совершает сила реакции опоры при движении тела по горизонтальной поверхности?",
    opts: [
      "Положительную",
      "Отрицательную",
      "Равную нулю, так как сила перпендикулярна перемещению",
      "Зависит от скорости движения"
    ],
    a: 2,
    ex: "Сила реакции опоры перпендикулярна перемещению ($\\alpha = 90°$), поэтому $A = F\\Delta r\\cos 90° = 0$."
  },
];

// ══ §34 Потенциальная энергия ══
const TASKS_P34 = [
  {
    q: "Тело массой $m = 2\\,\\text{кг}$ находится на высоте $h = 5\\,\\text{м}$ над нулевым уровнем, $g = 10\\,\\text{м/с}^2$. Найдите потенциальную энергию.",
    hint: "$E_\\text{п} = mgh$",
    unit: "Дж", a: 100,
    ex: "$E_\\text{п} = 2 \\cdot 10 \\cdot 5 = 100\\,\\text{Дж}$"
  },
  {
    q: "Потенциальная энергия тела $E_\\text{п} = 500\\,\\text{Дж}$, масса $m = 5\\,\\text{кг}$, $g = 10\\,\\text{м/с}^2$. Найдите высоту над нулевым уровнем.",
    hint: "$h = E_\\text{п}/(mg)$",
    unit: "м", a: 10,
    ex: "$h = 500/(5 \\cdot 10) = 10\\,\\text{м}$"
  },
  {
    q: "Пружину жёсткостью $k = 400\\,\\text{Н/м}$ деформировали на $x = 0{,}1\\,\\text{м}$. Найдите потенциальную энергию пружины.",
    hint: "$E_\\text{п} = kx^2/2$",
    unit: "Дж", a: 2,
    ex: "$E_\\text{п} = 400 \\cdot 0{,}01/2 = 2\\,\\text{Дж}$"
  },
  {
    q: "Камень медленно поднимают из ямы глубиной $h = 2{,}0\\,\\text{м}$ на поверхность, $g = 10\\,\\text{м/с}^2$. При этом совершена работа $A = 100\\,\\text{Дж}$. Найдите массу камня.",
    hint: "$A = mgh \\Rightarrow m = A/(gh)$",
    unit: "кг", a: 5,
    ex: "$m = 100/(10 \\cdot 2{,}0) = 5\\,\\text{кг}$"
  },
  {
    q: "В результате растяжения пружина приобрела потенциальную энергию $E_\\text{п} = 0{,}32\\,\\text{Дж}$. Деформация $\\Delta l = 8{,}0\\,\\text{см} = 0{,}08\\,\\text{м}$. Найдите жёсткость пружины.",
    hint: "$E_\\text{п} = kx^2/2 \\Rightarrow k = 2E_\\text{п}/x^2$",
    unit: "Н/м", a: 100,
    ex: "$k = 2 \\cdot 0{,}32 / 0{,}08^2 = 0{,}64/0{,}0064 = 100\\,\\text{Н/м}$"
  },
  {
    q: "Тело опускается с высоты $h_1 = 10\\,\\text{м}$ до $h_2 = 4\\,\\text{м}$, масса $m = 3\\,\\text{кг}$, $g = 10\\,\\text{м/с}^2$. Найдите работу силы тяжести.",
    hint: "$A = mg(h_1 - h_2)$",
    unit: "Дж", a: 180,
    ex: "$A = 3 \\cdot 10 \\cdot (10-4) = 180\\,\\text{Дж}$"
  },
  {
    q: "В каких случаях тело обладает потенциальной энергией?",
    opts: [
      "Только при движении с большой скоростью",
      "Только в состоянии покоя",
      "Когда тело взаимодействует с другими телами (поднято над Землёй или деформировано)",
      "Только при наличии заряда"
    ],
    a: 2,
    ex: "Потенциальная энергия — мера способности сил взаимодействия совершать работу. Тело обладает ею при взаимодействии: гравитационном ($mgh$) или упругом ($kx^2/2$)."
  },
  {
    q: "Как изменится потенциальная энергия тела в поле тяжести, если высоту увеличить в 3 раза?",
    opts: [
      "Увеличится в 9 раз",
      "Увеличится в 3 раза",
      "Увеличится в $\\sqrt{3}$ раз",
      "Не изменится"
    ],
    a: 1,
    ex: "$E_\\text{п} = mgh$ — прямо пропорциональна высоте: увеличится в 3 раза."
  },
  {
    q: "Как изменится потенциальная энергия пружины, если деформацию увеличить в 2 раза?",
    opts: [
      "Увеличится в 2 раза",
      "Увеличится в 4 раза",
      "Уменьшится в 2 раза",
      "Не изменится"
    ],
    a: 1,
    ex: "$E_\\text{п} = kx^2/2$ — пропорциональна квадрату деформации: при $x' = 2x$ → $E_\\text{п}' = 4E_\\text{п}$."
  },
];

// ══ §35 Кинетическая энергия. Полная энергия ══
const TASKS_P35 = [
  {
    q: "Мяч массой $m = 0{,}5\\,\\text{кг}$ летит со скоростью $v = 8\\,\\text{м/с}$. Найдите его кинетическую энергию.",
    hint: "$E_\\text{к} = mv^2/2$",
    unit: "Дж", a: 16,
    ex: "$E_\\text{к} = \\dfrac{0{,}5 \\cdot 64}{2} = 16\\,\\text{Дж}$"
  },
  {
    q: "Тело массой $m = 4\\,\\text{кг}$ имеет кинетическую энергию $E_\\text{к} = 50\\,\\text{Дж}$. Найдите скорость тела.",
    hint: "$v = \\sqrt{2E_\\text{к}/m}$",
    unit: "м/с", a: 5,
    ex: "$v = \\sqrt{\\dfrac{2 \\cdot 50}{4}} = \\sqrt{25} = 5\\,\\text{м/с}$"
  },
  {
    q: "Тело массой $m = 2\\,\\text{кг}$ разгоняется с нуля до $v = 6\\,\\text{м/с}$. Найдите работу, совершённую над телом.",
    hint: "$A = \\Delta E_\\text{к} = mv^2/2 - 0$",
    unit: "Дж", a: 36,
    ex: "$A = \\Delta E_\\text{к} = \\dfrac{2 \\cdot 36}{2} = 36\\,\\text{Дж}$"
  },
  {
    q: "Тело массой $m = 2\\,\\text{кг}$ тормозит с $v_0 = 7\\,\\text{м/с}$ до $v = 3\\,\\text{м/с}$. На сколько уменьшилась кинетическая энергия тела?",
    hint: "$|\\Delta E_\\text{к}| = mv_0^2/2 - mv^2/2$",
    unit: "Дж", a: 40,
    ex: "$|\\Delta E_\\text{к}| = \\dfrac{2 \\cdot 49}{2} - \\dfrac{2 \\cdot 9}{2} = 49 - 9 = 40\\,\\text{Дж}$"
  },
  {
    q: "Шар массой $m = 0{,}4\\,\\text{кг}$ бросают вертикально вверх с $v_0 = 10\\,\\text{м/с}$ с уровня $h = 0$, $g = 10\\,\\text{м/с}^2$. Найдите механическую энергию шара в начальный момент.",
    hint: "$E_\\text{мех} = E_\\text{к} + E_\\text{п} = mv_0^2/2 + mgh$",
    unit: "Дж", a: 20,
    ex: "$E_\\text{мех} = \\dfrac{0{,}4 \\cdot 100}{2} + 0 = 20\\,\\text{Дж}$"
  },
  {
    q: "Тело массой $m = 3\\,\\text{кг}$ находится на высоте $h = 5\\,\\text{м}$ и движется со скоростью $v = 4\\,\\text{м/с}$, $g = 10\\,\\text{м/с}^2$. Найдите его механическую энергию.",
    hint: "$E_\\text{мех} = mv^2/2 + mgh$",
    unit: "Дж", a: 174,
    ex: "$E_\\text{мех} = \\dfrac{3 \\cdot 16}{2} + 3 \\cdot 10 \\cdot 5 = 24 + 150 = 174\\,\\text{Дж}$"
  },
  {
    q: "Как изменится кинетическая энергия тела при увеличении его скорости в 3 раза?",
    opts: [
      "Увеличится в 3 раза",
      "Увеличится в 6 раз",
      "Увеличится в 9 раз",
      "Уменьшится в 3 раза"
    ],
    a: 2,
    ex: "$E_\\text{к} = mv^2/2$ — пропорциональна $v^2$. При $v' = 3v$: $E_\\text{к}' = m(3v)^2/2 = 9\\,E_\\text{к}$."
  },
  {
    q: "Что гласит теорема о кинетической энергии?",
    opts: [
      "Кинетическая энергия тела сохраняется при любом движении",
      "Изменение кинетической энергии тела равно работе всех сил, действующих на него",
      "Кинетическая энергия равна произведению массы на скорость",
      "Кинетическая энергия тела не зависит от направления скорости"
    ],
    a: 1,
    ex: "Теорема: $\\Delta E_\\text{к} = A_\\text{рез}$. Именно все силы сразу определяют изменение $E_\\text{к}$."
  },
];

// ══ §36 Закон сохранения энергии ══
const TASKS_P36 = [
  {
    q: "Шарик массой $m = 0{,}2\\,\\text{кг}$ падает без трения с высоты $h = 5\\,\\text{м}$, $g = 10\\,\\text{м/с}^2$. Найдите его скорость у земли.",
    hint: "$mgh = mv^2/2 \\Rightarrow v = \\sqrt{2gh}$",
    unit: "м/с", a: 10,
    ex: "$v = \\sqrt{2 \\cdot 10 \\cdot 5} = \\sqrt{100} = 10\\,\\text{м/с}$"
  },
  {
    q: "Шарик массой $m = 0{,}5\\,\\text{кг}$ бросают вертикально вверх с $v_0 = 20\\,\\text{м/с}$. Без трения, $g = 10\\,\\text{м/с}^2$. Найдите максимальную высоту подъёма.",
    hint: "$mv_0^2/2 = mgh \\Rightarrow h = v_0^2/(2g)$",
    unit: "м", a: 20,
    ex: "$h = \\dfrac{v_0^2}{2g} = \\dfrac{400}{20} = 20\\,\\text{м}$"
  },
  {
    q: "Шар катится с горки высотой $h = 3{,}2\\,\\text{м}$ без трения. $g = 10\\,\\text{м/с}^2$. Найдите скорость шара у подножия горки.",
    hint: "$mgh = mv^2/2 \\Rightarrow v = \\sqrt{2gh}$",
    unit: "м/с", a: 8,
    ex: "$v = \\sqrt{2 \\cdot 10 \\cdot 3{,}2} = \\sqrt{64} = 8\\,\\text{м/с}$"
  },
  {
    q: "Маятник отклонили так, что шарик поднялся на высоту $h = 0{,}2\\,\\text{м}$ над положением равновесия. Без трения, $g = 10\\,\\text{м/с}^2$. Найдите скорость шарика в нижней точке.",
    hint: "$mgh = mv^2/2 \\Rightarrow v = \\sqrt{2gh}$",
    unit: "м/с", a: 2,
    ex: "$v = \\sqrt{2 \\cdot 10 \\cdot 0{,}2} = \\sqrt{4} = 2\\,\\text{м/с}$"
  },
  {
    q: "Тело массой $m = 1\\,\\text{кг}$ скользит с горки высотой $h = 4\\,\\text{м}$. Внизу скорость $v = 6\\,\\text{м/с}$, $g = 10\\,\\text{м/с}^2$. Найдите потери механической энергии на трение (величину, без знака).",
    hint: "Потери $= E_{\\text{мех}1} - E_{\\text{мех}2} = mgh - mv^2/2$",
    unit: "Дж", a: 22,
    ex: "Потери $= 1 \\cdot 10 \\cdot 4 - \\dfrac{1 \\cdot 36}{2} = 40 - 18 = 22\\,\\text{Дж}$ (столько ушло в тепло)"
  },
  {
    q: "Тело свободно падает с высоты $h = 45\\,\\text{м}$, $g = 10\\,\\text{м/с}^2$. Найдите скорость тела у земли.",
    hint: "$v = \\sqrt{2gh}$ (из ЗСЭ)",
    unit: "м/с", a: 30,
    ex: "$v = \\sqrt{2 \\cdot 10 \\cdot 45} = \\sqrt{900} = 30\\,\\text{м/с}$"
  },
  {
    q: "При каком условии механическая энергия тела сохраняется?",
    opts: [
      "При любом равномерном движении",
      "Когда на тело не действуют никакие силы",
      "Когда на тело действуют только консервативные силы: тяжесть и упругость (нет трения)",
      "Только при свободном падении"
    ],
    a: 2,
    ex: "$E_\\text{мех} = \\text{const}$ только при отсутствии сил трения и других диссипативных сил. Тяжесть и упругость — консервативные: их работа не приводит к потере механической энергии."
  },
  {
    q: "Как связаны изменение механической энергии тела и работа внешних (диссипативных) сил?",
    opts: [
      "$\\Delta E_\\text{мех} = 2A_\\text{внеш}$",
      "$\\Delta E_\\text{мех} = A_\\text{внеш}$",
      "$E_\\text{мех} + A_\\text{внеш} = mv^2$",
      "$\\Delta E_\\text{мех} = -A_\\text{внеш}$"
    ],
    a: 1,
    ex: "По теореме: $\\Delta E_\\text{мех} = A_\\text{внеш}$. При трении $A_\\text{тр} < 0$, поэтому $E_\\text{мех}$ уменьшается."
  },
];

// ══ §1 Механическое движение ══
var TASKS_P1 = [
  {
    q: "Что называют механическим движением?",
    opts: ["Изменение формы тела", "Изменение положения тела в пространстве относительно других тел", "Изменение массы тела", "Нагревание тела"],
    a: 1,
    ex: "Механическое движение — это изменение положения тела в пространстве относительно других тел с течением времени."
  },
  {
    q: "Тело движется по прямой. За 5 с оно прошло 40 м. Какова его средняя скорость?",
    hint: "$v = s/t$",
    unit: "м/с", a: 8,
    ex: "$v = 40/5 = 8\\,\\text{м/с}$"
  },
  {
    q: "Какое из движений является равномерным?",
    opts: ["Автобус разгоняется на светофоре", "Поезд идёт со скоростью 60 км/ч без изменений", "Мяч летит после броска", "Самолёт делает разворот"],
    a: 1,
    ex: "Равномерное движение — скорость не изменяется ни по модулю, ни по направлению."
  },
  {
    q: "Велосипедист едет 10 минут со скоростью 6 м/с. Какой путь он проехал?",
    hint: "$s = v \\cdot t$, перевести минуты в секунды",
    unit: "м", a: 3600,
    ex: "$t = 10 \\cdot 60 = 600\\,\\text{с}$; $s = 6 \\cdot 600 = 3600\\,\\text{м}$"
  },
  {
    q: "Какое движение называют прямолинейным?",
    opts: ["Движение по кривой", "Движение, при котором траектория — прямая линия", "Движение с постоянной скоростью", "Движение без трения"],
    a: 1,
    ex: "Прямолинейное движение — траектория является прямой линией."
  },
  {
    q: "Автомобиль проехал 180 км за 2 часа. Его средняя скорость в км/ч:",
    hint: "$v = s/t$",
    unit: "км/ч", a: 90,
    ex: "$v = 180/2 = 90\\,\\text{км/ч}$"
  },
  {
    q: "Что такое траектория движения?",
    opts: ["Расстояние между начальной и конечной точками", "Линия, которую описывает тело при движении", "Скорость тела", "Время движения"],
    a: 1,
    ex: "Траектория — воображаемая линия, которую описывает материальная точка при своём движении."
  },
  {
    q: "Пешеход шёл 30 минут. За это время он прошёл 2100 м. Найдите его скорость.",
    hint: "$v = s/t$",
    unit: "м/с", a: 1.167, tol: 0.05,
    ex: "$t = 30 \\cdot 60 = 1800\\,\\text{с}$; $v = 2100/1800 \\approx 1{,}17\\,\\text{м/с}$"
  }
];

// ══ §2 Относительность движения. Система отсчёта ══
var TASKS_P2 = [
  {
    q: "Что такое система отсчёта?",
    opts: ["Прибор для измерения времени", "Тело отсчёта + система координат + часы", "Единица измерения пути", "Направление движения"],
    a: 1,
    ex: "Система отсчёта: тело отсчёта, связанная с ним система координат и часы для отсчёта времени."
  },
  {
    q: "Пассажир в вагоне идёт вперёд со скоростью 2 м/с. Поезд движется со скоростью 20 м/с. Скорость пассажира относительно земли:",
    hint: "$v = v_1 + v_2$",
    unit: "м/с", a: 22,
    ex: "$v = 20 + 2 = 22\\,\\text{м/с}$ (движутся в одну сторону)"
  },
  {
    q: "Относительно чего определяется движение тела?",
    opts: ["Только относительно Земли", "Только относительно Солнца", "Относительно выбранного тела отсчёта", "Относительно воздуха"],
    a: 2,
    ex: "Движение всегда относительно — оно характеризуется относительно выбранного тела отсчёта."
  },
  {
    q: "Два поезда движутся навстречу друг другу. Скорость первого 60 км/ч, второго — 80 км/ч. Скорость сближения:",
    hint: "Сложить скорости при встречном движении",
    unit: "км/ч", a: 140,
    ex: "$v_{\\text{сбл}} = 60 + 80 = 140\\,\\text{км/ч}$"
  },
  {
    q: "Человек стоит в вагоне поезда. Относительно другого пассажира в том же вагоне он:",
    opts: ["Движется", "Покоится", "Движется вертикально", "Движется по кругу"],
    a: 1,
    ex: "Оба пассажира движутся вместе с поездом, поэтому относительно друг друга — в покое."
  },
  {
    q: "Два велосипедиста едут в одном направлении: первый 4 м/с, второй 6 м/с. Скорость второго относительно первого:",
    hint: "$v_{\\text{отн}} = v_2 - v_1$",
    unit: "м/с", a: 2,
    ex: "$v_{\\text{отн}} = 6 - 4 = 2\\,\\text{м/с}$ (в направлении движения)"
  },
  {
    q: "Что описывает система координат?",
    opts: ["Время", "Положение тела в пространстве", "Скорость тела", "Силу, действующую на тело"],
    a: 1,
    ex: "Система координат задаёт способ описания положения тела в пространстве."
  },
  {
    q: "Лодка плывёт поперёк реки шириной 60 м. Скорость лодки относительно воды 3 м/с. Время переправы:",
    hint: "$t = d/v_\\text{лодки}$",
    unit: "с", a: 20,
    ex: "$t = 60/3 = 20\\,\\text{с}$"
  }
];

// ══ §3 Скаляры и векторы. Сложение векторов ══
var TASKS_P3 = [
  {
    q: "Какая из величин является векторной?",
    opts: ["Масса", "Температура", "Скорость", "Объём"],
    a: 2,
    ex: "Скорость — векторная величина, так как имеет и модуль, и направление."
  },
  {
    q: "Два вектора направлены в одну сторону: $a = 30\\,\\text{м}$, $b = 50\\,\\text{м}$. Модуль суммы:",
    hint: "Сонаправленные векторы: $|\\vec{a}+\\vec{b}| = a+b$",
    unit: "м", a: 80,
    ex: "$|\\vec{a}+\\vec{b}| = 30 + 50 = 80\\,\\text{м}$"
  },
  {
    q: "Два противоположно направленных вектора: $a = 50\\,\\text{м}$, $b = 30\\,\\text{м}$. Модуль суммы:",
    hint: "Противоположные векторы: $|\\vec{a}+\\vec{b}| = |a-b|$",
    unit: "м", a: 20,
    ex: "$|\\vec{a}+\\vec{b}| = |50 - 30| = 20\\,\\text{м}$"
  },
  {
    q: "Что называют модулем вектора?",
    opts: ["Направление вектора", "Длина (числовое значение) вектора без учёта направления", "Угол вектора", "Проекция вектора"],
    a: 1,
    ex: "Модуль вектора — его длина, числовое значение без учёта направления."
  },
  {
    q: "Два взаимно перпендикулярных вектора: $a = 3\\,\\text{м}$, $b = 4\\,\\text{м}$. Модуль суммы:",
    hint: "Теорема Пифагора: $c = \\sqrt{a^2+b^2}$",
    unit: "м", a: 5,
    ex: "$|\\vec{a}+\\vec{b}| = \\sqrt{3^2 + 4^2} = \\sqrt{9+16} = 5\\,\\text{м}$"
  },
  {
    q: "Какая из величин является скалярной?",
    opts: ["Перемещение", "Ускорение", "Сила", "Температура"],
    a: 3,
    ex: "Температура — скалярная величина, не имеет направления."
  },
  {
    q: "Правило параллелограмма используется для:",
    opts: ["Деления векторов", "Нахождения суммы (и разности) двух векторов", "Нахождения проекции", "Умножения на число"],
    a: 1,
    ex: "Правило параллелограмма: диагональ параллелограмма, построенного на двух векторах, равна их сумме."
  },
  {
    q: "Векторы $\\vec{a}$ и $\\vec{b}$ перпендикулярны. $a = 5\\,\\text{м}$, $b = 12\\,\\text{м}$. Найдите модуль суммы.",
    hint: "$c = \\sqrt{a^2+b^2}$",
    unit: "м", a: 13,
    ex: "$c = \\sqrt{25 + 144} = \\sqrt{169} = 13\\,\\text{м}$"
  }
];

// ══ §4 Проекции вектора ══
var TASKS_P4 = [
  {
    q: "Как вычислить проекцию вектора $\\vec{a}$ на ось $x$?",
    opts: ["$a_x = a / \\cos\\varphi$", "$a_x = a \\cdot \\sin\\varphi$", "$a_x = a \\cdot \\cos\\varphi$", "$a_x = a^2$"],
    a: 2,
    ex: "Проекция на ось x: $a_x = a \\cdot \\cos\\varphi$, где $\\varphi$ — угол между вектором и осью x."
  },
  {
    q: "Вектор длиной $10\\,\\text{м}$ направлен под углом $0°$ к оси $x$. Проекция на ось $x$:",
    hint: "$a_x = a \\cdot \\cos 0°$",
    unit: "м", a: 10,
    ex: "$a_x = 10 \\cdot \\cos 0° = 10 \\cdot 1 = 10\\,\\text{м}$"
  },
  {
    q: "Вектор длиной $20\\,\\text{м}$ направлен под углом $90°$ к оси $x$. Проекция на ось $x$:",
    hint: "$\\cos 90° = 0$",
    unit: "м", a: 0,
    ex: "$a_x = 20 \\cdot \\cos 90° = 20 \\cdot 0 = 0\\,\\text{м}$"
  },
  {
    q: "Вектор $a = 8\\,\\text{м}$ направлен под углом $60°$ к оси $x$. Найдите $a_x$.",
    hint: "$\\cos 60° = 0{,}5$",
    unit: "м", a: 4,
    ex: "$a_x = 8 \\cdot \\cos 60° = 8 \\cdot 0{,}5 = 4\\,\\text{м}$"
  },
  {
    q: "Вектор $a = 10\\,\\text{м}$ направлен под углом $30°$ к оси $x$. Найдите $a_y$.",
    hint: "$a_y = a \\cdot \\sin 30°$, $\\sin 30° = 0{,}5$",
    unit: "м", a: 5,
    ex: "$a_y = 10 \\cdot \\sin 30° = 10 \\cdot 0{,}5 = 5\\,\\text{м}$"
  },
  {
    q: "Если $a_x > 0$ и $a_y > 0$, то вектор направлен:",
    opts: ["В первый квадрант (вправо-вверх)", "Во второй квадрант (влево-вверх)", "В третий квадрант", "В четвёртый квадрант"],
    a: 0,
    ex: "Положительные обе проекции — вектор в первом квадранте."
  },
  {
    q: "Известны проекции: $a_x = 6\\,\\text{м}$, $a_y = 8\\,\\text{м}$. Модуль вектора:",
    hint: "$a = \\sqrt{a_x^2 + a_y^2}$",
    unit: "м", a: 10,
    ex: "$a = \\sqrt{36 + 64} = \\sqrt{100} = 10\\,\\text{м}$"
  },
  {
    q: "Вектор $a = 20\\,\\text{м}$ направлен под углом $45°$ к оси $x$. Найдите $a_x$. ($\\sin 45° = \\cos 45° \\approx 0{,}707$)",
    hint: "$a_x = a \\cdot \\cos 45°$",
    unit: "м", a: 14.14, tol: 0.05,
    ex: "$a_x = 20 \\cdot 0{,}707 \\approx 14{,}14\\,\\text{м}$"
  }
];

// ══ §5 Путь и перемещение ══
var TASKS_P5 = [
  {
    q: "В чём разница между путём и перемещением?",
    opts: ["Это одно и то же", "Путь — скалярная длина траектории; перемещение — вектор от начальной до конечной точки", "Перемещение всегда больше пути", "Путь — вектор, перемещение — скаляр"],
    a: 1,
    ex: "Путь $s$ — длина траектории (скаляр). Перемещение $\\vec{\\Delta r}$ — вектор из начальной точки в конечную."
  },
  {
    q: "Человек прошёл 4 м на восток и 3 м на север. Модуль его перемещения:",
    hint: "$|\\Delta r| = \\sqrt{4^2+3^2}$",
    unit: "м", a: 5,
    ex: "$|\\Delta r| = \\sqrt{16+9} = 5\\,\\text{м}$"
  },
  {
    q: "В каком случае путь равен модулю перемещения?",
    opts: ["Всегда", "При движении по кривой", "При прямолинейном движении в одном направлении", "Только при движении по кругу"],
    a: 2,
    ex: "При прямолинейном движении в одну сторону $s = |\\Delta r|$."
  },
  {
    q: "Спортсмен пробежал по стадиону один круг длиной 400 м и вернулся в начальную точку. Модуль перемещения:",
    hint: "Начальная и конечная точки совпадают",
    unit: "м", a: 0,
    ex: "После полного круга начальная и конечная точки совпадают, поэтому $|\\Delta r| = 0\\,\\text{м}$."
  },
  {
    q: "Тело прошло путь $s = 10\\,\\text{м}$. Наименьший возможный модуль перемещения равен:",
    hint: "Модуль перемещения не превышает путь",
    unit: "м", a: 0,
    ex: "Если тело вернулось в исходную точку, $|\\Delta r| = 0$. Минимальное значение — 0."
  },
  {
    q: "Тело переместилось из точки $x_1 = 3\\,\\text{м}$ в точку $x_2 = 8\\,\\text{м}$. Перемещение:",
    hint: "$\\Delta x = x_2 - x_1$",
    unit: "м", a: 5,
    ex: "$\\Delta x = 8 - 3 = 5\\,\\text{м}$"
  },
  {
    q: "Тело переместилось из точки $x_1 = 7\\,\\text{м}$ в точку $x_2 = 2\\,\\text{м}$. Перемещение:",
    hint: "$\\Delta x = x_2 - x_1$ (может быть отрицательным)",
    unit: "м", a: -5,
    ex: "$\\Delta x = 2 - 7 = -5\\,\\text{м}$ (движение в отрицательном направлении)"
  },
  {
    q: "Велосипедист проехал 3 км на запад и 4 км на север. Путь равен:",
    hint: "$s = s_1 + s_2$",
    unit: "км", a: 7,
    ex: "$s = 3 + 4 = 7\\,\\text{км}$ (путь — сумма всех расстояний)"
  }
];

// ══ §6 Равномерное прямолинейное движение ══
var TASKS_P6 = [
  {
    q: "Что такое равномерное прямолинейное движение?",
    opts: ["Движение с постоянным ускорением", "Движение, при котором скорость постоянна по модулю и направлению", "Движение по кривой", "Движение с нулевой скоростью"],
    a: 1,
    ex: "Равномерное прямолинейное движение — скорость тела постоянна по модулю и направлению."
  },
  {
    q: "Автомобиль движется равномерно. За 4 с он проехал 80 м. Скорость автомобиля:",
    hint: "$v = s/t$",
    unit: "м/с", a: 20,
    ex: "$v = 80/4 = 20\\,\\text{м/с}$"
  },
  {
    q: "Поезд движется со скоростью 25 м/с. Какой путь он пройдёт за 3 минуты?",
    hint: "$s = v \\cdot t$",
    unit: "м", a: 4500,
    ex: "$t = 180\\,\\text{с}$; $s = 25 \\cdot 180 = 4500\\,\\text{м}$"
  },
  {
    q: "За какое время автомобиль со скоростью 30 м/с проедет 1,5 км?",
    hint: "$t = s/v$",
    unit: "с", a: 50,
    ex: "$t = 1500/30 = 50\\,\\text{с}$"
  },
  {
    q: "График $x(t)$ для равномерного движения — это:",
    opts: ["Парабола", "Прямая линия", "Синусоида", "Гипербола"],
    a: 1,
    ex: "При равномерном движении $x = x_0 + vt$ — линейная зависимость, прямая линия."
  },
  {
    q: "Тело начинает движение из точки $x_0 = 5\\,\\text{м}$ со скоростью $v = 3\\,\\text{м/с}$. Координата через $t = 4\\,\\text{с}$:",
    hint: "$x = x_0 + vt$",
    unit: "м", a: 17,
    ex: "$x = 5 + 3 \\cdot 4 = 5 + 12 = 17\\,\\text{м}$"
  },
  {
    q: "Что даёт угол наклона прямой на графике $x(t)$?",
    opts: ["Ускорение", "Путь", "Скорость движения", "Время"],
    a: 2,
    ex: "Тангенс угла наклона прямой $x(t)$ численно равен скорости тела."
  },
  {
    q: "Тело движется равномерно со скоростью $v = 2\\,\\text{м/с}$. Начальная координата $x_0 = 0$. Когда координата достигнет $x = 14\\,\\text{м}$?",
    hint: "$t = (x - x_0)/v$",
    unit: "с", a: 7,
    ex: "$t = 14/2 = 7\\,\\text{с}$"
  }
];

// ══ §7 Движение двух тел на одной прямой ══
var TASKS_P7 = [
  {
    q: "Два тела движутся навстречу из точек $x_1=0$ и $x_2=100\\,\\text{м}$ со скоростями $v_1=5\\,\\text{м/с}$ и $v_2=5\\,\\text{м/с}$. Когда встретятся?",
    hint: "$t = (x_2-x_1)/(v_1+v_2)$",
    unit: "с", a: 10,
    ex: "$t = 100/(5+5) = 10\\,\\text{с}$"
  },
  {
    q: "Два тела движутся в одном направлении. Первое: $x_0=0$, $v_1=10\\,\\text{м/с}$. Второе: $x_0=30\\,\\text{м}$, $v_2=4\\,\\text{м/с}$. Когда первое догонит второе?",
    hint: "$t = \\Delta x_0/(v_1-v_2)$",
    unit: "с", a: 5,
    ex: "$t = 30/(10-4) = 5\\,\\text{с}$"
  },
  {
    q: "Где на числовой оси встретятся два тела, если $x_1=0$ ($v_1=6\\,\\text{м/с}$) и $x_2=90\\,\\text{м}$ ($v_2=3\\,\\text{м/с}$) движутся навстречу?",
    hint: "Сначала найди время встречи, потом координату",
    unit: "м", a: 60,
    ex: "$t = 90/9 = 10\\,\\text{с}$; $x = 6 \\cdot 10 = 60\\,\\text{м}$"
  },
  {
    q: "Что означает, что два тела «встретились»?",
    opts: ["Они имеют одинаковую скорость", "Они находятся в одной точке в один момент времени", "Они движутся с одинаковым ускорением", "Они одновременно остановились"],
    a: 1,
    ex: "Встреча — тела находятся в одной точке пространства в один момент времени: $x_1(t) = x_2(t)$."
  },
  {
    q: "На графике $x(t)$ встреча двух тел определяется как:",
    opts: ["Параллельные прямые", "Точка пересечения прямых двух тел", "Максимум функции", "Точка, где прямая горизонтальна"],
    a: 1,
    ex: "Точка пересечения прямых на $x(t)$-графике — момент и место встречи."
  },
  {
    q: "Два тела движутся навстречу. Расстояние между ними 120 м. Скорости: $v_1 = 8\\,\\text{м/с}$, $v_2 = 4\\,\\text{м/с}$. Встреча через:",
    hint: "$t = d/(v_1+v_2)$",
    unit: "с", a: 10,
    ex: "$t = 120/(8+4) = 10\\,\\text{с}$"
  },
  {
    q: "Тело А впереди тела Б на 40 м и движется в том же направлении со скоростью 3 м/с. Тело Б догоняет со скоростью 7 м/с. Через сколько секунд Б догонит А?",
    hint: "$t = \\Delta x_0/(v_\\text{Б}-v_\\text{А})$",
    unit: "с", a: 10,
    ex: "$t = 40/(7-3) = 10\\,\\text{с}$"
  },
  {
    q: "Два тела одновременно выехали навстречу. Расстояние 200 м. $v_1=10\\,\\text{м/с}$, $v_2=15\\,\\text{м/с}$. Где встретятся от точки старта первого тела?",
    hint: "$t = 200/25$, $x = v_1 \\cdot t$",
    unit: "м", a: 80,
    ex: "$t = 200/25 = 8\\,\\text{с}$; $x = 10 \\cdot 8 = 80\\,\\text{м}$"
  }
];

// ══ §8 Средняя скорость ══
var TASKS_P8 = [
  {
    q: "Средняя скорость движения определяется как:",
    opts: ["Полный путь делённый на время", "Полуразность максимальной и минимальной скоростей", "Скорость в середине пути", "Сумма скоростей делённая на 2"],
    a: 0,
    ex: "Средняя скорость: $\\langle v \\rangle = s_{\\text{полн}} / t_{\\text{полн}}$"
  },
  {
    q: "Первую половину пути тело шло 20 мин, вторую — 40 мин. Средняя скорость в два раза меньше скорости на первом участке. Верно ли?",
    opts: ["Да, средняя скорость = (v₁+v₂)/2", "Нет. Средняя скорость ≠ среднеарифметическому, если времена разные", "Да, всегда", "Нет, средняя скорость = 0"],
    a: 1,
    ex: "$\\langle v \\rangle = s/t$ — отношение пути ко времени. Среднеарифметическое скоростей не даёт истинную среднюю скорость."
  },
  {
    q: "Тело прошло 60 м за 4 с, затем 80 м за 6 с. Средняя скорость всего пути:",
    hint: "$\\langle v \\rangle = (s_1+s_2)/(t_1+t_2)$",
    unit: "м/с", a: 14,
    ex: "$\\langle v \\rangle = (60+80)/(4+6) = 140/10 = 14\\,\\text{м/с}$"
  },
  {
    q: "Автомобиль ехал 2 ч со скоростью 60 км/ч, затем 1 ч со скоростью 90 км/ч. Средняя скорость всей поездки:",
    hint: "$\\langle v \\rangle = (s_1+s_2)/(t_1+t_2)$",
    unit: "км/ч", a: 70,
    ex: "$s_1 = 120$, $s_2 = 90$; $\\langle v \\rangle = (120+90)/3 = 70\\,\\text{км/ч}$"
  },
  {
    q: "Велосипедист первые 5 км ехал 20 мин, следующие 5 км — 40 мин. Средняя скорость всего пути:",
    hint: "$\\langle v \\rangle = 10\\,\\text{км}/60\\,\\text{мин}$",
    unit: "км/ч", a: 10,
    ex: "$\\langle v \\rangle = 10/1 = 10\\,\\text{км/ч}$"
  },
  {
    q: "Почему средняя скорость может быть меньше, чем каждая из частичных скоростей?",
    opts: ["Это невозможно", "Средняя скорость усредняет по пути, поэтому большее время на малой скорости снижает среднюю", "Скорости прибавляются неправильно", "Из-за ошибок измерений"],
    a: 1,
    ex: "Если на меньшей скорости тратится больше времени, средняя скорость тянется к меньшему значению."
  },
  {
    q: "Тело 3 с двигалось со скоростью 4 м/с, потом 7 с со скоростью 6 м/с. Средняя скорость:",
    hint: "$\\langle v \\rangle = (3 \\cdot 4 + 7 \\cdot 6)/(3+7)$",
    unit: "м/с", a: 5.4,
    ex: "$\\langle v \\rangle = (12+42)/10 = 54/10 = 5{,}4\\,\\text{м/с}$"
  },
  {
    q: "Автомобиль проехал 150 км. Первые 90 км за 1 ч, остальные 60 км за 2 ч. Средняя скорость:",
    hint: "$\\langle v \\rangle = 150/3$",
    unit: "км/ч", a: 50,
    ex: "$\\langle v \\rangle = 150/3 = 50\\,\\text{км/ч}$"
  }
];

// ══ §9 Сложение скоростей (кинематика) ══
var TASKS_P9 = [
  {
    q: "Лодка движется относительно воды со скоростью 5 м/с. Течение реки 3 м/с. Скорость лодки относительно берега (по течению):",
    hint: "Скорости направлены в одну сторону",
    unit: "м/с", a: 8,
    ex: "$v = 5 + 3 = 8\\,\\text{м/с}$"
  },
  {
    q: "Лодка движется против течения со скоростью 5 м/с. Скорость течения 2 м/с. Скорость лодки относительно берега:",
    hint: "Вычитаем скорость течения",
    unit: "м/с", a: 3,
    ex: "$v = 5 - 2 = 3\\,\\text{м/с}$"
  },
  {
    q: "Лодка движется поперёк реки (перпендикулярно берегу). Скорость лодки 4 м/с, течение 3 м/с. Скорость лодки относительно берега:",
    hint: "$v = \\sqrt{v_\\text{лод}^2 + v_\\text{теч}^2}$",
    unit: "м/с", a: 5,
    ex: "$v = \\sqrt{16+9} = \\sqrt{25} = 5\\,\\text{м/с}$"
  },
  {
    q: "Самолёт летит на восток со скоростью 200 м/с. Боковой ветер с севера 50 м/с. Модуль результирующей скорости:",
    hint: "Перпендикулярные скорости: теорема Пифагора",
    unit: "м/с", a: 206, tol: 0.02,
    ex: "$v = \\sqrt{200^2+50^2} = \\sqrt{40000+2500} \\approx 206\\,\\text{м/с}$"
  },
  {
    q: "Закон сложения скоростей гласит:",
    opts: ["$\\vec{v}_{13} = \\vec{v}_{12} \\cdot \\vec{v}_{23}$", "$\\vec{v}_{13} = \\vec{v}_{12} + \\vec{v}_{23}$", "$\\vec{v}_{13} = \\vec{v}_{12} - 2\\vec{v}_{23}$", "$v_{13} = v_{12}^2 + v_{23}^2$"],
    a: 1,
    ex: "Скорость тела 1 относительно тела 3 равна векторной сумме скоростей: $\\vec{v}_{13} = \\vec{v}_{12} + \\vec{v}_{23}$."
  },
  {
    q: "Пешеход идёт в вагоне поезда назад со скоростью 1 м/с. Поезд идёт вперёд 20 м/с. Скорость пешехода относительно земли:",
    hint: "Вычитаем скорость пешехода относительно вагона",
    unit: "м/с", a: 19,
    ex: "$v = 20 - 1 = 19\\,\\text{м/с}$ (относительно земли)"
  },
  {
    q: "Река шириной 120 м. Лодка движется поперёк со скоростью 4 м/с. Течение 3 м/с. За сколько секунд переплывёт реку?",
    hint: "Время зависит только от поперечной составляющей",
    unit: "с", a: 30,
    ex: "$t = 120/4 = 30\\,\\text{с}$"
  },
  {
    q: "На сколько метров снесёт лодку течением при переправе из предыдущей задачи ($t=30\\,\\text{с}$, течение 3 м/с)?",
    hint: "$x_\\text{снос} = v_\\text{теч} \\cdot t$",
    unit: "м", a: 90,
    ex: "$x_\\text{снос} = 3 \\cdot 30 = 90\\,\\text{м}$"
  }
];

// ══ §10 Ускорение ══
var TASKS_P10 = [
  {
    q: "Что называют ускорением тела?",
    opts: ["Пройденный путь за единицу времени", "Изменение скорости за единицу времени", "Произведение скорости на время", "Скорость в начальный момент"],
    a: 1,
    ex: "Ускорение $\\vec{a} = \\Delta\\vec{v}/\\Delta t$ — векторная физическая величина."
  },
  {
    q: "Автомобиль разогнался с 0 до 20 м/с за 5 с. Ускорение:",
    hint: "$a = \\Delta v / t$",
    unit: "м/с²", a: 4,
    ex: "$a = 20/5 = 4\\,\\text{м/с}^2$"
  },
  {
    q: "Тело двигалось со скоростью 30 м/с и затормозило до 10 м/с за 4 с. Ускорение торможения (модуль):",
    hint: "$a = |\\Delta v|/t = (v_0-v)/t$",
    unit: "м/с²", a: 5,
    ex: "$a = (30-10)/4 = 5\\,\\text{м/с}^2$"
  },
  {
    q: "Единица измерения ускорения в СИ:",
    opts: ["м/с", "м/с²", "Н·с", "кг·м/с"],
    a: 1,
    ex: "Ускорение измеряется в метрах в секунду в квадрате: м/с²."
  },
  {
    q: "Тело движется с ускорением $a = 3\\,\\text{м/с}^2$. Начальная скорость $v_0 = 2\\,\\text{м/с}$. Скорость через $t = 4\\,\\text{с}$:",
    hint: "$v = v_0 + at$",
    unit: "м/с", a: 14,
    ex: "$v = 2 + 3 \\cdot 4 = 14\\,\\text{м/с}$"
  },
  {
    q: "Мяч брошен вертикально вверх с $v_0 = 15\\,\\text{м/с}$. Ускорение свободного падения $g = 10\\,\\text{м/с}^2$. Через сколько секунд мяч остановится?",
    hint: "$t = v_0/g$",
    unit: "с", a: 1.5,
    ex: "$t = 15/10 = 1{,}5\\,\\text{с}$"
  },
  {
    q: "Если скорость тела возрастает, ускорение направлено:",
    opts: ["Против движения", "В сторону движения", "Перпендикулярно движению", "Направление не важно"],
    a: 1,
    ex: "При разгоне скорость и ускорение направлены одинаково."
  },
  {
    q: "Поезд тормозит с $v_0 = 36\\,\\text{м/с}$ с ускорением $a = 1\\,\\text{м/с}^2$. Через сколько секунд он остановится?",
    hint: "$t = v_0/a$",
    unit: "с", a: 36,
    ex: "$t = 36/1 = 36\\,\\text{с}$"
  }
];

// ══ §11 Равноускоренное движение: скорость ══
var TASKS_P11 = [
  {
    q: "Формула скорости при равноускоренном движении:",
    opts: ["$v = v_0 / (at)$", "$v = v_0 + at$", "$v = v_0 \\cdot a \\cdot t$", "$v = at^2$"],
    a: 1,
    ex: "При равноускоренном движении: $v = v_0 + at$."
  },
  {
    q: "Тело начинает движение из покоя с ускорением $a = 5\\,\\text{м/с}^2$. Скорость через $t = 6\\,\\text{с}$:",
    hint: "$v = 0 + at$",
    unit: "м/с", a: 30,
    ex: "$v = 5 \\cdot 6 = 30\\,\\text{м/с}$"
  },
  {
    q: "При равноускоренном движении график $v(t)$ — это:",
    opts: ["Парабола", "Прямая линия", "Гипербола", "Синусоида"],
    a: 1,
    ex: "$v = v_0 + at$ — линейная функция от $t$, прямая линия."
  },
  {
    q: "Из графика $v(t)$ можно определить ускорение как:",
    opts: ["Ординату при $t=0$", "Площадь под графиком", "Тангенс угла наклона прямой", "Максимальную скорость"],
    a: 2,
    ex: "Наклон прямой $v(t)$ — ускорение: $a = \\tan\\alpha = \\Delta v/\\Delta t$."
  },
  {
    q: "Автомобиль движется со скоростью $v_0 = 10\\,\\text{м/с}$ и разгоняется с $a = 2\\,\\text{м/с}^2$. Скорость через $t = 5\\,\\text{с}$:",
    hint: "$v = v_0 + at$",
    unit: "м/с", a: 20,
    ex: "$v = 10 + 2 \\cdot 5 = 20\\,\\text{м/с}$"
  },
  {
    q: "Тело тормозит: $v_0 = 25\\,\\text{м/с}$, $a = -5\\,\\text{м/с}^2$. Через сколько секунд остановится?",
    hint: "$0 = v_0 + at \\Rightarrow t = v_0/|a|$",
    unit: "с", a: 5,
    ex: "$t = 25/5 = 5\\,\\text{с}$"
  },
  {
    q: "Велосипедист имеет начальную скорость 4 м/с и разгоняется с ускорением 1 м/с². Какова его скорость через 8 с?",
    hint: "$v = v_0 + at$",
    unit: "м/с", a: 12,
    ex: "$v = 4 + 1 \\cdot 8 = 12\\,\\text{м/с}$"
  },
  {
    q: "Площадь под графиком $v(t)$ при равноускоренном движении соответствует:",
    opts: ["Ускорению", "Пути, пройденному телом", "Силе", "Мощности"],
    a: 1,
    ex: "Площадь под $v(t)$ — это путь: $s = \\int v\\,dt$."
  }
];

// ══ §12 Равноускоренное движение: координата x(t) ══
var TASKS_P12 = [
  {
    q: "Формула перемещения при равноускоренном движении (из покоя):",
    opts: ["$s = v_0 t$", "$s = at$", "$s = \\dfrac{at^2}{2}$", "$s = v_0^2/(2a)$"],
    a: 2,
    ex: "Из покоя ($v_0=0$): $s = \\dfrac{at^2}{2}$."
  },
  {
    q: "Тело начинает движение из покоя с ускорением $a = 2\\,\\text{м/с}^2$. Путь за $t = 4\\,\\text{с}$:",
    hint: "$s = at^2/2$",
    unit: "м", a: 16,
    ex: "$s = 2 \\cdot 16/2 = 16\\,\\text{м}$"
  },
  {
    q: "Тело: $v_0 = 6\\,\\text{м/с}$, $a = 2\\,\\text{м/с}^2$, $t = 5\\,\\text{с}$. Путь:",
    hint: "$s = v_0 t + at^2/2$",
    unit: "м", a: 55,
    ex: "$s = 6 \\cdot 5 + 2 \\cdot 25/2 = 30+25 = 55\\,\\text{м}$"
  },
  {
    q: "Автомобиль разгонялся с места. За первые 3 с прошёл 9 м. Ускорение:",
    hint: "$s = at^2/2 \\Rightarrow a = 2s/t^2$",
    unit: "м/с²", a: 2,
    ex: "$a = 2 \\cdot 9/9 = 2\\,\\text{м/с}^2$"
  },
  {
    q: "График $x(t)$ при равноускоренном движении из покоя — это:",
    opts: ["Прямая линия", "Парабола", "Горизонтальная линия", "Гипербола"],
    a: 1,
    ex: "$x = x_0 + v_0 t + at^2/2$ — при $v_0=0$: $x \\propto t^2$ — парабола."
  },
  {
    q: "Тело тормозит: $v_0 = 20\\,\\text{м/с}$, $a = -4\\,\\text{м/с}^2$. Путь до остановки:",
    hint: "$v^2 = v_0^2 - 2as \\Rightarrow s = v_0^2/(2a)$",
    unit: "м", a: 50,
    ex: "$s = 20^2/(2 \\cdot 4) = 400/8 = 50\\,\\text{м}$"
  },
  {
    q: "Тело: $x_0 = 10\\,\\text{м}$, $v_0 = 0$, $a = 3\\,\\text{м/с}^2$. Координата через $t = 4\\,\\text{с}$:",
    hint: "$x = x_0 + at^2/2$",
    unit: "м", a: 34,
    ex: "$x = 10 + 3 \\cdot 16/2 = 10+24 = 34\\,\\text{м}$"
  },
  {
    q: "При равноускоренном движении путь за $n$-ю секунду больше, чем за $(n-1)$-ю. Почему?",
    opts: ["Скорость уменьшается", "Ускорение возрастает", "Скорость возрастает — за каждую следующую секунду тело проходит больший путь", "Это неверно"],
    a: 2,
    ex: "При разгоне скорость растёт, поэтому расстояния за равные промежутки времени нарастают."
  }
];

// ══ §13 Равномерное движение по окружности ══
var TASKS_P13 = [
  {
    q: "Что такое период обращения?",
    opts: ["Скорость движения по окружности", "Время одного полного оборота", "Число оборотов в секунду", "Радиус окружности"],
    a: 1,
    ex: "Период $T$ — время одного полного оборота."
  },
  {
    q: "Что такое частота вращения?",
    opts: ["Время одного оборота", "Число оборотов в единицу времени", "Длина окружности", "Ускорение"],
    a: 1,
    ex: "Частота $\\nu = 1/T$ — число оборотов за единицу времени (единица — Гц = 1/с)."
  },
  {
    q: "Тело совершает 5 оборотов за 2 с. Период обращения:",
    hint: "$T = t/N$",
    unit: "с", a: 0.4,
    ex: "$T = 2/5 = 0{,}4\\,\\text{с}$"
  },
  {
    q: "Скорость движения по окружности: колесо радиуса $r = 0{,}5\\,\\text{м}$ делает $n = 10\\,\\text{об/с}$. Линейная скорость:",
    hint: "$v = 2\\pi r / T = 2\\pi r \\cdot \\nu$",
    unit: "м/с", a: 31.4, tol: 0.03,
    ex: "$v = 2\\pi \\cdot 0{,}5 \\cdot 10 \\approx 31{,}4\\,\\text{м/с}$"
  },
  {
    q: "Направление скорости при движении по окружности:",
    opts: ["По радиусу к центру", "По радиусу от центра", "По касательной к окружности", "Вдоль оси вращения"],
    a: 2,
    ex: "Мгновенная скорость всегда направлена по касательной к траектории."
  },
  {
    q: "Тело равномерно движется по окружности. Его скорость:",
    opts: ["Не изменяется совсем", "Постоянна по модулю, но изменяется по направлению", "Постоянно возрастает", "Равна нулю"],
    a: 1,
    ex: "При равномерном движении по окружности: $|v| = \\text{const}$, но направление меняется непрерывно."
  },
  {
    q: "Колесо вращается с периодом $T = 0{,}2\\,\\text{с}$. Частота вращения:",
    hint: "$\\nu = 1/T$",
    unit: "об/с", a: 5,
    ex: "$\\nu = 1/0{,}2 = 5\\,\\text{об/с}$"
  },
  {
    q: "Точка находится на радиусе $r = 2\\,\\text{м}$ вращающегося диска с $T = 4\\,\\text{с}$. Линейная скорость точки:",
    hint: "$v = 2\\pi r/T$",
    unit: "м/с", a: 3.14, tol: 0.03,
    ex: "$v = 2\\pi \\cdot 2/4 = \\pi \\approx 3{,}14\\,\\text{м/с}$"
  }
];

// ══ §14 Центростремительное ускорение ══
var TASKS_P14 = [
  {
    q: "Центростремительное ускорение направлено:",
    opts: ["По касательной к траектории", "В сторону движения", "К центру окружности", "Против движения"],
    a: 2,
    ex: "Центростремительное ускорение всегда направлено к центру окружности."
  },
  {
    q: "Формула центростремительного ускорения:",
    opts: ["$a = v \\cdot T$", "$a = v^2/r$", "$a = vr$", "$a = r/v$"],
    a: 1,
    ex: "$a_\\text{цс} = v^2/r = \\omega^2 r$"
  },
  {
    q: "Тело движется по окружности радиуса $r = 4\\,\\text{м}$ со скоростью $v = 8\\,\\text{м/с}$. Центростремительное ускорение:",
    hint: "$a = v^2/r$",
    unit: "м/с²", a: 16,
    ex: "$a = 64/4 = 16\\,\\text{м/с}^2$"
  },
  {
    q: "Спутник летит по круговой орбите радиуса $R = 7000\\,\\text{км}$ со скоростью $v = 7{,}8\\,\\text{км/с}$. Центростремительное ускорение (в м/с²):",
    hint: "$a = v^2/R$; перевести единицы",
    unit: "м/с²", a: 8.69, tol: 0.05,
    ex: "$a = (7800)^2/(7\\cdot10^6) \\approx 8{,}69\\,\\text{м/с}^2$"
  },
  {
    q: "Центростремительное ускорение обеспечивается:",
    opts: ["Только силой тяжести", "Равнодействующей сил, направленной к центру орбиты", "Скоростью тела", "Инерцией"],
    a: 1,
    ex: "Центростремительное ускорение вызывается силой, направленной к центру: $F = ma_\\text{цс}$."
  },
  {
    q: "Автомобиль проходит поворот радиуса $r = 50\\,\\text{м}$ со скоростью $v = 20\\,\\text{м/с}$. Центростремительное ускорение:",
    hint: "$a = v^2/r$",
    unit: "м/с²", a: 8,
    ex: "$a = 400/50 = 8\\,\\text{м/с}^2$"
  },
  {
    q: "Если радиус окружности удвоить, а скорость оставить прежней, центростремительное ускорение:",
    opts: ["Удвоится", "Уменьшится в 2 раза", "Увеличится в 4 раза", "Не изменится"],
    a: 1,
    ex: "$a = v^2/r$. При удвоении $r$ ускорение уменьшается в 2 раза."
  },
  {
    q: "Точка на ободе колеса радиуса $r = 0{,}3\\,\\text{м}$ вращается с частотой $\\nu = 5\\,\\text{об/с}$. Центростремительное ускорение:",
    hint: "$v = 2\\pi r\\nu$, $a = v^2/r = 4\\pi^2 r \\nu^2$",
    unit: "м/с²", a: 296.1, tol: 0.03,
    ex: "$a = 4\\pi^2 \\cdot 0{,}3 \\cdot 25 \\approx 296\\,\\text{м/с}^2$"
  }
];

// ══ §15 Первый закон Ньютона ══
var TASKS_P15 = [
  {
    q: "Тело движется равномерно прямолинейно. Сила тяги $F_\text{тяга} = 80\,\text{Н}$. Чему равна сила трения?",
    hint: "$\\vec{F}_\\text{рез} = 0 \\Rightarrow F_\\text{тяга} = F_\\text{тр}$",
    unit: "Н", a: 80,
    ex: "При равномерном движении $a = 0$, значит $F_\\text{рез} = 0$: $F_\\text{тр} = F_\\text{тяга} = 80\\,\\text{Н}$."
  },
  {
    q: "Тело равномерно едет по горизонтальной поверхности. Сила сопротивления $F_\\text{сопр} = 200\\,\\text{Н}$. Чему равна сила тяги двигателя?",
    hint: "Равномерное движение: $\\vec{F}_\\text{рез} = 0$",
    unit: "Н", a: 200,
    ex: "При $a = 0$: $F_\\text{тяга} = F_\\text{сопр} = 200\\,\\text{Н}$."
  },
  {
    q: "Что такое инерция?",
    opts: [
      "Сила, действующая на тело при ускорении",
      "Свойство тела сохранять скорость в отсутствие сил или при скомпенсированных силах",
      "Ускорение тела под действием тяги",
      "Сила тяжести"
    ],
    a: 1,
    ex: "Инерция — свойство тела сохранять скорость (и её направление) при $\\vec{F}_\\text{рез} = 0$."
  },
  {
    q: "Пассажир в автобусе откидывается назад при резком старте. Причина?",
    opts: [
      "На пассажира действует сила тяги двигателя",
      "Пассажир обладает инерцией и стремится остаться в покое",
      "Реакция опоры уменьшилась",
      "Сила трения исчезает при ускорении"
    ],
    a: 1,
    ex: "Тело (пассажир) стремится сохранить исходное состояние покоя по инерции, пока автобус ускоряется вперёд."
  },
  {
    q: "Что такое инерциальная система отсчёта (ИСО)?",
    opts: [
      "Система отсчёта, связанная с покоящимся телом",
      "Система отсчёта, в которой выполняется первый закон Ньютона",
      "Система отсчёта, связанная с ускоряющимся телом",
      "Любая система отсчёта, связанная с Землёй"
    ],
    a: 1,
    ex: "ИСО — та, в которой тело без действия сил покоится или движется равномерно прямолинейно (1-й закон)."
  },
  {
    q: "Мяч брошен горизонтально. Какова равнодействующая всех сил во время полёта (без учёта сопротивления воздуха)?",
    opts: [
      "Равна нулю",
      "Равна силе тяжести, направлена вертикально вниз",
      "Равна начальной силе броска",
      "Равна силе нормального давления"
    ],
    a: 1,
    ex: "В полёте на мяч действует только сила тяжести (воздух не учитываем). $\\vec{F}_\\text{рез} = m\\vec{g}$ — вертикально вниз."
  },
  {
    q: "На тело одновременно действуют сила тяги $F_1 = 150\\,\\text{Н}$ вправо и сила трения $F_2 = 150\\,\\text{Н}$ влево. Каково ускорение тела?",
    opts: [
      "$a = 300/m$",
      "$a = 150/m$",
      "$a = 0$",
      "Зависит от массы тела"
    ],
    a: 2,
    ex: "$\\vec{F}_\\text{рез} = 150 - 150 = 0\\,\\text{Н}$, поэтому $a = 0$. Тело движется равномерно (или стоит)."
  },
  {
    q: "Теннисный мяч летит горизонтально. Никаких сил нет. Что произойдёт?",
    opts: [
      "Мяч начнёт ускоряться",
      "Мяч замедлится и остановится",
      "Мяч будет двигаться равномерно прямолинейно вечно",
      "Мяч упадёт под действием инерции"
    ],
    a: 2,
    ex: "По 1-му закону Ньютона: без сил $\\vec{F}_\\text{рез} = 0 \\Rightarrow a = 0$ — мяч движется равномерно прямолинейно."
  },
];

// ══ §16 Масса. Сила тяжести ══
var TASKS_P16 = [
  {
    q: "Найдите силу тяжести тела массой $m = 8\\,\\text{кг}$, $g = 10\\,\\text{м/с}^2$.",
    hint: "$F_\\text{т} = mg$",
    unit: "Н", a: 80,
    ex: "$F_\\text{т} = 8 \\cdot 10 = 80\\,\\text{Н}$"
  },
  {
    q: "Сила тяжести тела $F_\\text{т} = 250\\,\\text{Н}$, $g = 10\\,\\text{м/с}^2$. Найдите массу тела.",
    hint: "$m = F_\\text{т}/g$",
    unit: "кг", a: 25,
    ex: "$m = 250/10 = 25\\,\\text{кг}$"
  },
  {
    q: "Плотность вещества $\\rho = 2700\\,\\text{кг/м}^3$ (алюминий), объём $V = 0{,}002\\,\\text{м}^3$. Найдите массу тела.",
    hint: "$m = \\rho V$",
    unit: "кг", a: 5.4,
    ex: "$m = 2700 \\cdot 0{,}002 = 5{,}4\\,\\text{кг}$"
  },
  {
    q: "Масса тела $m = 10\\,\\text{кг}$. Найдите силу тяжести на Луне, где $g_\\text{Л} = 1{,}6\\,\\text{м/с}^2$.",
    hint: "$F_\\text{т} = mg_\\text{Л}$",
    unit: "Н", a: 16,
    ex: "$F_\\text{т} = 10 \\cdot 1{,}6 = 16\\,\\text{Н}$"
  },
  {
    q: "Что характеризует масса тела?",
    opts: [
      "Объём тела",
      "Меру инертности тела",
      "Силу тяжести тела",
      "Скорость тела"
    ],
    a: 1,
    ex: "Масса — количественная мера инертности: чем больше масса, тем труднее разогнать или затормозить тело."
  },
  {
    q: "Как изменится масса тела при перемещении с Земли на Луну?",
    opts: [
      "Уменьшится в 6 раз",
      "Увеличится в 6 раз",
      "Не изменится",
      "Зависит от скорости перемещения"
    ],
    a: 2,
    ex: "Масса — фундаментальная характеристика тела, не зависящая от гравитационного поля и положения."
  },
  {
    q: "Воздух в комнате $6 \\times 4 \\times 3\\,\\text{м}$, плотность воздуха $\\rho = 1{,}25\\,\\text{кг/м}^3$. Найдите массу воздуха в комнате.",
    hint: "$V = 6 \\cdot 4 \\cdot 3\\,\\text{м}^3$; $m = \\rho V$",
    unit: "кг", a: 90,
    ex: "$V = 72\\,\\text{м}^3$; $m = 1{,}25 \\cdot 72 = 90\\,\\text{кг}$"
  },
  {
    q: "Тело весит на Земле $F_\\text{т} = 600\\,\\text{Н}$. На Луне ($g_\\text{Л} = 1{,}6\\,\\text{м/с}^2$) сила тяжести равна?",
    hint: "Сначала найди массу: $m = F_\\text{т}/g$, затем $F_\\text{Л} = mg_\\text{Л}$",
    unit: "Н", a: 96,
    ex: "$m = 600/10 = 60\\,\\text{кг}$; $F_\\text{Л} = 60 \\cdot 1{,}6 = 96\\,\\text{Н}$"
  },
];

// ══ §17 Второй закон Ньютона ══
var TASKS_P17 = [
  {
    q: "Тело массой $m = 5\\,\\text{кг}$ движется с ускорением $a = 4\\,\\text{м/с}^2$. Найдите равнодействующую сил.",
    hint: "$F = ma$",
    unit: "Н", a: 20,
    ex: "$F = 5 \\cdot 4 = 20\\,\\text{Н}$"
  },
  {
    q: "На тело действует сила $F = 36\\,\\text{Н}$, ускорение $a = 4\\,\\text{м/с}^2$. Найдите массу тела.",
    hint: "$m = F/a$",
    unit: "кг", a: 9,
    ex: "$m = 36/4 = 9\\,\\text{кг}$"
  },
  {
    q: "Тело массой $m = 8\\,\\text{кг}$ тянут силой $F = 32\\,\\text{Н}$. Найдите ускорение тела (трение пренебречь).",
    hint: "$a = F/m$",
    unit: "м/с²", a: 4,
    ex: "$a = 32/8 = 4\\,\\text{м/с}^2$"
  },
  {
    q: "Тело массой $m = 10\\,\\text{кг}$: сила тяги $F_\\text{тяга} = 80\\,\\text{Н}$, сила трения $F_\\text{тр} = 30\\,\\text{Н}$. Найдите ускорение.",
    hint: "$F_\\text{рез} = F_\\text{тяга} - F_\\text{тр}$; $a = F_\\text{рез}/m$",
    unit: "м/с²", a: 5,
    ex: "$F_\\text{рез} = 80 - 30 = 50\\,\\text{Н}$; $a = 50/10 = 5\\,\\text{м/с}^2$"
  },
  {
    q: "Как изменится ускорение тела, если равнодействующую увеличить в 4 раза?",
    opts: [
      "Уменьшится в 4 раза",
      "Увеличится в 4 раза",
      "Увеличится в 2 раза",
      "Не изменится"
    ],
    a: 1,
    ex: "$a = F/m$: при $F' = 4F$ и $m = \\text{const}$ получаем $a' = 4F/m = 4a$."
  },
  {
    q: "Как изменится ускорение тела, если при постоянной силе массу уменьшить в 3 раза?",
    opts: [
      "Уменьшится в 3 раза",
      "Увеличится в 9 раз",
      "Увеличится в 3 раза",
      "Не изменится"
    ],
    a: 2,
    ex: "$a = F/m$: при $m' = m/3$ получаем $a' = F/(m/3) = 3F/m = 3a$."
  },
  {
    q: "Ракета массой $m = 500\\,\\text{кг}$. Сила тяги $F = 10000\\,\\text{Н}$ (вертикально вверх), $g = 10\\,\\text{м/с}^2$. Найдите ускорение ракеты.",
    hint: "$F_\\text{рез} = F_\\text{тяга} - mg$; $a = F_\\text{рез}/m$",
    unit: "м/с²", a: 10,
    ex: "$F_\\text{рез} = 10000 - 500 \\cdot 10 = 5000\\,\\text{Н}$; $a = 5000/500 = 10\\,\\text{м/с}^2$"
  },
  {
    q: "Сила $F = 1\\,\\text{Н}$ сообщает телу ускорение $a = 1\\,\\text{м/с}^2$. Какова масса тела?",
    hint: "$m = F/a$",
    unit: "кг", a: 1,
    ex: "$m = 1/1 = 1\\,\\text{кг}$. Именно так определяется единица «1 Ньютон»."
  },
  {
    q: "Автомобиль массой $m = 1000\\,\\text{кг}$ разгоняется с $v_0 = 0$ до $v = 20\\,\\text{м/с}$ за $\\Delta t = 10\\,\\text{с}$. Найдите силу тяги (трение пренебречь).",
    hint: "$a = \\Delta v/\\Delta t$; $F = ma$",
    unit: "Н", a: 2000,
    ex: "$a = 20/10 = 2\\,\\text{м/с}^2$; $F = 1000 \\cdot 2 = 2000\\,\\text{Н}$"
  },
];

// ══ §18 Третий закон Ньютона ══
var TASKS_P18 = [
  {
    q: "Тело A давит на тело B с силой $F = 120\\,\\text{Н}$. С какой силой тело B действует на тело A?",
    opts: [
      "$60\\,\\text{Н}$ в том же направлении",
      "$120\\,\\text{Н}$ в противоположном направлении",
      "$240\\,\\text{Н}$ в противоположном направлении",
      "Нулевая — B неподвижно"
    ],
    a: 1,
    ex: "По 3-му закону Ньютона: $|\\vec{F}_{A \\to B}| = |\\vec{F}_{B \\to A}| = 120\\,\\text{Н}$, силы противоположны."
  },
  {
    q: "Лошадь тянет телегу с силой $F = 500\\,\\text{Н}$. С какой силой телега действует на лошадь?",
    hint: "$\\vec{F}_{1\\to2} = -\\vec{F}_{2\\to1}$",
    unit: "Н", a: 500,
    ex: "По 3-му закону: $|\\vec{F}_{\\text{телега} \\to \\text{лошадь}}| = 500\\,\\text{Н}$ (противоположно направлению тяги)."
  },
  {
    q: "Чем отличаются силы пары по 3-му закону Ньютона от двух сил, уравновешивающих тело?",
    opts: [
      "Ничем не отличаются",
      "Силы пары 3-го закона приложены к разным телам и не могут уравновесить одно тело",
      "Силы пары 3-го закона всегда направлены в одну сторону",
      "Силы пары 3-го закона могут иметь разную природу"
    ],
    a: 1,
    ex: "Пара 3-го закона приложена к <b>разным</b> телам — они не компенсируют друг друга. Уравновешивающие силы приложены к <b>одному</b> телу."
  },
  {
    q: "Два конькобёжца стоят на льду и отталкиваются. Коньки не тормозят. Что произойдёт?",
    opts: [
      "Оба останутся на месте",
      "Более тяжёлый останется на месте",
      "Оба начнут двигаться в противоположных направлениях",
      "Только лёгкий начнёт двигаться"
    ],
    a: 2,
    ex: "По 3-му закону: силы равны, но направлены в разные стороны. Оба конькобёжца получат ускорение (разное, зависящее от массы)."
  },
  {
    q: "Что из перечисленного является примером применения 3-го закона Ньютона?",
    opts: [
      "Движение тела по инерции",
      "Прыжок с лодки на берег (лодка отплывает назад)",
      "Ускорение тела под действием силы",
      "Равновесие тела на опоре"
    ],
    a: 1,
    ex: "При прыжке человек отталкивается от лодки: человек действует на лодку, лодка с равной силой действует на человека — они расходятся в разные стороны."
  },
  {
    q: "Что означает принцип относительности Галилея?",
    opts: [
      "Скорость света одинакова во всех системах отсчёта",
      "Все тела падают с одинаковым ускорением",
      "Законы механики одинаковы во всех инерциальных системах отсчёта",
      "Масса тела не зависит от скорости"
    ],
    a: 2,
    ex: "Принцип Галилея: механические явления протекают одинаково в любой ИСО. Физику нельзя отличить, находясь внутри равномерно движущегося вагона."
  },
  {
    q: "Силы пары по 3-му закону Ньютона:",
    opts: [
      "Всегда разной природы",
      "Всегда одинаковой природы",
      "Могут быть разной природы",
      "Обе всегда направлены вниз"
    ],
    a: 1,
    ex: "Если тела взаимодействуют гравитационно — обе силы гравитационные. Если упруго — обе упругие. Природа сил в паре всегда одна."
  },
  {
    q: "Книга лежит на столе. Какие две силы образуют пару по 3-му закону Ньютона с силой тяжести книги $m\\vec{g}$?",
    opts: [
      "Сила реакции стола $\\vec{N}$ на книгу",
      "Сила тяжести Земли, с которой книга притягивает Землю к себе",
      "Давление воздуха на книгу",
      "Трение между книгой и столом"
    ],
    a: 1,
    ex: "Сила тяжести книги — Земля тянет книгу вниз. Парная сила — книга тянет Землю вверх с той же силой. Обе гравитационные, на разных телах."
  },
];

// ══ §19 Закон Гука ══
var TASKS_P19 = [
  {
    q: "Жёсткость пружины $k = 400\\,\\text{Н/м}$, деформация $\\Delta l = 0{,}05\\,\\text{м}$. Найдите силу упругости.",
    hint: "$F_\\text{упр} = k|\\Delta l|$",
    unit: "Н", a: 20,
    ex: "$F_\\text{упр} = 400 \\cdot 0{,}05 = 20\\,\\text{Н}$"
  },
  {
    q: "Сила упругости $F = 30\\,\\text{Н}$, жёсткость $k = 600\\,\\text{Н/м}$. Найдите деформацию пружины.",
    hint: "$\\Delta l = F/k$",
    unit: "м", a: 0.05,
    ex: "$\\Delta l = 30/600 = 0{,}05\\,\\text{м} = 5\\,\\text{см}$"
  },
  {
    q: "Пружина деформирована на $x = 0{,}08\\,\\text{м}$, сила упругости $F = 120\\,\\text{Н}$. Найдите жёсткость.",
    hint: "$k = F/\\Delta l$",
    unit: "Н/м", a: 1500,
    ex: "$k = 120/0{,}08 = 1500\\,\\text{Н/м}$"
  },
  {
    q: "На пружину жёсткостью $k = 100\\,\\text{Н/м}$ подвесили груз $m = 0{,}5\\,\\text{кг}$, $g = 10\\,\\text{м/с}^2$. Найдите деформацию пружины при равновесии.",
    hint: "$F_\\text{упр} = F_\\text{т} = mg$; $\\Delta l = mg/k$",
    unit: "м", a: 0.05,
    ex: "$\\Delta l = mg/k = 0{,}5 \\cdot 10 / 100 = 0{,}05\\,\\text{м}$"
  },
  {
    q: "Пружина жёсткостью $k = 200\\,\\text{Н/м}$ растянута силой $F = 50\\,\\text{Н}$. Найдите деформацию.",
    hint: "$\\Delta l = F/k$",
    unit: "м", a: 0.25,
    ex: "$\\Delta l = 50/200 = 0{,}25\\,\\text{м} = 25\\,\\text{см}$"
  },
  {
    q: "При какой деформации выполняется закон Гука?",
    opts: [
      "При любой деформации",
      "Только при пластической деформации",
      "Только при упругой деформации (не превышающей предела упругости)",
      "Только при деформациях сжатия"
    ],
    a: 2,
    ex: "Закон Гука выполняется для упругой деформации — когда тело возвращается к исходной форме. При пластической деформации закон нарушается."
  },
  {
    q: "Какова природа сил упругости?",
    opts: [
      "Гравитационная",
      "Электромагнитная",
      "Ядерная",
      "Термодинамическая"
    ],
    a: 1,
    ex: "Силы упругости обусловлены электромагнитным взаимодействием атомов и молекул тела при деформации."
  },
  {
    q: "Как изменится деформация пружины, если жёсткость увеличить в 2 раза при той же силе?",
    opts: [
      "Увеличится в 2 раза",
      "Уменьшится в 2 раза",
      "Не изменится",
      "Увеличится в 4 раза"
    ],
    a: 1,
    ex: "$\\Delta l = F/k$: при $k' = 2k$ → $\\Delta l' = F/(2k) = \\Delta l/2$ — уменьшится в 2 раза."
  },
  {
    q: "Груз $m = 2\\,\\text{кг}$, $g = 10\\,\\text{м/с}^2$ подвешен к пружине, удлинение $\\Delta l = 4\\,\\text{см} = 0{,}04\\,\\text{м}$. Найдите жёсткость пружины.",
    hint: "При равновесии: $F_\\text{упр} = mg$; $k = mg/\\Delta l$",
    unit: "Н/м", a: 500,
    ex: "$k = mg/\\Delta l = 2 \\cdot 10 / 0{,}04 = 500\\,\\text{Н/м}$"
  },
];

// ══ §20 Силы трения ══
var TASKS_P20 = [
  {
    q: "Коэффициент трения $\\mu = 0{,}4$, сила нормального давления $N = 150\\,\\text{Н}$. Найдите силу трения скольжения.",
    hint: "$F_\\text{тр} = \\mu N$",
    unit: "Н", a: 60,
    ex: "$F_\\text{тр} = 0{,}4 \\cdot 150 = 60\\,\\text{Н}$"
  },
  {
    q: "Сила трения $F_\\text{тр} = 45\\,\\text{Н}$, сила нормального давления $N = 150\\,\\text{Н}$. Найдите коэффициент трения.",
    hint: "$\\mu = F_\\text{тр}/N$",
    unit: "", a: 0.3, tol: 0.05,
    ex: "$\\mu = 45/150 = 0{,}3$"
  },
  {
    q: "Брусок массой $m = 5\\,\\text{кг}$ скользит по горизонтальной поверхности, $\\mu = 0{,}3$, $g = 10\\,\\text{м/с}^2$. Найдите силу трения скольжения.",
    hint: "На горизонтали: $N = mg$; $F_\\text{тр} = \\mu mg$",
    unit: "Н", a: 15,
    ex: "$N = 5 \\cdot 10 = 50\\,\\text{Н}$; $F_\\text{тр} = 0{,}3 \\cdot 50 = 15\\,\\text{Н}$"
  },
  {
    q: "Куда направлена сила трения скольжения?",
    opts: [
      "В направлении движения тела",
      "Перпендикулярно поверхности",
      "Против направления скорости скольжения",
      "Всегда вертикально вниз"
    ],
    a: 2,
    ex: "Сила трения скольжения всегда направлена противоположно скорости скольжения тела относительно поверхности."
  },
  {
    q: "Максимальная сила трения покоя при $\\mu_\\text{пок} = 0{,}5$, $N = 80\\,\\text{Н}$?",
    hint: "$F_\\text{тр.пок}^{max} = \\mu_\\text{пок} N$",
    unit: "Н", a: 40,
    ex: "$F_\\text{тр.пок}^{max} = 0{,}5 \\cdot 80 = 40\\,\\text{Н}$"
  },
  {
    q: "Тело движется равномерно. Сила тяги $F = 120\\,\\text{Н}$, масса $m = 30\\,\\text{кг}$, $g = 10\\,\\text{м/с}^2$. Найдите $\\mu$.",
    hint: "При $a=0$: $F_\\text{тяга} = F_\\text{тр} = \\mu mg$; $\\mu = F/(mg)$",
    unit: "", a: 0.4, tol: 0.05,
    ex: "$\\mu = F/(mg) = 120/(30 \\cdot 10) = 0{,}4$"
  },
  {
    q: "Зависит ли сила трения скольжения от площади соприкасающихся поверхностей?",
    opts: [
      "Да, больше площадь — больше трение",
      "Нет, не зависит от площади контакта",
      "Зависит, но только при малых скоростях",
      "Зависит при смазке"
    ],
    a: 1,
    ex: "Сила трения $F_\\text{тр} = \\mu N$ — не зависит от площади контакта. Это экспериментальный факт (при одинаковой нормальной силе)."
  },
  {
    q: "Тело массой $m = 10\\,\\text{кг}$ начали толкать силой $F = 20\\,\\text{Н}$. $\\mu_\\text{пок} = 0{,}3$, $g = 10\\,\\text{м/с}^2$. Тронется ли тело с места?",
    opts: [
      "Да, тронется — $F > F_\\text{тр.пок}^{max}$",
      "Нет, не тронется — $F < F_\\text{тр.пок}^{max}$",
      "Тронется только при $F = F_\\text{тр.пок}^{max}$",
      "Зависит от времени действия силы"
    ],
    a: 1,
    ex: "$F_\\text{тр.пок}^{max} = 0{,}3 \\cdot 10 \\cdot 10 = 30\\,\\text{Н}$. $F = 20\\,\\text{Н} < 30\\,\\text{Н}$ → тело не тронется."
  },
  {
    q: "Автомобиль $m = 800\\,\\text{кг}$ тормозит до остановки. $\\mu = 0{,}5$, $g = 10\\,\\text{м/с}^2$. Найдите тормозную силу.",
    hint: "$F_\\text{тр} = \\mu mg$",
    unit: "Н", a: 4000,
    ex: "$F_\\text{тр} = 0{,}5 \\cdot 800 \\cdot 10 = 4000\\,\\text{Н}$"
  },
];

// ══ §21 Движение тела под действием силы тяжести ══
var TASKS_P21 = [
  {
    q: "Тело падает свободно с высоты $h = 20\\,\\text{м}$, $g = 10\\,\\text{м/с}^2$. Найдите время падения.",
    hint: "$t = \\sqrt{2h/g}$",
    unit: "с", a: 2,
    ex: "$t = \\sqrt{2 \\cdot 20/10} = \\sqrt{4} = 2\\,\\text{с}$"
  },
  {
    q: "Тело падает свободно с высоты $h = 45\\,\\text{м}$, $g = 10\\,\\text{м/с}^2$. Найдите скорость тела у земли.",
    hint: "$v = \\sqrt{2gh}$",
    unit: "м/с", a: 30,
    ex: "$v = \\sqrt{2 \\cdot 10 \\cdot 45} = \\sqrt{900} = 30\\,\\text{м/с}$"
  },
  {
    q: "Тело падает $t = 3\\,\\text{с}$, $g = 10\\,\\text{м/с}^2$. Какое расстояние пролетело тело?",
    hint: "$y = gt^2/2$",
    unit: "м", a: 45,
    ex: "$y = 10 \\cdot 9/2 = 45\\,\\text{м}$"
  },
  {
    q: "Что такое свободное падение?",
    opts: [
      "Любое падение предмета с высоты",
      "Движение тела под действием только силы тяжести (без сопротивления воздуха)",
      "Падение в вакууме со скоростью $g$",
      "Равномерное движение вниз"
    ],
    a: 1,
    ex: "Свободное падение — движение тела, на которое действует <b>только сила тяжести</b> (воздух не учитывается)."
  },
  {
    q: "Шарик брошен горизонтально с высоты $h = 20\\,\\text{м}$ со скоростью $v_0 = 5\\,\\text{м/с}$, $g = 10\\,\\text{м/с}^2$. Найдите горизонтальную дальность полёта.",
    hint: "$t = \\sqrt{2h/g}$; $l = v_0 t$",
    unit: "м", a: 10,
    ex: "$t = \\sqrt{2 \\cdot 20/10} = 2\\,\\text{с}$; $l = 5 \\cdot 2 = 10\\,\\text{м}$"
  },
  {
    q: "Мяч брошен вертикально вверх со скоростью $v_0 = 30\\,\\text{м/с}$, $g = 10\\,\\text{м/с}^2$. Найдите максимальную высоту подъёма.",
    hint: "$H = v_0^2/(2g)$",
    unit: "м", a: 45,
    ex: "$H = 900/20 = 45\\,\\text{м}$"
  },
  {
    q: "Какова форма траектории тела, брошенного горизонтально (без учёта сопротивления воздуха)?",
    opts: [
      "Прямая линия",
      "Парабола",
      "Окружность",
      "Гипербола"
    ],
    a: 1,
    ex: "Горизонтальное движение равномерное ($x = v_0 t$), вертикальное — равноускоренное ($y = gt^2/2$). Исключая $t$: $y = gx^2/(2v_0^2)$ — уравнение параболы."
  },
  {
    q: "Тело падает $t = 5\\,\\text{с}$, $g = 10\\,\\text{м/с}^2$. Найдите скорость тела в момент удара о землю.",
    hint: "$v = gt$",
    unit: "м/с", a: 50,
    ex: "$v = g \\cdot t = 10 \\cdot 5 = 50\\,\\text{м/с}$"
  },
  {
    q: "Камешек бросают горизонтально с высоты $h = 1{,}25\\,\\text{м}$ над водой со скоростью $v_0 = 4\\,\\text{м/с}$, $g = 10\\,\\text{м/с}^2$. Найдите дальность полёта.",
    hint: "$t = \\sqrt{2h/g}$; $l = v_0 t$",
    unit: "м", a: 2,
    ex: "$t = \\sqrt{2 \\cdot 1{,}25/10} = \\sqrt{0{,}25} = 0{,}5\\,\\text{с}$; $l = 4 \\cdot 0{,}5 = 2\\,\\text{м}$"
  },
];

// ══ §22 Бросок тела под углом к горизонту ══
var TASKS_P22 = [
  {
    q: "Тело брошено под углом $\\alpha = 30°$ к горизонту с начальной скоростью $v_0 = 20\\,\\text{м/с}$, $g = 10\\,\\text{м/с}^2$. Найдите горизонтальную дальность полёта.",
    hint: "$L = v_0^2 \\sin 2\\alpha / g$",
    unit: "м", a: 34.6, tol: 0.5,
    ex: "$L = 20^2 \\cdot \\sin 60° / 10 = 400 \\cdot 0{,}866 / 10 \\approx 34{,}6\\,\\text{м}$"
  },
  {
    q: "При каком угле броска горизонтальная дальность полёта максимальна (без учёта сопротивления воздуха)?",
    opts: ["30°","45°","60°","90°"],
    a: 1,
    ex: "$L = v_0^2 \\sin 2\\alpha / g$ максимально при $\\sin 2\\alpha = 1$, то есть при $2\\alpha = 90°$, $\\alpha = 45°$."
  },
  {
    q: "Тело брошено под углом $45°$ к горизонту с $v_0 = 30\\,\\text{м/с}$, $g = 10\\,\\text{м/с}^2$. Найдите максимальную высоту подъёма.",
    hint: "$H = v_0^2 \\sin^2\\!\\alpha / (2g)$",
    unit: "м", a: 22.5,
    ex: "$H = 30^2 \\cdot \\sin^2 45° / 20 = 900 \\cdot 0{,}5 / 20 = 22{,}5\\,\\text{м}$"
  },
  {
    q: "Что происходит с горизонтальной составляющей скорости тела в полёте (без учёта воздуха)?",
    opts: [
      "Уменьшается под действием силы тяжести",
      "Не изменяется (остаётся постоянной)",
      "Сначала уменьшается, затем увеличивается",
      "Увеличивается"
    ],
    a: 1,
    ex: "Сила тяжести направлена вертикально и изменяет только вертикальную составляющую. Горизонтальная составляющая $v_x = v_0\\cos\\alpha = \\text{const}$."
  },
  {
    q: "Снаряд выпущен с $v_0 = 50\\,\\text{м/с}$ под углом $\\alpha = 60°$. Найдите полное время полёта. $g = 10\\,\\text{м/с}^2$.",
    hint: "$T = 2v_0\\sin\\alpha / g$",
    unit: "с", a: 8.66, tol: 0.1,
    ex: "$T = 2 \\cdot 50 \\cdot \\sin 60° / 10 = 100 \\cdot 0{,}866 / 10 \\approx 8{,}66\\,\\text{с}$"
  },
  {
    q: "Мяч брошен под углом $45°$ к горизонту, $v_0 = 10\\,\\text{м/с}$, $g = 10\\,\\text{м/с}^2$. Найдите горизонтальную дальность полёта.",
    hint: "$L = v_0^2 \\sin 2\\alpha / g$",
    unit: "м", a: 10,
    ex: "$L = 100 \\cdot \\sin 90° / 10 = 100/10 = 10\\,\\text{м}$"
  },
  {
    q: "Какова форма траектории тела, брошенного под углом к горизонту (без учёта воздуха)?",
    opts: ["Прямая линия","Окружность","Парабола","Эллипс"],
    a: 2,
    ex: "Горизонтально — равномерно ($x = v_0\\cos\\alpha\\cdot t$), вертикально — равноускоренно ($y = v_0\\sin\\alpha\\cdot t - gt^2/2$). Исключая $t$ — получаем уравнение параболы."
  },
  {
    q: "Тело брошено под углом $\\alpha = 90°$ (вертикально вверх) с $v_0 = 20\\,\\text{м/с}$, $g = 10\\,\\text{м/с}^2$. Найдите максимальную высоту подъёма.",
    hint: "$H = v_0^2 / (2g)$ при $\\alpha = 90°$",
    unit: "м", a: 20,
    ex: "$H = v_0^2 \\sin^2 90° / (2g) = 400 \\cdot 1 / 20 = 20\\,\\text{м}$"
  },
];

// ══ §23 Закон всемирного тяготения ══
var TASKS_P23 = [
  {
    q: "Расстояние между двумя телами уменьшили в 3 раза. Как изменилась сила тяготения между ними?",
    opts: [
      "Уменьшилась в 3 раза",
      "Увеличилась в 3 раза",
      "Увеличилась в 9 раз",
      "Уменьшилась в 9 раз"
    ],
    a: 2,
    ex: "$F = Gm_1m_2/r^2$. При $r' = r/3$: $F' = Gm_1m_2/(r/3)^2 = 9Gm_1m_2/r^2 = 9F$. Сила увеличилась в 9 раз."
  },
  {
    q: "Чему равна гравитационная постоянная $G$?",
    opts: [
      "$9{,}8\\,\\text{Н}{\\cdot}\\text{м}^2/\\text{кг}^2$",
      "$6{,}67 \\cdot 10^{-11}\\,\\text{Н}{\\cdot}\\text{м}^2/\\text{кг}^2$",
      "$3 \\cdot 10^8\\,\\text{Н}{\\cdot}\\text{м}^2/\\text{кг}^2$",
      "$1{,}67 \\cdot 10^{-27}\\,\\text{Н}{\\cdot}\\text{м}^2/\\text{кг}^2$"
    ],
    a: 1,
    ex: "$G = 6{,}67 \\cdot 10^{-11}\\,\\text{Н}{\\cdot}\\text{м}^2/\\text{кг}^2$ — гравитационная постоянная, измеренная Кавендишем в 1798 году."
  },
  {
    q: "Ускорение свободного падения на поверхности Луны $g_\\text{Л} \\approx 1{,}6\\,\\text{м/с}^2$. Масса тела $m = 60\\,\\text{кг}$. Найдите его вес на Луне.",
    hint: "$F_\\text{т} = mg$",
    unit: "Н", a: 96,
    ex: "$F_\\text{т} = 60 \\cdot 1{,}6 = 96\\,\\text{Н}$"
  },
  {
    q: "Как изменится сила тяготения между двумя телами, если массу одного из них увеличить в 4 раза, а расстояние увеличить в 2 раза?",
    opts: [
      "Увеличится в 4 раза",
      "Останется прежней",
      "Уменьшится в 2 раза",
      "Увеличится в 2 раза"
    ],
    a: 1,
    ex: "$F' = G(4m_1)m_2/(2r)^2 = 4Gm_1m_2/(4r^2) = Gm_1m_2/r^2 = F$. Сила не изменилась!"
  },
  {
    q: "Первая космическая скорость для Земли ($g = 9{,}8\\,\\text{м/с}^2$, $R = 6400\\,\\text{км}$). Найдите $v_1$ (в км/с).",
    hint: "$v_1 = \\sqrt{gR}$",
    unit: "км/с", a: 7.9, tol: 0.1,
    ex: "$v_1 = \\sqrt{9{,}8 \\cdot 6{,}4 \\cdot 10^6} = \\sqrt{6{,}27 \\cdot 10^7} \\approx 7920\\,\\text{м/с} \\approx 7{,}9\\,\\text{км/с}$"
  },
  {
    q: "Два шара массами $m_1 = 2\\,\\text{кг}$ и $m_2 = 5\\,\\text{кг}$ находятся на расстоянии $r = 1\\,\\text{м}$. Найдите силу тяготения между ними ($G = 6{,}67 \\cdot 10^{-11}$).",
    hint: "$F = Gm_1m_2/r^2$",
    unit: "нН", a: 0.667, tol: 0.05,
    ex: "$F = 6{,}67 \\cdot 10^{-11} \\cdot 2 \\cdot 5 / 1 = 6{,}67 \\cdot 10^{-10}\\,\\text{Н} = 0{,}667\\,\\text{нН}$"
  },
  {
    q: "Что такое первая космическая скорость?",
    opts: [
      "Скорость освобождения от гравитации Земли",
      "Минимальная скорость для орбитального полёта у поверхности Земли",
      "Скорость вращения Земли вокруг Солнца",
      "Скорость света в вакууме"
    ],
    a: 1,
    ex: "Первая космическая скорость — минимальная скорость для круговой орбиты у поверхности Земли: $v_1 = \\sqrt{gR} \\approx 7{,}9\\,\\text{км/с}$."
  },
  {
    q: "Ускорение свободного падения на поверхности планеты. Масса планеты увеличилась в 4 раза, радиус — в 2 раза. Как изменилось $g$?",
    opts: [
      "Не изменилось",
      "Увеличилось в 2 раза",
      "Уменьшилось в 2 раза",
      "Увеличилось в 4 раза"
    ],
    a: 0,
    ex: "$g = GM/R^2$. $g' = G(4M)/(2R)^2 = 4GM/(4R^2) = GM/R^2 = g$. Не изменилось!"
  },
];

// ══ §24 Вес тела. Невесомость ══
var TASKS_P24 = [
  {
    q: "Человек массой $m = 70\\,\\text{кг}$ стоит в лифте. Лифт движется вверх с ускорением $a = 2\\,\\text{м/с}^2$, $g = 10\\,\\text{м/с}^2$. Найдите вес человека.",
    hint: "$P = m(g + a)$",
    unit: "Н", a: 840,
    ex: "$P = 70 \\cdot (10 + 2) = 70 \\cdot 12 = 840\\,\\text{Н}$"
  },
  {
    q: "Человек массой $m = 70\\,\\text{кг}$ стоит в лифте. Лифт движется вниз с ускорением $a = 3\\,\\text{м/с}^2$, $g = 10\\,\\text{м/с}^2$. Найдите вес человека.",
    hint: "$P = m(g - a)$",
    unit: "Н", a: 490,
    ex: "$P = 70 \\cdot (10 - 3) = 70 \\cdot 7 = 490\\,\\text{Н}$"
  },
  {
    q: "При каком условии тело находится в состоянии невесомости?",
    opts: [
      "Тело движется с постоянной скоростью",
      "Тело движется только под действием силы тяжести (свободное падение)",
      "Тело находится на большой высоте, где нет воздуха",
      "Тело движется горизонтально"
    ],
    a: 1,
    ex: "Невесомость — состояние, при котором исчезает сила давления на опору. Наступает при свободном падении: тело движется только под действием силы тяжести, реакция опоры = 0."
  },
  {
    q: "Человек стоит на весах в лифте. Весы показывают $85\\,\\text{кг}$. Масса человека $70\\,\\text{кг}$, $g = 10\\,\\text{м/с}^2$. Найдите ускорение лифта.",
    hint: "$P = m(g+a) \\Rightarrow a = P/m - g$",
    unit: "м/с²", a: 2.14, tol: 0.1,
    ex: "$P = 85 \\cdot 10 = 850\\,\\text{Н}$; $a = P/m - g = 850/70 - 10 \\approx 12{,}14 - 10 \\approx 2{,}14\\,\\text{м/с}^2$ (вверх)"
  },
  {
    q: "Чем отличается вес тела от силы тяжести?",
    opts: [
      "Это одно и то же — оба равны $mg$",
      "Вес зависит от ускорения тела, сила тяжести — нет",
      "Сила тяжести зависит от ускорения, вес — нет",
      "Вес всегда больше силы тяжести"
    ],
    a: 1,
    ex: "Сила тяжести $F_\\text{т} = mg$ определяется только массой и $g$. Вес $P$ — сила, с которой тело давит на опору. При ускорении $P = m(g \\pm a)$."
  },
  {
    q: "Тело массой $m = 5\\,\\text{кг}$ брошено вертикально вниз. В полёте (без опоры) его вес равен:",
    opts: [
      "$50\\,\\text{Н}$",
      "$25\\,\\text{Н}$",
      "$0\\,\\text{Н}$ (невесомость)",
      "Зависит от скорости"
    ],
    a: 2,
    ex: "В свободном падении нет опоры, нет реакции опоры. Вес как сила давления на опору равен нулю — невесомость. Сила тяжести при этом остаётся $F_\\text{т} = mg = 50\\,\\text{Н}$."
  },
  {
    q: "Человек $m = 60\\,\\text{кг}$ в лифте. Лифт движется равномерно вниз. Найдите вес человека. $g = 10\\,\\text{м/с}^2$.",
    hint: "$a = 0 \\Rightarrow P = mg$",
    unit: "Н", a: 600,
    ex: "При равномерном движении $a = 0$: $P = mg = 60 \\cdot 10 = 600\\,\\text{Н}$ — такой же, как и в покое."
  },
  {
    q: "Почему космонавты на МКС испытывают невесомость, хотя на высоте 400 км гравитация составляет около 88% от земной?",
    opts: [
      "Потому что на такой высоте нет воздуха",
      "Потому что станция находится в постоянном свободном падении вокруг Земли",
      "Потому что вдали от Земли масса тел уменьшается",
      "Потому что на высоте 400 км сила тяжести обнуляется"
    ],
    a: 1,
    ex: "МКС и всё, что в ней, постоянно «падает» вокруг Земли (орбитальный полёт = свободное падение, только быстрое). Опора не давит на тело → $P = 0$ → невесомость."
  },
];

// ══ §25 Момент силы. Условия равновесия ══
var TASKS_P25 = [
  {
    q: "Что называется плечом силы?",
    opts: [
      "Расстояние от оси до точки приложения силы",
      "Кратчайшее расстояние от оси вращения до линии действия силы",
      "Проекция силы на ось",
      "Расстояние между двумя точками приложения сил"
    ],
    a: 1,
    ex: "Плечо силы — это <b>перпендикуляр</b> из оси вращения на линию действия силы (не до точки приложения!)."
  },
  {
    q: "Сила $F = 75\\,\\text{Н}$ приложена на расстоянии $l = 0{,}20\\,\\text{м}$ от оси. Найдите момент силы.",
    hint: "$M = F \\cdot l$",
    unit: "Н·м", a: 15,
    ex: "$M = 75 \\cdot 0{,}20 = 15\\,\\text{Н}\\cdot\\text{м}$"
  },
  {
    q: "Каковы оба условия равновесия тела?",
    opts: [
      "Тело покоится и не нагревается",
      "Векторная сумма сил = 0 и алгебраическая сумма моментов = 0",
      "Скорость = 0 и ускорение = 0",
      "Нет внешних сил"
    ],
    a: 1,
    ex: "1-е условие: $\\sum \\vec{F} = \\vec{0}$ (нет поступательного ускорения). 2-е условие: $\\sum M = 0$ (нет вращения)."
  },
  {
    q: "Момент силы $M = 24\\,\\text{Н}\\cdot\\text{м}$, плечо $l = 0{,}6\\,\\text{м}$. Найдите силу.",
    hint: "$F = M / l$",
    unit: "Н", a: 40,
    ex: "$F = 24 / 0{,}6 = 40\\,\\text{Н}$"
  },
  {
    q: "На рычаг действует сила $F = 50\\,\\text{Н}$, плечо $l = 0{,}4\\,\\text{м}$. Вычислите момент.",
    hint: "$M = F \\cdot l$",
    unit: "Н·м", a: 20,
    ex: "$M = 50 \\cdot 0{,}4 = 20\\,\\text{Н}\\cdot\\text{м}$"
  },
  {
    q: "Рычаг в равновесии: $F_1 = 40\\,\\text{Н}$, $l_1 = 0{,}3\\,\\text{м}$, $l_2 = 0{,}6\\,\\text{м}$. Найдите $F_2$.",
    hint: "$F_1 l_1 = F_2 l_2$",
    unit: "Н", a: 20,
    ex: "$F_2 = F_1 l_1 / l_2 = 40 \\cdot 0{,}3 / 0{,}6 = 20\\,\\text{Н}$"
  },
  {
    q: "Что надо увеличить, чтобы меньшей силой создать тот же момент?",
    opts: [
      "Массу тела",
      "Плечо силы",
      "Число точек приложения",
      "Скорость вращения"
    ],
    a: 1,
    ex: "$M = F \\cdot l$ — при том же $F$ увеличение плеча $l$ увеличивает момент. Поэтому у гаечных ключей длинные рукоятки."
  },
  {
    q: "Рычаг в равновесии: $F_1 = 60\\,\\text{Н}$, $l_1 = 0{,}5\\,\\text{м}$. Если $l_2 = 0{,}3\\,\\text{м}$, найдите $F_2$.",
    hint: "$F_1 l_1 = F_2 l_2$",
    unit: "Н", a: 100,
    ex: "$F_2 = 60 \\cdot 0{,}5 / 0{,}3 = 100\\,\\text{Н}$"
  },
];

// ══ §26 Рычаги и блоки ══
var TASKS_P26 = [
  {
    q: "Что называется выигрышем в силе?",
    opts: [
      "Разность сил $F_2 - F_1$",
      "Во сколько раз сила нагрузки больше приложенной силы ($F_2/F_1$)",
      "Отношение плеч $l_1/l_2$",
      "Ответы 2 и 3 верны"
    ],
    a: 3,
    ex: "Выигрыш в силе — это $F_2/F_1 = l_1/l_2$. Оба определения равнозначны (следуют из условия равновесия рычага)."
  },
  {
    q: "Рычаг: $l_1 = 0{,}8\\,\\text{м}$, $l_2 = 0{,}2\\,\\text{м}$, нагрузка $F_2 = 200\\,\\text{Н}$. Найдите нужную силу $F_1$.",
    hint: "$F_1 = F_2 \\cdot l_2 / l_1$",
    unit: "Н", a: 50,
    ex: "$F_1 = 200 \\cdot 0{,}2 / 0{,}8 = 50\\,\\text{Н}$. Выигрыш в силе = 4."
  },
  {
    q: "Что даёт неподвижный блок?",
    opts: [
      "Выигрыш в силе в 2 раза",
      "Только изменяет направление силы (выигрыш = 1)",
      "Выигрыш в работе",
      "Проигрыш в силе в 2 раза"
    ],
    a: 1,
    ex: "Неподвижный блок — лишь <b>изменяет направление</b>: тянем вниз, груз поднимается вверх. В силе выигрыша нет."
  },
  {
    q: "Подвижный блок: груз $G = 240\\,\\text{Н}$. Какую силу нужно приложить (без учёта масс блока и нити)?",
    hint: "Подвижный блок: $F = G/2$",
    unit: "Н", a: 120,
    ex: "Подвижный блок даёт выигрыш в 2 раза: $F = G/2 = 240/2 = 120\\,\\text{Н}$."
  },
  {
    q: "Рычаг: $l_1 = 1{,}5\\,\\text{м}$, $l_2 = 0{,}3\\,\\text{м}$. Во сколько раз выигрыш в силе?",
    hint: "Выигрыш $= l_1/l_2$",
    unit: "раз", a: 5,
    ex: "Выигрыш $= l_1/l_2 = 1{,}5/0{,}3 = 5$. Сила нужна в 5 раз меньше нагрузки."
  },
  {
    q: "Тело массой $m = 60\\,\\text{кг}$, $g = 10\\,\\text{м/с}^2$ надо поднять рычагом: $l_1 = 1{,}2\\,\\text{м}$, $l_2 = 0{,}3\\,\\text{м}$. Найдите нужную силу.",
    hint: "$F_1 = mg \\cdot l_2/l_1$",
    unit: "Н", a: 150,
    ex: "$F_1 = 60 \\cdot 10 \\cdot 0{,}3/1{,}2 = 150\\,\\text{Н}$. Выигрыш в силе = 4."
  },
  {
    q: "«Золотое правило механики» означает: нет выигрыша в...",
    opts: [
      "Силе",
      "Расстоянии",
      "Работе",
      "Скорости"
    ],
    a: 2,
    ex: "Любой механизм: $A_\\text{затр} \\geq A_\\text{пол}$. Выиграл в силе $n$ раз — проиграл в пути $n$ раз. Работа та же."
  },
  {
    q: "Какую силу надо приложить для подъёма груза $G = 400\\,\\text{Н}$ с помощью системы из двух подвижных блоков?",
    hint: "Два подвижных блока: выигрыш = 4",
    unit: "Н", a: 100,
    ex: "Каждый подвижный блок даёт выигрыш ×2. Два блока: $F = G/4 = 400/4 = 100\\,\\text{Н}$."
  },
];

// ══ §27 Наклонная плоскость. КПД ══
var TASKS_P27 = [
  {
    q: "Что показывает КПД механизма?",
    opts: [
      "Во сколько раз механизм выигрывает в силе",
      "Долю полезной работы от затраченной (в %)",
      "Мощность механизма",
      "Отношение скоростей"
    ],
    a: 1,
    ex: "$\\eta = A_\\text{пол}/A_\\text{затр} \\cdot 100\\%$ — КПД показывает, <b>какая доля работы используется с пользой</b>. Остаток — потери на трение и нагрев."
  },
  {
    q: "$A_\\text{полез} = 600\\,\\text{Дж}$, $A_\\text{затрач} = 800\\,\\text{Дж}$. Найдите КПД.",
    hint: "$\\eta = A_\\text{пол}/A_\\text{затр} \\cdot 100\\%$",
    unit: "%", a: 75,
    ex: "$\\eta = 600/800 \\cdot 100\\% = 75\\%$"
  },
  {
    q: "Наклонная плоскость: длина $l = 5\\,\\text{м}$, высота $h = 1\\,\\text{м}$. Во сколько раз выигрыш в силе?",
    hint: "Выигрыш $= l/h$",
    unit: "раз", a: 5,
    ex: "Выигрыш $= l/h = 5/1 = 5$. Нужная сила в 5 раз меньше веса груза (без трения)."
  },
  {
    q: "«Золотое правило»: если выигрываем в силе в 3 раза, то в пути...",
    opts: [
      "Тоже выигрываем в 3 раза",
      "Проигрываем в 3 раза (путь в 3 раза длиннее)",
      "Ничего не меняется",
      "Выигрываем в 9 раз"
    ],
    a: 1,
    ex: "Золотое правило: $F_1 \\cdot s_1 = F_2 \\cdot s_2$. Уменьшил силу в 3 раза → увеличил путь в 3 раза. Работа та же."
  },
  {
    q: "Груз $m = 30\\,\\text{кг}$ затащили по наклонной плоскости $l = 6\\,\\text{м}$, $h = 2\\,\\text{м}$, без трения. Найдите нужную силу.",
    hint: "$F = mg \\cdot h/l$",
    unit: "Н", a: 100,
    ex: "$F = 30 \\cdot 10 \\cdot 2/6 = 100\\,\\text{Н}$. Без трения: сила в $l/h = 3$ раза меньше веса."
  },
  {
    q: "$A_\\text{затрач} = 500\\,\\text{Дж}$, $\\eta = 80\\%$. Найдите полезную работу.",
    hint: "$A_\\text{пол} = \\eta \\cdot A_\\text{затр} / 100$",
    unit: "Дж", a: 400,
    ex: "$A_\\text{пол} = 0{,}80 \\cdot 500 = 400\\,\\text{Дж}$"
  },
  {
    q: "Может ли КПД механизма быть больше 100%?",
    opts: [
      "Да, при идеальном механизме",
      "Да, если нет трения",
      "Нет, КПД всегда меньше 100%",
      "Да, при использовании смазки"
    ],
    a: 2,
    ex: "КПД <b>никогда не превышает 100%</b>: полезная работа не может быть больше затраченной (закон сохранения энергии). Трение всегда «ворует» часть работы."
  },
  {
    q: "Груз $m = 20\\,\\text{кг}$ подняли по наклонной плоскости $l = 5\\,\\text{м}$, $h = 2\\,\\text{м}$, приложив силу $F = 100\\,\\text{Н}$. Найдите КПД.",
    hint: "$A_\\text{пол} = mgh$; $A_\\text{затр} = Fl$",
    unit: "%", a: 80,
    ex: "$A_\\text{пол} = 20\\cdot10\\cdot2 = 400\\,\\text{Дж}$; $A_\\text{затр} = 100\\cdot5 = 500\\,\\text{Дж}$; $\\eta = 400/500 \\cdot 100\\% = 80\\%$"
  },
];

// ══ §28 Центр тяжести. Виды равновесия ══
var TASKS_P28 = [
  {
    q: "Что такое центр тяжести тела?",
    opts: [
      "Геометрический центр тела",
      "Точка, через которую проходит равнодействующая всех сил тяжести, действующих на тело",
      "Точка наибольшей массы тела",
      "Точка опоры тела"
    ],
    a: 1,
    ex: "Центр тяжести — точка, через которую проходит равнодействующая всех сил тяжести. Для однородного тела совпадает с геометрическим центром."
  },
  {
    q: "Два тела массами $m_1 = 3\\,\\text{кг}$ и $m_2 = 7\\,\\text{кг}$ находятся на расстоянии $10\\,\\text{м}$ друг от друга. Найдите расстояние от первого тела до центра тяжести системы.",
    hint: "$x_c = m_2 \\cdot d / (m_1 + m_2)$",
    unit: "м", a: 7,
    ex: "$x_c = m_2 \\cdot d/(m_1+m_2) = 7 \\cdot 10/10 = 7\\,\\text{м}$ от первого тела (ЦТ ближе к тяжёлому)"
  },
  {
    q: "Какой вид равновесия у шарика, лежащего в сферической лунке?",
    opts: ["Неустойчивое","Устойчивое","Безразличное","Нейтральное"],
    a: 1,
    ex: "В лунке при отклонении возникает возвращающая сила. Центр тяжести поднимается при отклонении → при отпускании тело возвращается. Это устойчивое равновесие."
  },
  {
    q: "Какой вид равновесия у карандаша, поставленного на острие?",
    opts: ["Устойчивое","Безразличное","Неустойчивое","Вынужденное"],
    a: 2,
    ex: "Центр тяжести карандаша выше точки опоры. При малейшем отклонении равнодействующая сил не возвращает карандаш в вертикальное положение — он падает. Неустойчивое равновесие."
  },
  {
    q: "При каком условии тело, стоящее на наклонной поверхности, не опрокидывается?",
    opts: [
      "Масса тела достаточно велика",
      "Вертикаль через центр тяжести проходит внутри площади опоры",
      "Угол наклона не превышает 45°",
      "Трение между телом и поверхностью достаточно большое"
    ],
    a: 1,
    ex: "Тело не опрокидывается, если вертикальная прямая через ЦТ пересекает площадь опоры. Как только эта вертикаль выходит за её пределы — тело опрокидывается."
  },
  {
    q: "Как изменить устойчивость тела?",
    opts: [
      "Увеличить массу",
      "Понизить центр тяжести и расширить площадь опоры",
      "Повысить центр тяжести",
      "Уменьшить площадь опоры"
    ],
    a: 1,
    ex: "Устойчивость повышается при понижении ЦТ (меньше опрокидывающий момент) и расширении площади опоры (вертикаль через ЦТ труднее выходит за её пределы)."
  },
  {
    q: "Какой вид равновесия у однородного шара на горизонтальной плоскости?",
    opts: ["Устойчивое","Неустойчивое","Безразличное","Вынужденное"],
    a: 2,
    ex: "При любом перемещении шара по плоскости высота ЦТ не меняется. Тело остаётся в новом положении. Это безразличное равновесие."
  },
  {
    q: "Нижний конец стержня закреплён в шарнире. Стержень стоит вертикально (свободный конец вверху). Это равновесие:",
    opts: [
      "Устойчивое — центр тяжести внизу",
      "Неустойчивое — центр тяжести выше точки опоры",
      "Безразличное — центр тяжести у шарнира",
      "Невозможно определить"
    ],
    a: 1,
    ex: "Центр тяжести вертикального стержня находится выше точки опоры (шарнира). Малейшее отклонение — стержень падает. Неустойчивое равновесие."
  },
];

// ══ §29 Закон Архимеда. Плавание тел ══
var TASKS_P29 = [
  {
    q: "Тело объёмом $V = 200\\,\\text{см}^3$ полностью погружено в воду ($\\rho_\\text{в} = 1000\\,\\text{кг/м}^3$, $g = 10\\,\\text{м/с}^2$). Найдите архимедову силу.",
    hint: "$F_\\text{выт} = \\rho_\\text{ж} g V$",
    unit: "Н", a: 2,
    ex: "$V = 200\\,\\text{см}^3 = 2 \\cdot 10^{-4}\\,\\text{м}^3$; $F_\\text{выт} = 1000 \\cdot 10 \\cdot 2 \\cdot 10^{-4} = 2\\,\\text{Н}$"
  },
  {
    q: "Кусок льда плотностью $\\rho_\\text{л} = 900\\,\\text{кг/м}^3$ плавает в воде ($\\rho_\\text{в} = 1000$). Какая доля объёма льда находится под водой?",
    hint: "$V_\\text{погр}/V = \\rho_\\text{т}/\\rho_\\text{ж}$",
    unit: "%", a: 90,
    ex: "$V_\\text{погр}/V = \\rho_\\text{л}/\\rho_\\text{в} = 900/1000 = 0{,}9 = 90\\%$. Именно поэтому видна только верхушка айсберга."
  },
  {
    q: "Деревянный кубик плотностью $600\\,\\text{кг/м}^3$ плавает в воде. Потонет ли он в ртути ($\\rho_\\text{Hg} = 13600\\,\\text{кг/м}^3$)?",
    opts: [
      "Потонет — ртуть тяжелее дерева",
      "Будет плавать — ртуть тяжелее дерева, выталкивающая сила больше",
      "Зависит от размера кубика",
      "Зависит от температуры"
    ],
    a: 1,
    ex: "$\\rho_\\text{дерева} = 600 < \\rho_\\text{Hg} = 13600$ — тело плавает. В ртути дерево будет почти полностью над поверхностью: $V_\\text{погр}/V = 600/13600 \\approx 4{,}4\\%$."
  },
  {
    q: "Тело весит в воздухе $F_\\text{возд} = 50\\,\\text{Н}$, а в воде — $F_\\text{в воде} = 38\\,\\text{Н}$. Найдите архимедову силу.",
    hint: "$F_\\text{выт} = F_\\text{возд} - F_\\text{в воде}$",
    unit: "Н", a: 12,
    ex: "$F_\\text{выт} = 50 - 38 = 12\\,\\text{Н}$. Это прямой способ измерения архимедовой силы — взвешивание в жидкости."
  },
  {
    q: "От чего зависит архимедова сила?",
    opts: [
      "От материала тела и его формы",
      "От плотности жидкости и объёма погружённой части тела",
      "От глубины погружения тела",
      "От скорости движения тела в жидкости"
    ],
    a: 1,
    ex: "$F_\\text{выт} = \\rho_\\text{ж} g V_\\text{погр}$ зависит только от плотности жидкости и объёма погружённой части. Форма тела, материал и глубина — не имеют значения."
  },
  {
    q: "Тело плотностью $\\rho_\\text{т} = 800\\,\\text{кг/м}^3$ объёмом $V = 0{,}5\\,\\text{л}$ плавает в воде. Найдите объём погружённой части.",
    hint: "$V_\\text{погр} = V \\cdot \\rho_\\text{т}/\\rho_\\text{ж}$",
    unit: "л", a: 0.4,
    ex: "$V_\\text{погр}/V = \\rho_\\text{т}/\\rho_\\text{ж} = 800/1000 = 0{,}8$; $V_\\text{погр} = 0{,}5 \\cdot 0{,}8 = 0{,}4\\,\\text{л}$"
  },
  {
    q: "Камень объёмом $V = 100\\,\\text{см}^3$ и плотностью $\\rho_\\text{т} = 2500\\,\\text{кг/м}^3$ погружён в воду. Найдите его кажущийся вес в воде ($g = 10$).",
    hint: "$F_\\text{каж} = mg - F_\\text{выт}$",
    unit: "Н", a: 1.5,
    ex: "$m = \\rho_\\text{т}V = 2500 \\cdot 10^{-4} = 0{,}25\\,\\text{кг}$; $F_\\text{выт} = 1000 \\cdot 10 \\cdot 10^{-4} = 1\\,\\text{Н}$; $F = 2{,}5 - 1 = 1{,}5\\,\\text{Н}$"
  },
  {
    q: "Тело потонет в жидкости, если:",
    opts: [
      "$\\rho_\\text{тела} < \\rho_\\text{жидкости}$",
      "$\\rho_\\text{тела} = \\rho_\\text{жидкости}$",
      "$\\rho_\\text{тела} > \\rho_\\text{жидкости}$",
      "Тело всегда тонет"
    ],
    a: 2,
    ex: "При $\\rho_\\text{т} > \\rho_\\text{ж}$: $F_\\text{выт} < mg$ даже при полном погружении → тело тонет. При $\\rho_\\text{т} < \\rho_\\text{ж}$ — тело плавает. При $\\rho_\\text{т} = \\rho_\\text{ж}$ — нейтральная плавучесть."
  },
  {
    q: "Одно и то же тело взвесили в воде и в масле ($\\rho_\\text{масло} = 800\\,\\text{кг/м}^3$). В какой жидкости архимедова сила больше?",
    opts: [
      "В масле — оно более вязкое",
      "В воде — она плотнее масла",
      "Одинаковая в обоих случаях",
      "Зависит от формы тела"
    ],
    a: 1,
    ex: "$F_\\text{выт} = \\rho_\\text{ж} g V_\\text{погр}$. Объём тела одинаков, $g$ одинаково, но $\\rho_\\text{воды} = 1000 > \\rho_\\text{масло} = 800$ → в воде сила больше."
  },
];

// ══ §30 Плавание судов. Воздухоплавание ══
var TASKS_P30 = [
  {
    q: "Стальной корабль плавает, хотя сталь тяжелее воды. Почему?",
    opts: [
      "Потому что сталь при намокании становится легче",
      "Потому что средняя плотность корабля (металл + воздух внутри) меньше плотности воды",
      "Потому что вода выталкивает металлические объекты с большой силой",
      "Потому что скорость хода не даёт кораблю затонуть"
    ],
    a: 1,
    ex: "Внутри корпуса корабля — воздух. Средняя плотность (вся масса / весь объём корпуса) меньше плотности воды → корабль плавает."
  },
  {
    q: "Корабль водоизмещением $m = 5000\\,\\text{т}$ плавает в морской воде ($\\rho = 1025\\,\\text{кг/м}^3$, $g = 10\\,\\text{м/с}^2$). Найдите объём вытесненной воды.",
    hint: "$V = m/\\rho$",
    unit: "м³", a: 4878, tol: 50,
    ex: "$V = m/\\rho = 5{,}0 \\cdot 10^6 / 1025 \\approx 4878\\,\\text{м}^3$"
  },
  {
    q: "Как изменится осадка корабля при переходе из пресной воды в морскую (солёную)?",
    opts: [
      "Осадка увеличится",
      "Осадка уменьшится — плотность воды больше, выталкивающая сила при меньшей осадке та же",
      "Осадка не изменится",
      "Зависит от водоизмещения"
    ],
    a: 1,
    ex: "В морской воде ($\\rho = 1025$) при том же объёме погружённой части архимедова сила больше. Значит, нужен меньший объём → корабль всплывёт немного выше."
  },
  {
    q: "Воздушный шар объёмом $V = 200\\,\\text{м}^3$ заполнен горячим воздухом ($\\rho_\\text{гор} = 0{,}9\\,\\text{кг/м}^3$). Атмосферный воздух: $\\rho_\\text{атм} = 1{,}29\\,\\text{кг/м}^3$. Найдите максимальный вес полезного груза ($g = 10$).",
    hint: "$F_\\text{подъём} = (\\rho_\\text{атм} - \\rho_\\text{гор}) \\cdot g \\cdot V$",
    unit: "Н", a: 780,
    ex: "$(1{,}29 - 0{,}9) \\cdot 10 \\cdot 200 = 0{,}39 \\cdot 2000 = 780\\,\\text{Н}$ (без учёта массы оболочки)"
  },
  {
    q: "Что такое линия Плимсоля?",
    opts: [
      "Граница между килем и корпусом",
      "Метка на борту судна, указывающая максимально допустимую осадку",
      "Линия курса корабля на карте",
      "Граница прибоя у берега"
    ],
    a: 1,
    ex: "Линия Плимсоля — обязательная марка на корпусе судна. Показывает максимальную допустимую осадку в разных условиях (морская, тропическая, пресная вода)."
  },
  {
    q: "Деревянный ящик плотностью $\\rho = 600\\,\\text{кг/м}^3$ объёмом $0{,}1\\,\\text{м}^3$ плавает в воде. Найдите архимедову силу, действующую на него. $g = 10\\,\\text{м/с}^2$.",
    hint: "При плавании $F_\\text{выт} = mg = \\rho_\\text{т} g V$",
    unit: "Н", a: 600,
    ex: "При плавании $F_\\text{выт} = mg = \\rho_\\text{т} g V = 600 \\cdot 10 \\cdot 0{,}1 = 600\\,\\text{Н}$"
  },
  {
    q: "Как подводная лодка ныряет?",
    opts: [
      "Включает мощные двигатели и уходит вниз",
      "Заполняет балластные цистерны водой, увеличивая среднюю плотность",
      "Складывает паруса",
      "Открывает специальные клапаны снизу"
    ],
    a: 1,
    ex: "Балластные цистерны заполняются забортной водой → общая масса лодки растёт → средняя плотность превышает плотность воды → лодка тонет."
  },
  {
    q: "Дирижабль заполнен гелием ($\\rho_\\text{He} = 0{,}178\\,\\text{кг/м}^3$), объём $V = 5000\\,\\text{м}^3$. Плотность воздуха $1{,}29\\,\\text{кг/м}^3$. Найдите подъёмную силу ($g = 10$).",
    hint: "$F_\\text{подъём} = (\\rho_\\text{возд} - \\rho_\\text{газа}) g V$",
    unit: "кН", a: 55.6, tol: 1,
    ex: "$(1{,}29 - 0{,}178) \\cdot 10 \\cdot 5000 = 1{,}112 \\cdot 50000 = 55600\\,\\text{Н} = 55{,}6\\,\\text{кН}$"
  },
];

// ══════════════════════════════════════════════
//  ПУЛЫ — единая таблица
// ══════════════════════════════════════════════
const POOLS = {
  p1: TASKS_P1, p2: TASKS_P2, p3: TASKS_P3, p4: TASKS_P4, p5: TASKS_P5,
  p6: TASKS_P6, p7: TASKS_P7, p8: TASKS_P8, p9: TASKS_P9, p10: TASKS_P10,
  p11: TASKS_P11, p12: TASKS_P12, p13: TASKS_P13, p14: TASKS_P14,
  p15: TASKS_P15,
  p16: TASKS_P16,
  p17: TASKS_P17,
  p18: TASKS_P18,
  p19: TASKS_P19,
  p20: TASKS_P20,
  p21: TASKS_P21,
  p22: TASKS_P22,
  p23: TASKS_P23,
  p24: TASKS_P24,
  p25: TASKS_P25,
  p26: TASKS_P26,
  p27: TASKS_P27,
  p28: TASKS_P28,
  p29: TASKS_P29,
  p30: TASKS_P30,
  p31: TASKS_P31,
  p32: TASKS_P32,
  p33: TASKS_P33,
  p34: TASKS_P34,
  p35: TASKS_P35,
  p36: TASKS_P36,
  hard: TASKS_HARD,
};

// ══════════════════════════════════════════════
//  СОСТОЯНИЕ
// ══════════════════════════════════════════════
function mkState(pool) {
  return {idx:0, answered:false, results:Array(pool.length).fill(null), selections:Array(pool.length).fill(null)};
}
const STATE = {
  p1: mkState(TASKS_P1), p2: mkState(TASKS_P2), p3: mkState(TASKS_P3),
  p4: mkState(TASKS_P4), p5: mkState(TASKS_P5), p6: mkState(TASKS_P6),
  p7: mkState(TASKS_P7), p8: mkState(TASKS_P8), p9: mkState(TASKS_P9),
  p10: mkState(TASKS_P10), p11: mkState(TASKS_P11), p12: mkState(TASKS_P12),
  p13: mkState(TASKS_P13), p14: mkState(TASKS_P14),
  p15:  mkState(TASKS_P15),
  p16:  mkState(TASKS_P16),
  p17:  mkState(TASKS_P17),
  p18:  mkState(TASKS_P18),
  p19:  mkState(TASKS_P19),
  p20:  mkState(TASKS_P20),
  p21:  mkState(TASKS_P21),
  p22:  mkState(TASKS_P22),
  p23:  mkState(TASKS_P23),
  p24:  mkState(TASKS_P24),
  p25:  mkState(TASKS_P25),
  p26:  mkState(TASKS_P26),
  p27:  mkState(TASKS_P27),
  p28:  mkState(TASKS_P28),
  p29:  mkState(TASKS_P29),
  p30:  mkState(TASKS_P30),
  p31:  mkState(TASKS_P31),
  p32:  mkState(TASKS_P32),
  p33:  mkState(TASKS_P33),
  p34:  mkState(TASKS_P34),
  p35:  mkState(TASKS_P35),
  p36:  mkState(TASKS_P36),
  hard: mkState(TASKS_HARD),
};

// ══════════════════════════════════════════════
//  KaTeX рендеринг
// ══════════════════════════════════════════════
function doRender(el) {
  if (!window.renderMathInElement) return;
  renderMathInElement(el, {
    delimiters:[{left:'$',right:'$',display:false},{left:'\\[',right:'\\]',display:true}],
    throwOnError:false
  });
}

// ══════════════════════════════════════════════
//  ТАБЫ
// ══════════════════════════════════════════════
document.querySelectorAll('.tab').forEach(t => {
  t.addEventListener('click', () => {
    document.querySelectorAll('.tab').forEach(x => x.classList.remove('active'));
    document.querySelectorAll('.content').forEach(x => x.classList.remove('active'));
    t.classList.add('active');
    document.getElementById('tab-' + t.dataset.tab).classList.add('active');
    // Trigger canvas draws when switching to these tabs
    var tn = t.dataset.tab;
    if (tn === 'ref1') setTimeout(startAnim1, 60);
    else if (tn === 'ref2') setTimeout(function(){ upd2(); }, 60);
    else if (tn === 'ref3') setTimeout(function(){ upd3(); }, 60);
    else if (tn === 'ref4') setTimeout(function(){ upd4(); }, 60);
    else if (tn === 'ref5') setTimeout(function(){ upd5(); }, 60);
    else if (tn === 'ref6') setTimeout(function(){ upd6(); }, 60);
    else if (tn === 'ref7') setTimeout(function(){ upd7(); }, 60);
    else if (tn === 'ref8') setTimeout(function(){ upd8(); }, 60);
    else if (tn === 'ref9') setTimeout(function(){ upd9(); }, 60);
    else if (tn === 'ref10') setTimeout(function(){ upd10(); }, 60);
    else if (tn === 'ref11') setTimeout(function(){ upd11(); }, 60);
    else if (tn === 'ref12') setTimeout(function(){ upd12(); }, 60);
    else if (tn === 'ref13') setTimeout(function(){ upd13(); }, 60);
    else if (tn === 'ref14') setTimeout(function(){ upd14(); }, 60);
    else if (tn === 'ref15') setTimeout(startAnim15, 60);
    else if (tn === 'ref17') setTimeout(startAnim17, 60);
    else if (tn === 'ref18') setTimeout(startAnim18, 60);
    else if (tn === 'ref19') setTimeout(drawSpring19, 60);
    else if (tn === 'ref20') setTimeout(drawFriction20, 60);
    else if (tn === 'ref21') setTimeout(startAnim21, 60);
    else if (tn === 'ref22') setTimeout(function(){ upd22(); }, 60);
    else if (tn === 'ref23') setTimeout(function(){ upd23(); }, 60);
    else if (tn === 'ref24') setTimeout(function(){ upd24(); }, 60);
    else if (tn === 'ref25') setTimeout(function(){ upd25(); }, 60);
    else if (tn === 'ref26') setTimeout(function(){ upd26(); }, 60);
    else if (tn === 'ref27') setTimeout(function(){ upd27(); upd27mu(); }, 60);
    else if (tn === 'ref28') setTimeout(function(){ upd28(); }, 60);
    else if (tn === 'ref29') setTimeout(function(){ upd29(); }, 60);
    else if (tn === 'ref30') setTimeout(function(){ upd30(); }, 60);
  });
});

// ══════════════════════════════════════════════
//  CHAPTER NAVIGATION
// ══════════════════════════════════════════════
document.querySelectorAll('.ch-btn').forEach(function(btn) {
  btn.addEventListener('click', function() {
    document.querySelectorAll('.ch-btn').forEach(function(b) { b.classList.remove('active'); });
    document.querySelectorAll('.sec-group').forEach(function(g) { g.classList.remove('show'); });
    btn.classList.add('active');
    var grp = document.querySelector('.sec-group[data-chg="' + btn.dataset.ch + '"]');
    if (grp) {
      grp.classList.add('show');
      if (!grp.querySelector('.tab.active')) {
        var first = grp.querySelector('.tab');
        if (first) first.click();
      }
    }
  });
});

// ══════════════════════════════════════════════
//  ПЕРЕКЛЮЧАТЕЛЬ ПАРАГРАФОВ
// ══════════════════════════════════════════════
function setParaTab(para) {
  ['p1','p2','p3','p4','p5','p6','p7','p8','p9','p10','p11','p12','p13','p14','p15','p16','p17','p18','p19','p20','p21','p22','p23','p24','p25','p26','p27','p28','p29','p30','p31','p32','p33','p34','p35','p36','hard'].forEach(p => {
    const el = document.getElementById('ptab-' + p);
    if (el) el.style.display = p === para ? 'block' : 'none';
    document.querySelectorAll('.para-pill[data-para="' + p + '"]').forEach(b =>
      b.classList.toggle('active', p === para)
    );
  });
}

// ══════════════════════════════════════════════
//  НАВИГАЦИЯ
// ══════════════════════════════════════════════
function renderNav(sec) {
  const pool = POOLS[sec];
  const s = STATE[sec];
  const el = document.getElementById('navDots' + sec);
  if (!el) return;
  el.innerHTML = pool.map((_, i) => {
    let cls = 'nav-dot';
    if (i === s.idx)                cls += ' nd-cur';
    else if (s.results[i] === true) cls += ' nd-ok';
    else if (s.results[i] === false) cls += ' nd-fail';
    return `<button class="${cls}" onclick="goToTask('${sec}',${i})" title="Задача ${i+1}">${i+1}</button>`;
  }).join('');
}

function goToTask(sec, idx) {
  const s = STATE[sec];
  s.idx = idx;
  s.answered = s.results[idx] !== null;
  renderTask(sec);
}

// ══════════════════════════════════════════════
//  ОТРИСОВКА ЗАДАЧ (numeric + MCQ)
// ══════════════════════════════════════════════
function renderTask(sec) {
  const pool = POOLS[sec];
  const s = STATE[sec];
  const area = document.getElementById('taskArea' + sec);
  const fb   = document.getElementById('fb' + sec);
  const sum  = document.getElementById('sum' + sec);
  if (!area || !fb || !sum || !pool || !s) return;  // секция отсутствует на этой странице
  sum.classList.remove('show');

  const q = pool[s.idx];
  const done = s.results[s.idx] !== null;
  s.answered = done;
  const isMcq = !!q.opts;

  const paraBadge = q.para
    ? `<span class="para-badge ${q.para==='§1'?'b1':q.para==='§2'?'b2':q.para==='§3'?'b3':q.para==='§4'?'b4':q.para==='§5'?'b5':q.para==='§6'?'b6':q.para==='§7'?'b7':q.para==='§8'?'b8':q.para==='§9'?'b9':q.para==='§10'?'b10':q.para==='§11'?'b11':q.para==='§12'?'b12':q.para==='§13'?'b13':q.para==='§14'?'b14':q.para==='§22'?'b22':q.para==='§23'?'b23':q.para==='§24'?'b24':q.para==='§25'?'b25':q.para==='§26'?'b26':q.para==='§27'?'b27':q.para==='§28'?'b28':q.para==='§29'?'b29':q.para==='§30'?'b30':q.para==='§32'?'b32':q.para==='§33'?'b33':q.para==='§34'?'b34':q.para==='§35'?'b35':q.para==='§36'?'b36':''}">${q.para}</span>`
    : '';

  if (isMcq) {
    const selIdx = s.selections[s.idx];
    area.innerHTML = `
      <div class="task-card">
        <div class="task-num">Задача ${s.idx+1} из ${pool.length} · Тест${paraBadge}</div>
        <div class="task-text">${q.q}</div>
        <div class="mcq-opts">
          ${q.opts.map((opt, i) => {
            let cls = 'mcq-opt';
            if (done) {
              if (i === q.a) cls += ' mcq-cor';
              else if (i === selIdx) cls += ' mcq-wrong';
            }
            return `<button class="${cls}" id="mcqOpt${sec}_${i}"
              onclick="${done ? '' : `selectMcq('${sec}',${i})`}"
              ${done ? 'disabled' : ''}>
              <span style="font-weight:800;margin-right:6px">${String.fromCharCode(65+i)}.</span>${opt}
            </button>`;
          }).join('')}
        </div>
      </div>`;
  } else {
    area.innerHTML = `
      <div class="task-card">
        <div class="task-num">Задача ${s.idx+1} из ${pool.length}${paraBadge}</div>
        <div class="task-text">${q.q}</div>
        <div class="task-hint"><svg class="ic" viewBox="0 0 24 24" style="width:14px;height:14px;display:inline-block;vertical-align:-2px;stroke:currentColor;fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round"><path d="M9 18h6M10 22h4M12 2a7 7 0 0 0-4 13c1 1 2 2 2 4h4c0-2 1-3 2-4a7 7 0 0 0-4-13z"/></svg><span>${q.hint}</span></div>
        <div class="ans-row">
          <label style="font-weight:700;font-size:.88rem">Ответ:</label>
          <input class="ans-inp" type="text" id="ainp${sec}" placeholder="?"
            autocomplete="off"
            ${done ? `disabled style="border-color:var(--${s.results[s.idx] ? 'ok' : 'fail'})"` : ''}>
          <span class="unit-lbl">${q.unit}</span>
          ${done ? '' : `<button class="btn btn-pri" onclick="checkNum('${sec}')"><svg class="ic" viewBox="0 0 24 24" style="width:14px;height:14px;display:inline-block;vertical-align:-2px;stroke:currentColor;fill:none;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round"><polyline points="20 6 9 17 4 12"/></svg> Проверить</button>`}
        </div>
      </div>`;
  }

  if (done) {
    const ok = s.results[s.idx];
    fb.className = 'feedback show ' + (ok ? 'fb-ok' : 'fb-fail');
    if (isMcq) {
      fb.innerHTML = ok
        ? ` Верно!&ensp;${q.ex || ''}`
        : ` Неверно. Правильный ответ: <strong>${q.opts[q.a]}</strong>&ensp;${q.ex || ''}`;
    } else {
      fb.innerHTML = ok
        ? ` Верно!&ensp;${q.ex}`
        : ` Неверно. Правильный ответ: <strong>${q.a}&nbsp;${q.unit}</strong>&ensp;${q.ex}`;
    }
    document.getElementById('nextBtn' + sec).style.display = 'inline-flex';
    doRender(fb);
  } else {
    fb.className = 'feedback';
    document.getElementById('nextBtn' + sec).style.display = 'none';
  }

  updateScoreBar(sec);
  renderNav(sec);
  doRender(area);

  if (!done && !isMcq) {
    const inp = document.getElementById('ainp' + sec);
    setTimeout(() => inp && inp.focus(), 80);
    inp && inp.addEventListener('keydown', e => { if (e.key === 'Enter') checkNum(sec); });
  }
}

// ══════════════════════════════════════════════
//  ПРОВЕРКА MCQ
// ══════════════════════════════════════════════
function selectMcq(sec, i) {
  const s = STATE[sec];
  if (s.answered) return;
  const pool = POOLS[sec];
  const q = pool[s.idx];
  const ok = i === q.a;
  s.results[s.idx] = ok;
  s.selections[s.idx] = i;
  s.answered = true;
  updateScoreBar(sec);
  renderNav(sec);

  q.opts.forEach((_, j) => {
    const btn = document.getElementById(`mcqOpt${sec}_${j}`);
    if (!btn) return;
    btn.disabled = true;
    if (j === q.a) btn.classList.add('mcq-cor');
    else if (j === i && !ok) btn.classList.add('mcq-wrong');
  });

  const fb = document.getElementById('fb' + sec);
  fb.className = 'feedback show ' + (ok ? 'fb-ok' : 'fb-fail');
  fb.innerHTML = ok
    ? ` Верно!&ensp;${q.ex || ''}`
    : ` Неверно. Правильный ответ: <strong>${q.opts[q.a]}</strong>&ensp;${q.ex || ''}`;
  doRender(fb);
  document.getElementById('nextBtn' + sec).style.display = 'inline-flex';

  if (s.results.every(r => r !== null)) {
    setTimeout(() => showSummary(sec), 2200);
  }
}

// ══════════════════════════════════════════════
//  ПРОВЕРКА ЧИСЛОВЫХ
// ══════════════════════════════════════════════
function checkNum(sec) {
  const s = STATE[sec];
  if (s.answered) return;
  const pool = POOLS[sec];
  const q = pool[s.idx];
  const inp = document.getElementById('ainp' + sec);
  const fb  = document.getElementById('fb' + sec);
  const val = inp.value.trim().replace(',', '.');
  const num = parseFloat(val);

  if (!val || isNaN(num)) {
    fb.className = 'feedback show fb-fail';
    fb.innerHTML = ' Введите числовой ответ!';
    return;
  }

  s.answered = true;
  // Относительная погрешность 3%, для нуля — абсолютная 0.05
  const tol = q.tol !== undefined ? q.tol : 0.03;
  const ok = q.a === 0
    ? Math.abs(num) < 0.05
    : Math.abs((num - q.a) / q.a) < tol;
  s.results[s.idx] = ok;
  updateScoreBar(sec);
  renderNav(sec);

  inp.disabled = true;
  inp.style.borderColor = ok ? 'var(--ok)' : 'var(--fail)';

  fb.className = 'feedback show ' + (ok ? 'fb-ok' : 'fb-fail');
  fb.innerHTML = ok
    ? ` Верно!&ensp;${q.ex}`
    : ` Неверно. Правильный ответ: <strong>${q.a}&nbsp;${q.unit}</strong>&ensp;${q.ex}`;
  doRender(fb);
  document.getElementById('nextBtn' + sec).style.display = 'inline-flex';

  if (s.results.every(r => r !== null)) {
    setTimeout(() => showSummary(sec), 2200);
  }
}

// Обратная совместимость — старый вызов check(sec) из HTML уже заменён, но на случай остатков:
function check(sec) { checkNum(sec); }

// ══════════════════════════════════════════════
//  ИНТЕРАКТИВНЫЕ СХЕМЫ
// ══════════════════════════════════════════════

// ── §1 — Анимация: виды движения ──────────────────────────
var anim1Id = null;
function startAnim1() {
  var cv = document.getElementById('cv1');
  if (!cv || cv.offsetWidth === 0) return;
  if (anim1Id) { cancelAnimationFrame(anim1Id); anim1Id = null; }
  var dpr = window.devicePixelRatio || 1;
  var W = cv.offsetWidth, H = cv.offsetHeight || 160;
  cv.width = Math.round(W * dpr); cv.height = Math.round(H * dpr);
  var ctx = cv.getContext('2d');
  ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
  var t = 0;
  function frame() {
    t += 0.018;
    var dark = document.body.classList.contains('dark');
    ctx.fillStyle = dark ? '#1e293b' : '#f8fafc';
    ctx.fillRect(0, 0, W, H);
    ctx.font = '11px Inter,sans-serif';
    // Row 1: uniform
    var y1 = H * 0.23;
    ctx.fillStyle = dark ? '#94a3b8' : '#475569';
    ctx.fillText('Равномерное  (v = const)', 6, y1 - 9);
    ctx.strokeStyle = dark ? '#334155' : '#e2e8f0'; ctx.lineWidth = 1;
    ctx.beginPath(); ctx.moveTo(0, y1); ctx.lineTo(W, y1); ctx.stroke();
    var x1 = ((t * 65) % (W + 22)) - 11;
    ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6');
    ctx.beginPath(); ctx.arc(x1, y1 - 11, 9, 0, 2*Math.PI); ctx.fill();
    // Row 2: accelerated
    var y2 = H * 0.57;
    ctx.fillStyle = dark ? '#94a3b8' : '#475569';
    ctx.fillText('Равноускоренное  (a > 0)', 6, y2 - 9);
    ctx.strokeStyle = dark ? '#334155' : '#e2e8f0';
    ctx.beginPath(); ctx.moveTo(0, y2); ctx.lineTo(W, y2); ctx.stroke();
    var ph2 = (t * 0.55) % 2.2;
    var x2 = ph2 * ph2 * W * 0.21;
    ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981');
    ctx.beginPath(); ctx.arc(Math.min(x2, W+9), y2 - 11, 9, 0, 2*Math.PI); ctx.fill();
    // Row 3: decelerated
    var y3 = H * 0.91;
    ctx.fillStyle = dark ? '#94a3b8' : '#475569';
    ctx.fillText('Равнозамедленное  (a < 0)', 6, y3 - 9);
    ctx.strokeStyle = dark ? '#334155' : '#e2e8f0';
    ctx.beginPath(); ctx.moveTo(0, y3); ctx.lineTo(W, y3); ctx.stroke();
    var ph3 = (t * 0.55) % 2.2;
    var x3 = W * (2*ph3 - 0.45*ph3*ph3) * 0.22;
    ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.acceleration:'#f97316');
    ctx.beginPath(); ctx.arc(Math.min(x3, W+9), y3 - 11, 9, 0, 2*Math.PI); ctx.fill();
    anim1Id = requestAnimationFrame(frame);
  }
  frame();
}

// ── §2 — Относительность движения ─────────────────────────
function upd2() {
  var cv = document.getElementById('cv2');
  if (!cv) return;
  var dpr = window.devicePixelRatio || 1;
  var W = cv.offsetWidth || 420, H = cv.offsetHeight || 160;
  cv.width = Math.round(W*dpr); cv.height = Math.round(H*dpr);
  var ctx = cv.getContext('2d');
  ctx.setTransform(dpr,0,0,dpr,0,0);
  var vp = +(document.getElementById('sl2v') ? document.getElementById('sl2v').value : 5);
  var vt = 20;
  var dark = document.body.classList.contains('dark');
  ctx.fillStyle = dark ? '#1e293b' : '#f0f9ff';
  ctx.fillRect(0,0,W,H);
  // Ground
  var gy = H*0.88;
  ctx.strokeStyle = dark ? '#475569' : '#94a3b8'; ctx.lineWidth = 2;
  ctx.beginPath(); ctx.moveTo(0,gy); ctx.lineTo(W,gy); ctx.stroke();
  ctx.strokeStyle = dark ? '#475569' : '#cbd5e1'; ctx.lineWidth = 1;
  for (var xi = 0; xi < W; xi += 30) {
    ctx.beginPath(); ctx.moveTo(xi,gy); ctx.lineTo(xi+12,gy+6); ctx.stroke();
  }
  // Train body
  var tx = W*0.1, tw = W*0.6, th = 44, ty = gy - th - 8;
  ctx.fillStyle = dark ? '#1e3a5f' : '#dbeafe';
  ctx.strokeStyle = dark ? '#3b82f6' : '#1d4ed8'; ctx.lineWidth = 2;
  ctx.beginPath(); roundRect(ctx, tx, ty, tw, th, 8); ctx.fill(); ctx.stroke();
  // Wheels
  [tx+18, tx+tw-18].forEach(function(wx) {
    ctx.fillStyle = dark ? '#475569' : '#64748b';
    ctx.beginPath(); ctx.arc(wx, gy-4, 8, 0, 2*Math.PI); ctx.fill();
    ctx.fillStyle = '#fff'; ctx.beginPath(); ctx.arc(wx, gy-4, 3, 0, 2*Math.PI); ctx.fill();
  });
  // Train label
  ctx.font = 'bold 11px Inter,sans-serif';
  ctx.fillStyle = dark ? '#93c5fd' : '#1d4ed8';
  ctx.fillText('Поезд: v₁ = '+vt+' м/с', tx+8, ty+16);
  // Passenger dot
  var px = tx + tw*0.5;
  ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444');
  ctx.beginPath(); ctx.arc(px, ty+th*0.5+2, 11, 0, 2*Math.PI); ctx.fill();
  ctx.font = 'bold 9px Inter,sans-serif'; ctx.fillStyle = '#fff';
  ctx.textAlign = 'center';
  ctx.fillText('+'+vp, px, ty+th*0.5+6); ctx.textAlign = 'left';
  // Arrow: absolute speed
  var ay = ty - 12, scale = (W*0.7) / (vt + 10);
  var aLen = (vt + vp) * scale;
  ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981'); ctx.lineWidth = 2.5;
  ctx.beginPath(); ctx.moveTo(tx, ay); ctx.lineTo(tx + aLen, ay); ctx.stroke();
  ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981');
  ctx.beginPath(); ctx.moveTo(tx+aLen,ay); ctx.lineTo(tx+aLen-8,ay-5); ctx.lineTo(tx+aLen-8,ay+5); ctx.fill();
  ctx.font = '11px Inter,sans-serif';
  ctx.fillText('v_пас = '+vt+'+'+vp+' = '+(vt+vp)+' м/с', tx, ay - 5);
  var el = document.getElementById('res2');
  if (el) el.textContent = 'Скорость относительно земли = ' + (vt+vp) + ' м/с';
  var ev = document.getElementById('v2v');
  if (ev) ev.textContent = vp + ' м/с';
}
function roundRect(ctx, x, y, w, h, r) {
  ctx.beginPath();
  ctx.moveTo(x+r,y); ctx.lineTo(x+w-r,y); ctx.quadraticCurveTo(x+w,y,x+w,y+r);
  ctx.lineTo(x+w,y+h-r); ctx.quadraticCurveTo(x+w,y+h,x+w-r,y+h);
  ctx.lineTo(x+r,y+h); ctx.quadraticCurveTo(x,y+h,x,y+h-r);
  ctx.lineTo(x,y+r); ctx.quadraticCurveTo(x,y,x+r,y); ctx.closePath();
}

// ── §3 — Сложение векторов ─────────────────────────────────
function upd3() {
  var cv = document.getElementById('cv3');
  if (!cv) return;
  var dpr = window.devicePixelRatio || 1;
  var W = cv.offsetWidth || 420, H = cv.offsetHeight || 180;
  cv.width = Math.round(W*dpr); cv.height = Math.round(H*dpr);
  var ctx = cv.getContext('2d');
  ctx.setTransform(dpr,0,0,dpr,0,0);
  var a = +(document.getElementById('sl3a') ? document.getElementById('sl3a').value : 60);
  var b = +(document.getElementById('sl3b') ? document.getElementById('sl3b').value : 50);
  var ang = +(document.getElementById('sl3ang') ? document.getElementById('sl3ang').value : 60);
  var angR = ang * Math.PI / 180;
  var dark = document.body.classList.contains('dark');
  ctx.fillStyle = dark ? '#1e293b' : '#f8fafc';
  ctx.fillRect(0,0,W,H);
  var ox = W*0.18, oy = H*0.65, sc = (W*0.55) / 120;
  // Vector a (horizontal)
  var ax = a * sc, ay = 0;
  drawArrow3(ctx,ox,oy,ox+ax,oy+ay,(window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6'), 'a='+a, true, dark);
  // Vector b (at angle)
  var bx = b*sc*Math.cos(angR), by = -b*sc*Math.sin(angR);
  drawArrow3(ctx,ox,oy,ox+bx,oy+by,(window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'), 'b='+b, true, dark);
  // Result vector (parallelogram diagonal)
  var rx = ax+bx, ry = ay+by;
  var cLen = Math.sqrt(rx*rx+ry*ry)/sc;
  drawArrow3(ctx,ox,oy,ox+rx,oy+ry,(window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981'), 'c='+cLen.toFixed(1), false, dark);
  // Dashed parallelogram lines
  ctx.strokeStyle = dark ? '#475569' : '#cbd5e1'; ctx.lineWidth = 1;
  ctx.setLineDash([4,3]);
  ctx.beginPath(); ctx.moveTo(ox+ax,oy+ay); ctx.lineTo(ox+rx,oy+ry); ctx.stroke();
  ctx.beginPath(); ctx.moveTo(ox+bx,oy+by); ctx.lineTo(ox+rx,oy+ry); ctx.stroke();
  ctx.setLineDash([]);
  var el3a=document.getElementById('v3a'); if(el3a) el3a.textContent=a;
  var el3b=document.getElementById('v3b'); if(el3b) el3b.textContent=b;
  var el3ang=document.getElementById('v3ang'); if(el3ang) el3ang.textContent=ang+'°';
  var el = document.getElementById('res3');
  if (el) { el.textContent = '|c| = √(a²+b²+2ab·cos α) = ' + cLen.toFixed(2); doRender(el); }
}
function drawArrow3(ctx, x1, y1, x2, y2, col, lbl, dashed, dark) {
  ctx.strokeStyle = col; ctx.lineWidth = dashed ? 2 : 3;
  if (dashed) { ctx.setLineDash([]); }
  ctx.beginPath(); ctx.moveTo(x1,y1); ctx.lineTo(x2,y2); ctx.stroke();
  var ang = Math.atan2(y2-y1,x2-x1);
  ctx.fillStyle = col;
  ctx.beginPath(); ctx.moveTo(x2,y2);
  ctx.lineTo(x2-10*Math.cos(ang-0.4),y2-10*Math.sin(ang-0.4));
  ctx.lineTo(x2-10*Math.cos(ang+0.4),y2-10*Math.sin(ang+0.4));
  ctx.fill();
  var mx = (x1+x2)/2, my = (y1+y2)/2 - 10;
  ctx.font = 'bold 11px Inter,sans-serif'; ctx.fillStyle = col;
  ctx.fillText(lbl, mx, my);
}

// ── §4 — Проекции вектора ──────────────────────────────────
function upd4() {
  var cv = document.getElementById('cv4');
  if (!cv) return;
  var dpr = window.devicePixelRatio || 1;
  var W = cv.offsetWidth || 420, H = cv.offsetHeight || 160;
  cv.width = Math.round(W*dpr); cv.height = Math.round(H*dpr);
  var ctx = cv.getContext('2d');
  ctx.setTransform(dpr,0,0,dpr,0,0);
  var phi = +(document.getElementById('sl4phi') ? document.getElementById('sl4phi').value : 37);
  var am = +(document.getElementById('sl4a') ? document.getElementById('sl4a').value : 70);
  var phiR = phi * Math.PI / 180;
  var dark = document.body.classList.contains('dark');
  ctx.fillStyle = dark ? '#1e293b' : '#f8fafc';
  ctx.fillRect(0,0,W,H);
  var ox = W*0.18, oy = H*0.72, sc = (W*0.6)/120;
  var vx = am*sc*Math.cos(phiR), vy = -am*sc*Math.sin(phiR);
  // Axes
  ctx.strokeStyle = dark ? '#475569' : '#94a3b8'; ctx.lineWidth = 1;
  ctx.beginPath(); ctx.moveTo(ox-10,oy); ctx.lineTo(ox+W*0.72,oy); ctx.stroke();
  ctx.beginPath(); ctx.moveTo(ox,oy+10); ctx.lineTo(ox,oy-H*0.7); ctx.stroke();
  ctx.fillStyle = dark ? '#94a3b8' : '#475569'; ctx.font = '11px Inter,sans-serif';
  ctx.fillText('x', ox+W*0.72-6, oy+14); ctx.fillText('y', ox+4, oy-H*0.7+12);
  // Vector
  ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6'); ctx.lineWidth = 2.5;
  ctx.beginPath(); ctx.moveTo(ox,oy); ctx.lineTo(ox+vx,oy+vy); ctx.stroke();
  ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6');
  var ang = Math.atan2(vy,vx);
  ctx.beginPath(); ctx.moveTo(ox+vx,oy+vy);
  ctx.lineTo(ox+vx-9*Math.cos(ang-0.4),oy+vy-9*Math.sin(ang-0.4));
  ctx.lineTo(ox+vx-9*Math.cos(ang+0.4),oy+vy-9*Math.sin(ang+0.4)); ctx.fill();
  ctx.fillText('a='+am, ox+vx/2-8, oy+vy/2-8);
  // Projection lines dashed
  ctx.strokeStyle = dark ? '#475569' : '#cbd5e1'; ctx.lineWidth = 1.2; ctx.setLineDash([4,3]);
  ctx.beginPath(); ctx.moveTo(ox+vx,oy+vy); ctx.lineTo(ox+vx,oy); ctx.stroke();
  ctx.beginPath(); ctx.moveTo(ox+vx,oy+vy); ctx.lineTo(ox,oy+vy); ctx.stroke();
  ctx.setLineDash([]);
  // Projection arrows
  ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.lineWidth = 2;
  ctx.beginPath(); ctx.moveTo(ox,oy); ctx.lineTo(ox+vx,oy); ctx.stroke();
  ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.font = 'bold 11px Inter,sans-serif';
  var axVal = (am*Math.cos(phiR)).toFixed(1);
  ctx.fillText('ax='+axVal, ox+vx/2-10, oy+16);
  ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.warn:'#f59e0b'); ctx.lineWidth = 2;
  ctx.beginPath(); ctx.moveTo(ox,oy); ctx.lineTo(ox,oy+vy); ctx.stroke();
  ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.warn:'#f59e0b');
  var ayVal = (am*Math.sin(phiR)).toFixed(1);
  ctx.fillText('ay='+ayVal, ox+6, oy+vy/2);
  // Angle arc
  ctx.strokeStyle = '#8b5cf6'; ctx.lineWidth = 1.5;
  ctx.beginPath(); ctx.arc(ox,oy,28,0,-phiR,true); ctx.stroke();
  ctx.fillStyle = '#8b5cf6'; ctx.font = '11px Inter,sans-serif';
  ctx.fillText('φ='+phi+'°', ox+30, oy-8);
  var el4phi=document.getElementById('v4phi'); if(el4phi) el4phi.textContent=phi+'°';
  var el4a=document.getElementById('v4a'); if(el4a) el4a.textContent=am;
  var el = document.getElementById('res4');
  if (el) el.textContent = 'ax = '+axVal+',  ay = '+ayVal;
}

// ── §5 — Путь и перемещение ───────────────────────────────
function upd5() {
  var cv = document.getElementById('cv5');
  if (!cv) return;
  var dpr = window.devicePixelRatio || 1;
  var W = cv.offsetWidth || 420, H = cv.offsetHeight || 130;
  cv.width = Math.round(W*dpr); cv.height = Math.round(H*dpr);
  var ctx = cv.getContext('2d');
  ctx.setTransform(dpr,0,0,dpr,0,0);
  var s1 = +(document.getElementById('sl5s1') ? document.getElementById('sl5s1').value : 120);
  var s2 = +(document.getElementById('sl5s2') ? document.getElementById('sl5s2').value : 60);
  var dark = document.body.classList.contains('dark');
  ctx.fillStyle = dark ? '#1e293b' : '#f8fafc';
  ctx.fillRect(0,0,W,H);
  var pad = W*0.08, sc = (W*0.84)/(s1+50);
  var y = H*0.48, r = 8;
  // Start point A
  var xa = pad, xb = pad + s1*sc, xc = pad + (s1-s2)*sc;
  // Draw detour arc (path above)
  ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.lineWidth = 2.5;
  ctx.beginPath();
  ctx.moveTo(xa,y); ctx.quadraticCurveTo((xa+xb)/2, y-38, xb, y);
  ctx.stroke();
  ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.font = '11px Inter,sans-serif';
  ctx.fillText('Путь s₁='+s1+' м', (xa+xb)/2-24, y-42);
  // Return path (dashed below)
  ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.acceleration:'#f97316'); ctx.lineWidth = 2; ctx.setLineDash([5,3]);
  ctx.beginPath(); ctx.moveTo(xb,y); ctx.lineTo(xc,y); ctx.stroke();
  ctx.setLineDash([]);
  ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.acceleration:'#f97316');
  ctx.fillText('s₂='+s2, (xb+xc)/2-10, y+18);
  // Displacement arrow
  ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6'); ctx.lineWidth = 2.5;
  ctx.beginPath(); ctx.moveTo(xa, y+30); ctx.lineTo(xc-4, y+30); ctx.stroke();
  ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6');
  var disp = s1-s2;
  ctx.beginPath(); ctx.moveTo(xc,y+30); ctx.lineTo(xc-10,y+25); ctx.lineTo(xc-10,y+35); ctx.fill();
  ctx.fillText('Перемещение |Δr| = '+(disp)+' м', xa, y+46);
  // Points
  [[xa,'A','#1d4ed8'],[xb,'B','#dc2626'],[xc,'C','#c2410c']].forEach(function(p){
    ctx.fillStyle = p[2]; ctx.beginPath(); ctx.arc(p[0],y,r,0,2*Math.PI); ctx.fill();
    ctx.fillStyle = dark ? '#e2e8f0' : '#1e293b'; ctx.font = 'bold 11px Inter,sans-serif';
    ctx.fillText(p[1], p[0]-4, y-r-4);
  });
  [['sl5s1','v5s1',s1],['sl5s2','v5s2',s2]].forEach(function(p){
    var el=document.getElementById(p[1]); if(el) el.textContent=p[2]+' м';
  });
  var el = document.getElementById('res5');
  if (el) el.textContent = 'Путь = '+(s1+s2)+' м, Перемещение = '+(s1-s2)+' м';
}

// ── §6 — График x(t) равномерного движения ────────────────
function upd6() {
  var cv = document.getElementById('cv6');
  if (!cv) return;
  var dpr = window.devicePixelRatio || 1;
  var W = cv.offsetWidth || 420, H = cv.offsetHeight || 180;
  cv.width = Math.round(W*dpr); cv.height = Math.round(H*dpr);
  var ctx = cv.getContext('2d');
  ctx.setTransform(dpr,0,0,dpr,0,0);
  var v = +(document.getElementById('sl6v') ? document.getElementById('sl6v').value : 10);
  var x0 = +(document.getElementById('sl6x0') ? document.getElementById('sl6x0').value : 0);
  var dark = document.body.classList.contains('dark');
  ctx.fillStyle = dark ? '#1e293b' : '#f8fafc';
  ctx.fillRect(0,0,W,H);
  var lpad = 44, bpad = 28, rpad = 18, tpad = 18;
  var gw = W-lpad-rpad, gh = H-tpad-bpad;
  var ox = lpad, oy = tpad+gh;
  // Grid
  ctx.strokeStyle = dark ? '#1e3a5f' : '#e2e8f0'; ctx.lineWidth = 1;
  var tmax = 8, xmin = -60, xmax = 100;
  for (var ti = 0; ti <= tmax; ti++) {
    var gx = ox + ti*(gw/tmax);
    ctx.beginPath(); ctx.moveTo(gx,tpad); ctx.lineTo(gx,oy); ctx.stroke();
    ctx.fillStyle = dark ? '#64748b' : '#94a3b8'; ctx.font = '10px Inter,sans-serif';
    ctx.fillText(ti, gx-3, oy+14);
  }
  var xstep = 20, nsteps = Math.ceil((xmax-xmin)/xstep);
  for (var xi = 0; xi <= nsteps; xi++) {
    var xv = xmin + xi*xstep;
    var gy = oy - (xv-xmin)/(xmax-xmin)*gh;
    if (gy < tpad-1 || gy > oy+1) continue;
    ctx.beginPath(); ctx.moveTo(ox,gy); ctx.lineTo(ox+gw,gy); ctx.stroke();
    ctx.fillStyle = dark ? '#64748b' : '#94a3b8'; ctx.font = '10px Inter,sans-serif';
    ctx.fillText(xv, ox-28, gy+4);
  }
  // Axes
  ctx.strokeStyle = dark ? '#94a3b8' : '#475569'; ctx.lineWidth = 1.5;
  ctx.beginPath(); ctx.moveTo(ox,tpad-4); ctx.lineTo(ox,oy+2); ctx.stroke();
  ctx.beginPath(); ctx.moveTo(ox-2,oy); ctx.lineTo(ox+gw+4,oy); ctx.stroke();
  ctx.fillStyle = dark ? '#94a3b8' : '#475569'; ctx.font = '11px Inter,sans-serif';
  ctx.fillText('t, с', ox+gw-4, oy+14); ctx.fillText('x, м', ox+4, tpad-6);
  // Line x(t)
  ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6'); ctx.lineWidth = 2.5;
  ctx.beginPath();
  for (var tc = 0; tc <= tmax; tc++) {
    var xc2 = x0 + v * tc;
    var gxc = ox + tc*(gw/tmax);
    var gyc = oy - (xc2-xmin)/(xmax-xmin)*gh;
    if (tc === 0) ctx.moveTo(gxc, gyc); else ctx.lineTo(gxc, gyc);
  }
  ctx.stroke();
  ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6'); ctx.font = 'bold 11px Inter,sans-serif';
  ctx.fillText('x = '+x0+(v>=0?'+':'')+v+'·t', ox+gw*0.4, tpad+12);
  [['v6v',v+' м/с'],['v6x0',x0+' м']].forEach(function(p){
    var el=document.getElementById(p[0]); if(el) el.textContent=p[1];
  });
  var el = document.getElementById('res6');
  if (el) el.textContent = 'x(t) = '+x0+(v>=0?'+':'')+v+'·t';
}

// ── §7 — Движение двух тел: встреча ──────────────────────
function upd7() {
  var cv = document.getElementById('cv7');
  if (!cv) return;
  var dpr = window.devicePixelRatio || 1;
  var W = cv.offsetWidth || 420, H = cv.offsetHeight || 200;
  cv.width = Math.round(W*dpr); cv.height = Math.round(H*dpr);
  var ctx = cv.getContext('2d');
  ctx.setTransform(dpr,0,0,dpr,0,0);
  var v1 = +(document.getElementById('sl7v1') ? document.getElementById('sl7v1').value : 6);
  var x01 = +(document.getElementById('sl7x1') ? document.getElementById('sl7x1').value : 0);
  var v2 = +(document.getElementById('sl7v2') ? document.getElementById('sl7v2').value : 4);
  var x02 = +(document.getElementById('sl7x2') ? document.getElementById('sl7x2').value : 100);
  var dark = document.body.classList.contains('dark');
  ctx.fillStyle = dark ? '#1e293b' : '#f8fafc';
  ctx.fillRect(0,0,W,H);
  // Parameters
  var lpad = 44, bpad = 28, rpad = 16, tpad = 18;
  var gw = W-lpad-rpad, gh = H-tpad-bpad;
  var ox = lpad, oy = tpad+gh;
  var tmax = 15, xmin = -10, xmax = 110;
  // Grid
  ctx.strokeStyle = dark ? '#1e3a5f' : '#e2e8f0'; ctx.lineWidth = 1;
  for (var ti = 0; ti <= tmax; ti += 3) {
    var gx = ox + ti*(gw/tmax);
    ctx.beginPath(); ctx.moveTo(gx,tpad); ctx.lineTo(gx,oy); ctx.stroke();
    ctx.fillStyle = dark ? '#64748b' : '#94a3b8'; ctx.font = '10px Inter,sans-serif';
    ctx.fillText(ti, gx-3, oy+14);
  }
  for (var xi = 0; xi <= 110; xi += 20) {
    var gy = oy - (xi-xmin)/(xmax-xmin)*gh;
    if (gy < tpad-1 || gy > oy+1) continue;
    ctx.beginPath(); ctx.moveTo(ox,gy); ctx.lineTo(ox+gw,gy); ctx.stroke();
    ctx.fillStyle = dark ? '#64748b' : '#94a3b8'; ctx.font = '10px Inter,sans-serif';
    ctx.fillText(xi, ox-26, gy+4);
  }
  // Axes
  ctx.strokeStyle = dark ? '#94a3b8' : '#475569'; ctx.lineWidth = 1.5;
  ctx.beginPath(); ctx.moveTo(ox,tpad-4); ctx.lineTo(ox,oy+2); ctx.stroke();
  ctx.beginPath(); ctx.moveTo(ox-2,oy); ctx.lineTo(ox+gw+4,oy); ctx.stroke();
  ctx.fillStyle = dark ? '#94a3b8' : '#475569'; ctx.font = '11px Inter,sans-serif';
  ctx.fillText('t, с', ox+gw-4, oy+14); ctx.fillText('x, м', ox+4, tpad-6);
  // Line 1
  ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6'); ctx.lineWidth = 2.5;
  ctx.beginPath();
  for (var tc = 0; tc <= tmax; tc++) {
    var xv = x01 + v1*tc;
    ctx.lineTo(ox+tc*(gw/tmax), oy-(xv-xmin)/(xmax-xmin)*gh);
    if (tc===0) ctx.moveTo(ox, oy-(x01-xmin)/(xmax-xmin)*gh);
  }
  ctx.stroke();
  ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6'); ctx.font = 'bold 10px Inter,sans-serif';
  ctx.fillText('Тело 1 (v='+v1+')', ox+4, oy-(x01-xmin)/(xmax-xmin)*gh - 5);
  // Line 2
  ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.lineWidth = 2.5;
  ctx.beginPath();
  ctx.moveTo(ox, oy-(x02-xmin)/(xmax-xmin)*gh);
  for (var tc2 = 0; tc2 <= tmax; tc2++) {
    var xv2 = x02 - v2*tc2;
    ctx.lineTo(ox+tc2*(gw/tmax), oy-(xv2-xmin)/(xmax-xmin)*gh);
  }
  ctx.stroke();
  ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444');
  ctx.fillText('Тело 2 (v='+v2+')', ox+gw*0.55, oy-(x02-xmin)/(xmax-xmin)*gh + 14);
  // Meeting point
  var dv = v1 + v2, dx = x02 - x01;
  if (dv > 0) {
    var tmeet = dx / dv;
    var xmeet = x01 + v1*tmeet;
    if (tmeet > 0 && tmeet < tmax && xmeet >= xmin && xmeet <= xmax) {
      var gxm = ox+tmeet*(gw/tmax);
      var gym = oy-(xmeet-xmin)/(xmax-xmin)*gh;
      ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981'); ctx.lineWidth = 1; ctx.setLineDash([4,3]);
      ctx.beginPath(); ctx.moveTo(gxm,gym); ctx.lineTo(gxm,oy); ctx.stroke();
      ctx.beginPath(); ctx.moveTo(ox,gym); ctx.lineTo(gxm,gym); ctx.stroke();
      ctx.setLineDash([]);
      ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981');
      ctx.beginPath(); ctx.arc(gxm,gym,5,0,2*Math.PI); ctx.fill();
      ctx.font = '10px Inter,sans-serif';
      ctx.fillText('t='+tmeet.toFixed(1)+' с', gxm+3, gym-5);
    }
  }
  [['v7v1',v1+' м/с'],['v7v2',v2+' м/с'],['v7x1',x01+' м'],['v7x2',x02+' м']].forEach(function(p){ var el=document.getElementById(p[0]); if(el) el.textContent=p[1]; });
  var el = document.getElementById('res7');
  if (el && dv > 0) {
    var tm = dx/dv;
    el.textContent = tm > 0 ? 'Встреча через t = '+tm.toFixed(2)+' с, в точке x = '+(x01+v1*tm).toFixed(1)+' м' : 'Движутся прочь друг от друга';
  }
}

// ── §8 — Средняя скорость ─────────────────────────────────
function upd8() {
  var cv = document.getElementById('cv8');
  if (!cv) return;
  var dpr = window.devicePixelRatio || 1;
  var W = cv.offsetWidth || 420, H = cv.offsetHeight || 140;
  cv.width = Math.round(W*dpr); cv.height = Math.round(H*dpr);
  var ctx = cv.getContext('2d');
  ctx.setTransform(dpr,0,0,dpr,0,0);
  var v1 = +(document.getElementById('sl8v1') ? document.getElementById('sl8v1').value : 40);
  var v2 = +(document.getElementById('sl8v2') ? document.getElementById('sl8v2').value : 60);
  var dark = document.body.classList.contains('dark');
  ctx.fillStyle = dark ? '#1e293b' : '#f8fafc';
  ctx.fillRect(0,0,W,H);
  // Two segments of equal length
  var pad = W*0.08, segW = W*0.38, y = H*0.42, h = 22;
  // Segment 1
  ctx.fillStyle = dark ? '#1e3a5f' : '#dbeafe';
  ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6'); ctx.lineWidth = 2;
  ctx.fillRect(pad, y, segW, h); ctx.strokeRect(pad, y, segW, h);
  ctx.fillStyle = dark ? '#93c5fd' : '#1d4ed8'; ctx.font = 'bold 11px Inter,sans-serif';
  ctx.textAlign = 'center';
  ctx.fillText('v₁ = '+v1+' км/ч', pad+segW/2, y+15);
  // Segment 2
  ctx.fillStyle = dark ? '#1c2d0f' : '#d1fae5';
  ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981'); ctx.lineWidth = 2;
  ctx.fillRect(pad+segW, y, segW, h); ctx.strokeRect(pad+segW, y, segW, h);
  ctx.fillStyle = dark ? '#6ee7b7' : '#065f46';
  ctx.fillText('v₂ = '+v2+' км/ч', pad+segW+segW/2, y+15);
  ctx.textAlign = 'left';
  // Labels
  ctx.fillStyle = dark ? '#94a3b8' : '#475569'; ctx.font = '11px Inter,sans-serif';
  ctx.fillText('s/2', pad, y-8); ctx.fillText('s/2', pad+segW, y-8);
  // Average speed formula
  var vavg = 2*v1*v2/(v1+v2);
  ctx.fillStyle = dark ? '#e2e8f0' : '#1e293b'; ctx.font = 'bold 12px Inter,sans-serif';
  ctx.fillText('⟨v⟩ = 2v₁v₂/(v₁+v₂) = '+vavg.toFixed(1)+' км/ч', pad, y+h+26);
  ctx.font = '10px Inter,sans-serif'; ctx.fillStyle = dark ? '#64748b' : '#94a3b8';
  ctx.fillText('(среднеарифметическое: '+(v1+v2)/2+' ≠ среднее по пути)', pad, y+h+42);
  [['v8v1',v1+' км/ч'],['v8v2',v2+' км/ч']].forEach(function(p){ var el=document.getElementById(p[0]); if(el) el.textContent=p[1]; });
  var el = document.getElementById('res8');
  if (el) el.textContent = '⟨v⟩ = ' + vavg.toFixed(2) + ' км/ч';
}

// ── §9 — Сложение скоростей (лодка на реке) ───────────────
var anim9Id = null;
function upd9() {
  var cv = document.getElementById('cv9');
  if (!cv) return;
  if (anim9Id) { cancelAnimationFrame(anim9Id); anim9Id = null; }
  var dpr = window.devicePixelRatio || 1;
  var W = cv.offsetWidth || 420, H = cv.offsetHeight || 180;
  cv.width = Math.round(W*dpr); cv.height = Math.round(H*dpr);
  var ctx = cv.getContext('2d');
  ctx.setTransform(dpr,0,0,dpr,0,0);
  var vb = +(document.getElementById('sl9vb') ? document.getElementById('sl9vb').value : 4);
  var vu = +(document.getElementById('sl9vu') ? document.getElementById('sl9vu').value : 3);
  var d = +(document.getElementById('sl9d') ? document.getElementById('sl9d').value : 60);
  var vres = Math.sqrt(vb*vb+vu*vu);
  var t = d/vb;
  var drift = vu*t;
  var dark = document.body.classList.contains('dark');
  var anim9t = 0;
  function frame9() {
    anim9t += 0.012;
    var ph = anim9t % 1;
    ctx.fillStyle = dark ? '#1e293b' : '#e0f2fe';
    ctx.fillRect(0,0,W,H);
    // River banks
    var bank1 = H*0.12, bank2 = H*0.88, riverH = bank2-bank1;
    ctx.fillStyle = dark ? '#0c4a6e' : '#bae6fd';
    ctx.fillRect(0, bank1, W, riverH);
    ctx.fillStyle = dark ? '#1e3a5f' : '#7dd3fc';
    // Ripples
    for (var ri = 0; ri < 5; ri++) {
      ctx.strokeStyle = dark ? '#1e3a5f' : '#38bdf8'; ctx.lineWidth = 1;
      ctx.beginPath(); ctx.moveTo(40+ri*60, (bank1+bank2)/2); ctx.lineTo(80+ri*60, (bank1+bank2)/2); ctx.stroke();
    }
    ctx.fillStyle = dark ? '#64748b' : '#475569';
    ctx.fillRect(0, 0, W, bank1); ctx.fillRect(0, bank2, W, H-bank2);
    ctx.font = 'bold 10px Inter,sans-serif';
    ctx.fillStyle = dark ? '#94a3b8' : '#334155';
    ctx.fillText('Берег 1', 6, bank1-4);
    ctx.fillText('Берег 2', 6, bank2+12);
    // Current arrows
    ctx.strokeStyle = '#0ea5e9'; ctx.lineWidth = 1.5;
    for (var ci = 0; ci < 4; ci++) {
      var cy = bank1 + riverH*(0.2+ci*0.2);
      ctx.beginPath(); ctx.moveTo(W*0.1+ci*20, cy); ctx.lineTo(W*0.1+ci*20+vu*8, cy); ctx.stroke();
      ctx.fillStyle = '#0ea5e9';
      ctx.beginPath(); ctx.moveTo(W*0.1+ci*20+vu*8,cy);
      ctx.lineTo(W*0.1+ci*20+vu*8-6,cy-3); ctx.lineTo(W*0.1+ci*20+vu*8-6,cy+3); ctx.fill();
    }
    // Boat position
    var scX = (W*0.75)/Math.max(drift+20,40);
    var scY = riverH;
    var bx = W*0.12 + ph*drift*scX;
    var by = bank1 + ph*scY;
    ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.warn:'#f59e0b');
    ctx.beginPath(); ctx.arc(bx, by, 8, 0, 2*Math.PI); ctx.fill();
    ctx.fillStyle = '#fff'; ctx.font = 'bold 9px Inter,sans-serif';
    ctx.textAlign = 'center'; ctx.fillText('', bx, by+4); ctx.textAlign = 'left';
    // Result
    var el = document.getElementById('res9');
    if (el) el.textContent = '|v_рез| = '+vres.toFixed(2)+' м/с, снос = '+drift.toFixed(1)+' м, t = '+t.toFixed(1)+' с';
    [['v9vb',vb+' м/с'],['v9vu',vu+' м/с'],['v9d',d+' м']].forEach(function(p){ var el=document.getElementById(p[0]); if(el) el.textContent=p[1]; });
    anim9Id = requestAnimationFrame(frame9);
  }
  frame9();
}

// ── §10 — Ускорение ───────────────────────────────────────
function upd10() {
  var cv = document.getElementById('cv10');
  if (!cv) return;
  var dpr = window.devicePixelRatio || 1;
  var W = cv.offsetWidth || 420, H = cv.offsetHeight || 160;
  cv.width = Math.round(W*dpr); cv.height = Math.round(H*dpr);
  var ctx = cv.getContext('2d');
  ctx.setTransform(dpr,0,0,dpr,0,0);
  var v0 = +(document.getElementById('sl10v0') ? document.getElementById('sl10v0').value : 10);
  var a = +(document.getElementById('sl10a') ? document.getElementById('sl10a').value : 2);
  var dark = document.body.classList.contains('dark');
  ctx.fillStyle = dark ? '#1e293b' : '#f8fafc';
  ctx.fillRect(0,0,W,H);
  // Show v(t) for a few seconds
  var tmax = 8, vmax = Math.max(v0+a*tmax, 5)+5;
  var lpad=44, bpad=28, rpad=16, tpad=18;
  var gw=W-lpad-rpad, gh=H-tpad-bpad;
  var ox=lpad, oy=tpad+gh;
  ctx.strokeStyle = dark ? '#1e3a5f' : '#e2e8f0'; ctx.lineWidth = 1;
  for (var ti=0; ti<=tmax; ti+=2) {
    var gx = ox+ti*(gw/tmax);
    ctx.beginPath(); ctx.moveTo(gx,tpad); ctx.lineTo(gx,oy); ctx.stroke();
    ctx.fillStyle = dark?'#64748b':'#94a3b8'; ctx.font='10px Inter,sans-serif';
    ctx.fillText(ti, gx-3, oy+14);
  }
  var vstep = vmax > 40 ? 20 : 10;
  for (var vi=0; vi<=vmax; vi+=vstep) {
    var gy = oy-vi/vmax*gh;
    if (gy < tpad-1) continue;
    ctx.beginPath(); ctx.moveTo(ox,gy); ctx.lineTo(ox+gw,gy); ctx.stroke();
    ctx.fillText(vi, ox-24, gy+4);
  }
  ctx.strokeStyle = dark?'#94a3b8':'#475569'; ctx.lineWidth=1.5;
  ctx.beginPath(); ctx.moveTo(ox,tpad-4); ctx.lineTo(ox,oy+2); ctx.stroke();
  ctx.beginPath(); ctx.moveTo(ox-2,oy); ctx.lineTo(ox+gw+4,oy); ctx.stroke();
  ctx.fillStyle = dark?'#94a3b8':'#475569'; ctx.font='11px Inter,sans-serif';
  ctx.fillText('t,с', ox+gw-4, oy+14); ctx.fillText('v,м/с', ox+4, tpad-6);
  // v(t) line
  ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6'); ctx.lineWidth=2.5;
  ctx.beginPath();
  ctx.moveTo(ox, oy-v0/vmax*gh);
  for (var tc=0; tc<=tmax; tc++) {
    var vc = v0+a*tc;
    if (vc < 0) vc = 0;
    ctx.lineTo(ox+tc*(gw/tmax), oy-Math.min(vc,vmax)/vmax*gh);
  }
  ctx.stroke();
  ctx.fillStyle=(window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6'); ctx.font='bold 11px Inter,sans-serif';
  ctx.fillText('v = '+v0+(a>=0?'+':'')+a+'·t', ox+gw*0.3, tpad+14);
  // a annotation
  ctx.strokeStyle=(window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.lineWidth=1.5; ctx.setLineDash([4,3]);
  var gx1=ox+(gw/tmax), gx2=ox+2*(gw/tmax);
  var vy1=oy-(v0+a)/vmax*gh, vy2=oy-(v0+2*a)/vmax*gh;
  ctx.beginPath(); ctx.moveTo(gx1,vy1); ctx.lineTo(gx2,vy1); ctx.lineTo(gx2,vy2); ctx.stroke();
  ctx.setLineDash([]);
  ctx.fillStyle=(window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.font='10px Inter,sans-serif';
  ctx.fillText('a='+a, gx2+3, (vy1+vy2)/2+4);
  [['v10v0',v0+' м/с'],['v10a',a+' м/с²']].forEach(function(p){ var el=document.getElementById(p[0]); if(el) el.textContent=p[1]; });
  var vFinal = v0+a*tmax;
  var el = document.getElementById('res10');
  if (el) el.textContent = 'Через '+tmax+' с: v = '+v0+(a>=0?'+':'')+a+'·'+tmax+' = '+(v0+a*tmax)+' м/с';
}

// ── §11 — Равноускоренное движение: v(t) ─────────────────
function upd11() {
  var cv = document.getElementById('cv11');
  if (!cv) return;
  var dpr = window.devicePixelRatio || 1;
  var W = cv.offsetWidth || 420, H = cv.offsetHeight || 180;
  cv.width = Math.round(W*dpr); cv.height = Math.round(H*dpr);
  var ctx = cv.getContext('2d');
  ctx.setTransform(dpr,0,0,dpr,0,0);
  var v0 = +(document.getElementById('sl11v0') ? document.getElementById('sl11v0').value : 5);
  var a = +(document.getElementById('sl11a') ? document.getElementById('sl11a').value : 3);
  var dark = document.body.classList.contains('dark');
  ctx.fillStyle = dark ? '#1e293b' : '#f8fafc';
  ctx.fillRect(0,0,W,H);
  var tmax = 10, vmax = Math.max(v0+a*tmax+4, 10);
  var lpad=44, bpad=28, rpad=16, tpad=18;
  var gw=W-lpad-rpad, gh=H-tpad-bpad;
  var ox=lpad, oy=tpad+gh;
  // Grid
  ctx.strokeStyle = dark?'#1e3a5f':'#e2e8f0'; ctx.lineWidth=1;
  for (var ti=0; ti<=tmax; ti+=2) {
    var gx=ox+ti*(gw/tmax);
    ctx.beginPath(); ctx.moveTo(gx,tpad); ctx.lineTo(gx,oy); ctx.stroke();
    ctx.fillStyle=dark?'#64748b':'#94a3b8'; ctx.font='10px Inter,sans-serif';
    ctx.fillText(ti, gx-3, oy+14);
  }
  var vstep = vmax > 60 ? 20 : 10;
  for (var vi=0; vi<=vmax; vi+=vstep) {
    var gy=oy-vi/vmax*gh; if(gy<tpad-1) continue;
    ctx.beginPath(); ctx.moveTo(ox,gy); ctx.lineTo(ox+gw,gy); ctx.stroke();
    ctx.fillText(vi, ox-24, gy+4);
  }
  // Axes
  ctx.strokeStyle=dark?'#94a3b8':'#475569'; ctx.lineWidth=1.5;
  ctx.beginPath(); ctx.moveTo(ox,tpad-4); ctx.lineTo(ox,oy+2); ctx.stroke();
  ctx.beginPath(); ctx.moveTo(ox-2,oy); ctx.lineTo(ox+gw+4,oy); ctx.stroke();
  ctx.fillStyle=dark?'#94a3b8':'#475569'; ctx.font='11px Inter,sans-serif';
  ctx.fillText('t,с',ox+gw-4,oy+14); ctx.fillText('v,м/с',ox+4,tpad-6);
  // v(t) line with area fill
  ctx.fillStyle = dark ? 'rgba(59,130,246,0.15)' : 'rgba(59,130,246,0.1)';
  ctx.beginPath(); ctx.moveTo(ox,oy);
  ctx.lineTo(ox, oy-Math.min(v0,vmax)/vmax*gh);
  for (var tc=0; tc<=tmax; tc++) {
    var vc=v0+a*tc; if(vc<0) vc=0;
    ctx.lineTo(ox+tc*(gw/tmax), oy-Math.min(vc,vmax)/vmax*gh);
  }
  ctx.lineTo(ox+gw,oy); ctx.closePath(); ctx.fill();
  ctx.strokeStyle=(window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6'); ctx.lineWidth=2.5;
  ctx.beginPath(); ctx.moveTo(ox, oy-Math.min(v0,vmax)/vmax*gh);
  for (var tc2=0; tc2<=tmax; tc2++) {
    var vc2=v0+a*tc2; if(vc2<0) vc2=0;
    ctx.lineTo(ox+tc2*(gw/tmax), oy-Math.min(vc2,vmax)/vmax*gh);
  }
  ctx.stroke();
  // Slope annotation
  ctx.fillStyle=(window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6'); ctx.font='bold 11px Inter,sans-serif';
  ctx.fillText('v = '+v0+(a>=0?'+':'')+a+'·t', ox+gw*0.45, tpad+14);
  ctx.fillStyle=dark?'#94a3b8':'#64748b'; ctx.font='10px Inter,sans-serif';
  ctx.fillText('Площадь = путь s', ox+gw*0.22, oy-gh*0.28);
  [['v11v0',v0+' м/с'],['v11a',a+' м/с²']].forEach(function(p){ var el=document.getElementById(p[0]); if(el) el.textContent=p[1]; });
  var el=document.getElementById('res11');
  if (el) el.textContent = 'v('+tmax+'с) = '+(v0+a*tmax)+' м/с;  s = '+(v0*tmax+a*tmax*tmax/2).toFixed(1)+' м';
}

// ── §12 — x(t) при равноускоренном движении ──────────────
function upd12() {
  var cv = document.getElementById('cv12');
  if (!cv) return;
  var dpr = window.devicePixelRatio || 1;
  var W = cv.offsetWidth || 420, H = cv.offsetHeight || 200;
  cv.width = Math.round(W*dpr); cv.height = Math.round(H*dpr);
  var ctx = cv.getContext('2d');
  ctx.setTransform(dpr,0,0,dpr,0,0);
  var v0 = +(document.getElementById('sl12v0') ? document.getElementById('sl12v0').value : 0);
  var a = +(document.getElementById('sl12a') ? document.getElementById('sl12a').value : 2);
  var dark = document.body.classList.contains('dark');
  ctx.fillStyle = dark ? '#1e293b' : '#f8fafc';
  ctx.fillRect(0,0,W,H);
  var tmax = 8;
  var xmax = v0*tmax + 0.5*a*tmax*tmax;
  var xmin = Math.min(0, xmax);
  if (xmax < 5 && xmax > -5) xmax = 20;
  if (xmin > -5) xmin = -5;
  var lpad=44, bpad=28, rpad=16, tpad=18;
  var gw=W-lpad-rpad, gh=H-tpad-bpad;
  var ox=lpad, oy=tpad+gh;
  // Grid
  ctx.strokeStyle=dark?'#1e3a5f':'#e2e8f0'; ctx.lineWidth=1;
  for (var ti=0; ti<=tmax; ti+=2) {
    var gx=ox+ti*(gw/tmax);
    ctx.beginPath(); ctx.moveTo(gx,tpad); ctx.lineTo(gx,oy); ctx.stroke();
    ctx.fillStyle=dark?'#64748b':'#94a3b8'; ctx.font='10px Inter,sans-serif';
    ctx.fillText(ti, gx-3, oy+14);
  }
  var xstep = (xmax-xmin) > 80 ? 40 : 20;
  for (var xi=Math.ceil(xmin/xstep)*xstep; xi<=xmax; xi+=xstep) {
    var gy=oy-(xi-xmin)/(xmax-xmin)*gh; if(gy<tpad-1||gy>oy+1) continue;
    ctx.beginPath(); ctx.moveTo(ox,gy); ctx.lineTo(ox+gw,gy); ctx.stroke();
    ctx.fillText(xi.toFixed(0), ox-30, gy+4);
  }
  // Axes
  ctx.strokeStyle=dark?'#94a3b8':'#475569'; ctx.lineWidth=1.5;
  ctx.beginPath(); ctx.moveTo(ox,tpad-4); ctx.lineTo(ox,oy+2); ctx.stroke();
  ctx.beginPath(); ctx.moveTo(ox-2,oy); ctx.lineTo(ox+gw+4,oy); ctx.stroke();
  ctx.fillStyle=dark?'#94a3b8':'#475569'; ctx.font='11px Inter,sans-serif';
  ctx.fillText('t,с',ox+gw-4,oy+14); ctx.fillText('x,м',ox+4,tpad-6);
  // x(t) curve (parabola)
  ctx.strokeStyle=(window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981'); ctx.lineWidth=2.5;
  ctx.beginPath();
  for (var tc=0; tc<=tmax*20; tc++) {
    var t2=tc/(tmax*20)*tmax;
    var xv=v0*t2+0.5*a*t2*t2;
    var gxc=ox+t2/tmax*gw;
    var gyc=oy-(xv-xmin)/(xmax-xmin)*gh;
    if (tc===0) ctx.moveTo(gxc,gyc); else ctx.lineTo(gxc,gyc);
  }
  ctx.stroke();
  ctx.fillStyle=(window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981'); ctx.font='bold 11px Inter,sans-serif';
  ctx.fillText('x = '+v0+'t + '+a+'/2·t²', ox+gw*0.3, tpad+14);
  [['v12v0',v0+' м/с'],['v12a',a+' м/с²']].forEach(function(p){ var el=document.getElementById(p[0]); if(el) el.textContent=p[1]; });
  var el=document.getElementById('res12');
  if (el) el.textContent = 'x('+tmax+'с) = '+(v0*tmax+0.5*a*tmax*tmax).toFixed(1)+' м';
}

// ── §13 — Равномерное движение по окружности ─────────────
var anim13Id = null;
function upd13() {
  var cv = document.getElementById('cv13');
  if (!cv) return;
  if (anim13Id) { cancelAnimationFrame(anim13Id); anim13Id = null; }
  var dpr = window.devicePixelRatio || 1;
  var W = cv.offsetWidth || 420, H = cv.offsetHeight || 180;
  cv.width = Math.round(W*dpr); cv.height = Math.round(H*dpr);
  var ctx = cv.getContext('2d');
  ctx.setTransform(dpr,0,0,dpr,0,0);
  var r = +(document.getElementById('sl13r') ? document.getElementById('sl13r').value : 3);
  var nu = +(document.getElementById('sl13nu') ? document.getElementById('sl13nu').value : 2);
  var v = 2*Math.PI*r*nu;
  var anim13t = 0;
  function frame13() {
    anim13t += 0.016;
    var dark = document.body.classList.contains('dark');
    ctx.fillStyle = dark ? '#1e293b' : '#f8fafc';
    ctx.fillRect(0,0,W,H);
    var cx = W*0.35, cy = H*0.5;
    var sc = Math.min(H*0.35, W*0.28) / 5;
    var R = r * sc;
    // Circle
    ctx.strokeStyle = dark ? '#334155' : '#e2e8f0'; ctx.lineWidth = 2;
    ctx.beginPath(); ctx.arc(cx,cy,R,0,2*Math.PI); ctx.stroke();
    // Radius
    var angle = 2*Math.PI*nu * anim13t;
    var px = cx + R*Math.cos(angle), py = cy + R*Math.sin(angle);
    ctx.strokeStyle = dark ? '#475569' : '#94a3b8'; ctx.lineWidth = 1.5;
    ctx.beginPath(); ctx.moveTo(cx,cy); ctx.lineTo(px,py); ctx.stroke();
    ctx.fillStyle = dark ? '#94a3b8' : '#64748b'; ctx.font = '10px Inter,sans-serif';
    ctx.fillText('r='+r+' м', cx+3, cy-4);
    // Point
    ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6');
    ctx.beginPath(); ctx.arc(px,py,7,0,2*Math.PI); ctx.fill();
    // Velocity vector (tangential)
    var tangX = -Math.sin(angle)*v*0.5*sc*0.8;
    var tangY = Math.cos(angle)*v*0.5*sc*0.8;
    ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981'); ctx.lineWidth = 2;
    ctx.beginPath(); ctx.moveTo(px,py); ctx.lineTo(px+tangX,py+tangY); ctx.stroke();
    ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981');
    ctx.beginPath(); ctx.moveTo(px+tangX,py+tangY);
    ctx.lineTo(px+tangX-7*Math.cos(Math.atan2(tangY,tangX)-0.4),py+tangY-7*Math.sin(Math.atan2(tangY,tangX)-0.4));
    ctx.lineTo(px+tangX-7*Math.cos(Math.atan2(tangY,tangX)+0.4),py+tangY-7*Math.sin(Math.atan2(tangY,tangX)+0.4));
    ctx.fill();
    ctx.font = '10px Inter,sans-serif';
    ctx.fillText('v', px+tangX+3, py+tangY-3);
    // Info panel
    var ix = W*0.63, iy = H*0.12;
    ctx.fillStyle = dark ? '#1e293b' : '#f1f5f9';
    ctx.strokeStyle = dark ? '#334155' : '#e2e8f0'; ctx.lineWidth = 1;
    ctx.fillRect(ix-4,iy-16,W*0.36,80);
    ctx.font = '11px Inter,sans-serif';
    ctx.fillStyle = dark ? '#e2e8f0' : '#1e293b';
    ctx.fillText('r = '+r+' м', ix, iy);
    ctx.fillText('ν = '+nu+' об/с', ix, iy+18);
    ctx.fillText('T = '+(1/nu).toFixed(2)+' с', ix, iy+36);
    ctx.fillText('v = '+v.toFixed(1)+' м/с', ix, iy+54);
    [['v13r',r+' м'],['v13nu',nu+' об/с']].forEach(function(p){ var el=document.getElementById(p[0]); if(el) el.textContent=p[1]; });
    var el=document.getElementById('res13');
    if (el) el.textContent = 'v = 2π·'+r+'·'+nu+' ≈ '+v.toFixed(2)+' м/с;  T = '+(1/nu).toFixed(2)+' с';
    anim13Id = requestAnimationFrame(frame13);
  }
  frame13();
}

// ── §14 — Центростремительное ускорение ──────────────────
var anim14Id = null;
function upd14() {
  var cv = document.getElementById('cv14');
  if (!cv) return;
  if (anim14Id) { cancelAnimationFrame(anim14Id); anim14Id = null; }
  var dpr = window.devicePixelRatio || 1;
  var W = cv.offsetWidth || 420, H = cv.offsetHeight || 180;
  cv.width = Math.round(W*dpr); cv.height = Math.round(H*dpr);
  var ctx = cv.getContext('2d');
  ctx.setTransform(dpr,0,0,dpr,0,0);
  var vms = +(document.getElementById('sl14v') ? document.getElementById('sl14v').value : 10);
  var r = +(document.getElementById('sl14r') ? document.getElementById('sl14r').value : 5);
  var ac = vms*vms/r;
  var anim14t = 0;
  function frame14() {
    anim14t += 0.016;
    var dark = document.body.classList.contains('dark');
    ctx.fillStyle = dark ? '#1e293b' : '#f8fafc';
    ctx.fillRect(0,0,W,H);
    var cx = W*0.35, cy = H*0.5;
    var sc = Math.min(H*0.35, W*0.28)/Math.max(r,3);
    var R = r*sc;
    var omega = vms/r;
    var angle = omega * anim14t;
    var px = cx + R*Math.cos(angle), py = cy + R*Math.sin(angle);
    // Circle
    ctx.strokeStyle = dark?'#334155':'#e2e8f0'; ctx.lineWidth=2;
    ctx.beginPath(); ctx.arc(cx,cy,R,0,2*Math.PI); ctx.stroke();
    // Radius
    ctx.strokeStyle = dark?'#475569':'#94a3b8'; ctx.lineWidth=1.5;
    ctx.beginPath(); ctx.moveTo(cx,cy); ctx.lineTo(px,py); ctx.stroke();
    // Center dot
    ctx.fillStyle = dark?'#475569':'#94a3b8';
    ctx.beginPath(); ctx.arc(cx,cy,4,0,2*Math.PI); ctx.fill();
    ctx.fillStyle=dark?'#94a3b8':'#64748b'; ctx.font='10px Inter,sans-serif';
    ctx.fillText('r='+r, cx+4, cy-4);
    // Point
    ctx.fillStyle=(window.PHYS9_COLORS?window.PHYS9_COLORS.acceleration:'#f97316');
    ctx.beginPath(); ctx.arc(px,py,7,0,2*Math.PI); ctx.fill();
    // Velocity arrow (tangent) — green
    var scV = 0.45*sc;
    var tvx = -Math.sin(angle)*vms*scV, tvy = Math.cos(angle)*vms*scV;
    ctx.strokeStyle=(window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981'); ctx.lineWidth=2;
    ctx.beginPath(); ctx.moveTo(px,py); ctx.lineTo(px+tvx,py+tvy); ctx.stroke();
    ctx.fillStyle=(window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981');
    var va=Math.atan2(tvy,tvx);
    ctx.beginPath(); ctx.moveTo(px+tvx,py+tvy);
    ctx.lineTo(px+tvx-7*Math.cos(va-0.4),py+tvy-7*Math.sin(va-0.4));
    ctx.lineTo(px+tvx-7*Math.cos(va+0.4),py+tvy-7*Math.sin(va+0.4)); ctx.fill();
    ctx.font='10px Inter,sans-serif'; ctx.fillText('v',px+tvx+3,py+tvy-3);
    // Centripetal acceleration arrow — red (toward center)
    var scA = 0.5*sc;
    var avx = (cx-px)/r * ac * scA, avy = (cy-py)/r * ac * scA;
    var aLen = Math.min(Math.sqrt(avx*avx+avy*avy), R*0.7);
    var aang = Math.atan2(cy-py, cx-px);
    var eax = px + Math.cos(aang)*aLen, eay = py + Math.sin(aang)*aLen;
    ctx.strokeStyle=(window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.lineWidth=2.5;
    ctx.beginPath(); ctx.moveTo(px,py); ctx.lineTo(eax,eay); ctx.stroke();
    ctx.fillStyle=(window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444');
    ctx.beginPath(); ctx.moveTo(eax,eay);
    ctx.lineTo(eax-8*Math.cos(aang-0.4),eay-8*Math.sin(aang-0.4));
    ctx.lineTo(eax-8*Math.cos(aang+0.4),eay-8*Math.sin(aang+0.4)); ctx.fill();
    ctx.font='10px Inter,sans-serif'; ctx.fillText('aцс',eax+3,eay-3);
    // Info panel
    var ix=W*0.63, iy=H*0.12;
    ctx.fillStyle=dark?'#1e293b':'#f1f5f9';
    ctx.strokeStyle=dark?'#334155':'#e2e8f0'; ctx.lineWidth=1;
    ctx.fillRect(ix-4,iy-16,W*0.37,68);
    ctx.font='11px Inter,sans-serif'; ctx.fillStyle=dark?'#e2e8f0':'#1e293b';
    ctx.fillText('v = '+vms+' м/с', ix, iy);
    ctx.fillText('r = '+r+' м', ix, iy+18);
    ctx.fillText('aцс = v²/r = '+ac.toFixed(1)+' м/с²', ix, iy+36);
    [['v14v',vms+' м/с'],['v14r',r+' м']].forEach(function(p){ var el=document.getElementById(p[0]); if(el) el.textContent=p[1]; });
    var el=document.getElementById('res14');
    if (el) el.textContent = 'aцс = '+vms+'²/'+r+' = '+ac.toFixed(2)+' м/с²';
    anim14Id = requestAnimationFrame(frame14);
  }
  frame14();
}

// §16 — F_т = mg
function upd16() {
  var m = +document.getElementById('sl16m').value;
  var g = +document.getElementById('sl16g').value;
  document.getElementById('v16m').textContent = m + ' кг';
  document.getElementById('v16g').textContent = g + ' м/с²';
  var F = m * g;
  var el = document.getElementById('res16');
  if (el) { el.textContent = 'Fт = ' + m + ' · ' + g + ' = ' + F.toFixed(0) + ' Н'; doRender(el); }
}

// §17 — a = F/m
function upd17() {
  var F = +document.getElementById('sl17f').value;
  var m = +document.getElementById('sl17m').value;
  document.getElementById('v17f').textContent = F + ' Н';
  document.getElementById('v17m').textContent = m + ' кг';
  var a = (F / m).toFixed(2).replace('.', ',');
  var el = document.getElementById('res17');
  if (el) { el.textContent = 'a = ' + F + ' / ' + m + ' = ' + a + ' м/с²'; doRender(el); }
}

// §19 — F_упр = k·Δl
function upd19() {
  var k = +document.getElementById('sl19k').value;
  var xcm = +document.getElementById('sl19x').value;
  document.getElementById('v19k').textContent = k + ' Н/м';
  document.getElementById('v19x').textContent = xcm + ' см';
  var xm = xcm / 100;
  var F = (k * xm).toFixed(1).replace('.', ',');
  var xStr = xm.toFixed(2).replace('.', ',');
  var el = document.getElementById('res19');
  if (el) { el.textContent = 'Fупр = ' + k + ' · ' + xStr + ' = ' + F + ' Н'; doRender(el); }
  drawSpring19();
}

// §20 — F_тр = μ·N
function upd20() {
  var muInt = +document.getElementById('sl20mu').value;
  var m = +document.getElementById('sl20m').value;
  var mu = (muInt / 100).toFixed(2);
  document.getElementById('v20mu').textContent = mu;
  document.getElementById('v20m').textContent = m + ' кг';
  var N = m * 10;
  var F = (muInt / 100 * N).toFixed(1).replace('.', ',');
  var el = document.getElementById('res20');
  if (el) { el.textContent = 'Fтр = ' + mu + ' · ' + N + ' = ' + F + ' Н'; doRender(el); }
  drawFriction20();
}

// §21 — t_пад, v_пад
function upd21() {
  var h = +document.getElementById('sl21h').value;
  document.getElementById('v21h').textContent = h + ' м';
  var t = Math.sqrt(2 * h / 10).toFixed(2).replace('.', ',');
  var v = Math.sqrt(2 * 10 * h).toFixed(1).replace('.', ',');
  var el = document.getElementById('res21');
  if (el) { el.textContent = 't = √(2·' + h + '/10) = ' + t + ' с;   v = √(2·10·' + h + ') = ' + v + ' м/с'; doRender(el); }
  // Restart parabola animation with new height
  if (document.getElementById('tab-ref21') && document.getElementById('tab-ref21').classList.contains('active')) {
    startAnim21();
  }
}

// ══════════════════════════════════════════════
//  §22 — БРОСОК ПОД УГЛОМ: ИНТЕРАКТИВ
// ══════════════════════════════════════════════
function upd22() {
  var deg = +document.getElementById('sl22a').value;
  var v0  = +document.getElementById('sl22v').value;
  document.getElementById('v22a').textContent = deg + '°';
  document.getElementById('v22v').textContent = v0 + ' м/с';
  var g = 10, rad = deg * Math.PI / 180;
  var L = v0 * v0 * Math.sin(2 * rad) / g;
  var H = v0 * v0 * Math.sin(rad) * Math.sin(rad) / (2 * g);
  var T = 2 * v0 * Math.sin(rad) / g;
  var el = document.getElementById('res22');
  if (el) el.textContent = 'L = ' + L.toFixed(1) + ' м | H = ' + H.toFixed(1) + ' м | T = ' + T.toFixed(2) + ' с';
  drawAngularThrow22(deg, v0);
}
function drawAngularThrow22(deg, v0) {
  var cv = document.getElementById('cv22');
  if (!cv || cv.offsetWidth === 0) return;
  var dpr = window.devicePixelRatio || 1;
  var W = cv.offsetWidth, H2 = cv.offsetHeight || 200;
  cv.width = Math.round(W * dpr); cv.height = Math.round(H2 * dpr);
  var ctx = cv.getContext('2d');
  ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
  var dark = document.body.classList.contains('dark');
  ctx.clearRect(0, 0, W, H2);
  var g = 10, rad = deg * Math.PI / 180;
  var L = v0 * v0 * Math.sin(2 * rad) / g;
  var Hmax = v0 * v0 * Math.sin(rad) * Math.sin(rad) / (2 * g);
  var pad = 30, bH = H2 - 30;
  var scX = (W - 2 * pad) / (L || 1);
  var scY = (bH - 20) / (Hmax || 1);
  // Ground
  ctx.strokeStyle = dark ? '#334155' : '#cbd5e1';
  ctx.lineWidth = 1.5;
  ctx.beginPath(); ctx.moveTo(pad, bH); ctx.lineTo(W - pad, bH); ctx.stroke();
  // Parabola
  ctx.strokeStyle = '#0369a1';
  ctx.lineWidth = 2.5;
  ctx.beginPath();
  var T = 2 * v0 * Math.sin(rad) / g;
  for (var i = 0; i <= 120; i++) {
    var t = T * i / 120;
    var x = pad + v0 * Math.cos(rad) * t * scX;
    var y = bH - (v0 * Math.sin(rad) * t - 0.5 * g * t * t) * scY;
    if (i === 0) ctx.moveTo(x, y); else ctx.lineTo(x, y);
  }
  ctx.stroke();
  // Ball
  var tMid = T * 0.5;
  var bx = pad + v0 * Math.cos(rad) * tMid * scX;
  var by = bH - (v0 * Math.sin(rad) * tMid - 0.5 * g * tMid * tMid) * scY;
  ctx.beginPath(); ctx.arc(bx, by, 7, 0, Math.PI * 2);
  ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.acceleration:'#f97316'); ctx.fill();
  // Angle arc
  ctx.strokeStyle = '#0369a1'; ctx.lineWidth = 1.5;
  ctx.beginPath(); ctx.arc(pad, bH, 28, -rad, 0, true); ctx.stroke();
  ctx.fillStyle = '#0369a1'; ctx.font = 'bold 11px Inter';
  ctx.fillText(deg + '°', pad + 30, bH - 8);
  // Labels
  ctx.fillStyle = dark ? '#94a3b8' : '#64748b'; ctx.font = '11px Inter';
  ctx.fillText('L = ' + L.toFixed(1) + ' м', pad + 5, bH + 18);
  ctx.fillText('H = ' + Hmax.toFixed(1) + ' м', bx - 20, by - 10);
  // Launch arrow
  ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981'); ctx.lineWidth = 2;
  var arLen = 40;
  ctx.beginPath();
  ctx.moveTo(pad, bH);
  ctx.lineTo(pad + arLen * Math.cos(rad), bH - arLen * Math.sin(rad));
  ctx.stroke();
}

// ══════════════════════════════════════════════
//  §23 — ЗАКОН ТЯГОТЕНИЯ: ИНТЕРАКТИВ
// ══════════════════════════════════════════════
function upd23() {
  var m1 = +document.getElementById('sl23m1').value;
  var m2 = +document.getElementById('sl23m2').value;
  var r  = +document.getElementById('sl23r').value;
  document.getElementById('v23m1').textContent = m1 + ' кг';
  document.getElementById('v23m2').textContent = m2 + ' кг';
  document.getElementById('v23r').textContent  = r + ' м';
  var G = 6.674e-11;
  var F = G * m1 * m2 / (r * r);
  var el = document.getElementById('res23');
  if (el) el.textContent = 'F = ' + F.toExponential(3) + ' Н';
  drawGravity23(m1, m2, r, F);
}
function drawGravity23(m1, m2, r, F) {
  var cv = document.getElementById('cv23');
  if (!cv || cv.offsetWidth === 0) return;
  var dpr = window.devicePixelRatio || 1;
  var W = cv.offsetWidth, H = cv.offsetHeight || 160;
  cv.width = Math.round(W * dpr); cv.height = Math.round(H * dpr);
  var ctx = cv.getContext('2d');
  ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
  var dark = document.body.classList.contains('dark');
  ctx.clearRect(0, 0, W, H);
  var cy = H / 2;
  var r1 = Math.max(12, Math.min(35, 8 + m1 * 0.4));
  var r2 = Math.max(12, Math.min(35, 8 + m2 * 0.4));
  var gap = Math.max(40, Math.min(W - 2 * r1 - 2 * r2 - 60, (r / 20) * (W - 80)));
  var x1 = 50, x2 = x1 + 2 * r1 + gap + 2 * r2;
  if (x2 > W - 30) x2 = W - 30;
  // Body 1
  ctx.beginPath(); ctx.arc(x1 + r1, cy, r1, 0, Math.PI * 2);
  ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.forceGravity:'#1d4ed8'); ctx.fill();
  ctx.fillStyle = '#fff'; ctx.font = 'bold 11px Inter'; ctx.textAlign = 'center';
  ctx.fillText(m1 + ' кг', x1 + r1, cy + 4);
  // Body 2
  ctx.beginPath(); ctx.arc(x2 - r2, cy, r2, 0, Math.PI * 2);
  ctx.fillStyle = '#0369a1'; ctx.fill();
  ctx.fillStyle = '#fff'; ctx.font = 'bold 11px Inter';
  ctx.fillText(m2 + ' кг', x2 - r2, cy + 4);
  // Arrows
  var maxArr = 60, normF = Math.log10(F + 1e-11) + 11;
  var arrLen = Math.max(8, Math.min(maxArr, normF * 8));
  ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.acceleration:'#f97316'); ctx.lineWidth = 2.5;
  // Left arrow (toward right)
  ctx.beginPath(); ctx.moveTo(x1 + r1, cy); ctx.lineTo(x1 + r1 + arrLen, cy); ctx.stroke();
  ctx.beginPath(); ctx.moveTo(x1 + r1 + arrLen, cy - 5); ctx.lineTo(x1 + r1 + arrLen + 8, cy); ctx.lineTo(x1 + r1 + arrLen, cy + 5); ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.acceleration:'#f97316'); ctx.fill();
  // Right arrow (toward left)
  ctx.beginPath(); ctx.moveTo(x2 - r2, cy); ctx.lineTo(x2 - r2 - arrLen, cy); ctx.stroke();
  ctx.beginPath(); ctx.moveTo(x2 - r2 - arrLen, cy - 5); ctx.lineTo(x2 - r2 - arrLen - 8, cy); ctx.lineTo(x2 - r2 - arrLen, cy + 5); ctx.fill();
  // r label
  ctx.fillStyle = dark ? '#94a3b8' : '#64748b'; ctx.font = '11px Inter'; ctx.textAlign = 'center';
  ctx.fillText('r = ' + r + ' м', (x1 + r1 + x2 - r2) / 2, cy + 30);
  // F label
  ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.acceleration:'#f97316'); ctx.font = 'bold 12px Inter';
  ctx.fillText('F = ' + F.toExponential(2) + ' Н', (x1 + r1 + x2 - r2) / 2, cy - 20);
  ctx.textAlign = 'left';
}

// ══════════════════════════════════════════════
//  §24 — ВЕС ТЕЛА В ЛИФТЕ: ИНТЕРАКТИВ
// ══════════════════════════════════════════════
function upd24() {
  var m  = +document.getElementById('sl24m').value;
  var a  = +document.getElementById('sl24a').value;
  document.getElementById('v24m').textContent = m + ' кг';
  document.getElementById('v24a').textContent = a > 0 ? '+' + a + ' м/с²' : (a < 0 ? a + ' м/с²' : '0 м/с² (покой/равном.)');
  var g = 10;
  var Ft = m * g;
  var P = m * (g + a);
  var el = document.getElementById('res24');
  if (el) {
    var status = a > 0 ? ' (перегрузка ⬆)' : (a < 0 ? ' (облегчение ⬇)' : ' (норма)');
    if (a <= -10) status = '  НЕВЕСОМОСТЬ!';
    el.textContent = 'P = ' + P.toFixed(0) + ' Н | F_т = ' + Ft.toFixed(0) + ' Н' + status;
  }
  drawElevator24(m, a, P, Ft);
}
function drawElevator24(m, a, P, Ft) {
  var cv = document.getElementById('cv24');
  if (!cv || cv.offsetWidth === 0) return;
  var dpr = window.devicePixelRatio || 1;
  var W = cv.offsetWidth, H = cv.offsetHeight || 200;
  cv.width = Math.round(W * dpr); cv.height = Math.round(H * dpr);
  var ctx = cv.getContext('2d');
  ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
  var dark = document.body.classList.contains('dark');
  ctx.clearRect(0, 0, W, H);
  var cx = W / 2, bY = H - 20;
  // Elevator cabin
  var ew = 120, eh = 80, ex = cx - ew / 2, ey = bY - eh - 60;
  ctx.strokeStyle = dark ? '#475569' : '#94a3b8'; ctx.lineWidth = 2;
  ctx.strokeRect(ex, ey, ew, eh);
  // Cable
  ctx.strokeStyle = dark ? '#64748b' : '#94a3b8'; ctx.lineWidth = 2;
  ctx.beginPath(); ctx.moveTo(cx, ey); ctx.lineTo(cx, 20); ctx.stroke();
  // Person inside elevator
  var px = cx, pBase = ey + eh - 5;
  ctx.fillStyle = dark ? '#93c5fd' : '#1d4ed8';
  ctx.beginPath(); ctx.arc(px, pBase - 30, 12, 0, Math.PI * 2); ctx.fill();
  ctx.strokeStyle = dark ? '#93c5fd' : '#1d4ed8'; ctx.lineWidth = 2.5;
  ctx.beginPath(); ctx.moveTo(px, pBase - 18); ctx.lineTo(px, pBase - 5); ctx.stroke();
  ctx.beginPath(); ctx.moveTo(px - 10, pBase - 10); ctx.lineTo(px + 10, pBase - 10); ctx.stroke();
  // Weight arrow (F_t - downward, red)
  var g = 10, sc = Math.max(15, Math.min(60, Ft / (m * g) * 35));
  ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.lineWidth = 2.5;
  ctx.beginPath(); ctx.moveTo(px + 25, pBase - 20); ctx.lineTo(px + 25, pBase - 20 + sc); ctx.stroke();
  ctx.beginPath(); ctx.moveTo(px + 22, pBase - 20 + sc - 6); ctx.lineTo(px + 25, pBase - 20 + sc + 4); ctx.lineTo(px + 28, pBase - 20 + sc - 6); ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.fill();
  ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.font = '10px Inter'; ctx.textAlign = 'left';
  ctx.fillText('F_т=' + Ft.toFixed(0) + 'Н', px + 30, pBase - 20 + sc / 2);
  // Reaction (P - upward, green), clamped to 0 if weightless
  var Pdisp = Math.max(0, P);
  var scP = Math.max(0, Math.min(60, Pdisp / (m * g) * 35));
  ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981'); ctx.lineWidth = 2.5;
  ctx.beginPath(); ctx.moveTo(px - 25, pBase); ctx.lineTo(px - 25, pBase - scP); ctx.stroke();
  if (scP > 3) {
    ctx.beginPath(); ctx.moveTo(px - 28, pBase - scP + 6); ctx.lineTo(px - 25, pBase - scP - 4); ctx.lineTo(px - 22, pBase - scP + 6); ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981'); ctx.fill();
  }
  ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981'); ctx.font = '10px Inter'; ctx.textAlign = 'right';
  ctx.fillText('P=' + Pdisp.toFixed(0) + 'Н', px - 28, pBase - scP / 2);
  // Acceleration arrow
  if (a !== 0) {
    ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.acceleration:'#f97316'); ctx.lineWidth = 2;
    var arDir = a > 0 ? -1 : 1;
    ctx.beginPath(); ctx.moveTo(ex - 20, ey + eh / 2); ctx.lineTo(ex - 20, ey + eh / 2 + arDir * 35); ctx.stroke();
    ctx.beginPath();
    var arTip = ey + eh / 2 + arDir * 35;
    ctx.moveTo(ex - 23, arTip - arDir * 6); ctx.lineTo(ex - 20, arTip + arDir * 4); ctx.lineTo(ex - 17, arTip - arDir * 6);
    ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.acceleration:'#f97316'); ctx.fill();
    ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.acceleration:'#f97316'); ctx.font = 'bold 10px Inter'; ctx.textAlign = 'center';
    ctx.fillText('a=' + (a > 0 ? '+' : '') + a + ' м/с²', ex - 20, ey + eh / 2 + arDir * 50 + (a > 0 ? -5 : 10));
  }
  // Label
  ctx.fillStyle = dark ? '#e2e8f0' : '#1e293b'; ctx.font = 'bold 12px Inter'; ctx.textAlign = 'center';
  var statusText = a > -10 ? 'P = ' + P.toFixed(0) + ' Н' : ' НЕВЕСОМОСТЬ!';
  ctx.fillStyle = a <= -10 ? '#f97316' : (P > Ft + 1 ? '#0369a1' : (P < Ft - 1 ? '#7e22ce' : (dark ? '#e2e8f0' : '#1e293b')));
  ctx.fillText(statusText, cx, H - 5);
  ctx.textAlign = 'left';
}

// ══════════════════════════════════════════════
//  §25 — МОМЕНТ СИЛЫ: КАЧЕЛИ + РЕЗУЛЬТАТ
// ══════════════════════════════════════════════
function upd25() {
  var l1 = +document.getElementById('sl25l1').value / 10; // 0.1–2.0 m
  var l2 = +document.getElementById('sl25l2').value / 10;
  document.getElementById('v25l1').textContent = l1.toFixed(1) + ' м';
  document.getElementById('v25l2').textContent = l2.toFixed(1) + ' м';
  var m1 = 4, m2 = 6, g = 10;
  var M1 = (m1 * g * l1).toFixed(1);
  var M2 = (m2 * g * l2).toFixed(1);
  var diff = Math.abs(parseFloat(M1) - parseFloat(M2));
  var status = diff < 1.0 ? ' РАВНОВЕСИЕ!' : (parseFloat(M1) > parseFloat(M2) ? '← наклон влево' : 'наклон вправо →');
  var el = document.getElementById('res25');
  if (el) { el.textContent = 'M₁ = ' + M1 + ' Н·м | M₂ = ' + M2 + ' Н·м — ' + status; doRender(el); }
  drawSeesaw25();
}

function drawSeesaw25() {
  var cv = document.getElementById('cv25');
  if (!cv || cv.offsetWidth === 0) return;
  var dpr = window.devicePixelRatio || 1;
  var W = cv.offsetWidth, H = cv.offsetHeight || 180;
  if (cv.width !== Math.round(W * dpr) || cv.height !== Math.round(H * dpr)) {
    cv.width = Math.round(W * dpr); cv.height = Math.round(H * dpr);
  }
  var ctx = cv.getContext('2d');
  ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
  ctx.clearRect(0, 0, W, H);
  var dk = document.body.classList.contains('dark');
  ctx.fillStyle = dk ? '#1e293b' : '#f0f9ff'; ctx.fillRect(0, 0, W, H);

  var l1 = +document.getElementById('sl25l1').value / 10;
  var l2 = +document.getElementById('sl25l2').value / 10;
  var m1 = 4, m2 = 6, g = 10;
  var M1 = m1 * g * l1, M2 = m2 * g * l2;
  var maxL = 2.0;
  var cx = W / 2, pivotY = H * 0.58;
  var scale = (W * 0.43) / maxL; // pixels per meter

  // Tilt angle based on moment imbalance
  var tilt = Math.min(0.36, Math.max(-0.36, (M1 - M2) / 80));

  // Draw pivot support (triangle)
  ctx.beginPath();
  ctx.moveTo(cx, pivotY + 2);
  ctx.lineTo(cx - 18, pivotY + 34);
  ctx.lineTo(cx + 18, pivotY + 34);
  ctx.closePath();
  ctx.fillStyle = dk ? '#475569' : '#94a3b8'; ctx.fill();
  ctx.strokeStyle = dk ? '#64748b' : '#64748b'; ctx.lineWidth = 1.5; ctx.stroke();
  // Base
  ctx.fillStyle = dk ? '#334155' : '#cbd5e1';
  ctx.fillRect(cx - 28, pivotY + 34, 56, 10);

  // Beam (tilted)
  var beamLen = (l1 + l2) * scale;
  ctx.save();
  ctx.translate(cx, pivotY);
  ctx.rotate(tilt);
  // Beam rect
  ctx.fillStyle = dk ? '#64748b' : '#94a3b8';
  ctx.fillRect(-beamLen * l1 / (l1 + l2) - 4, -6, beamLen + 8, 12);
  ctx.strokeStyle = dk ? '#475569' : '#64748b'; ctx.lineWidth = 1; ctx.strokeRect(-beamLen * l1 / (l1 + l2) - 4, -6, beamLen + 8, 12);

  // Left weight (blue, m1=4kg) at distance l1
  var x1 = -l1 * scale;
  var bH = 30 + m1 * 4;
  ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6');
  ctx.fillRect(x1 - 20, -6 - bH, 40, bH);
  ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.forceGravity:'#1d4ed8'); ctx.lineWidth = 2; ctx.strokeRect(x1 - 20, -6 - bH, 40, bH);
  ctx.fillStyle = '#fff'; ctx.font = 'bold 9px Inter'; ctx.textAlign = 'center';
  ctx.fillText(m1 + ' кг', x1, -6 - bH/2 + 4);
  // l1 label
  ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6'); ctx.font = '8px Inter';
  ctx.fillText('l₁=' + l1.toFixed(1) + 'м', x1/2, 16);
  // M1 label
  ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6'); ctx.font = 'bold 9px Inter';
  ctx.fillText('M₁=' + M1.toFixed(0) + ' Н·м', x1, -6 - bH - 10);

  // Right weight (orange, m2=6kg) at distance l2
  var x2 = l2 * scale;
  var bH2 = 30 + m2 * 4;
  ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.acceleration:'#f97316');
  ctx.fillRect(x2 - 20, -6 - bH2, 40, bH2);
  ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.acceleration:'#ea580c'); ctx.lineWidth = 2; ctx.strokeRect(x2 - 20, -6 - bH2, 40, bH2);
  ctx.fillStyle = '#fff'; ctx.font = 'bold 9px Inter';
  ctx.fillText(m2 + ' кг', x2, -6 - bH2/2 + 4);
  // l2 label
  ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.acceleration:'#f97316'); ctx.font = '8px Inter';
  ctx.fillText('l₂=' + l2.toFixed(1) + 'м', x2/2, 16);
  // M2 label
  ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.acceleration:'#f97316'); ctx.font = 'bold 9px Inter';
  ctx.fillText('M₂=' + M2.toFixed(0) + ' Н·м', x2, -6 - bH2 - 10);

  ctx.textAlign = 'left';
  ctx.restore();

  // Balance indicator
  var diff = Math.abs(M1 - M2);
  ctx.font = 'bold 11px Inter'; ctx.textAlign = 'center';
  if (diff < 1.5) {
    ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981');
    ctx.fillText(' РАВНОВЕСИЕ!  M₁ = M₂', W/2, H - 8);
  } else {
    ctx.fillStyle = dk ? '#94a3b8' : '#64748b';
    ctx.fillText('Наклон: ΔM = ' + diff.toFixed(0) + ' Н·м', W/2, H - 8);
  }
  ctx.textAlign = 'left';
}

// ══════════════════════════════════════════════
//  §26 — РЫЧАГ: ИНТЕРАКТИВ
// ══════════════════════════════════════════════
function upd26() {
  var l2 = +document.getElementById('sl26l2').value / 10; // нагрузка
  var l1 = +document.getElementById('sl26l1').value / 10; // сила
  document.getElementById('v26l2').textContent = l2.toFixed(1) + ' м';
  document.getElementById('v26l1').textContent = l1.toFixed(1) + ' м';
  var mg = 500; // 50 кг × 10
  var F = (mg * l2 / l1).toFixed(0);
  var gain = (l1 / l2).toFixed(1);
  var el = document.getElementById('res26');
  if (el) { el.textContent = 'F = ' + F + ' Н  |  Выигрыш = ' + gain + '×  |  Нагрузка 50 кг'; doRender(el); }
  drawLever26();
}

function drawLever26() {
  var cv = document.getElementById('cv26');
  if (!cv || cv.offsetWidth === 0) return;
  var dpr = window.devicePixelRatio || 1;
  var W = cv.offsetWidth, H = cv.offsetHeight || 160;
  if (cv.width !== Math.round(W * dpr) || cv.height !== Math.round(H * dpr)) {
    cv.width = Math.round(W * dpr); cv.height = Math.round(H * dpr);
  }
  var ctx = cv.getContext('2d');
  ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
  ctx.clearRect(0, 0, W, H);
  var dk = document.body.classList.contains('dark');
  ctx.fillStyle = dk ? '#1e293b' : '#f0f9ff'; ctx.fillRect(0, 0, W, H);

  var l2 = +document.getElementById('sl26l2').value / 10;
  var l1 = +document.getElementById('sl26l1').value / 10;
  var mg = 500, F = mg * l2 / l1;
  var gain = l1 / l2;

  var pivotY = H * 0.52, cx = W * 0.42;
  var scale = Math.min((W - 40) / (l1 + l2 + 0.3), 90);
  var x_load = cx - l2 * scale; // left side: load
  var x_force = cx + l1 * scale; // right side: force applied

  // Ground
  ctx.fillStyle = dk ? '#334155' : '#e2e8f0'; ctx.fillRect(0, pivotY + 28, W, H - pivotY - 28);
  ctx.strokeStyle = dk ? '#64748b' : '#94a3b8'; ctx.lineWidth = 1.5;
  ctx.beginPath(); ctx.moveTo(0, pivotY + 28); ctx.lineTo(W, pivotY + 28); ctx.stroke();

  // Fulcrum
  ctx.beginPath();
  ctx.moveTo(cx, pivotY + 3);
  ctx.lineTo(cx - 15, pivotY + 28);
  ctx.lineTo(cx + 15, pivotY + 28);
  ctx.closePath();
  ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.acceleration:'#f97316'); ctx.fill();

  // Beam
  ctx.fillStyle = dk ? '#64748b' : '#94a3b8';
  ctx.fillRect(x_load - 4, pivotY - 5, x_force - x_load + 8, 10);
  ctx.strokeStyle = dk ? '#475569' : '#64748b'; ctx.lineWidth = 1; ctx.stroke();

  // Load (left, down) — mg arrow
  var arrowScale = Math.min(55, mg * 0.055);
  ctx.beginPath(); ctx.moveTo(x_load, pivotY - 5); ctx.lineTo(x_load, pivotY - 5 - arrowScale);
  ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.lineWidth = 2.5; ctx.stroke();
  ctx.beginPath(); ctx.moveTo(x_load, pivotY - 5 - arrowScale);
  ctx.lineTo(x_load - 6, pivotY - 5 - arrowScale + 12); ctx.lineTo(x_load + 6, pivotY - 5 - arrowScale + 12);
  ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.fill();
  ctx.font = 'bold 9px Inter'; ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.textAlign = 'center';
  ctx.fillText('G = ' + mg + ' Н', x_load, pivotY - 5 - arrowScale - 5);

  // Applied force (right, down)
  var fArrow = Math.min(55, F * 0.055);
  ctx.beginPath(); ctx.moveTo(x_force, pivotY - 5); ctx.lineTo(x_force, pivotY - 5 - fArrow);
  ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6'); ctx.lineWidth = 2.5; ctx.stroke();
  ctx.beginPath(); ctx.moveTo(x_force, pivotY - 5 - fArrow);
  ctx.lineTo(x_force - 6, pivotY - 5 - fArrow + 12); ctx.lineTo(x_force + 6, pivotY - 5 - fArrow + 12);
  ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6'); ctx.fill();
  ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6'); ctx.font = 'bold 9px Inter';
  ctx.fillText('F = ' + F.toFixed(0) + ' Н', x_force, pivotY - 5 - fArrow - 5);

  // l1 and l2 labels
  ctx.font = '9px Inter'; ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444');
  ctx.fillText('l₂ = ' + l2.toFixed(1) + ' м', (x_load + cx) / 2, pivotY + 20);
  ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6');
  ctx.fillText('l₁ = ' + l1.toFixed(1) + ' м', (cx + x_force) / 2, pivotY + 20);

  // Gain badge
  ctx.font = 'bold 11px Inter'; ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981'); ctx.textAlign = 'center';
  ctx.fillText('Выигрыш = ' + gain.toFixed(1) + '×  →  F в ' + gain.toFixed(1) + ' раз меньше нагрузки!', W/2, H - 8);
  ctx.textAlign = 'left';
}

// ══════════════════════════════════════════════
//  §27 — НАКЛОННАЯ ПЛОСКОСТЬ + КПД
// ══════════════════════════════════════════════
function upd27() {
  var alpha = +document.getElementById('sl27a').value;
  var m = +document.getElementById('sl27m').value;
  document.getElementById('v27a').textContent = alpha + '°';
  document.getElementById('v27m').textContent = m + ' кг';
  var rad = alpha * Math.PI / 180;
  var F = (m * 10 * Math.sin(rad)).toFixed(0);
  var gain = (1 / Math.sin(rad)).toFixed(1);
  var el = document.getElementById('res27');
  if (el) { el.textContent = 'F = ' + F + ' Н (против ' + (m*10) + ' Н напрямую) | Выигрыш = ' + gain + '×'; doRender(el); }
  drawIncline27();
}

function upd27mu() {
  var muInt = +document.getElementById('sl27mu').value;
  var mu = (muInt / 100).toFixed(2);
  document.getElementById('v27mu').textContent = mu;
  var alpha = +document.getElementById('sl27a').value;
  var rad = alpha * Math.PI / 180;
  var sinA = Math.sin(rad), cosA = Math.cos(rad);
  var eta, label;
  if (sinA < 0.001) {
    eta = 100;
  } else {
    // F_ideal = mg*sin(a), F_real = mg*(sin(a)+mu*cos(a))
    // eta = F_ideal/F_real = sin/(sin+mu*cos)
    eta = Math.min(100, (sinA / (sinA + mu * cosA) * 100)).toFixed(0);
  }
  var loss = (100 - eta);
  var el = document.getElementById('res27mu');
  if (el) { el.textContent = 'КПД = ' + eta + '%  |  Потери на трение: ' + loss + '%'; doRender(el); }
  drawEfficiency27(+eta);
}

function drawIncline27() {
  var cv = document.getElementById('cv27');
  if (!cv || cv.offsetWidth === 0) return;
  var dpr = window.devicePixelRatio || 1;
  var W = cv.offsetWidth, H = cv.offsetHeight || 180;
  if (cv.width !== Math.round(W * dpr) || cv.height !== Math.round(H * dpr)) {
    cv.width = Math.round(W * dpr); cv.height = Math.round(H * dpr);
  }
  var ctx = cv.getContext('2d');
  ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
  ctx.clearRect(0, 0, W, H);
  var dk = document.body.classList.contains('dark');
  ctx.fillStyle = dk ? '#1e293b' : '#f0f9ff'; ctx.fillRect(0, 0, W, H);

  var alpha = +document.getElementById('sl27a').value;
  var m = +document.getElementById('sl27m').value;
  var rad = alpha * Math.PI / 180;
  var mg = m * 10;
  var F = mg * Math.sin(rad);
  var N = mg * Math.cos(rad);

  // Draw inclined plane (triangle)
  var bX = 20, bY = H - 30, triW = W - 40, triH = triW * Math.tan(rad);
  if (triH > H - 55) { triH = H - 55; triW = triH / Math.tan(rad); bX = 20; }
  var topX = bX, topY = bY - triH;
  var rightX = bX + triW, rightY = bY;

  ctx.beginPath();
  ctx.moveTo(bX, bY); ctx.lineTo(rightX, rightY); ctx.lineTo(topX, topY);
  ctx.closePath();
  ctx.fillStyle = dk ? 'rgba(71,85,105,.35)' : 'rgba(203,213,225,.65)'; ctx.fill();
  ctx.strokeStyle = dk ? '#64748b' : '#94a3b8'; ctx.lineWidth = 2; ctx.stroke();

  // Angle arc
  ctx.beginPath(); ctx.arc(rightX, rightY, 28, Math.PI - rad, Math.PI);
  ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.warn:'#f59e0b'); ctx.lineWidth = 1.5; ctx.stroke();
  ctx.font = 'bold 10px Inter'; ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.warn:'#f59e0b');
  ctx.fillText('α=' + alpha + '°', rightX - 52, rightY - 10);

  // Block on slope
  var blockDist = 0.35; // fraction along slope from top
  var slopeLen = Math.sqrt(triW * triW + triH * triH);
  var bBlockX = topX + blockDist * triW;
  var bBlockY = topY + blockDist * triH;
  var bW = 30, bH = 20;

  ctx.save();
  ctx.translate(bBlockX, bBlockY);
  ctx.rotate(Math.atan2(triH, triW));
  ctx.fillStyle = '#6366f1';
  ctx.fillRect(-bW/2, -bH, bW, bH);
  ctx.strokeStyle = '#4338ca'; ctx.lineWidth = 2; ctx.strokeRect(-bW/2, -bH, bW, bH);
  ctx.fillStyle = '#fff'; ctx.font = 'bold 9px Inter'; ctx.textAlign = 'center';
  ctx.fillText(m + ' кг', 0, -bH/2 + 4);
  ctx.textAlign = 'left';
  ctx.restore();

  // mg arrow (vertical down)
  var arLen = Math.min(55, mg * 0.25);
  ctx.beginPath(); ctx.moveTo(bBlockX, bBlockY); ctx.lineTo(bBlockX, bBlockY + arLen);
  ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.lineWidth = 2.5; ctx.stroke();
  ctx.beginPath(); ctx.moveTo(bBlockX, bBlockY+arLen); ctx.lineTo(bBlockX-5,bBlockY+arLen-10); ctx.lineTo(bBlockX+5,bBlockY+arLen-10);
  ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.fill();
  ctx.font = 'bold 9px Inter'; ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.textAlign = 'left';
  ctx.fillText('mg=' + mg + 'Н', bBlockX + 6, bBlockY + arLen - 2);

  // F arrow (along slope, up)
  var fLen = Math.min(50, F * 0.55);
  var slopeUx = -triW / slopeLen, slopeUy = -triH / slopeLen; // up the slope
  ctx.beginPath(); ctx.moveTo(bBlockX, bBlockY);
  ctx.lineTo(bBlockX + slopeUx * fLen, bBlockY + slopeUy * fLen);
  ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6'); ctx.lineWidth = 2.5; ctx.stroke();
  var ax2 = bBlockX + slopeUx * fLen, ay2 = bBlockY + slopeUy * fLen;
  ctx.beginPath(); ctx.moveTo(ax2, ay2);
  ctx.lineTo(ax2 - slopeUx * 12 + slopeUy * 5, ay2 - slopeUy * 12 - slopeUx * 5);
  ctx.lineTo(ax2 - slopeUx * 12 - slopeUy * 5, ay2 - slopeUy * 12 + slopeUx * 5);
  ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6'); ctx.fill();
  ctx.font = 'bold 9px Inter'; ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6');
  ctx.fillText('F=' + F.toFixed(0) + 'Н', ax2 + 5, ay2 - 3);

  // N arrow (perpendicular to slope, outward)
  var nLen = Math.min(45, N * 0.22);
  var nUx = triH / slopeLen, nUy = -triW / slopeLen; // outward normal
  ctx.beginPath(); ctx.moveTo(bBlockX, bBlockY);
  ctx.lineTo(bBlockX + nUx * nLen, bBlockY + nUy * nLen);
  ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981'); ctx.lineWidth = 2; ctx.stroke();
  ctx.font = '9px Inter'; ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981');
  ctx.fillText('N=' + N.toFixed(0) + 'Н', bBlockX + nUx * nLen + 3, bBlockY + nUy * nLen - 2);

  // h and l labels
  ctx.font = '9px Inter'; ctx.fillStyle = dk ? '#94a3b8' : '#64748b';
  ctx.textAlign = 'center';
  ctx.fillText('l = ' + (slopeLen * 0.035).toFixed(1) + 'м (условно)', (topX + rightX)/2, bY + 16);
  ctx.fillText('h', topX - 14, (topY + bY)/2);
  ctx.textAlign = 'left';
}

function drawEfficiency27(eta) {
  var cv = document.getElementById('cv27eff');
  if (!cv || cv.offsetWidth === 0) return;
  var dpr = window.devicePixelRatio || 1;
  var W = cv.offsetWidth, H = cv.offsetHeight || 70;
  if (cv.width !== Math.round(W * dpr) || cv.height !== Math.round(H * dpr)) {
    cv.width = Math.round(W * dpr); cv.height = Math.round(H * dpr);
  }
  var ctx = cv.getContext('2d');
  ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
  ctx.clearRect(0, 0, W, H);
  var dk = document.body.classList.contains('dark');
  ctx.fillStyle = dk ? '#1e293b' : '#f0f9ff'; ctx.fillRect(0, 0, W, H);

  var barH = 30, barY = (H - barH) / 2, pad = 16;
  // Background bar
  ctx.fillStyle = dk ? '#334155' : '#e2e8f0';
  ctx.beginPath();
  if (ctx.roundRect) ctx.roundRect(pad, barY, W - pad*2, barH, 8);
  else ctx.rect(pad, barY, W - pad*2, barH);
  ctx.fill();
  // Useful work (green)
  var usefulW = Math.max(0, (eta / 100) * (W - pad*2));
  if (usefulW > 0) {
    ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981');
    ctx.beginPath();
    if (ctx.roundRect) ctx.roundRect(pad, barY, usefulW, barH, 8);
    else ctx.rect(pad, barY, usefulW, barH);
    ctx.fill();
  }
  // Waste (red)
  var wasteW = (W - pad*2) - usefulW;
  if (wasteW > 4) {
    ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444');
    ctx.beginPath();
    ctx.rect(pad + usefulW, barY, wasteW, barH);
    ctx.fill();
    // Round right corner
    if (ctx.roundRect) {
      ctx.beginPath(); ctx.roundRect(pad + usefulW, barY, wasteW, barH, [0, 8, 8, 0]); ctx.fill();
    }
  }
  // Labels
  ctx.font = 'bold 10px Inter'; ctx.fillStyle = '#fff'; ctx.textAlign = 'center';
  if (usefulW > 60) ctx.fillText('Полезная ' + eta + '%', pad + usefulW / 2, barY + barH/2 + 4);
  if (wasteW > 50) ctx.fillText('Потери ' + (100 - eta) + '%', pad + usefulW + wasteW/2, barY + barH/2 + 4);
  ctx.textAlign = 'left';
}

// ══════════════════════════════════════════════
//  §15 — АНИМАЦИЯ ИНЕРЦИИ
// ══════════════════════════════════════════════
var anim15Id = null;
function startAnim15() {
  var cv = document.getElementById('cv15');
  if (!cv || cv.offsetWidth === 0) return;
  if (anim15Id) { cancelAnimationFrame(anim15Id); anim15Id = null; }
  var dpr = window.devicePixelRatio || 1;
  var W = cv.offsetWidth, H = cv.offsetHeight || 170;
  cv.width = Math.round(W * dpr); cv.height = Math.round(H * dpr);
  var ctx = cv.getContext('2d');
  ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
  var x_ice = 30, x_asp = 30, v_ice = 3.2, v_asp = 3.2, t15 = 0;
  function fr15() {
    ctx.clearRect(0, 0, W, H);
    var dk = document.body.classList.contains('dark');
    ctx.fillStyle = dk ? '#1e293b' : '#f0f9ff'; ctx.fillRect(0, 0, W, H);
    var mid = H / 2;
    // Ice track
    ctx.fillStyle = dk ? 'rgba(186,230,253,.12)' : 'rgba(224,242,254,.7)';
    ctx.fillRect(0, 4, W, mid - 8);
    ctx.beginPath(); ctx.moveTo(0, mid - 2); ctx.lineTo(W, mid - 2);
    ctx.strokeStyle = '#7dd3fc'; ctx.lineWidth = 2; ctx.stroke();
    // Asphalt track
    ctx.fillStyle = dk ? 'rgba(120,113,108,.15)' : 'rgba(231,229,228,.65)';
    ctx.fillRect(0, mid + 4, W, H - mid - 8);
    ctx.strokeStyle = dk ? '#78716c' : '#a8a29e'; ctx.lineWidth = 1;
    for (var bx = 8; bx < W; bx += 20) {
      ctx.beginPath(); ctx.arc(bx, H - 12, 3, 0, Math.PI); ctx.stroke();
    }
    // Track labels
    ctx.font = 'bold 10px Inter,sans-serif';
    ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.velocity:'#0284c7'); ctx.fillText(' Лёд — без трения', 8, 18);
    ctx.fillStyle = '#78716c'; ctx.fillText(' Асфальт — трение', 8, mid + 18);
    // Physics
    x_ice += v_ice;
    if (x_ice > W - 18) { x_ice = W - 18; v_ice = -Math.abs(v_ice); }
    if (x_ice < 18) { x_ice = 18; v_ice = Math.abs(v_ice); }
    if (v_asp > 0) v_asp = Math.max(0, v_asp - 0.038);
    x_asp += v_asp;
    if (x_asp > W - 18) x_asp = W - 18;
    // Ice ball (blue)
    var yIce = mid / 2;
    ctx.beginPath(); ctx.arc(x_ice, yIce, 13, 0, Math.PI * 2);
    ctx.fillStyle = '#38bdf8'; ctx.fill();
    ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.velocity:'#0284c7'); ctx.lineWidth = 2; ctx.stroke();
    if (Math.abs(v_ice) > 0.3) {
      var d = v_ice > 0 ? 1 : -1;
      ctx.beginPath(); ctx.moveTo(x_ice + d*14, yIce); ctx.lineTo(x_ice + d*28, yIce);
      ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.velocity:'#0284c7'); ctx.lineWidth = 2; ctx.stroke();
      ctx.beginPath(); ctx.moveTo(x_ice+d*28, yIce); ctx.lineTo(x_ice+d*21,yIce-5); ctx.lineTo(x_ice+d*21,yIce+5);
      ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.velocity:'#0284c7'); ctx.fill();
    }
    ctx.font = 'bold 9px Inter'; ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.velocity:'#0284c7');
    ctx.fillText('v=' + Math.abs(v_ice).toFixed(1), x_ice - 12, yIce + 24);
    // Asphalt ball (orange)
    var yAsp = mid + (H - mid) / 2;
    ctx.beginPath(); ctx.arc(x_asp, yAsp, 13, 0, Math.PI * 2);
    ctx.fillStyle = '#fb923c'; ctx.fill();
    ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.acceleration:'#ea580c'); ctx.lineWidth = 2; ctx.stroke();
    ctx.font = 'bold 9px Inter'; ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.acceleration:'#ea580c');
    if (v_asp > 0.3) {
      ctx.beginPath(); ctx.moveTo(x_asp+14,yAsp); ctx.lineTo(x_asp+28,yAsp);
      ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.acceleration:'#ea580c'); ctx.lineWidth = 2; ctx.stroke();
      ctx.beginPath(); ctx.moveTo(x_asp+28,yAsp); ctx.lineTo(x_asp+21,yAsp-5); ctx.lineTo(x_asp+21,yAsp+5);
      ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.acceleration:'#ea580c'); ctx.fill();
      ctx.fillText('v=' + v_asp.toFixed(1), x_asp - 12, yAsp - 17);
    } else {
      ctx.fillText(' СТОИТ', x_asp - 18, yAsp - 17);
    }
    t15++;
    if (t15 < 420) anim15Id = requestAnimationFrame(fr15);
  }
  x_ice = 30; x_asp = 30; v_ice = 3.2; v_asp = 3.2; t15 = 0; fr15();
}

// ══════════════════════════════════════════════
//  §16 — ПЛАНЕТНАЯ СЕТКА
// ══════════════════════════════════════════════
function initPlanetGrid16() {
  var grid = document.getElementById('planetGrid16');
  if (!grid) return;
  var planets = [
    { name: 'Земля',   icon: '', g: 9.8,  color: '#3b82f6' },
    { name: 'Луна',    icon: '', g: 1.6,  color: '#94a3b8' },
    { name: 'Марс',    icon: '', g: 3.7,  color: '#ef4444' },
    { name: 'Юпитер',  icon: '🪐', g: 25.0, color: '#f59e0b' },
    { name: 'Венера',  icon: '', g: 8.9,  color: '#fbbf24' }
  ];
  var m = 60;
  var html = '';
  for (var i = 0; i < planets.length; i++) {
    var p = planets[i];
    var F = (m * p.g).toFixed(0);
    var pct = Math.min(100, (p.g / 25 * 100)).toFixed(0);
    html += '<div style="background:var(--card);border:1.5px solid var(--border);border-radius:12px;padding:10px 8px;text-align:center">' +
      '<div style="font-size:1.5rem;margin-bottom:4px">' + p.icon + '</div>' +
      '<div style="font-weight:800;font-size:.82rem">' + p.name + '</div>' +
      '<div style="font-size:.74rem;color:var(--muted);margin:2px 0">g = ' + p.g + ' м/с²</div>' +
      '<div style="font-weight:700;font-size:.95rem;color:' + p.color + '">' + F + ' Н</div>' +
      '<div style="margin-top:5px;height:5px;background:var(--border);border-radius:3px;overflow:hidden">' +
      '<div style="height:100%;width:' + pct + '%;background:' + p.color + ';border-radius:3px"></div></div>' +
      '</div>';
  }
  grid.innerHTML = html;
}

// ══════════════════════════════════════════════
//  §17 — АНИМАЦИЯ F=ma
// ══════════════════════════════════════════════
var anim17Id = null;
function startAnim17() {
  var cv = document.getElementById('cv17');
  if (!cv || cv.offsetWidth === 0) return;
  if (anim17Id) { cancelAnimationFrame(anim17Id); anim17Id = null; }
  var dpr = window.devicePixelRatio || 1;
  var W = cv.offsetWidth, H = cv.offsetHeight || 120;
  cv.width = Math.round(W * dpr); cv.height = Math.round(H * dpr);
  var ctx = cv.getContext('2d');
  ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
  var F17 = +document.getElementById('sl17f').value;
  var m17 = +document.getElementById('sl17m').value;
  var a17 = F17 / m17;
  var x17 = 20, v17 = 0, t17 = 0;
  function fr17() {
    ctx.clearRect(0, 0, W, H);
    var dk = document.body.classList.contains('dark');
    ctx.fillStyle = dk ? '#1e293b' : '#f0f9ff'; ctx.fillRect(0, 0, W, H);
    // Ground
    ctx.fillStyle = dk ? '#334155' : '#e2e8f0';
    ctx.fillRect(0, H * 0.72, W, H - H * 0.72);
    ctx.strokeStyle = dk ? '#64748b' : '#94a3b8'; ctx.lineWidth = 1.5;
    ctx.beginPath(); ctx.moveTo(0, H * 0.72); ctx.lineTo(W, H * 0.72); ctx.stroke();
    var bW = 42, bH = 30, by = H * 0.72 - bH;
    // Block
    ctx.fillStyle = '#6366f1';
    ctx.fillRect(x17, by, bW, bH);
    ctx.strokeStyle = '#4338ca'; ctx.lineWidth = 2; ctx.stroke();
    ctx.fillStyle = '#fff'; ctx.font = 'bold 9px Inter'; ctx.textAlign = 'center';
    ctx.fillText(m17 + ' кг', x17 + bW / 2, by + bH / 2 + 4); ctx.textAlign = 'left';
    // Force arrow
    var aLen = Math.min(55, F17 * 1.1);
    ctx.beginPath(); ctx.moveTo(x17 + bW, by + bH / 2); ctx.lineTo(x17 + bW + aLen, by + bH / 2);
    ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.lineWidth = 3; ctx.stroke();
    ctx.beginPath(); var ax = x17 + bW + aLen;
    ctx.moveTo(ax, by+bH/2); ctx.lineTo(ax-11,by+bH/2-5); ctx.lineTo(ax-11,by+bH/2+5);
    ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.fill();
    ctx.font = 'bold 9px Inter'; ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444');
    ctx.fillText('F=' + F17 + 'Н', x17 + bW + 2, by - 4);
    // Velocity
    if (v17 > 0.5) {
      ctx.font = 'bold 9px Inter'; ctx.fillStyle = dk ? '#818cf8' : '#4338ca';
      ctx.fillText('v = ' + v17.toFixed(1) + ' м/с →', x17, by - 16);
    }
    ctx.font = 'bold 9px Inter'; ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981');
    ctx.fillText('a = ' + a17.toFixed(1) + ' м/с²', 6, 14);
    // Physics
    v17 += a17 * 0.06; x17 += v17 * 0.7; t17++;
    if (x17 < W - 70 && t17 < 280) {
      anim17Id = requestAnimationFrame(fr17);
    } else {
      ctx.font = 'bold 12px Inter'; ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981'); ctx.textAlign = 'center';
      ctx.fillText(' v = ' + v17.toFixed(0) + ' м/с  |  a = ' + a17.toFixed(1) + ' м/с²', W/2, H/2 - 5);
      ctx.font = '10px Inter'; ctx.fillStyle = dk?'#94a3b8':'#64748b';
      ctx.fillText('Поменяй ползунки и нажми «Запустить снова»', W/2, H/2 + 12);
      ctx.textAlign = 'left';
    }
  }
  x17 = 20; v17 = 0; t17 = 0; fr17();
}

// ══════════════════════════════════════════════
//  §18 — АНИМАЦИЯ ОТДАЧИ (3-й закон)
// ══════════════════════════════════════════════
var anim18Id = null;
function startAnim18() {
  var cv = document.getElementById('cv18');
  if (!cv || cv.offsetWidth === 0) return;
  if (anim18Id) { cancelAnimationFrame(anim18Id); anim18Id = null; }
  var dpr = window.devicePixelRatio || 1;
  var W = cv.offsetWidth, H = cv.offsetHeight || 120;
  cv.width = Math.round(W * dpr); cv.height = Math.round(H * dpr);
  var ctx = cv.getContext('2d');
  ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
  var cx18 = W / 2;
  var x1 = cx18 - 18, x2 = cx18 + 18; // inner edges
  var v1 = 0, v2 = 0, phase18 = 0, pt18 = 0, t18 = 0;
  var m18a = 3, m18b = 9; // masses
  function fr18() {
    ctx.clearRect(0, 0, W, H);
    var dk = document.body.classList.contains('dark');
    ctx.fillStyle = dk ? '#1e293b' : '#f0f9ff'; ctx.fillRect(0, 0, W, H);
    // Ground
    ctx.fillStyle = dk ? '#334155' : '#e2e8f0'; ctx.fillRect(0, H * 0.75, W, H * 0.25);
    ctx.strokeStyle = dk ? '#64748b' : '#94a3b8'; ctx.lineWidth = 1.5;
    ctx.beginPath(); ctx.moveTo(0, H * 0.75); ctx.lineTo(W, H * 0.75); ctx.stroke();
    var bH = 34, y = H * 0.75 - bH;
    if (phase18 === 0) {
      // Static with spring
      ctx.fillStyle = '#6366f1'; ctx.fillRect(x1 - 34, y, 34, bH);
      ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.acceleration:'#f97316'); ctx.fillRect(x2, y, 44, bH);
      ctx.fillStyle = '#fff'; ctx.font = 'bold 9px Inter'; ctx.textAlign = 'center';
      ctx.fillText(m18a + ' кг', x1 - 17, y + bH/2 + 4);
      ctx.fillText(m18b + ' кг', x2 + 22, y + bH/2 + 4); ctx.textAlign = 'left';
      ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981'); ctx.lineWidth = 2; ctx.beginPath();
      for (var ss = x1; ss < x2; ss += 4) {
        ctx.lineTo(ss, y + (ss % 8 < 4 ? bH * 0.25 : bH * 0.75));
      }
      ctx.stroke();
      ctx.font = 'bold 10px Inter'; ctx.fillStyle = dk ? '#e2e8f0' : '#1e293b';
      ctx.textAlign = 'center'; ctx.fillText('Сжатая пружина — сейчас разожмётся!', W/2, 16); ctx.textAlign = 'left';
      pt18++;
      if (pt18 > 55) { phase18 = 1; pt18 = 0; }
    } else {
      // Flying
      var a1 = 40 / m18a, a2 = 40 / m18b;
      if (phase18 === 1 && pt18 < 18) {
        v1 -= a1 * 0.06; v2 += a2 * 0.06;
        pt18++;
        if (pt18 >= 18) phase18 = 2;
      }
      x1 += v1; x2 += v2;
      ctx.fillStyle = '#6366f1'; ctx.fillRect(x1 - 34, y, 34, bH);
      ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.acceleration:'#f97316'); ctx.fillRect(x2, y, 44, bH);
      ctx.fillStyle = '#fff'; ctx.font = 'bold 9px Inter'; ctx.textAlign = 'center';
      ctx.fillText(m18a + ' кг', x1 - 17, y + bH/2 + 4);
      ctx.fillText(m18b + ' кг', x2 + 22, y + bH/2 + 4); ctx.textAlign = 'left';
      ctx.font = 'bold 9px Inter';
      ctx.fillStyle = '#818cf8';
      ctx.fillText('← v₁=' + Math.abs(v1).toFixed(1), x1 - 60, y - 5);
      ctx.fillStyle = '#fb923c';
      ctx.fillText('v₂=' + v2.toFixed(1) + ' →', x2 + 50, y - 5);
      ctx.font = '9px Inter'; ctx.fillStyle = dk ? '#94a3b8' : '#64748b';
      ctx.textAlign = 'center';
      ctx.fillText('F₁₂ = F₂₁, но m₁ < m₂  →  |v₁| > |v₂|', W/2, H - 6);
      ctx.textAlign = 'left';
    }
    t18++;
    if (x1 > -70 && x2 < W + 50 && t18 < 380) anim18Id = requestAnimationFrame(fr18);
  }
  cx18 = W/2; x1 = cx18-18; x2 = cx18+18; v1 = 0; v2 = 0; phase18 = 0; pt18 = 0; t18 = 0; fr18();
}

// ══════════════════════════════════════════════
//  §19 — ПРУЖИНА (рисуется при движении слайдеров)
// ══════════════════════════════════════════════
function drawSpring19() {
  var cv = document.getElementById('cv19');
  if (!cv || cv.offsetWidth === 0) return;
  var dpr = window.devicePixelRatio || 1;
  var W = cv.offsetWidth, H = cv.offsetHeight || 160;
  if (cv.width !== Math.round(W * dpr) || cv.height !== Math.round(H * dpr)) {
    cv.width = Math.round(W * dpr); cv.height = Math.round(H * dpr);
  }
  var ctx = cv.getContext('2d');
  ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
  ctx.clearRect(0, 0, W, H);
  var dk = document.body.classList.contains('dark');
  ctx.fillStyle = dk ? '#1e293b' : '#f0f9ff'; ctx.fillRect(0, 0, W, H);
  var k = +document.getElementById('sl19k').value;
  var xcm = +document.getElementById('sl19x').value;
  var xm = xcm / 100;
  var F = k * xm;
  // Wall
  ctx.fillStyle = dk ? '#334155' : '#cbd5e1'; ctx.fillRect(4, 18, 14, H - 28);
  ctx.strokeStyle = dk ? '#475569' : '#94a3b8'; ctx.lineWidth = 1;
  for (var hy = 22; hy < H - 18; hy += 12) {
    ctx.beginPath(); ctx.moveTo(4, hy); ctx.lineTo(17, hy + 7); ctx.stroke();
  }
  // Spring coils
  var sx0 = 18, sx1 = 18 + 80 + xcm * 1.4;
  var sy = H / 2, coils = 8;
  var cW = (sx1 - sx0) / coils, cH = 17;
  var springCol = xcm > 30 ? '#ef4444' : xcm > 12 ? '#f59e0b' : '#10b981';
  ctx.beginPath(); ctx.moveTo(sx0, sy);
  for (var ci = 0; ci < coils; ci++) {
    var px = sx0 + ci * cW;
    ctx.lineTo(px + cW * 0.25, sy - cH);
    ctx.lineTo(px + cW * 0.75, sy + cH);
    ctx.lineTo(px + cW, sy);
  }
  ctx.strokeStyle = springCol; ctx.lineWidth = 2.5; ctx.stroke();
  // Block
  var bX = sx1, bW = 38, bH = 38;
  ctx.fillStyle = '#6366f1'; ctx.fillRect(bX, sy - bH/2, bW, bH);
  ctx.strokeStyle = '#4338ca'; ctx.lineWidth = 2; ctx.stroke();
  ctx.fillStyle = '#fff'; ctx.font = 'bold 9px Inter'; ctx.textAlign = 'center';
  ctx.fillText('груз', bX + bW/2, sy + 2);
  ctx.fillText(xcm + ' см', bX + bW/2, sy + 13); ctx.textAlign = 'left';
  // F arrow (back toward wall)
  var arLen = Math.min(65, F * 0.55);
  if (arLen > 4) {
    ctx.beginPath(); ctx.moveTo(bX, sy); ctx.lineTo(bX - arLen, sy);
    ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.lineWidth = 2.5; ctx.stroke();
    ctx.beginPath();
    ctx.moveTo(bX - arLen, sy); ctx.lineTo(bX - arLen + 11, sy - 5); ctx.lineTo(bX - arLen + 11, sy + 5);
    ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.fill();
    ctx.font = 'bold 9px Inter'; ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444');
    ctx.fillText('F = ' + F.toFixed(1) + ' Н', bX - arLen - 2, sy + 15);
  }
  ctx.font = '9px Inter'; ctx.fillStyle = dk ? '#94a3b8' : '#64748b';
  ctx.fillText('∆l = ' + xcm + ' см', sx0 + 2, sy - cH - 5);
  ctx.fillText('k = ' + k + ' Н/м', sx0 + 2, 14);
}

// ══════════════════════════════════════════════
//  §20 — ДИАГРАММА СИЛ ТРЕНИЯ
// ══════════════════════════════════════════════
function drawFriction20() {
  var cv = document.getElementById('cv20');
  if (!cv || cv.offsetWidth === 0) return;
  var dpr = window.devicePixelRatio || 1;
  var W = cv.offsetWidth, H = cv.offsetHeight || 150;
  if (cv.width !== Math.round(W * dpr) || cv.height !== Math.round(H * dpr)) {
    cv.width = Math.round(W * dpr); cv.height = Math.round(H * dpr);
  }
  var ctx = cv.getContext('2d');
  ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
  ctx.clearRect(0, 0, W, H);
  var dk = document.body.classList.contains('dark');
  ctx.fillStyle = dk ? '#1e293b' : '#f0f9ff'; ctx.fillRect(0, 0, W, H);
  var muInt = +document.getElementById('sl20mu').value;
  var m20 = +document.getElementById('sl20m').value;
  var mu = muInt / 100, N20 = m20 * 10, Ftr = mu * N20;
  // Ground
  ctx.fillStyle = dk ? '#334155' : '#e2e8f0'; ctx.fillRect(0, H * 0.73, W, H * 0.27);
  ctx.strokeStyle = dk ? '#64748b' : '#94a3b8'; ctx.lineWidth = 1.5;
  ctx.beginPath(); ctx.moveTo(0, H * 0.73); ctx.lineTo(W, H * 0.73); ctx.stroke();
  ctx.strokeStyle = dk ? '#475569' : '#b0b0b0'; ctx.lineWidth = 1;
  for (var tx = 18; tx < W; tx += 22) {
    ctx.beginPath(); ctx.moveTo(tx, H * 0.73); ctx.lineTo(tx - 9, H * 0.73 + 11); ctx.stroke();
  }
  var bW = 58, bH = 38, cx20 = W / 2;
  var bx20 = cx20 - bW/2, by20 = H * 0.73 - bH;
  ctx.fillStyle = '#6366f1'; ctx.fillRect(bx20, by20, bW, bH);
  ctx.strokeStyle = '#4338ca'; ctx.lineWidth = 2; ctx.stroke();
  ctx.fillStyle = '#fff'; ctx.font = 'bold 9px Inter'; ctx.textAlign = 'center';
  ctx.fillText(m20 + ' кг', cx20, by20 + bH/2 + 4); ctx.textAlign = 'left';
  function arr(x1, y1, x2, y2, col, lbl, side) {
    var dx = x2-x1, dy = y2-y1, len = Math.sqrt(dx*dx+dy*dy);
    if (len < 4) return;
    var ux = dx/len, uy = dy/len;
    ctx.beginPath(); ctx.moveTo(x1,y1); ctx.lineTo(x2,y2);
    ctx.strokeStyle = col; ctx.lineWidth = 2.5; ctx.stroke();
    var hw = 5;
    ctx.beginPath(); ctx.moveTo(x2,y2);
    ctx.lineTo(x2-ux*11-uy*hw, y2-uy*11+ux*hw);
    ctx.lineTo(x2-ux*11+uy*hw, y2-uy*11-ux*hw);
    ctx.fillStyle = col; ctx.fill();
    ctx.font = 'bold 9px Inter'; ctx.fillStyle = col;
    if (side==='r') ctx.fillText(lbl, x2+4, y2+4);
    else if (side==='l') { ctx.textAlign='right'; ctx.fillText(lbl, x2-4, y2+4); ctx.textAlign='left'; }
    else if (side==='t') { ctx.textAlign='center'; ctx.fillText(lbl,(x1+x2)/2,Math.min(y1,y2)-4); ctx.textAlign='left'; }
    else if (side==='b') { ctx.textAlign='center'; ctx.fillText(lbl,(x1+x2)/2,Math.max(y1,y2)+12); ctx.textAlign='left'; }
  }
  var midX20 = cx20, midY20 = by20 + bH/2;
  var sc = 0.45;
  var mgLen = Math.min(52, N20 * sc);
  arr(midX20, by20+bH, midX20, by20+bH+mgLen, '#ef4444', 'mg='+N20+'Н', 'r');
  arr(midX20, by20, midX20, by20-mgLen, '#10b981', 'N='+N20+'Н', 'r');
  var fLen = Math.max(8, Math.min(60, Ftr * sc));
  arr(cx20+bW/2, midY20, cx20+bW/2+fLen, midY20, '#3b82f6', 'F тяги', 'r');
  if (Ftr > 0) arr(cx20-bW/2, midY20, cx20-bW/2-fLen, midY20, '#f59e0b', 'Fтр='+Ftr.toFixed(0)+'Н', 'l');
  ctx.font = 'bold 10px Inter'; ctx.fillStyle = dk ? '#e2e8f0' : '#1e293b';
  ctx.fillText('μ = ' + mu.toFixed(2), 7, 14);
}

// ══════════════════════════════════════════════
//  §21 — АНИМАЦИЯ ГОРИЗОНТАЛЬНОГО БРОСКА
// ══════════════════════════════════════════════
var anim21Id = null;
function startAnim21() {
  var cv = document.getElementById('cv21');
  if (!cv || cv.offsetWidth === 0) return;
  if (anim21Id) { cancelAnimationFrame(anim21Id); anim21Id = null; }
  var dpr = window.devicePixelRatio || 1;
  var W = cv.offsetWidth, H = cv.offsetHeight || 220;
  cv.width = Math.round(W * dpr); cv.height = Math.round(H * dpr);
  var ctx = cv.getContext('2d');
  ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
  var h21 = +document.getElementById('sl21h').value;
  var g21 = 10, v0_21 = 18;
  var tTotal = Math.sqrt(2 * h21 / g21);
  var frames21 = 110, t21 = 0;
  var margin21 = 22;
  var groundY21 = H - margin21;
  var scaleY21 = (groundY21 - margin21) / h21;
  var startX21 = 28;
  var scaleX21 = (W - startX21 - 22) / (v0_21 * tTotal);
  var trail21 = [], landed21 = false;
  function fr21() {
    ctx.clearRect(0, 0, W, H);
    var dk = document.body.classList.contains('dark');
    ctx.fillStyle = dk ? '#1e293b' : '#e0f2fe'; ctx.fillRect(0, 0, W, groundY21);
    // Ground
    ctx.fillStyle = dk ? '#14532d' : '#bbf7d0'; ctx.fillRect(0, groundY21, W, H - groundY21);
    ctx.strokeStyle = dk ? '#166534' : '#16a34a'; ctx.lineWidth = 2;
    ctx.beginPath(); ctx.moveTo(0, groundY21); ctx.lineTo(W, groundY21); ctx.stroke();
    // Height dashed line
    ctx.setLineDash([4, 4]); ctx.strokeStyle = dk ? '#475569' : '#94a3b8'; ctx.lineWidth = 1;
    ctx.beginPath(); ctx.moveTo(startX21 - 4, margin21); ctx.lineTo(startX21 - 4, groundY21); ctx.stroke();
    ctx.setLineDash([]);
    ctx.font = '9px Inter'; ctx.fillStyle = dk ? '#94a3b8' : '#64748b'; ctx.textAlign = 'center';
    ctx.fillText('h=' + h21 + 'м', startX21 - 14, (margin21 + groundY21) / 2); ctx.textAlign = 'left';
    var frac21 = t21 / frames21;
    var simT21 = frac21 * tTotal;
    var fallY_m = 0.5 * g21 * simT21 * simT21;
    var fallY_px = margin21 + fallY_m * scaleY21;
    if (fallY_px > groundY21) fallY_px = groundY21;
    var thrX_px = startX21 + v0_21 * simT21 * scaleX21;
    var thrY_px = margin21 + fallY_m * scaleY21;
    if (thrY_px > groundY21) thrY_px = groundY21;
    if (thrX_px > W - 12) thrX_px = W - 12;
    if (t21 % 2 === 0 && thrY_px < groundY21) trail21.push({ x: thrX_px, y: thrY_px });
    // Parabola trail
    if (trail21.length > 1) {
      ctx.beginPath(); ctx.moveTo(trail21[0].x, trail21[0].y);
      for (var ti = 1; ti < trail21.length; ti++) ctx.lineTo(trail21[ti].x, trail21[ti].y);
      ctx.strokeStyle = 'rgba(56,189,248,0.55)'; ctx.lineWidth = 2; ctx.setLineDash([3,2]); ctx.stroke(); ctx.setLineDash([]);
    }
    // Drop ball (orange)
    ctx.beginPath(); ctx.arc(startX21, fallY_px, 11, 0, Math.PI * 2);
    ctx.fillStyle = '#fb923c'; ctx.fill(); ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.acceleration:'#ea580c'); ctx.lineWidth = 2; ctx.stroke();
    // Thrown ball (blue)
    ctx.beginPath(); ctx.arc(thrX_px, thrY_px, 11, 0, Math.PI * 2);
    ctx.fillStyle = '#38bdf8'; ctx.fill(); ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.velocity:'#0284c7'); ctx.lineWidth = 2; ctx.stroke();
    // Labels (first frame only)
    if (t21 < 4) {
      ctx.font = 'bold 9px Inter'; ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.acceleration:'#ea580c');
      ctx.fillText(' падение', startX21 + 14, fallY_px);
      ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.velocity:'#0284c7');
      ctx.fillText(' бросок →', thrX_px + 14, thrY_px - 4);
    }
    // Velocity components on thrown ball
    if (thrY_px < groundY21 - 8 && t21 > 3) {
      var vxL = Math.min(22, v0_21 * scaleX21 * 0.3);
      var vyL = Math.min(22, g21 * simT21 * scaleY21 * 0.3);
      ctx.beginPath(); ctx.moveTo(thrX_px+12, thrY_px); ctx.lineTo(thrX_px+12+vxL, thrY_px);
      ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.velocity:'#0284c7'); ctx.lineWidth = 1.5; ctx.stroke();
      ctx.beginPath(); ctx.moveTo(thrX_px, thrY_px+12); ctx.lineTo(thrX_px, thrY_px+12+vyL);
      ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.forceFriction:'#7c3aed'); ctx.lineWidth = 1.5; ctx.stroke();
    }
    if (frac21 >= 1.0) landed21 = true;
    if (landed21) {
      ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981'); ctx.font = 'bold 13px Inter'; ctx.textAlign = 'center';
      ctx.fillText(' Упали ОДНОВРЕМЕННО!   t = ' + tTotal.toFixed(1) + ' с', W/2, groundY21 - 16);
      ctx.font = '10px Inter'; ctx.fillStyle = dk ? '#94a3b8' : '#475569';
      ctx.fillText('Горизонтальная скорость не влияет на время падения!', W/2, groundY21 - 3);
      ctx.textAlign = 'left';
    } else {
      ctx.font = '9px Inter'; ctx.fillStyle = dk ? '#94a3b8' : '#475569';
      ctx.fillText('t = ' + simT21.toFixed(2) + ' с', W - 68, 13);
    }
    t21++;
    if (t21 <= frames21 + 50) anim21Id = requestAnimationFrame(fr21);
  }
  trail21 = []; landed21 = false; t21 = 0; fr21();
}

// ══════════════════════════════════════════════
//  §28 — ВИДЫ РАВНОВЕСИЯ: ИНТЕРАКТИВ
// ══════════════════════════════════════════════
function upd28() {
  var typeIdx = +document.getElementById('sl28type').value;
  var ang     = +document.getElementById('sl28angle').value;
  var types = ['Устойчивое', 'Неустойчивое', 'Безразличное'];
  document.getElementById('v28type').textContent  = types[typeIdx];
  document.getElementById('v28angle').textContent = ang + '°';
  var msg = typeIdx === 0 ? 'Устойчивое: тело вернётся в исходное положение!'
          : typeIdx === 1 ? (Math.abs(ang) > 5 ? ' Неустойчивое: тело УПАДЁТ!' : 'Неустойчивое: малейшее отклонение — и тело упадёт')
          : 'Безразличное: тело останется в новом положении';
  var el = document.getElementById('res28');
  if (el) el.textContent = msg;
  drawEquilibrium28(typeIdx, ang);
}
function drawEquilibrium28(typeIdx, ang) {
  var cv = document.getElementById('cv28');
  if (!cv || cv.offsetWidth === 0) return;
  var dpr = window.devicePixelRatio || 1;
  var W = cv.offsetWidth, H = cv.offsetHeight || 220;
  cv.width = Math.round(W * dpr); cv.height = Math.round(H * dpr);
  var ctx = cv.getContext('2d');
  ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
  var dark = document.body.classList.contains('dark');
  ctx.clearRect(0, 0, W, H);
  var rad = ang * Math.PI / 180;
  // Ground
  ctx.strokeStyle = dark ? '#334155' : '#cbd5e1'; ctx.lineWidth = 1.5;
  ctx.beginPath(); ctx.moveTo(20, H - 30); ctx.lineTo(W - 20, H - 30); ctx.stroke();
  // Draw depending on type
  if (typeIdx === 0) {
    // Stable: pendulum from top pivot, CG below
    var px = W / 2, pivY = 60, rodLen = 100;
    var bx = px + rodLen * Math.sin(rad), by = pivY + rodLen * Math.cos(rad);
    ctx.strokeStyle = dark ? '#475569' : '#94a3b8'; ctx.lineWidth = 2;
    ctx.beginPath(); ctx.moveTo(px, pivY); ctx.lineTo(bx, by); ctx.stroke();
    ctx.beginPath(); ctx.arc(px, pivY, 6, 0, Math.PI * 2);
    ctx.fillStyle = dark ? '#64748b' : '#94a3b8'; ctx.fill();
    ctx.beginPath(); ctx.arc(bx, by, 18, 0, Math.PI * 2);
    ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.forceGravity:'#1d4ed8'); ctx.fill();
    ctx.fillStyle = '#fff'; ctx.font = 'bold 10px Inter'; ctx.textAlign = 'center';
    ctx.fillText('ЦТ', bx, by + 4);
    // Restore arrow
    if (Math.abs(ang) > 5) {
      ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981'); ctx.lineWidth = 2;
      ctx.beginPath(); ctx.arc(px, pivY, rodLen + 15, Math.PI/2, Math.PI/2 - rad * 0.5, rad > 0);
      ctx.stroke();
    }
    ctx.fillStyle = dark ? '#94a3b8' : '#64748b'; ctx.font = '12px Inter'; ctx.textAlign = 'center';
    ctx.fillText('Устойчивое: ЦТ ниже опоры', W / 2, H - 5);
  } else if (typeIdx === 1) {
    // Unstable: inverted pendulum, CG above
    var px2 = W / 2, pivY2 = H - 80, rodLen2 = 100;
    var bx2 = px2 + rodLen2 * Math.sin(rad), by2 = pivY2 - rodLen2 * Math.cos(rad);
    ctx.strokeStyle = dark ? '#475569' : '#94a3b8'; ctx.lineWidth = 2;
    ctx.beginPath(); ctx.moveTo(px2, pivY2); ctx.lineTo(bx2, by2); ctx.stroke();
    ctx.beginPath(); ctx.arc(px2, pivY2, 6, 0, Math.PI * 2);
    ctx.fillStyle = dark ? '#64748b' : '#94a3b8'; ctx.fill();
    ctx.beginPath(); ctx.arc(bx2, by2, 18, 0, Math.PI * 2);
    var falling = Math.abs(ang) > 5;
    ctx.fillStyle = falling ? '#ef4444' : '#f97316'; ctx.fill();
    ctx.fillStyle = '#fff'; ctx.font = 'bold 10px Inter'; ctx.textAlign = 'center';
    ctx.fillText('ЦТ', bx2, by2 + 4);
    ctx.fillStyle = dark ? '#94a3b8' : '#64748b'; ctx.font = '12px Inter';
    ctx.fillText('Неустойчивое: ЦТ выше опоры', W / 2, H - 5);
  } else {
    // Neutral: ball on flat surface
    var ballX = W / 2 + ang * 3, ballY = H - 30 - 22;
    ctx.beginPath(); ctx.arc(ballX, ballY, 22, 0, Math.PI * 2);
    ctx.fillStyle = '#0ea5e9'; ctx.fill();
    ctx.fillStyle = '#fff'; ctx.font = 'bold 10px Inter'; ctx.textAlign = 'center';
    ctx.fillText('ЦТ', ballX, ballY + 4);
    ctx.fillStyle = dark ? '#94a3b8' : '#64748b'; ctx.font = '12px Inter';
    ctx.fillText('Безразличное: ЦТ = ось вращения', W / 2, H - 5);
  }
  ctx.textAlign = 'left';
}

// ══════════════════════════════════════════════
//  §29 — АРХИМЕДОВА СИЛА: ИНТЕРАКТИВ
// ══════════════════════════════════════════════
function upd29() {
  var rhoT = +document.getElementById('sl29rho').value;
  var Vdm  = +document.getElementById('sl29v').value;
  document.getElementById('v29rho').textContent = rhoT + ' кг/м³';
  document.getElementById('v29v').textContent   = Vdm + ' дм³';
  var rhoW = 1000, g = 10;
  var V = Vdm * 1e-3; // m^3
  var Fout = rhoT * g * V;
  var Farch = rhoW * g * V;
  var el = document.getElementById('res29');
  if (el) {
    var status = rhoT < rhoW ? '⬆ ПЛАВАЕТ' : (rhoT > rhoW ? '⬇ ТОНЕТ' : '⇔ нейтральная плавучесть');
    el.textContent = 'F_выт = ' + Farch.toFixed(1) + ' Н | F_т = ' + Fout.toFixed(1) + ' Н  —  ' + status;
  }
  drawArchimedes29(rhoT, V, Fout, Farch);
}
function drawArchimedes29(rhoT, V, Ft, Farch) {
  var cv = document.getElementById('cv29');
  if (!cv || cv.offsetWidth === 0) return;
  var dpr = window.devicePixelRatio || 1;
  var W = cv.offsetWidth, H = cv.offsetHeight || 200;
  cv.width = Math.round(W * dpr); cv.height = Math.round(H * dpr);
  var ctx = cv.getContext('2d');
  ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
  var dark = document.body.classList.contains('dark');
  ctx.clearRect(0, 0, W, H);
  var rhoW = 1000;
  // Water fill
  var waterY = H * 0.45;
  ctx.fillStyle = dark ? 'rgba(30,100,180,0.25)' : 'rgba(186,230,253,0.6)';
  ctx.fillRect(30, waterY, W - 60, H - waterY - 20);
  ctx.strokeStyle = dark ? '#0369a1' : '#0ea5e9'; ctx.lineWidth = 1.5;
  ctx.beginPath(); ctx.moveTo(30, waterY); ctx.lineTo(W - 30, waterY); ctx.stroke();
  ctx.fillStyle = dark ? '#38bdf8' : '#0284c7'; ctx.font = '11px Inter'; ctx.textAlign = 'left';
  ctx.fillText('вода  ρ = 1000 кг/м³', 36, waterY - 5);
  // Block
  var cx = W / 2;
  var blockSize = 40;
  var subFrac = Math.min(1, rhoT / rhoW);
  var subH = blockSize * subFrac;
  var aboveH = blockSize - subH;
  var blockTopY = waterY - aboveH;
  var blockY = blockTopY;
  ctx.fillStyle = rhoT < rhoW ? '#1d4ed8' : (rhoT > rhoW ? '#ef4444' : '#10b981');
  ctx.fillRect(cx - blockSize / 2, blockY, blockSize, blockSize);
  ctx.strokeStyle = '#fff'; ctx.lineWidth = 1;
  ctx.strokeRect(cx - blockSize / 2, blockY, blockSize, blockSize);
  ctx.fillStyle = '#fff'; ctx.font = 'bold 10px Inter'; ctx.textAlign = 'center';
  ctx.fillText(rhoT, cx, blockY + blockSize / 2 + 4);
  // Archimedes arrow (up, green)
  var sc = Math.max(10, Math.min(60, Farch / 10));
  ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981'); ctx.lineWidth = 2.5;
  ctx.beginPath(); ctx.moveTo(cx + 35, blockY + blockSize); ctx.lineTo(cx + 35, blockY + blockSize - sc); ctx.stroke();
  ctx.beginPath(); ctx.moveTo(cx + 32, blockY + blockSize - sc + 6); ctx.lineTo(cx + 35, blockY + blockSize - sc - 4); ctx.lineTo(cx + 38, blockY + blockSize - sc + 6);
  ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981'); ctx.fill();
  ctx.font = '10px Inter'; ctx.textAlign = 'left';
  ctx.fillText('F_выт=' + Farch.toFixed(0) + 'Н', cx + 40, blockY + blockSize - sc / 2 + 4);
  // Weight arrow (down, red)
  var scFt = Math.max(10, Math.min(60, Ft / 10));
  ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.lineWidth = 2.5;
  ctx.beginPath(); ctx.moveTo(cx - 35, blockY); ctx.lineTo(cx - 35, blockY + scFt); ctx.stroke();
  ctx.beginPath(); ctx.moveTo(cx - 38, blockY + scFt - 6); ctx.lineTo(cx - 35, blockY + scFt + 4); ctx.lineTo(cx - 32, blockY + scFt - 6);
  ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.fill();
  ctx.font = '10px Inter'; ctx.textAlign = 'right';
  ctx.fillText('F_т=' + Ft.toFixed(0) + 'Н', cx - 40, blockY + scFt / 2 + 4);
  ctx.textAlign = 'left';
}

// ══════════════════════════════════════════════
//  §30 — КОРАБЛЬ С ГРУЗОМ: ИНТЕРАКТИВ
// ══════════════════════════════════════════════
function upd30() {
  var ms = +document.getElementById('sl30ms').value; // tons
  var mg = +document.getElementById('sl30mg').value; // tons
  var Vc = +document.getElementById('sl30v').value;  // m^3
  document.getElementById('v30ms').textContent = ms + ' т';
  document.getElementById('v30mg').textContent = mg + ' т';
  document.getElementById('v30v').textContent  = Vc + ' м³';
  var rhoW = 1000, g = 10;
  var totalMass = (ms + mg) * 1000; // kg
  var rhoAvg = totalMass / Vc;
  var Vpogr = totalMass / rhoW; // m^3 submerged (for floating)
  var el = document.getElementById('res30');
  if (el) {
    var status = rhoAvg < rhoW ? (' Плавает | осадка ≈ ' + (Vpogr / Vc * 100).toFixed(0) + '% корпуса') : ' ТОНЕТ! Перегружен!';
    el.textContent = 'ρ_ср = ' + rhoAvg.toFixed(0) + ' кг/м³ — ' + status;
  }
  drawShip30(ms, mg, Vc, rhoAvg);
}
function drawShip30(ms, mg, Vc, rhoAvg) {
  var cv = document.getElementById('cv30');
  if (!cv || cv.offsetWidth === 0) return;
  var dpr = window.devicePixelRatio || 1;
  var W = cv.offsetWidth, H = cv.offsetHeight || 200;
  cv.width = Math.round(W * dpr); cv.height = Math.round(H * dpr);
  var ctx = cv.getContext('2d');
  ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
  var dark = document.body.classList.contains('dark');
  ctx.clearRect(0, 0, W, H);
  var rhoW = 1000;
  var sinking = rhoAvg >= rhoW;
  // Water
  var waterY = H * 0.5;
  ctx.fillStyle = dark ? 'rgba(30,100,180,0.3)' : 'rgba(186,230,253,0.7)';
  ctx.fillRect(0, waterY, W, H - waterY);
  ctx.strokeStyle = dark ? '#0369a1' : '#0ea5e9'; ctx.lineWidth = 1.5;
  ctx.beginPath(); ctx.moveTo(0, waterY); ctx.lineTo(W, waterY); ctx.stroke();
  // Ship hull
  var subFrac = sinking ? 1.0 : Math.min(0.95, rhoAvg / rhoW);
  var shipH = 60, shipW = 160;
  var cx = W / 2;
  var shipTop = waterY - shipH * (1 - subFrac);
  ctx.beginPath();
  ctx.moveTo(cx - shipW / 2, shipTop);
  ctx.lineTo(cx + shipW / 2, shipTop);
  ctx.lineTo(cx + shipW / 2 - 10, shipTop + shipH);
  ctx.lineTo(cx - shipW / 2 + 10, shipTop + shipH);
  ctx.closePath();
  ctx.fillStyle = sinking ? '#ef4444' : (dark ? '#334155' : '#94a3b8'); ctx.fill();
  ctx.strokeStyle = sinking ? '#b91c1c' : (dark ? '#475569' : '#64748b'); ctx.lineWidth = 2; ctx.stroke();
  // Cabin/superstructure (only if not sinking)
  if (!sinking) {
    ctx.fillStyle = dark ? '#1e293b' : '#e2e8f0';
    ctx.fillRect(cx - 30, shipTop - 28, 60, 28);
    ctx.strokeStyle = dark ? '#475569' : '#94a3b8'; ctx.lineWidth = 1.5;
    ctx.strokeRect(cx - 30, shipTop - 28, 60, 28);
  }
  // Waterline label
  ctx.fillStyle = dark ? '#38bdf8' : '#0284c7'; ctx.font = '11px Inter'; ctx.textAlign = 'right';
  ctx.fillText('ватерлиния', W - 35, waterY - 4);
  // Status
  ctx.fillStyle = sinking ? '#ef4444' : '#065f46'; ctx.font = 'bold 13px Inter'; ctx.textAlign = 'center';
  ctx.fillText(sinking ? ' ТОНЕТ! ρ_ср = ' + rhoAvg.toFixed(0) + ' > 1000' : ' ρ_ср = ' + rhoAvg.toFixed(0) + ' кг/м³', cx, H - 5);
  // Waves
  ctx.strokeStyle = dark ? 'rgba(56,189,248,0.3)' : 'rgba(14,165,233,0.3)'; ctx.lineWidth = 1.5;
  for (var wx = 20; wx < W - 20; wx += 40) {
    ctx.beginPath(); ctx.arc(wx, waterY, 10, Math.PI, 0); ctx.stroke();
  }
  ctx.textAlign = 'left';
}

// §31 — p = mv
function upd31() {
  const m = +document.getElementById('sl31m').value;
  const v = +document.getElementById('sl31v').value;
  document.getElementById('v31m').textContent = m + ' кг';
  document.getElementById('v31v').textContent = v + ' м/с';
  const p = m * v;
  document.getElementById('res31').innerHTML =
    'p = ' + m + ' × ' + v + ' = <b style="font-size:1.1em;color:var(--pri)">' + p + '</b> кг·м/с';
  const w = Math.max(8, Math.min(374, (p / 600) * 374));
  document.getElementById('bar31').setAttribute('width', w);
  document.getElementById('barlbl31').textContent = p + ' кг·м/с';
}

// §33 — угол α и работа
function upd33() {
  const a = +document.getElementById('sl33a').value;
  document.getElementById('v33a').textContent = a + '°';
  document.getElementById('aval33').textContent = a;
  const rad = a * Math.PI / 180;
  const cosA = Math.cos(rad);
  document.getElementById('cosval33').textContent = cosA.toFixed(2);

  // F vector: origin = body centre (80, 75), length 40
  const ox = 80, oy = 75, len = 40;
  const fx2 = ox + len * Math.cos(rad);
  const fy2 = oy - len * Math.sin(rad);   // SVG y is inverted

  document.getElementById('fline33').setAttribute('x2', fx2.toFixed(1));
  document.getElementById('fline33').setAttribute('y2', fy2.toFixed(1));

  // arrowhead
  const dx = fx2 - ox, dy = fy2 - oy;
  const ll = Math.sqrt(dx * dx + dy * dy);
  const ux = dx / ll, uy = dy / ll;
  const bx = fx2 - ux * 12, by = fy2 - uy * 12;
  const nx = -uy * 5, ny = ux * 5;
  document.getElementById('farrow33').setAttribute('points',
    fx2.toFixed(1) + ',' + fy2.toFixed(1) + ' ' +
    (bx + nx).toFixed(1) + ',' + (by + ny).toFixed(1) + ' ' +
    (bx - nx).toFixed(1) + ',' + (by - ny).toFixed(1));

  document.getElementById('ftxt33').setAttribute('x', (fx2 + 4).toFixed(1));
  document.getElementById('ftxt33').setAttribute('y', (fy2 - 3).toFixed(1));

  // α label position
  const mid = rad / 2;
  document.getElementById('albl33').setAttribute('x', (ox + 22 * Math.cos(mid)).toFixed(1));
  document.getElementById('albl33').setAttribute('y', (oy - 22 * Math.sin(mid) + 4).toFixed(1));

  // color
  const color = cosA > 0.02 ? '#10b981' : cosA > -0.02 ? '#f59e0b' : '#ef4444';
  ['fline33', 'farrow33', 'ftxt33'].forEach(id => {
    const el = document.getElementById(id);
    if (el) { el.setAttribute('stroke', color); el.setAttribute('fill', color); }
  });
  document.getElementById('fline33').setAttribute('stroke', color);

  // work sign
  let sign = '', cls = '', desc = '';
  if (cosA > 0.02)       { sign = 'A &gt; 0 — положительная'; cls = 'work-pos'; desc = 'Сила «помогает» движению'; }
  else if (cosA > -0.02) { sign = 'A = 0 — равна нулю';       cls = 'work-zero'; desc = 'Сила ⊥ перемещению, работы нет'; }
  else                   { sign = 'A &lt; 0 — отрицательная'; cls = 'work-neg';  desc = 'Сила «тормозит» движение'; }
  document.getElementById('worksign33').innerHTML = '<span class="' + cls + '">' + sign + '</span>';
  document.getElementById('workdesc33').textContent = desc;
}

// §34 — нулевой уровень
// 1 м = 22px. Реальный пол = 0 м → y=196. Земля (улица) = -1 м → y=218.
// Шар А реальная высота 2 м → cy=140 (фиксировано). Шар Б 5 м → cy=74.
function upd34zero() {
  const z  = +document.getElementById('sl34zero').value;  // 0–6 м
  const m  = 2, g = 10;
  // реальные высоты шаров
  const hA_real = 2, hB_real = 5;
  // высоты относительно нулевого уровня
  const h1 = +(hA_real - z).toFixed(1);
  const h2 = +(hB_real - z).toFixed(1);
  const Ep1 = +(m * g * h1).toFixed(0);
  const Ep2 = +(m * g * h2).toFixed(0);
  const dEp = +(m * g * (hB_real - hA_real)).toFixed(0); // всегда 600

  document.getElementById('h1val').textContent  = h1;
  document.getElementById('h2val').textContent  = h2;
  document.getElementById('ep1val').textContent = Ep1;
  document.getElementById('ep2val').textContent = Ep2;
  document.getElementById('depval').textContent = dEp;
  document.getElementById('dep_note').textContent =
    '= ' + m + ' × ' + g + ' × ' + (hB_real - hA_real) + ' = не меняется!';

  // Метка слайдера
  const names = {0:'пол (0 м)',1:'1 м над полом',2:'2 м (нижняя полка)',
                  3:'3 м',4:'4 м',5:'5 м (верхняя полка)',6:'6 м (потолок)'};
  document.getElementById('v34zero').textContent = names[z] || z + ' м';

  // Позиция зелёной линии в SVG: y = 196 - z*22
  const zy = 196 - z * 22;
  document.getElementById('zline34').setAttribute('y1', zy);
  document.getElementById('zline34').setAttribute('y2', zy);
  document.getElementById('zlbl34').setAttribute('y', zy - 4);

  // Стрелки h₁: от zy до cy=140 (шар А)
  const cyA = 140;
  document.getElementById('za_line').setAttribute('y1', zy);
  document.getElementById('za_line').setAttribute('y2', cyA);
  // наконечники
  if (zy > cyA) {
    document.getElementById('za_arr1').setAttribute('points', `22,${cyA} 18,${cyA+11} 26,${cyA+11}`);
    document.getElementById('za_arr2').setAttribute('points', `22,${zy}  18,${zy-11}  26,${zy-11}`);
  } else {
    document.getElementById('za_arr1').setAttribute('points', `22,${cyA} 18,${cyA-11} 26,${cyA-11}`);
    document.getElementById('za_arr2').setAttribute('points', `22,${zy}  18,${zy+11}  26,${zy+11}`);
  }
  document.getElementById('za_lbl').setAttribute('y', ((zy + cyA) / 2 + 3).toFixed(0));
  document.getElementById('za_lbl').setAttribute('fill', h1 < 0 ? '#ef4444' : '#1d4ed8');
  document.getElementById('za_lbl').textContent = h1 >= 0 ? 'h₁' : 'h₁<0';

  // Стрелки h₂: от zy до cy=74 (шар Б)
  const cyB = 74;
  document.getElementById('zb_line').setAttribute('y1', zy);
  document.getElementById('zb_line').setAttribute('y2', cyB);
  if (zy > cyB) {
    document.getElementById('zb_arr1').setAttribute('points', `33,${cyB} 29,${cyB+11} 37,${cyB+11}`);
    document.getElementById('zb_arr2').setAttribute('points', `33,${zy}  29,${zy-11}  37,${zy-11}`);
  } else {
    document.getElementById('zb_arr1').setAttribute('points', `33,${cyB} 29,${cyB-11} 37,${cyB-11}`);
    document.getElementById('zb_arr2').setAttribute('points', `33,${zy}  29,${zy+11}  37,${zy+11}`);
  }
  document.getElementById('zb_lbl').setAttribute('y', ((zy + cyB) / 2 + 3).toFixed(0));
  document.getElementById('zb_lbl').setAttribute('fill', h2 < 0 ? '#ef4444' : '#7c3aed');
  document.getElementById('zb_lbl').textContent = h2 >= 0 ? 'h₂' : 'h₂<0';

  // Цвет Eп₁ и Eп₂ — красный если отрицательная
  document.getElementById('ep1val').style.color = Ep1 < 0 ? '#ef4444' : '#1d4ed8';
  document.getElementById('ep2val').style.color = Ep2 < 0 ? '#ef4444' : '#7c3aed';
}

// §34 — Eп = mgh
function upd34() {
  const m = +document.getElementById('sl34m').value;
  const h = +document.getElementById('sl34h').value;
  document.getElementById('v34m').textContent = m + ' кг';
  document.getElementById('v34h').textContent = h + ' м';
  const Ep = m * 10 * h;
  document.getElementById('res34').innerHTML =
    'Eп = ' + m + ' × 10 × ' + h + ' = <b style="font-size:1.1em;color:var(--pri)">' + Ep + '</b> Дж';
  const maxEp = 4000;
  const barH = Math.max(2, Math.min(96, (Ep / maxEp) * 96));
  const barY = 101 - barH;
  document.getElementById('liftbar34').setAttribute('height', barH);
  document.getElementById('liftbar34').setAttribute('y', barY);
  const ballY = Math.max(15, barY - 11);
  document.getElementById('liftball34').setAttribute('cy', ballY);
  const txt = document.getElementById('liftballtxt');
  if (txt) txt.setAttribute('y', ballY + 4);
}

// §35 — Eк = mv²/2
function upd35() {
  const m = +document.getElementById('sl35m').value;
  const v = +document.getElementById('sl35v').value;
  document.getElementById('v35m').textContent = m + ' кг';
  document.getElementById('v35v').textContent = v + ' м/с';
  const Ek = m * v * v / 2;
  document.getElementById('res35').innerHTML =
    'Eк = ' + m + ' × ' + v + '² / 2 = <b style="font-size:1.1em;color:var(--pri)">' + Ek + '</b> Дж';
  const maxEk = 4500;
  const w = Math.max(2, Math.min(100, (Ek / maxEk) * 100));
  document.getElementById('bar35').style.width = w + '%';
}

// §36 — маятник анимация
let pend36Timer = null;
let pend36Angle = Math.PI / 4;   // начальный угол (рад)
let pend36Phase = 0;
const PEND36_AMP = Math.PI / 4;  // 45°
const PEND36_L = 151;             // длина нити (px, от y=14 до cy=165)

function pend36Frame() {
  pend36Phase += 0.04;
  const angle = PEND36_AMP * Math.cos(pend36Phase);
  const cx = 100 + PEND36_L * Math.sin(angle);
  const cy = 14 + PEND36_L * Math.cos(angle);

  const rope = document.getElementById('pend-rope');
  const ball = document.getElementById('pend-ball');
  const ekBar = document.getElementById('bar-ek36');
  const epBar = document.getElementById('bar-ep36');
  const pendEk = document.getElementById('pend-ek');
  const pendEp = document.getElementById('pend-ep');
  if (!rope || !ball) return;

  rope.setAttribute('x2', cx.toFixed(1));
  rope.setAttribute('y2', cy.toFixed(1));
  ball.setAttribute('cx', cx.toFixed(1));
  ball.setAttribute('cy', cy.toFixed(1));

  // высота над нижней точкой (cy_bottom = 14 + PEND36_L = 165)
  const h = 165 - cy;
  // h_max = 165 - (14 + PEND36_L*(1-cos(AMP))) ≈ PEND36_L*(1-cos(AMP))
  const h_max = PEND36_L * (1 - Math.cos(PEND36_AMP));
  const epFrac = Math.max(0, Math.min(1, h / h_max));
  const ekFrac = 1 - epFrac;

  ekBar.style.width = (ekFrac * 100).toFixed(1) + '%';
  epBar.style.width = (epFrac * 100).toFixed(1) + '%';
  pendEk.textContent = 'Eк = ' + (ekFrac * 100).toFixed(0) + '%';
  pendEp.textContent = 'Eп = ' + (epFrac * 100).toFixed(0) + '%';

  // Velocity arrow at ball
  const vline = document.getElementById('pend-vline');
  const varr  = document.getElementById('pend-varr');
  if (vline && varr) {
    const v = ekFrac;
    const ex = cx - Math.sin(angle) * 30 * v;
    const ey = cy + Math.cos(angle) * 30 * v;
    const sign = Math.sin(pend36Phase) > 0 ? 1 : -1;
    const vex = cx + (-Math.cos(angle)) * 25 * v * sign;
    const vey = cy + (-Math.sin(angle)) * 25 * v * sign;
    vline.setAttribute('x1', cx.toFixed(1)); vline.setAttribute('y1', cy.toFixed(1));
    vline.setAttribute('x2', vex.toFixed(1)); vline.setAttribute('y2', vey.toFixed(1));
    vline.setAttribute('stroke', ekFrac > 0.05 ? '#6d28d9' : 'transparent');
    varr.setAttribute('fill', ekFrac > 0.05 ? '#6d28d9' : 'transparent');
    // arrowhead
    const dx = vex - cx, dy = vey - cy;
    const ll = Math.sqrt(dx*dx+dy*dy) || 1;
    const ux = dx/ll, uy = dy/ll;
    const bx = vex - ux*9, by = vey - uy*9;
    const nx = -uy*4, ny = ux*4;
    varr.setAttribute('points',
      vex.toFixed(1)+','+vey.toFixed(1)+' '+(bx+nx).toFixed(1)+','+(by+ny).toFixed(1)+' '+(bx-nx).toFixed(1)+','+(by-ny).toFixed(1));
  }
  // h-line
  const hline = document.getElementById('pend-hline');
  const hlbl  = document.getElementById('pend-hlbl');
  if (hline && h > 2) {
    hline.setAttribute('x1', (cx+5).toFixed(1)); hline.setAttribute('y1', cy.toFixed(1));
    hline.setAttribute('x2', (cx+5).toFixed(1)); hline.setAttribute('y2', '165');
    hlbl.setAttribute('x', (cx+9).toFixed(1));
    hlbl.setAttribute('y', ((cy+165)/2+4).toFixed(1));
    hlbl.textContent = 'h';
  } else if (hline) {
    hline.setAttribute('x1','0'); hline.setAttribute('y1','0');
    hline.setAttribute('x2','0'); hline.setAttribute('y2','0');
    if (hlbl) hlbl.textContent = '';
  }
}

function togglePend36() {
  const btn = document.getElementById('pendBtn36');
  if (pend36Timer) {
    clearInterval(pend36Timer);
    pend36Timer = null;
    if (btn) btn.innerHTML = '<svg class="ic" viewBox="0 0 24 24" style="width:14px;height:14px;display:inline-block;vertical-align:-2px;stroke:currentColor;fill:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round"><polygon points="6 4 20 12 6 20 6 4"/></svg> Запустить';
  } else {
    pend36Timer = setInterval(pend36Frame, 30);
    if (btn) btn.innerHTML = '<svg class="ic" viewBox="0 0 24 24" style="width:14px;height:14px;display:inline-block;vertical-align:-2px;stroke:currentColor;fill:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round"><rect x="6" y="4" width="4" height="16"/><rect x="14" y="4" width="4" height="16"/></svg> Стоп';
  }
}

function nextTask(sec) {
  const pool = POOLS[sec];
  const s = STATE[sec];
  let next = -1;
  for (let i = s.idx + 1; i < pool.length; i++) {
    if (s.results[i] === null) { next = i; break; }
  }
  if (next === -1) {
    for (let i = 0; i < s.idx; i++) {
      if (s.results[i] === null) { next = i; break; }
    }
  }
  if (next === -1) { showSummary(sec); return; }
  s.idx = next;
  s.answered = false;
  renderTask(sec);
}

function resetTasks(sec) {
  STATE[sec] = mkState(POOLS[sec]);
  document.getElementById('sum' + sec).classList.remove('show');
  renderTask(sec);
}

function updateScoreBar(sec) {
  const pool = POOLS[sec];
  const s = STATE[sec];
  const okCnt   = s.results.filter(r => r === true).length;
  const doneCnt = s.results.filter(r => r !== null).length;
  document.getElementById('ok' + sec).textContent  = okCnt;
  document.getElementById('cur' + sec).textContent = doneCnt;
  document.getElementById('max' + sec).textContent = pool.length;
  document.getElementById('prog' + sec).style.width = (doneCnt / pool.length * 100) + '%';
}

function showSummary(sec) {
  const pool = POOLS[sec];
  const s = STATE[sec];
  document.getElementById('prog' + sec).style.width = '100%';
  document.getElementById('sum' + sec).classList.add('show');
  const okCnt = s.results.filter(r => r === true).length;
  document.getElementById('sumScore' + sec).textContent = `${okCnt} / ${pool.length}`;
  const p = okCnt / pool.length;
  document.getElementById('sumGrade' + sec).textContent =
    p >= .9  ? ' Отлично — тема освоена!' :
    p >= .75 ? '⭐ Хорошо! Разбери пропущенные задачи.' :
    p >= .5  ? ' Неплохо. Повтори формулы и попробуй ещё раз.' :
               ' Прочитай теорию и реши снова.';
}


// ══════════════════════════════════════════════
//  ЛАБ. РАБОТА №11 — Проверка ЗСИ
// ══════════════════════════════════════════════
const L11 = { rows: [], g: 9.81, H: 0.15 };

function l11ph() {
  const m1 = +document.getElementById('l11m1').value / 1000;
  const m2 = +document.getElementById('l11m2').value / 1000;
  const h  = +document.getElementById('l11h').value  / 100;
  const v0 = Math.sqrt(2 * L11.g * h);
  const tF = Math.sqrt(2 * L11.H / L11.g);
  const v1p = (m1 - m2) / (m1 + m2) * v0;
  const v2p = 2 * m1 / (m1 + m2) * v0;
  return { m1, m2, h, v0, v1p, v2p, tF,
    l1: v0 * tF, l1p: v1p * tF, l2p: v2p * tF };
}

function updLab11() {
  const p = l11ph();
  document.getElementById('l11m1v').textContent = (+document.getElementById('l11m1').value);
  document.getElementById('l11m2v').textContent = (+document.getElementById('l11m2').value);
  document.getElementById('l11hv').textContent  = (+document.getElementById('l11h').value);
  document.getElementById('l11r1').textContent  = p.l1.toFixed(3);
  document.getElementById('l11r1p').textContent = Math.abs(p.l1p).toFixed(3);
  document.getElementById('l11r2p').textContent = p.l2p.toFixed(3);
  drawLab11();
}

function drawLab11() {
  const cv = document.getElementById('cvLab11');
  if (!cv) return;

  // ── HiDPI: resize canvas to physical pixels ──────────────────
  const dpr   = window.devicePixelRatio || 1;
  const cssW  = cv.clientWidth || 540;
  const cssH  = 195;   // logical CSS height (canvas keeps aspect via style)
  if (cv.width  !== Math.round(cssW * dpr) ||
      cv.height !== Math.round(cssH * dpr)) {
    cv.width  = Math.round(cssW * dpr);
    cv.height = Math.round(cssH * dpr);
    cv.style.height = cssH + 'px';
  }

  const ctx  = cv.getContext('2d');
  ctx.setTransform(dpr, 0, 0, dpr, 0, 0);   // draw in CSS-pixel space

  const W  = cssW, Hc = cssH;
  const dark = document.body.classList.contains('dark');
  const p    = l11ph();

  // ── Layout (CSS px) ───────────────────────────────────────────
  const FVH  = 52;             // floor-to-table vertical px  (= H = 0.15m)
  const FY   = Hc - 20;       // floor baseline  (room below for labels)
  const TY   = FY - FVH;      // table surface
  const EX_F = 0.27;          // table-edge x as fraction of W
  const EX   = Math.round(W * EX_F);
  const SV   = FVH / L11.H;  // px / m  (vertical)
  const BR   = 8;

  // ── Auto-scale SH so all marks stay within canvas ─────────────
  const rDist = Math.max(p.l1, Math.max(0, p.l1p), p.l2p, 0.05);
  const lDist = Math.max(0, -p.l1p);
  const rightAvail = W - EX - 14;
  const leftAvail  = EX - 46;   // 46 px reserved for h-label on left
  const SH = Math.min(
    rightAvail / rDist,
    lDist > 0.001 ? leftAvail / lDist : Infinity
  ) * 0.96;

  // ── Colours ───────────────────────────────────────────────────
  const cFloor = dark ? '#334155' : '#e2e8f0';
  const cTab   = dark ? '#1e3a5f' : '#dbeafe';
  const cStr   = dark ? '#475569' : '#94a3b8';
  const cTxt   = dark ? '#94a3b8' : '#475569';
  const cRamp  = dark ? '#93c5fd' : '#3b82f6';
  const cL1    = '#818cf8';   // reference (indigo, faint)
  const cL1p   = '#3b82f6';   // ball 1 after (blue)
  const cL2p   = '#f97316';   // ball 2 after (orange)

  ctx.clearRect(0, 0, W, Hc);

  // ── Floor fill ────────────────────────────────────────────────
  ctx.fillStyle = cFloor;
  ctx.fillRect(EX - 3, FY, W - EX + 3, Hc - FY);
  ctx.fillStyle = dark ? '#64748b' : '#94a3b8';
  ctx.fillRect(EX - 3, FY, W - EX + 3, 1.5);

  // ── Table legs ────────────────────────────────────────────────
  ctx.fillStyle = cStr;
  ctx.fillRect(32, TY + 4, 6, FY - TY - 4);
  ctx.fillRect(EX - 15, TY + 4, 6, FY - TY - 4);

  // ── Table surface ─────────────────────────────────────────────
  ctx.fillStyle = cTab;
  ctx.fillRect(28, TY, EX - 28, 5);
  ctx.strokeStyle = dark ? '#93c5fd' : '#2563eb';
  ctx.lineWidth = 1.5; ctx.setLineDash([]);
  ctx.strokeRect(28, TY, EX - 28, 5);

  // ── H dimension (right of edge) ───────────────────────────────
  const hx = EX + 9;
  ctx.strokeStyle = cTxt; ctx.lineWidth = 1; ctx.setLineDash([2.5, 2.5]);
  ctx.beginPath(); ctx.moveTo(hx, TY); ctx.lineTo(hx, FY); ctx.stroke();
  ctx.setLineDash([]);
  const _arrowV = (x, y, dir) => {
    ctx.beginPath();
    ctx.moveTo(x-3, y+dir*5); ctx.lineTo(x, y); ctx.lineTo(x+3, y+dir*5);
    ctx.stroke();
  };
  _arrowV(hx, TY, 1); _arrowV(hx, FY, -1);
  ctx.fillStyle = cTxt; ctx.font = '9px Inter'; ctx.textAlign = 'left';
  ctx.fillText('H=15 см', hx + 4, (TY + FY) / 2 + 4);

  // ── Ramp ──────────────────────────────────────────────────────
  const hPx  = p.h * SV * 0.70;
  const RW   = Math.round(W * 0.20);   // ramp horizontal extent
  const RTX  = EX - RW;
  const RTY  = TY - hPx;

  ctx.beginPath();
  ctx.moveTo(RTX, RTY); ctx.lineTo(EX, TY);
  ctx.lineTo(EX, RTY + 6); ctx.lineTo(RTX, RTY + 6);
  ctx.closePath();
  ctx.fillStyle = cTab; ctx.fill();
  ctx.strokeStyle = dark ? '#93c5fd' : '#2563eb'; ctx.lineWidth = 2;
  ctx.beginPath(); ctx.moveTo(RTX, RTY); ctx.lineTo(EX, TY); ctx.stroke();

  // ── h dimension (left of ramp) ────────────────────────────────
  const hax = RTX - 12;
  ctx.strokeStyle = cTxt; ctx.lineWidth = 1; ctx.setLineDash([2.5, 2.5]);
  ctx.beginPath(); ctx.moveTo(hax, RTY); ctx.lineTo(hax, TY); ctx.stroke();
  ctx.setLineDash([]);
  _arrowV(hax, RTY, 1); _arrowV(hax, TY, -1);
  ctx.fillStyle = cTxt; ctx.font = '9px Inter'; ctx.textAlign = 'right';
  const hVal = +document.getElementById('l11h').value;
  ctx.fillText('h=' + hVal + 'см', hax - 3, (RTY + TY) / 2 + 4);

  // ── Ball 1 on ramp ────────────────────────────────────────────
  const ang  = Math.atan2(TY - RTY, EX - RTX);
  const bpx  = RTX + (EX - RTX) * 0.28;
  const bpy  = RTY + (TY - RTY) * 0.28;
  const b1x  = bpx - Math.sin(ang) * (BR + 1);
  const b1y  = bpy + Math.cos(ang) * (BR + 1);
  ctx.beginPath(); ctx.arc(b1x, b1y, BR, 0, Math.PI * 2);
  ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.displacement:'#2563eb'); ctx.fill();
  ctx.strokeStyle = '#93c5fd'; ctx.lineWidth = 1.5; ctx.stroke();
  ctx.fillStyle = '#fff'; ctx.font = 'bold 8px Inter'; ctx.textAlign = 'center';
  ctx.fillText('1', b1x, b1y + 3);

  // ── Ball 2 at edge ────────────────────────────────────────────
  const b2x = EX + BR + 2, b2y = TY - BR;
  ctx.beginPath(); ctx.arc(b2x, b2y, BR, 0, Math.PI * 2);
  ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.acceleration:'#ea580c'); ctx.fill();
  ctx.strokeStyle = '#fbbf24'; ctx.lineWidth = 1.5; ctx.stroke();
  ctx.fillStyle = '#fff'; ctx.font = 'bold 8px Inter'; ctx.textAlign = 'center';
  ctx.fillText('2', b2x, b2y + 3);

  // ── Clip canvas so trajectories don't bleed outside ───────────
  ctx.save();
  ctx.beginPath();
  ctx.rect(0, 0, W, Hc);
  ctx.clip();

  // ── Draw parabola + landing mark ──────────────────────────────
  function parab(vx, col, lbl, alpha) {
    if (!isFinite(vx) || isNaN(vx)) return;
    ctx.globalAlpha = alpha || 1;
    const landPx = EX + vx * p.tF * SH;   // unclamped x of landing
    const clampX = Math.max(6, Math.min(W - 6, landPx));

    // Parabolic curve
    ctx.strokeStyle = col; ctx.lineWidth = 1.8; ctx.setLineDash([5, 3.5]);
    ctx.beginPath();
    if (Math.abs(vx) < 0.001) {
      // Falls straight down from edge
      ctx.moveTo(EX, TY); ctx.lineTo(EX, FY);
    } else {
      const steps = 36;
      for (let i = 0; i <= steps; i++) {
        const t  = i / steps * p.tF;
        const cx = EX + vx * t * SH;
        const cy = TY + 0.5 * L11.g * t * t * SV;
        i === 0 ? ctx.moveTo(cx, cy) : ctx.lineTo(cx, cy);
      }
    }
    ctx.stroke(); ctx.setLineDash([]);

    // Landing tick mark
    ctx.strokeStyle = col; ctx.lineWidth = 2;
    ctx.beginPath(); ctx.moveTo(clampX, FY - 8); ctx.lineTo(clampX, FY + 1); ctx.stroke();
    // Triangle pointer
    ctx.beginPath();
    ctx.moveTo(clampX - 4, FY - 3);
    ctx.lineTo(clampX, FY + 4);
    ctx.lineTo(clampX + 4, FY - 3);
    ctx.fillStyle = col; ctx.fill();
    // Label (stays within canvas)
    ctx.globalAlpha = 1;
    ctx.fillStyle = col;
    ctx.font = 'bold 9.5px Inter'; ctx.textAlign = 'center';
    const lblX = Math.max(14, Math.min(W - 14, clampX));
    ctx.fillText(lbl, lblX, FY + 14);
    ctx.globalAlpha = 1;
  }

  parab(p.v0,  cL1,  'l₁',  0.40);
  parab(p.v1p, cL1p, "l₁'", 1);
  parab(p.v2p, cL2p, "l₂'", 1);

  ctx.restore();  // remove clip

  // ── Legend (top-right, outside clip so always visible) ────────
  const lgX = W - 102, lgY = 7;
  [[cL1,"l₁ (без м₂)",0.40],[cL1p,"l₁' (шар 1)",1],[cL2p,"l₂' (шар 2)",1]]
    .forEach(([col, lbl, a], i) => {
      const y = lgY + i * 15;
      ctx.globalAlpha = a;
      ctx.fillStyle = col;
      ctx.fillRect(lgX, y + 3, 16, 3);
      ctx.globalAlpha = 1;
      ctx.fillStyle = cTxt;
      ctx.font = '8.5px Inter'; ctx.textAlign = 'left';
      ctx.fillText(lbl, lgX + 20, y + 8);
    });
}
function l11noise() { return 1 + (Math.random()*0.04 - 0.02); }

function lab11add() {
  if (L11.rows.length >= 5) return;
  const p = l11ph();
  L11.rows.push({
    m1: p.m1, m2: p.m2,
    l1:  p.l1  * l11noise(),
    l1p: Math.abs(p.l1p) * l11noise(),
    l2p: p.l2p * l11noise()
  });
  l11tbl();
  if (L11.rows.length >= 5) {
    document.getElementById('lab11b1').disabled = true;
    l11verif();
  }
}

function lab11all()   { while (L11.rows.length < 5) lab11add(); }
function lab11reset() {
  L11.rows = [];
  document.getElementById('lab11b1').disabled = false;
  document.getElementById('lab11vrf').style.display = 'none';
  l11tbl();
}

function l11tbl() {
  const mn = k => L11.rows.length ? L11.rows.reduce((s,r)=>s+r[k],0)/L11.rows.length : 0;
  let h = '';
  for (let i=0; i<5; i++) {
    const r = L11.rows[i];
    h += r
      ? `<tr><td>${i+1}</td><td>${r.m1.toFixed(3)}</td><td>${r.m2.toFixed(3)}</td><td>${r.l1.toFixed(3)}</td><td>${r.l1p.toFixed(3)}</td><td>${r.l2p.toFixed(3)}</td></tr>`
      : `<tr><td>${i+1}</td><td>—</td><td>—</td><td>—</td><td>—</td><td>—</td></tr>`;
  }
  if (L11.rows.length)
    h += `<tr class="lab11-avg"><td>⟨⟩</td><td>${mn('m1').toFixed(3)}</td><td>${mn('m2').toFixed(3)}</td><td>${mn('l1').toFixed(3)}</td><td>${mn('l1p').toFixed(3)}</td><td>${mn('l2p').toFixed(3)}</td></tr>`;
  document.getElementById('lab11tb').innerHTML = h;
}


function l11verif() {
  document.getElementById('lab11vrf').style.display = 'block';

  var avg  = function(k) { return L11.rows.reduce(function(s,r){ return s + r[k]; }, 0) / 5; };
  var m1   = avg('m1'), m2  = avg('m2');
  var al1  = avg('l1'), al1p = avg('l1p'), al2p = avg('l2p');
  var lhs  = m1 * al1;
  var rhs  = m1 * al1p + m2 * al2p;
  var dP   = Math.abs(lhs - rhs);
  var eps  = dP / lhs * 100;
  var l1arr = L11.rows.map(function(r){ return r.l1; });
  var dL1  = Math.max.apply(null, l1arr.map(function(v){ return Math.abs(v - al1); }));
  var ok   = eps < 5;

  function f3(v){ return '<span class="nb-v">' + v.toFixed(3) + '</span>'; }
  function f4(v){ return '<span class="nb-v">' + v.toFixed(4) + '</span>'; }
  function bx(s){ return '<span class="nb-box">' + s + '</span>'; }

  var devRows = l1arr.map(function(v, i) {
    var dev = Math.abs(v - al1);
    return '<span class="nb-i">l<sub>' + (i+1) + '</sub>: |' +
           v.toFixed(3) + ' &minus; ' + al1.toFixed(3) + '| = ' +
           f3(dev) + '&nbsp;\u043c</span>';
  }).join('');

  var nb = [
    '<div class="nb-wrap">',
    '<div class="nb-hdr">\uD83D\uDCCB&nbsp; \u0412\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f (\u043a\u0430\u043a \u0432 \u0442\u0435\u0442\u0440\u0430\u0434\u0438)</div>',
    '<div class="nb-dado">',
    '<div><span class="nb-clbl">\u0414\u0430\u043d\u043e:</span><br>',
    'm\u2081 = ' + f3(m1) + '&nbsp;\u043a\u0433<br>',
    'm\u2082 = ' + f3(m2) + '&nbsp;\u043a\u0433<br>',
    '\u27E8l\u2081\u27E9 = ' + f3(al1)  + '&nbsp;\u043c<br>',
    '\u27E8l\u2081\u2019\u27E9 = ' + f3(al1p) + '&nbsp;\u043c<br>',
    '\u27E8l\u2082\u2019\u27E9 = ' + f3(al2p) + '&nbsp;\u043c</div>',
    '<div><span class="nb-clbl">\u041d\u0430\u0439\u0442\u0438:</span><br>',
    'p\u2081 = m\u2081\u27E8l\u2081\u27E9 \u2014 ?<br>',
    'p\u2081\u2032 + p\u2082\u2032 \u2014 ?<br>',
    '\u03B5 \u2014 ?<br>',
    '\u0394l\u2081, \u03B4l\u2081 \u2014 ?</div>',
    '</div>',
    '<hr class="nb-div">',
    '<div class="nb-sh">\u0420\u0435\u0448\u0435\u043d\u0438\u0435:</div>',
    '<div class="nb-step">',
    '<b>1.&nbsp; \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0417\u0421\u0418:</b><br>',
    '<span class="nb-i"><em>\u041b\u0435\u0432\u0430\u044f \u0447\u0430\u0441\u0442\u044c:</em></span>',
    '<span class="nb-i">p\u2081 = m\u2081&middot;\u27E8l\u2081\u27E9 = ' +
      m1.toFixed(3) + '&nbsp;&middot;&nbsp;' + al1.toFixed(3) + ' = ' + bx(lhs.toFixed(4) + '&nbsp;\u043a\u0433&middot;\u043c') + '</span>',
    '<span class="nb-i"><em>\u041f\u0440\u0430\u0432\u0430\u044f \u0447\u0430\u0441\u0442\u044c:</em></span>',
    '<span class="nb-i">p\u2081\u2032 + p\u2082\u2032 = m\u2081&middot;\u27E8l\u2081\u2032\u27E9 + m\u2082&middot;\u27E8l\u2082\u2032\u27E9</span>',
    '<span class="nb-i">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= ' +
      m1.toFixed(3) + '&middot;' + al1p.toFixed(3) + ' + ' + m2.toFixed(3) + '&middot;' + al2p.toFixed(3) + '</span>',
    '<span class="nb-i">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= ' +
      (m1*al1p).toFixed(4) + ' + ' + (m2*al2p).toFixed(4) + '</span>',
    '<span class="nb-i">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= ' + bx(rhs.toFixed(4) + '&nbsp;\u043a\u0433&middot;\u043c') + '</span>',
    '</div>',
    '<div class="nb-step">',
    '<b>2.&nbsp; \u041e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u0440\u0430\u0441\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u0435:</b><br>',
    '<span class="nb-i">\u03B5 = |p\u2081 &minus; (p\u2081\u2032+p\u2082\u2032)| / p\u2081 &middot; 100%</span>',
    '<span class="nb-i">&nbsp;&nbsp;= |' + lhs.toFixed(4) + ' &minus; ' + rhs.toFixed(4) + '| / ' + lhs.toFixed(4) + ' &middot; 100%</span>',
    '<span class="nb-i">&nbsp;&nbsp;= ' + dP.toFixed(4) + ' / ' + lhs.toFixed(4) + ' &middot; 100% = ' +
      bx(eps.toFixed(1) + '%') + '&nbsp;<span class="' + (ok ? 'nb-ok' : 'nb-bad') + '">' +
      (ok ? '&lt; 5%&nbsp;\u2713' : '&gt; 5%&nbsp;\u2717') + '</span></span>',
    '</div>',
    '<div class="nb-step">',
    '<b>3.&nbsp; \u041f\u043e\u0433\u0440\u0435\u0448\u043d\u043e\u0441\u0442\u044c \u043f\u0440\u044f\u043c\u044b\u0445 \u0438\u0437\u043c\u0435\u0440\u0435\u043d\u0438\u0439 l\u2081:</b><br>',
    devRows,
    '<span class="nb-i">\u0394l\u2081 = max|l<sub>i</sub> &minus; \u27E8l\u2081\u27E9| = ' + bx(dL1.toFixed(4) + '&nbsp;\u043c') + '</span>',
    '<span class="nb-i">\u03B4l\u2081 = ' + dL1.toFixed(4) + ' / ' + al1.toFixed(3) +
      ' &middot; 100% = ' + bx((dL1/al1*100).toFixed(1) + '%') + '</span>',
    '</div>',
    '<div class="nb-ans">',
    '\u041e\u0442\u0432\u0435\u0442:&nbsp;&nbsp; l\u2081 = (' + al1.toFixed(3) + ' &plusmn; ' + dL1.toFixed(3) + ')&nbsp;\u043c,&nbsp;&nbsp;' +
      '\u03B4l\u2081 = ' + (dL1/al1*100).toFixed(1) + '%&nbsp;&nbsp;&nbsp;' +
      '<span class="' + (ok ? 'nb-ok' : 'nb-bad') + '">' +
      (ok ? '\u0417\u0421\u0418 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0451\u043d \u2713' : '\u0420\u0430\u0441\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u0435 \u0432\u0435\u043b\u0438\u043a\u043e \u2717') + '</span>',
    '</div>',
    '</div>'
  ].join('\n');

  document.getElementById('lab11nb').innerHTML = nb;

  var cn = document.getElementById('lab11cn');
  cn.style.cssText = 'padding:14px 18px;border-radius:12px;font-size:.88rem;font-weight:700;line-height:1.7;background:' +
    (ok ? 'var(--ok-bg);color:#065f46' : 'var(--warn-bg);color:#92400e');
  cn.textContent = ok
    ? '\u2705 \u0417\u0430\u043a\u043e\u043d \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0438\u043c\u043f\u0443\u043b\u044c\u0441\u0430 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0451\u043d: \u03B5 = ' + eps.toFixed(1) + '% < 5% \u2014 \u0440\u0430\u0441\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u0435 \u0432 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u0445 \u043f\u043e\u0433\u0440\u0435\u0448\u043d\u043e\u0441\u0442\u0438.'
    : '\u26A0\uFE0F \u0420\u0430\u0441\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u0435 \u03B5 = ' + eps.toFixed(1) + '% > 5%. \u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043c\u0430\u0441\u0441\u044b \u0448\u0430\u0440\u043e\u0432 \u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u044c \u043e\u043f\u044b\u0442.';
}
function toggleSuperAns() {
  var el  = document.getElementById('superAns');
  var btn = document.getElementById('superAnsBtn');
  if (el.style.display === 'none') {
    el.style.display = 'block';
    btn.innerHTML = '<svg class="ic" viewBox="0 0 24 24" style="width:14px;height:14px;display:inline-block;vertical-align:-2px;stroke:currentColor;fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round"><path d="M9.88 9.88a3 3 0 1 0 4.24 4.24"/><path d="M10.73 5.08A10.43 10.43 0 0 1 12 5c7 0 10 7 10 7a13.16 13.16 0 0 1-1.67 2.68"/><path d="M6.61 6.61A13.526 13.526 0 0 0 2 12s3 7 10 7a9.74 9.74 0 0 0 5.39-1.61"/><line x1="2" y1="2" x2="22" y2="22"/></svg>&nbsp; Скрыть решение';
  } else {
    el.style.display = 'none';
    btn.innerHTML = '<svg class="ic" viewBox="0 0 24 24" style="width:14px;height:14px;display:inline-block;vertical-align:-2px;stroke:currentColor;fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round"><path d="M9 18h6M10 22h4M12 2a7 7 0 0 0-4 13c1 1 2 2 2 4h4c0-2 1-3 2-4a7 7 0 0 0-4-13z"/></svg>&nbsp; Показать решение';
  }
}

// ══════════════════════════════════════════════
//  ТЕМА (день/ночь)
// ══════════════════════════════════════════════
const themeBtn = document.getElementById('themeBtn');
if (themeBtn) {
  themeBtn.addEventListener('click', () => {
    const d = document.body.classList.toggle('dark');
    themeBtn.innerHTML = d ? '<svg class="ic" viewBox="0 0 24 24" style="width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round"><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41"/></svg>' : '<svg class="ic" viewBox="0 0 24 24" style="width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round"><path d="M21 12.8A9 9 0 1 1 11.2 3a7 7 0 0 0 9.8 9.8z"/></svg>';
    localStorage.setItem('phys9_theme', d ? '1' : '');
  });
  if (localStorage.getItem('phys9_theme') === '1') {
    document.body.classList.add('dark');
    themeBtn.innerHTML = '<svg class="ic" viewBox="0 0 24 24" style="width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round"><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41"/></svg>';
  }
}

// ══════════════════════════════════════════════
//  СПРАВОЧНИК (плавающий)
// ══════════════════════════════════════════════
const refToggle = document.getElementById('refToggle');
const refPanel  = document.getElementById('refPanel');
if (refToggle && refPanel) {
  refToggle.addEventListener('click', e => { e.stopPropagation(); refPanel.classList.toggle('show'); });
  document.addEventListener('click', e => {
    if (!refPanel.contains(e.target) && e.target !== refToggle) refPanel.classList.remove('show');
  });
}

// ══════════════════════════════════════════════
//  ИНИЦИАЛИЗАЦИЯ
// ══════════════════════════════════════════════
try {
  ['p1','p2','p3','p4','p5','p6','p7','p8','p9','p10','p11','p12','p13','p14','p15','p16','p17','p18','p19','p20','p21','p22','p23','p24','p25','p26','p27','p28','p29','p30','p31','p32','p33','p34','p35','p36','hard'].forEach(sec => { try { renderTask(sec); } catch(e){} });
} catch(e) {}
try { setParaTab('p1'); } catch(e) {}
[upd2,upd3,upd4,upd5,upd6,upd7,upd8,upd10,upd11,upd12].forEach(fn => { try { fn(); } catch(e){} });

try {
upd16(); upd17(); upd19(); upd20(); upd21();
upd22(); upd23(); upd24();
upd25(); upd26(); upd27(); upd27mu();
upd28(); upd29(); upd30();
upd31(); upd33(); upd34zero(); upd34(); upd35(); updLab11();
// §15–§21 init: planet grid + canvas draws for active tab
initPlanetGrid16();
startAnim1();
startAnim15();
// §9, §13, §14 are animation loops — deferred to tab click (hidden at load)
// §19 and §20 canvas draw is deferred: the tabs are hidden at load,
// drawSpring19/drawFriction20 are called via tab-click handler and upd* functions
// Redraw lab11 canvas when its tab becomes visible
if (window.ResizeObserver) {
  const _ro11 = new ResizeObserver(entries => {
    if (entries[0].contentRect.width > 0) drawLab11();
  });
  const _cv11 = document.getElementById('cvLab11');
  if (_cv11) _ro11.observe(_cv11);
}

} catch(e) { console.warn("phys9_legacy setup skipped:", e.message); }


// === Expose handlers + task pools to global scope ===
try { if (typeof setParaTab !== "undefined") window.setParaTab = setParaTab; } catch(e) {}
try { if (typeof renderNav !== "undefined") window.renderNav = renderNav; } catch(e) {}
try { if (typeof goToTask !== "undefined") window.goToTask = goToTask; } catch(e) {}
try { if (typeof renderTask !== "undefined") window.renderTask = renderTask; } catch(e) {}
try { if (typeof selectMcq !== "undefined") window.selectMcq = selectMcq; } catch(e) {}
try { if (typeof checkNum !== "undefined") window.checkNum = checkNum; } catch(e) {}
try { if (typeof check !== "undefined") window.check = check; } catch(e) {}
try { if (typeof startAnim1 !== "undefined") window.startAnim1 = startAnim1; } catch(e) {}
try { if (typeof upd2 !== "undefined") window.upd2 = upd2; } catch(e) {}
try { if (typeof upd3 !== "undefined") window.upd3 = upd3; } catch(e) {}
try { if (typeof drawArrow3 !== "undefined") window.drawArrow3 = drawArrow3; } catch(e) {}
try { if (typeof upd4 !== "undefined") window.upd4 = upd4; } catch(e) {}
try { if (typeof upd5 !== "undefined") window.upd5 = upd5; } catch(e) {}
try { if (typeof upd6 !== "undefined") window.upd6 = upd6; } catch(e) {}
try { if (typeof upd7 !== "undefined") window.upd7 = upd7; } catch(e) {}
try { if (typeof upd8 !== "undefined") window.upd8 = upd8; } catch(e) {}
try { if (typeof upd9 !== "undefined") window.upd9 = upd9; } catch(e) {}
try { if (typeof upd10 !== "undefined") window.upd10 = upd10; } catch(e) {}
try { if (typeof upd11 !== "undefined") window.upd11 = upd11; } catch(e) {}
try { if (typeof upd12 !== "undefined") window.upd12 = upd12; } catch(e) {}
try { if (typeof upd13 !== "undefined") window.upd13 = upd13; } catch(e) {}
try { if (typeof upd14 !== "undefined") window.upd14 = upd14; } catch(e) {}
try { if (typeof upd16 !== "undefined") window.upd16 = upd16; } catch(e) {}
try { if (typeof upd17 !== "undefined") window.upd17 = upd17; } catch(e) {}
try { if (typeof upd19 !== "undefined") window.upd19 = upd19; } catch(e) {}
try { if (typeof upd20 !== "undefined") window.upd20 = upd20; } catch(e) {}
try { if (typeof upd21 !== "undefined") window.upd21 = upd21; } catch(e) {}
try { if (typeof upd22 !== "undefined") window.upd22 = upd22; } catch(e) {}
try { if (typeof drawAngularThrow22 !== "undefined") window.drawAngularThrow22 = drawAngularThrow22; } catch(e) {}
try { if (typeof upd23 !== "undefined") window.upd23 = upd23; } catch(e) {}
try { if (typeof drawGravity23 !== "undefined") window.drawGravity23 = drawGravity23; } catch(e) {}
try { if (typeof upd24 !== "undefined") window.upd24 = upd24; } catch(e) {}
try { if (typeof drawElevator24 !== "undefined") window.drawElevator24 = drawElevator24; } catch(e) {}
try { if (typeof upd25 !== "undefined") window.upd25 = upd25; } catch(e) {}
try { if (typeof drawSeesaw25 !== "undefined") window.drawSeesaw25 = drawSeesaw25; } catch(e) {}
try { if (typeof upd26 !== "undefined") window.upd26 = upd26; } catch(e) {}
try { if (typeof drawLever26 !== "undefined") window.drawLever26 = drawLever26; } catch(e) {}
try { if (typeof upd27 !== "undefined") window.upd27 = upd27; } catch(e) {}
try { if (typeof upd27mu !== "undefined") window.upd27mu = upd27mu; } catch(e) {}
try { if (typeof drawIncline27 !== "undefined") window.drawIncline27 = drawIncline27; } catch(e) {}
try { if (typeof drawEfficiency27 !== "undefined") window.drawEfficiency27 = drawEfficiency27; } catch(e) {}
try { if (typeof startAnim15 !== "undefined") window.startAnim15 = startAnim15; } catch(e) {}
try { if (typeof initPlanetGrid16 !== "undefined") window.initPlanetGrid16 = initPlanetGrid16; } catch(e) {}
try { if (typeof startAnim17 !== "undefined") window.startAnim17 = startAnim17; } catch(e) {}
try { if (typeof startAnim18 !== "undefined") window.startAnim18 = startAnim18; } catch(e) {}
try { if (typeof drawSpring19 !== "undefined") window.drawSpring19 = drawSpring19; } catch(e) {}
try { if (typeof drawFriction20 !== "undefined") window.drawFriction20 = drawFriction20; } catch(e) {}
try { if (typeof startAnim21 !== "undefined") window.startAnim21 = startAnim21; } catch(e) {}
try { if (typeof upd28 !== "undefined") window.upd28 = upd28; } catch(e) {}
try { if (typeof drawEquilibrium28 !== "undefined") window.drawEquilibrium28 = drawEquilibrium28; } catch(e) {}
try { if (typeof upd29 !== "undefined") window.upd29 = upd29; } catch(e) {}
try { if (typeof drawArchimedes29 !== "undefined") window.drawArchimedes29 = drawArchimedes29; } catch(e) {}
try { if (typeof upd30 !== "undefined") window.upd30 = upd30; } catch(e) {}
try { if (typeof drawShip30 !== "undefined") window.drawShip30 = drawShip30; } catch(e) {}
try { if (typeof upd31 !== "undefined") window.upd31 = upd31; } catch(e) {}
try { if (typeof upd33 !== "undefined") window.upd33 = upd33; } catch(e) {}
try { if (typeof upd34zero !== "undefined") window.upd34zero = upd34zero; } catch(e) {}
try { if (typeof upd34 !== "undefined") window.upd34 = upd34; } catch(e) {}
try { if (typeof upd35 !== "undefined") window.upd35 = upd35; } catch(e) {}
try { if (typeof togglePend36 !== "undefined") window.togglePend36 = togglePend36; } catch(e) {}
try { if (typeof nextTask !== "undefined") window.nextTask = nextTask; } catch(e) {}
try { if (typeof resetTasks !== "undefined") window.resetTasks = resetTasks; } catch(e) {}
try { if (typeof updateScoreBar !== "undefined") window.updateScoreBar = updateScoreBar; } catch(e) {}
try { if (typeof showSummary !== "undefined") window.showSummary = showSummary; } catch(e) {}
try { if (typeof updLab11 !== "undefined") window.updLab11 = updLab11; } catch(e) {}
try { if (typeof drawLab11 !== "undefined") window.drawLab11 = drawLab11; } catch(e) {}
try { if (typeof lab11add !== "undefined") window.lab11add = lab11add; } catch(e) {}
try { if (typeof lab11all !== "undefined") window.lab11all = lab11all; } catch(e) {}
try { if (typeof lab11reset !== "undefined") window.lab11reset = lab11reset; } catch(e) {}
try { if (typeof toggleSuperAns !== "undefined") window.toggleSuperAns = toggleSuperAns; } catch(e) {}
try { if (typeof TASKS_P31 !== "undefined") window.TASKS_P31 = TASKS_P31; } catch(e) {}
try { if (typeof TASKS_P32 !== "undefined") window.TASKS_P32 = TASKS_P32; } catch(e) {}
try { if (typeof TASKS_HARD !== "undefined") window.TASKS_HARD = TASKS_HARD; } catch(e) {}
try { if (typeof TASKS_P33 !== "undefined") window.TASKS_P33 = TASKS_P33; } catch(e) {}
try { if (typeof TASKS_P34 !== "undefined") window.TASKS_P34 = TASKS_P34; } catch(e) {}
try { if (typeof TASKS_P35 !== "undefined") window.TASKS_P35 = TASKS_P35; } catch(e) {}
try { if (typeof TASKS_P36 !== "undefined") window.TASKS_P36 = TASKS_P36; } catch(e) {}
try { if (typeof POOLS !== "undefined") window.POOLS = POOLS; } catch(e) {}
try { if (typeof STATE !== "undefined") window.STATE = STATE; } catch(e) {}
})();
