// Inject IV-5 «Расчётные задачи» into MCQ-only paragraphs of physics_8_ch2.html
// and physics_8_ch3.html — параграфы §12,13,14,16,17,19,21,28,29,30,31,32,39.
'use strict';
const fs = require('fs');
const path = require('path');

const TBOOKS = path.join(__dirname, '..', '..', 'frontend', 'textbooks');

// === Numeric tasks per paragraph ===
const TASKS = {

// === Ch2: Электромагнитные явления ===

p12: [  // Электризация
  { q: 'Два одинаковых шарика имели заряды $q_1 = +6$ мкКл и $q_2 = -2$ мкКл. После соприкосновения и разделения, какой заряд (мкКл) остался на каждом?', ans: 2, tol: 0.05, why: 'При контакте одинаковых шаров заряды выравниваются: $q = (q_1 + q_2)/2 = (+6 - 2)/2 = +2$ мкКл.' },
  { q: 'У эбонитовой палочки $-30$ нКл, у шерсти $+30$ нКл. Какой суммарный заряд (нКл) системы по закону сохранения заряда?', ans: 0, tol: 0.5, why: 'Заряд изолированной системы сохраняется. Если до трения было $0$ — и после $0$: $-30 + 30 = 0$.' },
  { q: 'У шарика заряд $q = +4$ мкКл. Сколько электронов нужно добавить, чтобы он стал нейтральным? ($e = 1{,}6 \\cdot 10^{-19}$ Кл). Ответ дайте в единицах $\\times 10^{13}$.', ans: 2.5, tol: 0.1, why: '$n = q/e = 4 \\cdot 10^{-6} / 1{,}6 \\cdot 10^{-19} = 2{,}5 \\cdot 10^{13}$ электронов.' },
  { q: 'Тело потеряло $n = 5 \\cdot 10^{12}$ электронов. Каков стал его заряд (мкКл)? ($e = 1{,}6 \\cdot 10^{-19}$ Кл)', ans: 0.8, tol: 0.02, why: '$q = n \\cdot e = 5 \\cdot 10^{12} \\cdot 1{,}6 \\cdot 10^{-19} = 8 \\cdot 10^{-7}$ Кл $= 0{,}8$ мкКл (положительный, т. к. потерял электроны).' },
  { q: 'Если соединить шары с зарядами $q_1 = +10$ нКл и $q_2 = +6$ нКл одинакового размера, какой заряд (нКл) будет на каждом после разделения?', ans: 8, tol: 0.2, why: '$q = (q_1 + q_2)/2 = 16/2 = 8$ нКл.' },
],

p13: [  // Проводники и диэлектрики
  { q: 'У проводника плотность свободных электронов $n = 10^{29}$ м⁻³, у диэлектрика $\\sim 10^{17}$ м⁻³. Во сколько раз больше носителей у проводника? (степень 10)', ans: 12, tol: 0.5, why: '$n_{пр}/n_{ди} = 10^{29}/10^{17} = 10^{12}$.' },
  { q: 'Стержень проводника $L = 10$ см заряжен. Если соединить с таким же незаряженным, какая часть (в %) заряда уйдёт на второй?', ans: 50, tol: 1, why: 'Заряды выравниваются, на каждом — половина исходного: $50\\,\\%$.' },
  { q: 'Какой материал лучший проводник: $1$ — стекло, $2$ — сухое дерево, $3$ — медь, $4$ — пластик? Введите номер.', ans: 3, tol: 0.1, why: 'Металлы (медь) — лучшие проводники из перечисленных.' },
  { q: 'У диэлектрика свободных зарядов нет, но связанные могут поляризоваться. Сколько свободных носителей в идеальном диэлектрике?', ans: 0, tol: 0.1, why: 'В идеальном диэлектрике $n_{своб} = 0$ — есть только связанные заряды атомов и молекул.' },
  { q: 'Через тело прошло за $t = 2$ с $q = 4$ Кл. Какова сила тока $I$ (А)?', ans: 2, tol: 0.05, why: '$I = q/t = 4/2 = 2$ А.' },
],

p14: [  // Электростатическая индукция
  { q: 'К незаряженному проводнику поднесли $+$-заряженный шар. Какой заряд индуцируется на ближнем конце проводника?', ans: -1, tol: 0.1, why: 'Свободные электроны притянутся к $+$ — на ближнем конце $-1$ (отрицательный заряд). Введите $-1$.' },
  { q: 'Шар с зарядом $q = +20$ нКл коснулся незаряженного такого же шара. Заряд (нКл) на одном шаре после разделения?', ans: 10, tol: 0.2, why: 'Заряды выравниваются: $q/2 = 10$ нКл.' },
  { q: 'Электроскоп заряжен зарядом $q = 5$ нКл. Что произойдёт с углом отклонения лепестков, если к нему поднести заряд того же знака? ($1$ — уменьшится, $2$ — увеличится, $3$ — не изменится)', ans: 2, tol: 0.1, why: 'Одноимённые заряды отталкиваются — лепестки разойдутся сильнее.' },
  { q: 'Если поднести $+$-заряд к нейтральному шару и заземлить его (отвести электроны), какой заряд останется на шаре после удаления $+$-заряда? ($1$ — положительный, $-1$ — отрицательный)', ans: -1, tol: 0.1, why: 'Электроны притянулись и не ушли — шар стал отрицательным. Ответ $-1$.' },
  { q: 'Заряженная палочка приближается к листку фольги. Лепесток отклоняется на угол $\\alpha$. Если палочку удалить, какой будет $\\alpha$?', ans: 0, tol: 0.1, why: 'Без внешнего поля индуцированные заряды перераспределяются обратно — отклонение $0$.' },
],

p16: [  // Строение атома
  { q: 'У атома водорода $1$ электрон. Каков заряд электронной оболочки (в единицах $e$)? Введите модуль.', ans: 1, tol: 0.1, why: 'Один электрон с зарядом $-e$. Модуль $|q| = e = 1$ в этих единицах.' },
  { q: 'Электрон имеет заряд $e = 1{,}6 \\cdot 10^{-19}$ Кл. Какой суммарный заряд (Кл) у $n = 10^{20}$ электронов? Дайте ответ в виде $\\times 10^{1}$ Кл.', ans: 16, tol: 0.5, why: '$q = ne = 10^{20} \\cdot 1{,}6 \\cdot 10^{-19} = 16$ Кл.' },
  { q: 'Какой заряд имеет атомное ядро углерода $^{12}_{6}$C (в единицах $e$)?', ans: 6, tol: 0.1, why: 'У углерода $Z = 6$ протонов, каждый с зарядом $+e$. Заряд ядра $= +6e$.' },
  { q: 'Атом нейтрален. Сколько электронов вокруг ядра кислорода $^{16}_{8}$O?', ans: 8, tol: 0.1, why: 'В нейтральном атоме число электронов равно числу протонов: $Z = 8$.' },
  { q: 'Сколько Кл составляет заряд $5$ протонов? ($e = 1{,}6 \\cdot 10^{-19}$ Кл). Ответ $\\times 10^{-19}$.', ans: 8, tol: 0.2, why: '$q = 5e = 5 \\cdot 1{,}6 \\cdot 10^{-19} = 8 \\cdot 10^{-19}$ Кл.' },
],

p17: [  // Электрическое поле
  { q: 'В точке поля на заряд $q = 2$ нКл действует сила $F = 4 \\cdot 10^{-5}$ Н. Найдите модуль напряжённости $E$ (В/м). $E = F/q$.', ans: 20000, tol: 500, why: '$E = F/q = 4 \\cdot 10^{-5} / 2 \\cdot 10^{-9} = 2 \\cdot 10^{4} = 20\\,000$ В/м.' },
  { q: 'Напряжённость поля $E = 1000$ В/м. Какая сила (мкН) действует на заряд $q = 5$ нКл?', ans: 5, tol: 0.2, why: '$F = qE = 5 \\cdot 10^{-9} \\cdot 1000 = 5 \\cdot 10^{-6}$ Н $= 5$ мкН.' },
  { q: 'Однородное поле напряжённостью $E = 200$ В/м. Какая работа поля (мкДж) при перемещении заряда $q = 1$ мкКл вдоль линии поля на $d = 10$ см?', ans: 20, tol: 1, why: '$A = qEd = 10^{-6} \\cdot 200 \\cdot 0{,}1 = 2 \\cdot 10^{-5}$ Дж $= 20$ мкДж.' },
  { q: 'На пробный заряд $q_0$ в поле действует сила $F$. Если заряд $q_0$ удвоить, во сколько раз изменится $E$ в этой точке?', ans: 1, tol: 0.05, why: '$E$ — характеристика поля, не зависит от пробного заряда: $E$ не меняется (коэффициент $= 1$).' },
  { q: 'Силовые линии однородного поля идут параллельно с плотностью $5$ линий/см. У сильного поля плотность $20$ линий/см. Во сколько раз больше $E$?', ans: 4, tol: 0.2, why: 'Густота линий пропорциональна $E$: $20/5 = 4$ раза.' },
],

p19: [  // Источники тока
  { q: 'Батарея делает работу $A = 12$ Дж по перемещению заряда $q = 4$ Кл. Найдите ЭДС $\\mathcal{E}$ (В). $\\mathcal{E} = A/q$.', ans: 3, tol: 0.05, why: '$\\mathcal{E} = A/q = 12/4 = 3$ В.' },
  { q: 'ЭДС источника $\\mathcal{E} = 9$ В. Какую работу (Дж) совершат сторонние силы по переносу заряда $q = 5$ Кл?', ans: 45, tol: 1, why: '$A = \\mathcal{E} \\cdot q = 9 \\cdot 5 = 45$ Дж.' },
  { q: 'Аккумулятор отдал заряд $q = 0{,}5$ Кл при ЭДС $\\mathcal{E} = 12$ В. Сколько Дж работы он совершил?', ans: 6, tol: 0.1, why: '$A = \\mathcal{E} q = 12 \\cdot 0{,}5 = 6$ Дж.' },
  { q: 'У батарейки ЭДС $1{,}5$ В. Сколько Кл нужно перенести, чтобы получить $3$ Дж?', ans: 2, tol: 0.05, why: '$q = A/\\mathcal{E} = 3/1{,}5 = 2$ Кл.' },
  { q: 'Гальванический элемент работает $t = 60$ с с током $I = 0{,}1$ А и ЭДС $\\mathcal{E} = 1{,}5$ В. Какую работу (Дж) он совершил? ($A = \\mathcal{E} I t$)', ans: 9, tol: 0.2, why: '$A = \\mathcal{E} \\cdot I \\cdot t = 1{,}5 \\cdot 0{,}1 \\cdot 60 = 9$ Дж.' },
],

p21: [  // Электрическая цепь
  { q: 'За $t = 2$ с через сечение проводника прошёл заряд $q = 6$ Кл. Найдите силу тока $I$ (А). $I = q/t$.', ans: 3, tol: 0.05, why: '$I = q/t = 6/2 = 3$ А.' },
  { q: 'В цепи течёт ток $I = 0{,}5$ А. Какой заряд (Кл) пройдёт за минуту?', ans: 30, tol: 0.5, why: '$q = It = 0{,}5 \\cdot 60 = 30$ Кл.' },
  { q: 'Через лампочку прошло $q = 60$ Кл за $t = 5$ мин. Найдите $I$ (мА). Внимание: переведите минуты в секунды.', ans: 200, tol: 5, why: '$t = 300$ с, $I = q/t = 60/300 = 0{,}2$ А $= 200$ мА.' },
  { q: 'В лампе сила тока $I = 0{,}3$ А. Сколько электронов проходит через сечение нити за $t = 1$ с? ($e = 1{,}6 \\cdot 10^{-19}$ Кл). Ответ $\\times 10^{18}$.', ans: 1.875, tol: 0.05, why: '$n = q/e = It/e = 0{,}3 / 1{,}6 \\cdot 10^{-19} \\approx 1{,}88 \\cdot 10^{18}$.' },
  { q: 'Какой ток (А) в цепи, где за $0{,}5$ часа прошло $q = 900$ Кл?', ans: 0.5, tol: 0.02, why: '$t = 1800$ с, $I = q/t = 900/1800 = 0{,}5$ А.' },
],

p28: [  // Постоянные магниты
  { q: 'Сколько полюсов у любого магнита?', ans: 2, tol: 0.1, why: 'У любого магнита всегда $2$ полюса: северный N и южный S. Магнитного «монополя» не существует.' },
  { q: 'Если разрезать магнит на $2$ части, сколько магнитов получится?', ans: 2, tol: 0.1, why: 'Каждая часть будет иметь свои $2$ полюса — получаем $2$ магнита.' },
  { q: 'Магнит разрезали на $5$ кусков. Сколько всего полюсов у всех кусков?', ans: 10, tol: 0.1, why: 'Каждый магнит имеет $2$ полюса. Всего: $5 \\cdot 2 = 10$.' },
  { q: 'У одного магнита N-полюс, у другого S-полюс. Они притягиваются или отталкиваются? ($1$ — притягиваются, $0$ — отталкиваются)', ans: 1, tol: 0.1, why: 'Разноимённые магнитные полюса притягиваются (как и разноимённые заряды).' },
  { q: 'Какой полюс у Земли находится около географического Северного полюса? ($1$ — северный магнитный, $2$ — южный магнитный)', ans: 2, tol: 0.1, why: 'Около географ. севера — южный магнитный полюс Земли (поэтому стрелка компаса N притягивается к нему).' },
],

p29: [  // Магнитное поле тока
  { q: 'Опыт Эрстеда: магнитная стрелка отклоняется при включении тока в проводнике. Это значит, что вокруг тока есть... ($1$ — электрическое поле, $2$ — магнитное поле, $3$ — гравитационное)', ans: 2, tol: 0.1, why: 'Вокруг любого тока существует магнитное поле — ключевое открытие Эрстеда (1820).' },
  { q: 'Линии магнитного поля прямого тока — это: ($1$ — прямые, $2$ — концентрические окружности вокруг проводника, $3$ — параболы)', ans: 2, tol: 0.1, why: 'Силовые линии магнитного поля прямого тока — концентрические окружности в плоскостях, перпендикулярных проводнику.' },
  { q: 'У одного провода ток $I_1 = 2$ А, у другого $I_2 = 8$ А. У какого индукция магнитного поля на одинаковом расстоянии больше во сколько раз? ($B \\propto I$)', ans: 4, tol: 0.1, why: '$B \\propto I$, поэтому $B_2/B_1 = I_2/I_1 = 8/2 = 4$ раза.' },
  { q: 'Сила, действующая на проводник с током в магнитном поле, при $I = 5$ А, $B = 0{,}2$ Тл, $L = 0{,}1$ м: $F = BIL$ (Н)?', ans: 0.1, tol: 0.005, why: '$F = BIL = 0{,}2 \\cdot 5 \\cdot 0{,}1 = 0{,}1$ Н.' },
  { q: 'Если ток в проводнике увеличить в $3$ раза, во сколько раз увеличится сила в магнитном поле?', ans: 3, tol: 0.1, why: '$F = BIL \\propto I$, поэтому $F$ увеличится в $3$ раза.' },
],

p30: [  // Опыт Эрстеда (в этом учебнике — продолжение)
  { q: 'В каком году Эрстед обнаружил магнитное действие тока?', ans: 1820, tol: 5, why: 'Х. Эрстед открыл связь электрического тока и магнетизма в 1820 году.' },
  { q: 'Стрелка компаса находится над проводником. Какой угол (в градусах) к проводнику она составит при отсутствии тока? ($1$ — $0°$, $2$ — $90°$)', ans: 1, tol: 0.1, why: 'Без тока стрелка направлена вдоль магнитного поля Земли. Над проводником, протянутым с севера на юг, стрелка $\\parallel$ проводнику ($0°$).' },
  { q: 'При включении тока стрелка отклоняется. Когда ток отключают, что произойдёт? ($1$ — останется, $2$ — вернётся в исходное положение)', ans: 2, tol: 0.1, why: 'Без тока магнитное поле проводника исчезает, на стрелку действует только поле Земли — она возвращается.' },
  { q: 'Правило буравчика: если ток течёт вверх, в каком направлении вращаются силовые линии магн. поля? ($1$ — по часовой при взгляде сверху, $2$ — против часовой при взгляде сверху)', ans: 2, tol: 0.1, why: 'Правило правой руки: большой палец — направление тока, согнутые пальцы показывают направление поля. При токе вверх — против часовой при взгляде сверху.' },
  { q: 'Сила тока удвоилась. Во сколько раз сильнее отклонится магнитная стрелка (приближённо)?', ans: 2, tol: 0.1, why: 'Магнитное поле $B \\propto I$, отклонение стрелки тоже растёт примерно линейно — в $2$ раза.' },
],

p31: [  // Электромагнит
  { q: 'У электромагнита было $N_1 = 100$ витков, его магнитное поле $B_1$. После добавления стало $N_2 = 500$ витков (тот же ток). Во сколько раз вырастет $B$?', ans: 5, tol: 0.2, why: '$B \\propto N$, поэтому $B_2/B_1 = N_2/N_1 = 5$.' },
  { q: 'Ток в катушке вырос с $I_1 = 0{,}2$ А до $I_2 = 1$ А. Во сколько раз увеличилось магнитное поле электромагнита?', ans: 5, tol: 0.2, why: '$B \\propto I$, поэтому $B_2/B_1 = I_2/I_1 = 5$.' },
  { q: 'Без сердечника поле электромагнита $B_0 = 1$ мТл. С железным сердечником стало $B = 1000$ мТл. Во сколько раз сердечник усилил поле?', ans: 1000, tol: 10, why: 'Железо имеет магнитную проницаемость $\\mu \\sim 1000$. $B/B_0 = 1000$.' },
  { q: 'Электромагнит подняет груз массой $m = 50$ кг с силой $F = 500$ Н. Какова перегрузка $F/(mg)$? ($g = 10$ м/с²)', ans: 1, tol: 0.05, why: '$F/(mg) = 500/(50 \\cdot 10) = 500/500 = 1$ — сила в точности уравновешивает вес.' },
  { q: 'Если ток отключить, что произойдёт с магн. полем электромагнита? ($1$ — останется, $0$ — исчезнет)', ans: 0, tol: 0.1, why: 'Магнитное поле электромагнита создаётся током. Нет тока — нет поля. (В отличие от постоянного магнита.)' },
],

// === Ch3: Световые явления ===

p32: [  // Источники света
  { q: 'Скорость света в вакууме $c = 3 \\cdot 10^{8}$ м/с. За какое время (мкс) свет пройдёт $L = 300$ км?', ans: 1000, tol: 10, why: '$t = L/c = 3 \\cdot 10^{5} / 3 \\cdot 10^{8} = 10^{-3}$ с $= 1000$ мкс.' },
  { q: 'Свет от Солнца достигает Земли за $t = 500$ с. Какое расстояние (в км)? Ответ $\\times 10^{8}$.', ans: 1.5, tol: 0.05, why: '$L = ct = 3 \\cdot 10^{8} \\cdot 500 = 1{,}5 \\cdot 10^{11}$ м $= 1{,}5 \\cdot 10^{8}$ км.' },
  { q: 'Сколько секунд лётит свет от Луны до Земли, если расстояние $L = 384\\,000$ км?', ans: 1.28, tol: 0.05, why: '$t = L/c = 3{,}84 \\cdot 10^{8} / 3 \\cdot 10^{8} = 1{,}28$ с.' },
  { q: 'Свет звезды доходит до нас за $4$ года. Сколько $4$ световых лет в км? Ответ $\\times 10^{13}$.', ans: 3.78, tol: 0.05, why: '$1$ год $\\approx 3{,}15 \\cdot 10^{7}$ с. $L = c \\cdot 4 \\cdot 3{,}15 \\cdot 10^{7} = 3{,}78 \\cdot 10^{16}$ м $= 3{,}78 \\cdot 10^{13}$ км.' },
  { q: 'Какой из источников света — точечный с практической точки зрения: ($1$ — Солнце на небе для нас, $2$ — лампа в комнате с метра, $3$ — звезда)?', ans: 3, tol: 0.1, why: 'Звёзды настолько далеки, что их можно считать точечными источниками света. Солнце и лампа — нет.' },
],

p39: [  // §39 в ch3 — обычно «Глаз / Дисперсия / Оптические приборы»
  { q: 'Из скольких основных цветов состоит спектр белого света (радуга)?', ans: 7, tol: 0.1, why: '$7$ цветов: красный, оранжевый, жёлтый, зелёный, голубой, синий, фиолетовый.' },
  { q: 'У какого цвета света наибольшая длина волны: ($1$ — красный, $2$ — синий, $3$ — фиолетовый, $4$ — зелёный)?', ans: 1, tol: 0.1, why: 'Красный свет имеет наибольшую длину волны ($\\sim 700$ нм) среди видимого спектра.' },
  { q: 'У какого цвета света наименьшая длина волны: ($1$ — красный, $2$ — жёлтый, $3$ — зелёный, $4$ — фиолетовый)?', ans: 4, tol: 0.1, why: 'Фиолетовый свет имеет наименьшую длину волны ($\\sim 400$ нм).' },
  { q: 'Линза с фокусом $F = 25$ см. Оптическая сила $D = 1/F$ (дптр). Найдите $D$ при $F$ в метрах.', ans: 4, tol: 0.1, why: '$F = 0{,}25$ м, $D = 1/F = 1/0{,}25 = 4$ дптр.' },
  { q: 'У близорукого человека очки $-2$ дптр. Найдите фокусное расстояние линзы $F$ в м.', ans: -0.5, tol: 0.02, why: '$F = 1/D = 1/(-2) = -0{,}5$ м (рассеивающая линза).' },
],

};

// === Generate IV-5 widget HTML + initializer function per pid ===
function makeIv5Widget(pid) {
  return `
  /* IV5 — Расчётные задачи (auto-injected) */
  h += '<div class="wg">'
    +'<div class="wg-header"><span class="wg-badge">IV-5</span><div class="wg-title">Тренажёр: ${TASKS[pid].length} расчётных задач</div></div>'
    +'<div class="wg-help">Введи числовой ответ (точка как разделитель). Решено все верно — +20 XP.</div>'
    +'<div id="${pid}-tasks5"></div>'
    +'<div class="score-display" style="margin-top:10px"><span>Задача: <b id="${pid}-tasks5-i">1</b> / ${TASKS[pid].length}</span><span>Правильно: <b id="${pid}-tasks5-ok">0</b></span></div>'
    +'</div>';
`;
}

function makeIv5Init(pid) {
  const tasksLit = JSON.stringify(TASKS[pid]);
  return `
function _init${pid}_iv5(){
  const TASKS = ${tasksLit};
  let i = 0, ok = 0, awarded = false;
  function render(){
    const t = TASKS[i]; const wrap = document.getElementById('${pid}-tasks5'); if(!wrap) return;
    wrap.innerHTML =
      '<div style="padding:10px 14px;background:rgba(15,23,42,.04);border-radius:9px;margin-bottom:10px;font-size:.95rem;line-height:1.55"><b>Задача '+(i+1)+'.</b> '+t.q+'</div>'
      +'<div class="actions"><input type="number" step="0.001" class="tinp" id="${pid}-iv5-inp" placeholder="число" style="width:140px">'
      +'<button class="btn primary" id="${pid}-iv5-go">Ответ</button>'
      +'<button class="btn" id="${pid}-iv5-hint">Подсказка</button>'
      +'<button class="btn" id="${pid}-iv5-next">Следующая</button></div>'
      +'<details class="spoiler" id="${pid}-iv5-why-wrap" style="margin-top:8px;display:none"><summary>Решение</summary><div class="spoiler-body">'+t.why+'</div></details>'
      +'<div class="feedback" id="${pid}-iv5-fb"></div>';
    if (window.renderMathInElement) try { renderMathInElement(wrap, {delimiters:[{left:'$',right:'$',display:false}],throwOnError:false}); } catch(e){}
    document.getElementById('${pid}-iv5-go').onclick = () => {
      const v = parseFloat(document.getElementById('${pid}-iv5-inp').value.replace(',','.'));
      const fb = document.getElementById('${pid}-iv5-fb');
      const wh = document.getElementById('${pid}-iv5-why-wrap');
      if (Math.abs(v - t.ans) <= t.tol) {
        fb.className = 'feedback ok'; fb.innerHTML = 'Верно!'; ok++;
        document.getElementById('${pid}-tasks5-ok').textContent = ok;
        wh.style.display = 'block';
      } else {
        fb.className = 'feedback fail'; fb.innerHTML = 'Не совсем. Ожидался $' + t.ans + '$. Загляни в подсказку.';
        if (window.renderMathInElement) try { renderMathInElement(fb, {delimiters:[{left:'$',right:'$',display:false}],throwOnError:false}); } catch(e){}
      }
    };
    document.getElementById('${pid}-iv5-hint').onclick = () => {
      const wh = document.getElementById('${pid}-iv5-why-wrap');
      wh.style.display = wh.style.display === 'block' ? 'none' : 'block';
    };
    document.getElementById('${pid}-iv5-next').onclick = () => {
      i = (i + 1) % TASKS.length;
      document.getElementById('${pid}-tasks5-i').textContent = i + 1;
      render();
      if (ok === TASKS.length && !awarded) { awarded = true; if (typeof addXp === 'function') addXp(20, '${pid}-iv5'); }
    };
  }
  render();
}
`;
}

// === Patch chapter file ===
function patchChapter(fname, pids) {
  const dst = path.join(TBOOKS, fname);
  let h = fs.readFileSync(dst, 'utf8');
  let patched = 0;
  for (const pid of pids) {
    if (!TASKS[pid]) { console.warn(`  ${pid}: no task data`); continue; }
    const widget = makeIv5Widget(pid);
    const init = makeIv5Init(pid);

    const insertWidgetBefore = `box.innerHTML = h + secNavFor('${pid}') + readButton('${pid}');`;
    if (!h.includes(insertWidgetBefore)) {
      console.warn(`  ${pid}: insert marker not found`);
      continue;
    }
    // Check if already injected
    if (h.includes(`id="${pid}-tasks5"`)) {
      console.log(`  ${pid}: already injected, skip`);
      continue;
    }

    h = h.replace(insertWidgetBefore, widget.trim() + '\n\n  ' + insertWidgetBefore);
    const wireMarker = `wireReadBtn('${pid}');`;
    h = h.replace(wireMarker, wireMarker + `\n  _init${pid}_iv5();`);

    const fnStart = h.indexOf(`function build_${pid}()`);
    const fnEnd = h.indexOf('\n}\n', fnStart);
    const insertPos = fnEnd + 3;
    h = h.slice(0, insertPos) + '\n' + init.trim() + '\n' + h.slice(insertPos);
    patched++;
    console.log(`  ${pid}: patched (${TASKS[pid].length} tasks)`);
  }
  fs.writeFileSync(dst, h);
  console.log(`${fname}: ${patched}/${pids.length} patched, ${h.length} bytes`);
  // Sanity parse
  const scripts = [...h.matchAll(/<script>([\s\S]*?)<\/script>/g)];
  for (const m of scripts) {
    try { new Function(m[1]); }
    catch(e) { console.error(`JS PARSE FAIL in ${fname}:`, e.message); process.exit(1); }
  }
  console.log(`${fname}: inline JS parses OK`);
}

console.log('=== physics_8_ch2.html ===');
patchChapter('physics_8_ch2.html', ['p12','p13','p14','p16','p17','p19','p21','p28','p29','p30','p31']);
console.log('=== physics_8_ch3.html ===');
patchChapter('physics_8_ch3.html', ['p32','p39']);
