style(trainer): премиум-консоль — двухпанельный рабочий стол

Полный визуальный редизайн страницы /trainer (разметка-каркас + CSS).
Логика не тронута (генераторы, адаптив, шаги, аналитика, конструктор):
сохранены все DOM-ID и инжектируемые классы. Кольцо мастерства в рейле
запитано из существующей updateOverall() (только отражает данные).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Maxim Dolgolyov
2026-06-25 16:48:08 +03:00
parent 5226deb975
commit 21ffbbfe6c
+380 -285
View File
@@ -10,231 +10,307 @@
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css"/>
<script src="https://unpkg.com/lucide@0.469.0/dist/umd/lucide.min.js"></script>
<style>
/* ═══════════════ Тренажёр — «рабочий лист в клетку» ═══════════════
Фон — ambient-клетка (материал предмета: тетрадь в клетку). Задача —
чистая карточка-герой с акцентной «решающей» полосой. Акцент индиго→
фиолет, успех — изумруд, мастерство — золото. Логика/классы не менялись. */
/* ═══════════════════════════════════════════════════════════════════
ТРЕНАЖЁР — премиум-консоль. Двухпанельный «рабочий стол»: слева панель
прогресса/навигации, справа кинематографичная карточка-задача. Индиго→
фиолет, изумруд — успех, золото — мастерство. Мягкая глубина (clay),
стекло, aurora-фон с тетрадной клеткой. Шрифт Manrope, математика serif.
⛔ Логика/ID/инжектируемые классы НЕ менялись — только визуальный слой. */
:root {
--ink: #1b1f38; --ink-soft: #5b6378; --ink-faint: #98a1b8;
--ink: #181b34; --ink-soft: #565d77; --ink-faint: #98a0bb;
--card: #ffffff;
--g1: #6366f1; --g2: #8b5cf6;
--g1: #6366f1; --g2: #8b5cf6; --g0: #4f46e5;
--accent-ink: #4338ca; --accent-soft: #eef0ff;
--ok: #10b981; --ok-ink: #047857; --ok-soft: #dcfce7;
--bad: #ef4444; --bad-soft: #fee2e2; --warn: #d97706;
--gold: #f59e0b;
--r-lg: 24px;
--line: rgba(99,102,241,.14);
--r-lg: 26px; --r-md: 18px;
--sh: 0 16px 40px rgba(27,31,56,.09), 0 2px 6px rgba(27,31,56,.04);
--sh-lg: 0 30px 70px rgba(27,31,56,.20);
--sh-1: 0 1px 0 rgba(255,255,255,.8) inset, 0 2px 6px rgba(27,31,56,.05), 0 18px 40px -24px rgba(80,70,200,.30);
--sh-2: 0 1px 0 rgba(255,255,255,.7) inset, 0 8px 20px -10px rgba(27,31,56,.14), 0 34px 70px -34px rgba(80,70,200,.45);
--ease: cubic-bezier(.22,.61,.36,1);
}
.sb-content {
background-color: #f5f6fb;
background-color: #eef0f8;
background-image:
radial-gradient(1000px 600px at 86% -10%, rgba(139,92,246,.10), transparent 60%),
radial-gradient(820px 560px at 2% -6%, rgba(99,102,241,.09), transparent 55%),
linear-gradient(rgba(99,102,241,.05) 1px, transparent 1px),
linear-gradient(90deg, rgba(99,102,241,.05) 1px, transparent 1px);
background-size: 100% 100%, 100% 100%, 26px 26px, 26px 26px;
radial-gradient(1100px 680px at 90% -12%, rgba(139,92,246,.15), transparent 58%),
radial-gradient(900px 620px at -6% 4%, rgba(99,102,241,.14), transparent 55%),
radial-gradient(760px 600px at 60% 118%, rgba(56,189,248,.08), transparent 60%),
linear-gradient(rgba(99,102,241,.045) 1px, transparent 1px),
linear-gradient(90deg, rgba(99,102,241,.045) 1px, transparent 1px);
background-size: 100% 100%, 100% 100%, 100% 100%, 28px 28px, 28px 28px;
background-attachment: fixed;
}
.tr-wrap { max-width: 740px; margin: 0 auto; padding: 34px 20px 90px; }
@keyframes trUp { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
.tr-head, .tr-overall, .tr-mode, .tr-subjects, .tr-topbar, .tr-skillpanel, .tr-card { animation: trUp .5s var(--ease) both; }
.tr-overall { animation-delay: .04s; } .tr-mode { animation-delay: .06s; }
.tr-subjects { animation-delay: .08s; } .tr-topbar { animation-delay: .1s; } .tr-skillpanel { animation-delay: .13s; } .tr-card { animation-delay: .16s; }
.tr-wrap { max-width: 1240px; margin: 0 auto; padding: 22px 28px 90px; font-family: 'Manrope', system-ui, sans-serif; color: var(--ink); }
/* ── фильтр по предмету (Алгебра / Геометрия) ── */
.tr-subjects { display: flex; gap: 7px; margin-bottom: 14px; }
.tr-subjects:empty { display: none; }
.tr-subbtn { font: inherit; font-size: .86rem; font-weight: 800; cursor: pointer; padding: 8px 18px; border-radius: 99px; border: 1px solid rgba(99,102,241,.2); background: #fff; color: var(--ink-soft); transition: .16s var(--ease); }
.tr-subbtn:hover { border-color: var(--g1); color: var(--accent-ink); }
.tr-subbtn.on { color: #fff; border-color: transparent; background: linear-gradient(135deg, var(--g1), var(--g2)); box-shadow: 0 8px 20px rgba(99,102,241,.3); }
.tr-head { margin-bottom: 20px; }
.tr-h1 {
font-family: 'Manrope', sans-serif; font-weight: 800; font-size: clamp(1.6rem, 4.4vw, 2.1rem);
letter-spacing: -.02em; color: var(--ink); margin: 0 0 6px; display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
}
.tr-sub { color: var(--ink-soft); font-size: .95rem; line-height: 1.5; }
.tr-pill {
display: inline-block; font-size: .66rem; font-weight: 800; text-transform: uppercase; letter-spacing: .06em;
padding: 5px 11px; border-radius: 99px; color: #fff; vertical-align: middle;
background: linear-gradient(135deg, var(--g1), var(--g2)); box-shadow: 0 6px 16px rgba(99,102,241,.30);
}
/* ── выбор темы (вкладки) ── */
.tr-topbar { margin: 18px 0 14px; }
.tr-nav-eyebrow { display: block; font-family: 'Manrope', sans-serif; font-size: .7rem; font-weight: 800; text-transform: uppercase; letter-spacing: .08em; color: var(--ink-faint); margin-bottom: 9px; }
.tr-topics { display: flex; flex-wrap: wrap; gap: 8px; margin: 0; }
.tr-grade { display: inline-flex; align-items: center; justify-content: center; margin-left: 7px; font-family: 'Manrope', sans-serif; font-size: .6rem; font-weight: 800; min-width: 16px; height: 16px; padding: 0 4px; border-radius: 99px; background: rgba(99,102,241,.14); color: var(--accent-ink); }
.tr-chip.on .tr-grade { background: rgba(255,255,255,.26); color: #fff; }
/* ── панель навыков выбранной темы ── */
.tr-skillpanel { background: rgba(99,102,241,.05); border: 1px solid rgba(99,102,241,.12); border-radius: 16px; padding: 13px 15px; margin-bottom: 22px; }
.tr-skillpanel-hd { font-family: 'Manrope', sans-serif; font-size: .74rem; font-weight: 800; color: var(--accent-ink); margin-bottom: 10px; }
.tr-chip {
font: inherit; font-size: .86rem; font-weight: 700; cursor: pointer; color: var(--ink-soft);
padding: 9px 16px; border-radius: 99px; border: 1px solid rgba(99,102,241,.18);
background: rgba(255,255,255,.7); backdrop-filter: blur(6px); transition: .18s var(--ease);
}
.tr-chip:hover { border-color: var(--g1); color: var(--accent-ink); transform: translateY(-1px); }
.tr-chip.on { color: #fff; border-color: transparent; background: linear-gradient(135deg, var(--g1), var(--g2)); box-shadow: 0 8px 20px rgba(99,102,241,.34); }
/* ── карточка задачи (герой) ── */
.tr-card {
position: relative; overflow: hidden; background: var(--card);
border: 1px solid rgba(99,102,241,.12); border-radius: var(--r-lg);
box-shadow: var(--sh); transition: box-shadow .3s var(--ease), transform .3s var(--ease);
}
.tr-card.tr-correct { box-shadow: 0 22px 56px rgba(16,185,129,.30); animation: trPop .5s var(--ease); }
.tr-card.tr-wrong { animation: trShake .42s var(--ease); }
@keyframes trPop { 0% { transform: scale(1); } 32% { transform: scale(1.014); } 100% { transform: scale(1); } }
@keyframes trUp { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
@keyframes trPop { 0% { transform: scale(1); } 32% { transform: scale(1.012); } 100% { transform: scale(1); } }
@keyframes trShake { 0%,100% { transform: translateX(0); } 18% { transform: translateX(-7px); } 38% { transform: translateX(6px); } 58% { transform: translateX(-4px); } 78% { transform: translateX(2px); } }
@keyframes trFade { from { opacity: 0; } to { opacity: 1; } }
@keyframes ringIn { from { stroke-dashoffset: 339.292; } }
/* ── «сцена»-герой: уравнение крупно на ярком градиенте ── */
/* ═══════════ верхняя панель (стекло, плавающая) ═══════════ */
.tr-topbar2 {
position: sticky; top: 14px; z-index: 30;
display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
padding: 13px 16px 13px 20px; margin-bottom: 22px;
background: rgba(255,255,255,.72); backdrop-filter: blur(18px) saturate(1.4);
border: 1px solid rgba(255,255,255,.7); border-radius: 20px; box-shadow: var(--sh-1);
animation: trUp .5s var(--ease) both;
}
.tr-brand { display: flex; align-items: center; gap: 13px; min-width: 0; }
.tr-brand-mark { width: 42px; height: 42px; border-radius: 13px; background: linear-gradient(135deg, var(--g0), var(--g2)); box-shadow: 0 10px 22px rgba(99,102,241,.4); display: grid; place-items: center; color: #fff; flex: none; }
.tr-brand-mark .ic { width: 22px; height: 22px; }
.tr-h1 { font-family: 'Manrope', sans-serif; font-weight: 800; font-size: 1.34rem; letter-spacing: -.02em; margin: 0; line-height: 1.1; color: var(--ink); }
.tr-brand-sub { display: flex; align-items: center; gap: 8px; margin-top: 3px; }
.tr-pill {
display: inline-block; font-size: .64rem; font-weight: 800; text-transform: uppercase; letter-spacing: .06em;
padding: 4px 10px; border-radius: 99px; color: #fff;
background: linear-gradient(135deg, var(--g1), var(--g2)); box-shadow: 0 6px 14px rgba(99,102,241,.3);
}
.tr-modes { display: flex; align-items: center; gap: 9px; margin-left: auto; flex-wrap: wrap; }
/* умная тренировка — премиальный тумблер-капсула */
.tr-smart {
display: inline-flex; align-items: center; gap: 11px; cursor: pointer; user-select: none;
padding: 7px 8px 7px 15px; border-radius: 99px; border: 1px solid var(--line);
background: #fff; box-shadow: var(--sh-1); transition: .18s var(--ease);
}
.tr-smart:hover { border-color: var(--g1); }
.tr-smart:focus-visible { outline: none; border-color: var(--g1); box-shadow: 0 0 0 4px rgba(99,102,241,.18); }
.tr-smart-txt { font-size: .82rem; font-weight: 800; color: var(--ink); display: inline-flex; align-items: center; gap: 7px; }
.tr-smart-txt .ic { width: 16px; height: 16px; color: var(--g1); }
.tr-switch { width: 42px; height: 24px; border-radius: 99px; background: rgba(99,102,241,.18); position: relative; transition: .2s var(--ease); flex: none; }
.tr-switch::after { content: ''; position: absolute; top: 3px; left: 3px; width: 18px; height: 18px; border-radius: 50%; background: #fff; box-shadow: 0 2px 6px rgba(0,0,0,.25); transition: .2s var(--ease); }
.tr-smart.on .tr-switch { background: linear-gradient(135deg, var(--g1), var(--g2)); box-shadow: 0 6px 14px rgba(99,102,241,.4); }
.tr-smart.on .tr-switch::after { left: 21px; }
.tr-session { display: inline-flex; align-items: center; font-size: .8rem; font-weight: 800; color: var(--accent-ink); padding: 8px 14px; border-radius: 99px; background: rgba(99,102,241,.1); }
.tr-session:empty { display: none; }
.tr-mode-btn {
font: inherit; font-size: .8rem; font-weight: 800; cursor: pointer; display: inline-flex; align-items: center; gap: 7px;
padding: 9px 15px; border-radius: 99px; border: 1px solid var(--line); background: #fff; color: var(--ink-soft);
box-shadow: var(--sh-1); transition: .16s var(--ease);
}
.tr-mode-btn .ic { width: 16px; height: 16px; }
.tr-mode-btn:hover { border-color: var(--g1); color: var(--accent-ink); transform: translateY(-1px); }
.tr-admin-btn { color: #fff; border-color: transparent; background: linear-gradient(135deg, #f59e0b, #f97316); box-shadow: 0 8px 18px rgba(245,158,11,.32); }
.tr-admin-btn:hover { color: #fff; transform: translateY(-1px); }
/* ═══════════ двухпанельная сетка ═══════════ */
.tr-grid { display: grid; grid-template-columns: 312px minmax(0, 1fr); gap: 22px; align-items: start; }
.tr-rail { position: sticky; top: 96px; display: flex; flex-direction: column; gap: 16px; animation: trUp .55s var(--ease) both; animation-delay: .05s; }
.tr-main { display: flex; flex-direction: column; gap: 18px; min-width: 0; animation: trUp .55s var(--ease) both; animation-delay: .1s; }
.tr-panel { background: var(--card); border: 1px solid var(--line); border-radius: var(--r-lg); box-shadow: var(--sh-1); }
/* секция «Предмет» скрывается, когда фильтр предметов пуст (один предмет) */
.tr-rail-sec:has(#tr-subjects:empty) { display: none; }
/* ── панель прогресса (кольцо мастерства) ── */
.tr-progress-card { padding: 20px; }
.tr-ring-row { display: flex; align-items: center; gap: 16px; }
.tr-ring { width: 92px; height: 92px; flex: none; position: relative; }
.tr-ring #tr-ring-arc { animation: ringIn 1s var(--ease); }
.tr-ring-core { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; }
.tr-ring-core b { font-size: 1.15rem; font-weight: 800; line-height: 1; color: var(--ink); }
.tr-ring-den { font-size: .7em; color: var(--ink-faint); }
.tr-ring-core span { font-size: .56rem; font-weight: 800; text-transform: uppercase; letter-spacing: .06em; color: var(--ink-faint); margin-top: 2px; }
.tr-progress-meta b { display: block; font-weight: 800; font-size: 1.02rem; color: var(--ink); }
.tr-progress-meta span { font-size: .82rem; color: var(--ink-soft); line-height: 1.45; }
.tr-overall { display: none; } /* свёрнут в кольцо; элемент сохранён для JS */
.tr-stat-tiles { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 16px; }
.tr-tile { padding: 13px; border-radius: var(--r-md); background: linear-gradient(180deg, #fbfbff, #f3f4fd); border: 1px solid var(--line); text-align: center; }
.tr-tile b { display: block; font-size: 1.7rem; font-weight: 800; line-height: 1; background: linear-gradient(135deg, var(--g1), var(--g2)); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; }
.tr-tile.gold b { background: linear-gradient(135deg, var(--gold), #f97316); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; }
.tr-tile span { display: block; margin-top: 5px; font-size: .64rem; font-weight: 800; text-transform: uppercase; letter-spacing: .06em; color: var(--ink-faint); }
/* ── секции рейла ── */
.tr-rail-sec { padding: 16px 18px 18px; }
.tr-rail-hd { font-family: 'Manrope', sans-serif; font-size: .68rem; font-weight: 800; text-transform: uppercase; letter-spacing: .09em; color: var(--ink-faint); margin: 0 0 12px; display: flex; align-items: center; gap: 7px; }
.tr-rail-hd .ic { width: 14px; height: 14px; color: var(--g1); }
/* сегмент-контрол предмета */
.tr-subjects { display: flex; gap: 5px; padding: 4px; border-radius: 14px; background: rgba(99,102,241,.08); }
.tr-subjects:empty { display: none; }
.tr-subbtn { flex: 1; font: inherit; font-size: .82rem; font-weight: 800; cursor: pointer; padding: 8px 12px; border-radius: 10px; border: none; background: transparent; color: var(--ink-soft); transition: .16s var(--ease); }
.tr-subbtn:hover { color: var(--accent-ink); }
.tr-subbtn.on { color: var(--accent-ink); background: #fff; box-shadow: 0 4px 12px rgba(27,31,56,.1); }
/* список тем (вертикальная навигация) */
.tr-topics { display: flex; flex-direction: column; gap: 5px; }
.tr-chip {
font: inherit; font-family: 'Manrope', sans-serif; font-size: .9rem; font-weight: 700; cursor: pointer; color: var(--ink-soft); text-align: left;
display: flex; align-items: center; gap: 9px; width: 100%; padding: 11px 13px; border-radius: 13px;
border: 1px solid transparent; background: transparent; transition: .16s var(--ease);
}
.tr-chip::before { content: ''; width: 7px; height: 7px; border-radius: 50%; background: rgba(99,102,241,.3); flex: none; transition: .16s var(--ease); }
.tr-chip:hover { background: rgba(99,102,241,.07); color: var(--accent-ink); }
.tr-chip:hover::before { background: var(--g1); transform: scale(1.25); }
.tr-chip.on { color: #fff; border-color: transparent; background: linear-gradient(135deg, var(--g1), var(--g2)); box-shadow: 0 10px 22px -8px rgba(99,102,241,.6); }
.tr-chip.on::before { background: #fff; }
.tr-grade { display: inline-flex; align-items: center; justify-content: center; font-family: 'Manrope', sans-serif; font-size: .58rem; font-weight: 800; min-width: 17px; height: 17px; padding: 0 4px; border-radius: 99px; background: rgba(99,102,241,.14); color: var(--accent-ink); }
/* первый мета-элемент чипа (класс/звезда) — к правому краю; если есть оба — рядом */
.tr-chip > .tr-grade, .tr-chip > .tr-badge { margin-left: auto; }
.tr-chip > .tr-grade ~ .tr-badge { margin-left: 6px; }
.tr-chip.on .tr-grade { background: rgba(255,255,255,.26); color: #fff; }
.tr-badge { display: inline-flex; color: var(--ok); }
.tr-badge .ic { width: 15px; height: 15px; }
.tr-chip.on .tr-badge { color: #fff; }
.tr-badge-n { font-size: .66rem; font-weight: 800; color: var(--ink-faint); background: rgba(99,102,241,.12); border-radius: 99px; padding: 1px 7px; }
.tr-chip.on .tr-badge-n { color: #fff; background: rgba(255,255,255,.24); }
/* ═══════════ навыки текущей темы (над карточкой) ═══════════ */
.tr-skillbar { padding: 14px 18px; }
.tr-skillpanel-hd { font-family: 'Manrope', sans-serif; font-size: .68rem; font-weight: 800; text-transform: uppercase; letter-spacing: .09em; color: var(--ink-faint); margin-bottom: 11px; }
.tr-skills { display: flex; flex-wrap: wrap; gap: 7px; margin: 0; }
.tr-skills .tr-skill {
font: inherit; font-size: .84rem; font-weight: 700; cursor: pointer; font-family: 'Cambria Math', 'Times New Roman', serif;
padding: 8px 14px; border-radius: 11px; border: 1px solid var(--line); background: rgba(255,255,255,.7);
color: var(--ink-soft); transition: .16s var(--ease); display: inline-flex; align-items: center; gap: 6px;
}
.tr-skills .tr-skill:hover { border-color: var(--g1); color: var(--accent-ink); transform: translateY(-1px); }
.tr-skills .tr-skill.on { background: var(--accent-soft); border-color: var(--g1); color: var(--accent-ink); box-shadow: 0 6px 14px -6px rgba(99,102,241,.4); }
.tr-pool-info { font-size: .82rem; color: var(--ink-soft); align-self: center; margin-right: 6px; }
#tr-gen-btn { border-style: dashed; color: var(--accent-ink); }
/* ═══════════ карточка-задача (герой) ═══════════ */
.tr-card {
position: relative; overflow: hidden; background: var(--card); border: 1px solid var(--line);
border-radius: var(--r-lg); box-shadow: var(--sh-2); transition: box-shadow .3s var(--ease), transform .3s var(--ease);
}
.tr-card.tr-correct { box-shadow: 0 30px 70px -28px rgba(16,185,129,.6); animation: trPop .5s var(--ease); }
.tr-card.tr-wrong { animation: trShake .42s var(--ease); }
/* сцена-герой */
.tr-stage {
position: relative; overflow: hidden; text-align: center; color: #fff;
padding: 32px 28px 36px; transition: background .35s var(--ease);
padding: 30px 30px 38px; transition: background .35s var(--ease);
background: linear-gradient(135deg, #4f46e5 0%, #6d3aed 52%, #8b5cf6 100%);
}
.tr-stage::before {
content: ''; position: absolute; inset: 0; pointer-events: none; opacity: .55;
content: ''; position: absolute; inset: 0; pointer-events: none; opacity: .6;
background-image:
radial-gradient(440px 220px at 80% -25%, rgba(255,255,255,.20), transparent 60%),
radial-gradient(520px 260px at 82% -30%, rgba(255,255,255,.28), transparent 60%),
radial-gradient(420px 320px at 8% 130%, rgba(0,0,0,.18), transparent 60%),
linear-gradient(rgba(255,255,255,.07) 1px, transparent 1px),
linear-gradient(90deg, rgba(255,255,255,.07) 1px, transparent 1px);
background-size: 100% 100%, 22px 22px, 22px 22px;
background-size: 100% 100%, 100% 100%, 24px 24px, 24px 24px;
}
.tr-stage > * { position: relative; }
.tr-card.tr-correct .tr-stage { background: linear-gradient(135deg, #059669, #10b981 58%, #34d399); }
.tr-card.tr-wrong .tr-stage { background: linear-gradient(135deg, #dc2626, #ef4444 58%, #fb7185); }
.tr-work { padding: 24px 26px 28px; }
/* ── уровни сложности ── */
.tr-difficulty { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; justify-content: center; margin-bottom: 18px; }
.tr-diff-label { font-size: .72rem; font-weight: 800; color: var(--ink-faint); text-transform: uppercase; letter-spacing: .06em; margin-right: 2px; }
.tr-diff-btn { font: inherit; font-size: .8rem; font-weight: 700; cursor: pointer; padding: 5px 13px; border-radius: 99px; border: 1px solid rgba(99,102,241,.2); background: #fff; color: var(--ink-soft); transition: .14s var(--ease); }
.tr-diff-btn:hover { border-color: var(--g1); color: var(--accent-ink); }
.tr-diff-btn.on { color: #fff; border-color: transparent; background: linear-gradient(135deg, var(--g1), var(--g2)); box-shadow: 0 6px 14px rgba(99,102,241,.26); }
#tr-skill {
color: rgba(255,255,255,.75); font-family: 'Manrope', sans-serif; font-size: .72rem; font-weight: 800;
text-transform: uppercase; letter-spacing: .1em; margin-bottom: 14px;
color: rgba(255,255,255,.82); font-family: 'Manrope', sans-serif; font-size: .7rem; font-weight: 800;
text-transform: uppercase; letter-spacing: .12em; margin-bottom: 16px;
}
.tr-eq {
font-family: 'Cambria Math', 'Times New Roman', Georgia, serif;
font-size: clamp(1.9rem, 5.6vw, 2.7rem); font-weight: 600; letter-spacing: .01em;
color: #fff; text-align: center; padding: 2px 0; user-select: none; text-shadow: 0 2px 14px rgba(0,0,0,.18);
font-size: clamp(2rem, 4.2vw, 3rem); font-weight: 600; letter-spacing: .01em;
color: #fff; text-align: center; padding: 2px 0; user-select: none; text-shadow: 0 2px 18px rgba(0,0,0,.22);
}
.tr-eq .katex-display { margin: 0; }
.tr-eq .katex { font-size: 1.16em; color: #fff; }
/* текстовый prompt (проценты/упрощение) — компактнее уравнения, на сцене белым */
.tr-eq.tr-eq-text { font-family: 'Manrope', sans-serif; font-weight: 600; font-size: clamp(1.2rem, 3vw, 1.7rem); line-height: 1.45; color: #fff; }
.tr-inrow { display: flex; gap: 10px; align-items: stretch; max-width: 440px; margin: 0 auto; }
#tr-eqx { font-family: 'Cambria Math', serif; font-size: 1.5rem; font-weight: 600; color: var(--accent-ink); align-self: center; padding-left: 4px; }
.tr-work { padding: 24px 28px 28px; }
/* ── уровни сложности ── */
.tr-difficulty { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; justify-content: center; margin-bottom: 22px; }
.tr-diff-label { font-size: .68rem; font-weight: 800; color: var(--ink-faint); text-transform: uppercase; letter-spacing: .07em; margin-right: 4px; }
.tr-diff-btn { font: inherit; font-size: .8rem; font-weight: 800; cursor: pointer; padding: 6px 14px; border-radius: 99px; border: 1px solid var(--line); background: #fff; color: var(--ink-soft); transition: .14s var(--ease); }
.tr-diff-btn:hover { border-color: var(--g1); color: var(--accent-ink); }
.tr-diff-btn.on { color: #fff; border-color: transparent; background: linear-gradient(135deg, var(--g1), var(--g2)); box-shadow: 0 8px 16px -6px rgba(99,102,241,.5); }
/* строка ответа */
.tr-inrow { display: flex; gap: 10px; align-items: stretch; max-width: 460px; margin: 0 auto; }
#tr-eqx { font-family: 'Cambria Math', serif; font-size: 1.55rem; font-weight: 600; color: var(--accent-ink); align-self: center; padding-left: 4px; }
.tr-input {
flex: 1; min-width: 0; font: inherit; font-size: 1.2rem; font-weight: 600; text-align: center; color: var(--ink);
padding: 13px 16px; border-radius: 14px; border: 2px solid rgba(99,102,241,.22); background: #fff; outline: none; transition: .18s var(--ease);
flex: 1; min-width: 0; font: inherit; font-size: 1.25rem; font-weight: 700; text-align: center; color: var(--ink);
padding: 14px 16px; border-radius: 15px; border: 2px solid rgba(99,102,241,.22); background: #fbfbff; outline: none; transition: .18s var(--ease);
}
.tr-input::placeholder { color: var(--ink-faint); font-weight: 500; }
.tr-input:focus { border-color: var(--g1); box-shadow: 0 0 0 4px rgba(99,102,241,.16); }
.tr-input:focus { border-color: var(--g1); background: #fff; box-shadow: 0 0 0 4px rgba(99,102,241,.16); }
.tr-input:disabled { background: #f3f4fb; color: var(--ink-soft); }
.tr-btn {
font: inherit; font-weight: 700; cursor: pointer; border: none; border-radius: 14px;
padding: 13px 22px; transition: .18s var(--ease); display: inline-flex; align-items: center; gap: 7px;
}
.tr-btn { font: inherit; font-weight: 800; cursor: pointer; border: none; border-radius: 15px; padding: 14px 22px; transition: .18s var(--ease); display: inline-flex; align-items: center; gap: 7px; }
.tr-btn .ic { width: 17px; height: 17px; }
.tr-primary { color: #fff; background: linear-gradient(135deg, var(--g1), var(--g2)); box-shadow: 0 10px 24px rgba(99,102,241,.34); }
.tr-primary:hover { transform: translateY(-2px); box-shadow: 0 14px 30px rgba(99,102,241,.42); }
.tr-primary { color: #fff; background: linear-gradient(135deg, var(--g1), var(--g2)); box-shadow: 0 12px 26px -8px rgba(99,102,241,.7); }
.tr-primary:hover { transform: translateY(-2px); box-shadow: 0 16px 32px -8px rgba(99,102,241,.8); }
.tr-primary:active { transform: translateY(0); }
.tr-ghost { background: rgba(99,102,241,.08); color: var(--accent-ink); }
.tr-ghost:hover { background: rgba(99,102,241,.15); }
.tr-feedback {
width: fit-content; margin: 20px auto 2px; min-height: 28px; padding: 7px 16px; border-radius: 99px;
font-weight: 700; font-size: 1rem; display: flex; align-items: center; justify-content: center; gap: 9px; transition: .2s var(--ease);
}
.tr-feedback:empty { padding: 0; min-height: 0; }
/* клавиатура */
.tr-keypad { display: flex; flex-wrap: wrap; gap: 6px; justify-content: center; max-width: 460px; margin: 12px auto 0; }
.tr-key { font: inherit; font-size: .98rem; font-weight: 700; font-family: 'Cambria Math', serif; cursor: pointer; min-width: 42px; padding: 8px 11px; border-radius: 11px; border: 1px solid var(--line); background: linear-gradient(180deg, #fff, #f4f5fd); color: var(--accent-ink); box-shadow: 0 2px 0 rgba(99,102,241,.12); transition: .12s var(--ease); }
.tr-key:hover { border-color: var(--g1); background: var(--accent-soft); transform: translateY(-1px); }
.tr-key:active { transform: translateY(1px); box-shadow: none; }
.tr-key .ic { width: 16px; height: 16px; }
.tr-preview { text-align: center; margin: 14px auto 0; color: var(--ink-soft); }
.tr-preview:empty { display: none; }
.tr-preview .katex { font-size: 1.14em; }
.tr-feedback { width: fit-content; margin: 20px auto 2px; min-height: 28px; padding: 8px 18px; border-radius: 99px; font-weight: 800; font-size: 1rem; display: flex; align-items: center; justify-content: center; gap: 9px; transition: .2s var(--ease); }
.tr-feedback:empty { padding: 0; min-height: 0; margin: 0; }
.tr-feedback .ic { width: 19px; height: 19px; }
.tr-feedback.ok { color: var(--ok-ink); background: var(--ok-soft); }
.tr-feedback.bad { color: #b91c1c; background: var(--bad-soft); }
.tr-feedback.warn { color: var(--warn); background: #fef3c7; font-weight: 600; }
.tr-feedback.warn { color: var(--warn); background: #fef3c7; font-weight: 700; }
.tr-actions { display: flex; flex-wrap: wrap; gap: 9px; justify-content: center; margin-top: 16px; }
.tr-actions { display: flex; flex-wrap: wrap; gap: 9px; justify-content: center; margin-top: 18px; }
/* ── мат-клавиатура + live-превью (P8) ── */
.tr-keypad { display: flex; flex-wrap: wrap; gap: 6px; justify-content: center; max-width: 440px; margin: 10px auto 0; }
.tr-key { font: inherit; font-size: .95rem; font-weight: 700; font-family: 'Cambria Math', serif; cursor: pointer; min-width: 40px; padding: 7px 10px; border-radius: 10px; border: 1px solid rgba(99,102,241,.18); background: rgba(255,255,255,.8); color: var(--accent-ink); transition: .14s var(--ease); }
.tr-key:hover { border-color: var(--g1); background: var(--accent-soft); transform: translateY(-1px); }
.tr-key:active { transform: translateY(0); }
.tr-key .ic { width: 16px; height: 16px; }
.tr-preview { text-align: center; margin: 12px auto 0; color: var(--ink-soft); }
.tr-preview:empty { display: none; }
.tr-preview .katex { font-size: 1.12em; }
/* ── пошаговое решение / репетитор (P7) ── */
/* пошаговое решение / репетитор (P7) */
.tr-steps { display: flex; flex-direction: column; gap: 8px; margin-bottom: 16px; }
.tr-steps:empty { display: none; }
.tr-step-line { display: flex; align-items: center; gap: 12px; padding: 10px 14px; border-radius: 12px; background: linear-gradient(180deg, #f4fbf7, #ecf9f1); border: 1px solid rgba(16,185,129,.22); animation: trUp .25s var(--ease) both; }
.tr-step-ic { flex-shrink: 0; width: 22px; height: 22px; border-radius: 50%; background: var(--ok); color: #fff; display: inline-flex; align-items: center; justify-content: center; }
.tr-step-line { display: flex; align-items: center; gap: 12px; padding: 11px 15px; border-radius: 13px; background: linear-gradient(180deg, #f4fbf7, #ecf9f1); border: 1px solid rgba(16,185,129,.22); animation: trUp .25s var(--ease) both; }
.tr-step-ic { flex: none; width: 23px; height: 23px; border-radius: 50%; background: var(--ok); color: #fff; display: inline-flex; align-items: center; justify-content: center; }
.tr-step-ic .ic { width: 14px; height: 14px; }
.tr-step-tex { font-family: 'Cambria Math', serif; font-size: 1.12rem; color: var(--ink); }
.tr-step-tex { font-family: 'Cambria Math', serif; font-size: 1.14rem; color: var(--ink); }
.tr-solution {
margin-top: 22px; padding: 18px 20px; border-radius: 16px;
background: linear-gradient(180deg, #fbfbff, #f4f5fd); border: 1px solid rgba(99,102,241,.14);
animation: trUp .35s var(--ease) both;
}
.tr-solution h4 { margin: 0 0 12px; font-family: 'Manrope', sans-serif; font-size: .74rem; text-transform: uppercase; letter-spacing: .07em; color: var(--accent-ink); font-weight: 800; }
.tr-step { color: #334155; padding: 12px 0; }
/* решение — нумерованная лента */
.tr-solution { margin-top: 22px; padding: 20px 22px; border-radius: var(--r-md); background: linear-gradient(180deg, #fbfbff, #f4f5fd); border: 1px solid var(--line); animation: trUp .35s var(--ease) both; }
.tr-solution h4 { margin: 0 0 14px; font-family: 'Manrope', sans-serif; font-size: .72rem; text-transform: uppercase; letter-spacing: .08em; color: var(--accent-ink); font-weight: 800; }
.tr-step { color: #334155; padding: 13px 0; }
.tr-step + .tr-step { border-top: 1px dashed rgba(99,102,241,.2); }
.tr-step-note { display: block; color: var(--ink-soft); font-family: 'Manrope', sans-serif; font-size: .92rem; line-height: 1.6; margin-bottom: 7px; }
.tr-step-math { display: block; font-family: 'Cambria Math', serif; font-size: 1.18rem; color: var(--ink); margin-left: 30px; }
.tr-step-n { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; border-radius: 50%; background: linear-gradient(135deg, var(--g1), var(--g2)); color: #fff; font-family: 'Manrope', sans-serif; font-size: .72rem; font-weight: 800; margin-right: 9px; vertical-align: 1px; }
.tr-eq .katex-display { margin: 0; }
.tr-eq .katex { font-size: 1.12em; color: #fff; }
/* текстовый prompt (проценты/упрощение) — компактнее уравнения, на сцене белым */
.tr-eq.tr-eq-text { font-family: 'Manrope', sans-serif; font-weight: 600; font-size: clamp(1.15rem, 3.4vw, 1.6rem); line-height: 1.45; color: #fff; }
.tr-step-math { display: block; font-family: 'Cambria Math', serif; font-size: 1.2rem; color: var(--ink); margin-left: 31px; }
.tr-step-n { display: inline-flex; align-items: center; justify-content: center; width: 23px; height: 23px; border-radius: 50%; background: linear-gradient(135deg, var(--g1), var(--g2)); color: #fff; font-family: 'Manrope', sans-serif; font-size: .72rem; font-weight: 800; margin-right: 9px; vertical-align: 1px; }
/* выбор навыка внутри темы (внутри панели) */
.tr-skills { display: flex; flex-wrap: wrap; gap: 7px; margin: 0; }
.tr-skills .tr-skill {
font: inherit; font-size: .85rem; font-weight: 600; cursor: pointer; font-family: 'Cambria Math', 'Times New Roman', serif;
padding: 7px 13px; border-radius: 11px; border: 1px solid rgba(99,102,241,.16); background: rgba(255,255,255,.7);
color: var(--ink-soft); transition: .16s var(--ease); display: inline-flex; align-items: center;
}
.tr-skills .tr-skill:hover { border-color: var(--g1); color: var(--accent-ink); transform: translateY(-1px); }
.tr-skills .tr-skill.on { background: var(--accent-soft); border-color: var(--g1); color: var(--accent-ink); }
.tr-pool-info { font-size: .82rem; color: var(--ink-soft); align-self: center; margin-right: 6px; }
#tr-gen-btn { border-style: dashed; color: var(--accent-ink); }
/* ── итог сессии ── */
.tr-summary { position: relative; overflow: hidden; background: #fff; border: 1px solid var(--line); border-radius: var(--r-lg); padding: 32px 28px; box-shadow: var(--sh-2); text-align: center; animation: trPop .5s var(--ease); }
.tr-summary::before { content: ''; position: absolute; left: 0; right: 0; top: 0; height: 6px; background: linear-gradient(90deg, var(--gold), var(--g2)); }
.tr-sum-h { margin: 6px 0 20px; font-family: 'Manrope', sans-serif; font-weight: 800; font-size: 1.4rem; color: var(--ink); }
.tr-sum-row { display: inline-flex; flex-direction: column; align-items: center; margin: 0 20px 12px; }
.tr-sum-row b { font-size: 2rem; font-weight: 800; font-family: 'Manrope', sans-serif; line-height: 1.1; background: linear-gradient(135deg, var(--g1), var(--g2)); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; }
.tr-sum-row span { font-size: .7rem; color: var(--ink-faint); text-transform: uppercase; letter-spacing: .06em; font-weight: 800; }
.tr-sum-weak { margin: 10px 0 22px; color: var(--warn); font-weight: 700; font-size: .92rem; }
.tr-sum-weak.tr-sum-good { color: var(--ok-ink); }
/* бейджи прогресса на чипах */
.tr-badge { display: inline-flex; margin-left: 7px; color: var(--ok); vertical-align: middle; }
.tr-badge .ic { width: 14px; height: 14px; }
.tr-chip.on .tr-badge { color: #fff; }
.tr-badge-n { margin-left: 7px; font-size: .7rem; font-weight: 800; color: var(--ink-faint); background: rgba(99,102,241,.12); border-radius: 99px; padding: 1px 7px; }
.tr-chip.on .tr-badge-n { color: #fff; background: rgba(255,255,255,.24); }
.tr-note { text-align: center; color: var(--ink-faint); font-size: .78rem; line-height: 1.55; padding: 0 10px; }
/* ── общий прогресс (лёгкая геймификация) ── */
.tr-overall { display: inline-flex; align-items: center; gap: 8px; color: var(--accent-ink); font-size: .82rem; font-weight: 700; margin: 0 0 14px; padding: 6px 13px; border-radius: 99px; background: rgba(99,102,241,.08); }
.tr-overall:empty { display: none; }
/* ── модалка ── */
/* ── модалка (аналитика / авторинг) ── */
.tr-modal { position: fixed; inset: 0; z-index: 50; background: rgba(20,22,45,.55); backdrop-filter: blur(4px); display: flex; align-items: center; justify-content: center; padding: 20px; animation: trFade .2s ease; }
@keyframes trFade { from { opacity: 0; } to { opacity: 1; } }
.tr-modal-card { background: #fff; border-radius: 20px; max-width: 920px; width: 100%; max-height: 86vh; overflow: auto; box-shadow: var(--sh-lg); animation: trUp .3s var(--ease) both; }
.tr-modal-head { display: flex; align-items: center; justify-content: space-between; padding: 18px 22px; border-bottom: 1px solid rgba(99,102,241,.12); font-weight: 800; font-family: 'Manrope', sans-serif; font-size: 1.06rem; color: var(--ink); position: sticky; top: 0; background: #fff; z-index: 1; }
.tr-modal-head { display: flex; align-items: center; justify-content: space-between; padding: 18px 22px; border-bottom: 1px solid var(--line); font-weight: 800; font-family: 'Manrope', sans-serif; font-size: 1.06rem; color: var(--ink); position: sticky; top: 0; background: #fff; z-index: 1; }
.tr-modal-x { background: none; border: none; cursor: pointer; color: var(--ink-soft); padding: 5px; border-radius: 9px; transition: .15s; }
.tr-modal-x:hover { background: rgba(99,102,241,.1); color: var(--ink); }
.tr-modal-x .ic { width: 18px; height: 18px; }
#tr-an-body, #tr-tch-body { padding: 20px 22px; }
.tr-an-picker { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 16px; }
.tr-an-cls { font: inherit; font-size: .85rem; font-weight: 600; cursor: pointer; padding: 8px 14px; border-radius: 99px; border: 1px solid rgba(99,102,241,.2); background: #fff; color: var(--ink-soft); transition: .15s; }
.tr-an-cls { font: inherit; font-size: .85rem; font-weight: 700; cursor: pointer; padding: 8px 14px; border-radius: 99px; border: 1px solid rgba(99,102,241,.2); background: #fff; color: var(--ink-soft); transition: .15s; }
.tr-an-cls:hover, .tr-an-cls.on { border-color: var(--g1); color: var(--accent-ink); background: var(--accent-soft); }
.tr-an-empty { color: var(--ink-faint); padding: 24px; text-align: center; }
.tr-hm-wrap { overflow-x: auto; border-radius: 12px; border: 1px solid rgba(99,102,241,.12); }
.tr-hm-wrap { overflow-x: auto; border-radius: 12px; border: 1px solid var(--line); }
table.tr-hm { border-collapse: collapse; font-size: .8rem; width: 100%; }
table.tr-hm th, table.tr-hm td { border: 1px solid rgba(99,102,241,.1); padding: 7px 9px; text-align: center; white-space: nowrap; }
table.tr-hm th { background: #f6f7fd; color: var(--ink-soft); font-weight: 700; position: sticky; top: 0; }
.tr-hm-name { text-align: left !important; font-weight: 600; color: var(--ink); background: #f6f7fd; position: sticky; left: 0; }
.tr-hm-name { text-align: left !important; font-weight: 700; color: var(--ink); background: #f6f7fd; position: sticky; left: 0; }
.tr-hm-none { color: #cbd5e1; }
.tr-hm-cell { font-weight: 700; color: #334155; }
.tr-hm-cell .ic { width: 14px; height: 14px; color: #fff; }
@@ -249,48 +325,25 @@
.tr-form-hint { font-size: .8rem; color: var(--ink-soft); line-height: 1.5; }
.tr-form-err { color: #dc2626; font-size: .85rem; font-weight: 600; min-height: 18px; }
/* ── режим (умная тренировка) ── */
.tr-mode { display: flex; align-items: center; gap: 10px; margin-bottom: 6px; flex-wrap: wrap; }
.tr-mode-btn {
font: inherit; font-size: .85rem; font-weight: 700; cursor: pointer; display: inline-flex; align-items: center; gap: 7px;
padding: 9px 15px; border-radius: 99px; border: 1px solid rgba(99,102,241,.18); background: rgba(255,255,255,.7); color: var(--ink-soft); transition: .16s var(--ease);
/* ── адаптив ── */
@media (max-width: 1080px) {
.tr-grid { grid-template-columns: 1fr; }
.tr-rail { position: static; }
.tr-progress-card .tr-stat-tiles { grid-template-columns: 1fr 1fr 1fr 1fr; }
.tr-topics { flex-direction: row; flex-wrap: wrap; }
.tr-chip { width: auto; }
.tr-chip > .tr-grade, .tr-chip > .tr-badge { margin-left: 0; }
}
.tr-mode-btn .ic { width: 16px; height: 16px; }
.tr-mode-btn:hover { border-color: var(--g1); color: var(--accent-ink); transform: translateY(-1px); }
.tr-mode-btn.on { color: #fff; border-color: transparent; background: linear-gradient(135deg, var(--g1), var(--g2)); box-shadow: 0 8px 20px rgba(99,102,241,.32); }
.tr-session { font-size: .82rem; font-weight: 800; color: var(--accent-ink); padding: 4px 12px; border-radius: 99px; background: rgba(99,102,241,.1); }
.tr-session:empty { display: none; }
/* конструктор — отдельный (янтарный) цвет, только админ */
.tr-admin-btn { color: #fff; border-color: transparent; background: linear-gradient(135deg, #f59e0b, #f97316); box-shadow: 0 8px 20px rgba(245,158,11,.32); }
.tr-admin-btn:hover { color: #fff; border-color: transparent; background: linear-gradient(135deg, #f59e0b, #f97316); transform: translateY(-1px); }
/* ── итог сессии ── */
.tr-summary {
position: relative; overflow: hidden; background: #fff; border: 1px solid rgba(99,102,241,.1); border-radius: var(--r-lg);
padding: 30px 26px; box-shadow: var(--sh); text-align: center; animation: trPop .5s var(--ease);
}
.tr-summary::before { content: ''; position: absolute; left: 0; right: 0; top: 0; height: 6px; background: linear-gradient(90deg, var(--gold), var(--g2)); }
.tr-sum-h { margin: 6px 0 18px; font-family: 'Manrope', sans-serif; font-weight: 800; font-size: 1.35rem; color: var(--ink); }
.tr-sum-row { display: inline-flex; flex-direction: column; align-items: center; margin: 0 18px 12px; }
.tr-sum-row b { font-size: 1.9rem; font-weight: 800; font-family: 'Manrope', sans-serif; line-height: 1.1; background: linear-gradient(135deg, var(--g1), var(--g2)); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; }
.tr-sum-row span { font-size: .72rem; color: var(--ink-faint); text-transform: uppercase; letter-spacing: .06em; font-weight: 700; }
.tr-sum-weak { margin: 10px 0 20px; color: var(--warn); font-weight: 600; font-size: .92rem; }
.tr-sum-weak.tr-sum-good { color: var(--ok-ink); }
/* ── статистика ── */
.tr-stats { display: flex; gap: 28px; justify-content: center; margin: 24px 0 4px; }
.tr-stat { text-align: center; }
.tr-stat b { display: block; font-size: 1.7rem; font-weight: 800; font-family: 'Manrope', sans-serif; line-height: 1.1; background: linear-gradient(135deg, var(--g1), var(--g2)); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; }
.tr-stat span { font-size: .72rem; color: var(--ink-faint); text-transform: uppercase; letter-spacing: .06em; font-weight: 700; }
.tr-note { margin-top: 26px; text-align: center; color: var(--ink-faint); font-size: .78rem; line-height: 1.5; }
@media (max-width: 560px) {
.tr-wrap { padding: 22px 14px 70px; }
.tr-card { padding: 26px 18px 24px; }
@media (max-width: 620px) {
.tr-wrap { padding: 16px 14px 70px; }
.tr-topbar2 { top: 8px; padding: 12px; }
.tr-h1 { font-size: 1.16rem; }
.tr-modes { gap: 7px; }
.tr-work { padding: 20px 16px 22px; }
.tr-stage { padding: 26px 18px 30px; }
.tr-progress-card .tr-stat-tiles { grid-template-columns: 1fr 1fr; }
.tr-inrow { flex-wrap: wrap; }
.tr-inrow .tr-btn { width: 100%; justify-content: center; }
.tr-stats { gap: 22px; }
}
@media (prefers-reduced-motion: reduce) {
* { animation-duration: .001ms !important; transition-duration: .001ms !important; }
@@ -302,29 +355,141 @@
<aside class="sidebar" id="app-sidebar"></aside>
<main class="sb-content">
<div class="tr-wrap">
<div class="tr-head">
<h1 class="tr-h1">Тренажёр<span class="tr-pill" id="tr-subject">Алгебра · 78 класс</span></h1>
<div class="tr-sub">Задачи генерируются автоматически и проверяются мгновенно. Решай по одной — бесконечно.</div>
<!-- ════ верхняя панель (стекло, плавающая) ════ -->
<div class="tr-topbar2">
<div class="tr-brand">
<span class="tr-brand-mark"><svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3l1.8 4.6L18.5 9l-4.7 1.4L12 15l-1.8-4.6L5.5 9l4.7-1.4z"/><path d="M19 14l.7 1.8L21.5 16.5l-1.8.7L19 19l-.7-1.8L16.5 16.5l1.8-.7z"/></svg></span>
<div>
<h1 class="tr-h1">Тренажёр</h1>
<div class="tr-brand-sub"><span class="tr-pill" id="tr-subject">Алгебра · 78 класс</span></div>
</div>
</div>
<div class="tr-modes">
<div class="tr-smart on" id="tr-smart-btn" role="switch" aria-checked="true" tabindex="0">
<span class="tr-smart-txt">
<svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3l1.8 4.6L18.5 9l-4.7 1.4L12 15l-1.8-4.6L5.5 9l4.7-1.4z"/><path d="M19 14l.7 1.8L21.5 16.5l-1.8.7L19 19l-.7-1.8L16.5 16.5l1.8-.7z"/></svg>
Умная тренировка
</span>
<span class="tr-switch"></span>
</div>
<span class="tr-session" id="tr-session"></span>
<button class="tr-mode-btn" id="tr-analytics-btn" type="button" style="display:none">
<svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 3v18h18"/><rect x="7" y="10" width="3" height="7"/><rect x="13" y="6" width="3" height="11"/></svg>
Аналитика класса
</button>
<button class="tr-mode-btn tr-admin-btn" id="tr-builder-btn" type="button" style="display:none">
<svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 4V2M15 16v-2M8 9h2M20 9h2M17.8 11.8 19 13M15 9h.01M17.8 6.2 19 5M3 21l9-9M12.2 6.2 11 5"/></svg>
Конструктор
</button>
</div>
</div>
<div class="tr-overall" id="tr-overall"></div>
<!-- ════ двухпанельная сетка ════ -->
<div class="tr-grid">
<div class="tr-mode">
<button class="tr-mode-btn on" id="tr-smart-btn" type="button">
<svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3l1.8 4.6L18.5 9l-4.7 1.4L12 15l-1.8-4.6L5.5 9l4.7-1.4z"/><path d="M19 14l.7 1.8L21.5 16.5l-1.8.7L19 19l-.7-1.8L16.5 16.5l1.8-.7z"/></svg>
Умная тренировка
</button>
<span class="tr-session" id="tr-session"></span>
<button class="tr-mode-btn" id="tr-analytics-btn" type="button" style="display:none;margin-left:auto">
<svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 3v18h18"/><rect x="7" y="10" width="3" height="7"/><rect x="13" y="6" width="3" height="11"/></svg>
Аналитика класса
</button>
<button class="tr-mode-btn tr-admin-btn" id="tr-builder-btn" type="button" style="display:none">
<svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 4V2M15 16v-2M8 9h2M20 9h2M17.8 11.8 19 13M15 9h.01M17.8 6.2 19 5M3 21l9-9M12.2 6.2 11 5"/></svg>
Конструктор
</button>
<!-- ── ЛЕВЫЙ РЕЙЛ ── -->
<aside class="tr-rail">
<div class="tr-panel tr-progress-card">
<div class="tr-ring-row">
<div class="tr-ring">
<svg width="92" height="92" viewBox="0 0 120 120">
<circle cx="60" cy="60" r="54" fill="none" stroke="rgba(99,102,241,.14)" stroke-width="11"/>
<circle id="tr-ring-arc" cx="60" cy="60" r="54" fill="none" stroke="url(#trrg)" stroke-width="11" stroke-linecap="round" stroke-dasharray="339.292" stroke-dashoffset="339.292" transform="rotate(-90 60 60)"/>
<defs><linearGradient id="trrg" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#6366f1"/><stop offset="1" stop-color="#8b5cf6"/></linearGradient></defs>
</svg>
<div class="tr-ring-core"><b><span id="tr-ring-num">0</span><span class="tr-ring-den" id="tr-ring-den"></span></b><span>навыков</span></div>
</div>
<div class="tr-progress-meta">
<b>Мастерство</b>
<span>Осваивай навыки — кольцо растёт с каждой освоенной темой.</span>
<div class="tr-overall" id="tr-overall"></div>
</div>
</div>
<div class="tr-stat-tiles">
<div class="tr-tile"><b id="tr-solved">0</b><span>решено</span></div>
<div class="tr-tile gold"><b id="tr-streak">0</b><span>серия</span></div>
</div>
</div>
<div class="tr-panel tr-rail-sec" id="tr-subjects-sec">
<div class="tr-rail-hd"><svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 7h18M3 12h18M3 17h18"/></svg>Предмет</div>
<div class="tr-subjects" id="tr-subjects"></div>
</div>
<div class="tr-panel tr-rail-sec">
<div class="tr-rail-hd"><svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20M4 4.5A2.5 2.5 0 0 1 6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5z"/></svg>Темы</div>
<div class="tr-topics" id="tr-topics"></div>
</div>
</aside>
<!-- ── ОСНОВНАЯ ОБЛАСТЬ ── -->
<section class="tr-main">
<div class="tr-panel tr-skillbar">
<div class="tr-skillpanel-hd" id="tr-skillpanel-hd">Навыки</div>
<div class="tr-skills" id="tr-skills"></div>
</div>
<div class="tr-card" id="tr-card">
<div class="tr-stage">
<div class="tr-skill" id="tr-skill"></div>
<div class="tr-eq" id="tr-eq"></div>
</div>
<div class="tr-work">
<div class="tr-difficulty" id="tr-difficulty"></div>
<div id="tr-answerbox">
<div class="tr-inrow">
<span class="tr-eqx" id="tr-eqx">x =</span>
<input class="tr-input" id="tr-input" type="text" inputmode="text" autocomplete="off"
placeholder="ответ" aria-label="Ваш ответ"/>
<button class="tr-btn tr-primary" id="tr-check" type="button">Проверить</button>
</div>
<div class="tr-keypad" id="tr-keypad"></div>
<div class="tr-preview" id="tr-preview"></div>
<div class="tr-feedback" id="tr-feedback"></div>
</div>
<div id="tr-stepbox" style="display:none">
<div class="tr-steps" id="tr-steps"></div>
<div class="tr-inrow">
<input class="tr-input" id="tr-stepin" type="text" autocomplete="off"
placeholder="следующий шаг, напр. 3x = 15" aria-label="Следующий шаг"/>
<button class="tr-btn tr-primary" id="tr-stepcheck" type="button">Шаг</button>
</div>
<div class="tr-keypad" id="tr-keypad2"></div>
<div class="tr-preview" id="tr-prev2"></div>
<div class="tr-feedback" id="tr-stepfb"></div>
</div>
<div class="tr-actions">
<button class="tr-btn tr-ghost" id="tr-step-toggle" type="button" style="display:none">
<svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M8 6h13M8 12h13M8 18h13M3 6h.01M3 12h.01M3 18h.01"/></svg>
Решить по шагам
</button>
<button class="tr-btn tr-ghost" id="tr-hint" type="button">
<svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 18h6M10 22h4M12 2a7 7 0 0 0-4 12.7c.6.5 1 1.3 1 2.1h6c0-.8.4-1.6 1-2.1A7 7 0 0 0 12 2Z"/></svg>
Подсказка
</button>
<button class="tr-btn tr-ghost" id="tr-solve" type="button">
<svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2zM22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"/></svg>
Решение
</button>
<button class="tr-btn tr-ghost" id="tr-skip" type="button">
<svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 4 12 8-12 8z"/><path d="M20 4v16"/></svg>
Другая
</button>
</div>
<div class="tr-solution" id="tr-solution" style="display:none"></div>
</div>
</div>
<div class="tr-summary" id="tr-summary" style="display:none"></div>
<div class="tr-note" id="tr-note"></div>
</section>
</div>
<!-- модалки (position:fixed — местоположение в потоке не важно) -->
<div class="tr-modal" id="tr-analytics" style="display:none">
<div class="tr-modal-card">
<div class="tr-modal-head">
@@ -348,81 +513,6 @@
<div id="tr-tch-body"></div>
</div>
</div>
<div class="tr-subjects" id="tr-subjects"></div>
<div class="tr-topbar">
<span class="tr-nav-eyebrow">Тема</span>
<div class="tr-topics" id="tr-topics"></div>
</div>
<div class="tr-skillpanel">
<div class="tr-skillpanel-hd" id="tr-skillpanel-hd">Навыки</div>
<div class="tr-skills" id="tr-skills"></div>
</div>
<div class="tr-card">
<div class="tr-stage">
<div class="tr-skill" id="tr-skill"></div>
<div class="tr-eq" id="tr-eq"></div>
</div>
<div class="tr-work">
<div class="tr-difficulty" id="tr-difficulty"></div>
<div id="tr-answerbox">
<div class="tr-inrow">
<span class="tr-eqx" id="tr-eqx">x =</span>
<input class="tr-input" id="tr-input" type="text" inputmode="text" autocomplete="off"
placeholder="ответ" aria-label="Ваш ответ"/>
<button class="tr-btn tr-primary" id="tr-check" type="button">Проверить</button>
</div>
<div class="tr-keypad" id="tr-keypad"></div>
<div class="tr-preview" id="tr-preview"></div>
<div class="tr-feedback" id="tr-feedback"></div>
</div>
<div id="tr-stepbox" style="display:none">
<div class="tr-steps" id="tr-steps"></div>
<div class="tr-inrow">
<input class="tr-input" id="tr-stepin" type="text" autocomplete="off"
placeholder="следующий шаг, напр. 3x = 15" aria-label="Следующий шаг"/>
<button class="tr-btn tr-primary" id="tr-stepcheck" type="button">Шаг</button>
</div>
<div class="tr-keypad" id="tr-keypad2"></div>
<div class="tr-preview" id="tr-prev2"></div>
<div class="tr-feedback" id="tr-stepfb"></div>
</div>
<div class="tr-actions">
<button class="tr-btn tr-ghost" id="tr-step-toggle" type="button" style="display:none">
<svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M8 6h13M8 12h13M8 18h13M3 6h.01M3 12h.01M3 18h.01"/></svg>
Решить по шагам
</button>
<button class="tr-btn tr-ghost" id="tr-hint" type="button">
<svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 18h6M10 22h4M12 2a7 7 0 0 0-4 12.7c.6.5 1 1.3 1 2.1h6c0-.8.4-1.6 1-2.1A7 7 0 0 0 12 2Z"/></svg>
Подсказка
</button>
<button class="tr-btn tr-ghost" id="tr-solve" type="button">
<svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2zM22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"/></svg>
Решение
</button>
<button class="tr-btn tr-ghost" id="tr-skip" type="button">
<svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 4 12 8-12 8z"/><path d="M20 4v16"/></svg>
Другая
</button>
</div>
<div class="tr-solution" id="tr-solution" style="display:none"></div>
</div>
</div>
<div class="tr-summary" id="tr-summary" style="display:none"></div>
<div class="tr-stats">
<div class="tr-stat"><b id="tr-solved">0</b><span>решено</span></div>
<div class="tr-stat"><b id="tr-streak">0</b><span>серия</span></div>
</div>
<div class="tr-note" id="tr-note"></div>
</div>
</main>
</div>
@@ -943,6 +1033,11 @@
solvedTotal += (p.solved || 0);
if (p.mastered) mastered++;
}
// премиум: кольцо мастерства в рейле (отражает уже посчитанные mastered/total)
var _total = gens.length || 1, _arc = $('tr-ring-arc');
if (_arc) { var _C = 339.292, _f = Math.max(0, Math.min(1, mastered / _total)); _arc.style.strokeDashoffset = (_C * (1 - _f)).toFixed(1); }
var _rn = $('tr-ring-num'); if (_rn) _rn.textContent = mastered;
var _rd = $('tr-ring-den'); if (_rd) _rd.textContent = '/' + _total;
var el = $('tr-overall');
if (el) el.textContent = solvedTotal ? ('Освоено навыков: ' + mastered + ' из ' + gens.length + ' · решено всего: ' + solvedTotal) : '';
}