// Физика 7 · Глава 2 «Строение вещества» · виджеты §§8–13 + финал (Wave 1+2+3).
// Экспорт: window.PHYS7_CH2_WIDGETS = { p8, p9, p10, p11, p12, p13, final2 }.
// Палитра главы — violet (#7c3aed).

(function(){
'use strict';

const ACCENT = '#7c3aed';
const ACCENT_D = '#5b21b6';
const ACCENT_SOFT = '#ede9fe';

function renderMath(root){
  if(window.renderMathInElement){
    try{
      window.renderMathInElement(root, {
        delimiters: [{left:'$$',right:'$$',display:true},{left:'$',right:'$',display:false}],
        throwOnError: false
      });
    }catch(e){}
  }
}

function makeCard(kind, title, badge, body){
  const colorByKind = { theory:ACCENT, rule:'#dc2626', example:'#10b981' };
  const labelByKind = { theory:'Теория', rule:'Правило', example:'Пример' };
  const c = colorByKind[kind] || ACCENT;
  return '<div style="background:#fff;border:1.5px solid ' + ACCENT_SOFT + ';border-left:5px solid ' + c + ';border-radius:11px;padding:14px 16px;margin-bottom:14px;box-shadow:0 2px 8px rgba(0,0,0,.05)">'
    + '<div style="display:flex;align-items:center;gap:10px;margin-bottom:8px;flex-wrap:wrap">'
    +   '<span style="background:' + c + ';color:#fff;padding:3px 10px;border-radius:99px;font-size:.7rem;font-weight:800;text-transform:uppercase;letter-spacing:.05em">' + labelByKind[kind] + '</span>'
    +   '<span style="font-size:.72rem;font-weight:700;color:#64748b;letter-spacing:.04em">' + (badge||'') + '</span>'
    +   '<span style="font-family:Unbounded,sans-serif;font-weight:800;font-size:.96rem;color:#0f172a;flex:1;min-width:0">' + title + '</span>'
    + '</div>'
    + '<div style="font-size:.94rem;line-height:1.6;color:#0f172a">' + body + '</div>'
    + '</div>';
}

function wgWrap(id, badge, title, hint, body){
  return '<div id="' + id + '" style="background:#fff;border:1.5px solid ' + ACCENT_SOFT + ';border-radius:12px;padding:14px 16px;margin-bottom:14px;box-shadow:0 2px 8px rgba(0,0,0,.05)">'
    + '<div style="display:flex;align-items:center;gap:10px;margin-bottom:8px;flex-wrap:wrap">'
    +   '<span style="background:' + ACCENT + ';color:#fff;padding:3px 10px;border-radius:99px;font-size:.7rem;font-weight:800;letter-spacing:.05em">' + badge + '</span>'
    +   '<span style="font-family:Unbounded,sans-serif;font-weight:800;font-size:.92rem;color:#0f172a">' + title + '</span>'
    + '</div>'
    + (hint ? '<div style="font-size:.84rem;color:#64748b;background:' + ACCENT_SOFT + ';border-left:3px solid ' + ACCENT + ';border-radius:6px;padding:8px 12px;margin-bottom:10px;line-height:1.5">' + hint + '</div>' : '')
    + body
    + '</div>';
}

function readButton(pid){
  return '<div style="text-align:center;margin-top:18px"><button class="ph7-read-btn" data-pid="' + pid + '" '
    + 'style="background:linear-gradient(135deg,#10b981,#047857);color:#fff;border:none;padding:11px 22px;border-radius:11px;font-weight:700;font-size:.92rem;cursor:pointer;font-family:inherit;display:inline-flex;align-items:center;gap:8px;box-shadow:0 4px 14px rgba(16,185,129,.32)">'
    + '<svg viewBox="0 0 24 24" style="width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round"><polyline points="20 6 9 17 4 12"/></svg>'
    + 'Я прочитал §  &nbsp;<span style="opacity:.85;font-size:.86rem">+10 XP</span>'
    + '</button></div>';
}

function wireReadBtn(pid){
  const btn = document.querySelector('.ph7-read-btn[data-pid="' + pid + '"]');
  if(!btn) return;
  const KEY = 'physics7_ch2_read_' + pid;
  if(localStorage.getItem(KEY) === '1'){
    btn.innerHTML = '<svg viewBox="0 0 24 24" style="width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round"><polyline points="20 6 9 17 4 12"/></svg> Прочитано';
    btn.disabled = true; btn.style.background = '#94a3b8'; btn.style.cursor = 'default';
    return;
  }
  btn.addEventListener('click', function(){
    if(localStorage.getItem(KEY) === '1') return;
    localStorage.setItem(KEY, '1');
    if(typeof window.bumpProgress === 'function') window.bumpProgress(pid, 30);
    if(typeof window.addXp === 'function') window.addXp(10, 'read-' + pid);
    btn.innerHTML = '<svg viewBox="0 0 24 24" style="width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round"><polyline points="20 6 9 17 4 12"/></svg> Прочитано';
    btn.disabled = true; btn.style.background = '#94a3b8'; btn.style.cursor = 'default';
  });
}

function wireDnd(host, items){
  const root = document.getElementById(host);
  if(!root) return;
  const checkBtn = root.querySelector('.dnd-check');
  const fb = root.querySelector('.dnd-fb');
  let placed = {};
  let armed = null;
  root.querySelectorAll('.dnd-chip').forEach(chip => chip.addEventListener('click', () => {
    if(armed === chip){ armed.classList.remove('armed'); armed.style.boxShadow = ''; armed = null; return; }
    if(armed){ armed.classList.remove('armed'); armed.style.boxShadow = ''; }
    armed = chip;
    chip.classList.add('armed');
    chip.style.boxShadow = '0 0 0 3px rgba(124,58,237,.3)';
  }));
  root.querySelectorAll('.drop-box').forEach(box => box.addEventListener('click', () => {
    if(!armed) return;
    const cat = box.dataset.cat;
    const id = armed.dataset.id;
    placed[id] = cat;
    const inner = box.querySelector('.drop-items');
    const clone = armed.cloneNode(true);
    clone.classList.remove('armed'); clone.classList.add('placed');
    clone.style.background = ACCENT_SOFT; clone.style.borderColor = ACCENT; clone.style.boxShadow = '';
    clone.addEventListener('click', e => {
      e.stopPropagation();
      delete placed[id];
      clone.remove();
      armed = null;
      const orig = root.querySelector('.dnd-chip[data-id="' + id + '"]:not(.placed)');
      if(orig) orig.style.display = '';
    });
    inner.appendChild(clone);
    armed.style.display = 'none';
    armed.classList.remove('armed'); armed.style.boxShadow = '';
    armed = null;
  }));
  if(checkBtn) checkBtn.addEventListener('click', () => {
    const total = items.length;
    let correct = 0;
    items.forEach(it => { if(placed[it.id] === it.cat) correct++; });
    fb.style.display = 'block';
    if(correct === total){
      fb.style.background = '#d1fae5'; fb.style.color = '#065f46'; fb.style.borderLeft = '4px solid #10b981';
      fb.innerHTML = '&#10003; Идеально! Все ' + total + ' карточек на своих местах.';
      if(typeof window.addXp === 'function') window.addXp(15, 'dnd-' + host);
    } else {
      fb.style.background = '#fee2e2'; fb.style.color = '#7f1d1d'; fb.style.borderLeft = '4px solid #dc2626';
      fb.innerHTML = '&#10007; Правильно: ' + correct + '/' + total + '. Попробуй ещё раз.';
    }
  });
}

function dndPool(host, items, cats){
  const chips = items.map(it => '<button class="dnd-chip" data-id="' + it.id + '" type="button" style="background:#fff;border:1.5px solid ' + ACCENT_SOFT + ';border-radius:10px;padding:7px 13px;cursor:pointer;font-size:.9rem;font-family:inherit;transition:all .15s">' + it.html + '</button>').join('');
  const boxes = cats.map(c => '<div class="drop-box" data-cat="' + c.cat + '" style="background:#fff;border:1.5px dashed ' + ACCENT_SOFT + ';border-radius:10px;padding:10px;min-height:80px"><h5 style="font-family:Unbounded,sans-serif;font-size:.76rem;color:' + ACCENT_D + ';margin-bottom:8px;text-transform:uppercase;letter-spacing:.04em">' + c.label + '</h5><div class="drop-items" style="display:flex;flex-wrap:wrap;gap:6px;min-height:32px"></div></div>').join('');
  return '<div id="' + host + '" class="dnd-host">'
    + '<div style="font-size:.86rem;color:#475569;margin-bottom:10px">Кликни по карточке, потом — на корзину. Чтобы вернуть: кликни по карточке в корзине.</div>'
    + '<div style="display:flex;flex-wrap:wrap;gap:8px;margin-bottom:14px;padding:10px;border:1.5px dashed ' + ACCENT_SOFT + ';border-radius:10px;background:#faf5ff">' + chips + '</div>'
    + '<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));gap:10px;margin-bottom:12px">' + boxes + '</div>'
    + '<div style="display:flex;gap:8px"><button class="dnd-check" type="button" style="background:linear-gradient(135deg,' + ACCENT + ',' + ACCENT_D + ');color:#fff;border:none;padding:9px 18px;border-radius:9px;font-weight:700;font-size:.86rem;cursor:pointer;font-family:inherit">Проверить</button></div>'
    + '<div class="dnd-fb" style="padding:10px 14px;border-radius:9px;font-weight:600;font-size:.88rem;margin-top:8px;display:none;line-height:1.45"></div>'
    + '</div>';
}

function quizQuestion(host, idx, q, opts, correctIdx, explain){
  const optsHtml = opts.map((o,i) => '<button class="qz-opt" data-i="' + i + '" type="button" style="background:#fff;border:1.5px solid ' + ACCENT_SOFT + ';border-radius:9px;padding:9px 14px;cursor:pointer;font-size:.92rem;font-family:inherit;text-align:left;width:100%;margin-bottom:6px">' + o + '</button>').join('');
  return '<div class="qz-q" data-idx="' + idx + '" style="background:' + ACCENT_SOFT + ';border:1.5px solid ' + ACCENT_SOFT + ';border-radius:10px;padding:12px 14px;margin-bottom:10px">'
    + '<div style="font-weight:700;margin-bottom:8px;font-size:.94rem">' + (idx+1) + '. ' + q + '</div>'
    + '<div class="qz-opts" data-correct="' + correctIdx + '" data-explain="' + (explain||'').replace(/"/g,'&quot;') + '">' + optsHtml + '</div>'
    + '<div class="qz-fb" style="padding:9px 12px;border-radius:8px;font-size:.86rem;margin-top:6px;display:none;line-height:1.45"></div>'
    + '</div>';
}

function wireQuiz(host, onAllCorrect){
  const root = document.getElementById(host);
  if(!root) return;
  const all = root.querySelectorAll('.qz-q');
  const done = new Set();
  all.forEach(qDiv => {
    const opts = qDiv.querySelectorAll('.qz-opt');
    const correct = +qDiv.querySelector('.qz-opts').dataset.correct;
    const explain = qDiv.querySelector('.qz-opts').dataset.explain;
    const fb = qDiv.querySelector('.qz-fb');
    opts.forEach(o => o.addEventListener('click', () => {
      if(done.has(qDiv)) return;
      const i = +o.dataset.i;
      opts.forEach(x => x.disabled = true);
      if(i === correct){
        o.style.background = '#d1fae5'; o.style.borderColor = '#10b981'; o.style.color = '#065f46';
        fb.style.display = 'block'; fb.style.background = '#d1fae5'; fb.style.color = '#065f46'; fb.style.borderLeft = '4px solid #10b981';
        fb.innerHTML = '&#10003; Верно!' + (explain ? ' ' + explain : '');
        done.add(qDiv);
        if(done.size === all.length && typeof onAllCorrect === 'function') onAllCorrect();
      } else {
        o.style.background = '#fee2e2'; o.style.borderColor = '#dc2626'; o.style.color = '#7f1d1d';
        opts[correct].style.background = '#d1fae5'; opts[correct].style.borderColor = '#10b981'; opts[correct].style.color = '#065f46';
        fb.style.display = 'block'; fb.style.background = '#fee2e2'; fb.style.color = '#7f1d1d'; fb.style.borderLeft = '4px solid #dc2626';
        fb.innerHTML = '&#10007; Неверно. Правильно: «' + opts[correct].textContent + '».' + (explain ? ' ' + explain : '');
        done.add(qDiv);
      }
    }));
  });
}

/* ========================================================== */
/* §8 — Дискретное строение вещества                          */
/* ========================================================== */
function add_p8(){
  const body = document.getElementById('p8-body');
  if(!body) return;
  let h = '';

  h += makeCard('theory', 'Из чего состоит вещество', '§ 8.1',
    'Все вещества состоят из <b>мельчайших частиц</b> — <b>молекул</b> и <b>атомов</b>. '
    + 'Они так малы, что не видны даже в обычный микроскоп. Между частицами есть <b>промежутки</b>. '
    + 'Молекула — это наименьшая частица вещества, сохраняющая его химические свойства. '
    + 'Молекулы состоят из <b>атомов</b>.');

  h += makeCard('rule', 'Размеры частиц', '§ 8.2',
    'Типичный диаметр молекулы — около $10^{-10}$ м. Сравни:'
    + '<table style="width:100%;border-collapse:collapse;margin-top:6px;font-size:.92rem">'
    + '<tr style="background:' + ACCENT_SOFT + '"><th style="padding:6px 10px;text-align:left;border-bottom:2px solid ' + ACCENT + '">Объект</th><th style="padding:6px 10px;text-align:right;border-bottom:2px solid ' + ACCENT + '">Размер</th></tr>'
    + [['Зерно мака','1 мм $= 10^{-3}$ м'],['Толщина волоса','$\\approx 10^{-4}$ м'],['Бактерия','$\\approx 10^{-6}$ м'],['Молекула','$\\approx 10^{-10}$ м'],['Атом','$\\approx 10^{-10}$ м'],['Ядро атома','$\\approx 10^{-15}$ м']].map(([nm, sz]) =>
        '<tr><td style="padding:5px 10px;border-bottom:1px solid ' + ACCENT_SOFT + '">' + nm + '</td><td style="padding:5px 10px;text-align:right;border-bottom:1px solid ' + ACCENT_SOFT + ';font-family:JetBrains Mono,monospace">' + sz + '</td></tr>').join('')
    + '</table>');

  h += makeCard('example', 'Доказательства дискретности', '§ 8.3',
    '<ol style="padding-left:20px;margin:6px 0;line-height:1.7">'
    + '<li><b>Сжимаемость газов</b> — при сдавливании поршнем объём уменьшается → есть пустоты между молекулами.</li>'
    + '<li><b>Растворение сахара в воде</b> — молекулы сахара заполняют промежутки между молекулами воды; уровень почти не поднимается.</li>'
    + '<li><b>Расширение тел при нагреве</b> — увеличиваются промежутки между частицами.</li>'
    + '</ol>');

  /* IV-1: визуал-масштабы */
  h += wgWrap('p8-iv1', 'СИМ', 'Шкала размеров', 'От огромного к крошечному (логарифмическая шкала).',
    '<div style="display:flex;flex-direction:column;gap:6px">'
    + [['1 м','Человек','#0284c7',1],['0,01 м','Монета','#10b981',0.85],['0,001 м','Зерно мака','#d97706',0.7],['10⁻⁴ м','Волос (толщина)','#dc2626',0.55],['10⁻⁶ м','Бактерия','#7c3aed',0.4],['10⁻⁸ м','Вирус','#0891b2',0.25],['10⁻¹⁰ м','Молекула','#92400e',0.12],['10⁻¹⁵ м','Ядро атома','#374151',0.05]].map(([sz, nm, col, w]) =>
      '<div style="display:flex;align-items:center;gap:10px;background:#faf5ff;border-radius:8px;padding:6px 10px">'
      + '<div style="font-family:JetBrains Mono,monospace;font-weight:700;color:' + col + ';min-width:64px;font-size:.86rem">' + sz + '</div>'
      + '<div style="flex:1;height:18px;background:#fff;border:1px solid ' + ACCENT_SOFT + ';border-radius:4px;overflow:hidden"><div style="height:100%;width:' + (w*100) + '%;background:linear-gradient(90deg,' + col + ',' + col + '88)"></div></div>'
      + '<div style="font-size:.86rem;color:#475569;min-width:120px">' + nm + '</div>'
      + '</div>').join('')
    + '</div>');

  /* IV-2: конструктор молекулы */
  h += wgWrap('p8-iv2', 'СИМ', 'Конструктор молекулы', 'Выбери — увидь схему молекулы из атомов.',
    '<div style="display:flex;gap:8px;flex-wrap:wrap;margin-bottom:12px">'
    + ['H2O','CO2','O2','N2','CH4','NaCl'].map(m =>
        '<button class="p8-mol" data-m="' + m + '" type="button" style="background:#fff;border:1.5px solid ' + ACCENT_SOFT + ';border-radius:8px;padding:7px 14px;cursor:pointer;font-family:JetBrains Mono,monospace;font-weight:700;font-size:.9rem">' + m + '</button>').join('')
    + '</div>'
    + '<svg id="p8-mol-svg" viewBox="0 0 320 130" width="100%" style="max-width:400px;display:block;margin:0 auto;background:#faf5ff;border-radius:9px;border:1px solid ' + ACCENT_SOFT + '"></svg>'
    + '<div id="p8-mol-desc" style="text-align:center;font-size:.88rem;color:#475569;margin-top:8px"></div>');

  /* IV-3: DnD */
  h += wgWrap('p8-iv3', 'DnD', 'Атом / молекула / тело', 'Распредели понятия по корзинам.',
    dndPool('p8-dnd', [
      { id:'a1', cat:'atom', html:'Атом водорода H' },
      { id:'a2', cat:'atom', html:'Атом кислорода O' },
      { id:'a3', cat:'mol',  html:'Молекула воды H₂O' },
      { id:'a4', cat:'mol',  html:'Молекула CO₂' },
      { id:'a5', cat:'body', html:'Капля воды' },
      { id:'a6', cat:'body', html:'Резиновый мяч' },
      { id:'a7', cat:'atom', html:'Атом железа Fe' },
      { id:'a8', cat:'mol',  html:'Молекула O₂' }
    ], [
      { cat:'atom', label:'Атом' },
      { cat:'mol',  label:'Молекула' },
      { cat:'body', label:'Тело' }
    ]));

  /* IV-4: тренажёр */
  h += wgWrap('p8-iv4', 'ТРН', 'Тренажёр §8', '5 вопросов на закрепление.',
    '<div id="p8-tr-host">'
    + quizQuestion('p8-tr', 0, 'Каков примерный диаметр молекулы воды?', ['$10^{-3}$ м','$10^{-6}$ м','$10^{-10}$ м','$10^{-15}$ м'], 2, 'Молекулы — порядка $10^{-10}$ м (десятая часть нанометра).')
    + quizQuestion('p8-tr', 1, 'Что меньше: молекула или ядро атома?', ['Молекула','Ядро атома','Они одинаковые','Зависит от вещества'], 1, 'Ядро в $\\sim 10^5$ раз меньше атома.')
    + quizQuestion('p8-tr', 2, 'Почему газы легко сжимаются?', ['Молекулы мягкие','Между молекулами большие промежутки','Газ не имеет молекул','Молекулы скользят'], 1)
    + quizQuestion('p8-tr', 3, 'Молекула — это…', ['Видимая частица','Наименьшая частица, сохраняющая свойства вещества','Атом','Кристалл'], 1)
    + quizQuestion('p8-tr', 4, 'Из чего состоят молекулы?', ['Из электронов','Из протонов','Из атомов','Из ядер'], 2)
    + '</div>');

  h += readButton('p8');
  body.innerHTML = h;

  // Wire molecule constructor
  const molData = {
    'H2O': { atoms:[{x:160,y:65,r:18,c:'#dc2626',l:'O'},{x:120,y:90,r:11,c:'#fff',l:'H',stroke:'#94a3b8'},{x:200,y:90,r:11,c:'#fff',l:'H',stroke:'#94a3b8'}], bonds:[[0,1],[0,2]], desc:'H₂O (вода): 1 атом кислорода + 2 атома водорода под углом 104,5°.' },
    'CO2': { atoms:[{x:160,y:65,r:14,c:'#0f172a',l:'C'},{x:100,y:65,r:18,c:'#dc2626',l:'O'},{x:220,y:65,r:18,c:'#dc2626',l:'O'}], bonds:[[0,1],[0,2]], desc:'CO₂ (углекислый газ): углерод между двумя кислородами, молекула линейная.' },
    'O2':  { atoms:[{x:120,y:65,r:18,c:'#dc2626',l:'O'},{x:200,y:65,r:18,c:'#dc2626',l:'O'}], bonds:[[0,1]], desc:'O₂ (кислород): два атома кислорода. Этим воздухом мы дышим.' },
    'N2':  { atoms:[{x:120,y:65,r:18,c:'#0891b2',l:'N'},{x:200,y:65,r:18,c:'#0891b2',l:'N'}], bonds:[[0,1]], desc:'N₂ (азот): два атома азота. 78 % воздуха — это N₂.' },
    'CH4': { atoms:[{x:160,y:65,r:14,c:'#0f172a',l:'C'},{x:160,y:30,r:11,c:'#fff',l:'H',stroke:'#94a3b8'},{x:160,y:100,r:11,c:'#fff',l:'H',stroke:'#94a3b8'},{x:110,y:65,r:11,c:'#fff',l:'H',stroke:'#94a3b8'},{x:210,y:65,r:11,c:'#fff',l:'H',stroke:'#94a3b8'}], bonds:[[0,1],[0,2],[0,3],[0,4]], desc:'CH₄ (метан): углерод в центре, 4 водорода по углам тетраэдра. Природный газ.' },
    'NaCl':{ atoms:[{x:130,y:65,r:18,c:'#7c3aed',l:'Na'},{x:200,y:65,r:18,c:'#10b981',l:'Cl'}], bonds:[[0,1]], desc:'NaCl (поваренная соль): натрий + хлор. В твёрдом виде образует кубическую решётку.' }
  };
  function drawMol(m){
    const d = molData[m];
    let s = '';
    d.bonds.forEach(([i,j]) => {
      s += '<line x1="' + d.atoms[i].x + '" y1="' + d.atoms[i].y + '" x2="' + d.atoms[j].x + '" y2="' + d.atoms[j].y + '" stroke="#475569" stroke-width="3"/>';
    });
    d.atoms.forEach(a => {
      s += '<circle cx="' + a.x + '" cy="' + a.y + '" r="' + a.r + '" fill="' + a.c + '" stroke="' + (a.stroke || a.c) + '" stroke-width="1.5"/>';
      s += '<text x="' + a.x + '" y="' + (a.y + 4) + '" text-anchor="middle" font-family="Inter,sans-serif" font-size="11" font-weight="700" fill="' + (a.c === '#fff' ? '#0f172a' : '#fff') + '">' + a.l + '</text>';
    });
    document.getElementById('p8-mol-svg').innerHTML = s;
    document.getElementById('p8-mol-desc').textContent = d.desc;
  }
  body.querySelectorAll('.p8-mol').forEach(btn => btn.addEventListener('click', () => {
    body.querySelectorAll('.p8-mol').forEach(b => { b.style.background = '#fff'; b.style.color = '#0f172a'; });
    btn.style.background = ACCENT; btn.style.color = '#fff';
    drawMol(btn.dataset.m);
  }));
  drawMol('H2O');
  body.querySelector('.p8-mol[data-m="H2O"]').style.background = ACCENT;
  body.querySelector('.p8-mol[data-m="H2O"]').style.color = '#fff';

  wireDnd('p8-dnd', [
    { id:'a1', cat:'atom' },{ id:'a2', cat:'atom' },{ id:'a3', cat:'mol' },{ id:'a4', cat:'mol' },
    { id:'a5', cat:'body' },{ id:'a6', cat:'body' },{ id:'a7', cat:'atom' },{ id:'a8', cat:'mol' }
  ]);
  wireQuiz('p8-tr-host', () => { if(window.addXp) window.addXp(15, 'tr-p8'); });
  wireReadBtn('p8');
  renderMath(body);
}

/* ========================================================== */
/* §9 — Тепловое движение частиц. Диффузия                    */
/* ========================================================== */
function add_p9(){
  const body = document.getElementById('p9-body');
  if(!body) return;
  let h = '';

  h += makeCard('theory', 'Молекулы вечно движутся', '§ 9.1',
    'Молекулы любого тела находятся в <b>непрерывном беспорядочном (хаотическом) движении</b>. '
    + 'Это движение называется <b>тепловым</b>: чем выше температура, тем быстрее движутся частицы.<br><br>'
    + 'Доказательство — <b>броуновское движение</b>: мельчайшие частицы в воде (пыльца, тушь) непрерывно дёргаются под ударами молекул.');

  h += makeCard('rule', 'Диффузия', '§ 9.2',
    '<b>Диффузия</b> — это самопроизвольное взаимное проникновение молекул одного вещества между молекулами другого.<br><br>'
    + 'Скорость диффузии зависит от:'
    + '<ul style="padding-left:20px;margin:5px 0">'
    + '<li><b>температуры:</b> выше $T$ → быстрее диффузия;</li>'
    + '<li><b>состояния вещества:</b> в газах ⪢ в жидкостях ⪢ в твёрдых телах.</li>'
    + '</ul>');

  h += makeCard('example', 'Где мы видим диффузию', '§ 9.3',
    '<ul style="padding-left:20px;margin:6px 0">'
    + '<li><b>Запах</b> духов или пищи распространяется по комнате — диффузия в воздухе.</li>'
    + '<li><b>Чай</b> завариваеётся быстрее в горячей воде — молекулы чая активно перемешиваются.</li>'
    + '<li><b>Засолка</b> огурцов идёт долго — диффузия в жидкости медленнее, чем в газе.</li>'
    + '<li><b>Сварка</b> металлов на самом деле — диффузия атомов в твёрдом теле, очень медленная.</li>'
    + '</ul>');

  /* IV-1: симуляция диффузии (свой простой газ) */
  h += wgWrap('p9-iv1', 'СИМ', 'Диффузия чернил в воде', 'Меняй температуру — наблюдай, как ускоряется смешивание.',
    '<div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:10px">'
    + '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">Температура $t$, °C: <b id="p9-T" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">20</b><input type="range" id="p9-T-r" min="0" max="90" step="1" value="20" style="display:block;width:100%;margin-top:6px;accent-color:' + ACCENT + '"></label>'
    + '<div style="display:flex;gap:6px;align-items:center;justify-content:flex-end;padding-top:6px"><button id="p9-reset" type="button" style="background:#fff;border:1.5px solid ' + ACCENT_SOFT + ';padding:8px 14px;border-radius:9px;cursor:pointer;font-family:inherit;font-weight:600">Сброс</button></div>'
    + '</div>'
    + '<svg id="p9-sim" viewBox="0 0 360 160" width="100%" style="max-width:600px;display:block;margin:0 auto;background:#cffafe;border-radius:9px;border:1px solid #67e8f9"></svg>'
    + '<div style="text-align:center;font-size:.86rem;color:#64748b;margin-top:6px">Синие молекулы — вода, тёмные — чернила. Видно, как чем теплее, тем быстрее они перемешиваются.</div>');

  /* IV-2: квиз */
  h += wgWrap('p9-iv2', 'КВИЗ', 'Про диффузию', 'Выбери верное.',
    '<div id="p9-q-host">'
    + quizQuestion('p9-q', 0, 'В каком веществе диффузия идёт быстрее всего?', ['В твёрдом','В жидком','В газообразном','Одинаково'], 2, 'В газах молекулы движутся быстрее и расстояния между ними больше.')
    + quizQuestion('p9-q', 1, 'Как ускорить заваривание чая?', ['Понизить температуру','Налить холодной воды','Налить горячей воды','Не размешивать'], 2)
    + quizQuestion('p9-q', 2, 'Что доказывает броуновское движение?', ['Что молекулы покоятся','Что молекулы движутся','Что молекулы видны','Что молекул нет'], 1)
    + '</div>');

  /* IV-3: DnD скорости */
  h += wgWrap('p9-iv3', 'DnD', 'Где диффузия быстрее?', 'Распредели 6 ситуаций.',
    dndPool('p9-dnd', [
      { id:'a1', cat:'fast', html:'Дым из костра в воздухе' },
      { id:'a2', cat:'fast', html:'Запах духов в комнате' },
      { id:'a3', cat:'med',  html:'Сахар в горячем чае' },
      { id:'a4', cat:'med',  html:'Раствор соли в воде' },
      { id:'a5', cat:'slow', html:'Сварка металлов' },
      { id:'a6', cat:'slow', html:'Свинцовая пломба со временем «врастает» в дерево' }
    ], [
      { cat:'fast', label:'Быстро (газ)' },
      { cat:'med',  label:'Средне (жидкость)' },
      { cat:'slow', label:'Медленно (твёрдое)' }
    ]));

  /* IV-4: тренажёр */
  h += wgWrap('p9-iv4', 'ТРН', 'Тренажёр §9', '5 вопросов.',
    '<div id="p9-tr-host">'
    + quizQuestion('p9-tr', 0, 'Тепловое движение — это…', ['Падение тел','Движение колеса','Хаотическое движение молекул','Движение звуковой волны'], 2)
    + quizQuestion('p9-tr', 1, 'При нагревании средняя скорость молекул…', ['Не меняется','Увеличивается','Уменьшается','Становится нулевой'], 1)
    + quizQuestion('p9-tr', 2, 'В каком случае диффузия пройдёт быстрее: в холодной или горячей воде?', ['В холодной','В горячей','Одинаково','Не зависит'], 1)
    + quizQuestion('p9-tr', 3, 'Через сколько примерно времени запах из открытого флакона духов распространится по комнате?', ['Доли секунды','За минуту-две','За сутки','За месяц'], 1, 'Диффузия в газе — относительно быстрая, но мгновенной не бывает.')
    + quizQuestion('p9-tr', 4, 'Броуновское движение — это движение…', ['Молекул','Атомов','Мельчайших видимых частиц под ударами молекул','Звуковых волн'], 2)
    + '</div>');

  h += readButton('p9');
  body.innerHTML = h;

  // Diffusion sim
  const sim = (function(){
    const W = 360, H = 160;
    const N = 60;
    const parts = [];
    function init(){
      parts.length = 0;
      for(let i = 0; i < N; i++){
        const isInk = i < 20;
        parts.push({
          x: isInk ? (40 + Math.random() * 60) : (Math.random() * W),
          y: isInk ? (40 + Math.random() * 60) : (Math.random() * H),
          vx: 0, vy: 0,
          ink: isInk
        });
      }
    }
    function step(T){
      const speed = 0.4 + T / 30; // px/frame
      parts.forEach(p => {
        p.vx += (Math.random() - 0.5) * speed * 0.6;
        p.vy += (Math.random() - 0.5) * speed * 0.6;
        p.vx *= 0.92; p.vy *= 0.92;
        p.x += p.vx; p.y += p.vy;
        if(p.x < 2){ p.x = 2; p.vx = -p.vx; }
        if(p.x > W-2){ p.x = W-2; p.vx = -p.vx; }
        if(p.y < 2){ p.y = 2; p.vy = -p.vy; }
        if(p.y > H-2){ p.y = H-2; p.vy = -p.vy; }
      });
    }
    function render(){
      const svg = document.getElementById('p9-sim');
      if(!svg) return false;
      let s = '';
      parts.forEach(p => {
        const c = p.ink ? '#0f172a' : '#3b82f6';
        s += '<circle cx="' + p.x.toFixed(1) + '" cy="' + p.y.toFixed(1) + '" r="' + (p.ink ? 3 : 2) + '" fill="' + c + '" opacity="' + (p.ink ? 0.9 : 0.55) + '"/>';
      });
      svg.innerHTML = s;
      return true;
    }
    return { init, step, render };
  })();
  let raf = 0;
  function loop(){
    const T = +document.getElementById('p9-T-r').value;
    sim.step(T);
    if(!sim.render()){ cancelAnimationFrame(raf); return; }
    raf = requestAnimationFrame(loop);
  }
  sim.init();
  raf = requestAnimationFrame(loop);
  document.getElementById('p9-T-r').addEventListener('input', () => {
    document.getElementById('p9-T').textContent = document.getElementById('p9-T-r').value;
  });
  document.getElementById('p9-reset').addEventListener('click', () => { sim.init(); });

  wireDnd('p9-dnd', [
    { id:'a1', cat:'fast' },{ id:'a2', cat:'fast' },{ id:'a3', cat:'med' },{ id:'a4', cat:'med' },
    { id:'a5', cat:'slow' },{ id:'a6', cat:'slow' }
  ]);
  wireQuiz('p9-q-host', () => { if(window.addXp) window.addXp(10, 'q-p9'); });
  wireQuiz('p9-tr-host', () => { if(window.addXp) window.addXp(15, 'tr-p9'); });
  wireReadBtn('p9');
  renderMath(body);
}

/* ========================================================== */
/* §10 — Взаимодействие частиц вещества                       */
/* ========================================================== */
function add_p10(){
  const body = document.getElementById('p10-body');
  if(!body) return;
  let h = '';

  h += makeCard('theory', 'Два вида сил между частицами', '§ 10.1',
    'Между молекулами одновременно действуют <b>силы притяжения</b> и <b>силы отталкивания</b>. '
    + 'Их интенсивность зависит от расстояния:'
    + '<ul style="padding-left:20px;margin:6px 0">'
    + '<li>на <b>малом</b> расстоянии (молекулы «прижаты») — преобладает <b>отталкивание</b>;</li>'
    + '<li>на <b>равновесном</b> расстоянии $r_0$ — силы уравновешиваются;</li>'
    + '<li>на <b>большом</b> расстоянии — преобладает <b>притяжение</b>;</li>'
    + '<li>на <b>очень большом</b> — силы пренебрежимо малы.</li>'
    + '</ul>');

  h += makeCard('rule', 'Зачем нужно знать про эти силы', '§ 10.2',
    'Силы между молекулами объясняют:'
    + '<ul style="padding-left:20px;margin:5px 0">'
    + '<li>почему <b>твёрдые</b> тела сохраняют форму (сильное притяжение),</li>'
    + '<li>почему трудно <b>растянуть</b> стальной трос (надо преодолеть притяжение),</li>'
    + '<li>почему трудно <b>сжать</b> жидкость (молекулы уже близко — мешает отталкивание),</li>'
    + '<li>почему <b>пружина</b> возвращается в исходное положение — силы упругости имеют ту же природу.</li>'
    + '</ul>');

  h += makeCard('example', 'Опыт с свинцовыми цилиндрами', '§ 10.3',
    'Если две тщательно отшлифованные свинцовые поверхности сжать вместе, '
    + 'они <b>«слипнутся»</b> — их можно даже подвесить на крючок, и они не разойдутся. '
    + 'Причина — притяжение молекул на малом расстоянии. '
    + 'Через грязный или окисленный слой это не работает: молекулы не подходят достаточно близко.');

  /* IV-1: график F(r) */
  h += wgWrap('p10-iv1', 'СИМ', 'График сил F(r) — притяжение и отталкивание', 'Двигай молекулу — увидь, какая сила преобладает.',
    '<div style="margin-bottom:10px"><label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">Расстояние $r/r_0$: <b id="p10-r" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">1.00</b><input type="range" id="p10-r-r" min="60" max="250" step="2" value="100" style="display:block;width:100%;margin-top:6px;accent-color:' + ACCENT + '"></label></div>'
    + '<svg id="p10-svg" viewBox="0 0 380 200" width="100%" style="max-width:600px;display:block;margin:0 auto;background:#faf5ff;border-radius:9px;border:1px solid ' + ACCENT_SOFT + '"></svg>'
    + '<div id="p10-info" style="background:' + ACCENT_SOFT + ';border-radius:9px;padding:10px 14px;margin-top:8px;font-size:.94rem;text-align:center"></div>');

  /* IV-2: квиз */
  h += wgWrap('p10-iv2', 'КВИЗ', 'Силы взаимодействия', 'Выбери верное.',
    '<div id="p10-q-host">'
    + quizQuestion('p10-q', 0, 'На равновесном расстоянии $r_0$ молекулы…', ['Только притягиваются','Только отталкиваются','Притяжение и отталкивание равны','Не взаимодействуют'], 2)
    + quizQuestion('p10-q', 1, 'Почему трудно сжать жидкость?', ['Молекул мало','Молекулы уже близко — мешает отталкивание','Жидкость не имеет молекул','Притяжение слишком сильно'], 1)
    + quizQuestion('p10-q', 2, 'Почему пружина возвращается в исходную форму?', ['Из-за гравитации','Из-за сил между молекулами','Сама по себе','Из-за воздуха'], 1)
    + quizQuestion('p10-q', 3, 'На очень большом расстоянии межмолекулярные силы…', ['Очень большие','Пренебрежимо малы','Отталкивают','Колеблются'], 1)
    + '</div>');

  /* IV-3: DnD */
  h += wgWrap('p10-iv3', 'DnD', 'Преобладает что?', 'Сопоставь расстояние и преобладающую силу.',
    dndPool('p10-dnd', [
      { id:'a1', cat:'rep',  html:'Молекулы прижаты вплотную' },
      { id:'a2', cat:'rep',  html:'Жидкость сжимают поршнем' },
      { id:'a3', cat:'eq',   html:'$r = r_0$ (равновесие)' },
      { id:'a4', cat:'attr', html:'Растягивание стального троса' },
      { id:'a5', cat:'attr', html:'Молекулы немного раздвинуты' },
      { id:'a6', cat:'zero', html:'$r \\gg r_0$ (далеко)' }
    ], [
      { cat:'rep',  label:'Отталкивание' },
      { cat:'eq',   label:'Равновесие' },
      { cat:'attr', label:'Притяжение' },
      { cat:'zero', label:'Силы малы' }
    ]));

  /* IV-4: тренажёр */
  h += wgWrap('p10-iv4', 'ТРН', 'Тренажёр §10', '4 вопроса.',
    '<div id="p10-tr-host">'
    + quizQuestion('p10-tr', 0, 'Между молекулами действуют…', ['Только притяжение','Только отталкивание','И притяжение, и отталкивание','Никаких сил'], 2)
    + quizQuestion('p10-tr', 1, 'Если молекулы оказались ближе $r_0$, то результирующая сила…', ['Отталкивает','Притягивает','Равна нулю','Не определена'], 0)
    + quizQuestion('p10-tr', 2, 'Опыт со свинцовыми цилиндрами показывает…', ['Что вещество твёрдое','Что молекулы притягиваются на близком расстоянии','Что свинец тяжёлый','Что молекулы движутся'], 1)
    + quizQuestion('p10-tr', 3, 'Силы упругости имеют ту же природу, что и…', ['Сила трения','Гравитация','Силы между молекулами','Электромагнитные волны'], 2)
    + '</div>');

  h += readButton('p10');
  body.innerHTML = h;

  function drawF(){
    const rRel = +document.getElementById('p10-r-r').value / 100; // r/r0 from 0.6 to 2.5
    document.getElementById('p10-r').textContent = rRel.toFixed(2);
    const W = 380, H = 200, pad = 30;
    // Чертим оси r (x) и F (y)
    // F(r) модельная: F = a/r^13 - b/r^7 (Lennard-Jones-like), минимум в r=1.
    function F(r){ return 12/Math.pow(r,13) - 12/Math.pow(r,7); }
    let s = '';
    // Оси
    s += '<line x1="' + pad + '" y1="' + (H/2) + '" x2="' + (W-pad+10) + '" y2="' + (H/2) + '" stroke="#0f172a" stroke-width="1.5"/>';
    s += '<line x1="' + pad + '" y1="20" x2="' + pad + '" y2="' + (H-20) + '" stroke="#0f172a" stroke-width="1.5"/>';
    s += '<text x="' + (W-pad+8) + '" y="' + (H/2 + 12) + '" font-family="Inter,sans-serif" font-size="11" fill="#0f172a">r</text>';
    s += '<text x="' + (pad+4) + '" y="20" font-family="Inter,sans-serif" font-size="11" fill="#0f172a">F</text>';
    // r=r0
    const r0X = pad + (W - 2*pad) * (1 - 0.6) / (2.5 - 0.6);
    s += '<line x1="' + r0X.toFixed(1) + '" y1="20" x2="' + r0X.toFixed(1) + '" y2="' + (H-20) + '" stroke="#94a3b8" stroke-width="1" stroke-dasharray="3 2"/>';
    s += '<text x="' + r0X.toFixed(1) + '" y="' + (H-6) + '" text-anchor="middle" font-family="Inter,sans-serif" font-size="10" fill="#64748b">r₀</text>';
    // Кривая F(r)
    let path = '';
    for(let i = 0; i <= 60; i++){
      const r = 0.6 + (2.5 - 0.6) * i / 60;
      const f = F(r);
      const fClamped = Math.max(-2, Math.min(4, f));
      const x = pad + (W - 2*pad) * (r - 0.6) / (2.5 - 0.6);
      const y = H/2 - fClamped * 18;
      path += (i === 0 ? 'M' : 'L') + x.toFixed(1) + ' ' + y.toFixed(1) + ' ';
    }
    s += '<path d="' + path + '" fill="none" stroke="' + ACCENT + '" stroke-width="2.5"/>';
    // Текущая точка
    const curX = pad + (W - 2*pad) * (rRel - 0.6) / (2.5 - 0.6);
    const curF = Math.max(-2, Math.min(4, F(rRel)));
    const curY = H/2 - curF * 18;
    s += '<circle cx="' + curX.toFixed(1) + '" cy="' + curY.toFixed(1) + '" r="6" fill="#dc2626" stroke="#fff" stroke-width="2"/>';
    s += '<line x1="' + curX.toFixed(1) + '" y1="' + (H/2) + '" x2="' + curX.toFixed(1) + '" y2="' + curY.toFixed(1) + '" stroke="#dc2626" stroke-width="1.5" stroke-dasharray="2 2"/>';
    // Подписи областей
    s += '<text x="' + (pad + 30) + '" y="40" font-family="Inter,sans-serif" font-size="10" fill="#dc2626" font-weight="700">отталкивание</text>';
    s += '<text x="' + (W - pad - 60) + '" y="' + (H - 40) + '" font-family="Inter,sans-serif" font-size="10" fill="#10b981" font-weight="700">притяжение</text>';

    document.getElementById('p10-svg').innerHTML = s;

    // Info
    const fVal = F(rRel);
    let label;
    if(rRel < 0.95) label = '<b style="color:#dc2626">Отталкивание</b> (молекулы слишком близко).';
    else if(rRel < 1.05) label = '<b style="color:#0c4a6e">Равновесие</b>: силы уравновешены, $F \\approx 0$.';
    else if(rRel < 1.6) label = '<b style="color:#10b981">Притяжение</b> (молекулы стремятся вернуться).';
    else label = '<b style="color:#64748b">Силы малы</b>: молекулы почти не взаимодействуют.';
    document.getElementById('p10-info').innerHTML = '$r/r_0 = ' + rRel.toFixed(2) + '$ &nbsp;&middot;&nbsp; ' + label;
    renderMath(document.getElementById('p10-info'));
  }
  document.getElementById('p10-r-r').addEventListener('input', drawF);
  drawF();

  wireDnd('p10-dnd', [
    { id:'a1', cat:'rep' },{ id:'a2', cat:'rep' },{ id:'a3', cat:'eq' },
    { id:'a4', cat:'attr' },{ id:'a5', cat:'attr' },{ id:'a6', cat:'zero' }
  ]);
  wireQuiz('p10-q-host', () => { if(window.addXp) window.addXp(10, 'q-p10'); });
  wireQuiz('p10-tr-host', () => { if(window.addXp) window.addXp(15, 'tr-p10'); });
  wireReadBtn('p10');
  renderMath(body);
}

/* ========================================================== */
/* §11 — Газообразное, жидкое, твёрдое состояния              */
/* ГЛАВНЫЙ ВИЗУАЛ ГЛАВЫ 2: переключатель состояний с анимацией */
/* ========================================================== */
function add_p11(){
  const body = document.getElementById('p11-body');
  if(!body) return;
  let h = '';

  h += makeCard('theory', 'Три состояния — три поведения частиц', '§ 11.1',
    '<b>Одно и то же вещество</b> может находиться в трёх состояниях. Различие — в том, '
    + 'как расположены и движутся его молекулы:'
    + '<table style="width:100%;border-collapse:collapse;margin-top:8px;font-size:.92rem">'
    + '<tr style="background:' + ACCENT_SOFT + '"><th style="padding:6px 10px;text-align:left;border-bottom:2px solid ' + ACCENT + '">Состояние</th><th style="padding:6px 10px;text-align:left;border-bottom:2px solid ' + ACCENT + '">Форма</th><th style="padding:6px 10px;text-align:left;border-bottom:2px solid ' + ACCENT + '">Объём</th></tr>'
    + '<tr><td style="padding:5px 10px;border-bottom:1px solid ' + ACCENT_SOFT + '"><b>Твёрдое</b></td><td style="padding:5px 10px;border-bottom:1px solid ' + ACCENT_SOFT + '">сохраняет</td><td style="padding:5px 10px;border-bottom:1px solid ' + ACCENT_SOFT + '">сохраняет</td></tr>'
    + '<tr><td style="padding:5px 10px;border-bottom:1px solid ' + ACCENT_SOFT + '"><b>Жидкое</b></td><td style="padding:5px 10px;border-bottom:1px solid ' + ACCENT_SOFT + '">принимает форму сосуда</td><td style="padding:5px 10px;border-bottom:1px solid ' + ACCENT_SOFT + '">сохраняет</td></tr>'
    + '<tr><td style="padding:5px 10px"><b>Газообразное</b></td><td style="padding:5px 10px">заполняет весь сосуд</td><td style="padding:5px 10px">не сохраняет</td></tr>'
    + '</table>');

  h += makeCard('rule', 'Чем отличается поведение молекул', '§ 11.2',
    '<ul style="padding-left:20px;margin:6px 0;line-height:1.7">'
    + '<li><b>Твёрдое</b>: молекулы в узлах кристаллической решётки; колеблются около положений равновесия. Притяжение сильное.</li>'
    + '<li><b>Жидкое</b>: молекулы упакованы плотно, но <i>«перескакивают»</i> с места на место. Промежутки малы — несжимаема, но течёт.</li>'
    + '<li><b>Газообразное</b>: молекулы летают почти свободно на больших расстояниях. Силы притяжения слабые. Газ занимает <b>весь</b> предоставленный объём.</li>'
    + '</ul>');

  h += makeCard('example', 'Вода — все три состояния', '§ 11.3',
    'Удивительно: одна и та же $\\text{H}_2\\text{O}$ существует во всех трёх состояниях:'
    + '<ul style="padding-left:20px;margin:6px 0">'
    + '<li><b>Лёд</b> (твёрдое) — при $t < 0$ °C. Сохраняет форму, можно расколоть.</li>'
    + '<li><b>Вода</b> (жидкое) — от $0$ до $100$ °C. Принимает форму сосуда.</li>'
    + '<li><b>Пар</b> (газообразное) — при $t > 100$ °C. Заполняет всё пространство.</li>'
    + '</ul>'
    + 'Сами молекулы при переходе <b>не меняются</b> — меняется лишь характер их движения и расположения.');

  /* IV-1: ГЛАВНЫЙ ВИЗУАЛ — переключатель 3 состояний с симуляцией МКТ */
  h += wgWrap('p11-iv1', 'СИМ', 'Молекулы в трёх состояниях', 'Переключай состояние — смотри, как меняется поведение частиц.',
    '<div style="display:flex;gap:6px;margin-bottom:10px;flex-wrap:wrap">'
    + ['solid','liquid','gas'].map((st, i) => {
        const labels = ['Твёрдое', 'Жидкое', 'Газ'];
        const colors = ['#4f46e5', '#0891b2', '#94a3b8'];
        return '<button class="p11-st" data-st="' + st + '" type="button" style="background:#fff;border:2px solid ' + colors[i] + ';color:' + colors[i] + ';padding:8px 18px;border-radius:9px;cursor:pointer;font-weight:700;font-size:.9rem;font-family:inherit">' + labels[i] + '</button>';
      }).join('')
    + '</div>'
    + '<svg id="p11-sim" viewBox="0 0 360 180" width="100%" style="max-width:600px;display:block;margin:0 auto;background:#faf5ff;border-radius:9px;border:1px solid ' + ACCENT_SOFT + '"></svg>'
    + '<div id="p11-info" style="background:' + ACCENT_SOFT + ';border-radius:9px;padding:10px 14px;margin-top:8px;font-size:.92rem;line-height:1.55"></div>');

  /* IV-2: квиз */
  h += wgWrap('p11-iv2', 'КВИЗ', 'Свойства состояний', '',
    '<div id="p11-q-host">'
    + quizQuestion('p11-q', 0, 'Какое состояние сохраняет и форму, и объём?', ['Твёрдое','Жидкое','Газообразное','Все три'], 0)
    + quizQuestion('p11-q', 1, 'Газ занимает…', ['Только дно сосуда','Половину сосуда','Весь сосуд','Часть, равную массе'], 2)
    + quizQuestion('p11-q', 2, 'Жидкость принимает форму…', ['Любую','Сосуда','Кубическую','Шарообразную'], 1)
    + quizQuestion('p11-q', 3, 'В каком состоянии молекулы движутся быстрее всего?', ['В твёрдом','В жидком','В газообразном','Одинаково'], 2)
    + '</div>');

  /* IV-3: DnD */
  h += wgWrap('p11-iv3', 'DnD', 'Что в каком состоянии?', 'Распредели 9 примеров.',
    dndPool('p11-dnd', [
      { id:'a1', cat:'sol', html:'Камень' },
      { id:'a2', cat:'sol', html:'Лёд' },
      { id:'a3', cat:'sol', html:'Железо' },
      { id:'a4', cat:'liq', html:'Молоко' },
      { id:'a5', cat:'liq', html:'Бензин' },
      { id:'a6', cat:'liq', html:'Расплавленный воск' },
      { id:'a7', cat:'gas', html:'Воздух' },
      { id:'a8', cat:'gas', html:'Водяной пар' },
      { id:'a9', cat:'gas', html:'Углекислый газ' }
    ], [
      { cat:'sol', label:'Твёрдое' },
      { cat:'liq', label:'Жидкое' },
      { cat:'gas', label:'Газообразное' }
    ]));

  /* IV-4: тренажёр */
  h += wgWrap('p11-iv4', 'ТРН', 'Тренажёр §11', '5 вопросов.',
    '<div id="p11-tr-host">'
    + quizQuestion('p11-tr', 0, 'Можно ли сжать газ в 2 раза в плотно закрытом шприце?', ['Нет','Да, легко','Только при высокой температуре','Только при очень низкой'], 1)
    + quizQuestion('p11-tr', 1, 'Жидкость практически не сжимается, потому что…', ['Молекул мало','Молекулы уже плотно упакованы','Жидкости лёгкие','Молекулы неподвижны'], 1)
    + quizQuestion('p11-tr', 2, 'В каком состоянии вещества молекулы располагаются в строгом порядке (кристалл)?', ['Твёрдое','Жидкое','Газообразное','Ни в каком'], 0)
    + quizQuestion('p11-tr', 3, 'При переходе из льда в воду молекулы $\\text{H}_2\\text{O}$…', ['Распадаются','Превращаются в другие','Остаются теми же, меняется лишь их движение','Исчезают'], 2)
    + quizQuestion('p11-tr', 4, '$0{,}5$ л воды налили в банку $1$ л. Какой объём займёт вода?', ['0,5 л','1 л','0,75 л','Зависит от формы'], 0, 'Жидкость сохраняет свой объём — только форму она меняет.')
    + '</div>');

  h += readButton('p11');
  body.innerHTML = h;

  // Wire 3-state simulator
  const st11 = (function(){
    const W = 360, H = 180, N = 50;
    let state = 'solid';
    const parts = [];
    for(let i = 0; i < N; i++) parts.push({ x:0, y:0, vx:0, vy:0, hx:0, hy:0 });
    function reset(){
      if(state === 'solid'){
        // Кристаллическая решётка 10×5
        for(let i = 0; i < N; i++){
          const r = Math.floor(i/10), c = i % 10;
          parts[i].hx = 40 + c * 28;
          parts[i].hy = 40 + r * 28;
          parts[i].x = parts[i].hx; parts[i].y = parts[i].hy;
          parts[i].vx = 0; parts[i].vy = 0;
        }
      } else if(state === 'liquid'){
        // Жидкость — занимает нижнюю половину
        for(let i = 0; i < N; i++){
          parts[i].x = 20 + Math.random() * (W - 40);
          parts[i].y = H/2 + Math.random() * (H/2 - 10);
          parts[i].vx = (Math.random() - 0.5) * 1;
          parts[i].vy = (Math.random() - 0.5) * 1;
        }
      } else { // gas
        for(let i = 0; i < N; i++){
          parts[i].x = 10 + Math.random() * (W - 20);
          parts[i].y = 10 + Math.random() * (H - 20);
          const ang = Math.random() * Math.PI * 2;
          parts[i].vx = Math.cos(ang) * 2.5;
          parts[i].vy = Math.sin(ang) * 2.5;
        }
      }
    }
    function step(){
      if(state === 'solid'){
        for(let i = 0; i < N; i++){
          parts[i].x = parts[i].hx + (Math.random() - 0.5) * 3;
          parts[i].y = parts[i].hy + (Math.random() - 0.5) * 3;
        }
      } else if(state === 'liquid'){
        for(let i = 0; i < N; i++){
          parts[i].vx += (Math.random() - 0.5) * 0.3;
          parts[i].vy += (Math.random() - 0.5) * 0.3;
          parts[i].vx *= 0.93; parts[i].vy *= 0.93;
          parts[i].x += parts[i].vx; parts[i].y += parts[i].vy;
          // Притяжение к дну (как жидкость)
          parts[i].vy += 0.1;
          if(parts[i].x < 6){ parts[i].x = 6; parts[i].vx = -parts[i].vx; }
          if(parts[i].x > W-6){ parts[i].x = W-6; parts[i].vx = -parts[i].vx; }
          if(parts[i].y < H/2 + 6){ parts[i].y = H/2 + 6; parts[i].vy = Math.abs(parts[i].vy)*0.5; }
          if(parts[i].y > H-6){ parts[i].y = H-6; parts[i].vy = -Math.abs(parts[i].vy)*0.7; }
        }
      } else {
        for(let i = 0; i < N; i++){
          parts[i].x += parts[i].vx; parts[i].y += parts[i].vy;
          if(parts[i].x < 6){ parts[i].x = 6; parts[i].vx = -parts[i].vx; }
          if(parts[i].x > W-6){ parts[i].x = W-6; parts[i].vx = -parts[i].vx; }
          if(parts[i].y < 6){ parts[i].y = 6; parts[i].vy = -parts[i].vy; }
          if(parts[i].y > H-6){ parts[i].y = H-6; parts[i].vy = -parts[i].vy; }
        }
      }
    }
    function render(){
      const svg = document.getElementById('p11-sim');
      if(!svg) return false;
      let s = '';
      // Контур сосуда
      s += '<rect x="2" y="2" width="' + (W-4) + '" height="' + (H-4) + '" fill="none" stroke="' + ACCENT_D + '" stroke-width="1.5" stroke-dasharray="4 3" rx="6"/>';
      // Уровень жидкости — линия
      if(state === 'liquid'){
        s += '<line x1="3" y1="' + (H/2) + '" x2="' + (W-3) + '" y2="' + (H/2) + '" stroke="#0891b2" stroke-width="1.5"/>';
      }
      const col = state === 'solid' ? '#4f46e5' : (state === 'liquid' ? '#0891b2' : '#64748b');
      parts.forEach(p => {
        s += '<circle cx="' + p.x.toFixed(1) + '" cy="' + p.y.toFixed(1) + '" r="4" fill="' + col + '" stroke="#0f172a" stroke-width="0.6" opacity="0.9"/>';
      });
      svg.innerHTML = s;
      return true;
    }
    return {
      setState(st){ state = st; reset(); updateInfo(); },
      step, render, getState(){ return state; }
    };
  })();
  function updateInfo(){
    const st = st11.getState();
    const descs = {
      solid:  '<b style="color:#4f46e5">Твёрдое:</b> молекулы в узлах решётки, только колеблются. Форма и объём сохраняются.',
      liquid: '<b style="color:#0891b2">Жидкость:</b> молекулы плотно упакованы и «перескакивают». Объём сохраняется, форма — нет.',
      gas:    '<b style="color:#64748b">Газ:</b> молекулы летают свободно. Ни форма, ни объём не сохраняются — газ занимает весь сосуд.'
    };
    document.getElementById('p11-info').innerHTML = descs[st];
  }
  body.querySelectorAll('.p11-st').forEach(btn => btn.addEventListener('click', () => {
    body.querySelectorAll('.p11-st').forEach(b => { b.style.background = '#fff'; b.style.color = b.style.borderColor; });
    btn.style.background = btn.style.borderColor; btn.style.color = '#fff';
    st11.setState(btn.dataset.st);
  }));
  st11.setState('solid');
  body.querySelector('.p11-st[data-st="solid"]').style.background = '#4f46e5';
  body.querySelector('.p11-st[data-st="solid"]').style.color = '#fff';
  let raf11 = 0;
  function loop11(){
    st11.step();
    if(!st11.render()){ cancelAnimationFrame(raf11); return; }
    raf11 = requestAnimationFrame(loop11);
  }
  raf11 = requestAnimationFrame(loop11);

  wireDnd('p11-dnd', [
    { id:'a1', cat:'sol' },{ id:'a2', cat:'sol' },{ id:'a3', cat:'sol' },
    { id:'a4', cat:'liq' },{ id:'a5', cat:'liq' },{ id:'a6', cat:'liq' },
    { id:'a7', cat:'gas' },{ id:'a8', cat:'gas' },{ id:'a9', cat:'gas' }
  ]);
  wireQuiz('p11-q-host', () => { if(window.addXp) window.addXp(10, 'q-p11'); });
  wireQuiz('p11-tr-host', () => { if(window.addXp) window.addXp(15, 'tr-p11'); });
  wireReadBtn('p11');
  renderMath(body);
}

/* ========================================================== */
/* §12 — Тепловое расширение                                  */
/* ========================================================== */
function add_p12(){
  const body = document.getElementById('p12-body');
  if(!body) return;
  let h = '';

  h += makeCard('theory', 'Почему тела расширяются при нагреве', '§ 12.1',
    'При нагревании молекулы движутся быстрее и амплитуда их колебаний возрастает. '
    + 'Среднее расстояние между молекулами <b>увеличивается</b> — тело расширяется. '
    + 'При охлаждении наоборот: тело сжимается.<br><br>'
    + 'Тепловое расширение есть у <b>всех</b> веществ — твёрдых, жидких и газообразных. '
    + 'Сильнее всех расширяются газы, меньше всех — твёрдые тела.');

  h += makeCard('rule', 'Где это важно учитывать', '§ 12.2',
    '<ul style="padding-left:20px;margin:6px 0">'
    + '<li><b>Рельсы</b> укладывают с зазорами — летом сталь удлиняется.</li>'
    + '<li><b>Мосты</b> опирают через катки или прокладки — иначе бы трескались.</li>'
    + '<li><b>Провода ЛЭП</b> летом провисают сильнее, чем зимой.</li>'
    + '<li><b>Биметаллическая пластина</b> — два металла спаяны вместе, гнётся от температуры. Используется в утюгах и термостатах.</li>'
    + '</ul>');

  h += makeCard('example', 'Аномалия воды', '§ 12.3',
    'Большинство веществ при нагревании расширяются. Но у воды есть <b>исключение</b>: '
    + 'при $t$ от $0$ до $+4$ °C она <b>сжимается</b>, а только начиная с $+4$ °C — расширяется. '
    + 'Поэтому самая плотная вода — при $+4$ °C; она опускается на дно водоёма. '
    + 'Это <b>спасает</b> жизнь в озёрах зимой: лёд плавает сверху, а под ним вода с $+4$ °C, где могут жить рыбы.');

  /* IV-1: расширение стержня + биметалла */
  h += wgWrap('p12-iv1', 'СИМ', 'Тепловое расширение стержня', 'Меняй температуру — наблюдай длину.',
    '<div style="margin-bottom:10px"><label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">Нагрев $\\Delta T$, °C: <b id="p12-T" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">50</b><input type="range" id="p12-T-r" min="0" max="200" step="5" value="50" style="display:block;width:100%;margin-top:6px;accent-color:' + ACCENT + '"></label></div>'
    + '<svg id="p12-svg" viewBox="0 0 380 140" width="100%" style="max-width:600px;display:block;margin:0 auto;background:#faf5ff;border-radius:9px;border:1px solid ' + ACCENT_SOFT + '"></svg>'
    + '<div id="p12-info" style="background:' + ACCENT_SOFT + ';border-radius:9px;padding:10px 14px;margin-top:8px;font-size:.9rem;text-align:center"></div>');

  /* IV-2: биметалл */
  h += wgWrap('p12-iv2', 'СИМ', 'Биметаллическая пластина', 'Два металла расширяются по-разному — пластина гнётся.',
    '<div style="margin-bottom:10px"><label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">Нагрев $\\Delta T$, °C: <b id="p12b-T" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">60</b><input type="range" id="p12b-T-r" min="-50" max="100" step="5" value="60" style="display:block;width:100%;margin-top:6px;accent-color:' + ACCENT + '"></label></div>'
    + '<svg id="p12b-svg" viewBox="0 0 280 200" width="100%" style="max-width:400px;display:block;margin:0 auto;background:#faf5ff;border-radius:9px;border:1px solid ' + ACCENT_SOFT + '"></svg>'
    + '<div style="text-align:center;font-size:.84rem;color:#64748b;margin-top:6px">Жёлтый слой — латунь (сильнее расширяется), серый — сталь. Принцип термостата.</div>');

  /* IV-3: DnD */
  h += wgWrap('p12-iv3', 'DnD', 'Кто сильнее расширяется?', 'Расставь по убыванию теплового расширения.',
    dndPool('p12-dnd', [
      { id:'a1', cat:'gas', html:'Воздух в шарике' },
      { id:'a2', cat:'gas', html:'Гелий в баллоне' },
      { id:'a3', cat:'liq', html:'Спирт в термометре' },
      { id:'a4', cat:'liq', html:'Ртуть в термометре' },
      { id:'a5', cat:'sol', html:'Железный рельс' },
      { id:'a6', cat:'sol', html:'Кварцевое стекло' }
    ], [
      { cat:'gas', label:'Сильно (газ)' },
      { cat:'liq', label:'Средне (жидкость)' },
      { cat:'sol', label:'Слабо (твёрдое)' }
    ]));

  /* IV-4: тренажёр */
  h += wgWrap('p12-iv4', 'ТРН', 'Тренажёр §12', '5 вопросов.',
    '<div id="p12-tr-host">'
    + quizQuestion('p12-tr', 0, 'Почему между рельсами оставляют зазоры?', ['Для экономии металла','Чтобы рельсы могли расширяться летом','Для прохода животных','Не оставляют, это миф'], 1)
    + quizQuestion('p12-tr', 1, 'При охлаждении тело…', ['Расширяется','Сжимается','Не меняется','Может то и другое'], 1)
    + quizQuestion('p12-tr', 2, 'У какой воды максимальная плотность?', ['При 0 °C','При +4 °C','При +100 °C','Не зависит от t'], 1, 'Это уникальная аномалия воды — спасает водоёмы зимой.')
    + quizQuestion('p12-tr', 3, 'Биметаллическая пластина при нагревании…', ['Не изменяется','Гнётся в одну сторону','Гнётся в случайную сторону','Распадается'], 1, 'Один металл расширяется сильнее, и пластина изгибается.')
    + quizQuestion('p12-tr', 4, 'Что сильнее расширяется при $\\Delta T = 50$ °C?', ['Стальной стержень','Воздушный шарик','Кварц','Лёд'], 1, 'Газы расширяются в сотни раз сильнее твёрдых тел.')
    + '</div>');

  h += readButton('p12');
  body.innerHTML = h;

  // §12 IV-1
  function drawRod(){
    const dT = +document.getElementById('p12-T-r').value;
    document.getElementById('p12-T').textContent = dT;
    const W = 380, baseLen = 200, alpha = 12e-6; // сталь
    const dl = baseLen * alpha * dT * 200; // визуально усилено
    const len = baseLen + dl;
    const y = 60, h = 22;
    const x = 30;
    // Цвет = функция температуры (0..200 → синий → красный)
    const hue = 240 - 240 * Math.min(1, dT / 200);
    const col = 'hsl(' + hue + ',70%,55%)';
    let s = '';
    // Базовая длина — пунктир
    s += '<rect x="' + x + '" y="' + (y-3) + '" width="' + baseLen + '" height="' + (h+6) + '" fill="none" stroke="#94a3b8" stroke-width="1" stroke-dasharray="3 2" rx="3"/>';
    // Реальный стержень
    s += '<rect x="' + x + '" y="' + y + '" width="' + len.toFixed(1) + '" height="' + h + '" fill="' + col + '" stroke="#0f172a" stroke-width="1.5" rx="3"/>';
    // Подписи
    s += '<text x="' + (x + baseLen/2) + '" y="' + (y - 8) + '" text-anchor="middle" font-family="Inter,sans-serif" font-size="10" fill="#64748b">базовая длина (при 0 °C)</text>';
    if(Math.abs(dl) > 1){
      s += '<line x1="' + (x + baseLen) + '" y1="' + (y + h + 8) + '" x2="' + (x + len) + '" y2="' + (y + h + 8) + '" stroke="#dc2626" stroke-width="2"/>';
      s += '<text x="' + (x + baseLen + dl/2) + '" y="' + (y + h + 24) + '" text-anchor="middle" font-family="Inter,sans-serif" font-size="11" font-weight="700" fill="#dc2626">Δl = ' + dl.toFixed(1) + ' px</text>';
    }
    document.getElementById('p12-svg').innerHTML = s;
    const realDl = (baseLen * alpha * dT * 100).toFixed(3); // реалистично в мм для l0=1 м
    document.getElementById('p12-info').innerHTML = 'Сталь, $l_0 = 1$ м, нагрев на $\\Delta T = ' + dT + '$ °C: реально удлинится примерно на $' + (alpha * 1000 * dT).toFixed(3) + '$ мм (масштаб усилен).';
    renderMath(document.getElementById('p12-info'));
  }
  document.getElementById('p12-T-r').addEventListener('input', drawRod);
  drawRod();

  // §12 IV-2 биметалл
  function drawBimet(){
    const dT = +document.getElementById('p12b-T-r').value;
    document.getElementById('p12b-T').textContent = dT;
    const ang = Math.max(-30, Math.min(30, -dT * 0.3));
    const cx = 140, cy = 50;
    let s = '';
    // Опора
    s += '<rect x="' + (cx - 30) + '" y="' + (cy - 8) + '" width="60" height="8" fill="#475569" stroke="#0f172a" stroke-width="1"/>';
    // Пластина с поворотом
    s += '<g transform="translate(' + cx + ',' + cy + ') rotate(' + ang + ')">';
    s += '<rect x="0" y="0" width="120" height="10" fill="#fbbf24" stroke="#92400e" stroke-width="1"/>';
    s += '<rect x="0" y="10" width="120" height="10" fill="#94a3b8" stroke="#374151" stroke-width="1"/>';
    s += '<text x="60" y="38" text-anchor="middle" font-family="Inter,sans-serif" font-size="10" font-weight="600" fill="#374151">Δt = ' + dT + ' °C</text>';
    s += '</g>';
    // Подписи цветов
    s += '<rect x="10" y="180" width="14" height="6" fill="#fbbf24"/>';
    s += '<text x="28" y="187" font-family="Inter,sans-serif" font-size="9" fill="#374151">латунь (сильнее расширяется)</text>';
    s += '<rect x="10" y="190" width="14" height="6" fill="#94a3b8"/>';
    s += '<text x="28" y="197" font-family="Inter,sans-serif" font-size="9" fill="#374151">сталь</text>';
    document.getElementById('p12b-svg').innerHTML = s;
  }
  document.getElementById('p12b-T-r').addEventListener('input', drawBimet);
  drawBimet();

  wireDnd('p12-dnd', [
    { id:'a1', cat:'gas' },{ id:'a2', cat:'gas' },{ id:'a3', cat:'liq' },
    { id:'a4', cat:'liq' },{ id:'a5', cat:'sol' },{ id:'a6', cat:'sol' }
  ]);
  wireQuiz('p12-tr-host', () => { if(window.addXp) window.addXp(15, 'tr-p12'); });
  wireReadBtn('p12');
  renderMath(body);
}

/* ========================================================== */
/* §13 — Температура. Термометры                              */
/* ========================================================== */
function add_p13(){
  const body = document.getElementById('p13-body');
  if(!body) return;
  let h = '';

  h += makeCard('theory', 'Что такое температура', '§ 13.1',
    '<b>Температура</b> — физическая величина, которая характеризует степень нагретости тела. '
    + 'Чем быстрее в среднем движутся молекулы — тем выше температура.<br><br>'
    + 'Обозначается $t$ (или $T$), измеряется в <b>градусах Цельсия</b> ($°C$). '
    + 'В физике также используют <b>Кельвины</b> ($K$); связь: $T = t + 273{,}15$.');

  h += makeCard('rule', 'Шкала Цельсия', '§ 13.2',
    'Шкала строится по двум опорным точкам:'
    + '<ul style="padding-left:20px;margin:6px 0">'
    + '<li><b>$0$ °C</b> — температура таяния льда (при нормальном давлении);</li>'
    + '<li><b>$100$ °C</b> — температура кипения чистой воды (при нормальном давлении).</li>'
    + '</ul>'
    + 'Промежуток разбит на $100$ равных частей — отсюда «градус Цельсия».');

  h += makeCard('example', 'Виды термометров', '§ 13.3',
    '<ul style="padding-left:20px;margin:6px 0">'
    + '<li><b>Жидкостный</b> (спирт, ртуть) — расширение жидкости в капилляре. От $-40$ до $+50$ °C — бытовой; до $+300$ °C — ртутный лабораторный.</li>'
    + '<li><b>Биметаллический</b> — стрелка двигается за счёт изгиба пластины. На печках, духовках.</li>'
    + '<li><b>Электронный</b> — термопара или термистор + дисплей. От $-200$ до $+1000$ °C.</li>'
    + '<li><b>Инфракрасный (пирометр)</b> — измеряет тепловое излучение без контакта. До тысяч °C.</li>'
    + '</ul>');

  /* IV-1: виртуальный термометр */
  h += wgWrap('p13-iv1', 'СИМ', 'Виртуальный термометр', 'Двигай слайдер — наблюдай столбик и сравнивай с реальными ситуациями.',
    '<div style="margin-bottom:10px"><label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">Температура $t$, °C: <b id="p13-t" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">22</b><input type="range" id="p13-t-r" min="-50" max="150" step="1" value="22" style="display:block;width:100%;margin-top:6px;accent-color:' + ACCENT + '"></label></div>'
    + '<div style="display:grid;grid-template-columns:140px 1fr;gap:14px;align-items:center">'
    +   '<svg id="p13-svg" viewBox="0 0 100 220" width="100%" style="max-width:140px"></svg>'
    +   '<div id="p13-info" style="background:' + ACCENT_SOFT + ';border-radius:9px;padding:12px 14px;font-size:.92rem;line-height:1.65"></div>'
    + '</div>');

  /* IV-2: конвертер °C ↔ K */
  h += wgWrap('p13-iv2', 'КАЛЬК', 'Конвертер °C ↔ K', 'Кельвин и Цельсий — две шкалы для одной температуры.',
    '<div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:10px">'
    + '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:8px 12px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">$t$, °C: <b id="p13c-c" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">25</b><input type="range" id="p13c-c-r" min="-273" max="500" step="1" value="25" style="display:block;width:100%;margin-top:6px;accent-color:' + ACCENT + '"></label>'
    + '<div style="background:#fff;padding:8px 12px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + ';font-size:.86rem;color:#475569">'
    +   '$T = t + 273{,}15 = $ <b id="p13c-k" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">298,15</b> K'
    +   '<div style="font-size:.78rem;color:#64748b;margin-top:4px">Абсолютный нуль: $T = 0$ K $= -273{,}15$ °C — теоретический предел холода.</div>'
    + '</div>'
    + '</div>');

  /* IV-3: DnD температуры */
  h += wgWrap('p13-iv3', 'DnD', 'Соотнеси температуру и объект', '',
    dndPool('p13-dnd', [
      { id:'a1', cat:'cold',  html:'$-180$ °C' },
      { id:'a2', cat:'cold',  html:'$-15$ °C' },
      { id:'a3', cat:'room',  html:'$+20$ °C' },
      { id:'a4', cat:'room',  html:'$+37$ °C' },
      { id:'a5', cat:'hot',   html:'$+100$ °C' },
      { id:'a6', cat:'hot',   html:'$+1500$ °C' }
    ], [
      { cat:'cold', label:'Холод (морозильник / жидкий азот)' },
      { cat:'room', label:'Норма (комната / тело человека)' },
      { cat:'hot',  label:'Горячо (кипяток / расплав металла)' }
    ]));

  /* IV-4: тренажёр */
  h += wgWrap('p13-iv4', 'ТРН', 'Тренажёр §13', '5 вопросов.',
    '<div id="p13-tr-host">'
    + quizQuestion('p13-tr', 0, 'Температура $t = 0$ °C соответствует…', ['Таянию льда','Кипению воды','Замерзанию ртути','Абсолютному нулю'], 0)
    + quizQuestion('p13-tr', 1, 'Сколько Кельвинов в $0$ °C?', ['0','100','273,15','373,15'], 2, '$T = 0 + 273{,}15 = 273{,}15$ K.')
    + quizQuestion('p13-tr', 2, 'В каком термометре используется расширение жидкости?', ['Биметаллическом','Электронном','Жидкостном (спиртовом/ртутном)','Инфракрасном'], 2)
    + quizQuestion('p13-tr', 3, 'Тело человека: $36{,}6$ °C $= ?$ K', ['36,6','273,15','309,75','310'], 2, '$T = 36{,}6 + 273{,}15 \\approx 309{,}75$ K.')
    + quizQuestion('p13-tr', 4, 'Может ли быть температура $-300$ °C?', ['Да','Нет, ниже -273,15 °C ничего не бывает','Только в космосе','Только в опытах'], 1)
    + '</div>');

  h += readButton('p13');
  body.innerHTML = h;

  // §13 IV-1 thermometer
  function drawTherm(){
    const t = +document.getElementById('p13-t-r').value;
    document.getElementById('p13-t').textContent = t;
    const W = 100, H = 220;
    const xC = 50, tubeTop = 20, tubeBot = 180, tubeW = 14;
    const minT = -50, maxT = 150;
    const frac = Math.max(0, Math.min(1, (t - minT) / (maxT - minT)));
    const colTop = tubeBot - (tubeBot - tubeTop) * frac;
    // Резервуар
    const bulbR = 18;
    const bulbY = 196;
    let s = '';
    s += '<rect x="' + (xC - tubeW/2 - 2) + '" y="' + tubeTop + '" width="' + (tubeW + 4) + '" height="' + (tubeBot - tubeTop + 6) + '" fill="#fff" stroke="#0f172a" stroke-width="1.5" rx="' + tubeW/2 + '"/>';
    s += '<circle cx="' + xC + '" cy="' + bulbY + '" r="' + bulbR + '" fill="#fff" stroke="#0f172a" stroke-width="1.5"/>';
    // Столбик
    const hue = 240 - 240 * frac;
    const col = 'hsl(' + hue + ',75%,50%)';
    s += '<rect x="' + (xC - tubeW/2 + 2) + '" y="' + colTop + '" width="' + (tubeW - 4) + '" height="' + (tubeBot - colTop + 8) + '" fill="' + col + '"/>';
    s += '<circle cx="' + xC + '" cy="' + bulbY + '" r="' + (bulbR - 4) + '" fill="' + col + '"/>';
    // Шкала
    for(let T = minT; T <= maxT; T += 10){
      const y = tubeBot - (tubeBot - tubeTop) * (T - minT) / (maxT - minT);
      const isBig = T % 50 === 0 || T === 0 || T === 100;
      s += '<line x1="' + (xC + tubeW/2 + 4) + '" y1="' + y + '" x2="' + (xC + tubeW/2 + (isBig ? 12 : 8)) + '" y2="' + y + '" stroke="#0f172a" stroke-width="' + (isBig ? 1.5 : 1) + '"/>';
      if(isBig) s += '<text x="' + (xC + tubeW/2 + 15) + '" y="' + (y + 3) + '" font-family="Inter,sans-serif" font-size="9" font-weight="600" fill="#0f172a">' + T + '</text>';
    }
    // Указатель текущей
    const tY = tubeBot - (tubeBot - tubeTop) * (t - minT) / (maxT - minT);
    s += '<polygon points="' + (xC - tubeW/2 - 14) + ',' + (tY - 5) + ' ' + (xC - tubeW/2 - 4) + ',' + tY + ' ' + (xC - tubeW/2 - 14) + ',' + (tY + 5) + '" fill="#dc2626"/>';
    s += '<text x="3" y="14" font-family="Inter,sans-serif" font-size="10" font-weight="700" fill="#92400e">°C</text>';
    document.getElementById('p13-svg').innerHTML = s;
    // Info
    let label;
    if(t < -50) label = 'Очень холодно (вряд ли встретишь в природе на Земле).';
    else if(t < -30) label = '<b>Сильный мороз</b> — Север, Сибирь зимой.';
    else if(t < 0) label = '<b>Минусовая температура</b> — вода замерзает.';
    else if(t < 10) label = '<b>Прохладно</b> — поздняя осень.';
    else if(t < 25) label = '<b>Комфортно</b> — обычная комнатная температура.';
    else if(t < 37) label = '<b>Тепло</b> — летний день.';
    else if(t < 60) label = '<b>Жарко</b> — около температуры тела или горячая вода из крана.';
    else if(t < 100) label = '<b>Очень горячо</b> — нельзя касаться, можно обжечься.';
    else if(t < 120) label = '<b>Кипяток / пар</b> — кипящая вода.';
    else label = '<b>Очень горячо</b> — выше точки кипения воды.';
    document.getElementById('p13-info').innerHTML = label + '<br><span style="font-size:.84rem;color:#64748b">$T = t + 273{,}15 = ' + (t + 273.15).toFixed(2) + '$ K</span>';
    renderMath(document.getElementById('p13-info'));
  }
  document.getElementById('p13-t-r').addEventListener('input', drawTherm);
  drawTherm();

  // §13 IV-2 converter
  document.getElementById('p13c-c-r').addEventListener('input', () => {
    const c = +document.getElementById('p13c-c-r').value;
    document.getElementById('p13c-c').textContent = c;
    document.getElementById('p13c-k').textContent = (c + 273.15).toFixed(2);
  });

  wireDnd('p13-dnd', [
    { id:'a1', cat:'cold' },{ id:'a2', cat:'cold' },{ id:'a3', cat:'room' },
    { id:'a4', cat:'room' },{ id:'a5', cat:'hot' },{ id:'a6', cat:'hot' }
  ]);
  wireQuiz('p13-tr-host', () => { if(window.addXp) window.addXp(15, 'tr-p13'); });
  wireReadBtn('p13');
  renderMath(body);
}

/* ========================================================== */
/* Финал главы 2 — 5 боссов + ачивка «Знаток вещества»        */
/* ========================================================== */
function add_final2(){
  const body = document.getElementById('final2-body');
  if(!body) return;
  let h = '';

  h += '<div style="background:linear-gradient(135deg,' + ACCENT_SOFT + ',#fdf4ff);border:1.5px solid ' + ACCENT + ';border-radius:14px;padding:16px;margin-bottom:14px;text-align:center">'
    + '<div style="font-family:Unbounded,sans-serif;font-weight:800;font-size:1.12rem;color:' + ACCENT_D + '">Финал главы 2: победи 5 боссов</div>'
    + '<div style="font-size:.88rem;color:#475569;margin-top:5px">Реши все 5 задач — получишь ачивку «Знаток вещества» и +50 XP.</div>'
    + '<div style="height:10px;background:#fff;border-radius:6px;overflow:hidden;margin-top:12px;border:1px solid ' + ACCENT_SOFT + '"><div id="ch2-fin-fill" style="height:100%;background:linear-gradient(90deg,' + ACCENT + ',' + ACCENT_D + ');width:0%;transition:width .4s"></div></div>'
    + '<div id="ch2-fin-lab" style="font-size:.84rem;color:#475569;margin-top:6px">Побеждено: 0 / 5</div>'
    + '</div>';

  const bosses = [
    { n:1, tag:'§8', title:'Размер молекулы',
      q:'Во сколько раз молекула воды ($\\sim 10^{-10}$ м) меньше толщины волоса ($\\sim 10^{-4}$ м)?',
      hint:'$10^{-4} / 10^{-10} = 10^6$ — в миллион раз.',
      ans:1000000, tol:50000, step:'1' },
    { n:2, tag:'§9', title:'Диффузия и температура',
      q:'Стакан кипятка ($+95$ °C) и стакан воды из-под крана ($+10$ °C). В обоих растворяют одинаковую щепотку соли. Через сколько минут вода в первом будет соленее по всему объёму, если во втором — за $30$ мин? Считать, что скорость диффузии примерно $\\sim T$ (в Кельвинах). Ответ — приблизительно в минутах (округли до целого).',
      hint:'$T_1 = 95+273 = 368$ K, $T_2 = 10+273 = 283$ K. Отношение $283/368 \\approx 0{,}77$. Время в горячей: $30 \\cdot 0{,}77 \\approx 23$ мин.',
      ans:23, tol:2, step:'1' },
    { n:3, tag:'§11', title:'Газ в шприце',
      q:'В шприце $V_1 = 50$ см³ воздуха. Поршнем сжали так, что объём стал $V_2 = 20$ см³. Какую часть от первоначального объёма занял газ (в процентах, округли до целого)?',
      hint:'$V_2/V_1 \\cdot 100\\% = 20/50 \\cdot 100\\% = 40\\,\\%$.',
      ans:40, tol:1, step:'1' },
    { n:4, tag:'§12', title:'Тепловое расширение рельса',
      q:'Стальной рельс длиной $l_0 = 25$ м летом нагревается с зимних $-20$ °C до летних $+40$ °C ($\\Delta T = 60$ °C). Коэффициент линейного расширения стали $\\alpha = 12 \\cdot 10^{-6}$ 1/°C. На сколько мм он удлинится?',
      hint:'$\\Delta l = l_0 \\alpha \\Delta T = 25 \\cdot 12 \\cdot 10^{-6} \\cdot 60 = 1{,}8 \\cdot 10^{-2}$ м $= 18$ мм.',
      ans:18, tol:1, step:'0.1' },
    { n:5, tag:'§13', title:'Знаток вещества (термометр)',
      q:'Термометр показывает $t = 27$ °C. Сколько это Кельвинов? Округли до десятых.',
      hint:'$T = t + 273{,}15 = 27 + 273{,}15 = 300{,}2$ K (при округлении до десятых).',
      ans:300.2, tol:0.2, step:'0.1' }
  ];

  const STATE_KEY = 'physics7_ch2_final_bosses';
  let solved = {};
  try{ solved = JSON.parse(localStorage.getItem(STATE_KEY) || '{}') || {}; }catch(e){}

  bosses.forEach(b => {
    const isSolved = !!solved[b.n];
    h += '<div data-boss="' + b.n + '" style="background:#fff;border:2px solid ' + (isSolved ? '#10b981' : ACCENT_SOFT) + ';border-radius:12px;padding:14px 16px;margin-bottom:12px;box-shadow:' + (isSolved ? '0 0 0 3px rgba(16,185,129,.16)' : '0 2px 8px rgba(0,0,0,.05)') + '">'
      + '<div style="display:flex;align-items:center;gap:10px;margin-bottom:8px;flex-wrap:wrap">'
      +   '<span style="background:' + ACCENT + ';color:#fff;padding:3px 10px;border-radius:99px;font-size:.7rem;font-weight:800;letter-spacing:.04em">' + b.tag + '</span>'
      +   '<span style="font-family:Unbounded,sans-serif;font-weight:800;font-size:.96rem;color:#0f172a">Босс ' + b.n + '. ' + b.title + '</span>'
      + '</div>'
      + '<div style="padding:10px 12px;background:' + ACCENT_SOFT + ';border-radius:8px;margin-bottom:10px;font-size:.94rem;line-height:1.55">' + b.q + '</div>'
      + '<div style="display:flex;gap:8px;flex-wrap:wrap;align-items:center">'
      +   '<input type="number" step="' + b.step + '" class="boss-inp" data-n="' + b.n + '" placeholder="число" style="padding:8px 12px;border:1.5px solid ' + ACCENT_SOFT + ';border-radius:8px;width:140px;text-align:center;font-family:JetBrains Mono,monospace;font-size:.95rem"' + (isSolved ? ' value="' + b.ans + '" disabled' : '') + '>'
      +   '<button class="boss-go" data-n="' + b.n + '" type="button" style="background:linear-gradient(135deg,' + ACCENT + ',' + ACCENT_D + ');color:#fff;border:none;padding:8px 16px;border-radius:9px;font-weight:700;font-size:.88rem;cursor:pointer;font-family:inherit"' + (isSolved ? ' disabled' : '') + '>Атаковать</button>'
      +   '<button class="boss-hint" data-n="' + b.n + '" type="button" style="background:#fff;color:#475569;border:1.5px solid ' + ACCENT_SOFT + ';padding:8px 14px;border-radius:9px;font-weight:600;font-size:.86rem;cursor:pointer;font-family:inherit">Подсказка</button>'
      + '</div>'
      + '<div class="boss-hint-txt" data-n="' + b.n + '" style="margin-top:8px;padding:9px 13px;background:#fef3c7;border-left:3px solid #f59e0b;border-radius:6px;font-size:.86rem;line-height:1.5;display:none">' + b.hint + '</div>'
      + '<div class="boss-fb" data-n="' + b.n + '" style="margin-top:8px;padding:9px 13px;border-radius:8px;font-weight:600;font-size:.88rem;line-height:1.45;' + (isSolved ? 'background:#d1fae5;color:#065f46;border-left:4px solid #10b981' : 'display:none') + '">' + (isSolved ? '&#10003; Босс повержен! +20 XP.' : '') + '</div>'
      + '</div>';
  });

  h += '<div id="ch2-mastered" style="margin-top:14px;padding:14px 18px;border-radius:12px;background:linear-gradient(135deg,#fef3c7,#fde68a);border:1.5px solid #f59e0b;display:none;align-items:center;gap:12px"><svg style="width:32px;height:32px;stroke:#92400e;fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round" viewBox="0 0 24 24"><polygon points="12,2 15,9 22,9.3 17,14 18.5,21 12,17 5.5,21 7,14 2,9.3 9,9"/></svg><div style="flex:1"><div style="font-weight:800;color:#92400e;font-family:Unbounded,sans-serif">Ачивка «Знаток вещества» получена!</div><div style="font-size:.86rem;color:#78350f;margin-top:2px">+50 XP &middot; Глава 2 полностью пройдена.</div></div></div>';

  body.innerHTML = h;
  renderMath(body);

  function updateBar(){
    const cnt = bosses.filter(b => solved[b.n]).length;
    document.getElementById('ch2-fin-fill').style.width = (cnt * 100 / bosses.length) + '%';
    document.getElementById('ch2-fin-lab').textContent = 'Побеждено: ' + cnt + ' / ' + bosses.length;
    if(cnt === bosses.length){
      document.getElementById('ch2-mastered').style.display = 'flex';
      const ACH_KEY = 'physics7_ch2_master';
      if(localStorage.getItem(ACH_KEY) !== '1'){
        localStorage.setItem(ACH_KEY, '1');
        if(window.addXp) window.addXp(50, 'ach-ch2-master');
        if(window.achievement) window.achievement('ch_done', 'Знаток вещества');
      }
    }
  }
  updateBar();

  body.querySelectorAll('.boss-hint').forEach(btn => btn.addEventListener('click', () => {
    const n = btn.dataset.n;
    const txt = body.querySelector('.boss-hint-txt[data-n="' + n + '"]');
    if(txt) txt.style.display = txt.style.display === 'none' ? 'block' : 'none';
  }));
  body.querySelectorAll('.boss-go').forEach(btn => btn.addEventListener('click', () => {
    const n = +btn.dataset.n;
    const b = bosses.find(x => x.n === n);
    const inp = body.querySelector('.boss-inp[data-n="' + n + '"]');
    const fb = body.querySelector('.boss-fb[data-n="' + n + '"]');
    const card = body.querySelector('[data-boss="' + n + '"]');
    const v = parseFloat((inp.value || '').replace(',', '.'));
    if(isNaN(v)){
      fb.style.display = 'block';
      fb.style.background = '#fee2e2'; fb.style.color = '#7f1d1d'; fb.style.borderLeft = '4px solid #dc2626';
      fb.textContent = 'Введи число.';
      return;
    }
    if(Math.abs(v - b.ans) < b.tol){
      fb.style.display = 'block';
      fb.style.background = '#d1fae5'; fb.style.color = '#065f46'; fb.style.borderLeft = '4px solid #10b981';
      fb.innerHTML = '&#10003; Босс повержен! +20 XP.';
      card.style.border = '2px solid #10b981';
      card.style.boxShadow = '0 0 0 3px rgba(16,185,129,.16)';
      btn.disabled = true; inp.disabled = true;
      if(!solved[n]){
        solved[n] = true;
        try{ localStorage.setItem(STATE_KEY, JSON.stringify(solved)); }catch(e){}
        if(window.addXp) window.addXp(20, 'boss-ch2-' + n);
        updateBar();
      }
    } else {
      fb.style.display = 'block';
      fb.style.background = '#fee2e2'; fb.style.color = '#7f1d1d'; fb.style.borderLeft = '4px solid #dc2626';
      fb.textContent = 'Не то. Перепроверь решение.';
    }
  }));
  body.querySelectorAll('.boss-inp').forEach(inp => inp.addEventListener('keydown', e => {
    if(e.key === 'Enter'){ e.preventDefault(); body.querySelector('.boss-go[data-n="' + inp.dataset.n + '"]').click(); }
  }));
}

window.PHYS7_CH2_WIDGETS = {
  p8: add_p8,
  p9: add_p9,
  p10: add_p10,
  p11: add_p11,
  p12: add_p12,
  p13: add_p13,
  final2: add_final2
};

})();
