STEREO3D.attachDragRotate(target, scene, onChange?) — мутирует scene.rotX/rotY на mouse/touch drag, по умолчанию пересобирает innerHTML контейнера через scene.render(). Применено к аннотированному кубу §1 (viz1-cube) в geometry_10_r1.html. Остальные сцены не затронуты.
- Карточка: горизонтальный layout, 74px высоты — цветная маркер-полоса слева (46px) с классом + 4-буквенной аббрев. предмета + watermark, справа название/счётчик параграфов/прогресс-бар (3px)
- В ряд помещается 5-7 карточек на десктопе (вместо 2-3)
- Вся карточка кликабельна (ведёт на 'Продолжить' или 'Открыть')
- Кнопка 'Назначить ДЗ' для учителя — overlay в углу, появляется на hover
- Сверху сетки чипсы-фильтры по предмету с счётчиком; скрыты, если предметов <2
- На hover чуть приподнимается, в углу появляется 'Продолжить →'
- Mobile: 160px минимум, узкие отступы
Linear-gradients tiled at 3px wide produced striped curtains, not
rain. Switched to two pseudo-element layers of elongated radial
ellipses (1.5px × 12-18px) scattered across 130-180px tiles —
sparse drops at two depths with different fall speeds.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Doubles the bg catalogue from 10 to 19 with richer multi-layer
animations. Every keyframe pack is CSS-only and respects the existing
prefers-reduced-motion fallback.
sunset 550 slow hue cycle through warm palette
rain 650 2-layer vertical streaks at different speeds
snow 700 3-layer drifting flakes pattern
clouds 750 drifting white blobs on day sky (only LIGHT one)
fireflies 800 pulsing glowing dots, opposing drift
cyber-grid 850 neon grid scrolling down with vignette
kaleidoscope 1000 two huge conic-gradients in opposite rotation
ocean 1100 layered blobs drift like undulating waves
aurora-dance 1500 multi-band aurora — new premium top-tier
Tonal classification mirrored in api.js DARK_BG_SLUGS so the veil
picks the right contrast: clouds is light, the other 8 join the dark
set (alongside dark, stars, aurora, nebula, grid).
Each background also gains a matching .bg-preview.bg-<slug> rule that
reuses the same animation at the shop's 90px swatch — WYSIWYG.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The pill containers (.p-tabs, .shop-filters) used a 6% black fill that
disappeared on the dark veil, so the rounded button group lost its
outline and the inactive tabs looked like floating text. Same for the
xp / progress tracks (.ach-xp-progress, .ep-bar, .po-bar) that used
7% black.
Dark-tone overrides:
• Containers get a 6% white wash + 10% white border so the pill
shape stays readable
• Inactive p-tab gets the same color/hover treatment that .shop-filter
already had (was an oversight in the previous fix)
• Active pills gain a darker shadow halo so they don't look detached
• Progress tracks switch to a 10% white track instead of 7% black
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The dark veil was right (deep navy at 78%), but every page chrome
element below it inherited light-theme text colors and faded to
invisible — 'Магазин наград' header, shop filter buttons, achievement
group titles, balance counter etc.
Targeted overrides for body[data-bg-tone='dark']: only the elements
that sit directly on the veil get a light text color. White cards
(.shop-item, .ach-item, .ep-card) keep their dark text intact.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The single bg-fx layer was painting at full vibrancy behind the entire
app. Most UI elements use rgba() fills — chips, sub-panels, the
achievements .ach-item, the goal-tier bar — so saturated colors bled
right through, hurting readability on the Достижения / dashboard /
mocks tabs.
Layered fix:
• bg-fx drops to z-index:-2 (the animated layer)
• new #ls-bg-veil sits on z-index:-1 with rgba(245,247,251,.78)
(light) or rgba(15,23,42,.55) when body[data-bg-tone='dark']
• applyCosmetics injects both elements and tags the body with
bg-tone based on the slug (dark/stars/aurora/nebula/grid go dark,
everything else light)
• clearing the bg removes both layers + the tone attribute
Result: animations stay perceptible (~22% of the chosen palette comes
through the veil), but the page chrome reads at normal contrast.
Shop swatches keep full vibrancy — the .bg-preview is meant to show
the raw palette so users can compare.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The shop item card .owned/.active states used semi-transparent fills
(rgba(34,197,94,0.03) / rgba(6,214,224,0.04)) for a subtle color hint.
Phase 6 made the free background presets auto-owned, so every
'Применить'-able card got the translucent overlay — and with an
animated background active, the page-wide gradient bled straight
through the content (see screenshot).
Switch to fully opaque #fff fills, keep the color cue in the border
plus a thin inner-shadow halo. Same visual signal, no bleed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A new cosmetic family: a fixed-position overlay painted behind every
page of the app, switchable from the profile shop. 4 free presets + 6
paid (250-1200 coins) so the new economy has another sink. Every
animation respects prefers-reduced-motion and falls back to its static
gradient.
Catalogue (migration 035):
free: none, gradient-soft, dots, dark
paid: gradient-flow, grid, bubbles, stars (mid)
aurora, nebula (premium)
Backend:
• migration 035 adds users.active_background + rebuilds shop_items
CHECK to include 'background' (standard SQLite 'new + copy + swap')
and seeds 10 items
• shopController.getMyActive returns { background: { slug } } and
activateItem handles type='background' (stores bare slug in
active_background) + skips the user_purchases check for price=0
so free presets work for everyone without per-user rows
• routes/shop validate schema lets 'background' through
Frontend:
• api.js applyCosmetics injects <div id='ls-bg-fx'> at body start
and toggles class to bg-<slug>. Cleared backgrounds remove the
element so dark→light transitions don't leave artifacts.
• ls.css gains a self-contained 'ANIMATED BACKGROUNDS' block:
keyframes per animated slug (ls-bg-flow, ls-bg-grid-scan,
ls-bg-bubble-rise, ls-bg-stars-twinkle, ls-bg-aurora-spin,
ls-bg-nebula-pan) wrapped in a prefers-reduced-motion kill-switch.
Same .bg-<slug> classes are reused for the .bg-preview swatches.
• profile.html shop:
- new 'Фоны' filter button between Рамки and Титулы
- _renderItemPreview type='background' draws a real 56-aspect swatch
(same CSS as the page bg — what you see is what you apply)
- _isItemActive matches by slug for background type
- free items (price===0) treated as auto-owned in render so users
can apply them without a fake 'purchase' step
Verified: getMyActive returns { background: { slug: 'nebula' } } after
flipping users.active_background; activate path updates the row.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When a teacher / admin turns off a module (per-class, per-role, or
globally), the matching achievements no longer clutter the user's
'Достижения' tab — but only the ones the user hasn't earned yet.
Already-unlocked achievements stay visible forever. We never take a
reward away after the fact.
Backend:
• migration 034 adds achievements.required_feature + backfills 42
rows (9 exam9, 8 red_book, 6 lab, 5 classroom, 4 textbooks, 3 each
of biochem/flashcards, 2 live_quiz, 2 pet). 32 core rows stay
NULL = always visible.
• middleware/features.js gains computeFeaturesForUser(userId, role)
+ isFeatureEnabledForUser — extracted from server.js#/api/features
so multiple consumers (gam achievements, future shop filter, etc.)
apply the same global+class+free_student merge.
• service.seedAchievements derives required_feature from track/group
when ACHIEVEMENT_DEFS doesn't spell one out, and UPDATE-syncs it on
every boot — keeps catalogue consistent across upgrades.
• _shared.getAllAchs SELECT now returns required_feature.
• gamification/api.getAchievements filters: drop locked rows whose
required_feature is === false for this user. Missing flag = ON
(opt-in disable model).
Verified: with exam9 + pet disabled, 12 locked achievements vanish from
the response while unlocked ones in those tracks remain.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Triples the catalogue from 10 to 32 active items so coins finally have
somewhere to land. Migration 033 seeds:
• 12 new frames at 200-1200 coin tiers (морская, лесная, закат,
минимал, винтаж, пиксельный, молния, космос, изумруд, призрак,
кибер, золотой ободок) — each with curated CSS that renders
correctly in the shop preview added in Phase 4
• 9 new titles at 150-2000 coin tiers (стажёр, аналитик, геометр,
алгебраист, физик, олимпиец, боссфайтер, магистр, профессор)
— colored pills that pair with the new title preview UI
• 1 new theme (тёплая бумага) using the existing active_theme slot
Effects are intentionally not extended in this migration — js/api.js
_applyEffect() only knows pulse/sparkle/snow today, and adding new
effect kinds belongs in a follow-up that updates the renderer in
tandem with the catalogue entries.
Re-runnable: each row is gated by WHERE NOT EXISTS (name, type) so
re-applying the migration on a partially-seeded environment is safe.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Coins were always 1:10 of XP. Now they have their own event log + a
helper that dedups by reason within a configurable window.
Backend:
• migration 032 creates coin_log (user_id, amount, reason, created_at)
with indices for the 'fired today?' check
• awardCoins now records into coin_log on every call (reason defaults
to 'xp_bonus' for the legacy XP-proportional path)
• awardCoinsOnce(userId, amount, reason, window) — fires the bonus
only if no row matches in the window:
'day' → DATE(created_at) = today
'week' → ISO week match
'forever' → never twice
Wired events (Phase 4 subset of the plan):
• Daily login — 10 coins, once/day. Hooked in updateStreak so the
bonus rides on the existing 'daily_activity' XP trigger.
• Daily goal completion — 15/25/40 coins (easy/medium/hard), once/day.
Sits next to the existing tier XP bonus in updateDailyGoal.
• Variant clear — 30 coins, once per (user, variant) forever. Fires
from the exam-prep attempts endpoint when the user's final correct
answer fills out a math9 variant.
Deferred (need invasive trigger hooks): weekly goal, paragraph close,
boss defeated, referral.
Verified end-to-end: awardCoinsOnce returns true→false on repeated
calls, coin_log records the first, coins balance moves once.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds achievement coverage for every feature shipped since the original
seed: exam-prep (math9), textbooks, classroom/board, biochemistry,
live-quiz, flashcards, hangman/crossword, pet, plus a new 'social' group
for class & leaderboard wins and 'consistency' extensions (streak_100,
goal_30, early_bird, night_owl).
74 achievements now (was 36), grouped into 7 sections:
onboarding (3) → volume (8) → mastery (16) → consistency (7) →
exam (9) → exploration (21) → social (10)
A new top-level group 'exam' slots between consistency and exploration
in the profile UI.
What's wired in service.checkPhase3Achievements (called from
checkAchievements):
• streak_100 — extends the existing streak track
• goal_30 — 30 days with daily_goals fully met (SUM check)
• early_bird / night_owl — strftime('%H', xp_log.created_at)
• exam_first / 25 / 100 — exam_attempts where is_correct=1
• exam_variant_clear / 5_variants — perfect mock-variant sessions
• exam_topic_master — ≥10 attempts at ≥90% on a single subtopic
• exam_mock_done / pass / perfect — exam_mock_sessions.score
• tb_first_para — textbook_progress
• fc_first_deck / 100_cards / 1000_cards — flashcard_reviews
• bc_first_molecule / 5_challenges / 20_challenges — bio_user_*
• game_win_5 / 25 — xp_log reason IN (hangman_win, crossword_win)
• pet_streak_7 / 30 — users.pet_petting_streak
• lq_first / 3_quizzes — live_answers grouped by session
• cr_first_join / 5 / 25_lessons — classroom_attendance
• class_5_members / 25 — teacher's biggest class
• parent_link — parent_links presence
• lb_top10 / lb_top1 — weekly XP rank among students
What's deferred (catalog entry only, no trigger yet):
• tb_chapter_done / tb_book_done / tb_3_books — need to parse
textbook_progress.paragraphs_read JSON against textbook structure
Every block is wrapped in its own try/catch so a missing table on a
legacy install can't take down the whole achievement sweep.
Verified end-to-end: admin user picked up 7 new unlocks on first
checkAchievements call after seed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Achievements gain four new columns: group_slug, track, tier, sort_order.
Existing 36 are backfilled into 5 groups (onboarding/volume/mastery/
consistency/exploration) by migration 030; 'social' stays empty until
Phase 3 adds class/leaderboard/live-quiz tracks.
Tracks bundle escalating thresholds into one progression (tests_10/50/
100 → track='tests', tiers 1-3), so the UI can show '★★★' on the top
tier and the user understands the relationship. sort_order is reserved
in blocks of 10 inside groups of 100, leaving room for inserts without
renumbering.
Backend:
• migration 030 adds the columns + index + backfill UPDATEs
• _shared.ACHIEVEMENT_DEFS gains group/track/tier/sort_order per row
• _shared exports new ACHIEVEMENT_GROUPS metadata for the UI
• service.seedAchievements writes the new fields on insert AND
backfills them via UPDATE on existing rows (fresh installs +
pre-migration installs both end up consistent)
• _shared.stmts.getAllAchs SELECT updated, ORDER BY sort_order
• gamification/api.getAchievements forwards the new fields
Frontend:
• profile.html groups achievements by group_slug with a per-section
header (icon + title + 'unlocked / total' chip) and a tier-star
badge (★★ etc.) on tier ≥ 2 items
• Hard-coded ACH_GROUPS mirror of the backend list (small, stable)
• New CSS for .ach-group / .ach-group-head / .ach-tier
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Until now the 'gamification' feature flag did nothing: it had no row in
app_settings, the admin couldn't toggle it, awardXP/awardCoins ignored
it, and the CSS only hid three dashboard widgets — XP bars in textbooks
stayed visible regardless.
Phase 1 closes every hole.
Backend (source of truth):
• migration 029 seeds feature_gamification_enabled=1
• new isGamificationEnabled() helper in gamification/_shared.js with a
30s cache + invalidateGamificationCache() for instant admin toggles
• awardXP / awardCoins / updateStreak / unlockAchievement /
checkAchievements all bail out when the flag is off
• /api/gamification/* and /api/shop/* (user routes) return 404 when
disabled; admin routes remain open so the switch itself is reachable
• adminController.updateFeatures gains 'gamification' in the allow-list
and invalidates the cache on flip
Frontend:
• LS.isGamificationEnabled() (synchronous, populated by loadFeatures)
so xp.js + applyCosmetics can bail without a round-trip
• xp.js load/add/flush become no-ops when the flag is off
• applyCosmetics skips the round-trip when off
• CSS .no-gamification rule expanded to cover .hero-xp-badge, .po-xp,
.xp-card, .xp-bar, #frames-section, and a universal [data-gamified]
hook for future blocks
Textbooks (Variant 2 of the plan):
• backend/scripts/wrap_textbook_xp.py — idempotent script that adds
data-gamified to 167 XP tags across 63 textbook files (chapters +
hubs, all subjects/grades). Single CSS rule now hides everything.
Verified end-to-end: with the flag off, awardXP/awardCoins write nothing;
flipping back restores normal behavior.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- ch8 — индиго-тема (--pri:#4f46e5), watermark ∞/★
- §45: эволюция картины мира (механика → ЭМ → СТО → ОТО → кванты → Стандартная модель), иерархия материи (от кварков до Вселенной), открытые проблемы (тёмная материя, тёмная энергия, объединение теорий)
- ФИНАЛ КУРСА: 12 интегральных боссов по всем 8 главам
- Босс I: Колебания (Гл. 1)
- Босс II: ЭМ-индукция (Гл. 2)
- Боссы III-IV: Оптика (Гл. 3, §14-§17 и §18-§23)
- Босс V: СТО (Гл. 4)
- Босс VI: Фотоны (Гл. 5)
- Боссы VII-VIII: Атом + Лазеры (Гл. 6)
- Боссы IX-XI: Ядерная физика (Гл. 7)
- Босс XII: Элем. частицы + картина мира
- Каждый босс 5 этапов, +80 XP
- При победе всех 12: ачивка phys11_master 'МАГИСТР ФИЗИКИ 11' + 500 XP бонус
- КУРС ФИЗИКИ 11 КЛАССА ЗАВЕРШЁН: 8 глав, 45 параграфов, ~80 боссов, 9 финальных ачивок
§34 «Электрический ток в металлах. Сверхпроводимость»:
- 3 makeCard: природа тока, R(t) для металлов, сверхпроводимость
- IV1: симуляция дрейфа электронов в решётке (SVG, slider U)
- IV2: график R(t) = R_0(1 + alpha t), переключение материалов + скачок T_c
- IV3: квикфайр на носителей заряда в средах (6 вопросов)
- IV4: тренажёр 5 задач (rho L/S, R при разных T, T_c ртути)
§35 «Электрический ток в электролитах. Электролиз»:
- 3 makeCard: электролиты/ионы, законы Фарадея, применение
- IV1: симуляция электролиза (катионы → катоду, анионы → аноду)
- IV2: калькулятор массы m = MIt/(Fn) для Cu/Ag/Al/Fe/H
- IV3: квикфайр направления ионов (6 вопросов, 2 кнопки)
- IV4: тренажёр 5 задач (расчёт m для Cu/Ag, F = 96500)
§10 Производство и передача электроэнергии:
- ТЭС/ГЭС/АЭС; формула потерь P=I²R
- Идея высоковольтных ЛЭП: чтобы уменьшить потери, повышают U
- Магистральные ЛЭП до 750 кВ → 220 В у потребителя
- 5 расчётов (включая повышение U в k раз → потери /k²)
- Босс §10: 5 этапов, +70 XP
§11 Экологические проблемы:
- ВИЭ: ВЭС, СЭС, ГеоТЭС, приливные, биогаз
- Достоинства (без CO₂) и недостатки (погода, площадь)
- 6+5 квизов на типы и плюсы/минусы
- Босс §11: 5 этапов, +70 XP
§12 ЭМ волны. Шкала ЭМ волн:
- ЭМ волна как поперечная, c = 1/√(ε₀μ₀) = 3·10⁸ м/с
- Inline SVG-шкала: радио/СВЧ/ИК/видимый/УФ/рентген/γ
с радужным градиентом для видимого света
- 5 расчётов λ↔ν + 5 MC на диапазоны
- Босс §12: 5 этапов, +70 XP
§13 Действие ЭМ на живые организмы:
- Ионизирующее (>10 эВ: УФ-С, рентген, γ) vs неионизирующее
- Полезные применения и опасности
- Защита: экранирование (свинец), расстояние, время
- Босс §13: 5 этапов, +65 XP
Финал главы 2:
- 4 интегральных босса (LC+ток, трансф+ЛЭП, ЭМ волны, сборная)
- Celebration: ачивка phys11_ch2_master + 100 XP бонус
Файл 63 → 91 КБ. JS валидируется.
Самый большой план проекта:
- 8 глав, 45 параграфов
- Новая библиотека phys-fx.js (~1000 строк): осциллограммы, маятники,
волны, LC-контуры, RayTracer (линзы/зеркала/призмы), фотоэффект,
атом Бора, спектры, ядро, радиоактивный распад, цепная реакция
- 8 цветовых тем по главам (cyan/violet/amber/sky/yellow/emerald/red/indigo)
- ~92 босса, ~135 квизов, 9 ачивок (включая phys11_master)
- 9 лабораторных работ — отдельная страница
- 16 волн реализации (~28 сессий) — крупнейший курс проекта
- Стиль единый с geom11_ch1 / geom10_r1 (2-кол layout, psel-grid, wg)
- Глобальный RAF-таймер для экономии CPU при 5-10 симуляциях на странице
- IntersectionObserver для паузы невидимых симуляций