Files
Learn_System/frontend/textbooks/geometry_8_ch3.html
T
Maxim Dolgolyov 4803f970c1 feat(geom8): Wave 3 Главы 3 — §6-§7 (второй СУС и третий ССС признаки подобия)
§6 Второй признак (СУС — сторона-угол-сторона): SVG двух треугольников
с 4 слайдерами (AB, AC, угол A, k), второй автомасштабируется через SAS;
5-шаговое доказательство; калькулятор через теорему косинусов; DnD
подобны/не подобны (5 пар); тренажёр; босс.

§7 Третий признак (ССС — три стороны): SVG двух треугольников с 4
слайдерами (a, b, c, k), оба строятся через теорему косинусов с проверкой
неравенства треугольника; 5-шаговое доказательство; калькулятор проверки
пропорциональности 6 сторон; DnD; mini-quiz из 5 вопросов на все 3
признака (УУ, СУС, ССС); тренажёр; босс.

File: 2338 → 3182 LOC. 7 of 9 §§ Главы 3 готовы.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 14:35:06 +03:00

3183 lines
268 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">
<title>Геометрия 8 · Глава 3 · Подобные треугольники</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css">
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.js"></script>
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/contrib/auto-render.min.js"
onload="renderMathInElement(document.body,{delimiters:[{left:'$$',right:'$$',display:true},{left:'$',right:'$',display:false},{left:'\\[',right:'\\]',display:true},{left:'\\(',right:'\\)',display:false}],throwOnError:false})"></script>
<script src="/js/api.js" defer></script>
<script src="/js/xp.js" defer></script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=Manrope:wght@600;700;800;900&family=Unbounded:wght@700;800;900&family=JetBrains+Mono:wght@500;700&display=swap" rel="stylesheet">
<style>
:root{
--bg:#fafafa; --card:#fff; --card-soft:#faf5ff; --text:#0f172a; --ink:#0f172a; --muted:#64748b;
--border:#e2e8f0; --sh:0 1px 3px rgba(0,0,0,.06); --sh2:0 4px 14px rgba(0,0,0,.08);
--pri:#7c3aed; --pri2:#6d28d9; --pri-soft:#ede9fe;
--acc:#8b5cf6; --acc2:#7c3aed; --acc-soft:#ddd6fe;
--ok:#10b981; --ok-bg:#d1fae5; --warn:#f59e0b; --warn-bg:#fef3c7;
--bad:#ef4444; --fail:#dc2626; --fail-bg:#fee2e2;
}
.dark{--bg:#08030e; --card:#10071a; --card-soft:#140820; --text:#f3e8ff; --ink:#f3e8ff; --muted:#9f7ec0; --border:#2a1040}
*{margin:0;padding:0;box-sizing:border-box;-webkit-tap-highlight-color:transparent}
html,body{font-family:'Inter',system-ui,sans-serif;background:var(--bg);color:var(--text);line-height:1.55;font-size:15px}
button,input,select,textarea{font-family:inherit;font-size:inherit}
button{cursor:pointer;border:0;background:transparent;color:inherit}
a{color:inherit;text-decoration:none}
.ic{width:16px;height:16px;display:inline-block;flex-shrink:0;stroke:currentColor;fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;vertical-align:middle}
.hdr{position:relative;background:linear-gradient(110deg,#3b0764 0%,#7c3aed 55%,#a78bfa 100%);color:#fff;padding:46px 22px 30px;overflow:hidden;border-bottom:2px solid rgba(167,139,250,.2);min-height:130px}
.hdr::before{content:'ГЛАВА 3';position:absolute;right:-12px;top:50%;transform:translateY(-50%);font-family:'Unbounded',sans-serif;font-size:clamp(5rem,15vw,11rem);font-weight:900;letter-spacing:-.04em;color:transparent;-webkit-text-stroke:1.5px rgba(220,200,255,.12);line-height:1;pointer-events:none;user-select:none;z-index:0}
.hdr-row{position:relative;z-index:1;display:flex;align-items:center;gap:14px;flex-wrap:wrap}
.hdr h1{font-family:'Unbounded',sans-serif;font-size:1.5rem;font-weight:900;letter-spacing:-.01em;line-height:1.3;padding-top:4px}
.hdr-sub{font-size:.85rem;opacity:.88;margin-top:6px;font-weight:500;line-height:1.4}
.hdr-side{margin-left:auto;display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.hdr-btn{padding:7px 12px;border-radius:9px;background:rgba(255,255,255,.14);color:#fff;font-weight:600;font-size:.82rem;display:inline-flex;align-items:center;gap:6px;transition:background .15s;text-decoration:none}
.hdr-btn:hover{background:rgba(255,255,255,.24)}
.main{max-width:1240px;margin:0 auto;padding:22px;width:100%;display:grid;grid-template-columns:1fr 280px;gap:24px}
@media(max-width:980px){.main{grid-template-columns:1fr;padding:14px}}
.col-main{min-width:0}
.hero{background:linear-gradient(135deg,var(--pri-soft) 0%,var(--acc-soft) 50%,var(--pri-soft) 100%);background-size:200% 200%;animation:heroShift 12s ease-in-out infinite;border:1px solid var(--border);border-radius:18px;padding:24px 22px;margin-bottom:24px;position:relative;overflow:hidden}
@keyframes heroShift{0%,100%{background-position:0% 50%}50%{background-position:100% 50%}}
.hero h2{font-family:'Unbounded',sans-serif;font-size:1.55rem;font-weight:800;color:var(--pri2);margin-bottom:10px;letter-spacing:-.01em}
.hero p{font-size:.95rem;color:var(--text);opacity:.88;margin-bottom:14px;max-width:640px}
.hero-row{display:flex;gap:14px;flex-wrap:wrap;align-items:center}
.btn-primary{padding:11px 22px;background:linear-gradient(135deg,var(--pri),var(--pri2));color:#fff;border-radius:11px;font-weight:700;font-size:.92rem;display:inline-flex;align-items:center;gap:8px;box-shadow:var(--sh2);transition:transform .15s,box-shadow .15s}
.btn-primary:hover{transform:translateY(-1px);box-shadow:0 8px 28px rgba(124,58,237,.32)}
.hero-progress{flex:1;min-width:200px;max-width:280px}
.hp-label{font-size:.74rem;font-weight:700;color:var(--muted);text-transform:uppercase;letter-spacing:.06em;display:block;margin-bottom:5px}
.hp-bar{height:8px;background:rgba(124,58,237,.18);border-radius:5px;overflow:hidden}
.hp-fill{height:100%;background:linear-gradient(90deg,var(--pri),var(--acc));border-radius:5px;width:0%;transition:width .6s cubic-bezier(.16,1,.3,1)}
.hp-text{font-size:.78rem;color:var(--muted);font-weight:700;margin-top:4px;display:block}
.hero-xp-badge{display:inline-flex;align-items:center;gap:6px;padding:6px 12px;background:linear-gradient(135deg,var(--warn,#f59e0b),var(--pri));color:#fff;border-radius:99px;font-size:.82rem;font-weight:800;letter-spacing:.02em;box-shadow:0 4px 12px rgba(124,58,237,.22);font-family:'Unbounded',sans-serif}
.psel{margin-bottom:24px}
.psel-title{font-size:.72rem;font-weight:800;color:var(--muted);text-transform:uppercase;letter-spacing:.08em;margin-bottom:10px}
.psel-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:10px}
.psel-card{background:var(--card);border:1.5px solid var(--border);border-radius:13px;padding:14px;cursor:pointer;transition:transform .2s,box-shadow .2s,border-color .2s;text-align:left;position:relative}
.psel-card:hover{transform:translateY(-3px);box-shadow:var(--sh2);border-color:var(--pri)}
.psel-card.active{border-color:var(--pri);background:linear-gradient(135deg,var(--pri-soft),var(--card));box-shadow:var(--sh2)}
.psel-card.active::after{content:'';position:absolute;top:0;left:0;right:0;height:3px;background:linear-gradient(90deg,var(--pri),var(--acc));border-radius:13px 13px 0 0}
.psel-num{font-family:'Unbounded',sans-serif;font-size:.72rem;font-weight:800;color:var(--pri);text-transform:uppercase;letter-spacing:.08em;margin-bottom:5px}
.psel-name{font-size:.88rem;font-weight:700;color:var(--text);line-height:1.3;margin-bottom:8px}
.psel-prog{height:4px;background:rgba(124,58,237,.10);border-radius:3px;overflow:hidden}
.psel-prog-fill{height:100%;background:var(--pri);width:0%;transition:width .4s}
.psel-card.final{background:linear-gradient(135deg,#f5f3ff,#ede9fe)}
.psel-card.final .psel-num{color:var(--warn)}
/* SECTION COLORS — purple/violet/indigo spectrum */
.sec[id="sec-p1"] { --sec-acc:#7c3aed; --sec-acc-d:#6d28d9; --sec-acc-soft:#ede9fe; }
.sec[id="sec-p2"] { --sec-acc:#8b5cf6; --sec-acc-d:#7c3aed; --sec-acc-soft:#ddd6fe; }
.sec[id="sec-p3"] { --sec-acc:#a78bfa; --sec-acc-d:#8b5cf6; --sec-acc-soft:#f3f0ff; }
.sec[id="sec-p4"] { --sec-acc:#6366f1; --sec-acc-d:#4f46e5; --sec-acc-soft:#e0e7ff; }
.sec[id="sec-p5"] { --sec-acc:#4f46e5; --sec-acc-d:#4338ca; --sec-acc-soft:#e0e7ff; }
.sec[id="sec-p6"] { --sec-acc:#7c3aed; --sec-acc-d:#6d28d9; --sec-acc-soft:#ede9fe; }
.sec[id="sec-p7"] { --sec-acc:#8b5cf6; --sec-acc-d:#7c3aed; --sec-acc-soft:#ddd6fe; }
.sec[id="sec-p8"] { --sec-acc:#c026d3; --sec-acc-d:#a21caf; --sec-acc-soft:#fae8ff; }
.sec[id="sec-p9"] { --sec-acc:#7c3aed; --sec-acc-d:#6d28d9; --sec-acc-soft:#ede9fe; }
.sec[id="sec-final3"] { --sec-acc:#7c3aed; --sec-acc-d:#6d28d9; --sec-acc-soft:#ede9fe; }
.sec{display:none;position:relative;animation:fadeIn .35s ease}
.sec.active{display:block}
@keyframes fadeIn{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
.sec::before{content:attr(data-watermark);position:absolute;right:-20px;top:10%;font-family:'Unbounded',sans-serif;font-size:clamp(6rem,18vw,14rem);font-weight:900;color:transparent;-webkit-text-stroke:1.5px var(--sec-acc-soft,var(--pri-soft));line-height:1;pointer-events:none;user-select:none;z-index:0;opacity:.35}
.sec-header{margin-bottom:22px;padding-bottom:14px;border-bottom:2px solid var(--sec-acc-soft,var(--pri-soft));position:relative;z-index:1}
.sec-num{display:inline-block;padding:4px 10px;background:linear-gradient(135deg,var(--sec-acc,var(--pri)),var(--sec-acc-d,var(--pri2)));color:#fff;border-radius:7px;font-family:'Unbounded',sans-serif;font-size:.78rem;font-weight:800;letter-spacing:.04em;margin-bottom:8px}
.sec-h{font-family:'Unbounded',sans-serif;font-size:1.7rem;font-weight:800;color:var(--sec-acc-d,var(--pri2));letter-spacing:-.01em;line-height:1.25}
.card{background:var(--card);border:1px solid var(--border);border-radius:14px;padding:18px 20px;margin-bottom:16px;box-shadow:0 1px 3px rgba(0,0,0,.04),0 8px 24px rgba(124,58,237,.06);position:relative;z-index:1;transition:transform .25s cubic-bezier(.16,1,.3,1),box-shadow .25s}
.card:hover{transform:translateY(-2px);box-shadow:0 4px 10px rgba(0,0,0,.06),0 16px 36px rgba(124,58,237,.12)}
.card-header{display:flex;align-items:center;gap:10px;margin-bottom:12px;padding-bottom:10px;border-bottom:1px dashed var(--border)}
.card-icon{width:32px;height:32px;border-radius:9px;display:flex;align-items:center;justify-content:center;flex-shrink:0;color:#fff}
.card-icon.repeat{background:#0ea5e9}.card-icon.theory{background:#8b5cf6}.card-icon.algo{background:#f59e0b}.card-icon.rule{background:#ec4899}.card-icon.example{background:#10b981}.card-icon.oral{background:#06b6d4}.card-icon.class{background:#3b82f6}.card-icon.home{background:#f97316}
.card-icon .ic{width:18px;height:18px}
.card-title{font-family:'Unbounded',sans-serif;font-size:.82rem;font-weight:800;text-transform:uppercase;letter-spacing:.06em;color:var(--muted);flex:1}
.card-num{font-size:.74rem;font-weight:700;color:var(--muted);background:var(--sec-acc-soft,var(--pri-soft));padding:3px 7px;border-radius:5px}
.card-body{font-size:.94rem;line-height:1.65}
.card-body p{margin-bottom:8px}
.wg{background:linear-gradient(135deg,var(--card),var(--sec-acc-soft,var(--pri-soft)));border:1.5px solid var(--sec-acc,var(--pri));border-radius:14px;padding:18px 20px;margin-bottom:18px;box-shadow:var(--sh2);position:relative;z-index:1}
.wg-header{display:flex;align-items:center;gap:8px;margin-bottom:14px}
.wg-badge{padding:4px 9px;background:var(--sec-acc,var(--pri));color:#fff;border-radius:6px;font-family:'Unbounded',sans-serif;font-size:.68rem;font-weight:800;text-transform:uppercase;letter-spacing:.06em}
.wg-title{font-family:'Unbounded',sans-serif;font-size:1.05rem;font-weight:800;color:var(--sec-acc-d,var(--pri2));flex:1}
.wg-help{font-size:.88rem;color:var(--text);margin-bottom:12px;line-height:1.55;background:linear-gradient(135deg,var(--warn-bg,#fef3c7),var(--sec-acc-soft,var(--pri-soft)));border-left:4px solid var(--warn,#f59e0b);padding:9px 14px;border-radius:9px}
.btn{padding:8px 16px;border-radius:8px;background:var(--card);color:var(--text);border:1.5px solid var(--border);font-weight:600;font-size:.88rem;transition:background .15s,border-color .15s,transform .1s}
.btn:hover{background:var(--sec-acc-soft,var(--pri-soft));border-color:var(--sec-acc,var(--pri))}
.btn:active{transform:scale(.96)}
.btn.primary{background:var(--sec-acc,var(--pri));color:#fff;border-color:var(--sec-acc,var(--pri))}
.btn.primary:hover{background:var(--sec-acc-d,var(--pri2));border-color:var(--sec-acc-d,var(--pri2))}
.btn.small{padding:5px 11px;font-size:.78rem}
.tinp{padding:8px 12px;border:1.5px solid var(--border);border-radius:8px;background:var(--card);color:var(--text);transition:border-color .15s}
.tinp:focus{outline:0;border-color:var(--sec-acc,var(--pri));box-shadow:0 0 0 3px var(--sec-acc-soft,var(--pri-soft))}
.feedback{padding:10px 14px;border-radius:9px;font-weight:600;font-size:.88rem;margin-top:8px;display:none}
.feedback.ok{display:block;background:var(--ok-bg);color:#065f46;border-left:4px solid var(--ok)}
.feedback.fail{display:block;background:var(--fail-bg);color:#7f1d1d;border-left:4px solid var(--fail)}
.col-side{position:sticky;top:14px;align-self:start;height:fit-content;max-height:calc(100vh - 28px);overflow-y:auto}
.sidecard{background:var(--card);border:1px solid var(--border);border-radius:14px;padding:16px;margin-bottom:14px;box-shadow:var(--sh)}
.sidecard h4{font-family:'Unbounded',sans-serif;font-size:.74rem;font-weight:800;color:var(--pri2);text-transform:uppercase;letter-spacing:.07em;margin-bottom:10px;padding-bottom:8px;border-bottom:1px solid var(--border)}
.sidecard-row{margin-bottom:8px;font-size:.86rem;line-height:1.6}
.sidecard-row b{color:var(--pri);font-weight:700}
.sidecard-row:last-child{margin-bottom:0}
@media(max-width:980px){.col-side{position:static;max-height:none}}
.xp-card{background:linear-gradient(135deg,var(--acc-soft),var(--pri-soft));border:1.5px solid var(--acc);border-radius:12px;padding:14px;margin-bottom:14px}
.xp-card-title{font-size:.68rem;font-weight:800;color:var(--acc2);text-transform:uppercase;letter-spacing:.07em;margin-bottom:8px;display:flex;align-items:center;justify-content:space-between}
.xp-level{font-size:1.1rem;font-weight:900;color:var(--acc2);font-family:'Unbounded',sans-serif}
.xp-bar{height:9px;background:rgba(139,92,246,.15);border-radius:6px;overflow:hidden;margin:7px 0}
.xp-fill{height:100%;background:linear-gradient(90deg,var(--acc),var(--pri));border-radius:6px;transition:width .5s cubic-bezier(.4,0,.2,1)}
.xp-nums{font-size:.74rem;color:var(--muted);display:flex;justify-content:space-between}
.spoiler{border:1px solid var(--border);border-radius:10px;background:var(--card);margin:10px 0;overflow:hidden}
.spoiler summary{padding:8px 14px;background:var(--sec-acc-soft,var(--pri-soft));font-weight:700;cursor:pointer;font-size:.88rem;color:var(--sec-acc-d,var(--pri2));list-style:none;display:flex;align-items:center;gap:8px}
.spoiler summary::-webkit-details-marker{display:none}
.spoiler summary::before{content:'+';font-size:1.2rem;font-weight:900;color:var(--sec-acc,var(--pri));width:18px}
.spoiler[open] summary::before{content:'\2212'}
.spoiler-body{padding:10px 14px;font-size:.92rem;line-height:1.6}
.sec-nav{display:flex;gap:10px;margin-top:24px;padding-top:20px;border-top:1px solid var(--border);justify-content:space-between;flex-wrap:wrap}
.foot{text-align:center;padding:30px 16px;color:var(--muted);font-size:.78rem;border-top:1px solid var(--border);margin-top:30px}
.tbl{width:100%;border-collapse:collapse;margin:12px 0;font-size:.88rem}
.tbl th,.tbl td{padding:7px 10px;border:1px solid var(--border);text-align:center}
.tbl th{background:var(--sec-acc-soft,var(--pri-soft));color:var(--sec-acc-d,var(--pri2));font-weight:700}
.ach-popup{position:fixed;top:80px;right:18px;background:linear-gradient(135deg,#7c3aed,#8b5cf6);color:#fff;padding:12px 18px;border-radius:11px;font-weight:700;font-size:.9rem;box-shadow:0 8px 28px rgba(124,58,237,.45);z-index:1002;display:none;align-items:center;gap:8px;animation:achIn .45s cubic-bezier(.34,1.56,.64,1) forwards;max-width:340px}
.ach-popup.show{display:flex}
@keyframes achIn{from{opacity:0;transform:translateX(40px)}to{opacity:1;transform:none}}
.dnd-pool{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:14px;padding:10px;border:1.5px dashed var(--border);border-radius:10px;min-height:54px;transition:border-color .18s,background .18s}
.dnd-pool.over{border-color:var(--sec-acc,var(--pri));background:var(--sec-acc-soft,var(--pri-soft));border-style:solid}
.dnd-pool.col{flex-direction:column;align-items:stretch}
.dnd-chip{display:inline-flex;align-items:center;gap:6px;padding:6px 12px;background:var(--card);border:1.5px solid var(--border);border-radius:10px;cursor:grab;user-select:none;font-size:.92rem;line-height:1.4;transition:transform .12s,box-shadow .12s,border-color .12s;touch-action:none;max-width:100%}
.dnd-chip:hover{transform:translateY(-1px);border-color:var(--sec-acc,var(--pri));box-shadow:var(--sh)}
.dnd-chip.armed{border-color:var(--sec-acc,var(--pri));background:var(--sec-acc-soft,var(--pri-soft));box-shadow:0 0 0 3px rgba(124,58,237,.22);transform:translateY(-1px)}
.dnd-chip.dragging{opacity:.28}
.dnd-chip.placed{background:var(--sec-acc-soft,var(--pri-soft));border-color:var(--sec-acc,var(--pri))}
.dnd-chip .dnd-x{padding:0 5px;color:var(--muted);font-weight:700;font-size:1.05rem;border-radius:4px;cursor:pointer}
.dnd-chip .dnd-x:hover{color:var(--bad,var(--fail));background:var(--fail-bg)}
.drop-box{background:var(--card);border:1.5px dashed var(--border);border-radius:10px;padding:10px;min-height:90px;transition:border-color .15s,background .15s}
.drop-box:hover{border-color:var(--sec-acc,var(--pri));background:var(--sec-acc-soft,var(--pri-soft))}
.drop-box h5{font-family:'Unbounded',sans-serif;font-size:.78rem;color:var(--sec-acc-d,var(--pri2));margin-bottom:8px;text-transform:uppercase;letter-spacing:.05em}
.drop-box.over{border-color:var(--sec-acc,var(--pri));background:var(--sec-acc-soft,var(--pri-soft));border-style:solid;transform:scale(1.015)}
.drop-items{display:flex;flex-wrap:wrap;gap:6px;min-height:32px}
.dnd-hint{font-size:.78rem;color:var(--muted);margin-bottom:8px;display:flex;align-items:center;gap:6px}
.dnd-hint svg{width:14px;height:14px;flex-shrink:0}
.actions{display:flex;gap:8px;flex-wrap:wrap;margin-top:10px}
.sliders{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:10px;margin-bottom:10px}
.sliders label{display:block;font-size:.92rem;color:var(--muted);background:var(--card);padding:8px 12px;border-radius:8px;border:1px solid var(--border);line-height:1.5}
.sliders label b{font-family:'JetBrains Mono',monospace;font-size:1.05rem;color:var(--sec-acc-d,var(--pri2));margin-left:4px}
.sliders label input[type="range"]{display:block;width:100%;margin-top:6px;accent-color:var(--sec-acc,var(--pri))}
.score-display{display:flex;gap:14px;flex-wrap:wrap;align-items:center;padding:10px 14px;background:var(--sec-acc-soft,var(--pri-soft));border-radius:10px;margin-bottom:12px}
.score-display b{color:var(--sec-acc-d,var(--pri2));font-size:1.15rem}
.col-side-backdrop{position:fixed;inset:0;background:rgba(0,0,0,.42);z-index:9990;display:none;animation:fadeIn .18s ease}
.col-side-backdrop.show{display:block}
@media(max-width:980px){
.col-side{position:fixed;top:0;right:0;height:100vh;width:300px;max-width:88vw;background:var(--bg);box-shadow:-12px 0 24px rgba(0,0,0,.18);padding:18px 16px;overflow-y:auto;transform:translateX(100%);transition:transform .25s ease;z-index:9991;max-height:none}
.col-side.open{transform:none}
}
.gloss-term{border-bottom:1.5px dotted var(--sec-acc,var(--pri));cursor:help;color:var(--sec-acc-d,var(--pri2));font-weight:600;padding:0 1px}
.gloss-term:hover{background:var(--sec-acc-soft,var(--pri-soft));border-radius:3px}
.gloss-tip{position:fixed;max-width:320px;padding:11px 14px;background:var(--card);border:1.5px solid var(--sec-acc,var(--pri));border-radius:11px;font-size:.84rem;line-height:1.55;box-shadow:0 12px 32px rgba(0,0,0,.18);z-index:9994;display:none;pointer-events:none;color:var(--text)}
.gloss-tip.show{display:block;animation:tipIn .15s ease}
.gloss-tip b{color:var(--sec-acc-d,var(--pri2));font-size:.92rem}
@keyframes tipIn{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}
.search-modal{position:fixed;inset:0;background:rgba(15,23,42,.55);backdrop-filter:blur(4px);z-index:9993;display:none;align-items:flex-start;justify-content:center;padding-top:14vh}
.search-modal.show{display:flex;animation:fadeIn .15s ease}
.search-box{background:var(--bg);border:1px solid var(--border);border-radius:14px;width:560px;max-width:92vw;max-height:70vh;display:flex;flex-direction:column;overflow:hidden;box-shadow:0 24px 64px rgba(0,0,0,.4)}
.search-input{padding:14px 16px;font-size:1rem;border:0;border-bottom:1px solid var(--border);background:transparent;color:var(--text);outline:none}
.search-results{flex:1;overflow-y:auto;padding:6px 0}
.search-row{display:block;padding:8px 16px;cursor:pointer;border-bottom:1px solid var(--border);text-align:left;background:transparent;border-left:0;border-right:0;border-top:0;width:100%;color:var(--text)}
.search-row:hover,.search-row.active{background:var(--sec-acc-soft,var(--pri-soft))}
.search-row .sr-kind{font-size:.7rem;font-weight:800;color:var(--muted);text-transform:uppercase;letter-spacing:.06em;margin-bottom:2px}
.search-row .sr-title{font-weight:700;font-size:.92rem;color:var(--text)}
.search-row .sr-desc{font-size:.8rem;color:var(--muted);margin-top:2px}
.search-empty{padding:20px;text-align:center;color:var(--muted);font-size:.88rem}
.search-foot{padding:8px 14px;border-top:1px solid var(--border);font-size:.74rem;color:var(--muted);display:flex;gap:14px;background:var(--card-soft,transparent)}
.search-foot kbd{padding:2px 6px;background:var(--card);border:1px solid var(--border);border-radius:4px;font-family:'JetBrains Mono',monospace;font-size:.72rem}
</style>
</head>
<body>
<header class="hdr">
<div class="hdr-row">
<div>
<h1>Геометрия 8 · Глава 3</h1>
<div class="hdr-sub">Подобные треугольники</div>
</div>
<div class="hdr-side">
<a href="/textbook/geometry-8" class="hdr-btn" title="К Геометрии 8 — все главы">
<svg class="ic" viewBox="0 0 24 24"><polyline points="15 18 9 12 15 6"/></svg>
К геометрии 8
</a>
<button id="search-btn" class="hdr-btn" title="Поиск (Ctrl+K)">
<svg class="ic" viewBox="0 0 24 24"><circle cx="11" cy="11" r="7"/><path d="m21 21-4-4"/></svg>
Поиск
</button>
<button id="sidebar-btn" class="hdr-btn" title="Шпаргалка">
<svg class="ic" viewBox="0 0 24 24"><line x1="4" y1="6" x2="20" y2="6"/><line x1="4" y1="12" x2="20" y2="12"/><line x1="4" y1="18" x2="14" y2="18"/></svg>
Шпаргалка
</button>
<button id="theme-btn" class="hdr-btn" title="Сменить тему">
<svg class="ic" viewBox="0 0 24 24"><path d="M21 12.8A9 9 0 1 1 11.2 3a7 7 0 0 0 9.8 9.8z"/></svg>
<span id="theme-lab">Тёмная</span>
</button>
</div>
</div>
</header>
<main class="main">
<div class="col-main">
<section class="hero">
<h2>Подобие: пропорции и три признака</h2>
<p>Подобные фигуры имеют одинаковую форму, но разный размер. Ключевые инструменты: <b>теорема Фалеса</b> (обобщённая), три признака подобия треугольников, свойство <b>биссектрисы</b>. Итог — отношение площадей подобных треугольников равно квадрату коэффициента подобия.</p>
<div class="hero-row">
<button class="btn-primary" onclick="goTo('p1')">
<svg class="ic" viewBox="0 0 24 24"><polygon points="6 4 20 12 6 20 6 4" fill="currentColor" stroke="none"/></svg>
Начать § 1
</button>
<div class="hero-progress">
<span class="hp-label">Прогресс по главе</span>
<div class="hp-bar"><div id="hero-hp-fill" class="hp-fill"></div></div>
<span id="hero-hp-text" class="hp-text">0%</span>
</div>
<div id="hero-xp-badge" class="hero-xp-badge" title="Опыт"></div>
</div>
</section>
<section class="psel">
<div class="psel-title">Параграфы главы</div>
<div id="psel-grid" class="psel-grid"></div>
</section>
<section id="sec-p1" class="sec" data-watermark="&#8741;"><div class="sec-header"><span class="sec-num">§ 1</span><h2 class="sec-h">Теорема Фалеса (обобщённая)</h2></div><div id="p1-body"></div></section>
<section id="sec-p2" class="sec" data-watermark="m:n"><div class="sec-header"><span class="sec-num">§ 2</span><h2 class="sec-h">Деление отрезка в отношении m : n</h2></div><div id="p2-body"></div></section>
<section id="sec-p3" class="sec" data-watermark="&#8764;"><div class="sec-header"><span class="sec-num">§ 3</span><h2 class="sec-h">Определение подобных треугольников</h2></div><div id="p3-body"></div></section>
<section id="sec-p4" class="sec" data-watermark="&#8741;k"><div class="sec-header"><span class="sec-num">§ 4</span><h2 class="sec-h">Свойство прямой, параллельной стороне треугольника</h2></div><div id="p4-body"></div></section>
<section id="sec-p5" class="sec" data-watermark="&#8736;&#8736;"><div class="sec-header"><span class="sec-num">§ 5</span><h2 class="sec-h">Первый признак подобия. Следствие</h2></div><div id="p5-body"></div></section>
<section id="sec-p6" class="sec" data-watermark="&#8710;"><div class="sec-header"><span class="sec-num">§ 6</span><h2 class="sec-h">Второй признак подобия</h2></div><div id="p6-body"></div></section>
<section id="sec-p7" class="sec" data-watermark="&#8710;&#8764;"><div class="sec-header"><span class="sec-num">§ 7</span><h2 class="sec-h">Третий признак подобия</h2></div><div id="p7-body"></div></section>
<section id="sec-p8" class="sec" data-watermark="&#8901;"><div class="sec-header"><span class="sec-num">§ 8</span><h2 class="sec-h">Свойство биссектрисы треугольника</h2></div><div id="p8-body"></div></section>
<section id="sec-p9" class="sec" data-watermark="k&#178;"><div class="sec-header"><span class="sec-num">§ 9</span><h2 class="sec-h">Отношение площадей подобных треугольников</h2></div><div id="p9-body"></div></section>
<section id="sec-final3" class="sec" data-watermark="&#9733;"><div class="sec-header"><span class="sec-num" style="background:linear-gradient(135deg,#7c3aed,#8b5cf6)">Финал главы</span><h2 class="sec-h">Итоги. Боссы главы 3</h2></div><div id="final3-body"></div></section>
</div>
<aside class="col-side" id="col-side"><div id="sidebar-content"></div></aside>
<div class="col-side-backdrop" id="col-side-backdrop"></div>
</main>
<footer class="foot">Интерактивный учебник «Геометрия 8» · Глава 3 · Подобные треугольники · LearnSpace</footer>
<div id="ach-popup" class="ach-popup"><svg class="ic" viewBox="0 0 24 24" style="width:22px;height:22px"><polygon points="12,2 22,20 2,20"/></svg><span id="ach-text">Достижение!</span></div>
<div id="gloss-tip" class="gloss-tip"></div>
<div id="search-modal" class="search-modal" role="dialog" aria-label="Поиск по главе">
<div class="search-box">
<input type="text" id="search-input" class="search-input" placeholder="Поиск: признак подобия, теорема…" autocomplete="off">
<div id="search-results" class="search-results"></div>
<div class="search-foot"><span><kbd>&#8593;&#8595;</kbd> навигация</span><span><kbd>Enter</kbd> открыть</span><span><kbd>Esc</kbd> закрыть</span></div>
</div>
</div>
<script>
'use strict';
const STATE={ current:'p1', progress:{p1:0,p2:0,p3:0,p4:0,p5:0,p6:0,p7:0,p8:0,p9:0,final3:0}, achievements:new Map(), xp:0, level:1 };
function calcLevel(xp){ return Math.floor(Math.sqrt((xp||0)/100))+1; }
function _xpForLevel(lv){ return (lv-1)*(lv-1)*100; }
const ACH_LABELS={ start:'Начало главы 3!', ch3_done:'Подобие изучено!' };
function loadProgress(){ try{ const s=localStorage.getItem('geometry8_ch3_progress');if(s)Object.assign(STATE.progress,JSON.parse(s)); const a=localStorage.getItem('geometry8_ch3_achievements');if(a){const p=JSON.parse(a);if(Array.isArray(p))p.forEach(id=>STATE.achievements.set(id,ACH_LABELS[id]||id));else if(p&&typeof p==='object')for(const[id,t]of Object.entries(p))STATE.achievements.set(id,(t&&t!==id)?t:(ACH_LABELS[id]||id));} STATE.xp=+(localStorage.getItem('geometry8_xp')||0);STATE.level=calcLevel(STATE.xp); }catch(e){} }
function saveProgress(){ try{localStorage.setItem('geometry8_ch3_progress',JSON.stringify(STATE.progress));localStorage.setItem('geometry8_ch3_achievements',JSON.stringify(Object.fromEntries(STATE.achievements)));localStorage.setItem('geometry8_xp',String(STATE.xp));}catch(e){} }
function bumpProgress(key,delta){ STATE.progress[key]=Math.max(0,Math.min(100,(STATE.progress[key]||0)+delta));saveProgress();refreshProgressUI();if(STATE.progress[key]>=50)markParaRead(key); }
const _TB_SLUG='geometry-8-ch3';const _markedRead=new Set();let _pendingProgressBody=null,_progressTimer=null;
function _flushProgress(){const body=_pendingProgressBody;_pendingProgressBody=null;if(!body)return;const tok=(window.LS&&LS.getToken)?LS.getToken():'';if(!tok)return;fetch('/api/textbooks/'+_TB_SLUG+'/progress',{method:'POST',headers:{'Content-Type':'application/json','Authorization':'Bearer '+tok},body:JSON.stringify(body),keepalive:true}).catch(()=>{});}
function _queueProgress(patch){_pendingProgressBody=Object.assign(_pendingProgressBody||{},patch);if(_progressTimer)clearTimeout(_progressTimer);_progressTimer=setTimeout(_flushProgress,600);}
function markLastPara(id){_queueProgress({last_para:id});}
function markParaRead(id){if(_markedRead.has(id))return;_markedRead.add(id);_queueProgress({mark_read:id});}
window.addEventListener('beforeunload',_flushProgress);
function loadServerReadState(){const tok=(window.LS&&LS.getToken)?LS.getToken():'';if(!tok)return;fetch('/api/textbooks/'+_TB_SLUG,{headers:{'Authorization':'Bearer '+tok}}).then(r=>r.ok?r.json():null).then(d=>{if(!d||!d.progress)return;(d.progress.read||[]).forEach(k=>{_markedRead.add(k);if((STATE.progress[k]||0)<50)STATE.progress[k]=100;});saveProgress();refreshProgressUI();}).catch(()=>{});}
function addXp(n,src){if(!n)return;const prev=STATE.level;STATE.xp=Math.max(0,(STATE.xp||0)+n);STATE.level=calcLevel(STATE.xp);saveProgress();refreshProgressUI();if(window.LS&&window.LS.xp)window.LS.xp.add(n,'geometry8-ch3-'+(src||'misc'));if(STATE.level>prev){const pop=document.getElementById('ach-popup');if(pop){document.getElementById('ach-text').textContent='Уровень '+STATE.level+'!';pop.classList.add('show');setTimeout(()=>pop.classList.remove('show'),2600);}if(window.confetti)try{confetti();}catch(e){}}}
const TOTAL_PARAS=10;
function refreshProgressUI(){
const total=Math.round(Object.values(STATE.progress).reduce((a,b)=>a+b,0)/TOTAL_PARAS);
const f=document.getElementById('hero-hp-fill');if(f)f.style.width=total+'%';
const t=document.getElementById('hero-hp-text');if(t)t.textContent=total+'% пройдено';
document.querySelectorAll('[data-prog-card]').forEach(el=>{const k=el.dataset.progCard;const fl=el.querySelector('.psel-prog-fill');if(fl)fl.style.width=(STATE.progress[k]||0)+'%';});
const xpBadge=document.getElementById('hero-xp-badge');if(xpBadge){xpBadge.innerHTML='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="width:13px;height:13px"><polygon points="12,2 22,20 2,20"/></svg> Ур. '+STATE.level+' \xb7 '+(STATE.xp||0)+' XP';}
if(STATE.current&&document.getElementById('sidebar-content')){try{buildSidebar(STATE.current);}catch(e){}}
}
function achievement(id,text){if(STATE.achievements.has(id))return;STATE.achievements.set(id,text||ACH_LABELS[id]||id);saveProgress();const pop=document.getElementById('ach-popup');if(pop){document.getElementById('ach-text').textContent=text||ACH_LABELS[id]||id;pop.classList.add('show');setTimeout(()=>pop.classList.remove('show'),3300);}addXp(20,'ach-'+id);}
const PARAS=[
{id:'p1',num:'§ 1',name:'Теорема Фалеса (обобщённая)',sub:'Параллельные и пропорции'},
{id:'p2',num:'§ 2',name:'Деление отрезка m:n',sub:'Внутреннее и внешнее'},
{id:'p3',num:'§ 3',name:'Подобные треугольники',sub:'Определение и коэффициент'},
{id:'p4',num:'§ 4',name:'Прямая || стороне',sub:'Отсекает подобный треугольник'},
{id:'p5',num:'§ 5',name:'1-й признак подобия',sub:'ДД — два угла'},
{id:'p6',num:'§ 6',name:'2-й признак подобия',sub:'СДС — пропорц. стороны и угол'},
{id:'p7',num:'§ 7',name:'3-й признак подобия',sub:'ССС — три пропорц. стороны'},
{id:'p8',num:'§ 8',name:'Биссектриса треугольника',sub:'Делит сторону пропорционально'},
{id:'p9',num:'§ 9',name:'Отношение площадей',sub:'S₁/S₂ = k²'},
{id:'final3',num:'★',name:'Финал главы',sub:'Итоги · Боссы',final:true},
];
function buildParaSelector(){const g=document.getElementById('psel-grid');g.innerHTML='';PARAS.forEach(p=>{const card=document.createElement('div');card.className='psel-card'+(p.final?' final':'');card.dataset.id=p.id;card.dataset.progCard=p.id;card.innerHTML=`<div class="psel-num">${p.num}</div><div class="psel-name">${p.name}</div><div class="psel-prog"><div class="psel-prog-fill"></div></div>`;card.addEventListener('click',()=>goTo(p.id));g.appendChild(card);});}
const BUILT=new Set();
const BUILDERS={p1:()=>buildP1(),p2:()=>buildP2(),p3:()=>buildP3(),p4:()=>buildP4(),p5:()=>buildP5(),p6:()=>buildP6(),p7:()=>buildP7(),p8:()=>buildP8stub(),p9:()=>buildP9stub(),final3:()=>buildFinal3stub()};
function ensureBuilt(id){if(BUILT.has(id))return;const fn=BUILDERS[id];if(fn){fn();BUILT.add(id);}}
function goTo(id){STATE.current=id;ensureBuilt(id);document.querySelectorAll('.sec').forEach(s=>s.classList.remove('active'));const el=document.getElementById('sec-'+id);if(el)el.classList.add('active');document.querySelectorAll('.psel-card').forEach(c=>c.classList.toggle('active',c.dataset.id===id));buildSidebar(id);window.scrollTo({top:0,behavior:'smooth'});if((STATE.progress[id]||0)<10)bumpProgress(id,10);if(window.renderMathInElement)setTimeout(()=>renderMath(el),0);setTimeout(()=>{try{wrapGlossary(el);}catch(e){}},60);markLastPara(id);}
const SIDEBARS={
p1:{title:'Шпаргалка § 1',rows:[['Теорема Фалеса','параллельные прямые пропорционально рассекают две прямые'],['Следствие','прямая || стороне треугольника отсекает подобный треугольник']]},
p2:{title:'Шпаргалка § 2',rows:[['Внутреннее деление','точка между крайними'],['Отношение','$AM:MB = m:n$']]},
p3:{title:'Шпаргалка § 3',rows:[['Подобие','$\\triangle ABC \\sim \\triangle A\'B\'C\'$'],['Коэффициент','$k = AB/A\'B\' = BC/B\'C\'$'],['Углы','попарно равны']]},
p4:{title:'Шпаргалка § 4',rows:[['Прямая || стороне','отсекает треугольник, подобный данному'],['Пропорция','отрезки пропорциональны']]},
p5:{title:'Шпаргалка § 5',rows:[['1-й признак (ДД)','два угла одного равны двум углам другого'],['Следствие','два прямоугольных с общим острым углом подобны']]},
p6:{title:'Шпаргалка § 6',rows:[['2-й признак (СДС)','два угла по стороне пропорциональны'],['$\\dfrac{AB}{A\'B\'} = \\dfrac{AC}{A\'C\'}$, угол $A = A\'$','']]},
p7:{title:'Шпаргалка § 7',rows:[['3-й признак (ССС)','все три пары сторон пропорциональны'],['$\\dfrac{a}{a\'}=\\dfrac{b}{b\'}=\\dfrac{c}{c\'}$','']]},
p8:{title:'Шпаргалка § 8',rows:[['Биссектриса','делит противоположную сторону в отношении прилежащих сторон'],['$\\dfrac{BD}{DC}=\\dfrac{AB}{AC}$','']]},
p9:{title:'Шпаргалка § 9',rows:[['Отношение площадей','$\\dfrac{S_1}{S_2} = k^2$'],['$k$','коэффициент подобия']]},
final3:{title:'Финал главы',rows:[['9 параграфов','подобие изучено'],['3 признака','ДД, СДС, ССС']]},
};
const TIPS=[
{sec:'p1',html:'Теорема Фалеса (обобщённая): несколько параллельных прямых пропорционально пересекают любые две секущие.'},
{sec:'p2',html:'Деление в отношении $m:n$: $AM = \\dfrac{m}{m+n}\\cdot AB$.'},
{sec:'p3',html:'Коэффициент подобия $k$ — отношение <b>соответственных</b> сторон.'},
{sec:'p4',html:'Прямая, параллельная стороне треугольника, отсекает треугольник, подобный исходному.'},
{sec:'p5',html:'1-й признак: два угла равны. Это наиболее часто используемый признак!'},
{sec:'p6',html:'2-й признак (СДС): стороны пропорциональны и угол между ними равен.'},
{sec:'p7',html:'3-й признак (ССС): все три пары сторон пропорциональны.'},
{sec:'p8',html:'Биссектриса угла треугольника делит противоположную сторону в отношении смежных сторон.'},
{sec:'p9',html:'Площади подобных фигур относятся как <b>квадрат</b> коэффициента подобия: $S_1/S_2 = k^2$.'},
{sec:'final3',html:'Три признака подобия — главный инструмент геометрических доказательств.'},
];
function buildSidebar(id){const box=document.getElementById('sidebar-content');const sb=SIDEBARS[id]||SIDEBARS.p1;let html='';const xpForLv=_xpForLevel(STATE.level),xpNext=_xpForLevel(STATE.level+1);const xpInLv=STATE.xp-xpForLv,xpRange=xpNext-xpForLv,xpPct=xpRange>0?Math.round(xpInLv/xpRange*100):100;html+=`<div class="xp-card"><div class="xp-card-title"><span>XP-прогресс</span><span class="xp-level">Ур. ${STATE.level}</span></div><div class="xp-bar"><div class="xp-fill" style="width:${xpPct}%"></div></div><div class="xp-nums"><span>${STATE.xp} XP</span><span>${xpNext} XP</span></div></div>`;html+=`<div class="sidecard"><h4>${sb.title}</h4>`;sb.rows.forEach(([k,v])=>{html+=`<div class="sidecard-row"><b>${k}</b>${v?' — '+v:''}</div>`;});html+='</div>';const tip=TIPS.find(t=>t.sec===id)||TIPS[0];html+=`<div class="sidecard" style="background:linear-gradient(135deg,var(--warn-bg,#fef3c7),var(--pri-soft));border-color:var(--warn,#f59e0b)"><h4 style="color:#4c1d95;display:flex;align-items:center;gap:6px"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="width:14px;height:14px"><polygon points="12,2 22,20 2,20"/></svg>Подсказка</h4><div class="sidecard-row" style="margin-bottom:0;font-size:.84rem;line-height:1.55">${tip.html}</div></div>`;if(STATE.achievements.size>0){html+=`<div class="sidecard"><h4>Достижения <span style="color:var(--warn);float:right">${STATE.achievements.size}</span></h4>`;[...STATE.achievements.values()].slice(-4).forEach(text=>{html+=`<div class="sidecard-row" style="font-size:.78rem;color:var(--ok)">&#10003; ${text}</div>`;});html+='</div>';}box.innerHTML=html;if(window.renderMathInElement)try{renderMath(box);}catch(e){}}
function initTheme(){const t=localStorage.getItem('geometry8_ch3_theme')||'light';if(t==='dark')document.documentElement.classList.add('dark');document.getElementById('theme-lab').textContent=t==='dark'?'Светлая':'Тёмная';document.getElementById('theme-btn').addEventListener('click',()=>{document.documentElement.classList.toggle('dark');const dark=document.documentElement.classList.contains('dark');localStorage.setItem('geometry8_ch3_theme',dark?'dark':'light');document.getElementById('theme-lab').textContent=dark?'Светлая':'Тёмная';});}
function renderMath(root){if(window.renderMathInElement){try{renderMathInElement(root,{delimiters:[{left:'$$',right:'$$',display:true},{left:'$',right:'$',display:false},{left:'\\[',right:'\\]',display:true},{left:'\\(',right:'\\)',display:false}],throwOnError:false});}catch(e){}}}
function feedback(elm,ok,text){elm.className='feedback '+(ok?'ok':'fail');elm.innerHTML=text||(ok?'&#10003; Верно!':'&#10007; Неверно');}
function fmt(n){if(!isFinite(n))return '?';if(Number.isInteger(n))return String(n);return Math.abs(n-Math.round(n))<1e-9?String(Math.round(n)):(+n.toFixed(4)).toString();}
const ICONS={repeat:'<svg class="ic" viewBox="0 0 24 24"><polyline points="9 11 12 14 22 4"/><path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"/></svg>',theory:'<svg class="ic" viewBox="0 0 24 24"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/></svg>',algo:'<svg class="ic" viewBox="0 0 24 24"><polyline points="17 11 21 7 17 3"/><line x1="21" y1="7" x2="9" y2="7"/><polyline points="7 13 3 17 7 21"/><line x1="3" y1="17" x2="15" y2="17"/></svg>',rule:'<svg class="ic" viewBox="0 0 24 24"><path d="M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9"/><path d="M10.3 21a1.94 1.94 0 0 0 3.4 0"/></svg>',example:'<svg class="ic" viewBox="0 0 24 24"><path d="M9 18h6"/><path d="M10 22h4"/><path d="M12 2a7 7 0 0 0-4 13c1 1 2 2 2 4h4c0-2 1-3 2-4a7 7 0 0 0-4-13z"/></svg>',oral:'<svg class="ic" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>',class:'<svg class="ic" viewBox="0 0 24 24"><rect x="3" y="3" width="18" height="14" rx="1"/><line x1="3" y1="21" x2="21" y2="21"/><polyline points="7 14 10 11 13 14 17 10"/></svg>',home:'<svg class="ic" viewBox="0 0 24 24"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/></svg>'};
function makeCard(kind,title,num,body){const labels={repeat:'Повторение',theory:'Теория',algo:'Алгоритм',rule:'Правило',example:'Пример',oral:'Устно',class:'Класс',home:'Домашка'};return `<div class="card"><div class="card-header"><div class="card-icon ${kind}">${ICONS[kind]}</div><div class="card-title">${labels[kind]||''}${title&&title!==labels[kind]?' \xb7 '+title:''}</div>${num?`<div class="card-num">${num}</div>`:''}</div><div class="card-body">${body}</div></div>`;}
function secNav(prev,next){const NAMES={p1:'§1',p2:'§2',p3:'§3',p4:'§4',p5:'§5',p6:'§6',p7:'§7',p8:'§8',p9:'§9',final3:'Финал'};let h='<div class="sec-nav">';h+=prev?`<button class="btn" onclick="goTo('${prev}')"><svg class="ic" viewBox="0 0 24 24"><polyline points="15 18 9 12 15 6"/></svg> ${NAMES[prev]}</button>`:'<span></span>';h+=next?`<button class="btn primary" onclick="goTo('${next}')">${NAMES[next]} <svg class="ic" viewBox="0 0 24 24"><polyline points="9 18 15 12 9 6"/></svg></button>`:'<span></span>';h+='</div>';return h;}
let _confettiCanvas=null,_confettiParticles=[],_confettiRaf=null;
function confetti(){if(!_confettiCanvas){_confettiCanvas=document.createElement('canvas');_confettiCanvas.style.cssText='position:fixed;top:0;left:0;width:100%;height:100%;pointer-events:none;z-index:9999';document.body.appendChild(_confettiCanvas);}const c=_confettiCanvas;c.width=window.innerWidth;c.height=window.innerHeight;const ctx=c.getContext('2d');const colors=['#7c3aed','#8b5cf6','#a78bfa','#f59e0b','#10b981'];for(let i=0;i<80;i++){_confettiParticles.push({x:window.innerWidth/2+(Math.random()-.5)*200,y:window.innerHeight/2,vx:(Math.random()-.5)*14,vy:-10-Math.random()*10,g:.4,life:100,color:colors[i%colors.length],r:4+Math.random()*4,rot:0,vRot:(Math.random()-.5)*.3});}if(_confettiRaf)cancelAnimationFrame(_confettiRaf);function frame(){ctx.clearRect(0,0,c.width,c.height);_confettiParticles=_confettiParticles.filter(p=>{p.x+=p.vx;p.y+=p.vy;p.vy+=p.g;p.life--;p.rot+=p.vRot;ctx.save();ctx.translate(p.x,p.y);ctx.rotate(p.rot);ctx.fillStyle=p.color;ctx.fillRect(-p.r,-p.r/2,p.r*2,p.r);ctx.restore();return p.life>0&&p.y<c.height+50;});if(_confettiParticles.length>0)_confettiRaf=requestAnimationFrame(frame);else{ctx.clearRect(0,0,c.width,c.height);_confettiRaf=null;}}frame();}
const GLOSSARY=[
{term:'пропорциональность',def:'Равенство двух отношений: $a/b = c/d$. Числа $a,b,c,d$ называются пропорциональными.',sec:'p1',aliases:['пропорциональность','пропорциональны','пропорциональные','пропорциональных','пропорциональными']},
{term:'подобные треугольники',def:'Треугольники, у которых углы равны попарно и стороны пропорциональны.',sec:'p3',aliases:['подобные треугольники','подобных треугольников','подобными треугольниками','подобный треугольник','подобного треугольника']},
{term:'коэффициент подобия',def:'Отношение соответственных сторон подобных треугольников.',sec:'p3',aliases:['коэффициент подобия','коэффициента подобия','коэффициенте подобия']},
{term:'биссектриса',def:'Луч из вершины угла, делящий угол пополам.',sec:'p8',aliases:['биссектриса','биссектрисы','биссектрису','биссектрисой']},
{term:'теорема Фалеса',def:'Параллельные прямые, пересекая две секущие, отсекают пропорциональные отрезки.',sec:'p1',aliases:['теорема Фалеса','теореме Фалеса','теоремы Фалеса']},
{term:'многоугольник',def:'Замкнутая ломаная линия, образующая плоскую фигуру.',sec:'p1',aliases:['многоугольник','многоугольника','многоугольников']},
{term:'медиана',def:'Отрезок от вершины до середины противоположной стороны.',sec:'p1',aliases:['медиана','медианы','медиан','медиану']},
{term:'площадь',def:'Числовая мера размера плоской фигуры.',sec:'p9',aliases:['площадь','площади','площадью']},
{term:'параллелограмм',def:'Четырёхугольник, у которого противоположные стороны параллельны.',sec:'p1',aliases:['параллелограмм','параллелограмма','параллелограммы']},
{term:'теорема Пифагора',def:'$a^2+b^2=c^2$ в прямоугольном треугольнике.',sec:'p9',aliases:['теорема Пифагора','теоремы Пифагора','теореме Пифагора']},
{term:'касательная',def:'Прямая, касающаяся окружности в одной точке.',sec:'p1',aliases:['касательная','касательной','касательную']},
{term:'вписанный угол',def:'Угол с вершиной на окружности, стороны которого — хорды.',sec:'p1',aliases:['вписанный угол','вписанного угла']},
{term:'центральный угол',def:'Угол с вершиной в центре окружности.',sec:'p1',aliases:['центральный угол','центрального угла']},
{term:'хорда',def:'Отрезок, соединяющий две точки окружности.',sec:'p1',aliases:['хорда','хорды','хорде','хорд']},
{term:'трапеция',def:'Четырёхугольник с одной парой параллельных сторон.',sec:'p1',aliases:['трапеция','трапеции','трапецию']},
{term:'диагональ',def:'Отрезок, соединяющий несмежные вершины многоугольника.',sec:'p1',aliases:['диагональ','диагонали','диагоналей']},
{term:'гипотенуза',def:'Сторона прямоугольного треугольника напротив прямого угла.',sec:'p1',aliases:['гипотенуза','гипотенузы','гипотенузу']},
{term:'высота',def:'Перпендикуляр из вершины на противоположную сторону.',sec:'p1',aliases:['высота','высоты','высоту']},
{term:'пифагорова тройка',def:'Три натуральных числа $(a,b,c)$ с $a^2+b^2=c^2$.',sec:'p9',aliases:['пифагорова тройка','пифагоровы тройки']},
{term:'секущая',def:'Прямая, пересекающая окружность в двух точках.',sec:'p1',aliases:['секущая','секущей','секущую']},
{term:'хорда',def:'Отрезок, соединяющий две точки окружности.',sec:'p1',aliases:['хорда','хорды','хорд']},
];
function wrapGlossary(root){if(!root||root.__glossDone)return;const allAliases=[];GLOSSARY.forEach((g,i)=>g.aliases.forEach(a=>allAliases.push({a,i})));allAliases.sort((x,y)=>y.a.length-x.a.length);const re=new RegExp('(?<![\\w\\u0400-\\u04ff-])('+allAliases.map(x=>x.a.replace(/[.*+?^${}()|[\]\\]/g,'\\$&')).join('|')+')(?![\\w\\u0400-\\u04ff-])','iu');const walker=document.createTreeWalker(root,NodeFilter.SHOW_TEXT,{acceptNode(node){const p=node.parentElement;if(!p)return NodeFilter.FILTER_REJECT;if(p.closest('.katex,.gloss-term,button,input,select,.wg-badge,.card-icon,.sec-num,.psel-num,.hdr,.ach-popup,script,style,.search-modal,.sidecard,.gloss-tip'))return NodeFilter.FILTER_REJECT;if(!re.test(node.nodeValue))return NodeFilter.FILTER_REJECT;return NodeFilter.FILTER_ACCEPT;}});const nodes=[];let n;while((n=walker.nextNode()))nodes.push(n);nodes.forEach(node=>{const text=node.nodeValue;const out=document.createDocumentFragment();let cursor=0;const global=new RegExp(re.source,'giu');let m;while((m=global.exec(text))!==null){if(m.index>cursor)out.appendChild(document.createTextNode(text.slice(cursor,m.index)));const found=m[0].toLowerCase();const hit=allAliases.find(x=>x.a.toLowerCase()===found);const g=hit?GLOSSARY[hit.i]:null;const sp=document.createElement('span');sp.className='gloss-term';sp.dataset.gloss=g?g.term:'';sp.textContent=m[0];out.appendChild(sp);cursor=m.index+m[0].length;}if(cursor<text.length)out.appendChild(document.createTextNode(text.slice(cursor)));node.parentNode.replaceChild(out,node);});root.__glossDone=true;}
function initGlossaryTip(){const tip=document.getElementById('gloss-tip');if(!tip)return;let lockOpen=null;function show(elm){const g=GLOSSARY.find(x=>x.term===elm.dataset.gloss);if(!g)return;tip.innerHTML='<b>'+g.term[0].toUpperCase()+g.term.slice(1)+'</b><div style="margin-top:4px">'+g.def+'</div><div style="margin-top:6px;font-size:.72rem;color:var(--muted);text-transform:uppercase;letter-spacing:.06em">См. § '+g.sec.replace('p','')+'</div>';if(window.renderMathInElement)renderMath(tip);const r=elm.getBoundingClientRect();tip.classList.add('show');const tw=tip.offsetWidth,th=tip.offsetHeight;let left=r.left,top=r.bottom+8;if(left+tw>window.innerWidth-12)left=window.innerWidth-tw-12;if(top+th>window.innerHeight-12)top=r.top-th-8;tip.style.left=Math.max(8,left)+'px';tip.style.top=Math.max(8,top)+'px';}function hide(){tip.classList.remove('show');}document.addEventListener('mouseover',e=>{const elm=e.target.closest&&e.target.closest('.gloss-term');if(elm&&!lockOpen)show(elm);});document.addEventListener('mouseout',e=>{const elm=e.target.closest&&e.target.closest('.gloss-term');if(elm&&!lockOpen)hide();});document.addEventListener('click',e=>{const elm=e.target.closest&&e.target.closest('.gloss-term');if(elm){if(lockOpen===elm){lockOpen=null;hide();}else{lockOpen=elm;show(elm);}}else if(lockOpen&&!e.target.closest('.gloss-tip')){lockOpen=null;hide();}});}
const SEARCH_INDEX=(function(){const arr=[];PARAS.forEach(p=>arr.push({kind:'Параграф',title:p.num+' '+p.name,desc:p.sub||'',sec:p.id}));GLOSSARY.forEach(g=>arr.push({kind:'Понятие',title:g.term,desc:g.def.replace(/\$/g,''),sec:g.sec,gloss:g.term}));[['Формула','Теорема Фалеса — пропорциональность','§1','p1'],['Формула','1-й признак подобия — два угла','§5','p5'],['Формула','Биссектриса: BD/DC = AB/AC','§8','p8'],['Формула','Отношение площадей = k²','§9','p9']].forEach(([k,t,d,s])=>arr.push({kind:k,title:t,desc:d,sec:s}));return arr;})();
function initSearch(){const modal=document.getElementById('search-modal'),inp=document.getElementById('search-input'),out=document.getElementById('search-results'),btn=document.getElementById('search-btn');if(!modal||!inp||!out)return;let cur=0,rows=[];function score(q,it){const t=(it.title+' '+it.desc).toLowerCase();if(t.includes(q))return 100+(it.title.toLowerCase().startsWith(q)?50:0);let s=0;q.split(/\s+/).forEach(w=>{if(w&&t.includes(w))s+=10;});return s;}function rank(q){q=q.trim().toLowerCase();if(!q)return SEARCH_INDEX.slice(0,12);return SEARCH_INDEX.map(it=>({it,s:score(q,it)})).filter(x=>x.s>0).sort((a,b)=>b.s-a.s).slice(0,20).map(x=>x.it);}function render(){cur=0;if(!rows.length){out.innerHTML='<div class="search-empty">Ничего не найдено</div>';return;}out.innerHTML=rows.map((r,i)=>`<button class="search-row${i===0?' active':''}" data-i="${i}"><div class="sr-kind">${r.kind}</div><div class="sr-title">${r.title}</div>${r.desc?`<div class="sr-desc">${r.desc.length>90?r.desc.slice(0,90)+'…':r.desc}</div>`:''}</button>`).join('');out.querySelectorAll('.search-row').forEach(b=>b.addEventListener('click',()=>{cur=+b.dataset.i;pick();}));}function pick(){const r=rows[cur];if(!r)return;close();goTo(r.sec);if(r.gloss){setTimeout(()=>{const sec=document.getElementById('sec-'+r.sec);const elm=sec&&sec.querySelector('[data-gloss="'+r.gloss+'"]');if(elm){elm.scrollIntoView({behavior:'smooth',block:'center'});elm.style.transition='background .3s';elm.style.background='var(--warn,#f59e0b)';setTimeout(()=>{elm.style.background='';},1400);}},400);}}function move(d){const items=out.querySelectorAll('.search-row');if(!items.length)return;items[cur]&&items[cur].classList.remove('active');cur=(cur+d+items.length)%items.length;items[cur].classList.add('active');items[cur].scrollIntoView({block:'nearest'});}function open(){modal.classList.add('show');inp.value='';rows=rank('');render();setTimeout(()=>inp.focus(),50);}function close(){modal.classList.remove('show');}btn&&btn.addEventListener('click',open);modal.addEventListener('click',e=>{if(e.target===modal)close();});inp.addEventListener('input',()=>{rows=rank(inp.value);render();});inp.addEventListener('keydown',e=>{if(e.key==='ArrowDown'){e.preventDefault();move(1);}else if(e.key==='ArrowUp'){e.preventDefault();move(-1);}else if(e.key==='Enter'){e.preventDefault();pick();}else if(e.key==='Escape'){e.preventDefault();close();}});document.addEventListener('keydown',e=>{if((e.ctrlKey||e.metaKey)&&(e.key==='k'||e.key==='K')){e.preventDefault();if(modal.classList.contains('show'))close();else open();}});}
function initSidebarToggle(){const side=document.getElementById('col-side'),back=document.getElementById('col-side-backdrop'),btn=document.getElementById('sidebar-btn');if(!side||!btn)return;function open(){side.classList.add('open');back.classList.add('show');}function close(){side.classList.remove('open');back.classList.remove('show');}btn.addEventListener('click',()=>{if(side.classList.contains('open'))close();else open();});back.addEventListener('click',close);document.addEventListener('keydown',e=>{if(e.key==='Escape')close();});}
function init(){loadProgress();initTheme();initSidebarToggle();initGlossaryTip();initSearch();buildParaSelector();refreshProgressUI();loadServerReadState();goTo('p1');setTimeout(()=>achievement('start','Начало главы 3!'),600);if(window.LS&&window.LS.xp){window.LS.xp.load().then(function(s){if(s&&s.xp>STATE.xp){STATE.xp=s.xp;STATE.level=calcLevel(STATE.xp);saveProgress();refreshProgressUI();if(STATE.current)buildSidebar(STATE.current);}});}}
document.addEventListener('DOMContentLoaded',init);
function buildP1(){
const box=document.getElementById('p1-body');
let html='';
html+=makeCard('theory','Теорема Фалеса (классическая)','1.1',`
<p><b>Теорема Фалеса.</b> Если параллельные прямые пересекают одну из сторон угла в равных частях, то они отсекают равные части и на другой стороне угла.</p>
<p style="margin-top:8px"><b>Следствие (обобщённая теорема Фалеса).</b> Если несколько параллельных прямых пересекают две секущие прямые, то они отсекают на этих секущих <em>пропорциональные</em> отрезки:</p>
$$\\dfrac{AB}{BC} = \\dfrac{A'B'}{B'C'}$$
<p style="margin-top:8px">где $A,B,C$ — точки на первой секущей, $A',B',C'$ — точки на второй секущей, отсекаемые теми же параллельными прямыми.</p>
<div style="display:flex;justify-content:center;margin-top:14px">
<svg viewBox="0 0 280 170" style="max-width:300px;background:#fafafa;border:1px solid var(--border);border-radius:10px">
<!-- угол с вершиной O=(30,150); два луча, три параллельные прямые -->
<!-- луч 1: O→(260,60), луч 2: O→(260,150) -->
<line x1="30" y1="150" x2="260" y2="60" stroke="#7c3aed" stroke-width="2"/>
<line x1="30" y1="150" x2="260" y2="150" stroke="#7c3aed" stroke-width="2"/>
<!-- параллельные прямые (3 шт, горизонтальные) пересекают оба луча -->
<!-- луч1: при x=80→y=120.5, при x=160→y=91, при x=240→y=61.5 -->
<!-- луч2: при x=80→y=150, при x=160→y=150, при x=240→y=150 -->
<line x1="80" y1="30" x2="80" y2="160" stroke="#a78bfa" stroke-width="1.5" stroke-dasharray="4,3"/>
<line x1="160" y1="30" x2="160" y2="160" stroke="#a78bfa" stroke-width="1.5" stroke-dasharray="4,3"/>
<line x1="240" y1="30" x2="240" y2="160" stroke="#a78bfa" stroke-width="1.5" stroke-dasharray="4,3"/>
<!-- точки на луче 1 -->
<circle cx="80" cy="121" r="3.5" fill="#7c3aed"/>
<circle cx="160" cy="91" r="3.5" fill="#7c3aed"/>
<circle cx="240" cy="62" r="3.5" fill="#7c3aed"/>
<!-- точки на луче 2 -->
<circle cx="80" cy="150" r="3.5" fill="#7c3aed"/>
<circle cx="160" cy="150" r="3.5" fill="#7c3aed"/>
<circle cx="240" cy="150" r="3.5" fill="#7c3aed"/>
<!-- метки луч1 -->
<text x="76" y="117" text-anchor="end" font-size="10" font-weight="700" fill="#6d28d9">A</text>
<text x="156" y="87" text-anchor="end" font-size="10" font-weight="700" fill="#6d28d9">B</text>
<text x="236" y="58" text-anchor="end" font-size="10" font-weight="700" fill="#6d28d9">C</text>
<!-- метки луч2 -->
<text x="80" y="165" text-anchor="middle" font-size="10" font-weight="700" fill="#6d28d9">A'</text>
<text x="160" y="165" text-anchor="middle" font-size="10" font-weight="700" fill="#6d28d9">B'</text>
<text x="240" y="165" text-anchor="middle" font-size="10" font-weight="700" fill="#6d28d9">C'</text>
<text x="18" y="153" font-size="10" font-weight="700" fill="#6d28d9">O</text>
<text x="140" y="20" text-anchor="middle" font-size="10" fill="#6d28d9" font-style="italic">AB/BC = A'B'/B'C'</text>
</svg>
</div>`);
html+=makeCard('rule','Пропорциональность отрезков','1.2',`
<p>Обозначим точки пересечения параллельных прямых $\\ell_1,\\ell_2,\\ell_3$ со сторонами угла как $A,B,C$ и $A',B',C'$ соответственно. Тогда:</p>
$$\\dfrac{AB}{BC} = \\dfrac{A'B'}{B'C'}, \\quad \\dfrac{AB}{AC} = \\dfrac{A'B'}{A'C'}$$
<p style="margin-top:8px">Это выражает <b>пропорциональность отрезков</b>, отсекаемых параллельными прямыми.</p>
<p style="margin-top:8px"><b>Применение:</b> с помощью теоремы Фалеса доказывают подобие треугольников, делят отрезок в заданном отношении, строят пропорциональные отрезки.</p>
<div style="display:flex;justify-content:center;margin-top:12px">
<svg viewBox="0 0 280 130" style="max-width:300px;background:#fafafa;border:1px solid var(--border);border-radius:10px">
<!-- треугольник ABC с точками D,E на сторонах, DE || BC -->
<polygon points="140,15 30,115 250,115" fill="rgba(124,58,237,.1)" stroke="#7c3aed" stroke-width="2"/>
<!-- DE параллельна BC, D на AB, E на AC -->
<line x1="85" y1="65" x2="195" y2="65" stroke="#a78bfa" stroke-width="2" stroke-dasharray="5,3"/>
<circle cx="85" cy="65" r="3" fill="#7c3aed"/>
<circle cx="195" cy="65" r="3" fill="#7c3aed"/>
<text x="140" y="12" text-anchor="middle" font-size="11" font-weight="700" fill="#6d28d9">A</text>
<text x="24" y="122" font-size="11" font-weight="700" fill="#6d28d9">B</text>
<text x="252" y="122" font-size="11" font-weight="700" fill="#6d28d9">C</text>
<text x="78" y="63" text-anchor="end" font-size="10" font-weight="700" fill="#8b5cf6">D</text>
<text x="201" y="63" font-size="10" font-weight="700" fill="#8b5cf6">E</text>
<text x="140" y="82" text-anchor="middle" font-size="9" fill="#6d28d9">DE ∥ BC</text>
<text x="140" y="126" text-anchor="middle" font-size="9" fill="#6d28d9" font-style="italic">AD/DB = AE/EC</text>
</svg>
</div>`);
html+=makeCard('example','Пример применения','1.3',`
<p><b>Пример.</b> Параллельные прямые отсекают на первой стороне угла отрезки $AB = 6$ и $BC = 9$. На второй стороне $A'B' = 4$. Найти $B'C'$.</p>
<p style="margin-top:8px"><b>Решение:</b> по теореме Фалеса $\\dfrac{AB}{BC}=\\dfrac{A'B'}{B'C'}$, то есть $\\dfrac{6}{9}=\\dfrac{4}{B'C'}$.</p>
<p style="margin-top:4px">$B'C' = \\dfrac{4 \\cdot 9}{6} = 6$.</p>`);
/* ИНТЕРАКТИВ 1 — SVG-угол с параллельными прямыми */
html+=`<div class="wg" id="p1-angle-wg">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 1</span><div class="wg-title">Угол с параллельными прямыми</div></div>
<div class="wg-help">Меняй количество параллельных прямых и угол наклона второй стороны. Видишь, как отношения остаются равными!</div>
<div class="sliders">
<label>Кол-во параллельных: <b id="p1-npar-val">3</b>
<input type="range" min="2" max="6" value="3" id="p1-npar-sl">
</label>
<label>Угол второй стороны: <b id="p1-angle-val">30</b>°
<input type="range" min="10" max="60" value="30" id="p1-angle-sl">
</label>
</div>
<div id="p1-angle-svg" style="display:flex;justify-content:center"></div>
<div id="p1-angle-info" style="margin-top:10px;padding:10px 14px;background:var(--sec-acc-soft,var(--pri-soft));border-radius:10px;font-size:.92rem;line-height:1.8"></div>
</div>`;
/* ИНТЕРАКТИВ 2 — Пошаговое доказательство */
html+=`<div class="wg" id="p1-proof-wg">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 2</span><div class="wg-title">Доказательство теоремы Фалеса — по шагам</div></div>
<div class="wg-help">Нажимай «Далее» — каждый шаг показывает ключевую идею.</div>
<div id="p1-proof-svg" style="display:flex;justify-content:center;margin-bottom:10px"></div>
<div id="p1-proof-desc" style="padding:10px 14px;background:var(--sec-acc-soft,var(--pri-soft));border-radius:10px;font-size:.95rem;line-height:1.6;margin-bottom:10px;min-height:60px"></div>
<div style="display:flex;gap:8px">
<button class="btn primary" id="p1-proof-next">Далее</button>
<button class="btn" id="p1-proof-reset">Сначала</button>
</div>
</div>`;
/* ИНТЕРАКТИВ 3 — Калькулятор пропорций */
html+=`<div class="wg">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 3</span><div class="wg-title">Калькулятор пропорций (Теорема Фалеса)</div></div>
<div class="wg-help">Дано три отрезка из пропорции $\\dfrac{a}{b}=\\dfrac{c}{x}$ — найди четвёртый.</div>
<div style="display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin-bottom:10px">
<div style="display:flex;flex-direction:column;align-items:center;gap:4px">
<input type="number" id="p1-pa" class="tinp" placeholder="a" style="width:70px" min="0.001">
<span style="font-size:.8rem;color:var(--muted)">AB</span>
</div>
<span style="font-size:1.3rem;color:var(--muted)">/</span>
<div style="display:flex;flex-direction:column;align-items:center;gap:4px">
<input type="number" id="p1-pb" class="tinp" placeholder="b" style="width:70px" min="0.001">
<span style="font-size:.8rem;color:var(--muted)">BC</span>
</div>
<span style="font-size:1.3rem;color:var(--muted)">=</span>
<div style="display:flex;flex-direction:column;align-items:center;gap:4px">
<input type="number" id="p1-pc" class="tinp" placeholder="c" style="width:70px" min="0.001">
<span style="font-size:.8rem;color:var(--muted)">A'B'</span>
</div>
<span style="font-size:1.3rem;color:var(--muted)">/</span>
<div style="display:flex;flex-direction:column;align-items:center;gap:4px">
<input type="number" id="p1-px" class="tinp" placeholder="x" style="width:70px" disabled style="background:var(--sec-acc-soft)">
<span style="font-size:.8rem;color:var(--muted)">B'C'</span>
</div>
<button class="btn primary" id="p1-pcalc">Найти x</button>
</div>
<div id="p1-pcalc-out" style="display:none;padding:10px 14px;background:var(--sec-acc-soft,var(--pri-soft));border-radius:10px;font-size:.95rem"></div>
</div>`;
/* ИНТЕРАКТИВ 4 — Тренажёр */
html+=`<div class="wg">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 4</span><div class="wg-title">Тренажёр §1 — Теорема Фалеса</div></div>
<div class="wg-help">5 задач на пропорциональность отрезков. Введи ответ и нажми «Проверить».</div>
<div class="score-display"><span>Задача <b id="p1-tr-i">1</b> / 5</span><span>Очки: <b id="p1-tr-score">0</b></span></div>
<div id="p1-tr-task" style="padding:14px;background:var(--sec-acc-soft,var(--pri-soft));border-radius:10px;font-size:1.02rem;margin-bottom:10px"></div>
<div style="display:flex;gap:8px;align-items:center;flex-wrap:wrap">
<input type="number" id="p1-tr-ans" class="tinp" placeholder="Ответ" style="width:120px">
<button class="btn primary" id="p1-tr-go">Проверить</button>
<button class="btn" id="p1-tr-start">Начать</button>
</div>
<div class="feedback" id="p1-tr-fb" style="display:none"></div>
</div>`;
/* ИНТЕРАКТИВ 5 — DnD-сортер */
html+=`<div class="wg">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 5</span><div class="wg-title">Определи: пропорциональные или нет?</div></div>
<div class="wg-help">Перетащи каждую карточку в нужную колонку.</div>
<div id="p1-dnd-pool" class="dnd-pool"></div>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-top:10px">
<div class="drop-box" id="p1-drop-yes"><h5>Пропорциональные</h5><div class="drop-items" id="p1-drop-yes-items"></div></div>
<div class="drop-box" id="p1-drop-no"><h5>Непропорциональные</h5><div class="drop-items" id="p1-drop-no-items"></div></div>
</div>
<div class="actions"><button class="btn primary" id="p1-dnd-check">Проверить</button><button class="btn" id="p1-dnd-reset">Сбросить</button></div>
<div class="feedback" id="p1-dnd-fb" style="display:none"></div>
</div>`;
/* ИНТЕРАКТИВ 6 — Босс §1 */
html+=`<div class="wg" style="border-color:var(--sec-acc-d,var(--pri2))">
<div class="wg-header"><span class="wg-badge" style="background:var(--sec-acc-d,var(--pri2))">БОСС §1</span><div class="wg-title">Итоговые задачи</div></div>
<div class="wg-help">4 задачи — каждая верная даёт +5 XP.</div>
<div id="p1-boss-tasks"></div>
</div>`;
html+=`<div style="margin-top:18px;display:flex;justify-content:center">
<button class="btn primary" id="p1-read-btn" onclick="addXp(10,'p1-read');bumpProgress('p1',40);this.textContent='Прочитано!';this.disabled=true;">
<svg class="ic" viewBox="0 0 24 24"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/></svg>
Я прочитал §1 (+10 XP)
</button>
</div>`;
html+=secNav(null,'p2');
box.innerHTML=html;
if(window.renderMathInElement) setTimeout(()=>renderMath(box),0);
/* == INIT ИНТЕРАКТИВ 1: угол с параллелями == */
(function(){
const nSl=document.getElementById('p1-npar-sl');
const nVal=document.getElementById('p1-npar-val');
const aSl=document.getElementById('p1-angle-sl');
const aVal=document.getElementById('p1-angle-val');
const svgWrap=document.getElementById('p1-angle-svg');
const info=document.getElementById('p1-angle-info');
function draw(){
const n=+nSl.value;
const angDeg=+aSl.value;
nVal.textContent=n;
aVal.textContent=angDeg;
const W=320, H=180;
const Ox=20, Oy=H-20;
const ang=angDeg*Math.PI/180;
const L=280;
// луч 1: горизонталь вправо
// луч 2: под углом ang вверх
const pts1=[]; // точки на луче1 (горизональном)
const pts2=[]; // точки на луче2
const step=L/(n);
for(let i=1;i<=n;i++){
const x=Ox+step*i;
pts1.push({x, y:Oy});
pts2.push({x, y:Oy-step*i*Math.tan(ang)});
}
let s=`<svg viewBox="0 0 ${W} ${H}" style="max-width:${W}px;width:100%;background:#fafafa;border:1px solid var(--border);border-radius:10px">`;
// лучи
s+=`<line x1="${Ox}" y1="${Oy}" x2="${Ox+L+10}" y2="${Oy}" stroke="#7c3aed" stroke-width="2"/>`;
s+=`<line x1="${Ox}" y1="${Oy}" x2="${Ox+L+10}" y2="${Oy-(L+10)*Math.tan(ang)}" stroke="#7c3aed" stroke-width="2"/>`;
// параллельные прямые (вертикальные)
for(let i=0;i<n;i++){
const cx=pts1[i].x;
s+=`<line x1="${cx}" y1="5" x2="${cx}" y2="${H-5}" stroke="#a78bfa" stroke-width="1.5" stroke-dasharray="4,3"/>`;
s+=`<circle cx="${pts1[i].x}" cy="${pts1[i].y}" r="4" fill="#7c3aed"/>`;
s+=`<circle cx="${pts2[i].x}" cy="${pts2[i].y}" r="4" fill="#7c3aed"/>`;
const lbl=String.fromCharCode(65+i);
s+=`<text x="${pts1[i].x}" y="${Oy+14}" text-anchor="middle" font-size="10" font-weight="700" fill="#6d28d9">${lbl}</text>`;
s+=`<text x="${pts2[i].x+4}" y="${pts2[i].y-5}" font-size="10" font-weight="700" fill="#6d28d9">${lbl}'</text>`;
}
s+=`<text x="${Ox-4}" y="${Oy+4}" font-size="10" font-weight="700" fill="#6d28d9">O</text>`;
s+='</svg>';
svgWrap.innerHTML=s;
// вычисляем отрезки
let infoHtml='';
for(let i=0;i<n-1;i++){
const seg1=Math.round((pts1[i+1].x-pts1[i].x)*10)/10;
const dy2=pts2[i+1].y-pts2[i].y, dx2=pts2[i+1].x-pts2[i].x;
const seg2=Math.round(Math.sqrt(dx2*dx2+dy2*dy2)*10)/10;
const lA=String.fromCharCode(65+i), lB=String.fromCharCode(66+i);
infoHtml+=`<span style="margin-right:16px">${lA}${lB} = <b>${seg1}</b> px; ${lA}'${lB}' = <b>${fmt(seg2)}</b> px</span>`;
}
if(n>=2){
const r1=Math.round((pts1[1].x-pts1[0].x)/(pts1[0].x-pts1[0].x+1)*1000)/1000;
const dy0=pts2[1].y-pts2[0].y, dx0=pts2[1].x-pts2[0].x;
const s1=pts1[1].x-pts1[0].x;
const s2=Math.sqrt(dx0*dx0+dy0*dy0);
infoHtml+=`<div style="margin-top:6px;color:var(--sec-acc-d,var(--pri2));font-weight:700">Отношение AB/A'B' = ${fmt(s1/s2)} ≈ постоянно для всех пар</div>`;
}
info.innerHTML=infoHtml;
addXp(1,'p1-angle');
}
nSl.addEventListener('input',draw);
aSl.addEventListener('input',draw);
draw();
})();
/* == INIT ИНТЕРАКТИВ 2: пошаговое доказательство == */
(function(){
const steps=[
{desc:'<b>Шаг 1.</b> Даны два луча из вершины O и три параллельные прямые, пересекающие их в точках A, B, C и A\', B\', C\'.',
svg:()=>{
const W=260,H=160,Ox=20,Oy=140;
let s=`<svg viewBox="0 0 ${W} ${H}" style="max-width:${W}px;width:100%;background:#fafafa;border:1px solid var(--border);border-radius:10px">`;
s+=`<line x1="${Ox}" y1="${Oy}" x2="250" y2="${Oy}" stroke="#7c3aed" stroke-width="2"/>`;
s+=`<line x1="${Ox}" y1="${Oy}" x2="250" y2="60" stroke="#7c3aed" stroke-width="2"/>`;
[[70,140,70,65],[150,140,150,92],[230,140,230,119]].forEach(([x1,y1,x2,y2])=>{
s+=`<line x1="${x1}" y1="${y1}" x2="${x2}" y2="${y2}" stroke="#a78bfa" stroke-width="1.5" stroke-dasharray="4,3"/>`;
});
s+=`<text x="${Ox-4}" y="${Oy+4}" font-size="10" fill="#6d28d9" font-weight="700">O</text>`;
['A','B','C'].forEach((l,i)=>s+=`<text x="${70+i*80}" y="${Oy+14}" text-anchor="middle" font-size="10" fill="#6d28d9" font-weight="700">${l}</text>`);
['A\'','B\'','C\''].forEach((l,i)=>s+=`<text x="${70+i*80+4}" y="${[62,89,116][i]-4}" font-size="10" fill="#6d28d9" font-weight="700">${l}</text>`);
s+='</svg>';return s;}},
{desc:'<b>Шаг 2.</b> Через точки A, B, C проводим прямые, параллельные второму лучу. Получаем параллелограммы.',
svg:()=>{
const W=260,H=160,Ox=20,Oy=140;
let s=`<svg viewBox="0 0 ${W} ${H}" style="max-width:${W}px;width:100%;background:#fafafa;border:1px solid var(--border);border-radius:10px">`;
s+=`<line x1="${Ox}" y1="${Oy}" x2="250" y2="${Oy}" stroke="#7c3aed" stroke-width="2"/>`;
s+=`<line x1="${Ox}" y1="${Oy}" x2="250" y2="60" stroke="#7c3aed" stroke-width="2"/>`;
[[70,140,70,65],[150,140,150,92],[230,140,230,119]].forEach(([x1,y1,x2,y2])=>{
s+=`<line x1="${x1}" y1="${y1}" x2="${x2}" y2="${y2}" stroke="#a78bfa" stroke-width="1.5" stroke-dasharray="4,3"/>`;
});
// вспомогательные параллельные линии через A, B
s+=`<line x1="70" y1="140" x2="150" y2="92" stroke="#f59e0b" stroke-width="1.5" stroke-dasharray="3,3"/>`;
s+=`<line x1="150" y1="140" x2="230" y2="119" stroke="#f59e0b" stroke-width="1.5" stroke-dasharray="3,3"/>`;
s+=`<text x="100" y="128" font-size="9" fill="#b45309" font-weight="700">параллелограмм</text>`;
s+='</svg>';return s;}},
{desc:'<b>Шаг 3.</b> В параллелограмме противоположные стороны равны: $A_1B_1 = AB_2 = AB$, поэтому параллельная прямая откладывает равные отрезки на обоих лучах (если исходные части равны).',
svg:()=>{
const W=260,H=160;
let s=`<svg viewBox="0 0 ${W} ${H}" style="max-width:${W}px;width:100%;background:#fafafa;border:1px solid var(--border);border-radius:10px">`;
s+=`<polygon points="70,140 150,140 150,92 70,65" fill="rgba(124,58,237,.12)" stroke="#7c3aed" stroke-width="1.5"/>`;
s+=`<text x="110" y="108" text-anchor="middle" font-size="10" fill="#6d28d9" font-weight="700">Параллелограмм</text>`;
s+=`<text x="110" y="120" text-anchor="middle" font-size="9" fill="#6d28d9">AB = A'B'</text>`;
s+='</svg>';return s;}},
{desc:'<b>Шаг 4.</b> Если параллельные прямые делят луч на <em>равные</em> части, то и второй луч делится на равные части. Это и есть теорема Фалеса в классической форме.',
svg:()=>{
const W=260,H=160,Ox=20,Oy=140;
let s=`<svg viewBox="0 0 ${W} ${H}" style="max-width:${W}px;width:100%;background:#fafafa;border:1px solid var(--border);border-radius:10px">`;
s+=`<line x1="${Ox}" y1="${Oy}" x2="250" y2="${Oy}" stroke="#7c3aed" stroke-width="2"/>`;
s+=`<line x1="${Ox}" y1="${Oy}" x2="250" y2="60" stroke="#7c3aed" stroke-width="2"/>`;
[[70,140,70,65],[150,140,150,92],[230,140,230,119]].forEach(([x1,y1,x2,y2])=>{
s+=`<line x1="${x1}" y1="${y1}" x2="${x2}" y2="${y2}" stroke="#a78bfa" stroke-width="1.5"/>`;
});
// равные отрезки
s+=`<text x="110" y="${Oy+14}" text-anchor="middle" font-size="10" fill="#10b981" font-weight="700">равно</text>`;
s+=`<text x="190" y="${Oy+14}" text-anchor="middle" font-size="10" fill="#10b981" font-weight="700">равно</text>`;
s+='</svg>';return s;}},
{desc:'<b>Шаг 5.</b> Обобщённая теорема Фалеса: при <em>произвольных</em> параллельных прямых (не обязательно с равными частями) отрезки на двух лучах всё равно пропорциональны: $\\dfrac{AB}{BC}=\\dfrac{A\'B\'}{B\'C\'}$. <b>Доказано.</b>',
svg:()=>{
const W=260,H=160;
let s=`<svg viewBox="0 0 ${W} ${H}" style="max-width:${W}px;width:100%;background:#fafafa;border:1px solid var(--border);border-radius:10px">`;
s+=`<line x1="20" y1="140" x2="250" y2="140" stroke="#7c3aed" stroke-width="2"/>`;
s+=`<line x1="20" y1="140" x2="250" y2="50" stroke="#7c3aed" stroke-width="2"/>`;
s+=`<line x1="80" y1="10" x2="80" y2="150" stroke="#a78bfa" stroke-width="1.5"/>`;
s+=`<line x1="170" y1="10" x2="170" y2="150" stroke="#a78bfa" stroke-width="1.5"/>`;
s+=`<text x="125" y="30" text-anchor="middle" font-size="11" fill="#6d28d9" font-weight="800">AB/BC = A'B'/B'C'</text>`;
s+=`<text x="125" y="100" text-anchor="middle" font-size="10" fill="#10b981" font-weight="700">QED</text>`;
s+='</svg>';return s;}},
];
let step=0;
const svgEl=document.getElementById('p1-proof-svg');
const descEl=document.getElementById('p1-proof-desc');
function show(){
svgEl.innerHTML=steps[step].svg();
descEl.innerHTML=steps[step].desc;
renderMath(descEl);
}
document.getElementById('p1-proof-next').addEventListener('click',()=>{
if(step<steps.length-1){step++;show();addXp(1,'p1-proof-step');}
else{addXp(5,'p1-proof-done');bumpProgress('p1',10);}
});
document.getElementById('p1-proof-reset').addEventListener('click',()=>{step=0;show();});
show();
})();
/* == INIT ИНТЕРАКТИВ 3: калькулятор пропорций == */
(function(){
document.getElementById('p1-pcalc').addEventListener('click',()=>{
const a=parseFloat(document.getElementById('p1-pa').value);
const b=parseFloat(document.getElementById('p1-pb').value);
const c=parseFloat(document.getElementById('p1-pc').value);
const out=document.getElementById('p1-pcalc-out');
if(!isFinite(a)||!isFinite(b)||!isFinite(c)||a<=0||b<=0||c<=0){
out.style.display='block';out.innerHTML='<span style="color:var(--bad)">Введи три положительных числа.</span>';return;
}
const x=b*c/a;
out.style.display='block';
out.innerHTML=`По теореме Фалеса: $x = \\dfrac{b \\cdot c}{a} = \\dfrac{${fmt(b)} \\cdot ${fmt(c)}}{${fmt(a)}} = ${fmt(x)}$`;
renderMath(out);
addXp(2,'p1-pcalc');bumpProgress('p1',5);
});
})();
/* == INIT ИНТЕРАКТИВ 4: тренажёр == */
(function(){
const tasks=[
{q:'Параллельные прямые отсекают на первом луче отрезки $AB=4$, $BC=6$. На втором луче $A\'B\'=6$. Найди $B\'C\'$.', ans:9, hint:'BC·A\'B\'/AB = 6·6/4 = 9.'},
{q:'$AB=3$, $BC=9$, $A\'B\'=5$. Найди $B\'C\'$.', ans:15, hint:'9·5/3 = 15.'},
{q:'Параллельные прямые отсекают $AB=8$, $BC=12$, $B\'C\'=9$. Найди $A\'B\'$.', ans:6, hint:'A\'B\' = AB·B\'C\'/BC = 8·9/12 = 6.'},
{q:'$AB=5$, $A\'B\'=7$, $B\'C\'=14$. Найди $BC$.', ans:10, hint:'BC = AB·B\'C\'/A\'B\' = 5·14/7 = 10.'},
{q:'Три параллельные прямые отсекают на луче отрезки $2$ и $3$. На другом луче первый отрезок равен $4$. Найди второй отрезок.', ans:6, hint:'4·3/2 = 6.'},
];
let idx=0,score=0;
function show(){
document.getElementById('p1-tr-i').textContent=idx+1;
const t=document.getElementById('p1-tr-task');
t.innerHTML=tasks[idx].q;
renderMath(t);
document.getElementById('p1-tr-ans').value='';
document.getElementById('p1-tr-fb').style.display='none';
}
document.getElementById('p1-tr-start').addEventListener('click',()=>{idx=0;score=0;document.getElementById('p1-tr-score').textContent=0;show();});
document.getElementById('p1-tr-go').addEventListener('click',()=>{
if(idx>=tasks.length)return;
const ans=+document.getElementById('p1-tr-ans').value;
const fb=document.getElementById('p1-tr-fb');
if(Math.abs(ans-tasks[idx].ans)<0.01){
score++;document.getElementById('p1-tr-score').textContent=score;
addXp(3,'p1-tr-'+idx);bumpProgress('p1',4);
if(idx<tasks.length-1){feedback(fb,true,'Верно! +3 XP');idx++;setTimeout(()=>show(),900);}
else{feedback(fb,true,'Все задачи решены! +5 XP');addXp(5,'p1-tr-all');bumpProgress('p1',10);confetti();}
} else {
feedback(fb,false,'Неверно. '+tasks[idx].hint);
}
});
document.getElementById('p1-tr-ans').addEventListener('keydown',e=>{if(e.key==='Enter')document.getElementById('p1-tr-go').click();});
show();
})();
/* == INIT ИНТЕРАКТИВ 5: DnD-сортер == */
(function(){
const items=[
{text:'AB=3, BC=6, A\'B\'=4, B\'C\'=8',yes:true},
{text:'AB=2, BC=4, A\'B\'=3, B\'C\'=7',yes:false},
{text:'AB=5, BC=10, A\'B\'=1, B\'C\'=2',yes:true},
{text:'AB=6, BC=3, A\'B\'=8, B\'C\'=5',yes:false},
{text:'AB=4, BC=8, A\'B\'=3, B\'C\'=6',yes:true},
];
const pool=document.getElementById('p1-dnd-pool');
const yesBox=document.getElementById('p1-drop-yes-items');
const noBox=document.getElementById('p1-drop-no-items');
let dragging=null;
function makeChip(it,idx){
const chip=document.createElement('div');
chip.className='dnd-chip';
chip.dataset.idx=idx;
chip.textContent=it.text;
chip.draggable=true;
chip.addEventListener('dragstart',e=>{dragging=chip;chip.classList.add('dragging');e.dataTransfer.effectAllowed='move';});
chip.addEventListener('dragend',()=>{chip.classList.remove('dragging');dragging=null;});
return chip;
}
items.forEach((it,i)=>pool.appendChild(makeChip(it,i)));
[document.getElementById('p1-drop-yes'),document.getElementById('p1-drop-no'),pool].forEach(box=>{
box.addEventListener('dragover',e=>{e.preventDefault();box.classList.add('over');});
box.addEventListener('dragleave',()=>box.classList.remove('over'));
box.addEventListener('drop',e=>{
e.preventDefault();box.classList.remove('over');
if(!dragging)return;
const target=box===document.getElementById('p1-drop-yes')?yesBox:box===document.getElementById('p1-drop-no')?noBox:pool;
target.appendChild(dragging);
});
});
document.getElementById('p1-dnd-check').addEventListener('click',()=>{
const fb=document.getElementById('p1-dnd-fb');
const yChips=[...yesBox.querySelectorAll('.dnd-chip')];
const nChips=[...noBox.querySelectorAll('.dnd-chip')];
if(yChips.length+nChips.length<items.length){feedback(fb,false,'Разложи все карточки.');return;}
let ok=true;
yChips.forEach(c=>{if(!items[+c.dataset.idx].yes)ok=false;});
nChips.forEach(c=>{if(items[+c.dataset.idx].yes)ok=false;});
if(ok){feedback(fb,true,'Верно! +5 XP');addXp(5,'p1-dnd');bumpProgress('p1',8);}
else{feedback(fb,false,'Есть ошибки — перепроверь отношения AB/BC и A\'B\'/B\'C\'.');}
});
document.getElementById('p1-dnd-reset').addEventListener('click',()=>{
[...yesBox.children].forEach(c=>pool.appendChild(c));
[...noBox.children].forEach(c=>pool.appendChild(c));
document.getElementById('p1-dnd-fb').style.display='none';
});
})();
/* == INIT: Босс §1 == */
(function(){
const tasks=[
{q:'<svg viewBox="0 0 240 130" style="display:block;max-width:250px;margin:0 auto 8px;background:#f5f3ff;border:1px solid #ddd6fe;border-radius:8px"><line x1="20" y1="110" x2="220" y2="110" stroke="#7c3aed" stroke-width="2"/><line x1="20" y1="110" x2="220" y2="30" stroke="#7c3aed" stroke-width="2"/><line x1="80" y1="10" x2="80" y2="118" stroke="#a78bfa" stroke-width="1.5" stroke-dasharray="4,3"/><line x1="160" y1="10" x2="160" y2="118" stroke="#a78bfa" stroke-width="1.5" stroke-dasharray="4,3"/><text x="120" y="125" text-anchor="middle" font-size="10" fill="#6d28d9" font-weight="700">AB=10, BC=?, A\'B\'=6, B\'C\'=9</text></svg>$AB=10$, $A\'B\'=6$, $B\'C\'=9$. Найди $BC$.', ans:15, hint:'BC = AB·B\'C\'/A\'B\' = 10·9/6 = 15.'},
{q:'Параллельные прямые отсекают на двух лучах: луч 1 — отрезки $4$ и $x$, луч 2 — отрезки $6$ и $12$. Найди $x$.', ans:8, hint:'4/x = 6/12 → x = 4·12/6 = 8.'},
{q:'Прямая $DE \\parallel BC$ в треугольнике $ABC$. $AD=6$, $DB=9$, $AE=8$. Найди $EC$.', ans:12, hint:'AD/DB = AE/EC → EC = DB·AE/AD = 9·8/6 = 12.'},
{q:'$AB=15$, $BC=25$, $B\'C\'=20$. Найди $A\'B\'$.', ans:12, hint:'A\'B\' = AB·B\'C\'/BC = 15·20/25 = 12.'},
];
const bossBox=document.getElementById('p1-boss-tasks');
bossBox.innerHTML=tasks.map((t,i)=>`
<div style="padding:14px;background:var(--card);border-radius:10px;border:1px solid var(--border);margin-bottom:10px">
<div style="margin-bottom:8px;font-size:.95rem">${t.q}</div>
<div style="display:flex;gap:8px;flex-wrap:wrap;align-items:center">
<input type="number" class="tinp" id="p1b-a${i}" placeholder="Ответ" style="width:110px">
<button class="btn primary small" onclick="(function(){
const v=+document.getElementById('p1b-a${i}').value;
const fb=document.getElementById('p1b-fb${i}');
if(Math.abs(v-${t.ans})<0.01){
feedback(fb,true,'Верно! +5 XP');
if(!window.p1BossSolved.has(${i})){ window.p1BossSolved.add(${i}); addXp(5,'p1-boss${i}'); bumpProgress('p1',8); }
} else feedback(fb,false,'Неверно. ${t.hint}');
})()">Проверить</button>
</div>
<div class="feedback" id="p1b-fb${i}" style="display:none;margin-top:8px"></div>
</div>`).join('');
window.p1BossSolved=new Set();
renderMath(bossBox);
})();
}
function buildP2(){
const box=document.getElementById('p2-body');
let html='';
html+=makeCard('theory','Деление отрезка в заданном отношении','2.1',`
<p><b>Определение.</b> Говорят, что точка $C$ делит отрезок $AB$ <em>в отношении $m:n$</em> (<em>внутреннее деление</em>), если $C$ лежит между $A$ и $B$, и:</p>
$$\\dfrac{AC}{CB} = \\dfrac{m}{n}, \\quad m,n > 0$$
<p style="margin-top:8px"><b>Формула координат.</b> Если $A = (x_A, y_A)$, $B = (x_B, y_B)$, то точка деления:</p>
$$C = \\left(\\dfrac{n\\,x_A + m\\,x_B}{m+n},\\; \\dfrac{n\\,y_A + m\\,y_B}{m+n}\\right)$$
<p style="margin-top:8px"><b>Частный случай $m=n$:</b> точка $C$ — середина $AB$.</p>
<div style="display:flex;justify-content:center;margin-top:14px">
<svg viewBox="0 0 280 80" style="max-width:300px;background:#fafafa;border:1px solid var(--border);border-radius:10px">
<!-- отрезок AB с точкой C -->
<line x1="20" y1="40" x2="260" y2="40" stroke="#7c3aed" stroke-width="2.5"/>
<circle cx="20" cy="40" r="4" fill="#7c3aed"/>
<circle cx="260" cy="40" r="4" fill="#7c3aed"/>
<!-- C делит в 2:3: x = 20 + 2/(2+3)*240 = 20+96 = 116 -->
<circle cx="116" cy="40" r="5" fill="#f59e0b"/>
<!-- скобки -->
<line x1="20" y1="52" x2="116" y2="52" stroke="#10b981" stroke-width="1.5"/>
<line x1="116" y1="52" x2="260" y2="52" stroke="#8b5cf6" stroke-width="1.5"/>
<text x="68" y="65" text-anchor="middle" font-size="11" fill="#10b981" font-weight="700">m = 2</text>
<text x="188" y="65" text-anchor="middle" font-size="11" fill="#8b5cf6" font-weight="700">n = 3</text>
<text x="20" y="32" text-anchor="middle" font-size="11" fill="#6d28d9" font-weight="700">A</text>
<text x="116" y="32" text-anchor="middle" font-size="11" fill="#b45309" font-weight="700">C</text>
<text x="260" y="32" text-anchor="middle" font-size="11" fill="#6d28d9" font-weight="700">B</text>
</svg>
</div>`);
html+=makeCard('algo','Построение циркулем и линейкой','2.2',`
<p>Чтобы разделить отрезок $AB$ в отношении $m:n$:</p>
<ol style="margin-left:18px;margin-top:6px;line-height:2">
<li>Из точки $A$ проводим луч $AK$, не совпадающий с $AB$.</li>
<li>На луче $AK$ последовательно откладываем $m+n$ равных отрезков единичной длины: точки $P_1, P_2, \\ldots, P_{m+n}$.</li>
<li>Соединяем точку $P_{m+n}$ с точкой $B$.</li>
<li>Через $P_m$ проводим прямую, параллельную $P_{m+n}B$ — она пересекает $AB$ в нужной точке $C$.</li>
</ol>
<p style="margin-top:8px">По теореме Фалеса $\\dfrac{AC}{CB} = \\dfrac{m}{n}$. $\\square$</p>
<div style="display:flex;justify-content:center;margin-top:12px">
<svg viewBox="0 0 280 160" style="max-width:300px;background:#fafafa;border:1px solid var(--border);border-radius:10px">
<!-- отрезок AB -->
<line x1="20" y1="60" x2="260" y2="60" stroke="#7c3aed" stroke-width="2"/>
<circle cx="20" cy="60" r="4" fill="#7c3aed"/>
<circle cx="260" cy="60" r="4" fill="#7c3aed"/>
<text x="16" y="52" font-size="10" fill="#6d28d9" font-weight="700">A</text>
<text x="256" y="52" font-size="10" fill="#6d28d9" font-weight="700">B</text>
<!-- луч AK: из A=(20,60) под углом вниз -->
<line x1="20" y1="60" x2="170" y2="140" stroke="#f59e0b" stroke-width="1.5"/>
<!-- 5 точек (m+n=2+3) на луче, шаг=30px по лучу -->
<!-- P1=(50,76), P2=(80,92), P3=(110,108), P4=(140,124), P5=(170,140) -->
<circle cx="50" cy="76" r="3" fill="#f59e0b"/>
<circle cx="80" cy="92" r="3" fill="#f59e0b"/>
<circle cx="110" cy="108" r="3" fill="#10b981"/>
<circle cx="140" cy="124" r="3" fill="#f59e0b"/>
<circle cx="170" cy="140" r="3" fill="#f59e0b"/>
<text x="50" y="72" text-anchor="middle" font-size="8" fill="#b45309">P₁</text>
<text x="80" y="88" text-anchor="middle" font-size="8" fill="#b45309">P₂</text>
<text x="110" y="104" text-anchor="middle" font-size="8" fill="#047857" font-weight="700">P_m</text>
<text x="165" y="155" text-anchor="middle" font-size="8" fill="#b45309">P₅</text>
<!-- линия P5B -->
<line x1="170" y1="140" x2="260" y2="60" stroke="#8b5cf6" stroke-width="1.2" stroke-dasharray="4,3"/>
<!-- параллельная через Pm: C на AB -->
<!-- C: x = 20 + 2/5*(260-20) = 20+96 = 116 -->
<line x1="110" y1="108" x2="116" y2="60" stroke="#10b981" stroke-width="1.8" stroke-dasharray="4,3"/>
<circle cx="116" cy="60" r="5" fill="#10b981"/>
<text x="116" y="52" text-anchor="middle" font-size="10" fill="#047857" font-weight="700">C</text>
</svg>
</div>`);
html+=makeCard('example','Пример','2.3',`
<p><b>Пример 1.</b> $A=(0,0)$, $B=(10,0)$, разделить в отношении $3:2$.</p>
<p>$C_x = \\dfrac{2\\cdot 0 + 3\\cdot 10}{3+2} = \\dfrac{30}{5} = 6$. Ответ: $C=(6,0)$.</p>
<p style="margin-top:8px"><b>Пример 2.</b> $A=(1,2)$, $B=(7,8)$, разделить в отношении $1:2$.</p>
<p>$C_x = \\dfrac{2\\cdot 1+1\\cdot 7}{3}=3$, $C_y=\\dfrac{2\\cdot 2+1\\cdot 8}{3}=4$. Ответ: $C=(3,4)$.</p>`);
/* ИНТЕРАКТИВ 1 — SVG-построение */
html+=`<div class="wg" id="p2-build-wg">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 1</span><div class="wg-title">Построение деления отрезка m:n</div></div>
<div class="wg-help">Меняй m и n — смотри, как перемещается точка C на отрезке AB.</div>
<div class="sliders">
<label>m = <b id="p2-m-val">2</b>
<input type="range" min="1" max="6" value="2" id="p2-m-sl">
</label>
<label>n = <b id="p2-n-val">3</b>
<input type="range" min="1" max="6" value="3" id="p2-n-sl">
</label>
</div>
<div id="p2-build-svg" style="display:flex;justify-content:center"></div>
<div id="p2-build-info" style="margin-top:10px;padding:10px 14px;background:var(--sec-acc-soft,var(--pri-soft));border-radius:10px;font-size:.93rem;line-height:1.8"></div>
</div>`;
/* ИНТЕРАКТИВ 2 — Калькулятор */
html+=`<div class="wg">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 2</span><div class="wg-title">Калькулятор деления отрезка</div></div>
<div class="wg-help">Введи длину отрезка и отношение m:n — получи расстояние AC от начала.</div>
<div style="display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin-bottom:10px">
<div style="display:flex;flex-direction:column;gap:4px">
<span style="font-size:.8rem;color:var(--muted)">AB</span>
<input type="number" id="p2-lab" class="tinp" placeholder="AB" style="width:80px" min="0.001">
</div>
<div style="display:flex;flex-direction:column;gap:4px">
<span style="font-size:.8rem;color:var(--muted)">m</span>
<input type="number" id="p2-lm" class="tinp" placeholder="m" style="width:60px" min="1">
</div>
<div style="display:flex;flex-direction:column;gap:4px">
<span style="font-size:.8rem;color:var(--muted)">n</span>
<input type="number" id="p2-ln" class="tinp" placeholder="n" style="width:60px" min="1">
</div>
<button class="btn primary" id="p2-lcalc">Вычислить</button>
</div>
<div id="p2-lcalc-out" style="display:none;padding:10px 14px;background:var(--sec-acc-soft,var(--pri-soft));border-radius:10px;font-size:.95rem"></div>
</div>`;
/* ИНТЕРАКТИВ 3 — Пошаговое доказательство */
html+=`<div class="wg" id="p2-proof-wg">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 3</span><div class="wg-title">Доказательство формулы — по шагам</div></div>
<div class="wg-help">4 шага — вывод формулы координат точки деления через теорему Фалеса.</div>
<div id="p2-proof-svg" style="display:flex;justify-content:center;margin-bottom:10px"></div>
<div id="p2-proof-desc" style="padding:10px 14px;background:var(--sec-acc-soft,var(--pri-soft));border-radius:10px;font-size:.95rem;line-height:1.6;margin-bottom:10px;min-height:60px"></div>
<div style="display:flex;gap:8px">
<button class="btn primary" id="p2-proof-next">Далее</button>
<button class="btn" id="p2-proof-reset">Сначала</button>
</div>
</div>`;
/* ИНТЕРАКТИВ 4 — Тренажёр */
html+=`<div class="wg">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 4</span><div class="wg-title">Тренажёр §2</div></div>
<div class="wg-help">5 задач на деление отрезка. Введи числовой ответ.</div>
<div class="score-display"><span>Задача <b id="p2-tr-i">1</b> / 5</span><span>Очки: <b id="p2-tr-score">0</b></span></div>
<div id="p2-tr-task" style="padding:14px;background:var(--sec-acc-soft,var(--pri-soft));border-radius:10px;font-size:1.02rem;margin-bottom:10px"></div>
<div style="display:flex;gap:8px;align-items:center;flex-wrap:wrap">
<input type="number" id="p2-tr-ans" class="tinp" placeholder="Ответ" style="width:120px">
<button class="btn primary" id="p2-tr-go">Проверить</button>
<button class="btn" id="p2-tr-start">Начать</button>
</div>
<div class="feedback" id="p2-tr-fb" style="display:none"></div>
</div>`;
/* ИНТЕРАКТИВ 5 — Босс §2 */
html+=`<div class="wg" style="border-color:var(--sec-acc-d,var(--pri2))">
<div class="wg-header"><span class="wg-badge" style="background:var(--sec-acc-d,var(--pri2))">БОСС §2</span><div class="wg-title">Итоговые задачи</div></div>
<div class="wg-help">4 задачи — каждая верная даёт +5 XP.</div>
<div id="p2-boss-tasks"></div>
</div>`;
html+=`<div style="margin-top:18px;display:flex;justify-content:center">
<button class="btn primary" id="p2-read-btn" onclick="addXp(10,'p2-read');bumpProgress('p2',40);this.textContent='Прочитано!';this.disabled=true;">
<svg class="ic" viewBox="0 0 24 24"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/></svg>
Я прочитал §2 (+10 XP)
</button>
</div>`;
html+=secNav('p1','p3');
box.innerHTML=html;
if(window.renderMathInElement) setTimeout(()=>renderMath(box),0);
/* == INIT ИНТЕРАКТИВ 1: построение == */
(function(){
const mSl=document.getElementById('p2-m-sl');
const nSl=document.getElementById('p2-n-sl');
const mVal=document.getElementById('p2-m-val');
const nVal=document.getElementById('p2-n-val');
const svgWrap=document.getElementById('p2-build-svg');
const infoEl=document.getElementById('p2-build-info');
function draw(){
const m=+mSl.value, n=+nSl.value;
mVal.textContent=m; nVal.textContent=n;
const W=320, H=140;
const Ax=24, Ay=50, Bx=296, By=50;
const AB=Bx-Ax;
const Cx=Ax+m/(m+n)*AB;
const Cy=50;
// луч AK: вниз под углом 30°
const rayLen=(m+n)*22;
const rayAngle=Math.PI/6;
const Kx=Ax+rayLen*Math.cos(rayAngle);
const Ky=Ay+rayLen*Math.sin(rayAngle);
let s=`<svg viewBox="0 0 ${W} ${H}" style="max-width:${W}px;width:100%;background:#fafafa;border:1px solid var(--border);border-radius:10px">`;
// отрезок AB
s+=`<line x1="${Ax}" y1="${Ay}" x2="${Bx}" y2="${By}" stroke="#7c3aed" stroke-width="2.5"/>`;
s+=`<circle cx="${Ax}" cy="${Ay}" r="4" fill="#7c3aed"/>`;
s+=`<circle cx="${Bx}" cy="${By}" r="4" fill="#7c3aed"/>`;
s+=`<text x="${Ax}" y="${Ay-8}" text-anchor="middle" font-size="11" fill="#6d28d9" font-weight="700">A</text>`;
s+=`<text x="${Bx}" y="${By-8}" text-anchor="middle" font-size="11" fill="#6d28d9" font-weight="700">B</text>`;
// луч AK
s+=`<line x1="${Ax}" y1="${Ay}" x2="${Kx}" y2="${Ky}" stroke="#f59e0b" stroke-width="1.5"/>`;
// точки P1..P(m+n) на луче
for(let i=1;i<=m+n;i++){
const px=Ax+i*22*Math.cos(rayAngle);
const py=Ay+i*22*Math.sin(rayAngle);
const isM=(i===m);
s+=`<circle cx="${px}" cy="${py}" r="${isM?5:3}" fill="${isM?'#10b981':'#f59e0b'}"/>`;
s+=`<text x="${px+6}" y="${py+4}" font-size="8" fill="${isM?'#047857':'#b45309'}" font-weight="${isM?'700':'400'}">P${i}${isM?' (m)':''}</text>`;
}
// линия P(m+n)→B
const Pmn_x=Ax+(m+n)*22*Math.cos(rayAngle);
const Pmn_y=Ay+(m+n)*22*Math.sin(rayAngle);
s+=`<line x1="${Pmn_x}" y1="${Pmn_y}" x2="${Bx}" y2="${By}" stroke="#8b5cf6" stroke-width="1.3" stroke-dasharray="4,3"/>`;
// параллельная через Pm → C
const Pm_x=Ax+m*22*Math.cos(rayAngle);
const Pm_y=Ay+m*22*Math.sin(rayAngle);
s+=`<line x1="${Pm_x}" y1="${Pm_y}" x2="${Cx}" y2="${Cy}" stroke="#10b981" stroke-width="2" stroke-dasharray="4,3"/>`;
// точка C
s+=`<circle cx="${Cx}" cy="${Cy}" r="6" fill="#10b981"/>`;
s+=`<text x="${Cx}" y="${Cy-10}" text-anchor="middle" font-size="11" fill="#047857" font-weight="700">C</text>`;
// метки AC, CB
s+=`<line x1="${Ax}" y1="${Ay+14}" x2="${Cx}" y2="${Cy+14}" stroke="#10b981" stroke-width="1.5"/>`;
s+=`<line x1="${Cx}" y1="${Cy+14}" x2="${Bx}" y2="${By+14}" stroke="#8b5cf6" stroke-width="1.5"/>`;
s+=`<text x="${(Ax+Cx)/2}" y="${Cy+26}" text-anchor="middle" font-size="10" fill="#047857" font-weight="700">m=${m}</text>`;
s+=`<text x="${(Cx+Bx)/2}" y="${Cy+26}" text-anchor="middle" font-size="10" fill="#6d28d9" font-weight="700">n=${n}</text>`;
s+='</svg>';
svgWrap.innerHTML=s;
const AClen=fmt(m/(m+n)*100);
const CBlen=fmt(n/(m+n)*100);
infoEl.innerHTML=`Отношение $AC:CB = ${m}:${n}$. Если $AB=100$, то $AC=${AClen}$, $CB=${CBlen}$.`;
renderMath(infoEl);
addXp(1,'p2-build');
}
mSl.addEventListener('input',draw);
nSl.addEventListener('input',draw);
draw();
})();
/* == INIT ИНТЕРАКТИВ 2: калькулятор == */
(function(){
document.getElementById('p2-lcalc').addEventListener('click',()=>{
const AB=parseFloat(document.getElementById('p2-lab').value);
const m=parseFloat(document.getElementById('p2-lm').value);
const n=parseFloat(document.getElementById('p2-ln').value);
const out=document.getElementById('p2-lcalc-out');
if(!isFinite(AB)||!isFinite(m)||!isFinite(n)||AB<=0||m<=0||n<=0){
out.style.display='block';out.innerHTML='<span style="color:var(--bad)">Введи положительные числа.</span>';return;
}
const AC=m/(m+n)*AB;
const CB=n/(m+n)*AB;
out.style.display='block';
out.innerHTML=`$AC = \\dfrac{m}{m+n}\\cdot AB = \\dfrac{${fmt(m)}}{${fmt(m+n)}}\\cdot ${fmt(AB)} = ${fmt(AC)}$<br>$CB = \\dfrac{${fmt(n)}}{${fmt(m+n)}}\\cdot ${fmt(AB)} = ${fmt(CB)}$`;
renderMath(out);
addXp(2,'p2-calc');bumpProgress('p2',5);
});
})();
/* == INIT ИНТЕРАКТИВ 3: доказательство == */
(function(){
const steps=[
{desc:'<b>Шаг 1.</b> Даны точки $A$ и $B$ на прямой. Хотим найти точку $C$ такую, что $AC:CB = m:n$.',
svg:`<svg viewBox="0 0 280 70" style="max-width:280px;background:#fafafa;border:1px solid var(--border);border-radius:10px"><line x1="20" y1="35" x2="260" y2="35" stroke="#7c3aed" stroke-width="2"/><circle cx="20" cy="35" r="4" fill="#7c3aed"/><circle cx="260" cy="35" r="4" fill="#7c3aed"/><text x="20" y="27" text-anchor="middle" font-size="11" fill="#6d28d9" font-weight="700">A</text><text x="260" y="27" text-anchor="middle" font-size="11" fill="#6d28d9" font-weight="700">B</text><text x="140" y="55" text-anchor="middle" font-size="10" fill="#6d28d9">AC : CB = m : n = ?</text></svg>`},
{desc:'<b>Шаг 2.</b> Проводим из $A$ луч $AK$ и откладываем $m+n$ равных единичных отрезков. Последняя точка — $P_{m+n}$, средняя (после $m$ шагов) — $P_m$.',
svg:`<svg viewBox="0 0 280 130" style="max-width:280px;background:#fafafa;border:1px solid var(--border);border-radius:10px"><line x1="20" y1="40" x2="260" y2="40" stroke="#7c3aed" stroke-width="2"/><line x1="20" y1="40" x2="140" y2="120" stroke="#f59e0b" stroke-width="1.5"/><circle cx="44" cy="57" r="3" fill="#f59e0b"/><circle cx="68" cy="73" r="3" fill="#f59e0b"/><circle cx="92" cy="90" r="5" fill="#10b981"/><circle cx="116" cy="106" r="3" fill="#f59e0b"/><circle cx="140" cy="120" r="3" fill="#f59e0b"/><text x="96" y="88" font-size="8" fill="#047857" font-weight="700">P_m</text><text x="142" y="118" font-size="8" fill="#b45309">P_{m+n}</text><text x="20" y="32" font-size="10" fill="#6d28d9" font-weight="700">A</text><text x="256" y="32" font-size="10" fill="#6d28d9" font-weight="700">B</text></svg>`},
{desc:'<b>Шаг 3.</b> Соединяем $P_{m+n}$ с $B$. Через $P_m$ проводим прямую, параллельную $P_{m+n}B$. По теореме Фалеса она пересекает $AB$ в точке $C$, делящей $AB$ в отношении $m:n$.',
svg:`<svg viewBox="0 0 280 130" style="max-width:280px;background:#fafafa;border:1px solid var(--border);border-radius:10px"><line x1="20" y1="40" x2="260" y2="40" stroke="#7c3aed" stroke-width="2"/><line x1="20" y1="40" x2="140" y2="120" stroke="#f59e0b" stroke-width="1.5"/><line x1="140" y1="120" x2="260" y2="40" stroke="#8b5cf6" stroke-width="1.3" stroke-dasharray="4,3"/><line x1="92" y1="90" x2="116" y2="40" stroke="#10b981" stroke-width="2" stroke-dasharray="4,3"/><circle cx="116" cy="40" r="6" fill="#10b981"/><text x="116" y="32" text-anchor="middle" font-size="11" fill="#047857" font-weight="700">C</text><circle cx="92" cy="90" r="4" fill="#10b981"/><circle cx="140" cy="120" r="4" fill="#f59e0b"/><text x="92" y="88" font-size="8" fill="#047857">P_m</text><text x="20" y="32" font-size="10" fill="#6d28d9" font-weight="700">A</text><text x="256" y="32" font-size="10" fill="#6d28d9" font-weight="700">B</text></svg>`},
{desc:'<b>Шаг 4.</b> Итог: по теореме Фалеса $\\dfrac{AC}{CB}=\\dfrac{m}{n}$. Координаты точки $C$: $C_x = \\dfrac{n\\,x_A+m\\,x_B}{m+n}$, $C_y = \\dfrac{n\\,y_A+m\\,y_B}{m+n}$. <b>Доказано.</b>',
svg:`<svg viewBox="0 0 280 70" style="max-width:280px;background:#fafafa;border:1px solid var(--border);border-radius:10px"><line x1="20" y1="35" x2="260" y2="35" stroke="#7c3aed" stroke-width="2"/><circle cx="20" cy="35" r="4" fill="#7c3aed"/><circle cx="260" cy="35" r="4" fill="#7c3aed"/><circle cx="116" cy="35" r="6" fill="#10b981"/><text x="20" y="27" text-anchor="middle" font-size="11" fill="#6d28d9" font-weight="700">A</text><text x="116" y="27" text-anchor="middle" font-size="11" fill="#047857" font-weight="700">C</text><text x="260" y="27" text-anchor="middle" font-size="11" fill="#6d28d9" font-weight="700">B</text><text x="140" y="58" text-anchor="middle" font-size="10" fill="#047857" font-weight="700">C = (n·A + m·B) / (m+n)</text></svg>`},
];
let step=0;
const svgEl=document.getElementById('p2-proof-svg');
const descEl=document.getElementById('p2-proof-desc');
function show(){
svgEl.innerHTML=steps[step].svg;
descEl.innerHTML=steps[step].desc;
renderMath(descEl);
}
document.getElementById('p2-proof-next').addEventListener('click',()=>{
if(step<steps.length-1){step++;show();addXp(1,'p2-proof-step');}
else{addXp(5,'p2-proof-done');bumpProgress('p2',10);}
});
document.getElementById('p2-proof-reset').addEventListener('click',()=>{step=0;show();});
show();
})();
/* == INIT ИНТЕРАКТИВ 4: тренажёр == */
(function(){
const tasks=[
{q:'Отрезок $AB=20$ делится точкой $C$ в отношении $1:4$. Найди $AC$.', ans:4, hint:'AC = 1/(1+4)·20 = 4.'},
{q:'$AB=15$, $AC:CB=2:3$. Найди $CB$.', ans:9, hint:'CB = 3/(2+3)·15 = 9.'},
{q:'$A=(0,0)$, $B=(8,0)$, деление $3:1$. Найди $x$-координату точки $C$.', ans:6, hint:'C_x = (1·0+3·8)/4 = 6.'},
{q:'Отрезок $AB=30$ делится в отношении $2:1$. Найди расстояние от $C$ до $B$.', ans:10, hint:'CB = 1/(2+1)·30 = 10.'},
{q:'$A=(0,0)$, $B=(0,12)$, деление $1:2$. Найди $y$-координату точки $C$.', ans:4, hint:'C_y = (2·0+1·12)/3 = 4.'},
];
let idx=0,score=0;
function show(){
document.getElementById('p2-tr-i').textContent=idx+1;
const t=document.getElementById('p2-tr-task');
t.innerHTML=tasks[idx].q;
renderMath(t);
document.getElementById('p2-tr-ans').value='';
document.getElementById('p2-tr-fb').style.display='none';
}
document.getElementById('p2-tr-start').addEventListener('click',()=>{idx=0;score=0;document.getElementById('p2-tr-score').textContent=0;show();});
document.getElementById('p2-tr-go').addEventListener('click',()=>{
if(idx>=tasks.length)return;
const ans=+document.getElementById('p2-tr-ans').value;
const fb=document.getElementById('p2-tr-fb');
if(Math.abs(ans-tasks[idx].ans)<0.01){
score++;document.getElementById('p2-tr-score').textContent=score;
addXp(3,'p2-tr-'+idx);bumpProgress('p2',4);
if(idx<tasks.length-1){feedback(fb,true,'Верно! +3 XP');idx++;setTimeout(()=>show(),900);}
else{feedback(fb,true,'Все задачи решены! +5 XP');addXp(5,'p2-tr-all');bumpProgress('p2',10);confetti();}
} else {
feedback(fb,false,'Неверно. '+tasks[idx].hint);
}
});
document.getElementById('p2-tr-ans').addEventListener('keydown',e=>{if(e.key==='Enter')document.getElementById('p2-tr-go').click();});
show();
})();
/* == INIT: Босс §2 == */
(function(){
const tasks=[
{q:'$AB=24$, деление в отношении $5:3$. Найди $AC$.', ans:15, hint:'AC = 5/8·24 = 15.'},
{q:'$A=(0,0)$, $B=(10,10)$, деление $3:2$. Найди $x_C+y_C$.', ans:12, hint:'C_x=6, C_y=6, сумма=12.'},
{q:'Точка $C$ делит $AB$ в отношении $AC:CB=4:1$. $CB=7$. Найди $AB$.', ans:35, hint:'AB = (4+1)·7 = 35.'},
{q:'$AB=100$, $C$ делит $AB$ в отношении $3:7$. Найди $BC$.', ans:70, hint:'BC = 7/10·100 = 70.'},
];
const bossBox=document.getElementById('p2-boss-tasks');
bossBox.innerHTML=tasks.map((t,i)=>`
<div style="padding:14px;background:var(--card);border-radius:10px;border:1px solid var(--border);margin-bottom:10px">
<div style="margin-bottom:8px;font-size:.95rem">${t.q}</div>
<div style="display:flex;gap:8px;flex-wrap:wrap;align-items:center">
<input type="number" class="tinp" id="p2b-a${i}" placeholder="Ответ" style="width:110px">
<button class="btn primary small" onclick="(function(){
const v=+document.getElementById('p2b-a${i}').value;
const fb=document.getElementById('p2b-fb${i}');
if(Math.abs(v-${t.ans})<0.01){
feedback(fb,true,'Верно! +5 XP');
if(!window.p2BossSolved.has(${i})){ window.p2BossSolved.add(${i}); addXp(5,'p2-boss${i}'); bumpProgress('p2',8); }
} else feedback(fb,false,'Неверно. ${t.hint}');
})()">Проверить</button>
</div>
<div class="feedback" id="p2b-fb${i}" style="display:none;margin-top:8px"></div>
</div>`).join('');
window.p2BossSolved=new Set();
renderMath(bossBox);
})();
}
function buildP3(){
const box=document.getElementById('p3-body');
let html='';
html+=makeCard('theory','Определение подобных треугольников','3.1',`
<p><b>Определение.</b> Треугольники $\\triangle ABC$ и $\\triangle A'B'C'$ называются <b>подобными</b> ($\\triangle ABC \\sim \\triangle A'B'C'$), если:</p>
<ol style="margin-left:18px;margin-top:6px;line-height:2">
<li>Соответственные углы равны: $\\angle A = \\angle A'$, $\\angle B = \\angle B'$, $\\angle C = \\angle C'$.</li>
<li>Соответственные стороны пропорциональны: $\\dfrac{a}{a'} = \\dfrac{b}{b'} = \\dfrac{c}{c'} = k$,</li>
</ol>
<p style="margin-top:6px">где $k > 0$ — <b>коэффициент подобия</b>.</p>
<p style="margin-top:8px"><b>Обозначения:</b> стороны треугольника: $a=BC$, $b=CA$, $c=AB$ и $a'=B'C'$, $b'=C'A'$, $c'=A'B'$.</p>
<div style="display:flex;justify-content:center;margin-top:14px">
<svg viewBox="0 0 280 150" style="max-width:300px;background:#fafafa;border:1px solid var(--border);border-radius:10px">
<!-- большой треугольник ABC -->
<polygon points="30,130 180,130 80,30" fill="rgba(124,58,237,.12)" stroke="#7c3aed" stroke-width="2"/>
<text x="74" y="24" font-size="11" font-weight="700" fill="#6d28d9">A</text>
<text x="22" y="143" font-size="11" font-weight="700" fill="#6d28d9">B</text>
<text x="183" y="143" font-size="11" font-weight="700" fill="#6d28d9">C</text>
<!-- малый треугольник A'B'C' (k=0.5) -->
<polygon points="200,130 270,130 237,70" fill="rgba(139,92,246,.15)" stroke="#8b5cf6" stroke-width="1.8"/>
<text x="233" y="64" font-size="10" font-weight="700" fill="#8b5cf6">A'</text>
<text x="194" y="143" font-size="10" font-weight="700" fill="#8b5cf6">B'</text>
<text x="271" y="143" font-size="10" font-weight="700" fill="#8b5cf6">C'</text>
<!-- коэффициент -->
<text x="140" y="16" text-anchor="middle" font-size="10" fill="#6d28d9">k = a/a' = b/b' = c/c'</text>
<!-- равенство углов -->
<text x="35" y="125" font-size="8" fill="#6d28d9">∠B</text>
<text x="203" y="125" font-size="8" fill="#8b5cf6">∠B'</text>
</svg>
</div>`);
html+=makeCard('rule','Коэффициент подобия и свойства','3.2',`
<p><b>Коэффициент подобия</b> $k = \\dfrac{a}{a'} = \\dfrac{b}{b'} = \\dfrac{c}{c'}$ показывает, во сколько раз стороны одного треугольника больше соответственных сторон другого.</p>
<p style="margin-top:8px"><b>Свойства подобия (отношение эквивалентности):</b></p>
<ul style="margin-left:18px;margin-top:6px;line-height:1.9">
<li><b>Рефлексивность:</b> $\\triangle ABC \\sim \\triangle ABC$ (с $k=1$).</li>
<li><b>Симметричность:</b> если $\\triangle ABC \\sim \\triangle A'B'C'$ с коэффициентом $k$, то $\\triangle A'B'C' \\sim \\triangle ABC$ с коэффициентом $\\tfrac{1}{k}$.</li>
<li><b>Транзитивность:</b> если $\\triangle ABC \\sim \\triangle A'B'C'$ и $\\triangle A'B'C' \\sim \\triangle A''B''C''$, то $\\triangle ABC \\sim \\triangle A''B''C''$.</li>
</ul>`);
html+=makeCard('example','Пример','3.3',`
<p><b>Пример.</b> $\\triangle ABC$: стороны $6, 8, 10$. $\\triangle A'B'C'$: стороны $3, 4, 5$. Подобны ли треугольники?</p>
<p style="margin-top:6px">$\\dfrac{6}{3}=2,\\; \\dfrac{8}{4}=2,\\; \\dfrac{10}{5}=2$ — отношения равны. Значит, $\\triangle ABC \\sim \\triangle A'B'C'$ с коэффициентом $k=2$.</p>
<p style="margin-top:8px"><b>Пример 2.</b> Треугольники $5,7,9$ и $10,15,18$ — подобны ли?</p>
<p>$10/5=2$, $15/7\\approx 2.14$ — отношения неравны. <b>Не подобны.</b></p>`);
/* ИНТЕРАКТИВ 1 — SVG два треугольника с slider k */
html+=`<div class="wg" id="p3-sim-wg">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 1</span><div class="wg-title">Два подобных треугольника — коэффициент k</div></div>
<div class="wg-help">Меняй коэффициент подобия $k$ — второй треугольник масштабируется. Углы всегда равны, стороны пропорциональны.</div>
<div class="sliders">
<label>Коэффициент k = <b id="p3-k-val">1.5</b>
<input type="range" min="5" max="30" value="15" id="p3-k-sl" step="1">
</label>
</div>
<div id="p3-sim-svg" style="display:flex;justify-content:center"></div>
<div id="p3-sim-info" style="margin-top:10px;padding:10px 14px;background:var(--sec-acc-soft,var(--pri-soft));border-radius:10px;font-size:.92rem;line-height:1.8"></div>
</div>`;
/* ИНТЕРАКТИВ 2 — Калькулятор */
html+=`<div class="wg">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 2</span><div class="wg-title">Калькулятор подобия</div></div>
<div class="wg-help">Введи стороны одного треугольника и коэффициент $k$ — получи стороны подобного.</div>
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(80px,1fr));gap:8px;margin-bottom:10px">
<div><span style="font-size:.8rem;color:var(--muted);display:block">a</span><input type="number" id="p3-ca" class="tinp" placeholder="a" style="width:100%"></div>
<div><span style="font-size:.8rem;color:var(--muted);display:block">b</span><input type="number" id="p3-cb" class="tinp" placeholder="b" style="width:100%"></div>
<div><span style="font-size:.8rem;color:var(--muted);display:block">c</span><input type="number" id="p3-cc" class="tinp" placeholder="c" style="width:100%"></div>
<div><span style="font-size:.8rem;color:var(--muted);display:block">k</span><input type="number" id="p3-ck" class="tinp" placeholder="k" style="width:100%" min="0.01"></div>
<div style="display:flex;align-items:flex-end"><button class="btn primary" id="p3-ccalc" style="width:100%">Вычислить</button></div>
</div>
<div id="p3-ccalc-out" style="display:none;padding:10px 14px;background:var(--sec-acc-soft,var(--pri-soft));border-radius:10px;font-size:.95rem"></div>
</div>`;
/* ИНТЕРАКТИВ 3 — DnD-сортер подобные / неподобные */
html+=`<div class="wg">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 3</span><div class="wg-title">Подобные или нет? — Сортировка</div></div>
<div class="wg-help">Перетащи каждую пару треугольников в нужную колонку.</div>
<div id="p3-dnd-pool" class="dnd-pool"></div>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-top:10px">
<div class="drop-box" id="p3-drop-yes"><h5>Подобные</h5><div class="drop-items" id="p3-drop-yes-items"></div></div>
<div class="drop-box" id="p3-drop-no"><h5>Не подобные</h5><div class="drop-items" id="p3-drop-no-items"></div></div>
</div>
<div class="actions"><button class="btn primary" id="p3-dnd-check">Проверить</button><button class="btn" id="p3-dnd-reset">Сбросить</button></div>
<div class="feedback" id="p3-dnd-fb" style="display:none"></div>
</div>`;
/* ИНТЕРАКТИВ 4 — Тренажёр */
html+=`<div class="wg">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 4</span><div class="wg-title">Тренажёр §3 — Подобные треугольники</div></div>
<div class="wg-help">5 задач на коэффициент подобия и неизвестные стороны.</div>
<div class="score-display"><span>Задача <b id="p3-tr-i">1</b> / 5</span><span>Очки: <b id="p3-tr-score">0</b></span></div>
<div id="p3-tr-task" style="padding:14px;background:var(--sec-acc-soft,var(--pri-soft));border-radius:10px;font-size:1.02rem;margin-bottom:10px"></div>
<div style="display:flex;gap:8px;align-items:center;flex-wrap:wrap">
<input type="number" id="p3-tr-ans" class="tinp" placeholder="Ответ" style="width:120px">
<button class="btn primary" id="p3-tr-go">Проверить</button>
<button class="btn" id="p3-tr-start">Начать</button>
</div>
<div class="feedback" id="p3-tr-fb" style="display:none"></div>
</div>`;
/* ИНТЕРАКТИВ 5 — Мини-квиз */
html+=`<div class="wg">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 5</span><div class="wg-title">Мини-квиз: теория подобия</div></div>
<div class="wg-help">4 вопроса на проверку понимания теории.</div>
<div id="p3-quiz-body"></div>
<div class="actions"><button class="btn primary" id="p3-quiz-check">Проверить квиз</button></div>
<div class="feedback" id="p3-quiz-fb" style="display:none;margin-top:8px"></div>
</div>`;
/* ИНТЕРАКТИВ 6 — Босс §3 */
html+=`<div class="wg" style="border-color:var(--sec-acc-d,var(--pri2))">
<div class="wg-header"><span class="wg-badge" style="background:var(--sec-acc-d,var(--pri2))">БОСС §3</span><div class="wg-title">Итоговые задачи</div></div>
<div class="wg-help">4 задачи — каждая верная даёт +5 XP.</div>
<div id="p3-boss-tasks"></div>
</div>`;
html+=`<div style="margin-top:18px;display:flex;justify-content:center">
<button class="btn primary" id="p3-read-btn" onclick="addXp(10,'p3-read');bumpProgress('p3',40);this.textContent='Прочитано!';this.disabled=true;">
<svg class="ic" viewBox="0 0 24 24"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/></svg>
Я прочитал §3 (+10 XP)
</button>
</div>`;
html+=secNav('p2','p4');
box.innerHTML=html;
if(window.renderMathInElement) setTimeout(()=>renderMath(box),0);
/* == INIT ИНТЕРАКТИВ 1: два треугольника == */
(function(){
const kSl=document.getElementById('p3-k-sl');
const kVal=document.getElementById('p3-k-val');
const svgWrap=document.getElementById('p3-sim-svg');
const infoEl=document.getElementById('p3-sim-info');
// базовый треугольник: A=(80,20), B=(20,120), C=(160,120)
const Ax=80,Ay=20,Bx=20,By=120,Cx=160,Cy=120;
const a=Math.hypot(Cx-Bx,Cy-By); // BC
const b=Math.hypot(Ax-Cx,Ay-Cy); // CA
const c=Math.hypot(Bx-Ax,By-Ay); // AB
function draw(){
const k=+kSl.value/10;
kVal.textContent=k.toFixed(1);
// второй треугольник масштабируем от центра C' = (240, 120)
const ox=240, oy=120;
const Ax2=ox+(Ax-Cx)/k, Ay2=oy+(Ay-Cy)/k;
const Bx2=ox+(Bx-Cx)/k, By2=oy+(By-Cy)/k;
const Cx2=ox, Cy2=oy;
const W=380, H=160;
let s=`<svg viewBox="0 0 ${W} ${H}" style="max-width:${W}px;width:100%;background:#fafafa;border:1px solid var(--border);border-radius:10px">`;
// большой треугольник
s+=`<polygon points="${Ax},${Ay} ${Bx},${By} ${Cx},${Cy}" fill="rgba(124,58,237,.12)" stroke="#7c3aed" stroke-width="2"/>`;
s+=`<text x="${Ax}" y="${Ay-6}" text-anchor="middle" font-size="11" fill="#6d28d9" font-weight="700">A</text>`;
s+=`<text x="${Bx-10}" y="${By+4}" font-size="11" fill="#6d28d9" font-weight="700">B</text>`;
s+=`<text x="${Cx+4}" y="${Cy+4}" font-size="11" fill="#6d28d9" font-weight="700">C</text>`;
// подписи сторон
s+=`<text x="${(Bx+Cx)/2}" y="${By+14}" text-anchor="middle" font-size="9" fill="#6d28d9">a=${fmt(a/10)}</text>`;
s+=`<text x="${(Ax+Bx)/2-10}" y="${(Ay+By)/2}" text-anchor="end" font-size="9" fill="#6d28d9">c=${fmt(c/10)}</text>`;
s+=`<text x="${(Ax+Cx)/2+4}" y="${(Ay+Cy)/2}" font-size="9" fill="#6d28d9">b=${fmt(b/10)}</text>`;
// второй треугольник
s+=`<polygon points="${Ax2},${Ay2} ${Bx2},${By2} ${Cx2},${Cy2}" fill="rgba(139,92,246,.15)" stroke="#8b5cf6" stroke-width="1.8"/>`;
s+=`<text x="${Ax2}" y="${Ay2-6}" text-anchor="middle" font-size="10" fill="#8b5cf6" font-weight="700">A'</text>`;
s+=`<text x="${Bx2-12}" y="${By2+4}" font-size="10" fill="#8b5cf6" font-weight="700">B'</text>`;
s+=`<text x="${Cx2+4}" y="${Cy2+4}" font-size="10" fill="#8b5cf6" font-weight="700">C'</text>`;
// подписи сторон 2
const a2=a/k,b2=b/k,c2=c/k;
s+=`<text x="${(Bx2+Cx2)/2}" y="${By2+14}" text-anchor="middle" font-size="9" fill="#8b5cf6">a'=${fmt(a2/10)}</text>`;
// k-label
s+=`<text x="190" y="15" text-anchor="middle" font-size="11" fill="#6d28d9" font-weight="800">k = ${k.toFixed(1)}</text>`;
s+='</svg>';
svgWrap.innerHTML=s;
infoEl.innerHTML=`$k=${k.toFixed(1)}$: $a/a'=${fmt(a/a*k/k)} \\to a'=${fmt(a/10/k)}$, $b'=${fmt(b/10/k)}$, $c'=${fmt(c/10/k)}$. Углы всегда равны: $\\angle A=\\angle A', \\angle B=\\angle B', \\angle C=\\angle C'$.`;
renderMath(infoEl);
addXp(1,'p3-sim');
}
kSl.addEventListener('input',draw);
draw();
})();
/* == INIT ИНТЕРАКТИВ 2: калькулятор == */
(function(){
document.getElementById('p3-ccalc').addEventListener('click',()=>{
const a=parseFloat(document.getElementById('p3-ca').value);
const b=parseFloat(document.getElementById('p3-cb').value);
const c=parseFloat(document.getElementById('p3-cc').value);
const k=parseFloat(document.getElementById('p3-ck').value);
const out=document.getElementById('p3-ccalc-out');
if([a,b,c,k].some(v=>!isFinite(v)||v<=0)){
out.style.display='block';out.innerHTML='<span style="color:var(--bad)">Введи положительные числа для a, b, c, k.</span>';return;
}
out.style.display='block';
out.innerHTML=`Стороны подобного треугольника при $k=${fmt(k)}$:<br>$a'=a/k=${fmt(a/k)}$, $b'=b/k=${fmt(b/k)}$, $c'=c/k=${fmt(c/k)}$`;
renderMath(out);
addXp(2,'p3-calc');bumpProgress('p3',5);
});
})();
/* == INIT ИНТЕРАКТИВ 3: DnD == */
(function(){
const items=[
{text:'(3,4,5) и (6,8,10)',yes:true},
{text:'(5,7,9) и (10,15,18)',yes:false},
{text:'(2,3,4) и (4,6,8)',yes:true},
{text:'(1,2,3) и (2,4,7)',yes:false},
{text:'(6,8,10) и (3,4,5)',yes:true},
];
const pool=document.getElementById('p3-dnd-pool');
const yesBox=document.getElementById('p3-drop-yes-items');
const noBox=document.getElementById('p3-drop-no-items');
let dragging=null;
function makeChip(it,idx){
const chip=document.createElement('div');
chip.className='dnd-chip';
chip.dataset.idx=idx;
chip.textContent=it.text;
chip.draggable=true;
chip.addEventListener('dragstart',e=>{dragging=chip;chip.classList.add('dragging');e.dataTransfer.effectAllowed='move';});
chip.addEventListener('dragend',()=>{chip.classList.remove('dragging');dragging=null;});
return chip;
}
items.forEach((it,i)=>pool.appendChild(makeChip(it,i)));
[document.getElementById('p3-drop-yes'),document.getElementById('p3-drop-no'),pool].forEach(box=>{
box.addEventListener('dragover',e=>{e.preventDefault();box.classList.add('over');});
box.addEventListener('dragleave',()=>box.classList.remove('over'));
box.addEventListener('drop',e=>{
e.preventDefault();box.classList.remove('over');
if(!dragging)return;
const target=box===document.getElementById('p3-drop-yes')?yesBox:box===document.getElementById('p3-drop-no')?noBox:pool;
target.appendChild(dragging);
});
});
document.getElementById('p3-dnd-check').addEventListener('click',()=>{
const fb=document.getElementById('p3-dnd-fb');
const yChips=[...yesBox.querySelectorAll('.dnd-chip')];
const nChips=[...noBox.querySelectorAll('.dnd-chip')];
if(yChips.length+nChips.length<items.length){feedback(fb,false,'Разложи все карточки.');return;}
let ok=true;
yChips.forEach(c=>{if(!items[+c.dataset.idx].yes)ok=false;});
nChips.forEach(c=>{if(items[+c.dataset.idx].yes)ok=false;});
if(ok){feedback(fb,true,'Верно! +5 XP');addXp(5,'p3-dnd');bumpProgress('p3',8);}
else{feedback(fb,false,'Есть ошибки — проверь пропорциональность сторон.');}
});
document.getElementById('p3-dnd-reset').addEventListener('click',()=>{
[...yesBox.children].forEach(c=>pool.appendChild(c));
[...noBox.children].forEach(c=>pool.appendChild(c));
document.getElementById('p3-dnd-fb').style.display='none';
});
})();
/* == INIT ИНТЕРАКТИВ 4: тренажёр == */
(function(){
const tasks=[
{q:'$\\triangle ABC$ со сторонами $6,8,10$ подобен $\\triangle A\'B\'C\'$ со сторонами $3,4,5$. Чему равен коэффициент подобия?', ans:2, hint:'k = 6/3 = 8/4 = 10/5 = 2.'},
{q:'$\\triangle ABC \\sim \\triangle A\'B\'C\'$, коэффициент $k=3$. Сторона $a=15$. Найди $a\'$.', ans:5, hint:'a\' = a/k = 15/3 = 5.'},
{q:'$\\triangle ABC \\sim \\triangle A\'B\'C\'$, $k=2$. Сторона $b\'=7$. Найди $b$.', ans:14, hint:'b = k·b\' = 2·7 = 14.'},
{q:'Стороны треугольников $4,6,8$ и $6,9,12$. Найди коэффициент подобия.', ans:1.5, hint:'k = 6/4 = 9/6 = 12/8 = 1.5.'},
{q:'$\\triangle ABC \\sim \\triangle A\'B\'C\'$, $a=20$, $a\'=4$. Чему равен $k$?', ans:5, hint:'k = a/a\' = 20/4 = 5.'},
];
let idx=0,score=0;
function show(){
document.getElementById('p3-tr-i').textContent=idx+1;
const t=document.getElementById('p3-tr-task');
t.innerHTML=tasks[idx].q;
renderMath(t);
document.getElementById('p3-tr-ans').value='';
document.getElementById('p3-tr-fb').style.display='none';
}
document.getElementById('p3-tr-start').addEventListener('click',()=>{idx=0;score=0;document.getElementById('p3-tr-score').textContent=0;show();});
document.getElementById('p3-tr-go').addEventListener('click',()=>{
if(idx>=tasks.length)return;
const ans=+document.getElementById('p3-tr-ans').value;
const fb=document.getElementById('p3-tr-fb');
if(Math.abs(ans-tasks[idx].ans)<0.05){
score++;document.getElementById('p3-tr-score').textContent=score;
addXp(3,'p3-tr-'+idx);bumpProgress('p3',4);
if(idx<tasks.length-1){feedback(fb,true,'Верно! +3 XP');idx++;setTimeout(()=>show(),900);}
else{feedback(fb,true,'Все задачи решены! +5 XP');addXp(5,'p3-tr-all');bumpProgress('p3',10);confetti();}
} else {
feedback(fb,false,'Неверно. '+tasks[idx].hint);
}
});
document.getElementById('p3-tr-ans').addEventListener('keydown',e=>{if(e.key==='Enter')document.getElementById('p3-tr-go').click();});
show();
})();
/* == INIT ИНТЕРАКТИВ 5: мини-квиз == */
(function(){
const qs=[
{q:'Коэффициент подобия равен 1. Что это означает?', opts:['Треугольники конгруэнтны','Треугольники не подобны','Треугольники равновелики по площади','Треугольники прямоугольные'], ans:0},
{q:'Если $\\triangle ABC \\sim \\triangle A\'B\'C\'$ с $k=3$, то $\\triangle A\'B\'C\' \\sim \\triangle ABC$ с коэффициентом:', opts:['3','1/3','9','1/9'], ans:1},
{q:'Что является достаточным условием подобия треугольников?', opts:['Равенство двух углов','Равенство одной стороны','Равенство периметров','Равенство площадей'], ans:0},
{q:'Подобие — это:', opts:['Отношение эквивалентности','Только рефлексивное отношение','Только транзитивное отношение','Отношение порядка'], ans:0},
];
const body=document.getElementById('p3-quiz-body');
body.innerHTML=qs.map((q,qi)=>`
<div style="margin-bottom:14px;padding:12px;background:var(--card);border-radius:10px;border:1px solid var(--border)">
<div style="font-weight:700;margin-bottom:8px;font-size:.95rem">${qi+1}. ${q.q}</div>
${q.opts.map((o,oi)=>`<label style="display:flex;align-items:center;gap:8px;margin-bottom:6px;cursor:pointer;font-size:.92rem"><input type="radio" name="p3q${qi}" value="${oi}" style="accent-color:var(--sec-acc,var(--pri))"> ${o}</label>`).join('')}
</div>`).join('');
document.getElementById('p3-quiz-check').addEventListener('click',()=>{
const fb=document.getElementById('p3-quiz-fb');
let correct=0;
qs.forEach((q,qi)=>{
const sel=document.querySelector(`input[name="p3q${qi}"]:checked`);
if(sel&&+sel.value===q.ans)correct++;
});
if(correct===qs.length){
feedback(fb,true,`Все ${qs.length} верно! +10 XP`);
addXp(10,'p3-quiz');bumpProgress('p3',10);confetti();
} else {
feedback(fb,false,`Верно ${correct} из ${qs.length}. Перечитай карточки теории.`);
}
});
})();
/* == INIT: Босс §3 == */
(function(){
const tasks=[
{q:'$\\triangle ABC$ со сторонами $9,12,15$. Коэффициент подобия с $\\triangle A\'B\'C\'$ равен $3$. Найди наименьшую сторону $\\triangle A\'B\'C\'$.', ans:3, hint:'a\' = 9/3 = 3.'},
{q:'$\\triangle ABC \\sim \\triangle A\'B\'C\'$. Стороны $\\triangle A\'B\'C\'$: $5,7,x$, стороны $\\triangle ABC$: $10,14,16$. Найди $x$.', ans:8, hint:'k=2, x = 16/2 = 8.'},
{q:'Периметр $\\triangle ABC = 36$, $k=3$. Найди периметр подобного треугольника $\\triangle A\'B\'C\'$.', ans:12, hint:'P\' = P/k = 36/3 = 12.'},
{q:'$\\triangle ABC \\sim \\triangle A\'B\'C\'$, $k=4$. Сторона $c=20$. Найди $c\'$.', ans:5, hint:'c\' = c/k = 20/4 = 5.'},
];
const bossBox=document.getElementById('p3-boss-tasks');
bossBox.innerHTML=tasks.map((t,i)=>`
<div style="padding:14px;background:var(--card);border-radius:10px;border:1px solid var(--border);margin-bottom:10px">
<div style="margin-bottom:8px;font-size:.95rem">${t.q}</div>
<div style="display:flex;gap:8px;flex-wrap:wrap;align-items:center">
<input type="number" class="tinp" id="p3b-a${i}" placeholder="Ответ" style="width:110px">
<button class="btn primary small" onclick="(function(){
const v=+document.getElementById('p3b-a${i}').value;
const fb=document.getElementById('p3b-fb${i}');
if(Math.abs(v-${t.ans})<0.05){
feedback(fb,true,'Верно! +5 XP');
if(!window.p3BossSolved.has(${i})){ window.p3BossSolved.add(${i}); addXp(5,'p3-boss${i}'); bumpProgress('p3',8); }
} else feedback(fb,false,'Неверно. ${t.hint}');
})()">Проверить</button>
</div>
<div class="feedback" id="p3b-fb${i}" style="display:none;margin-top:8px"></div>
</div>`).join('');
window.p3BossSolved=new Set();
renderMath(bossBox);
})();
}
function buildP4(){
const box=document.getElementById('p4-body');
let html='';
/* ---- Theory cards ---- */
html+=makeCard('theory','Теорема о прямой, параллельной стороне треугольника','4.1',`
<p><b>Теорема.</b> Прямая, параллельная одной из сторон треугольника и пересекающая две другие стороны, отсекает треугольник, подобный исходному.</p>
<p style="margin-top:8px"><b>Формально:</b> в $\\triangle ABC$ прямая $MN \\parallel BC$ пересекает $AB$ в точке $M$ и $AC$ в точке $N$. Тогда $\\triangle AMN \\sim \\triangle ABC$ с коэффициентом подобия:</p>
$$k = \\dfrac{AM}{AB} = \\dfrac{AN}{AC} = \\dfrac{MN}{BC}$$
<div style="display:flex;justify-content:center;margin-top:14px">
<svg viewBox="0 0 280 175" style="max-width:300px;background:#fafafa;border:1px solid var(--border);border-radius:10px">
<!-- triangle ABC -->
<polygon points="140,15 30,155 250,155" fill="rgba(99,102,241,.10)" stroke="#6366f1" stroke-width="2"/>
<!-- MN line at t=0.45 -->
<!-- M on AB: M = A + 0.45*(B-A) = (140+0.45*(30-140), 15+0.45*(155-15)) = (89.5, 78) -->
<!-- N on AC: N = A + 0.45*(C-A) = (140+0.45*(250-140), 15+0.45*(155-15)) = (189.5, 78) -->
<polygon points="140,15 89.5,78 189.5,78" fill="rgba(99,102,241,.22)" stroke="#4f46e5" stroke-width="2"/>
<line x1="72" y1="78" x2="210" y2="78" stroke="#4f46e5" stroke-width="1.8" stroke-dasharray="5,3"/>
<!-- labels -->
<text x="140" y="10" text-anchor="middle" font-size="11" font-weight="700" fill="#4338ca">A</text>
<text x="22" y="165" font-size="11" font-weight="700" fill="#4338ca">B</text>
<text x="253" y="165" font-size="11" font-weight="700" fill="#4338ca">C</text>
<text x="82" y="76" text-anchor="end" font-size="10" font-weight="700" fill="#4f46e5">M</text>
<text x="196" y="76" font-size="10" font-weight="700" fill="#4f46e5">N</text>
<text x="140" y="95" text-anchor="middle" font-size="9" fill="#4f46e5">MN ∥ BC</text>
<text x="140" y="170" text-anchor="middle" font-size="9" fill="#4338ca" font-style="italic">△AMN △ABC</text>
<!-- k label -->
<text x="265" y="30" font-size="10" fill="#4f46e5" font-weight="700">k=AM/AB</text>
</svg>
</div>`);
html+=makeCard('rule','Следствие — теорема Фалеса для треугольника','4.2',`
<p><b>Следствие.</b> Если $MN \\parallel BC$ в $\\triangle ABC$, то:</p>
$$\\dfrac{AM}{MB} = \\dfrac{AN}{NC}$$
<p style="margin-top:8px">То есть прямая, параллельная стороне треугольника, делит две другие стороны пропорционально.</p>
<p style="margin-top:8px">Это прямое следствие обобщённой теоремы Фалеса: прямые $BC$, $MN$ и $A$ порождают пропорциональное деление сторон $AB$ и $AC$.</p>
<div style="display:flex;justify-content:center;margin-top:12px">
<svg viewBox="0 0 280 155" style="max-width:300px;background:#fafafa;border:1px solid var(--border);border-radius:10px">
<polygon points="140,12 30,140 250,140" fill="rgba(99,102,241,.08)" stroke="#6366f1" stroke-width="2"/>
<!-- MN at t=0.5 -->
<line x1="85" y1="76" x2="195" y2="76" stroke="#4f46e5" stroke-width="2"/>
<circle cx="85" cy="76" r="3.5" fill="#4f46e5"/>
<circle cx="195" cy="76" r="3.5" fill="#4f46e5"/>
<text x="140" y="8" text-anchor="middle" font-size="11" font-weight="700" fill="#4338ca">A</text>
<text x="22" y="150" font-size="11" font-weight="700" fill="#4338ca">B</text>
<text x="253" y="150" font-size="11" font-weight="700" fill="#4338ca">C</text>
<text x="78" y="74" text-anchor="end" font-size="10" font-weight="700" fill="#4f46e5">M</text>
<text x="200" y="74" font-size="10" font-weight="700" fill="#4f46e5">N</text>
<!-- AM, MB labels -->
<text x="62" y="44" text-anchor="middle" font-size="9" fill="#4f46e5">AM</text>
<text x="56" y="112" text-anchor="middle" font-size="9" fill="#6366f1">MB</text>
<!-- AN, NC labels -->
<text x="221" y="44" text-anchor="middle" font-size="9" fill="#4f46e5">AN</text>
<text x="228" y="112" text-anchor="middle" font-size="9" fill="#6366f1">NC</text>
<text x="140" y="148" text-anchor="middle" font-size="9" fill="#4338ca" font-style="italic">AM/MB = AN/NC</text>
</svg>
</div>`);
html+=makeCard('example','Пример вычисления','4.3',`
<p><b>Пример.</b> В $\\triangle ABC$ прямая $MN \\parallel BC$. $AM = 6$, $AB = 10$, $BC = 15$. Найти $MN$.</p>
<p style="margin-top:8px"><b>Решение:</b> коэффициент подобия $k = AM/AB = 6/10 = 0{,}6$.</p>
<p style="margin-top:4px">$MN = k \\cdot BC = 0{,}6 \\cdot 15 = 9$.</p>
<p style="margin-top:8px"><b>Пример 2.</b> $AM = 4$, $MB = 6$. Найти $AN/NC$.</p>
<p style="margin-top:4px">По следствию: $AN/NC = AM/MB = 4/6 = 2/3$.</p>`);
/* ---- ИНТЕРАКТИВ 1: SVG треугольник со slider ---- */
html+=`<div class="wg" id="p4-par-wg">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 1</span><div class="wg-title">Параллельная прямая отсекает подобный треугольник</div></div>
<div class="wg-help">Перемещай прямую $MN \\parallel BC$ по высоте треугольника. Коэффициент подобия $k$ меняется — $\\triangle AMN \\sim \\triangle ABC$.</div>
<div class="sliders">
<label>Положение $MN$ (t = AM/AB): <b id="p4-t-val">0.50</b>
<input type="range" min="10" max="90" value="50" id="p4-t-sl" step="1">
</label>
</div>
<div id="p4-par-svg" style="display:flex;justify-content:center"></div>
<div id="p4-par-info" style="margin-top:10px;padding:10px 14px;background:var(--sec-acc-soft,var(--pri-soft));border-radius:10px;font-size:.92rem;line-height:1.8"></div>
</div>`;
/* ---- ИНТЕРАКТИВ 2: Пошаговое доказательство ---- */
html+=`<div class="wg" id="p4-proof-wg">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 2</span><div class="wg-title">Доказательство — по шагам</div></div>
<div class="wg-help">Нажимай «Далее» — каждый шаг раскрывает ключевую идею доказательства.</div>
<div id="p4-proof-svg" style="display:flex;justify-content:center;margin-bottom:10px"></div>
<div id="p4-proof-desc" style="padding:10px 14px;background:var(--sec-acc-soft,var(--pri-soft));border-radius:10px;font-size:.95rem;line-height:1.6;margin-bottom:10px;min-height:60px"></div>
<div style="display:flex;gap:8px">
<button class="btn primary" id="p4-proof-next">Далее</button>
<button class="btn" id="p4-proof-reset">Сначала</button>
</div>
</div>`;
/* ---- ИНТЕРАКТИВ 3: Калькулятор ---- */
html+=`<div class="wg">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 3</span><div class="wg-title">Калькулятор: параллельная сторона</div></div>
<div class="wg-help">Введи $AM$, $AB$, $BC$ → найди $MN = BC \\cdot AM/AB$. Или задай $MN$, $BC$ → найди $AM/AB$.</div>
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(80px,1fr));gap:8px;margin-bottom:10px">
<div><span style="font-size:.8rem;color:var(--muted);display:block">AM</span><input type="number" id="p4-cAM" class="tinp" placeholder="AM" style="width:100%"></div>
<div><span style="font-size:.8rem;color:var(--muted);display:block">AB</span><input type="number" id="p4-cAB" class="tinp" placeholder="AB" style="width:100%"></div>
<div><span style="font-size:.8rem;color:var(--muted);display:block">BC</span><input type="number" id="p4-cBC" class="tinp" placeholder="BC" style="width:100%"></div>
<div style="display:flex;align-items:flex-end"><button class="btn primary" id="p4-ccalc" style="width:100%">Вычислить MN</button></div>
</div>
<div id="p4-ccalc-out" style="display:none;padding:10px 14px;background:var(--sec-acc-soft,var(--pri-soft));border-radius:10px;font-size:.95rem"></div>
</div>`;
/* ---- ИНТЕРАКТИВ 4: Тренажёр ---- */
html+=`<div class="wg">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 4</span><div class="wg-title">Тренажёр §4</div></div>
<div class="wg-help">5 задач на нахождение MN, AN, AM и отношений.</div>
<div class="score-display"><span>Задача <b id="p4-tr-i">1</b> / 5</span><span>Очки: <b id="p4-tr-score">0</b></span></div>
<div id="p4-tr-task" style="padding:14px;background:var(--sec-acc-soft,var(--pri-soft));border-radius:10px;font-size:1.02rem;margin-bottom:10px"></div>
<div style="display:flex;gap:8px;align-items:center;flex-wrap:wrap">
<input type="number" id="p4-tr-ans" class="tinp" placeholder="Ответ" style="width:120px">
<button class="btn primary" id="p4-tr-go">Проверить</button>
<button class="btn" id="p4-tr-start">Начать</button>
</div>
<div class="feedback" id="p4-tr-fb" style="display:none"></div>
</div>`;
/* ---- ИНТЕРАКТИВ 5: DnD-сортер ---- */
html+=`<div class="wg">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 5</span><div class="wg-title">Соотнеси параллельные прямые и пропорции</div></div>
<div class="wg-help">Перетащи каждую карточку: «Пропорция верна» или «Пропорция неверна».</div>
<div id="p4-dnd-pool" class="dnd-pool"></div>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-top:10px">
<div class="drop-box" id="p4-drop-yes"><h5>Пропорция верна</h5><div class="drop-items" id="p4-drop-yes-items"></div></div>
<div class="drop-box" id="p4-drop-no"><h5>Пропорция неверна</h5><div class="drop-items" id="p4-drop-no-items"></div></div>
</div>
<div class="actions"><button class="btn primary" id="p4-dnd-check">Проверить</button><button class="btn" id="p4-dnd-reset">Сбросить</button></div>
<div class="feedback" id="p4-dnd-fb" style="display:none"></div>
</div>`;
/* ---- ИНТЕРАКТИВ 6: Босс §4 ---- */
html+=`<div class="wg" style="border-color:var(--sec-acc-d,var(--pri2))">
<div class="wg-header"><span class="wg-badge" style="background:var(--sec-acc-d,var(--pri2))">БОСС §4</span><div class="wg-title">Итоговые задачи</div></div>
<div class="wg-help">4 задачи — каждая верная даёт +5 XP.</div>
<div id="p4-boss-tasks"></div>
</div>`;
html+=`<div style="margin-top:18px;display:flex;justify-content:center">
<button class="btn primary" id="p4-read-btn" onclick="addXp(10,'p4-read');bumpProgress('p4',40);this.textContent='Прочитано!';this.disabled=true;">
<svg class="ic" viewBox="0 0 24 24"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/></svg>
Я прочитал §4 (+10 XP)
</button>
</div>`;
html+=secNav('p3','p5');
box.innerHTML=html;
if(window.renderMathInElement) setTimeout(()=>renderMath(box),0);
/* == INIT ИНТЕРАКТИВ 1: slider параллельной прямой == */
(function(){
const tSl=document.getElementById('p4-t-sl');
const tVal=document.getElementById('p4-t-val');
const svgWrap=document.getElementById('p4-par-svg');
const infoEl=document.getElementById('p4-par-info');
// base triangle: A=(140,15), B=(30,155), C=(250,155)
const Ax=140,Ay=15,Bx=30,By=155,Cx=250,Cy=155;
const BC=Math.hypot(Cx-Bx,Cy-By);
const AB=Math.hypot(Bx-Ax,By-Ay);
const AC=Math.hypot(Cx-Ax,Cy-Ay);
function draw(){
const t=+tSl.value/100;
tVal.textContent=t.toFixed(2);
const Mx=Ax+t*(Bx-Ax), My=Ay+t*(By-Ay);
const Nx=Ax+t*(Cx-Ax), Ny=Ay+t*(Cy-Ay);
const MN=Math.hypot(Nx-Mx,Ny-My);
const AM=Math.hypot(Mx-Ax,My-Ay);
const AN=Math.hypot(Nx-Ax,Ny-Ay);
const W=300, H=180;
let s=`<svg viewBox="0 0 ${W} ${H}" style="max-width:${W}px;width:100%;background:#fafafa;border:1px solid var(--border);border-radius:10px">`;
// full triangle light
s+=`<polygon points="${Ax},${Ay} ${Bx},${By} ${Cx},${Cy}" fill="rgba(99,102,241,.07)" stroke="#6366f1" stroke-width="1.5"/>`;
// inner triangle AMN highlighted
s+=`<polygon points="${Ax},${Ay} ${Mx},${My} ${Nx},${Ny}" fill="rgba(79,70,229,.22)" stroke="#4f46e5" stroke-width="2"/>`;
// MN line
s+=`<line x1="${Mx}" y1="${My}" x2="${Nx}" y2="${Ny}" stroke="#4f46e5" stroke-width="2"/>`;
// points
s+=`<circle cx="${Mx}" cy="${My}" r="4" fill="#4f46e5"/>`;
s+=`<circle cx="${Nx}" cy="${Ny}" r="4" fill="#4f46e5"/>`;
// labels
s+=`<text x="${Ax}" y="${Ay-5}" text-anchor="middle" font-size="11" font-weight="700" fill="#4338ca">A</text>`;
s+=`<text x="${Bx-8}" y="${By+2}" font-size="11" font-weight="700" fill="#4338ca">B</text>`;
s+=`<text x="${Cx+4}" y="${Cy+2}" font-size="11" font-weight="700" fill="#4338ca">C</text>`;
s+=`<text x="${Mx-8}" y="${My}" text-anchor="end" font-size="10" font-weight="700" fill="#4f46e5">M</text>`;
s+=`<text x="${Nx+4}" y="${Ny}" font-size="10" font-weight="700" fill="#4f46e5">N</text>`;
// k badge
s+=`<text x="${W/2}" y="14" text-anchor="middle" font-size="11" font-weight="800" fill="#4338ca">k = ${t.toFixed(2)}</text>`;
s+='</svg>';
svgWrap.innerHTML=s;
infoEl.innerHTML=`$k = AM/AB = ${t.toFixed(3)}$. $MN = k \\cdot BC = ${t.toFixed(3)} \\cdot ${fmt(BC/10)} = ${fmt(MN/10)}$. <br> $AM/MB = ${fmt(t/(1-t+1e-9))}$. По следствию: $AN/NC = AM/MB = ${fmt(t/(1-t+1e-9))}$.`;
renderMath(infoEl);
addXp(1,'p4-par');
}
tSl.addEventListener('input',draw);
draw();
})();
/* == INIT ИНТЕРАКТИВ 2: пошаговое доказательство == */
(function(){
const steps=[
{desc:'<b>Шаг 1.</b> Дан $\\triangle ABC$. Прямая $MN \\parallel BC$ пересекает $AB$ в $M$ и $AC$ в $N$. Требуется доказать $\\triangle AMN \\sim \\triangle ABC$.',
svg:`<svg viewBox="0 0 260 160" style="max-width:260px;background:#fafafa;border:1px solid var(--border);border-radius:10px"><polygon points="130,14 25,148 235,148" fill="rgba(99,102,241,.08)" stroke="#6366f1" stroke-width="2"/><line x1="78" y1="81" x2="182" y2="81" stroke="#4f46e5" stroke-width="2" stroke-dasharray="5,3"/><circle cx="78" cy="81" r="3.5" fill="#4f46e5"/><circle cx="182" cy="81" r="3.5" fill="#4f46e5"/><text x="130" y="10" text-anchor="middle" font-size="11" font-weight="700" fill="#4338ca">A</text><text x="17" y="157" font-size="11" font-weight="700" fill="#4338ca">B</text><text x="237" y="157" font-size="11" font-weight="700" fill="#4338ca">C</text><text x="70" y="79" text-anchor="end" font-size="10" font-weight="700" fill="#4f46e5">M</text><text x="186" y="79" font-size="10" font-weight="700" fill="#4f46e5">N</text><text x="130" y="97" text-anchor="middle" font-size="9" fill="#4f46e5">MN ∥ BC</text></svg>`},
{desc:'<b>Шаг 2.</b> $\\angle AMN = \\angle ABC$, так как $MN \\parallel BC$ и $AB$ — секущая: это соответственные углы при параллельных прямых и секущей.',
svg:`<svg viewBox="0 0 260 160" style="max-width:260px;background:#fafafa;border:1px solid var(--border);border-radius:10px"><polygon points="130,14 25,148 235,148" fill="rgba(99,102,241,.08)" stroke="#6366f1" stroke-width="2"/><line x1="78" y1="81" x2="182" y2="81" stroke="#4f46e5" stroke-width="2"/><circle cx="78" cy="81" r="3.5" fill="#4f46e5"/><circle cx="182" cy="81" r="3.5" fill="#4f46e5"/><text x="130" y="10" text-anchor="middle" font-size="11" font-weight="700" fill="#4338ca">A</text><text x="17" y="157" font-size="11" font-weight="700" fill="#4338ca">B</text><text x="237" y="157" font-size="11" font-weight="700" fill="#4338ca">C</text><text x="70" y="79" text-anchor="end" font-size="10" font-weight="700" fill="#4f46e5">M</text><text x="186" y="79" font-size="10" font-weight="700" fill="#4f46e5">N</text><path d="M78,81 Q88,88 83,95" fill="none" stroke="#f59e0b" stroke-width="2"/><path d="M25,148 Q38,138 33,128" fill="none" stroke="#f59e0b" stroke-width="2"/><text x="96" y="100" font-size="9" fill="#b45309" font-weight="700">∠AMN = ∠ABC</text></svg>`},
{desc:'<b>Шаг 3.</b> Аналогично $\\angle ANM = \\angle ACB$: $MN \\parallel BC$ и $AC$ — секущая, получаем соответственные углы.',
svg:`<svg viewBox="0 0 260 160" style="max-width:260px;background:#fafafa;border:1px solid var(--border);border-radius:10px"><polygon points="130,14 25,148 235,148" fill="rgba(99,102,241,.08)" stroke="#6366f1" stroke-width="2"/><line x1="78" y1="81" x2="182" y2="81" stroke="#4f46e5" stroke-width="2"/><circle cx="78" cy="81" r="3.5" fill="#4f46e5"/><circle cx="182" cy="81" r="3.5" fill="#4f46e5"/><text x="130" y="10" text-anchor="middle" font-size="11" font-weight="700" fill="#4338ca">A</text><text x="17" y="157" font-size="11" font-weight="700" fill="#4338ca">B</text><text x="237" y="157" font-size="11" font-weight="700" fill="#4338ca">C</text><text x="70" y="79" text-anchor="end" font-size="10" font-weight="700" fill="#4f46e5">M</text><text x="186" y="79" font-size="10" font-weight="700" fill="#4f46e5">N</text><path d="M182,81 Q172,88 177,95" fill="none" stroke="#10b981" stroke-width="2"/><path d="M235,148 Q222,138 227,128" fill="none" stroke="#10b981" stroke-width="2"/><text x="130" y="100" text-anchor="middle" font-size="9" fill="#047857" font-weight="700">∠ANM = ∠ACB</text></svg>`},
{desc:'<b>Шаг 4.</b> Угол $\\angle A$ общий у $\\triangle AMN$ и $\\triangle ABC$. Два угла $\\triangle AMN$ равны соответствующим двум углам $\\triangle ABC$ → по признаку ДД (два угла) $\\triangle AMN \\sim \\triangle ABC$.',
svg:`<svg viewBox="0 0 260 160" style="max-width:260px;background:#fafafa;border:1px solid var(--border);border-radius:10px"><polygon points="130,14 25,148 235,148" fill="rgba(99,102,241,.08)" stroke="#6366f1" stroke-width="1.5"/><polygon points="130,14 78,81 182,81" fill="rgba(79,70,229,.22)" stroke="#4f46e5" stroke-width="2"/><text x="130" y="10" text-anchor="middle" font-size="11" font-weight="700" fill="#4338ca">A</text><text x="17" y="157" font-size="11" font-weight="700" fill="#4338ca">B</text><text x="237" y="157" font-size="11" font-weight="700" fill="#4338ca">C</text><text x="70" y="79" text-anchor="end" font-size="10" font-weight="700" fill="#4f46e5">M</text><text x="186" y="79" font-size="10" font-weight="700" fill="#4f46e5">N</text><text x="130" y="95" text-anchor="middle" font-size="9" fill="#4f46e5">△AMN △ABC</text></svg>`},
{desc:'<b>Шаг 5.</b> Из подобия следует пропорциональность сторон: $AM/AB = AN/AC = MN/BC = k$. Следствие: $AM/MB = AN/NC$ — прямое следствие теоремы Фалеса. <b>Доказано.</b>',
svg:`<svg viewBox="0 0 260 80" style="max-width:260px;background:#fafafa;border:1px solid var(--border);border-radius:10px"><text x="130" y="24" text-anchor="middle" font-size="11" font-weight="800" fill="#4338ca">AM/AB = AN/AC = MN/BC = k</text><text x="130" y="46" text-anchor="middle" font-size="10" fill="#4f46e5" font-weight="700">AM/MB = AN/NC</text><text x="130" y="68" text-anchor="middle" font-size="10" fill="#10b981" font-weight="800">QED ∎</text></svg>`},
];
let step=0;
const svgEl=document.getElementById('p4-proof-svg');
const descEl=document.getElementById('p4-proof-desc');
function show(){
svgEl.innerHTML=steps[step].svg;
descEl.innerHTML=steps[step].desc;
renderMath(descEl);
}
document.getElementById('p4-proof-next').addEventListener('click',()=>{
if(step<steps.length-1){step++;show();addXp(1,'p4-proof-step');}
else{addXp(5,'p4-proof-done');bumpProgress('p4',10);}
});
document.getElementById('p4-proof-reset').addEventListener('click',()=>{step=0;show();});
show();
})();
/* == INIT ИНТЕРАКТИВ 3: калькулятор == */
(function(){
document.getElementById('p4-ccalc').addEventListener('click',()=>{
const AM=parseFloat(document.getElementById('p4-cAM').value);
const AB=parseFloat(document.getElementById('p4-cAB').value);
const BC=parseFloat(document.getElementById('p4-cBC').value);
const out=document.getElementById('p4-ccalc-out');
if(!isFinite(AM)||!isFinite(AB)||!isFinite(BC)||AM<=0||AB<=0||BC<=0||AM>AB){
out.style.display='block';out.innerHTML='<span style="color:var(--bad)">Введи положительные числа; AM должно быть ≤ AB.</span>';return;
}
const k=AM/AB;
const MN=k*BC;
const AN_over_NC=AM/(AB-AM);
out.style.display='block';
out.innerHTML=`$k = AM/AB = ${fmt(AM)}/${fmt(AB)} = ${fmt(k)}$<br>$MN = k \\cdot BC = ${fmt(k)} \\cdot ${fmt(BC)} = ${fmt(MN)}$<br>Следствие: $AM/MB = AN/NC = ${fmt(AM)}/${fmt(AB-AM)} = ${fmt(AN_over_NC)}$`;
renderMath(out);
addXp(2,'p4-calc');bumpProgress('p4',5);
});
})();
/* == INIT ИНТЕРАКТИВ 4: тренажёр == */
(function(){
const tasks=[
{q:'В $\\triangle ABC$ прямая $MN \\parallel BC$, $AM=4$, $AB=10$, $BC=20$. Найди $MN$.',ans:8,hint:'k=4/10=0.4; MN=0.4·20=8.'},
{q:'В $\\triangle ABC$ прямая $MN \\parallel BC$, $AM=6$, $AB=9$, $BC=12$. Найди $MN$.',ans:8,hint:'k=6/9=2/3; MN=2/3·12=8.'},
{q:'$MN \\parallel BC$, $AM=5$, $MB=10$. Найди $AN/NC$.',ans:0.5,hint:'AN/NC = AM/MB = 5/10 = 0.5.'},
{q:'$MN \\parallel BC$, $k=0.4$, $BC=30$. Найди $MN$.',ans:12,hint:'MN=k·BC=0.4·30=12.'},
{q:'$MN \\parallel BC$, $AM=3$, $MB=6$. Чему равно $AN/AC$?',ans:0.333,hint:'AN/AC = AM/AB = 3/(3+6) = 1/3 ≈ 0.333.'},
];
let idx=0,score=0;
function show(){
document.getElementById('p4-tr-i').textContent=idx+1;
const t=document.getElementById('p4-tr-task');
t.innerHTML=tasks[idx].q;
renderMath(t);
document.getElementById('p4-tr-ans').value='';
document.getElementById('p4-tr-fb').style.display='none';
}
document.getElementById('p4-tr-start').addEventListener('click',()=>{idx=0;score=0;document.getElementById('p4-tr-score').textContent=0;show();});
document.getElementById('p4-tr-go').addEventListener('click',()=>{
if(idx>=tasks.length)return;
const ans=+document.getElementById('p4-tr-ans').value;
const fb=document.getElementById('p4-tr-fb');
if(Math.abs(ans-tasks[idx].ans)<0.01){
score++;document.getElementById('p4-tr-score').textContent=score;
addXp(3,'p4-tr-'+idx);bumpProgress('p4',4);
if(idx<tasks.length-1){feedback(fb,true,'Верно! +3 XP');idx++;setTimeout(()=>show(),900);}
else{feedback(fb,true,'Все задачи решены! +5 XP');addXp(5,'p4-tr-all');bumpProgress('p4',10);confetti();}
} else {
feedback(fb,false,'Неверно. '+tasks[idx].hint);
}
});
document.getElementById('p4-tr-ans').addEventListener('keydown',e=>{if(e.key==='Enter')document.getElementById('p4-tr-go').click();});
show();
})();
/* == INIT ИНТЕРАКТИВ 5: DnD-сортер == */
(function(){
const items=[
{text:'MN∥BC, AM=3, AB=6, AN=4, AC=8 → AM/MB=AN/NC',yes:true},
{text:'MN∥BC, AM=4, MB=6, AN=3, NC=5 → AM/MB≠AN/NC',yes:false},
{text:'MN∥BC, AM/AB=0.5, MN/BC=0.5',yes:true},
{text:'MN∥BC, AM=2, MB=4, AN=3, NC=6 → AM/MB=AN/NC',yes:true},
{text:'MN∥BC, k=1/3, MN=BC/2',yes:false},
];
const pool=document.getElementById('p4-dnd-pool');
const yesBox=document.getElementById('p4-drop-yes-items');
const noBox=document.getElementById('p4-drop-no-items');
let dragging=null;
function makeChip(it,idx){
const chip=document.createElement('div');
chip.className='dnd-chip';
chip.dataset.idx=idx;
chip.textContent=it.text;
chip.draggable=true;
chip.addEventListener('dragstart',e=>{dragging=chip;chip.classList.add('dragging');e.dataTransfer.effectAllowed='move';});
chip.addEventListener('dragend',()=>{chip.classList.remove('dragging');dragging=null;});
return chip;
}
items.forEach((it,i)=>pool.appendChild(makeChip(it,i)));
[document.getElementById('p4-drop-yes'),document.getElementById('p4-drop-no'),pool].forEach(box=>{
box.addEventListener('dragover',e=>{e.preventDefault();box.classList.add('over');});
box.addEventListener('dragleave',()=>box.classList.remove('over'));
box.addEventListener('drop',e=>{
e.preventDefault();box.classList.remove('over');
if(!dragging)return;
const target=box===document.getElementById('p4-drop-yes')?yesBox:box===document.getElementById('p4-drop-no')?noBox:pool;
target.appendChild(dragging);
});
});
document.getElementById('p4-dnd-check').addEventListener('click',()=>{
const fb=document.getElementById('p4-dnd-fb');
const yChips=[...yesBox.querySelectorAll('.dnd-chip')];
const nChips=[...noBox.querySelectorAll('.dnd-chip')];
if(yChips.length+nChips.length<items.length){feedback(fb,false,'Разложи все карточки.');return;}
let ok=true;
yChips.forEach(c=>{if(!items[+c.dataset.idx].yes)ok=false;});
nChips.forEach(c=>{if(items[+c.dataset.idx].yes)ok=false;});
if(ok){feedback(fb,true,'Верно! +5 XP');addXp(5,'p4-dnd');bumpProgress('p4',8);}
else{feedback(fb,false,'Есть ошибки. Проверь: MN∥BC → AM/MB=AN/NC и MN/BC=AM/AB.');}
});
document.getElementById('p4-dnd-reset').addEventListener('click',()=>{
[...yesBox.children].forEach(c=>pool.appendChild(c));
[...noBox.children].forEach(c=>pool.appendChild(c));
document.getElementById('p4-dnd-fb').style.display='none';
});
})();
/* == INIT: Босс §4 == */
(function(){
const tasks=[
{q:'<svg viewBox="0 0 240 140" style="display:block;max-width:240px;margin:0 auto 8px;background:#e0e7ff;border:1px solid #a5b4fc;border-radius:8px"><polygon points="120,12 20,128 220,128" fill="rgba(99,102,241,.12)" stroke="#6366f1" stroke-width="2"/><line x1="70" y1="70" x2="170" y2="70" stroke="#4f46e5" stroke-width="2"/><text x="120" y="8" text-anchor="middle" font-size="10" fill="#4338ca" font-weight="700">A</text><text x="12" y="136" font-size="10" fill="#4338ca" font-weight="700">B</text><text x="222" y="136" font-size="10" fill="#4338ca" font-weight="700">C</text><text x="62" y="68" text-anchor="end" font-size="10" fill="#4f46e5" font-weight="700">M</text><text x="174" y="68" font-size="10" fill="#4f46e5" font-weight="700">N</text><text x="120" y="90" text-anchor="middle" font-size="9" fill="#4f46e5">AM=5, AB=8, BC=24</text></svg>$MN \\parallel BC$. $AM=5$, $AB=8$, $BC=24$. Найди $MN$.',ans:15,hint:'k=5/8; MN=5/8·24=15.'},
{q:'$MN \\parallel BC$, $AM=6$, $MB=9$. Найди $AN/NC$.',ans:0.667,hint:'AN/NC = AM/MB = 6/9 = 2/3 ≈ 0.667.'},
{q:'$MN \\parallel BC$, $MN=8$, $BC=12$. Найди $AM/AB$.',ans:0.667,hint:'AM/AB = MN/BC = 8/12 = 2/3 ≈ 0.667.'},
{q:'В $\\triangle ABC$ прямая $MN \\parallel BC$, $AM=3$, $AB=9$, $BC=18$. Найди $MN$.',ans:6,hint:'k=3/9=1/3; MN=1/3·18=6.'},
];
const bossBox=document.getElementById('p4-boss-tasks');
bossBox.innerHTML=tasks.map((t,i)=>`
<div style="padding:14px;background:var(--card);border-radius:10px;border:1px solid var(--border);margin-bottom:10px">
<div style="margin-bottom:8px;font-size:.95rem">${t.q}</div>
<div style="display:flex;gap:8px;flex-wrap:wrap;align-items:center">
<input type="number" class="tinp" id="p4b-a${i}" placeholder="Ответ" style="width:110px">
<button class="btn primary small" onclick="(function(){
const v=+document.getElementById('p4b-a${i}').value;
const fb=document.getElementById('p4b-fb${i}');
if(Math.abs(v-${t.ans})<0.01){
feedback(fb,true,'Верно! +5 XP');
if(!window.p4BossSolved.has(${i})){ window.p4BossSolved.add(${i}); addXp(5,'p4-boss${i}'); bumpProgress('p4',8); }
} else feedback(fb,false,'Неверно. ${t.hint}');
})()">Проверить</button>
</div>
<div class="feedback" id="p4b-fb${i}" style="display:none;margin-top:8px"></div>
</div>`).join('');
window.p4BossSolved=new Set();
renderMath(bossBox);
})();
}
function buildP5(){
const box=document.getElementById('p5-body');
let html='';
/* ---- Theory cards ---- */
html+=makeCard('theory','Первый признак подобия треугольников (ДД — два угла)','5.1',`
<p><b>Теорема (1-й признак подобия).</b> Если два угла одного треугольника соответственно равны двум углам другого треугольника, то такие треугольники подобны.</p>
<p style="margin-top:8px">Если $\\angle A = \\angle A'$ и $\\angle B = \\angle B'$, то $\\triangle ABC \\sim \\triangle A'B'C'$.</p>
<p style="margin-top:8px"><b>Почему достаточно двух углов?</b> Сумма углов треугольника равна $180°$. Если два угла равны, третий автоматически тоже равен: $\\angle C = 180° - \\angle A - \\angle B = 180° - \\angle A' - \\angle B' = \\angle C'$.</p>
<div style="display:flex;justify-content:center;margin-top:14px">
<svg viewBox="0 0 280 155" style="max-width:300px;background:#fafafa;border:1px solid var(--border);border-radius:10px">
<!-- большой треугольник ABC -->
<polygon points="50,140 180,140 100,30" fill="rgba(79,70,229,.11)" stroke="#4f46e5" stroke-width="2"/>
<text x="96" y="25" font-size="11" font-weight="700" fill="#4338ca">A</text>
<text x="40" y="150" font-size="11" font-weight="700" fill="#4338ca">B</text>
<text x="183" y="150" font-size="11" font-weight="700" fill="#4338ca">C</text>
<!-- угловые метки -->
<path d="M100,30 Q112,40 105,50" fill="none" stroke="#f59e0b" stroke-width="2"/>
<path d="M50,140 Q62,130 70,136" fill="none" stroke="#10b981" stroke-width="2"/>
<!-- маленький треугольник A'B'C' -->
<polygon points="200,140 264,140 230,76" fill="rgba(99,102,241,.15)" stroke="#6366f1" stroke-width="1.8"/>
<text x="227" y="70" font-size="10" font-weight="700" fill="#4f46e5">A'</text>
<text x="193" y="150" font-size="10" font-weight="700" fill="#4f46e5">B'</text>
<text x="266" y="150" font-size="10" font-weight="700" fill="#4f46e5">C'</text>
<!-- угловые метки -->
<path d="M230,76 Q237,84 232,91" fill="none" stroke="#f59e0b" stroke-width="1.5"/>
<path d="M200,140 Q210,132 215,136" fill="none" stroke="#10b981" stroke-width="1.5"/>
<text x="140" y="15" text-anchor="middle" font-size="10" fill="#4338ca">∠A=∠A', ∠B=∠B' → △ABC∼△A'B'C'</text>
</svg>
</div>`);
html+=makeCard('rule','Следствие: прямоугольные треугольники','5.2',`
<p><b>Следствие.</b> Два прямоугольных треугольника подобны, если у них равны острые углы (достаточно одной пары).</p>
<p style="margin-top:8px">Если $\\angle C = \\angle C' = 90°$ и $\\angle A = \\angle A'$, то $\\triangle ABC \\sim \\triangle A'B'C'$.</p>
<p style="margin-top:8px">Это потому, что прямой угол — один из двух равных углов, а второй угол задан условием.</p>
<div style="display:flex;justify-content:center;margin-top:12px">
<svg viewBox="0 0 280 130" style="max-width:300px;background:#fafafa;border:1px solid var(--border);border-radius:10px">
<!-- прямоугольный треугольник 1: A=(40,20), B=(40,110), C=(160,110) -->
<polygon points="40,20 40,110 160,110" fill="rgba(79,70,229,.10)" stroke="#4f46e5" stroke-width="2"/>
<!-- marker угла B (прямой) — inside polygon -->
<polyline points="40,100 50,100 50,110" fill="none" stroke="#4f46e5" stroke-width="1.5"/>
<text x="34" y="16" font-size="11" font-weight="700" fill="#4338ca">A</text>
<text x="28" y="120" font-size="11" font-weight="700" fill="#4338ca">B</text>
<text x="163" y="120" font-size="11" font-weight="700" fill="#4338ca">C</text>
<text x="36" y="116" font-size="8" fill="#4f46e5">90°</text>
<!-- прямоугольный треугольник 2: A'=(185,50), B'=(185,110), C'=(250,110) -->
<polygon points="185,50 185,110 250,110" fill="rgba(99,102,241,.15)" stroke="#6366f1" stroke-width="1.8"/>
<!-- marker прямого угла B' -->
<polyline points="185,100 195,100 195,110" fill="none" stroke="#6366f1" stroke-width="1.5"/>
<text x="178" y="46" font-size="10" font-weight="700" fill="#4f46e5">A'</text>
<text x="172" y="120" font-size="10" font-weight="700" fill="#4f46e5">B'</text>
<text x="253" y="120" font-size="10" font-weight="700" fill="#4f46e5">C'</text>
<text x="140" y="14" text-anchor="middle" font-size="9" fill="#4338ca">∠B=∠B'=90°, ∠A=∠A' → подобны</text>
</svg>
</div>`);
html+=makeCard('example','Пример применения признака ДД','5.3',`
<p><b>Пример 1.</b> В $\\triangle ABC$: $\\angle A = 50°$, $\\angle B = 70°$. В $\\triangle A'B'C'$: $\\angle A' = 50°$, $\\angle C' = 60°$. Подобны ли треугольники?</p>
<p style="margin-top:6px">$\\angle C = 180° - 50° - 70° = 60°$. $\\angle B' = 180° - 50° - 60° = 70°$. Углы: $50°, 70°, 60°$ в обоих. По признаку ДД: $\\triangle ABC \\sim \\triangle A'C'B'$.</p>
<p style="margin-top:8px"><b>Пример 2.</b> Два прямоугольных треугольника, у одного острый угол $35°$, у другого $35°$. Подобны ли?</p>
<p style="margin-top:4px">Да. Оба имеют $90°$ и $35°$ — два совпадающих угла.</p>`);
/* ---- ИНТЕРАКТИВ 1: SVG два треугольника, слайдер углов ---- */
html+=`<div class="wg" id="p5-ang-wg">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 1</span><div class="wg-title">Два угла задают форму — первый признак</div></div>
<div class="wg-help">Задай углы $\\alpha$ и $\\beta$. Оба треугольника строятся с этими углами — они подобны. Коэффициент $k$ определяется масштабом.</div>
<div class="sliders">
<label>Угол $\\alpha$: <b id="p5-a-val">50</b>°
<input type="range" min="20" max="130" value="50" id="p5-a-sl" step="1">
</label>
<label>Угол $\\beta$: <b id="p5-b-val">60</b>°
<input type="range" min="20" max="130" value="60" id="p5-b-sl" step="1">
</label>
<label>Масштаб $k$: <b id="p5-k-val">1.8</b>
<input type="range" min="12" max="30" value="18" id="p5-k-sl" step="1">
</label>
</div>
<div id="p5-ang-svg" style="display:flex;justify-content:center"></div>
<div id="p5-ang-info" style="margin-top:10px;padding:10px 14px;background:var(--sec-acc-soft,var(--pri-soft));border-radius:10px;font-size:.92rem;line-height:1.8"></div>
</div>`;
/* ---- ИНТЕРАКТИВ 2: Пошаговое доказательство ---- */
html+=`<div class="wg" id="p5-proof-wg">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 2</span><div class="wg-title">Доказательство 1-го признака — по шагам</div></div>
<div class="wg-help">Нажимай «Далее» — шаг за шагом увидишь логику доказательства.</div>
<div id="p5-proof-svg" style="display:flex;justify-content:center;margin-bottom:10px"></div>
<div id="p5-proof-desc" style="padding:10px 14px;background:var(--sec-acc-soft,var(--pri-soft));border-radius:10px;font-size:.95rem;line-height:1.6;margin-bottom:10px;min-height:60px"></div>
<div style="display:flex;gap:8px">
<button class="btn primary" id="p5-proof-next">Далее</button>
<button class="btn" id="p5-proof-reset">Сначала</button>
</div>
</div>`;
/* ---- ИНТЕРАКТИВ 3: Тренажёр ---- */
html+=`<div class="wg">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 3</span><div class="wg-title">Тренажёр §5 — Признак ДД</div></div>
<div class="wg-help">5 задач на подобие по углам и нахождение сторон.</div>
<div class="score-display"><span>Задача <b id="p5-tr-i">1</b> / 5</span><span>Очки: <b id="p5-tr-score">0</b></span></div>
<div id="p5-tr-task" style="padding:14px;background:var(--sec-acc-soft,var(--pri-soft));border-radius:10px;font-size:1.02rem;margin-bottom:10px"></div>
<div style="display:flex;gap:8px;align-items:center;flex-wrap:wrap">
<input type="number" id="p5-tr-ans" class="tinp" placeholder="Ответ" style="width:120px">
<button class="btn primary" id="p5-tr-go">Проверить</button>
<button class="btn" id="p5-tr-start">Начать</button>
</div>
<div class="feedback" id="p5-tr-fb" style="display:none"></div>
</div>`;
/* ---- ИНТЕРАКТИВ 4: DnD-сортер ---- */
html+=`<div class="wg">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 4</span><div class="wg-title">Подобные пары или нет? — Сортировка по углам</div></div>
<div class="wg-help">Перетащи каждую пару треугольников в нужную колонку.</div>
<div id="p5-dnd-pool" class="dnd-pool"></div>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-top:10px">
<div class="drop-box" id="p5-drop-yes"><h5>Подобны (ДД)</h5><div class="drop-items" id="p5-drop-yes-items"></div></div>
<div class="drop-box" id="p5-drop-no"><h5>Не подобны</h5><div class="drop-items" id="p5-drop-no-items"></div></div>
</div>
<div class="actions"><button class="btn primary" id="p5-dnd-check">Проверить</button><button class="btn" id="p5-dnd-reset">Сбросить</button></div>
<div class="feedback" id="p5-dnd-fb" style="display:none"></div>
</div>`;
/* ---- ИНТЕРАКТИВ 5: Калькулятор ---- */
html+=`<div class="wg">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 5</span><div class="wg-title">Калькулятор: найти сторону через подобие ДД</div></div>
<div class="wg-help">Введи два угла обоих треугольников и одну сторону первого — получи соответствующую сторону второго.</div>
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(100px,1fr));gap:8px;margin-bottom:10px">
<div><span style="font-size:.8rem;color:var(--muted);display:block">∠A₁ (°)</span><input type="number" id="p5-cA1" class="tinp" placeholder="напр. 50" style="width:100%"></div>
<div><span style="font-size:.8rem;color:var(--muted);display:block">∠B₁ (°)</span><input type="number" id="p5-cB1" class="tinp" placeholder="напр. 70" style="width:100%"></div>
<div><span style="font-size:.8rem;color:var(--muted);display:block">∠A₂ (°)</span><input type="number" id="p5-cA2" class="tinp" placeholder="напр. 50" style="width:100%"></div>
<div><span style="font-size:.8rem;color:var(--muted);display:block">∠B₂ (°)</span><input type="number" id="p5-cB2" class="tinp" placeholder="напр. 70" style="width:100%"></div>
<div><span style="font-size:.8rem;color:var(--muted);display:block">сторона a₁</span><input type="number" id="p5-ca1" class="tinp" placeholder="напр. 12" style="width:100%"></div>
<div style="display:flex;align-items:flex-end"><button class="btn primary" id="p5-ccalc" style="width:100%">Найти a₂</button></div>
</div>
<div id="p5-ccalc-out" style="display:none;padding:10px 14px;background:var(--sec-acc-soft,var(--pri-soft));border-radius:10px;font-size:.95rem"></div>
</div>`;
/* ---- ИНТЕРАКТИВ 6: Босс §5 ---- */
html+=`<div class="wg" style="border-color:var(--sec-acc-d,var(--pri2))">
<div class="wg-header"><span class="wg-badge" style="background:var(--sec-acc-d,var(--pri2))">БОСС §5</span><div class="wg-title">Итоговые задачи</div></div>
<div class="wg-help">4 задачи — каждая верная даёт +5 XP.</div>
<div id="p5-boss-tasks"></div>
</div>`;
html+=`<div style="margin-top:18px;display:flex;justify-content:center">
<button class="btn primary" id="p5-read-btn" onclick="addXp(10,'p5-read');bumpProgress('p5',40);this.textContent='Прочитано!';this.disabled=true;">
<svg class="ic" viewBox="0 0 24 24"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/></svg>
Я прочитал §5 (+10 XP)
</button>
</div>`;
html+=secNav('p4','p6');
box.innerHTML=html;
if(window.renderMathInElement) setTimeout(()=>renderMath(box),0);
/* == INIT ИНТЕРАКТИВ 1: слайдер углов == */
(function(){
const aSl=document.getElementById('p5-a-sl');
const bSl=document.getElementById('p5-b-sl');
const kSl=document.getElementById('p5-k-sl');
const aVal=document.getElementById('p5-a-val');
const bVal=document.getElementById('p5-b-val');
const kVal=document.getElementById('p5-k-val');
const svgWrap=document.getElementById('p5-ang-svg');
const infoEl=document.getElementById('p5-ang-info');
function buildTriFromAngles(alpha,beta,baseLen,ox,oy){
// alpha at A (left), beta at B (right)
// base AB horizontal, C above
const gamma=Math.PI-alpha-beta;
if(gamma<=0.05) return null;
// by sine rule: a/sin(alpha) = base/sin(gamma)
const sinG=Math.sin(gamma);
const AB=baseLen;
const BC=AB*Math.sin(alpha)/sinG;
const AC=AB*Math.sin(beta)/sinG;
// place A at (ox,oy), B at (ox+AB,oy)
const Ax=ox, Ay=oy;
const Bx=ox+AB, By=oy;
// C: from A at angle alpha above AB
const Cx=Ax+AC*Math.cos(alpha);
const Cy=Ay-AC*Math.sin(alpha);
return {Ax,Ay,Bx,By,Cx,Cy,AB,BC,AC};
}
function draw(){
const alpha=+aSl.value*Math.PI/180;
const beta=+bSl.value*Math.PI/180;
const k=+kSl.value/10;
aVal.textContent=+aSl.value;
bVal.textContent=+bSl.value;
kVal.textContent=k.toFixed(1);
const gamma=(Math.PI-alpha-beta)*180/Math.PI;
if(gamma<=3){
svgWrap.innerHTML='<div style="color:var(--bad);padding:10px">Сумма углов превышает 180°. Уменьши углы.</div>';
infoEl.innerHTML='Сумма углов не должна превышать 180°.';
return;
}
const W=360, H=170;
const t1=buildTriFromAngles(alpha,beta,90,20,145);
if(!t1){svgWrap.innerHTML='';return;}
const t2=buildTriFromAngles(alpha,beta,90/k,240,145);
if(!t2){svgWrap.innerHTML='';return;}
let s=`<svg viewBox="0 0 ${W} ${H}" style="max-width:${W}px;width:100%;background:#fafafa;border:1px solid var(--border);border-radius:10px">`;
// triangle 1
s+=`<polygon points="${t1.Ax},${t1.Ay} ${t1.Bx},${t1.By} ${t1.Cx},${t1.Cy}" fill="rgba(79,70,229,.12)" stroke="#4f46e5" stroke-width="2"/>`;
s+=`<text x="${t1.Cx}" y="${t1.Cy-5}" text-anchor="middle" font-size="10" font-weight="700" fill="#4338ca">A</text>`;
s+=`<text x="${t1.Ax-8}" y="${t1.Ay+4}" font-size="10" font-weight="700" fill="#4338ca">B</text>`;
s+=`<text x="${t1.Bx+4}" y="${t1.By+4}" font-size="10" font-weight="700" fill="#4338ca">C</text>`;
// angle markers t1
s+=`<path d="M${t1.Cx},${t1.Cy} Q${t1.Cx+(t1.Ax-t1.Cx)*0.18+3},${t1.Cy+(t1.Ay-t1.Cy)*0.18} ${t1.Cx+(t1.Ax-t1.Cx)*0.22},${t1.Cy+(t1.Ay-t1.Cy)*0.22}" fill="none" stroke="#f59e0b" stroke-width="1.5"/>`;
s+=`<path d="M${t1.Ax},${t1.Ay} Q${t1.Ax+(t1.Cx-t1.Ax)*0.12+(t1.Bx-t1.Ax)*0.08},${t1.Ay+(t1.Cy-t1.Ay)*0.12} ${t1.Ax+(t1.Bx-t1.Ax)*0.15},${t1.Ay}" fill="none" stroke="#10b981" stroke-width="1.5"/>`;
// triangle 2 (smaller)
s+=`<polygon points="${t2.Ax},${t2.Ay} ${t2.Bx},${t2.By} ${t2.Cx},${t2.Cy}" fill="rgba(99,102,241,.18)" stroke="#6366f1" stroke-width="1.8"/>`;
s+=`<text x="${t2.Cx}" y="${t2.Cy-5}" text-anchor="middle" font-size="10" font-weight="700" fill="#4f46e5">A'</text>`;
s+=`<text x="${t2.Ax-10}" y="${t2.Ay+4}" font-size="10" font-weight="700" fill="#4f46e5">B'</text>`;
s+=`<text x="${t2.Bx+4}" y="${t2.By+4}" font-size="10" font-weight="700" fill="#4f46e5">C'</text>`;
// angle markers t2
s+=`<path d="M${t2.Cx},${t2.Cy} Q${t2.Cx+(t2.Ax-t2.Cx)*0.22+2},${t2.Cy+(t2.Ay-t2.Cy)*0.22} ${t2.Cx+(t2.Ax-t2.Cx)*0.28},${t2.Cy+(t2.Ay-t2.Cy)*0.28}" fill="none" stroke="#f59e0b" stroke-width="1.5"/>`;
s+=`<path d="M${t2.Ax},${t2.Ay} Q${t2.Ax+(t2.Cx-t2.Ax)*0.14+(t2.Bx-t2.Ax)*0.10},${t2.Ay+(t2.Cy-t2.Ay)*0.14} ${t2.Ax+(t2.Bx-t2.Ax)*0.18},${t2.Ay}" fill="none" stroke="#10b981" stroke-width="1.5"/>`;
// label
s+=`<text x="${W/2}" y="12" text-anchor="middle" font-size="10" font-weight="800" fill="#4338ca">k = ${k.toFixed(1)}</text>`;
s+='</svg>';
svgWrap.innerHTML=s;
infoEl.innerHTML=`$\\alpha=${+aSl.value}°$, $\\beta=${+bSl.value}°$, $\\gamma=${fmt(gamma)}°$. Оба треугольника имеют одинаковые углы → по признаку ДД они подобны. Коэффициент подобия $k=${k.toFixed(1)}$.`;
renderMath(infoEl);
addXp(1,'p5-ang');
}
aSl.addEventListener('input',draw);
bSl.addEventListener('input',draw);
kSl.addEventListener('input',draw);
draw();
})();
/* == INIT ИНТЕРАКТИВ 2: пошаговое доказательство == */
(function(){
const steps=[
{desc:'<b>Шаг 1.</b> Даны $\\triangle ABC$ и $\\triangle A\'B\'C\'$ с $\\angle A = \\angle A\'$ и $\\angle B = \\angle B\'$. Требуется доказать $\\triangle ABC \\sim \\triangle A\'B\'C\'$.',
svg:`<svg viewBox="0 0 280 145" style="max-width:280px;background:#fafafa;border:1px solid var(--border);border-radius:10px"><polygon points="50,130 170,130 100,30" fill="rgba(79,70,229,.10)" stroke="#4f46e5" stroke-width="2"/><polygon points="185,130 255,130 220,68" fill="rgba(99,102,241,.15)" stroke="#6366f1" stroke-width="1.8"/><text x="97" y="25" font-size="11" font-weight="700" fill="#4338ca">A</text><text x="40" y="140" font-size="11" font-weight="700" fill="#4338ca">B</text><text x="172" y="140" font-size="11" font-weight="700" fill="#4338ca">C</text><text x="218" y="63" font-size="10" font-weight="700" fill="#4f46e5">A'</text><text x="177" y="140" font-size="10" font-weight="700" fill="#4f46e5">B'</text><text x="257" y="140" font-size="10" font-weight="700" fill="#4f46e5">C'</text><text x="140" y="14" text-anchor="middle" font-size="9" fill="#4338ca">∠A=∠A', ∠B=∠B' — условие</text></svg>`},
{desc:'<b>Шаг 2.</b> Из суммы углов треугольника: $\\angle C = 180° - \\angle A - \\angle B$ и $\\angle C\' = 180° - \\angle A\' - \\angle B\'$. Так как $\\angle A=\\angle A\'$ и $\\angle B=\\angle B\'$, получаем $\\angle C = \\angle C\'$.',
svg:`<svg viewBox="0 0 280 90" style="max-width:280px;background:#fafafa;border:1px solid var(--border);border-radius:10px"><text x="140" y="26" text-anchor="middle" font-size="11" fill="#4338ca" font-weight="700">∠A+∠B+∠C = 180°</text><text x="140" y="46" text-anchor="middle" font-size="11" fill="#4f46e5" font-weight="700">∠A'+∠B'+∠C' = 180°</text><text x="140" y="72" text-anchor="middle" font-size="11" fill="#10b981" font-weight="800">∠C = 180°−∠A−∠B = 180°−∠A'−∠B' = ∠C'</text></svg>`},
{desc:'<b>Шаг 3.</b> На луче $A\'B\'$ откладываем отрезок $A\'M = AB$. Через $M$ проводим прямую, параллельную $B\'C\'$ — она встречает $A\'C\'$ в точке $N$. По теореме §4: $\\triangle A\'MN \\sim \\triangle A\'B\'C\'$.',
svg:`<svg viewBox="0 0 280 145" style="max-width:280px;background:#fafafa;border:1px solid var(--border);border-radius:10px"><polygon points="185,130 255,130 220,68" fill="rgba(99,102,241,.10)" stroke="#6366f1" stroke-width="1.5"/><polygon points="185,130 230,130 207,99" fill="rgba(79,70,229,.22)" stroke="#4f46e5" stroke-width="2"/><line x1="207" y1="99" x2="230" y2="130" stroke="#4f46e5" stroke-width="1.5" stroke-dasharray="4,3"/><text x="218" y="63" font-size="10" font-weight="700" fill="#4f46e5">A'</text><text x="177" y="140" font-size="10" font-weight="700" fill="#4338ca">B'</text><text x="257" y="140" font-size="10" font-weight="700" fill="#4338ca">C'</text><text x="228" y="138" font-size="9" font-weight="700" fill="#4f46e5">M</text><text x="209" y="97" font-size="9" font-weight="700" fill="#4f46e5">N</text><text x="50" y="80" font-size="9" fill="#4338ca">△A'MN∼△A'B'C'</text></svg>`},
{desc:'<b>Шаг 4.</b> Поскольку $A\'M = AB$ и углы треугольников $\\triangle A\'MN$ и $\\triangle ABC$ попарно равны (все три угла), а $\\angle A\' = \\angle A$ — вершины совпадают, то $\\triangle A\'MN \\cong \\triangle ABC$ (по условию и построению).',
svg:`<svg viewBox="0 0 280 90" style="max-width:280px;background:#fafafa;border:1px solid var(--border);border-radius:10px"><text x="140" y="26" text-anchor="middle" font-size="11" fill="#4338ca" font-weight="700">A'M = AB, ∠A'=∠A, ∠B'=∠B</text><text x="140" y="46" text-anchor="middle" font-size="11" fill="#4f46e5" font-weight="700">→ △A'MN ≅ △ABC (признак у-с-у)</text><text x="140" y="70" text-anchor="middle" font-size="10" fill="#6366f1">Следовательно MN = BC, A'N = AC</text></svg>`},
{desc:'<b>Шаг 5.</b> Итог: $\\triangle A\'MN \\cong \\triangle ABC$ и $\\triangle A\'MN \\sim \\triangle A\'B\'C\'$ — отсюда $\\triangle ABC \\sim \\triangle A\'B\'C\'$ (транзитивность подобия). <b>Первый признак подобия доказан.</b>',
svg:`<svg viewBox="0 0 280 80" style="max-width:280px;background:#fafafa;border:1px solid var(--border);border-radius:10px"><text x="140" y="26" text-anchor="middle" font-size="12" fill="#4338ca" font-weight="800">∠A=∠A', ∠B=∠B' → △ABC △A'B'C'</text><text x="140" y="50" text-anchor="middle" font-size="10" fill="#4f46e5">Признак ДД — первый признак подобия</text><text x="140" y="70" text-anchor="middle" font-size="10" fill="#10b981" font-weight="800">QED ∎</text></svg>`},
];
let step=0;
const svgEl=document.getElementById('p5-proof-svg');
const descEl=document.getElementById('p5-proof-desc');
function show(){
svgEl.innerHTML=steps[step].svg;
descEl.innerHTML=steps[step].desc;
renderMath(descEl);
}
document.getElementById('p5-proof-next').addEventListener('click',()=>{
if(step<steps.length-1){step++;show();addXp(1,'p5-proof-step');}
else{addXp(5,'p5-proof-done');bumpProgress('p5',10);}
});
document.getElementById('p5-proof-reset').addEventListener('click',()=>{step=0;show();});
show();
})();
/* == INIT ИНТЕРАКТИВ 3: тренажёр == */
(function(){
const tasks=[
{q:'В $\\triangle ABC$: $\\angle A=40°$, $\\angle B=70°$. В $\\triangle A\'B\'C\'$: $\\angle A\'=40°$, $\\angle B\'=70°$. Чему равен $\\angle C\'$?',ans:70,hint:'∠C\'=1804070=70°.'},
{q:'$\\triangle ABC \\sim \\triangle A\'B\'C\'$ по признаку ДД. $AB=12$, $A\'B\'=4$. Найди коэффициент подобия $k$.',ans:3,hint:'k=AB/A\'B\'=12/4=3.'},
{q:'$\\triangle ABC \\sim \\triangle A\'B\'C\'$, $k=2.5$. Сторона $a\'=6$. Найди $a$.',ans:15,hint:'a=k·a\'=2.5·6=15.'},
{q:'Два прямоугольных треугольника. В первом острый угол $37°$, во втором $37°$. Сторона при прямом угле в первом — $10$, во втором — $6$. Найди коэффициент подобия.',ans:1.667,hint:'k=10/6≈1.667.'},
{q:'$\\angle A=\\angle A\'=55°$, $\\angle B=\\angle B\'=65°$. Сторона $c=18$ в $\\triangle ABC$, $c\'=9$ в $\\triangle A\'B\'C\'$. Найди $k$.',ans:2,hint:'k=c/c\'=18/9=2.'},
];
let idx=0,score=0;
function show(){
document.getElementById('p5-tr-i').textContent=idx+1;
const t=document.getElementById('p5-tr-task');
t.innerHTML=tasks[idx].q;
renderMath(t);
document.getElementById('p5-tr-ans').value='';
document.getElementById('p5-tr-fb').style.display='none';
}
document.getElementById('p5-tr-start').addEventListener('click',()=>{idx=0;score=0;document.getElementById('p5-tr-score').textContent=0;show();});
document.getElementById('p5-tr-go').addEventListener('click',()=>{
if(idx>=tasks.length)return;
const ans=+document.getElementById('p5-tr-ans').value;
const fb=document.getElementById('p5-tr-fb');
if(Math.abs(ans-tasks[idx].ans)<0.02){
score++;document.getElementById('p5-tr-score').textContent=score;
addXp(3,'p5-tr-'+idx);bumpProgress('p5',4);
if(idx<tasks.length-1){feedback(fb,true,'Верно! +3 XP');idx++;setTimeout(()=>show(),900);}
else{feedback(fb,true,'Все задачи решены! +5 XP');addXp(5,'p5-tr-all');bumpProgress('p5',10);confetti();}
} else {
feedback(fb,false,'Неверно. '+tasks[idx].hint);
}
});
document.getElementById('p5-tr-ans').addEventListener('keydown',e=>{if(e.key==='Enter')document.getElementById('p5-tr-go').click();});
show();
})();
/* == INIT ИНТЕРАКТИВ 4: DnD-сортер == */
(function(){
const items=[
{text:'(50°,70°,60°) и (50°,70°,60°)',yes:true},
{text:'(40°,60°,80°) и (40°,50°,90°)',yes:false},
{text:'(90°,35°,55°) и (90°,35°,55°)',yes:true},
{text:'(30°,60°,90°) и (45°,45°,90°)',yes:false},
{text:'(80°,60°,40°) и (80°,40°,60°)',yes:true},
];
const pool=document.getElementById('p5-dnd-pool');
const yesBox=document.getElementById('p5-drop-yes-items');
const noBox=document.getElementById('p5-drop-no-items');
let dragging=null;
function makeChip(it,idx){
const chip=document.createElement('div');
chip.className='dnd-chip';
chip.dataset.idx=idx;
chip.textContent=it.text;
chip.draggable=true;
chip.addEventListener('dragstart',e=>{dragging=chip;chip.classList.add('dragging');e.dataTransfer.effectAllowed='move';});
chip.addEventListener('dragend',()=>{chip.classList.remove('dragging');dragging=null;});
return chip;
}
items.forEach((it,i)=>pool.appendChild(makeChip(it,i)));
[document.getElementById('p5-drop-yes'),document.getElementById('p5-drop-no'),pool].forEach(box=>{
box.addEventListener('dragover',e=>{e.preventDefault();box.classList.add('over');});
box.addEventListener('dragleave',()=>box.classList.remove('over'));
box.addEventListener('drop',e=>{
e.preventDefault();box.classList.remove('over');
if(!dragging)return;
const target=box===document.getElementById('p5-drop-yes')?yesBox:box===document.getElementById('p5-drop-no')?noBox:pool;
target.appendChild(dragging);
});
});
document.getElementById('p5-dnd-check').addEventListener('click',()=>{
const fb=document.getElementById('p5-dnd-fb');
const yChips=[...yesBox.querySelectorAll('.dnd-chip')];
const nChips=[...noBox.querySelectorAll('.dnd-chip')];
if(yChips.length+nChips.length<items.length){feedback(fb,false,'Разложи все карточки.');return;}
let ok=true;
yChips.forEach(c=>{if(!items[+c.dataset.idx].yes)ok=false;});
nChips.forEach(c=>{if(items[+c.dataset.idx].yes)ok=false;});
if(ok){feedback(fb,true,'Верно! +5 XP');addXp(5,'p5-dnd');bumpProgress('p5',8);}
else{feedback(fb,false,'Есть ошибки. Два треугольника подобны, если у них есть хотя бы две пары равных углов.');}
});
document.getElementById('p5-dnd-reset').addEventListener('click',()=>{
[...yesBox.children].forEach(c=>pool.appendChild(c));
[...noBox.children].forEach(c=>pool.appendChild(c));
document.getElementById('p5-dnd-fb').style.display='none';
});
})();
/* == INIT ИНТЕРАКТИВ 5: калькулятор == */
(function(){
document.getElementById('p5-ccalc').addEventListener('click',()=>{
const A1=parseFloat(document.getElementById('p5-cA1').value);
const B1=parseFloat(document.getElementById('p5-cB1').value);
const A2=parseFloat(document.getElementById('p5-cA2').value);
const B2=parseFloat(document.getElementById('p5-cB2').value);
const a1=parseFloat(document.getElementById('p5-ca1').value);
const out=document.getElementById('p5-ccalc-out');
if([A1,B1,A2,B2,a1].some(v=>!isFinite(v)||v<=0)){
out.style.display='block';out.innerHTML='<span style="color:var(--bad)">Введи все поля.</span>';return;
}
const C1=180-A1-B1, C2=180-A2-B2;
if(C1<=0||C2<=0){
out.style.display='block';out.innerHTML='<span style="color:var(--bad)">Сумма углов превышает 180°.</span>';return;
}
// check similarity: sort angles and compare
const ang1=[A1,B1,C1].sort((a,b)=>a-b);
const ang2=[A2,B2,C2].sort((a,b)=>a-b);
const similar=ang1.every((v,i)=>Math.abs(v-ang2[i])<0.5);
if(!similar){
out.style.display='block';out.innerHTML=`$\\angle C_1=${fmt(C1)}°$, $\\angle C_2=${fmt(C2)}°$. Наборы углов различаются — треугольники <b>не подобны</b>. Признак ДД не выполнен.`;
renderMath(out);return;
}
// find matching side using sine rule: a/sin(A)=b/sin(B)
// k = a1 / (2R sin(A)) ... use ratio of sides
// match angles: find which angle in t2 corresponds to A1
// simplification: by ratio of corresponding sides via sine rule
// a1/sin(A1) = a2/sin(A2) → a2 = a1*sin(A2*pi/180)/sin(A1*pi/180)
const a2=a1*Math.sin(A2*Math.PI/180)/Math.sin(A1*Math.PI/180);
const k=a1/a2;
out.style.display='block';
out.innerHTML=`Треугольники подобны по признаку ДД.<br>$\\angle C_1 = ${fmt(C1)}°$, $\\angle C_2 = ${fmt(C2)}°$.<br>По теореме синусов: $a_2 = a_1 \\cdot \\dfrac{\\sin \\angle A_2}{\\sin \\angle A_1} = ${fmt(a1)} \\cdot \\dfrac{${fmt(Math.sin(A2*Math.PI/180).toFixed(4))}}{${fmt(Math.sin(A1*Math.PI/180).toFixed(4))}} = ${fmt(a2)}$.<br>Коэффициент подобия $k = a_1/a_2 = ${fmt(k)}$.`;
renderMath(out);
addXp(3,'p5-calc');bumpProgress('p5',5);
});
})();
/* == INIT: Босс §5 == */
(function(){
const tasks=[
{q:'<svg viewBox="0 0 240 140" style="display:block;max-width:240px;margin:0 auto 8px;background:#e0e7ff;border:1px solid #a5b4fc;border-radius:8px"><polygon points="50,125 165,125 100,30" fill="rgba(79,70,229,.12)" stroke="#4f46e5" stroke-width="2"/><polygon points="175,125 230,125 200,78" fill="rgba(99,102,241,.18)" stroke="#6366f1" stroke-width="1.8"/><text x="97" y="26" font-size="10" fill="#4338ca" font-weight="700">A</text><text x="40" y="134" font-size="10" fill="#4338ca" font-weight="700">B</text><text x="167" y="134" font-size="10" fill="#4338ca" font-weight="700">C</text><text x="197" y="74" font-size="9" fill="#4f46e5" font-weight="700">A\'</text><text x="168" y="134" font-size="9" fill="#4f46e5" font-weight="700">B\'</text><text x="232" y="134" font-size="9" fill="#4f46e5" font-weight="700">C\'</text><text x="120" y="12" text-anchor="middle" font-size="8" fill="#4338ca">∠A=∠A\'=60°, ∠B=∠B\'=80°</text></svg>$\\angle A=\\angle A\'=60°$, $\\angle B=\\angle B\'=80°$. $AB=15$, $A\'B\'=5$. Найди $k$.',ans:3,hint:'k=AB/A\'B\'=15/5=3.'},
{q:'Два прямоугольных треугольника. Острый угол одного $42°$, другого $42°$. Подобны ли? Гипотенуза первого $13$, второго $6.5$. Найди $k$.',ans:2,hint:'Подобны (ДД). k=13/6.5=2.'},
{q:'$\\triangle ABC \\sim \\triangle A\'B\'C\'$ по ДД. $k=4$. Периметр $\\triangle A\'B\'C\'=18$. Найди периметр $\\triangle ABC$.',ans:72,hint:'P=k·P\'=4·18=72.'},
{q:'В $\\triangle ABC$ и $\\triangle DEF$: $\\angle A=\\angle D=55°$, $\\angle B=\\angle E=75°$. $BC=20$, $EF=8$. Найди $k=BC/EF$.',ans:2.5,hint:'k=20/8=2.5.'},
];
const bossBox=document.getElementById('p5-boss-tasks');
bossBox.innerHTML=tasks.map((t,i)=>`
<div style="padding:14px;background:var(--card);border-radius:10px;border:1px solid var(--border);margin-bottom:10px">
<div style="margin-bottom:8px;font-size:.95rem">${t.q}</div>
<div style="display:flex;gap:8px;flex-wrap:wrap;align-items:center">
<input type="number" class="tinp" id="p5b-a${i}" placeholder="Ответ" style="width:110px">
<button class="btn primary small" onclick="(function(){
const v=+document.getElementById('p5b-a${i}').value;
const fb=document.getElementById('p5b-fb${i}');
if(Math.abs(v-${t.ans})<0.02){
feedback(fb,true,'Верно! +5 XP');
if(!window.p5BossSolved.has(${i})){ window.p5BossSolved.add(${i}); addXp(5,'p5-boss${i}'); bumpProgress('p5',8); }
} else feedback(fb,false,'Неверно. ${t.hint}');
})()">Проверить</button>
</div>
<div class="feedback" id="p5b-fb${i}" style="display:none;margin-top:8px"></div>
</div>`).join('');
window.p5BossSolved=new Set();
renderMath(bossBox);
})();
}
function buildP6(){
const box=document.getElementById('p6-body');
let html='';
/* ---- Theory cards ---- */
html+=makeCard('theory','Второй признак подобия треугольников (СУС — сторона-угол-сторона)','6.1',`
<p><b>Теорема (2-й признак подобия, СУС).</b> Если две стороны одного треугольника пропорциональны двум сторонам другого треугольника, а углы между этими сторонами равны, то такие треугольники подобны.</p>
<p style="margin-top:8px">Если $\\dfrac{AB}{A'B'} = \\dfrac{AC}{A'C'} = k$ и $\\angle A = \\angle A'$, то $\\triangle ABC \\sim \\triangle A'B'C'$.</p>
<p style="margin-top:8px">Это означает: двух пропорциональных сторон и равного угла между ними <b>достаточно</b> для подобия — третью сторону и остальные углы можно не проверять.</p>
<div style="display:flex;justify-content:center;margin-top:14px">
<svg viewBox="0 0 300 160" style="max-width:320px;background:#fafafa;border:1px solid var(--border);border-radius:10px">
<!-- Triangle 1: A=(100,20) B=(30,140) C=(195,140) -->
<polygon points="100,20 30,140 195,140" fill="rgba(124,58,237,.11)" stroke="#7c3aed" stroke-width="2"/>
<!-- Angle mark at A -->
<path d="M100,20 Q118,38 108,52" fill="none" stroke="#f59e0b" stroke-width="2"/>
<!-- Side labels -->
<text x="100" y="14" text-anchor="middle" font-size="11" font-weight="800" fill="#6d28d9">A</text>
<text x="20" y="150" font-size="11" font-weight="800" fill="#6d28d9">B</text>
<text x="198" y="150" font-size="11" font-weight="800" fill="#6d28d9">C</text>
<text x="54" y="90" text-anchor="middle" font-size="10" fill="#7c3aed" font-style="italic">AB</text>
<text x="155" y="88" text-anchor="middle" font-size="10" fill="#7c3aed" font-style="italic">AC</text>
<!-- Triangle 2: A'=(235,48) B'=(208,118) C'=(275,118) -->
<polygon points="235,48 208,118 275,118" fill="rgba(99,102,241,.18)" stroke="#6366f1" stroke-width="1.8"/>
<!-- Angle mark at A' -->
<path d="M235,48 Q246,59 241,68" fill="none" stroke="#f59e0b" stroke-width="1.8"/>
<text x="235" y="42" text-anchor="middle" font-size="10" font-weight="800" fill="#4f46e5">A'</text>
<text x="199" y="127" font-size="10" font-weight="800" fill="#4f46e5">B'</text>
<text x="277" y="127" font-size="10" font-weight="800" fill="#4f46e5">C'</text>
<text x="218" y="87" text-anchor="middle" font-size="9" fill="#6366f1" font-style="italic">A'B'</text>
<text x="262" y="85" text-anchor="middle" font-size="9" fill="#6366f1" font-style="italic">A'C'</text>
<!-- Equal angle label -->
<text x="150" y="12" text-anchor="middle" font-size="9" fill="#f59e0b" font-weight="800">∠A = ∠A'</text>
<text x="150" y="24" text-anchor="middle" font-size="9" fill="#7c3aed">AB/A'B' = AC/A'C' = k → △ABC∼△A'B'C'</text>
</svg>
</div>`);
html+=makeCard('rule','Доказательство 2-го признака — схема','6.2',`
<p>На луче $A'B'$ откладываем $A'M = AB$. Через $M$ проводим прямую $MN \\parallel B'C'$, встречающую $A'C'$ в точке $N$.</p>
<p style="margin-top:6px">По теореме о прямой, параллельной стороне (§4): $\\dfrac{A'M}{A'B'} = \\dfrac{A'N}{A'C'}$, то есть $A'N = A'C' \\cdot \\dfrac{A'M}{A'B'} = A'C' \\cdot \\dfrac{AB}{A'B'} = AC$.</p>
<p style="margin-top:6px">Итак $A'M=AB$, $A'N=AC$, $\\angle A' = \\angle A$ → по признаку SAS: $\\triangle A'MN \\cong \\triangle ABC$.</p>
<p style="margin-top:6px">Также $\\triangle A'MN \\sim \\triangle A'B'C'$ (§4). Значит $\\triangle ABC \\sim \\triangle A'B'C'$. <b>QED.</b></p>
<div style="display:flex;justify-content:center;margin-top:12px">
<svg viewBox="0 0 280 140" style="max-width:300px;background:#fafafa;border:1px solid var(--border);border-radius:10px">
<!-- large triangle A'B'C': A'=(140,15) B'=(30,130) C'=(250,130) -->
<polygon points="140,15 30,130 250,130" fill="rgba(99,102,241,.10)" stroke="#6366f1" stroke-width="1.5"/>
<!-- inner triangle A'MN: M on A'B', N on A'C' -->
<!-- M on A'B' at ratio 0.55: M=(140+(30-140)*0.55, 15+(130-15)*0.55)=(79.5, 78.25) -->
<!-- N on A'C' at ratio 0.55: N=(140+(250-140)*0.55, 15+(130-15)*0.55)=(200.5, 78.25) -->
<polygon points="140,15 80,78 200,78" fill="rgba(124,58,237,.22)" stroke="#7c3aed" stroke-width="2"/>
<line x1="80" y1="78" x2="200" y2="78" stroke="#7c3aed" stroke-width="2" stroke-dasharray="5,3"/>
<text x="140" y="10" text-anchor="middle" font-size="10" font-weight="800" fill="#4f46e5">A'</text>
<text x="20" y="138" font-size="10" font-weight="800" fill="#4f46e5">B'</text>
<text x="252" y="138" font-size="10" font-weight="800" fill="#4f46e5">C'</text>
<text x="74" y="88" font-size="10" font-weight="800" fill="#7c3aed">M</text>
<text x="202" y="88" font-size="10" font-weight="800" fill="#7c3aed">N</text>
<text x="140" y="125" text-anchor="middle" font-size="8" fill="#6366f1">MN ∥ B'C'</text>
<text x="30" y="14" font-size="8" fill="#7c3aed">△A'MN≅△ABC и △A'MN∼△A'B'C'</text>
</svg>
</div>`);
html+=makeCard('example','Примеры применения признака СУС','6.3',`
<p><b>Пример 1.</b> $AB=6$, $AC=9$, $A'B'=4$, $A'C'=6$, $\\angle A=\\angle A'=50°$. Подобны ли треугольники?</p>
<p style="margin-top:4px">$\\dfrac{AB}{A'B'}=\\dfrac{6}{4}=1{,}5$; $\\dfrac{AC}{A'C'}=\\dfrac{9}{6}=1{,}5$. Отношения равны, углы между ними равны → по СУС: $\\triangle ABC \\sim \\triangle A'B'C'$, $k=1{,}5$.</p>
<p style="margin-top:8px"><b>Пример 2.</b> $PQ=10$, $PR=15$, $P'Q'=6$, $P'R'=9$, $\\angle P=\\angle P'$. $PQ/P'Q'=10/6=5/3$, $PR/P'R'=15/9=5/3$. Подобны ($k=5/3$).</p>
<p style="margin-top:8px"><b>Пример 3 (не подобны).</b> $AB=8$, $AC=6$, $A'B'=4$, $A'C'=5$, $\\angle A=\\angle A'$. $AB/A'B'=2$, $AC/A'C'=1{,}2$ — отношения неравны → <b>не подобны</b>.</p>`);
/* ---- ИНТЕРАКТИВ 1: SVG два треугольника, слайдер k ---- */
html+=`<div class="wg" id="p6-svg-wg">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 1</span><div class="wg-title">Два треугольника — признак СУС</div></div>
<div class="wg-help">Задай стороны $AB$, $AC$ и угол $\\angle A$ первого треугольника. Второй строится автоматически с тем же углом и пропорциональными сторонами. Меняй коэффициент $k$.</div>
<div class="sliders">
<label>Сторона $AB$: <b id="p6-ab-val">8</b>
<input type="range" min="4" max="14" value="8" id="p6-ab-sl" step="1">
</label>
<label>Сторона $AC$: <b id="p6-ac-val">10</b>
<input type="range" min="4" max="14" value="10" id="p6-ac-sl" step="1">
</label>
<label>Угол $\\angle A$ (°): <b id="p6-ang-val">55</b>°
<input type="range" min="20" max="140" value="55" id="p6-ang-sl" step="1">
</label>
<label>Коэффициент $k$: <b id="p6-k-val">2.0</b>
<input type="range" min="12" max="35" value="20" id="p6-k-sl" step="1">
</label>
</div>
<div id="p6-svg-out" style="display:flex;justify-content:center"></div>
<div id="p6-svg-info" style="margin-top:10px;padding:10px 14px;background:var(--sec-acc-soft,var(--pri-soft));border-radius:10px;font-size:.92rem;line-height:1.8"></div>
</div>`;
/* ---- ИНТЕРАКТИВ 2: Пошаговое доказательство ---- */
html+=`<div class="wg" id="p6-proof-wg">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 2</span><div class="wg-title">Доказательство 2-го признака — по шагам</div></div>
<div class="wg-help">Нажимай «Далее» для каждого шага доказательства.</div>
<div id="p6-proof-svg" style="display:flex;justify-content:center;margin-bottom:10px"></div>
<div id="p6-proof-desc" style="padding:10px 14px;background:var(--sec-acc-soft,var(--pri-soft));border-radius:10px;font-size:.95rem;line-height:1.6;margin-bottom:10px;min-height:60px"></div>
<div style="display:flex;gap:8px">
<button class="btn primary" id="p6-proof-next">Далее</button>
<button class="btn" id="p6-proof-reset">Сначала</button>
</div>
</div>`;
/* ---- ИНТЕРАКТИВ 3: Калькулятор СУС ---- */
html+=`<div class="wg">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 3</span><div class="wg-title">Калькулятор признака СУС</div></div>
<div class="wg-help">Введи $AB, AC, \\angle A$ первого треугольника и коэффициент $k$ — получи стороны и угол второго. Или введи стороны двух треугольников и угол — система проверит подобие.</div>
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(110px,1fr));gap:8px;margin-bottom:10px">
<div><span style="font-size:.8rem;color:var(--muted);display:block">AB</span><input type="number" id="p6-cAB" class="tinp" placeholder="напр. 6" style="width:100%"></div>
<div><span style="font-size:.8rem;color:var(--muted);display:block">AC</span><input type="number" id="p6-cAC" class="tinp" placeholder="напр. 9" style="width:100%"></div>
<div><span style="font-size:.8rem;color:var(--muted);display:block">∠A (°)</span><input type="number" id="p6-cAng" class="tinp" placeholder="напр. 55" style="width:100%"></div>
<div><span style="font-size:.8rem;color:var(--muted);display:block">k</span><input type="number" id="p6-ck" class="tinp" placeholder="напр. 1.5" style="width:100%"></div>
<div style="display:flex;align-items:flex-end"><button class="btn primary" id="p6-ccalc" style="width:100%">Найти</button></div>
</div>
<div id="p6-ccalc-out" style="display:none;padding:10px 14px;background:var(--sec-acc-soft,var(--pri-soft));border-radius:10px;font-size:.95rem;line-height:1.7"></div>
</div>`;
/* ---- ИНТЕРАКТИВ 4: Тренажёр ---- */
html+=`<div class="wg">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 4</span><div class="wg-title">Тренажёр §6 — Признак СУС</div></div>
<div class="wg-help">5 задач на подобие по признаку СУС.</div>
<div class="score-display"><span>Задача <b id="p6-tr-i">1</b> / 5</span><span>Очки: <b id="p6-tr-score">0</b></span></div>
<div id="p6-tr-task" style="padding:14px;background:var(--sec-acc-soft,var(--pri-soft));border-radius:10px;font-size:1.02rem;margin-bottom:10px"></div>
<div style="display:flex;gap:8px;align-items:center;flex-wrap:wrap">
<input type="number" id="p6-tr-ans" class="tinp" placeholder="Ответ" style="width:130px">
<button class="btn primary" id="p6-tr-go">Проверить</button>
<button class="btn" id="p6-tr-start">Начать</button>
</div>
<div class="feedback" id="p6-tr-fb" style="display:none"></div>
</div>`;
/* ---- ИНТЕРАКТИВ 5: DnD-сортер ---- */
html+=`<div class="wg">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 5</span><div class="wg-title">Подобны по СУС или нет? — Сортировка</div></div>
<div class="wg-help">Перетащи каждую пару в нужную колонку.</div>
<div id="p6-dnd-pool" class="dnd-pool"></div>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-top:10px">
<div class="drop-box" id="p6-drop-yes"><h5>Подобны (СУС)</h5><div class="drop-items" id="p6-drop-yes-items"></div></div>
<div class="drop-box" id="p6-drop-no"><h5>Не подобны</h5><div class="drop-items" id="p6-drop-no-items"></div></div>
</div>
<div class="actions"><button class="btn primary" id="p6-dnd-check">Проверить</button><button class="btn" id="p6-dnd-reset">Сбросить</button></div>
<div class="feedback" id="p6-dnd-fb" style="display:none"></div>
</div>`;
/* ---- ИНТЕРАКТИВ 6: Босс §6 ---- */
html+=`<div class="wg" style="border-color:var(--sec-acc-d,var(--pri2))">
<div class="wg-header"><span class="wg-badge" style="background:var(--sec-acc-d,var(--pri2))">БОСС §6</span><div class="wg-title">Итоговые задачи</div></div>
<div class="wg-help">4 задачи — каждая верная даёт +5 XP.</div>
<div id="p6-boss-tasks"></div>
</div>`;
html+=`<div style="margin-top:18px;display:flex;justify-content:center">
<button class="btn primary" id="p6-read-btn" onclick="addXp(10,'p6-read');bumpProgress('p6',40);this.textContent='Прочитано!';this.disabled=true;">
<svg class="ic" viewBox="0 0 24 24"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/></svg>
Я прочитал §6 (+10 XP)
</button>
</div>`;
html+=secNav('p5','p7');
box.innerHTML=html;
if(window.renderMathInElement) setTimeout(()=>renderMath(box),0);
/* == INIT ИНТЕРАКТИВ 1: SVG слайдеры СУС == */
(function(){
const abSl=document.getElementById('p6-ab-sl');
const acSl=document.getElementById('p6-ac-sl');
const angSl=document.getElementById('p6-ang-sl');
const kSl=document.getElementById('p6-k-sl');
const abVal=document.getElementById('p6-ab-val');
const acVal=document.getElementById('p6-ac-val');
const angVal=document.getElementById('p6-ang-val');
const kVal=document.getElementById('p6-k-val');
const svgOut=document.getElementById('p6-svg-out');
const infoEl=document.getElementById('p6-svg-info');
function triFromSAS(ab,ac,angRad,ox,oy){
const Ax=ox, Ay=oy;
const Bx=ox+ab, By=oy;
const Cx=ox+ac*Math.cos(angRad);
const Cy=oy-ac*Math.sin(angRad);
return {Ax,Ay,Bx,By,Cx,Cy};
}
function draw(){
const ab=+abSl.value;
const ac=+acSl.value;
const angDeg=+angSl.value;
const k=+kSl.value/10;
abVal.textContent=ab;
acVal.textContent=ac;
angVal.textContent=angDeg;
kVal.textContent=k.toFixed(1);
const scale=14;
const angRad=angDeg*Math.PI/180;
const W=380, H=180;
const t1=triFromSAS(ab*scale,ac*scale,angRad,24,155);
const ab2=ab/k, ac2=ac/k;
const t2=triFromSAS(ab2*scale,ac2*scale,angRad,220,155);
let s=`<svg viewBox="0 0 ${W} ${H}" style="max-width:${W}px;width:100%;background:#fafafa;border:1px solid var(--border);border-radius:10px">`;
s+=`<polygon points="${t1.Ax},${t1.Ay} ${t1.Bx},${t1.By} ${t1.Cx},${t1.Cy}" fill="rgba(124,58,237,.12)" stroke="#7c3aed" stroke-width="2"/>`;
s+=`<text x="${t1.Ax-3}" y="${t1.Ay+4}" text-anchor="end" font-size="11" font-weight="800" fill="#6d28d9">A</text>`;
s+=`<text x="${t1.Bx+4}" y="${t1.By+4}" font-size="11" font-weight="800" fill="#6d28d9">B</text>`;
s+=`<text x="${t1.Cx}" y="${t1.Cy-5}" text-anchor="middle" font-size="11" font-weight="800" fill="#6d28d9">C</text>`;
const mABx1=(t1.Ax+t1.Bx)/2, mABx1y=(t1.Ay+t1.By)/2;
const mACx1=(t1.Ax+t1.Cx)/2, mACy1=(t1.Ay+t1.Cy)/2;
s+=`<text x="${mABx1}" y="${mABx1y+12}" text-anchor="middle" font-size="9" fill="#7c3aed">${ab}</text>`;
s+=`<text x="${mACx1-8}" y="${mACy1}" text-anchor="end" font-size="9" fill="#7c3aed">${ac}</text>`;
s+=`<path d="M${t1.Ax+14},${t1.Ay} Q${t1.Ax+10+8*Math.cos(angRad/2)},${t1.Ay-8*Math.sin(angRad/2)} ${t1.Ax+8*Math.cos(angRad)},${t1.Ay-8*Math.sin(angRad)}" fill="none" stroke="#f59e0b" stroke-width="1.8"/>`;
s+=`<polygon points="${t2.Ax},${t2.Ay} ${t2.Bx},${t2.By} ${t2.Cx},${t2.Cy}" fill="rgba(99,102,241,.18)" stroke="#6366f1" stroke-width="1.8"/>`;
s+=`<text x="${t2.Ax-3}" y="${t2.Ay+4}" text-anchor="end" font-size="10" font-weight="800" fill="#4f46e5">A'</text>`;
s+=`<text x="${t2.Bx+4}" y="${t2.By+4}" font-size="10" font-weight="800" fill="#4f46e5">B'</text>`;
s+=`<text x="${t2.Cx}" y="${t2.Cy-5}" text-anchor="middle" font-size="10" font-weight="800" fill="#4f46e5">C'</text>`;
const mABx2=(t2.Ax+t2.Bx)/2, mABy2=(t2.Ay+t2.By)/2;
const mACx2=(t2.Ax+t2.Cx)/2, mACy2=(t2.Ay+t2.Cy)/2;
s+=`<text x="${mABx2}" y="${mABy2+12}" text-anchor="middle" font-size="9" fill="#6366f1">${fmt(ab2)}</text>`;
s+=`<text x="${mACx2-6}" y="${mACy2}" text-anchor="end" font-size="9" fill="#6366f1">${fmt(ac2)}</text>`;
s+=`<path d="M${t2.Ax+10},${t2.Ay} Q${t2.Ax+8+6*Math.cos(angRad/2)},${t2.Ay-6*Math.sin(angRad/2)} ${t2.Ax+6*Math.cos(angRad)},${t2.Ay-6*Math.sin(angRad)}" fill="none" stroke="#f59e0b" stroke-width="1.5"/>`;
s+=`<text x="${W/2}" y="12" text-anchor="middle" font-size="10" font-weight="800" fill="#7c3aed">k = ${k.toFixed(1)}</text>`;
s+='</svg>';
svgOut.innerHTML=s;
infoEl.innerHTML=`$AB=${ab}$, $AC=${ac}$, $\\angle A=${angDeg}°$. Второй треугольник: $A'B'=${fmt(ab2)}$, $A'C'=${fmt(ac2)}$, $\\angle A'=${angDeg}°$. Отношение сторон $k=${k.toFixed(1)}$ — треугольники подобны по признаку СУС.`;
renderMath(infoEl);
addXp(1,'p6-svg');
}
abSl.addEventListener('input',draw);
acSl.addEventListener('input',draw);
angSl.addEventListener('input',draw);
kSl.addEventListener('input',draw);
draw();
})();
/* == INIT ИНТЕРАКТИВ 2: пошаговое доказательство == */
(function(){
const steps=[
{desc:'<b>Шаг 1.</b> Дано: $\\dfrac{AB}{A\'B\'} = \\dfrac{AC}{A\'C\'} = k$ и $\\angle A = \\angle A\'$. Нужно доказать: $\\triangle ABC \\sim \\triangle A\'B\'C\'$.',
svg:`<svg viewBox="0 0 280 140" style="max-width:280px;background:#fafafa;border:1px solid var(--border);border-radius:10px"><polygon points="100,20 30,130 200,130" fill="rgba(124,58,237,.10)" stroke="#7c3aed" stroke-width="2"/><polygon points="210,48 185,115 255,115" fill="rgba(99,102,241,.18)" stroke="#6366f1" stroke-width="1.8"/><text x="100" y="14" text-anchor="middle" font-size="11" font-weight="800" fill="#6d28d9">A</text><text x="20" y="138" font-size="11" font-weight="800" fill="#6d28d9">B</text><text x="202" y="138" font-size="11" font-weight="800" fill="#6d28d9">C</text><text x="210" y="43" text-anchor="middle" font-size="10" font-weight="800" fill="#4f46e5">A'</text><text x="177" y="124" font-size="10" font-weight="800" fill="#4f46e5">B'</text><text x="257" y="124" font-size="10" font-weight="800" fill="#4f46e5">C'</text><text x="140" y="12" text-anchor="middle" font-size="9" fill="#f59e0b" font-weight="800">AB/A'B'=AC/A'C'=k, ∠A=∠A'</text></svg>`},
{desc:'<b>Шаг 2.</b> На луче $A\'B\'$ откладываем точку $M$ так, что $A\'M = AB$. Через $M$ проводим прямую $MN \\parallel B\'C\'$, где $N$ на луче $A\'C\'$.',
svg:`<svg viewBox="0 0 280 140" style="max-width:280px;background:#fafafa;border:1px solid var(--border);border-radius:10px"><polygon points="140,15 30,130 250,130" fill="rgba(99,102,241,.10)" stroke="#6366f1" stroke-width="1.5"/><polygon points="140,15 80,78 200,78" fill="rgba(124,58,237,.22)" stroke="#7c3aed" stroke-width="2"/><line x1="80" y1="78" x2="200" y2="78" stroke="#7c3aed" stroke-width="2" stroke-dasharray="5,3"/><text x="140" y="10" text-anchor="middle" font-size="10" font-weight="800" fill="#4f46e5">A'</text><text x="20" y="138" font-size="10" font-weight="800" fill="#4f46e5">B'</text><text x="252" y="138" font-size="10" font-weight="800" fill="#4f46e5">C'</text><text x="74" y="88" font-size="10" font-weight="800" fill="#7c3aed">M</text><text x="202" y="88" font-size="10" font-weight="800" fill="#7c3aed">N</text><text x="140" y="110" text-anchor="middle" font-size="9" fill="#7c3aed">A'M=AB, MN∥B'C'</text></svg>`},
{desc:'<b>Шаг 3.</b> По теореме о прямой, параллельной стороне (§4): $\\dfrac{A\'M}{A\'B\'} = \\dfrac{A\'N}{A\'C\'}$. Так как $A\'M = AB$ и $\\dfrac{AB}{A\'B\'} = k$, получаем $A\'N = A\'C\' \\cdot \\dfrac{AB}{A\'B\'}= AC$.',
svg:`<svg viewBox="0 0 280 90" style="max-width:280px;background:#fafafa;border:1px solid var(--border);border-radius:10px"><text x="140" y="22" text-anchor="middle" font-size="11" fill="#4f46e5" font-weight="700">A'M/A'B' = A'N/A'C' (§4, пропорция)</text><text x="140" y="44" text-anchor="middle" font-size="11" fill="#7c3aed" font-weight="700">A'M=AB → A'N=AC</text><text x="140" y="70" text-anchor="middle" font-size="10" fill="#10b981" font-weight="800">Итак: A'M=AB, A'N=AC, ∠A'=∠A</text></svg>`},
{desc:'<b>Шаг 4.</b> Теперь: $A\'M = AB$, $A\'N = AC$, $\\angle A\' = \\angle A$. По признаку равенства треугольников (SAS): $\\triangle A\'MN \\cong \\triangle ABC$. Кроме того, $\\triangle A\'MN \\sim \\triangle A\'B\'C\'$ (§4).',
svg:`<svg viewBox="0 0 280 80" style="max-width:280px;background:#fafafa;border:1px solid var(--border);border-radius:10px"><text x="140" y="22" text-anchor="middle" font-size="11" fill="#4338ca" font-weight="700">△A'MN ≅ △ABC (SAS)</text><text x="140" y="44" text-anchor="middle" font-size="11" fill="#7c3aed" font-weight="700">△A'MN △A'B'C' (§4)</text><text x="140" y="66" text-anchor="middle" font-size="10" fill="#6366f1">По транзитивности подобия:</text></svg>`},
{desc:'<b>Шаг 5.</b> По транзитивности: $\\triangle ABC \\cong \\triangle A\'MN \\sim \\triangle A\'B\'C\'$ → $\\triangle ABC \\sim \\triangle A\'B\'C\'$. <b>Второй признак подобия (СУС) доказан.</b>',
svg:`<svg viewBox="0 0 280 80" style="max-width:280px;background:#fafafa;border:1px solid var(--border);border-radius:10px"><text x="140" y="26" text-anchor="middle" font-size="12" fill="#7c3aed" font-weight="800">AB/A'B'=AC/A'C'=k, ∠A=∠A' → △ABC∼△A'B'C'</text><text x="140" y="50" text-anchor="middle" font-size="10" fill="#6366f1">Признак СУС — второй признак подобия</text><text x="140" y="70" text-anchor="middle" font-size="12" fill="#10b981" font-weight="900">QED ∎</text></svg>`},
];
let step=0;
const svgEl=document.getElementById('p6-proof-svg');
const descEl=document.getElementById('p6-proof-desc');
function show(){svgEl.innerHTML=steps[step].svg;descEl.innerHTML=steps[step].desc;renderMath(descEl);}
document.getElementById('p6-proof-next').addEventListener('click',()=>{
if(step<steps.length-1){step++;show();addXp(1,'p6-proof-step');}
else{addXp(5,'p6-proof-done');bumpProgress('p6',10);}
});
document.getElementById('p6-proof-reset').addEventListener('click',()=>{step=0;show();});
show();
})();
/* == INIT ИНТЕРАКТИВ 3: калькулятор == */
(function(){
document.getElementById('p6-ccalc').addEventListener('click',()=>{
const AB=parseFloat(document.getElementById('p6-cAB').value);
const AC=parseFloat(document.getElementById('p6-cAC').value);
const ang=parseFloat(document.getElementById('p6-cAng').value);
const k=parseFloat(document.getElementById('p6-ck').value);
const out=document.getElementById('p6-ccalc-out');
if([AB,AC,ang,k].some(v=>!isFinite(v)||v<=0)){
out.style.display='block';out.innerHTML='<span style="color:var(--bad)">Введи все поля (положительные числа).</span>';return;
}
if(ang>=180){out.style.display='block';out.innerHTML='<span style="color:var(--bad)">Угол должен быть меньше 180°.</span>';return;}
const AB2=AB/k, AC2=AC/k;
const angRad=ang*Math.PI/180;
const BC=Math.sqrt(AB*AB+AC*AC-2*AB*AC*Math.cos(angRad));
const BC2=BC/k;
out.style.display='block';
out.innerHTML=`Второй треугольник: $A'B'=\\dfrac{AB}{k}=\\dfrac{${fmt(AB)}}{${fmt(k)}}=${fmt(AB2)}$, $A'C'=\\dfrac{AC}{k}=\\dfrac{${fmt(AC)}}{${fmt(k)}}=${fmt(AC2)}$, $\\angle A'=${fmt(ang)}°$.<br>По теореме косинусов: $BC=${fmt(BC)}$, $B'C'=${fmt(BC2)}$.<br>Треугольники подобны по признаку СУС с $k=${fmt(k)}$.`;
renderMath(out);
addXp(3,'p6-calc');bumpProgress('p6',5);
});
})();
/* == INIT ИНТЕРАКТИВ 4: тренажёр == */
(function(){
const tasks=[
{q:'$AB=12$, $AC=8$, $A\'B\'=6$, $A\'C\'=4$, $\\angle A=\\angle A\'=40°$. Найди коэффициент подобия $k=AB/A\'B\'$.',ans:2,hint:'k=12/6=2. Проверь: AC/A\'C\'=8/4=2. ✓'},
{q:'$PQ=15$, $PR=9$, $P\'Q\'=5$, $P\'R\'=3$, $\\angle P=\\angle P\'$. Подобны ли треугольники? Введи $k$ (или 0 если не подобны).',ans:3,hint:'PQ/P\'Q\'=15/5=3, PR/P\'R\'=9/3=3. Подобны, k=3.'},
{q:'$\\triangle ABC \\sim \\triangle A\'B\'C\'$ по СУС, $k=2.5$. $A\'B\'=6$. Найди $AB$.',ans:15,hint:'AB=k·A\'B\'=2.5·6=15.'},
{q:'$AB=10$, $AC=6$, $A\'B\'=4$, $A\'C\'=3$, $\\angle A=\\angle A\'$. Проверь подобие: $AB/A\'B\'=?$ (введи значение)',ans:2.5,hint:'AB/A\'B\'=10/4=2.5, AC/A\'C\'=6/3=2. Отношения разные → не подобны по СУС.'},
{q:'$\\triangle ABC \\sim \\triangle A\'B\'C\'$ по СУС, $k=3$. Стороны второго: $A\'B\'=4$, $A\'C\'=5$. Найди $AB+AC$.',ans:27,hint:'AB=3·4=12, AC=3·5=15. AB+AC=27.'},
];
let idx=0,score=0;
function show(){
document.getElementById('p6-tr-i').textContent=idx+1;
const t=document.getElementById('p6-tr-task');
t.innerHTML=tasks[idx].q;
renderMath(t);
document.getElementById('p6-tr-ans').value='';
document.getElementById('p6-tr-fb').style.display='none';
}
document.getElementById('p6-tr-start').addEventListener('click',()=>{idx=0;score=0;document.getElementById('p6-tr-score').textContent=0;show();});
document.getElementById('p6-tr-go').addEventListener('click',()=>{
if(idx>=tasks.length)return;
const ans=+document.getElementById('p6-tr-ans').value;
const fb=document.getElementById('p6-tr-fb');
if(Math.abs(ans-tasks[idx].ans)<0.05){
score++;document.getElementById('p6-tr-score').textContent=score;
addXp(3,'p6-tr-'+idx);bumpProgress('p6',4);
if(idx<tasks.length-1){feedback(fb,true,'Верно! +3 XP');idx++;setTimeout(()=>show(),900);}
else{feedback(fb,true,'Все задачи решены! +5 XP');addXp(5,'p6-tr-all');bumpProgress('p6',10);confetti();}
} else {
feedback(fb,false,'Неверно. '+tasks[idx].hint);
}
});
document.getElementById('p6-tr-ans').addEventListener('keydown',e=>{if(e.key==='Enter')document.getElementById('p6-tr-go').click();});
show();
})();
/* == INIT ИНТЕРАКТИВ 5: DnD-сортер == */
(function(){
const items=[
{text:'AB=6,AC=9,A\'B\'=4,A\'C\'=6, ∠A=∠A\'',yes:true},
{text:'AB=8,AC=6,A\'B\'=4,A\'C\'=4, ∠A=∠A\'',yes:false},
{text:'PQ=15,PR=10,P\'Q\'=6,P\'R\'=4, ∠P=∠P\'',yes:true},
{text:'AB=10,AC=6,A\'B\'=5,A\'C\'=4, ∠A=∠A\'',yes:false},
{text:'MK=12,ML=8,M\'K\'=9,M\'L\'=6, ∠M=∠M\'',yes:true},
];
const pool=document.getElementById('p6-dnd-pool');
const yesBox=document.getElementById('p6-drop-yes-items');
const noBox=document.getElementById('p6-drop-no-items');
let dragging=null;
function makeChip(it,idx){
const chip=document.createElement('div');
chip.className='dnd-chip';
chip.dataset.idx=idx;
chip.textContent=it.text;
chip.draggable=true;
chip.addEventListener('dragstart',e=>{dragging=chip;chip.classList.add('dragging');e.dataTransfer.effectAllowed='move';});
chip.addEventListener('dragend',()=>{chip.classList.remove('dragging');dragging=null;});
return chip;
}
items.forEach((it,i)=>pool.appendChild(makeChip(it,i)));
[document.getElementById('p6-drop-yes'),document.getElementById('p6-drop-no'),pool].forEach(box=>{
box.addEventListener('dragover',e=>{e.preventDefault();box.classList.add('over');});
box.addEventListener('dragleave',()=>box.classList.remove('over'));
box.addEventListener('drop',e=>{
e.preventDefault();box.classList.remove('over');
if(!dragging)return;
const target=box===document.getElementById('p6-drop-yes')?yesBox:box===document.getElementById('p6-drop-no')?noBox:pool;
target.appendChild(dragging);
});
});
document.getElementById('p6-dnd-check').addEventListener('click',()=>{
const fb=document.getElementById('p6-dnd-fb');
const yChips=[...yesBox.querySelectorAll('.dnd-chip')];
const nChips=[...noBox.querySelectorAll('.dnd-chip')];
if(yChips.length+nChips.length<items.length){feedback(fb,false,'Разложи все карточки.');return;}
let ok=true;
yChips.forEach(c=>{if(!items[+c.dataset.idx].yes)ok=false;});
nChips.forEach(c=>{if(items[+c.dataset.idx].yes)ok=false;});
if(ok){feedback(fb,true,'Верно! +5 XP');addXp(5,'p6-dnd');bumpProgress('p6',8);}
else{feedback(fb,false,'Есть ошибки. Проверь равенство отношений двух пар сторон и равенство углов между ними.');}
});
document.getElementById('p6-dnd-reset').addEventListener('click',()=>{
[...yesBox.children].forEach(c=>pool.appendChild(c));
[...noBox.children].forEach(c=>pool.appendChild(c));
document.getElementById('p6-dnd-fb').style.display='none';
});
})();
/* == INIT: Босс §6 == */
(function(){
const tasks=[
{q:'<svg viewBox="0 0 240 130" style="display:block;max-width:240px;margin:0 auto 8px;background:#ede9fe;border:1px solid #c4b5fd;border-radius:8px"><polygon points="100,15 25,120 205,120" fill="rgba(124,58,237,.12)" stroke="#7c3aed" stroke-width="2"/><polygon points="196,42 168,105 250,105" fill="rgba(99,102,241,.18)" stroke="#6366f1" stroke-width="1.8"/><text x="100" y="10" text-anchor="middle" font-size="10" fill="#6d28d9" font-weight="800">A</text><text x="16" y="128" font-size="10" fill="#6d28d9" font-weight="800">B</text><text x="207" y="128" font-size="10" fill="#6d28d9" font-weight="800">C</text><text x="196" y="37" text-anchor="middle" font-size="9" fill="#4f46e5" font-weight="800">A\'</text><text x="160" y="114" font-size="9" fill="#4f46e5" font-weight="800">B\'</text><text x="252" y="114" font-size="9" fill="#4f46e5" font-weight="800">C\'</text><text x="120" y="10" text-anchor="middle" font-size="8" fill="#7c3aed">AB=9, AC=12, A\'B\'=6, A\'C\'=8, ∠A=∠A\'</text></svg>$AB=9$, $AC=12$, $A\'B\'=6$, $A\'C\'=8$, $\\angle A=\\angle A\'$. Найди $k=AB/A\'B\'$.',ans:1.5,hint:'k=9/6=1.5. Проверь: 12/8=1.5. ✓ Признак СУС выполнен.'},
{q:'$\\triangle ABC \\sim \\triangle A\'B\'C\'$ по СУС, $k=4$. Стороны второго: $A\'B\'=3$, $A\'C\'=5$. Чему равно $AB+AC$?',ans:32,hint:'AB=4·3=12, AC=4·5=20. Сумма 32.'},
{q:'$AB=10$, $AC=15$, $\\angle A=60°$. По признаку СУС треугольник подобен другому с $k=2.5$. Найди $A\'B\'$.',ans:4,hint:'A\'B\'=AB/k=10/2.5=4.'},
{q:'Даны два треугольника: $AB=18$, $AC=12$, $A\'B\'=6$, $A\'C\'=4$, $\\angle A=\\angle A\'=75°$. Найди $BC$, если $B\'C\'=5$.',ans:15,hint:'k=18/6=3. BC=k·B\'C\'=3·5=15.'},
];
const bossBox=document.getElementById('p6-boss-tasks');
bossBox.innerHTML=tasks.map((t,i)=>`
<div style="padding:14px;background:var(--card);border-radius:10px;border:1px solid var(--border);margin-bottom:10px">
<div style="margin-bottom:8px;font-size:.95rem">${t.q}</div>
<div style="display:flex;gap:8px;flex-wrap:wrap;align-items:center">
<input type="number" class="tinp" id="p6b-a${i}" placeholder="Ответ" style="width:110px">
<button class="btn primary small" onclick="(function(){
const v=+document.getElementById('p6b-a${i}').value;
const fb=document.getElementById('p6b-fb${i}');
if(Math.abs(v-${t.ans})<0.05){
feedback(fb,true,'Верно! +5 XP');
if(!window.p6BossSolved.has(${i})){ window.p6BossSolved.add(${i}); addXp(5,'p6-boss${i}'); bumpProgress('p6',8); }
} else feedback(fb,false,'Неверно. ${t.hint}');
})()">Проверить</button>
</div>
<div class="feedback" id="p6b-fb${i}" style="display:none;margin-top:8px"></div>
</div>`).join('');
window.p6BossSolved=new Set();
renderMath(bossBox);
})();
}
function buildP7(){
const box=document.getElementById('p7-body');
let html='';
/* ---- Theory cards ---- */
html+=makeCard('theory','Третий признак подобия треугольников (ССС — три стороны)','7.1',`
<p><b>Теорема (3-й признак подобия, ССС).</b> Если три стороны одного треугольника пропорциональны трём сторонам другого треугольника, то такие треугольники подобны.</p>
<p style="margin-top:8px">Если $\\dfrac{a}{a'} = \\dfrac{b}{b'} = \\dfrac{c}{c'} = k$, то $\\triangle ABC \\sim \\triangle A'B'C'$.</p>
<p style="margin-top:8px">Здесь $a=BC$, $b=AC$, $c=AB$ и аналогично для второго треугольника. Это самый сильный признак — он <b>не требует</b> проверки углов.</p>
<div style="display:flex;justify-content:center;margin-top:14px">
<svg viewBox="0 0 300 165" style="max-width:320px;background:#fafafa;border:1px solid var(--border);border-radius:10px">
<!-- Triangle 1: A=(100,18) B=(28,140) C=(205,140) -->
<polygon points="100,18 28,140 205,140" fill="rgba(124,58,237,.11)" stroke="#7c3aed" stroke-width="2"/>
<text x="100" y="12" text-anchor="middle" font-size="11" font-weight="800" fill="#6d28d9">A</text>
<text x="18" y="149" font-size="11" font-weight="800" fill="#6d28d9">B</text>
<text x="208" y="149" font-size="11" font-weight="800" fill="#6d28d9">C</text>
<!-- Side labels t1 -->
<text x="55" y="96" text-anchor="middle" font-size="10" fill="#7c3aed" font-style="italic">c=AB</text>
<text x="115" y="155" text-anchor="middle" font-size="10" fill="#7c3aed" font-style="italic">a=BC</text>
<text x="160" y="93" text-anchor="middle" font-size="10" fill="#7c3aed" font-style="italic">b=AC</text>
<!-- Triangle 2: A'=(238,42) B'=(212,122) C'=(278,122) -->
<polygon points="238,42 212,122 278,122" fill="rgba(99,102,241,.18)" stroke="#6366f1" stroke-width="1.8"/>
<text x="238" y="36" text-anchor="middle" font-size="10" font-weight="800" fill="#4f46e5">A'</text>
<text x="202" y="131" font-size="10" font-weight="800" fill="#4f46e5">B'</text>
<text x="280" y="131" font-size="10" font-weight="800" fill="#4f46e5">C'</text>
<!-- Side labels t2 -->
<text x="221" y="87" text-anchor="middle" font-size="9" fill="#6366f1" font-style="italic">c'</text>
<text x="245" y="131" text-anchor="middle" font-size="9" fill="#6366f1" font-style="italic">a'</text>
<text x="263" y="86" text-anchor="middle" font-size="9" fill="#6366f1" font-style="italic">b'</text>
<!-- Ratio text -->
<text x="150" y="12" text-anchor="middle" font-size="9" fill="#f59e0b" font-weight="800">a/a' = b/b' = c/c' = k → △ABC∼△A'B'C'</text>
</svg>
</div>`);
html+=makeCard('rule','Доказательство 3-го признака — схема','7.2',`
<p>Доказательство сводится к 2-му признаку (СУС).</p>
<p style="margin-top:6px">Пусть $\\dfrac{a}{a'}=\\dfrac{b}{b'}=\\dfrac{c}{c'}=k$. На стороне $A'B'$ откладываем $A'M=AB=kA'B'$. Через $M \\parallel B'C'$ строим точку $N$ на $A'C'$, тогда $\\triangle A'MN \\sim \\triangle A'B'C'$ и все стороны $\\triangle A'MN$ равны сторонам $\\triangle ABC$.</p>
<p style="margin-top:6px">По признаку равенства SSS: $\\triangle A'MN \\cong \\triangle ABC$. Значит $\\triangle ABC \\sim \\triangle A'B'C'$ (транзитивность). <b>QED.</b></p>
<div style="display:flex;justify-content:center;margin-top:10px">
<svg viewBox="0 0 280 130" style="max-width:300px;background:#fafafa;border:1px solid var(--border);border-radius:10px">
<polygon points="140,14 30,122 250,122" fill="rgba(99,102,241,.10)" stroke="#6366f1" stroke-width="1.5"/>
<polygon points="140,14 82,72 198,72" fill="rgba(124,58,237,.22)" stroke="#7c3aed" stroke-width="2"/>
<line x1="82" y1="72" x2="198" y2="72" stroke="#7c3aed" stroke-width="2" stroke-dasharray="5,3"/>
<text x="140" y="9" text-anchor="middle" font-size="10" font-weight="800" fill="#4f46e5">A'</text>
<text x="20" y="130" font-size="10" font-weight="800" fill="#4f46e5">B'</text>
<text x="252" y="130" font-size="10" font-weight="800" fill="#4f46e5">C'</text>
<text x="76" y="82" font-size="10" font-weight="800" fill="#7c3aed">M</text>
<text x="200" y="82" font-size="10" font-weight="800" fill="#7c3aed">N</text>
<text x="140" y="105" text-anchor="middle" font-size="8" fill="#6366f1">△A'MN∼△A'B'C', △A'MN≅△ABC → △ABC∼△A'B'C'</text>
</svg>
</div>`);
html+=makeCard('example','Примеры применения признака ССС','7.3',`
<p><b>Пример 1.</b> $a=6$, $b=8$, $c=10$; $a'=3$, $b'=4$, $c'=5$. Подобны ли треугольники?</p>
<p style="margin-top:4px">$a/a'=6/3=2$, $b/b'=8/4=2$, $c/c'=10/5=2$. Все отношения равны $k=2$ → по ССС: подобны.</p>
<p style="margin-top:8px"><b>Пример 2.</b> $a=9$, $b=12$, $c=6$; $a'=6$, $b'=8$, $c'=4$. $9/6=1{,}5$, $12/8=1{,}5$, $6/4=1{,}5$. $k=1{,}5$ — подобны.</p>
<p style="margin-top:8px"><b>Пример 3 (не подобны).</b> $a=5$, $b=7$, $c=9$; $a'=5$, $b'=7$, $c'=10$. $5/5=1$, $7/7=1$, $9/10=0{,}9$. Отношения различны → <b>не подобны</b>.</p>`);
/* ---- ИНТЕРАКТИВ 1: SVG три стороны + слайдер k ---- */
html+=`<div class="wg" id="p7-svg-wg">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 1</span><div class="wg-title">Два треугольника — признак ССС</div></div>
<div class="wg-help">Задай три стороны первого треугольника и коэффициент $k$. Второй строится автоматически: все стороны уменьшены в $k$ раз. Треугольное неравенство проверяется автоматически.</div>
<div class="sliders">
<label>Сторона $a$: <b id="p7-a-val">6</b>
<input type="range" min="3" max="14" value="6" id="p7-a-sl" step="1">
</label>
<label>Сторона $b$: <b id="p7-b-val">8</b>
<input type="range" min="3" max="14" value="8" id="p7-b-sl" step="1">
</label>
<label>Сторона $c$: <b id="p7-c-val">9</b>
<input type="range" min="3" max="14" value="9" id="p7-c-sl" step="1">
</label>
<label>Коэффициент $k$: <b id="p7-k-val">2.0</b>
<input type="range" min="12" max="35" value="20" id="p7-k-sl" step="1">
</label>
</div>
<div id="p7-svg-out" style="display:flex;justify-content:center"></div>
<div id="p7-svg-info" style="margin-top:10px;padding:10px 14px;background:var(--sec-acc-soft,var(--pri-soft));border-radius:10px;font-size:.92rem;line-height:1.8"></div>
</div>`;
/* ---- ИНТЕРАКТИВ 2: Пошаговое доказательство ---- */
html+=`<div class="wg" id="p7-proof-wg">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 2</span><div class="wg-title">Доказательство 3-го признака — по шагам</div></div>
<div class="wg-help">Нажимай «Далее» для каждого шага доказательства признака ССС.</div>
<div id="p7-proof-svg" style="display:flex;justify-content:center;margin-bottom:10px"></div>
<div id="p7-proof-desc" style="padding:10px 14px;background:var(--sec-acc-soft,var(--pri-soft));border-radius:10px;font-size:.95rem;line-height:1.6;margin-bottom:10px;min-height:60px"></div>
<div style="display:flex;gap:8px">
<button class="btn primary" id="p7-proof-next">Далее</button>
<button class="btn" id="p7-proof-reset">Сначала</button>
</div>
</div>`;
/* ---- ИНТЕРАКТИВ 3: Калькулятор ССС ---- */
html+=`<div class="wg">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 3</span><div class="wg-title">Калькулятор: проверка подобия по трём сторонам</div></div>
<div class="wg-help">Введи стороны двух треугольников — система проверит пропорциональность и найдёт $k$.</div>
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(90px,1fr));gap:8px;margin-bottom:10px">
<div><span style="font-size:.8rem;color:var(--muted);display:block">a (BC)</span><input type="number" id="p7-ca" class="tinp" placeholder="напр. 6" style="width:100%"></div>
<div><span style="font-size:.8rem;color:var(--muted);display:block">b (AC)</span><input type="number" id="p7-cb" class="tinp" placeholder="напр. 8" style="width:100%"></div>
<div><span style="font-size:.8rem;color:var(--muted);display:block">c (AB)</span><input type="number" id="p7-cc" class="tinp" placeholder="напр. 10" style="width:100%"></div>
<div><span style="font-size:.8rem;color:var(--muted);display:block">a' (B'C')</span><input type="number" id="p7-ca2" class="tinp" placeholder="напр. 3" style="width:100%"></div>
<div><span style="font-size:.8rem;color:var(--muted);display:block">b' (A'C')</span><input type="number" id="p7-cb2" class="tinp" placeholder="напр. 4" style="width:100%"></div>
<div><span style="font-size:.8rem;color:var(--muted);display:block">c' (A'B')</span><input type="number" id="p7-cc2" class="tinp" placeholder="напр. 5" style="width:100%"></div>
<div style="display:flex;align-items:flex-end"><button class="btn primary" id="p7-ccalc" style="width:100%">Проверить</button></div>
</div>
<div id="p7-ccalc-out" style="display:none;padding:10px 14px;background:var(--sec-acc-soft,var(--pri-soft));border-radius:10px;font-size:.95rem;line-height:1.7"></div>
</div>`;
/* ---- ИНТЕРАКТИВ 4: Тренажёр ---- */
html+=`<div class="wg">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 4</span><div class="wg-title">Тренажёр §7 — Признак ССС</div></div>
<div class="wg-help">5 задач на проверку подобия по сторонам и нахождение коэффициента.</div>
<div class="score-display"><span>Задача <b id="p7-tr-i">1</b> / 5</span><span>Очки: <b id="p7-tr-score">0</b></span></div>
<div id="p7-tr-task" style="padding:14px;background:var(--sec-acc-soft,var(--pri-soft));border-radius:10px;font-size:1.02rem;margin-bottom:10px"></div>
<div style="display:flex;gap:8px;align-items:center;flex-wrap:wrap">
<input type="number" id="p7-tr-ans" class="tinp" placeholder="Ответ" style="width:130px">
<button class="btn primary" id="p7-tr-go">Проверить</button>
<button class="btn" id="p7-tr-start">Начать</button>
</div>
<div class="feedback" id="p7-tr-fb" style="display:none"></div>
</div>`;
/* ---- ИНТЕРАКТИВ 5: DnD-сортер ---- */
html+=`<div class="wg">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 5</span><div class="wg-title">Подобны по ССС или нет? — Сортировка</div></div>
<div class="wg-help">Перетащи каждую пару троек сторон в нужную колонку.</div>
<div id="p7-dnd-pool" class="dnd-pool"></div>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-top:10px">
<div class="drop-box" id="p7-drop-yes"><h5>Подобны (ССС)</h5><div class="drop-items" id="p7-drop-yes-items"></div></div>
<div class="drop-box" id="p7-drop-no"><h5>Не подобны</h5><div class="drop-items" id="p7-drop-no-items"></div></div>
</div>
<div class="actions"><button class="btn primary" id="p7-dnd-check">Проверить</button><button class="btn" id="p7-dnd-reset">Сбросить</button></div>
<div class="feedback" id="p7-dnd-fb" style="display:none"></div>
</div>`;
/* ---- ИНТЕРАКТИВ 6: Мини-квиз (три признака) ---- */
html+=`<div class="wg">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 6</span><div class="wg-title">Мини-квиз: все три признака подобия</div></div>
<div class="wg-help">5 вопросов о трёх признаках подобия. Выбери правильный ответ.</div>
<div id="p7-quiz-wrap"></div>
<div class="actions"><button class="btn primary" id="p7-quiz-check">Проверить</button></div>
<div class="feedback" id="p7-quiz-fb" style="display:none"></div>
</div>`;
/* ---- ИНТЕРАКТИВ 7: Босс §7 ---- */
html+=`<div class="wg" style="border-color:var(--sec-acc-d,var(--pri2))">
<div class="wg-header"><span class="wg-badge" style="background:var(--sec-acc-d,var(--pri2))">БОСС §7</span><div class="wg-title">Итоговые задачи</div></div>
<div class="wg-help">4 задачи — каждая верная даёт +5 XP.</div>
<div id="p7-boss-tasks"></div>
</div>`;
html+=`<div style="margin-top:18px;display:flex;justify-content:center">
<button class="btn primary" id="p7-read-btn" onclick="addXp(10,'p7-read');bumpProgress('p7',40);this.textContent='Прочитано!';this.disabled=true;">
<svg class="ic" viewBox="0 0 24 24"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/></svg>
Я прочитал §7 (+10 XP)
</button>
</div>`;
html+=secNav('p6','p8');
box.innerHTML=html;
if(window.renderMathInElement) setTimeout(()=>renderMath(box),0);
/* == INIT ИНТЕРАКТИВ 1: SVG по трём сторонам == */
(function(){
const aSl=document.getElementById('p7-a-sl');
const bSl=document.getElementById('p7-b-sl');
const cSl=document.getElementById('p7-c-sl');
const kSl=document.getElementById('p7-k-sl');
const aVal=document.getElementById('p7-a-val');
const bVal=document.getElementById('p7-b-val');
const cVal=document.getElementById('p7-c-val');
const kVal=document.getElementById('p7-k-val');
const svgOut=document.getElementById('p7-svg-out');
const infoEl=document.getElementById('p7-svg-info');
function triFromSSS(aa,bb,cc,ox,oy){
// a=BC, b=AC, c=AB. Place B=(ox,oy), C=(ox+a,oy)
// Find A using law of cosines: cosB=(c²+a²-b²)/(2ca)
const cosB=(cc*cc+aa*aa-bb*bb)/(2*cc*aa);
if(cosB<-1||cosB>1) return null;
const Bx=ox, By=oy;
const Cx=ox+aa, Cy=oy;
const Ax=ox+cc*cosB;
const Ay=oy-cc*Math.sqrt(1-cosB*cosB);
return {Ax,Ay,Bx,By,Cx,Cy};
}
function draw(){
const a=+aSl.value, b=+bSl.value, c=+cSl.value;
const k=+kSl.value/10;
aVal.textContent=a; bVal.textContent=b; cVal.textContent=c;
kVal.textContent=k.toFixed(1);
// Triangle inequality check
if(a+b<=c||a+c<=b||b+c<=a){
svgOut.innerHTML='<div style="color:var(--bad);padding:10px">Нарушено треугольное неравенство. Измени стороны.</div>';
infoEl.innerHTML='Треугольное неравенство нарушено.';
return;
}
const scale=13;
const a2=a/k, b2=b/k, c2=c/k;
const W=400, H=185;
const t1=triFromSSS(a*scale,b*scale,c*scale,18,165);
if(!t1){svgOut.innerHTML='';return;}
const t2=triFromSSS(a2*scale,b2*scale,c2*scale,230,165);
if(!t2){svgOut.innerHTML='';return;}
let s=`<svg viewBox="0 0 ${W} ${H}" style="max-width:${W}px;width:100%;background:#fafafa;border:1px solid var(--border);border-radius:10px">`;
s+=`<polygon points="${t1.Ax},${t1.Ay} ${t1.Bx},${t1.By} ${t1.Cx},${t1.Cy}" fill="rgba(124,58,237,.12)" stroke="#7c3aed" stroke-width="2"/>`;
s+=`<text x="${t1.Ax}" y="${t1.Ay-5}" text-anchor="middle" font-size="11" font-weight="800" fill="#6d28d9">A</text>`;
s+=`<text x="${t1.Bx-8}" y="${t1.By+4}" font-size="11" font-weight="800" fill="#6d28d9">B</text>`;
s+=`<text x="${t1.Cx+4}" y="${t1.Cy+4}" font-size="11" font-weight="800" fill="#6d28d9">C</text>`;
const mBCx=(t1.Bx+t1.Cx)/2, mBCy=(t1.By+t1.Cy)/2;
const mACx=(t1.Ax+t1.Cx)/2, mACy=(t1.Ay+t1.Cy)/2;
const mABx=(t1.Ax+t1.Bx)/2, mABy=(t1.Ay+t1.By)/2;
s+=`<text x="${mBCx}" y="${mBCy+11}" text-anchor="middle" font-size="9" fill="#7c3aed">a=${a}</text>`;
s+=`<text x="${mACx+8}" y="${mACy}" font-size="9" fill="#7c3aed">b=${b}</text>`;
s+=`<text x="${mABx-8}" y="${mABy}" text-anchor="end" font-size="9" fill="#7c3aed">c=${c}</text>`;
s+=`<polygon points="${t2.Ax},${t2.Ay} ${t2.Bx},${t2.By} ${t2.Cx},${t2.Cy}" fill="rgba(99,102,241,.18)" stroke="#6366f1" stroke-width="1.8"/>`;
s+=`<text x="${t2.Ax}" y="${t2.Ay-5}" text-anchor="middle" font-size="10" font-weight="800" fill="#4f46e5">A'</text>`;
s+=`<text x="${t2.Bx-10}" y="${t2.By+4}" font-size="10" font-weight="800" fill="#4f46e5">B'</text>`;
s+=`<text x="${t2.Cx+4}" y="${t2.Cy+4}" font-size="10" font-weight="800" fill="#4f46e5">C'</text>`;
const mBCx2=(t2.Bx+t2.Cx)/2, mBCy2=(t2.By+t2.Cy)/2;
const mACx2=(t2.Ax+t2.Cx)/2, mACy2=(t2.Ay+t2.Cy)/2;
const mABx2=(t2.Ax+t2.Bx)/2, mABy2=(t2.Ay+t2.By)/2;
s+=`<text x="${mBCx2}" y="${mBCy2+11}" text-anchor="middle" font-size="9" fill="#6366f1">a'=${fmt(a2)}</text>`;
s+=`<text x="${mACx2+6}" y="${mACy2}" font-size="9" fill="#6366f1">b'=${fmt(b2)}</text>`;
s+=`<text x="${mABx2-6}" y="${mABy2}" text-anchor="end" font-size="9" fill="#6366f1">c'=${fmt(c2)}</text>`;
s+=`<text x="${W/2}" y="12" text-anchor="middle" font-size="10" font-weight="800" fill="#7c3aed">k = ${k.toFixed(1)}</text>`;
s+='</svg>';
svgOut.innerHTML=s;
infoEl.innerHTML=`$a=${a}$, $b=${b}$, $c=${c}$. Второй: $a'=${fmt(a2)}$, $b'=${fmt(b2)}$, $c'=${fmt(c2)}$. $\\dfrac{a}{a'}=\\dfrac{b}{b'}=\\dfrac{c}{c'}=${k.toFixed(1)}$ → по признаку ССС треугольники подобны.`;
renderMath(infoEl);
addXp(1,'p7-svg');
}
aSl.addEventListener('input',draw);
bSl.addEventListener('input',draw);
cSl.addEventListener('input',draw);
kSl.addEventListener('input',draw);
draw();
})();
/* == INIT ИНТЕРАКТИВ 2: пошаговое доказательство == */
(function(){
const steps=[
{desc:'<b>Шаг 1.</b> Дано: $\\dfrac{a}{a\'}=\\dfrac{b}{b\'}=\\dfrac{c}{c\'}=k$. Нужно доказать: $\\triangle ABC \\sim \\triangle A\'B\'C\'$.',
svg:`<svg viewBox="0 0 280 140" style="max-width:280px;background:#fafafa;border:1px solid var(--border);border-radius:10px"><polygon points="100,18 28,132 210,132" fill="rgba(124,58,237,.10)" stroke="#7c3aed" stroke-width="2"/><polygon points="210,46 188,112 258,112" fill="rgba(99,102,241,.18)" stroke="#6366f1" stroke-width="1.8"/><text x="100" y="13" text-anchor="middle" font-size="11" font-weight="800" fill="#6d28d9">A</text><text x="18" y="140" font-size="11" font-weight="800" fill="#6d28d9">B</text><text x="213" y="140" font-size="11" font-weight="800" fill="#6d28d9">C</text><text x="210" y="41" text-anchor="middle" font-size="10" font-weight="800" fill="#4f46e5">A'</text><text x="180" y="120" font-size="10" font-weight="800" fill="#4f46e5">B'</text><text x="260" y="120" font-size="10" font-weight="800" fill="#4f46e5">C'</text><text x="140" y="12" text-anchor="middle" font-size="9" fill="#f59e0b" font-weight="800">a/a'=b/b'=c/c'=k — условие</text></svg>`},
{desc:'<b>Шаг 2.</b> На луче $A\'B\'$ откладываем $A\'M = AB = k \\cdot A\'B\'$. Через $M$ проводим $MN \\parallel B\'C\'$, $N$ на $A\'C\'$. По теореме §4: $\\triangle A\'MN \\sim \\triangle A\'B\'C\'$.',
svg:`<svg viewBox="0 0 280 140" style="max-width:280px;background:#fafafa;border:1px solid var(--border);border-radius:10px"><polygon points="140,14 30,126 250,126" fill="rgba(99,102,241,.10)" stroke="#6366f1" stroke-width="1.5"/><polygon points="140,14 82,70 198,70" fill="rgba(124,58,237,.22)" stroke="#7c3aed" stroke-width="2"/><line x1="82" y1="70" x2="198" y2="70" stroke="#7c3aed" stroke-width="2" stroke-dasharray="5,3"/><text x="140" y="9" text-anchor="middle" font-size="10" font-weight="800" fill="#4f46e5">A'</text><text x="20" y="134" font-size="10" font-weight="800" fill="#4f46e5">B'</text><text x="252" y="134" font-size="10" font-weight="800" fill="#4f46e5">C'</text><text x="76" y="80" font-size="10" font-weight="800" fill="#7c3aed">M</text><text x="200" y="80" font-size="10" font-weight="800" fill="#7c3aed">N</text><text x="140" y="110" text-anchor="middle" font-size="9" fill="#7c3aed">A'M=AB, MN∥B'C'</text></svg>`},
{desc:'<b>Шаг 3.</b> Поскольку $\\triangle A\'MN \\sim \\triangle A\'B\'C\'$ с коэффициентом $k$, все стороны $\\triangle A\'MN$ равны соответствующим сторонам $\\triangle ABC$: $A\'M=AB$, $MN=a$, $A\'N=b$.',
svg:`<svg viewBox="0 0 280 90" style="max-width:280px;background:#fafafa;border:1px solid var(--border);border-radius:10px"><text x="140" y="22" text-anchor="middle" font-size="11" fill="#4f46e5" font-weight="700">△A'MN∼△A'B'C' с коэфф. k</text><text x="140" y="44" text-anchor="middle" font-size="11" fill="#7c3aed" font-weight="700">A'M=AB=c, MN=BC=a, A'N=AC=b</text><text x="140" y="68" text-anchor="middle" font-size="10" fill="#10b981" font-weight="800">Все стороны △A'MN = сторонам △ABC</text></svg>`},
{desc:'<b>Шаг 4.</b> По признаку равенства треугольников (SSS): $\\triangle A\'MN \\cong \\triangle ABC$ (у них равны все три пары сторон).',
svg:`<svg viewBox="0 0 280 80" style="max-width:280px;background:#fafafa;border:1px solid var(--border);border-radius:10px"><text x="140" y="26" text-anchor="middle" font-size="12" fill="#4338ca" font-weight="800">△A'MN ≅ △ABC (SSS)</text><text x="140" y="52" text-anchor="middle" font-size="10" fill="#6366f1">Три стороны равны попарно → конгруэнтны</text><text x="140" y="70" text-anchor="middle" font-size="9" fill="#7c3aed">△A'MN∼△A'B'C' также выполнено</text></svg>`},
{desc:'<b>Шаг 5.</b> По транзитивности: $\\triangle ABC \\cong \\triangle A\'MN \\sim \\triangle A\'B\'C\'$ → $\\triangle ABC \\sim \\triangle A\'B\'C\'$. <b>Третий признак подобия (ССС) доказан.</b>',
svg:`<svg viewBox="0 0 280 80" style="max-width:280px;background:#fafafa;border:1px solid var(--border);border-radius:10px"><text x="140" y="26" text-anchor="middle" font-size="12" fill="#7c3aed" font-weight="800">a/a'=b/b'=c/c'=k → △ABC∼△A'B'C'</text><text x="140" y="50" text-anchor="middle" font-size="10" fill="#6366f1">Признак ССС — третий признак подобия</text><text x="140" y="70" text-anchor="middle" font-size="12" fill="#10b981" font-weight="900">QED ∎</text></svg>`},
];
let step=0;
const svgEl=document.getElementById('p7-proof-svg');
const descEl=document.getElementById('p7-proof-desc');
function show(){svgEl.innerHTML=steps[step].svg;descEl.innerHTML=steps[step].desc;renderMath(descEl);}
document.getElementById('p7-proof-next').addEventListener('click',()=>{
if(step<steps.length-1){step++;show();addXp(1,'p7-proof-step');}
else{addXp(5,'p7-proof-done');bumpProgress('p7',10);}
});
document.getElementById('p7-proof-reset').addEventListener('click',()=>{step=0;show();});
show();
})();
/* == INIT ИНТЕРАКТИВ 3: калькулятор ССС == */
(function(){
document.getElementById('p7-ccalc').addEventListener('click',()=>{
const a=parseFloat(document.getElementById('p7-ca').value);
const b=parseFloat(document.getElementById('p7-cb').value);
const c=parseFloat(document.getElementById('p7-cc').value);
const a2=parseFloat(document.getElementById('p7-ca2').value);
const b2=parseFloat(document.getElementById('p7-cb2').value);
const c2=parseFloat(document.getElementById('p7-cc2').value);
const out=document.getElementById('p7-ccalc-out');
if([a,b,c,a2,b2,c2].some(v=>!isFinite(v)||v<=0)){
out.style.display='block';out.innerHTML='<span style="color:var(--bad)">Введи все шесть сторон.</span>';return;
}
const k1=a/a2, k2=b/b2, k3=c/c2;
const tol=0.001;
const ok=Math.abs(k1-k2)<tol&&Math.abs(k2-k3)<tol;
out.style.display='block';
if(ok){
out.innerHTML=`$\\dfrac{a}{a'}=\\dfrac{${fmt(a)}}{${fmt(a2)}}=${fmt(k1)}$, $\\dfrac{b}{b'}=\\dfrac{${fmt(b)}}{${fmt(b2)}}=${fmt(k2)}$, $\\dfrac{c}{c'}=\\dfrac{${fmt(c)}}{${fmt(c2)}}=${fmt(k3)}$.<br><b>Все отношения равны $k=${fmt(k1)}$</b> → треугольники <b>подобны по признаку ССС</b>.`;
addXp(3,'p7-calc');bumpProgress('p7',5);
} else {
out.innerHTML=`$\\dfrac{a}{a'}=${fmt(k1)}$, $\\dfrac{b}{b'}=${fmt(k2)}$, $\\dfrac{c}{c'}=${fmt(k3)}$.<br>Отношения <b>не равны</b> → треугольники <b>не подобны</b> по признаку ССС.`;
}
renderMath(out);
});
})();
/* == INIT ИНТЕРАКТИВ 4: тренажёр == */
(function(){
const tasks=[
{q:'$a=9$, $b=12$, $c=6$; $a\'=3$, $b\'=4$, $c\'=2$. Найди коэффициент подобия $k=a/a\'$.',ans:3,hint:'9/3=12/4=6/2=3. k=3.'},
{q:'$\\triangle ABC \\sim \\triangle A\'B\'C\'$ по ССС, $k=2.5$. Стороны первого: $a=10$, $b=15$. Найди $a\'$.',ans:4,hint:'a\'=a/k=10/2.5=4.'},
{q:'Стороны: $(6,8,10)$ и $(3,4,5)$. Подобны ли? Введи $k$ (или 0 если нет).',ans:2,hint:'6/3=8/4=10/5=2. Подобны, k=2.'},
{q:'$a=5$, $b=7$, $c=9$; $a\'=5$, $b\'=7$, $c\'=10$. Подобны ли? Введи $k$ (или 0 если нет).',ans:0,hint:'5/5=1, 7/7=1, но 9/10≠1. Не подобны. Ответ 0.'},
{q:'$\\triangle ABC \\sim \\triangle A\'B\'C\'$ по ССС, $k=4$. Периметр $\\triangle A\'B\'C\'=21$. Найди периметр $\\triangle ABC$.',ans:84,hint:'P=k·P\'=4·21=84.'},
];
let idx=0,score=0;
function show(){
document.getElementById('p7-tr-i').textContent=idx+1;
const t=document.getElementById('p7-tr-task');
t.innerHTML=tasks[idx].q;
renderMath(t);
document.getElementById('p7-tr-ans').value='';
document.getElementById('p7-tr-fb').style.display='none';
}
document.getElementById('p7-tr-start').addEventListener('click',()=>{idx=0;score=0;document.getElementById('p7-tr-score').textContent=0;show();});
document.getElementById('p7-tr-go').addEventListener('click',()=>{
if(idx>=tasks.length)return;
const ans=+document.getElementById('p7-tr-ans').value;
const fb=document.getElementById('p7-tr-fb');
if(Math.abs(ans-tasks[idx].ans)<0.05){
score++;document.getElementById('p7-tr-score').textContent=score;
addXp(3,'p7-tr-'+idx);bumpProgress('p7',4);
if(idx<tasks.length-1){feedback(fb,true,'Верно! +3 XP');idx++;setTimeout(()=>show(),900);}
else{feedback(fb,true,'Все задачи решены! +5 XP');addXp(5,'p7-tr-all');bumpProgress('p7',10);confetti();}
} else {
feedback(fb,false,'Неверно. '+tasks[idx].hint);
}
});
document.getElementById('p7-tr-ans').addEventListener('keydown',e=>{if(e.key==='Enter')document.getElementById('p7-tr-go').click();});
show();
})();
/* == INIT ИНТЕРАКТИВ 5: DnD-сортер ССС == */
(function(){
const items=[
{text:'(6,8,10) и (3,4,5)',yes:true},
{text:'(5,7,9) и (5,7,10)',yes:false},
{text:'(9,12,6) и (6,8,4)',yes:true},
{text:'(4,6,8) и (3,5,8)',yes:false},
{text:'(15,10,5) и (6,4,2)',yes:true},
];
const pool=document.getElementById('p7-dnd-pool');
const yesBox=document.getElementById('p7-drop-yes-items');
const noBox=document.getElementById('p7-drop-no-items');
let dragging=null;
function makeChip(it,idx){
const chip=document.createElement('div');
chip.className='dnd-chip';
chip.dataset.idx=idx;
chip.textContent=it.text;
chip.draggable=true;
chip.addEventListener('dragstart',e=>{dragging=chip;chip.classList.add('dragging');e.dataTransfer.effectAllowed='move';});
chip.addEventListener('dragend',()=>{chip.classList.remove('dragging');dragging=null;});
return chip;
}
items.forEach((it,i)=>pool.appendChild(makeChip(it,i)));
[document.getElementById('p7-drop-yes'),document.getElementById('p7-drop-no'),pool].forEach(box=>{
box.addEventListener('dragover',e=>{e.preventDefault();box.classList.add('over');});
box.addEventListener('dragleave',()=>box.classList.remove('over'));
box.addEventListener('drop',e=>{
e.preventDefault();box.classList.remove('over');
if(!dragging)return;
const target=box===document.getElementById('p7-drop-yes')?yesBox:box===document.getElementById('p7-drop-no')?noBox:pool;
target.appendChild(dragging);
});
});
document.getElementById('p7-dnd-check').addEventListener('click',()=>{
const fb=document.getElementById('p7-dnd-fb');
const yChips=[...yesBox.querySelectorAll('.dnd-chip')];
const nChips=[...noBox.querySelectorAll('.dnd-chip')];
if(yChips.length+nChips.length<items.length){feedback(fb,false,'Разложи все карточки.');return;}
let ok=true;
yChips.forEach(c=>{if(!items[+c.dataset.idx].yes)ok=false;});
nChips.forEach(c=>{if(items[+c.dataset.idx].yes)ok=false;});
if(ok){feedback(fb,true,'Верно! +5 XP');addXp(5,'p7-dnd');bumpProgress('p7',8);}
else{feedback(fb,false,'Есть ошибки. Проверь: все три отношения a/a\', b/b\', c/c\' должны быть равны.');}
});
document.getElementById('p7-dnd-reset').addEventListener('click',()=>{
[...yesBox.children].forEach(c=>pool.appendChild(c));
[...noBox.children].forEach(c=>pool.appendChild(c));
document.getElementById('p7-dnd-fb').style.display='none';
});
})();
/* == INIT ИНТЕРАКТИВ 6: мини-квиз == */
(function(){
const qs=[
{q:'По какому признаку два угла одного треугольника равны двум углам другого?',opts:['ДД','СУС','ССС','Нет такого признака'],ans:0},
{q:'Сколько признаков подобия треугольников есть в курсе 8 класса?',opts:['1','2','3','4'],ans:2},
{q:'Признак СУС требует равенства...',opts:['двух углов','двух сторон и угла между ними','трёх сторон','двух сторон и угла напротив'],ans:1},
{q:'Если $a/a\'=2$, $b/b\'=2$, $c/c\'=2$, то треугольники подобны по признаку...',opts:['ДД','СУС','ССС','Нельзя определить'],ans:2},
{q:'По признаку ССС требуется проверить...',opts:['2 угла','2 стороны и угол','3 стороны','1 угол и 2 стороны'],ans:2},
];
const wrap=document.getElementById('p7-quiz-wrap');
wrap.innerHTML=qs.map((q,qi)=>`
<div style="margin-bottom:14px;padding:12px;background:var(--card);border:1px solid var(--border);border-radius:10px">
<div style="font-weight:700;margin-bottom:8px;font-size:.95rem">${qi+1}. ${q.q}</div>
<div style="display:flex;flex-direction:column;gap:6px">
${q.opts.map((o,oi)=>`<label style="display:flex;align-items:center;gap:8px;cursor:pointer;font-size:.92rem"><input type="radio" name="p7q${qi}" value="${oi}" style="accent-color:var(--sec-acc,var(--pri))"> ${o}</label>`).join('')}
</div>
</div>`).join('');
document.getElementById('p7-quiz-check').addEventListener('click',()=>{
const fb=document.getElementById('p7-quiz-fb');
let correct=0;
qs.forEach((q,qi)=>{
const sel=document.querySelector(`input[name="p7q${qi}"]:checked`);
if(sel&&+sel.value===q.ans)correct++;
});
if(correct===qs.length){
feedback(fb,true,`Все ${qs.length} ответов верны! +8 XP`);
addXp(8,'p7-quiz');bumpProgress('p7',12);confetti();
} else {
feedback(fb,false,`Верных ответов: ${correct} из ${qs.length}. Повтори параграфы с признаками.`);
}
});
})();
/* == INIT: Босс §7 == */
(function(){
const tasks=[
{q:'<svg viewBox="0 0 240 128" style="display:block;max-width:240px;margin:0 auto 8px;background:#ddd6fe;border:1px solid #c4b5fd;border-radius:8px"><polygon points="100,14 24,118 210,118" fill="rgba(124,58,237,.12)" stroke="#7c3aed" stroke-width="2"/><polygon points="196,40 168,108 252,108" fill="rgba(99,102,241,.18)" stroke="#6366f1" stroke-width="1.8"/><text x="100" y="9" text-anchor="middle" font-size="10" fill="#6d28d9" font-weight="800">A</text><text x="14" y="126" font-size="10" fill="#6d28d9" font-weight="800">B</text><text x="213" y="126" font-size="10" fill="#6d28d9" font-weight="800">C</text><text x="196" y="35" text-anchor="middle" font-size="9" fill="#4f46e5" font-weight="800">A\'</text><text x="160" y="116" font-size="9" fill="#4f46e5" font-weight="800">B\'</text><text x="254" y="116" font-size="9" fill="#4f46e5" font-weight="800">C\'</text><text x="120" y="9" text-anchor="middle" font-size="8" fill="#7c3aed">a=12,b=9,c=15; a\'=8,b\'=6,c\'=10</text></svg>$a=12$, $b=9$, $c=15$; $a\'=8$, $b\'=6$, $c\'=10$. Найди $k=a/a\'$.',ans:1.5,hint:'12/8=9/6=15/10=1.5. k=1.5. Признак ССС выполнен.'},
{q:'$\\triangle ABC \\sim \\triangle A\'B\'C\'$ по ССС, $k=3$. Периметр $\\triangle A\'B\'C\'=28$. Найди периметр $\\triangle ABC$.',ans:84,hint:'P=3·28=84.'},
{q:'Стороны первого: $4, 6, 8$. Стороны второго: $6, 9, 12$. По какому признаку они подобны? Введи $k$ (большего к меньшему).',ans:1.5,hint:'6/4=9/6=12/8=1.5. Признак ССС. k=1.5.'},
{q:'$\\triangle DEF$: $DE=10$, $EF=24$, $DF=26$ (прямоугольный). $\\triangle D\'E\'F\'$: $D\'E\'=5$, $E\'F\'=12$, $D\'F\'=13$. Найди $k$.',ans:2,hint:'10/5=24/12=26/13=2. k=2. Признак ССС.'},
];
const bossBox=document.getElementById('p7-boss-tasks');
bossBox.innerHTML=tasks.map((t,i)=>`
<div style="padding:14px;background:var(--card);border-radius:10px;border:1px solid var(--border);margin-bottom:10px">
<div style="margin-bottom:8px;font-size:.95rem">${t.q}</div>
<div style="display:flex;gap:8px;flex-wrap:wrap;align-items:center">
<input type="number" class="tinp" id="p7b-a${i}" placeholder="Ответ" style="width:110px">
<button class="btn primary small" onclick="(function(){
const v=+document.getElementById('p7b-a${i}').value;
const fb=document.getElementById('p7b-fb${i}');
if(Math.abs(v-${t.ans})<0.05){
feedback(fb,true,'Верно! +5 XP');
if(!window.p7BossSolved.has(${i})){ window.p7BossSolved.add(${i}); addXp(5,'p7-boss${i}'); bumpProgress('p7',8); }
} else feedback(fb,false,'Неверно. ${t.hint}');
})()">Проверить</button>
</div>
<div class="feedback" id="p7b-fb${i}" style="display:none;margin-top:8px"></div>
</div>`).join('');
window.p7BossSolved=new Set();
renderMath(bossBox);
})();
}
function buildP8stub(){ document.getElementById('p8-body').innerHTML='<div class="card"><div class="card-body"><p><b>§8 — Волна 1</b>: содержимое появится в следующем обновлении.</p></div></div>'+secNav('p7','p9'); }
function buildP9stub(){ document.getElementById('p9-body').innerHTML='<div class="card"><div class="card-body"><p><b>§9 — Волна 1</b>: содержимое появится в следующем обновлении.</p></div></div>'+secNav('p8','final3'); }
function buildFinal3stub(){ document.getElementById('final3-body').innerHTML='<div class="card"><div class="card-body"><p><b>Финал главы 3 — Волна 1</b>: боссы и итоги появятся в следующем обновлении.</p></div></div>'+secNav('p9',null); }
</script>
</body>
</html>