Commit Graph

611 Commits

Author SHA1 Message Date
Maxim Dolgolyov e88cd431ca style(notifications): редизайн dropdown — иконки по типу, левый акцент у непрочитанных, sticky-шапка 2026-06-01 10:47:06 +03:00
Maxim Dolgolyov 8641bb6954 style(flashcards): переработка стат-бара — большое цветное число, тихий градиент фона, иконка в подписи 2026-06-01 10:07:31 +03:00
Maxim Dolgolyov de205a598d style(flashcards): редизайн — цветные заголовки колод, улучшенные карточки изучения, стат-бар с иконками 2026-06-01 10:06:06 +03:00
Maxim Dolgolyov 2d83896a9a fix(dashboard): hero-аватар показывает загруженную картинку, а не только инициалы 2026-06-01 10:00:46 +03:00
Maxim Dolgolyov 7d478c1c1b style(dashboard): редизайн sticky-шапки
- Аватар: 48px + violet glow shadow
- Шапка: высота 68px, blur 16px, border rgba(violet .1), box-shadow
- Статы: пилл-обёртка с фиолетовым тинтом и бордером; разделители между кольцами
- Stat rings: горизонтальный layout SVG(36px) + sr-val + sr-label; значение вынесено из SVG наружу — читается крупно цветным шрифтом

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 09:51:39 +03:00
Maxim Dolgolyov 57ffbc8ae6 style(dashboard): улучшен визуал гамификационной полосы
- Фон: radial-gradient пятно за бейджем уровня + inset highlight
- Бейдж уровня: 56px, гло-тень + внешнее кольцо rgba
- Progress bar: 10px, 3-стоп градиент + box-shadow свечение
- Разделитель border-left между прогрессом и чипами
- Чипы: белый фон с тенью, увеличен padding, крупнее шрифт

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 09:47:28 +03:00
Maxim Dolgolyov b22a1fad3c style(dashboard): улучшен визуал карточки питомца
- Тёплый кремовый градиент фона вместо чистого белого
- Декоративный SVG-фон: рассыпанные искры/звёздочки
- Тег-пилл с янтарным оттенком
- Glow-эффект drop-shadow вокруг спрайта питомца
- Progress bar 7px с оранжевым свечением
- Цветные чипы: стрик → огненный, цель → изумрудный, настроение → фиолетовый
- Кнопка «Ухаживать» — градиент жёлтый→оранжевый с тенью

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 09:40:50 +03:00
Maxim Dolgolyov 5b103ab606 refactor(lab): превью симуляций вынесены в общий lab-previews.js (единый источник)
~45 SVG-превью (P_*) и хелперы _grid/_axes/_svg вынесены из lab-glue.js в
общий /js/lab-previews.js: window.LabPreviews (карта id→SVG, 40 симуляций) +
window.__LabP (по имени, lab-glue берёт алиасы оттуда). SIMS не тронут.
lab.html подключает lab-previews.js перед lab-glue.js. Теперь дашборд берёт
настоящие превью симуляций из того же источника → «Лаборатория дня» крутит
весь каталог, а не 6 захардкоженных. Дублирование 6 превью устранено.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 09:34:29 +03:00
Maxim Dolgolyov ed8323cbb9 style(dashboard): улучшен визуал карточки «Продолжить чтение»
- Декоративный SVG-фон (открытая книга) поверх градиента
- Тег-пилл с frosted-glass эффектом
- Progress bar 7px с белым свечением
- Мета и процент сгруппированы слева, кнопка — справа с тенью
- Градиент обогащён третьим стопом (#8b3010)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 09:33:50 +03:00
Maxim Dolgolyov 927b39b0d6 feat(dashboard): «Лаборатория дня» синхронизирована с каталогом /api/lab/sims
Раньше карточка использовала захардкоженный список из 6 симуляций и не знала
о каталоге. Теперь ежедневный выбор берётся из /api/lab/sims: только включённые
симуляции, у которых есть превью (приоритет featured), title/категория — из БД,
поэтому переименование/выключение/рекомендация в админке отражаются автоматически.
Время/уровень/цель — из curated-карты по id (в каталоге их нет) c дефолтами.
Фолбэк на статичный список, если API недоступен. Заодно исправлен mismatch
isoprocess→molphys (href теперь = id симуляции).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 09:20:10 +03:00
Maxim Dolgolyov ec2a207fb8 feat(classroom): тумблер «Вызов на урок» в профиле + интеграция мелодии в LS.sfx
Мелодию-вызов перевёл с кастомного Web Audio на общий движок звуков LS.sfx:
- длинный вестминстерский бой теперь в sound.js (звук lesson_start);
- api.js лениво подгружает sound.js на любой странице и играет lesson_start
  по SSE classroom_started (вместо собственного синтезатора);
- отдельный pref lessonCall + тумблер «Вызов на урок» и кнопка прослушивания
  в профиле (Настройки → Звуки); уважает мастер-тумблер и громкость;
- lesson_start выведен из категории classroom (управляется своим тумблером);
- разблокировка AudioContext по первому жесту перенесена в sound.js.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 09:11:44 +03:00
Maxim Dolgolyov 0b2e7c8880 fix(exam-prep): стилизованное окно завершения пробника вместо нативного confirm
Окно подтверждения завершения пробника использовало нативный confirm()
(и alert() при ошибке) — без стилей. Заменено на LS.confirm (стилизованный
модал) и LS.toast для ошибки завершения.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 08:47:12 +03:00
Maxim Dolgolyov 536261ceb5 fix(whiteboard): фон annotate-режима очищается сразу, не после первого штриха
setAnnotateMode менял _annotateMode и вызывал render(), но не помечал
статический слой грязным (_staticDirty). Фон рисуется в статич. слое и
перерисовывается только при _staticDirty=true, поэтому непрозрачный фон
доски оставался поверх учебника/симуляции до первого штриха. Ставим
_staticDirty=true при смене режима.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 08:43:32 +03:00
Maxim Dolgolyov 06b23c36dd fix(dashboard): пустой виджет карточек — кнопка ведёт на /flashcards
Кнопка «Создать карточку» в пустом состоянии вызывала click() по FAB,
но исходный клик всплывал до document-листенера, который сразу закрывал
поп-ап — внешне ничего не происходило. Заменено на ссылку на /flashcards.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 16:10:34 +03:00
Maxim Dolgolyov 0d2ddee874 feat(dashboard): карточка чтения берёт данные и цвет из «Учебников»
Источник — /api/textbooks (как страница «Учебники»):
- учебник в процессе (есть прочитанные §) → «Продолжить чтение» с
  прогресс-баром и «N из M § прочитано», ссылка на last_para;
- иначе первый учебник каталога → «Начать чтение», «M § · новый учебник»;
- фон карточки = градиент обложки по t.color (TB_COVER — зеркало
  .tb-cover из textbooks.html), полная синхронизация цвета.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 12:32:00 +03:00
Maxim Dolgolyov a34137c41c fix(profile): добавлен CSS рейтинга (кнопки/строки были без стилей)
Классы .lb-tab/.lb-tabs/.lb-row/.lb-list/.lb-avatar и др. отсутствовали
в profile.html — карточка рейтинга рендерилась голой. Добавлены стили
под дизайн-систему профиля.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 12:29:12 +03:00
Maxim Dolgolyov 6551990e8e fix(dashboard): иконка испытания «Марафонец» (running → footprints)
Иконка Lucide 'running' не существует, поэтому createIcons() оставлял
<i> пустым — у испытания типа 'tests' не было иконки. Заменено на
валидную 'footprints'.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 12:20:33 +03:00
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 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 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