diff --git a/frontend/textbooks/algebra_8.html b/frontend/textbooks/algebra_8.html index e3d1fa1..1a075f8 100644 --- a/frontend/textbooks/algebra_8.html +++ b/frontend/textbooks/algebra_8.html @@ -410,6 +410,71 @@ input,select,textarea{font-family:inherit} .psel-card{flex:0 0 148px;scroll-snap-align:start} body{font-size:.94rem} } + +/* ═══════════════════════════════════════════════ + WAVE 2 — INTERACTIVE DEPTH + ═══════════════════════════════════════════════ */ + +/* Task 5: live-check indicators */ +.live-ind{display:inline-block;margin-left:6px;font-weight:900;font-size:1rem;transition:color .15s} +.live-ind.ok{color:var(--ok)} +.live-ind.fail{color:var(--fail)} + +/* Task 3: drag-and-drop DnD card */ +.dnd-card{display:inline-flex;align-items:center;justify-content:center;padding:8px 16px;background:linear-gradient(135deg,var(--acc),var(--acc2));color:#fff;border-radius:10px;font-weight:700;font-size:1rem;cursor:grab;user-select:none;font-family:'JetBrains Mono',monospace;box-shadow:var(--sh2);transition:transform .15s,box-shadow .15s;touch-action:none} +.dnd-card:active{cursor:grabbing;transform:scale(1.06);box-shadow:0 8px 24px rgba(3,169,244,.35)} +.dnd-card.dragging-active{opacity:.55;transform:scale(.95)} +.dnd-card.correct-dnd{background:linear-gradient(135deg,var(--ok),#059669);animation:dndCorrect .4s ease} +.dnd-card.wrong-dnd{animation:dndWrong .5s ease} +@keyframes dndCorrect{0%{transform:scale(1.15)}100%{transform:scale(1)}} +@keyframes dndWrong{0%,100%{transform:translateX(0)}25%{transform:translateX(-8px)}75%{transform:translateX(8px)}} +.dnd-dropzone{min-height:60px;border:2.5px dashed var(--sec-acc,var(--pri));border-radius:12px;background:var(--card);padding:10px 14px;display:flex;align-items:center;justify-content:center;transition:border-color .15s,background .15s;font-size:.88rem;color:var(--muted);font-weight:600} +.dnd-dropzone.over{border-color:var(--ok);background:var(--ok-bg)} + +/* Task 4: SVG connection lines for match */ +#match-svg-overlay{position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none;z-index:5;overflow:visible} +.match-line{stroke-width:2.5;fill:none;stroke-dasharray:none;transition:stroke .25s} +.match-line.pending{stroke:var(--acc);stroke-dasharray:6 3;animation:dashFlow .8s linear infinite} +.match-line.correct-line{stroke:var(--ok)} +.match-line.wrong-line{stroke:var(--fail);animation:lineFlash .3s ease 3} +@keyframes dashFlow{to{stroke-dashoffset:-18}} +@keyframes lineFlash{0%,100%{opacity:1}50%{opacity:.2}} + +/* Task 6: game-over modal */ +.game-over-modal{position:fixed;inset:0;z-index:2000;display:flex;align-items:center;justify-content:center;background:rgba(0,0,0,.55);backdrop-filter:blur(4px);animation:modalIn .3s ease} +@keyframes modalIn{from{opacity:0}to{opacity:1}} +.game-over-box{background:var(--card);border-radius:20px;padding:32px 36px;text-align:center;max-width:360px;width:90%;box-shadow:0 24px 64px rgba(0,0,0,.28);animation:boxIn .4s cubic-bezier(.34,1.56,.64,1)} +@keyframes boxIn{from{transform:scale(.75);opacity:0}to{transform:scale(1);opacity:1}} +.game-over-score{font-size:3rem;font-weight:900;color:var(--pri2);font-family:'Unbounded',sans-serif;margin:10px 0} +.game-over-record{display:inline-flex;align-items:center;gap:8px;padding:8px 16px;background:linear-gradient(135deg,#fcd34d,#f59e0b);color:#451a03;border-radius:10px;font-weight:800;font-size:.95rem;margin:10px 0;animation:recordPulse 1s ease infinite} +@keyframes recordPulse{0%,100%{box-shadow:0 0 0 0 rgba(245,158,11,.5)}50%{box-shadow:0 0 0 8px rgba(245,158,11,0)}} + +/* Task 7: psel-card hover preview */ +.psel-card{overflow:visible} +/* restore border-radius clip for the active stripe via pseudo-element only on non-preview */ +.psel-card-preview{display:none;position:absolute;left:105%;top:0;width:200px;background:var(--card);border:1.5px solid var(--pri);border-radius:12px;padding:12px 14px;z-index:100;box-shadow:var(--sh2);pointer-events:none;animation:previewIn .18s ease} +@keyframes previewIn{from{opacity:0;transform:translateX(-8px)}to{opacity:1;transform:none}} +.psel-card:hover .psel-card-preview{display:block} +.psel-preview-title{font-size:.72rem;font-weight:800;color:var(--pri2);text-transform:uppercase;letter-spacing:.06em;margin-bottom:6px} +.psel-preview-topic{font-size:.78rem;color:var(--text);margin-bottom:2px;padding-left:8px;border-left:2px solid var(--sec-acc,var(--pri))} +.psel-preview-bar{height:5px;background:rgba(233,30,99,.12);border-radius:3px;overflow:hidden;margin-top:8px} +.psel-preview-fill{height:100%;background:var(--pri);border-radius:3px;transition:width .4s} +.psel-preview-pct{font-size:.72rem;color:var(--muted);margin-top:2px} +@media(max-width:768px){.psel-card-preview{display:none!important}} + +/* Task 8: section fade transitions */ +.sec.fade-out{animation:secFadeOut .18s ease forwards} +.sec.fade-in{animation:secFadeIn .22s ease forwards} +@keyframes secFadeOut{from{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(-8px)}} +@keyframes secFadeIn{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:none}} + +/* Task 1: boxer ring extras */ +.ring-boxer{animation:boxerBounce .4s ease infinite alternate} +@keyframes boxerBounce{from{transform:translateY(0)}to{transform:translateY(-4px)}} + +/* Task 2: geo proof animation badge */ +.proof-badge{display:inline-flex;align-items:center;gap:6px;padding:6px 14px;background:linear-gradient(135deg,var(--ok),#059669);color:#fff;border-radius:8px;font-weight:700;font-size:.85rem;animation:badgeIn .4s cubic-bezier(.34,1.56,.64,1)} +@keyframes badgeIn{from{transform:scale(.5);opacity:0}to{transform:scale(1);opacity:1}}
@@ -636,13 +701,20 @@ function achievement(id, text){ PARA SELECTOR ════════════════════════════════════════════════════════ */ const PARAS = [ - { id:'p1', num:'§ 1', name:'Квадратный корень', sub:'Арифметический корень' }, - { id:'p2', num:'§ 2', name:'Действительные числа', sub:'Иррациональные числа' }, - { id:'p3', num:'§ 3', name:'Свойства корней', sub:'√(ab) = √a·√b' }, - { id:'p4', num:'§ 4', name:'Применение свойств', sub:'Преобразования' }, - { id:'p5', num:'§ 5', name:'Числовые промежутки', sub:'∪ и ∩' }, - { id:'p6', num:'§ 6', name:'Системы неравенств', sub:'Двойные неравенства' }, - { id:'final', num:'★', name:'Финал главы', sub:'Самооценка · Практика · Увлекательно', final:true }, + { id:'p1', num:'§ 1', name:'Квадратный корень', sub:'Арифметический корень', + topics:['Определение корня','Арифметический корень','Извлечение корня','Игра «Таблица квадратов»','Ринг: S=36'] }, + { id:'p2', num:'§ 2', name:'Действительные числа', sub:'Иррациональные числа', + topics:['ℕ ⊂ ℤ ⊂ ℚ ⊂ ℝ','Иррациональные числа','Числовая ось','Классификация чисел'] }, + { id:'p3', num:'§ 3', name:'Свойства корней', sub:'√(ab) = √a·√b', + topics:['√(ab) = √a·√b','√(a/b) = √a/√b','√(a²) = |a|','Match-игра','Тренажёр упрощения'] }, + { id:'p4', num:'§ 4', name:'Применение свойств', sub:'Преобразования', + topics:['Вынесение множителя','Внесение под корень','Освобождение от иррац.','Сравнение корней','Drag «упрости √»'] }, + { id:'p5', num:'§ 5', name:'Числовые промежутки', sub:'∪ и ∩', + topics:['9 типов промежутков','Конструктор промежутка','Объединение A ∪ B','Пересечение A ∩ B'] }, + { id:'p6', num:'§ 6', name:'Системы неравенств', sub:'Двойные неравенства', + topics:['Система неравенств','Совокупность неравенств','Двойные неравенства','Решение на числовой оси'] }, + { id:'final', num:'★', name:'Финал главы', sub:'Самооценка · Практика · Увлекательно', final:true, + topics:['10 задач самооценки','3 практические задачи','История знака √','Олимпиадные задачи'] }, ]; function buildParaSelector(){ @@ -653,10 +725,18 @@ function buildParaSelector(){ card.className = 'psel-card' + (p.final ? ' final' : ''); card.dataset.id = p.id; card.dataset.progCard = p.id; + const topicsHtml = (p.topics||[]).map(t=>`Площади всегда равны → $\\sqrt{ab}$ — сторона эквивалентного квадрата
+