1. Финал главы:
- После buildAssessment() повторный renderMath(body) — захватывает формулы из квиза
- Дополнительный renderMath через 300ms — на случай если KaTeX не успел загрузиться
2. Мета-теги Cache-Control no-cache, no-store, must-revalidate / Pragma no-cache / Expires 0 — чтобы прежняя версия страницы не зависала в кэше браузера (поэтому и шапка не обновлялась)
Было: init() синхронно вызывал buildP1...buildFinal — 7 секций × ~500 строк HTML, плюс KaTeX renderMathInElement сканировал весь body. На медленном CPU могло подвисать на 2-5 секунд.
Стало: init() строит только §1 (через goTo('p1')). Остальные секции строятся лениво при первом goTo(id) — кэшируются в BUILT Set.
Профит: первая отрисовка в 7 раз быстрее. KaTeX-рендер тоже только для активной секции.
Прошлый коммит хранил название в Map, но старые записи в LocalStorage (Set из id-ов) подгружались с id в качестве текста — пользователь по-прежнему видел 'ring36', 'start'.
Фикс: словарь ACH_LABELS (id → название) применяется при загрузке как fallback:
- старый формат массив id-ов: id → ACH_LABELS[id]
- новый формат объект {id:text}: если text === id, используем ACH_LABELS[id]
Теперь при следующем открытии учебника старые достижения автоматически получат красивые названия.
Было: 'ring36', 'start' — внутренние id-ы достижений
Стало: 'Начало пути по корням!', 'Нашёл сторону ринга'
STATE.achievements теперь Map(id → text). Старый формат массива id-ов читается с обратной совместимостью (id используется как текст). При сохранении пишется как объект.
Убраны:
- <section class="intro"> с заголовком 'Изучаем 3 раздела физики' (там всё ещё видна была старая надпись 'Автор: Исаченкова Л. А.')
- <section class="info-grid"> с 4 info-карточками (Интерактив в каждом §, Прогресс сохраняется, Формулы — KaTeX, Светлая и тёмная тема)
Hub теперь чище: шапка → общий прогресс → 3 карточки разделов → подвал.
- Миграция 011: UPDATE textbooks SET author='' (все 4 записи)
- algebra_8.html: убрано из <title> и футера
- physics_8.html (hub): убрано из title/header/intro/footer, заменено на LearnSpace
- physics8_*.html (3 файла): убраны все вхождения '· Исаченкова' в подписях §
- physics_9.html: убраны все вхождения '· Исаченкова' в подписях §
- chemistry_9.html: убраны 3 упоминания '· Шиманович' в подписях
В каталоге /textbooks автор больше не отображается под названием (так как поле пустое).
Подход: hub-страница, а не слияние файлов.
Проблема: 3 готовых файла-главы (thermal/electro/optics) занимали 3 карточки в каталоге. Физическое слияние в один файл = 800КБ+, конфликты CSS/JS namespaces, риск сломать KaTeX.
Решение:
- Создан frontend/textbooks/physics_8.html — hub-страница с 3 крупными карточками-разделами (амбер/синий/фиолетовый)
- Карточки ссылаются напрямую на /textbooks/physics8_thermal.html и т.д. (express.static уже отдаёт эти файлы)
- Из каталога /textbooks теперь видна ОДНА карточка «Физика 8», sort_order 4
- Hub-страница показывает прогресс по каждой главе через LocalStorage (best-effort парсинг)
- Header «К каталогу», переключатель темы синхронизирован с главами
Миграция 010: удалила 3 прежние записи (physics-8-thermal/electro/optics), добавила физическо-8 → physics_8.html, para_count=40.
Эмодзи в hub не используются (только inline SVG). Эмодзи в файлах глав остались — это контент.
Интегрирован готовый интерактивный учебник по физике 8 класса (40 параграфов, разбитых на 3 файла):
- physics8_thermal.html (§1–11) — Тепловые явления
- physics8_electro.html (§12–31) — Электрические явления
- physics8_optics.html (§32–40) — Световые явления
Все три самодостаточные (KaTeX через CDN, шрифт Outfit, dark mode, анимации, эмодзи).
Автор: Исаченкова Л. А.
Миграция 009 регистрирует три новых textbook-записи:
- physics-8-thermal (amber, sort 4)
- physics-8-electro (blue, sort 5)
- physics-8-optics (violet, sort 6)
После миграции доступны через /textbook/physics-8-thermal и т.д. и видны в каталоге /textbooks.
Pre-commit hook на эмодзи обойден --no-verify по разрешению пользователя: эмодзи здесь являются частью авторского контента учебника (визуальные маркеры разделов: тепловые/электрические/оптические явления), а не нашим кодом.
Боковая шпаргалка строилась обычным HTML (Unicode-символы √ ≤ ⊂), формулы не оформлялись как настоящие математические.
Фикс:
- Все формулы в SIDEBARS обёрнуты $-делимитерами KaTeX (\sqrt, \mathbb, \cap, \subset, \Leftrightarrow и т.д.)
- После buildSidebar() вызывается renderMathInElement(box) для встроенного рендера
- Учебник теперь показывает корни и множества в правильной типографике
Причина: .geo-acc и .dyn-acc имели overflow:hidden и без flex:0 0 auto. В flex-колонке родительская панель сжимала их при раскрытии, и контент клипировался или наезжал на соседние секции.
Фикс:
- Убран overflow:hidden — контент не клипируется
- flex: 0 0 auto — секция занимает свою натуральную высоту без сжатия
- Border-radius на summary отдельно (без overflow:hidden иначе углы тела торчат)
- Open-состояние: верхние углы скруглены, нижние квадратные (стыкуются с body)
Причина: .geo-tool-btn имел white-space:nowrap, длинные подписи ('Подобие (гомотетия)', 'Параллельность', 'Средняя линия') вылезали за пределы 1fr-ячейки 2-колоночного грида.
Фикс:
- white-space:normal + word-break:break-word + line-height 1.15 в .geo-panel-modern → текст переносится в 2 строки
- overflow-x:hidden на саму панель — гарантия что горизонтальный скролл не появится
- min-width:0 на грид и его ячейки — иначе текст не сжимался
- 'Подобие (гомотетия)' → 'Подобие' (полное название осталось в title)
Было: 13 секций подряд (включая дублирующийся заголовок 'Построения'), 35 кнопок одним сплошным длинным списком, ширина 210px, шрифт .73rem — приходилось много скроллить, инструменты сложно находить.
Стало:
- Ширина 210px → 260px
- Sticky quick-bar сверху с 4 самыми частыми: Выбор / Точка / Отрезок / Круг (фиолетовая подсветка, всегда видна)
- Все остальные инструменты — в 7 collapsible-секциях <details>:
- Линии (Прямая, Луч)
- Фигуры (Треугольник, Четырёхугольник, Многоугольник, Параллелограмм, n-угольник + control)
- Построения (Середина, Пересечение, ⊥ биссектриса, ∠ биссектриса, ∥ прямая, ⊥ прямая, Основание, Касательные, Диагонали, Описанная, Вписанная) — теперь без дублирующегося заголовка
- Треугольник (Высота, Медиана, Центроид, Ортоцентр, Средняя линия, Фалес)
- Преобразования (Симметрия, Перенос, Подобие + k-control)
- Измерения и ГМТ (Длина, Угол, Площадь, ГМТ, Т. на отрезке, Т. на круге)
- Метки (Штрихи, Дуги, Параллельность)
- Шрифт .73rem → .78rem
- Параметры/Объектов/Очистить/Задачник остались внизу без сворачивания
Причины 'один луч, работает неправильно':
1. tangDir = efVec/efLen давал тангенциальное направление, при котором преломлённый луч внутри призмы уходил вниз в основание (sFace > 1), а не в выходную правую грань → внешнего луча не было
2. По умолчанию был включён моно-режим — пользователь видел один луч без дисперсии
Исправлено:
- tangDir = 90° по часовой от efNorm (efNorm.y, -efNorm.x) — теперь падающий луч при стандартных углах попадает в выходную грань правильно
- При первом входе в режим призмы window._obWhiteLight = true → 6 спектральных лучей сразу видны (расхождение цветов)
- Добавлена кнопка 'Белый / Моно' в панель призмы для переключения
PrismSim был сломан в 3 местах:
1. incDir строился с -efNorm (наружу), а не efNorm (внутрь) → падающий луч рисовался не с той стороны
2. cosI = -(incDir·efNorm) с уже-перевёрнутым incDir давал противоречивые знаки
3. Формула Снелла rDir имела + вместо - на коэффициенте efNorm
Итог: при incAngle≈0 преломлённый луч уходил в обратную сторону, точка пересечения с выходной гранью не находилась (tRay<0), и наружный луч с дисперсией не отрисовывался → визуально 'призма не работает'.
Теперь incDir — направление распространения (внутрь призмы), cosI = +(incDir·efNorm), формула: r = (1/n)·l + (cosR − cosI/n)·n
- Расширена с 248px до 300px
- Mode selector: 5 в ряд → 2 ряда (Песочница/Классика, I/II/III законы) с понятными названиями + tooltips
- Sandbox-панель: секции Мир/Отображение/Время/Пресеты обёрнуты в <details> (collapsible) с акцентом-стрелкой
- 21 пресет сгруппирован по 5 категориям: Базовые/Столкновения/Пружины и осцилляторы/Маятники и блоки/Горки и стопки
- Шрифты увеличены с .65-.72rem до .78-.82rem (mode buttons, tool grid, checkboxes, presets, подсказки)
- Newton-панель: сцены A/B/C, классические Атвуд/Наклон/Качение — кнопки крупнее
- Topbar ctrl-dynamics: .65rem → .78rem для всех инструментов и сцен
- Подсказки (help boxes) перерисованы с большим контрастом и шрифтом
- Новый CSS-блок .dyn-panel-modern с детализированным acc-styling
- Менделеев: clamp() для font-size символа элемента (2.4rem..4.4rem) + padding-top 28px → символ не обрезается на узких панелях
- Качественные реакции: в Свободно/Тренировке Проб1-4 содержат известные ионы (видна подпись), в Тренировке Образец — отдельный неизвестный; в Экзамене можно переключаться между пробирками и ответить отдельно для каждой (verdict сохраняется)
- Стехиометрия: непрерывный анимационный цикл — волна на поверхности жидкости, пузырьки в газах/растворах, пульсирующая красная рамка + ЛИМИТ-лейбл у лимитирующего реагента, искры вдоль стрелки реакции, glow на стрелке во время реакции
- Стехиометрия → 4-шаговый wizard (Реакция → Количества → Лимит → Продукты), KaTeX в displayMode, крупные карточки
- Качественные реакции → центрированная сцена с большой пробиркой, журнал справа 290px, нижняя полка реагентов, убран список ионов
- Контраст: основной текст rgba(.92), вторичный (.7), шрифты от .85rem
ВОЛНА A — Расширенная база данных:
- Новый файл _periodic_data.js (~70 KB): PERIODIC_EXT_DATA + ISOTOPES + SPECTRA
- 30 элементов полностью (H..Au): радиусы, ионизация, теплоёмкость, теплопроводность,
кристалл, распространённость, биология, токсичность, пламя, применения, история,
этимология, минералы, типичные реакции
- 9 элементов с минимумом (Sc, Ti, V, As, Se, Kr, Hg, Pb, I)
- 60 изотопов в 20 элементах (включая ¹³¹I, ¹³⁷Cs, ⁶⁰Co, ⁹⁰Sr, ¹⁴C, ³H, U-235/238)
- 43 эмиссионных линий для 8 элементов (H, He, Li, Na, K, Ne, Ar, Hg)
ВОЛНА B — Визуальные режимы:
- Heatmap по 9 свойствам (En, mass, density, melt, boil, discovered + расширенные)
с jet-colormap, lin/log toggle, легендой, анимацией 400ms
- 3D-таблица через Three.js: bar / wave / stack modes, orbit camera, raycaster hover
- Морф между формами таблицы: standard / long (32-col, f-block inline) / short (8-col)
с staggered fade-in 800ms
- Тренды стрелками: радиус / ЭО / ИЕ / металличность с градиентными arrows
ВОЛНА C — Карточка элемента 2.0 (11 табов):
- Обзор (hero 96px символ + Z + категория-бейдж + quick stats)
- Свойства (17-row таблица расширенных параметров)
- Электроника (Bohr + статичная конфигурация)
- Изотопы (список + bar chart + weighted average mass)
- История (timeline + этимология)
- Применения (15 SVG иконок-сфер + текст)
- Биология (badge: macro/micro/trace/toxic/inert/radioactive)
- Минералы (формулы)
- Спектр (rainbow 380-780nm + линии эмиссии)
- Пламя (цвет + название)
- Реакции (типовые уравнения по типу элемента)
- Hero header с цветом типа; smooth fade transitions между табами
ВОЛНА D — Интерактивные режимы:
- Бинарные соединения: drag 2 элемента → формула (NaCl, Fe₂O₃) + тип связи (ΔЭО)
- Сравнить до 4 элементов: side-by-side + min/max highlight + chart
- Ряд активности металлов: 28 элементов от Li до Au, разделитель H
- Таблица Менделеева 1869: 63 элемента + 4 предсказанных (Ga, Sc, Ge, Tc)
с popup «предсказано vs реально»
- Таймлайн открытий 1660-2024 с slider и auto-play
ВОЛНА G — Электронные конфигурации углубление:
- Orbital filling diagram: квадратики с электронами по Хунду/Паули, glow на валентном
- Aufbau diagram с slider Z 1-118 и анимированным указателем порядка заполнения
- Квантовые числа (n, l, m_l, m_s) — hover на электрон → tooltip
- Возбуждение электронов: click на электрон в Bohr → выбор уровня → анимация
перехода с фотоном (цвет ∝ длине волны через ΔE = 13.6 eV × ...)
periodic.js: 750 → 3239 строк. Все 5 волн ADDITIVE — старая база сохранена.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Hydrostatics использовал P_SANDBOX как у dynamics — оба показывали одну
и ту же карточку с блоком/шаром и силами. Добавлен P_HYDRO: мензурка
с погруженным телом + F_A, U-образный манометр с Δh, сообщающиеся сосуды.
Геометрия (планиметрия):
- Живые измерения как объекты: длина / угол / площадь — auto-recompute, draggable chips
- Инструмент ГМТ: sweep мовера через параметр, рисует кривую места точек
- Новые типы точек: on_segment (скользит по отрезку, _t), on_circle (по окружности, _theta)
- Toolbar: «Длина», «Угол», «Площадь», «ГМТ», «На отрезке», «На окружности»
Электромагнитные поля (emfield):
- Merge magnetic.js + coulomb.js в один EMFieldSim с 3 режимами (E / B / комбинированное)
- Унифицированный pipeline: colormap, field lines, vectors, equipotentials, flux loop, test particle
- Combined-режим: полная сила Лоренца F=q(E+v×B)
- Backward compat: #coulomb и #magnetic хеши и ?sim= параметры редиректят в emfield
- Удалены: magnetic.js, coulomb.js. Добавлен: emfield.js
Бросок тела (projectile):
- Режим целей: 3 окна, hit-детекция, HUD «Цели: N/M / Попыток: K»
- Графики x(t), y(t), vx(t), vy(t) — 2×2 Canvas 2D, real-time
- Двойной бросок: одновременно 2 траектории для сравнения (cyan vs gold)
UI fixes (по результатам аудита):
- Заменены emoji/unicode на inline SVG .ic: switch ⌇, spring 〜 (5 мест), download ⬇ (2), camera 📷
- Убраны декоративные символы ☉ ○ из geometry tool labels
- Добавлены THEORY entries: geometry, hydrostatics (раньше показывали fallback)
- Стандартизирована ширина panel для sim-proj и sim-coll (240px)
- waves перенесён в физический блок SIMS catalog (был после биологии)
- Очищен дефолтный sim-topbar-title (был «График функции»)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
lab.html 4324L → 3499L (-825L). 824 lines of glue code moved.
Position preserved: lab-glue.js loads after lab-init.js, before
newton.js / forcesandbox.js / etc. — same execution order as inline.
node --check passes. /lab returns 200. /js/labs/lab-glue.js returns 200.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
lab.html 5180L → 4324L (-856L). All CSS moved to frontend/css/lab.css
(855L). Added <link> tag after ls.css for proper cascade.
Visual rendering unchanged — pure file move.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The feature_classroom_enabled flag was fully wired in backend
(classroom/sessions.js:11-14 returns 403 when '0', initialized in
legacy-migrate.js:870 to '1') but had no UI control — admin could
only flip it via direct SQL.
- adminController.updateFeatures: classroom was ALREADY in allowed list
- admin/sections/games.js: new toggle row with video icon added to GAME_FEATURES
- js/api.js hideDisabledFeatures: classroom path mapping added ('/classroom')
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
3D rendering (toggle3D/render3D with VDW radii + sphere gradients) was
implemented but had no visible Esc-key exit and cursor was left in 'grab'
state when leaving 3D mode. Changes:
- Esc key now exits 3D mode (toggle3D) in addition to cancel/close actions
- cursor correctly resets to 'crosshair' on 3D exit and 'grab' on enter
- btn-3d toolbar button confirmed visible with mode-3d-active active state
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>