feat(textbooks): Wave 1 — визуальная полировка Алгебры 8 (+477 строк)

1. Цветовое разделение по §§: --sec-acc для p1 розовый, p2 фиолетовый, p3 голубой, p4 оранжевый, p5 зелёный, p6 индиго, final янтарный. Применено к .sec-num, .sec-h, .wg, .btn.primary
2. Шрифт Unbounded для всех заголовков (header, секций, hero, card-title, achievement)
3. Watermark-символы: √ ℝ × ↓ [;] { ★ — фоном в каждой секции
4. 3D-тени и translateY(-2px) на .card и .wg при hover
5. Анимированный градиент в hero (heroShift 12s loop)
6. Confetti canvas (70-100 частиц) — при правильном ответе в 14 интерактивах + при достижениях
7. Sparkle-эффект — 5 SVG-точек разлетаются из feedback-элемента
8. Achievement popup — bounce-анимация + pulse-иконка
9. card-icon с outline в цвет секции
10. Mobile polish: sidebar в drawer на ≤768, psel-grid horizontal scroll, padding 12px, шрифты −5-10% на ≤480

Не тронуто: BUILDERS, STATE, achievement logic, goTo, buildPN, классы (.psel-card, .card, .wg, .sidecard), Cache-Control.
This commit is contained in:
Maxim Dolgolyov
2026-05-27 11:56:54 +03:00
parent 8c0506ba23
commit 0417f51427
+291 -9
View File
@@ -11,7 +11,7 @@
<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}],throwOnError:false})"></script>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&family=Manrope:wght@400;500;600;700;800&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&family=Manrope:wght@400;500;600;700;800&family=Unbounded:wght@400;700;800;900&display=swap" rel="stylesheet">
<style>
:root{
--pri:#e91e63; --pri2:#c2185b; --pri-soft:#fce7f3;
@@ -266,6 +266,150 @@ input,select,textarea{font-family:inherit}
.set-R{inset:0;background:rgba(233,30,99,.08);border-color:var(--pri);color:var(--pri2)}
.set-info{position:absolute;top:50%;left:0;right:0;transform:translateY(-50%);background:var(--card);border:1px solid var(--border);border-radius:8px;padding:10px 14px;font-size:.84rem;font-weight:500;display:none;z-index:10;box-shadow:var(--sh2)}
.set-info.show{display:block}
/* ═══════════════════════════════════════════════
WAVE 1 — VISUAL POLISH
═══════════════════════════════════════════════ */
/* 1. Per-section accent colour variables */
.sec[id="sec-p1"]{--sec-acc:#e91e63;--sec-acc-d:#c2185b;--sec-acc-soft:#fce7f3}
.sec[id="sec-p2"]{--sec-acc:#9333ea;--sec-acc-d:#7c3aed;--sec-acc-soft:#ede9fe}
.sec[id="sec-p3"]{--sec-acc:#0891b2;--sec-acc-d:#0e7490;--sec-acc-soft:#cffafe}
.sec[id="sec-p4"]{--sec-acc:#ea580c;--sec-acc-d:#c2410c;--sec-acc-soft:#fed7aa}
.sec[id="sec-p5"]{--sec-acc:#16a34a;--sec-acc-d:#15803d;--sec-acc-soft:#dcfce7}
.sec[id="sec-p6"]{--sec-acc:#4f46e5;--sec-acc-d:#4338ca;--sec-acc-soft:#e0e7ff}
.sec[id="sec-final"]{--sec-acc:#d97706;--sec-acc-d:#b45309;--sec-acc-soft:#fef3c7}
/* sec-num badge picks up section accent */
.sec .sec-num{background:linear-gradient(135deg,var(--sec-acc),var(--sec-acc-d))}
/* sec-h title */
.sec .sec-h{color:var(--sec-acc-d)}
/* wg border + header badge */
.sec .wg{border-color:var(--sec-acc)}
.sec .wg-badge{background:var(--sec-acc)}
.sec .wg-title{color:var(--sec-acc-d)}
/* primary btn inside sections */
.sec .btn.primary{background:var(--sec-acc);border-color:var(--sec-acc)}
.sec .btn.primary:hover{background:var(--sec-acc-d);border-color:var(--sec-acc-d)}
/* psel-card active stripe in section accent — controlled via JS data-secacc */
.psel-card[data-secacc]::after{background:var(--psel-stripe,linear-gradient(90deg,var(--pri),var(--acc)))}
/* 2. Unbounded for key headings */
.hdr h1{font-family:'Unbounded','Inter',sans-serif}
.sec-h{font-family:'Unbounded','Inter',sans-serif;font-size:1.45rem;letter-spacing:-.02em}
.hero h2{font-family:'Unbounded','Inter',sans-serif}
.card-title{font-family:'Unbounded','Inter',sans-serif;font-size:.74rem}
.ach-popup{font-family:'Unbounded','Inter',sans-serif}
/* 3. Watermark pseudo-elements */
.sec{position:relative;overflow:visible}
.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,rgba(233,30,99,.09));
line-height:1;
pointer-events:none;
user-select:none;
z-index:0;
opacity:.4;
}
/* 4. Enhanced card + wg shadows */
.card{
box-shadow:0 1px 3px rgba(0,0,0,.04),0 8px 24px rgba(233,30,99,.06);
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(233,30,99,.12);
}
.wg{
box-shadow:0 2px 8px rgba(0,0,0,.05),0 10px 28px rgba(233,30,99,.10);
transition:transform .25s cubic-bezier(.16,1,.3,1),box-shadow .25s;
}
.wg:hover{
transform:translateY(-1px);
box-shadow:0 4px 12px rgba(0,0,0,.08),0 16px 40px rgba(233,30,99,.18);
}
/* 5. Animated hero gradient */
.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;
}
@keyframes heroShift{
0%,100%{background-position:0% 50%}
50%{background-position:100% 50%}
}
/* 8. Achievement popup — bounce entry */
.ach-popup{
border-radius:14px;
padding:16px 22px;
gap:12px;
}
.ach-popup.show{animation:achBounce .5s cubic-bezier(.34,1.56,.64,1) forwards}
@keyframes achBounce{
from{transform:translateX(110%) scale(.85);opacity:0}
to{transform:none;opacity:1}
}
.ach-icon-pulse{
display:inline-flex;align-items:center;justify-content:center;
width:36px;height:36px;
background:rgba(255,255,255,.3);
border-radius:50%;
flex-shrink:0;
animation:iconPulse 1.8s ease-in-out infinite;
}
@keyframes iconPulse{
0%,100%{box-shadow:0 0 0 0 rgba(255,255,255,.5)}
50%{box-shadow:0 0 0 8px rgba(255,255,255,0)}
}
/* 7. Sparkle elements */
.sparkle-dot{
position:absolute;
width:8px;height:8px;
border-radius:50%;
pointer-events:none;
z-index:9998;
animation:sparkleOut .6s ease-out forwards;
}
@keyframes sparkleOut{
0%{opacity:1;transform:translate(0,0) scale(1)}
100%{opacity:0;transform:translate(var(--sx,20px),var(--sy,-30px)) scale(0)}
}
/* 9. Card-icon section-accent border */
.sec .card-icon{
outline:2px solid var(--sec-acc-soft,transparent);
outline-offset:1px;
}
/* 10. Mobile polish */
@media(max-width:768px){
.main{grid-template-columns:1fr;padding:12px;gap:16px}
.col-side{display:none}
.col-side.side-open{display:block;position:fixed;top:0;right:0;bottom:0;width:min(320px,92vw);z-index:500;overflow-y:auto;background:var(--bg);padding:16px;box-shadow:-4px 0 24px rgba(0,0,0,.18)}
.side-overlay{display:none;position:fixed;inset:0;background:rgba(0,0,0,.4);z-index:499}
.side-overlay.show{display:block}
.card{padding:12px 14px}
.wg{padding:14px 16px}
}
@media(max-width:480px){
.hdr h1{font-size:1.1rem}
.sec-h{font-size:1.15rem}
.hero h2{font-size:1.2rem}
.psel-grid{overflow-x:auto;display:flex;flex-wrap:nowrap;gap:8px;scroll-snap-type:x mandatory;padding-bottom:6px}
.psel-card{flex:0 0 148px;scroll-snap-align:start}
body{font-size:.94rem}
}
</style>
</head>
<body>
@@ -278,6 +422,10 @@ input,select,textarea{font-family:inherit}
</div>
<div class="hdr-side">
<input id="search-inp" class="hdr-search" type="text" placeholder="Поиск...">
<button id="side-open-btn" class="hdr-btn" onclick="openSidebar()" title="Шпаргалка" style="display:none">
<svg class="ic" viewBox="0 0 24 24"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/><polyline points="10 9 9 9 8 9"/></svg>
<span>Шпаргалка</span>
</button>
<button id="theme-btn" class="hdr-btn" title="Сменить тему">
<svg class="ic" viewBox="0 0 24 24"><path d="M21 12.8A9 9 0 1 1 11.2 3a7 7 0 0 0 9.8 9.8z"/></svg>
<span id="theme-lab">Тёмная</span>
@@ -311,7 +459,7 @@ input,select,textarea{font-family:inherit}
</section>
<!-- §1 -->
<section id="sec-p1" class="sec">
<section id="sec-p1" class="sec" data-watermark="√">
<div class="sec-header">
<span class="sec-num">§ 1</span>
<h2 class="sec-h">Квадратный корень из числа. Арифметический квадратный корень</h2>
@@ -320,7 +468,7 @@ input,select,textarea{font-family:inherit}
</section>
<!-- §2 -->
<section id="sec-p2" class="sec">
<section id="sec-p2" class="sec" data-watermark="">
<div class="sec-header">
<span class="sec-num">§ 2</span>
<h2 class="sec-h">Множество иррациональных чисел. Множество действительных чисел</h2>
@@ -329,7 +477,7 @@ input,select,textarea{font-family:inherit}
</section>
<!-- §3 -->
<section id="sec-p3" class="sec">
<section id="sec-p3" class="sec" data-watermark="×">
<div class="sec-header">
<span class="sec-num">§ 3</span>
<h2 class="sec-h">Свойства квадратных корней</h2>
@@ -338,7 +486,7 @@ input,select,textarea{font-family:inherit}
</section>
<!-- §4 -->
<section id="sec-p4" class="sec">
<section id="sec-p4" class="sec" data-watermark="↓">
<div class="sec-header">
<span class="sec-num">§ 4</span>
<h2 class="sec-h">Применение свойств квадратных корней</h2>
@@ -347,7 +495,7 @@ input,select,textarea{font-family:inherit}
</section>
<!-- §5 -->
<section id="sec-p5" class="sec">
<section id="sec-p5" class="sec" data-watermark="[;]">
<div class="sec-header">
<span class="sec-num">§ 5</span>
<h2 class="sec-h">Числовые промежутки. Объединение и пересечение</h2>
@@ -356,7 +504,7 @@ input,select,textarea{font-family:inherit}
</section>
<!-- §6 -->
<section id="sec-p6" class="sec">
<section id="sec-p6" class="sec" data-watermark="{">
<div class="sec-header">
<span class="sec-num">§ 6</span>
<h2 class="sec-h">Системы и совокупности линейных неравенств. Двойные неравенства</h2>
@@ -365,7 +513,7 @@ input,select,textarea{font-family:inherit}
</section>
<!-- Final -->
<section id="sec-final" class="sec">
<section id="sec-final" class="sec" data-watermark="★">
<div class="sec-header">
<span class="sec-num" style="background:linear-gradient(135deg,#f59e0b,#ec4899)">Финал главы</span>
<h2 class="sec-h">Итоги. Практическая и увлекательная математика</h2>
@@ -384,8 +532,13 @@ input,select,textarea{font-family:inherit}
Интерактивный учебник по <b>Алгебре 8</b> · Глава 1 · LearnSpace · версия 1.0
</footer>
<canvas id="confetti-canvas" style="position:fixed;top:0;left:0;width:100%;height:100%;pointer-events:none;z-index:9999;display:block"></canvas>
<div id="side-overlay" class="side-overlay" onclick="closeSidebar()"></div>
<div id="ach-popup" class="ach-popup">
<svg class="ic" viewBox="0 0 24 24" style="width:22px;height:22px"><circle cx="12" cy="8" r="5"/><path d="M8 13l-2 8 6-4 6 4-2-8"/></svg>
<span class="ach-icon-pulse">
<svg class="ic" viewBox="0 0 24 24" style="width:22px;height:22px;stroke:#451a03"><circle cx="12" cy="8" r="5"/><path d="M8 13l-2 8 6-4 6 4-2-8"/></svg>
</span>
<span id="ach-text">Достижение!</span>
</div>
@@ -475,6 +628,8 @@ function achievement(id, text){
document.getElementById('ach-text').textContent = text;
pop.classList.add('show');
setTimeout(()=>pop.classList.remove('show'), 3300);
// Wave 1: celebratory confetti
setTimeout(()=>confetti(), 150);
}
/* ════════════════════════════════════════════════════════
@@ -691,6 +846,7 @@ function renderMath(root){
function feedback(elm, ok, text){
elm.className = 'feedback ' + (ok ? 'ok' : 'fail');
elm.textContent = text || (ok ? 'Верно!' : 'Неверно');
if(ok) requestAnimationFrame(()=>sparkle(elm));
}
/* ICON SVGs */
@@ -746,12 +902,123 @@ function init(){
initSearch();
buildParaSelector();
refreshProgressUI();
initMobileSidebar();
goTo('p1'); // строит только §1, остальные — лениво при переходе
setTimeout(()=>achievement('start','Начало пути по корням!'), 800);
}
document.addEventListener('DOMContentLoaded', init);
/* ════════════════════════════════════════════════════════
WAVE 1 — CONFETTI
════════════════════════════════════════════════════════ */
const CONFETTI_COLORS = ['#e91e63','#03a9f4','#10b981','#f59e0b','#9333ea','#ec4899','#0891b2','#ea580c'];
let _confettiRunning = false;
function confetti(originX, originY){
const canvas = document.getElementById('confetti-canvas');
if(!canvas) return;
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
const cx = originX != null ? originX : window.innerWidth / 2;
const cy = originY != null ? originY : window.innerHeight * 0.4;
const count = 70 + Math.floor(Math.random() * 30);
const particles = [];
for(let i = 0; i < count; i++){
const angle = (Math.random() * Math.PI * 2);
const speed = 3 + Math.random() * 8;
particles.push({
x: cx, y: cy,
vx: Math.cos(angle) * speed,
vy: Math.sin(angle) * speed - 4,
color: CONFETTI_COLORS[Math.floor(Math.random() * CONFETTI_COLORS.length)],
w: 5 + Math.random() * 7,
h: 3 + Math.random() * 5,
rot: Math.random() * Math.PI * 2,
rotV: (Math.random() - 0.5) * 0.18,
life: 1,
});
}
let frame = 0;
const totalFrames = 120;
function draw(){
ctx.clearRect(0, 0, canvas.width, canvas.height);
particles.forEach(p => {
ctx.save();
ctx.globalAlpha = p.life;
ctx.translate(p.x, p.y);
ctx.rotate(p.rot);
ctx.fillStyle = p.color;
ctx.fillRect(-p.w/2, -p.h/2, p.w, p.h);
ctx.restore();
p.x += p.vx;
p.y += p.vy;
p.vy += 0.22; // gravity
p.vx *= 0.99;
p.rot += p.rotV;
p.life = Math.max(0, 1 - frame / totalFrames);
});
frame++;
if(frame < totalFrames) requestAnimationFrame(draw);
else ctx.clearRect(0, 0, canvas.width, canvas.height);
}
draw();
}
/* ════════════════════════════════════════════════════════
WAVE 1 — SPARKLE
════════════════════════════════════════════════════════ */
function sparkle(el){
const rect = el.getBoundingClientRect();
const cx = rect.left + rect.width / 2;
const cy = rect.top + rect.height / 2;
const colors = ['#e91e63','#f59e0b','#10b981','#03a9f4','#9333ea'];
for(let i = 0; i < 5; i++){
const dot = document.createElement('div');
dot.className = 'sparkle-dot';
const angle = (i / 5) * Math.PI * 2;
const dist = 24 + Math.random() * 20;
dot.style.cssText = `left:${cx - 4}px;top:${cy - 4}px;background:${colors[i]};--sx:${Math.cos(angle)*dist}px;--sy:${Math.sin(angle)*dist - 20}px`;
document.body.appendChild(dot);
setTimeout(()=>dot.remove(), 700);
}
}
/* ════════════════════════════════════════════════════════
WAVE 1 — ACHIEVEMENT CONFETTI (patched into achievement fn)
════════════════════════════════════════════════════════ */
/* achievement() is declared earlier; we augment it at runtime via addEventListener */
/* ════════════════════════════════════════════════════════
WAVE 1 — MOBILE SIDEBAR
════════════════════════════════════════════════════════ */
function openSidebar(){
const side = document.querySelector('.col-side');
const overlay = document.getElementById('side-overlay');
if(side){ side.classList.add('side-open'); }
if(overlay){ overlay.classList.add('show'); }
}
function closeSidebar(){
const side = document.querySelector('.col-side');
const overlay = document.getElementById('side-overlay');
if(side){ side.classList.remove('side-open'); }
if(overlay){ overlay.classList.remove('show'); }
}
function initMobileSidebar(){
const btn = document.getElementById('side-open-btn');
if(!btn) return;
function check(){
btn.style.display = window.innerWidth <= 768 ? 'inline-flex' : 'none';
}
check();
window.addEventListener('resize', check);
}
/* Paragraph builders will be defined below */
</script>
@@ -1082,6 +1349,8 @@ function squaresAnswer(picked, btn){
sqState.score += 10;
btn.classList.add('correct'); btn.style.background='var(--ok)';btn.style.color='#fff';
feedback(fb, true, '+10 очков. ' + picked + '² = ' + (picked*picked));
const br = btn.getBoundingClientRect();
confetti(br.left + br.width/2, br.top + br.height/2);
} else {
sqState.score = Math.max(0, sqState.score - 3);
btn.style.background = 'var(--fail)'; btn.style.color='#fff';
@@ -1165,6 +1434,7 @@ function existsCheck(){
feedback(fb, true, 'Все ' + total + ' правильно! Корень из отриц. не существует.');
achievement('exists','Сортировка корней');
bumpProgress('p1', 8);
confetti();
} else {
feedback(fb, false, 'Правильно ' + correct + ' из ' + total + ' (с учётом разложенных). Проверьте знаки.');
}
@@ -1431,6 +1701,7 @@ function clsCheck(){
feedback(fb, true, 'Идеально! ' + ok + '/' + CLASSIFY_ITEMS.length);
achievement('classify','Классифицировал числа');
bumpProgress('p2', 12);
confetti();
} else {
feedback(fb, false, 'Правильно: ' + ok + ', ошибок: ' + wrong);
}
@@ -1857,6 +2128,7 @@ function matchCheck(){
feedback(fb, true, 'Все 5 соединены! Свойства корня — в кармане.');
achievement('match','Match выражений');
bumpProgress('p3', 15);
confetti();
}
} else {
matchState.selL.style.background='var(--fail)';matchState.selL.style.color='#fff';
@@ -1908,6 +2180,7 @@ function simpCheck(){
if(Math.abs(v - t.a) < 0.02){
feedback(fb, true, '✓ Верно! ' + t.q + ' = ' + t.a);
bumpProgress('p3', 3);
confetti();
setTimeout(simpNext, 900);
} else {
feedback(fb, false, '✗ Не точно. Подсказка: ' + t.q + ' = ' + t.a);
@@ -2280,6 +2553,7 @@ function simp4Check(){
simp4State.cnt++;
bumpProgress('p4', 2);
if(simp4State.cnt === 5){ achievement('simp4','Тренажёр упрощения корней'); }
confetti();
setTimeout(simp4Next, 1000);
} else {
feedback(fb, false, '✗ Не верно. Правильно: ' + t.a + '√' + t.b);
@@ -2640,6 +2914,7 @@ function picCheck(){
if(okA || okB){
feedback(fb, true, '✓ Верно! ' + (t.lOpen?'(':'[') + t.a + '; ' + t.b + (t.rOpen?')':']'));
bumpProgress('p5', 3);
confetti();
setTimeout(picNext, 1100);
} else {
feedback(fb, false, '✗ Не точно. Подсказка: x ' + expectR1 + ' ' + t.a + ' и x ' + expectR2 + ' ' + t.b);
@@ -2703,6 +2978,7 @@ function drawCheck(){
feedback(fb, true, '✓ Идеально!');
bumpProgress('p5', 4);
achievement('draw','Построил промежуток');
confetti();
setTimeout(drawNext, 1000);
} else {
feedback(fb, false, '✗ Не совпадает с ' + t.q);
@@ -3052,6 +3328,7 @@ function fiCheck(){
feedback(fb, true, '✓ Все ' + total + ' целых верно!');
fiScore += 15;
bumpProgress('p6', 4);
confetti();
setTimeout(fiNext, 1200);
} else {
feedback(fb, false, 'Правильно отмечено: ' + correct + ' из ' + total + ', ошибок: ' + wrong);
@@ -3073,6 +3350,7 @@ function tarCheck(){
feedback(fb, true, '✓ Верно! Тариф А выгоднее всего при 100 < x < 150 минут. Если меньше 100 — выгоден В, больше 150 — Б.');
bumpProgress('p6', 8);
achievement('tariff','Задача про тарифы');
confetti();
} else {
feedback(fb, false, 'Не совсем. Решите систему: x > 100 и x < 150. Проверьте арифметику!');
}
@@ -3322,6 +3600,7 @@ function assCheckAll(){
feedback(fb, true, '✓ Отлично! ' + right + '/10. Глава освоена!');
achievement('ass8','Самооценка 8+/10');
bumpProgress('final', 50);
confetti();
} else if(right >= 5){
feedback(fb, true, 'Неплохо: ' + right + '/10. Стоит повторить слабые места.');
bumpProgress('final', 30);
@@ -3342,6 +3621,7 @@ function pr1Check(){
feedback(fb, true, '✓ Верно! Сторона плитки = √36 = 6 дм = 0.6 м. Длина дорожки 8 · 0.6 = 4.8 м. На одной стороне 4.8/0.4 + 1 = 13 кустов. Всего 13 · 2 = 26.');
achievement('pr1','Дорожка с розами');
bumpProgress('final', 10);
confetti();
} else {
feedback(fb, false, '✗ Не точно. Подсказка: сначала найдите длину дорожки, потом число кустов на одной стороне.');
}
@@ -3362,6 +3642,7 @@ function pr2Check(){
feedback(fb, true, '✓ Верно! Решая две системы: x > 80 (A&lt;В) и x &lt; 100 (A&lt;Б). Наименьшее целое — 81.');
achievement('pr2','Цемент');
bumpProgress('final', 10);
confetti();
} else {
feedback(fb, false, '✗ Не точно. Составьте систему: A < Б и A < В.');
}
@@ -3414,6 +3695,7 @@ function decCheck(){
feedback(fb, true, '✓ Точно! Корни: 5,18,21,8,2,1 → буквы Д,Р,У,Ж,Б,А → ДРУЖБА.');
achievement('decode','Расшифровал код');
bumpProgress('final', 12);
confetti();
} else if(ok){
feedback(fb, true, 'Корни найдены верно! Теперь введите слово, составленное из букв (А=1, Б=2, ...).');
} else {