// Физика 7 · Лабораторный практикум · 6 виртуальных ЛР.
// Палитра cyan (#0891b2). Каждая ЛР: Цель + Оборудование + Ход + Симуляция +
// Таблица измерений + Контрольные вопросы + Кнопка «Сдать ЛР».
// Ачивка «Лаборант 7 класса» (+80 XP) — за прохождение всех 6.

(function(){
'use strict';

const ACCENT = '#0891b2';
const ACCENT_D = '#0e7490';
const ACCENT_SOFT = '#cffafe';

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, body){
  const colorByKind = { goal:ACCENT, equip:'#d97706', steps:'#7c3aed', concl:'#10b981' };
  const labelByKind = { goal:'Цель', equip:'Оборудование', steps:'Ход работы', concl:'Вывод' };
  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:12px;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-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 submitBtn(lrId){
  return '<div style="text-align:center;margin-top:18px"><button class="ph7-lr-submit" data-lr="' + lrId + '" '
    + 'style="background:linear-gradient(135deg,' + ACCENT + ',' + ACCENT_D + ');color:#fff;border:none;padding:11px 26px;border-radius:11px;font-weight:700;font-size:.96rem;cursor:pointer;font-family:inherit;display:inline-flex;align-items:center;gap:8px;box-shadow:0 4px 14px rgba(8,145,178,.32)">'
    + '<svg viewBox="0 0 24 24" style="width:18px;height:18px;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:.84rem">+30 XP</span>'
    + '</button><div id="ph7-lr-fb-' + lrId + '" style="margin-top:10px;font-size:.92rem;font-weight:700"></div></div>';
}

function wireSubmit(lrId){
  const btn = document.querySelector('.ph7-lr-submit[data-lr="' + lrId + '"]');
  if(!btn) return;
  const KEY = 'physics7_lab_done_' + lrId;
  if(localStorage.getItem(KEY) === '1'){
    btn.innerHTML = '<svg viewBox="0 0 24 24" style="width:18px;height:18px;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', () => {
    if(localStorage.getItem(KEY) === '1') return;
    localStorage.setItem(KEY, '1');
    if(typeof window.bumpProgress === 'function') window.bumpProgress(lrId, 100);
    if(typeof window.addXp === 'function') window.addXp(30, 'lr-' + lrId);
    btn.innerHTML = '<svg viewBox="0 0 24 24" style="width:18px;height:18px;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';
    const fb = document.getElementById('ph7-lr-fb-' + lrId);
    if(fb){ fb.style.color = '#047857'; fb.textContent = '+30 XP получено.'; }
    // Проверка ачивки «Лаборант»
    const allDone = ['lr1','lr2','lr3','lr4','lr5','lr6'].every(k => localStorage.getItem('physics7_lab_done_' + k) === '1');
    if(allDone && localStorage.getItem('physics7_lab_master') !== '1'){
      localStorage.setItem('physics7_lab_master', '1');
      if(typeof window.addXp === 'function') window.addXp(80, 'lab-master');
      if(typeof window.achievement === 'function') window.achievement('all_labs', 'Лаборант 7 класса');
      if(fb) fb.innerHTML = '+30 XP. <span style="color:#92400e">&#10003; Ачивка «Лаборант 7 класса» +80 XP!</span>';
    }
  });
}

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" 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){
  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 : '');
      } 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);
    }));
  });
}

/* ========================================================== */
/* ЛР-1 — Цена деления шкалы измерительного прибора            */
/* ========================================================== */
function build_lr1(){
  const body = document.getElementById('lr1-body');
  if(!body) return;
  let h = '';

  h += makeCard('goal', 'Цель',
    'Научиться определять цену деления любого измерительного прибора по двум подписанным значениям и числу делений между ними.');

  h += makeCard('equip', 'Оборудование (виртуальное)',
    '<ul style="padding-left:20px;margin:5px 0"><li>Линейка</li><li>Мензурка</li><li>Термометр</li><li>Динамометр</li></ul>');

  h += makeCard('steps', 'Ход работы',
    '<ol style="padding-left:20px;margin:6px 0">'
    + '<li>Найди на шкале <b>две соседние подписанные отметки</b> $X_1$ и $X_2$.</li>'
    + '<li>Посчитай число малых делений <b>$N$</b> между ними.</li>'
    + '<li>Вычисли цену деления: $C = (X_2 - X_1)/N$.</li>'
    + '<li>Запиши результаты в таблицу.</li>'
    + '</ol>');

  /* Виджет: 4 прибора */
  h += wgWrap('lr1-w', 'СИМ', 'Виртуальные приборы',
    'Каждый прибор имеет свою цену деления. Подвинь slider — отсчёт пересчитывается.',
    '<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:14px">'
    + ['Линейка','Термометр','Мензурка','Динамометр'].map((nm, i) =>
        '<div style="background:#f0f9ff;border:1.5px solid ' + ACCENT_SOFT + ';border-radius:10px;padding:10px">'
        + '<div style="font-weight:700;color:' + ACCENT_D + ';font-size:.88rem;margin-bottom:8px">' + nm + '</div>'
        + '<svg id="lr1-svg-' + i + '" viewBox="0 0 200 90" width="100%" style="background:#fff;border-radius:6px"></svg>'
        + '<div style="margin-top:6px;font-size:.82rem;color:#475569;font-family:JetBrains Mono,monospace">$C = $ <b id="lr1-C-' + i + '" style="color:' + ACCENT_D + '">—</b></div>'
        + '</div>').join('')
    + '</div>');

  /* Таблица измерений */
  h += wgWrap('lr1-tbl', 'ТБЛ', 'Таблица измерений', '',
    '<table style="width:100%;border-collapse:collapse;font-size:.9rem">'
    + '<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 + '">$X_1$</th><th style="padding:6px 10px;text-align:right;border-bottom:2px solid ' + ACCENT + '">$X_2$</th><th style="padding:6px 10px;text-align:right;border-bottom:2px solid ' + ACCENT + '">$N$</th><th style="padding:6px 10px;text-align:right;border-bottom:2px solid ' + ACCENT + '">$C$</th></tr>'
    + [['Линейка','0','1 см','10','0,1 см = 1 мм'],['Термометр','0','10 °C','5','2 °C'],['Мензурка','0','100 мл','5','20 мл'],['Динамометр','0','5 Н','10','0,5 Н']].map(r =>
        '<tr><td style="padding:5px 10px;border-bottom:1px solid ' + ACCENT_SOFT + '">' + r[0] + '</td><td style="padding:5px 10px;text-align:right;border-bottom:1px solid ' + ACCENT_SOFT + ';font-family:JetBrains Mono,monospace">' + r[1] + '</td><td style="padding:5px 10px;text-align:right;border-bottom:1px solid ' + ACCENT_SOFT + ';font-family:JetBrains Mono,monospace">' + r[2] + '</td><td style="padding:5px 10px;text-align:right;border-bottom:1px solid ' + ACCENT_SOFT + ';font-family:JetBrains Mono,monospace">' + r[3] + '</td><td style="padding:5px 10px;text-align:right;border-bottom:1px solid ' + ACCENT_SOFT + ';font-family:JetBrains Mono,monospace;font-weight:700;color:' + ACCENT_D + '">' + r[4] + '</td></tr>').join('')
    + '</table>');

  /* Контрольные вопросы */
  h += wgWrap('lr1-q', 'ВОПР', 'Контрольные вопросы', '',
    '<div id="lr1-q-host">'
    + quizQuestion('lr1-q', 0, 'Что такое цена деления?', ['Расстояние между прибором и телом','Значение наименьшего деления шкалы','Размер шкалы','Цена прибора'], 1)
    + quizQuestion('lr1-q', 1, 'Между $0$ и $1$ см на линейке $10$ делений. $C = ?$', ['1 мм','5 мм','10 мм','0,1 мм'], 0, '$C = (10-0)/10 = 1$ мм.')
    + quizQuestion('lr1-q', 2, 'Чем меньше цена деления, тем прибор…', ['Дешевле','Меньше','Точнее','Тяжелее'], 2)
    + '</div>');

  h += makeCard('concl', 'Вывод',
    'Мы научились определять цену деления любого измерительного прибора. Формула $C = (X_2 - X_1)/N$ '
    + 'универсальна — работает для линейки, термометра, мензурки, динамометра и других приборов со шкалой. '
    + 'Чем меньше $C$, тем точнее прибор.');

  h += submitBtn('lr1');
  body.innerHTML = h;

  // Render 4 instruments
  const insts = [
    { ticks:11, lbl:i => i%10===0?(i/10):'', unit:'см', color:'#0284c7' },
    { ticks:6,  lbl:i => i*10, unit:'°C', color:'#dc2626' },
    { ticks:6,  lbl:i => i*100, unit:'мл', color:'#0891b2' },
    { ticks:11, lbl:i => i%2===0?(i*0.5):'', unit:'Н', color:'#d97706' }
  ];
  insts.forEach((inst, idx) => {
    const W = 200, H = 90;
    let s = '<rect x="0" y="20" width="' + W + '" height="40" fill="#fef9c3" stroke="' + inst.color + '" stroke-width="1.5" rx="2"/>';
    for(let i = 0; i < inst.ticks; i++){
      const x = 10 + (i * (W - 20) / (inst.ticks - 1));
      const tickH = 14;
      s += '<line x1="' + x + '" y1="20" x2="' + x + '" y2="' + (20 + tickH) + '" stroke="#0f172a" stroke-width="1.2"/>';
      const lbl = inst.lbl(i);
      if(lbl !== '') s += '<text x="' + x + '" y="' + (20 + tickH + 12) + '" text-anchor="middle" font-family="Inter,sans-serif" font-size="10" font-weight="600" fill="#0f172a">' + lbl + '</text>';
    }
    s += '<text x="' + (W-8) + '" y="35" text-anchor="end" font-family="Inter,sans-serif" font-size="10" fill="' + inst.color + '" font-weight="700">' + inst.unit + '</text>';
    document.getElementById('lr1-svg-' + idx).innerHTML = s;
    const cVals = ['1 мм','2 °C','20 мл','0,5 Н'];
    document.getElementById('lr1-C-' + idx).textContent = cVals[idx];
  });

  wireQuiz('lr1-q-host');
  wireSubmit('lr1');
  renderMath(body);
}

/* ========================================================== */
/* ЛР-2 — Измерение длины                                      */
/* ========================================================== */
function build_lr2(){
  const body = document.getElementById('lr2-body');
  if(!body) return;
  let h = '';

  h += makeCard('goal', 'Цель',
    'Научиться измерять длину предметов линейкой и записывать результат с учётом погрешности измерения.');

  h += makeCard('equip', 'Оборудование',
    '<ul style="padding-left:20px;margin:5px 0"><li>Линейка с миллиметровой шкалой</li><li>3 предмета разной длины (карандаш, тетрадь, брусок)</li></ul>');

  h += makeCard('steps', 'Ход работы',
    '<ol style="padding-left:20px;margin:6px 0">'
    + '<li>Положи предмет вдоль линейки. Совмести один край с отметкой $0$.</li>'
    + '<li>Прочитай отсчёт у другого края, округлив до ближайшего деления.</li>'
    + '<li>Цена деления $C = 1$ мм, поэтому погрешность $\\Delta l = C/2 = 0{,}5$ мм.</li>'
    + '<li>Запиши: $l = (l_0 \\pm \\Delta l)$ мм.</li>'
    + '</ol>');

  /* Виджет: 3 предмета по линейке */
  h += wgWrap('lr2-w', 'СИМ', 'Измерь 3 предмета', 'Выбери предмет — увидь его длину на линейке.',
    '<div style="display:flex;gap:6px;margin-bottom:10px;flex-wrap:wrap">'
    + [['penc','Карандаш',125],['tetr','Тетрадь',204],['brusk','Брусок',83]].map((o, i) =>
        '<button class="lr2-obj" data-l="' + o[2] + '" data-nm="' + o[1] + '" type="button" style="background:' + (i===0 ? ACCENT : '#fff') + ';color:' + (i===0 ? '#fff' : ACCENT) + ';border:2px solid ' + ACCENT + ';padding:7px 14px;border-radius:9px;cursor:pointer;font-weight:700;font-family:inherit;font-size:.86rem">' + o[1] + '</button>').join('')
    + '</div>'
    + '<svg id="lr2-svg" viewBox="0 0 360 110" width="100%" style="max-width:600px;display:block;margin:0 auto;background:#f0f9ff;border-radius:9px;border:1px solid ' + ACCENT_SOFT + '"></svg>'
    + '<div id="lr2-info" style="background:' + ACCENT_SOFT + ';border-radius:9px;padding:10px 14px;margin-top:8px;font-size:.94rem;text-align:center"></div>');

  /* Таблица */
  h += wgWrap('lr2-tbl', 'ТБЛ', 'Таблица измерений',
    '',
    '<table style="width:100%;border-collapse:collapse;font-size:.9rem">'
    + '<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 + '">$l_0$, мм</th><th style="padding:6px 10px;text-align:right;border-bottom:2px solid ' + ACCENT + '">$\\Delta l$, мм</th><th style="padding:6px 10px;text-align:right;border-bottom:2px solid ' + ACCENT + '">Запись</th></tr>'
    + [['Карандаш',125,0.5,'(125,0 ± 0,5) мм'],['Тетрадь',204,0.5,'(204,0 ± 0,5) мм'],['Брусок',83,0.5,'(83,0 ± 0,5) мм']].map(r =>
        '<tr><td style="padding:5px 10px;border-bottom:1px solid ' + ACCENT_SOFT + '">' + r[0] + '</td><td style="padding:5px 10px;text-align:right;border-bottom:1px solid ' + ACCENT_SOFT + ';font-family:JetBrains Mono,monospace">' + r[1] + '</td><td style="padding:5px 10px;text-align:right;border-bottom:1px solid ' + ACCENT_SOFT + ';font-family:JetBrains Mono,monospace">' + r[2] + '</td><td style="padding:5px 10px;text-align:right;border-bottom:1px solid ' + ACCENT_SOFT + ';font-family:JetBrains Mono,monospace;font-weight:700;color:' + ACCENT_D + '">' + r[3] + '</td></tr>').join('')
    + '</table>');

  h += wgWrap('lr2-q', 'ВОПР', 'Контрольные вопросы', '',
    '<div id="lr2-q-host">'
    + quizQuestion('lr2-q', 0, 'Чему равна погрешность миллиметровой линейки?', ['1 мм','0,5 мм','0,1 мм','2 мм'], 1, 'Половина цены деления: $1/2 = 0{,}5$ мм.')
    + quizQuestion('lr2-q', 1, 'Зачем записывать $\\Delta l$ в результате?', ['Для красоты','Чтобы показать границы возможной ошибки','По привычке','Не нужно'], 1)
    + quizQuestion('lr2-q', 2, 'Запись $l = (15{,}0 \\pm 0{,}5)$ мм означает, что $l$ может быть…', ['Любым','От 14,5 до 15,5 мм','От 10 до 20 мм','Точно 15 мм'], 1)
    + '</div>');

  h += makeCard('concl', 'Вывод',
    'Мы научились измерять длину предметов с погрешностью $\\Delta l = C/2 = 0{,}5$ мм. '
    + 'Любое измерение записывается в виде $l = (l_0 \\pm \\Delta l)$ — это указывает на границы, в которых лежит истинная длина.');

  h += submitBtn('lr2');
  body.innerHTML = h;

  // Render ruler with object
  function draw2(lenMm, nm){
    const W = 360, H = 110;
    const xPad = 20;
    const rulerW = W - 2 * xPad;
    const totalMm = 300;
    const pxPerMm = rulerW / totalMm;
    let s = '';
    // Object
    const objW = lenMm * pxPerMm;
    s += '<rect x="' + xPad + '" y="20" width="' + objW + '" height="22" fill="' + ACCENT + '" stroke="' + ACCENT_D + '" stroke-width="1.5" rx="2"/>';
    s += '<text x="' + (xPad + objW/2) + '" y="35" text-anchor="middle" font-family="Inter,sans-serif" font-size="11" font-weight="700" fill="#fff">' + nm + '</text>';
    // Ruler
    s += '<rect x="' + xPad + '" y="60" width="' + rulerW + '" height="32" fill="#fef9c3" stroke="#92400e" stroke-width="1.5" rx="2"/>';
    for(let mm = 0; mm <= totalMm; mm += 10){
      const x = xPad + mm * pxPerMm;
      const isCm = mm % 10 === 0, isBig = mm % 50 === 0;
      const tickH = isBig ? 14 : 10;
      s += '<line x1="' + x + '" y1="60" x2="' + x + '" y2="' + (60 + tickH) + '" stroke="#0f172a" stroke-width="' + (isBig ? 1.5 : 1) + '"/>';
      if(isBig) s += '<text x="' + x + '" y="' + (60 + 30) + '" text-anchor="middle" font-family="Inter,sans-serif" font-size="9" font-weight="600" fill="#0f172a">' + (mm/10) + '</text>';
    }
    // Mark of length
    const markX = xPad + lenMm * pxPerMm;
    s += '<line x1="' + markX + '" y1="40" x2="' + markX + '" y2="95" stroke="#dc2626" stroke-width="1.5" stroke-dasharray="3 2"/>';
    s += '<text x="' + (W - 6) + '" y="78" text-anchor="end" font-family="Inter,sans-serif" font-size="10" font-weight="700" fill="#92400e">см</text>';
    document.getElementById('lr2-svg').innerHTML = s;
    document.getElementById('lr2-info').innerHTML = '<b>' + nm + ':</b> отсчёт $l_0 = ' + lenMm + '$ мм $= ' + (lenMm/10).toFixed(1) + '$ см. С погрешностью: $l = (' + lenMm + ' \\pm 0{,}5)$ мм.';
    renderMath(document.getElementById('lr2-info'));
  }
  body.querySelectorAll('.lr2-obj').forEach(btn => btn.addEventListener('click', () => {
    body.querySelectorAll('.lr2-obj').forEach(b => { b.style.background = '#fff'; b.style.color = ACCENT; });
    btn.style.background = ACCENT; btn.style.color = '#fff';
    draw2(+btn.dataset.l, btn.dataset.nm);
  }));
  draw2(125, 'Карандаш');

  wireQuiz('lr2-q-host');
  wireSubmit('lr2');
  renderMath(body);
}

/* ========================================================== */
/* ЛР-3 — Измерение объёма (вытеснение жидкости)               */
/* ========================================================== */
function build_lr3(){
  const body = document.getElementById('lr3-body');
  if(!body) return;
  let h = '';

  h += makeCard('goal', 'Цель',
    'Научиться измерять объём тела неправильной формы методом вытеснения жидкости.');

  h += makeCard('equip', 'Оборудование',
    '<ul style="padding-left:20px;margin:5px 0"><li>Мензурка с водой</li><li>Тело неправильной формы (камень, гайка, болт)</li><li>Нитка</li></ul>');

  h += makeCard('steps', 'Ход работы',
    '<ol style="padding-left:20px;margin:6px 0">'
    + '<li>Налей в мензурку воды до отметки $V_1$. Запиши.</li>'
    + '<li>Опусти тело в мензурку (полностью под водой!).</li>'
    + '<li>Прочитай новый уровень $V_2$.</li>'
    + '<li>Объём тела: $V = V_2 - V_1$.</li>'
    + '</ol>');

  /* Виджет: мензурка с телом */
  h += wgWrap('lr3-w', 'СИМ', 'Измерь объём тела', 'Выбери тело и опусти его в мензурку.',
    '<div style="display:flex;gap:6px;margin-bottom:10px;flex-wrap:wrap">'
    + [['stone','Камень',45],['nut','Гайка',12],['bolt','Болт',23]].map((o, i) =>
        '<button class="lr3-obj" data-v="' + o[2] + '" data-nm="' + o[1] + '" type="button" style="background:' + (i===0 ? ACCENT : '#fff') + ';color:' + (i===0 ? '#fff' : ACCENT) + ';border:2px solid ' + ACCENT + ';padding:7px 14px;border-radius:9px;cursor:pointer;font-weight:700;font-family:inherit;font-size:.86rem">' + o[1] + '</button>').join('')
    + '</div>'
    + '<svg id="lr3-svg" viewBox="0 0 320 240" width="100%" style="max-width:400px;display:block;margin:0 auto;background:#f0f9ff;border-radius:9px;border:1px solid ' + ACCENT_SOFT + '"></svg>'
    + '<div id="lr3-info" style="background:' + ACCENT_SOFT + ';border-radius:9px;padding:10px 14px;margin-top:8px;font-size:.94rem;line-height:1.6"></div>');

  /* Таблица */
  h += wgWrap('lr3-tbl', 'ТБЛ', 'Таблица измерений', '',
    '<table style="width:100%;border-collapse:collapse;font-size:.9rem">'
    + '<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 + '">$V_1$, мл</th><th style="padding:6px 10px;text-align:right;border-bottom:2px solid ' + ACCENT + '">$V_2$, мл</th><th style="padding:6px 10px;text-align:right;border-bottom:2px solid ' + ACCENT + '">$V$, мл = см³</th></tr>'
    + [['Камень',100,145,45],['Гайка',100,112,12],['Болт',100,123,23]].map(r =>
        '<tr><td style="padding:5px 10px;border-bottom:1px solid ' + ACCENT_SOFT + '">' + r[0] + '</td><td style="padding:5px 10px;text-align:right;border-bottom:1px solid ' + ACCENT_SOFT + ';font-family:JetBrains Mono,monospace">' + r[1] + '</td><td style="padding:5px 10px;text-align:right;border-bottom:1px solid ' + ACCENT_SOFT + ';font-family:JetBrains Mono,monospace">' + r[2] + '</td><td style="padding:5px 10px;text-align:right;border-bottom:1px solid ' + ACCENT_SOFT + ';font-family:JetBrains Mono,monospace;font-weight:700;color:' + ACCENT_D + '">' + r[3] + '</td></tr>').join('')
    + '</table>');

  h += wgWrap('lr3-q', 'ВОПР', 'Контрольные вопросы', '',
    '<div id="lr3-q-host">'
    + quizQuestion('lr3-q', 0, 'Можно ли измерить объём картофелины линейкой?', ['Да','Нет — неправильная форма, нужна мензурка','Только если разрезать','Только большие'], 1)
    + quizQuestion('lr3-q', 1, '$V_1 = 50$ мл, $V_2 = 78$ мл. $V_{тела}$?', ['28 мл','78 мл','128 мл','50 мл'], 0, '$V = V_2 - V_1 = 78 - 50 = 28$ мл.')
    + quizQuestion('lr3-q', 2, '$1$ мл — это сколько см³?', ['0,1','1','10','100'], 1)
    + '</div>');

  h += makeCard('concl', 'Вывод',
    'Метод вытеснения жидкости позволяет измерить объём тела <b>любой</b> формы. Это пример <b>косвенного измерения</b>: '
    + 'мы напрямую измеряем уровни $V_1$ и $V_2$, а затем по формуле $V = V_2 - V_1$ вычисляем искомый объём.');

  h += submitBtn('lr3');
  body.innerHTML = h;

  function draw3(vTel, nm){
    const W = 320, H = 240;
    const W1 = 100, W2 = 200; // позиции 2 мензурок
    const mWidth = 60, mHeight = 180, mY = 30;
    const maxMl = 200;
    function drawMenz(x, label, V){
      let s = '';
      // Стенки
      s += '<line x1="' + x + '" y1="' + mY + '" x2="' + x + '" y2="' + (mY + mHeight) + '" stroke="#0f172a" stroke-width="2"/>';
      s += '<line x1="' + (x + mWidth) + '" y1="' + mY + '" x2="' + (x + mWidth) + '" y2="' + (mY + mHeight) + '" stroke="#0f172a" stroke-width="2"/>';
      s += '<line x1="' + x + '" y1="' + (mY + mHeight) + '" x2="' + (x + mWidth) + '" y2="' + (mY + mHeight) + '" stroke="#0f172a" stroke-width="2"/>';
      // Вода
      const waterH = (V / maxMl) * mHeight;
      s += '<rect x="' + (x + 1) + '" y="' + (mY + mHeight - waterH) + '" width="' + (mWidth - 2) + '" height="' + waterH + '" fill="#60a5fa" opacity="0.7"/>';
      // Шкала
      for(let ml = 0; ml <= maxMl; ml += 20){
        const y = mY + mHeight - (ml / maxMl) * mHeight;
        s += '<line x1="' + x + '" y1="' + y + '" x2="' + (x - 6) + '" y2="' + y + '" stroke="#0f172a" stroke-width="1"/>';
        if(ml % 40 === 0) s += '<text x="' + (x - 8) + '" y="' + (y + 3) + '" text-anchor="end" font-family="Inter,sans-serif" font-size="9" fill="#0f172a">' + ml + '</text>';
      }
      // Подпись V
      s += '<text x="' + (x + mWidth/2) + '" y="' + (mY + mHeight + 18) + '" text-anchor="middle" font-family="Unbounded,sans-serif" font-size="11" font-weight="800" fill="' + ACCENT_D + '">' + label + '</text>';
      s += '<text x="' + (x + mWidth/2) + '" y="' + (mY + mHeight + 32) + '" text-anchor="middle" font-family="JetBrains Mono,monospace" font-size="11" font-weight="700" fill="#0f172a">' + V + ' мл</text>';
      return s;
    }
    let s = '';
    s += drawMenz(W1, 'V₁', 100);
    s += drawMenz(W2, 'V₂', 100 + vTel);
    // Тело во второй мензурке
    s += '<circle cx="' + (W2 + mWidth/2) + '" cy="' + (mY + mHeight - 20) + '" r="' + Math.min(15, Math.sqrt(vTel)*1.4) + '" fill="#475569" stroke="#0f172a" stroke-width="1.5"/>';
    // Стрелка
    s += '<line x1="170" y1="120" x2="195" y2="120" stroke="' + ACCENT + '" stroke-width="2"/>';
    s += '<polygon points="195,120 188,116 188,124" fill="' + ACCENT + '"/>';
    s += '<text x="182" y="110" text-anchor="middle" font-family="Inter,sans-serif" font-size="10" fill="' + ACCENT_D + '" font-weight="700">опускаем</text>';
    s += '<text x="182" y="138" text-anchor="middle" font-family="Inter,sans-serif" font-size="10" fill="' + ACCENT_D + '">тело</text>';
    document.getElementById('lr3-svg').innerHTML = s;
    document.getElementById('lr3-info').innerHTML = '<b>' + nm + '</b>: $V_1 = 100$ мл, $V_2 = ' + (100 + vTel) + '$ мл &nbsp;→&nbsp; '
      + '<b>$V = V_2 - V_1 = ' + vTel + '$ мл $= ' + vTel + '$ см³</b>';
    renderMath(document.getElementById('lr3-info'));
  }
  body.querySelectorAll('.lr3-obj').forEach(btn => btn.addEventListener('click', () => {
    body.querySelectorAll('.lr3-obj').forEach(b => { b.style.background = '#fff'; b.style.color = ACCENT; });
    btn.style.background = ACCENT; btn.style.color = '#fff';
    draw3(+btn.dataset.v, btn.dataset.nm);
  }));
  draw3(45, 'Камень');

  wireQuiz('lr3-q-host');
  wireSubmit('lr3');
  renderMath(body);
}

/* ========================================================== */
/* ЛР-4 — Изучение неравномерного движения                     */
/* ========================================================== */
function build_lr4(){
  const body = document.getElementById('lr4-body');
  if(!body) return;
  let h = '';

  h += makeCard('goal', 'Цель',
    'Измерить среднюю скорость движения шарика, скатывающегося по наклонной плоскости, для разных углов наклона.');

  h += makeCard('equip', 'Оборудование',
    '<ul style="padding-left:20px;margin:5px 0"><li>Желоб (наклонная плоскость)</li><li>Шарик</li><li>Секундомер</li><li>Линейка / мерная лента</li></ul>');

  h += makeCard('steps', 'Ход работы',
    '<ol style="padding-left:20px;margin:6px 0">'
    + '<li>Установи желоб под углом 15°. Отпусти шарик с верха.</li>'
    + '<li>Засеки время $t$ от старта до конца желоба.</li>'
    + '<li>Измерь путь $s$ (длину желоба).</li>'
    + '<li>Вычисли $\\langle v\\rangle = s/t$.</li>'
    + '<li>Повтори для углов 30° и 45°.</li>'
    + '</ol>');

  /* Виджет: симуляция шарика */
  h += wgWrap('lr4-w', 'СИМ', 'Шарик на наклонной плоскости',
    'Меняй угол, нажимай «Запустить» — шарик скатится, время и средняя скорость измерятся автоматически.',
    '<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:8px;margin-bottom:10px">'
    + '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:7px 11px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">Угол $\\alpha$, °: <b id="lr4-a" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">15</b><input type="range" id="lr4-a-r" min="10" max="60" step="5" value="15" style="display:block;width:100%;margin-top:5px;accent-color:' + ACCENT + '"></label>'
    + '<div style="display:flex;gap:6px;align-items:end"><button id="lr4-go" type="button" style="background:linear-gradient(135deg,' + ACCENT + ',' + ACCENT_D + ');color:#fff;border:none;padding:8px 18px;border-radius:9px;cursor:pointer;font-weight:700;font-family:inherit;font-size:.88rem">Запустить</button></div>'
    + '</div>'
    + '<svg id="lr4-svg" viewBox="0 0 360 200" width="100%" style="max-width:500px;display:block;margin:0 auto;background:#f0f9ff;border-radius:9px;border:1px solid ' + ACCENT_SOFT + '"></svg>'
    + '<div id="lr4-info" style="background:' + ACCENT_SOFT + ';border-radius:9px;padding:10px 14px;margin-top:8px;font-size:.94rem;text-align:center"></div>');

  h += wgWrap('lr4-tbl', 'ТБЛ', 'Таблица измерений', '',
    '<table style="width:100%;border-collapse:collapse;font-size:.9rem">'
    + '<tr style="background:' + ACCENT_SOFT + '"><th style="padding:6px 10px;text-align:left;border-bottom:2px solid ' + ACCENT + '">Угол $\\alpha$</th><th style="padding:6px 10px;text-align:right;border-bottom:2px solid ' + ACCENT + '">$s$, м</th><th style="padding:6px 10px;text-align:right;border-bottom:2px solid ' + ACCENT + '">$t$, с</th><th style="padding:6px 10px;text-align:right;border-bottom:2px solid ' + ACCENT + '">$\\langle v\\rangle$, м/с</th></tr>'
    + [['15°','1,0','1,7','0,59'],['30°','1,0','1,1','0,91'],['45°','1,0','0,8','1,25']].map(r =>
        '<tr><td style="padding:5px 10px;border-bottom:1px solid ' + ACCENT_SOFT + '">' + r[0] + '</td><td style="padding:5px 10px;text-align:right;border-bottom:1px solid ' + ACCENT_SOFT + ';font-family:JetBrains Mono,monospace">' + r[1] + '</td><td style="padding:5px 10px;text-align:right;border-bottom:1px solid ' + ACCENT_SOFT + ';font-family:JetBrains Mono,monospace">' + r[2] + '</td><td style="padding:5px 10px;text-align:right;border-bottom:1px solid ' + ACCENT_SOFT + ';font-family:JetBrains Mono,monospace;font-weight:700;color:' + ACCENT_D + '">' + r[3] + '</td></tr>').join('')
    + '</table>');

  h += wgWrap('lr4-q', 'ВОПР', 'Контрольные вопросы', '',
    '<div id="lr4-q-host">'
    + quizQuestion('lr4-q', 0, 'Каков физический смысл $\\langle v\\rangle$?', ['Скорость в средней точке','Скорость, при которой за то же время прошёл бы тот же путь','Полусумма начальной и конечной','Скорость покоя'], 1)
    + quizQuestion('lr4-q', 1, 'Что изменится, если увеличить угол?', ['Время больше, скорость меньше','Время меньше, $\\langle v\\rangle$ больше','Ничего не изменится','Скорость станет нулевой'], 1, 'Чем круче — тем быстрее скатывается.')
    + quizQuestion('lr4-q', 2, 'Шарик прошёл $s = 2$ м за $t = 4$ с. $\\langle v\\rangle$?', ['0,2 м/с','0,5 м/с','1 м/с','2 м/с'], 1, '$\\langle v\\rangle = 2/4 = 0{,}5$ м/с.')
    + '</div>');

  h += makeCard('concl', 'Вывод',
    'Чем больше угол наклона, тем сильнее ускорение шарика и тем выше его средняя скорость. '
    + 'Движение шарика — <b>неравномерное</b>: его мгновенная скорость растёт от нуля в начале до максимума в конце. '
    + 'Формула $\\langle v\\rangle = s/t$ даёт усреднённую характеристику, удобную для сравнения.');

  h += submitBtn('lr4');
  body.innerHTML = h;

  let lr4Anim = { raf: 0, t: 0, running: false, totalT: 0, ang: 15 };
  function drawTrack(){
    const ang = +document.getElementById('lr4-a-r').value;
    document.getElementById('lr4-a').textContent = ang;
    lr4Anim.ang = ang;
    const W = 360, H = 200, baseY = 170;
    const len = 220;
    const a = ang * Math.PI / 180;
    const x1 = 40, y1 = baseY;
    const x2 = x1 + len * Math.cos(a);
    const y2 = baseY - len * Math.sin(a);
    let s = '';
    s += '<line x1="0" y1="' + baseY + '" x2="' + W + '" y2="' + baseY + '" stroke="#0f172a" stroke-width="1.5"/>';
    s += '<polygon points="' + x1 + ',' + y1 + ' ' + (x1 + len*Math.cos(a)) + ',' + y1 + ' ' + x2 + ',' + y2 + '" fill="' + ACCENT_SOFT + '" stroke="' + ACCENT_D + '" stroke-width="1.5"/>';
    // Шарик в начальной позиции (на верху)
    const t = lr4Anim.t;
    const totalT = Math.max(0.5, 2.0 - ang * 0.025); // эмпирическая формула: больше угол — меньше время
    lr4Anim.totalT = totalT;
    let progress = t / totalT;
    if(progress > 1) progress = 1;
    // Шарик ускоряется (квадратичная зависимость пути от времени)
    const sFrac = progress * progress;
    const bx = x2 + (x1 - x2) * sFrac;
    const by = y2 + (y1 - y2) * sFrac;
    s += '<circle cx="' + bx.toFixed(1) + '" cy="' + (by - 10).toFixed(1) + '" r="9" fill="' + ACCENT + '" stroke="' + ACCENT_D + '" stroke-width="1.5"/>';
    // Подпись
    s += '<text x="' + W + '" y="20" text-anchor="end" font-family="Inter,sans-serif" font-size="11" font-weight="700" fill="' + ACCENT_D + '">α = ' + ang + '°</text>';
    s += '<text x="' + W + '" y="36" text-anchor="end" font-family="Inter,sans-serif" font-size="11" font-weight="700" fill="' + ACCENT_D + '">s = 1,0 м</text>';
    s += '<text x="' + W + '" y="52" text-anchor="end" font-family="Inter,sans-serif" font-size="11" font-weight="700" fill="#dc2626">t = ' + t.toFixed(2) + ' с</text>';
    document.getElementById('lr4-svg').innerHTML = s;
    const vavg = progress >= 1 ? (1.0 / totalT) : 0;
    document.getElementById('lr4-info').innerHTML = progress >= 1
      ? '<b>Шарик скатился!</b> $t = ' + totalT.toFixed(2) + '$ с &middot; $s = 1{,}0$ м &middot; $\\langle v\\rangle = s/t = ' + vavg.toFixed(2) + '$ м/с'
      : 'В движении... $t = ' + t.toFixed(2) + '$ с';
    renderMath(document.getElementById('lr4-info'));
  }
  function lr4Loop(){
    if(!lr4Anim.running) return;
    lr4Anim.t += 0.02;
    if(lr4Anim.t >= lr4Anim.totalT){
      lr4Anim.t = lr4Anim.totalT;
      lr4Anim.running = false;
      drawTrack();
      return;
    }
    drawTrack();
    lr4Anim.raf = requestAnimationFrame(lr4Loop);
  }
  document.getElementById('lr4-a-r').addEventListener('input', () => { lr4Anim.t = 0; lr4Anim.running = false; drawTrack(); });
  document.getElementById('lr4-go').addEventListener('click', () => {
    lr4Anim.t = 0; lr4Anim.running = true;
    if(lr4Anim.raf) cancelAnimationFrame(lr4Anim.raf);
    lr4Loop();
  });
  drawTrack();

  wireQuiz('lr4-q-host');
  wireSubmit('lr4');
  renderMath(body);
}

/* ========================================================== */
/* ЛР-5 — Измерение плотности вещества                         */
/* ========================================================== */
function build_lr5(){
  const body = document.getElementById('lr5-body');
  if(!body) return;
  let h = '';

  h += makeCard('goal', 'Цель',
    'Измерить плотности трёх веществ и определить, что это за материалы, по таблице плотностей.');

  h += makeCard('equip', 'Оборудование',
    '<ul style="padding-left:20px;margin:5px 0"><li>Весы (электронные или рычажные)</li><li>Мензурка</li><li>3 образца разных материалов</li><li>Нитка для опускания</li></ul>');

  h += makeCard('steps', 'Ход работы',
    '<ol style="padding-left:20px;margin:6px 0">'
    + '<li>Измерь массу $m$ образца на весах.</li>'
    + '<li>Измерь его объём $V$ методом вытеснения (как в ЛР-3).</li>'
    + '<li>Вычисли $\\rho = m/V$.</li>'
    + '<li>Найди в таблице вещество с такой плотностью.</li>'
    + '</ol>');

  /* Виджет */
  h += wgWrap('lr5-w', 'СИМ', '3 образца — определи вещество', 'Выбери образец — увидь массу и объём, вычисли плотность.',
    '<div style="display:flex;gap:6px;margin-bottom:10px;flex-wrap:wrap">'
    + [['s1','Образец 1',54,20],['s2','Образец 2',156,20],['s3','Образец 3',272,20]].map((o, i) =>
        '<button class="lr5-obj" data-m="' + o[2] + '" data-v="' + o[3] + '" data-nm="' + o[1] + '" type="button" style="background:' + (i===0 ? ACCENT : '#fff') + ';color:' + (i===0 ? '#fff' : ACCENT) + ';border:2px solid ' + ACCENT + ';padding:7px 14px;border-radius:9px;cursor:pointer;font-weight:700;font-family:inherit;font-size:.86rem">' + o[1] + '</button>').join('')
    + '</div>'
    + '<div style="display:grid;grid-template-columns:1fr 1fr;gap:14px;align-items:center;background:#f0f9ff;border-radius:9px;border:1px solid ' + ACCENT_SOFT + ';padding:14px">'
    +   '<div style="text-align:center">'
    +     '<div style="font-size:.84rem;color:#475569;margin-bottom:6px">Весы</div>'
    +     '<div style="background:#fff;border:2px solid ' + ACCENT_D + ';border-radius:8px;padding:14px;font-family:JetBrains Mono,monospace;font-weight:800;font-size:1.4rem;color:' + ACCENT_D + '" id="lr5-m">54 г</div>'
    +   '</div>'
    +   '<div style="text-align:center">'
    +     '<div style="font-size:.84rem;color:#475569;margin-bottom:6px">Мензурка</div>'
    +     '<div style="background:#fff;border:2px solid ' + ACCENT_D + ';border-radius:8px;padding:14px;font-family:JetBrains Mono,monospace;font-weight:800;font-size:1.4rem;color:' + ACCENT_D + '" id="lr5-V">20 см³</div>'
    +   '</div>'
    + '</div>'
    + '<div id="lr5-info" style="background:' + ACCENT_SOFT + ';border-radius:9px;padding:12px 14px;margin-top:10px;font-size:.96rem;line-height:1.7;text-align:center"></div>');

  /* Таблица */
  h += wgWrap('lr5-tbl', 'ТБЛ', 'Таблица плотностей (для сравнения)', '',
    '<table style="width:100%;border-collapse:collapse;font-size:.9rem">'
    + '<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 + '">$\\rho$, г/см³</th></tr>'
    + [['Сосна',0.5],['Лёд',0.9],['Вода',1.0],['Алюминий',2.7],['Железо',7.8],['Медь',8.9],['Свинец',11.3],['Ртуть',13.6],['Золото',19.3]].map(r =>
        '<tr><td style="padding:5px 10px;border-bottom:1px solid ' + ACCENT_SOFT + '">' + r[0] + '</td><td style="padding:5px 10px;text-align:right;border-bottom:1px solid ' + ACCENT_SOFT + ';font-family:JetBrains Mono,monospace;font-weight:700">' + r[1] + '</td></tr>').join('')
    + '</table>');

  h += wgWrap('lr5-q', 'ВОПР', 'Контрольные вопросы', '',
    '<div id="lr5-q-host">'
    + quizQuestion('lr5-q', 0, 'Образец 1 имеет $m = 54$ г, $V = 20$ см³. $\\rho$?', ['1,7 г/см³','2,7 г/см³','3,7 г/см³','5,4 г/см³'], 1, '$54/20 = 2{,}7$ г/см³ — алюминий.')
    + quizQuestion('lr5-q', 1, 'Образец 2: $m = 156$ г, $V = 20$ см³. Что это?', ['Лёд','Алюминий','Железо','Свинец'], 2, '$156/20 = 7{,}8$ г/см³ — железо.')
    + quizQuestion('lr5-q', 2, 'Какое измерение здесь косвенное?', ['Массы','Объёма','Плотности','Времени'], 2, 'Плотность вычисляется через прямые $m$ и $V$.')
    + '</div>');

  h += makeCard('concl', 'Вывод',
    'Зная массу и объём тела, можно вычислить плотность вещества и определить, что это за материал. '
    + 'Измерение плотности — пример <b>косвенного</b> измерения через два прямых ($m$ и $V$). '
    + 'Таблицы плотностей позволяют идентифицировать неизвестные вещества.');

  h += submitBtn('lr5');
  body.innerHTML = h;

  function matName(rho){
    if(rho < 0.6) return 'дерево (сосна)';
    if(rho < 0.95) return 'лёд';
    if(rho < 1.1) return 'вода';
    if(rho < 3) return 'алюминий';
    if(rho < 9) return 'железо / медь';
    if(rho < 14) return 'свинец / ртуть';
    return 'золото / платина';
  }
  function upd5(m, V, nm){
    document.getElementById('lr5-m').textContent = m + ' г';
    document.getElementById('lr5-V').textContent = V + ' см³';
    const rho = m / V;
    document.getElementById('lr5-info').innerHTML = '<b>' + nm + ':</b> $\\rho = m/V = ' + m + '/' + V + ' = $ <b style="color:' + ACCENT_D + '">' + rho.toFixed(2) + '</b> г/см³.<br>'
      + '<span style="color:#475569;font-size:.88rem">Похоже на: <b>' + matName(rho) + '</b></span>';
    renderMath(document.getElementById('lr5-info'));
  }
  body.querySelectorAll('.lr5-obj').forEach(btn => btn.addEventListener('click', () => {
    body.querySelectorAll('.lr5-obj').forEach(b => { b.style.background = '#fff'; b.style.color = ACCENT; });
    btn.style.background = ACCENT; btn.style.color = '#fff';
    upd5(+btn.dataset.m, +btn.dataset.v, btn.dataset.nm);
  }));
  upd5(54, 20, 'Образец 1');

  wireQuiz('lr5-q-host');
  wireSubmit('lr5');
  renderMath(body);
}

/* ========================================================== */
/* ЛР-6 — Изучение силы трения                                 */
/* ========================================================== */
function build_lr6(){
  const body = document.getElementById('lr6-body');
  if(!body) return;
  let h = '';

  h += makeCard('goal', 'Цель',
    'Измерить силу трения скольжения для разных поверхностей и убедиться, что $F_{тр} \\sim N$ (зависит от нормальной реакции).');

  h += makeCard('equip', 'Оборудование',
    '<ul style="padding-left:20px;margin:5px 0"><li>Деревянный брусок</li><li>Грузы по 100 г</li><li>Динамометр</li><li>Разные поверхности (дерево, пластик, резина)</li></ul>');

  h += makeCard('steps', 'Ход работы',
    '<ol style="padding-left:20px;margin:6px 0">'
    + '<li>Положи брусок на поверхность. Прицепи к нему динамометр.</li>'
    + '<li>Тяни <b>равномерно</b> и измерь $F_{тр}$ — это сила, которую показал динамометр (=сила тяги при равномерном движении).</li>'
    + '<li>Добавляй грузы по 100 г и снова измеряй $F_{тр}$.</li>'
    + '<li>Поменяй поверхность — повтори.</li>'
    + '</ol>');

  /* Виджет */
  h += wgWrap('lr6-w', 'СИМ', 'Брусок с динамометром', 'Меняй массу и поверхность — увидь силу трения.',
    '<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:8px;margin-bottom:10px">'
    + '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:7px 11px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">Масса (брусок + грузы), г: <b id="lr6-m" style="color:' + ACCENT_D + ';font-family:JetBrains Mono,monospace">100</b><input type="range" id="lr6-m-r" min="100" max="500" step="100" value="100" style="display:block;width:100%;margin-top:5px;accent-color:' + ACCENT + '"></label>'
    + '<label style="display:block;font-size:.86rem;color:#475569;background:#fff;padding:7px 11px;border-radius:8px;border:1px solid ' + ACCENT_SOFT + '">Поверхность:<select id="lr6-surf" style="width:100%;margin-top:5px;padding:6px;border-radius:6px;border:1px solid ' + ACCENT_SOFT + ';font-family:inherit"><option value="0.3" selected>Дерево по дереву (μ=0,3)</option><option value="0.2">Дерево по пластику (μ=0,2)</option><option value="0.5">Дерево по резине (μ=0,5)</option><option value="0.04">Дерево по льду (μ=0,04)</option></select></label>'
    + '</div>'
    + '<svg id="lr6-svg" viewBox="0 0 380 180" width="100%" style="max-width:600px;display:block;margin:0 auto;background:#f0f9ff;border-radius:9px;border:1px solid ' + ACCENT_SOFT + '"></svg>'
    + '<div id="lr6-info" style="background:' + ACCENT_SOFT + ';border-radius:9px;padding:10px 14px;margin-top:8px;font-size:.94rem;text-align:center"></div>');

  h += wgWrap('lr6-tbl', 'ТБЛ', 'Таблица измерений (μ=0,3, дерево по дереву)',
    '',
    '<table style="width:100%;border-collapse:collapse;font-size:.9rem">'
    + '<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 + '">$m$, кг</th><th style="padding:6px 10px;text-align:right;border-bottom:2px solid ' + ACCENT + '">$N = mg$, Н</th><th style="padding:6px 10px;text-align:right;border-bottom:2px solid ' + ACCENT + '">$F_{тр}$, Н</th></tr>'
    + [['0 (брусок)',0.1,1.0,0.3],['+1 груз',0.2,2.0,0.6],['+2 груза',0.3,3.0,0.9],['+3 груза',0.4,4.0,1.2],['+4 груза',0.5,5.0,1.5]].map(r =>
        '<tr><td style="padding:5px 10px;border-bottom:1px solid ' + ACCENT_SOFT + '">' + r[0] + '</td><td style="padding:5px 10px;text-align:right;border-bottom:1px solid ' + ACCENT_SOFT + ';font-family:JetBrains Mono,monospace">' + r[1] + '</td><td style="padding:5px 10px;text-align:right;border-bottom:1px solid ' + ACCENT_SOFT + ';font-family:JetBrains Mono,monospace">' + r[2] + '</td><td style="padding:5px 10px;text-align:right;border-bottom:1px solid ' + ACCENT_SOFT + ';font-family:JetBrains Mono,monospace;font-weight:700;color:' + ACCENT_D + '">' + r[3] + '</td></tr>').join('')
    + '</table>'
    + '<p style="margin-top:8px;font-size:.86rem;color:#475569">Видно, что $F_{тр}$ растёт <b>пропорционально</b> массе — то есть пропорционально $N$. Это и есть закон $F_{тр} \\sim N$.</p>');

  h += wgWrap('lr6-q', 'ВОПР', 'Контрольные вопросы', '',
    '<div id="lr6-q-host">'
    + quizQuestion('lr6-q', 0, 'Если массу удвоить, $F_{тр}$ скольжения…', ['Не изменится','Удвоится','Уменьшится в 2 раза','Останется','Станет 0'], 1)
    + quizQuestion('lr6-q', 1, 'Какая поверхность дает наименьшее трение?', ['Дерево','Резина','Лёд','Пластик'], 2, 'У льда $\\mu \\approx 0{,}04$ — поэтому скользко.')
    + quizQuestion('lr6-q', 2, 'Брусок $m = 0{,}5$ кг, $\\mu = 0{,}3$, $g = 10$. $F_{тр}$?', ['0,5 Н','1 Н','1,5 Н','3 Н'], 2, '$F_{тр} = \\mu mg = 0{,}3 \\cdot 0{,}5 \\cdot 10 = 1{,}5$ Н.')
    + '</div>');

  h += makeCard('concl', 'Вывод',
    'Эксперимент подтвердил, что сила трения скольжения <b>прямо пропорциональна</b> нормальной реакции (а значит — массе тела). '
    + 'Коэффициент трения $\\mu$ зависит от пары поверхностей: для дерево-лёд он очень мал ($\\sim 0{,}04$), '
    + 'для дерево-резина — большой ($\\sim 0{,}5$). Поэтому шипованная резина не скользит по асфальту и снегу.');

  h += submitBtn('lr6');
  body.innerHTML = h;

  function draw6(){
    const m = +document.getElementById('lr6-m-r').value;
    const mu = +document.getElementById('lr6-surf').value;
    document.getElementById('lr6-m').textContent = m;
    const N = m / 1000 * 10; // m в г → кг → N
    const Ftr = mu * N;
    const W = 380, H = 180, baseY = 130;
    let s = '';
    s += '<rect x="0" y="' + baseY + '" width="' + W + '" height="50" fill="#94a3b8"/>';
    for(let i = 0; i < 18; i++) s += '<line x1="' + (i*22+5) + '" y1="' + baseY + '" x2="' + (i*22+15) + '" y2="' + (baseY+8) + '" stroke="#374151" stroke-width="0.8"/>';
    const bx = 80, bw = 60, bh = 40;
    // Грузы наверху
    const numGr = Math.max(0, (m - 100) / 100);
    for(let i = 0; i < numGr; i++){
      s += '<rect x="' + (bx + 12) + '" y="' + (baseY - bh - 12 - i*10) + '" width="36" height="10" fill="#475569" stroke="#1f2937" stroke-width="0.8" rx="2"/>';
    }
    // Брусок
    s += '<rect x="' + bx + '" y="' + (baseY - bh) + '" width="' + bw + '" height="' + bh + '" fill="' + ACCENT + '" stroke="' + ACCENT_D + '" stroke-width="1.5" rx="3"/>';
    s += '<text x="' + (bx + bw/2) + '" y="' + (baseY - bh/2 + 5) + '" text-anchor="middle" font-family="Inter,sans-serif" font-size="11" font-weight="700" fill="#fff">' + m + ' г</text>';
    // Динамометр + нить
    const dynX = bx + bw + 20;
    s += '<line x1="' + (bx + bw) + '" y1="' + (baseY - bh/2) + '" x2="' + dynX + '" y2="' + (baseY - bh/2) + '" stroke="#0f172a" stroke-width="1.5"/>';
    s += '<rect x="' + dynX + '" y="' + (baseY - bh/2 - 18) + '" width="60" height="36" fill="#fef3c7" stroke="#92400e" stroke-width="1.5" rx="4"/>';
    s += '<text x="' + (dynX + 30) + '" y="' + (baseY - bh/2 + 3) + '" text-anchor="middle" font-family="JetBrains Mono,monospace" font-size="13" font-weight="800" fill="#92400e">' + Ftr.toFixed(2) + ' Н</text>';
    s += '<text x="' + (dynX + 30) + '" y="' + (baseY - bh/2 - 22) + '" text-anchor="middle" font-family="Inter,sans-serif" font-size="9" fill="#92400e" font-weight="700">динамометр</text>';
    // Стрелка тяги
    s += '<line x1="' + (dynX + 60) + '" y1="' + (baseY - bh/2) + '" x2="' + (dynX + 100) + '" y2="' + (baseY - bh/2) + '" stroke="#10b981" stroke-width="2.5"/>';
    s += '<polygon points="' + (dynX + 100) + ',' + (baseY - bh/2) + ' ' + (dynX + 92) + ',' + (baseY - bh/2 - 5) + ' ' + (dynX + 92) + ',' + (baseY - bh/2 + 5) + '" fill="#10b981"/>';
    // Стрелка трения
    s += '<line x1="' + bx + '" y1="' + (baseY - 5) + '" x2="' + (bx - 40) + '" y2="' + (baseY - 5) + '" stroke="#92400e" stroke-width="2.5"/>';
    s += '<polygon points="' + (bx - 40) + ',' + (baseY - 5) + ' ' + (bx - 32) + ',' + (baseY - 10) + ' ' + (bx - 32) + ',' + baseY + '" fill="#92400e"/>';
    s += '<text x="' + (bx - 42) + '" y="' + (baseY - 12) + '" text-anchor="end" font-family="Inter,sans-serif" font-size="10" font-weight="700" fill="#92400e">F_тр</text>';
    document.getElementById('lr6-svg').innerHTML = s;
    document.getElementById('lr6-info').innerHTML = '$m = ' + (m/1000).toFixed(2) + '$ кг, $N = mg = ' + N.toFixed(1) + '$ Н, $\\mu = ' + mu + '$ &nbsp;→&nbsp; <b>$F_{тр} = \\mu N = ' + Ftr.toFixed(2) + '$ Н</b>';
    renderMath(document.getElementById('lr6-info'));
  }
  document.getElementById('lr6-m-r').addEventListener('input', draw6);
  document.getElementById('lr6-surf').addEventListener('change', draw6);
  draw6();

  wireQuiz('lr6-q-host');
  wireSubmit('lr6');
  renderMath(body);
}

window.PHYS7_LAB_WIDGETS = {
  lr1: build_lr1,
  lr2: build_lr2,
  lr3: build_lr3,
  lr4: build_lr4,
  lr5: build_lr5,
  lr6: build_lr6
};

})();
