diff --git a/backend/tests/math5-page.test.js b/backend/tests/math5-page.test.js
index b166d9e..3500727 100644
--- a/backend/tests/math5-page.test.js
+++ b/backend/tests/math5-page.test.js
@@ -106,6 +106,12 @@ test('ch1: §1 «как решать задачу», §2 «разрядная т
assert.ok(doc.querySelector('#p8-iv2 #p8-xa'), '§8: «найди неизвестное»');
win.goTo('p9'); await wait(80);
assert.ok(doc.querySelector('#p9-fig svg circle'), '§9: прямоугольник из точек');
+ win.goTo('p10'); await wait(80);
+ assert.ok(doc.querySelector('#p10-fig svg rect'), '§10: квадрат из клеток');
+ win.goTo('p11'); await wait(80);
+ assert.ok(doc.querySelector('#p11-fig svg circle'), '§11: точки-группы с остатком');
+ win.goTo('p12'); await wait(80);
+ assert.ok(doc.querySelector('#p12-fig'), '§12: делители-чипсы (НОД)');
win.goTo('final'); await wait(80);
assert.ok(doc.querySelector('#fin-go'), 'финал: арена боссов');
win.bumpProgress('final', 100); await wait(20);
diff --git a/frontend/textbooks/math_5_ch1.html b/frontend/textbooks/math_5_ch1.html
index cf34185..f632a6d 100644
--- a/frontend/textbooks/math_5_ch1.html
+++ b/frontend/textbooks/math_5_ch1.html
@@ -832,6 +832,223 @@ function buildP9(){
})();
}
+/* ===================== § 10. СТЕПЕНЬ ЧИСЛА ===================== */
+function buildP10(){
+ var box=document.getElementById('p10-body'); var h='';
+ h+=makeCard('oral','Где это в жизни','10.0',
+ '
Степень прячется там, где что-то многократно повторяется. Площадь квадратного ковра со стороной $3$ м — это $3^2=9$ м². Объём кубика со стороной $2$ см — $2^3=8$ см³. А если каждый день репост видят вдвое больше людей — рост идёт степенями двойки.
');
+ h+=makeCard('theory','Что такое степень','10.1',
+ '
Степенью числа $a$ с натуральным показателем $n$ называют произведение $n$ одинаковых множителей $a$:
$2\\cdot2=4$, затем $4\\cdot2=8$, затем $8\\cdot2=16$.
'
+ +'
Ответ: $2^4=16$.
'
+ +'');
+ h+=makeCard('theory','А знаешь ли ты?','10.4',
+ '
По легенде, изобретатель шахмат попросил у правителя «всего лишь» зёрнышко за первую клетку, $2$ за вторую, $4$ за третью и так далее — удваивая. На $64$-й клетке вышло $2^{63}$ зёрен — больше, чем во всех амбарах мира! Вот как быстро растут степени двойки.
');
+ h+='
Интерактив 1
Квадрат числа
'
+ +'
Клетки образуют квадрат со стороной $a$. Сколько всего клеток ($a^2$)?
'
+ +'
Вопрос 1 / 5Очки: 0 / 5
'
+ +''
+ +''
+ +'
';
+ h+='
Интерактив 2
Вычисли степень
'
+ +'
Вычисли значение степени.
'
+ +'
Пример 1 / 6Очки: 0 / 6
'
+ +''
+ +''
+ +'
';
+ h+=secNav('p9','p11')+readBtn('p10');
+ box.innerHTML=h; renderMath(box);
+
+ (function(){
+ var i=0,score=0,cur=null;
+ function sqSVG(a){ var u=Math.min(26,Math.floor(150/a)),x0=4,W=x0*2+a*u; var s=''; }
+ function gen(){ cur=_ri(2,9); }
+ function show(){ if(i>=5){ document.getElementById('p10-fig').innerHTML='Готово! '+score+' / 5'; if(score>=4){addXp(15,'p10-iv1');bumpProgress('p10',30);}else if(score>=2){addXp(8,'p10-iv1');bumpProgress('p10',16);} return; }
+ gen(); document.getElementById('p10-i').textContent=i+1;
+ document.getElementById('p10-fig').innerHTML=sqSVG(cur)+'
сторона '+cur+', значит '+cur+'2
';
+ document.getElementById('p10-a').value=''; document.getElementById('p10-fb').style.display='none'; }
+ function go(){ if(i>=5)return; var fb=document.getElementById('p10-fb'), a=parseInt(document.getElementById('p10-a').value,10);
+ if(isNaN(a)){ feedback(fb,false,'Введи число.'); return; }
+ if(a===cur*cur){ score++; feedback(fb,true,'✓ Верно! $'+cur+'^2='+(cur*cur)+'$.'); renderMath(fb); } else { feedback(fb,false,'✗ Нет. $'+cur+'^2='+(cur*cur)+'$.'); renderMath(fb); }
+ document.getElementById('p10-s').textContent=score; i++; setTimeout(show,1200); }
+ document.getElementById('p10-go').addEventListener('click',go);
+ document.getElementById('p10-a').addEventListener('keydown',function(e){ if(e.key==='Enter')go(); });
+ show();
+ })();
+
+ (function(){
+ var i=0,score=0,cur=null;
+ function gen(){ var a=_ri(2,7), n=_pick([2,2,3,3,4]); if(a>=6)n=_pick([2,3]); cur={a:a,n:n,ans:Math.pow(a,n)}; }
+ function show(){ if(i>=6){ document.getElementById('p10-pq').innerHTML='Готово! '+score+' / 6'; if(score>=5){addXp(15,'p10-iv2');bumpProgress('p10',30);}else if(score>=3){addXp(8,'p10-iv2');bumpProgress('p10',16);} return; }
+ gen(); document.getElementById('p10-pi').textContent=i+1;
+ document.getElementById('p10-pq').innerHTML='Вычисли $'+cur.a+'^{'+cur.n+'}$'; renderMath(document.getElementById('p10-pq'));
+ document.getElementById('p10-pa').value=''; document.getElementById('p10-pfb').style.display='none'; }
+ function go(){ if(i>=6)return; var fb=document.getElementById('p10-pfb'), a=parseInt(document.getElementById('p10-pa').value,10);
+ if(isNaN(a)){ feedback(fb,false,'Введи число.'); return; }
+ if(a===cur.ans){ score++; feedback(fb,true,'✓ Верно! Ответ '+cur.ans+'.'); } else feedback(fb,false,'✗ Нет. Правильно: '+cur.ans+'.');
+ document.getElementById('p10-ps').textContent=score; i++; setTimeout(show,1200); }
+ document.getElementById('p10-pgo').addEventListener('click',go);
+ document.getElementById('p10-pa').addEventListener('keydown',function(e){ if(e.key==='Enter')go(); });
+ show();
+ })();
+}
+
+/* ===================== § 11. ДЕЛЕНИЕ С ОСТАТКОМ ===================== */
+function buildP11(){
+ var box=document.getElementById('p11-body'); var h='';
+ h+=makeCard('oral','Где это в жизни','11.0',
+ '
Разделить $25$ конфет на $4$ детей поровну не получится — по $6$ и ещё одна лишняя. Эта «лишняя» — остаток. Деление с остатком повсюду: дни недели, страницы по тетрадям, ученики по командам.
');
+ h+=makeCard('rule','Деление с остатком','11.1',
+ '
Разделить $a$ на $b$ с остатком — значит найти такие числа $q$ и $r$, что
'
+ +'
$a = b\\cdot q + r$, где $0\\le r < b$.
'
+ +'
$q$ — неполное частное, $r$ — остаток. Остаток всегда меньше делителя.
');
+ h+=makeCard('example','Примеры','11.2',
+ '
$47:5=9$ (ост. $2$), ведь $5\\cdot9+2=47$. $30:6=5$ (ост. $0$) — делится нацело.
');
+ h+=makeCard('example','Разбор по шагам','11.3',
+ '
Разделим $47$ на $5$ с остатком.
'
+ +''
+ +'
Ищем наибольшее число «пятёрок» в $47$: $5\\cdot9=45$, а $5\\cdot10=50$ — уже много.
'
+ +'
Значит неполное частное $q=9$.
'
+ +'
Остаток: $47-45=2$. Проверяем: $2<5$. Верно.
'
+ +'
Ответ: $47=5\\cdot9+2$.
'
+ +'');
+ h+=makeCard('theory','А знаешь ли ты?','11.4',
+ '
Часы — это деление с остатком! Если сейчас $10$ часов, то через $5$ часов будет не $15$, а $3$ часа: $15:12=1$ (ост. $3$). Математики называют такой счёт «арифметикой остатков», и на ней держится вся компьютерная защита данных.
');
+ h+='
Интерактив 1
Найди остаток
'
+ +'
Точки раскладывают по $b$ в ряд. Сколько точек останется в неполном ряду?
'
+ +'
Вопрос 1 / 6Очки: 0 / 6
'
+ +''
+ +''
+ +'
';
+ h+='
Интерактив 2
Неполное частное
'
+ +'
Найди неполное частное $q$ (сколько целых раз делитель помещается в делимом).
'
+ +'
Вопрос 1 / 5Очки: 0 / 5
'
+ +''
+ +''
+ +'
';
+ h+=secNav('p10','p12')+readBtn('p11');
+ box.innerHTML=h; renderMath(box);
+
+ (function(){
+ var i=0,score=0,cur=null;
+ function dotsSVG(a,b){ var u=15,x0=6,cols=b,rows=Math.ceil(a/b),W=x0*2+cols*u,H=x0*2+rows*u; var s=''; }
+ function gen(){ var b=_ri(3,7), q=_ri(3,8), r=_ri(1,b-1); cur={a:b*q+r,b:b,r:r}; }
+ function show(){ if(i>=6){ document.getElementById('p11-fig').innerHTML='Готово! '+score+' / 6'; if(score>=5){addXp(15,'p11-iv1');bumpProgress('p11',30);}else if(score>=3){addXp(8,'p11-iv1');bumpProgress('p11',16);} return; }
+ gen(); document.getElementById('p11-i').textContent=i+1;
+ document.getElementById('p11-fig').innerHTML=dotsSVG(cur.a,cur.b)+'
'+cur.a+' точек по '+cur.b+' в ряд
';
+ document.getElementById('p11-a').value=''; document.getElementById('p11-fb').style.display='none'; }
+ function go(){ if(i>=6)return; var fb=document.getElementById('p11-fb'), a=parseInt(document.getElementById('p11-a').value,10);
+ if(isNaN(a)){ feedback(fb,false,'Введи число.'); return; }
+ if(a===cur.r){ score++; feedback(fb,true,'✓ Верно! Остаток '+cur.r+' (красные точки).'); } else feedback(fb,false,'✗ Нет. Остаток '+cur.r+'.');
+ document.getElementById('p11-s').textContent=score; i++; setTimeout(show,1300); }
+ document.getElementById('p11-go').addEventListener('click',go);
+ document.getElementById('p11-a').addEventListener('keydown',function(e){ if(e.key==='Enter')go(); });
+ show();
+ })();
+
+ (function(){
+ var i=0,score=0,cur=null;
+ function gen(){ var b=_ri(3,12), q=_ri(4,15), r=_ri(0,b-1); cur={a:b*q+r,b:b,q:q}; }
+ function show(){ if(i>=5){ document.getElementById('p11-qq').innerHTML='Готово! '+score+' / 5'; if(score>=4){addXp(15,'p11-iv2');bumpProgress('p11',30);}else if(score>=2){addXp(8,'p11-iv2');bumpProgress('p11',16);} return; }
+ gen(); document.getElementById('p11-qi').textContent=i+1;
+ document.getElementById('p11-qq').innerHTML='Раздели $'+cur.a+'$ на $'+cur.b+'$ с остатком. Чему равно неполное частное?'; renderMath(document.getElementById('p11-qq'));
+ document.getElementById('p11-qa').value=''; document.getElementById('p11-qfb').style.display='none'; }
+ function go(){ if(i>=5)return; var fb=document.getElementById('p11-qfb'), a=parseInt(document.getElementById('p11-qa').value,10);
+ if(isNaN(a)){ feedback(fb,false,'Введи число.'); return; }
+ if(a===cur.q){ score++; feedback(fb,true,'✓ Верно! '+cur.a+'='+cur.b+'·'+cur.q+'+'+(cur.a-cur.b*cur.q)+'.'); } else feedback(fb,false,'✗ Нет. Неполное частное '+cur.q+'.');
+ document.getElementById('p11-qs').textContent=score; i++; setTimeout(show,1300); }
+ document.getElementById('p11-qgo').addEventListener('click',go);
+ document.getElementById('p11-qa').addEventListener('keydown',function(e){ if(e.key==='Enter')go(); });
+ show();
+ })();
+}
+
+/* ===================== § 12. ДЕЛИТЕЛИ И КРАТНЫЕ. НОД И НОК ===================== */
+function buildP12(){
+ var box=document.getElementById('p12-body'); var h='';
+ h+=makeCard('oral','Где это в жизни','12.0',
+ '
Чтобы рассадить $24$ ученика за столы поровну, нужны делители числа $24$. Чтобы два светофора, мигающие через $4$ и $6$ секунд, мигнули одновременно, ищут общее кратное. Эти понятия — основа всей работы с дробями.
');
+ h+=makeCard('theory','Делители и кратные','12.1',
+ '
Делитель числа $a$ — число, на которое $a$ делится нацело. Делители $12$: $1,2,3,4,6,12$.
'
+ +'
Кратное числа $a$ — число, которое делится на $a$ нацело. Кратные $4$: $4,8,12,16,\\dots$
');
+ h+=makeCard('rule','НОД и НОК','12.2',
+ '
НОД (наибольший общий делитель) — самое большое число, на которое делятся оба числа.
'
+ +'
НОК (наименьшее общее кратное) — самое маленькое число, которое делится на каждое из них.
НОК: кратные $18$: $18,36,54,\\dots$; $36$ делится на $12$. Значит НОК$=36$.
'
+ +'
Проверка: $6\\cdot36=216=12\\cdot18$. Верно!
'
+ +'');
+ h+=makeCard('theory','А знаешь ли ты?','12.4',
+ '
Быстрый способ найти НОД придумал ещё Евклид $2300$ лет назад: большее число заменяют остатком от деления на меньшее — и так, пока остаток не станет нулём. Это один из древнейших алгоритмов, и он до сих пор работает в компьютерах!
');
+ h+='
Интерактив 1
Найди НОД
'
+ +'
Общие делители подсвечены. Введи наибольший из них (НОД).
'
+ +'
Вопрос 1 / 5Очки: 0 / 5
'
+ +''
+ +''
+ +'
';
+ h+='
Интерактив 2
Найди НОК
'
+ +'
Найди наименьшее общее кратное двух чисел.
'
+ +'
Вопрос 1 / 5Очки: 0 / 5
'
+ +''
+ +''
+ +'
';
+ h+=secNav('p11','p13')+readBtn('p12');
+ box.innerHTML=h; renderMath(box);
+
+ function divisors(n){ var d=[]; for(var k=1;k<=n;k++)if(n%k===0)d.push(k); return d; }
+ function gcd(a,b){ while(b){ var t=b; b=a%b; a=t; } return a; }
+
+ (function(){
+ var i=0,score=0,cur=null;
+ function gen(){ var pairs=[[12,18],[8,12],[16,24],[15,20],[18,24],[14,21],[20,30],[9,12]]; cur=_pick(pairs); cur=cur.slice(); cur.g=gcd(cur[0],cur[1]); }
+ function chips(n,common){ var ds=divisors(n),s='
Делители '+n+': '; ds.forEach(function(d){ var hot=common.indexOf(d)>=0; s+=''+d+''; }); return s+'