feat(phys8 ch2): Phase 2.3 — оставшиеся 14 IV-6 (Ch2 завершена)

scrubberWidget() helper в скрипте — генерирует виджет с N
scrubbers + 1 readout + live SVG render.

§13 Проводники/диэлектрики: 2 стержня, движущиеся электроны в меди,
застрявшие в стекле. Анимация через setInterval.

§14 Электростатическая индукция: + палочка + проводник, при
сближении видны индуцированные −/+ заряды на сторонах.

§15 q=ne: сфера тела с радиально размещёнными ±зарядами,
расчёт n = q/e.

§16 Строение атома: ядро + N электронов на orbitals (2-8-8-2 shells).

§18 A=qU: 2 пластины + drag-arrow с подписью работы.

§19 ЭДС: батарея с readout ε = A/q.

§20 I=q/t: провод с анимированными носителями.

§21 Замкнутая цепь: батарея + switch + лампа, кнопка открыть/замкнуть.

§23 R=ρl/S: динамический wire с длиной/толщиной по scrubberу,
R вычисляется для меди.

§24 Последовательное: 2 резистора, общее R=R1+R2, I.

§26 P=UI: светящаяся лампа brightness ∝ P, лучи при P>120 Вт.

§27 A=UIt: time-bar 0-24 ч, A в кВт·ч.

§29 B≈I вокруг провода: концентрические штриховые круги, opacity ∝ |I|.

§31 Электромагнит: соленоид (число катушек по N), железный сердечник,
полевые линии-параболы с интенсивностью по B=NI.
This commit is contained in:
Maxim Dolgolyov
2026-05-30 10:20:49 +03:00
parent 4d53919e9a
commit 0d9226f6d5
2 changed files with 1157 additions and 84 deletions
+650 -84
View File
@@ -1,4 +1,534 @@
<!
function _initP31_iv6(){
const sb = document.getElementById('p31-iv6-sandbox');
if (!sb || !window.P8Helpers) return;
const svg = P8Helpers.svg.create(560, 200);
svg.setAttribute('width','100%'); svg.setAttribute('height','100%'); svg.style.display='block';
sb.appendChild(svg);
const state = {};
function render(){
svg.innerHTML = '';
const N = state.n, I = state.i;
const B = N * I;
/* Solenoid coils */
const coils = Math.min(20, Math.round(N / 50) + 4);
const coilW = 16;
for (let k = 0; k < coils; k++) {
const x = 130 + k * coilW;
svg.appendChild(P8Helpers.svg.el('ellipse', { cx: x, cy: 100, rx: 6, ry: 32, fill: 'none', stroke: '#b45309', 'stroke-width': 2 }));
}
/* Iron core */
svg.appendChild(P8Helpers.svg.el('rect', { x: 120, y: 90, width: coils * coilW + 20, height: 20, fill: '#64748b', stroke: '#0f172a', 'stroke-width': 1 }));
/* Field lines */
const intensity = Math.min(1, B / 2000);
if (intensity > 0.05) {
[40, 70, 100].forEach((dy, k) => {
const op = intensity * (1 - k * 0.25);
if (op < 0.05) return;
svg.appendChild(P8Helpers.svg.el('path', { d: 'M 50 '+(100-dy)+' Q 280 '+(100-dy*1.5)+', 510 '+(100-dy), fill: 'none', stroke: '#7c3aed', 'stroke-width': 1.5, opacity: op }));
svg.appendChild(P8Helpers.svg.el('path', { d: 'M 50 '+(100+dy)+' Q 280 '+(100+dy*1.5)+', 510 '+(100+dy), fill: 'none', stroke: '#7c3aed', 'stroke-width': 1.5, opacity: op }));
});
}
svg.appendChild(P8Helpers.svg.el('text', { x: 280, y: 180, 'font-family':"'JetBrains Mono',monospace", 'font-size':12, 'font-weight':800, fill:'var(--el-mid,#06b6d4)', 'text-anchor':'middle', text: 'B ∝ N·I = '+B+' (отн.)' }));
document.getElementById('p31-iv6-out').textContent = B;
}
state.n = 100;
const nInp = document.getElementById('p31-iv6-n');
const nLab = document.getElementById('p31-iv6-n-val');
nInp.oninput = ev => { state.n = +ev.target.value; nLab.textContent = (state.n).toFixed(0); render(); };
state.i = 1;
const iInp = document.getElementById('p31-iv6-i');
const iLab = document.getElementById('p31-iv6-i-val');
iInp.oninput = ev => { state.i = +ev.target.value; iLab.textContent = (state.i).toFixed(2); render(); };
render();
}
function _initP29_iv6(){
const sb = document.getElementById('p29-iv6-sandbox');
if (!sb || !window.P8Helpers) return;
const svg = P8Helpers.svg.create(560, 200);
svg.setAttribute('width','100%'); svg.setAttribute('height','100%'); svg.style.display='block';
sb.appendChild(svg);
const state = {};
function render(){
svg.innerHTML = '';
const I = state.i;
/* Wire (vertical center) */
svg.appendChild(P8Helpers.svg.el('line', { x1: 280, y1: 20, x2: 280, y2: 180, stroke: '#0f172a', 'stroke-width': 5 }));
/* Current direction */
if (Math.abs(I) > 0.05) {
const dir = I > 0 ? 1 : -1;
svg.appendChild(P8Helpers.svg.el('polygon', { points: '280,'+(dir>0?20:180)+' 274,'+(dir>0?30:170)+' 286,'+(dir>0?30:170), fill: '#dc2626' }));
}
/* Field circles around wire */
const intensity = Math.abs(I) / 10;
[25, 45, 65, 90, 115].forEach((r, k) => {
const opacity = intensity * (1 - k * 0.15);
if (opacity > 0.05) {
svg.appendChild(P8Helpers.svg.el('circle', { cx: 280, cy: 100, r, fill: 'none', stroke: '#7c3aed', 'stroke-width': 1.5, opacity, 'stroke-dasharray': '5 3' }));
}
});
svg.appendChild(P8Helpers.svg.el('text', { x: 280, y: 195, 'font-family':"'JetBrains Mono',monospace", 'font-size':12, 'font-weight':800, fill:'var(--el-mid,#06b6d4)', 'text-anchor':'middle', text: 'I = '+I.toFixed(1)+' А, B ∝ |I|' }));
document.getElementById('p29-iv6-out').textContent = Math.abs(I).toFixed(1);
}
state.i = 3;
const iInp = document.getElementById('p29-iv6-i');
const iLab = document.getElementById('p29-iv6-i-val');
iInp.oninput = ev => { state.i = +ev.target.value; iLab.textContent = (state.i).toFixed(2); render(); };
render();
}
function _initP27_iv6(){
const sb = document.getElementById('p27-iv6-sandbox');
if (!sb || !window.P8Helpers) return;
const svg = P8Helpers.svg.create(560, 200);
svg.setAttribute('width','100%'); svg.setAttribute('height','100%'); svg.style.display='block';
sb.appendChild(svg);
const state = {};
function render(){
svg.innerHTML = '';
const P = state.p, t = state.t;
const A = P * t / 1000; /* kWh */
/* Time bar */
const barW = (t / 24) * 460;
svg.appendChild(P8Helpers.svg.el('rect', { x: 50, y: 80, width: 460, height: 40, fill: '#e5e7eb', stroke: '#0f172a' }));
svg.appendChild(P8Helpers.svg.el('rect', { x: 50, y: 80, width: barW, height: 40, fill: 'var(--el-mid,#06b6d4)', opacity: 0.7 }));
svg.appendChild(P8Helpers.svg.el('text', { x: 280, y: 105, 'font-family':"'JetBrains Mono',monospace", 'font-size':14, 'font-weight':800, fill:'#fff', 'text-anchor':'middle', text: t.toFixed(1)+' ч из 24' }));
/* A display */
svg.appendChild(P8Helpers.svg.el('text', { x: 280, y: 160, 'font-family':"'Unbounded',sans-serif", 'font-size':18, 'font-weight':900, fill:'#0f172a', 'text-anchor':'middle', text: 'A = '+A.toFixed(3)+' кВт·ч' }));
document.getElementById('p27-iv6-out').textContent = A.toFixed(3);
}
state.p = 100;
const pInp = document.getElementById('p27-iv6-p');
const pLab = document.getElementById('p27-iv6-p-val');
pInp.oninput = ev => { state.p = +ev.target.value; pLab.textContent = (state.p).toFixed(0); render(); };
state.t = 5;
const tInp = document.getElementById('p27-iv6-t');
const tLab = document.getElementById('p27-iv6-t-val');
tInp.oninput = ev => { state.t = +ev.target.value; tLab.textContent = (state.t).toFixed(2); render(); };
render();
}
function _initP26_iv6(){
const sb = document.getElementById('p26-iv6-sandbox');
if (!sb || !window.P8Helpers) return;
const svg = P8Helpers.svg.create(560, 200);
svg.setAttribute('width','100%'); svg.setAttribute('height','100%'); svg.style.display='block';
sb.appendChild(svg);
const state = {};
function render(){
svg.innerHTML = '';
const U = state.u, I = state.i;
const P = U * I;
/* Lamp brightness */
const brightness = Math.min(1, P / 200);
svg.appendChild(P8Helpers.svg.el('circle', { cx: 280, cy: 100, r: 50, fill: '#fef3c7', opacity: brightness * 0.5 + 0.2 }));
svg.appendChild(P8Helpers.svg.el('circle', { cx: 280, cy: 100, r: 30, fill: '#fde047', stroke: '#0f172a', 'stroke-width': 2 }));
svg.appendChild(P8Helpers.svg.el('text', { x: 280, y: 105, 'font-family':"'Unbounded',sans-serif", 'font-size':16, 'font-weight':900, fill: '#0f172a', 'text-anchor':'middle', text: P.toFixed(0) }));
svg.appendChild(P8Helpers.svg.el('text', { x: 280, y: 122, 'font-family':"'Inter',sans-serif", 'font-size':11, 'font-weight':700, fill: '#0f172a', 'text-anchor':'middle', text: 'Вт' }));
if (brightness > 0.6) {
/* Rays */
for (let i = 0; i < 8; i++) {
const a = i * Math.PI / 4;
const x1 = 280 + 38 * Math.cos(a), y1 = 100 + 38 * Math.sin(a);
const x2 = 280 + 58 * Math.cos(a), y2 = 100 + 58 * Math.sin(a);
svg.appendChild(P8Helpers.svg.el('line', { x1, y1, x2, y2, stroke: '#facc15', 'stroke-width': 3 }));
}
}
svg.appendChild(P8Helpers.svg.el('text', { x: 280, y: 180, 'font-family':"'JetBrains Mono',monospace", 'font-size':12, 'font-weight':700, fill:'#0f172a', 'text-anchor':'middle', text: 'P = U·I = '+U+'·'+I.toFixed(2)+' = '+P.toFixed(1)+' Вт' }));
document.getElementById('p26-iv6-out').textContent = P.toFixed(1);
}
state.u = 220;
const uInp = document.getElementById('p26-iv6-u');
const uLab = document.getElementById('p26-iv6-u-val');
uInp.oninput = ev => { state.u = +ev.target.value; uLab.textContent = (state.u).toFixed(0); render(); };
state.i = 0.5;
const iInp = document.getElementById('p26-iv6-i');
const iLab = document.getElementById('p26-iv6-i-val');
iInp.oninput = ev => { state.i = +ev.target.value; iLab.textContent = (state.i).toFixed(2); render(); };
render();
}
function _initP24_iv6(){
const sb = document.getElementById('p24-iv6-sandbox');
if (!sb || !window.P8Helpers) return;
const svg = P8Helpers.svg.create(560, 200);
svg.setAttribute('width','100%'); svg.setAttribute('height','100%'); svg.style.display='block';
sb.appendChild(svg);
const state = {};
function render(){
svg.innerHTML = '';
const R1 = state.r1, R2 = state.r2;
const R = R1 + R2;
const U = 12;
const I = U / R;
/* Battery */
svg.appendChild(P8Helpers.em.circuitComponent('battery', 80, 100, 'h', U+' В'));
/* R1 */
svg.appendChild(P8Helpers.em.circuitComponent('resistor', 240, 100, 'h', R1+' Ом'));
/* R2 */
svg.appendChild(P8Helpers.em.circuitComponent('resistor', 400, 100, 'h', R2+' Ом'));
/* Wires */
svg.appendChild(P8Helpers.svg.el('line', { x1: 110, y1: 100, x2: 210, y2: 100, stroke: '#0f172a', 'stroke-width': 2 }));
svg.appendChild(P8Helpers.svg.el('line', { x1: 270, y1: 100, x2: 370, y2: 100, stroke: '#0f172a', 'stroke-width': 2 }));
svg.appendChild(P8Helpers.svg.el('line', { x1: 430, y1: 100, x2: 510, y2: 100, stroke: '#0f172a', 'stroke-width': 2 }));
svg.appendChild(P8Helpers.svg.el('line', { x1: 510, y1: 100, x2: 510, y2: 160, stroke: '#0f172a', 'stroke-width': 2 }));
svg.appendChild(P8Helpers.svg.el('line', { x1: 50, y1: 100, x2: 50, y2: 160, stroke: '#0f172a', 'stroke-width': 2 }));
svg.appendChild(P8Helpers.svg.el('line', { x1: 50, y1: 160, x2: 510, y2: 160, stroke: '#0f172a', 'stroke-width': 2 }));
/* Labels */
svg.appendChild(P8Helpers.svg.el('text', { x: 280, y: 180, 'font-family':"'JetBrains Mono',monospace", 'font-size':12, 'font-weight':800, fill:'var(--el-mid,#06b6d4)', 'text-anchor':'middle', text: 'R = R₁+R₂ = '+R+' Ом, I = U/R = '+I.toFixed(3)+' А' }));
document.getElementById('p24-iv6-out').textContent = R;
}
state.r1 = 20;
const r1Inp = document.getElementById('p24-iv6-r1');
const r1Lab = document.getElementById('p24-iv6-r1-val');
r1Inp.oninput = ev => { state.r1 = +ev.target.value; r1Lab.textContent = (state.r1).toFixed(0); render(); };
state.r2 = 30;
const r2Inp = document.getElementById('p24-iv6-r2');
const r2Lab = document.getElementById('p24-iv6-r2-val');
r2Inp.oninput = ev => { state.r2 = +ev.target.value; r2Lab.textContent = (state.r2).toFixed(0); render(); };
render();
}
function _initP23_iv6(){
const sb = document.getElementById('p23-iv6-sandbox');
if (!sb || !window.P8Helpers) return;
const svg = P8Helpers.svg.create(560, 200);
svg.setAttribute('width','100%'); svg.setAttribute('height','100%'); svg.style.display='block';
sb.appendChild(svg);
const state = {};
function render(){
svg.innerHTML = '';
const l = state.l, S = state.s * 1e-6;
const rho = 1.7e-8;
const R = rho * l / S;
/* Wire shape: длина = l*60 max, толщина = sqrt(S)*8 max */
const wireL = Math.min(440, 50 + l * 40);
const wireH = Math.min(40, 6 + Math.sqrt(state.s) * 8);
svg.appendChild(P8Helpers.svg.el('rect', { x: (560 - wireL) / 2, y: (200 - wireH) / 2, width: wireL, height: wireH, fill: '#b45309', stroke: '#0f172a', 'stroke-width': 2, rx: 4 }));
svg.appendChild(P8Helpers.svg.el('text', { x: 280, y: (200 - wireH)/2 - 8, 'font-family':"'JetBrains Mono',monospace", 'font-size':11, 'font-weight':700, fill:'#0f172a', 'text-anchor':'middle', text: 'l = '+l.toFixed(1)+' м, S = '+state.s.toFixed(1)+' мм²' }));
svg.appendChild(P8Helpers.svg.el('text', { x: 280, y: 170, 'font-family':"'Unbounded',sans-serif", 'font-size':14, 'font-weight':800, fill:'var(--el-mid,#06b6d4)', 'text-anchor':'middle', text: 'R = '+R.toFixed(4)+' Ом' }));
document.getElementById('p23-iv6-out').textContent = R.toFixed(4);
}
state.l = 1;
const lInp = document.getElementById('p23-iv6-l');
const lLab = document.getElementById('p23-iv6-l-val');
lInp.oninput = ev => { state.l = +ev.target.value; lLab.textContent = (state.l).toFixed(2); render(); };
state.s = 1;
const sInp = document.getElementById('p23-iv6-s');
const sLab = document.getElementById('p23-iv6-s-val');
sInp.oninput = ev => { state.s = +ev.target.value; sLab.textContent = (state.s).toFixed(2); render(); };
render();
}
function _initP21_iv6(){
const sb = document.getElementById('p21-iv6-sandbox');
if (!sb || !window.P8Helpers) return;
const svg = P8Helpers.svg.create(560, 200);
svg.setAttribute('width','100%'); svg.setAttribute('height','100%'); svg.style.display='block';
sb.appendChild(svg);
const state = {};
function render(){
svg.innerHTML = '';
const closed = state.s > 0.5;
/* Battery */
svg.appendChild(P8Helpers.em.circuitComponent('battery', 120, 100, 'h', '6 В'));
/* Switch */
svg.appendChild(P8Helpers.em.circuitComponent('switch', 270, 100, 'h'));
if (closed) {
svg.appendChild(P8Helpers.svg.el('line', { x1: 258, y1: 100, x2: 282, y2: 100, stroke: '#0f172a', 'stroke-width': 2 }));
}
/* Lamp */
svg.appendChild(P8Helpers.em.circuitComponent('lamp', 420, 100, 'h'));
if (closed) {
svg.appendChild(P8Helpers.svg.el('circle', { cx: 420, cy: 100, r: 22, fill: '#fef3c7', opacity: 0.5 }));
}
/* Wires */
svg.appendChild(P8Helpers.svg.el('line', { x1: 150, y1: 100, x2: 240, y2: 100, stroke: '#0f172a', 'stroke-width': 2 }));
svg.appendChild(P8Helpers.svg.el('line', { x1: 300, y1: 100, x2: 394, y2: 100, stroke: '#0f172a', 'stroke-width': 2 }));
svg.appendChild(P8Helpers.svg.el('line', { x1: 446, y1: 100, x2: 500, y2: 100, stroke: '#0f172a', 'stroke-width': 2 }));
svg.appendChild(P8Helpers.svg.el('line', { x1: 500, y1: 100, x2: 500, y2: 160, stroke: '#0f172a', 'stroke-width': 2 }));
svg.appendChild(P8Helpers.svg.el('line', { x1: 90, y1: 100, x2: 90, y2: 160, stroke: '#0f172a', 'stroke-width': 2 }));
svg.appendChild(P8Helpers.svg.el('line', { x1: 90, y1: 160, x2: 500, y2: 160, stroke: '#0f172a', 'stroke-width': 2 }));
svg.appendChild(P8Helpers.svg.el('text', { x: 280, y: 185, 'font-family':"'Inter',sans-serif", 'font-size':11, 'font-weight':700, fill: closed ? '#16a34a' : '#dc2626', 'text-anchor':'middle', text: closed ? '✓ Цепь замкнута — ток идёт' : '✗ Цепь разомкнута' }));
document.getElementById('p21-iv6-out').textContent = closed ? 'замкнута' : 'разомкнута';
}
state.s = 1;
const sInp = document.getElementById('p21-iv6-s');
const sLab = document.getElementById('p21-iv6-s-val');
sInp.oninput = ev => { state.s = +ev.target.value; sLab.textContent = (state.s).toFixed(0); render(); };
render();
}
function _initP20_iv6(){
const sb = document.getElementById('p20-iv6-sandbox');
if (!sb || !window.P8Helpers) return;
const svg = P8Helpers.svg.create(560, 200);
svg.setAttribute('width','100%'); svg.setAttribute('height','100%'); svg.style.display='block';
sb.appendChild(svg);
const state = {};
function render(){
svg.innerHTML = '';
const q = state.q, t = state.t;
const I = q / t;
/* Wire with flowing charges */
svg.appendChild(P8Helpers.svg.el('rect', { x: 80, y: 90, width: 400, height: 20, fill: '#cbd5e1', stroke: '#0f172a', 'stroke-width': 2 }));
const numE = Math.min(20, Math.round(q));
for (let i = 0; i < numE; i++) {
const t0 = (Date.now() / 200 + i / numE) % 1;
const x = 90 + t0 * 380;
svg.appendChild(P8Helpers.svg.el('circle', { cx: x, cy: 100, r: 4, fill: '#dc2626' }));
}
/* Arrow direction */
svg.appendChild(P8Helpers.svg.gradientArrow(svg, 480, 100, 530, 100, { colorFrom: '#dc2626', colorTo: '#7f1d1d', width: 3, headSize: 12 }));
svg.appendChild(P8Helpers.svg.el('text', { x: 280, y: 140, 'font-family':"'JetBrains Mono',monospace", 'font-size':14, 'font-weight':800, fill:'var(--el-mid,#06b6d4)', 'text-anchor':'middle', text: 'I = '+q+'/'+t+' = '+I.toFixed(2)+' А' }));
document.getElementById('p20-iv6-out').textContent = I.toFixed(2);
if (!sb._anim) sb._anim = setInterval(() => { if (sb.isConnected) render(); else clearInterval(sb._anim); }, 100);
}
state.q = 6;
const qInp = document.getElementById('p20-iv6-q');
const qLab = document.getElementById('p20-iv6-q-val');
qInp.oninput = ev => { state.q = +ev.target.value; qLab.textContent = (state.q).toFixed(2); render(); };
state.t = 2;
const tInp = document.getElementById('p20-iv6-t');
const tLab = document.getElementById('p20-iv6-t-val');
tInp.oninput = ev => { state.t = +ev.target.value; tLab.textContent = (state.t).toFixed(2); render(); };
render();
}
function _initP19_iv6(){
const sb = document.getElementById('p19-iv6-sandbox');
if (!sb || !window.P8Helpers) return;
const svg = P8Helpers.svg.create(560, 200);
svg.setAttribute('width','100%'); svg.setAttribute('height','100%'); svg.style.display='block';
sb.appendChild(svg);
const state = {};
function render(){
svg.innerHTML = '';
const A = state.a, q = state.q;
const E = A / q;
/* Battery shape */
svg.appendChild(P8Helpers.svg.el('rect', { x: 200, y: 60, width: 160, height: 80, fill: '#facc15', stroke: '#0f172a', 'stroke-width': 3, rx: 8 }));
svg.appendChild(P8Helpers.svg.el('rect', { x: 215, y: 50, width: 30, height: 10, fill: '#475569' }));
svg.appendChild(P8Helpers.svg.el('rect', { x: 320, y: 50, width: 30, height: 10, fill: '#475569' }));
svg.appendChild(P8Helpers.svg.el('text', { x: 280, y: 100, 'font-family':"'Unbounded',sans-serif", 'font-size':22, 'font-weight':900, fill:'#0f172a', 'text-anchor':'middle', text: E.toFixed(1)+' В' }));
svg.appendChild(P8Helpers.svg.el('text', { x: 280, y: 125, 'font-family':"'Inter',sans-serif", 'font-size':11, fill:'#0f172a', 'text-anchor':'middle', text: 'A = '+A+' Дж, q = '+q+' Кл' }));
document.getElementById('p19-iv6-out').textContent = E.toFixed(1);
}
state.a = 24;
const aInp = document.getElementById('p19-iv6-a');
const aLab = document.getElementById('p19-iv6-a-val');
aInp.oninput = ev => { state.a = +ev.target.value; aLab.textContent = (state.a).toFixed(0); render(); };
state.q = 2;
const qInp = document.getElementById('p19-iv6-q');
const qLab = document.getElementById('p19-iv6-q-val');
qInp.oninput = ev => { state.q = +ev.target.value; qLab.textContent = (state.q).toFixed(2); render(); };
render();
}
function _initP18_iv6(){
const sb = document.getElementById('p18-iv6-sandbox');
if (!sb || !window.P8Helpers) return;
const svg = P8Helpers.svg.create(560, 200);
svg.setAttribute('width','100%'); svg.setAttribute('height','100%'); svg.style.display='block';
sb.appendChild(svg);
const state = {};
function render(){
svg.innerHTML = '';
const q = state.q, U = state.u;
const A = q * U;
/* Two plates */
svg.appendChild(P8Helpers.svg.el('line', { x1: 100, y1: 40, x2: 100, y2: 160, stroke: '#dc2626', 'stroke-width': 6 }));
svg.appendChild(P8Helpers.svg.el('text', { x: 100, y: 30, 'font-family':"'Unbounded',sans-serif", 'font-size':14, 'font-weight':900, fill:'#dc2626', 'text-anchor':'middle', text: '+' }));
svg.appendChild(P8Helpers.svg.el('line', { x1: 400, y1: 40, x2: 400, y2: 160, stroke: '#2563eb', 'stroke-width': 6 }));
svg.appendChild(P8Helpers.svg.el('text', { x: 400, y: 30, 'font-family':"'Unbounded',sans-serif", 'font-size':14, 'font-weight':900, fill:'#2563eb', 'text-anchor':'middle', text: '' }));
/* Charge moving */
svg.appendChild(P8Helpers.svg.el('circle', { cx: 200, cy: 100, r: 14, fill: '#fecaca', stroke: '#dc2626', 'stroke-width': 2 }));
svg.appendChild(P8Helpers.svg.el('text', { x: 200, y: 105, 'font-family':"'Inter',sans-serif", 'font-size':14, 'font-weight':900, fill:'#dc2626', 'text-anchor':'middle', text: '+q' }));
/* Arrow direction of work */
svg.appendChild(P8Helpers.svg.gradientArrow(svg, 220, 100, 380, 100, { colorFrom: '#facc15', colorTo: '#dc2626', width: 3, headSize: 12, glow: true }));
svg.appendChild(P8Helpers.svg.el('text', { x: 300, y: 90, 'font-family':"'JetBrains Mono',monospace", 'font-size':14, 'font-weight':800, fill:'#0f172a', 'text-anchor':'middle', text: 'A = qU = '+A.toFixed(1)+' мкДж' }));
svg.appendChild(P8Helpers.svg.el('text', { x: 250, y: 180, 'font-family':"'Inter',sans-serif", 'font-size':11, fill:'var(--p8-muted,#64748b)', 'text-anchor':'middle', text: 'U = '+U+' В, между пластинами' }));
document.getElementById('p18-iv6-out').textContent = A.toFixed(1);
}
state.q = 1;
const qInp = document.getElementById('p18-iv6-q');
const qLab = document.getElementById('p18-iv6-q-val');
qInp.oninput = ev => { state.q = +ev.target.value; qLab.textContent = (state.q).toFixed(2); render(); };
state.u = 12;
const uInp = document.getElementById('p18-iv6-u');
const uLab = document.getElementById('p18-iv6-u-val');
uInp.oninput = ev => { state.u = +ev.target.value; uLab.textContent = (state.u).toFixed(0); render(); };
render();
}
function _initP16_iv6(){
const sb = document.getElementById('p16-iv6-sandbox');
if (!sb || !window.P8Helpers) return;
const svg = P8Helpers.svg.create(560, 200);
svg.setAttribute('width','100%'); svg.setAttribute('height','100%'); svg.style.display='block';
sb.appendChild(svg);
const state = {};
function render(){
svg.innerHTML = '';
const Z = Math.round(state.z);
/* Nucleus */
svg.appendChild(P8Helpers.svg.el('circle', { cx: 280, cy: 100, r: 14, fill: '#dc2626', stroke: '#0f172a', 'stroke-width': 2 }));
svg.appendChild(P8Helpers.svg.el('text', { x: 280, y: 105, 'font-family':"'Unbounded',sans-serif", 'font-size':12, 'font-weight':900, fill:'#fff', 'text-anchor':'middle', text: '+'+Z }));
/* Orbits — fill shell by shell: 2, 8, 8, 2 */
const shells = [];
let remaining = Z;
[2, 8, 8, 2].forEach(cap => { if (remaining > 0) { shells.push(Math.min(cap, remaining)); remaining -= cap; }});
shells.forEach((electrons, shellIdx) => {
const radius = 35 + shellIdx * 20;
svg.appendChild(P8Helpers.svg.el('circle', { cx: 280, cy: 100, r: radius, fill: 'none', stroke: '#94a3b8', 'stroke-width': 1, 'stroke-dasharray': '3 3' }));
for (let i = 0; i < electrons; i++) {
const a = i * 2 * Math.PI / electrons;
svg.appendChild(P8Helpers.svg.el('circle', { cx: 280 + radius * Math.cos(a), cy: 100 + radius * Math.sin(a), r: 4.5, fill: '#2563eb', stroke: '#0f172a', 'stroke-width': 1 }));
}
});
document.getElementById('p16-iv6-out').textContent = '+'+Z+'e';
}
state.z = 6;
const zInp = document.getElementById('p16-iv6-z');
const zLab = document.getElementById('p16-iv6-z-val');
zInp.oninput = ev => { state.z = +ev.target.value; zLab.textContent = (state.z).toFixed(0); render(); };
render();
}
function _initP15_iv6(){
const sb = document.getElementById('p15-iv6-sandbox');
if (!sb || !window.P8Helpers) return;
const svg = P8Helpers.svg.create(560, 200);
svg.setAttribute('width','100%'); svg.setAttribute('height','100%'); svg.style.display='block';
sb.appendChild(svg);
const state = {};
function render(){
svg.innerHTML = '';
const q = state.q * 1e-9;
const n = Math.abs(q / 1.6e-19);
const sign = q > 0 ? 1 : -1;
/* Body (sphere) */
svg.appendChild(P8Helpers.svg.el('circle', { cx: 200, cy: 100, r: 50, fill: sign > 0 ? '#fecaca' : '#bfdbfe', stroke: sign > 0 ? '#dc2626' : '#2563eb', 'stroke-width': 3 }));
/* +/- charges around */
const numE = Math.min(12, Math.round(n / 1e10) + 1);
for (let i = 0; i < numE; i++) {
const a = i * 2 * Math.PI / numE;
svg.appendChild(P8Helpers.svg.el('text', { x: 200 + 38 * Math.cos(a), y: 105 + 38 * Math.sin(a), 'font-family':"'Inter',sans-serif", 'font-size':14, 'font-weight':900, fill: sign > 0 ? '#dc2626' : '#2563eb', 'text-anchor':'middle', text: sign > 0 ? '+' : '' }));
}
/* Counter */
svg.appendChild(P8Helpers.svg.el('text', { x: 380, y: 90, 'font-family':"'Unbounded',sans-serif", 'font-size':14, 'font-weight':800, fill:'#0f172a', 'text-anchor':'middle', text: 'n = q/e' }));
svg.appendChild(P8Helpers.svg.el('text', { x: 380, y: 115, 'font-family':"'JetBrains Mono',monospace", 'font-size':16, 'font-weight':700, fill:'var(--el-mid,#06b6d4)', 'text-anchor':'middle', text: '≈ '+(n/1e10).toFixed(2)+'·10¹⁰' }));
document.getElementById('p15-iv6-out').textContent = (n / 1e10).toFixed(2);
}
state.q = 1;
const qInp = document.getElementById('p15-iv6-q');
const qLab = document.getElementById('p15-iv6-q-val');
qInp.oninput = ev => { state.q = +ev.target.value; qLab.textContent = (state.q).toFixed(2); render(); };
render();
}
function _initP14_iv6(){
const sb = document.getElementById('p14-iv6-sandbox');
if (!sb || !window.P8Helpers) return;
const svg = P8Helpers.svg.create(560, 200);
svg.setAttribute('width','100%'); svg.setAttribute('height','100%'); svg.style.display='block';
sb.appendChild(svg);
const state = {};
function render(){
svg.innerHTML = '';
const d = state.d;
/* Charged rod (left) */
svg.appendChild(P8Helpers.svg.el('rect', { x: 30, y: 80, width: 60, height: 30, fill: '#fecaca', stroke: '#dc2626', 'stroke-width': 2, rx: 5 }));
svg.appendChild(P8Helpers.svg.el('text', { x: 60, y: 100, 'font-family':"'Unbounded',sans-serif", 'font-size':18, 'font-weight':900, fill: '#dc2626', 'text-anchor':'middle', text: '+++' }));
/* Conductor (right at position 90 + d) */
const condX = 90 + d;
svg.appendChild(P8Helpers.svg.el('rect', { x: condX, y: 70, width: 140, height: 50, fill: '#fef3c7', stroke: '#0f172a', 'stroke-width': 2, rx: 5 }));
/* Distribution: near side , far side + (induction) */
const intensity = Math.max(0, Math.min(1, (300 - d) / 250));
if (intensity > 0.1) {
svg.appendChild(P8Helpers.svg.el('text', { x: condX + 25, y: 100, 'font-family':"'Unbounded',sans-serif", 'font-size':16, 'font-weight':900, fill: '#2563eb', 'text-anchor':'middle', text: '−−' }));
svg.appendChild(P8Helpers.svg.el('text', { x: condX + 115, y: 100, 'font-family':"'Unbounded',sans-serif", 'font-size':16, 'font-weight':900, fill: '#dc2626', 'text-anchor':'middle', text: '++' }));
}
document.getElementById('p14-iv6-out').textContent = intensity.toFixed(2);
}
state.d = 200;
const dInp = document.getElementById('p14-iv6-d');
const dLab = document.getElementById('p14-iv6-d-val');
dInp.oninput = ev => { state.d = +ev.target.value; dLab.textContent = (state.d).toFixed(0); render(); };
render();
}
function _initP13_iv6(){
const sb = document.getElementById('p13-iv6-sandbox');
if (!sb || !window.P8Helpers) return;
const svg = P8Helpers.svg.create(560, 200);
svg.setAttribute('width','100%'); svg.setAttribute('height','100%'); svg.style.display='block';
sb.appendChild(svg);
const state = {};
function render(){
svg.innerHTML = '';
const U = state.u;
/* Conductor (left) — copper bar */
svg.appendChild(P8Helpers.svg.el('rect', { x: 50, y: 60, width: 180, height: 60, fill: '#b45309', stroke: '#0f172a', 'stroke-width': 2, rx: 5 }));
svg.appendChild(P8Helpers.svg.el('text', { x: 140, y: 50, 'font-family':"'Inter',sans-serif", 'font-size':12, 'font-weight':700, fill:'#0f172a', 'text-anchor':'middle', text: 'Проводник (медь)' }));
/* Moving electrons in conductor */
const numE = 8;
for (let i = 0; i < numE; i++) {
const t = (Date.now() / 100 + i * 20) % 100 / 100;
const x = 60 + t * 160;
svg.appendChild(P8Helpers.svg.el('circle', { cx: x, cy: 80 + (i % 2) * 20, r: 4, fill: '#dc2626', opacity: U > 5 ? 1 : 0.3 }));
}
/* Insulator (right) — glass bar */
svg.appendChild(P8Helpers.svg.el('rect', { x: 320, y: 60, width: 180, height: 60, fill: '#bae6fd', stroke: '#0f172a', 'stroke-width': 2, rx: 5 }));
svg.appendChild(P8Helpers.svg.el('text', { x: 410, y: 50, 'font-family':"'Inter',sans-serif", 'font-size':12, 'font-weight':700, fill:'#0f172a', 'text-anchor':'middle', text: 'Диэлектрик (стекло)' }));
/* Stuck electrons */
for (let i = 0; i < 8; i++) {
svg.appendChild(P8Helpers.svg.el('circle', { cx: 335 + i * 22, cy: 80 + (i % 2) * 20, r: 4, fill: '#475569' }));
}
/* Current ↦ in conductor only */
const I = U > 1 ? U / 10 : 0;
svg.appendChild(P8Helpers.svg.el('text', { x: 140, y: 145, 'font-family':"'JetBrains Mono',monospace", 'font-size':12, 'font-weight':800, fill:'#dc2626', 'text-anchor':'middle', text: 'I = '+I.toFixed(2)+' А' }));
svg.appendChild(P8Helpers.svg.el('text', { x: 410, y: 145, 'font-family':"'JetBrains Mono',monospace", 'font-size':12, 'font-weight':800, fill:'#94a3b8', 'text-anchor':'middle', text: 'I = 0 А' }));
document.getElementById('p13-iv6-out').textContent = I.toFixed(2);
/* Animate by re-render every 50ms */
if (!sb._anim) sb._anim = setInterval(() => { if (sb.isConnected) render(); else { clearInterval(sb._anim); } }, 100);
}
state.u = 0;
const uInp = document.getElementById('p13-iv6-u');
const uLab = document.getElementById('p13-iv6-u-val');
uInp.oninput = ev => { state.u = +ev.target.value; uLab.textContent = (state.u).toFixed(0); render(); };
render();
}
function _initP30_iv6(){
const sb = document.getElementById('p30-iv6-sandbox');
if (!sb || !window.P8Helpers) return;
@@ -2072,19 +2602,21 @@ function build_p13(){
+'<div class="score-display" style="margin-top:10px"><span>Задача: <b id="p13-tasks5-i">1</b> / 5</span><span>Правильно: <b id="p13-tasks5-ok">0</b></span></div>'
+'</div>';
/* IV6 — flagship интерактив (заглушка Phase 2, наполнение в Phase 2.13) */
/* IV6 — Проводники vs диэлектрики (Phase 2.3) */
h += '<div class="wg p8-iv6">'
+'<div class="wg-header"><span class="wg-badge p8-badge p8-badge-electric">IV-6</span><div class="wg-title">Новый интерактив §13</div></div>'
+'<div class="wg-help">Готовится: интерактивная визуализация с drag-and-drop для углубления темы. Скоро будет доступна.</div>'
+'<div style="padding:30px;text-align:center;color:var(--p8-muted);font-style:italic">'
+'<svg viewBox="0 0 24 24" style="width:32px;height:32px;stroke:currentColor;fill:none;stroke-width:1.5;opacity:.4"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>'
+'<div style="margin-top:8px;font-size:.86rem">Phase 2.13 — coming soon</div>'
+'<div class="wg-header"><span class="wg-badge p8-badge p8-badge-electric">IV-6</span><div class="wg-title">Проводники vs диэлектрики</div></div>'
+'<div class="wg-help">Двигай напряжение — в проводнике (медь, $n \\sim 10^{29}$/м³) свободные электроны легко движутся, в диэлектрике (стекло) — нет.</div>'
+'<div class="p8-sandbox" id="p13-iv6-sandbox" style="height:200px"></div>'
+'<div style="margin-top:10px;display:flex;gap:10px;flex-wrap:wrap">'
+'<div class="p8-scrubber" style="flex:1;min-width:170px"><span class="p8-scrubber-label">U</span><input type="range" id="p13-iv6-u" min="0" max="100" step="1" value="0"><span class="p8-scrubber-value"><span id="p13-iv6-u-val">0</span><span class="p8-unit">В</span></span></div>'
+'<div class="p8-readout"><span class="p8-readout-label">Ток</span><span class="p8-readout-value" id="p13-iv6-out">0</span><span class="p8-readout-unit">А</span></div>'
+'</div>'
+'</div>';
box.innerHTML = h + secNavFor('p13') + readButton('p13');
renderMath(box);
wireReadBtn('p13');
_initP13_iv6();
_initp13_iv5();
_initP13_sim();
@@ -2326,19 +2858,21 @@ function build_p14(){
+'<div class="score-display" style="margin-top:10px"><span>Задача: <b id="p14-tasks5-i">1</b> / 5</span><span>Правильно: <b id="p14-tasks5-ok">0</b></span></div>'
+'</div>';
/* IV6 — flagship интерактив (заглушка Phase 2, наполнение в Phase 2.14) */
/* IV6 — Электростатическая индукция (Phase 2.3) */
h += '<div class="wg p8-iv6">'
+'<div class="wg-header"><span class="wg-badge p8-badge p8-badge-electric">IV-6</span><div class="wg-title">Новый интерактив §14</div></div>'
+'<div class="wg-help">Готовится: интерактивная визуализация с drag-and-drop для углубления темы. Скоро будет доступна.</div>'
+'<div style="padding:30px;text-align:center;color:var(--p8-muted);font-style:italic">'
+'<svg viewBox="0 0 24 24" style="width:32px;height:32px;stroke:currentColor;fill:none;stroke-width:1.5;opacity:.4"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>'
+'<div style="margin-top:8px;font-size:.86rem">Phase 2.14 — coming soon</div>'
+'<div class="wg-header"><span class="wg-badge p8-badge p8-badge-electric">IV-6</span><div class="wg-title">Электростатическая индукция</div></div>'
+'<div class="wg-help">Двигай заряженную палочку к незаряженному проводнику. Свободные электроны притягиваются к + или отталкиваются от −, на дальней стороне возникает противоположный заряд.</div>'
+'<div class="p8-sandbox" id="p14-iv6-sandbox" style="height:200px"></div>'
+'<div style="margin-top:10px;display:flex;gap:10px;flex-wrap:wrap">'
+'<div class="p8-scrubber" style="flex:1;min-width:170px"><span class="p8-scrubber-label">Расстояние</span><input type="range" id="p14-iv6-d" min="50" max="300" step="5" value="200"><span class="p8-scrubber-value"><span id="p14-iv6-d-val">200</span><span class="p8-unit">мм</span></span></div>'
+'<div class="p8-readout"><span class="p8-readout-label">Индукция</span><span class="p8-readout-value" id="p14-iv6-out">0</span><span class="p8-readout-unit">отн.</span></div>'
+'</div>'
+'</div>';
box.innerHTML = h + secNavFor('p14') + readButton('p14');
renderMath(box);
wireReadBtn('p14');
_initP14_iv6();
_initp14_iv5();
_initP14_sim();
@@ -2563,19 +3097,21 @@ function build_p15(){
+'<div class="score-display" style="margin-top:10px"><span>Задача: <b id="p15-task-i">1</b> / 5</span><span>Правильно: <b id="p15-task-ok">0</b></span></div>'
+'</div>';
/* IV6 — flagship интерактив (заглушка Phase 2, наполнение в Phase 2.15) */
/* IV6 — Элементарный заряд: $q = ne$ (Phase 2.3) */
h += '<div class="wg p8-iv6">'
+'<div class="wg-header"><span class="wg-badge p8-badge p8-badge-electric">IV-6</span><div class="wg-title">Новый интерактив §15</div></div>'
+'<div class="wg-help">Готовится: интерактивная визуализация с drag-and-drop для углубления темы. Скоро будет доступна.</div>'
+'<div style="padding:30px;text-align:center;color:var(--p8-muted);font-style:italic">'
+'<svg viewBox="0 0 24 24" style="width:32px;height:32px;stroke:currentColor;fill:none;stroke-width:1.5;opacity:.4"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>'
+'<div style="margin-top:8px;font-size:.86rem">Phase 2.15 — coming soon</div>'
+'<div class="wg-header"><span class="wg-badge p8-badge p8-badge-electric">IV-6</span><div class="wg-title">Элементарный заряд: $q = ne$</div></div>'
+'<div class="wg-help">Любой заряд кратен $e = 1{,}6 \\cdot 10^{-19}$ Кл. Двигай заряд тела — посчитаем число избыточных электронов.</div>'
+'<div class="p8-sandbox" id="p15-iv6-sandbox" style="height:200px"></div>'
+'<div style="margin-top:10px;display:flex;gap:10px;flex-wrap:wrap">'
+'<div class="p8-scrubber" style="flex:1;min-width:170px"><span class="p8-scrubber-label">q</span><input type="range" id="p15-iv6-q" min="-10" max="10" step="0.1" value="1"><span class="p8-scrubber-value"><span id="p15-iv6-q-val">1</span><span class="p8-unit">нКл</span></span></div>'
+'<div class="p8-readout"><span class="p8-readout-label">n электронов</span><span class="p8-readout-value" id="p15-iv6-out">6.25</span><span class="p8-readout-unit">×10¹⁰</span></div>'
+'</div>'
+'</div>';
box.innerHTML = h + secNavFor('p15') + readButton('p15');
renderMath(box);
wireReadBtn('p15');
_initP15_iv6();
_initP15_calc();
_initP15_quiz();
@@ -2778,19 +3314,21 @@ function build_p16(){
+'<div class="score-display" style="margin-top:10px"><span>Задача: <b id="p16-tasks5-i">1</b> / 5</span><span>Правильно: <b id="p16-tasks5-ok">0</b></span></div>'
+'</div>';
/* IV6 — flagship интерактив (заглушка Phase 2, наполнение в Phase 2.16) */
/* IV6 — Строение атома (Phase 2.3) */
h += '<div class="wg p8-iv6">'
+'<div class="wg-header"><span class="wg-badge p8-badge p8-badge-electric">IV-6</span><div class="wg-title">Новый интерактив §16</div></div>'
+'<div class="wg-help">Готовится: интерактивная визуализация с drag-and-drop для углубления темы. Скоро будет доступна.</div>'
+'<div style="padding:30px;text-align:center;color:var(--p8-muted);font-style:italic">'
+'<svg viewBox="0 0 24 24" style="width:32px;height:32px;stroke:currentColor;fill:none;stroke-width:1.5;opacity:.4"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>'
+'<div style="margin-top:8px;font-size:.86rem">Phase 2.16 — coming soon</div>'
+'<div class="wg-header"><span class="wg-badge p8-badge p8-badge-electric">IV-6</span><div class="wg-title">Строение атома</div></div>'
+'<div class="wg-help">Атом нейтрален: число протонов $Z$ = число электронов. Двигай Z, наблюдай орбиту электронов вокруг ядра.</div>'
+'<div class="p8-sandbox" id="p16-iv6-sandbox" style="height:200px"></div>'
+'<div style="margin-top:10px;display:flex;gap:10px;flex-wrap:wrap">'
+'<div class="p8-scrubber" style="flex:1;min-width:170px"><span class="p8-scrubber-label">Z (протоны)</span><input type="range" id="p16-iv6-z" min="1" max="20" step="1" value="6"><span class="p8-scrubber-value"><span id="p16-iv6-z-val">6</span><span class="p8-unit"></span></span></div>'
+'<div class="p8-readout"><span class="p8-readout-label">Заряд ядра</span><span class="p8-readout-value" id="p16-iv6-out">+6e</span><span class="p8-readout-unit"></span></div>'
+'</div>'
+'</div>';
box.innerHTML = h + secNavFor('p16') + readButton('p16');
renderMath(box);
wireReadBtn('p16');
_initP16_iv6();
_initp16_iv5();
_initP16_atom();
@@ -3227,19 +3765,22 @@ function build_p18(){
+'<div class="score-display" style="margin-top:10px"><span>Задача: <b id="p18-task-i">1</b> / 5</span><span>Правильно: <b id="p18-task-ok">0</b></span></div>'
+'</div>';
/* IV6 — flagship интерактив (заглушка Phase 2, наполнение в Phase 2.18) */
/* IV6 — Работа поля: $A = qU$ (Phase 2.3) */
h += '<div class="wg p8-iv6">'
+'<div class="wg-header"><span class="wg-badge p8-badge p8-badge-electric">IV-6</span><div class="wg-title">Новый интерактив §18</div></div>'
+'<div class="wg-help">Готовится: интерактивная визуализация с drag-and-drop для углубления темы. Скоро будет доступна.</div>'
+'<div style="padding:30px;text-align:center;color:var(--p8-muted);font-style:italic">'
+'<svg viewBox="0 0 24 24" style="width:32px;height:32px;stroke:currentColor;fill:none;stroke-width:1.5;opacity:.4"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>'
+'<div style="margin-top:8px;font-size:.86rem">Phase 2.18 — coming soon</div>'
+'<div class="wg-header"><span class="wg-badge p8-badge p8-badge-electric">IV-6</span><div class="wg-title">Работа поля: $A = qU$</div></div>'
+'<div class="wg-help">Двигай заряд $q$ и напряжение $U$. Работа $A = qU$ обновляется live.</div>'
+'<div class="p8-sandbox" id="p18-iv6-sandbox" style="height:200px"></div>'
+'<div style="margin-top:10px;display:flex;gap:10px;flex-wrap:wrap">'
+'<div class="p8-scrubber" style="flex:1;min-width:170px"><span class="p8-scrubber-label">q</span><input type="range" id="p18-iv6-q" min="0.1" max="10" step="0.1" value="1"><span class="p8-scrubber-value"><span id="p18-iv6-q-val">1</span><span class="p8-unit">мкКл</span></span></div>'
+'<div class="p8-scrubber" style="flex:1;min-width:170px"><span class="p8-scrubber-label">U</span><input type="range" id="p18-iv6-u" min="1" max="100" step="1" value="12"><span class="p8-scrubber-value"><span id="p18-iv6-u-val">12</span><span class="p8-unit">В</span></span></div>'
+'<div class="p8-readout"><span class="p8-readout-label">A</span><span class="p8-readout-value" id="p18-iv6-out">12</span><span class="p8-readout-unit">мкДж</span></div>'
+'</div>'
+'</div>';
box.innerHTML = h + secNavFor('p18') + readButton('p18');
renderMath(box);
wireReadBtn('p18');
_initP18_iv6();
_initP18_calc();
_initP18_quiz();
@@ -3448,19 +3989,22 @@ function build_p19(){
+'<div class="score-display" style="margin-top:10px"><span>Задача: <b id="p19-tasks5-i">1</b> / 5</span><span>Правильно: <b id="p19-tasks5-ok">0</b></span></div>'
+'</div>';
/* IV6 — flagship интерактив (заглушка Phase 2, наполнение в Phase 2.19) */
/* IV6 — ЭДС источника: $\\mathcal{E} = A/q$ (Phase 2.3) */
h += '<div class="wg p8-iv6">'
+'<div class="wg-header"><span class="wg-badge p8-badge p8-badge-electric">IV-6</span><div class="wg-title">Новый интерактив §19</div></div>'
+'<div class="wg-help">Готовится: интерактивная визуализация с drag-and-drop для углубления темы. Скоро будет доступна.</div>'
+'<div style="padding:30px;text-align:center;color:var(--p8-muted);font-style:italic">'
+'<svg viewBox="0 0 24 24" style="width:32px;height:32px;stroke:currentColor;fill:none;stroke-width:1.5;opacity:.4"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>'
+'<div style="margin-top:8px;font-size:.86rem">Phase 2.19 — coming soon</div>'
+'<div class="wg-header"><span class="wg-badge p8-badge p8-badge-electric">IV-6</span><div class="wg-title">ЭДС источника: $\\mathcal{E} = A/q$</div></div>'
+'<div class="wg-help">Источник тока совершает работу $A$ над зарядом $q$. ЭДС $\\mathcal{E} = A/q$.</div>'
+'<div class="p8-sandbox" id="p19-iv6-sandbox" style="height:200px"></div>'
+'<div style="margin-top:10px;display:flex;gap:10px;flex-wrap:wrap">'
+'<div class="p8-scrubber" style="flex:1;min-width:170px"><span class="p8-scrubber-label">A</span><input type="range" id="p19-iv6-a" min="1" max="100" step="1" value="24"><span class="p8-scrubber-value"><span id="p19-iv6-a-val">24</span><span class="p8-unit">Дж</span></span></div>'
+'<div class="p8-scrubber" style="flex:1;min-width:170px"><span class="p8-scrubber-label">q</span><input type="range" id="p19-iv6-q" min="0.5" max="20" step="0.5" value="2"><span class="p8-scrubber-value"><span id="p19-iv6-q-val">2</span><span class="p8-unit">Кл</span></span></div>'
+'<div class="p8-readout"><span class="p8-readout-label">ЭДС</span><span class="p8-readout-value" id="p19-iv6-out">12</span><span class="p8-readout-unit">В</span></div>'
+'</div>'
+'</div>';
box.innerHTML = h + secNavFor('p19') + readButton('p19');
renderMath(box);
wireReadBtn('p19');
_initP19_iv6();
_initp19_iv5();
_initP19_sim();
@@ -3715,19 +4259,22 @@ function build_p20(){
+'<div class="score-display" style="margin-top:10px"><span>Задача: <b id="p20-task-i">1</b> / 5</span><span>Правильно: <b id="p20-task-ok">0</b></span></div>'
+'</div>';
/* IV6 — flagship интерактив (заглушка Phase 2, наполнение в Phase 2.20) */
/* IV6 — Сила тока: $I = q/t$ (Phase 2.3) */
h += '<div class="wg p8-iv6">'
+'<div class="wg-header"><span class="wg-badge p8-badge p8-badge-electric">IV-6</span><div class="wg-title">Новый интерактив §20</div></div>'
+'<div class="wg-help">Готовится: интерактивная визуализация с drag-and-drop для углубления темы. Скоро будет доступна.</div>'
+'<div style="padding:30px;text-align:center;color:var(--p8-muted);font-style:italic">'
+'<svg viewBox="0 0 24 24" style="width:32px;height:32px;stroke:currentColor;fill:none;stroke-width:1.5;opacity:.4"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>'
+'<div style="margin-top:8px;font-size:.86rem">Phase 2.20 — coming soon</div>'
+'<div class="wg-header"><span class="wg-badge p8-badge p8-badge-electric">IV-6</span><div class="wg-title">Сила тока: $I = q/t$</div></div>'
+'<div class="wg-help">Двигай заряд и время — найдём ток.</div>'
+'<div class="p8-sandbox" id="p20-iv6-sandbox" style="height:200px"></div>'
+'<div style="margin-top:10px;display:flex;gap:10px;flex-wrap:wrap">'
+'<div class="p8-scrubber" style="flex:1;min-width:170px"><span class="p8-scrubber-label">q</span><input type="range" id="p20-iv6-q" min="0.1" max="100" step="0.1" value="6"><span class="p8-scrubber-value"><span id="p20-iv6-q-val">6</span><span class="p8-unit">Кл</span></span></div>'
+'<div class="p8-scrubber" style="flex:1;min-width:170px"><span class="p8-scrubber-label">t</span><input type="range" id="p20-iv6-t" min="0.1" max="60" step="0.1" value="2"><span class="p8-scrubber-value"><span id="p20-iv6-t-val">2</span><span class="p8-unit">с</span></span></div>'
+'<div class="p8-readout"><span class="p8-readout-label">I</span><span class="p8-readout-value" id="p20-iv6-out">3.0</span><span class="p8-readout-unit">А</span></div>'
+'</div>'
+'</div>';
box.innerHTML = h + secNavFor('p20') + readButton('p20');
renderMath(box);
wireReadBtn('p20');
_initP20_iv6();
_initP20_sim();
_initP20_quiz();
@@ -3962,19 +4509,21 @@ function build_p21(){
+'<div class="score-display" style="margin-top:10px"><span>Задача: <b id="p21-tasks5-i">1</b> / 5</span><span>Правильно: <b id="p21-tasks5-ok">0</b></span></div>'
+'</div>';
/* IV6 — flagship интерактив (заглушка Phase 2, наполнение в Phase 2.21) */
/* IV6 — Замкнутая электрическая цепь (Phase 2.3) */
h += '<div class="wg p8-iv6">'
+'<div class="wg-header"><span class="wg-badge p8-badge p8-badge-electric">IV-6</span><div class="wg-title">Новый интерактив §21</div></div>'
+'<div class="wg-help">Готовится: интерактивная визуализация с drag-and-drop для углубления темы. Скоро будет доступна.</div>'
+'<div style="padding:30px;text-align:center;color:var(--p8-muted);font-style:italic">'
+'<svg viewBox="0 0 24 24" style="width:32px;height:32px;stroke:currentColor;fill:none;stroke-width:1.5;opacity:.4"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>'
+'<div style="margin-top:8px;font-size:.86rem">Phase 2.21 — coming soon</div>'
+'<div class="wg-header"><span class="wg-badge p8-badge p8-badge-electric">IV-6</span><div class="wg-title">Замкнутая электрическая цепь</div></div>'
+'<div class="wg-help">Состоит из источника, потребителя и соединительных проводов. Переключи выключатель — пойдёт ток.</div>'
+'<div class="p8-sandbox" id="p21-iv6-sandbox" style="height:200px"></div>'
+'<div style="margin-top:10px;display:flex;gap:10px;flex-wrap:wrap">'
+'<div class="p8-scrubber" style="flex:1;min-width:170px"><span class="p8-scrubber-label">Замкнут</span><input type="range" id="p21-iv6-s" min="0" max="1" step="1" value="1"><span class="p8-scrubber-value"><span id="p21-iv6-s-val">1</span><span class="p8-unit"></span></span></div>'
+'<div class="p8-readout"><span class="p8-readout-label">Цепь</span><span class="p8-readout-value" id="p21-iv6-out">замкнута</span><span class="p8-readout-unit"></span></div>'
+'</div>'
+'</div>';
box.innerHTML = h + secNavFor('p21') + readButton('p21');
renderMath(box);
wireReadBtn('p21');
_initP21_iv6();
_initp21_iv5();
_initP21_sim();
@@ -4431,19 +4980,22 @@ function build_p23(){
+'<div class="score-display" style="margin-top:10px"><span>Задача: <b id="p23-task-i">1</b> / 5</span><span>Правильно: <b id="p23-task-ok">0</b></span></div>'
+'</div>';
/* IV6 — flagship интерактив (заглушка Phase 2, наполнение в Phase 2.23) */
/* IV6 — Сопротивление: $R = \\rho l / S$ (Phase 2.3) */
h += '<div class="wg p8-iv6">'
+'<div class="wg-header"><span class="wg-badge p8-badge p8-badge-electric">IV-6</span><div class="wg-title">Новый интерактив §23</div></div>'
+'<div class="wg-help">Готовится: интерактивная визуализация с drag-and-drop для углубления темы. Скоро будет доступна.</div>'
+'<div style="padding:30px;text-align:center;color:var(--p8-muted);font-style:italic">'
+'<svg viewBox="0 0 24 24" style="width:32px;height:32px;stroke:currentColor;fill:none;stroke-width:1.5;opacity:.4"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>'
+'<div style="margin-top:8px;font-size:.86rem">Phase 2.23 — coming soon</div>'
+'<div class="wg-header"><span class="wg-badge p8-badge p8-badge-electric">IV-6</span><div class="wg-title">Сопротивление: $R = \\rho l / S$</div></div>'
+'<div class="wg-help">Длина увеличивает $R$ пропорционально, площадь — обратно пропорционально. Удельное $\\rho$ — для меди 1.7·10⁻⁸ Ом·м.</div>'
+'<div class="p8-sandbox" id="p23-iv6-sandbox" style="height:200px"></div>'
+'<div style="margin-top:10px;display:flex;gap:10px;flex-wrap:wrap">'
+'<div class="p8-scrubber" style="flex:1;min-width:170px"><span class="p8-scrubber-label">l</span><input type="range" id="p23-iv6-l" min="0.1" max="10" step="0.1" value="1"><span class="p8-scrubber-value"><span id="p23-iv6-l-val">1</span><span class="p8-unit">м</span></span></div>'
+'<div class="p8-scrubber" style="flex:1;min-width:170px"><span class="p8-scrubber-label">S</span><input type="range" id="p23-iv6-s" min="0.5" max="10" step="0.1" value="1"><span class="p8-scrubber-value"><span id="p23-iv6-s-val">1</span><span class="p8-unit">мм²</span></span></div>'
+'<div class="p8-readout"><span class="p8-readout-label">R (медь)</span><span class="p8-readout-value" id="p23-iv6-out">0.017</span><span class="p8-readout-unit">Ом</span></div>'
+'</div>'
+'</div>';
box.innerHTML = h + secNavFor('p23') + readButton('p23');
renderMath(box);
wireReadBtn('p23');
_initP23_iv6();
_initP23_calc();
_initP23_quiz();
@@ -4657,19 +5209,22 @@ function build_p24(){
+'<div class="score-display" style="margin-top:10px"><span>Задача: <b id="p24-task-i">1</b> / 5</span><span>Правильно: <b id="p24-task-ok">0</b></span></div>'
+'</div>';
/* IV6 — flagship интерактив (заглушка Phase 2, наполнение в Phase 2.24) */
/* IV6 — Последовательное соединение: $R = R_1 + R_2$ (Phase 2.3) */
h += '<div class="wg p8-iv6">'
+'<div class="wg-header"><span class="wg-badge p8-badge p8-badge-electric">IV-6</span><div class="wg-title">Новый интерактив §24</div></div>'
+'<div class="wg-help">Готовится: интерактивная визуализация с drag-and-drop для углубления темы. Скоро будет доступна.</div>'
+'<div style="padding:30px;text-align:center;color:var(--p8-muted);font-style:italic">'
+'<svg viewBox="0 0 24 24" style="width:32px;height:32px;stroke:currentColor;fill:none;stroke-width:1.5;opacity:.4"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>'
+'<div style="margin-top:8px;font-size:.86rem">Phase 2.24 — coming soon</div>'
+'<div class="wg-header"><span class="wg-badge p8-badge p8-badge-electric">IV-6</span><div class="wg-title">Последовательное соединение: $R = R_1 + R_2$</div></div>'
+'<div class="wg-help">Сложи $R_1$ и $R_2$ — получишь общее $R$. Ток через них одинаков, напряжения складываются: $U = U_1 + U_2$.</div>'
+'<div class="p8-sandbox" id="p24-iv6-sandbox" style="height:200px"></div>'
+'<div style="margin-top:10px;display:flex;gap:10px;flex-wrap:wrap">'
+'<div class="p8-scrubber" style="flex:1;min-width:170px"><span class="p8-scrubber-label">R₁</span><input type="range" id="p24-iv6-r1" min="1" max="100" step="1" value="20"><span class="p8-scrubber-value"><span id="p24-iv6-r1-val">20</span><span class="p8-unit">Ом</span></span></div>'
+'<div class="p8-scrubber" style="flex:1;min-width:170px"><span class="p8-scrubber-label">R₂</span><input type="range" id="p24-iv6-r2" min="1" max="100" step="1" value="30"><span class="p8-scrubber-value"><span id="p24-iv6-r2-val">30</span><span class="p8-unit">Ом</span></span></div>'
+'<div class="p8-readout"><span class="p8-readout-label">R_общ</span><span class="p8-readout-value" id="p24-iv6-out">50</span><span class="p8-readout-unit">Ом</span></div>'
+'</div>'
+'</div>';
box.innerHTML = h + secNavFor('p24') + readButton('p24');
renderMath(box);
wireReadBtn('p24');
_initP24_iv6();
_initP24_rheostat();
_initP24_calc();
@@ -5128,19 +5683,22 @@ function build_p26(){
+'<div class="score-display" style="margin-top:10px"><span>Задача: <b id="p26-task-i">1</b> / 6</span><span>Правильно: <b id="p26-task-ok">0</b></span></div>'
+'</div>';
/* IV6 — flagship интерактив (заглушка Phase 2, наполнение в Phase 2.26) */
/* IV6 — Мощность: $P = UI$ (Phase 2.3) */
h += '<div class="wg p8-iv6">'
+'<div class="wg-header"><span class="wg-badge p8-badge p8-badge-electric">IV-6</span><div class="wg-title">Новый интерактив §26</div></div>'
+'<div class="wg-help">Готовится: интерактивная визуализация с drag-and-drop для углубления темы. Скоро будет доступна.</div>'
+'<div style="padding:30px;text-align:center;color:var(--p8-muted);font-style:italic">'
+'<svg viewBox="0 0 24 24" style="width:32px;height:32px;stroke:currentColor;fill:none;stroke-width:1.5;opacity:.4"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>'
+'<div style="margin-top:8px;font-size:.86rem">Phase 2.26 — coming soon</div>'
+'<div class="wg-header"><span class="wg-badge p8-badge p8-badge-electric">IV-6</span><div class="wg-title">Мощность: $P = UI$</div></div>'
+'<div class="wg-help">Двигай напряжение и ток — мощность.</div>'
+'<div class="p8-sandbox" id="p26-iv6-sandbox" style="height:200px"></div>'
+'<div style="margin-top:10px;display:flex;gap:10px;flex-wrap:wrap">'
+'<div class="p8-scrubber" style="flex:1;min-width:170px"><span class="p8-scrubber-label">U</span><input type="range" id="p26-iv6-u" min="1" max="220" step="1" value="220"><span class="p8-scrubber-value"><span id="p26-iv6-u-val">220</span><span class="p8-unit">В</span></span></div>'
+'<div class="p8-scrubber" style="flex:1;min-width:170px"><span class="p8-scrubber-label">I</span><input type="range" id="p26-iv6-i" min="0.01" max="10" step="0.01" value="0.5"><span class="p8-scrubber-value"><span id="p26-iv6-i-val">0.5</span><span class="p8-unit">А</span></span></div>'
+'<div class="p8-readout"><span class="p8-readout-label">P</span><span class="p8-readout-value" id="p26-iv6-out">110</span><span class="p8-readout-unit">Вт</span></div>'
+'</div>'
+'</div>';
box.innerHTML = h + secNavFor('p26') + readButton('p26');
renderMath(box);
wireReadBtn('p26');
_initP26_iv6();
_initP26_sim();
_initP26_quiz();
@@ -5357,19 +5915,22 @@ function build_p27(){
+'<div class="score-display" style="margin-top:10px"><span>Задача: <b id="p27-task-i">1</b> / 5</span><span>Правильно: <b id="p27-task-ok">0</b></span></div>'
+'</div>';
/* IV6 — flagship интерактив (заглушка Phase 2, наполнение в Phase 2.27) */
/* IV6 — Электроэнергия: $A = UIt$ (Phase 2.3) */
h += '<div class="wg p8-iv6">'
+'<div class="wg-header"><span class="wg-badge p8-badge p8-badge-electric">IV-6</span><div class="wg-title">Новый интерактив §27</div></div>'
+'<div class="wg-help">Готовится: интерактивная визуализация с drag-and-drop для углубления темы. Скоро будет доступна.</div>'
+'<div style="padding:30px;text-align:center;color:var(--p8-muted);font-style:italic">'
+'<svg viewBox="0 0 24 24" style="width:32px;height:32px;stroke:currentColor;fill:none;stroke-width:1.5;opacity:.4"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>'
+'<div style="margin-top:8px;font-size:.86rem">Phase 2.27 — coming soon</div>'
+'<div class="wg-header"><span class="wg-badge p8-badge p8-badge-electric">IV-6</span><div class="wg-title">Электроэнергия: $A = UIt$</div></div>'
+'<div class="wg-help">За время $t$ потребитель потратит $A = UIt$ или $A = Pt$.</div>'
+'<div class="p8-sandbox" id="p27-iv6-sandbox" style="height:200px"></div>'
+'<div style="margin-top:10px;display:flex;gap:10px;flex-wrap:wrap">'
+'<div class="p8-scrubber" style="flex:1;min-width:170px"><span class="p8-scrubber-label">P</span><input type="range" id="p27-iv6-p" min="1" max="3000" step="1" value="100"><span class="p8-scrubber-value"><span id="p27-iv6-p-val">100</span><span class="p8-unit">Вт</span></span></div>'
+'<div class="p8-scrubber" style="flex:1;min-width:170px"><span class="p8-scrubber-label">t</span><input type="range" id="p27-iv6-t" min="0.1" max="24" step="0.1" value="5"><span class="p8-scrubber-value"><span id="p27-iv6-t-val">5</span><span class="p8-unit">ч</span></span></div>'
+'<div class="p8-readout"><span class="p8-readout-label">A</span><span class="p8-readout-value" id="p27-iv6-out">0.5</span><span class="p8-readout-unit">кВт·ч</span></div>'
+'</div>'
+'</div>';
box.innerHTML = h + secNavFor('p27') + readButton('p27');
renderMath(box);
wireReadBtn('p27');
_initP27_iv6();
_initP27_meter();
_initP27_quiz();
@@ -5812,19 +6373,21 @@ function build_p29(){
+'<div class="score-display" style="margin-top:10px"><span>Задача: <b id="p29-tasks5-i">1</b> / 5</span><span>Правильно: <b id="p29-tasks5-ok">0</b></span></div>'
+'</div>';
/* IV6 — flagship интерактив (заглушка Phase 2, наполнение в Phase 2.29) */
/* IV6 — Магнитное поле тока: $B \\propto I$ (Phase 2.3) */
h += '<div class="wg p8-iv6">'
+'<div class="wg-header"><span class="wg-badge p8-badge p8-badge-electric">IV-6</span><div class="wg-title">Новый интерактив §29</div></div>'
+'<div class="wg-help">Готовится: интерактивная визуализация с drag-and-drop для углубления темы. Скоро будет доступна.</div>'
+'<div style="padding:30px;text-align:center;color:var(--p8-muted);font-style:italic">'
+'<svg viewBox="0 0 24 24" style="width:32px;height:32px;stroke:currentColor;fill:none;stroke-width:1.5;opacity:.4"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>'
+'<div style="margin-top:8px;font-size:.86rem">Phase 2.29 — coming soon</div>'
+'<div class="wg-header"><span class="wg-badge p8-badge p8-badge-electric">IV-6</span><div class="wg-title">Магнитное поле тока: $B \\propto I$</div></div>'
+'<div class="wg-help">Чем больше ток — тем сильнее поле вокруг проводника. Густота линий ∝ $|I|$.</div>'
+'<div class="p8-sandbox" id="p29-iv6-sandbox" style="height:200px"></div>'
+'<div style="margin-top:10px;display:flex;gap:10px;flex-wrap:wrap">'
+'<div class="p8-scrubber" style="flex:1;min-width:170px"><span class="p8-scrubber-label">I</span><input type="range" id="p29-iv6-i" min="-10" max="10" step="0.1" value="3"><span class="p8-scrubber-value"><span id="p29-iv6-i-val">3</span><span class="p8-unit">А</span></span></div>'
+'<div class="p8-readout"><span class="p8-readout-label">B (отн.)</span><span class="p8-readout-value" id="p29-iv6-out">3</span><span class="p8-readout-unit"></span></div>'
+'</div>'
+'</div>';
box.innerHTML = h + secNavFor('p29') + readButton('p29');
renderMath(box);
wireReadBtn('p29');
_initP29_iv6();
_initp29_iv5();
_initP29_lines();
@@ -6292,19 +6855,22 @@ function build_p31(){
+'<div class="score-display" style="margin-top:10px"><span>Задача: <b id="p31-tasks5-i">1</b> / 5</span><span>Правильно: <b id="p31-tasks5-ok">0</b></span></div>'
+'</div>';
/* IV6 — flagship интерактив (заглушка Phase 2, наполнение в Phase 2.31) */
/* IV6 — Электромагнит: $B \\propto NI$ (Phase 2.3) */
h += '<div class="wg p8-iv6">'
+'<div class="wg-header"><span class="wg-badge p8-badge p8-badge-electric">IV-6</span><div class="wg-title">Новый интерактив §31</div></div>'
+'<div class="wg-help">Готовится: интерактивная визуализация с drag-and-drop для углубления темы. Скоро будет доступна.</div>'
+'<div style="padding:30px;text-align:center;color:var(--p8-muted);font-style:italic">'
+'<svg viewBox="0 0 24 24" style="width:32px;height:32px;stroke:currentColor;fill:none;stroke-width:1.5;opacity:.4"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>'
+'<div style="margin-top:8px;font-size:.86rem">Phase 2.31 — coming soon</div>'
+'<div class="wg-header"><span class="wg-badge p8-badge p8-badge-electric">IV-6</span><div class="wg-title">Электромагнит: $B \\propto NI$</div></div>'
+'<div class="wg-help">Соленоид с $N$ витками и током $I$ — поле растёт пропорционально и тому, и другому. Сердечник из железа усиливает в $\\mu \\sim 1000$ раз.</div>'
+'<div class="p8-sandbox" id="p31-iv6-sandbox" style="height:200px"></div>'
+'<div style="margin-top:10px;display:flex;gap:10px;flex-wrap:wrap">'
+'<div class="p8-scrubber" style="flex:1;min-width:170px"><span class="p8-scrubber-label">Витки N</span><input type="range" id="p31-iv6-n" min="10" max="1000" step="10" value="100"><span class="p8-scrubber-value"><span id="p31-iv6-n-val">100</span><span class="p8-unit"></span></span></div>'
+'<div class="p8-scrubber" style="flex:1;min-width:170px"><span class="p8-scrubber-label">I</span><input type="range" id="p31-iv6-i" min="0" max="5" step="0.1" value="1"><span class="p8-scrubber-value"><span id="p31-iv6-i-val">1</span><span class="p8-unit">А</span></span></div>'
+'<div class="p8-readout"><span class="p8-readout-label">B (отн.)</span><span class="p8-readout-value" id="p31-iv6-out">100</span><span class="p8-readout-unit"></span></div>'
+'</div>'
+'</div>';
box.innerHTML = h + secNavFor('p31') + readButton('p31');
renderMath(box);
wireReadBtn('p31');
_initP31_iv6();
_initp31_iv5();
_initP31_emagnet();