diff --git a/frontend/textbooks/physics_8_ch1.html b/frontend/textbooks/physics_8_ch1.html
index 0541b2c..e53818e 100644
--- a/frontend/textbooks/physics_8_ch1.html
+++ b/frontend/textbooks/physics_8_ch1.html
@@ -320,8 +320,23 @@ const SIDEBARS = {
["природ. газ","$q = 4{,}4 \\cdot 10^7$"],
["КПД котла","$\\eta = Q_{пол}/(q m)$"]
]},
- p8:{title:"Шпаргалка § 8",rows:[["В разработке","Phase 1 Wave 4"]]},
- p9:{title:"Шпаргалка § 9",rows:[["В разработке","Phase 1 Wave 4"]]},
+ p8:{title:"Шпаргалка § 8",rows:[
+ ["Плавление","$T = T_{пл} = $ const"],
+ ["Кристаллизация","$T = T_{кр} = T_{пл}$"],
+ ["На графике","горизонт. плато"],
+ ["Энергия идёт на","разрушение / построение решётки"],
+ ["лёд","$T_{пл} = 0$ °C"],
+ ["алюминий","$T_{пл} = 660$ °C"],
+ ["железо","$T_{пл} = 1539$ °C"]
+ ]},
+ p9:{title:"Шпаргалка § 9",rows:[
+ ["Формула","$Q = \\lambda m$"],
+ ["$\\lambda$","удельная теплота плавления, Дж/кг"],
+ ["лёд","$\\lambda = 3{,}34 \\cdot 10^5$"],
+ ["свинец","$\\lambda = 2{,}5 \\cdot 10^4$"],
+ ["железо","$\\lambda = 2{,}7 \\cdot 10^5$"],
+ ["Баланс","$Q_{нагр} + Q_{пл} + Q_{нагр.ж}$"]
+ ]},
p10:{title:"Шпаргалка § 10",rows:[["В разработке","Phase 1 Wave 5"]]},
p11:{title:"Шпаргалка § 11",rows:[["В разработке","Phase 1 Wave 5"]]},
final1:{title:"Шпаргалка ★",rows:[["В разработке","Phase 1 Wave 5"]]}
@@ -335,8 +350,8 @@ const TIPS=[
{sec:'p5',html:"Солнце греет Землю через космический вакуум — теплопроводность и конвекция тут невозможны. Это излучение электромагнитными волнами. Чёрная футболка в жаркий день нагревается сильнее белой."},
{sec:'p6',html:"Чтобы нагреть тело массой $m$ на $\\Delta T$ градусов, нужно $Q = c m \\Delta T$. Здесь $c$ — это «сколько энергии съедает 1 кг этого вещества на 1 градус». У воды $c$ самое большое — поэтому вода долго греется и долго остывает."},
{sec:'p7',html:"При сгорании 1 кг топлива выделяется $q$ Дж энергии. Полное выделение: $Q = q m$. У бензина $q$ в 4,5 раза больше, чем у дров, — поэтому литр бензина греет дольше, чем литр дров."},
- {sec:'p8',html:"Параграф § 8 будет реализован в Phase 1 Wave 4. Используем хелперы из phys.js и optics.js."},
- {sec:'p9',html:"Параграф § 9 будет реализован в Phase 1 Wave 4. Используем хелперы из phys.js и optics.js."},
+ {sec:'p8',html:"Пока лёд плавится, температура смеси «лёд + вода» сидит на 0 °C — даже если плита продолжает греть. На графике $T(t)$ это видно как горизонтальная площадка (плато)."},
+ {sec:'p9',html:"Чтобы расплавить 1 кг льда (без нагрева!), нужно $\\lambda = 334$ кДж. Это столько же, сколько на нагрев той же массы воды от 0 до 80 °C. Поэтому лёд — хороший «холодильник»."},
{sec:'p10',html:"Параграф § 10 будет реализован в Phase 1 Wave 5. Используем хелперы из phys.js и optics.js."},
{sec:'p11',html:"Параграф § 11 будет реализован в Phase 1 Wave 5. Используем хелперы из phys.js и optics.js."},
{sec:'final1',html:"Параграф ★ будет реализован в Phase 1 Wave 5. Используем хелперы из phys.js и optics.js."}
@@ -350,8 +365,8 @@ const BUILDERS = {
p5: ()=>{ build_p5(); },
p6: ()=>{ build_p6(); },
p7: ()=>{ build_p7(); },
- p8: ()=>{ const box=document.getElementById('p8-body'); box.innerHTML = buildStub('p8', 'Плавление и кристаллизация', 'Phase 1 Wave 4') + secNavFor('p8') + readButton('p8'); renderMath(box); wireReadBtn('p8'); },
- p9: ()=>{ const box=document.getElementById('p9-body'); box.innerHTML = buildStub('p9', 'Удельная теплота плавления и кристаллизации', 'Phase 1 Wave 4') + secNavFor('p9') + readButton('p9'); renderMath(box); wireReadBtn('p9'); },
+ p8: ()=>{ build_p8(); },
+ p9: ()=>{ build_p9(); },
p10: ()=>{ const box=document.getElementById('p10-body'); box.innerHTML = buildStub('p10', 'Испарение жидкостей. Факторы, влияющие на скорость испарения', 'Phase 1 Wave 5') + secNavFor('p10') + readButton('p10'); renderMath(box); wireReadBtn('p10'); },
p11: ()=>{ const box=document.getElementById('p11-body'); box.innerHTML = buildStub('p11', 'Кипение жидкостей. Удельная теплота парообразования', 'Phase 1 Wave 5') + secNavFor('p11') + readButton('p11'); renderMath(box); wireReadBtn('p11'); },
final1: ()=>{ const box=document.getElementById('final1-body'); box.innerHTML = buildStub('final1', 'Финал главы', 'Phase 1 Wave 5') + secNavFor('final1') + readButton('final1'); renderMath(box); wireReadBtn('final1'); }
@@ -2509,6 +2524,450 @@ function _initP7_tasks(){
render();
}
+/* ======================================================================
+ PHASE 1 · WAVE 4 — §8, §9
+ ====================================================================== */
+
+/* Таблица температур плавления и λ */
+const MAT_MELT = [
+ {key:'mercury',name:'ртуть', Tm:-39, lam:1.18e4},
+ {key:'ice', name:'лёд', Tm:0, lam:3.34e5},
+ {key:'lead', name:'свинец', Tm:327, lam:2.5e4},
+ {key:'zinc', name:'цинк', Tm:420, lam:1.12e5},
+ {key:'al', name:'алюминий', Tm:660, lam:3.9e5},
+ {key:'cu', name:'медь', Tm:1085, lam:2.1e5},
+ {key:'fe', name:'железо', Tm:1539, lam:2.7e5}
+];
+
+/* ======== §8 — Плавление и кристаллизация ======== */
+function build_p8(){
+ const box = document.getElementById('p8-body');
+ let h = '';
+
+ h += makeCard('theory', 'Плавление', '§ 8.1',
+ '
Плавление — переход вещества из твёрдого состояния в жидкое.
'
+ +'У каждого кристаллического вещества есть своя температура плавления $T_{пл}$ — она одинакова и для плавления, и для обратного процесса — кристаллизации.
'
+ +'Во время плавления температура смеси «твёрдое + жидкое» не меняется , пока всё не расплавится. Подведённая теплота тратится на разрушение кристаллической решётки.
'
+ );
+ h += makeCard('rule', 'График фазового перехода', '§ 8.2',
+ 'Если нагревать твёрдое тело и записывать температуру со временем, получится характерный график с плато :
'
+ +''
+ +'нагрев твёрдого ($T$ растёт); '
+ +'плавление ($T = T_{пл} = $ const, идёт время); '
+ +'нагрев жидкости ($T$ снова растёт). '
+ +' '
+ +'При охлаждении — зеркальный процесс: $T$ падает $\\to$ плато кристаллизации $\\to$ $T$ продолжает падать.
'
+ );
+ h += makeCard('example', 'Примеры', '§ 8.3',
+ ''
+ +'Лёд в стакане воды держит $T = 0$ °C, пока не растает весь. '
+ +'Снег зимой переносит много энергии при таянии — поэтому весной долго холодно. '
+ +'Расплавленный металл (магма, чугун) застывает в кристаллы при остывании. '
+ +'Аморфные тела (стекло, смола) не имеют чёткой $T_{пл}$ — они плавятся плавно. '
+ +' '
+ );
+
+ /* IV1 — главный визуал: график T(t) с плато */
+ let optsT = '';
+ MAT_MELT.forEach(m=>{ optsT += ''+m.name+' ($T_{пл}='+m.Tm+'$ °C) '; });
+ h += ''
+ +''
+ +'
Выбери вещество — увидь характерный «ступенчатый» график. Время плато ∝ массе и удельной теплоте плавления.
'
+ +'
'
+ +'Вещество: '+optsT+' '
+ +'Длительность плато: средняя '
+ +'
'
+ +'
'
+ +'
'
+ +'■ участок 1 — нагрев твёрдого '
+ +'■ участок 2 — плавление ($T = T_{пл}$) '
+ +'■ участок 3 — нагрев жидкости '
+ +'
'
+ +'
';
+
+ /* IV2 — квикфайр «температура смеси лёд+вода» */
+ h += ''
+ +''
+ +'
В стакане плавающий лёд и вода. Какая температура смеси?
'
+ +'
'
+ +'
Следующий
'
+ +'
Раунд: 1 / 6 Правильно: 0
'
+ +'
';
+
+ /* IV3 — DnD веществ по T_пл */
+ h += ''
+ +''
+ +'
От самого «мягкого» (плавится при низкой $T$) до самого тугоплавкого.
'
+ +'
'
+ +'
'
+ +'
'
+ +'
'
+ +'
'
+ +'
'
+ +'
'
+ +'
'
+ +'
Проверить Сброс
'
+ +'
'
+ +'
';
+
+ /* IV4 — MCQ тренажёр */
+ h += ''
+ +''
+ +'
4+ правильных — +15 XP.
'
+ +'
'
+ +'
Вопрос: 1 / 6 Правильно: 0
'
+ +'
';
+
+ box.innerHTML = h + secNavFor('p8') + readButton('p8');
+ renderMath(box);
+ wireReadBtn('p8');
+
+ _initP8_graph();
+ _initP8_quiz();
+ _initP8_dnd();
+ _initP8_mcq();
+}
+
+function _initP8_graph(){
+ const svg = document.getElementById('p8-sim'); if(!svg) return;
+ function draw(){
+ const Tm = +document.getElementById('p8-mat').value;
+ const p = +document.getElementById('p8-p').value;
+ document.getElementById('p8-pv').textContent = ['очень кратк.','краткая','средняя','длинная','очень длин.'][p-1];
+ const W = 460, H = 280, pad = 36;
+ /* Сегменты графика T(t).
+ Подбор: ось T от (Tm - 60) до (Tm + 80), ось t от 0 до 10. */
+ const Tmin = Math.min(Tm - 60, -50);
+ const Tmax = Math.max(Tm + 100, 50);
+ const tStart = Tm - 50;
+ const plateauW = p * 0.8; /* 0.8..4 единиц времени */
+ const segs = [
+ { tStart: 0, tEnd: 2, Tstart: tStart, Tend: Tm, label: 'твёрдое' },
+ { tStart: 2, tEnd: 2+plateauW, Tstart: Tm, Tend: Tm, label: 'плавление' },
+ { tStart: 2+plateauW,tEnd: 10, Tstart: Tm, Tend: Tm + 60, label: 'жидкость' }
+ ];
+ const r = window.PHYS.phaseGraphTT(W, H, pad, segs, 10, Tmin, Tmax);
+ /* Подсветка плато */
+ const x1 = r.toX(2), x2 = r.toX(2+plateauW), yp = r.toY(Tm);
+ let extra = ' ';
+ /* Подпись T_пл */
+ extra += ' ';
+ extra += 'T_пл = '+Tm+' °C ';
+ /* Перекрашиваем сегменты разными цветами */
+ let seg1 = ' ';
+ let seg2 = ' ';
+ let seg3 = ' ';
+ /* собираем: оси из r.svg, нужно вырезать только path и оставить оси/подписи */
+ /* r.svg уже содержит оси и красный path; мы его перерисуем поверх */
+ svg.innerHTML = r.svg + extra + seg1 + seg2 + seg3;
+ }
+ document.getElementById('p8-mat').addEventListener('change', draw);
+ document.getElementById('p8-p').addEventListener('input', draw);
+ draw();
+}
+
+function _initP8_quiz(){
+ const QS = [
+ {sit:'В стакане плавающие кусочки льда + вода. Какая температура смеси?', opts:['-5 °C','0 °C','+5 °C','+10 °C'], ans:1, why:'Лёд и вода в равновесии — это точка плавления, $T = 0$ °C.'},
+ {sit:'Нагреваем железо. Температура 1539 °C, на плите плато. Что происходит?', opts:['Греется как обычно','Плавится','Остывает','Кипит'], ans:1, why:'1539 °C — это $T_{пл}$ железа.'},
+ {sit:'У стекла НЕТ чёткой температуры плавления. Что это значит?', opts:['Оно никогда не плавится','Это аморфное вещество','Оно газ','Оно ядовито'], ans:1, why:'Стекло — аморфное тело, нет дальнего порядка, плавится плавно.'},
+ {sit:'Свинец плавится при 327 °C. При 320 °C он …', opts:['твёрдый','плавится','жидкий','газ'], ans:0, why:'320 < 327, значит ещё твёрдый.'},
+ {sit:'Жидкая ртуть остывает с 0 °C до -50 °C. Где плато на графике?', opts:['нет плато','на -50','на -39','на 0'], ans:2, why:'$T_{пл}$ ртути $= -39$ °C — там плато кристаллизации.'},
+ {sit:'Куда уходит подведённая теплота во время плавления?', opts:['На нагрев','На разрушение связей в кристалле','На испарение','На сжатие'], ans:1, why:'Энергия рвёт кристаллическую решётку, $T$ не меняется.'}
+ ];
+ let i = 0, ok = 0;
+ function render(){
+ const q = QS[i]; const wrap = document.getElementById('p8-quiz'); if(!wrap) return;
+ let html = ''+q.sit+'
';
+ q.opts.forEach((opt,k)=>{ html += ''+String.fromCharCode(65+k)+'. '+opt+' '; });
+ html += '
';
+ wrap.innerHTML = html;
+ document.getElementById('p8-quiz-r').textContent = (i+1);
+ document.getElementById('p8-quiz-ok').textContent = ok;
+ wrap.querySelectorAll('[data-k]').forEach(btn=>{
+ btn.addEventListener('click', ()=>{
+ if(btn.disabled) return; wrap.querySelectorAll('[data-k]').forEach(b=>b.disabled=true);
+ const k = +btn.dataset.k; const fb = document.getElementById('p8-quiz-fb');
+ if(k===q.ans){ ok++; fb.className='feedback ok'; fb.innerHTML='✓ Верно. '+q.why; addXp(3,'p8-quiz'); bumpProgress('p8', 4); }
+ else { fb.className='feedback fail'; fb.innerHTML='✗ Не то. '+q.why; }
+ document.getElementById('p8-quiz-ok').textContent = ok;
+ });
+ });
+ }
+ document.getElementById('p8-quiz-next').addEventListener('click', ()=>{ i=(i+1)%QS.length; render(); });
+ render();
+}
+
+function _initP8_dnd(){
+ /* 5 веществ по возрастанию T_пл: ртуть(-39) → лёд(0) → свинец(327) → алюминий(660) → железо(1539) */
+ const items = [
+ {id:'hg', cat:'r1', html:'ртуть (-39)'},
+ {id:'ic', cat:'r2', html:'лёд (0)'},
+ {id:'pb', cat:'r3', html:'свинец (327)'},
+ {id:'al', cat:'r4', html:'алюминий (660)'},
+ {id:'fe', cat:'r5', html:'железо (1539)'}
+ ];
+ const dnd = setupSorter({ poolId:'p8-dnd-pool', scopeSelector:'#sec-p8', cats:['r1','r2','r3','r4','r5'], items, columnLayout:false });
+ document.getElementById('p8-dnd-check').addEventListener('click', ()=>{
+ const fb = document.getElementById('p8-dnd-fb');
+ let wrong = 0; items.forEach(it=>{ if(dnd.placed[it.id] !== it.cat) wrong++; });
+ if(wrong===0){ fb.className='feedback ok'; fb.innerHTML='✓ Идеально! +15 XP. Чем прочнее связи между атомами, тем выше $T_{пл}$.'; addXp(15,'p8-dnd'); bumpProgress('p8', 20); renderMath(fb); }
+ else { fb.className='feedback fail'; fb.innerHTML='✗ Ошибок: '+wrong+'. У ртути минимум, у железа максимум.'; }
+ });
+ document.getElementById('p8-dnd-reset').addEventListener('click', ()=>{ dnd.reset(); const fb=document.getElementById('p8-dnd-fb'); fb.style.display='none'; });
+}
+
+function _initP8_mcq(){
+ const QS = [
+ {q:'Что происходит во время плавления?', opts:['$T$ растёт','$T$ не меняется','$T$ падает','зависит от вещества'], ans:1, why:'Энергия идёт на разрушение решётки, $T$ постоянна.'},
+ {q:'Какой график соответствует нагреву и плавлению?', opts:['прямая линия','зигзаг','рост, плато, рост','падение, плато, падение'], ans:2, why:'Плато плавления разделяет две прямые роста.'},
+ {q:'Аморфные тела (стекло, смола) …', opts:['не плавятся','имеют резкую $T_{пл}$','плавятся плавно без плато','состоят из жидкости'], ans:2, why:'Нет кристаллической решётки $\\Rightarrow$ нет резкого перехода.'},
+ {q:'Когда лёд тает в воде, температура смеси…', opts:['опускается','растёт','равна 0 °C, пока тает весь лёд','зависит от количества'], ans:2, why:'Это точка плавления льда.'},
+ {q:'Что происходит при кристаллизации?', opts:['тепло поглощается','тепло выделяется','$T$ растёт','$T$ падает резко'], ans:1, why:'Молекулы выстраиваются в решётку и отдают связанную энергию.'},
+ {q:'$T_{пл}$ и $T_{кр}$ одного вещества…', opts:['$T_{пл} > T_{кр}$','$T_{пл} < T_{кр}$','равны','зависит от давления'], ans:2, why:'Это одна и та же температура — точка фазового равновесия.'}
+ ];
+ let i = 0, ok = 0, done = 0, awarded = false;
+ function render(){
+ const q = QS[i]; const wrap = document.getElementById('p8-mcq'); if(!wrap) return;
+ let h = 'Вопрос '+(i+1)+'. '+q.q+'
';
+ q.opts.forEach((opt,k)=>{ h += ''+String.fromCharCode(65+k)+'. '+opt+' '; });
+ h += '
Следующий
';
+ wrap.innerHTML = h;
+ document.getElementById('p8-mcq-i').textContent = (i+1);
+ document.getElementById('p8-mcq-ok').textContent = ok;
+ wrap.querySelectorAll('[data-k]').forEach(btn=>{
+ btn.addEventListener('click', ()=>{
+ if(btn.disabled) return; wrap.querySelectorAll('[data-k]').forEach(b=>b.disabled=true);
+ const k = +btn.dataset.k; const fb = document.getElementById('p8-mcq-fb');
+ if(k===q.ans){ ok++; done++; fb.className='feedback ok'; fb.innerHTML='✓ Верно. '+q.why; addXp(2,'p8-mcq'); bumpProgress('p8', 3); }
+ else { done++; fb.className='feedback fail'; fb.innerHTML='✗ Не то. '+q.why; }
+ document.getElementById('p8-mcq-ok').textContent = ok;
+ renderMath(wrap);
+ if(done >= QS.length && !awarded && ok >= 4){ awarded = true; setTimeout(()=>{ const wf=document.getElementById('p8-mcq-fb'); wf.className='feedback ok'; wf.innerHTML='✓ +15 XP — тренажёр пройден ('+ok+'/'+QS.length+').'; addXp(15,'p8-mcq-bonus'); bumpProgress('p8', 15); }, 600); }
+ });
+ });
+ const nb = document.getElementById('p8-mcq-next'); if(nb) nb.addEventListener('click', ()=>{ i=(i+1)%QS.length; render(); });
+ renderMath(wrap);
+ }
+ render();
+}
+
+/* ======== §9 — Q = λm ======== */
+function build_p9(){
+ const box = document.getElementById('p9-body');
+ let h = '';
+
+ h += makeCard('theory', 'Удельная теплота плавления', '§ 9.1',
+ 'Чтобы расплавить массу $m$ кристаллического вещества при $T = T_{пл}$, нужно подвести количество теплоты:
'
+ +'$$Q = \\lambda\\,m$$
'
+ +'$\\lambda$ (лямбда) — удельная теплота плавления , Дж/кг.
'
+ +'Это «цена входа» в жидкое состояние: сколько энергии нужно потратить, чтобы расплавить 1 кг. При кристаллизации та же $Q$ возвращается в окружающую среду.
'
+ );
+ h += makeCard('rule', 'Таблица $\\lambda$', '§ 9.2',
+ 'Вещество $T_{пл}$, °C $\\lambda$, $\\dfrac{\\text{Дж}}{\\text{кг}}$ '
+ + MAT_MELT.map(m=>''+m.name+' '+m.Tm+' '+m.lam.toExponential(2).replace('+','')+' ').join('')
+ +'
'
+ +'У льда $\\lambda$ велика — поэтому весной снег тает медленно, поглощая много энергии.
'
+ );
+ h += makeCard('example', 'Сложная задача: «лёд → вода → пар»', '§ 9.3',
+ 'Если у нас есть кусок льда при -10 °C и мы хотим довести его до 50 °C, нужно три порции теплоты:
'
+ +''
+ +'$Q_1 = c_{льда} \\cdot m \\cdot (0 - (-10))$ — нагрев льда до 0 °C; '
+ +'$Q_2 = \\lambda \\cdot m$ — плавление льда при 0 °C; '
+ +'$Q_3 = c_{воды} \\cdot m \\cdot (50 - 0)$ — нагрев воды до 50 °C. '
+ +' '
+ +'Всего: $Q = Q_1 + Q_2 + Q_3$.
'
+ );
+
+ /* IV1 — калькулятор Q = λm с визуалом */
+ h += ''
+ +''
+ +'
Выбери вещество и массу — увидь, сколько теплоты нужно для плавления.
'
+ +'
'
+ +'Вещество: '
+ + MAT_MELT.map(m=>''+m.name+' ($\\lambda='+m.lam.toExponential(1).replace('+','')+'$) ').join('')
+ +' '
+ +'$m$, кг: 1.0 '
+ +'
'
+ +'
'
+ +'
'
+ +'$\\lambda$ = 3.34×105 Дж/кг '
+ +'$Q$ = 334 кДж '
+ +'Это столько же, сколько на нагрев 80 кг воды на 1 К. '
+ +'
'
+ +'
';
+
+ /* IV2 — тренажёр «лёд → вода → пар» */
+ h += '';
+
+ /* IV3 — DnD ранжирование λ */
+ h += ''
+ +''
+ +'
От самого «лёгкого в плавке» к самому «энергоёмкому».
'
+ +'
'
+ +'
'
+ +'
'
+ +'
'
+ +'
'
+ +'
'
+ +'
'
+ +'
'
+ +'
Проверить Сброс
'
+ +'
'
+ +'
';
+
+ /* IV4 — расчётные задачи */
+ h += ''
+ +''
+ +'
4+ верных — +15 XP. Допуск ±3 %.
'
+ +'
'
+ +'
Задача: 1 / 6 Правильно: 0
'
+ +'
';
+
+ box.innerHTML = h + secNavFor('p9') + readButton('p9');
+ renderMath(box);
+ wireReadBtn('p9');
+
+ _initP9_calc();
+ _initP9_chain();
+ _initP9_dnd();
+ _initP9_tasks();
+}
+
+function _initP9_calc(){
+ const svg = document.getElementById('p9-sim'); if(!svg) return;
+ function update(){
+ const sel = document.getElementById('p9-mat');
+ const opt = sel.options[sel.selectedIndex];
+ const lam = +sel.value;
+ const m = +document.getElementById('p9-m').value;
+ const name = opt.getAttribute('data-name');
+ const Tm = opt.getAttribute('data-tm');
+ document.getElementById('p9-mv').textContent = m.toFixed(1);
+ document.getElementById('p9-lv').innerHTML = lam.toExponential(2).replace('+','').replace('e','×10')+' ';
+ const Q = lam * m;
+ const QkJ = Q / 1000;
+ document.getElementById('p9-q').textContent = QkJ.toFixed(0)+' кДж';
+ /* эквивалент в "кг воды на 1 K" */
+ const eqkg = Q / 4200;
+ document.getElementById('p9-eq').textContent = eqkg.toFixed(1);
+ /* SVG */
+ let s = '';
+ /* куб льда / металла, превращается в лужицу */
+ s += ' ';
+ s += ''+name+' ';
+ s += 'm = '+m.toFixed(1)+' кг, T = '+Tm+' °C ';
+ /* arrow */
+ s += window.PHYS.drawArrow(140, 70, 220, 70, '#f59e0b', 2.4, 10);
+ s += 'Q = λm ';
+ /* жидкость */
+ s += ' ';
+ s += 'расплав '+name+' ';
+ /* подпись Q */
+ s += 'Q = '+QkJ.toFixed(0)+' кДж ';
+ svg.innerHTML = s;
+ }
+ document.getElementById('p9-mat').addEventListener('change', update);
+ document.getElementById('p9-m').addEventListener('input', update);
+ update();
+}
+
+function _initP9_chain(){
+ function update(){
+ const m = +document.getElementById('p9-ym').value;
+ const T1 = +document.getElementById('p9-y1').value;
+ const T2 = +document.getElementById('p9-y2').value;
+ document.getElementById('p9-ymv').textContent = m.toFixed(1);
+ document.getElementById('p9-y1v').textContent = T1;
+ document.getElementById('p9-y2v').textContent = T2;
+ const cIce = 2100, lam = 3.34e5, cW = 4200;
+ const Q1 = cIce * m * (0 - T1);
+ const Q2 = lam * m;
+ const Q3 = cW * m * (T2 - 0);
+ document.getElementById('p9-q1').textContent = (Q1/1000).toFixed(0);
+ document.getElementById('p9-q2').textContent = (Q2/1000).toFixed(0);
+ document.getElementById('p9-q3').textContent = (Q3/1000).toFixed(0);
+ document.getElementById('p9-qall').textContent = ((Q1+Q2+Q3)/1000).toFixed(0);
+ }
+ ['p9-ym','p9-y1','p9-y2'].forEach(id => document.getElementById(id).addEventListener('input', update));
+ update();
+}
+
+function _initP9_dnd(){
+ /* 5 веществ по возрастанию λ:
+ ртуть(1.18e4) → свинец(2.5e4) → цинк(1.12e5) → железо(2.7e5) → лёд(3.34e5)
+ (алюминий 3.9e5 не используем) */
+ const items = [
+ {id:'hg', cat:'r1', html:'ртуть ($1{,}2\\cdot10^4$)'},
+ {id:'pb', cat:'r2', html:'свинец ($2{,}5\\cdot10^4$)'},
+ {id:'zn', cat:'r3', html:'цинк ($1{,}1\\cdot10^5$)'},
+ {id:'fe', cat:'r4', html:'железо ($2{,}7\\cdot10^5$)'},
+ {id:'ic', cat:'r5', html:'лёд ($3{,}3\\cdot10^5$)'}
+ ];
+ const dnd = setupSorter({ poolId:'p9-dnd-pool', scopeSelector:'#sec-p9', cats:['r1','r2','r3','r4','r5'], items, columnLayout:false });
+ document.getElementById('p9-dnd-check').addEventListener('click', ()=>{
+ const fb = document.getElementById('p9-dnd-fb');
+ let wrong = 0; items.forEach(it=>{ if(dnd.placed[it.id] !== it.cat) wrong++; });
+ if(wrong===0){ fb.className='feedback ok'; fb.innerHTML='✓ Идеально! +15 XP. У льда $\\lambda$ велика — поэтому снег тает медленно.'; addXp(15,'p9-dnd'); bumpProgress('p9', 20); renderMath(fb); }
+ else { fb.className='feedback fail'; fb.innerHTML='✗ Ошибок: '+wrong+'. Подсказка: у льда $\\lambda$ больше всех в этом списке.'; renderMath(fb); }
+ });
+ document.getElementById('p9-dnd-reset').addEventListener('click', ()=>{ dnd.reset(); const fb=document.getElementById('p9-dnd-fb'); fb.style.display='none'; });
+}
+
+function _initP9_tasks(){
+ const TASKS = [
+ {q:'Сколько энергии (в кДж) нужно, чтобы расплавить 0,5 кг льда при 0 °C? ($\\lambda = 3{,}34 \\cdot 10^5$)', ans: 167, tol: 3, why:'$Q = \\lambda m = 3{,}34\\cdot10^5 \\cdot 0{,}5 = 1{,}67\\cdot10^5$ Дж = $167$ кДж.'},
+ {q:'Сколько кг свинца можно расплавить при $T_{пл}$, имея 25 кДж? ($\\lambda = 2{,}5 \\cdot 10^4$)', ans: 1, tol: 0.05, why:'$m = Q/\\lambda = 25\\,000 / 2{,}5\\cdot10^4 = 1$ кг.'},
+ {q:'Лёд массой 2 кг при -10 °C довести до воды при 0 °C. Сколько кДж нужно? ($c_{л}=2100$, $\\lambda=3{,}34\\cdot10^5$)', ans: 710, tol: 14, why:'$Q_1 = 2100 \\cdot 2 \\cdot 10 = 42\\,000$, $Q_2 = 3{,}34\\cdot10^5 \\cdot 2 = 668\\,000$, итого $710\\,000$ Дж $= 710$ кДж.'},
+ {q:'У какого вещества $\\lambda$ выше: у воды (лёд → жидкость) или у железа? Запиши 1 — если у льда, 2 — если у железа.', ans: 1, tol: 0.1, why:'$\\lambda_{льда} = 3{,}3\\cdot10^5$ > $\\lambda_{железа} = 2{,}7\\cdot10^5$.'},
+ {q:'Сколько кДж выделится при кристаллизации 1,5 кг олова? ($\\lambda \\approx 5{,}9 \\cdot 10^4$)', ans: 88.5, tol: 2, why:'$Q = \\lambda m = 5{,}9\\cdot10^4 \\cdot 1{,}5 = 88\\,500$ Дж = $88{,}5$ кДж.'},
+ {q:'Кубик льда 200 г (0 °C) положили в стакан с водой и он расплавился. Сколько кДж теплоты он отнял у воды?', ans: 66.8, tol: 2, why:'$Q = \\lambda m = 3{,}34\\cdot10^5 \\cdot 0{,}2 = 66\\,800$ Дж = $66{,}8$ кДж.'}
+ ];
+ let i = 0, ok = 0, done = 0, awarded = false;
+ function render(){
+ const t = TASKS[i]; const wrap = document.getElementById('p9-task'); if(!wrap) return;
+ wrap.innerHTML =
+ 'Задача '+(i+1)+'. '+t.q+'
'
+ +' '
+ +'Ответ '
+ +'Подсказка '
+ +'Следующая
'
+ +''+t.why+'
'
+ +'
';
+ document.getElementById('p9-task-i').textContent = (i+1);
+ document.getElementById('p9-task-ok').textContent = ok;
+ document.getElementById('p9-task-go').addEventListener('click', ()=>{
+ const v = parseFloat((document.getElementById('p9-task-inp').value || '').replace(',','.'));
+ const fb = document.getElementById('p9-task-fb');
+ if(isNaN(v)){ fb.className='feedback fail'; fb.innerHTML='Введи число.'; return; }
+ done++;
+ if(Math.abs(v - t.ans) < t.tol){ ok++; fb.className='feedback ok'; fb.innerHTML='✓ Верно! '+t.why; addXp(4,'p9-task'); bumpProgress('p9', 6); }
+ else { fb.className='feedback fail'; fb.innerHTML='✗ Не то. Правильный ответ: '+t.ans+'. '+t.why; }
+ document.getElementById('p9-task-ok').textContent = ok;
+ renderMath(wrap);
+ if(done >= TASKS.length && !awarded && ok >= 4){ awarded = true; setTimeout(()=>{ const wf=document.getElementById('p9-task-fb'); wf.className='feedback ok'; wf.innerHTML='✓ +15 XP — расчёты сданы ('+ok+'/'+TASKS.length+').'; addXp(15,'p9-task-bonus'); bumpProgress('p9', 15); }, 600); }
+ });
+ document.getElementById('p9-task-hint').addEventListener('click', ()=>{ document.getElementById('p9-task-hint-txt').classList.toggle('show'); });
+ document.getElementById('p9-task-next').addEventListener('click', ()=>{ i=(i+1)%TASKS.length; render(); });
+ renderMath(wrap);
+ }
+ render();
+}
+
function init(){
loadProgress(); initTheme(); initSidebarToggle(); initSearch();
buildParaSelector(); refreshProgressUI(); loadServerReadState(); goTo(PARAS[0].id);