7 Commits

Author SHA1 Message Date
Maxim Dolgolyov ce9f29fcd0 feat(phys9): 129 canvas-цветов на PHYS9_COLORS — тёмная тема работает (Phase 3)
Mass-replace через node-скрипт (без правки HTML/CSS-частей файла):
- ctx.fillStyle = '#xxx' → ctx.fillStyle = (window.PHYS9_COLORS?...:'#xxx')
- ctx.strokeStyle = '#xxx' → аналогично
- ctx.shadowColor = '#xxx' → аналогично
- drawArrow3(..., '#xxx', ...) → drawArrow3(..., PHYS9_COLORS.x|fallback, ...)

Маппинг по физическим смыслам:
- #94a3b8 → forceNormal (slate-400, пунктир/нормаль)
- #475569 → body (тело)
- #1e293b → axis (координат. оси)
- #ef4444 → plotPrimary (основной график)
- #10b981 → force (сила)
- #3b82f6 → liquid (жидкость)
- #0284c7 → velocity (скорость)
- #ea580c → acceleration (ускорение)
- #7c3aed → forceFriction (трение)
- #2563eb → displacement (перемещение)
- ещё 8 других цветов

Все 129 замен с fallback: если PHYS9_COLORS не загружен (старый кеш),
работает прежний #цвет. Тёмная тема автоматически переключается
благодаря get-проперти в phys9_palette.js.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-30 09:32:40 +03:00
Maxim Dolgolyov b6ea1ae398 fix(phys9): удалить Font Awesome — заменено на inline SVG (Phase 1)
Согласно проектной политике CLAUDE.md «никаких эмодзи и Font Awesome,
только inline SVG .ic», вычистил все 14 вхождений FA из Физики 9.

frontend/textbooks/physics_9_ch{1..5}.html (10 правок):
- Удалён <link rel=stylesheet ... font-awesome.css> (5 файлов)
- Заменён <i class="fas fa-star"></i> на inline SVG звезды (5 мест)

frontend/js/phys9_legacy.js (8 правок):
- fa-lightbulb → SVG лампочки (2 места: подсказка задачи, кнопка «решение»)
- fa-check → SVG галочки (кнопка «Проверить»)
- fa-play → SVG треугольник (кнопка «Запустить»)
- fa-pause → SVG двух полосок (кнопка «Стоп»)
- fa-eye-slash → SVG перечёркнутого глаза («Скрыть решение»)
- fa-sun → SVG солнца (тема — день)
- fa-moon → SVG луны (тема — ночь)

Все SVG имеют атрибут class="ic", stroke=currentColor, viewBox 0 0 24 24
для тёмной темы и масштабируемости.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-30 09:29:25 +03:00
Maxim Dolgolyov c34fd27c6a feat(phys9 ch): добавлен блок задач параграфа из legacy POOLS
Раньше в монолите physics_9.html на каждый § был блок задач
(navDots, taskArea, fb, sum, progress-bar и chip-ok), но в новых
ch-страницах physics_9_ch{1..5}.html этого не было.

Изменения:

1. В каждой ch1..ch5.html добавлен hook поверх ensureBuilt:
   - Функция _makeTaskBlock(sec) генерирует HTML контейнеров
     legacy-tasks (#taskArea<sec>, #navDots<sec>, #fb<sec>, #sum<sec>,
     #prog<sec>, #ok<sec>, #cur<sec>, #max<sec>, кнопка «Заново»,
     кнопка «Следующая»).
   - _injectTasks(id) добавляет блок в #<id>-body если есть
     window.POOLS[id], и вызывает window.renderTask(id) +
     window.renderNav(id) для рендера первой задачи.
   - ensureBuilt обёрнут так, чтобы вызывать _injectTasks
     после оригинального билда.

2. В phys9_legacy.js добавлен экспорт POOLS и STATE в window
   (раньше они были скрыты внутри IIFE).

Стили блока задач используют CSS-переменные секции (var(--sec-acc, ...))
и работают с любой темой главы.

Теперь по каждому §1-§36 показывается соответствующий пул задач
(TASKS_P1..P36).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-30 09:17:38 +03:00
Maxim Dolgolyov fe0bfa62c6 fix(phys9 legacy): null-guard в renderTask + try/catch вокруг инициализации
Ошибка: renderTask() падал на secций, отсутствующих на странице ch1
(нет элементов #sum<sec>, #taskArea<sec>, #fb<sec>) — getElementById
возвращал null, .classList.remove падал → IIFE прерывался → экспорт
функций в window не выполнялся → startAnim1 is not defined.

Фиксы:
1. renderTask: early return если area/fb/sum/pool/s — null.
2. Инициализационный forEach обёрнут в try/catch + per-item try/catch.
3. setParaTab('p1') и блок upd2..upd12 обёрнуты в try/catch
   (некоторые элементы могут отсутствовать на отдельных ch-страницах).

Теперь экспорт функций гарантированно выполняется до конца файла.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-30 09:13:03 +03:00
Maxim Dolgolyov 66bd7ac1f4 fix(textbooks): Физика 9 — STATE collision, KaTeX escape, авто-init симуляций
Три бага из жалобы пользователя:

1) phys9_legacy.js упал с 'Identifier STATE has already been declared' —
   const STATE в монолите конфликтовал с const STATE в chapter inline JS.
   Скрипт extract_phys9_legacy.cjs теперь оборачивает извлечённый код в IIFE
   и явно экспортит через window 70 функций (upd*/draw*/init*/start*/lab*/
   check*/toggle*/render*/show*/...) + 7 const-массивов (TASKS_PN, PUZ_PN).

2) В боковой панели формулы рендерились как 'Delta vecr' вместо Δr⃗ —
   мой переход на JSON.stringify в gen_phys9_ch.js добавил лишний слой
   escape backslash. Уменьшил \\ → \ в SIDEBAR_ROWS, TIPS_HTML,
   PARA_SUBS, LR_SUBS (90 строк). Цепочка теперь: source \Delta → string
   \Delta → JSON "\\Delta" → HTML JS \Delta → runtime \Delta →
   KaTeX \Delta ✓.

3) 'не работают симуляции' — функции из legacy.js были доступны, но
   chapter goTo(id) их не вызывал. Добавлен авто-вызов upd<N>(),
   startAnim<N>(), init<N>(), draw<N>() при переключении на параграф,
   и updLab<N>(), drawLab<N>() — для ЛР.
2026-05-30 09:06:20 +03:00
Maxim Dolgolyov c26423b7d4 fix(phys9 legacy): null-guard для themeBtn и refToggle в дочерних страницах
На страницах physics-9-ch1..ch5 нет элементов #themeBtn, #refToggle, #refPanel
(они только в hub). Без проверки на null код падал с
"Cannot read properties of null", из-за чего НЕ выполнялся
последующий экспорт функций в window (startAnim1, startAnim15 и т.д.) —
и кликам по кнопкам onclick="startAnim1()" соответствовало
ReferenceError: startAnim1 is not defined.

Обёрнуто в `if (themeBtn) {...}` и `if (refToggle && refPanel) {...}` —
теперь скрипт продолжает работу на любой странице, а функции
анимаций корректно экспортируются.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-30 09:04:31 +03:00
Maxim Dolgolyov dcdcde5b4e fix(textbooks): Физика 9 — escape § в num + phys9_legacy.js + финалы 5 глав
Багфиксы:
- gen_phys9_ch.js: убран двойной escape \u00a7 → литерал §
  (раньше карточка показывала '\u00a7 1' вместо '§ 1')
- phys9_legacy.js (262 КБ): извлечён весь JS монолита для глобальных onclick-
  обработчиков (startAnim1, lab11add/all/reset, checkNum, togglePend36 и пр.).
  Setup-код в конце обёрнут в try/catch — он рассчитан на DOM монолита.
- migrate_phys9_ch4.js + migrate_phys9_content.js: подключают phys9_legacy.js
  во все 5 ch-файлов перед закрытием <head>.

Финалы глав (write_phys9_finals.js):
- ch1: 5 задач (кинематика — поезд, разгон, окружность, лодка/река)
- ch2: 5 задач (динамика — трение, Гук, свободное падение, перегрузка)
- ch3: 5 задач (статика — рычаг, Архимед, блок, КПД накл. плоск., льдина)
- ch4: 5 задач (импульс — неупр. удар, ЗСЭ, мощность крана, пуля, бросок)
- ch5: 5 контрольных по практикуму (среднее, ЛР2, ЛР4, ЛР6, ЛР10)

Все задачи с автопроверкой через checkNum() (теперь работает из legacy.js).
2026-05-30 08:55:00 +03:00