Commit Graph

677 Commits

Author SHA1 Message Date
Maxim Dolgolyov 4fed35fec8 feat(dashboard): карточка чтения наполняется данными (фон+инфо учебника)
Раньше при отсутствии начатого курса карточка оставалась статичной
заглушкой («Учебники»). Теперь:
- при прогрессе — «Продолжить чтение»: курс, урок, прогресс-бар, %;
- иначе — рекомендованный учебник из /api/courses: название, описание,
  число параграфов;
- фон-градиент карточки по предмету (SUBJ_GRADIENT, как обложки).
Синтаксис всех инлайн-скриптов проверен (0 ошибок).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 12:18:40 +03:00
Maxim Dolgolyov eaba6b7389 fix(profile): рейтинг виден всегда (пустое состояние вместо скрытия)
Раньше карточка пряталась при отсутствии данных API — выглядело как
«рейтинга нет». Теперь всегда видна: либо список, либо подсказка
«Пока нет данных рейтинга».

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 12:11:47 +03:00
Maxim Dolgolyov 2addb8ec02 fix(dashboard): Активность видна всегда + ряд одинаковой высоты
- loadActivityWidget показывает блок всегда (пустое состояние рисует
  renderHeatmap), даже при 0 сессий и при ошибке истории.
- .bottom-grid: align-items stretch + height 100% — карточки ряда
  (Активность/Мои сдачи/Испытания) одной высоты.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 12:02:32 +03:00
Maxim Dolgolyov e6120c6fc8 fix(profile): добавлена разметка карточки рейтинга (JS был без markup)
Контейнер lb-section не попал в файл ранее — loadLeaderboard молча
выходил. Теперь рейтинг реально виден в табе «Достижения».

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 12:01:22 +03:00
Maxim Dolgolyov 3ffe4ff560 feat(profile): рейтинг (leaderboard) перенесён в таб «Достижения»
Карточка рейтинга с табами Неделя/Всё время, /api/gamification/leaderboard,
самодостаточный JS (свой esc). Рейтинг убран с дашборда ранее.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 11:53:48 +03:00
Maxim Dolgolyov edfa799d9c feat(dashboard): «Активность» в нижний ряд + удалён остаток «Теории»
- Блок «Активность» (heatmap + календарь) вынесен из 3-й колонки в
  отдельный нижний ряд .bottom-grid рядом с «Мои сдачи» и «Испытания».
- Удалён остаток разметки «Теория — в процессе» и разметка рейтинга
  (lb-section) с дашборда; конфиг виджетов обновлён (Активность вместо
  Теории/Рейтинга).
- Селектор скрытия для учителя и адаптив обновлены под .bottom-grid.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 11:39:54 +03:00
Maxim Dolgolyov 5a93751ccc fix(dashboard): синхрон XP питомца 1-в-1 с модулем /pet
Полный XP и абсолютный порог уровня (d.xp / d.xpForNextLevel),
уровень пользователя d.level — как в pet.html, а не относительный
расчёт по petLevel.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 11:31:08 +03:00
Maxim Dolgolyov 5c611166f3 fix(dashboard): добавлено определение loadPetHero (ReferenceError на проде)
Функция loadPetHero вызывалась, но её тело не попало в коммит
667054f (Edit не применился). Восстановлено: рендер питомца через
PetSprite + загрузка /api/pet, как и задумано.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 11:18:46 +03:00
Maxim Dolgolyov c6662b3056 refactor(dashboard): убран блок «Теория» и «Рейтинг» с главной
- Рейтинг (lb-section) перенесён в профиль — удалён с дашборда вместе
  с вызовами loadLeaderboard()/_populateLbClasses() и тоглом конфига.
- Виджет «Теория» (w-theory-progress) удалён вместе с тоглом конфига.
- applyDashboardPrefs/toggleDashWidget null-безопасны к удалённым id.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 11:14:24 +03:00
Maxim Dolgolyov 667054fa58 feat(dashboard): hero-карточки главной — чтение, лаборатория дня, питомец
Пересборка верхней зоны дашборда по скриншоту (редизайн был утерян):
- 3 hero-карточки вместо action-cards: «Начать чтение» (продолжение
  курса через /api/courses/continue), «Лаборатория дня» (детерминир.
  выбор по дню + SVG-превью из lab-previews.js), «Питомец» (синхрон
  с модулем /pet через /api/pet + единый PetSprite.render).
- Подключены восстановленные ассеты pet-sprite.js и lab-previews.js.
- Убран weak-topics из hero; питомец показывает уровень/XP/стрик/
  цель дня/настроение, синхронно со страницей /pet.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 11:11:20 +03:00
Maxim Dolgolyov ca5dc3a4f3 fix(dashboard): командный центр — навигация ведёт в /admin, дни в «висит»
Кнопки инбокса (Открыть/Разблокировать/Разобрать) и ссылки
все алерты/все сессии вели на голый #hash и оставались на /dashboard.
Теперь ведут в /admin#sessions|#users. fmtSince показывает дни для
сессий старше 48ч (1888ч → 78д 16ч).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 11:01:14 +03:00
Maxim Dolgolyov 8629616a04 feat(dashboard): командный центр администратора на /dashboard
Админ при входе на /dashboard видит редизайн-обзор (порт макета
admin-dashboard-redesign.html) на реальных данных /api/admin/overview:
KPI-пульс со спарклайнами, инбокс «Требует внимания» с табами
(блокировки/зависшие/брошенные), лента топ-сессий, распределение по
предметам, здоровье контента, топ/худшие результаты, быстрые действия.
Стили заскоуплены под #admin-command-center. Учитель/ученик без изменений.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 10:58:43 +03:00
Maxim Dolgolyov 29301ff87d feat(flashcards): фаза 1 полировки — хоткеи, поиск, drag-reorder, честные интервалы
- study: хоткеи Space/стрелки=флип, 1-4/←→=оценка
- превью интервалов = точная копия серверного SM-2 (было враньё «<1 мин»)
- поиск/фильтр карточек внутри колоды
- drag-reorder карточек + endpoint PUT /decks/:id/reorder (requireOwnership)
- flashcard_decks добавлен в ALLOWED_TABLES requireOwnership
- эмодзи в empty-state → inline SVG .ic
- deleteCard: нативный confirm() → LS.confirm

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 09:53:03 +03:00
Maxim Dolgolyov 1dcc4cbf6e feat(flashcards): глобальный quick-add FAB + виджет «повтори карточку»
Backend:
- POST /api/flashcards/quick — добавить карточку из любой точки; колода по
  выбору или автоколода «Быстрые карточки» (создаётся при первом обращении)
- GET /api/flashcards/random — случайная карточка из всего пула пользователя

Frontend:
- /js/flashcard-fab.js — плавающая кнопка «запомнить» на всех страницах
  (учебник, лаборатория, симуляция…). Поповер: вопрос/ответ/колода, Ctrl+Enter.
  Гейт по фиче-флагу flashcards; исключены classroom/login/error/сама /flashcards.
  Загружается лениво из sidebar.js (на 45 страницах с шапкой).
- dashboard: виджет #w-flashcard в колонке прогресса — флип-карта (вопрос↔ответ),
  кнопка «Другая», счётчик пула, CTA при пустом пуле; слушает событие
  flashcard:added для авто-обновления.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 09:38:23 +03:00
Maxim Dolgolyov d4ab7993c5 fix(flashcards): добавлен /api/ префикс в 12 вызовах LS.api
LS.api = apiFetch — принимает полный путь без автодобавления /api/.
Все 12 вызовов исправлены: /flashcards/... → /api/flashcards/...

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 09:21:10 +03:00
Maxim Dolgolyov d85da0198c fix(flashcards): COLORS перемещён перед IIFE — устранён ReferenceError
const COLORS и let _deckColor объявлены в temporal dead zone во время
вызова init() из IIFE (const не hoisting, function — да). Перемещены
перед IIFE: теперь COLORS инициализирован до первого вызова buildColorPicker().

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 09:19:11 +03:00
Maxim Dolgolyov 400a229959 fix(flashcards): LS.init → LS.initPage + renderNavAvatar; добавлен в сайдбар
- flashcards.html: замена несуществующего LS.init() на LS.initPage()
  с деструктуризацией { user }; аватарка через LS.renderNavAvatar
- sidebar.js: добавлена ссылка /flashcards (иконка copy) в раздел «Знания»
  после «Карта знаний»; feature_flashcards_enabled=1 в БД уже активен

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 09:13:40 +03:00
Maxim Dolgolyov 358b761eb2 fix(biochem): статичный subnav без мигания + редизайн
Проблема: динамическая вставка через JS вызывала мигание (nav
появлялся через ~100ms после первого пейнта).

Решение: nav — статичный HTML в каждой странице, CSS — в <head>.
Активная вкладка проставлена в HTML (class bsn-active) — нет JS,
нет мигания, работает с первого байта.

Редизайн .biochem-subnav:
- frosted glass (backdrop-filter blur 14px, rgba 0.92)
- активная вкладка: фиолетовый фон-пилюля + нижняя линия 2.5px
- hover: мягкий фиолетовый фон
- mobile <560px: только иконки (bsn-label display:none)
- overflow-x auto + scrollbar-width:none — горизонтальная прокрутка без полосы
- biochem-nav.js сведён к no-op комментарию

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 08:54:38 +03:00
Maxim Dolgolyov b7db2fc229 feat(biochem): межстраничная навигация модуля (biochem-nav.js)
Новый /js/biochem-nav.js: вставляет sticky-полосу .biochem-subnav
с вкладками Редактор / Библиотека / Реакции / Свойства / Пути.
Текущая вкладка подсвечивается (bsn-active + фиолетовая нижняя линия).
На узких экранах (<560px) — только иконки. Скрипт подключён на всех 5 страницах.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 08:50:10 +03:00
Maxim Dolgolyov dca1fd54ce fix(teacher-guide): исправлены сломанные стили, admin-блок восстановлен корректно
Причина: Python-скрипт при удалении секций нарушил баланс div-ов (diff=-2).
Решение: восстановлен файл из коммита 2354353, все правки через Edit.

Изменения:
- div balance восстановлен: 0
- s-14-4 (управление симуляциями) и s-16-3 (начисление XP) убраны из teacher-глав
- CHAPTERS в JS: s-14-4 и s-16-3 убраны из sections/sLabels ch-14/ch-16
- buildNavItem(): общая функция рендера пунктов nav (teacher + admin)
- Admin блок (ch-a1..ch-a6): display:none → show при isAdmin
- ALL_CHAPTERS(), scrollToSection, updateReadUI, initHash обновлены

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 08:46:55 +03:00
Maxim Dolgolyov 0676e6e12d feat(teacher-guide): admin-only блок руководства (главы A1-A6)
Видимость по роли:
- Teacher: главы 1-17 без admin-секций (убраны 14.4/16.3/17 → перенесены в A3/A4)
- Admin: дополнительный блок A1-A6 (isAdmin → display:none → show)

Руководство администратора (6 глав):
- A1: Командный центр — KPI, очередь триажа, лента завершений
- A2: Пользователи — список, карточка (роль/блок/история/удаление), Ctrl+K поиск
- A3: Контент и доступ — allowlist учебников, симуляции, feature flags
- A4: Геймификация — статистика, начисление XP/монет с пресетами, сброс прогресса
- A5: Аудит и безопасность — аудит-лог, RBAC, модерация аватаров
- A6: System Health — CPU/RAM/event loop, HTTP-статистика, журнал ошибок

Технические изменения:
- initPage → const { isAdmin }
- ALL_CHAPTERS() = CHAPTERS + (isAdmin ? ADMIN_CHAPTERS : [])
- admin nav в sidebar (tg-nav-admin), admin chapters в tg-admin-content
- scrollToSection/updateReadUI/initHash используют ALL_CHAPTERS()
- прогресс-бар считает все главы (17 или 23 в зависимости от роли)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 08:37:50 +03:00
Maxim Dolgolyov 2354353e93 docs(teacher-guide): главы 14–17 — лаборатория, биохимия, геймификация, доступ
+ Глава 14: Виртуальная лаборатория (40 симуляций, deep-link, стереометрия 3D,
  связь с учебниками, управление в админке)
+ Глава 15: Биохимия (молекулярный редактор 2D/3D, VSEPR, SMILES, валентность,
  библиотека, реакции с ΔH, метаболические пути)
+ Глава 16: Геймификация (XP/уровни/достижения, питомец эволюция/цвет/настроение,
  начисление XP через панель, сброс прогресса)
+ Глава 17: Доступ к контенту (allowlist учебников/экзаменов по классам,
  feature flags, System Health)
~ Ch-13: nav → ch-14 вместо ch-1; убран «Готово! 13 глав»
~ CHAPTERS array: 13 → 17 записей, прогресс-бар пересчитается автоматически

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 08:26:51 +03:00
Maxim Dolgolyov 8c44115d32 docs(readme): полное обновление документации
Добавлено/обновлено:
- Учебники: 18 учебников (химия/физика/алгебра/геометрия 7-11), движок Химии 7/8
- Лаборатория: 40 симуляций по категориям, Lab Content Engine, LabRegistry
- Биохимия: biochem-core dual-export, services/chem.js, /analyze, valency
- Dashboard: карточки учебника/лабы/питомца, командный центр админа
- Геймификация: панель начисления XP, питомец с pet-sprite.js
- Архитектура: node:sqlite, 47 миграций, 106 таблиц, 60 страниц, 40 routes
- Feature flags: таблица флагов
- Content access allowlist, galaxy map, планиметрия/стереометрия, System Health
- Shared модули: pet-sprite.js, lab-previews.js
- API: полная таблица 33 групп маршрутов

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 08:22:32 +03:00
Maxim Dolgolyov 192055dc0f style(admin/gam): CSS-классы вместо inline-style, без эмоджи
- gam-award-grid/gam-reset-grid: CSS Grid, адаптив 800px
- gam-user-col/filter/select — единые стили из design system
- gam-preset/gam-reason-tag — через CSS-классы, без inline
- gam-num-input: Unbounded шрифт, выровненный по центру
- gam-award-footer + gam-reset-warning как отдельные блоки
- убраны все эмоджи; пресеты сбрасываются через gamSetXP/gamSetCoins

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 08:13:56 +03:00
Maxim Dolgolyov ec8403e26c feat(admin/gam): переработана форма начисления XP/монет
- select с полным списком пользователей + фильтр по имени (вместо typeahead)
- пресеты XP (0/10/25/50/100/250) и монет (0/10/25/50) с подсветкой активного
- пресеты причин (кнопки) + поле для своей причины
- fix: xp/coins теперь Number(value) без || 0 — значение 0 не начисляется
- форма сброса прогресса — тоже select из того же кэша пользователей

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 08:11:19 +03:00
Maxim Dolgolyov cff9973dcf fix(biochem): аватарка через LS.renderNavAvatar на всех страницах модуля
Заменил ручное ava.textContent=initials на LS.renderNavAvatar(ava, user)
в biochem.html / -library / -reactions / -properties.
biochem-pathways.html уже был корректен.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 08:03:02 +03:00
Maxim Dolgolyov b67fac6407 feat(biochem): Фаза 2.1/2.2/2.4 — серверный chem.js + /analyze + подсказки валентности
- biochem-core.js dual-export (browser window.BIO + Node module.exports), без дублей
- BIO.valency: подробные подсказки валентности (2.4), общие для редактора и сервера
- services/chem.js: серверный анализ поверх того же ядра (analyze/validate)
- POST /api/biochem/analyze (2.2); /validate переведён на ядро (+фикс формата связей)
- api.js: LS.biochemAnalyze

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 22:37:59 +03:00
Maxim Dolgolyov 8b5d9238b5 chore(backend): nodemon.json — авто-перезагрузка сервера при изменении src/
Следим только за src/ (js,json,yaml), игнорируем тесты; data/, логи и
uploads/ вне src/, поэтому циклов перезапуска нет. Запуск: npm run dev.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 21:34:34 +03:00
Maxim Dolgolyov 7c32501e18 fix(admin): отображать HTML-разметку вопросов в секции «Вопросы» при allow_html
Секция игнорировала флаг allow_html и всегда экранировала текст/опции/
пояснение, из-за чего <div class=task-figure><img>, <b> и пр. показывались
как сырой текст. Теперь — как в test-run.html: allow_html ? raw : esc.
Также добавлен q.allow_html в SELECT списка вопросов (его не было в ответе API).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 21:29:00 +03:00
Maxim Dolgolyov 5f481f5d11 fix(admin): рендер KaTeX в секции «Вопросы» — добавлены разделители $…$ и $$…$$
renderMath в _shared.js распознавал только \(…\) и \[…\], из-за чего
873 вопроса с долларовыми разделителями не рендерили формулы в админке.
$$ ставится раньше $, чтобы auto-render не принял его за два пустых $.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 21:25:17 +03:00
Maxim Dolgolyov ac6552b44f feat(chemistry7): визуал V1-хвост — §9 валентные связи + §12 подсчёт атомов
§9: добавлена схема «связей-крючков» (Chem7Anim.valenceLink, SVG) — атомы A и B
с чёрточками валентности, связи прорисовываются (draw-in); число связей = НОК.
§12: под балансировщиком — анимированный подсчёт атомов (реагенты vs продукты),
атомы-точки появляются масштабированием; подтверждается баланс слева=справа.

Все интерактивы Химии 7 анимированы. Тесты chem7: 16/16; полный прогон 162/165.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 20:07:06 +03:00
Maxim Dolgolyov 639f985e6f feat(chemistry7): визуал V4 (Глава 4) — электролиз 2:1, индикаторы, титрование
Подключён chem7_anim.js в Главу 4.
- §23 (звёздный): электролиз воды — два потока пузырьков H₂ (18) и O₂ (9),
  наглядно 2:1;
- §24/ЛО5 индикаторы щёлочи: блок плавно меняет цвет (фенолфталеин → малиновый);
- §25/ПР4 нейтрализация (звёздный): раствор плавно обесцвечивается
  малиновый → бесцветный (colorBlock).

Все 4 главы анимированы. Тесты chem7: 16/16; полный прогон 162/165 (3 — baseline Auth).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 19:54:50 +03:00
Maxim Dolgolyov 33f968bff9 feat(chemistry7): визуал V3 (Глава 3) — пузырьки, морфинг цвета, индикаторы
Подключён chem7_anim.js в Главу 3.
- §21 ряд активности (звёздный): клик металла левее H₂ → анимация пузырьков
  H₂ (bubbleField); правее (Cu, Ag) — «реакция не идёт»;
- §19 восстановление CuO: colorBlock плавно чёрный→красный (медь); горение —
  пламя водорода;
- §20/ЛО3 индикаторы: блок плавно меняет цвет на цвет индикатора в кислоте.

Тесты chem7: 16/16; полный прогон 162/165 (3 — baseline Auth).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 19:51:27 +03:00
Maxim Dolgolyov e8cb95be55 feat(chemistry7): визуал V2 — звёздный флагман §15 «Горение» (анимация пламени)
Подключён chem7_anim.js в Главу 2. §15: статичное SVG-пламя заменено на
анимированный flameBox с достоверным цветом по веществу — углерод оранжевое,
сера синее, фосфор ярко-белое, железо/магний с искрами; продукт-оксид и
уравнение всплывают. Тесты chem7: 16/16 pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 19:45:53 +03:00
Maxim Dolgolyov 41985a93eb feat(chemistry7): визуал V1 — анимация §10 (признаки реакции) и §11 (осадок)
chem7_anim.js: CSS-хелперы (jsdom-safe, без canvas) — bubbleField (пузырьки
газа), precipField (падающий осадок + слой), flameBox (мерцающее пламя+искры),
colorBlock (плавная смена цвета вещества).
§10/ЛО1: «Провести опыт» проигрывает анимацию по типу опыта (малахит
зеленеет→чернеет, голубой осадок CuSO4+NaOH, синее пламя серы, пузырьки CO2).
§11: при «Смешать» формируется осадок Cu(OH)2, весы остаются ровными.

Тесты chem7: 16/16 pass; полный прогон 162/165 (3 — baseline Auth).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 19:42:33 +03:00
Maxim Dolgolyov f620562124 feat(chemistry7): визуальный апгрейд V0 (движок) + пилот V1
chem7_anim.js — анимационный движок (window.Chem7Anim): RAF-цикл с паузой
вне экрана (IntersectionObserver), prefers-reduced-motion, headless-guard
(jsdom-safe: молекулы на SVG, canvas без getContext в тестах),
molecule3d (вращающаяся 3D-модель, drag), separation (частицы:
фильтр/выпаривание/магнит/отстаивание/перегонка), colorMorph, confettiSmall.

Пилот в Главе 1:
- §5/§6: статичные галереи → вращающиеся 3D-модели (H2/O2/O3/N2, H2O/CO2/CH4/NH3) с переключателем;
- §2/ПР1: при верном методе разделения проигрывается анимация частиц.

Тесты chem7: 16/16 pass; полный прогон 162/165 (3 — baseline Auth).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 19:35:44 +03:00
Maxim Dolgolyov c1ef1ecee9 docs(chemistry7): план визуального и интерактивного апгрейда (анимации)
~15 флагманских анимированных интерактивов поверх готового учебника:
общий движок chem7_anim.js (частицы, пузырьки, пламя, морфинг цвета,
RAF-реестр с паузой вне экрана), апгрейд виджетов по главам
(разделение смесей, 3D-молекулы, горение, ряд активности с пузырьками,
электролиз 2:1, титрование). Фазы V0-V5, правила (reduced-motion,
тёмная тема, перф, достоверная химия). Монтаж в существующие контейнеры.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 19:25:06 +03:00
Maxim Dolgolyov a33f622a35 style(textbooks): компактная кнопка «В лабораторию» (иконка + счётчик)
Кнопка на карточке учебника наследовала .tb-btn{flex:1} и растягивалась
наравне с «Продолжить» — длинный текст переносился на 3 строки, колба
вставала посреди слова. Теперь .tb-lab-btn — компактный квадрат (как
кнопка ДЗ): только колба, при нескольких связях добавляется число;
полное название в title. flex:0 0 auto + white-space:nowrap убирают
перенос, колба тонирована в --violet как научный акцент.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 19:12:48 +03:00
Maxim Dolgolyov 26eaee5c57 fix(chemistry7): тема главы + фон para-hero (область §-заголовка сливалась)
Страницы глав наследовали amber-палитру chem8-textbook.css и базовый
.para-hero без фона (нужен модификатор .ph-N) → блок заголовка § сливался
с фоном. Добавлен per-chapter <style>: своя палитра (emerald/cyan/violet/blue,
как карточки в хабе) + сплошной градиент .para-hero. Тесты chem7: 15/15.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 19:09:17 +03:00
Maxim Dolgolyov 7574d16678 feat(chemistry7): Phase 4 — Глава 4 «Вода» завершена (§§23–26 + ЛО5 + ПР4 + финал)
§23 Состав и свойства воды (разложение 2:1 + реакции воды),
§24 Основания (конструктор Me(OH)n + индикаторы щёлочи),
ЛО5 Действие щелочей на индикаторы,
§25 Реакция нейтрализации (анимация фенолфталеин малиновый → бесцветный),
ПР4 Реакция нейтрализации, §26 Охрана окружающей среды (экология-инфографика),
финал главы (6 боссов). chem7_ch4_widgets.js.

ВСЕ 26 параграфов курса «Химия 7» наполнены. Тесты chem7: 15/15 pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 19:04:49 +03:00
Maxim Dolgolyov 1635bc6051 feat(chemistry7): Phase 3 Волна 2 — Глава 3 завершена (§21, ЛО4, §22, ПР3, финал)
§21 Кислоты и металлы (интерактивный ряд активности),
ЛО4 Кислоты с металлами (опыт: пузырьки H2, медь не реагирует),
§22 Соли как продукты замещения (конструктор солей по валентности),
ПР3 Получение водорода (проверка чистоты — гремучий газ),
финал главы (6 интегрированных боссов + шпаргалка).

Глава 3 «Водород» наполнена полностью (§§18–22). Тесты chem7: 14/14 pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 19:00:18 +03:00
Maxim Dolgolyov 0af08bcc55 feat(chemistry7): Phase 3 Волна 1 — Глава 3, §18 + §19 + §20 + ЛО3
§18 Водород — элемент и простое вещество (паспорт + модель H2),
§19 Химические свойства водорода (горение → вода, восстановление CuO → Cu),
§20 Понятие о кислотах (индикаторы лакмус/метилоранж + таблица кислот),
ЛО3 Действие кислот на индикаторы. chem7_ch3_widgets.js. Тест: 13/13 pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 18:57:28 +03:00
Maxim Dolgolyov 2c80a52d6f feat(chemistry7): Phase 2 Волна 2 — Глава 2 завершена (§16, §17, ПР2, финал)
§16 Оксиды (конструктор оксида по валентности + классификатор оксид/не оксид),
§17 Получение кислорода (схема разложения KMnO4/H2O2, понятие катализатора),
ПР2 Получение кислорода (доказательство тлеющей лучинкой),
финал главы (6 интегрированных боссов + шпаргалка).

Глава 2 «Кислород» наполнена полностью (§§13–17). Тесты chem7: 12/12 pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 18:50:23 +03:00
Maxim Dolgolyov e949cb18a5 feat(chemistry7): Phase 2 Волна 1 — Глава 2, §13 + ЛО2 + §14 + §15
§13 Воздух как смесь газов (интерактивная диаграмма состава),
ЛО2 Сборка приборов и собирание газов (выбор способа собирания),
§14 Кислород — элемент и простое вещество (переключатель O/O2/O3 + модели),
§15 Химические свойства кислорода (симулятор горения C/S/P/Fe/Mg → оксид).
chem7_ch2_widgets.js. Тест: 11/11 pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 18:40:16 +03:00
Maxim Dolgolyov a6567d0938 feat(admin/health): System Health Level 4 — диагностика + последние ошибки
adminController.getHealth: активные health-проверки — отклик БД (ping, мс) и
тест записи на диск рядом с БД; вердикт уходит в critical при недоступной БД
или диске, warning при медленном отклике БД (>100мс). Плюс recentErrorList —
последние 8 записей error_log (level/route/method/message/время).

admin.js: панель «Диагностика» — индикаторы БД/диска (зелёный/красный) +
лента последних ошибок с цветом по уровню.

Проверено: checks {dbOk,dbPingMs,diskWritable}, список ошибок отдаётся.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 18:38:56 +03:00
Maxim Dolgolyov 6a934ca6c6 feat(admin/health): System Health Level 3 — тренды (сэмплинг + canvas-графики)
metrics.js: сэмплинг раз в минуту в кольцевой буфер (cap 24ч, unref) —
ts/rss/heapUsed/reqPerMin/reqDelta/err5xx/p95; history() + поле history в
snapshot (последние 180 точек).

admin.js: секция «Тренды» с 4 мини-графиками (canvas): Память RSS, Запросы/мин,
Ошибки 5xx, Латентность p95 — линия + заливка + подписи макс/последнее.
Обновляются вместе с live-рефрешем.

Проверено: сэмплер пишет, история в snapshot, графики рисуются (на старте —
«накопление данных…», далее наполняются).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 18:36:04 +03:00
Maxim Dolgolyov 13cbbacc1f feat(chemistry7): Phase 1 Волна 4 — Глава 1 завершена (§§10–12 + ЛО1 + финал)
§10 Физические и химические явления (детектор признаков реакции),
ЛО1 Признаки реакций (опыты с признаками), §11 Закон сохранения массы
(весы сохранения массы), §12 Составление уравнений (балансировщик через
Chem8.equationBalancer), финал главы (6 интегрированных боссов + шпаргалка).

Глава 1 «Первоначальные химические понятия» наполнена полностью (12§).
Тесты: 10/10 chem7 pass; полный прогон 156/159 (3 — известный baseline Auth).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 18:33:55 +03:00
Maxim Dolgolyov bc50a0d9f1 feat(chemistry7): Phase 1 Волна 3 — Глава 1, §§7–9
§7 Химическая формула (разбор формулы на состав, индекс/коэффициент),
§8 Относительная молекулярная масса (калькулятор M_r через Chem8.molarMass),
§9 Валентность (конструктор формулы по валентности через НОК индексов).
Теория, тренажёры задач. Тест: 9/9 pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 18:29:40 +03:00
Maxim Dolgolyov 4a424505a8 feat(admin/health): System Health Level 2 — метрики HTTP-запросов
backend/src/utils/metrics.js: лёгкие in-memory метрики (сброс при рестарте) —
всего запросов, req/min (скользящее окно), латентность avg/p50/p95/p99,
разбивка по статусам 2xx/3xx/4xx/5xx, топ маршрутов по частоте/латентности/
ошибкам (группировка по шаблону route.path, не по URL).

server.js: middleware (на /api, по res 'finish') пишет латентность и статус.
adminController.getMetrics + GET /api/admin/metrics (под admin-auth).

admin.js: health-страница переведена на refreshHealth/renderHealth (Level 1)
+ секция «Метрики запросов»: карточки req/min/всего/avg/p95/p99/5xx, цветная
полоса статусов, топ медленных/частых/ошибочных маршрутов.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 18:27:58 +03:00
Maxim Dolgolyov f7d27ecb91 feat(chemistry7): Phase 1 Волна 2 — Глава 1, §§4–6
§4 Относительная атомная масса (весы атомов: во сколько раз тяжелее),
§5 Молекулы и простые вещества (галерея молекул O2/O3/H2/N2 шариками),
§6 Сложные вещества (классификатор простое/сложное + галерея H2O/CO2/CH4/NH3).
Теория, тренажёры задач. Тест: 8/8 pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 18:26:17 +03:00