Files
Learn_System/frontend/textbooks/geometry_10_r2.html
T
Maxim Dolgolyov 8e39993bb0 feat(geom10 W3): Раздел 2 §4-§6 — Параллельность (полная реализация)
§4 Прямые в пространстве:
- 3 случая side-by-side (пересек./парал./скрещ.)
- Куб с 3 типами пар рёбер подсвечены тремя цветами
- 6 теоретических карточек (определения, признак скрещ., теорема о парал., угол, расстояние)
- 3 тренажёра: тип пары (7), угол между прямыми (5), верно/неверно (5)
- Босс §4: 5 этапов, +65 XP

§5 Прямая и плоскость:
- 3 случая (a⊂α / a∩α=M / a∥α)
- Признак параллельности прямой и плоскости (SVG)
- 4 теоретические карточки
- 3 тренажёра: какой случай (6), применение признака (5), параллельность в кубе (5)
- Босс §5: 5 этапов, +65 XP

§6 Две плоскости:
- 2 случая (пересекаются по прямой / параллельны)
- Признак параллельности плоскостей через 2 пересек. прямые
- 4 теоретические карточки
- 3 тренажёра: расположение (5), достаточно ли условий (5), свойства (5)
- Босс §6: 5 этапов, +65 XP

Финал R2 — stub до W4 (4 босса + ачивка stereo10_r2_master).
2026-05-29 15:04:10 +03:00

1198 lines
74 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 name="viewport" content="width=device-width,initial-scale=1.0">
<title>Геометрия 10 · Раздел 2 · Параллельность</title>
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@400;500;600;700;800;900&family=Inter:wght@400;500;600;700&family=Unbounded:wght@400;700;800;900&family=JetBrains+Mono:wght@400;500;700&display=swap" rel="stylesheet">
<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"></script>
<script src="/js/api.js" defer></script>
<script src="/js/xp.js" defer></script>
<script src="/js/stereo3d.js?v=1"></script>
<style>
:root{
--bg:#f0fdf4; --card:#fff; --card-2:#f1f5f9;
--text:#052e16; --text-2:#14532d; --muted:#475569;
--border:#d1fae5; --border-2:#e2e8f0;
--pri:#059669; --pri-d:#047857; --pri-l:#86efac;
--pri-soft:#d1fae5; --pri-soft-2:#ecfdf5;
--dark:#064e3b;
--accent:#dc2626;
--good:#16a34a;
--warn:#d97706;
--sh:0 4px 16px rgba(5,150,105,.08);
--sh-h:0 12px 36px rgba(5,150,105,.18);
}
html.dark{
--bg:#022c22; --card:#0a2218; --card-2:#0f2e22;
--text:#d1fae5; --text-2:#a7f3d0; --muted:#94a3b8;
--border:#14532d; --border-2:#1e293b;
--pri-soft:rgba(5,150,105,.18); --pri-soft-2:rgba(5,150,105,.10);
}
*{margin:0;padding:0;box-sizing:border-box}
html,body{min-height:100vh}
body{font-family:'Inter',system-ui,sans-serif;background:var(--bg);color:var(--text);line-height:1.6;transition:background .25s,color .25s}
.hdr{position:relative;background:linear-gradient(110deg,var(--dark) 0%,var(--pri) 55%,var(--pri-l) 100%);color:#fff;padding:32px 24px 28px;overflow:hidden}
.hdr::before{content:'∥';position:absolute;right:8px;top:-18%;font-family:'Outfit',sans-serif;font-size:clamp(8rem,22vw,18rem);font-weight:900;color:rgba(255,255,255,.10);line-height:1;pointer-events:none;user-select:none}
.hdr-inner{position:relative;z-index:1;max-width:1100px;margin:0 auto;display:flex;align-items:center;gap:18px;flex-wrap:wrap}
.hdr-back{display:inline-flex;align-items:center;gap:8px;padding:8px 14px;background:rgba(255,255,255,.14);border-radius:9px;color:#fff;text-decoration:none;font-size:.85rem;font-weight:600;transition:background .15s}
.hdr-back:hover{background:rgba(255,255,255,.24)}
.hdr h1{font-family:'Outfit',sans-serif;font-size:1.7rem;font-weight:900;letter-spacing:-.01em}
.hdr-sub{font-size:.92rem;opacity:.88;margin-top:4px}
.hdr-side{margin-left:auto;display:flex;gap:8px;align-items:center}
.hdr-btn{padding:8px 12px;background:rgba(255,255,255,.14);border:none;color:#fff;border-radius:9px;cursor:pointer;font-weight:600;font-size:.82rem;display:inline-flex;align-items:center;gap:6px;transition:background .15s;font-family:inherit}
.hdr-btn:hover{background:rgba(255,255,255,.24)}
.hdr-xp{display:inline-flex;align-items:center;gap:6px;padding:6px 12px;background:linear-gradient(135deg,#f59e0b,#dc2626);border-radius:99px;font-family:'Unbounded',sans-serif;font-size:.78rem;font-weight:800;letter-spacing:.04em;color:#fff;box-shadow:0 4px 12px rgba(220,38,38,.32)}
.ic{width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.sec-nav{position:sticky;top:0;z-index:30;background:var(--bg);border-bottom:1px solid var(--border-2);padding:10px 16px;overflow-x:auto;white-space:nowrap;box-shadow:0 2px 8px rgba(0,0,0,.04)}
.sec-nav-inner{display:inline-flex;gap:6px;max-width:1100px;margin:0 auto}
.sec-tab{display:inline-flex;align-items:center;gap:6px;padding:7px 14px;background:var(--card-2);border:1px solid var(--border-2);border-radius:10px;font-size:.82rem;font-weight:700;color:var(--muted);cursor:pointer;transition:all .15s;text-decoration:none;font-family:inherit}
.sec-tab:hover{background:var(--pri-soft);color:var(--pri-d);border-color:var(--pri-l)}
.sec-tab.active{background:var(--pri);color:#fff;border-color:var(--pri-d)}
.sec-tab .dot{width:8px;height:8px;border-radius:50%;background:rgba(0,0,0,.15);transition:background .25s}
.sec-tab.read .dot{background:var(--good)}
.sec-tab.active .dot{background:#fff}
.sec-tab.locked{opacity:.55}
main{max-width:1100px;margin:0 auto;padding:32px 24px 80px}
.para{margin-bottom:48px;scroll-margin-top:72px}
.para-head{display:flex;align-items:flex-start;gap:16px;margin-bottom:18px}
.para-num{font-family:'Outfit',sans-serif;font-size:1.6rem;font-weight:900;color:#fff;background:linear-gradient(135deg,var(--pri),var(--pri-d));padding:10px 16px;border-radius:11px;letter-spacing:-.02em;flex-shrink:0;box-shadow:var(--sh)}
.para-h{flex:1;min-width:0}
.para-h h2{font-family:'Outfit',sans-serif;font-size:1.6rem;font-weight:800;letter-spacing:-.01em;line-height:1.2;margin-bottom:4px}
.para-h-sub{color:var(--muted);font-size:.95rem}
.theory{display:grid;grid-template-columns:1fr;gap:14px;margin-bottom:24px}
@media(min-width:760px){.theory{grid-template-columns:repeat(2,1fr)}}
.t-card{background:var(--card);border:1.5px solid var(--border-2);border-radius:13px;padding:16px 18px;box-shadow:var(--sh);transition:border-color .15s}
.t-card:hover{border-color:var(--pri-l)}
.t-tag{display:inline-block;padding:3px 9px;background:var(--pri-soft);color:var(--pri-d);border-radius:6px;font-size:.7rem;font-weight:800;letter-spacing:.06em;text-transform:uppercase;margin-bottom:8px}
.t-title{font-family:'Outfit',sans-serif;font-size:1.02rem;font-weight:800;margin-bottom:6px;color:var(--text)}
.t-body{font-size:.92rem;color:var(--text);opacity:.9;line-height:1.6}
.t-body p{margin-bottom:8px}
.t-body ul{margin:6px 0 6px 20px}
.t-body li{margin-bottom:4px}
.t-body code{background:var(--card-2);padding:2px 6px;border-radius:5px;font-family:'JetBrains Mono',monospace;font-size:.86em}
.viz{background:var(--card);border:1.5px solid var(--border-2);border-radius:14px;padding:18px;margin-bottom:18px;box-shadow:var(--sh)}
.viz-title{font-family:'Outfit',sans-serif;font-size:.94rem;font-weight:800;color:var(--text);margin-bottom:10px;display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.viz-title .badge{padding:2px 8px;background:var(--pri-soft);color:var(--pri-d);border-radius:5px;font-size:.7rem;letter-spacing:.04em}
.viz-cap{font-size:.84rem;color:var(--muted);margin-top:8px;line-height:1.55}
.viz-row{display:flex;gap:12px;flex-wrap:wrap;justify-content:center}
.viz-cell{flex:1 1 200px;max-width:230px;text-align:center}
.viz-cell-label{font-size:.78rem;color:var(--muted);font-weight:700;margin-top:6px}
.inter{background:var(--card);border:1.5px solid var(--border-2);border-radius:14px;padding:18px;margin-bottom:18px;box-shadow:var(--sh)}
.inter-h{display:flex;align-items:center;gap:10px;margin-bottom:12px}
.inter-icon{width:34px;height:34px;border-radius:9px;background:var(--pri-soft);color:var(--pri-d);display:flex;align-items:center;justify-content:center;flex-shrink:0;font-family:'Outfit',sans-serif;font-weight:900;font-size:.96rem}
.inter-title{font-family:'Outfit',sans-serif;font-size:1rem;font-weight:800;flex:1}
.inter-progress{font-size:.78rem;color:var(--muted);font-weight:700;font-family:'JetBrains Mono',monospace}
.quiz{display:flex;gap:14px;align-items:center;flex-wrap:wrap}
.quiz-q{flex:1;min-width:200px;font-size:.95rem;font-weight:600;line-height:1.55}
.quiz-opts{display:flex;gap:8px;flex-wrap:wrap}
.quiz-opt{padding:8px 14px;background:var(--card-2);border:1.5px solid var(--border-2);border-radius:9px;font-weight:700;font-size:.88rem;cursor:pointer;color:var(--text);font-family:inherit;transition:all .15s}
.quiz-opt:hover{background:var(--pri-soft);border-color:var(--pri-l)}
.quiz-opt.correct{background:linear-gradient(135deg,#dcfce7,#bbf7d0);border-color:#16a34a;color:#166534;animation:pop .35s}
.quiz-opt.wrong{background:linear-gradient(135deg,#fee2e2,#fecaca);border-color:#dc2626;color:#991b1b;animation:shake .35s}
@keyframes pop{0%{transform:scale(1)}50%{transform:scale(1.07)}100%{transform:scale(1)}}
@keyframes shake{0%,100%{transform:translateX(0)}25%{transform:translateX(-4px)}75%{transform:translateX(4px)}}
.quiz-input{display:inline-flex;align-items:center;gap:8px;background:var(--card-2);border:1.5px solid var(--border-2);border-radius:9px;padding:4px 6px;transition:border-color .15s}
.quiz-input.correct{border-color:#16a34a;background:linear-gradient(135deg,#dcfce7,#bbf7d0)}
.quiz-input.wrong{border-color:#dc2626;background:linear-gradient(135deg,#fee2e2,#fecaca)}
.quiz-input input{background:transparent;border:none;outline:none;padding:6px 8px;font-family:'JetBrains Mono',monospace;font-size:.92rem;font-weight:700;color:var(--text);width:90px}
.quiz-input button{background:var(--pri);border:none;color:#fff;padding:6px 10px;border-radius:6px;cursor:pointer;font-weight:700;font-size:.82rem;font-family:inherit}
.quiz-input button:hover{filter:brightness(1.08)}
.quiz-feedback{margin-top:10px;padding:10px 14px;background:var(--card-2);border-radius:9px;font-size:.88rem;color:var(--muted);display:none}
.quiz-feedback.show{display:block}
.quiz-feedback.good{background:linear-gradient(135deg,#dcfce7,#f0fdf4);color:#166534;border-left:3px solid #16a34a}
.quiz-feedback.bad{background:linear-gradient(135deg,#fee2e2,#fef2f2);color:#991b1b;border-left:3px solid #dc2626}
.boss{background:linear-gradient(135deg,#064e3b 0%,#065f46 50%,#047857 100%);color:#fff;border-radius:18px;padding:24px;margin-bottom:24px;position:relative;overflow:hidden;box-shadow:0 16px 48px rgba(4,120,87,.30)}
.boss::before{content:'';position:absolute;inset:0;background:radial-gradient(circle at 20% 30%,rgba(255,255,255,.10),transparent 50%);pointer-events:none}
.boss-h{display:flex;align-items:center;gap:12px;margin-bottom:14px;position:relative;z-index:1;flex-wrap:wrap}
.boss-badge{padding:5px 12px;background:rgba(245,158,11,.32);border:1px solid rgba(251,191,36,.5);border-radius:99px;font-family:'Unbounded',sans-serif;font-size:.72rem;font-weight:800;letter-spacing:.06em;color:#fde68a;text-transform:uppercase}
.boss-title{font-family:'Outfit',sans-serif;font-size:1.2rem;font-weight:800;flex:1}
.boss-hp{margin-bottom:14px;position:relative;z-index:1}
.boss-hp-label{display:flex;justify-content:space-between;font-size:.78rem;font-weight:700;margin-bottom:5px;color:#bbf7d0}
.boss-hp-bar{height:12px;background:rgba(255,255,255,.10);border-radius:7px;overflow:hidden;border:1px solid rgba(255,255,255,.18)}
.boss-hp-fill{height:100%;background:linear-gradient(90deg,#f59e0b,#ef4444);transition:width .5s ease-out}
.boss-question{background:rgba(0,0,0,.32);border-radius:12px;padding:16px;margin-bottom:14px;position:relative;z-index:1;border:1px solid rgba(255,255,255,.10)}
.boss-stage-label{font-size:.74rem;color:#86efac;font-weight:700;letter-spacing:.08em;text-transform:uppercase;margin-bottom:6px}
.boss-q{font-size:1.02rem;font-weight:700;margin-bottom:14px;line-height:1.55}
.boss-opts{display:flex;gap:8px;flex-wrap:wrap}
.boss-opt{padding:10px 16px;background:rgba(255,255,255,.10);border:1.5px solid rgba(255,255,255,.20);border-radius:9px;color:#fff;font-weight:700;font-size:.92rem;cursor:pointer;font-family:inherit;transition:all .15s}
.boss-opt:hover{background:rgba(255,255,255,.18);border-color:rgba(255,255,255,.4)}
.boss-opt.correct{background:linear-gradient(135deg,#16a34a,#22c55e);border-color:#86efac;animation:pop .35s}
.boss-opt.wrong{background:linear-gradient(135deg,#dc2626,#ef4444);border-color:#fca5a5;animation:shake .35s}
.boss-input{display:inline-flex;align-items:center;gap:6px;background:rgba(0,0,0,.36);border:1.5px solid rgba(255,255,255,.20);border-radius:9px;padding:4px 6px}
.boss-input.wrong{border-color:#fca5a5;animation:shake .35s}
.boss-input input{background:transparent;border:none;outline:none;color:#fff;font-family:'JetBrains Mono',monospace;font-size:.95rem;font-weight:700;padding:6px 8px;width:100px}
.boss-input button{background:#f59e0b;border:none;color:#fff;padding:6px 12px;border-radius:6px;cursor:pointer;font-weight:800;font-size:.82rem;font-family:inherit}
.boss-defeated{text-align:center;padding:16px;position:relative;z-index:1}
.boss-defeated-title{font-family:'Outfit',sans-serif;font-size:1.3rem;font-weight:900;color:#fde68a;margin-bottom:8px;letter-spacing:-.01em}
.boss-defeated-sub{font-size:.92rem;color:#a7f3d0;margin-bottom:14px}
.boss-defeated-xp{display:inline-flex;align-items:center;gap:6px;padding:8px 16px;background:linear-gradient(135deg,#f59e0b,#dc2626);border-radius:99px;font-family:'Unbounded',sans-serif;font-weight:800;font-size:.86rem;letter-spacing:.06em;box-shadow:0 6px 20px rgba(245,158,11,.4)}
.boss.victory{background:linear-gradient(135deg,#15803d,#22c55e 50%,#86efac)}
.boss.victory::before{background:radial-gradient(circle at 50% 50%,rgba(254,240,138,.20),transparent 70%)}
.para-actions{display:flex;justify-content:center;margin-top:18px;gap:10px}
.mark-btn{padding:11px 22px;background:var(--pri);color:#fff;border:none;border-radius:11px;font-weight:800;font-size:.92rem;cursor:pointer;font-family:'Inter',sans-serif;display:inline-flex;align-items:center;gap:8px;transition:filter .15s,transform .15s;box-shadow:var(--sh)}
.mark-btn:hover{filter:brightness(1.10);transform:translateY(-1px)}
.mark-btn.done{background:linear-gradient(135deg,var(--good),#22c55e)}
.stub-card{background:linear-gradient(135deg,var(--pri-soft),transparent);border:1px dashed var(--pri-l);border-radius:14px;padding:24px;text-align:center;color:var(--pri-d);margin-bottom:24px}
.stub-card b{font-family:'Outfit',sans-serif;font-size:1.1rem;display:block;margin-bottom:4px}
.stub-card small{display:block;margin-top:6px;color:var(--muted);font-size:.84rem}
.foot{text-align:center;padding:24px 16px;color:var(--muted);font-size:.78rem;border-top:1px solid var(--border-2);margin-top:30px}
@media (max-width:560px){
.hdr h1{font-size:1.35rem}
.hdr-sub{font-size:.85rem}
.para-num{font-size:1.3rem;padding:8px 12px}
.para-h h2{font-size:1.3rem}
.quiz{flex-direction:column;align-items:flex-start}
}
</style>
</head>
<body>
<header class="hdr">
<div class="hdr-inner">
<div>
<a href="/textbook/geometry-10" class="hdr-back">
<svg class="ic" viewBox="0 0 24 24"><polyline points="15 18 9 12 15 6"/></svg>
К курсу
</a>
</div>
<div>
<h1>Раздел 2. Параллельность</h1>
<div class="hdr-sub">Прямые · Прямая и плоскость · Плоскости</div>
</div>
<div class="hdr-side">
<span class="hdr-xp" id="hdr-xp">0 XP</span>
<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>
<nav class="sec-nav">
<div class="sec-nav-inner">
<a class="sec-tab active" data-tab="4" href="#para-4"><span class="dot"></span>§4 Прямые</a>
<a class="sec-tab" data-tab="5" href="#para-5"><span class="dot"></span>§5 Прямая и плоск.</a>
<a class="sec-tab" data-tab="6" href="#para-6"><span class="dot"></span>§6 Две плоскости</a>
<a class="sec-tab locked" data-tab="final" href="#para-final"><span class="dot"></span>Финал</a>
</div>
</nav>
<main>
<!-- §4 -->
<section id="para-4" class="para">
<div class="para-head">
<div class="para-num">§ 4</div>
<div class="para-h">
<h2>Расположение прямых в пространстве</h2>
<div class="para-h-sub">Пересекающиеся · параллельные · скрещивающиеся · угол между скрещ.</div>
</div>
</div>
<div class="viz">
<div class="viz-title"><span class="badge">3 СЛУЧАЯ</span> Как могут располагаться 2 прямые в пространстве</div>
<div class="viz-row">
<div class="viz-cell"><div id="viz4-cross"></div><div class="viz-cell-label">Пересекающиеся</div></div>
<div class="viz-cell"><div id="viz4-par"></div><div class="viz-cell-label">Параллельные</div></div>
<div class="viz-cell"><div id="viz4-skew"></div><div class="viz-cell-label">Скрещивающиеся</div></div>
</div>
<div class="viz-cap">В плоскости прямые бывают <b>пересекающиеся</b> и <b>параллельные</b>. В пространстве добавляется третий случай — <b>скрещивающиеся</b>: прямые, не лежащие в одной плоскости.</div>
</div>
<div class="viz">
<div class="viz-title"><span class="badge">КУБ</span> Все 3 типа на одном теле</div>
<div id="viz4-cube"></div>
<div class="viz-cap">В кубе $ABCDA_1B_1C_1D_1$: пара <span style="color:#dc2626;font-weight:800">$AB$ и $AD$</span> — пересекающиеся (общая точка $A$); пара <span style="color:#16a34a;font-weight:800">$AA_1$ и $BB_1$</span> — параллельные; пара <span style="color:#d97706;font-weight:800">$AB$ и $CC_1$</span> — скрещивающиеся (не лежат в одной плоскости).</div>
</div>
<div class="theory">
<div class="t-card">
<span class="t-tag">4.1</span>
<div class="t-title">Параллельные прямые в пространстве</div>
<div class="t-body">
<p>Две прямые в пространстве называются <b>параллельными</b>, если они лежат в одной плоскости и не пересекаются.</p>
<p>Обозначение: $a \parallel b$.</p>
</div>
</div>
<div class="t-card">
<span class="t-tag">4.2</span>
<div class="t-title">Скрещивающиеся прямые</div>
<div class="t-body">
<p>Две прямые называются <b>скрещивающимися</b>, если они <b>не лежат в одной плоскости</b>.</p>
<p>Признак: если прямая $a \subset \alpha$, а прямая $b$ пересекает $\alpha$ в точке, не лежащей на $a$, — то $a$ и $b$ скрещиваются.</p>
</div>
</div>
<div class="t-card">
<span class="t-tag">4.3</span>
<div class="t-title">Теорема о параллельных</div>
<div class="t-body">
<p>Через точку $M$, не лежащую на прямой $a$, проходит <b>единственная</b> прямая, параллельная $a$.</p>
<p>Транзитивность: если $a \parallel b$ и $b \parallel c$, то $a \parallel c$.</p>
</div>
</div>
<div class="t-card">
<span class="t-tag">4.4</span>
<div class="t-title">Угол между прямыми</div>
<div class="t-body">
<p>Углом между <b>пересекающимися</b> прямыми — острый или прямой угол между ними.</p>
<p>Углом между <b>скрещивающимися</b> прямыми $a$ и $b$ называется угол между двумя пересекающимися прямыми $a' \parallel a$ и $b' \parallel b$ (выбираются в общей точке).</p>
</div>
</div>
<div class="t-card">
<span class="t-tag">4.5</span>
<div class="t-title">Расстояние между скрещ.</div>
<div class="t-body">
<p><b>Расстояние</b> между скрещивающимися прямыми — длина их общего перпендикуляра (отрезка, перпендикулярного обеим прямым).</p>
<p>Общий перпендикуляр существует и единствен.</p>
</div>
</div>
<div class="t-card">
<span class="t-tag">4.6</span>
<div class="t-title">Признак скрещивающихся</div>
<div class="t-body">
<p>Если две прямые в пространстве не пересекаются и не параллельны — они <b>скрещивающиеся</b>.</p>
<p>Не пересекающиеся прямые могут быть параллельными (в одной плоскости) или скрещивающимися (в разных плоскостях).</p>
</div>
</div>
</div>
<div class="inter" data-inter="i4-type">
<div class="inter-h">
<div class="inter-icon">1</div>
<div class="inter-title">Определи тип пары рёбер в кубе</div>
<div class="inter-progress" id="i4-type-prog">0 / 7</div>
</div>
<div class="quiz">
<div class="quiz-q" id="i4-type-q"></div>
<div class="quiz-opts" id="i4-type-opts"></div>
</div>
<div class="quiz-feedback" id="i4-type-fb"></div>
</div>
<div class="inter" data-inter="i4-angle">
<div class="inter-h">
<div class="inter-icon">2</div>
<div class="inter-title">Угол между рёбрами куба</div>
<div class="inter-progress" id="i4-angle-prog">0 / 5</div>
</div>
<div class="quiz">
<div class="quiz-q" id="i4-angle-q"></div>
<div class="quiz-input">
<input id="i4-angle-in" type="text" inputmode="numeric" placeholder="?°">
<button id="i4-angle-go">OK</button>
</div>
</div>
<div class="quiz-feedback" id="i4-angle-fb"></div>
</div>
<div class="inter" data-inter="i4-true">
<div class="inter-h">
<div class="inter-icon">3</div>
<div class="inter-title">Верно или неверно</div>
<div class="inter-progress" id="i4-true-prog">0 / 5</div>
</div>
<div class="quiz">
<div class="quiz-q" id="i4-true-q"></div>
<div class="quiz-opts" id="i4-true-opts"></div>
</div>
<div class="quiz-feedback" id="i4-true-fb"></div>
</div>
<div class="boss" id="boss-4"></div>
<div class="para-actions">
<button class="mark-btn" id="mark-4">
<svg class="ic" viewBox="0 0 24 24"><polyline points="20 6 9 17 4 12"/></svg>
<span>Отметить §4 как изученный</span>
</button>
</div>
</section>
<!-- §5 -->
<section id="para-5" class="para">
<div class="para-head">
<div class="para-num">§ 5</div>
<div class="para-h">
<h2>Прямая и плоскость</h2>
<div class="para-h-sub">3 случая · признак параллельности прямой и плоскости</div>
</div>
</div>
<div class="viz">
<div class="viz-title"><span class="badge">3 СЛУЧАЯ</span> Взаимное расположение прямой и плоскости</div>
<div class="viz-row">
<div class="viz-cell"><div id="viz5-in"></div><div class="viz-cell-label">$a \subset \alpha$</div></div>
<div class="viz-cell"><div id="viz5-cross"></div><div class="viz-cell-label">$a \cap \alpha = M$</div></div>
<div class="viz-cell"><div id="viz5-par"></div><div class="viz-cell-label">$a \parallel \alpha$</div></div>
</div>
<div class="viz-cap">Прямая может: <b>лежать в плоскости</b>, <b>пересекать</b> её в одной точке, или быть <b>параллельной</b> (не иметь с плоскостью общих точек).</div>
</div>
<div class="viz">
<div class="viz-title"><span class="badge">ПРИЗНАК ПАРАЛЛЕЛЬНОСТИ</span> $a \parallel b \subset \alpha,\ a \not\subset \alpha \Rightarrow a \parallel \alpha$</div>
<div id="viz5-sign" style="text-align:center"></div>
<div class="viz-cap">Если прямая $a$ <b>параллельна</b> некоторой прямой $b$, лежащей в плоскости $\alpha$, и сама $a$ не лежит в $\alpha$, то $a$ параллельна $\alpha$. Это самый частый способ доказать параллельность прямой и плоскости.</div>
</div>
<div class="theory">
<div class="t-card">
<span class="t-tag">5.1</span>
<div class="t-title">Параллельная прямая и плоскость</div>
<div class="t-body">
<p>Прямая называется <b>параллельной плоскости</b>, если они не имеют общих точек.</p>
<p>Обозначение: $a \parallel \alpha$.</p>
</div>
</div>
<div class="t-card">
<span class="t-tag">5.2</span>
<div class="t-title">Признак параллельности</div>
<div class="t-body">
<p>Если прямая $a$ параллельна некоторой прямой $b \subset \alpha$ и не лежит в $\alpha$, то $a \parallel \alpha$.</p>
<p>Это удобный способ установить параллельность — найти в плоскости прямую, параллельную $a$.</p>
</div>
</div>
<div class="t-card">
<span class="t-tag">5.3</span>
<div class="t-title">Свойство параллельной</div>
<div class="t-body">
<p>Если $a \parallel \alpha$ и плоскость $\beta$, содержащая $a$, пересекает $\alpha$ по прямой $c$, то $a \parallel c$.</p>
<p>То есть линии пересечения параллельной плоскости с проходящей через прямую плоскостью — параллельны самой прямой.</p>
</div>
</div>
<div class="t-card">
<span class="t-tag">5.4</span>
<div class="t-title">Транзитивность</div>
<div class="t-body">
<p>Если $a \parallel \alpha$ и $b \parallel a$, то $b \parallel \alpha$ или $b \subset \alpha$.</p>
<p>Параллельность прямой плоскости — устойчивое свойство при параллельных переносах.</p>
</div>
</div>
</div>
<div class="inter" data-inter="i5-case">
<div class="inter-h">
<div class="inter-icon">1</div>
<div class="inter-title">Какой случай взаимного расположения?</div>
<div class="inter-progress" id="i5-case-prog">0 / 6</div>
</div>
<div class="quiz">
<div class="quiz-q" id="i5-case-q"></div>
<div class="quiz-opts" id="i5-case-opts"></div>
</div>
<div class="quiz-feedback" id="i5-case-fb"></div>
</div>
<div class="inter" data-inter="i5-sign">
<div class="inter-h">
<div class="inter-icon">2</div>
<div class="inter-title">Применение признака параллельности</div>
<div class="inter-progress" id="i5-sign-prog">0 / 5</div>
</div>
<div class="quiz">
<div class="quiz-q" id="i5-sign-q"></div>
<div class="quiz-opts" id="i5-sign-opts"></div>
</div>
<div class="quiz-feedback" id="i5-sign-fb"></div>
</div>
<div class="inter" data-inter="i5-cube">
<div class="inter-h">
<div class="inter-icon">3</div>
<div class="inter-title">Параллельность в кубе</div>
<div class="inter-progress" id="i5-cube-prog">0 / 5</div>
</div>
<div class="quiz">
<div class="quiz-q" id="i5-cube-q"></div>
<div class="quiz-opts" id="i5-cube-opts"></div>
</div>
<div class="quiz-feedback" id="i5-cube-fb"></div>
</div>
<div class="boss" id="boss-5"></div>
<div class="para-actions">
<button class="mark-btn" id="mark-5">
<svg class="ic" viewBox="0 0 24 24"><polyline points="20 6 9 17 4 12"/></svg>
<span>Отметить §5 как изученный</span>
</button>
</div>
</section>
<!-- §6 -->
<section id="para-6" class="para">
<div class="para-head">
<div class="para-num">§ 6</div>
<div class="para-h">
<h2>Две плоскости</h2>
<div class="para-h-sub">Пересекаются или параллельны · признак параллельности плоскостей</div>
</div>
</div>
<div class="viz">
<div class="viz-title"><span class="badge">2 СЛУЧАЯ</span> Как могут располагаться 2 плоскости</div>
<div class="viz-row">
<div class="viz-cell"><div id="viz6-cross"></div><div class="viz-cell-label">Пересекаются по прямой</div></div>
<div class="viz-cell"><div id="viz6-par"></div><div class="viz-cell-label">Параллельны</div></div>
</div>
<div class="viz-cap">Две плоскости либо <b>пересекаются по прямой</b>, либо <b>параллельны</b> (не имеют общих точек). Третьего не дано.</div>
</div>
<div class="viz">
<div class="viz-title"><span class="badge">ПРИЗНАК ПАРАЛЛЕЛЬНОСТИ</span> Через 2 пересекающиеся прямые</div>
<div id="viz6-sign" style="text-align:center"></div>
<div class="viz-cap">Если плоскость $\alpha$ содержит <b>две пересекающиеся прямые</b> $a, b$, каждая из которых параллельна плоскости $\beta$, — то $\alpha \parallel \beta$.</div>
</div>
<div class="theory">
<div class="t-card">
<span class="t-tag">6.1</span>
<div class="t-title">Параллельные плоскости</div>
<div class="t-body">
<p>Две плоскости называются <b>параллельными</b>, если они не имеют общих точек.</p>
<p>Обозначение: $\alpha \parallel \beta$.</p>
</div>
</div>
<div class="t-card">
<span class="t-tag">6.2</span>
<div class="t-title">Признак параллельности плоскостей</div>
<div class="t-body">
<p>Если плоскость $\alpha$ содержит 2 пересекающиеся прямые $a$ и $b$, каждая из которых параллельна $\beta$ — то $\alpha \parallel \beta$.</p>
<p>Одной параллельной прямой недостаточно: нужно именно <b>две пересекающиеся</b>.</p>
</div>
</div>
<div class="t-card">
<span class="t-tag">6.3</span>
<div class="t-title">Свойства параллельных плоскостей</div>
<div class="t-body">
<ul>
<li>Через точку вне плоскости — единственная плоскость, параллельная данной.</li>
<li>Если $\alpha \parallel \beta$ и $\gamma$ пересекает $\alpha$ по $a$, то $\gamma$ пересекает $\beta$ по прямой $b \parallel a$.</li>
<li>Параллельные плоскости отсекают на параллельных прямых равные отрезки.</li>
</ul>
</div>
</div>
<div class="t-card">
<span class="t-tag">6.4</span>
<div class="t-title">Транзитивность</div>
<div class="t-body">
<p>Если $\alpha \parallel \gamma$ и $\beta \parallel \gamma$, то $\alpha \parallel \beta$.</p>
<p>В кубе: верхняя и нижняя грани параллельны; левая и правая параллельны; передняя и задняя параллельны.</p>
</div>
</div>
</div>
<div class="inter" data-inter="i6-case">
<div class="inter-h">
<div class="inter-icon">1</div>
<div class="inter-title">Параллельны или пересекаются?</div>
<div class="inter-progress" id="i6-case-prog">0 / 5</div>
</div>
<div class="quiz">
<div class="quiz-q" id="i6-case-q"></div>
<div class="quiz-opts" id="i6-case-opts"></div>
</div>
<div class="quiz-feedback" id="i6-case-fb"></div>
</div>
<div class="inter" data-inter="i6-sign">
<div class="inter-h">
<div class="inter-icon">2</div>
<div class="inter-title">Достаточно ли условий для параллельности?</div>
<div class="inter-progress" id="i6-sign-prog">0 / 5</div>
</div>
<div class="quiz">
<div class="quiz-q" id="i6-sign-q"></div>
<div class="quiz-opts" id="i6-sign-opts"></div>
</div>
<div class="quiz-feedback" id="i6-sign-fb"></div>
</div>
<div class="inter" data-inter="i6-prop">
<div class="inter-h">
<div class="inter-icon">3</div>
<div class="inter-title">Свойства параллельных плоскостей</div>
<div class="inter-progress" id="i6-prop-prog">0 / 5</div>
</div>
<div class="quiz">
<div class="quiz-q" id="i6-prop-q"></div>
<div class="quiz-opts" id="i6-prop-opts"></div>
</div>
<div class="quiz-feedback" id="i6-prop-fb"></div>
</div>
<div class="boss" id="boss-6"></div>
<div class="para-actions">
<button class="mark-btn" id="mark-6">
<svg class="ic" viewBox="0 0 24 24"><polyline points="20 6 9 17 4 12"/></svg>
<span>Отметить §6 как изученный</span>
</button>
</div>
</section>
<!-- Final stub -->
<section id="para-final" class="para">
<div class="para-head">
<div class="para-num"></div>
<div class="para-h">
<h2>Финал раздела 2</h2>
<div class="para-h-sub">4 интегральных босса · ачивка «Параллельность освоена»</div>
</div>
</div>
<div class="stub-card">
<b>Откроется в Волне W4</b>
Финал содержит 4 босса (прямые в пространстве, прямая и плоскость, две плоскости, сборная задача) и спецачивку <code>stereo10_r2_master</code>.
<small>До этого момента — побеждай боссов §4, §5, §6, чтобы заработать XP.</small>
</div>
</section>
</main>
<footer class="foot">
Геометрия — 10 класс · Раздел 2 · LearnSpace
</footer>
<script>
'use strict';
(function(){
var saved = localStorage.getItem('geometry10_theme') || localStorage.getItem('theme') || 'light';
if (saved === 'dark') document.documentElement.classList.add('dark');
var lab = document.getElementById('theme-lab');
if (lab) lab.textContent = saved === 'dark' ? 'Светлая' : 'Тёмная';
document.getElementById('theme-btn').addEventListener('click', function(){
document.documentElement.classList.toggle('dark');
var dark = document.documentElement.classList.contains('dark');
localStorage.setItem('geometry10_theme', dark ? 'dark' : 'light');
localStorage.setItem('theme', dark ? 'dark' : 'light');
if (lab) lab.textContent = dark ? 'Светлая' : 'Тёмная';
});
})();
var STATE_KEY = 'geometry10_r2_state';
var STATE = (function(){
try { var raw = localStorage.getItem(STATE_KEY); if (raw) return JSON.parse(raw); } catch(e){}
return { read:[], bosses:{}, interactives:{} };
})();
function saveState(){ try { localStorage.setItem(STATE_KEY, JSON.stringify(STATE)); } catch(e){} }
function addXp(amount, reason){
var cur = parseInt(localStorage.getItem('geometry10_xp') || '0', 10) || 0;
cur += amount;
localStorage.setItem('geometry10_xp', String(cur));
updateXpBadge();
if (window.LS && window.LS.xp && typeof window.LS.xp.toast === 'function'){
window.LS.xp.toast('+' + amount + ' XP — ' + (reason || ''));
}
}
function updateXpBadge(){
var el = document.getElementById('hdr-xp');
if (el) el.textContent = (parseInt(localStorage.getItem('geometry10_xp')||'0',10)||0) + ' XP';
}
updateXpBadge();
var syncTimer = null;
function syncProgress(){
if (syncTimer) clearTimeout(syncTimer);
syncTimer = setTimeout(function(){
if (!window.LS || typeof window.LS.api !== 'function') return;
window.LS.api('/api/textbooks/geometry-10-r2/progress', {
method:'POST',
body: JSON.stringify({ read: STATE.read })
}).catch(function(){});
}, 600);
}
function markRead(paraNum){
if (STATE.read.indexOf(paraNum) < 0){
STATE.read.push(paraNum);
saveState();
syncProgress();
}
refreshTabs();
refreshMarkBtn(paraNum);
}
function refreshMarkBtn(n){
var btn = document.getElementById('mark-' + n);
if (!btn) return;
if (STATE.read.indexOf(n) >= 0){
btn.classList.add('done');
btn.querySelector('span').textContent = '§' + n + ' изучен';
}
}
function refreshTabs(){
document.querySelectorAll('.sec-tab').forEach(function(t){
var n = t.getAttribute('data-tab');
if (n === '4' || n === '5' || n === '6'){
if (STATE.read.indexOf(parseInt(n,10)) >= 0) t.classList.add('read');
else t.classList.remove('read');
}
});
}
/* ========== SVG VIZ ========== */
function buildLineCases(){
if (!window.STEREO3D) return setTimeout(buildLineCases, 80);
var S = window.STEREO3D;
// Пересекающиеся
(function(){
var sc = new S.Scene(220, 200, {view:'CABINET', scale:40});
sc.addPlane([0,0,0],[0,0,1],{size:1.8, opacity:0.12});
sc.addEdge([-1.4, -0.6, 0],[1.4, 0.6, 0], {stroke:'#dc2626', width:2.6});
sc.addEdge([-1.0, 0.9, 0],[1.1, -1.0, 0], {stroke:'#1e3a8a', width:2.6});
sc.addVertex([0.05, 0.05, 0], 'O', {dx:8, dy:-8, color:'#0b1d33'});
sc.addLabel('a', [1.4, 0.6, 0], {dx:12, dy:-4, color:'#dc2626', fontSize:14, anchor:'start'});
sc.addLabel('b', [1.1, -1.0, 0], {dx:12, dy:-4, color:'#1e3a8a', fontSize:14, anchor:'start'});
document.getElementById('viz4-cross').innerHTML = sc.render();
})();
// Параллельные
(function(){
var sc = new S.Scene(220, 200, {view:'CABINET', scale:40});
sc.addPlane([0,0,0],[0,0,1],{size:1.8, opacity:0.12});
sc.addEdge([-1.4, -0.6, 0],[1.4, -0.6, 0], {stroke:'#16a34a', width:2.6});
sc.addEdge([-1.4, 0.6, 0],[1.4, 0.6, 0], {stroke:'#16a34a', width:2.6});
sc.addLabel('a', [1.4, -0.6, 0], {dx:12, dy:-4, color:'#16a34a', fontSize:14, anchor:'start'});
sc.addLabel('b', [1.4, 0.6, 0], {dx:12, dy:-4, color:'#16a34a', fontSize:14, anchor:'start'});
document.getElementById('viz4-par').innerHTML = sc.render();
})();
// Скрещивающиеся
(function(){
var sc = new S.Scene(220, 200, {view:'CABINET', scale:40});
sc.addPlane([0,0,0],[0,0,1],{size:1.7, opacity:0.10, fill:'#86efac'});
sc.addEdge([-1.4, -0.5, 0],[1.4, 0.5, 0], {stroke:'#dc2626', width:2.6});
// вторая прямая выше (в другой плоскости)
sc.addEdge([-1.4, 0.4, 0.9],[1.4, -0.4, 0.9], {stroke:'#d97706', width:2.6});
sc.addLabel('a', [1.4, 0.5, 0], {dx:12, dy:-4, color:'#dc2626', fontSize:14, anchor:'start'});
sc.addLabel('b', [1.4, -0.4, 0.9], {dx:12, dy:-4, color:'#d97706', fontSize:14, anchor:'start'});
document.getElementById('viz4-skew').innerHTML = sc.render();
})();
}
function buildCubePairs(){
if (!window.STEREO3D) return setTimeout(buildCubePairs, 80);
var S = window.STEREO3D;
var sc = new S.Scene(440, 340, {view:'CABINET', scale:60});
sc.addCube({center:[0,0,0], size:2.0, labels:true, color:'#d1fae5', opacity:0.20});
// AB и AD пересекаются (общая точка A)
sc.addEdge([-1,-1,-1],[1,-1,-1], {stroke:'#dc2626', width:3.2});
sc.addEdge([-1,-1,-1],[-1,1,-1], {stroke:'#dc2626', width:3.2});
// AA1 и BB1 параллельны
sc.addEdge([-1,-1,-1],[-1,-1,1], {stroke:'#16a34a', width:3.2});
sc.addEdge([1,-1,-1],[1,-1,1], {stroke:'#16a34a', width:3.2});
// AB и CC1 скрещиваются (одна на нижней грани, другая боковое ребро)
// (AB уже подсвечена красным как пересекающаяся с AD; для скрещ. возьмём пару AD и BB1)
// Лучше выделим AD (которая уже красная) и CC1 — но цвет конфликтует. Возьмём BC и DD1
sc.addEdge([1,-1,-1],[1,1,-1], {stroke:'#d97706', width:3.2}); // BC
sc.addEdge([-1,1,-1],[-1,1,1], {stroke:'#d97706', width:3.2}); // DD1
document.getElementById('viz4-cube').innerHTML = sc.render();
}
function buildPlaneLineCases(){
if (!window.STEREO3D) return setTimeout(buildPlaneLineCases, 80);
var S = window.STEREO3D;
// a ⊂ α
(function(){
var sc = new S.Scene(220, 200, {view:'CABINET', scale:40});
sc.addPlane([0,0,0],[0,0,1],{size:1.8, label:'α'});
sc.addEdge([-1.4, -0.5, 0],[1.4, 0.5, 0], {stroke:'#1e3a8a', width:2.6});
sc.addLabel('a', [1.4, 0.5, 0], {dx:12, dy:-4, color:'#1e3a8a', fontSize:14, anchor:'start'});
document.getElementById('viz5-in').innerHTML = sc.render();
})();
// a ∩ α = M
(function(){
var sc = new S.Scene(220, 200, {view:'CABINET', scale:40});
sc.addPlane([0,0,0],[0,0,1],{size:1.8, label:'α'});
sc.addEdge([-0.4, -0.6, 1.3],[+0.6, +0.6, -0.8], {stroke:'#dc2626', width:2.6});
sc.addVertex([0.15, 0.06, 0], 'M', {dx:8, dy:-8, color:'#dc2626'});
sc.addLabel('a', [-0.4, -0.6, 1.3], {dx:-18, dy:-4, color:'#dc2626', fontSize:14, anchor:'end'});
document.getElementById('viz5-cross').innerHTML = sc.render();
})();
// a ∥ α
(function(){
var sc = new S.Scene(220, 200, {view:'CABINET', scale:40});
sc.addPlane([0,0,0],[0,0,1],{size:1.8, label:'α'});
sc.addEdge([-1.4, -0.4, 0.9],[1.4, 0.4, 0.9], {stroke:'#16a34a', width:2.6});
sc.addLabel('a', [1.4, 0.4, 0.9], {dx:12, dy:-4, color:'#16a34a', fontSize:14, anchor:'start'});
document.getElementById('viz5-par').innerHTML = sc.render();
})();
}
function buildSignLineToPlane(){
if (!window.STEREO3D) return setTimeout(buildSignLineToPlane, 80);
var S = window.STEREO3D;
var sc = new S.Scene(420, 280, {view:'CABINET', scale:50});
sc.addPlane([0,0,0],[0,0,1],{size:2.2, label:'α'});
// прямая b в плоскости
sc.addEdge([-1.6, -0.6, 0],[1.6, 0.6, 0], {stroke:'#1e3a8a', width:2.6});
sc.addLabel('b', [1.6, 0.6, 0], {dx:12, dy:-4, color:'#1e3a8a', fontSize:14, anchor:'start'});
// прямая a — параллельна b, но выше плоскости
sc.addEdge([-1.6, -0.6, 1.1],[1.6, 0.6, 1.1], {stroke:'#16a34a', width:2.8});
sc.addLabel('a', [1.6, 0.6, 1.1], {dx:12, dy:-4, color:'#16a34a', fontSize:14, anchor:'start'});
// подпись соответствия
sc.addEdge([-1.0, -0.3, 1.1],[-1.0, -0.3, 0], {stroke:'#94a3b8', width:1, dash:'3 3'});
document.getElementById('viz5-sign').innerHTML = sc.render();
}
function buildPlanePlaneCases(){
if (!window.STEREO3D) return setTimeout(buildPlanePlaneCases, 80);
var S = window.STEREO3D;
// Пересекаются
(function(){
var sc = new S.Scene(260, 220, {view:'CABINET', scale:44});
sc.addPlane([0,0,0],[0,0,1],{size:1.6, label:'α', opacity:0.22});
sc.addPlane([0,0,0],[Math.cos(Math.PI/4),0,Math.sin(Math.PI/4)],{size:1.6, label:'β', opacity:0.24, fill:'#fde047'});
sc.addEdge([-1.4, 0, 0],[1.4, 0, 0], {stroke:'#dc2626', width:2.8});
sc.addLabel('c', [1.4, 0, 0], {dx:14, dy:-4, color:'#dc2626', fontSize:15, anchor:'start'});
document.getElementById('viz6-cross').innerHTML = sc.render();
})();
// Параллельные
(function(){
var sc = new S.Scene(260, 220, {view:'CABINET', scale:44});
sc.addPlane([0,0,-0.6],[0,0,1],{size:1.6, label:'α'});
sc.addPlane([0,0,+0.6],[0,0,1],{size:1.6, label:'β', fill:'#86efac', opacity:0.32});
document.getElementById('viz6-par').innerHTML = sc.render();
})();
}
function buildSignPlaneToPlane(){
if (!window.STEREO3D) return setTimeout(buildSignPlaneToPlane, 80);
var S = window.STEREO3D;
var sc = new S.Scene(420, 300, {view:'CABINET', scale:50});
sc.addPlane([0,0,-0.5],[0,0,1],{size:2.2, label:'β'});
sc.addPlane([0,0,+0.5],[0,0,1],{size:2.2, label:'α', fill:'#86efac', opacity:0.32});
// 2 пересекающиеся прямые в α
sc.addEdge([-1.6, -0.6, 0.5],[1.6, 0.6, 0.5], {stroke:'#dc2626', width:2.6});
sc.addEdge([-1.0, 0.9, 0.5],[1.1, -1.0, 0.5], {stroke:'#1e3a8a', width:2.6});
sc.addVertex([0.05, 0.05, 0.5], 'O', {dx:8, dy:-8, color:'#0b1d33'});
sc.addLabel('a', [1.6, 0.6, 0.5], {dx:12, dy:-4, color:'#dc2626', fontSize:14, anchor:'start'});
sc.addLabel('b', [1.1, -1.0, 0.5], {dx:12, dy:-4, color:'#1e3a8a', fontSize:14, anchor:'start'});
// обе параллельны β
document.getElementById('viz6-sign').innerHTML = sc.render();
}
/* ========== Quiz Engine (same as r1) ========== */
function runQuizMC(opts){
var state = STATE.interactives[opts.id] || { idx: 0, solved: 0 };
var qEl = document.getElementById(opts.id + '-q');
var optsEl = document.getElementById(opts.id + '-opts');
var fbEl = document.getElementById(opts.id + '-fb');
var progEl = document.getElementById(opts.id + '-prog');
function render(){
if (state.solved >= opts.items.length){
qEl.innerHTML = '<b style="color:var(--good)">Все задания решены!</b> +' + (opts.xpPerAll || 10) + ' XP.';
optsEl.innerHTML = '';
fbEl.classList.remove('show');
progEl.textContent = opts.items.length + ' / ' + opts.items.length;
if (!state.awarded){
state.awarded = true;
STATE.interactives[opts.id] = state;
saveState();
addXp(opts.xpPerAll || 10, opts.title || 'тренажёр');
}
return;
}
var item = opts.items[state.idx % opts.items.length];
qEl.innerHTML = item.q;
optsEl.innerHTML = '';
fbEl.classList.remove('show');
for (var i = 0; i < item.opts.length; i++){
(function(i){
var btn = document.createElement('button');
btn.className = 'quiz-opt';
btn.innerHTML = item.opts[i];
btn.addEventListener('click', function(){
var correct = (i === item.correct);
if (correct){
btn.classList.add('correct');
state.solved++;
state.idx++;
STATE.interactives[opts.id] = state;
saveState();
progEl.textContent = state.solved + ' / ' + opts.items.length;
fbEl.className = 'quiz-feedback show good';
fbEl.innerHTML = '<b>Верно.</b> ' + (item.explain || '');
tryKatex(fbEl);
setTimeout(render, 900);
} else {
btn.classList.add('wrong');
fbEl.className = 'quiz-feedback show bad';
fbEl.innerHTML = '<b>Не так.</b> ' + (item.explain || '');
tryKatex(fbEl);
}
});
optsEl.appendChild(btn);
})(i);
}
progEl.textContent = state.solved + ' / ' + opts.items.length;
tryKatex(qEl);
}
render();
}
function runQuizInput(opts){
var state = STATE.interactives[opts.id] || { idx:0, solved:0 };
var qEl = document.getElementById(opts.id + '-q');
var inEl = document.getElementById(opts.id + '-in');
var goEl = document.getElementById(opts.id + '-go');
var fbEl = document.getElementById(opts.id + '-fb');
var progEl = document.getElementById(opts.id + '-prog');
var box = inEl.parentNode;
function render(){
if (state.solved >= opts.items.length){
qEl.innerHTML = '<b style="color:var(--good)">Все задания решены!</b> +' + (opts.xpPerAll || 10) + ' XP.';
inEl.value = ''; inEl.disabled = true; goEl.disabled = true;
progEl.textContent = opts.items.length + ' / ' + opts.items.length;
box.className = 'quiz-input correct';
if (!state.awarded){
state.awarded = true;
STATE.interactives[opts.id] = state;
saveState();
addXp(opts.xpPerAll || 10, opts.title || 'тренажёр');
}
return;
}
var item = opts.items[state.idx % opts.items.length];
qEl.innerHTML = item.q;
inEl.value = ''; inEl.disabled = false; goEl.disabled = false;
fbEl.classList.remove('show');
box.className = 'quiz-input';
progEl.textContent = state.solved + ' / ' + opts.items.length;
tryKatex(qEl);
}
function check(){
var item = opts.items[state.idx % opts.items.length];
var v = (inEl.value || '').trim().toLowerCase().replace(/\s+/g,'').replace('°','');
var ans = String(item.answer).toLowerCase().replace(/\s+/g,'');
if (v === ans){
box.className = 'quiz-input correct';
state.solved++;
state.idx++;
STATE.interactives[opts.id] = state;
saveState();
fbEl.className = 'quiz-feedback show good';
fbEl.innerHTML = '<b>Верно.</b> ' + (item.explain || '');
tryKatex(fbEl);
setTimeout(render, 900);
} else {
box.className = 'quiz-input wrong';
fbEl.className = 'quiz-feedback show bad';
fbEl.innerHTML = '<b>Не так.</b> ' + (item.explain || '');
tryKatex(fbEl);
}
}
goEl.addEventListener('click', check);
inEl.addEventListener('keydown', function(e){ if (e.key === 'Enter') check(); });
render();
}
/* ========== Quiz Items ========== */
var i4TypeItems = [
{ q:'Куб $ABCDA_1B_1C_1D_1$: пара $AB$ и $AD$ — это…', opts:['Параллельные','Пересекающиеся','Скрещивающиеся'], correct:1, explain:'$AB$ и $AD$ имеют общую точку $A$ — пересекающиеся.' },
{ q:'Куб: пара $AA_1$ и $CC_1$ — это…', opts:['Параллельные','Пересекающиеся','Скрещивающиеся'], correct:0, explain:'Все боковые рёбра прямой призмы параллельны между собой.' },
{ q:'Куб: пара $AB$ и $CC_1$ — это…', opts:['Параллельные','Пересекающиеся','Скрещивающиеся'], correct:2, explain:'$AB$ лежит в нижней грани, $CC_1$ — боковое ребро. Они не пересекаются и не параллельны.' },
{ q:'Куб: пара $AB$ и $A_1B_1$ — это…', opts:['Параллельные','Пересекающиеся','Скрещивающиеся'], correct:0, explain:'Противоположные стороны прямоугольника $ABB_1A_1$ — параллельны.' },
{ q:'Куб: пара $A_1B_1$ и $C_1D_1$ — это…', opts:['Параллельные','Пересекающиеся','Скрещивающиеся'], correct:0, explain:'Противоположные стороны верхней грани — параллельны.' },
{ q:'Куб: пара $AB$ и $A_1D_1$ — это…', opts:['Параллельные','Пересекающиеся','Скрещивающиеся'], correct:2, explain:'$AB$ на нижней, $A_1D_1$ на верхней; они не лежат в одной плоскости и не параллельны (перпендикулярны при проекции).' },
{ q:'Куб: диагональ $AC$ нижней грани и ребро $BB_1$ — это…', opts:['Параллельные','Пересекающиеся','Скрещивающиеся'], correct:2, explain:'Не пересекаются (ребро $BB_1$ выходит из $B$, а диагональ $AC$ проходит мимо) и не параллельны.' }
];
var i4AngleItems = [
{ q:'Угол между рёбрами $AB$ и $AD$ куба?', answer:'90', explain:'Это смежные стороны квадрата — угол 90°.' },
{ q:'Угол между скрещ. рёбрами $AB$ и $CC_1$ куба?', answer:'90', explain:'Сдвинем $CC_1$ параллельно в точку $B$ → получим $BB_1 \\perp AB$. Угол 90°.' },
{ q:'Угол между диагоналями смежных граней куба (выходящих из одной вершины)?', answer:'60', explain:'$AB_1$ и $AD_1$ — стороны равностороннего треугольника $AB_1D_1$ → угол 60°.' },
{ q:'Угол между параллельными прямыми всегда равен … градусов.', answer:'0', explain:'Параллельные прямые образуют угол $0°$.' },
{ q:'Угол между скрещ. диагоналями $AC$ и $B_1D_1$ куба (диагонали верхней и нижней граней)?', answer:'90', explain:'$AC \\parallel A_1C_1$, а $A_1C_1 \\perp B_1D_1$ (диагонали квадрата). Угол 90°.' }
];
var i4TrueItems = [
{ q:'Если две прямые не пересекаются, то они параллельны.', opts:['Верно','Неверно'], correct:1, explain:'Могут быть скрещивающимися. Параллельны — только в одной плоскости.' },
{ q:'Скрещивающиеся прямые могут лежать в одной плоскости.', opts:['Верно','Неверно'], correct:1, explain:'По определению — нет: скрещ. = не лежат в одной плоскости.' },
{ q:'Через точку, не лежащую на прямой, можно провести единственную параллельную ей прямую.', opts:['Верно','Неверно'], correct:0, explain:'Это теорема о параллельных в пространстве (аналог Евклида).' },
{ q:'Если $a \\parallel b$ и $b \\parallel c$, то $a \\parallel c$.', opts:['Верно','Неверно'], correct:0, explain:'Параллельность транзитивна.' },
{ q:'Через любые 2 прямые в пространстве можно провести плоскость.', opts:['Верно','Неверно'], correct:1, explain:'Только если прямые лежат в одной плоскости (пересек. или парал.). Через скрещ. — нельзя.' }
];
var i5CaseItems = [
{ q:'Прямая $a$ имеет ровно одну общую точку с плоскостью $\\alpha$. Это…', opts:['$a \\subset \\alpha$','$a \\cap \\alpha = M$','$a \\parallel \\alpha$'], correct:1, explain:'Одна общая точка — прямая пересекает плоскость.' },
{ q:'Прямая $a$ не имеет общих точек с плоскостью $\\alpha$. Это…', opts:['$a \\subset \\alpha$','$a \\cap \\alpha = M$','$a \\parallel \\alpha$'], correct:2, explain:'Нет общих точек — параллельность.' },
{ q:'Прямая $a$ имеет 2 точки в плоскости. Это…', opts:['$a \\subset \\alpha$','$a \\cap \\alpha = M$','$a \\parallel \\alpha$'], correct:0, explain:'A2: 2 точки прямой в плоскости ⇒ вся прямая в плоскости.' },
{ q:'Сколько общих точек у параллельной плоскости прямой и самой плоскости?', opts:['0','1','Бесконечно'], correct:0, explain:'По определению — 0.' },
{ q:'Прямая лежит в плоскости. Сколько у них общих точек?', opts:['1','2','Бесконечно'], correct:2, explain:'Все точки прямой — общие.' },
{ q:'Прямая пересекает плоскость в точке $M$. Сколько у них общих точек?', opts:['Одна','Две','Бесконечно'], correct:0, explain:'Только $M$.' }
];
var i5SignItems = [
{ q:'Прямая $a$ параллельна прямой $b \\subset \\alpha$, и $a \\not\\subset \\alpha$. Каков вывод?', opts:['$a \\parallel \\alpha$','$a \\subset \\alpha$','$a \\cap \\alpha$'], correct:0, explain:'Признак параллельности: $a \\parallel \\alpha$.' },
{ q:'Прямая $a \\parallel b \\subset \\alpha$, но $a \\subset \\alpha$. Каков вывод?', opts:['$a \\parallel \\alpha$','$a \\subset \\alpha$','Невозможно'], correct:1, explain:'Если $a$ лежит в той же плоскости — это не параллельность плоскости, а просто прямые в плоскости.' },
{ q:'Достаточно ли для $a \\parallel \\alpha$ только того, что $a$ не пересекает плоскость?', opts:['Да','Нет, нужна параллельная прямая','Только в плоскости'], correct:0, explain:'По определению $a \\parallel \\alpha$ — отсутствие общих точек. Этого достаточно.' },
{ q:'Если $a \\parallel \\alpha$, и плоскость $\\beta \\supset a$ пересекает $\\alpha$ по $c$ — то $a$ и $c$…', opts:['Скрещиваются','Параллельны','Пересекаются'], correct:1, explain:'Свойство: $a \\parallel c$.' },
{ q:'$a \\parallel \\alpha$ и $b \\parallel a$. Тогда $b$…', opts:['$\\parallel \\alpha$ или $\\subset \\alpha$','Пересекает $\\alpha$','Скрещивается с $\\alpha$'], correct:0, explain:'Транзитивность: $b$ либо параллельна, либо лежит в плоскости.' }
];
var i5CubeItems = [
{ q:'Куб: прямая $AB$ и плоскость верхней грани $A_1B_1C_1D_1$. Их расположение?', opts:['Лежит','Пересекает','Параллельна'], correct:2, explain:'$AB$ параллельна $A_1B_1$, лежащей в верхней грани ⇒ $AB \\parallel$ верхней плоскости.' },
{ q:'Куб: прямая $AA_1$ и плоскость нижней грани $ABCD$.', opts:['Лежит','Пересекает в точке $A$','Параллельна'], correct:1, explain:'Боковое ребро выходит из вершины $A$ и пересекает нижнюю грань в этой точке.' },
{ q:'Куб: диагональ $AC$ и плоскость нижней грани $ABCD$.', opts:['Лежит','Пересекает','Параллельна'], correct:0, explain:'$AC$ — диагональ нижней грани, лежит в её плоскости.' },
{ q:'Куб: ребро $A_1B_1$ и плоскость нижней грани $ABCD$.', opts:['Лежит','Пересекает','Параллельна'], correct:2, explain:'$A_1B_1 \\parallel AB \\subset ABCD$ ⇒ параллельна нижней плоскости.' },
{ q:'Сколько рёбер куба параллельно одной заданной грани (не лежащих в ней)?', opts:['2','4','6','8'], correct:1, explain:'$4$ ребра противоположной грани параллельны плоскости. Сама грань содержит ещё 4 ребра (в плоскости), 4 боковых ребра — перпендикулярны.' }
];
var i6CaseItems = [
{ q:'Две плоскости имеют общую точку $P$. Они…', opts:['Параллельны','Пересекаются','Совпадают или пересекаются'], correct:2, explain:'A3: общая точка ⇒ общая прямая. Если общих точек больше — могут совпадать или пересекаться по прямой.' },
{ q:'Плоскости не имеют общих точек. Они…', opts:['Параллельны','Пересекаются','Скрещиваются'], correct:0, explain:'По определению — параллельны.' },
{ q:'Сколько типов взаимного расположения двух различных плоскостей?', opts:['1','2','3','4'], correct:1, explain:'Только 2: параллельны или пересекаются по прямой.' },
{ q:'Куб: плоскости верхней и нижней граней — какое расположение?', opts:['Параллельны','Пересекаются'], correct:0, explain:'Параллельны (расстояние между ними = ребру куба).' },
{ q:'Куб: плоскости передней ($ABB_1A_1$) и правой ($BCC_1B_1$) граней — какое расположение?', opts:['Параллельны','Пересекаются по ребру $BB_1$'], correct:1, explain:'Они имеют общее ребро $BB_1$ — пересекаются по нему.' }
];
var i6SignItems = [
{ q:'$\\alpha$ содержит 2 параллельные прямые, каждая $\\parallel \\beta$. Тогда $\\alpha \\parallel \\beta$?', opts:['Да','Не всегда','Никогда'], correct:1, explain:'Нет! Нужны 2 ПЕРЕСЕКАЮЩИЕСЯ прямые. Две параллельные могут лежать и в плоскости, пересекающей $\\beta$.' },
{ q:'$\\alpha$ содержит 2 пересекающиеся прямые, обе $\\parallel \\beta$. Тогда $\\alpha \\parallel \\beta$?', opts:['Да','Не всегда','Нет'], correct:0, explain:'Это и есть признак параллельности плоскостей.' },
{ q:'$\\alpha$ содержит 1 прямую $a \\parallel \\beta$. Достаточно ли этого?', opts:['Да','Нет'], correct:1, explain:'Одной параллельной мало — плоскости могут пересекаться.' },
{ q:'Все рёбра одной грани куба параллельны другой грани. Грани параллельны?', opts:['Да','Нет','Не всегда'], correct:0, explain:'4 ребра грани включают 2 пересекающиеся ⇒ признак работает.' },
{ q:'$\\alpha$ содержит прямую $a$, перпендикулярную всем прямым в $\\beta$. Это даёт параллельность $\\alpha \\parallel \\beta$?', opts:['Да','Нет'], correct:1, explain:'Это даёт перпендикулярность плоскостей, а не параллельность.' }
];
var i6PropItems = [
{ q:'Если $\\alpha \\parallel \\beta$ и $\\gamma$ пересекает $\\alpha$ по $a$, то $\\gamma$ пересекает $\\beta$ по прямой, $?$ к $a$.', opts:['Параллельной','Перпендикулярной','Скрещивающейся'], correct:0, explain:'Линии пересечения секущей плоскости с парой параллельных — параллельны между собой.' },
{ q:'Через точку $M \\notin \\alpha$ можно провести … плоскостей, параллельных $\\alpha$.', opts:['1','2','Бесконечно'], correct:0, explain:'Единственную.' },
{ q:'$\\alpha \\parallel \\gamma$, $\\beta \\parallel \\gamma$. Тогда $\\alpha$ и $\\beta$…', opts:['Параллельны или совпадают','Пересекаются','Скрещиваются'], correct:0, explain:'Транзитивность параллельности плоскостей.' },
{ q:'Параллельные плоскости отсекают на параллельных прямых … отрезки.', opts:['Равные','Перпендикулярные','Разные'], correct:0, explain:'Равные — это свойство параллельных плоскостей.' },
{ q:'Если $\\alpha \\parallel \\beta$ и $a \\parallel \\alpha$, то $a$…', opts:['Параллельна $\\beta$ или лежит в ней','Пересекает $\\beta$','Перпендикулярна $\\beta$'], correct:0, explain:'Параллельность сохраняется относительно параллельной плоскости.' }
];
/* ========== Bosses ========== */
var BOSS_DEFS = {
4: {
title:'§4 — Прямые в пространстве',
xp:65,
stages:[
{ q:'Куб: пара $AB$ и $D_1C_1$ — это…', type:'mc', opts:['Параллельные','Пересекающиеся','Скрещивающиеся'], correct:0, explain:'$AB \\parallel DC \\parallel D_1C_1$ (все параллельные противоположные стороны).' },
{ q:'Угол между скрещ. рёбрами $AB$ и $CC_1$ куба?', type:'input', a:'90', explain:'Сдвинем $CC_1$ в точку $B$ ⇒ $BB_1 \\perp AB$.' },
{ q:'Через 2 скрещивающиеся прямые можно провести плоскость?', type:'mc', opts:['Да','Нет','Иногда'], correct:1, explain:'Нельзя по определению.' },
{ q:'Если $a \\parallel b$ и $b \\parallel c$, что верно для $a$ и $c$?', type:'mc', opts:['$\\parallel$','Скрещиваются','Пересекаются'], correct:0, explain:'Транзитивность параллельности.' },
{ q:'Угол между параллельными прямыми равен (в градусах)?', type:'input', a:'0', explain:'$0°$ по определению.' }
]
},
5: {
title:'§5 — Прямая и плоскость',
xp:65,
stages:[
{ q:'Сколько случаев взаимного расположения прямой и плоскости?', type:'input', a:'3', explain:'Лежит, пересекает, параллельна.' },
{ q:'$a \\parallel b \\subset \\alpha$, $a \\not\\subset \\alpha$. Вывод?', type:'mc', opts:['$a \\subset \\alpha$','$a \\parallel \\alpha$','$a \\cap \\alpha = M$'], correct:1, explain:'Признак параллельности.' },
{ q:'Прямая параллельна плоскости. Сколько у них общих точек?', type:'input', a:'0', explain:'Нуль — по определению.' },
{ q:'Куб: прямая $AB$ и плоскость верхней грани. Как расположены?', type:'mc', opts:['Лежит','Пересекает','Параллельна'], correct:2, explain:'$AB \\parallel A_1B_1 \\subset$ верх. грани.' },
{ q:'$a \\parallel \\alpha$ и $\\beta \\supset a$ пересекает $\\alpha$ по $c$. Тогда $a$ и $c$…', type:'mc', opts:['Скрещиваются','Параллельны','Пересекаются'], correct:1, explain:'$a \\parallel c$ (свойство параллельной).' }
]
},
6: {
title:'§6 — Две плоскости',
xp:65,
stages:[
{ q:'Сколько случаев взаимного расположения двух различных плоскостей?', type:'input', a:'2', explain:'Параллельны или пересекаются по прямой.' },
{ q:'$\\alpha$ содержит 2 пересекающиеся прямые $a, b \\parallel \\beta$. Тогда…', type:'mc', opts:['$\\alpha \\parallel \\beta$','$\\alpha = \\beta$','$\\alpha \\cap \\beta = c$'], correct:0, explain:'Признак параллельности плоскостей.' },
{ q:'$\\alpha \\parallel \\beta$ и $\\gamma$ пересекает $\\alpha$ по $a$, $\\beta$ по $b$. Тогда $a$ и $b$…', type:'mc', opts:['Параллельны','Скрещиваются','Перпендикулярны'], correct:0, explain:'$a \\parallel b$.' },
{ q:'Через точку $M \\notin \\alpha$ — сколько плоскостей параллельно $\\alpha$?', type:'input', a:'1', explain:'Единственная.' },
{ q:'$\\alpha \\parallel \\gamma$ и $\\beta \\parallel \\gamma$. Тогда $\\alpha$ и $\\beta$…', type:'mc', opts:['Параллельны или совпадают','Пересекаются','Скрещиваются'], correct:0, explain:'Транзитивность.' }
]
}
};
function renderBoss(num){
var def = BOSS_DEFS[num];
if (!def) return;
var el = document.getElementById('boss-' + num);
if (!el) return;
var st = STATE.bosses[num] || { stage:0, defeated:false };
STATE.bosses[num] = st;
if (st.defeated){
el.classList.add('victory');
el.innerHTML = '<div class="boss-defeated">'
+ '<div class="boss-defeated-title">Босс §' + num + ' побеждён!</div>'
+ '<div class="boss-defeated-sub">' + def.title + '</div>'
+ '<span class="boss-defeated-xp">+' + def.xp + ' XP</span>'
+ '</div>';
return;
}
el.classList.remove('victory');
var total = def.stages.length;
var stage = def.stages[st.stage];
var hp = Math.round((1 - st.stage/total) * 100);
var optsHtml;
if (stage.type === 'mc'){
optsHtml = '<div class="boss-opts">';
for (var i = 0; i < stage.opts.length; i++){
optsHtml += '<button class="boss-opt" data-i="' + i + '">' + stage.opts[i] + '</button>';
}
optsHtml += '</div>';
} else {
optsHtml = '<div class="boss-input"><input type="text" id="boss-' + num + '-in" inputmode="text" placeholder="ответ"><button id="boss-' + num + '-go">Атака</button></div>';
}
el.innerHTML = '<div class="boss-h">'
+ '<span class="boss-badge">Босс</span>'
+ '<span class="boss-title">' + def.title + '</span>'
+ '</div>'
+ '<div class="boss-hp"><div class="boss-hp-label"><span>HP босса</span><span>' + hp + '%</span></div>'
+ '<div class="boss-hp-bar"><div class="boss-hp-fill" style="width:' + hp + '%"></div></div></div>'
+ '<div class="boss-question">'
+ '<div class="boss-stage-label">Этап ' + (st.stage+1) + ' / ' + total + '</div>'
+ '<div class="boss-q">' + stage.q + '</div>'
+ optsHtml + '</div>';
if (stage.type === 'mc'){
el.querySelectorAll('.boss-opt').forEach(function(btn){
btn.addEventListener('click', function(){
var i = parseInt(btn.getAttribute('data-i'), 10);
var ok = (i === stage.correct);
if (ok){
btn.classList.add('correct');
setTimeout(function(){ advanceBoss(num); }, 600);
} else {
btn.classList.add('wrong');
setTimeout(function(){ btn.classList.remove('wrong'); }, 600);
}
});
});
} else {
var inEl = document.getElementById('boss-' + num + '-in');
var goEl = document.getElementById('boss-' + num + '-go');
var box = inEl.parentNode;
function attack(){
var v = (inEl.value || '').trim().toLowerCase().replace(/\s+/g,'').replace('°','');
var a = String(stage.a).toLowerCase().replace(/\s+/g,'');
if (v === a){
box.classList.remove('wrong');
inEl.style.background = 'rgba(34,197,94,.25)';
setTimeout(function(){ advanceBoss(num); }, 500);
} else {
box.classList.add('wrong');
inEl.style.background = 'rgba(220,38,38,.25)';
setTimeout(function(){ box.classList.remove('wrong'); inEl.style.background=''; }, 600);
}
}
goEl.addEventListener('click', attack);
inEl.addEventListener('keydown', function(e){ if (e.key === 'Enter') attack(); });
}
tryKatex(el);
}
function advanceBoss(num){
var st = STATE.bosses[num];
var def = BOSS_DEFS[num];
st.stage++;
if (st.stage >= def.stages.length){
st.defeated = true;
saveState();
addXp(def.xp, 'босс §' + num);
} else {
saveState();
}
renderBoss(num);
}
function tryKatex(scope){
if (!window.renderMathInElement) return;
try {
window.renderMathInElement(scope || document.body, {
delimiters: [
{left:'$$', right:'$$', display:true},
{left:'$', right:'$', display:false},
{left:'\\(', right:'\\)', display:false},
{left:'\\[', right:'\\]', display:true}
],
throwOnError: false
});
} catch(e){}
}
function start(){
buildLineCases();
buildCubePairs();
buildPlaneLineCases();
buildSignLineToPlane();
buildPlanePlaneCases();
buildSignPlaneToPlane();
runQuizMC({ id:'i4-type', items:i4TypeItems, xpPerAll:14, title:'тип пары прямых' });
runQuizInput({ id:'i4-angle', items:i4AngleItems, xpPerAll:14, title:'угол между прямыми' });
runQuizMC({ id:'i4-true', items:i4TrueItems, xpPerAll:10, title:'верно/неверно' });
runQuizMC({ id:'i5-case', items:i5CaseItems, xpPerAll:12, title:'случаи прямой и плоскости' });
runQuizMC({ id:'i5-sign', items:i5SignItems, xpPerAll:12, title:'признак параллельности' });
runQuizMC({ id:'i5-cube', items:i5CubeItems, xpPerAll:12, title:'параллельность в кубе' });
runQuizMC({ id:'i6-case', items:i6CaseItems, xpPerAll:12, title:'параллельны или пересек.' });
runQuizMC({ id:'i6-sign', items:i6SignItems, xpPerAll:12, title:'признак параллел. плоск.' });
runQuizMC({ id:'i6-prop', items:i6PropItems, xpPerAll:12, title:'свойства параллел. плоск.' });
renderBoss(4);
renderBoss(5);
renderBoss(6);
document.getElementById('mark-4').addEventListener('click', function(){ markRead(4); });
document.getElementById('mark-5').addEventListener('click', function(){ markRead(5); });
document.getElementById('mark-6').addEventListener('click', function(){ markRead(6); });
refreshMarkBtn(4); refreshMarkBtn(5); refreshMarkBtn(6);
refreshTabs();
var tabs = document.querySelectorAll('.sec-tab[data-tab]');
var sections = ['para-4','para-5','para-6','para-final'];
function onScroll(){
var y = window.scrollY + 100;
var active = 0;
for (var i = 0; i < sections.length; i++){
var el = document.getElementById(sections[i]);
if (!el) continue;
if (el.offsetTop <= y) active = i;
}
tabs.forEach(function(t,j){ if (j === active) t.classList.add('active'); else t.classList.remove('active'); });
}
window.addEventListener('scroll', onScroll, {passive:true});
setTimeout(function(){ tryKatex(document.body); }, 50);
}
if (document.readyState === 'loading'){
document.addEventListener('DOMContentLoaded', start);
} else {
start();
}
</script>
</body>
</html>