Files
Learn_System/frontend/textbooks/physics_10_ch6.html
T

2570 lines
172 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">
<title>Физика 10 · Глава 6 · «Ток в различных средах»</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css">
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.js"></script>
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/contrib/auto-render.min.js"
onload="renderMathInElement(document.body,{delimiters:[{left:'$$',right:'$$',display:true},{left:'$',right:'$',display:false},{left:'\\[',right:'\\]',display:true},{left:'\\(',right:'\\)',display:false}],throwOnError:false})"></script>
<script src="/js/api.js" defer></script>
<script src="/js/xp.js" defer></script>
<script src="/js/g3d.js" defer></script>
<script src="/js/phys.js" defer></script>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=Manrope:wght@600;700;800;900&family=Unbounded:wght@700;800;900&family=JetBrains+Mono:wght@500;700&display=swap" rel="stylesheet">
<style>
:root{
--bg:#fafafa; --card:#fff; --card-soft:#f8fafc; --text:#0f172a; --ink:#0f172a; --muted:#64748b;
--border:#e2e8f0; --sh:0 1px 3px rgba(0,0,0,.06); --sh2:0 4px 14px rgba(0,0,0,.08);
--pri:#10b981; --pri2:#059669; --pri-soft:#d1fae5;
--acc:#6ee7b7; --acc2:#10b981; --acc-soft:#d1fae5;
--ok:#10b981; --ok-bg:#d1fae5; --warn:#f59e0b; --warn-bg:#fef3c7;
--bad:#ef4444; --fail:#dc2626; --fail-bg:#fee2e2;
}
.dark{--bg:#0a0a0e; --card:#13120a; --card-soft:#18160a; --text:#fef9e7; --ink:#fef9e7; --muted:#a39070; --border:#2a2512}
*{margin:0;padding:0;box-sizing:border-box;-webkit-tap-highlight-color:transparent}
html,body{font-family:'Inter',system-ui,sans-serif;background:var(--bg);color:var(--text);line-height:1.55;font-size:15px}
button,input,select,textarea{font-family:inherit;font-size:inherit}
button{cursor:pointer;border:0;background:transparent;color:inherit}
a{color:inherit;text-decoration:none}
.ic{width:16px;height:16px;display:inline-block;flex-shrink:0;stroke:currentColor;fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;vertical-align:middle}
.hdr{position:relative;background:linear-gradient(110deg,#064e3b 0%,#10b981 55%,#6ee7b7 100%);color:#fff;padding:46px 22px 30px;overflow:hidden;border-bottom:2px solid rgba(255,255,255,.2);min-height:130px}
.hdr::before{content:'ГЛАВА 6';position:absolute;right:-12px;top:50%;transform:translateY(-50%);font-family:'Unbounded',sans-serif;font-size:clamp(5rem,15vw,11rem);font-weight:900;letter-spacing:-.04em;color:transparent;-webkit-text-stroke:1.5px rgba(255,255,255,.12);line-height:1;pointer-events:none;user-select:none;z-index:0}
.hdr-row{position:relative;z-index:1;display:flex;align-items:center;gap:14px;flex-wrap:wrap}
.hdr h1{font-family:'Unbounded',sans-serif;font-size:1.5rem;font-weight:900;letter-spacing:-.01em;line-height:1.3;padding-top:4px}
.hdr-sub{font-size:.85rem;opacity:.88;margin-top:6px;font-weight:500;line-height:1.4}
.hdr-side{margin-left:auto;display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.hdr-btn{padding:7px 12px;border-radius:9px;background:rgba(255,255,255,.14);color:#fff;font-weight:600;font-size:.82rem;display:inline-flex;align-items:center;gap:6px;transition:background .15s;text-decoration:none}
.hdr-btn:hover{background:rgba(255,255,255,.24)}
.main{max-width:1240px;margin:0 auto;padding:22px;width:100%;display:grid;grid-template-columns:1fr 280px;gap:24px}
@media(max-width:980px){.main{grid-template-columns:1fr;padding:14px}}
.col-main{min-width:0}
.hero{background:linear-gradient(135deg,var(--pri-soft) 0%,var(--acc-soft) 50%,var(--pri-soft) 100%);background-size:200% 200%;animation:heroShift 12s ease-in-out infinite;border:1px solid var(--border);border-radius:18px;padding:24px 22px;margin-bottom:24px;position:relative;overflow:hidden}
@keyframes heroShift{0%,100%{background-position:0% 50%}50%{background-position:100% 50%}}
.hero::before{content:'n/p';position:absolute;right:0;top:-30px;font-size:clamp(2rem,12vw,8rem);font-weight:900;color:var(--pri);opacity:.10;line-height:1;pointer-events:none;font-family:'Unbounded',sans-serif}
.hero h2{font-family:'Unbounded',sans-serif;font-size:1.55rem;font-weight:800;color:var(--pri2);margin-bottom:10px;letter-spacing:-.01em}
.hero p{font-size:.95rem;color:var(--text);opacity:.88;margin-bottom:14px;max-width:640px}
.hero-row{display:flex;gap:14px;flex-wrap:wrap;align-items:center}
.btn-primary{padding:11px 22px;background:linear-gradient(135deg,var(--pri),var(--pri2));color:#fff;border-radius:11px;font-weight:700;font-size:.92rem;display:inline-flex;align-items:center;gap:8px;box-shadow:var(--sh2);transition:transform .15s,box-shadow .15s}
.btn-primary:hover{transform:translateY(-1px);box-shadow:0 8px 28px rgba(0,0,0,.18)}
.hero-progress{flex:1;min-width:200px;max-width:280px}
.hp-label{font-size:.74rem;font-weight:700;color:var(--muted);text-transform:uppercase;letter-spacing:.06em;display:block;margin-bottom:5px}
.hp-bar{height:8px;background:rgba(0,0,0,.12);border-radius:5px;overflow:hidden}
.hp-fill{height:100%;background:linear-gradient(90deg,var(--pri),var(--acc));border-radius:5px;width:0%;transition:width .6s cubic-bezier(.16,1,.3,1)}
.hp-text{font-size:.78rem;color:var(--muted);font-weight:700;margin-top:4px;display:block}
.hero-xp-badge{display:inline-flex;align-items:center;gap:6px;padding:6px 12px;background:linear-gradient(135deg,var(--warn,#f59e0b),var(--pri));color:#fff;border-radius:99px;font-size:.82rem;font-weight:800;letter-spacing:.02em;box-shadow:0 4px 12px rgba(0,0,0,.18);font-family:'Unbounded',sans-serif}
.psel{margin-bottom:24px}
.psel-title{font-size:.72rem;font-weight:800;color:var(--muted);text-transform:uppercase;letter-spacing:.08em;margin-bottom:10px}
.psel-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:10px}
.psel-card{background:var(--card);border:1.5px solid var(--border);border-radius:13px;padding:14px;cursor:pointer;transition:transform .2s,box-shadow .2s,border-color .2s;text-align:left;position:relative}
.psel-card:hover{transform:translateY(-3px);box-shadow:var(--sh2);border-color:var(--pri)}
.psel-card.active{border-color:var(--pri);background:linear-gradient(135deg,var(--pri-soft),var(--card));box-shadow:var(--sh2)}
.psel-card.active::after{content:'';position:absolute;top:0;left:0;right:0;height:3px;background:linear-gradient(90deg,var(--pri),var(--acc));border-radius:13px 13px 0 0}
.psel-num{font-family:'Unbounded',sans-serif;font-size:.72rem;font-weight:800;color:var(--pri);text-transform:uppercase;letter-spacing:.08em;margin-bottom:5px}
.psel-name{font-size:.86rem;font-weight:700;color:var(--text);line-height:1.3;margin-bottom:8px}
.psel-prog{height:4px;background:rgba(0,0,0,.10);border-radius:3px;overflow:hidden}
.psel-prog-fill{height:100%;background:var(--pri);width:0%;transition:width .4s}
.psel-card.final{background:linear-gradient(135deg,var(--acc-soft),var(--pri-soft))}
.psel-card.final .psel-num{color:var(--warn)}
.sec[id="sec-p34"]{ --sec-acc:#10b981; --sec-acc-d:#059669; --sec-acc-soft:#d1fae5; }
.sec[id="sec-p35"]{ --sec-acc:#10b981; --sec-acc-d:#059669; --sec-acc-soft:#d1fae5; }
.sec[id="sec-p36"]{ --sec-acc:#10b981; --sec-acc-d:#059669; --sec-acc-soft:#d1fae5; }
.sec[id="sec-p37"]{ --sec-acc:#10b981; --sec-acc-d:#059669; --sec-acc-soft:#d1fae5; }
.sec[id="sec-final6"]{ --sec-acc:#10b981; --sec-acc-d:#059669; --sec-acc-soft:#d1fae5; }
.sec{display:none;position:relative;animation:fadeIn .35s ease}
.sec.active{display:block}
@keyframes fadeIn{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
.sec::before{content:attr(data-watermark);position:absolute;right:-20px;top:10%;font-family:'Unbounded',sans-serif;font-size:clamp(6rem,18vw,14rem);font-weight:900;color:transparent;-webkit-text-stroke:1.5px var(--sec-acc-soft,var(--pri-soft));line-height:1;pointer-events:none;user-select:none;z-index:0;opacity:.35}
.sec-header{margin-bottom:22px;padding-bottom:14px;border-bottom:2px solid var(--sec-acc-soft,var(--pri-soft));position:relative;z-index:1}
.sec-num{display:inline-block;padding:4px 10px;background:linear-gradient(135deg,var(--sec-acc,var(--pri)),var(--sec-acc-d,var(--pri2)));color:#fff;border-radius:7px;font-family:'Unbounded',sans-serif;font-size:.78rem;font-weight:800;letter-spacing:.04em;margin-bottom:8px}
.sec-h{font-family:'Unbounded',sans-serif;font-size:1.6rem;font-weight:800;color:var(--sec-acc-d,var(--pri2));letter-spacing:-.01em;line-height:1.25}
.card{background:var(--card);border:1px solid var(--border);border-radius:14px;padding:18px 20px;margin-bottom:16px;box-shadow:0 1px 3px rgba(0,0,0,.04),0 8px 24px rgba(0,0,0,.04);position:relative;z-index:1;transition:transform .25s cubic-bezier(.16,1,.3,1),box-shadow .25s}
.card:hover{transform:translateY(-2px);box-shadow:0 4px 10px rgba(0,0,0,.06),0 16px 36px rgba(0,0,0,.08)}
.card-header{display:flex;align-items:center;gap:10px;margin-bottom:12px;padding-bottom:10px;border-bottom:1px dashed var(--border)}
.card-icon{width:32px;height:32px;border-radius:9px;display:flex;align-items:center;justify-content:center;flex-shrink:0;color:#fff}
.card-icon.repeat{background:#0ea5e9}.card-icon.theory{background:#8b5cf6}.card-icon.algo{background:#f59e0b}.card-icon.rule{background:#ec4899}.card-icon.example{background:#10b981}.card-icon.oral{background:#06b6d4}
.card-icon .ic{width:18px;height:18px}
.card-title{font-family:'Unbounded',sans-serif;font-size:.82rem;font-weight:800;text-transform:uppercase;letter-spacing:.06em;color:var(--muted);flex:1}
.card-num{font-size:.74rem;font-weight:700;color:var(--muted);background:var(--sec-acc-soft,var(--pri-soft));padding:3px 7px;border-radius:5px}
.card-body{font-size:.94rem;line-height:1.65}
.card-body p{margin-bottom:8px}
.card-body p:last-child{margin-bottom:0}
.btn{padding:8px 16px;border-radius:8px;background:var(--card);color:var(--text);border:1.5px solid var(--border);font-weight:600;font-size:.88rem;transition:background .15s,border-color .15s,transform .1s}
.btn:hover{background:var(--sec-acc-soft,var(--pri-soft));border-color:var(--sec-acc,var(--pri))}
.btn:active{transform:scale(.96)}
.btn.primary{background:var(--sec-acc,var(--pri));color:#fff;border-color:var(--sec-acc,var(--pri))}
.btn.primary:hover{background:var(--sec-acc-d,var(--pri2));border-color:var(--sec-acc-d,var(--pri2))}
.feedback{padding:10px 14px;border-radius:9px;font-weight:600;font-size:.88rem;margin-top:8px;display:none}
.feedback.ok{display:block;background:var(--ok-bg);color:#065f46;border-left:4px solid var(--ok)}
.feedback.fail{display:block;background:var(--fail-bg);color:#7f1d1d;border-left:4px solid var(--fail)}
.wg{background:linear-gradient(135deg,var(--card),var(--sec-acc-soft,var(--pri-soft)));border:1.5px solid var(--sec-acc,var(--pri));border-radius:14px;padding:18px 20px;margin-bottom:18px;box-shadow:var(--sh2);position:relative;z-index:1}
.wg-header{display:flex;align-items:center;gap:8px;margin-bottom:14px}
.wg-badge{padding:4px 9px;background:var(--sec-acc,var(--pri));color:#fff;border-radius:6px;font-family:'Unbounded',sans-serif;font-size:.68rem;font-weight:800;text-transform:uppercase;letter-spacing:.06em}
.wg-title{font-family:'Unbounded',sans-serif;font-size:1.05rem;font-weight:800;color:var(--sec-acc-d,var(--pri2));flex:1}
.wg-help{font-size:.88rem;color:var(--text);margin-bottom:12px;line-height:1.55;background:linear-gradient(135deg,var(--warn-bg,#fef3c7),var(--sec-acc-soft,var(--pri-soft)));border-left:4px solid var(--warn,#f59e0b);padding:9px 14px;border-radius:9px}
.tinp{padding:8px 12px;border:1.5px solid var(--border);border-radius:8px;background:var(--card);color:var(--text);transition:border-color .15s;font-family:'JetBrains Mono',monospace}
.tinp:focus{outline:0;border-color:var(--sec-acc,var(--pri));box-shadow:0 0 0 3px var(--sec-acc-soft,var(--pri-soft))}
.actions{display:flex;gap:8px;flex-wrap:wrap;margin-top:10px}
.sliders{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:10px;margin-bottom:10px}
.sliders label{display:block;font-size:.92rem;color:var(--muted);background:var(--card);padding:8px 12px;border-radius:8px;border:1px solid var(--border);line-height:1.5}
.sliders label b{font-family:'JetBrains Mono',monospace;font-size:1.05rem;color:var(--sec-acc-d,var(--pri2));margin-left:4px}
.sliders label input[type="range"]{display:block;width:100%;margin-top:6px;accent-color:var(--sec-acc,var(--pri))}
.score-display{display:flex;gap:14px;flex-wrap:wrap;align-items:center;padding:10px 14px;background:var(--sec-acc-soft,var(--pri-soft));border-radius:10px;margin-bottom:12px}
.score-display b{color:var(--sec-acc-d,var(--pri2));font-size:1.15rem}
.spoiler{border:1px solid var(--border);border-radius:10px;background:var(--card);margin:10px 0;overflow:hidden}
.spoiler summary{padding:8px 14px;background:var(--sec-acc-soft,var(--pri-soft));font-weight:700;cursor:pointer;font-size:.88rem;color:var(--sec-acc-d,var(--pri2));list-style:none;display:flex;align-items:center;gap:8px}
.spoiler summary::-webkit-details-marker{display:none}
.spoiler summary::before{content:'+';font-size:1.2rem;font-weight:900;color:var(--sec-acc,var(--pri));width:18px}
.spoiler[open] summary::before{content:'\2212'}
.spoiler-body{padding:10px 14px;font-size:.92rem;line-height:1.6}
.dnd-pool{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:14px;padding:10px;border:1.5px dashed var(--border);border-radius:10px;min-height:54px;transition:border-color .18s,background .18s}
.dnd-pool.over{border-color:var(--sec-acc,var(--pri));background:var(--sec-acc-soft,var(--pri-soft));border-style:solid}
.dnd-pool.col{flex-direction:column;align-items:stretch}
.dnd-pool.col .dnd-chip{width:auto}
.dnd-chip{display:inline-flex;align-items:center;gap:6px;padding:6px 12px;background:var(--card);border:1.5px solid var(--border);border-radius:10px;cursor:grab;user-select:none;font-size:.92rem;line-height:1.4;transition:transform .12s,box-shadow .12s,border-color .12s;touch-action:none;max-width:100%}
.dnd-chip:hover{transform:translateY(-1px);border-color:var(--sec-acc,var(--pri));box-shadow:var(--sh)}
.dnd-chip:active{cursor:grabbing}
.dnd-chip.armed{border-color:var(--sec-acc,var(--pri));background:var(--sec-acc-soft,var(--pri-soft));box-shadow:0 0 0 3px rgba(0,0,0,.10);transform:translateY(-1px)}
.dnd-chip.dragging{opacity:.28}
.dnd-chip.placed{background:var(--sec-acc-soft,var(--pri-soft));border-color:var(--sec-acc,var(--pri))}
.dnd-chip .dnd-x{padding:0 5px;color:var(--muted);font-weight:700;font-size:1.05rem;border-radius:4px;cursor:pointer}
.dnd-chip .dnd-x:hover{color:var(--bad,var(--fail));background:var(--fail-bg)}
.drop-box{background:var(--card);border:1.5px dashed var(--border);border-radius:10px;padding:10px;min-height:90px;transition:border-color .15s,background .15s}
.drop-box:hover{border-color:var(--sec-acc,var(--pri));background:var(--sec-acc-soft,var(--pri-soft))}
.drop-box h5{font-family:'Unbounded',sans-serif;font-size:.78rem;color:var(--sec-acc-d,var(--pri2));margin-bottom:8px;text-transform:uppercase;letter-spacing:.05em}
.drop-box.over{border-color:var(--sec-acc,var(--pri));background:var(--sec-acc-soft,var(--pri-soft));border-style:solid;transform:scale(1.015)}
.drop-items{display:flex;flex-wrap:wrap;gap:6px;min-height:32px}
.dnd-hint{font-size:.78rem;color:var(--muted);margin-bottom:8px;display:flex;align-items:center;gap:6px}
.dnd-hint svg{width:14px;height:14px;flex-shrink:0}
.col-side{position:sticky;top:14px;align-self:start;height:fit-content;max-height:calc(100vh - 28px);overflow-y:auto}
.sidecard{background:var(--card);border:1px solid var(--border);border-radius:14px;padding:16px;margin-bottom:14px;box-shadow:var(--sh)}
.sidecard h4{font-family:'Unbounded',sans-serif;font-size:.74rem;font-weight:800;color:var(--pri2);text-transform:uppercase;letter-spacing:.07em;margin-bottom:10px;padding-bottom:8px;border-bottom:1px solid var(--border)}
.sidecard-row{margin-bottom:8px;font-size:.86rem;line-height:1.6}
.sidecard-row b{color:var(--pri);font-weight:700}
.sidecard-row:last-child{margin-bottom:0}
@media(max-width:980px){.col-side{position:static;max-height:none}}
.xp-card{background:linear-gradient(135deg,var(--acc-soft),var(--pri-soft));border:1.5px solid var(--acc);border-radius:12px;padding:14px;margin-bottom:14px}
.xp-card-title{font-size:.68rem;font-weight:800;color:var(--acc2);text-transform:uppercase;letter-spacing:.07em;margin-bottom:8px;display:flex;align-items:center;justify-content:space-between}
.xp-level{font-size:1.1rem;font-weight:900;color:var(--acc2);font-family:'Unbounded',sans-serif}
.xp-bar{height:9px;background:rgba(0,0,0,.10);border-radius:6px;overflow:hidden;margin:7px 0}
.xp-fill{height:100%;background:linear-gradient(90deg,var(--acc),var(--pri));border-radius:6px;transition:width .5s cubic-bezier(.4,0,.2,1)}
.xp-nums{font-size:.74rem;color:var(--muted);display:flex;justify-content:space-between}
.sec-nav{display:flex;gap:10px;margin-top:24px;padding-top:20px;border-top:1px solid var(--border);justify-content:space-between;flex-wrap:wrap}
.foot{text-align:center;padding:30px 16px;color:var(--muted);font-size:.78rem;border-top:1px solid var(--border);margin-top:30px}
.ach-popup{position:fixed;top:80px;right:18px;background:linear-gradient(135deg,var(--pri),var(--acc));color:#fff;padding:12px 18px;border-radius:11px;font-weight:700;font-size:.9rem;box-shadow:0 8px 28px rgba(0,0,0,.32);z-index:1002;display:none;align-items:center;gap:8px;max-width:340px}
.ach-popup.show{display:flex}
.col-side-backdrop{position:fixed;inset:0;background:rgba(0,0,0,.42);z-index:9990;display:none}
.col-side-backdrop.show{display:block}
@media(max-width:980px){
.col-side{position:fixed;top:0;right:0;height:100vh;width:300px;max-width:88vw;background:var(--bg);box-shadow:-12px 0 24px rgba(0,0,0,.18);padding:18px 16px;overflow-y:auto;transform:translateX(100%);transition:transform .25s ease;z-index:9991;max-height:none}
.col-side.open{transform:none}
}
.search-modal{position:fixed;inset:0;background:rgba(15,23,42,.55);backdrop-filter:blur(4px);z-index:9993;display:none;align-items:flex-start;justify-content:center;padding-top:14vh}
.search-modal.show{display:flex}
.search-box{background:var(--bg);border:1px solid var(--border);border-radius:14px;width:560px;max-width:92vw;max-height:70vh;display:flex;flex-direction:column;overflow:hidden;box-shadow:0 24px 64px rgba(0,0,0,.4)}
.search-input{padding:14px 16px;font-size:1rem;border:0;border-bottom:1px solid var(--border);background:transparent;color:var(--text);outline:none}
.search-results{flex:1;overflow-y:auto;padding:6px 0}
.search-row{display:block;padding:8px 16px;cursor:pointer;border-bottom:1px solid var(--border);text-align:left;background:transparent;border:0;width:100%;color:var(--text)}
.search-row:hover,.search-row.active{background:var(--sec-acc-soft,var(--pri-soft))}
.search-row .sr-kind{font-size:.7rem;font-weight:800;color:var(--muted);text-transform:uppercase;letter-spacing:.06em;margin-bottom:2px}
.search-row .sr-title{font-weight:700;font-size:.92rem;color:var(--text)}
.search-row .sr-desc{font-size:.8rem;color:var(--muted);margin-top:2px}
.search-empty{padding:20px;text-align:center;color:var(--muted);font-size:.88rem}
.search-foot{padding:8px 14px;border-top:1px solid var(--border);font-size:.74rem;color:var(--muted);display:flex;gap:14px}
.search-foot kbd{padding:2px 6px;background:var(--card);border:1px solid var(--border);border-radius:4px;font-family:'JetBrains Mono',monospace;font-size:.72rem}
/* === PHYS10 POLISH (visual + micro-interactions) === */
@keyframes wgFadeIn{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
.sec.active .wg{animation:wgFadeIn .35s cubic-bezier(.16,1,.3,1) backwards}
.sec.active .wg:nth-of-type(1){animation-delay:.02s}
.sec.active .wg:nth-of-type(2){animation-delay:.08s}
.sec.active .wg:nth-of-type(3){animation-delay:.14s}
.sec.active .wg:nth-of-type(4){animation-delay:.20s}
.sec.active .wg:nth-of-type(5){animation-delay:.26s}
.sec.active .wg:nth-of-type(6){animation-delay:.32s}
.wg svg{transition:filter .25s ease}
.wg:hover svg{filter:drop-shadow(0 4px 16px rgba(0,0,0,.10))}
input[type=range]:active{box-shadow:0 0 0 4px var(--pri-soft);border-radius:8px}
.wg input[type=range]{cursor:ew-resize}
.score-display b{transition:transform .22s cubic-bezier(.16,1,.3,1),color .22s;display:inline-block;transform-origin:center}
.score-display b.bump{transform:scale(1.28);color:var(--pri)}
.katex{transition:color .2s}
.wg-help .katex:hover,.card-body .katex:hover{color:var(--pri2,var(--pri));cursor:help}
.hp-fill,.psel-prog-fill,.xp-fill,[id$="-overall-fill"]{transition:width .6s cubic-bezier(.16,1,.3,1)!important}
.boss-card,.btn.primary,.btn-primary{position:relative;overflow:hidden}
.btn.primary::after,.btn-primary::after{content:'';position:absolute;inset:0;background:radial-gradient(circle at center,rgba(255,255,255,.42) 0%,transparent 60%);opacity:0;transition:opacity .25s;pointer-events:none}
.btn.primary:hover::after,.btn-primary:hover::after{opacity:1}
.psel-card{position:relative}
.psel-card .psel-done{position:absolute;top:6px;right:6px;width:18px;height:18px;border-radius:50%;background:#10b981;display:none;align-items:center;justify-content:center;box-shadow:0 2px 6px rgba(16,185,129,.45);z-index:2}
.psel-card .psel-done svg{width:11px;height:11px;stroke:#fff;fill:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round}
.psel-card.done .psel-done{display:flex}
.boss-card{transition:border-color .35s,box-shadow .6s,background .3s,transform .2s}
.boss-card.glow{box-shadow:0 0 24px rgba(16,185,129,.6),0 0 0 2px rgba(16,185,129,.45)!important}
@keyframes bossPulse{0%{box-shadow:0 0 0 0 rgba(16,185,129,.55)}70%{box-shadow:0 0 0 14px rgba(16,185,129,0)}100%{box-shadow:0 0 0 0 rgba(16,185,129,0)}}
.boss-card.pulse{animation:bossPulse .8s ease-out}
.sec{transition:opacity .25s}
</style>
</head>
<body>
<header class="hdr">
<div class="hdr-row">
<div>
<h1>Физика 10 · Глава 6</h1>
<div class="hdr-sub">Металлы · сверхпроводимость · электролиз · газы · плазма · полупроводники</div>
</div>
<div class="hdr-side">
<a href="/textbook/physics-10" class="hdr-btn"><svg class="ic" viewBox="0 0 24 24"><polyline points="15 18 9 12 15 6"/></svg> К физике 10</a>
<button id="search-btn" class="hdr-btn"><svg class="ic" viewBox="0 0 24 24"><circle cx="11" cy="11" r="7"/><path d="m21 21-4-4"/></svg> Поиск</button>
<button id="sidebar-btn" class="hdr-btn"><svg class="ic" viewBox="0 0 24 24"><line x1="4" y1="6" x2="20" y2="6"/><line x1="4" y1="12" x2="20" y2="12"/><line x1="4" y1="18" x2="14" y2="18"/></svg> Шпаргалка</button>
<button id="theme-btn" class="hdr-btn"><svg class="ic" viewBox="0 0 24 24"><path d="M21 12.8A9 9 0 1 1 11.2 3a7 7 0 0 0 9.8 9.8z"/></svg><span id="theme-lab">Тёмная</span></button>
</div>
</div>
</header>
<main class="main">
<div class="col-main">
<section class="hero">
<h2>Электрический ток в разных средах</h2>
<p>Электрический ток ведёт себя по-разному в металлах, электролитах, газах и полупроводниках. Сверхпроводимость, электролиз, плазма, p-n переход.</p>
<div class="hero-row">
<button class="btn-primary" onclick="goTo('p34')"><svg class="ic" viewBox="0 0 24 24"><polygon points="6 4 20 12 6 20 6 4" fill="currentColor" stroke="none"/></svg> Начать § 34</button>
<div class="hero-progress">
<span class="hp-label">Прогресс по главе</span>
<div class="hp-bar"><div id="hero-hp-fill" class="hp-fill"></div></div>
<span id="hero-hp-text" class="hp-text">0%</span>
</div>
<div id="hero-xp-badge" class="hero-xp-badge"></div>
</div>
</section>
<section class="psel">
<div class="psel-title">Параграфы главы</div>
<div id="psel-grid" class="psel-grid"></div>
</section>
<section id="sec-p34" class="sec" data-watermark="&rho;(T)"><div class="sec-header"><span class="sec-num">§ 34</span><h2 class="sec-h">Ток в металлах. Сверхпроводимость</h2></div><div id="p34-body"></div></section>
<section id="sec-p35" class="sec" data-watermark="m=kIt"><div class="sec-header"><span class="sec-num">§ 35</span><h2 class="sec-h">Ток в электролитах</h2></div><div id="p35-body"></div></section>
<section id="sec-p36" class="sec" data-watermark="plasma"><div class="sec-header"><span class="sec-num">§ 36</span><h2 class="sec-h">Ток в газах. Плазма</h2></div><div id="p36-body"></div></section>
<section id="sec-p37" class="sec" data-watermark="n/p"><div class="sec-header"><span class="sec-num">§ 37</span><h2 class="sec-h">Ток в полупроводниках</h2></div><div id="p37-body"></div></section>
<section id="sec-final6" class="sec" data-watermark="&#9733;"><div class="sec-header"><span class="sec-num" style="background:linear-gradient(135deg,#10b981,#6ee7b7)"></span><h2 class="sec-h">Финал главы</h2></div><div id="final6-body"></div></section>
</div>
<aside class="col-side" id="col-side"><div id="sidebar-content"></div></aside>
<div class="col-side-backdrop" id="col-side-backdrop"></div>
</main>
<footer class="foot">Интерактивный учебник «Физика 10» · Глава 6 · «Ток в различных средах» · LearnSpace</footer>
<div id="ach-popup" class="ach-popup"><svg class="ic" viewBox="0 0 24 24" style="width:22px;height:22px"><polygon points="12,2 22,20 2,20"/></svg><span id="ach-text">Достижение!</span></div>
<div id="search-modal" class="search-modal" role="dialog">
<div class="search-box">
<input type="text" id="search-input" class="search-input" placeholder="Поиск…" autocomplete="off">
<div id="search-results" class="search-results"></div>
<div class="search-foot"><span><kbd>↑↓</kbd> навигация</span><span><kbd>Enter</kbd> открыть</span><span><kbd>Esc</kbd> закрыть</span></div>
</div>
</div>
<script>
'use strict';
const STATE = { current:'p34', progress:{}, achievements:new Map(), xp:0, level:1 };
const TOTAL_PARAS = 5;
const _TB_SLUG = 'physics-10-ch6';
const PARAS = [
{ id:'p34', num:'\u00a7 34', name:"Ток в металлах. Сверхпроводимость", sub:'$\\rho(T)$' },
{ id:'p35', num:'\u00a7 35', name:"Ток в электролитах", sub:'$m = kIt$' },
{ id:'p36', num:'\u00a7 36', name:"Ток в газах. Плазма", sub:'Виды разрядов' },
{ id:'p37', num:'\u00a7 37', name:"Ток в полупроводниках", sub:'n-/p-тип' },
{ id:'final6', num:'\u2605', name:'Финал главы', sub:'Итоги \u00b7 боссы главы 6', final:true }
];
PARAS.forEach(p => { STATE.progress[p.id] = 0; });
function calcLevel(xp){ return Math.floor(Math.sqrt((xp||0)/100))+1; }
function _xpForLevel(lv){ return (lv-1)*(lv-1)*100; }
const ACH_LABELS = {
start:"Начало главы 6!",
p34_done:"Ток в металлах. Сверхпроводимость освоен!",
p35_done:"Ток в электролитах освоен!",
p36_done:"Ток в газах. Плазма освоен!",
p37_done:"Ток в полупроводниках освоен!",
ch6_done:"Глава 6 пройдена!"
};
function loadProgress(){
try{
const s=localStorage.getItem('physics10_ch6_progress'); if(s) Object.assign(STATE.progress, JSON.parse(s));
const a=localStorage.getItem('physics10_ch6_achievements');
if(a){ const p=JSON.parse(a); if(Array.isArray(p)) p.forEach(id=>STATE.achievements.set(id, ACH_LABELS[id]||id)); else if(p&&typeof p==='object'){ for(const[id,t] of Object.entries(p)) STATE.achievements.set(id,(t&&t!==id)?t:(ACH_LABELS[id]||id)); } }
STATE.xp=+(localStorage.getItem('physics10_xp')||0); STATE.level=calcLevel(STATE.xp);
}catch(e){}
}
function saveProgress(){
try{
localStorage.setItem('physics10_ch6_progress', JSON.stringify(STATE.progress));
localStorage.setItem('physics10_ch6_achievements', JSON.stringify(Object.fromEntries(STATE.achievements)));
localStorage.setItem('physics10_xp', String(STATE.xp));
}catch(e){}
}
function bumpProgress(key, delta){
STATE.progress[key]=Math.max(0,Math.min(100,(STATE.progress[key]||0)+delta));
saveProgress(); refreshProgressUI();
if(STATE.progress[key]>=50) markParaRead(key);
}
const _markedRead=new Set();
let _pendingProgressBody=null, _progressTimer=null;
function _flushProgress(){
const body=_pendingProgressBody; _pendingProgressBody=null; if(!body) return;
const tok=(window.LS&&LS.getToken)?LS.getToken():''; if(!tok) return;
fetch('/api/textbooks/'+_TB_SLUG+'/progress',{method:'POST',headers:{'Content-Type':'application/json','Authorization':'Bearer '+tok},body:JSON.stringify(body),keepalive:true}).catch(()=>{});
}
function _queueProgress(patch){ _pendingProgressBody=Object.assign(_pendingProgressBody||{},patch); if(_progressTimer) clearTimeout(_progressTimer); _progressTimer=setTimeout(_flushProgress, 600); }
function markLastPara(id){ _queueProgress({last_para:id}); }
function markParaRead(id){ if(_markedRead.has(id)) return; _markedRead.add(id); _queueProgress({mark_read:id}); }
window.addEventListener('beforeunload', _flushProgress);
function loadServerReadState(){
const tok=(window.LS&&LS.getToken)?LS.getToken():''; if(!tok) return;
fetch('/api/textbooks/'+_TB_SLUG,{headers:{'Authorization':'Bearer '+tok}}).then(r=>r.ok?r.json():null).then(d=>{
if(!d||!d.progress) return;
(d.progress.read||[]).forEach(k=>{_markedRead.add(k); if((STATE.progress[k]||0)<50) STATE.progress[k]=100;});
saveProgress(); refreshProgressUI();
}).catch(()=>{});
}
function addXp(n,src){
if(!n) return;
const prev=STATE.level; STATE.xp=Math.max(0,(STATE.xp||0)+n); STATE.level=calcLevel(STATE.xp);
saveProgress(); refreshProgressUI();
if(window.LS&&window.LS.xp) window.LS.xp.add(n,'physics10-ch6-'+(src||'misc'));
if(STATE.level>prev){
const pop=document.getElementById('ach-popup');
if(pop){ document.getElementById('ach-text').textContent='Уровень '+STATE.level+'!'; pop.classList.add('show'); setTimeout(()=>pop.classList.remove('show'),2600); }
}
}
function refreshProgressUI(){
const total=Math.round(Object.values(STATE.progress).reduce((a,b)=>a+b,0)/TOTAL_PARAS);
const f=document.getElementById('hero-hp-fill'); if(f) f.style.width=total+'%';
const t=document.getElementById('hero-hp-text'); if(t) t.textContent=total+'% пройдено';
document.querySelectorAll('[data-prog-card]').forEach(el=>{ const k=el.dataset.progCard; const fl=el.querySelector('.psel-prog-fill'); if(fl) fl.style.width=(STATE.progress[k]||0)+'%'; });
const xpBadge=document.getElementById('hero-xp-badge');
if(xpBadge){ xpBadge.innerHTML='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="width:13px;height:13px"><polygon points="12 2 22 20 2 20"/></svg> Ур. '+STATE.level+' \xb7 '+(STATE.xp||0)+' XP'; }
if(STATE.current && document.getElementById('sidebar-content')){ try{ buildSidebar(STATE.current); }catch(e){} }
}
function achievement(id,text){
if(STATE.achievements.has(id)) return;
STATE.achievements.set(id, text||ACH_LABELS[id]||id); saveProgress();
const pop=document.getElementById('ach-popup');
if(pop){ document.getElementById('ach-text').textContent=text||ACH_LABELS[id]||id; pop.classList.add('show'); setTimeout(()=>pop.classList.remove('show'),3300); }
addXp(20,'ach-'+id);
}
function buildParaSelector(){
const g=document.getElementById('psel-grid'); g.innerHTML='';
PARAS.forEach(p=>{
const card=document.createElement('div');
card.className='psel-card'+(p.final?' final':'');
card.dataset.id=p.id; card.dataset.progCard=p.id;
card.innerHTML='<div class="psel-num">'+p.num+'</div><div class="psel-name">'+p.name+'</div><div class="psel-prog"><div class="psel-prog-fill"></div></div>';
card.addEventListener('click', ()=>goTo(p.id));
g.appendChild(card);
});
}
const BUILT=new Set();
const BUILDERS = { p34:()=>build_p34(), p35:()=>build_p35(), p36:()=>build_p36(), p37:()=>build_p37(), final6:()=>build_final6() };
function ensureBuilt(id){ if(BUILT.has(id)) return; const fn=BUILDERS[id]; if(fn){ fn(); BUILT.add(id); } }
function goTo(id){
STATE.current=id; ensureBuilt(id);
document.querySelectorAll('.sec').forEach(s=>s.classList.remove('active'));
const el=document.getElementById('sec-'+id); if(el) el.classList.add('active');
document.querySelectorAll('.psel-card').forEach(c=>c.classList.toggle('active', c.dataset.id===id));
buildSidebar(id);
window.scrollTo({top:0,behavior:'smooth'});
if((STATE.progress[id]||0)<10) bumpProgress(id, 10);
if(window.renderMathInElement) setTimeout(()=>renderMath(el), 0);
markLastPara(id);
}
const SIDEBARS = {
p34:{title:"Шпаргалка §34",rows:[["Носители","свободные электроны"],["$\\rho(T) = \\rho_0(1 + \\alpha t)$","зависимость от $T$"],["Сверхпров.","$T < T_c$, $\\rho = 0$"]]},
p35:{title:"Шпаргалка §35",rows:[["Электролит","раствор/расплав ионных в-в"],["$m = kIt$","1-й закон Фарадея"],["$k = M/(zF)$","эл.-хим. эквивалент"],["$F$","$F = 96485$ Кл/моль"]]},
p36:{title:"Шпаргалка §36",rows:[["Несам.","требует ионизатора"],["Самост.","тлеющий, искровой, дуговой, коронный"],["Плазма","газ из ионов и электронов"]]},
p37:{title:"Шпаргалка §37",rows:[["n-тип","примесь-донор, носители — электроны"],["p-тип","примесь-акцептор, носители — дырки"],["p-n","одностор. проводимость, диод"]]},
final6:{title:"Финал главы 6",rows:[["§§3437","теория главы 6"],["Награда","+50 XP"]]}
};
const TIPS=[
{sec:'p34',html:"В металлах носители — свободные электроны. $\\rho(T) = \\rho_0(1 + \\alpha t)$. Сверхпров.: $\\rho = 0$."},
{sec:'p35',html:"Электролиз: $m = kIt$ — 1-й закон Фарадея. $k = M/(zF)$, $F = 96485$ Кл/моль."},
{sec:'p36',html:"Самостоятельный разряд: тлеющий, искровой, дуговой, коронный. Плазма — ионизованный газ."},
{sec:'p37',html:"Полупроводники: n-тип (донор, электроны) и p-тип (акцептор, дырки). p-n переход — диод."},
{sec:'final6',html:"Финал главы 6 — интегрированные задачи по §§34–37. В разработке (Phase 6+)."}
];
function buildSidebar(id){
const box=document.getElementById('sidebar-content');
const sb=SIDEBARS[id]||SIDEBARS[PARAS[0].id];
let html='';
const xpForLv=_xpForLevel(STATE.level), xpNext=_xpForLevel(STATE.level+1);
const xpInLv=STATE.xp-xpForLv, xpRange=xpNext-xpForLv;
const xpPct=xpRange>0?Math.round(xpInLv/xpRange*100):100;
html+='<div class="xp-card"><div class="xp-card-title"><span>XP-прогресс</span><span class="xp-level">Ур. '+STATE.level+'</span></div><div class="xp-bar"><div class="xp-fill" style="width:'+xpPct+'%"></div></div><div class="xp-nums"><span>'+STATE.xp+' XP</span><span>'+xpNext+' XP</span></div></div>';
html+='<div class="sidecard"><h4>'+sb.title+'</h4>';
sb.rows.forEach(([k,v])=>{ html+='<div class="sidecard-row"><b>'+k+'</b>'+(v?' \u2014 '+v:'')+'</div>'; });
html+='</div>';
const tip=TIPS.find(t=>t.sec===id)||TIPS[0];
if(tip){
html+='<div class="sidecard" style="background:linear-gradient(135deg,var(--warn-bg,#fef3c7),var(--pri-soft));border-color:var(--warn,#f59e0b)"><h4 style="color:#92400e;display:flex;align-items:center;gap:6px"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="width:14px;height:14px"><polygon points="12,2 22,20 2,20"/></svg>Подсказка</h4><div class="sidecard-row" style="margin-bottom:0;font-size:.84rem;line-height:1.55">'+tip.html+'</div></div>';
}
if(STATE.achievements.size>0){
html+='<div class="sidecard"><h4>Достижения <span style="color:var(--warn);float:right">'+STATE.achievements.size+'</span></h4>';
[...STATE.achievements.values()].slice(-4).forEach(text=>{ html+='<div class="sidecard-row" style="font-size:.78rem;color:var(--ok)">&#10003; '+text+'</div>'; });
html+='</div>';
}
box.innerHTML=html;
if(window.renderMathInElement) try{ renderMath(box); }catch(e){}
}
function initTheme(){
const t=localStorage.getItem('physics10_ch6_theme')||'light';
if(t==='dark') document.documentElement.classList.add('dark');
document.getElementById('theme-lab').textContent=t==='dark'?'Светлая':'Тёмная';
document.getElementById('theme-btn').addEventListener('click', ()=>{
document.documentElement.classList.toggle('dark');
const dark=document.documentElement.classList.contains('dark');
localStorage.setItem('physics10_ch6_theme', dark?'dark':'light');
document.getElementById('theme-lab').textContent=dark?'Светлая':'Тёмная';
});
}
function renderMath(root){ if(window.renderMathInElement){ try{ renderMathInElement(root, {delimiters:[{left:'$$',right:'$$',display:true},{left:'$',right:'$',display:false},{left:'\\[',right:'\\]',display:true},{left:'\\(',right:'\\)',display:false}],throwOnError:false}); }catch(e){} } }
function feedback(elm, ok, text){ if(!elm) return; elm.className='feedback '+(ok?'ok':'fail'); elm.innerHTML=text||(ok?'&#10003; Верно!':'&#10007; Неверно'); elm.style.display='block'; try{renderMath(elm);}catch(e){} }
function fmt(n){ if(!isFinite(n)) return '?'; if(Number.isInteger(n)) return String(n); return Math.abs(n-Math.round(n))<1e-9?String(Math.round(n)):(+n.toFixed(6)).toString(); }
function ipow(base, exp){ let r=1; for(let i=0;i<Math.abs(exp);i++) r*=base; return exp<0 ? 1/r : r; }
function gcd(a,b){ a=Math.abs(a|0); b=Math.abs(b|0); while(b){ const t=b; b=a%b; a=t; } return a||1; }
function makeCard(kind, title, num, body){
const labels = {repeat:'Повторение',theory:'Теория',algo:'Алгоритм',rule:'Правило',example:'Пример',oral:'Устно'};
return '<div class="card"><div class="card-header"><div class="card-icon '+kind+'">'+ICONS[kind]+'</div><div class="card-title">'+(labels[kind]||'')+(title&&title!==labels[kind]?' \xb7 '+title:'')+'</div>'+(num?'<div class="card-num">'+num+'</div>':'')+'</div><div class="card-body">'+body+'</div></div>';
}
function setupSorter(cfg){
const placed = {}; const pool = document.getElementById(cfg.poolId); const scope = document.querySelector(cfg.scopeSelector);
if(!pool||!scope) return {placed,render:()=>{},reset:()=>{}};
pool.classList.add('dnd-pool'); if(cfg.columnLayout) pool.classList.add('col');
let armed = null;
function buildChip(it,isPlaced){ const e=document.createElement('div'); e.className='dnd-chip'+(isPlaced?' placed':''); e.dataset.id=it.id; e.innerHTML='<span class="dnd-txt">'+it.html+'</span><span class="dnd-x" title="Убрать">\xd7</span>'; attach(e,it.id); return e; }
function attach(elm,itId){ let ghost=null,dragging=false,sx=0,sy=0; elm.addEventListener('pointerdown',ev=>{ if(ev.button!==undefined&&ev.button!==0) return;
ev.preventDefault(); if(ev.target.classList&&ev.target.classList.contains('dnd-x')){ ev.stopPropagation(); if(placed[itId]){delete placed[itId];render();}else if(armed===itId){armed=null;render();} return; } sx=ev.clientX;sy=ev.clientY; const r=elm.getBoundingClientRect(); const ox=ev.clientX-r.left,oy=ev.clientY-r.top; try{elm.setPointerCapture(ev.pointerId);}catch(e){} function onMove(e){ const dx=e.clientX-sx,dy=e.clientY-sy; if(!dragging&&Math.hypot(dx,dy)>8){ dragging=true; ghost=elm.cloneNode(true); ghost.classList.remove('armed'); ghost.style.cssText='position:fixed;z-index:9999;pointer-events:none;opacity:.9;transform:rotate(-2.5deg);box-shadow:0 14px 36px rgba(0,0,0,.32);width:'+r.width+'px;left:'+(e.clientX-ox)+'px;top:'+(e.clientY-oy)+'px'; document.body.appendChild(ghost); elm.classList.add('dragging'); } if(dragging&&ghost){ ghost.style.left=(e.clientX-ox)+'px';ghost.style.top=(e.clientY-oy)+'px'; const under=document.elementsFromPoint(e.clientX,e.clientY); scope.querySelectorAll('.drop-box.over,.dnd-pool.over').forEach(n=>n.classList.remove('over')); const tgt=under.find(n=>n.classList&&(n.classList.contains('drop-box')||n.classList.contains('dnd-pool'))); if(tgt)tgt.classList.add('over'); } } function onUp(e){ elm.removeEventListener('pointermove',onMove);elm.removeEventListener('pointerup',onUp);elm.removeEventListener('pointercancel',onUp);elm.classList.remove('dragging'); if(ghost){ghost.remove();ghost=null;} scope.querySelectorAll('.drop-box.over,.dnd-pool.over').forEach(n=>n.classList.remove('over')); if(dragging){ const under=document.elementsFromPoint(e.clientX,e.clientY); const box=under.find(n=>n.classList&&n.classList.contains('drop-box')); const pl=under.find(n=>n.classList&&n.classList.contains('dnd-pool')); if(box){const di=box.querySelector('[data-cat]');if(di){placed[itId]=di.dataset.cat;armed=null;render();return;}}else if(pl){delete placed[itId];armed=null;render();return;} }else{ if(placed[itId]){delete placed[itId];armed=null;render();}else{armed=(armed===itId)?null:itId;render();} } dragging=false; } elm.addEventListener('pointermove',onMove);elm.addEventListener('pointerup',onUp);elm.addEventListener('pointercancel',onUp); }); }
function attachBoxTaps(){ scope.querySelectorAll('.drop-box').forEach(box=>{ box.addEventListener('click',ev=>{ if(!armed)return; if(ev.target.closest('.dnd-chip'))return; const di=box.querySelector('[data-cat]'); if(di){placed[armed]=di.dataset.cat;armed=null;render();} }); }); }
function render(){ pool.innerHTML=''; cfg.items.forEach(it=>{if(placed[it.id])return;const c=buildChip(it,false);if(armed===it.id)c.classList.add('armed');pool.appendChild(c);}); cfg.cats.forEach(cat=>{const box=scope.querySelector('.drop-items[data-cat="'+cat+'"]');if(!box)return;box.innerHTML='';cfg.items.forEach(it=>{if(placed[it.id]!==cat)return;box.appendChild(buildChip(it,true));});}); if(window.renderMathInElement)try{renderMath(scope);}catch(_){} }
attachBoxTaps(); render();
return {placed,render,reset(){ for(const k in placed)delete placed[k];armed=null;render(); }};
}
/* === SVG-хелперы (axes2D, plotFunc, pointWithDrop, asymptote, snapToValue, геом.) === */
function axes2D(W, H, pad, xmin, xmax, ymin, ymax){
const ux = (W - 2*pad) / (xmax - xmin);
const uy = (H - 2*pad) / (ymax - ymin);
const toX = v => pad + (v - xmin) * ux;
const toY = v => H - pad - (v - ymin) * uy;
let g = '';
g += '<g stroke="#e5e7eb" stroke-width="1">';
for (let x = Math.ceil(xmin); x <= xmax; x++){
g += '<line x1="'+toX(x)+'" y1="'+pad+'" x2="'+toX(x)+'" y2="'+(H-pad)+'"/>';
}
for (let y = Math.ceil(ymin); y <= ymax; y++){
g += '<line x1="'+pad+'" y1="'+toY(y)+'" x2="'+(W-pad)+'" y2="'+toY(y)+'"/>';
}
g += '</g>';
const y0 = toY(0), x0 = toX(0);
g += '<line x1="'+pad+'" y1="'+y0+'" x2="'+(W-pad)+'" y2="'+y0+'" stroke="#0f172a" stroke-width="1.5"/>';
g += '<line x1="'+x0+'" y1="'+pad+'" x2="'+x0+'" y2="'+(H-pad)+'" stroke="#0f172a" stroke-width="1.5"/>';
g += '<text x="'+(W-pad+2)+'" y="'+(y0-4)+'" font-size="11" fill="#0f172a">x</text>';
g += '<text x="'+(x0+4)+'" y="'+(pad-2)+'" font-size="11" fill="#0f172a">y</text>';
g += '<g font-size="10" fill="#64748b">';
for (let x = Math.ceil(xmin); x <= xmax; x++){
if (x !== 0) g += '<text x="'+(toX(x)-3)+'" y="'+(y0+12)+'">'+x+'</text>';
}
for (let y = Math.ceil(ymin); y <= ymax; y++){
if (y !== 0) g += '<text x="'+(x0+4)+'" y="'+(toY(y)+3)+'">'+y+'</text>';
}
g += '<text x="'+(x0+4)+'" y="'+(y0+12)+'">0</text>';
g += '</g>';
return { content: g, toX, toY, ux, uy };
}
function plotFunc(f, xmin, xmax, toX, toY, color, N){
N = N || 200;
let d = '';
let prevValid = false;
for (let i = 0; i <= N; i++){
const x = xmin + (xmax - xmin) * i / N;
let y;
try { y = f(x); } catch(e){ y = NaN; }
if (!isFinite(y) || isNaN(y) || y < -1e4 || y > 1e4){ prevValid = false; continue; }
d += (prevValid ? ' L' : ' M') + toX(x).toFixed(2) + ',' + toY(y).toFixed(2);
prevValid = true;
}
return '<path d="'+d+'" stroke="'+color+'" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/>';
}
function pointWithDrop(x, fx, toX, toY, color, label){
const px = toX(x), py = toY(fx);
let s = '';
s += '<line x1="'+px+'" y1="'+py+'" x2="'+px+'" y2="'+toY(0)+'" stroke="'+color+'" stroke-width="1.2" stroke-dasharray="3 3" opacity=".7"/>';
s += '<line x1="'+px+'" y1="'+py+'" x2="'+toX(0)+'" y2="'+py+'" stroke="'+color+'" stroke-width="1.2" stroke-dasharray="3 3" opacity=".7"/>';
s += '<circle cx="'+px+'" cy="'+py+'" r="4.5" fill="'+color+'" stroke="#fff" stroke-width="2"/>';
if (label){
s += '<text x="'+(px+8)+'" y="'+(py-8)+'" font-family="Inter,sans-serif" font-size="12" font-weight="700" fill="'+color+'">'+label+'</text>';
}
return s;
}
function asymptote(orientation, value, toX, toY, xmin, xmax, ymin, ymax, color){
color = color || '#94a3b8';
if (orientation === 'h'){
const y = toY(value);
return '<line x1="'+toX(xmin)+'" y1="'+y+'" x2="'+toX(xmax)+'" y2="'+y+'" stroke="'+color+'" stroke-width="1.3" stroke-dasharray="6 4"/>';
} else {
const x = toX(value);
return '<line x1="'+x+'" y1="'+toY(ymin)+'" x2="'+x+'" y2="'+toY(ymax)+'" stroke="'+color+'" stroke-width="1.3" stroke-dasharray="6 4"/>';
}
}
function snapToValue(value, snapPoints, tolerance){
tolerance = tolerance || 0.1;
for (const sp of snapPoints){
if (Math.abs(value - sp) < tolerance) return sp;
}
return value;
}
function rightAngleMark(V, uIn, wIn, s){
s = s || 9;
const p1 = {x: V.x + s*uIn.x, y: V.y + s*uIn.y};
const c = {x: p1.x + s*wIn.x, y: p1.y + s*wIn.y};
const p2 = {x: V.x + s*wIn.x, y: V.y + s*wIn.y};
return p1.x+','+p1.y+' '+c.x+','+c.y+' '+p2.x+','+p2.y;
}
function angleArcAuto(V, uA, uB, R){
const sA = {x: V.x + R*uA.x, y: V.y + R*uA.y};
const eB = {x: V.x + R*uB.x, y: V.y + R*uB.y};
const cross = uA.x*uB.y - uA.y*uB.x;
const sweep = cross > 0 ? 1 : 0;
return 'M'+sA.x+','+sA.y+' A'+R+','+R+' 0 0,'+sweep+' '+eB.x+','+eB.y;
}
function unitVec(p1, p2){
const dx = p2.x - p1.x, dy = p2.y - p1.y;
const len = Math.sqrt(dx*dx + dy*dy) || 1;
return {x: dx/len, y: dy/len};
}
function deg2rad(d){ return d * Math.PI / 180; }
const ICONS = {
repeat:'<svg class="ic" viewBox="0 0 24 24"><polyline points="9 11 12 14 22 4"/><path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"/></svg>',
theory:'<svg class="ic" viewBox="0 0 24 24"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/></svg>',
algo:'<svg class="ic" viewBox="0 0 24 24"><polyline points="17 11 21 7 17 3"/><line x1="21" y1="7" x2="9" y2="7"/><polyline points="7 13 3 17 7 21"/><line x1="3" y1="17" x2="15" y2="17"/></svg>',
rule:'<svg class="ic" viewBox="0 0 24 24"><path d="M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9"/><path d="M10.3 21a1.94 1.94 0 0 0 3.4 0"/></svg>',
example:'<svg class="ic" viewBox="0 0 24 24"><path d="M9 18h6"/><path d="M10 22h4"/><path d="M12 2a7 7 0 0 0-4 13c1 1 2 2 2 4h4c0-2 1-3 2-4a7 7 0 0 0-4-13z"/></svg>',
oral:'<svg class="ic" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>',
};
function secNavFor(curId){
const idx = PARAS.findIndex(p => p.id === curId);
const prev = idx > 0 ? PARAS[idx-1].id : null;
const next = idx < PARAS.length - 1 ? PARAS[idx+1].id : null;
return secNav(prev, next);
}
function secNav(prev, next){
const NAMES = {p34:'\xA734',p35:'\xA735',p36:'\xA736',p37:'\xA737',final6:'Финал'};
let h='<div class="sec-nav">';
h+=prev?'<button class="btn" onclick="goTo(\''+prev+'\')"><svg class="ic" viewBox="0 0 24 24"><polyline points="15 18 9 12 15 6"/></svg> '+NAMES[prev]+'</button>':'<span></span>';
h+=next?'<button class="btn primary" onclick="goTo(\''+next+'\')">'+NAMES[next]+' <svg class="ic" viewBox="0 0 24 24"><polyline points="9 18 15 12 9 6"/></svg></button>':'<span></span>';
h+='</div>'; return h;
}
function readButton(paraId){
const p = PARAS.find(x => x.id === paraId);
const labelTail = p && p.final ? 'финал' : (p ? p.num : '\xA7?');
return '<div style="margin-top:18px;display:flex;justify-content:center">'
+'<button class="btn primary" id="'+paraId+'-read-btn">'
+'<svg class="ic" viewBox="0 0 24 24"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/></svg>'
+' Я прочитал — '+labelTail+' (+10 XP)'
+'</button></div>';
}
function wireReadBtn(paraId){
const btn = document.getElementById(paraId+'-read-btn'); if(!btn) return;
btn.addEventListener('click', ()=>{
addXp(10, paraId+'-read'); bumpProgress(paraId, 30);
btn.textContent='Прочитано! +10 XP'; btn.disabled=true; btn.style.opacity=.6;
const aId = paraId+'_done';
if(ACH_LABELS[aId]) achievement(aId);
});
}
/* ===== STUB BUILDERS — наполнение в Phase 1+ ===== */
function build_p34(){
const box = document.getElementById('p34-body');
let html = '';
/* THEORY 1 — Природа тока в металлах */
html += makeCard('theory', "Природа тока в металлах", "§34", `
<p>В <b>металлах</b> свободными носителями заряда являются <b>электроны проводимости</b> — внешние электроны атомов, не связанные с конкретным узлом решётки.</p>
<p style="margin-top:10px">Концентрация свободных электронов огромна: $n \\sim 10^{29}$ в м³.</p>
<p style="margin-top:10px"><b>Кристаллическая решётка</b> металла состоит из положительных ионов в узлах. Между ними движется «электронный газ» — почти свободные электроны.</p>
<p style="margin-top:10px"><b>Без электрического поля</b>: электроны движутся <b>хаотически</b> со скоростями $\\sim 10^5 - 10^6$ м/с. Средняя скорость направленного движения равна нулю — тока нет.</p>
<p style="margin-top:10px"><b>В электрическом поле $\\vec{E}$</b>: на хаотическое движение накладывается <b>дрейфовое</b> движение в сторону, противоположную $\\vec{E}$ (так как заряд электрона отрицательный). Средняя дрейфовая скорость очень мала: $v_{др} \\sim 10^{-3} - 10^{-5}$ м/с.</p>
<p style="margin-top:10px;padding:10px 14px;background:var(--sec-acc-soft);border-radius:9px"><b>Парадокс.</b> Дрейф электронов очень медленный, но ток в проводнике включается «мгновенно» — электрическое поле в проводнике устанавливается со скоростью света $c \\approx 3\\cdot 10^8$ м/с.</p>
`);
/* THEORY 2 — Сопротивление и температура */
html += makeCard('rule', "Сопротивление и зависимость от температуры", "§34", `
<p><b>Сопротивление</b> однородного проводника:</p>
<p style="text-align:center;margin:8px 0">$$R = \\rho\\,\\dfrac{L}{S}$$</p>
<ul style="margin:6px 0 6px 22px">
<li>$\\rho$ — удельное сопротивление (Ом·м);</li>
<li>$L$ — длина проводника (м);</li>
<li>$S$ — площадь поперечного сечения (м²).</li>
</ul>
<p style="margin-top:10px"><b>Зависимость от температуры</b> для металлов — линейная:</p>
<p style="text-align:center;margin:8px 0">$$\\rho(t) = \\rho_0\\,(1 + \\alpha t)$$</p>
<p>где $\\rho_0$ — удельное сопротивление при $0°$C, $t$ — температура в $°$C, $\\alpha$ — <b>температурный коэффициент сопротивления</b> (К$^{-1}$).</p>
<p style="margin-top:10px"><b>Эталонные значения $\\alpha$</b>:</p>
<ul style="margin:6px 0 6px 22px">
<li>Медь: $\\alpha \\approx 0{,}0043$ К$^{-1}$;</li>
<li>Алюминий: $\\alpha \\approx 0{,}0042$ К$^{-1}$;</li>
<li>Железо: $\\alpha \\approx 0{,}0066$ К$^{-1}$;</li>
<li>Платина: $\\alpha \\approx 0{,}0039$ К$^{-1}$ — используется в термометрах сопротивления.</li>
</ul>
<p style="margin-top:10px">С нагревом сопротивление металлов <b>увеличивается</b>: атомы решётки сильнее колеблются и чаще «мешают» электронам дрейфовать.</p>
`);
/* THEORY 3 — Сверхпроводимость */
html += makeCard('example', "Сверхпроводимость", "§34", `
<p><b>Сверхпроводимость</b> — явление полного исчезновения сопротивления у некоторых металлов при температурах ниже <b>критической</b> $T_c$.</p>
<p style="margin-top:10px">Открыта в 1911 году для ртути ($T_c = 4{,}2$ К — близко к абсолютному нулю).</p>
<p style="margin-top:10px"><b>Критические температуры</b>:</p>
<ul style="margin:6px 0 6px 22px">
<li>Ртуть: $T_c = 4{,}2$ К;</li>
<li>Свинец: $T_c = 7{,}2$ К;</li>
<li>Ниобий: $T_c = 9{,}2$ К;</li>
<li>Высокотемпературные сверхпроводники (керамика YBa$_2$Cu$_3$O$_7$): $T_c \\approx 95$ К — выше точки кипения жидкого азота (77 К). Открыты в 1986, революция, Нобелевская премия.</li>
</ul>
<p style="margin-top:10px"><b>В сверхпроводнике ток может циркулировать бесконечно долго без потерь.</b></p>
<p style="margin-top:10px"><b>Применение:</b></p>
<ul style="margin:6px 0 6px 22px">
<li><b>Сверхмощные магниты</b> — МРТ, ускорители (в Большом адронном коллайдере все магниты сверхпроводящие);</li>
<li><b>Маглев-поезда</b> — левитация на сверхпроводящих магнитах;</li>
<li><b>Беспотерьная передача электроэнергии</b> — экспериментально для коротких линий.</li>
</ul>
`);
/* INTERACTIVE 1 — Симуляция дрейфа электронов */
html += `<div class="wg" id="p34-iv1">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 1</span><div class="wg-title">Симуляция дрейфа электронов</div></div>
<div class="wg-help">При $U = 0$ — электроны движутся <b>хаотически</b>, тока нет. При $U > 0$ — на хаос накладывается медленный <b>дрейф</b> в сторону, противоположную $\\vec{E}$. Дрейф $\\Rightarrow$ ток.</div>
<div class="sliders">
<label>Напряжение $U$ (В): <b id="p34-iv1-UL">0.0</b><input type="range" id="p34-iv1-U" min="0" max="10" value="0" step="0.5"></label>
</div>
<div style="background:var(--card);border:1px solid var(--border);border-radius:9px;padding:8px;margin-top:8px">
<svg id="p34-iv1-svg" viewBox="0 0 380 240" width="100%" style="height:auto"></svg>
</div>
<div id="p34-iv1-out" style="margin-top:10px;padding:10px 14px;background:var(--sec-acc-soft);border-radius:9px;font-size:.95rem;line-height:1.7;text-align:center"></div>
</div>`;
/* INTERACTIVE 2 — Температурная зависимость */
html += `<div class="wg" id="p34-iv2">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 2</span><div class="wg-title">Сопротивление: график $R(t)$</div></div>
<div class="wg-help">Для металлов: $R(t) = R_0(1 + \\alpha t)$ — прямая линия. Сверхпроводники имеют <b>скачок</b> до $R = 0$ при $T < T_c$.</div>
<div class="sliders">
<label>Материал: <b id="p34-iv2-ML">Медь</b><input type="range" id="p34-iv2-M" min="0" max="3" value="0" step="1"></label>
<label>$R_0$ при $0°$C (Ом): <b id="p34-iv2-RL">1.0</b><input type="range" id="p34-iv2-R" min="0.1" max="10" value="1" step="0.1"></label>
</div>
<div style="background:var(--card);border:1px solid var(--border);border-radius:9px;padding:8px;margin-top:8px">
<svg id="p34-iv2-svg" viewBox="0 0 380 260" width="100%" style="height:auto"></svg>
</div>
<div id="p34-iv2-out" style="margin-top:10px;padding:10px 14px;background:var(--sec-acc-soft);border-radius:9px;font-size:.95rem;line-height:1.7;text-align:center"></div>
</div>`;
/* INTERACTIVE 3 — Носители заряда в разных средах */
html += `<div class="wg" id="p34-iv3">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 3</span><div class="wg-title">Кто переносит ток?</div></div>
<div class="wg-help">В каждой среде свои носители заряда — определи правильно.</div>
<div class="score-display"><span>Задача <b id="p34-iv3-i">1</b> / 6</span><span>Очки: <b id="p34-iv3-s">0</b> / 6</span></div>
<div id="p34-iv3-q" style="padding:14px;background:var(--sec-acc-soft);border-radius:10px;font-size:1.02rem;margin-bottom:10px;text-align:center;min-height:54px"></div>
<div id="p34-iv3-opts" style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:8px"></div>
<div class="feedback" id="p34-iv3-fb"></div>
<div class="actions"><button class="btn" id="p34-iv3-restart">Начать заново</button></div>
</div>`;
/* INTERACTIVE 4 — Тренажёр сопротивления */
html += `<div class="wg" id="p34-iv4">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 4</span><div class="wg-title">Тренажёр: сопротивление и сверхпроводимость</div></div>
<div class="wg-help">5 задач. Допуск $\\pm 5\\%$. Формулы: $R = \\rho L/S$, $R(t) = R_0(1+\\alpha t)$.</div>
<div class="score-display"><span>Задача <b id="p34-iv4-i">1</b> / 5</span><span>Очки: <b id="p34-iv4-s">0</b> / 5</span></div>
<div id="p34-iv4-q" style="padding:14px;background:var(--sec-acc-soft);border-radius:10px;font-size:1.02rem;margin-bottom:10px;text-align:center;min-height:54px"></div>
<div id="p34-iv4-form" style="display:flex;gap:8px;justify-content:center;margin-bottom:8px;flex-wrap:wrap">
<input type="number" id="p34-iv4-inp" step="any" style="padding:8px 10px;border:1px solid var(--border);border-radius:6px;width:140px;font-size:1rem">
<button class="btn primary" id="p34-iv4-go">Проверить</button>
</div>
<div class="feedback" id="p34-iv4-fb"></div>
<div class="actions"><button class="btn" id="p34-iv4-restart">Начать заново</button></div>
</div>`;
html += secNav(null, 'p35');
html += readButton('p34');
box.innerHTML = html;
renderMath(box);
/* IV1 — Дрейф электронов */
(function(){
const svg = document.getElementById('p34-iv1-svg');
const out = document.getElementById('p34-iv1-out');
const UI = document.getElementById('p34-iv1-U'), UL = document.getElementById('p34-iv1-UL');
const W = 380, H = 240;
// Решётка ионов: сетка
const ions = [];
for(let r=0; r<4; r++){
for(let c=0; c<7; c++){
ions.push({x: 40 + c*48, y: 50 + r*48});
}
}
// Электроны
const N = 22;
const els = [];
for(let k=0; k<N; k++){
els.push({
x: 30 + Math.random()*320,
y: 30 + Math.random()*180,
vx: (Math.random()-0.5)*1.8,
vy: (Math.random()-0.5)*1.8
});
}
let rafId = null;
let configsSeen = new Set(), _done = false;
function step(){
const U = +UI.value;
const drift = U * 0.18; // дрейфовая скорость "пиксели/кадр"
// обновим электроны: хаос + дрейф вправо (если U>0)
els.forEach(e => {
// случайные толчки от ионов
e.vx += (Math.random()-0.5)*0.45;
e.vy += (Math.random()-0.5)*0.45;
// ограничение
const sp = Math.hypot(e.vx, e.vy);
if(sp > 2.4){ e.vx *= 2.4/sp; e.vy *= 2.4/sp; }
e.x += e.vx + drift;
e.y += e.vy;
// отскок от границ
if(e.x < 16){ e.x = 364; }
if(e.x > 364){ e.x = 16; }
if(e.y < 16){ e.y = 16; e.vy = Math.abs(e.vy); }
if(e.y > 220){ e.y = 220; e.vy = -Math.abs(e.vy); }
});
draw();
rafId = requestAnimationFrame(step);
}
function draw(){
const U = +UI.value;
UL.textContent = U.toFixed(1);
let g = '';
g += '<rect x="0" y="0" width="'+W+'" height="'+H+'" fill="#fafafa"/>';
// рамка проводника
g += '<rect x="8" y="14" width="364" height="212" fill="none" stroke="#cbd5e1" stroke-width="1.4" rx="6"/>';
// подпись E
if(U > 0){
g += PHYS.drawArrow(40, 8, 90, 8, '#dc2626', 2, 8);
g += '<text x="100" y="12" font-family="JetBrains Mono,monospace" font-size="12" font-weight="700" fill="#dc2626">E</text>';
}
// ионы (большие красные +)
ions.forEach(io => {
g += '<circle cx="'+io.x+'" cy="'+io.y+'" r="7" fill="#fecaca" stroke="#dc2626" stroke-width="1.4"/>';
g += '<text x="'+io.x+'" y="'+(io.y+3.5)+'" text-anchor="middle" font-family="Inter,sans-serif" font-size="11" font-weight="800" fill="#7f1d1d">+</text>';
});
// электроны
els.forEach(e => {
g += '<circle cx="'+e.x.toFixed(1)+'" cy="'+e.y.toFixed(1)+'" r="3.2" fill="#0891b2" stroke="#fff" stroke-width="0.8"/>';
// вектор скорости
if(U > 0){
const sx = e.x, sy = e.y;
const ex = sx + 6, ey = sy;
g += '<line x1="'+sx.toFixed(1)+'" y1="'+sy.toFixed(1)+'" x2="'+ex.toFixed(1)+'" y2="'+ey.toFixed(1)+'" stroke="#0891b2" stroke-width="1" opacity=".7"/>';
}
});
svg.innerHTML = g;
const vDrift = U > 0 ? (U * 0.0002).toFixed(4) : '0';
out.innerHTML = U === 0
? 'При $U = 0$ электроны движутся <b>хаотически</b> — тока нет.'
: '$U = '+U.toFixed(1)+'$ В $\\Rightarrow$ дрейф электронов вправо, $v_{др} \\sim '+vDrift+'$ м/с (примерная оценка).';
renderMath(out);
}
UI.addEventListener('input', ()=>{
configsSeen.add(UI.value);
if(!_done && configsSeen.size >= 4){ _done = true; addXp(15, 'p34-iv1'); bumpProgress('p34', 20); }
});
draw();
rafId = requestAnimationFrame(step);
})();
/* IV2 — R(t) график */
(function(){
const svg = document.getElementById('p34-iv2-svg');
const out = document.getElementById('p34-iv2-out');
const MI = document.getElementById('p34-iv2-M'), ML = document.getElementById('p34-iv2-ML');
const RI = document.getElementById('p34-iv2-R'), RL = document.getElementById('p34-iv2-RL');
const MATS = [
{ name:'Медь', alpha:0.0043, color:'#b45309', sc:false },
{ name:'Алюминий', alpha:0.0042, color:'#64748b', sc:false },
{ name:'Железо', alpha:0.0066, color:'#374151', sc:false },
{ name:'Свинец (сверхпр. при $T<7{,}2$ К)', alpha:0.0042, color:'#7c3aed', sc:true, Tc:7.2 }
];
let switched = new Set(), _done = false;
function draw(){
const m = MATS[Math.min(3, Math.max(0, +MI.value))];
const R0 = +RI.value;
ML.innerHTML = m.name;
RL.textContent = R0.toFixed(1);
renderMath(MI.parentNode);
// Оси: t от -50 до 500 °C; R от 0 до примерно R0*(1+alpha*500)
const Rmax = R0 * (1 + m.alpha * 500) * 1.1;
const Wd = 380, Hd = 260, pad = 38;
const tmin = -50, tmax = 500;
const ux = (Wd - 2*pad) / (tmax - tmin);
const uy = (Hd - 2*pad) / (Rmax - 0);
const toX = t => pad + (t - tmin) * ux;
const toY = R => Hd - pad - R * uy;
let g = '';
g += '<rect x="0" y="0" width="'+Wd+'" height="'+Hd+'" fill="#fafafa"/>';
// сетка
g += '<g stroke="#e5e7eb" stroke-width="1">';
for(let t=0; t<=500; t+=100){
const x = toX(t);
g += '<line x1="'+x+'" y1="'+pad+'" x2="'+x+'" y2="'+(Hd-pad)+'"/>';
}
g += '</g>';
// оси
g += '<line x1="'+pad+'" y1="'+toY(0)+'" x2="'+(Wd-pad)+'" y2="'+toY(0)+'" stroke="#0f172a" stroke-width="1.4"/>';
g += '<line x1="'+toX(0)+'" y1="'+pad+'" x2="'+toX(0)+'" y2="'+(Hd-pad)+'" stroke="#0f172a" stroke-width="1.4"/>';
g += '<text x="'+(Wd-pad+2)+'" y="'+(toY(0)-4)+'" font-size="11" fill="#0f172a">t, °C</text>';
g += '<text x="'+(toX(0)+4)+'" y="'+(pad-2)+'" font-size="11" fill="#0f172a">R, Ом</text>';
// tick labels
g += '<g font-size="10" fill="#64748b">';
for(let t=0; t<=500; t+=100){
g += '<text x="'+(toX(t)-3)+'" y="'+(toY(0)+12)+'">'+t+'</text>';
}
g += '<text x="'+(toX(0)+4)+'" y="'+(toY(R0)+3)+'">'+R0.toFixed(1)+'</text>';
g += '</g>';
// Линия R(t)
let path = '';
for(let i=0; i<=80; i++){
const t = tmin + (tmax - tmin)*i/80;
const Rv = R0 * (1 + m.alpha * t);
path += (i===0 ? 'M' : 'L') + toX(t).toFixed(1) + ',' + toY(Math.max(0,Rv)).toFixed(1) + ' ';
}
g += '<path d="'+path+'" stroke="'+m.color+'" stroke-width="2.4" fill="none"/>';
// Если сверхпроводник — вертикальный скачок до 0 при T=Tc
if(m.sc){
// Tc в °C
const tcC = m.Tc - 273.15;
// отметим линию
const xTc = toX(tcC);
if(xTc > pad && xTc < Wd - pad){
g += '<line x1="'+xTc+'" y1="'+toY(0)+'" x2="'+xTc+'" y2="'+toY(R0)+'" stroke="#dc2626" stroke-width="2.2" stroke-dasharray="4 3"/>';
g += '<text x="'+(xTc+4)+'" y="'+toY(R0*0.5)+'" font-size="10" fill="#dc2626">T_c</text>';
}
g += '<text x="'+(Wd/2)+'" y="'+(Hd-8)+'" text-anchor="middle" font-size="10" fill="#7c3aed">Слева от $T_c$ — сверхпроводимость: $R = 0$</text>';
}
// Точка R при t=100
const t100 = 100;
const R100 = R0 * (1 + m.alpha * t100);
g += '<circle cx="'+toX(t100)+'" cy="'+toY(R100)+'" r="4.5" fill="'+m.color+'" stroke="#fff" stroke-width="2"/>';
g += '<text x="'+(toX(t100)+8)+'" y="'+(toY(R100)-6)+'" font-family="JetBrains Mono,monospace" font-size="10" fill="'+m.color+'">R(100°C) = '+R100.toFixed(2)+'</text>';
svg.innerHTML = g;
out.innerHTML = '$\\alpha = '+m.alpha.toFixed(4)+'$ К$^{-1}$ &nbsp; $R(100°C) = '+R0.toFixed(2)+'\\cdot(1+'+m.alpha.toFixed(4)+'\\cdot 100) = '+R100.toFixed(3)+'$ Ом';
renderMath(out);
}
MI.addEventListener('input', ()=>{
switched.add(MI.value);
draw();
if(!_done && switched.size >= 3){ _done = true; addXp(15, 'p34-iv2'); bumpProgress('p34', 20); }
});
RI.addEventListener('input', draw);
draw();
})();
/* IV3 — Носители заряда */
(function(){
const OPTS = ['Электроны', 'Ионы', 'Электроны + ионы'];
const Q = [
{ q:'В <b>металлах</b> ток переносят…', ans:0, why:'Свободные электроны проводимости (~$10^{29}$ в м³). Ионы решётки неподвижны.' },
{ q:'В <b>электролитах</b> (раствор соли) ток переносят…', ans:1, why:'Положительные катионы и отрицательные анионы движутся к электродам.' },
{ q:'В <b>газах при электрическом разряде</b> ток переносят…', ans:2, why:'Электроны (ионизированные при разряде) и положительные ионы.' },
{ q:'В <b>вакуумной электронной лампе</b> ток переносят…', ans:0, why:'Только электроны, испускаемые горячим катодом (термоэлектронная эмиссия).' },
{ q:'В <b>сверхпроводнике</b> (металл при $T<T_c$) ток переносят…', ans:0, why:'Электроны, но <b>без сопротивления</b> — куперовские пары не рассеиваются на решётке.' },
{ q:'В <b>полупроводнике</b> ток переносят…', ans:2, why:'Электроны проводимости и «дырки» (положительные носители) — оба типа.' }
];
let i = 0, score = 0;
const qEl = document.getElementById('p34-iv3-q');
const oEl = document.getElementById('p34-iv3-opts');
const fb = document.getElementById('p34-iv3-fb');
const iEl = document.getElementById('p34-iv3-i');
const sEl = document.getElementById('p34-iv3-s');
function show(){
if(i >= Q.length){
qEl.innerHTML = '<b>Готово!</b> Результат: ' + score + ' / ' + Q.length;
oEl.innerHTML = '';
if(score === Q.length){ addXp(15, 'p34-iv3'); bumpProgress('p34', 25); }
else if(score >= 4){ addXp(8, 'p34-iv3'); bumpProgress('p34', 15); }
return;
}
iEl.textContent = (i+1);
sEl.textContent = score;
qEl.innerHTML = Q[i].q;
oEl.innerHTML = OPTS.map((t,k) => '<button class="btn primary" data-v="'+k+'">'+t+'</button>').join('');
fb.style.display = 'none';
renderMath(qEl);
oEl.querySelectorAll('button').forEach(b => {
b.addEventListener('click', () => {
const v = +b.dataset.v;
if(v === Q[i].ans){ score++; feedback(fb, true, '&#10003; Верно! '+Q[i].why+' Дальше ▶'); }
else feedback(fb, false, '&#10007; Верно: '+OPTS[Q[i].ans]+'. '+Q[i].why+' Дальше ▶');
sEl.textContent = score;
oEl.querySelectorAll('button').forEach(x => x.disabled = true);
i++;
setTimeout(show, 1900);
});
});
}
document.getElementById('p34-iv3-restart').addEventListener('click', () => { i = 0; score = 0; show(); });
show();
})();
/* IV4 — Тренажёр */
(function(){
const Q = [
{ q:'Медь: $\\rho = 1{,}7\\cdot 10^{-8}$ Ом·м. Провод $L = 10$ м, сечение $S = 1$ мм² $= 10^{-6}$ м². Найди $R$ (Ом).', ans:0.17, tol:0.01, why:'$R = \\rho L/S = 1{,}7\\cdot 10^{-8}\\cdot 10 / 10^{-6} = 0{,}17$ Ом.' },
{ q:'Медь: $R_0 = 1$ Ом при $0°$C, $\\alpha = 0{,}0043$ К$^{-1}$. Найди $R$ при $100°$C (Ом).', ans:1.43, tol:0.05, why:'$R = R_0(1 + \\alpha t) = 1\\cdot(1 + 0{,}0043\\cdot 100) = 1{,}43$ Ом.' },
{ q:'Сверхпроводимость — это явление, когда $R$… (1=максимально, 2=равно нулю, 3=пропорц. $T$). Введи номер.', ans:2, tol:0.1, why:'При $T<T_c$ сопротивление сверхпроводника <b>равно нулю</b>.' },
{ q:'Первая критическая температура сверхпроводимости ртути (в кельвинах). Введи число.', ans:4.2, tol:0.3, why:'Камерлинг-Оннес, 1911: $T_c({Hg}) = 4{,}2$ К.' },
{ q:'Алюминий ($\\alpha = 0{,}0042$ К$^{-1}$). $R_0 = 5$ Ом при $0°$C. Найди $R$ при $50°$C (Ом).', ans:6.05, tol:0.2, why:'$R = 5(1 + 0{,}0042\\cdot 50) = 5\\cdot 1{,}21 = 6{,}05$ Ом.' }
];
let i = 0, score = 0;
const qEl = document.getElementById('p34-iv4-q');
const fb = document.getElementById('p34-iv4-fb');
const iEl = document.getElementById('p34-iv4-i');
const sEl = document.getElementById('p34-iv4-s');
const inp = document.getElementById('p34-iv4-inp');
const bGo = document.getElementById('p34-iv4-go');
function show(){
if(i >= Q.length){
qEl.innerHTML = '<b>Готово!</b> Результат: ' + score + ' / ' + Q.length;
inp.disabled = true; bGo.disabled = true;
if(score === Q.length){ addXp(15, 'p34-iv4'); bumpProgress('p34', 25); }
else if(score >= 3){ addXp(8, 'p34-iv4'); bumpProgress('p34', 15); }
return;
}
iEl.textContent = (i+1);
sEl.textContent = score;
qEl.innerHTML = Q[i].q;
fb.style.display = 'none';
inp.value = ''; inp.disabled = false; bGo.disabled = false; inp.focus();
renderMath(qEl);
}
function check(){
if(inp.disabled) return;
const v = parseFloat(inp.value.replace(',','.'));
if(!isFinite(v)){ feedback(fb, false, 'Введи число.'); return; }
const tol = Math.max(Q[i].tol, Math.abs(Q[i].ans)*0.05);
const ok = Math.abs(v - Q[i].ans) <= tol;
if(ok){ score++; feedback(fb, true, '&#10003; Верно! '+Q[i].why+' Дальше ▶'); }
else feedback(fb, false, '&#10007; Верно: '+Q[i].ans+'. '+Q[i].why+' Дальше ▶');
sEl.textContent = score;
inp.disabled = true; bGo.disabled = true;
i++;
setTimeout(show, 1900);
}
bGo.addEventListener('click', check);
inp.addEventListener('keydown', e => { if(e.key==='Enter') check(); });
document.getElementById('p34-iv4-restart').addEventListener('click', () => { i = 0; score = 0; inp.disabled=false; bGo.disabled=false; show(); });
show();
})();
wireReadBtn('p34');
}
function build_p35(){
const box = document.getElementById('p35-body');
let html = '';
/* THEORY 1 — Электролиты и ионная проводимость */
html += makeCard('theory', "Электролиты и ионная проводимость", "§35", `
<p><b>Электролиты</b> — вещества, проводящие электрический ток в растворе или расплаве за счёт движения ионов:</p>
<ul style="margin:6px 0 6px 22px">
<li>Растворы солей, кислот, щелочей в воде;</li>
<li>Расплавы солей.</li>
</ul>
<p style="margin-top:10px">В электролите присутствуют <b>свободные ионы</b> — продукт диссоциации молекул электролита:</p>
<ul style="margin:6px 0 6px 22px">
<li><b>Катионы</b> ($+$): Na$^+$, K$^+$, Cu$^{2+}$, Fe$^{2+}$, H$^+$ и др.;</li>
<li><b>Анионы</b> ($-$): Cl$^-$, SO$_4^{2-}$, NO$_3^-$, OH$^-$ и др.</li>
</ul>
<p style="margin-top:10px"><b>В электрическом поле</b> ионы движутся к электродам:</p>
<ul style="margin:6px 0 6px 22px">
<li>Катионы $(+)$ — к <b>катоду</b> $(-$ электрод);</li>
<li>Анионы $(-)$ — к <b>аноду</b> $(+$ электрод).</li>
</ul>
<p style="margin-top:10px;padding:10px 14px;background:var(--sec-acc-soft);border-radius:9px"><b>Главное отличие от металлов:</b> в электролите переносится не только заряд, но и <b>вещество</b> — на электродах идут химические реакции. Это явление называется <b>электролизом</b>.</p>
`);
/* THEORY 2 — Законы Фарадея */
html += makeCard('rule', "Законы Фарадея для электролиза", "§35", `
<p><b>Первый закон Фарадея</b>: масса вещества, выделившегося на электроде, прямо пропорциональна заряду, прошедшему через электролит:</p>
<p style="text-align:center;margin:8px 0">$$m = k\\,I\\,t = k\\,q$$</p>
<ul style="margin:6px 0 6px 22px">
<li>$m$ — масса вещества (кг);</li>
<li>$I$ — сила тока (А);</li>
<li>$t$ — время (с);</li>
<li>$k$ — <b>электрохимический эквивалент</b> вещества (кг/Кл).</li>
</ul>
<p style="margin-top:10px"><b>Второй закон Фарадея</b>: электрохимический эквивалент пропорционален молярной массе и обратно пропорционален валентности:</p>
<p style="text-align:center;margin:8px 0">$$k = \\dfrac{M}{F\\,n}$$</p>
<ul style="margin:6px 0 6px 22px">
<li>$M$ — молярная масса (кг/моль);</li>
<li>$n$ — валентность иона;</li>
<li>$F = N_A\\,e \\approx 96\\,500$ Кл/моль — <b>постоянная Фарадея</b>.</li>
</ul>
<p style="margin-top:10px"><b>Объединённый закон Фарадея</b>:</p>
<p style="text-align:center;margin:8px 0">$$m = \\dfrac{M}{F\\,n}\\,I\\,t$$</p>
<p style="margin-top:10px;padding:10px 14px;background:var(--sec-acc-soft);border-radius:9px"><b>Физический смысл $F$:</b> это заряд $\\sim 1$ моль однозарядных ионов, $F = N_A\\,e \\approx 6{,}022\\cdot 10^{23}\\cdot 1{,}6\\cdot 10^{-19} \\approx 96\\,500$ Кл.</p>
`);
/* THEORY 3 — Применение электролиза */
html += makeCard('example', "Применение электролиза", "§35", `
<p><b>Промышленные применения</b>:</p>
<ul style="margin:6px 0 6px 22px">
<li><b>Электролиз алюминия</b> — основной способ его получения из боксита. Огромные ванны рядом с электростанциями.</li>
<li><b>Электрометаллургия меди</b>: получение чистой меди электролизом раствора CuSO$_4$.</li>
<li><b>Производство хлора и каустической соды</b> — электролиз раствора NaCl.</li>
<li><b>Гальванопластика</b>: точные металлические копии скульптур, форм для печати — осаждение металла на форму.</li>
<li><b>Гальваностегия</b>: декоративные и защитные покрытия — хромирование, золочение, никелирование.</li>
<li><b>Зарядка аккумуляторов</b> — процесс, обратный разрядке (тоже электролиз).</li>
</ul>
<p style="margin-top:10px"><b>Пример расчёта.</b> Сколько меди ($M = 64$ г/моль, $n = 2$) выделится на катоде при $I = 5$ А за $t = 1$ ч?</p>
<p style="text-align:center;margin:8px 0">$m = \\dfrac{M I t}{F n} = \\dfrac{0{,}064 \\cdot 5 \\cdot 3600}{96\\,500 \\cdot 2} \\approx 5{,}97$ г</p>
<p style="margin-top:10px"><b>Серебро</b> $(M = 108$ г/моль, $n = 1)$ при тех же условиях:</p>
<p style="text-align:center;margin:8px 0">$m = \\dfrac{0{,}108 \\cdot 5 \\cdot 3600}{96\\,500 \\cdot 1} \\approx 20{,}15$ г — почти в 4 раза больше!</p>
`);
/* INTERACTIVE 1 — Симуляция электролиза */
html += `<div class="wg" id="p35-iv1">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 1</span><div class="wg-title">Симуляция электролиза</div></div>
<div class="wg-help">Положительные катионы (красные) движутся к <b>катоду</b> (слева, $-$). Отрицательные анионы (синие) — к <b>аноду</b> (справа, $+$). Скорость пропорциональна току $I$.</div>
<div class="sliders">
<label>Сила тока $I$ (А): <b id="p35-iv1-IL">0.0</b><input type="range" id="p35-iv1-I" min="0" max="10" value="0" step="0.5"></label>
</div>
<div style="background:var(--card);border:1px solid var(--border);border-radius:9px;padding:8px;margin-top:8px">
<svg id="p35-iv1-svg" viewBox="0 0 380 280" width="100%" style="height:auto"></svg>
</div>
<div id="p35-iv1-out" style="margin-top:10px;padding:10px 14px;background:var(--sec-acc-soft);border-radius:9px;font-size:.95rem;line-height:1.7;text-align:center"></div>
</div>`;
/* INTERACTIVE 2 — Калькулятор электролиза */
html += `<div class="wg" id="p35-iv2">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 2</span><div class="wg-title">Калькулятор массы вещества при электролизе</div></div>
<div class="wg-help">Формула: $m = \\dfrac{M\\,I\\,t}{F\\,n}$, $F = 96\\,500$ Кл/моль.</div>
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:10px;margin-bottom:10px">
<label style="display:flex;flex-direction:column;gap:4px;font-size:.92rem">Вещество:
<select id="p35-iv2-sub" style="padding:7px;border:1px solid var(--border);border-radius:6px">
<option value="0">Медь (Cu): M=64, n=2</option>
<option value="1">Серебро (Ag): M=108, n=1</option>
<option value="2">Алюминий (Al): M=27, n=3</option>
<option value="3">Железо (Fe): M=56, n=2</option>
<option value="4">Водород (H): M=1, n=1</option>
</select>
</label>
<label style="display:flex;flex-direction:column;gap:4px;font-size:.92rem">$I$ (А):<input type="number" id="p35-iv2-I" value="5" step="0.1" min="0" style="padding:7px;border:1px solid var(--border);border-radius:6px"></label>
<label style="display:flex;flex-direction:column;gap:4px;font-size:.92rem">$t$ (с):<input type="number" id="p35-iv2-t" value="3600" step="any" min="0" style="padding:7px;border:1px solid var(--border);border-radius:6px"></label>
</div>
<div class="actions"><button class="btn primary" id="p35-iv2-calc">Вычислить массу $m$</button></div>
<div id="p35-iv2-out" style="margin-top:10px;padding:10px 14px;background:var(--sec-acc-soft);border-radius:9px;font-size:.98rem;line-height:1.8;text-align:center;min-height:40px"></div>
</div>`;
/* INTERACTIVE 3 — Куда движется ион? */
html += `<div class="wg" id="p35-iv3">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 3</span><div class="wg-title">Куда движется ион?</div></div>
<div class="wg-help">Катионы $(+)$ → к катоду $(-)$. Анионы $(-)$ → к аноду $(+)$.</div>
<div class="score-display"><span>Задача <b id="p35-iv3-i">1</b> / 6</span><span>Очки: <b id="p35-iv3-s">0</b> / 6</span></div>
<div id="p35-iv3-q" style="padding:14px;background:var(--sec-acc-soft);border-radius:10px;font-size:1.05rem;margin-bottom:10px;text-align:center;min-height:54px"></div>
<div id="p35-iv3-opts" style="display:grid;grid-template-columns:1fr 1fr;gap:8px"></div>
<div class="feedback" id="p35-iv3-fb"></div>
<div class="actions"><button class="btn" id="p35-iv3-restart">Начать заново</button></div>
</div>`;
/* INTERACTIVE 4 — Тренажёр электролиза */
html += `<div class="wg" id="p35-iv4">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 4</span><div class="wg-title">Тренажёр: электролиз</div></div>
<div class="wg-help">5 задач. $F = 96\\,500$ Кл/моль. Допуск $\\pm 5\\%$.</div>
<div class="score-display"><span>Задача <b id="p35-iv4-i">1</b> / 5</span><span>Очки: <b id="p35-iv4-s">0</b> / 5</span></div>
<div id="p35-iv4-q" style="padding:14px;background:var(--sec-acc-soft);border-radius:10px;font-size:1.02rem;margin-bottom:10px;text-align:center;min-height:54px"></div>
<div id="p35-iv4-form" style="display:flex;gap:8px;justify-content:center;margin-bottom:8px;flex-wrap:wrap">
<input type="number" id="p35-iv4-inp" step="any" style="padding:8px 10px;border:1px solid var(--border);border-radius:6px;width:140px;font-size:1rem">
<button class="btn primary" id="p35-iv4-go">Проверить</button>
</div>
<div class="feedback" id="p35-iv4-fb"></div>
<div class="actions"><button class="btn" id="p35-iv4-restart">Начать заново</button></div>
</div>`;
html += secNav('p34', 'p36');
html += readButton('p35');
box.innerHTML = html;
renderMath(box);
/* IV1 — Симуляция электролиза */
(function(){
const svg = document.getElementById('p35-iv1-svg');
const out = document.getElementById('p35-iv1-out');
const II = document.getElementById('p35-iv1-I'), IL = document.getElementById('p35-iv1-IL');
const W = 380, H = 280;
// Ионы: красные катионы (+) и синие анионы (-)
const NCat = 12, NAn = 12;
const cats = [], ans = [];
for(let k=0; k<NCat; k++){
cats.push({ x: 80 + Math.random()*220, y: 80 + Math.random()*160, vy: (Math.random()-0.5)*1.0 });
}
for(let k=0; k<NAn; k++){
ans.push({ x: 80 + Math.random()*220, y: 80 + Math.random()*160, vy: (Math.random()-0.5)*1.0 });
}
let rafId = null;
let configs = new Set(), _done = false;
function step(){
const I = +II.value;
const v = I * 0.25;
cats.forEach(p => {
p.x -= v; // катионы влево (к катоду)
p.vy += (Math.random()-0.5)*0.4;
if(Math.abs(p.vy) > 1.4) p.vy *= 0.7;
p.y += p.vy;
if(p.x < 75){ p.x = 295; }
if(p.y < 80){ p.y = 80; p.vy = Math.abs(p.vy); }
if(p.y > 240){ p.y = 240; p.vy = -Math.abs(p.vy); }
});
ans.forEach(p => {
p.x += v; // анионы вправо (к аноду)
p.vy += (Math.random()-0.5)*0.4;
if(Math.abs(p.vy) > 1.4) p.vy *= 0.7;
p.y += p.vy;
if(p.x > 305){ p.x = 85; }
if(p.y < 80){ p.y = 80; p.vy = Math.abs(p.vy); }
if(p.y > 240){ p.y = 240; p.vy = -Math.abs(p.vy); }
});
draw();
rafId = requestAnimationFrame(step);
}
function draw(){
const I = +II.value;
IL.textContent = I.toFixed(1);
let g = '';
g += '<rect x="0" y="0" width="'+W+'" height="'+H+'" fill="#fafafa"/>';
// ванна с электролитом
g += '<rect x="60" y="65" width="260" height="195" rx="10" fill="#e0f2fe" stroke="#0891b2" stroke-width="2"/>';
g += '<text x="190" y="58" text-anchor="middle" font-family="Inter,sans-serif" font-size="11" font-weight="700" fill="#0f172a">Электролит (раствор)</text>';
// катод (слева, минус)
g += '<rect x="70" y="75" width="14" height="180" fill="#6b7280" stroke="#374151" stroke-width="1.4"/>';
g += '<text x="77" y="68" text-anchor="middle" font-family="JetBrains Mono,monospace" font-size="13" font-weight="800" fill="#0891b2">К ('+''+')</text>';
// анод (справа, плюс)
g += '<rect x="296" y="75" width="14" height="180" fill="#6b7280" stroke="#374151" stroke-width="1.4"/>';
g += '<text x="303" y="68" text-anchor="middle" font-family="JetBrains Mono,monospace" font-size="13" font-weight="800" fill="#dc2626">А (+)</text>';
// батарея внизу
g += '<text x="190" y="276" text-anchor="middle" font-family="Inter,sans-serif" font-size="10" fill="#64748b">Источник тока</text>';
g += PHYS.batteryEMF(190, 270, undefined, 'h');
// провода
g += PHYS.wire(77, 257, 77, 270);
g += PHYS.wire(77, 270, 175, 270);
g += PHYS.wire(205, 270, 303, 270);
g += PHYS.wire(303, 270, 303, 257);
// ионы — катионы (красные, +)
cats.forEach(p => {
g += '<circle cx="'+p.x.toFixed(1)+'" cy="'+p.y.toFixed(1)+'" r="6" fill="#fecaca" stroke="#dc2626" stroke-width="1.4"/>';
g += '<text x="'+p.x.toFixed(1)+'" y="'+(p.y+3).toFixed(1)+'" text-anchor="middle" font-family="Inter,sans-serif" font-size="10" font-weight="800" fill="#7f1d1d">+</text>';
});
// анионы (синие, -)
ans.forEach(p => {
g += '<circle cx="'+p.x.toFixed(1)+'" cy="'+p.y.toFixed(1)+'" r="6" fill="#dbeafe" stroke="#1d4ed8" stroke-width="1.4"/>';
g += '<text x="'+p.x.toFixed(1)+'" y="'+(p.y+3).toFixed(1)+'" text-anchor="middle" font-family="Inter,sans-serif" font-size="11" font-weight="800" fill="#1e3a8a">'+''+'</text>';
});
// стрелка направления для катионов и анионов
if(I > 0){
g += PHYS.drawArrow(200, 50, 130, 50, '#dc2626', 1.6, 7);
g += '<text x="200" y="48" font-family="Inter,sans-serif" font-size="10" fill="#dc2626">катионы</text>';
g += PHYS.drawArrow(180, 30, 250, 30, '#1d4ed8', 1.6, 7);
g += '<text x="120" y="33" font-family="Inter,sans-serif" font-size="10" fill="#1d4ed8">анионы</text>';
}
svg.innerHTML = g;
out.innerHTML = I === 0
? 'При $I = 0$ ионы движутся хаотически (тока нет).'
: '$I = '+I.toFixed(1)+'$ А — катионы дрейфуют к <b>катоду</b> ($-$), анионы к <b>аноду</b> ($+$).';
renderMath(out);
}
II.addEventListener('input', ()=>{
configs.add(II.value);
if(!_done && configs.size >= 4){ _done = true; addXp(15, 'p35-iv1'); bumpProgress('p35', 20); }
});
draw();
rafId = requestAnimationFrame(step);
})();
/* IV2 — Калькулятор */
(function(){
const out = document.getElementById('p35-iv2-out');
const sub = document.getElementById('p35-iv2-sub');
const iI = document.getElementById('p35-iv2-I');
const iT = document.getElementById('p35-iv2-t');
const bGo = document.getElementById('p35-iv2-calc');
const SUBS = [
{ name:'Cu (медь)', M:0.064, n:2 },
{ name:'Ag (серебро)', M:0.108, n:1 },
{ name:'Al (алюминий)', M:0.027, n:3 },
{ name:'Fe (железо)', M:0.056, n:2 },
{ name:'H (водород)', M:0.001, n:1 }
];
const F = 96500;
let count = 0, _done = false;
function calc(){
const s = SUBS[+sub.value];
const I = +iI.value, t = +iT.value;
if(![I,t].every(isFinite) || I < 0 || t < 0){
out.innerHTML = '<b style="color:#dc2626">Проверь ввод: $I \\ge 0$, $t \\ge 0$.</b>';
renderMath(out);
return;
}
const m_kg = (s.M * I * t) / (F * s.n);
const m_g = m_kg * 1000;
let html = '';
html += '<b>'+s.name+'</b>: $M = '+(s.M*1000)+'$ г/моль, $n = '+s.n+'$<br>';
html += '$m = \\dfrac{M\\,I\\,t}{F\\,n} = \\dfrac{'+s.M+'\\cdot '+I+'\\cdot '+t+'}{'+F+'\\cdot '+s.n+'}$<br>';
html += '$m \\approx $ <b>'+m_g.toFixed(3)+' г</b> ($'+m_kg.toExponential(3)+'$ кг)';
out.innerHTML = html;
renderMath(out);
count++;
if(!_done && count >= 3){ _done = true; addXp(10, 'p35-iv2'); bumpProgress('p35', 15); }
}
bGo.addEventListener('click', calc);
[iI, iT].forEach(x => x.addEventListener('keydown', e => { if(e.key==='Enter') calc(); }));
sub.addEventListener('change', calc);
})();
/* IV3 — Куда движется ион */
(function(){
const OPTS = ['К катоду ()', 'К аноду (+)'];
const Q = [
{ q:'Ион меди Cu$^{2+}$ движется…', ans:0, why:'Катион (+) → к катоду ($-$). На катоде восстанавливается до Cu.' },
{ q:'Ион SO$_4^{2-}$ движется…', ans:1, why:'Анион ($-$) → к аноду (+).' },
{ q:'Ион натрия Na$^+$ движется…', ans:0, why:'Катион → к катоду.' },
{ q:'Ион хлора Cl$^-$ движется…', ans:1, why:'Анион → к аноду. На аноде окисляется до Cl$_2$.' },
{ q:'Ион водорода H$^+$ движется…', ans:0, why:'Катион → к катоду. На катоде восстанавливается до H$_2$.' },
{ q:'Ион гидроксила OH$^-$ движется…',ans:1, why:'Анион → к аноду. На аноде окисляется (выделяется O$_2$).' }
];
let i = 0, score = 0;
const qEl = document.getElementById('p35-iv3-q');
const oEl = document.getElementById('p35-iv3-opts');
const fb = document.getElementById('p35-iv3-fb');
const iEl = document.getElementById('p35-iv3-i');
const sEl = document.getElementById('p35-iv3-s');
function show(){
if(i >= Q.length){
qEl.innerHTML = '<b>Готово!</b> Результат: ' + score + ' / ' + Q.length;
oEl.innerHTML = '';
if(score === Q.length){ addXp(15, 'p35-iv3'); bumpProgress('p35', 25); }
else if(score >= 4){ addXp(8, 'p35-iv3'); bumpProgress('p35', 15); }
return;
}
iEl.textContent = (i+1);
sEl.textContent = score;
qEl.innerHTML = Q[i].q;
oEl.innerHTML = OPTS.map((t,k) => '<button class="btn primary" data-v="'+k+'">'+t+'</button>').join('');
fb.style.display = 'none';
renderMath(qEl);
oEl.querySelectorAll('button').forEach(b => {
b.addEventListener('click', () => {
const v = +b.dataset.v;
if(v === Q[i].ans){ score++; feedback(fb, true, '&#10003; Верно! '+Q[i].why+' Дальше ▶'); }
else feedback(fb, false, '&#10007; Верно: '+OPTS[Q[i].ans]+'. '+Q[i].why+' Дальше ▶');
sEl.textContent = score;
oEl.querySelectorAll('button').forEach(x => x.disabled = true);
i++;
setTimeout(show, 1900);
});
});
}
document.getElementById('p35-iv3-restart').addEventListener('click', () => { i = 0; score = 0; show(); });
show();
})();
/* IV4 — Тренажёр */
(function(){
const Q = [
{ q:'$I = 2$ А, $t = 30$ мин $= 1800$ с. Медь (Cu, $M = 64$ г/моль, $n = 2$), $F = 96\\,500$ Кл/моль. Найди $m$ (в <b>граммах</b>).', ans:1.19, tol:0.06, why:'$m = MIt/(Fn) = 64\\cdot 2\\cdot 1800/(96\\,500\\cdot 2) \\approx 1{,}19$ г.' },
{ q:'$I = 5$ А, $t = 1$ ч $= 3600$ с. Медь ($M=64$, $n=2$). Найди $m$ (г).', ans:5.97, tol:0.3, why:'$m = 64\\cdot 5\\cdot 3600/(96\\,500\\cdot 2) \\approx 5{,}97$ г.' },
{ q:'Серебро ($M = 108$ г/моль, $n = 1$). $I = 1$ А, $t = 3600$ с. Найди $m$ (г).', ans:4.03, tol:0.2, why:'$m = 108\\cdot 1\\cdot 3600/(96\\,500\\cdot 1) \\approx 4{,}03$ г.' },
{ q:'К какому электроду движутся <b>катионы</b>? (1 = анод, 2 = катод). Введи номер.', ans:2, tol:0.1, why:'Катионы $(+)$ движутся к катоду $(-)$.' },
{ q:'Постоянная Фарадея $F$ в Кл/моль (округлённое значение). Введи число.', ans:96500, tol:500, why:'$F = N_A \\cdot e \\approx 96\\,500$ Кл/моль.' }
];
let i = 0, score = 0;
const qEl = document.getElementById('p35-iv4-q');
const fb = document.getElementById('p35-iv4-fb');
const iEl = document.getElementById('p35-iv4-i');
const sEl = document.getElementById('p35-iv4-s');
const inp = document.getElementById('p35-iv4-inp');
const bGo = document.getElementById('p35-iv4-go');
function show(){
if(i >= Q.length){
qEl.innerHTML = '<b>Готово!</b> Результат: ' + score + ' / ' + Q.length;
inp.disabled = true; bGo.disabled = true;
if(score === Q.length){ addXp(15, 'p35-iv4'); bumpProgress('p35', 25); }
else if(score >= 3){ addXp(8, 'p35-iv4'); bumpProgress('p35', 15); }
return;
}
iEl.textContent = (i+1);
sEl.textContent = score;
qEl.innerHTML = Q[i].q;
fb.style.display = 'none';
inp.value = ''; inp.disabled = false; bGo.disabled = false; inp.focus();
renderMath(qEl);
}
function check(){
if(inp.disabled) return;
const v = parseFloat(inp.value.replace(',','.'));
if(!isFinite(v)){ feedback(fb, false, 'Введи число.'); return; }
const tol = Math.max(Q[i].tol, Math.abs(Q[i].ans)*0.05);
const ok = Math.abs(v - Q[i].ans) <= tol;
if(ok){ score++; feedback(fb, true, '&#10003; Верно! '+Q[i].why+' Дальше ▶'); }
else feedback(fb, false, '&#10007; Верно: '+Q[i].ans+'. '+Q[i].why+' Дальше ▶');
sEl.textContent = score;
inp.disabled = true; bGo.disabled = true;
i++;
setTimeout(show, 1900);
}
bGo.addEventListener('click', check);
inp.addEventListener('keydown', e => { if(e.key==='Enter') check(); });
document.getElementById('p35-iv4-restart').addEventListener('click', () => { i = 0; score = 0; inp.disabled=false; bGo.disabled=false; show(); });
show();
})();
wireReadBtn('p35');
}
function build_p36(){
const box = document.getElementById('p36-body');
let html = '';
/* THEORY 1 — Ионизация газа */
html += makeCard('theory', "Ионизация газа", "§36", `
<p>В <b>нормальных условиях</b> газы — <b>диэлектрики</b>: молекулы электрически нейтральны, свободных зарядов нет.</p>
<p style="margin-top:10px"><b>Ионизация</b> — процесс, при котором атом или молекула теряет электрон, превращаясь в <b>положительный ион</b>. В газе образуются:</p>
<ul style="margin:6px 0 6px 22px">
<li><b>Положительные ионы</b> (потерявшие электрон атомы);</li>
<li><b>Свободные электроны</b>.</li>
</ul>
<p style="margin-top:10px"><b>Причины ионизации</b>:</p>
<ul style="margin:6px 0 6px 22px">
<li><b>Высокая температура</b> (нагрев): тепловое движение → столкновения с энергией, достаточной для отрыва электрона;</li>
<li><b>Излучение</b>: ультрафиолет, рентген, $\\gamma$-кванты;</li>
<li><b>Сильное электрическое поле</b>;</li>
<li><b>Удары быстрых частиц</b>: космические лучи, электроны.</li>
</ul>
<p style="margin-top:10px">Ионизованный газ <b>проводит ток</b> — носителями заряда служат ионы и электроны.</p>
<p style="margin-top:10px;padding:10px 14px;background:var(--sec-acc-soft);border-radius:9px"><b>Рекомбинация</b> — обратный процесс: ион $+$ электрон $\\to$ нейтральный атом. Без поддержки ионизатора в обычном газе она быстро прекращает ток.</p>
`);
/* THEORY 2 — Виды разрядов */
html += makeCard('rule', "Виды газовых разрядов", "§36", `
<p><b>Несамостоятельный разряд</b>: ток в газе поддерживается только при действии <b>внешнего ионизатора</b> (УФ-лампа, нагрев, радиация). При его удалении ток быстро прекращается из-за рекомбинации.</p>
<p style="margin-top:10px"><b>Самостоятельный разряд</b>: ионизация поддерживается <b>самим током</b> — электроны, разогнанные полем, выбивают новые электроны (электронная лавина). Газ светится.</p>
<p style="margin-top:10px;font-weight:600">Четыре основных вида самостоятельных разрядов:</p>
<ul style="margin:6px 0 6px 22px">
<li><b>Тлеющий</b> — при <b>низком давлении</b> в трубках с холодными электродами. Применение: <b>лампы дневного света</b>, неоновая реклама.</li>
<li><b>Дуговой</b> — яркое свечение между раскалёнными электродами. Применение: <b>сварка</b>, прожекторы, мощные фонари.</li>
<li><b>Искровой</b> — мгновенный пробой газа. Примеры: <b>молния</b> (плазменный канал до $3$ км), свеча зажигания в авто.</li>
<li><b>Коронный</b> — слабое свечение у <b>остриёв</b> и тонких проводов при высоком напряжении. Слышно «гудение» проводов ЛЭП — там идут потери энергии.</li>
</ul>
<p style="margin-top:10px;padding:10px 14px;background:var(--sec-acc-soft);border-radius:9px;font-size:.93rem"><b>Запомни:</b> молния $\\Rightarrow$ <b>искровой</b>, лампа дневного света $\\Rightarrow$ <b>тлеющий</b>, сварка $\\Rightarrow$ <b>дуговой</b>, провода ЛЭП $\\Rightarrow$ <b>коронный</b>.</p>
`);
/* THEORY 3 — Плазма */
html += makeCard('example', "Плазма — четвёртое состояние вещества", "§36", `
<p><b>Плазма</b> — это <b>четвёртое агрегатное состояние</b> вещества: <b>ионизованный газ</b> с приблизительно равными концентрациями положительных ионов и электронов.</p>
<p style="margin-top:10px">В целом плазма электрически <b>квазинейтральна</b> (нейтральна в среднем), но содержит огромное число свободных зарядов.</p>
<p style="margin-top:10px;font-weight:600">Свойства плазмы:</p>
<ul style="margin:6px 0 6px 22px">
<li><b>Высокая электропроводность</b> — сравнима с металлами;</li>
<li><b>Сильное взаимодействие с магнитным полем</b> — заряженные частицы закручиваются по силовым линиям;</li>
<li><b>Излучает свет</b> — за счёт переходов электронов в возбуждённых атомах;</li>
<li>Существует в широком диапазоне температур: от $\\sim 10^3$ К до $\\sim 10^7$ К и выше.</li>
</ul>
<p style="margin-top:10px;font-weight:600">Где встречается плазма:</p>
<ul style="margin:6px 0 6px 22px">
<li><b>Солнце и все звёзды</b> — гигантские плазменные шары;</li>
<li><b>Молния</b> — мгновенный плазменный канал;</li>
<li><b>Северное и южное сияние</b> — солнечная плазма $+$ атмосфера $+$ магнитное поле Земли;</li>
<li><b>Газоразрядные лампы</b>, плазменные мониторы;</li>
<li><b>Термоядерные реакторы</b> (ТОКАМАК, ITER) — удержание плазмы магнитным полем для синтеза.</li>
</ul>
<p style="margin-top:10px;padding:10px 14px;background:var(--sec-acc-soft);border-radius:9px"><b>Удивительно:</b> плазма — самое распространённое состояние видимого вещества во Вселенной — более <b>$99\\%$</b>!</p>
`);
/* INTERACTIVE 1 — Виды разрядов (галерея) */
html += `<div class="wg" id="p36-iv1">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 1</span><div class="wg-title">Виды разрядов в газах</div></div>
<div class="wg-help">Пролистай 4 типа разрядов — у каждого свой механизм и характерное применение.</div>
<div class="sliders">
<label>Тип разряда: <b id="p36-iv1-NL">1 / 4</b><input type="range" id="p36-iv1-N" min="1" max="4" value="1" step="1"></label>
</div>
<div style="background:var(--card);border:1px solid var(--border);border-radius:9px;padding:8px;margin-top:8px">
<svg id="p36-iv1-svg" viewBox="0 0 420 240" width="100%" style="height:auto"></svg>
</div>
<div id="p36-iv1-out" style="margin-top:10px;padding:10px 14px;background:var(--sec-acc-soft);border-radius:9px;font-size:.95rem;line-height:1.7"></div>
</div>`;
/* INTERACTIVE 2 — Плазма и температура */
html += `<div class="wg" id="p36-iv2">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 2</span><div class="wg-title">Плазма: степень ионизации</div></div>
<div class="wg-help">При нагреве газа доля ионизованных атомов растёт. При $T \\gtrsim 10^4$ К — почти полная плазма.</div>
<div class="sliders">
<label>Температура $T$ (К): <b id="p36-iv2-TL">1000</b><input type="range" id="p36-iv2-T" min="1000" max="100000" value="1000" step="1000"></label>
</div>
<div style="background:var(--card);border:1px solid var(--border);border-radius:9px;padding:8px;margin-top:8px">
<svg id="p36-iv2-svg" viewBox="0 0 380 260" width="100%" style="height:auto"></svg>
</div>
<div id="p36-iv2-out" style="margin-top:10px;padding:10px 14px;background:var(--sec-acc-soft);border-radius:9px;font-size:.95rem;line-height:1.7;text-align:center"></div>
</div>`;
/* INTERACTIVE 3 — Какой это разряд? */
html += `<div class="wg" id="p36-iv3">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 3</span><div class="wg-title">Какой это разряд?</div></div>
<div class="wg-help">Тлеющий — низкое давление и трубки. Дуговой — раскалённые электроды. Искровой — мгновенный пробой. Коронный — острия и провода ЛЭП.</div>
<div class="score-display"><span>Задача <b id="p36-iv3-i">1</b> / 6</span><span>Очки: <b id="p36-iv3-s">0</b> / 6</span></div>
<div id="p36-iv3-q" style="padding:14px;background:var(--sec-acc-soft);border-radius:10px;font-size:1.05rem;margin-bottom:10px;text-align:center;min-height:54px"></div>
<div id="p36-iv3-opts" style="display:grid;grid-template-columns:1fr 1fr;gap:8px"></div>
<div class="feedback" id="p36-iv3-fb"></div>
<div class="actions"><button class="btn" id="p36-iv3-restart">Начать заново</button></div>
</div>`;
/* INTERACTIVE 4 — Тренажёр плазмы */
html += `<div class="wg" id="p36-iv4">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 4</span><div class="wg-title">Тренажёр: газы и плазма</div></div>
<div class="wg-help">5 задач с выбором ответа. Введи номер правильного варианта.</div>
<div class="score-display"><span>Задача <b id="p36-iv4-i">1</b> / 5</span><span>Очки: <b id="p36-iv4-s">0</b> / 5</span></div>
<div id="p36-iv4-q" style="padding:14px;background:var(--sec-acc-soft);border-radius:10px;font-size:1.02rem;margin-bottom:10px;line-height:1.55;min-height:80px"></div>
<div id="p36-iv4-form" style="display:flex;gap:8px;justify-content:center;margin-bottom:8px;flex-wrap:wrap">
<input type="number" id="p36-iv4-inp" step="1" style="padding:8px 10px;border:1px solid var(--border);border-radius:6px;width:140px;font-size:1rem" placeholder="№ ответа">
<button class="btn primary" id="p36-iv4-go">Проверить</button>
</div>
<div class="feedback" id="p36-iv4-fb"></div>
<div class="actions"><button class="btn" id="p36-iv4-restart">Начать заново</button></div>
</div>`;
html += secNav('p35', 'p37');
html += readButton('p36');
box.innerHTML = html;
renderMath(box);
/* IV1 — Виды разрядов (галерея) */
(function(){
const svg = document.getElementById('p36-iv1-svg');
const out = document.getElementById('p36-iv1-out');
const NN = document.getElementById('p36-iv1-N'), NL = document.getElementById('p36-iv1-NL');
const W = 420, H = 240;
const TYPES = [
{
name:'Несамостоятельный разряд',
desc:'Газ в трубке проводит ток <b>только при действии внешнего ионизатора</b> (УФ-лампа, рентген, нагрев). Уберёшь источник — ток прекратится.',
color:'#0891b2', glow:'#bae6fd'
},
{
name:'Тлеющий разряд',
desc:'Низкое давление. Холодные электроды. Тонкое розовое или зелёное свечение. <b>Лампы дневного света</b>, неоновая реклама. $U \\sim$ сотни В.',
color:'#9333ea', glow:'#e9d5ff'
},
{
name:'Дуговой разряд',
desc:'Раскалённые электроды. Яркая <b>дуга</b> между ними при больших токах. <b>Сварка</b>, прожекторы. $I$ от десятков ампер.',
color:'#f59e0b', glow:'#fef3c7'
},
{
name:'Искровой разряд',
desc:'<b>Мгновенный пробой</b> газа при очень большом напряжении. <b>Молния</b> ($U \\sim 10^9$ В, $I \\sim 10^5$ А), свеча зажигания.',
color:'#dc2626', glow:'#fecaca'
}
];
let seen = new Set(), _done = false;
function draw(){
const n = +NN.value;
NL.textContent = n + ' / 4';
const t = TYPES[n-1];
seen.add(n);
let g = '';
g += '<rect x="0" y="0" width="'+W+'" height="'+H+'" fill="#fafafa"/>';
// Заголовок
g += '<text x="'+(W/2)+'" y="22" text-anchor="middle" font-family="Inter,sans-serif" font-size="14" font-weight="800" fill="'+t.color+'">'+t.name+'</text>';
if(n === 1){
// ванна газа + УФ источник сверху
g += '<rect x="80" y="80" width="260" height="120" rx="10" fill="#ecfeff" stroke="#0e7490" stroke-width="2"/>';
// электроды
g += '<rect x="90" y="90" width="12" height="100" fill="#6b7280"/>';
g += '<text x="96" y="84" text-anchor="middle" font-size="12" font-weight="700" fill="#0e7490"></text>';
g += '<rect x="318" y="90" width="12" height="100" fill="#6b7280"/>';
g += '<text x="324" y="84" text-anchor="middle" font-size="12" font-weight="700" fill="#dc2626">+</text>';
// УФ-лампа
g += '<rect x="160" y="40" width="100" height="14" rx="6" fill="#fde68a" stroke="#f59e0b" stroke-width="1.5"/>';
g += '<text x="210" y="38" text-anchor="middle" font-size="10" fill="#92400e" font-weight="700">УФ-ионизатор</text>';
for(let k=0; k<7; k++){
const x = 175 + k*12;
g += '<line x1="'+x+'" y1="56" x2="'+x+'" y2="78" stroke="#f59e0b" stroke-width="1.2" stroke-dasharray="3,2"/>';
}
// несколько ионов и электронов
for(let k=0; k<5; k++){
const x = 130 + k*45, y = 130 + (k%2)*30;
g += '<circle cx="'+x+'" cy="'+y+'" r="5" fill="#fecaca" stroke="#dc2626" stroke-width="1.2"/>';
g += '<text x="'+x+'" y="'+(y+3)+'" text-anchor="middle" font-size="9" font-weight="800" fill="#7f1d1d">+</text>';
}
for(let k=0; k<5; k++){
const x = 145 + k*45, y = 160 + (k%2)*15;
g += '<circle cx="'+x+'" cy="'+y+'" r="4" fill="#dbeafe" stroke="#1d4ed8" stroke-width="1.2"/>';
g += '<text x="'+x+'" y="'+(y+3)+'" text-anchor="middle" font-size="9" font-weight="800" fill="#1e3a8a"></text>';
}
} else if(n === 2){
// тлеющий — длинная трубка
g += '<rect x="60" y="100" width="300" height="50" rx="22" fill="url(#glow2)" stroke="#7e22ce" stroke-width="2"/>';
g += '<defs><linearGradient id="glow2" x1="0" y1="0" x2="1" y2="0"><stop offset="0" stop-color="#f3e8ff"/><stop offset=".5" stop-color="#d8b4fe"/><stop offset="1" stop-color="#f3e8ff"/></linearGradient></defs>';
// электроды
g += '<rect x="64" y="106" width="14" height="38" fill="#374151"/>';
g += '<rect x="342" y="106" width="14" height="38" fill="#374151"/>';
// свечение
for(let k=0; k<20; k++){
const x = 90 + k*14;
g += '<circle cx="'+x+'" cy="125" r="3" fill="#a855f7" opacity=".55"/>';
}
g += '<text x="'+(W/2)+'" y="172" text-anchor="middle" font-size="11" fill="#7e22ce" font-weight="700">Газоразрядная трубка (низкое $p$)</text>';
g += '<text x="'+(W/2)+'" y="200" text-anchor="middle" font-size="10" fill="#64748b">Лампа дневного света</text>';
} else if(n === 3){
// дуговой — два электрода + яркая дуга
g += '<rect x="60" y="60" width="300" height="160" fill="#1f2937"/>';
// электроды
g += '<rect x="120" y="100" width="22" height="40" fill="#9ca3af"/>';
g += '<rect x="278" y="100" width="22" height="40" fill="#9ca3af"/>';
// дуга (изогнутая)
g += '<path d="M142 120 Q210 70 278 120" stroke="#fbbf24" stroke-width="6" fill="none" opacity=".9"/>';
g += '<path d="M142 120 Q210 75 278 120" stroke="#fef9c3" stroke-width="2.5" fill="none"/>';
// лучи
for(let k=0; k<6; k++){
const ang = -Math.PI/2 + (k-2.5)*0.25;
const x2 = 210 + Math.cos(ang)*60, y2 = 95 + Math.sin(ang)*30;
g += '<line x1="210" y1="95" x2="'+x2.toFixed(0)+'" y2="'+y2.toFixed(0)+'" stroke="#fef08a" stroke-width="1.4" opacity=".7"/>';
}
g += '<text x="'+(W/2)+'" y="200" text-anchor="middle" font-size="11" fill="#fde68a" font-weight="700">Электрическая дуга</text>';
g += '<text x="'+(W/2)+'" y="218" text-anchor="middle" font-size="10" fill="#fef3c7">сварка, прожекторы</text>';
} else if(n === 4){
// искровой — резкая ломаная между точкой и пластиной
g += '<rect x="60" y="60" width="300" height="160" fill="#0f172a"/>';
// верхняя пластина (туча)
g += '<ellipse cx="210" cy="90" rx="100" ry="18" fill="#475569" stroke="#94a3b8" stroke-width="1.5"/>';
g += '<text x="210" y="78" text-anchor="middle" font-size="10" fill="#cbd5e1">Туча ()</text>';
// молния
g += '<polyline points="200,108 190,135 215,150 195,175 220,200" stroke="#fbbf24" stroke-width="3" fill="none"/>';
g += '<polyline points="200,108 190,135 215,150 195,175 220,200" stroke="#fef9c3" stroke-width="1.4" fill="none"/>';
// земля
g += '<rect x="60" y="200" width="300" height="20" fill="#365314"/>';
g += '<text x="210" y="215" text-anchor="middle" font-size="10" fill="#bef264" font-weight="700">Земля (+)</text>';
g += '<text x="'+(W/2)+'" y="232" text-anchor="middle" font-size="10" fill="#facc15">молния — искровой разряд</text>';
}
svg.innerHTML = g;
out.innerHTML = '<b>'+t.name+'.</b> '+t.desc;
renderMath(out);
if(!_done && seen.size >= 4){ _done = true; addXp(15, 'p36-iv1'); bumpProgress('p36', 20); }
}
NN.addEventListener('input', draw);
draw();
})();
/* IV2 — Плазма и температура */
(function(){
const svg = document.getElementById('p36-iv2-svg');
const out = document.getElementById('p36-iv2-out');
const TT = document.getElementById('p36-iv2-T'), TL = document.getElementById('p36-iv2-TL');
const W = 380, H = 260;
let seen = new Set(), _done = false;
function alpha(T){
// эмпирически: доля ионизации растёт с T
const x = (T - 1000) / (100000 - 1000);
return Math.max(0, Math.min(1, Math.pow(x, 0.5)));
}
function draw(){
const T = +TT.value;
TL.textContent = T;
const a = alpha(T);
const N = 36; // частиц
const Ni = Math.round(N * a); // ионизованных пар
const Na = N - Ni;
let g = '';
g += '<rect x="0" y="0" width="'+W+'" height="'+H+'" fill="#fafafa"/>';
g += '<rect x="20" y="40" width="340" height="180" rx="14" fill="#fff7ed" stroke="#ea580c" stroke-width="2"/>';
g += '<text x="'+(W/2)+'" y="30" text-anchor="middle" font-family="Inter,sans-serif" font-size="12" font-weight="700" fill="#9a3412">Объём газа при $T = '+T+'$ К</text>';
// нейтральные молекулы (зелёные)
let placed = 0;
for(let r=0; r<6 && placed<N; r++){
for(let c=0; c<6 && placed<N; c++){
const x = 50 + c*48 + (r%2)*8;
const y = 60 + r*26;
if(placed < Na){
g += '<circle cx="'+x+'" cy="'+y+'" r="6" fill="#bbf7d0" stroke="#15803d" stroke-width="1.3"/>';
} else {
// ионизированная пара: + ион и - электрон рядом
g += '<circle cx="'+(x-4)+'" cy="'+y+'" r="5.5" fill="#fecaca" stroke="#dc2626" stroke-width="1.3"/>';
g += '<text x="'+(x-4)+'" y="'+(y+3)+'" text-anchor="middle" font-size="8" font-weight="800" fill="#7f1d1d">+</text>';
g += '<circle cx="'+(x+8)+'" cy="'+(y-3)+'" r="3.5" fill="#dbeafe" stroke="#1d4ed8" stroke-width="1.1"/>';
}
placed++;
}
}
// легенда
g += '<circle cx="40" cy="240" r="5" fill="#bbf7d0" stroke="#15803d" stroke-width="1.2"/>';
g += '<text x="50" y="244" font-size="10" fill="#15803d">нейтр. атомы</text>';
g += '<circle cx="160" cy="240" r="5" fill="#fecaca" stroke="#dc2626" stroke-width="1.2"/>';
g += '<text x="170" y="244" font-size="10" fill="#dc2626">ионы (+)</text>';
g += '<circle cx="240" cy="240" r="4" fill="#dbeafe" stroke="#1d4ed8" stroke-width="1.2"/>';
g += '<text x="250" y="244" font-size="10" fill="#1d4ed8">электроны</text>';
svg.innerHTML = g;
const pct = (a*100).toFixed(0);
let label = 'слабая ионизация (газ)';
if(a > 0.3) label = 'частично ионизованный газ';
if(a > 0.6) label = '<b>плазма</b>';
if(a > 0.9) label = '<b>полностью ионизованная плазма</b>';
out.innerHTML = '$T = '+T+'$ К $\\Rightarrow$ степень ионизации $\\alpha \\approx '+pct+'\\%$ — '+label+'.';
renderMath(out);
seen.add(Math.floor(T/20000));
if(!_done && seen.size >= 3){ _done = true; addXp(15, 'p36-iv2'); bumpProgress('p36', 20); }
}
TT.addEventListener('input', draw);
draw();
})();
/* IV3 — Какой разряд? */
(function(){
const OPTS = ['Тлеющий', 'Дуговой', 'Искровой', 'Коронный'];
const Q = [
{ q:'Лампа дневного света в кабинете…', ans:0, why:'<b>Тлеющий</b> разряд при низком давлении в стеклянной трубке.' },
{ q:'Сварочный аппарат: яркая дуга между электродами…', ans:1, why:'<b>Дуговой</b> разряд с раскалёнными электродами.' },
{ q:'Молния во время грозы…', ans:2, why:'<b>Искровой</b> разряд — мгновенный пробой воздуха.' },
{ q:'Слабое свечение и «гудение» вокруг проводов ЛЭП…', ans:3, why:'<b>Коронный</b> разряд у тонких проводов высокого напряжения.' },
{ q:'Неоновая реклама в витрине магазина…', ans:0, why:'<b>Тлеющий</b> разряд в трубке с неоном при низком давлении.' },
{ q:'Свеча зажигания в двигателе авто…', ans:2, why:'<b>Искровой</b> разряд между электродами свечи поджигает топливо.' }
];
let i = 0, score = 0;
const qEl = document.getElementById('p36-iv3-q');
const oEl = document.getElementById('p36-iv3-opts');
const fb = document.getElementById('p36-iv3-fb');
const iEl = document.getElementById('p36-iv3-i');
const sEl = document.getElementById('p36-iv3-s');
function show(){
if(i >= Q.length){
qEl.innerHTML = '<b>Готово!</b> Результат: '+score+' / '+Q.length;
oEl.innerHTML = '';
if(score === Q.length){ addXp(15, 'p36-iv3'); bumpProgress('p36', 25); }
else if(score >= 4){ addXp(8, 'p36-iv3'); bumpProgress('p36', 15); }
return;
}
iEl.textContent = (i+1);
sEl.textContent = score;
qEl.innerHTML = Q[i].q;
oEl.innerHTML = OPTS.map((t,k) => '<button class="btn primary" data-v="'+k+'">'+t+'</button>').join('');
fb.style.display = 'none';
renderMath(qEl);
oEl.querySelectorAll('button').forEach(b => {
b.addEventListener('click', () => {
const v = +b.dataset.v;
if(v === Q[i].ans){ score++; feedback(fb, true, '&#10003; Верно! '+Q[i].why+' Дальше ▶'); }
else feedback(fb, false, '&#10007; Верно: '+OPTS[Q[i].ans]+'. '+Q[i].why+' Дальше ▶');
sEl.textContent = score;
oEl.querySelectorAll('button').forEach(x => x.disabled = true);
i++;
setTimeout(show, 1900);
});
});
}
document.getElementById('p36-iv3-restart').addEventListener('click', () => { i = 0; score = 0; show(); });
show();
})();
/* IV4 — Тренажёр плазмы */
(function(){
const Q = [
{ q:'<b>Плазма</b> — это:<br>1 — четвёртое агрегатное состояние вещества,<br>2 — жидкость,<br>3 — твёрдое тело.', ans:1, why:'Плазма — ионизованный газ, выделяемый в отдельное (4-е) состояние вещества.' },
{ q:'Что светится в люминесцентных лампах?<br>1 — раскалённый металл,<br>2 — плазма (ионизованный газ),<br>3 — твёрдый люминофор без газа.', ans:2, why:'В трубке тлеющий разряд возбуждает атомы — плазма излучает УФ, а люминофор переизлучает свет.' },
{ q:'Самое распространённое состояние материи во Вселенной:<br>1 — твёрдое,<br>2 — жидкое,<br>3 — газ,<br>4 — плазма.', ans:4, why:'Звёзды состоят из плазмы — это $>99\\%$ видимой материи.' },
{ q:'Молния — это разряд какого типа?<br>1 — тлеющий,<br>2 — искровой,<br>3 — дуговой.', ans:2, why:'Молния — мгновенный искровой разряд (плазменный канал длиной до $3$ км).' },
{ q:'При ионизации газа атомы:<br>1 — притягивают дополнительные ядра,<br>2 — теряют только нейтроны,<br>3 — теряют электроны и становятся положительными ионами.', ans:3, why:'Атом теряет электрон $\\Rightarrow$ ион (+) и свободный электрон.' }
];
let i = 0, score = 0;
const qEl = document.getElementById('p36-iv4-q');
const fb = document.getElementById('p36-iv4-fb');
const iEl = document.getElementById('p36-iv4-i');
const sEl = document.getElementById('p36-iv4-s');
const inp = document.getElementById('p36-iv4-inp');
const bGo = document.getElementById('p36-iv4-go');
function show(){
if(i >= Q.length){
qEl.innerHTML = '<b>Готово!</b> Результат: '+score+' / '+Q.length;
inp.disabled = true; bGo.disabled = true;
if(score === Q.length){ addXp(15, 'p36-iv4'); bumpProgress('p36', 25); }
else if(score >= 3){ addXp(8, 'p36-iv4'); bumpProgress('p36', 15); }
return;
}
iEl.textContent = (i+1);
sEl.textContent = score;
qEl.innerHTML = Q[i].q;
fb.style.display = 'none';
inp.value = ''; inp.disabled = false; bGo.disabled = false; inp.focus();
renderMath(qEl);
}
function check(){
if(inp.disabled) return;
const v = parseInt(inp.value, 10);
if(!isFinite(v)){ feedback(fb, false, 'Введи номер ответа (число).'); return; }
if(v === Q[i].ans){ score++; feedback(fb, true, '&#10003; Верно! '+Q[i].why+' Дальше ▶'); }
else feedback(fb, false, '&#10007; Верно: '+Q[i].ans+'. '+Q[i].why+' Дальше ▶');
sEl.textContent = score;
inp.disabled = true; bGo.disabled = true;
i++;
setTimeout(show, 1900);
}
bGo.addEventListener('click', check);
inp.addEventListener('keydown', e => { if(e.key==='Enter') check(); });
document.getElementById('p36-iv4-restart').addEventListener('click', () => { i = 0; score = 0; inp.disabled=false; bGo.disabled=false; show(); });
show();
})();
wireReadBtn('p36');
}
function build_p37(){
const box = document.getElementById('p37-body');
let html = '';
/* THEORY 1 — Собственная проводимость */
html += makeCard('theory', "Полупроводники. Собственная проводимость", "§37", `
<p><b>Полупроводники</b> — материалы с <b>проводимостью между металлами и диэлектриками</b>: $\\rho \\sim 10^{-4}-10^4$ Ом$\\cdot$м.</p>
<p style="margin-top:10px">Главные представители: <b>кремний (Si)</b>, <b>германий (Ge)</b>, арсенид галлия (GaAs).</p>
<p style="margin-top:10px"><b>Собственная проводимость</b> (в чистом полупроводнике без примесей):</p>
<ul style="margin:6px 0 6px 22px">
<li>При $T = 0$ К — все электроны связаны, свободных носителей <b>нет</b>;</li>
<li>При нагреве — часть электронов вырывается из ковалентных связей, оставляя <b>дырку</b> (отсутствие электрона);</li>
<li>Получаются <b>2 типа носителей</b>: электроны ($-$) и дырки ($+$).</li>
</ul>
<p style="margin-top:10px"><b>Дырка</b> ведёт себя как положительная частица: когда соседний электрон занимает её место, дырка «переходит» туда, откуда пришёл электрон.</p>
<p style="margin-top:10px;padding:10px 14px;background:var(--sec-acc-soft);border-radius:9px"><b>Важно — в отличие от металлов:</b> с ростом температуры <b>проводимость полупроводника растёт</b> (появляется больше носителей), а сопротивление <b>падает</b>.</p>
`);
/* THEORY 2 — Примесная проводимость */
html += makeCard('rule', "Примесная проводимость: n-тип и p-тип", "§37", `
<p>Добавление микроскопических количеств <b>примесей</b> (концентрация $\\sim 10^{-6}$$10^{-9}$) резко меняет проводимость и определяет тип основных носителей.</p>
<p style="margin-top:10px;font-weight:600;color:#1d4ed8">n-тип (от англ. negative)</p>
<p>Добавляется <b>донорная</b> примесь — атомы с <b>лишним электроном</b> относительно кремния. Примеры: фосфор (P), мышьяк (As), сурьма (Sb).</p>
<ul style="margin:6px 0 6px 22px">
<li><b>Основные носители</b>: электроны ($-$);</li>
<li>Неосновные: немного дырок (от собственной проводимости).</li>
</ul>
<p style="margin-top:10px;font-weight:600;color:#dc2626">p-тип (от англ. positive)</p>
<p>Добавляется <b>акцепторная</b> примесь — атомы с <b>недостатком электрона</b>. Примеры: бор (B), индий (In), галлий (Ga).</p>
<ul style="margin:6px 0 6px 22px">
<li><b>Основные носители</b>: дырки ($+$);</li>
<li>Неосновные: немного электронов.</li>
</ul>
<p style="margin-top:10px;padding:10px 14px;background:var(--sec-acc-soft);border-radius:9px;font-size:.93rem"><b>Запомни:</b> донор $\\to$ <b>n</b>-тип (электроны), акцептор $\\to$ <b>p</b>-тип (дырки). Концентрации примесей крошечные, но влияние огромное — на этом стоит вся электроника.</p>
`);
/* THEORY 3 — p-n переход */
html += makeCard('example', "p-n переход и диод", "§37", `
<p><b>p-n переход</b> — контакт между p- и n-областями в одном кристалле полупроводника.</p>
<p style="margin-top:10px">В области контакта:</p>
<ul style="margin:6px 0 6px 22px">
<li>Электроны <b>диффундируют</b> из n-области в p-область;</li>
<li>Дырки — наоборот, из p в n;</li>
<li>На границе возникает <b>запирающий слой</b> с электрическим полем от n к p;</li>
<li>Когда диффузия уравновешена этим полем — устанавливается равновесие.</li>
</ul>
<p style="margin-top:10px;font-weight:600;color:#16a34a">Прямое смещение</p>
<p>$+$ источника подключают к <b>p</b>-области, $-$ к <b>n</b>:</p>
<ul style="margin:6px 0 6px 22px">
<li>Внешнее поле направлено против запирающего;</li>
<li>Запирающий слой <b>сужается</b>;</li>
<li>Через переход <b>идёт большой ток</b>.</li>
</ul>
<p style="margin-top:10px;font-weight:600;color:#dc2626">Обратное смещение</p>
<p>$+$ источника к <b>n</b>-области, $-$ к <b>p</b>:</p>
<ul style="margin:6px 0 6px 22px">
<li>Внешнее поле <b>усиливает</b> запирающее;</li>
<li>Запирающий слой <b>расширяется</b>;</li>
<li>Ток почти <b>не течёт</b> (только малый ток неосновных носителей).</li>
</ul>
<p style="margin-top:10px">p-n переход — это <b>полупроводниковый диод</b>: пропускает ток в одну сторону и не пропускает в другую.</p>
<p style="margin-top:10px;font-weight:600">На основе p-n переходов сделаны:</p>
<ul style="margin:6px 0 6px 22px">
<li><b>Диоды</b> — выпрямление переменного тока;</li>
<li><b>Транзисторы</b> — усиление и переключение сигналов;</li>
<li><b>Светодиоды</b> (LED): излучают свет при рекомбинации электронов и дырок;</li>
<li><b>Солнечные батареи</b>: преобразуют свет в электричество;</li>
<li><b>Микросхемы и процессоры</b>: миллиарды транзисторов на одном кристалле.</li>
</ul>
`);
/* INTERACTIVE 1 — p-n переход: прямое и обратное смещение */
html += `<div class="wg" id="p37-iv1">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 1</span><div class="wg-title">p-n переход: прямое и обратное смещение</div></div>
<div class="wg-help">$U > 0$ — прямое смещение ($+$ к p): ток течёт. $U < 0$ — обратное: ток почти нулевой. Слева p-область (дырки), справа n-область (электроны).</div>
<div class="sliders">
<label>Напряжение $U$ (В): <b id="p37-iv1-UL">0.0</b><input type="range" id="p37-iv1-U" min="-5" max="5" value="0" step="0.5"></label>
</div>
<div style="background:var(--card);border:1px solid var(--border);border-radius:9px;padding:8px;margin-top:8px">
<svg id="p37-iv1-svg" viewBox="0 0 480 260" width="100%" style="height:auto"></svg>
</div>
<div id="p37-iv1-out" style="margin-top:10px;padding:10px 14px;background:var(--sec-acc-soft);border-radius:9px;font-size:.95rem;line-height:1.7;text-align:center"></div>
</div>`;
/* INTERACTIVE 2 — n-тип vs p-тип */
html += `<div class="wg" id="p37-iv2">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 2</span><div class="wg-title">Примеси: n-тип vs p-тип</div></div>
<div class="wg-help">Кремниевая решётка $+$ один атом примеси. P (фосфор) — донор $\\to$ лишний электрон. B (бор) — акцептор $\\to$ дырка.</div>
<div class="sliders">
<label>Примесь: <b id="p37-iv2-NL">нет (чистый Si)</b><input type="range" id="p37-iv2-N" min="0" max="2" value="0" step="1"></label>
</div>
<div style="background:var(--card);border:1px solid var(--border);border-radius:9px;padding:8px;margin-top:8px">
<svg id="p37-iv2-svg" viewBox="0 0 380 260" width="100%" style="height:auto"></svg>
</div>
<div id="p37-iv2-out" style="margin-top:10px;padding:10px 14px;background:var(--sec-acc-soft);border-radius:9px;font-size:.95rem;line-height:1.7;text-align:center"></div>
</div>`;
/* INTERACTIVE 3 — Что за полупроводник? */
html += `<div class="wg" id="p37-iv3">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 3</span><div class="wg-title">Что это за полупроводник?</div></div>
<div class="wg-help">Чистый Si/Ge — собственный. P, As, Sb — доноры (n-тип). B, In, Ga — акцепторы (p-тип).</div>
<div class="score-display"><span>Задача <b id="p37-iv3-i">1</b> / 6</span><span>Очки: <b id="p37-iv3-s">0</b> / 6</span></div>
<div id="p37-iv3-q" style="padding:14px;background:var(--sec-acc-soft);border-radius:10px;font-size:1.05rem;margin-bottom:10px;text-align:center;min-height:54px"></div>
<div id="p37-iv3-opts" style="display:grid;grid-template-columns:repeat(3,1fr);gap:8px"></div>
<div class="feedback" id="p37-iv3-fb"></div>
<div class="actions"><button class="btn" id="p37-iv3-restart">Начать заново</button></div>
</div>`;
/* INTERACTIVE 4 — Тренажёр */
html += `<div class="wg" id="p37-iv4">
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 4</span><div class="wg-title">Тренажёр: полупроводники</div></div>
<div class="wg-help">5 задач с выбором ответа. Введи номер правильного варианта.</div>
<div class="score-display"><span>Задача <b id="p37-iv4-i">1</b> / 5</span><span>Очки: <b id="p37-iv4-s">0</b> / 5</span></div>
<div id="p37-iv4-q" style="padding:14px;background:var(--sec-acc-soft);border-radius:10px;font-size:1.02rem;margin-bottom:10px;line-height:1.55;min-height:80px"></div>
<div id="p37-iv4-form" style="display:flex;gap:8px;justify-content:center;margin-bottom:8px;flex-wrap:wrap">
<input type="number" id="p37-iv4-inp" step="1" style="padding:8px 10px;border:1px solid var(--border);border-radius:6px;width:140px;font-size:1rem" placeholder="№ ответа">
<button class="btn primary" id="p37-iv4-go">Проверить</button>
</div>
<div class="feedback" id="p37-iv4-fb"></div>
<div class="actions"><button class="btn" id="p37-iv4-restart">Начать заново</button></div>
</div>`;
html += secNav('p36', 'final6');
html += readButton('p37');
box.innerHTML = html;
renderMath(box);
/* IV1 — p-n переход */
(function(){
const svg = document.getElementById('p37-iv1-svg');
const out = document.getElementById('p37-iv1-out');
const UU = document.getElementById('p37-iv1-U'), UL = document.getElementById('p37-iv1-UL');
const W = 480, H = 260;
let seen = new Set(), _done = false;
function draw(){
const U = +UU.value;
UL.textContent = U.toFixed(1);
// ширина запирающего слоя
let dep = 60; // нейтральная
if(U > 0) dep = Math.max(8, 60 - U*10); // сужается
else dep = 60 - U*8; // расширяется (U<0 → -U>0)
// ток: ~ 0 при U<0, экспоненциальный рост при U>0
let I = 0;
if(U > 0.3) I = Math.min(1, (Math.exp(U*0.9) - 1)/30);
else if(U > 0) I = U * 0.05;
else I = -0.01 * (1 - Math.exp(U*0.3));
let g = '';
g += '<rect x="0" y="0" width="'+W+'" height="'+H+'" fill="#fafafa"/>';
// подложка
const x0 = 70, x1 = 410, y0 = 60, y1 = 180;
const midX = (x0+x1)/2;
const depX1 = midX - dep/2, depX2 = midX + dep/2;
// p-область (синяя/розовая)
g += '<rect x="'+x0+'" y="'+y0+'" width="'+(midX-x0)+'" height="'+(y1-y0)+'" fill="#fee2e2" stroke="#7f1d1d" stroke-width="1.6"/>';
// n-область
g += '<rect x="'+midX+'" y="'+y0+'" width="'+(x1-midX)+'" height="'+(y1-y0)+'" fill="#dbeafe" stroke="#1e3a8a" stroke-width="1.6"/>';
// запирающий слой
g += '<rect x="'+depX1+'" y="'+y0+'" width="'+dep+'" height="'+(y1-y0)+'" fill="#fde68a" opacity=".75" stroke="#92400e" stroke-width="1" stroke-dasharray="4,3"/>';
// подписи
g += '<text x="'+((x0+midX)/2)+'" y="50" text-anchor="middle" font-family="Inter,sans-serif" font-size="13" font-weight="800" fill="#dc2626">p-область</text>';
g += '<text x="'+((x0+midX)/2)+'" y="200" text-anchor="middle" font-family="Inter,sans-serif" font-size="10" fill="#7f1d1d">дырки (+)</text>';
g += '<text x="'+((midX+x1)/2)+'" y="50" text-anchor="middle" font-family="Inter,sans-serif" font-size="13" font-weight="800" fill="#1d4ed8">n-область</text>';
g += '<text x="'+((midX+x1)/2)+'" y="200" text-anchor="middle" font-family="Inter,sans-serif" font-size="10" fill="#1e3a8a">электроны ()</text>';
// носители: дырки в p
for(let k=0; k<8; k++){
const px = x0 + 18 + k*(midX-x0-30)/7;
const py = y0 + 18 + (k%2)*(y1-y0-36);
if(px > depX1 - 2) continue;
g += '<circle cx="'+px.toFixed(1)+'" cy="'+py.toFixed(1)+'" r="5" fill="#fca5a5" stroke="#dc2626" stroke-width="1.2"/>';
g += '<text x="'+px.toFixed(1)+'" y="'+(py+3).toFixed(1)+'" text-anchor="middle" font-size="9" font-weight="800" fill="#7f1d1d">+</text>';
}
// электроны в n
for(let k=0; k<8; k++){
const px = midX + 18 + k*(x1-midX-30)/7;
const py = y0 + 18 + (k%2)*(y1-y0-36);
if(px < depX2 + 2) continue;
g += '<circle cx="'+px.toFixed(1)+'" cy="'+py.toFixed(1)+'" r="5" fill="#93c5fd" stroke="#1d4ed8" stroke-width="1.2"/>';
g += '<text x="'+px.toFixed(1)+'" y="'+(py+3).toFixed(1)+'" text-anchor="middle" font-size="9" font-weight="800" fill="#1e3a8a"></text>';
}
// источник снизу — клеммы
const polP = (U >= 0) ? '+' : '';
const polN = (U >= 0) ? '' : '+';
g += '<text x="'+(x0-12)+'" y="125" text-anchor="middle" font-size="14" font-weight="800" fill="'+(U>=0?'#dc2626':'#1d4ed8')+'">'+polP+'</text>';
g += '<text x="'+(x1+12)+'" y="125" text-anchor="middle" font-size="14" font-weight="800" fill="'+(U>=0?'#1d4ed8':'#dc2626')+'">'+polN+'</text>';
// стрелка тока
if(I > 0.02){
g += PHYS.drawArrow(midX-40, 232, midX+40, 232, '#16a34a', 2.2, 9);
g += '<text x="'+midX+'" y="222" text-anchor="middle" font-size="11" font-weight="700" fill="#16a34a">ток течёт</text>';
} else if(U < -0.5){
g += '<text x="'+midX+'" y="230" text-anchor="middle" font-size="11" font-weight="700" fill="#dc2626">ток ≈ 0 (заперт)</text>';
} else {
g += '<text x="'+midX+'" y="230" text-anchor="middle" font-size="11" fill="#64748b">равновесие</text>';
}
// мини-ВАХ внизу
const vx0 = 30, vy0 = 240;
g += '<text x="'+(vx0+20)+'" y="250" font-size="9" fill="#64748b">I</text>';
svg.innerHTML = g;
let txt;
if(U > 0.3) txt = '<b>Прямое смещение</b>: $U = '+U.toFixed(1)+'$ В, ток <b>течёт</b> (запирающий слой сужен).';
else if(U < -0.3) txt = '<b>Обратное смещение</b>: $U = '+U.toFixed(1)+'$ В, ток ≈ 0 (запирающий слой расширен).';
else txt = '$U \\approx 0$: равновесие, тока почти нет.';
out.innerHTML = txt;
renderMath(out);
seen.add(U > 0.3 ? 'fwd' : (U < -0.3 ? 'rev' : 'zero'));
if(!_done && seen.size >= 3){ _done = true; addXp(15, 'p37-iv1'); bumpProgress('p37', 25); }
}
UU.addEventListener('input', draw);
draw();
})();
/* IV2 — n-тип vs p-тип */
(function(){
const svg = document.getElementById('p37-iv2-svg');
const out = document.getElementById('p37-iv2-out');
const NN = document.getElementById('p37-iv2-N'), NL = document.getElementById('p37-iv2-NL');
const W = 380, H = 260;
const TYPES = [
{ label:'нет (чистый Si)', tag:'Собственная проводимость: только тепловые пары электрон-дырка.' },
{ label:'P (фосфор) — донор', tag:'<b>n-тип</b>: атом P даёт <b>лишний электрон</b>. Основные носители — электроны.' },
{ label:'B (бор) — акцептор', tag:'<b>p-тип</b>: атом B создаёт <b>дырку</b>. Основные носители — дырки.' }
];
let seen = new Set(), _done = false;
function draw(){
const n = +NN.value;
NL.innerHTML = TYPES[n].label;
let g = '';
g += '<rect x="0" y="0" width="'+W+'" height="'+H+'" fill="#fafafa"/>';
// решётка кремния
g += '<text x="'+(W/2)+'" y="22" text-anchor="middle" font-size="12" font-weight="700" fill="#0f172a">Кристаллическая решётка Si</text>';
const cols = 6, rows = 4;
const cellW = 50, cellH = 42;
const ox = (W - cols*cellW)/2, oy = 40;
// узлы решётки — атомы Si
for(let r=0; r<rows; r++){
for(let c=0; c<cols; c++){
const x = ox + c*cellW + cellW/2;
const y = oy + r*cellH + cellH/2;
// связи (просто крестик)
if(c < cols-1) g += '<line x1="'+x+'" y1="'+y+'" x2="'+(x+cellW)+'" y2="'+y+'" stroke="#94a3b8" stroke-width="1"/>';
if(r < rows-1) g += '<line x1="'+x+'" y1="'+y+'" x2="'+x+'" y2="'+(y+cellH)+'" stroke="#94a3b8" stroke-width="1"/>';
}
}
// атомы
for(let r=0; r<rows; r++){
for(let c=0; c<cols; c++){
const x = ox + c*cellW + cellW/2;
const y = oy + r*cellH + cellH/2;
let fill = '#e2e8f0', stroke = '#475569', label = 'Si';
// примесь в центре
if(n === 1 && r === 1 && c === 3){ fill = '#bfdbfe'; stroke = '#1d4ed8'; label = 'P'; }
if(n === 2 && r === 1 && c === 3){ fill = '#fecaca'; stroke = '#dc2626'; label = 'B'; }
g += '<circle cx="'+x+'" cy="'+y+'" r="11" fill="'+fill+'" stroke="'+stroke+'" stroke-width="1.5"/>';
g += '<text x="'+x+'" y="'+(y+4)+'" text-anchor="middle" font-size="11" font-weight="700" fill="'+stroke+'">'+label+'</text>';
}
}
// свободный электрон или дырка рядом с примесью
if(n === 1){
const x = ox + 3*cellW + cellW/2, y = oy + 1*cellH + cellH/2;
g += '<circle cx="'+(x+22)+'" cy="'+(y-22)+'" r="6" fill="#dbeafe" stroke="#1d4ed8" stroke-width="1.4"/>';
g += '<text x="'+(x+22)+'" y="'+(y-19)+'" text-anchor="middle" font-size="9" font-weight="800" fill="#1e3a8a"></text>';
g += '<text x="'+(x+38)+'" y="'+(y-22)+'" font-size="9" fill="#1d4ed8">лишний е</text>';
}
if(n === 2){
const x = ox + 3*cellW + cellW/2, y = oy + 1*cellH + cellH/2;
g += '<circle cx="'+(x+22)+'" cy="'+(y-22)+'" r="6" fill="#fff" stroke="#dc2626" stroke-width="1.4" stroke-dasharray="2,2"/>';
g += '<text x="'+(x+22)+'" y="'+(y-19)+'" text-anchor="middle" font-size="9" font-weight="800" fill="#7f1d1d">+</text>';
g += '<text x="'+(x+38)+'" y="'+(y-22)+'" font-size="9" fill="#dc2626">дырка</text>';
}
// легенда
g += '<text x="'+(W/2)+'" y="244" text-anchor="middle" font-size="11" fill="#475569">Тип: <tspan font-weight="800" fill="'+(n===0?'#0f172a':n===1?'#1d4ed8':'#dc2626')+'">'+TYPES[n].label+'</tspan></text>';
svg.innerHTML = g;
out.innerHTML = TYPES[n].tag;
renderMath(out);
seen.add(n);
if(!_done && seen.size >= 3){ _done = true; addXp(15, 'p37-iv2'); bumpProgress('p37', 20); }
}
NN.addEventListener('input', draw);
draw();
})();
/* IV3 — Что за полупроводник? */
(function(){
const OPTS = ['n-тип', 'p-тип', 'Собственный'];
const Q = [
{ q:'Чистый кристалл кремния (без примесей)…', ans:2, why:'<b>Собственная</b> проводимость: только тепловые пары электрон-дырка.' },
{ q:'Si $+$ фосфор (P) — донор…', ans:0, why:'P даёт <b>лишний электрон</b> → <b>n-тип</b>.' },
{ q:'Si $+$ бор (B) — акцептор…', ans:1, why:'B создаёт <b>дырку</b> → <b>p-тип</b>.' },
{ q:'Ge $+$ мышьяк (As)…', ans:0, why:'As — донор (V группа), даёт лишний электрон → <b>n-тип</b>.' },
{ q:'Si $+$ индий (In)…', ans:1, why:'In — акцептор (III группа), создаёт дырку → <b>p-тип</b>.' },
{ q:'Чистый кристалл германия (без примесей)…', ans:2, why:'<b>Собственная</b> проводимость — оба типа носителей в равной концентрации.' }
];
let i = 0, score = 0;
const qEl = document.getElementById('p37-iv3-q');
const oEl = document.getElementById('p37-iv3-opts');
const fb = document.getElementById('p37-iv3-fb');
const iEl = document.getElementById('p37-iv3-i');
const sEl = document.getElementById('p37-iv3-s');
function show(){
if(i >= Q.length){
qEl.innerHTML = '<b>Готово!</b> Результат: '+score+' / '+Q.length;
oEl.innerHTML = '';
if(score === Q.length){ addXp(15, 'p37-iv3'); bumpProgress('p37', 25); }
else if(score >= 4){ addXp(8, 'p37-iv3'); bumpProgress('p37', 15); }
return;
}
iEl.textContent = (i+1);
sEl.textContent = score;
qEl.innerHTML = Q[i].q;
oEl.innerHTML = OPTS.map((t,k) => '<button class="btn primary" data-v="'+k+'">'+t+'</button>').join('');
fb.style.display = 'none';
renderMath(qEl);
oEl.querySelectorAll('button').forEach(b => {
b.addEventListener('click', () => {
const v = +b.dataset.v;
if(v === Q[i].ans){ score++; feedback(fb, true, '&#10003; Верно! '+Q[i].why+' Дальше ▶'); }
else feedback(fb, false, '&#10007; Верно: '+OPTS[Q[i].ans]+'. '+Q[i].why+' Дальше ▶');
sEl.textContent = score;
oEl.querySelectorAll('button').forEach(x => x.disabled = true);
i++;
setTimeout(show, 1900);
});
});
}
document.getElementById('p37-iv3-restart').addEventListener('click', () => { i = 0; score = 0; show(); });
show();
})();
/* IV4 — Тренажёр полупроводников */
(function(){
const Q = [
{ q:'В <b>p-типе</b> основные носители заряда:<br>1 — электроны,<br>2 — дырки,<br>3 — положительные ионы.', ans:2, why:'p-тип создан акцепторной примесью — основные носители <b>дырки</b>.' },
{ q:'В <b>n-типе</b> основные носители заряда:<br>1 — электроны,<br>2 — дырки.', ans:1, why:'Донорная примесь дала <b>электроны</b> — они и основные.' },
{ q:'При <b>прямом смещении</b> p-n перехода ток:<br>1 — течёт,<br>2 — не течёт.', ans:1, why:'$+$ к p, $-$ к n: запирающий слой сужается, ток <b>течёт</b>.' },
{ q:'Полупроводниковый диод пропускает ток:<br>1 — в обе стороны,<br>2 — только в одну сторону.', ans:2, why:'В этом и смысл диода — однонаправленная проводимость.' },
{ q:'При повышении температуры сопротивление полупроводника:<br>1 — уменьшается,<br>2 — увеличивается.', ans:1, why:'Появляется больше носителей $\\Rightarrow$ сопротивление <b>падает</b> (в отличие от металлов).' }
];
let i = 0, score = 0;
const qEl = document.getElementById('p37-iv4-q');
const fb = document.getElementById('p37-iv4-fb');
const iEl = document.getElementById('p37-iv4-i');
const sEl = document.getElementById('p37-iv4-s');
const inp = document.getElementById('p37-iv4-inp');
const bGo = document.getElementById('p37-iv4-go');
function show(){
if(i >= Q.length){
qEl.innerHTML = '<b>Готово!</b> Результат: '+score+' / '+Q.length;
inp.disabled = true; bGo.disabled = true;
if(score === Q.length){ addXp(15, 'p37-iv4'); bumpProgress('p37', 25); }
else if(score >= 3){ addXp(8, 'p37-iv4'); bumpProgress('p37', 15); }
return;
}
iEl.textContent = (i+1);
sEl.textContent = score;
qEl.innerHTML = Q[i].q;
fb.style.display = 'none';
inp.value = ''; inp.disabled = false; bGo.disabled = false; inp.focus();
renderMath(qEl);
}
function check(){
if(inp.disabled) return;
const v = parseInt(inp.value, 10);
if(!isFinite(v)){ feedback(fb, false, 'Введи номер ответа (число).'); return; }
if(v === Q[i].ans){ score++; feedback(fb, true, '&#10003; Верно! '+Q[i].why+' Дальше ▶'); }
else feedback(fb, false, '&#10007; Верно: '+Q[i].ans+'. '+Q[i].why+' Дальше ▶');
sEl.textContent = score;
inp.disabled = true; bGo.disabled = true;
i++;
setTimeout(show, 1900);
}
bGo.addEventListener('click', check);
inp.addEventListener('keydown', e => { if(e.key==='Enter') check(); });
document.getElementById('p37-iv4-restart').addEventListener('click', () => { i = 0; score = 0; inp.disabled=false; bGo.disabled=false; show(); });
show();
})();
wireReadBtn('p37');
}
function build_final6(){
const box = document.getElementById('final6-body');
let html = '';
/* Часть А — Шпаргалка главы (4 mini-карточки) */
const SHEET = [
{ t:'§ 34 · Металлы', icon:'<svg viewBox="0 0 24 24" fill="none" stroke="#0ea5e9" stroke-width="2" style="width:18px;height:18px"><path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z"/></svg>',
body:'Носители — электроны ($\\sim 10^{29}$/м$^3$). $R = \\rho L/S$. $\\rho(t) = \\rho_0(1 + \\alpha t)$. Сверхпроводимость при $T < T_c$.' },
{ t:'§ 35 · Электролиты', icon:'<svg viewBox="0 0 24 24" fill="none" stroke="#10b981" stroke-width="2" style="width:18px;height:18px"><path d="M12 2v8"/><circle cx="12" cy="14" r="6"/></svg>',
body:'Носители — ионы. Закон Фарадея: $m = MIt/(Fn)$. $F = 96\\,500$ Кл/моль. Электролиз, гальваностегия.' },
{ t:'§ 36 · Газы и плазма', icon:'<svg viewBox="0 0 24 24" fill="none" stroke="#f59e0b" stroke-width="2" style="width:18px;height:18px"><polyline points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/></svg>',
body:'Ионизация. Разряды: <b>тлеющий, дуговой, искровой, коронный</b>. Плазма — 4-е состояние, $>99\\%$ вещества Вселенной.' },
{ t:'§ 37 · Полупроводники', icon:'<svg viewBox="0 0 24 24" fill="none" stroke="#dc2626" stroke-width="2" style="width:18px;height:18px"><rect x="3" y="3" width="18" height="18" rx="2"/><path d="M9 9h6v6H9z"/></svg>',
body:'Электроны + дырки. <b>n-тип</b> (донор P), <b>p-тип</b> (акцептор B). p-n переход — диод. $R$ падает с $T$.' },
];
html += `<div class="card">
<div class="card-header">
<span class="card-icon theory">${ICONS.theory}</span>
<span class="card-title">Шпаргалка главы 6 — Ток в различных средах</span>
<span class="card-num">Итог</span>
</div>
<div class="card-body">
<p>Ключевые формулы и идеи четырёх параграфов главы — повтори перед битвой с боссами.</p>
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:12px;margin-top:10px">
${SHEET.map(s => `<div style="padding:12px 14px;background:var(--sec-acc-soft);border-radius:11px;border-left:3px solid var(--pri)">
<div style="display:flex;align-items:center;gap:8px;margin-bottom:6px">
${s.icon}
<div style="font-family:'Unbounded',sans-serif;font-weight:700;color:var(--pri2);font-size:.88rem">${s.t}</div>
</div>
<div style="font-size:.92rem;line-height:1.55">${s.body}</div>
</div>`).join('')}
</div>
</div>
</div>`;
/* Часть Б — 5 боссов intro */
html += `<div class="card">
<div class="card-header">
<span class="card-icon rule">${ICONS.rule}</span>
<span class="card-title">Боссы главы 6</span>
<span class="card-num">5</span>
</div>
<div class="card-body">
<p>5 интегрированных задач по §§34–37. За каждого побеждённого босса: <b>+10 XP, +18% к прогрессу</b>. Победишь всех — ачивка <b>«Мастер токов»</b> и <b>+50 XP бонус</b>.</p>
<p style="margin-top:6px;font-size:.92rem;color:var(--muted)">Допуск $\\pm 5\\%$. Боссы 3–5 требуют целочисленный номер варианта.</p>
</div>
</div>`;
html += '<div id="ch6-bosses-container"></div>';
html += `<div style="margin-top:18px;padding:18px 20px;background:linear-gradient(135deg,var(--pri-soft),var(--sec-acc-soft));border-radius:14px;border:1.5px solid var(--pri);text-align:center" id="ch6-final-summary">
<div style="font-family:'Unbounded',sans-serif;font-weight:800;color:var(--pri2);font-size:1.1rem;margin-bottom:6px">Прогресс по боссам</div>
<div id="ch6-boss-overall" style="font-size:.95rem;color:var(--text);margin-bottom:10px">0 / 5 боссов побеждено</div>
<div style="height:12px;background:var(--card);border-radius:8px;overflow:hidden;border:1px solid var(--border)">
<div id="ch6-boss-overall-fill" style="height:100%;width:0%;background:linear-gradient(90deg,#d97706,#fbbf24);transition:width .35s"></div>
</div>
<div id="ch6-final-reward" style="margin-top:14px;display:none;padding:14px;background:var(--card);border-radius:11px;border:2px solid #f59e0b">
<div style="font-family:'Unbounded',sans-serif;font-weight:800;color:#92400e;font-size:1.05rem;margin-bottom:6px">Мастер токов</div>
<div style="font-size:.92rem;margin-bottom:10px">Глава 6 пройдена! Все 5 боссов повержены. +50 XP бонус.</div>
<a class="btn primary" href="/textbook/physics-10" style="text-decoration:none">К хабу Физики 10 <svg class="ic" viewBox="0 0 24 24"><polyline points="9 18 15 12 9 6"/></svg></a>
</div>
</div>`;
html += secNav('p37', null);
box.innerHTML = html;
renderMath(box);
/* Боссы */
const BOSSES = [
{
n:1, color:'#0ea5e9',
title:'Страж Медной Жилы',
tag:'§ 34',
q:'Медный провод длиной $L = 50$ м, сечение $S = 1$ мм$^2 = 10^{-6}$ м$^2$, $\\rho = 1{,}7 \\cdot 10^{-8}$ Ом$\\cdot$м. Найди $R$ в Ом.',
ans:0.85, tol:0.05,
hint:'$R = \\rho L/S = 1{,}7\\cdot 10^{-8} \\cdot 50 / 10^{-6} = 0{,}85$ Ом.'
},
{
n:2, color:'#10b981',
title:'Хранитель Фарадея',
tag:'§ 35',
q:'Электролиз меди ($M = 64$ г/моль, $n = 2$), $I = 2$ А, $t = 1$ ч $= 3600$ с, $F = 96\\,500$ Кл/моль. Найди массу выделившейся меди в <b>граммах</b>.',
ans:2.39, tol:0.1,
hint:'$m = MIt/(Fn) = 64\\cdot 2 \\cdot 3600 / (96\\,500 \\cdot 2) \\approx 2{,}39$ г.'
},
{
n:3, color:'#f59e0b',
title:'Повелитель Разрядов',
tag:'§ 36',
q:'Молния во время грозы — это разряд какого типа?<br>1 — тлеющий, 2 — дуговой, 3 — искровой, 4 — коронный.',
ans:3, tol:0.1,
hint:'Молния — мгновенный <b>искровой</b> разряд (плазменный канал длиной до 3 км).'
},
{
n:4, color:'#7c3aed',
title:'Властелин p-n Перехода',
tag:'§ 37',
q:'При <b>прямом смещении</b> p-n перехода ток через диод:<br>1 — течёт, 2 — не течёт.',
ans:1, tol:0.1,
hint:'$+$ к p-области, $-$ к n: запирающий слой сужается, ток <b>течёт</b>.'
},
{
n:5, color:'#dc2626',
title:'Магистр Токов',
tag:'§§ 3437',
q:'В каком из этих материалов проводимость <b>увеличивается</b> при нагреве?<br>1 — металл, 2 — полупроводник, 3 — сверхпроводник в области $T < T_c$.',
ans:2, tol:0.1,
hint:'Только в <b>полупроводниках</b> сопротивление падает (а проводимость растёт) с ростом $T$ — появляются новые электронно-дырочные пары.'
},
];
const cont = document.getElementById('ch6-bosses-container');
const STATE_KEY = 'physics10_ch6_bosses';
const BOSS_STATE = (function(){
try{ const s = localStorage.getItem(STATE_KEY); if(s){ const p = JSON.parse(s); if(Array.isArray(p) && p.length === BOSSES.length) return p; } }catch(e){}
return BOSSES.map(()=>({defeated:false}));
})();
function saveBosses(){ try{ localStorage.setItem(STATE_KEY, JSON.stringify(BOSS_STATE)); }catch(e){} }
cont.innerHTML = BOSSES.map((b)=>{
return '<div class="boss-card" id="boss6-'+b.n+'-card" style="padding:16px;background:var(--card);border-radius:12px;border:2px solid '+b.color+';margin-bottom:14px">'
+'<div style="display:flex;align-items:center;gap:10px;margin-bottom:10px;flex-wrap:wrap">'
+'<svg viewBox="0 0 24 24" fill="none" stroke="'+b.color+'" stroke-width="2.2" style="width:28px;height:28px;flex-shrink:0"><polygon points="12,2 22,20 2,20"/></svg>'
+'<div style="font-family:\'Unbounded\',sans-serif;font-weight:800;color:'+b.color+';font-size:1.05rem">Босс '+b.n+': '+b.title+'</div>'
+'<div style="margin-left:auto;font-size:.78rem;color:var(--muted);padding:3px 8px;background:var(--sec-acc-soft);border-radius:6px">'+b.tag+'</div>'
+'</div>'
+'<div class="boss-q" id="boss6-'+b.n+'-q" style="padding:12px 14px;background:var(--sec-acc-soft);border-radius:9px;font-size:1rem;line-height:1.5;margin-bottom:10px">'+b.q+'</div>'
+'<div style="display:flex;gap:8px;align-items:center;flex-wrap:wrap">'
+'<span style="font-family:\'JetBrains Mono\',monospace;font-size:.92rem">ответ =</span>'
+'<input type="number" id="boss6-'+b.n+'-ans" class="tinp" style="width:130px;text-align:center" step="0.01" placeholder="число">'
+'<button class="btn primary" id="boss6-'+b.n+'-go" style="background:'+b.color+';border-color:'+b.color+'">Атаковать</button>'
+'<button class="btn" id="boss6-'+b.n+'-hint">Подсказка</button>'
+'</div>'
+'<div class="feedback" id="boss6-'+b.n+'-fb"></div>'
+'</div>';
}).join('');
renderMath(cont);
function refreshOverall(){
const won = BOSS_STATE.filter(s => s.defeated).length;
const txt = document.getElementById('ch6-boss-overall');
const fill = document.getElementById('ch6-boss-overall-fill');
if(txt) txt.textContent = won + ' / ' + BOSSES.length + ' боссов побеждено';
if(fill) fill.style.width = (won * 100 / BOSSES.length) + '%';
if(won >= BOSSES.length){
const reward = document.getElementById('ch6-final-reward');
if(reward && reward.style.display === 'none'){
reward.style.display = 'block';
if(!STATE.achievements.has('ch6_done')){
achievement('ch6_done','Мастер токов');
addXp(50, 'ch6-bonus');
bumpProgress('final6', 30);
if(window.confetti){ try{ confetti(); }catch(e){} }
}
}
}
}
BOSSES.forEach((b, idx)=>{
const card = document.getElementById('boss6-'+b.n+'-card');
const goBtn = document.getElementById('boss6-'+b.n+'-go');
const hintBtn = document.getElementById('boss6-'+b.n+'-hint');
const ansInp = document.getElementById('boss6-'+b.n+'-ans');
if(BOSS_STATE[idx].defeated){
card.style.background = 'linear-gradient(135deg,var(--sec-acc-soft),var(--pri-soft))';
card.classList.add('glow');
goBtn.disabled = true; goBtn.style.opacity = .55; goBtn.textContent = '✓ Повержен';
ansInp.disabled = true;
}
goBtn.addEventListener('click', ()=>{
if(BOSS_STATE[idx].defeated) return;
const fb = document.getElementById('boss6-'+b.n+'-fb');
const raw = ansInp.value.replace(',', '.');
const val = parseFloat(raw);
if(isNaN(val)){ feedback(fb, false, '&#10007; Введи число.'); return; }
const tol = (typeof b.tol === 'number') ? b.tol : Math.max(0.05 * Math.abs(b.ans), 0.05);
if(Math.abs(val - b.ans) < tol + 0.001){
BOSS_STATE[idx].defeated = true; saveBosses();
feedback(fb, true, '&#10003; Босс '+b.n+' повержен! +10 XP. '+b.hint);
addXp(10, 'boss-ch6-'+b.n);
bumpProgress('final6', 18);
goBtn.disabled = true; goBtn.style.opacity = .55; goBtn.textContent = '✓ Повержен';
ansInp.disabled = true;
card.style.background = 'linear-gradient(135deg,var(--sec-acc-soft),var(--pri-soft))';
card.classList.add('glow','pulse');
setTimeout(()=>card.classList.remove('pulse'), 900);
refreshOverall();
} else {
feedback(fb, false, '&#10007; Промах. Попробуй ещё. Подсказка доступна.');
}
});
hintBtn.addEventListener('click', ()=>{
const fb = document.getElementById('boss6-'+b.n+'-fb');
fb.className = 'feedback ok';
fb.innerHTML = '<b>Подсказка:</b> '+b.hint;
fb.style.display = 'block';
fb.style.background = 'var(--warn-bg)';
fb.style.color = '#92400e';
fb.style.borderLeftColor = 'var(--warn)';
renderMath(fb);
});
ansInp.addEventListener('keydown', e=>{ if(e.key === 'Enter') goBtn.click(); });
});
refreshOverall();
}
/* ===== Search ===== */
const SEARCH_INDEX = (function(){
const arr=[];
PARAS.forEach(p=>arr.push({kind:'Параграф',title:p.num+' '+p.name,desc:p.sub||'',sec:p.id}));
return arr;
})();
function initSearch(){
const modal=document.getElementById('search-modal'),inp=document.getElementById('search-input'),out=document.getElementById('search-results'),btn=document.getElementById('search-btn');
if(!modal||!inp||!out) return;
let cur=0,rows=[];
function score(q,it){ const t=(it.title+' '+it.desc).toLowerCase(); if(t.includes(q)) return 100+(it.title.toLowerCase().startsWith(q)?50:0); let s=0; q.split(/\s+/).forEach(w=>{if(w&&t.includes(w))s+=10;}); return s; }
function rank(q){ q=q.trim().toLowerCase(); if(!q) return SEARCH_INDEX.slice(0,12); return SEARCH_INDEX.map(it=>({it,s:score(q,it)})).filter(x=>x.s>0).sort((a,b)=>b.s-a.s).slice(0,20).map(x=>x.it); }
function render(){ cur=0; if(!rows.length){out.innerHTML='<div class="search-empty">Ничего не найдено</div>';return;} out.innerHTML=rows.map((r,i)=>'<button class="search-row'+(i===0?' active':'')+'" data-i="'+i+'"><div class="sr-kind">'+r.kind+'</div><div class="sr-title">'+r.title+'</div>'+(r.desc?'<div class="sr-desc">'+(r.desc.length>90?r.desc.slice(0,90)+'…':r.desc)+'</div>':'')+'</button>').join(''); out.querySelectorAll('.search-row').forEach(b=>b.addEventListener('click',()=>{cur=+b.dataset.i;pick();})); }
function pick(){ const r=rows[cur]; if(!r) return; close(); goTo(r.sec); }
function move(d){ const items=out.querySelectorAll('.search-row'); if(!items.length) return; items[cur]&&items[cur].classList.remove('active'); cur=(cur+d+items.length)%items.length; items[cur].classList.add('active'); items[cur].scrollIntoView({block:'nearest'}); }
function open(){ modal.classList.add('show'); inp.value=''; rows=rank(''); render(); setTimeout(()=>inp.focus(),50); }
function close(){ modal.classList.remove('show'); }
btn&&btn.addEventListener('click',open);
modal.addEventListener('click',e=>{if(e.target===modal)close();});
inp.addEventListener('input',()=>{rows=rank(inp.value);render();});
inp.addEventListener('keydown',e=>{ if(e.key==='ArrowDown'){e.preventDefault();move(1);}else if(e.key==='ArrowUp'){e.preventDefault();move(-1);}else if(e.key==='Enter'){e.preventDefault();pick();}else if(e.key==='Escape'){e.preventDefault();close();} });
document.addEventListener('keydown',e=>{ if((e.ctrlKey||e.metaKey)&&(e.key==='k'||e.key==='K')){ e.preventDefault(); if(modal.classList.contains('show')) close(); else open(); } });
}
function initSidebarToggle(){
const side=document.getElementById('col-side'),back=document.getElementById('col-side-backdrop'),btn=document.getElementById('sidebar-btn');
if(!side||!btn) return;
function open(){ side.classList.add('open'); back.classList.add('show'); }
function close(){ side.classList.remove('open'); back.classList.remove('show'); }
btn.addEventListener('click',()=>{ if(side.classList.contains('open')) close(); else open(); });
back.addEventListener('click',close);
document.addEventListener('keydown',e=>{ if(e.key==='Escape') close(); });
}
function init(){
loadProgress(); initTheme(); initSidebarToggle(); initSearch();
buildParaSelector(); refreshProgressUI(); loadServerReadState(); goTo(PARAS[0].id);
setTimeout(()=>achievement('start'), 600);
if(window.LS&&window.LS.xp){
window.LS.xp.load().then(function(s){ if(s&&s.xp>STATE.xp){ STATE.xp=s.xp; STATE.level=calcLevel(STATE.xp); saveProgress(); refreshProgressUI(); if(STATE.current) buildSidebar(STATE.current); } });
}
}
document.addEventListener('DOMContentLoaded', init);
/* === PHYS10 POLISH JS === */
(function(){
function bumpScore(el){
if(!el) return;
el.classList.remove('bump');
void el.offsetWidth;
el.classList.add('bump');
setTimeout(function(){ try{ el.classList.remove('bump'); }catch(e){} }, 270);
}
window.__phys10BumpScore = bumpScore;
function observeScores(root){
root = root || document;
var nodes = root.querySelectorAll('.score-display b');
nodes.forEach(function(b){
if(b.__scoreObs) return;
b.__scoreObs = true;
var last = b.textContent;
try{
var mo = new MutationObserver(function(){
var nv = b.textContent;
if(nv !== last){ last = nv; bumpScore(b); }
});
mo.observe(b, {childList:true, characterData:true, subtree:true});
}catch(e){}
});
}
function rescanScores(){ try{ observeScores(document); }catch(e){} }
if(document.readyState === 'loading') document.addEventListener('DOMContentLoaded', rescanScores);
else rescanScores();
try{
var rootObs = new MutationObserver(function(muts){
var need = false;
for(var i=0;i<muts.length && !need;i++){
var m = muts[i];
for(var j=0;j<m.addedNodes.length;j++){
var n = m.addedNodes[j];
if(n.nodeType===1){
if(n.classList && n.classList.contains('score-display')) { need = true; break; }
if(n.querySelector && n.querySelector('.score-display b')) { need = true; break; }
}
}
}
if(need) rescanScores();
});
rootObs.observe(document.body, {childList:true, subtree:true});
}catch(e){}
function refreshDoneMarks(){
try{
if(typeof STATE === 'undefined' || !STATE.progress) return;
document.querySelectorAll('.psel-card').forEach(function(c){
var id = c.dataset.id || c.dataset.progCard;
if(!id) return;
var pct = +STATE.progress[id] || 0;
if(!c.querySelector('.psel-done')){
var s = document.createElement('span');
s.className = 'psel-done';
s.setAttribute('title','Прочитано');
s.innerHTML = '<svg viewBox="0 0 24 24"><polyline points="20 6 9 17 4 12"/></svg>';
c.appendChild(s);
}
c.classList.toggle('done', pct >= 50);
});
}catch(e){}
}
try{
if(typeof window.refreshProgressUI === 'function'){
var _origRP = window.refreshProgressUI;
window.refreshProgressUI = function(){ var r = _origRP.apply(this, arguments); setTimeout(refreshDoneMarks, 0); return r; };
}
}catch(e){}
setTimeout(refreshDoneMarks, 600);
setTimeout(refreshDoneMarks, 1800);
window.addEventListener('focus', function(){ setTimeout(refreshDoneMarks, 200); });
document.addEventListener('click', function(e){
var card = e.target.closest && e.target.closest('.psel-card');
if(!card) return;
var id = card.dataset.id;
if(!id) return;
setTimeout(function(){
var sec = document.getElementById('sec-' + id);
if(sec) try{ sec.scrollIntoView({behavior:'smooth', block:'start'}); }catch(e){}
}, 60);
});
})();
</script>
</body>
</html>