Files
Learn_System/frontend/textbooks/geometry_10_r3.html
T
Maxim Dolgolyov e6a1a697bd feat(geom10 W5): Раздел 3 §7 + §8 — Перпендикулярность и расстояния
§7 Перпендикулярность прямой и плоскости:
- SVG определения: плоскость α + вертикальная l + 4 прямые в α с маркерами 90°
- SVG признака: l + m + n пересекающиеся в O, прямые углы
- 6 теоретических карточек (определение, признак, свойства, параллельность+⊥, существование, куб)
- 3 тренажёра: перпендикулярна ли (6), применение признака (5), ⊥ в кубе (5)
- Босс §7: 5 этапов, +70 XP

§8 Расстояния:
- 4 случая side-by-side (точка→плоскость / прямая∥плоскость / парал. плоскости / скрещ. прямые)
- Детальный SVG: точка A над плоскостью + перпендикуляр AO + наклонная AB
- 6 теоретических карточек
- 3 тренажёра: расстояния в кубе (6, с поддержкой √2 / sqrt(2) / корень), какой тип задачи (5), верно/неверно (5)
- Босс §8: 5 этапов, +70 XP
- normalizeAns: общая утилита для ввода √2, sqrt(2), корень2, 1.41, 1.414

§9, §10, Финал — stub до W6/W7.
2026-05-29 15:14:50 +03:00

1074 lines
62 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 · Раздел 3 · Перпендикулярность</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:#fff1f2; --card:#fff; --card-2:#f1f5f9;
--text:#3f0a1c; --text-2:#7f1d1d; --muted:#475569;
--border:#fecdd3; --border-2:#e2e8f0;
--pri:#e11d48; --pri-d:#be123c; --pri-l:#fda4af;
--pri-soft:#fecdd3; --pri-soft-2:#ffe4e6;
--dark:#7f1d1d;
--accent:#7c3aed;
--good:#16a34a;
--warn:#d97706;
--sh:0 4px 16px rgba(225,29,72,.08);
--sh-h:0 12px 36px rgba(225,29,72,.18);
}
html.dark{
--bg:#1c0612; --card:#240a1c; --card-2:#2d1024;
--text:#fecdd3; --text-2:#fda4af; --muted:#94a3b8;
--border:#7f1d1d; --border-2:#1e293b;
--pri-soft:rgba(225,29,72,.18); --pri-soft-2:rgba(225,29,72,.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,#7c3aed);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(124,58,237,.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:240px;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:100px}
.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,#7f1d1d 0%,#9f1239 50%,#be123c 100%);color:#fff;border-radius:18px;padding:24px;margin-bottom:24px;position:relative;overflow:hidden;box-shadow:0 16px 48px rgba(190,18,60,.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:#fecdd3}
.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:#fda4af;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:110px}
.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:#fecdd3;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>Раздел 3. Перпендикулярность</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="7" href="#para-7"><span class="dot"></span>§7 Прямая ⊥ пл-сть</a>
<a class="sec-tab" data-tab="8" href="#para-8"><span class="dot"></span>§8 Расстояния</a>
<a class="sec-tab locked" data-tab="9" href="#para-9"><span class="dot"></span>§9 Угол</a>
<a class="sec-tab locked" data-tab="10" href="#para-10"><span class="dot"></span>§10 Пл-сти ⊥</a>
<a class="sec-tab locked" data-tab="final" href="#para-final"><span class="dot"></span>Финал</a>
</div>
</nav>
<main>
<!-- §7 -->
<section id="para-7" class="para">
<div class="para-head">
<div class="para-num">§ 7</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">ОПРЕДЕЛЕНИЕ</span> Прямая, перпендикулярная плоскости</div>
<div id="viz7-def" style="text-align:center"></div>
<div class="viz-cap">Прямая $l$ перпендикулярна плоскости $\alpha$, если она <b>перпендикулярна любой</b> прямой, лежащей в этой плоскости и проходящей через точку пересечения. Обозначение: $l \perp \alpha$.</div>
</div>
<div class="viz">
<div class="viz-title"><span class="badge">ПРИЗНАК</span> $l \perp m,\ l \perp n,\ m \cap n = O \Rightarrow l \perp \alpha$</div>
<div id="viz7-sign" style="text-align:center"></div>
<div class="viz-cap">Если прямая $l$ перпендикулярна <b>двум пересекающимся</b> прямым $m$ и $n$ в плоскости $\alpha$, то $l \perp \alpha$. Двух пересекающихся достаточно — необязательно проверять все прямые плоскости.</div>
</div>
<div class="theory">
<div class="t-card">
<span class="t-tag">7.1</span>
<div class="t-title">Определение</div>
<div class="t-body">
<p>Прямая $l$ называется <b>перпендикулярной плоскости</b> $\alpha$, если она перпендикулярна <b>каждой</b> прямой в $\alpha$, проходящей через точку их пересечения.</p>
<p>Обозначение: $l \perp \alpha$.</p>
</div>
</div>
<div class="t-card">
<span class="t-tag">7.2</span>
<div class="t-title">Признак перпендикулярности</div>
<div class="t-body">
<p>Если прямая $l$ перпендикулярна двум пересекающимся прямым $m$ и $n$ плоскости $\alpha$, то $l \perp \alpha$.</p>
<p>Это основной инструмент для доказательства перпендикулярности.</p>
</div>
</div>
<div class="t-card">
<span class="t-tag">7.3</span>
<div class="t-title">Свойство</div>
<div class="t-body">
<p>Если $l \perp \alpha$, то $l$ перпендикулярна <b>любой</b> прямой плоскости $\alpha$ (не только проходящей через точку пересечения, но и параллельной ей).</p>
<p>$l \perp \alpha,\ a \subset \alpha \Rightarrow l \perp a$.</p>
</div>
</div>
<div class="t-card">
<span class="t-tag">7.4</span>
<div class="t-title">Параллельность и перпендикулярность</div>
<div class="t-body">
<p>Если $l \perp \alpha$ и $l \parallel l'$, то $l' \perp \alpha$.</p>
<p>Если $l_1 \perp \alpha$ и $l_2 \perp \alpha$, то $l_1 \parallel l_2$.</p>
<p>Две прямые, перпендикулярные одной плоскости, всегда параллельны между собой.</p>
</div>
</div>
<div class="t-card">
<span class="t-tag">7.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">7.6</span>
<div class="t-title">Куб и перпендикулярность</div>
<div class="t-body">
<p>В кубе $ABCDA_1B_1C_1D_1$: ребро $AA_1$ перпендикулярно нижней грани $ABCD$, потому что $AA_1 \perp AB$ и $AA_1 \perp AD$ (две пересек. прямые в плоскости).</p>
<p>Аналогично — каждое боковое ребро перпендикулярно обоим основаниям.</p>
</div>
</div>
</div>
<div class="inter" data-inter="i7-perp">
<div class="inter-h">
<div class="inter-icon">1</div>
<div class="inter-title">Перпендикулярна ли прямая плоскости?</div>
<div class="inter-progress" id="i7-perp-prog">0 / 6</div>
</div>
<div class="quiz">
<div class="quiz-q" id="i7-perp-q"></div>
<div class="quiz-opts" id="i7-perp-opts"></div>
</div>
<div class="quiz-feedback" id="i7-perp-fb"></div>
</div>
<div class="inter" data-inter="i7-sign">
<div class="inter-h">
<div class="inter-icon">2</div>
<div class="inter-title">Применение признака</div>
<div class="inter-progress" id="i7-sign-prog">0 / 5</div>
</div>
<div class="quiz">
<div class="quiz-q" id="i7-sign-q"></div>
<div class="quiz-opts" id="i7-sign-opts"></div>
</div>
<div class="quiz-feedback" id="i7-sign-fb"></div>
</div>
<div class="inter" data-inter="i7-cube">
<div class="inter-h">
<div class="inter-icon">3</div>
<div class="inter-title">Перпендикулярность в кубе</div>
<div class="inter-progress" id="i7-cube-prog">0 / 5</div>
</div>
<div class="quiz">
<div class="quiz-q" id="i7-cube-q"></div>
<div class="quiz-opts" id="i7-cube-opts"></div>
</div>
<div class="quiz-feedback" id="i7-cube-fb"></div>
</div>
<div class="boss" id="boss-7"></div>
<div class="para-actions">
<button class="mark-btn" id="mark-7">
<svg class="ic" viewBox="0 0 24 24"><polyline points="20 6 9 17 4 12"/></svg>
<span>Отметить §7 как изученный</span>
</button>
</div>
</section>
<!-- §8 -->
<section id="para-8" class="para">
<div class="para-head">
<div class="para-num">§ 8</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">4 ВИДА РАССТОЯНИЙ</span> Все через перпендикуляр</div>
<div class="viz-row">
<div class="viz-cell"><div id="viz8-pt-pl"></div><div class="viz-cell-label">Точка → плоскость</div></div>
<div class="viz-cell"><div id="viz8-ln-pl"></div><div class="viz-cell-label">Прямая ∥ плоскость</div></div>
<div class="viz-cell"><div id="viz8-pl-pl"></div><div class="viz-cell-label">Парал. плоскости</div></div>
<div class="viz-cell"><div id="viz8-skew"></div><div class="viz-cell-label">Скрещ. прямые</div></div>
</div>
<div class="viz-cap">Расстояние в стереометрии — всегда длина <b>перпендикуляра</b>. От точки до плоскости — это длина перпендикуляра, опущенного из точки.</div>
</div>
<div class="viz">
<div class="viz-title"><span class="badge">ТОЧКА И ПЛОСКОСТЬ</span> Расстояние $\rho(A, \alpha) = |AO|$</div>
<div id="viz8-detail" style="text-align:center"></div>
<div class="viz-cap">Точка $A$ вне плоскости $\alpha$. Опускаем перпендикуляр $AO$ ($O \in \alpha$). Длина $|AO|$ — расстояние от $A$ до $\alpha$. Любая <span style="color:#1e3a8a;font-weight:800">наклонная $AB$</span> всегда длиннее перпендикуляра.</div>
</div>
<div class="theory">
<div class="t-card">
<span class="t-tag">8.1</span>
<div class="t-title">Расстояние от точки до плоскости</div>
<div class="t-body">
<p>Длина перпендикуляра, опущенного из точки $A$ на плоскость $\alpha$.</p>
<p>Перпендикуляр короче любой наклонной из той же точки.</p>
</div>
</div>
<div class="t-card">
<span class="t-tag">8.2</span>
<div class="t-title">От прямой до параллельной плоскости</div>
<div class="t-body">
<p>Если $a \parallel \alpha$, то расстояние от $a$ до $\alpha$ — это расстояние от <b>любой точки</b> прямой $a$ до $\alpha$ (оно постоянно).</p>
</div>
</div>
<div class="t-card">
<span class="t-tag">8.3</span>
<div class="t-title">Между параллельными плоскостями</div>
<div class="t-body">
<p>Длина общего перпендикуляра между $\alpha \parallel \beta$. Равна расстоянию от любой точки одной плоскости до другой.</p>
</div>
</div>
<div class="t-card">
<span class="t-tag">8.4</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">8.5</span>
<div class="t-title">Свойство перпендикуляра</div>
<div class="t-body">
<p>Перпендикуляр из точки на плоскость — это <b>кратчайший</b> отрезок от точки до плоскости.</p>
<p>Если из точки опущен перпендикуляр $AO$ и наклонная $AB$, то $|AO| \le |AB|$, причём равенство — только если $B = O$.</p>
</div>
</div>
<div class="t-card">
<span class="t-tag">8.6</span>
<div class="t-title">Куб: типовые расстояния</div>
<div class="t-body">
<p>В кубе с ребром $a$:</p>
<ul>
<li>Расстояние от $A$ до плоскости $A_1B_1C_1D_1$ равно $a$ (ребро $AA_1$).</li>
<li>Расстояние между рёбрами $AB$ и $C_1D_1$ равно $a\sqrt{2}$ (диагональ грани).</li>
<li>Расстояние между $AB$ и $CC_1$ равно $a$ (ребро $BC$).</li>
</ul>
</div>
</div>
</div>
<div class="inter" data-inter="i8-cube">
<div class="inter-h">
<div class="inter-icon">1</div>
<div class="inter-title">Расстояния в кубе (ребро $a = 1$)</div>
<div class="inter-progress" id="i8-cube-prog">0 / 6</div>
</div>
<div class="quiz">
<div class="quiz-q" id="i8-cube-q"></div>
<div class="quiz-input">
<input id="i8-cube-in" type="text" placeholder="ответ">
<button id="i8-cube-go">OK</button>
</div>
</div>
<div class="quiz-feedback" id="i8-cube-fb"></div>
</div>
<div class="inter" data-inter="i8-type">
<div class="inter-h">
<div class="inter-icon">2</div>
<div class="inter-title">Какое расстояние ищется?</div>
<div class="inter-progress" id="i8-type-prog">0 / 5</div>
</div>
<div class="quiz">
<div class="quiz-q" id="i8-type-q"></div>
<div class="quiz-opts" id="i8-type-opts"></div>
</div>
<div class="quiz-feedback" id="i8-type-fb"></div>
</div>
<div class="inter" data-inter="i8-true">
<div class="inter-h">
<div class="inter-icon">3</div>
<div class="inter-title">Верно или неверно</div>
<div class="inter-progress" id="i8-true-prog">0 / 5</div>
</div>
<div class="quiz">
<div class="quiz-q" id="i8-true-q"></div>
<div class="quiz-opts" id="i8-true-opts"></div>
</div>
<div class="quiz-feedback" id="i8-true-fb"></div>
</div>
<div class="boss" id="boss-8"></div>
<div class="para-actions">
<button class="mark-btn" id="mark-8">
<svg class="ic" viewBox="0 0 24 24"><polyline points="20 6 9 17 4 12"/></svg>
<span>Отметить §8 как изученный</span>
</button>
</div>
</section>
<!-- §9 stub -->
<section id="para-9" class="para">
<div class="para-head">
<div class="para-num">§ 9</div>
<div class="para-h">
<h2>Угол между прямой и плоскостью</h2>
<div class="para-h-sub">Наклонная и её проекция · теорема о 3 перпендикулярах</div>
</div>
</div>
<div class="stub-card">
<b>В разработке (Волна W6)</b>
Параграф появится в следующей волне: теорема о трёх перпендикулярах и углы наклонных в кубе/пирамиде.
</div>
</section>
<!-- §10 stub -->
<section id="para-10" class="para">
<div class="para-head">
<div class="para-num">§ 10</div>
<div class="para-h">
<h2>Перпендикулярность плоскостей</h2>
<div class="para-h-sub">Двугранный угол · линейный угол · признак перпендикулярности плоскостей</div>
</div>
</div>
<div class="stub-card">
<b>В разработке (Волна W6)</b>
Параграф появится в следующей волне: двугранный угол, линейный угол, признак $\alpha \perp \beta$.
</div>
</section>
<!-- Final stub -->
<section id="para-final" class="para">
<div class="para-head">
<div class="para-num"></div>
<div class="para-h">
<h2>Финал раздела 3</h2>
<div class="para-h-sub">5 интегральных боссов · ачивка «Перпендикулярность освоена»</div>
</div>
</div>
<div class="stub-card">
<b>Откроется в Волне W7</b>
Финал содержит 5 боссов и спецачивку <code>stereo10_r3_master</code>.
</div>
</section>
</main>
<footer class="foot">
Геометрия — 10 класс · Раздел 3 · 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_r3_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-r3/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 === '7' || n === '8' || n === '9' || n === '10'){
if (STATE.read.indexOf(parseInt(n,10)) >= 0) t.classList.add('read');
else t.classList.remove('read');
}
});
}
/* ========== SVG VIZ ========== */
function buildPerpDef(){
if (!window.STEREO3D) return setTimeout(buildPerpDef, 80);
var S = window.STEREO3D;
var sc = new S.Scene(420, 320, {view:'CABINET', scale:50});
sc.addPlane([0,0,0],[0,0,1],{size:2.2, label:'α'});
// Прямая l вертикально через O
sc.addEdge([0,0,-0.3],[0,0,1.8], {stroke:'#dc2626', width:3});
sc.addLabel('l', [0,0,1.8], {dx:12, dy:-4, color:'#dc2626', fontSize:16, anchor:'start'});
sc.addVertex([0,0,0], 'O', {dx:10, dy:14, color:'#0b1d33'});
// 4 прямые в плоскости через O (под разными углами)
var dirs = [
[1.5, 0, 0], // x
[0, 1.5, 0], // y
[1.2, 1.0, 0],
[-1.2, 1.0, 0]
];
for (var i = 0; i < dirs.length; i++){
sc.addEdge([-dirs[i][0], -dirs[i][1], 0], dirs[i], {stroke:'#1e3a8a', width:1.8});
// маркер прямого угла
sc.addRightAngleMark([0,0,0], [0,0,0.3], [dirs[i][0]*0.25, dirs[i][1]*0.25, 0], {color:'#7c3aed', width:1.5, size:0.18});
}
document.getElementById('viz7-def').innerHTML = sc.render();
}
function buildPerpSign(){
if (!window.STEREO3D) return setTimeout(buildPerpSign, 80);
var S = window.STEREO3D;
var sc = new S.Scene(420, 320, {view:'CABINET', scale:50});
sc.addPlane([0,0,0],[0,0,1],{size:2.2, label:'α'});
// l вертикально
sc.addEdge([0,0,-0.2],[0,0,1.8], {stroke:'#dc2626', width:3});
sc.addLabel('l', [0,0,1.8], {dx:12, dy:-4, color:'#dc2626', fontSize:16, anchor:'start'});
// m в плоскости α (вдоль x)
sc.addEdge([-1.6, 0, 0],[1.6, 0, 0], {stroke:'#16a34a', width:2.4});
sc.addLabel('m', [1.6, 0, 0], {dx:12, dy:-4, color:'#16a34a', fontSize:14, anchor:'start'});
// n в плоскости α (вдоль y)
sc.addEdge([0, -1.4, 0],[0, 1.4, 0], {stroke:'#0891b2', width:2.4});
sc.addLabel('n', [0, 1.4, 0], {dx:12, dy:-4, color:'#0891b2', fontSize:14, anchor:'start'});
// O — точка пересечения
sc.addVertex([0,0,0], 'O', {dx:-22, dy:14, color:'#0b1d33'});
// правый угол l-m и l-n
sc.addRightAngleMark([0,0,0], [0,0,0.3], [0.3, 0, 0], {color:'#7c3aed', width:1.5, size:0.20});
sc.addRightAngleMark([0,0,0], [0,0,0.3], [0, 0.3, 0], {color:'#7c3aed', width:1.5, size:0.20});
document.getElementById('viz7-sign').innerHTML = sc.render();
}
function buildDistanceCases(){
if (!window.STEREO3D) return setTimeout(buildDistanceCases, 80);
var S = window.STEREO3D;
// 1) Точка → плоскость
(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.addVertex([0, 0, 1.2], 'A', {dx:10, dy:-6, color:'#dc2626'});
sc.addEdge([0, 0, 1.2],[0, 0, 0], {stroke:'#dc2626', width:2.6});
sc.addVertex([0, 0, 0], 'O', {dx:-14, dy:14, color:'#0b1d33'});
sc.addRightAngleMark([0,0,0], [0,0,0.3], [0.3, 0, 0], {color:'#7c3aed', width:1.5, size:0.20});
document.getElementById('viz8-pt-pl').innerHTML = sc.render();
})();
// 2) Прямая ∥ плоскость
(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'});
sc.addEdge([0, 0, 0.9],[0, 0, 0], {stroke:'#dc2626', width:2.4, dash:'5 3'});
document.getElementById('viz8-ln-pl').innerHTML = sc.render();
})();
// 3) Параллельные плоскости
(function(){
var sc = new S.Scene(220, 200, {view:'CABINET', scale:40});
sc.addPlane([0,0,-0.4],[0,0,1],{size:1.5, label:'α'});
sc.addPlane([0,0,+0.6],[0,0,1],{size:1.5, label:'β', fill:'#86efac', opacity:0.32});
sc.addEdge([0, 0, 0.6],[0, 0, -0.4], {stroke:'#dc2626', width:2.6});
document.getElementById('viz8-pl-pl').innerHTML = sc.render();
})();
// 4) Скрещивающиеся прямые
(function(){
var sc = new S.Scene(220, 200, {view:'CABINET', scale:40});
sc.addEdge([-1.3, -0.5, 0],[1.3, 0.5, 0], {stroke:'#1e3a8a', width:2.4});
sc.addEdge([-1.3, 0.5, 1.1],[1.3, -0.5, 1.1], {stroke:'#0891b2', width:2.4});
// общий перпендикуляр
sc.addEdge([0,0,0],[0,0,1.1], {stroke:'#dc2626', width:2.6});
sc.addLabel('a', [1.3, 0.5, 0], {dx:10, dy:-4, color:'#1e3a8a', fontSize:13, anchor:'start'});
sc.addLabel('b', [1.3, -0.5, 1.1], {dx:10, dy:-4, color:'#0891b2', fontSize:13, anchor:'start'});
document.getElementById('viz8-skew').innerHTML = sc.render();
})();
}
function buildDistanceDetail(){
if (!window.STEREO3D) return setTimeout(buildDistanceDetail, 80);
var S = window.STEREO3D;
var sc = new S.Scene(440, 320, {view:'CABINET', scale:60});
sc.addPlane([0,0,0],[0,0,1],{size:2.2, label:'α'});
// Точка A над плоскостью
sc.addVertex([0.2, 0.3, 1.2], 'A', {dx:10, dy:-6, color:'#dc2626'});
// Перпендикуляр AO
sc.addEdge([0.2, 0.3, 1.2],[0.2, 0.3, 0], {stroke:'#dc2626', width:2.8});
sc.addVertex([0.2, 0.3, 0], 'O', {dx:-18, dy:14, color:'#0b1d33'});
// Наклонная AB
sc.addEdge([0.2, 0.3, 1.2],[-1.2, -0.7, 0], {stroke:'#1e3a8a', width:2.4, dash:'4 3'});
sc.addVertex([-1.2, -0.7, 0], 'B', {dx:-16, dy:14, color:'#1e3a8a'});
// Прямой угол при O
sc.addRightAngleMark([0.2,0.3,0], [0.2,0.3,0.3], [0.5, 0.3, 0], {color:'#7c3aed', width:1.5, size:0.18});
// Подписи длин
sc.addLabel('h', [0.2, 0.3, 0.6], {dx:14, dy:0, color:'#dc2626', fontSize:14, anchor:'start'});
document.getElementById('viz8-detail').innerHTML = sc.render();
}
/* ========== Quiz Engine (shared) ========== */
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 normalizeAns(s){
return String(s||'').toLowerCase()
.replace(/\s+/g,'')
.replace(/°/g,'')
.replace(/sqrt/g,'√')
.replace(/корень/g,'√')
.replace(/,/g,'.');
}
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 = normalizeAns(inEl.value);
var answers = Array.isArray(item.answer) ? item.answer.map(normalizeAns) : [normalizeAns(item.answer)];
if (answers.indexOf(v) >= 0){
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 i7PerpItems = [
{ q:'Прямая $l$ перпендикулярна одной прямой $a \\subset \\alpha$. Достаточно для $l \\perp \\alpha$?', opts:['Да','Нет','Иногда'], correct:1, explain:'Нужны две пересекающиеся прямые в плоскости — одной мало.' },
{ q:'Прямая $l$ перпендикулярна двум параллельным прямым $a, b \\subset \\alpha$. Достаточно?', opts:['Да','Нет'], correct:1, explain:'Нужны именно две ПЕРЕСЕКАЮЩИЕСЯ. Параллельные мало.' },
{ q:'Прямая $l$ перпендикулярна двум пересекающимся $m, n \\subset \\alpha$. Тогда $l \\perp \\alpha$?', opts:['Да','Нет','Иногда'], correct:0, explain:'Это и есть признак перпендикулярности.' },
{ q:'Если $l \\perp \\alpha$ и $p \\subset \\alpha$, то…', opts:['$l \\perp p$','$l \\parallel p$','$l$ скрещ. с $p$'], correct:0, explain:'$l$ перпендикулярна любой прямой плоскости.' },
{ q:'Если $l_1 \\perp \\alpha$ и $l_2 \\perp \\alpha$, то $l_1$ и $l_2$…', opts:['Параллельны','Пересекаются','Перпендикулярны'], correct:0, explain:'Две прямые, перпендикулярные одной плоскости, всегда параллельны.' },
{ q:'Через точку проходит сколько прямых, перпендикулярных данной плоскости?', opts:['1','2','Бесконечно'], correct:0, explain:'Единственная.' }
];
var i7SignItems = [
{ q:'В кубе ребро $AA_1$ перпендикулярно $AB$ и $AD$. Каков вывод?', opts:['$AA_1 \\perp ABCD$','$AA_1 \\parallel ABCD$','Никакого'], correct:0, explain:'$AB$ и $AD$ пересекаются в $A$ — признак работает: $AA_1 \\perp$ плоскости $ABCD$.' },
{ q:'Прямая $l$ перпендикулярна двум прямым $a, b \\subset \\alpha$, но $a \\parallel b$. Можем ли утверждать $l \\perp \\alpha$?', opts:['Да','Нет','Иногда'], correct:1, explain:'Признак требует ПЕРЕСЕКАЮЩИЕСЯ прямые. Параллельных недостаточно.' },
{ q:'Доказано $l \\perp \\alpha$. Что можем заключить про любую прямую $p \\subset \\alpha$?', opts:['$l \\perp p$','$l \\parallel p$','Ничего'], correct:0, explain:'Свойство: $l \\perp$ каждой прямой плоскости.' },
{ q:'Если $l_1 \\perp \\alpha$ и $l_1 \\parallel l_2$, то $l_2$…', opts:['$\\perp \\alpha$','$\\parallel \\alpha$','Лежит в $\\alpha$'], correct:0, explain:'Если параллельна перпендикулярной — сама перпендикулярна.' },
{ q:'Прямая $l$ пересекает плоскость $\\alpha$ и образует с двумя пересек. прямыми $m, n \\subset \\alpha$ равные углы. Что нельзя заключить?', opts:['$l \\perp \\alpha$','$l$ наклонная','Угол с $\\alpha$ определён'], correct:0, explain:'Равные углы — недостаточно для перпендикулярности. Нужны прямые углы.' }
];
var i7CubeItems = [
{ q:'Куб: ребро $AA_1$ и плоскость $ABCD$ — это…', opts:['$\\perp$','$\\parallel$','Лежит'], correct:0, explain:'$AA_1 \\perp AB$ и $AA_1 \\perp AD$ ⇒ $AA_1 \\perp ABCD$.' },
{ q:'Куб: ребро $BB_1$ и плоскость $ABCD$ — это…', opts:['$\\perp$','$\\parallel$','Под углом 45°'], correct:0, explain:'Все боковые рёбра перпендикулярны основанию.' },
{ q:'Куб: ребро $AB$ и плоскость $ADD_1A_1$ (левая боковая) — это…', opts:['$\\perp$','$\\parallel$','Лежит'], correct:0, explain:'$AB \\perp AD$ и $AB \\perp AA_1$ ⇒ $AB \\perp$ плоскости $ADD_1A_1$.' },
{ q:'Куб: какая прямая перпендикулярна плоскости $BCC_1B_1$ (правая грань)?', opts:['$AB$','$BC$','$BB_1$','$AC$'], correct:0, explain:'$AB \\perp BC$ и $AB \\perp BB_1$ — обе в правой грани ⇒ $AB \\perp BCC_1B_1$.' },
{ q:'Куб: диагональ $AC$ нижней грани и ребро $AA_1$ — это…', opts:['$\\perp$','$\\parallel$','Под углом 45°'], correct:0, explain:'$AA_1 \\perp$ всей плоскости $ABCD$, значит $AA_1 \\perp AC$ (свойство).' }
];
var i8CubeItems = [
{ q:'Куб с ребром $1$. Расстояние от $A$ до плоскости $A_1B_1C_1D_1$?', answer:'1', explain:'Это длина бокового ребра $AA_1 = 1$.' },
{ q:'Куб с ребром $1$. Расстояние между параллельными гранями?', answer:'1', explain:'Расстояние = ребро куба = $1$.' },
{ q:'Куб с ребром $1$. Расстояние между скрещ. рёбрами $AB$ и $CC_1$?', answer:'1', explain:'Общий перпендикуляр — это $BC = 1$.' },
{ q:'Куб с ребром $1$. Расстояние между скрещ. рёбрами $AB$ и $C_1D_1$? (Запиши без $\\sqrt{}$: используй число или формулу типа sqrt(2)).', answer:['√2','sqrt(2)','sqrt2','корень2','1.41','1.414'], explain:'Это диагональ грани квадрата 1×1: $\\sqrt{2}$.' },
{ q:'Куб с ребром $1$. Расстояние между параллельными прямыми $AB$ и $D_1C_1$?', answer:['√2','sqrt(2)','sqrt2','1.41','1.414'], explain:'$AB$ и $D_1C_1$ лежат на противоположных гранях по диагонали; расстояние — диагональ квадрата 1×1 = $\\sqrt{2}$.' },
{ q:'Куб с ребром $2$. Расстояние от $A$ до плоскости $A_1B_1C_1D_1$?', answer:'2', explain:'Ребро куба = 2.' }
];
var i8TypeItems = [
{ q:'«Дан куб. Найди расстояние от $A$ до $B_1$.» Какой это тип задачи?', opts:['Точка → точка','Точка → плоскость','Точка → прямая','Скрещ. прямые'], correct:0, explain:'Просто длина отрезка — расстояние между двумя точками.' },
{ q:'«Дан куб. Найди расстояние от $A$ до плоскости $BB_1C_1C$.» Какой тип?', opts:['Точка → точка','Точка → плоскость','Точка → прямая','Скрещ. прямые'], correct:1, explain:'Точка до плоскости — длина перпендикуляра.' },
{ q:'«Найди расстояние между скрещ. рёбрами куба $AD$ и $BB_1$.»', opts:['Точка → точка','Точка → плоскость','Параллельные плоскости','Скрещ. прямые'], correct:3, explain:'Скрещ. прямые — общий перпендикуляр.' },
{ q:'«Между параллельными гранями куба.»', opts:['Точка → плоскость','Парал. плоскости','Парал. прямые','Скрещ. прямые'], correct:1, explain:'Параллельные плоскости — длина их общего перпендикуляра.' },
{ q:'«Дана прямая $a \\parallel \\alpha$. Найти $\\rho(a, \\alpha)$.»', opts:['Точка → точка','Прямая → парал. пл-ть','Парал. плоскости','Скрещ. прямые'], correct:1, explain:'От параллельной прямой до плоскости — расстояние от любой точки прямой.' }
];
var i8TrueItems = [
{ q:'Перпендикуляр из точки на плоскость — это кратчайший отрезок до неё.', opts:['Верно','Неверно'], correct:0, explain:'Любая наклонная длиннее перпендикуляра.' },
{ q:'Если из точки $A$ опущены перпендикуляр $AO$ и наклонная $AB$, то $|AO| \\ge |AB|$.', opts:['Верно','Неверно'], correct:1, explain:'Наоборот: $|AO| \\le |AB|$. Перпендикуляр — самый короткий.' },
{ q:'Расстояние между скрещ. прямыми — длина общего перпендикуляра.', opts:['Верно','Неверно'], correct:0, explain:'Общий перпендикуляр существует, единствен и реализует кратчайшее расстояние.' },
{ q:'Расстояние от прямой $a \\parallel \\alpha$ до плоскости $\\alpha$ зависит от выбора точки прямой.', opts:['Верно','Неверно'], correct:1, explain:'Не зависит — для любой точки расстояние одинаково.' },
{ q:'У двух параллельных плоскостей есть бесконечно много общих перпендикуляров одинаковой длины.', opts:['Верно','Неверно'], correct:0, explain:'Каждый перпендикуляр к плоскостям имеет одну и ту же длину — расстояние между ними.' }
];
/* ========== Bosses ========== */
var BOSS_DEFS = {
7: {
title:'§7 — Перпендикулярность прямой и плоскости',
xp:70,
stages:[
{ q:'Достаточно ли $l$ перпендикулярна одной прямой плоскости, чтобы $l \\perp \\alpha$?', type:'mc', opts:['Да','Нет','Иногда'], correct:1, explain:'Нужны две ПЕРЕСЕКАЮЩИЕСЯ.' },
{ q:'$l \\perp m$, $l \\perp n$, $m \\cap n = O \\in \\alpha$. Вывод?', type:'mc', opts:['$l \\perp \\alpha$','$l \\parallel \\alpha$','Никакой'], correct:0, explain:'Признак перпендикулярности.' },
{ q:'Сколько прямых, перпендикулярных плоскости, можно провести через точку?', type:'input', a:'1', explain:'Единственная.' },
{ q:'Если $l_1 \\perp \\alpha$ и $l_2 \\perp \\alpha$, то $l_1$ и $l_2$…', type:'mc', opts:['$\\parallel$','$\\perp$','Скрещ.'], correct:0, explain:'Параллельны.' },
{ q:'Куб: ребро $CC_1$ перпендикулярно плоскости $ABCD$?', type:'mc', opts:['Да','Нет','Зависит от куба'], correct:0, explain:'Боковое ребро ⊥ основанию.' }
]
},
8: {
title:'§8 — Расстояния',
xp:70,
stages:[
{ q:'Куб с ребром $1$. Расстояние от $A_1$ до плоскости $ABCD$?', type:'input', a:'1', explain:'Длина $AA_1 = 1$.' },
{ q:'Куб с ребром $1$. Расстояние между $AA_1$ и $CC_1$? (форма ответа: число)', type:'input', a:['√2','sqrt(2)','sqrt2','1.41','1.414'], explain:'$AA_1 \\parallel CC_1$ (параллельные прямые); расстояние = диагональ $AC = \\sqrt{2}$.' },
{ q:'Перпендикуляр короче любой наклонной из той же точки?', type:'mc', opts:['Да','Нет','Иногда'], correct:0, explain:'Да — основное свойство.' },
{ q:'Куб с ребром $2$. Расстояние между параллельными гранями?', type:'input', a:'2', explain:'Расстояние = ребро = 2.' },
{ q:'Расстояние между скрещ. прямыми — это длина чего?', type:'mc', opts:['Любого отрезка','Общего перпендикуляра','Касательной','Биссектрисы'], correct:1, 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>';
function normalizeAns(s){
return String(s||'').toLowerCase()
.replace(/\s+/g,'')
.replace(/°/g,'')
.replace(/sqrt/g,'√')
.replace(/корень/g,'√')
.replace(/,/g,'.');
}
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 = normalizeAns(inEl.value);
var answers = Array.isArray(stage.a) ? stage.a.map(normalizeAns) : [normalizeAns(stage.a)];
if (answers.indexOf(v) >= 0){
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(){
buildPerpDef();
buildPerpSign();
buildDistanceCases();
buildDistanceDetail();
runQuizMC({ id:'i7-perp', items:i7PerpItems, xpPerAll:14, title:'перпендикулярность' });
runQuizMC({ id:'i7-sign', items:i7SignItems, xpPerAll:12, title:'признак' });
runQuizMC({ id:'i7-cube', items:i7CubeItems, xpPerAll:12, title:'⊥ в кубе' });
runQuizInput({ id:'i8-cube', items:i8CubeItems, xpPerAll:18, title:'расстояния в кубе' });
runQuizMC({ id:'i8-type', items:i8TypeItems, xpPerAll:12, title:'тип расстояния' });
runQuizMC({ id:'i8-true', items:i8TrueItems, xpPerAll:10, title:'верно/неверно' });
renderBoss(7);
renderBoss(8);
document.getElementById('mark-7').addEventListener('click', function(){ markRead(7); });
document.getElementById('mark-8').addEventListener('click', function(){ markRead(8); });
refreshMarkBtn(7); refreshMarkBtn(8);
refreshTabs();
var tabs = document.querySelectorAll('.sec-tab[data-tab]');
var sections = ['para-7','para-8','para-9','para-10','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>