diff --git a/frontend/textbooks/physics_10_ch5.html b/frontend/textbooks/physics_10_ch5.html
index c3f9e05..fae6c8d 100644
--- a/frontend/textbooks/physics_10_ch5.html
+++ b/frontend/textbooks/physics_10_ch5.html
@@ -1407,34 +1407,715 @@ function build_p28(){
function build_p29(){
const box = document.getElementById('p29-body');
let html = '';
+
+ /* THEORY 1 — Сила Ампера */
html += makeCard('theory', "Сила Ампера", "§29", `
-
Сила Ампера — этот параграф в разработке (Phase 1+).
-
Здесь появятся: теория, формулы, разобранные примеры и 3–4 интерактива в стиле «алгебры 11» — таблицы, симуляции, ползунки, drag-and-drop и автопроверяемые тренажёры.
-
- Phase 0: создан скелет учебника. Phase 5+: наполнение этого § содержанием по учебнику «Физика 10» (Беларусь, 2019).
-
+
Сила Ампера — сила, действующая на проводник с током, помещённый в магнитное поле.
+
Модуль:
+
$$F_A = B I L \\sin\\alpha$$
+
+
$B$ — индукция магнитного поля (Тл),
+
$I$ — сила тока в проводнике (А),
+
$L$ — длина участка проводника в поле (м),
+
$\\alpha$ — угол между направлением тока и вектором $\\vec{B}$.
+
+
Особые случаи:
+
+
$\\alpha = 90°$ (ток $\\perp \\vec{B}$): $F_{max} = B I L$ — максимум.
+
$\\alpha = 0°$ или $180°$ (ток $\\parallel \\vec{B}$): $F_A = 0$ — сила отсутствует.
+
+
Главная мысль. Магнитное поле действует на ток. Чем сильнее поле, длиннее провод, больше ток и удачнее ориентация (ближе к $90°$), тем больше сила.
`);
+
+ /* THEORY 2 — Правило левой руки */
+ html += makeCard('rule', "Правило левой руки", "§29", `
+
Правило левой руки — приём для определения направления силы Ампера.
+
Расположи левую руку так, чтобы:
+
+
Линии магнитной индукции $\\vec{B}$ входили в ладонь (поле «прокалывало» ладонь).
+
Четыре выпрямленных пальца показывали направление тока $I$.
+
Тогда отогнутый под $90°$ большой палец покажет направление силы Ампера $\\vec{F_A}$.
+
+
Свойство. Сила Ампера $\\vec{F_A}$ всегда перпендикулярна и проводнику с током, и вектору $\\vec{B}$.
+
Важно. Это же правило (с заменой «тока» на «скорость положительного заряда») работает для силы Лоренца (§30). Для отрицательного заряда направление противоположное.
+ `);
+
+ /* THEORY 3 — Применение */
+ html += makeCard('example', "Где работает сила Ампера", "§29", `
+
Электродвигатель. В магнитном поле находится рамка с током. Силы Ампера, действующие на её стороны, создают вращающий момент. Рамка вращается — получается механическое движение из электрического тока. От детских игрушек до электровозов и промышленных приводов — везде это устройство.
+
Электроизмерительные приборы. В гальванометре рамка с током отклоняется в поле постоянного магнита; угол отклонения пропорционален силе тока, и стрелка показывает его на шкале.
+
Громкоговоритель. Переменный ток в катушке, помещённой в поле постоянного магнита, заставляет мембрану колебаться в такт со звуковым сигналом — рождаются звуковые волны.
+
Магнитная левитация. Токи в катушках поездов на магнитной подвеске (маглев) создают поля, которые отталкивают сверхпроводящие или ферромагнитные элементы пути — поезд буквально парит над рельсами.
+
Принцип суперпозиции для $\\vec{B}$. Магнитное поле от нескольких источников равно векторной сумме полей от каждого. Поэтому сложные конфигурации (катушки, рамки, провода) разбиваются на простые и складываются.
+ `);
+
+ /* INTERACTIVE 1 — Правило левой руки (визуализатор) */
+ html += `
+
ИНТЕРАКТИВ 1
Правило левой руки: куда направлена $\\vec{F_A}$?
+
Магнитное поле $\\vec{B}$ направлено в экран (×). Выбери направление тока и параметры — увидишь силу Ампера.
5 числовых задач. Допуск ±5%. Введи число и нажми Enter.
+
Задача 1 / 5Очки: 0 / 5
+
+
+
+
+
+
+
+
`;
+
html += secNav('p28', 'p30');
html += readButton('p29');
+
box.innerHTML = html;
renderMath(box);
+
+ /* IV1 — Визуализатор правила левой руки */
+ (function(){
+ const svg = document.getElementById('p29-iv1-svg');
+ const out = document.getElementById('p29-iv1-out');
+ const bUp = document.getElementById('p29-iv1-up');
+ const bDn = document.getElementById('p29-iv1-dn');
+ const bRt = document.getElementById('p29-iv1-rt');
+ const bLt = document.getElementById('p29-iv1-lt');
+ const IS = document.getElementById('p29-iv1-I');
+ const BS = document.getElementById('p29-iv1-B');
+ const IL = document.getElementById('p29-iv1-IL');
+ const BL = document.getElementById('p29-iv1-BL');
+ const seen = new Set();
+ let _done = false;
+ let dir = 'up';
+
+ function setDir(d){
+ dir = d;
+ [bUp,bDn,bRt,bLt].forEach(b => b.classList.remove('primary'));
+ ({up:bUp,dn:bDn,rt:bRt,lt:bLt}[d]).classList.add('primary');
+ render();
+ }
+
+ function render(){
+ const I = +IS.value, B = +BS.value;
+ IL.textContent = I.toFixed(1);
+ BL.textContent = B.toFixed(2);
+ const W = 480, H = 320;
+ let g = '';
+ g += '';
+ g += '$\\vec{B}$ направлено в экран (×). Правило левой руки'.replace('$\\vec{B}$','B');
+ // Сетка магнитного поля (×)
+ g += PHYS.magneticFieldGrid(50, 50, 380, 220, 8, 5, 'in');
+
+ const cx = 240, cy = 160;
+ // Проводник с током
+ const L = 90; // длина рисунка
+ let x1,y1,x2,y2; // конечные точки тока (стрелка от начала к концу)
+ if(dir === 'up'){ x1=cx; y1=cy+L; x2=cx; y2=cy-L; }
+ else if(dir === 'dn'){ x1=cx; y1=cy-L; x2=cx; y2=cy+L; }
+ else if(dir === 'rt'){ x1=cx-L; y1=cy; x2=cx+L; y2=cy; }
+ else { x1=cx+L; y1=cy; x2=cx-L; y2=cy; }
+ // Сам провод (в нейтральном цвете)
+ g += '';
+ // Стрелка тока
+ g += PHYS.drawArrow(x1, y1, x2, y2, '#dc2626', 3.5, 16);
+ // Метка I
+ const Imx = x2 + (dir==='rt'?14:dir==='lt'?-14:0);
+ const Imy = y2 + (dir==='up'?-12:dir==='dn'?16:0);
+ g += 'I';
+
+ // Направление силы по правилу левой руки (B в экран):
+ // F = I × B. B = -z (в экран). I вверх (+y) → F = y × (-z) = -(y×z) = -x → влево
+ // I вниз (-y) → F вправо. I вправо (+x) → F = x×(-z) = -(x×z) = +y? В экранных координатах y растёт вниз; но физический y вверх. В физической системе F=qv×B; в экранных: вверх — это -y_экр. Будем выводить так:
+ // Take I dir (ix,iy экранные) and B = into page (z-out screen is "к нам", into page = -z_screen).
+ // Use formula: F_screen = I_screen × B_into_screen. Cross with -ẑ: (ix, iy, 0) × (0,0,-1) = (iy*(-1) - 0, 0 - ix*(-1), 0) = (-iy, ix, 0)
+ // For 'up': I=(0,-1) → F=(-(-1), 0)=(1,0) → вправо. But правило левой руки: B в экран, I вверх → F влево.
+ // The discrepancy is sign of B. "В экран" we treated as B = -ẑ_screen. Let's check by physics: B is into page → in standard right-handed coord (x right, y up, z out of page) B = -ẑ. I up = +ŷ. F = IL × B = ŷ × (-ẑ) = -(ŷ×ẑ) = -x̂ → влево. Yes that matches.
+ // In SCREEN coordinates: x_screen=x, y_screen=-y. So I_up means y_screen=-1, y_phys=+1. Convert back: ix_screen=0,iy_screen=-1 → ix_phys=0, iy_phys=+1.
+ // Compute F in phys: ix_phys × B(=-ẑ) per above formula F_phys=(-iy_phys, ix_phys). For ix_phys=0,iy_phys=+1: F_phys=(-1,0) → x_phys=-1 → влево. ✓
+ // To get F_screen we negate y: F_screen=(F_x_phys, -F_y_phys)=(-1,0) → влево. ✓
+ // Generalize: given i_screen=(ix,iy), iy_phys=-iy. F_phys=(-iy_phys, ix_phys)=(iy, ix?). Wait ix_phys=ix. F_phys=(-iy_phys, ix_phys)=(iy, ix). Then F_screen=(F_x_phys, -F_y_phys)=(iy, -ix).
+ // Test: up i_screen=(0,-1)→F_screen=(-1, 0)=влево ✓. down (0,1)→(1,0) вправо ✓. right (1,0)→(0,-1)=вверх ✓. left(-1,0)→(0,1)=вниз ✓.
+ const map = { up:{ix:0,iy:-1, label:'вверх'}, dn:{ix:0,iy:1, label:'вниз'}, rt:{ix:1,iy:0, label:'вправо'}, lt:{ix:-1,iy:0, label:'влево'} };
+ const cur = map[dir];
+ const fx = cur.iy, fy = -cur.ix;
+ const fLabel = (fx===1)?'вправо':(fx===-1)?'влево':(fy===-1)?'вверх':'вниз';
+ // Рисуем силу: начинается из центра провода
+ const fLen = 70;
+ const fEndX = cx + fx * fLen;
+ const fEndY = cy + fy * fLen;
+ g += PHYS.drawArrow(cx, cy, fEndX, fEndY, '#0891b2', 4, 18);
+ g += 'F';
+
+ // Подпись внизу
+ const Fmod = B * I * 1.0; // L=1 м
+ g += 'L = 1 м, $\\alpha = 90°$'.replace('$\\alpha = 90°$','α=90°');
+
+ svg.innerHTML = g;
+ out.innerHTML = 'Ток '+cur.label+', $\\vec{B}$ в экран → сила Ампера направлена '+fLabel+'. $F_A = B \\cdot I \\cdot L = '+B.toFixed(2)+' \\cdot '+I.toFixed(2)+' \\cdot 1 = '+Fmod.toFixed(2)+'$ Н.';
+ renderMath(out);
+
+ seen.add(dir);
+ if(!_done && seen.size >= 4){ _done = true; addXp(10, 'p29-iv1'); bumpProgress('p29', 15); }
+ }
+
+ [bUp,bDn,bRt,bLt].forEach(b => b.addEventListener('click', () => setDir(b.dataset.d)));
+ IS.addEventListener('input', render);
+ BS.addEventListener('input', render);
+ setDir('up');
+ })();
+
+ /* IV2 — Калькулятор */
+ (function(){
+ const out = document.getElementById('p29-iv2-out');
+ const bGo = document.getElementById('p29-iv2-calc');
+ const inB = document.getElementById('p29-iv2-B');
+ const inI = document.getElementById('p29-iv2-I');
+ const inL = document.getElementById('p29-iv2-L');
+ const inA = document.getElementById('p29-iv2-A');
+ let count = 0, _done = false;
+
+ function calc(){
+ const B = +inB.value, I = +inI.value, L = +inL.value, A = +inA.value;
+ if(!isFinite(B)||!isFinite(I)||!isFinite(L)||!isFinite(A)){
+ out.innerHTML = 'Введи все значения.';
+ return;
+ }
+ const rad = A * Math.PI / 180;
+ const F = B * I * L * Math.sin(rad);
+ out.innerHTML = '$F_A = B \\cdot I \\cdot L \\cdot \\sin\\alpha = '+B+' \\cdot '+I+' \\cdot '+L+' \\cdot \\sin '+A+'° = \\mathbf{'+F.toFixed(4)+'}$ Н';
+ renderMath(out);
+ count++;
+ if(!_done && count >= 3){ _done = true; addXp(10, 'p29-iv2'); bumpProgress('p29', 15); }
+ }
+ bGo.addEventListener('click', calc);
+ [inB,inI,inL,inA].forEach(x => x.addEventListener('keydown', e => { if(e.key==='Enter') calc(); }));
+ })();
+
+ /* IV3 — Куда направлена F_A? */
+ (function(){
+ const OPTS = ['Вправо','Влево','Вверх','Вниз'];
+ const Q = [
+ { q:'$\\vec{B}$ в экран (×), ток вверх. Куда направлена $\\vec{F_A}$?', ans:1, why:'По правилу левой руки: B входит в ладонь, 4 пальца — вверх (ток), большой — влево.' },
+ { q:'$\\vec{B}$ из экрана (•), ток вверх. Куда направлена $\\vec{F_A}$?', ans:0, why:'B теперь из ладони, четыре пальца — вверх; большой палец — вправо.' },
+ { q:'$\\vec{B}$ в экран (×), ток вправо. Куда направлена $\\vec{F_A}$?', ans:2, why:'B входит в ладонь, пальцы — вправо; большой палец — вверх.' },
+ { q:'$\\vec{B}$ в экран (×), ток влево. Куда направлена $\\vec{F_A}$?', ans:3, why:'B входит в ладонь, пальцы — влево; большой палец — вниз.' },
+ { q:'$\\vec{B}$ из экрана (•), ток вниз. Куда направлена $\\vec{F_A}$?', ans:1, why:'B из ладони, пальцы — вниз; большой палец — влево.' },
+ { q:'$\\vec{B}$ из экрана (•), ток вправо. Куда направлена $\\vec{F_A}$?', ans:3, why:'B из ладони, пальцы — вправо; большой палец — вниз.' }
+ ];
+ let i = 0, score = 0;
+ const qEl = document.getElementById('p29-iv3-q');
+ const oEl = document.getElementById('p29-iv3-opts');
+ const fb = document.getElementById('p29-iv3-fb');
+ const iEl = document.getElementById('p29-iv3-i');
+ const sEl = document.getElementById('p29-iv3-s');
+
+ function show(){
+ if(i >= Q.length){
+ qEl.innerHTML = 'Готово! Результат: ' + score + ' / ' + Q.length;
+ oEl.innerHTML = '';
+ if(score === Q.length){ addXp(15, 'p29-iv3'); bumpProgress('p29', 25); }
+ else if(score >= 4){ addXp(8, 'p29-iv3'); bumpProgress('p29', 15); }
+ return;
+ }
+ iEl.textContent = (i+1);
+ sEl.textContent = score;
+ qEl.innerHTML = Q[i].q;
+ oEl.innerHTML = OPTS.map((t, k) => '').join('');
+ fb.style.display = 'none';
+ renderMath(qEl);
+ oEl.querySelectorAll('button').forEach(b => {
+ b.addEventListener('click', () => {
+ const v = +b.dataset.v;
+ if(v === Q[i].ans){ score++; feedback(fb, true, '✓ Верно! ' + Q[i].why + ' Дальше ▶'); }
+ else feedback(fb, false, '✗ Верно: ' + OPTS[Q[i].ans] + '. ' + Q[i].why + ' Дальше ▶');
+ sEl.textContent = score;
+ oEl.querySelectorAll('button').forEach(x => x.disabled = true);
+ i++;
+ setTimeout(show, 1800);
+ });
+ });
+ }
+ document.getElementById('p29-iv3-restart').addEventListener('click', () => { i = 0; score = 0; show(); });
+ show();
+ })();
+
+ /* IV4 — Тренажёр числовой */
+ (function(){
+ const Q = [
+ { q:'$B = 0{,}5$ Тл, $I = 2$ А, $L = 0{,}1$ м, $\\alpha = 90°$. Найди $F_A$ (Н).', ans:0.1, tol:0.005, why:'$F_A = 0{,}5 \\cdot 2 \\cdot 0{,}1 \\cdot 1 = 0{,}1$ Н.' },
+ { q:'Те же данные, но $\\alpha = 30°$. Найди $F_A$ (Н).', ans:0.05, tol:0.005, why:'$F_A = 0{,}1 \\cdot \\sin 30° = 0{,}1 \\cdot 0{,}5 = 0{,}05$ Н.' },
+ { q:'При каком угле $\\alpha$ (в °, $0\\le\\alpha\\le 90$) сила Ампера равна нулю?', ans:0, tol:1, why:'$F_A = 0$ при $\\alpha = 0°$ (или $180°$): ток параллелен $\\vec{B}$.' },
+ { q:'$F_A = 0{,}4$ Н, $I = 2$ А, $L = 0{,}2$ м, $\\alpha = 90°$. Найди $B$ (Тл).', ans:1.0, tol:0.05, why:'$B = F/(IL) = 0{,}4/(2\\cdot 0{,}2) = 1$ Тл.' },
+ { q:'Проводник с током «вверх» в поле $\\vec{B}$, направленном в экран. Куда отклонится? Введи: 1 — вправо, 2 — влево, 3 — в экран, 4 — из экрана.', ans:2, tol:0, why:'По правилу левой руки сила направлена влево (ответ 2).' }
+ ];
+ let i = 0, score = 0;
+ const qEl = document.getElementById('p29-iv4-q');
+ const fb = document.getElementById('p29-iv4-fb');
+ const iEl = document.getElementById('p29-iv4-i');
+ const sEl = document.getElementById('p29-iv4-s');
+ const inp = document.getElementById('p29-iv4-inp');
+ const bGo = document.getElementById('p29-iv4-go');
+
+ function show(){
+ if(i >= Q.length){
+ qEl.innerHTML = 'Готово! Результат: ' + score + ' / ' + Q.length;
+ inp.disabled = true; bGo.disabled = true;
+ if(score === Q.length){ addXp(15, 'p29-iv4'); bumpProgress('p29', 25); }
+ else if(score >= 3){ addXp(8, 'p29-iv4'); bumpProgress('p29', 15); }
+ return;
+ }
+ iEl.textContent = (i+1);
+ sEl.textContent = score;
+ qEl.innerHTML = Q[i].q;
+ fb.style.display = 'none';
+ inp.value = ''; inp.disabled = false; bGo.disabled = false; inp.focus();
+ renderMath(qEl);
+ }
+ function check(){
+ if(inp.disabled) return;
+ const v = parseFloat(inp.value.replace(',','.'));
+ if(!isFinite(v)){ feedback(fb, false, 'Введи число.'); return; }
+ const ok = Math.abs(v - Q[i].ans) <= Math.max(Q[i].tol, Math.abs(Q[i].ans)*0.05);
+ if(ok){ score++; feedback(fb, true, '✓ Верно! ' + Q[i].why + ' Дальше ▶'); }
+ else feedback(fb, false, '✗ Верно: ' + Q[i].ans + '. ' + Q[i].why + ' Дальше ▶');
+ sEl.textContent = score;
+ inp.disabled = true; bGo.disabled = true;
+ i++;
+ setTimeout(show, 1900);
+ }
+ bGo.addEventListener('click', check);
+ inp.addEventListener('keydown', e => { if(e.key==='Enter') check(); });
+ document.getElementById('p29-iv4-restart').addEventListener('click', () => { i = 0; score = 0; inp.disabled=false; bGo.disabled=false; show(); });
+ show();
+ })();
+
wireReadBtn('p29');
}
function build_p30(){
const box = document.getElementById('p30-body');
let html = '';
+
+ /* THEORY 1 — Сила Лоренца */
html += makeCard('theory', "Сила Лоренца", "§30", `
-
Сила Лоренца — этот параграф в разработке (Phase 1+).
-
Здесь появятся: теория, формулы, разобранные примеры и 3–4 интерактива в стиле «алгебры 11» — таблицы, симуляции, ползунки, drag-and-drop и автопроверяемые тренажёры.
-
- Phase 0: создан скелет учебника. Phase 5+: наполнение этого § содержанием по учебнику «Физика 10» (Беларусь, 2019).
-
+
Сила Лоренца — сила, действующая на электрический заряд $q$, движущийся со скоростью $\\vec{v}$ в магнитном поле $\\vec{B}$.
+
Модуль:
+
$$F_L = |q|\\, v\\, B\\, \\sin\\alpha$$
+
где $\\alpha$ — угол между $\\vec{v}$ и $\\vec{B}$.
+
Направление:
+
+
Для положительного заряда — по правилу левой руки (ладонь — $\\vec{B}$ входит, 4 пальца — направление $\\vec{v}$, большой палец — $\\vec{F_L}$).
+
Для отрицательного заряда — противоположно.
+
+
Важнейшее свойство. $\\vec{F_L} \\perp \\vec{v}$ всегда, значит работа силы Лоренца равна нулю. Магнитное поле не меняет модуль скорости (и кинетическую энергию) — только направление движения.
`);
+
+ /* THEORY 2 — Движение по окружности */
+ html += makeCard('rule', "Движение заряда по окружности", "§30", `
+
Если заряд $q$ влетает в однородное магнитное поле перпендикулярно $\\vec{B}$ ($\\alpha = 90°$), он движется по окружности.
Удивительный факт. Период $T$ не зависит от скорости $v$! Это используется в циклотронах: частицы ускоряются, но за каждый оборот всё равно проходят за одно и то же время.
+ `);
+
+ /* THEORY 3 — Спираль и применение */
+ html += makeCard('example', "Спираль и применение", "§30", `
+
Если $\\vec{v}$ направлена под произвольным углом к $\\vec{B}$ (не $0°$ и не $90°$), движение — по винтовой линии (спирали):
+
+
Компонента $v_{\\parallel}$ (вдоль $\\vec{B}$) даёт прямолинейное движение.
Масс-спектрометр: ионы одинаковой энергии, но разной массы движутся по окружностям разного радиуса $R \\propto m$ — это позволяет их разделить и измерить массы.
+
МРТ (магнитно-резонансная томография) использует магнитное поле для управления спинами протонов в тканях.
+
Полярное сияние: частицы солнечного ветра захватываются геомагнитным полем и движутся по спиралям вдоль линий поля Земли, возбуждая свечение атмосферы у полюсов.