diff --git a/frontend/js/phys7_ch3_widgets.js b/frontend/js/phys7_ch3_widgets.js
index bceb9a8..be5ebaf 100644
--- a/frontend/js/phys7_ch3_widgets.js
+++ b/frontend/js/phys7_ch3_widgets.js
@@ -1068,15 +1068,1057 @@ function add_p20(){
renderMath(body);
}
+/* ========================================================== */
+/* §21 — Сила */
+/* ========================================================== */
+function add_p21(){
+ const body = document.getElementById('p21-body');
+ if(!body) return;
+ let h = '';
+
+ h += makeCard('theory', 'Что такое сила', '§ 21.1',
+ 'Сила $\\vec F$ — физическая величина, которая характеризует взаимодействие двух тел. '
+ + 'Сила всегда возникает в паре: одно тело действует на другое.
'
+ + '$[F] = $ Н (ньютон) — в честь Исаака Ньютона.');
+
+ h += makeCard('rule', 'Что значит «изобразить силу»', '§ 21.2',
+ 'У силы три характеристики (поэтому её рисуют стрелкой — вектором):'
+ + '
'
+ + '
Модуль (длина стрелки) — численное значение в ньютонах.
'
+ + '
Направление — куда направлена стрелка.
'
+ + '
Точка приложения — где начало стрелки (где сила «приложена» к телу).
'
+ + '
');
+
+ h += makeCard('example', 'Четыре силы из жизни', '§ 21.3',
+ '
');
+
+ /* IV-1 СИМ: визуал силы со стрелкой */
+ h += wgWrap('p21-iv1', 'СИМ', 'Сила-стрелка', 'Меняй модуль и направление — посмотри, как меняется стрелка.',
+ '
'
+ + quizQuestion('p21-tr', 0, 'Силу обозначают…', ['$s$','$v$','$F$','$t$'], 2)
+ + quizQuestion('p21-tr', 1, 'Сила — мера…', ['Длины','Времени','Взаимодействия тел','Объёма'], 2)
+ + quizQuestion('p21-tr', 2, 'В каких единицах СИ выражают силу?', ['Кг','Н (ньютоны)','Дж','м/с²'], 1)
+ + quizQuestion('p21-tr', 3, 'Что нужно для того, чтобы изобразить силу?', ['Только число','Только направление','Стрелка с заданной длиной, направлением и точкой приложения','Только подпись'], 2)
+ + '
');
+
+ h += readButton('p21');
+ body.innerHTML = h;
+
+ function draw21(){
+ const F = +document.getElementById('p21-F-r').value;
+ const ang = +document.getElementById('p21-ang-r').value;
+ document.getElementById('p21-F').textContent = F;
+ document.getElementById('p21-ang').textContent = ang;
+ const cx = 150, cy = 110;
+ const len = F * 2.5;
+ const a = -ang * Math.PI / 180;
+ const x2 = cx + len * Math.cos(a);
+ const y2 = cy + len * Math.sin(a);
+ let s = '';
+ // Тело — кружок
+ s += '';
+ // Стрелка силы
+ s += '';
+ // Наконечник
+ const ah = 10;
+ const ax1 = x2 - ah * Math.cos(a - 0.4);
+ const ay1 = y2 - ah * Math.sin(a - 0.4);
+ const ax2 = x2 - ah * Math.cos(a + 0.4);
+ const ay2 = y2 - ah * Math.sin(a + 0.4);
+ s += '';
+ // Подпись
+ s += 'F = ' + F + ' Н';
+ document.getElementById('p21-svg').innerHTML = s;
+ }
+ ['p21-F-r','p21-ang-r'].forEach(id => document.getElementById(id).addEventListener('input', draw21));
+ draw21();
+
+ wireDnd('p21-dnd', [
+ { id:'a1', cat:'grav' },{ id:'a2', cat:'grav' },{ id:'a3', cat:'el' },{ id:'a4', cat:'el' },
+ { id:'a5', cat:'fr' },{ id:'a6', cat:'fr' },{ id:'a7', cat:'norm' },{ id:'a8', cat:'norm' }
+ ]);
+ wireQuiz('p21-q-host', () => { if(window.addXp) window.addXp(10, 'q-p21'); });
+ wireQuiz('p21-tr-host', () => { if(window.addXp) window.addXp(15, 'tr-p21'); });
+ wireReadBtn('p21');
+ renderMath(body);
+}
+
+/* ========================================================== */
+/* §22 — Сила тяжести */
+/* ========================================================== */
+function add_p22(){
+ const body = document.getElementById('p22-body');
+ if(!body) return;
+ let h = '';
+
+ h += makeCard('theory', 'Притяжение к Земле', '§ 22.1',
+ 'Земля притягивает все тела возле своей поверхности. Сила, с которой Земля действует на тело, '
+ + 'называется силой тяжести $\\vec F_т$. Она направлена вертикально вниз '
+ + '(точнее — к центру Земли).');
+
+ h += makeCard('rule', 'Формула силы тяжести', '§ 22.2',
+ '$$F_т = m g$$ '
+ + 'где $m$ — масса тела (кг), $g$ — ускорение свободного падения.
'
+ + 'На Земле: $g = 9{,}8$ Н/кг (часто округляют до $g \\approx 10$ Н/кг). '
+ + 'На Луне: $g_Л \\approx 1{,}6$ Н/кг (в 6 раз меньше). '
+ + 'На Марсе: $g_М \\approx 3{,}7$ Н/кг. '
+ + 'На Юпитере: $g_Ю \\approx 24{,}8$ Н/кг.');
+
+ h += makeCard('example', 'Сколько весит яблоко?', '§ 22.3',
+ 'Масса среднего яблока $m = 100$ г $= 0{,}1$ кг. На Земле: '
+ + '$F_т = mg = 0{,}1 \\cdot 9{,}8 \\approx 1$ Н.
'
+ + 'Поэтому 1 ньютон — это «сила, с которой Земля притягивает 100 г».');
+
+ /* IV-1 КАЛЬК: F_т = mg, выбор планеты */
+ h += wgWrap('p22-iv1', 'КАЛЬК', 'Сила тяжести на разных планетах', 'Выбери планету и тело — узнай, как меняется $F_т$.',
+ '
'
+ + quizQuestion('p22-q', 0, 'Куда направлена сила тяжести на поверхности Земли?', ['Вверх','Вертикально вниз (к центру Земли)','В сторону Солнца','В произвольном направлении'], 1)
+ + quizQuestion('p22-q', 1, '$g$ на Земле примерно равно…', ['1 Н/кг','9,8 Н/кг','100 Н/кг','1000 Н/кг'], 1)
+ + quizQuestion('p22-q', 2, 'На Луне $g_Л$ примерно в 6 раз меньше земного. Что произойдёт с $F_т$ камня?', ['Не изменится','Увеличится в 6 раз','Уменьшится в 6 раз','Станет нулевой'], 2)
+ + quizQuestion('p22-q', 3, 'Масса остаётся постоянной на Земле и Луне, а сила тяжести?', ['Тоже постоянна','Уменьшается на Луне','Увеличивается на Луне','Зависит от формы тела'], 1, 'Масса = «количество вещества», она не меняется. А $F_т = mg$ меняется через $g$.')
+ + '
'
+ + quizQuestion('p22-tr', 0, '$m = 5$ кг. $F_т$ на Земле ($g = 10$ Н/кг)?', ['5 Н','15 Н','50 Н','500 Н'], 2, '$F_т = mg = 5 \\cdot 10 = 50$ Н.')
+ + quizQuestion('p22-tr', 1, '$m = 200$ г. $F_т$ на Земле ($g = 9{,}8$ Н/кг) ≈?', ['0,98 Н','1,96 Н','19,6 Н','2 Н'], 1, '$F_т = 0{,}2 \\cdot 9{,}8 = 1{,}96$ Н.')
+ + quizQuestion('p22-tr', 2, 'Космонавт $m = 80$ кг. $F_т$ на Луне ($g_Л = 1{,}6$ Н/кг)?', ['80 Н','128 Н','480 Н','800 Н'], 1, '$F_т = 80 \\cdot 1{,}6 = 128$ Н.')
+ + quizQuestion('p22-tr', 3, 'Где $F_т$ одной и той же массы больше: на Юпитере или Луне?', ['На Луне','На Юпитере','Одинаково','Зависит от вещества'], 1, 'У Юпитера $g$ намного больше.')
+ + quizQuestion('p22-tr', 4, 'Чтобы $F_т$ на Земле была $30$ Н, нужна масса…', ['1 кг','2 кг','3 кг','30 кг'], 2, 'При $g \\approx 10$ Н/кг: $m = F_т/g = 30/10 = 3$ кг.')
+ + '
');
+
+ h += readButton('p22');
+ body.innerHTML = h;
+
+ let g22 = 9.8;
+ let plName = 'Земле';
+ function upd22(){
+ const m = +document.getElementById('p22-m-r').value / 1000; // ползунок в граммах
+ document.getElementById('p22-m').textContent = (m).toFixed(2);
+ const Ft = m * g22;
+ document.getElementById('p22-Ft').textContent = Ft.toFixed(2);
+ document.getElementById('p22-pl-nm').textContent = plName;
+ document.getElementById('p22-g-val').textContent = g22.toString().replace('.', ',');
+ }
+ body.querySelectorAll('.p22-pl').forEach(btn => btn.addEventListener('click', () => {
+ body.querySelectorAll('.p22-pl').forEach(b => { b.style.background = '#fff'; b.style.color = '#dc2626'; });
+ btn.style.background = '#dc2626'; btn.style.color = '#fff';
+ g22 = +btn.dataset.g;
+ plName = btn.dataset.nm;
+ upd22();
+ }));
+ document.getElementById('p22-m-r').addEventListener('input', upd22);
+ upd22();
+
+ wireDnd('p22-dnd', [
+ { id:'a1', cat:'1n' },{ id:'a2', cat:'10n' },{ id:'a3', cat:'100n' },
+ { id:'a4', cat:'1n' },{ id:'a5', cat:'10n' },{ id:'a6', cat:'100n' }
+ ]);
+ wireQuiz('p22-q-host', () => { if(window.addXp) window.addXp(10, 'q-p22'); });
+ wireQuiz('p22-tr-host', () => { if(window.addXp) window.addXp(15, 'tr-p22'); });
+ wireReadBtn('p22');
+ renderMath(body);
+}
+
+/* ========================================================== */
+/* §23 — Сила упругости */
+/* ========================================================== */
+function add_p23(){
+ const body = document.getElementById('p23-body');
+ if(!body) return;
+ let h = '';
+
+ h += makeCard('theory', 'Когда возникает упругая сила', '§ 23.1',
+ 'Если тело деформировано (сжато, растянуто, изогнуто), внутри него возникает '
+ + 'сила упругости $\\vec F_{упр}$, которая стремится вернуть тело в исходную форму.
'
+ + 'Природа этой силы — взаимодействие молекул, изученное в §10.');
+
+ h += makeCard('rule', 'Закон Гука (качественно)', '§ 23.2',
+ '$$F_{упр} \\sim \\Delta l$$ '
+ + 'Сила упругости пропорциональна удлинению $\\Delta l$. '
+ + 'То есть в 2 раза больше растянули → в 2 раза больше сила.
'
+ + 'Внимание: закон работает только пока деформация мала. Если перерастянуть пружину — '
+ + 'она не вернётся в исходное положение (пластическая деформация).');
+
+ h += makeCard('example', 'Где встречается', '§ 23.3',
+ '
'
+ + '
Пружина матраса, ручки, амортизатора.
'
+ + '
Резинка для волос, рогатка.
'
+ + '
Лук: тетива растянута → возвращает стрелу.
'
+ + '
Опора прогибается под весом и отвечает реакцией $\\vec N$ — это тоже упругая сила.
'
+ + '
');
+
+ /* IV-1 СИМ: пружина с slider */
+ h += wgWrap('p23-iv1', 'СИМ', 'Пружина: растяжение и сила', 'Меняй удлинение — увидь, как растёт сила упругости.',
+ ''
+ + ''
+ + '');
+
+ /* IV-2 КВИЗ */
+ h += wgWrap('p23-iv2', 'КВИЗ', 'Упругость', '',
+ '
'
+ + quizQuestion('p23-q', 0, 'Когда возникает сила упругости?', ['Всегда','Только в жидкостях','При деформации тела','При движении'], 2)
+ + quizQuestion('p23-q', 1, 'Куда направлена $\\vec F_{упр}$?', ['В сторону деформации','Против деформации (возвращает в исходное)','Вертикально вниз','Зависит от тела'], 1)
+ + quizQuestion('p23-q', 2, 'Если растянуть пружину в 3 раза сильнее, $F_{упр}$ изменится…', ['Не изменится','Увеличится в 3 раза','Уменьшится в 3 раза','Увеличится в 9 раз'], 1, 'Это закон Гука: $F \\sim \\Delta l$.')
+ + '
'
+ + quizQuestion('p23-tr', 0, 'Природа силы упругости — это…', ['Гравитация','Взаимодействие молекул','Магнетизм','Электричество'], 1)
+ + quizQuestion('p23-tr', 1, 'Если пружину растянуть слишком сильно, она…', ['Останется упругой','Может остаться растянутой (пластическая деформация)','Станет тяжелее','Не изменится'], 1)
+ + quizQuestion('p23-tr', 2, 'Что является примером упругой деформации?', ['Растяжение пружины и возврат','Лепка из пластилина','Раскалывание камня','Резка хлеба'], 0)
+ + quizQuestion('p23-tr', 3, 'Какая из сил из жизни — упругая?', ['Сила тяжести','Сила трения','Реакция опоры $\\vec N$','Лунное притяжение'], 2, 'Опора прогибается и «отвечает» упругой силой.')
+ + '
');
+
+ h += readButton('p23');
+ body.innerHTML = h;
+
+ function draw23(){
+ const dl = +document.getElementById('p23-dl-r').value;
+ document.getElementById('p23-dl').textContent = dl;
+ const F = dl * 2; // условный коэф. жёсткости 2 Н/см
+ const W = 380, H = 160;
+ const topY = 20, hookX = 80;
+ const naturalLen = 60;
+ const totalLen = naturalLen + dl * 3.5; // визуально усилено
+ let s = '';
+ // Потолок
+ s += '';
+ for(let i = 0; i < 6; i++) s += '';
+ // Подвес
+ s += '';
+ // Пружина (зигзаг)
+ const coils = 8;
+ let path = 'M ' + hookX + ' ' + topY;
+ for(let i = 0; i < coils; i++){
+ const y = topY + (i + 0.5) * (totalLen / coils);
+ path += ' L ' + (hookX + (i%2 ? 18 : -18)) + ' ' + y;
+ }
+ path += ' L ' + hookX + ' ' + (topY + totalLen);
+ s += '';
+ // Груз
+ s += '';
+ s += 'груз';
+ // Стрелка F_упр (вверх) и F_т (вниз) если dl>0
+ if(dl > 0){
+ const arrY = topY + totalLen + 50;
+ // F_упр вверх
+ s += '';
+ s += '';
+ s += 'F_упр = ' + F + ' Н ↑';
+ // F_т вниз
+ s += '';
+ s += '';
+ s += 'F_т ↓';
+ }
+ document.getElementById('p23-svg').innerHTML = s;
+ document.getElementById('p23-info').innerHTML = 'Удлинение $\\Delta l = ' + dl + '$ см · $F_{упр} \\approx $ ' + F + ' Н (при коэф. жёсткости $k = 2$ Н/см)';
+ renderMath(document.getElementById('p23-info'));
+ }
+ document.getElementById('p23-dl-r').addEventListener('input', draw23);
+ draw23();
+
+ wireDnd('p23-dnd', [
+ { id:'a1', cat:'def' },{ id:'a2', cat:'def' },{ id:'a3', cat:'def' },
+ { id:'a4', cat:'def' },{ id:'a5', cat:'no' },{ id:'a6', cat:'no' }
+ ]);
+ wireQuiz('p23-q-host', () => { if(window.addXp) window.addXp(10, 'q-p23'); });
+ wireQuiz('p23-tr-host', () => { if(window.addXp) window.addXp(15, 'tr-p23'); });
+ wireReadBtn('p23');
+ renderMath(body);
+}
+
+/* ========================================================== */
+/* §24 — Вес тела */
+/* ========================================================== */
+function add_p24(){
+ const body = document.getElementById('p24-body');
+ if(!body) return;
+ let h = '';
+
+ h += makeCard('theory', 'Что такое вес', '§ 24.1',
+ 'Вес $\\vec P$ — это сила, с которой тело давит на опору (или растягивает подвес) '
+ + 'вследствие притяжения к Земле.
'
+ + 'Это не то же самое, что сила тяжести! Хоть на покоящемся теле они равны по модулю, '
+ + 'они приложены к разным телам:'
+ + '
'
+ + '
$\\vec F_т$ — действует на само тело от Земли;
'
+ + '
$\\vec P$ — действует на опору или подвес от тела.
'
+ + '
');
+
+ h += makeCard('rule', 'Когда $P = F_т$, а когда нет', '§ 24.2',
+ 'Покоится на горизонтальной опоре или висит на нити: $P = F_т = mg$.
'
+ + 'Невесомость (свободное падение): $P = 0$ — тело не давит на опору. '
+ + 'Космонавт на МКС в невесомости — у него масса есть, $F_т$ от Земли тоже есть, '
+ + 'а вот вес $P = 0$, потому что станция падает на Землю вместе с ним.
'
+ + 'Перегрузка: в ускоряющемся лифте вверх вес больше $mg$. В лифте вниз — меньше.');
+
+ h += makeCard('example', 'Как взвешивают тело', '§ 24.3',
+ 'На чашечных весах сравнивают вес тела и вес гирь. '
+ + 'Когда чашечки уравновешены — массы равны (поскольку $g$ одинаков, и $P = mg$).
'
+ + 'На пружинных весах (динамометре) измеряют силу, с которой тело растягивает пружину. '
+ + 'Это и есть вес тела в Ньютонах.');
+
+ /* IV-1 СИМ: тело в 3 ситуациях */
+ h += wgWrap('p24-iv1', 'СИМ', 'Три ситуации: покой, падение, ускорение', 'Выбери ситуацию — увидь стрелки сил.',
+ '
'
+ + quizQuestion('p24-tr', 0, '$m = 0{,}5$ кг лежит на столе. Вес (при $g = 10$ Н/кг)?', ['0,5 Н','5 Н','50 Н','500 Н'], 1)
+ + quizQuestion('p24-tr', 1, 'Гиря $m = 100$ г висит на нити. Сила, с которой нить растягивается, равна:', ['1 Н','10 Н','100 Н','0,1 Н'], 0, '$P = mg = 0{,}1 \\cdot 10 = 1$ Н.')
+ + quizQuestion('p24-tr', 2, 'В свободно падающем лифте чувствует ли пассажир свой вес?', ['Да, как всегда','Нет, наступает невесомость','В 2 раза больше','В 2 раза меньше'], 1)
+ + quizQuestion('p24-tr', 3, 'На Луне ($g_Л = 1{,}6$ Н/кг) тело массой $5$ кг весит:', ['5 Н','8 Н','16 Н','50 Н'], 1, '$P = 5 \\cdot 1{,}6 = 8$ Н.')
+ + '
');
+
+ h += readButton('p24');
+ body.innerHTML = h;
+
+ function draw24(s){
+ const svg = document.getElementById('p24-svg');
+ if(!svg) return;
+ const cx = 180, cy = 100;
+ let html = '';
+ let info = '';
+ if(s === 'rest'){
+ // Тело на столе
+ html += '';
+ for(let i = 0; i < 14; i++) html += '';
+ html += '';
+ // F_т вниз (фиолетовая)
+ html += '';
+ html += '';
+ html += 'F_т (на тело)';
+ // P вниз от низа тела (индиго)
+ html += '';
+ html += '';
+ html += 'P (на стол)';
+ info = 'Покой на горизонтальной опоре: $P = F_т = mg$, но приложены к разным телам.';
+ } else if(s === 'fall'){
+ html += '';
+ // F_т вниз
+ html += '';
+ html += '';
+ html += 'F_т ↓';
+ // P = 0 — пиктограмма
+ html += 'P = 0';
+ html += 'невесомость';
+ info = 'Свободное падение / орбита: сила тяжести есть ($F_т = mg \\ne 0$), но вес $P = 0$ — тело ни на что не давит.';
+ } else if(s === 'up'){
+ html += '';
+ html += ''; // тяга вверх
+ html += '';
+ // F_т
+ html += '';
+ html += '';
+ html += 'F_т = mg';
+ // P больше — длинная стрелка
+ html += '';
+ html += '';
+ html += 'P > mg (перегрузка)';
+ info = 'Лифт ускоряется вверх: вес больше $mg$ — это перегрузка. Космонавты на старте испытывают $P \\approx 3 mg$.';
+ } else {
+ // down
+ html += '';
+ html += '';
+ html += '';
+ html += '';
+ html += 'F_т = mg';
+ // P меньше — короткая стрелка
+ html += '';
+ html += '';
+ html += 'P < mg';
+ info = 'Лифт ускоряется вниз: вес меньше $mg$. Если ускорение $= g$, то $P = 0$ — невесомость.';
+ }
+ svg.innerHTML = html;
+ document.getElementById('p24-info').innerHTML = info;
+ renderMath(document.getElementById('p24-info'));
+ }
+ body.querySelectorAll('.p24-sit').forEach(btn => btn.addEventListener('click', () => {
+ body.querySelectorAll('.p24-sit').forEach(b => { b.style.background = '#fff'; b.style.color = '#dc2626'; });
+ btn.style.background = '#dc2626'; btn.style.color = '#fff';
+ draw24(btn.dataset.s);
+ }));
+ draw24('rest');
+
+ wireDnd('p24-dnd', [
+ { id:'a1', cat:'ft' },{ id:'a2', cat:'ft' },{ id:'a3', cat:'p' },
+ { id:'a4', cat:'p' },{ id:'a5', cat:'zero' },{ id:'a6', cat:'zero' }
+ ]);
+ wireQuiz('p24-q-host', () => { if(window.addXp) window.addXp(10, 'q-p24'); });
+ wireQuiz('p24-tr-host', () => { if(window.addXp) window.addXp(15, 'tr-p24'); });
+ wireReadBtn('p24');
+ renderMath(body);
+}
+
+/* ========================================================== */
+/* §25 — Динамометр */
+/* ========================================================== */
+function add_p25(){
+ const body = document.getElementById('p25-body');
+ if(!body) return;
+ let h = '';
+
+ h += makeCard('theory', 'Принцип работы', '§ 25.1',
+ 'Динамометр (от греч. динамис — сила) — прибор для измерения силы.
'
+ + 'В основе — пружина: чем сильнее её растягивают, тем больше она удлиняется. '
+ + 'Шкала проградуирована так, чтобы каждому положению указателя соответствовала сила в ньютонах.');
+
+ h += makeCard('rule', 'Виды динамометров', '§ 25.2',
+ '
'
+ + '
Школьный лабораторный — обычно $0..4$ Н или $0..10$ Н, цена деления $0{,}1$ Н.
'
+ + '
Медицинский (для силы кисти) — до $600$ Н.
'
+ + '
Промышленный — для измерения тяги машин, до тысяч Н и больше.
'
+ + '
'
+ + 'Правила: прибор калибруют в вертикальном положении; не превышай предел шкалы (иначе пружина испортится).');
+
+ h += makeCard('example', 'Связь с массой', '§ 25.3',
+ 'Динамометр измеряет силу (например, вес висящего груза). Если знаешь $g$, можно найти массу: '
+ + '$$m = \\dfrac{F}{g}$$ '
+ + 'Например, динамометр показал $P = 5$ Н. Тогда $m = 5 / 10 = 0{,}5$ кг $= 500$ г.');
+
+ /* IV-1 СИМ: виртуальный динамометр */
+ h += wgWrap('p25-iv1', 'СИМ', 'Виртуальный динамометр', 'Меняй силу — наблюдай растяжение пружины и положение указателя.',
+ '
'
+ + quizQuestion('p25-tr', 0, 'Динамометр показал $F = 4$ Н на Земле ($g = 10$). Масса тела?', ['0,4 кг','4 кг','40 кг','0,04 кг'], 0)
+ + quizQuestion('p25-tr', 1, 'Какова цена деления школьного динамометра 0..4 Н с 40 малыми делениями?', ['0,01 Н','0,1 Н','0,4 Н','1 Н'], 1, '$C = 4/40 = 0{,}1$ Н.')
+ + quizQuestion('p25-tr', 2, 'Принцип работы динамометра основан на…', ['Силе тяжести','Растяжении пружины (упругая сила)','Магнитном поле','Электричестве'], 1)
+ + quizQuestion('p25-tr', 3, 'Что произойдёт, если превысить предел шкалы?', ['Ничего','Пружина испортится','Прибор сам сломается','Подаст звуковой сигнал'], 1)
+ + '
');
+
+ h += readButton('p25');
+ body.innerHTML = h;
+
+ function draw25(){
+ const F = +document.getElementById('p25-F-r').value;
+ const Fmax = +document.getElementById('p25-Fmax-r').value;
+ document.getElementById('p25-F').textContent = F.toFixed(1);
+ document.getElementById('p25-Fmax').textContent = Fmax;
+ if(window.PHYS && window.PHYS.dynamometer){
+ let svgInner = window.PHYS.dynamometer(80, 20, 160, Fmax, Math.min(F, Fmax));
+ // Цвет фона для подложки
+ document.getElementById('p25-svg').innerHTML = '' + svgInner;
+ }
+ document.getElementById('p25-info').innerHTML = F > Fmax
+ ? 'Превышение предела! Реальная сила $F = ' + F.toFixed(1) + '$ Н > $F_{max} = ' + Fmax + '$ Н. Пружина может испортиться.'
+ : 'Показание: $F = ' + F.toFixed(1) + '$ Н из $' + Fmax + '$ Н. Цена деления $\\approx ' + (Fmax/20).toFixed(2) + '$ Н.';
+ renderMath(document.getElementById('p25-info'));
+ }
+ ['p25-F-r','p25-Fmax-r'].forEach(id => document.getElementById(id).addEventListener('input', draw25));
+ draw25();
+
+ const upd25c = () => {
+ const F = +document.getElementById('p25c-F-r').value;
+ const g = +document.getElementById('p25c-g-s').value;
+ document.getElementById('p25c-F').textContent = F.toFixed(1);
+ document.getElementById('p25c-g').textContent = g.toString().replace('.', ',');
+ const m = F / g;
+ document.getElementById('p25c-m').textContent = m.toFixed(3);
+ document.getElementById('p25c-mg').textContent = (m * 1000).toFixed(0);
+ };
+ document.getElementById('p25c-F-r').addEventListener('input', upd25c);
+ document.getElementById('p25c-g-s').addEventListener('change', upd25c);
+ upd25c();
+
+ wireDnd('p25-dnd', [
+ { id:'a1', cat:'school' },{ id:'a2', cat:'school' },{ id:'a3', cat:'med' },
+ { id:'a4', cat:'med' },{ id:'a5', cat:'ind' },{ id:'a6', cat:'ind' }
+ ]);
+ wireQuiz('p25-tr-host', () => { if(window.addXp) window.addXp(15, 'tr-p25'); });
+ wireReadBtn('p25');
+ renderMath(body);
+}
+
+/* ========================================================== */
+/* §26 — Сложение сил. Равнодействующая (ГЛАВНЫЙ ВИЗУАЛ ГЛАВЫ 3) */
+/* ========================================================== */
+function add_p26(){
+ const body = document.getElementById('p26-body');
+ if(!body) return;
+ let h = '';
+
+ h += makeCard('theory', 'Что такое равнодействующая', '§ 26.1',
+ 'Если на тело действует несколько сил, их совместное действие можно заменить одной силой — '
+ + 'равнодействующей $\\vec R$.
'
+ + 'Тело ведёт себя так, словно на него действует только $\\vec R$. Например, если $R = 0$ — тело покоится '
+ + 'или движется равномерно (силы уравновешены).');
+
+ h += makeCard('rule', 'Силы на одной прямой', '§ 26.2',
+ 'Сонаправленные силы (в одну сторону): $$R = F_1 + F_2$$ направление — то же.
'
+ + 'Противоположные силы: $$R = |F_1 - F_2|$$ направление — в сторону большей силы.
'
+ + 'Если $F_1 = F_2$ и они противоположны — $R = 0$, тело в равновесии.');
+
+ h += makeCard('example', 'Перетягивание каната', '§ 26.3',
+ 'Команда А тянет канат с силой $F_A = 600$ Н вправо. Команда Б — $F_Б = 500$ Н влево. '
+ + '$R = 600 - 500 = 100$ Н вправо. Канат смещается в сторону команды А.
'
+ + 'Если бы $F_A = F_Б = 600$ Н, было бы равновесие — канат стоял бы на месте.');
+
+ /* IV-1 ГЛАВНЫЙ ВИЗУАЛ: Конструктор сил на теле */
+ h += wgWrap('p26-iv1', 'СИМ', 'Конструктор сил на теле — главный визуал', 'Двигай ползунки 4 сил → видишь, как меняется равнодействующая и поведение тела.',
+ '
'
+ + ''
+ + ''
+ + ''
+ + ''
+ + '
'
+ + ''
+ + '');
+
+ /* IV-2 КАЛЬК */
+ h += wgWrap('p26-iv2', 'КАЛЬК', 'Сложение двух сил на одной прямой', '',
+ '
'
+ + quizQuestion('p26-tr', 0, '$F_1 = 6$ Н, $F_2 = 4$ Н, сонаправлены. R?', ['2 Н','4 Н','10 Н','24 Н'], 2)
+ + quizQuestion('p26-tr', 1, '$F_1 = 10$ Н, $F_2 = 6$ Н, противоположны. Модуль R?', ['4 Н','6 Н','10 Н','16 Н'], 0)
+ + quizQuestion('p26-tr', 2, 'Книга лежит на столе. Действуют $F_т$ и $N$. Чему равна R?', ['$mg$','$2mg$','$0$','$N - F_т$'], 2, 'Тело в покое → силы уравновешены, $R = 0$.')
+ + quizQuestion('p26-tr', 3, 'На брусок действуют $F_{тяги} = 12$ Н → и $F_{тр} = 5$ Н ←. Куда движется?', ['Покоится','Влево','Вправо','Невозможно сказать'], 2, '$R = 12-5 = 7$ Н → — вправо.')
+ + quizQuestion('p26-tr', 4, '$F_1 = F_2 = 8$ Н, противоположны. R?', ['0','8 Н','16 Н','Зависит от массы'], 0)
+ + '
');
+
+ h += readButton('p26');
+ body.innerHTML = h;
+
+ function draw26(){
+ const Ft = +document.getElementById('p26-ft-r').value;
+ const N = +document.getElementById('p26-N-r').value;
+ const Ftt = +document.getElementById('p26-Ft2-r').value;
+ const Ftr = +document.getElementById('p26-Ftr-r').value;
+ document.getElementById('p26-ft').textContent = Ft;
+ document.getElementById('p26-N').textContent = N;
+ document.getElementById('p26-Ft2').textContent = Ftt;
+ document.getElementById('p26-Ftr').textContent = Ftr;
+ const Rx = Ftt - Ftr;
+ const Ry = Ft - N; // положительное Ry — вниз
+ const R = Math.hypot(Rx, Ry);
+
+ const cx = 200, cy = 130;
+ const sc = 3.5; // px/Н
+ let s = '';
+ // Земля
+ s += '';
+ for(let i = 0; i < 14; i++) s += '';
+ // Тело — куб
+ s += '';
+ // Стрелки сил
+ function arrow(x1,y1,x2,y2,col,label){
+ const len = Math.hypot(x2-x1, y2-y1);
+ if(len < 4) return '';
+ const a = Math.atan2(y2-y1, x2-x1);
+ const ah = 8;
+ const ax1 = x2 - ah * Math.cos(a - 0.45);
+ const ay1 = y2 - ah * Math.sin(a - 0.45);
+ const ax2 = x2 - ah * Math.cos(a + 0.45);
+ const ay2 = y2 - ah * Math.sin(a + 0.45);
+ return ''
+ + ''
+ + '' + label + '';
+ }
+ s += arrow(cx, cy, cx, cy + Ft * sc, '#7c3aed', 'F_т=' + Ft); // вниз
+ s += arrow(cx, cy, cx, cy - N * sc, '#475569', 'N=' + N); // вверх
+ s += arrow(cx, cy, cx + Ftt * sc, cy, '#10b981', 'F_тяги=' + Ftt); // вправо
+ s += arrow(cx, cy, cx - Ftr * sc, cy, '#92400e', 'F_тр=' + Ftr); // влево
+ // Равнодействующая
+ if(R > 0.1){
+ s += arrow(cx, cy, cx + Rx * sc, cy + Ry * sc, '#dc2626', 'R=' + R.toFixed(1));
+ }
+ document.getElementById('p26-svg').innerHTML = s;
+
+ // Info
+ let verdict;
+ if(R < 0.1) verdict = 'Силы уравновешены. R = 0 — тело в покое или движется равномерно.';
+ else if(Math.abs(Ry) < 0.1 && Rx > 0) verdict = 'R = ' + Rx + ' Н вправо — тело ускоряется вправо.';
+ else if(Math.abs(Ry) < 0.1 && Rx < 0) verdict = 'R = ' + (-Rx) + ' Н влево — тело ускоряется влево.';
+ else if(Math.abs(Rx) < 0.1 && Ry > 0) verdict = 'R = ' + Ry + ' Н вниз — тело падает / провалится.';
+ else if(Math.abs(Rx) < 0.1 && Ry < 0) verdict = 'R = ' + (-Ry) + ' Н вверх — тело подпрыгнет.';
+ else verdict = 'R ≈ ' + R.toFixed(1) + ' Н — тело ускоряется под углом.';
+ document.getElementById('p26-info').innerHTML = verdict + ' $R_x = F_{тяги} - F_{тр} = ' + Rx + '$, $R_y = F_т - N = ' + Ry + '$';
+ renderMath(document.getElementById('p26-info'));
+ }
+ ['p26-ft-r','p26-N-r','p26-Ft2-r','p26-Ftr-r'].forEach(id => document.getElementById(id).addEventListener('input', draw26));
+ draw26();
+
+ const upd26c = () => {
+ const F1 = +document.getElementById('p26c-F1-r').value;
+ const F2 = +document.getElementById('p26c-F2-r').value;
+ const dir = document.getElementById('p26c-dir').value;
+ document.getElementById('p26c-F1').textContent = F1;
+ document.getElementById('p26c-F2').textContent = F2;
+ let R;
+ if(dir === 'same') R = F1 + F2;
+ else R = Math.abs(F1 - F2);
+ let arrow1 = '→', arrow2 = '→';
+ if(dir === 'opp') arrow2 = '←';
+ let result;
+ if(dir === 'same') result = '$R = F_1 + F_2 = ' + F1 + ' + ' + F2 + ' = $ ' + R + ' Н (→)';
+ else {
+ const dir_arrow = F1 > F2 ? '→' : (F2 > F1 ? '←' : '');
+ result = '$R = |F_1 - F_2| = |' + F1 + ' - ' + F2 + '| = $ ' + R + ' Н ' + (R === 0 ? '(равновесие)' : '(' + dir_arrow + ')');
+ }
+ document.getElementById('p26c-out').innerHTML = result;
+ renderMath(document.getElementById('p26c-out'));
+ };
+ ['p26c-F1-r','p26c-F2-r'].forEach(id => document.getElementById(id).addEventListener('input', upd26c));
+ document.getElementById('p26c-dir').addEventListener('change', upd26c);
+ upd26c();
+
+ wireDnd('p26-dnd', [
+ { id:'a1', cat:'right' },{ id:'a2', cat:'right' },{ id:'a3', cat:'left' },
+ { id:'a4', cat:'left' },{ id:'a5', cat:'zero' },{ id:'a6', cat:'zero' }
+ ]);
+ wireQuiz('p26-tr-host', () => { if(window.addXp) window.addXp(15, 'tr-p26'); });
+ wireReadBtn('p26');
+ renderMath(body);
+}
+
+/* ========================================================== */
+/* §27 — Трение. Сила трения */
+/* ========================================================== */
+function add_p27(){
+ const body = document.getElementById('p27-body');
+ if(!body) return;
+ let h = '';
+
+ h += makeCard('theory', 'Откуда берётся трение', '§ 27.1',
+ 'При движении (или попытке движения) одного тела по поверхности другого возникает сила, '
+ + 'мешающая движению — сила трения $\\vec F_{тр}$. Она направлена против движения.
'
+ + 'Причины: шероховатость поверхностей и притяжение молекул в местах контакта.');
+
+ h += makeCard('rule', 'Виды трения', '§ 27.2',
+ '
'
+ + '
Трение покоя — мешает сдвинуть тело с места. Бывает максимальным, после чего тело начинает скользить.
'
+ + '
Трение скольжения — действует на скользящее тело. $F_{тр} \\approx \\mu N$, где $\\mu$ — коэффициент трения, $N$ — нормальная реакция (≈ вес).
'
+ + '
Трение качения — катит колесо. Намного меньше скольжения. Поэтому колесо — гениальное изобретение.
'
+ + '
'
+ + '$F_{тр}$ не зависит (почти) от площади контакта, но зависит от $N$ и от шероховатости.');
+
+ h += makeCard('example', 'Где трение мешает, а где помогает', '§ 27.3',
+ 'Полезно: идти и ехать (без трения — гололёд!), тормоза, гвозди в дереве, держать карандаш. '
+ + 'Мешает: греет и изнашивает детали машин, замедляет движение. Чтобы уменьшить — смазывают маслом, ставят подшипники.');
+
+ /* IV-1 СИМ: брусок на поверхности с slider массы, μ, тяги */
+ h += wgWrap('p27-iv1', 'СИМ', 'Симулятор трения', 'Меняй массу, материал и силу тяги — посмотри, едет брусок или стоит.',
+ '