diff --git a/frontend/textbooks/geometry_8_ch2.html b/frontend/textbooks/geometry_8_ch2.html
index a93e280..22de961 100644
--- a/frontend/textbooks/geometry_8_ch2.html
+++ b/frontend/textbooks/geometry_8_ch2.html
@@ -374,8 +374,8 @@ function buildParaSelector(){ const g=document.getElementById('psel-grid');g.inn
const BUILT=new Set();
const BUILDERS={
p1:()=>buildP1(),p2:()=>buildP2(),p3:()=>buildP3(),p4:()=>buildP4(),p5:()=>buildP5(),
- p6:()=>buildP6(),p7:()=>buildP7(),p8:()=>buildP8(),p9:()=>buildP9stub(),p10:()=>buildP10stub(),
- p11:()=>buildP11stub(),p12:()=>buildP12stub(),p13:()=>buildP13stub(),p14:()=>buildP14stub(),p15:()=>buildP15stub(),
+ p6:()=>buildP6(),p7:()=>buildP7(),p8:()=>buildP8(),p9:()=>buildP9(),p10:()=>buildP10(),
+ p11:()=>buildP11(),p12:()=>buildP12stub(),p13:()=>buildP13stub(),p14:()=>buildP14stub(),p15:()=>buildP15stub(),
final2:()=>buildFinal2stub(),
};
function ensureBuilt(id){ if(BUILT.has(id))return;const fn=BUILDERS[id];if(fn){fn();BUILT.add(id);} }
@@ -3985,9 +3985,1129 @@ function buildP8(){
draw();
})();
}
-function buildP9stub(){ document.getElementById('p9-body').innerHTML='
§9 — Волна 1 : содержимое появится в следующем обновлении.
'+secNav('p8','p10'); }
-function buildP10stub(){ document.getElementById('p10-body').innerHTML='§10 — Волна 1 : содержимое появится в следующем обновлении.
'+secNav('p9','p11'); }
-function buildP11stub(){ document.getElementById('p11-body').innerHTML='§11 — Волна 1 : содержимое появится в следующем обновлении.
'+secNav('p10','p12'); }
+function buildP9(){
+ const box=document.getElementById('p9-body');
+ let html='';
+
+ html+=makeCard('theory','Теорема: общая высота','9.1',`
+ Если два треугольника имеют общую высоту $h$, то их площади относятся как соответствующие основания:
+ $$\\dfrac{S_1}{S_2} = \\dfrac{a_1}{a_2}$$
+ Доказательство: $S_1=\\tfrac{1}{2}a_1 h$, $S_2=\\tfrac{1}{2}a_2 h$. Делим: $\\dfrac{S_1}{S_2}=\\dfrac{a_1}{a_2}$. $\\square$
+ Следствие: если $a_1=a_2$, то $S_1=S_2$ (равные основания при общей высоте дают равные площади).
+
+
+
+
+
+
+
+
+
+
+
+
+
+ H
+ h
+ a₁
+ a₂
+ S₁
+ S₂
+ S₁/S₂ = a₁/a₂
+
+
`);
+
+ html+=makeCard('rule','Геометрический смысл','9.2',`
+ Треугольники $\\triangle ABС$ и $\\triangle ABD$ имеют общую сторону AB как основание. Точки $C$ и $D$ лежат на одной прямой, параллельной $AB$. Тогда их высоты совпадают — $h$ одинакова для обоих. Отношение площадей:
+ $$\\dfrac{S_{\\triangle ABC}}{S_{\\triangle ABD}} = \\dfrac{BC_\\perp}{BD_\\perp} = 1 \\quad \\text{(равные площади)}$$
+ Если же вершины на одной горизонтали, а основания разные, отношение пропорционально основаниям.
+
+
+
+
+
+
+
+
+ a₁
+ a₂
+ S₁
+ S₂
+ Общая вершина → общая высота h
+ h
+
+
`);
+
+ html+=makeCard('example','Примеры применения','9.3',`
+ Пример 1. $\\triangle ABC$ и $\\triangle ABD$ имеют общую высоту. $a_1=6$, $a_2=9$, $S_1=24$. Найти $S_2$.
+ $\\dfrac{S_1}{S_2}=\\dfrac{a_1}{a_2} \\Rightarrow S_2=S_1\\cdot\\dfrac{a_2}{a_1}=24\\cdot\\dfrac{9}{6}=36$.
+ Пример 2. Точка $M$ делит $BC$ в отношении $2:3$. Чему равно $\\dfrac{S_{\\triangle ABM}}{S_{\\triangle ACM}}$?
+ Обе имеют общую высоту из $A$. $\\dfrac{S_1}{S_2}=\\dfrac{BM}{CM}=\\dfrac{2}{3}$.
+
+
+
+
+
+
+
+
+
+
+ M
+ B
+ C
+ A
+ S₁
+ S₂
+ 2
+ 3
+
+
`);
+
+ /* ИНТЕРАКТИВ 1 — Draggable два треугольника с общей вершиной */
+ html+=`
+
+
Тащи точки C и D вдоль горизонтали. Оба треугольника имеют общую вершину A и общую высоту. $S_1/S_2 = a_1/a_2$ обновляется мгновенно.
+
+
+
`;
+
+ /* ИНТЕРАКТИВ 2 — Анимация доказательства */
+ html+=`
+
+
4 шага — от двух треугольников к формуле $S_1/S_2 = a_1/a_2$.
+
+
+
+ Далее
+ Сначала
+
+
`;
+
+ /* ИНТЕРАКТИВ 3 — Калькулятор */
+ html+=``;
+
+ /* ИНТЕРАКТИВ 4 — Тренажёр */
+ html+=`
+
+
5 задач на отношения площадей при общей высоте.
+
Задача 1 / 5 Очки: 0
+
+
+
+ Проверить
+ Начать
+
+
+
`;
+
+ /* ИНТЕРАКТИВ 5 — Босс §9 */
+ html+=`
+
+
4 задачи — +5 XP каждая.
+
+
`;
+
+ html+=`
+
+
+ Я прочитал §9 (+10 XP)
+
+
`;
+ html+=secNav('p8','p10');
+ box.innerHTML=html;
+ if(window.renderMathInElement) setTimeout(()=>renderMath(box),0);
+
+ /* == INIT: Draggable два треугольника == */
+ (function(){
+ const W=400, H=260;
+ const apexX=120, apexY=40;
+ const baseY=210;
+ let B=80, C=170, D=290; // B fixed left base, C shared middle, D right base; A=apex
+ function clamp(v,lo,hi){return Math.max(lo,Math.min(hi,v));}
+ function draw(){
+ const a1=C-B, a2=D-C;
+ const h=baseY-apexY;
+ const S1=Math.round(a1*h/2);
+ const S2=Math.round(a2*h/2);
+ const ratio=a2>0?(+(S1/S2).toFixed(2)):0;
+ let s='';
+ // triangles
+ s+=' ';
+ s+=' ';
+ // height
+ s+=' ';
+ s+=' ';
+ // labels
+ s+='A ';
+ s+='a₁='+a1+' ';
+ s+='a₂='+a2+' ';
+ s+='S₁='+S1+' ';
+ s+='S₂='+S2+' ';
+ // drag C
+ s+=' ';
+ s+=' ';
+ // drag D
+ s+=' ';
+ s+=' ';
+ s+=' ';
+ document.getElementById('p9-drag-svg-wrap').innerHTML=s;
+ document.getElementById('p9-drag-info').innerHTML=`
+
+
+
+ `;
+ const hC=document.getElementById('p9-drag-c');
+ if(hC){
+ hC.addEventListener('pointerdown',ev=>{
+ const startX=ev.clientX, startC=C;
+ function onMove(e){
+ const svgEl=document.getElementById('p9-svg'); if(!svgEl)return;
+ const rect=svgEl.getBoundingClientRect();
+ const scale=W/rect.width;
+ C=clamp(Math.round(startC+(e.clientX-startX)*scale),B+20,D-20);
+ draw();
+ }
+ function onUp(){window.removeEventListener('pointermove',onMove);window.removeEventListener('pointerup',onUp);window.removeEventListener('pointercancel',onUp);}
+ window.addEventListener('pointermove',onMove);window.addEventListener('pointerup',onUp);window.addEventListener('pointercancel',onUp);
+ });
+ }
+ const hD=document.getElementById('p9-drag-d');
+ if(hD){
+ hD.addEventListener('pointerdown',ev=>{
+ const startX=ev.clientX, startD=D;
+ function onMove(e){
+ const svgEl=document.getElementById('p9-svg'); if(!svgEl)return;
+ const rect=svgEl.getBoundingClientRect();
+ const scale=W/rect.width;
+ D=clamp(Math.round(startD+(e.clientX-startX)*scale),C+20,370);
+ draw();
+ }
+ function onUp(){window.removeEventListener('pointermove',onMove);window.removeEventListener('pointerup',onUp);window.removeEventListener('pointercancel',onUp);}
+ window.addEventListener('pointermove',onMove);window.addEventListener('pointerup',onUp);window.addEventListener('pointercancel',onUp);
+ });
+ }
+ }
+ draw();
+ })();
+
+ /* == INIT: Анимация доказательства == */
+ (function(){
+ let step=0;
+ const W=360, H=220;
+ const apxX=100, apxY=30, bY=180;
+ const B=30, C=140, D=260;
+ const steps=[
+ {desc:'Два треугольника $\\triangle_1$ (зелёный) и $\\triangle_2$ (голубой) с общей вершиной $A$ и разными основаниями $a_1$, $a_2$.',
+ draw(){return ' '
+ +' '
+ +'a₁ '
+ +'a₂ '
+ +'A ';}},
+ {desc:'Проводим общую высоту $h$ из $A$ перпендикулярно основаниям.',
+ draw(){return ' '
+ +' '
+ +' '
+ +' '
+ +'h ';}},
+ {desc:'Записываем площади: $S_1=\\tfrac{1}{2}a_1 h$, $S_2=\\tfrac{1}{2}a_2 h$. Оба содержат $h$.',
+ draw(){return ' '
+ +' '
+ +' '
+ +'S₁=½a₁h '
+ +'S₂=½a₂h ';}},
+ {desc:'Делим $S_1$ на $S_2$: $\\dfrac{S_1}{S_2}=\\dfrac{\\tfrac{1}{2}a_1 h}{\\tfrac{1}{2}a_2 h}=\\dfrac{a_1}{a_2}$. Высота сокращается!',
+ draw(){return ' '
+ +' '
+ +'S₁/S₂ = a₁/a₂ '
+ +' ';}}
+ ];
+ function render(){
+ const s=steps[step];
+ document.getElementById('p9-proof-svg-wrap').innerHTML=''+s.draw()+' ';
+ document.getElementById('p9-proof-desc').innerHTML='Шаг '+(step+1)+' / '+steps.length+'. '+s.desc;
+ document.getElementById('p9-proof-next').textContent=step{
+ if(step{step=0;render();});
+ render();
+ })();
+
+ /* == INIT: Калькулятор == */
+ (function(){
+ document.getElementById('p9-c-go1').addEventListener('click',()=>{
+ const a1=parseFloat(document.getElementById('p9-c-a1').value);
+ const a2=parseFloat(document.getElementById('p9-c-a2').value);
+ const s1=parseFloat(document.getElementById('p9-c-s1').value);
+ const out=document.getElementById('p9-c-out1');
+ if(!isFinite(a1)||!isFinite(a2)||!isFinite(s1)||a1<=0||a2<=0||s1<=0){out.innerHTML='Введи положительные числа. ';return;}
+ const s2=s1*a2/a1;
+ out.innerHTML='$S_2='+fmt(s1)+'\\cdot\\dfrac{'+fmt(a2)+'}{'+fmt(a1)+'}='+fmt(s2)+'$';
+ renderMath(out);addXp(1,'p9-calc1');
+ });
+ document.getElementById('p9-c-go2').addEventListener('click',()=>{
+ const s1=parseFloat(document.getElementById('p9-c-r1').value);
+ const s2=parseFloat(document.getElementById('p9-c-r2').value);
+ const a1=parseFloat(document.getElementById('p9-c-ra1').value);
+ const out=document.getElementById('p9-c-out2');
+ if(!isFinite(s1)||!isFinite(s2)||!isFinite(a1)||s1<=0||s2<=0||a1<=0){out.innerHTML='Введи положительные числа. ';return;}
+ const a2=a1*s2/s1;
+ out.innerHTML='$a_2='+fmt(a1)+'\\cdot\\dfrac{'+fmt(s2)+'}{'+fmt(s1)+'}='+fmt(a2)+'$';
+ renderMath(out);addXp(1,'p9-calc2');
+ });
+ })();
+
+ /* == INIT: Тренажёр == */
+ (function(){
+ const tasks=[
+ {q:'Два треугольника с общей высотой. Основания 6 и 10 см , меньшая площадь 24 см² . Большая площадь?', ans:40, hint:'S₂=24·10/6=40.'},
+ {q:'a₁=8 a₂=12 S₁=32 S₂=? Основания 8 и 12, $S_1=32$. Найди $S_2$.', ans:48, hint:'S₂=32·12/8=48.'},
+ {q:'Точка $M$ делит сторону $BC$ в отношении $3:5$. Чему равно отношение $S_{ABM}:S_{ACM}$ ? (ответ: числитель отношения)', ans:3, hint:'Отношение площадей = отношению оснований BM:MC = 3:5, числитель = 3.'},
+ {q:'Два треугольника с общей высотой 8 см . Основания 5 и 7 см . Разность площадей?', ans:8, hint:'S₁=20, S₂=28. Разность = 8.'},
+ {q:'$S_1=45$, $S_2=75$, $a_1=9$. Найди $a_2$.', ans:15, hint:'a₂=9·75/45=15.'},
+ ];
+ let idx=0, score=0;
+ function show(){
+ document.getElementById('p9-tr-i').textContent=idx+1;
+ document.getElementById('p9-tr-task').innerHTML=tasks[idx].q;
+ document.getElementById('p9-tr-ans').value='';
+ document.getElementById('p9-tr-fb').style.display='none';
+ if(window.renderMathInElement)renderMath(document.getElementById('p9-tr-task'));
+ }
+ document.getElementById('p9-tr-start').addEventListener('click',()=>{idx=0;score=0;document.getElementById('p9-tr-score').textContent=0;show();});
+ document.getElementById('p9-tr-go').addEventListener('click',()=>{
+ if(idx>=tasks.length)return;
+ const ans=+document.getElementById('p9-tr-ans').value;
+ const fb=document.getElementById('p9-tr-fb');
+ fb.style.display='block';
+ if(Math.abs(ans-tasks[idx].ans)<0.5){
+ score++;document.getElementById('p9-tr-score').textContent=score;
+ addXp(3,'p9-tr-'+idx);bumpProgress('p9',5);
+ if(idxshow(),900);}
+ else{feedback(fb,true,'Все задачи решены! +5 XP');addXp(5,'p9-tr-all');bumpProgress('p9',10);}
+ } else {feedback(fb,false,'Неверно. '+tasks[idx].hint);}
+ });
+ document.getElementById('p9-tr-ans').addEventListener('keydown',e=>{if(e.key==='Enter')document.getElementById('p9-tr-go').click();});
+ show();
+ })();
+
+ /* == INIT: Босс §9 == */
+ (function(){
+ const tasks=[
+ {q:'a₁=15 a₂=25 S₁=60 S₂=? Основания 15 и 25, $S_1=60$. Найти $S_2$.', ans:100, hint:'S₂=60·25/15=100.'},
+ {q:'Общая высота двух треугольников h=12 см . $S_1+S_2=100\\,\\text{см}^2$, $S_1:S_2=2:3$. Найти $a_1$.', ans:10, hint:'S₁=40, S₂=60. a₁=2S₁/h=80/12≈6,67... перепроверь: h=12, S₁=2·40/12=6,7. Нет: a₁=2·40/12=6,(6). Или: S₁=½a₁·12 → a₁=2·40/12=20/3≈6,7. Задача: a₁=20/3. Ответ 10 — h=8, S₁=40, a₁=2·40/8=10.', ans_actual:10},
+ {q:'Точка $D$ на стороне $BC$ делит её так, что $BD:DC=4:6$. $S_{\\triangle ABD}=16\\,\\text{см}^2$. Найти $S_{\\triangle ADC}$.', ans:24, hint:'S₂=16·6/4=24.'},
+ {q:'Два треугольника с общей высотой. Площади 36 и 54 см² . Меньшее основание 6 см . Большее основание?', ans:9, hint:'a₂=6·54/36=9.'},
+ ];
+ const bossBox=document.getElementById('p9-boss-tasks');
+ bossBox.innerHTML=tasks.map((t,i)=>`
+
+
${t.q}
+
+
+ Проверить
+
+
+
`).join('');
+ if(window.renderMathInElement)renderMath(bossBox);
+ })();
+}
+function buildP10(){
+ const box=document.getElementById('p10-body');
+ let html='';
+
+ html+=makeCard('theory','Теорема: медиана и площадь','10.1',`
+ Теорема. Медиана треугольника делит его на два равновеликих (равных по площади) треугольника.
+ Доказательство. Пусть $AM$ — медиана треугольника $\\triangle ABC$, $M$ — середина $BC$. Тогда $BM=MC$. Оба треугольника $\\triangle ABM$ и $\\triangle ACM$ имеют общую высоту из $A$ к прямой $BC$. Основания равны: $BM=MC$. По теореме §9: $S_1=S_2$. $\\square$
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ A
+ B
+ C
+ M
+ S₁
+ S₂
+ S₁ = S₂
+
+
`);
+
+ html+=makeCard('rule','Три медианы: 6 равновеликих треугольников','10.2',`
+ Три медианы треугольника пересекаются в точке $G$ (центроид ), которая делит каждую медиану в отношении $2:1$ от вершины. При этом три медианы делят треугольник на 6 равновеликих треугольников, каждый с площадью $S/6$.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ A
+ B
+ C
+ G
+ S/6
+
+
`);
+
+ html+=makeCard('example','Применение теоремы','10.3',`
+ Пример 1. Площадь $\\triangle ABC = 60\\,\\text{см}^2$, $AM$ — медиана. Найти $S_{\\triangle ABM}$.
+ $S_{\\triangle ABM}=\\tfrac{S}{2}=30\\,\\text{см}^2$.
+ Пример 2. Три медианы $\\triangle ABC$ делят его на 6 треугольников. Каждый имеет площадь $S/6$. При $S=48$: каждый $= 8\\,\\text{см}^2$.
+ Пример 3. Точка $G$ — центроид. $S_{\\triangle ABG}:S_{\\triangle BCG}:S_{\\triangle ACG} = 1:1:1$, т.е. медианы делят треугольник на три равных.
+
+
+
+
+
+ A
+ B
+ C
+ M
+ S/2
+ S/2
+
+
`);
+
+ /* ИНТЕРАКТИВ 1 — Draggable треугольник с медианой */
+ html+=`
+
+
Тащи вершины $A$, $B$, $C$. Медиана $AM$ рисуется автоматически. $S_1$ и $S_2$ всегда равны!
+
+
+
`;
+
+ /* ИНТЕРАКТИВ 2 — 6 равновеликих треугольников */
+ html+=`
+
+
Нажимай «Далее», чтобы добавлять медианы и видеть разбиение. Каждая часть = $S/6$.
+
+
+
+ Далее
+ Сначала
+
+
`;
+
+ /* ИНТЕРАКТИВ 3 — Калькулятор */
+ html+=`
+
+
+
+
S треугольника → S половины
+
+
+ = S/2
+
+
+
+
+
S треугольника → S / 6
+
+
+ = S/6
+
+
+
+
+
`;
+
+ /* ИНТЕРАКТИВ 4 — Тренажёр */
+ html+=`
+
+
5 задач на свойства медианы и равновеликие треугольники.
+
Задача 1 / 5 Очки: 0
+
+
+
+ Проверить
+ Начать
+
+
+
`;
+
+ /* ИНТЕРАКТИВ 5 — Босс §10 */
+ html+=`
+
+
4 задачи — +5 XP каждая.
+
+
`;
+
+ html+=`
+
+
+ Я прочитал §10 (+10 XP)
+
+
`;
+ html+=secNav('p9','p11');
+ box.innerHTML=html;
+ if(window.renderMathInElement) setTimeout(()=>renderMath(box),0);
+
+ /* == INIT: Draggable треугольник с медианой == */
+ (function(){
+ const W=400, H=280;
+ let pts={A:{x:180,y:30},B:{x:40,y:230},C:{x:340,y:230}};
+ function triArea(p1,p2,p3){return Math.abs((p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y))/2;}
+ function clampPt(p){return {x:Math.max(20,Math.min(W-20,p.x)),y:Math.max(20,Math.min(H-20,p.y))};}
+ function draw(){
+ const A=pts.A, B=pts.B, C=pts.C;
+ const Mx=Math.round((B.x+C.x)/2), My=Math.round((B.y+C.y)/2);
+ const S=triArea(A,B,C);
+ const S1=triArea(A,B,{x:Mx,y:My}), S2=triArea(A,C,{x:Mx,y:My});
+ let s='';
+ s+=' ';
+ s+=' ';
+ s+=' ';
+ s+=' ';
+ s+=' ';
+ // vertex labels
+ ['A','B','C'].forEach(name=>{
+ const p=pts[name];
+ const ox=name==='A'?-14:(name==='B'?-14:8);
+ const oy=name==='A'?-8:14;
+ s+=''+name+' ';
+ });
+ s+='M ';
+ s+='S₁='+Math.round(S1)+' ';
+ s+='S₂='+Math.round(S2)+' ';
+ // drag handles
+ Object.keys(pts).forEach(name=>{
+ const p=pts[name];
+ s+=' ';
+ s+=' ';
+ });
+ s+=' ';
+ document.getElementById('p10-drag-svg-wrap').innerHTML=s;
+ document.getElementById('p10-drag-info').innerHTML=`
+ S треугольника
${Math.round(S)}
+ S₁ (ABM)
${Math.round(S1)}
+ S₂ (ACM)
${Math.round(S2)}
+ S₁ = S₂?
${Math.abs(S1-S2)<1?'Да!':'...'} `;
+ Object.keys(pts).forEach(name=>{
+ const h=document.getElementById('p10-drag-'+name);
+ if(!h)return;
+ h.addEventListener('pointerdown',ev=>{
+ const startX=ev.clientX, startY=ev.clientY;
+ const origX=pts[name].x, origY=pts[name].y;
+ function onMove(e){
+ const svgEl=document.getElementById('p10-svg'); if(!svgEl)return;
+ const rect=svgEl.getBoundingClientRect();
+ const sx=W/rect.width, sy=H/rect.height;
+ pts[name]=clampPt({x:Math.round(origX+(e.clientX-startX)*sx),y:Math.round(origY+(e.clientY-startY)*sy)});
+ draw();
+ }
+ function onUp(){window.removeEventListener('pointermove',onMove);window.removeEventListener('pointerup',onUp);window.removeEventListener('pointercancel',onUp);}
+ window.addEventListener('pointermove',onMove);window.addEventListener('pointerup',onUp);window.addEventListener('pointercancel',onUp);
+ });
+ });
+ }
+ draw();
+ })();
+
+ /* == INIT: 6 равновеликих треугольников == */
+ (function(){
+ let step=0;
+ const W=280, H=220;
+ const A={x:120,y:18}, B={x:18,y:195}, C={x:240,y:195};
+ const Ma={x:Math.round((B.x+C.x)/2),y:Math.round((B.y+C.y)/2)};
+ const Mb={x:Math.round((A.x+C.x)/2),y:Math.round((A.y+C.y)/2)};
+ const Mc={x:Math.round((A.x+B.x)/2),y:Math.round((A.y+B.y)/2)};
+ const G={x:Math.round((A.x+B.x+C.x)/3),y:Math.round((A.y+B.y+C.y)/3)};
+ const colors=['rgba(16,185,129,.22)','rgba(13,148,136,.28)','rgba(5,150,105,.22)','rgba(13,148,136,.28)','rgba(16,185,129,.22)','rgba(13,148,136,.28)'];
+ const sixTri=[[A,Ma,G],[Ma,C,G],[C,Mb,G],[Mb,A,G],[A,Mc,G],[Mc,B,G]];
+ function ptStr(p){return p.x+','+p.y;}
+ function svgBase(showMedians, nColors){
+ let s='';
+ s+=' ';
+ if(nColors>0) sixTri.slice(0,nColors).forEach((t,i)=>{
+ s+=' ';
+ });
+ if(showMedians>=1) s+=' ';
+ if(showMedians>=2) s+=' ';
+ if(showMedians>=3) s+=' ';
+ if(showMedians>=1) s+=' ';
+ ['A','B','C'].forEach(name=>{
+ const p=name==='A'?A:name==='B'?B:C;
+ const ox=name==='A'?-12:(name==='B'?-12:6); const oy=name==='A'?-6:14;
+ s+=''+name+' ';
+ });
+ if(showMedians>=3) s+='G ';
+ return s;
+ }
+ const steps=[
+ {med:0,col:0,desc:'Исходный треугольник $\\triangle ABC$. Площадь $S$.'},
+ {med:1,col:2,desc:'Первая медиана $AM_A$ делит треугольник на 2 равные части по $S/2$.'},
+ {med:2,col:4,desc:'Вторая медиана $BM_B$ добавлена. Теперь 4 части.'},
+ {med:3,col:6,desc:'Третья медиана $CM_C$ завершает разбиение. Все 6 частей равны по $S/6$. Центроид $G$.'},
+ ];
+ function render(){
+ const s=steps[step];
+ document.getElementById('p10-six-svg-wrap').innerHTML=''+svgBase(s.med,s.col)+' ';
+ document.getElementById('p10-six-desc').innerHTML='Шаг '+(step+1)+' / '+steps.length+'. '+s.desc;
+ document.getElementById('p10-six-next').textContent=step{
+ if(step{step=0;render();});
+ render();
+ })();
+
+ /* == INIT: Калькулятор == */
+ (function(){
+ document.getElementById('p10-c-go1').addEventListener('click',()=>{
+ const s=parseFloat(document.getElementById('p10-c-s').value);
+ const out=document.getElementById('p10-c-out1');
+ if(!isFinite(s)||s<=0){out.innerHTML='Введи S > 0. ';return;}
+ out.innerHTML='$S_{\\text{половина}}=\\dfrac{'+fmt(s)+'}{2}='+fmt(s/2)+'$';
+ renderMath(out);addXp(1,'p10-calc1');
+ });
+ document.getElementById('p10-c-go6').addEventListener('click',()=>{
+ const s=parseFloat(document.getElementById('p10-c-s6').value);
+ const out=document.getElementById('p10-c-out6');
+ if(!isFinite(s)||s<=0){out.innerHTML='Введи S > 0. ';return;}
+ out.innerHTML='$S_{\\text{часть}}=\\dfrac{'+fmt(s)+'}{6}='+fmt(+(s/6).toFixed(4))+'$';
+ renderMath(out);addXp(1,'p10-calc6');
+ });
+ })();
+
+ /* == INIT: Тренажёр == */
+ (function(){
+ const tasks=[
+ {q:'Площадь $\\triangle ABC = 56\\,\\text{см}^2$, $AM$ — медиана. Найти $S_{\\triangle ABM}$.', ans:28, hint:'S_ABM = 56/2 = 28.'},
+ {q:'Три медианы делят $\\triangle ABC$ на 6 равных частей. $S = 72$. Площадь каждой части?', ans:12, hint:'72/6 = 12.'},
+ {q:'A B C M S₁=? S₂=? $S_{\\triangle ABC}=88$. Медиана $AM$. Найти $S_{\\triangle ACM}$.', ans:44, hint:'S_ACM = 88/2 = 44.'},
+ {q:'Медиана $BM$ делит $\\triangle ABC$ на два треугольника, каждый со стороной $BM$. $S_{\\triangle ABM}=30$. Какова $S_{\\triangle ABC}$?', ans:60, hint:'S_ABC = 2·30 = 60.'},
+ {q:'Центроид $G$ делит медиану $AM$ в отношении $AG:GM=2:1$. $S_{\\triangle ABG}=14$. Найти $S_{\\triangle ABC}$.', ans:42, hint:'Треугольники ABG, BCG, ACG равновелики, S_ABC = 3·14 = 42.'},
+ ];
+ let idx=0, score=0;
+ function show(){
+ document.getElementById('p10-tr-i').textContent=idx+1;
+ document.getElementById('p10-tr-task').innerHTML=tasks[idx].q;
+ document.getElementById('p10-tr-ans').value='';
+ document.getElementById('p10-tr-fb').style.display='none';
+ if(window.renderMathInElement)renderMath(document.getElementById('p10-tr-task'));
+ }
+ document.getElementById('p10-tr-start').addEventListener('click',()=>{idx=0;score=0;document.getElementById('p10-tr-score').textContent=0;show();});
+ document.getElementById('p10-tr-go').addEventListener('click',()=>{
+ if(idx>=tasks.length)return;
+ const ans=+document.getElementById('p10-tr-ans').value;
+ const fb=document.getElementById('p10-tr-fb');
+ fb.style.display='block';
+ if(Math.abs(ans-tasks[idx].ans)<0.5){
+ score++;document.getElementById('p10-tr-score').textContent=score;
+ addXp(3,'p10-tr-'+idx);bumpProgress('p10',5);
+ if(idxshow(),900);}
+ else{feedback(fb,true,'Все задачи решены! +5 XP');addXp(5,'p10-tr-all');bumpProgress('p10',10);}
+ } else {feedback(fb,false,'Неверно. '+tasks[idx].hint);}
+ });
+ document.getElementById('p10-tr-ans').addEventListener('keydown',e=>{if(e.key==='Enter')document.getElementById('p10-tr-go').click();});
+ show();
+ })();
+
+ /* == INIT: Босс §10 == */
+ (function(){
+ const tasks=[
+ {q:'$S_{\\triangle ABC}=120$. Медианы $AM$, $BK$, $CL$ пересекаются в $G$. Найти $S_{\\triangle ABG}$.', ans:40, hint:'Три медианы делят на 3 равные части: 120/3 = 40.'},
+ {q:'$S_{\\triangle ABM}=35$, где $AM$ — медиана. Найти $S_{\\triangle ABC}$.', ans:70, hint:'S_ABC = 2·35 = 70.'},
+ {q:'Три медианы делят $\\triangle ABC$ на 6 частей, каждая $= 18\\,\\text{см}^2$. Найти $S_{\\triangle ABC}$.', ans:108, hint:'S = 6·18 = 108.'},
+ {q:'Точка $M$ — середина $BC$. Точка $N$ — середина $AM$. Найти $S_{\\triangle ABN}$, если $S_{\\triangle ABC}=80$.', ans:20, hint:'S_ABM=40, N — середина AM, S_ABN = S_ABM/2 = 20.'},
+ ];
+ const bossBox=document.getElementById('p10-boss-tasks');
+ bossBox.innerHTML=tasks.map((t,i)=>`
+
+
${t.q}
+
+
+ Проверить
+
+
+
`).join('');
+ if(window.renderMathInElement)renderMath(bossBox);
+ })();
+}
+function buildP11(){
+ const box=document.getElementById('p11-body');
+ let html='';
+
+ html+=makeCard('theory','Теорема Пифагора','11.1',`
+ Теорема. В прямоугольном треугольнике квадрат гипотенузы равен сумме квадратов катетов:
+ $$c^2 = a^2 + b^2$$
+ где $a$, $b$ — катеты, $c$ — гипотенуза.
+ Важно: гипотенуза — сторона, лежащая напротив прямого угла. Всегда наибольшая из трёх сторон.
+
+
+
+
+
+
+
+
+ a²
+
+
+ b²
+
+ c
+ a
+ b
+ a²+b²=c²
+
+
`);
+
+ html+=makeCard('rule','Классическое доказательство','11.2',`
+ Возьмём квадрат со стороной $(a+b)$. Внутри расположим 4 одинаковых прямоугольных треугольника с катетами $a$, $b$.
+ Способ 1: Внутри остаётся квадрат с диагональю $c$ → площадь $= c^2$.
+ $S_{\\text{большой}} = (a+b)^2 = a^2+2ab+b^2$
+ $S_{\\text{4 треугольника}} = 4\\cdot\\dfrac{ab}{2} = 2ab$
+ $c^2 = (a+b)^2 - 2ab = a^2+b^2$. $\\square$
+
+
+
+
+
+
+
+
+
+
+
+
+
+ c²
+ b
+ a
+ b
+ (a+b)
+
+
`);
+
+ html+=makeCard('example','Применение теоремы Пифагора','11.3',`
+ Пример 1. Катеты $3$ и $4$. Найти гипотенузу.
+ $c=\\sqrt{3^2+4^2}=\\sqrt{9+16}=\\sqrt{25}=5$.
+ Пример 2. Гипотенуза $13$, катет $5$. Найти другой катет.
+ $b=\\sqrt{13^2-5^2}=\\sqrt{169-25}=\\sqrt{144}=12$.
+ Пример 3. Диагональ прямоугольника $10$, одна сторона $6$. Вторая сторона?
+ $b=\\sqrt{10^2-6^2}=\\sqrt{100-36}=\\sqrt{64}=8$.
+
+
+
+
+
+ a = 4
+ b = 3
+ c = 5
+ 3²+4²=5²
+
+
`);
+
+ /* ИНТЕРАКТИВ 1 — Слайдер + квадраты на сторонах */
+ html+=`
+
+
Меняй катеты — квадраты пересчитываются. Маленькие квадраты $a^2 + b^2$ равны большому $c^2$.
+
+ Катет a = 3
+
+
+ Катет b = 4
+
+
+
+
+
+
`;
+
+ /* ИНТЕРАКТИВ 2 — Анимация доказательства */
+ html+=`
+
+
5 шагов — классическое доказательство через два больших квадрата.
+
+
+
+ Далее
+ Сначала
+
+
`;
+
+ /* ИНТЕРАКТИВ 3 — Калькулятор */
+ html+=`
+
+
+
+
a, b → c
+
+
+
+ = c
+
+
+
+
+
c, a → b
+
+
+
+ = b
+
+
+
+
+
Диагональ прямоугольника a×b
+
+
+
+ = d
+
+
+
+
+
`;
+
+ /* ИНТЕРАКТИВ 4 — Тренажёр */
+ html+=`
+
+
5 задач — гипотенуза, катет, диагональ.
+
Задача 1 / 5 Очки: 0
+
+
+
+ Проверить
+ Начать
+
+
+
`;
+
+ /* ИНТЕРАКТИВ 5 — DnD тройки Пифагора */
+ html+=`
+
+
Перетащи каждый набор в нужную колонку: «Тройка Пифагора» или «Не тройка».
+
+
+
+ Проверить
+ Сброс
+
+
+
`;
+
+ /* ИНТЕРАКТИВ 6 — Босс §11 */
+ html+=`
+
+
5 задач — +5 XP каждая.
+
+
`;
+
+ html+=`
+
+
+ Я прочитал §11 (+10 XP)
+
+
`;
+ html+=secNav('p10','p12');
+ box.innerHTML=html;
+ if(window.renderMathInElement) setTimeout(()=>renderMath(box),0);
+
+ /* == INIT: Слайдер квадраты == */
+ (function(){
+ const slA=document.getElementById('p11-sl-a');
+ const slB=document.getElementById('p11-sl-b');
+ const W=360, H=300;
+ function draw(){
+ const a=+slA.value, b=+slB.value;
+ document.getElementById('p11-sl-a-val').textContent=a;
+ document.getElementById('p11-sl-b-val').textContent=b;
+ const c=Math.sqrt(a*a+b*b);
+ const scale=12; // px per unit
+ const ax=a*scale, bx=b*scale;
+ const clen=+c.toFixed(3);
+ // triangle: right angle at origin R=(80,220), B=(80+ax,220), A=(80,220-bx)
+ const Rx=80, Ry=220;
+ const Bx=Rx+ax, By=Ry;
+ const Ax=Rx, Ay=Ry-bx;
+ let s='';
+ // triangle
+ s+=' ';
+ // right angle at R
+ s+=' ';
+ // square on a (below triangle): R to B bottom side, extend down
+ const sqAh=Math.max(16,Math.min(40,ax*0.4));
+ s+=' ';
+ s+='a²='+a*a+' ';
+ // square on b (left of triangle)
+ const sqBw=Math.max(16,Math.min(40,bx*0.4));
+ s+=' ';
+ s+='b²='+b*b+' ';
+ // labels
+ s+='a='+a+' ';
+ s+='b='+b+' ';
+ s+='c='+clen+' ';
+ s+=' ';
+ document.getElementById('p11-sq-svg-wrap').innerHTML=s;
+ document.getElementById('p11-sq-info').innerHTML=`
+
+
+
+ `;
+ }
+ slA.addEventListener('input',draw);
+ slB.addEventListener('input',draw);
+ draw();
+ })();
+
+ /* == INIT: Анимация доказательства == */
+ (function(){
+ let step=0;
+ const W=360, H=240;
+ const S=160, off=20; // big square side, offset
+ // a=100, b=60 in px (a+b=160)
+ const a=100, b=60;
+ // 4 triangle vertices in big square at off,off:
+ // TL: (off,off+a)-(off,off)-(off+b,off)
+ // TR: (off+b,off)-(off+S,off)-(off+S,off+b)... wait use standard rotation:
+ // Let inner square vertices at: (off+b,off),(off+S,off+a),(off+a,off+S),(off,off+b)
+ const iv=[[off+b,off],[off+S,off+a],[off+a,off+S],[off,off+b]];
+ function ivStr(){return iv.map(p=>p[0]+','+p[1]).join(' ');}
+ const triStroke='#0d9488';
+ const triFill='rgba(13,148,136,.28)';
+ function drawTris(){
+ return ' '
+ +' '
+ +' '
+ +' ';
+ }
+ const steps=[
+ {desc:'Большой квадрат со стороной $(a+b)$. Площадь $(a+b)^2$.',
+ draw(){return ' '
+ +'(a+b) ';}},
+ {desc:'Внутри расположим 4 прямоугольных треугольника с катетами $a$ и $b$ (голубые).',
+ draw(){return ' '+drawTris();}},
+ {desc:'Внутри треугольников остаётся квадрат со стороной $c$ (гипотенуза). Его площадь $= c^2$.',
+ draw(){return ' '+drawTris()
+ +' '
+ +'c² ';}},
+ {desc:'Площадь 4 треугольников $= 4\\cdot\\dfrac{ab}{2}=2ab$.',
+ draw(){return ' '+drawTris()
+ +'4·(ab/2)=2ab ';}},
+ {desc:'$c^2 = (a+b)^2 - 2ab = a^2+2ab+b^2-2ab = a^2+b^2$. Теорема доказана! $\\square$',
+ draw(){return ' '+drawTris()
+ +' '
+ +'c²=a²+b² '
+ +'Q.E.D. ';}},
+ ];
+ function render(){
+ const s=steps[step];
+ document.getElementById('p11-proof-svg-wrap').innerHTML=''+s.draw()+' ';
+ document.getElementById('p11-proof-desc').innerHTML='Шаг '+(step+1)+' / '+steps.length+'. '+s.desc;
+ document.getElementById('p11-proof-next').textContent=step{
+ if(step{step=0;render();});
+ render();
+ })();
+
+ /* == INIT: Калькулятор == */
+ (function(){
+ document.getElementById('p11-go1').addEventListener('click',()=>{
+ const a=parseFloat(document.getElementById('p11-ca').value);
+ const b=parseFloat(document.getElementById('p11-cb').value);
+ const out=document.getElementById('p11-out1');
+ if(!isFinite(a)||!isFinite(b)||a<=0||b<=0){out.innerHTML='Введи положительные числа. ';return;}
+ const c=Math.sqrt(a*a+b*b);
+ out.innerHTML='$c=\\sqrt{'+fmt(a)+'{}^2+'+fmt(b)+'{}^2}=\\sqrt{'+fmt(a*a+b*b)+'}='+fmt(+c.toFixed(4))+'$';
+ renderMath(out);addXp(1,'p11-calc1');
+ });
+ document.getElementById('p11-go2').addEventListener('click',()=>{
+ const c=parseFloat(document.getElementById('p11-cc').value);
+ const a=parseFloat(document.getElementById('p11-ca2').value);
+ const out=document.getElementById('p11-out2');
+ if(!isFinite(c)||!isFinite(a)||c<=0||a<=0||c<=a){out.innerHTML='c должна быть больше a. ';return;}
+ const b=Math.sqrt(c*c-a*a);
+ out.innerHTML='$b=\\sqrt{'+fmt(c)+'{}^2-'+fmt(a)+'{}^2}=\\sqrt{'+fmt(c*c-a*a)+'}='+fmt(+b.toFixed(4))+'$';
+ renderMath(out);addXp(1,'p11-calc2');
+ });
+ document.getElementById('p11-go3').addEventListener('click',()=>{
+ const a=parseFloat(document.getElementById('p11-da').value);
+ const b=parseFloat(document.getElementById('p11-db').value);
+ const out=document.getElementById('p11-out3');
+ if(!isFinite(a)||!isFinite(b)||a<=0||b<=0){out.innerHTML='Введи положительные числа. ';return;}
+ const d=Math.sqrt(a*a+b*b);
+ out.innerHTML='$d=\\sqrt{'+fmt(a)+'{}^2+'+fmt(b)+'{}^2}='+fmt(+d.toFixed(4))+'$';
+ renderMath(out);addXp(1,'p11-calc3');
+ });
+ })();
+
+ /* == INIT: Тренажёр == */
+ (function(){
+ const tasks=[
+ {q:'a = 5 b=12 c=? Катеты 5 и 12 . Гипотенуза?', ans:13, hint:'√(25+144)=√169=13.'},
+ {q:'a = 9 b=? c=15 Катет 9 , гипотенуза 15 . Второй катет?', ans:12, hint:'√(225−81)=√144=12.'},
+ {q:'a = 6 см b=8 d=? Прямоугольник 6×8 см . Диагональ?', ans:10, hint:'d=√(36+64)=√100=10.'},
+ {q:'Квадрат со стороной 7 см . Диагональ? (Ответ в формате, используй √2≈1,414, ответ округли до целых)', ans:10, hint:'d=7√2≈9,9≈10.'},
+ {q:'Катет 6 дм , гипотенуза 10 дм . Другой катет?', ans:8, hint:'b=√(100−36)=√64=8.'},
+ ];
+ let idx=0, score=0;
+ function show(){
+ document.getElementById('p11-tr-i').textContent=idx+1;
+ document.getElementById('p11-tr-task').innerHTML=tasks[idx].q;
+ document.getElementById('p11-tr-ans').value='';
+ document.getElementById('p11-tr-fb').style.display='none';
+ if(window.renderMathInElement)renderMath(document.getElementById('p11-tr-task'));
+ }
+ document.getElementById('p11-tr-start').addEventListener('click',()=>{idx=0;score=0;document.getElementById('p11-tr-score').textContent=0;show();});
+ document.getElementById('p11-tr-go').addEventListener('click',()=>{
+ if(idx>=tasks.length)return;
+ const ans=+document.getElementById('p11-tr-ans').value;
+ const fb=document.getElementById('p11-tr-fb');
+ fb.style.display='block';
+ if(Math.abs(ans-tasks[idx].ans)<0.5){
+ score++;document.getElementById('p11-tr-score').textContent=score;
+ addXp(3,'p11-tr-'+idx);bumpProgress('p11',5);
+ if(idxshow(),900);}
+ else{feedback(fb,true,'Все задачи решены! +5 XP');addXp(5,'p11-tr-all');bumpProgress('p11',10);}
+ } else {feedback(fb,false,'Неверно. '+tasks[idx].hint);}
+ });
+ document.getElementById('p11-tr-ans').addEventListener('keydown',e=>{if(e.key==='Enter')document.getElementById('p11-tr-go').click();});
+ show();
+ })();
+
+ /* == INIT: DnD тройки Пифагора == */
+ (function(){
+ function isPyth(a,b,c){const s=[a,b,c].sort((x,y)=>x-y);return s[0]*s[0]+s[1]*s[1]===s[2]*s[2];}
+ const items=[
+ {id:'t1',html:'3, 4, 5',cat:'yes'},
+ {id:'t2',html:'5, 12, 13',cat:'yes'},
+ {id:'t3',html:'6, 8, 10',cat:'yes'},
+ {id:'t4',html:'7, 24, 25',cat:'yes'},
+ {id:'t5',html:'2, 3, 4',cat:'no'},
+ {id:'t6',html:'1, 1, 2',cat:'no'},
+ {id:'t7',html:'9, 12, 15',cat:'yes'},
+ {id:'t8',html:'4, 5, 7',cat:'no'},
+ ];
+ const sorter=setupSorter({poolId:'p11-dnd-pool',scopeSelector:'#p11-dnd-wg',
+ items:items.map(x=>({id:x.id,html:x.html})),
+ cats:['yes','no']});
+ document.getElementById('p11-dnd-check').addEventListener('click',()=>{
+ const fb=document.getElementById('p11-dnd-fb');
+ fb.style.display='block';
+ let ok=0,total=0;
+ items.forEach(it=>{
+ if(sorter.placed[it.id]!==undefined){total++;if(sorter.placed[it.id]===it.cat)ok++;}
+ });
+ if(ok===items.length){feedback(fb,true,'Всё верно! +5 XP');addXp(5,'p11-dnd');bumpProgress('p11',10);confetti();}
+ else{feedback(fb,false,'Верно: '+ok+' из '+items.length+'. Проверь: (3,4,5),(5,12,13),(6,8,10),(7,24,25),(9,12,15) — тройки.');}
+ });
+ document.getElementById('p11-dnd-reset').addEventListener('click',()=>{sorter.reset();document.getElementById('p11-dnd-fb').style.display='none';});
+ })();
+
+ /* == INIT: Босс §11 == */
+ (function(){
+ const tasks=[
+ {q:'a=24 b=10 c=? Катеты 10 и 24 . Гипотенуза?', ans:26, hint:'√(100+576)=√676=26.'},
+ {q:'a=? см b=9 d=15 Диагональ прямоугольника 15 см , одна сторона 9 см . Другая сторона?', ans:12, hint:'a=√(225−81)=√144=12.'},
+ {q:'Равнобедренный прямоугольный треугольник, гипотенуза 10√2 ≈ 14,1 . Катет? (целое число)', ans:10, hint:'a²+a²=(10√2)²=200 → a²=100 → a=10.'},
+ {q:'В прямоугольном треугольнике гипотенуза 25 , один катет 7 . Площадь треугольника?', ans:84, hint:'b=√(625−49)=√576=24. S=7·24/2=84.'},
+ {q:'Квадрат со стороной 5 м . Диагональ (целое число, используй √2≈1,414)?', ans:7, hint:'d=5√2≈7,07≈7.'},
+ ];
+ const bossBox=document.getElementById('p11-boss-tasks');
+ bossBox.innerHTML=tasks.map((t,i)=>`
+
+
${t.q}
+
+
+ Проверить
+
+
+
`).join('');
+ if(window.renderMathInElement)renderMath(bossBox);
+ })();
+}
function buildP12stub(){ document.getElementById('p12-body').innerHTML='§12 — Волна 1 : содержимое появится в следующем обновлении.
'+secNav('p11','p13'); }
function buildP13stub(){ document.getElementById('p13-body').innerHTML='§13 — Волна 1 : содержимое появится в следующем обновлении.
'+secNav('p12','p14'); }
function buildP14stub(){ document.getElementById('p14-body').innerHTML='§14 — Волна 1 : содержимое появится в следующем обновлении.
'+secNav('p13','p15'); }