diff --git a/frontend/js/lab-previews.js b/frontend/js/lab-previews.js
index 6c5ae56..8cfc58d 100644
--- a/frontend/js/lab-previews.js
+++ b/frontend/js/lab-previews.js
@@ -1,12 +1,16 @@
'use strict';
/*
- * LabPreviews — реальные SVG-превью симуляций (зеркало P_* из labs/lab-glue.js)
- * для карточки «Лаборатория дня» на дашборде. Тёмные тайлы 270×140.
- * Источник истины — lab-glue.js; здесь лёгкая копия, чтобы не грузить весь
- * движок лаборатории на дашборде.
+ * lab-previews.js — ЕДИНЫЙ источник SVG-превью симуляций лаборатории.
+ * Вынесено из lab-glue.js, чтобы превью были доступны и на /lab (карточки),
+ * и на дашборде («Лаборатория дня»), без загрузки тяжёлого lab-glue.js.
+ *
+ * window.LabPreviews — карта id симуляции -> SVG-строка (для дашборда/реестра).
+ * window.__LabP — те же превью по имени P_* (lab-glue.js берёт их отсюда).
+ *
+ * Грузить ПЕРЕД lab-glue.js (на /lab) и на дашборде.
*/
(function () {
- function _grid(fg='rgba(255,255,255,0.06)') {
+function _grid(fg='rgba(255,255,255,0.06)') {
return `
@@ -15,23 +19,139 @@
`;
}
-
+ function _axes() {
+ return `
+
+
+ `;
+ }
function _svg(body) {
- return `
+ return `
${body} `;
}
- const P_LENS = _svg(`${_grid('rgba(255,255,255,0.04)')}
-
-
-
-
-
-
-
-
- `);
+ /* 1 — Graph */
+ const P_GRAPH = _svg(`${_grid()}${_axes()}
+
+ `);
+ /* 2 — Transform: three shifted/scaled sines */
+ const P_TRANSFORM = _svg(`${_grid()}${_axes()}
+
+
+ `);
+
+ /* 3 — Triangle geometry */
+ const P_TRIANGLE = _svg(`${_grid('rgba(255,255,255,0.04)')}
+
+
+
+
+
+ `);
+
+ /* 4 — Inscribed/circumscribed circles */
+ const P_CIRCLES = _svg(`${_grid('rgba(255,255,255,0.04)')}
+
+
+
+
+ `);
+
+ /* 5 — Quadratic roots: parabola crossing x-axis */
+ const P_QUADRATIC = _svg(`${_grid()}${_axes()}
+
+
+
+
+
+ D = b²− 4ac `);
+
+ /* 6 — 3D geometry: isometric cube */
+ const P_3D = _svg(`${_grid('rgba(255,255,255,0.04)')}
+
+
+
+
+ V = a³ `);
+
+ /* 7 — Probability: histogram bars */
+ const P_PROB = _svg(`${_grid()}
+
+
+
+
+
+
+
+
+ `);
+
+ /* 8 — Normal distribution: bell curve */
+ const P_NORMAL = _svg(`${_grid()}
+
+
+
+
+ μ = 0, σ = 1 `);
+
+ /* 8b — Trig circle */
+ const P_TRIGCIRCLE = _svg(`${_grid('rgba(255,255,255,0.04)')}
+
+
+
+
+
+
+
+
+ sin · cos · tg · ctg `);
+
+ /* 9 — Projectile motion */
+ const P_PROJECTILE = _svg(`${_grid('rgba(255,255,255,0.04)')}
+
+
+
+
+
+
+
+
+ x = v₀cos(α)·t `);
+
+ /* 10 — Pendulum */
+ const P_PENDULUM = _svg(`${_grid('rgba(255,255,255,0.04)')}
+
+
+
+
+
+
+ T = 2π√(l/g) `);
+
+ /* 11 — Collision */
+ const P_COLLISION = _svg(`${_grid('rgba(255,255,255,0.04)')}
+
+
+ m₁
+
+
+ m₂
+
+
+
+
+ `);
+
+
+ /* 13 — Electric circuit */
const P_CIRCUIT = _svg(`${_grid('rgba(255,255,255,0.04)')}
@@ -45,25 +165,95 @@
I = U/R `);
- const P_PENDULUM = _svg(`${_grid('rgba(255,255,255,0.04)')}
-
-
-
-
-
-
- T = 2π√(l/g) `);
+ /* 14 — Magnetic field */
+ const P_MAGNETIC = _svg(`
+
+ ${_grid('rgba(155,93,229,0.06)')}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ B = μ₀I / 2πr `);
- const P_WAVES = _svg(`${_grid()}
-
-
-
-
- v = \u03bbf \u00b7 y = A sin(\u03c9t \u2212 kx) \u00b7 \u0441\u0442\u043e\u044f\u0447\u0438\u0435 \u0432\u043e\u043b\u043d\u044b `);
+ /* 14 — Electric field lines */
+ const P_FIELD = _svg(`${_grid('rgba(255,255,255,0.04)')}
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+ `);
+ /* 15 — Thin lens */
+ const P_LENS = _svg(`${_grid('rgba(255,255,255,0.04)')}
+
+
+
+
+
+
+
+
+ `);
+
+ /* 16 — Refraction */
+ const P_REFRACTION = _svg(`
+
+
+
+
+
+
+
+
+
+
+ α
+ β
+ n₁sinα = n₂sinβ `);
+
+ /* 17 — Mirrors */
+ const P_MIRROR = _svg(`${_grid('rgba(255,255,255,0.04)')}
+
+
+
+
+
+
+
+
+ F
+
+
+
+
+
+
+
+ `);
+
+ /* 18 — Isoprocesses */
const P_ISOPROCESS = _svg(`${_grid('rgba(255,255,255,0.04)')}
@@ -79,15 +269,506 @@
V
P `);
- const P_3D = _svg(`${_grid('rgba(255,255,255,0.04)')}
-
-
-
-
- V = a³ `);
+ /* ── Chemistry / Molecular Physics previews ── */
+ const P_GAS = _svg(`
+
+
+ ${[
+ [40,30,'#4CC9F0'],[70,80,'#7BF5A4'],[110,25,'#EF476F'],[150,60,'#FFD166'],[190,30,'#4CC9F0'],
+ [220,90,'#EF476F'],[55,110,'#7BF5A4'],[95,65,'#4CC9F0'],[130,110,'#EF476F'],[170,40,'#FFD166'],
+ [210,115,'#4CC9F0'],[240,55,'#7BF5A4'],[30,70,'#FFD166'],[80,120,'#EF476F'],[165,95,'#4CC9F0']
+ ].map(([x,y,c])=>` `).join('')}
+
+
+
+
+
+
+
+ PV=nRT `);
+
+ /* ── Законы Ньютона ── */
+ const P_NEWTON = _svg(`
+
+
+
+
+
+ F
+
+
+
+ m₂
+
+
+ a = F/m · III законы Ньютона `);
+
+ /* ── Песочница сил ── */
+ const P_SANDBOX = _svg(`
+
+ ${_grid('rgba(255,255,255,0.03)')}
+
+
+ 5кг
+
+ 8кг
+
+
+
+
+
+
+ F₁
+ F₂
+ Песочница сил · F = ma `);
+
+ const P_HYDRO = _svg(`
+
+ ${_grid('rgba(255,255,255,0.03)')}
+
+
+
+
+ P = ρgh
+
+
+
+ F_A
+
+
+
+
+
+
+
+
+ Δh
+
+
+
+
+
+
+
+
+
+ Архимед · Паскаль · капиллярность `);
+
+ /* ── coming soon chem previews (simple) ── */
+ const P_KINETICS = _svg(`
+
+ ${_grid()}
+
+
+
+
+ [C] продукт
+ [A] реагент `);
+
+ const P_EQUILIBRIUM = _svg(`
+
+ A + B ⇌ C + D
+
+
+
+ A,B
+ K
+ C,D `);
+
+ const P_ELECTROLYSIS = _svg(`
+
+
+
+
+ ${[55,58,61,64,67,70].map(x=>` `).join('')}
+ ${[210,214,218,222,226].map(x=>` `).join('')}
+ −
+ + `);
+
+ const P_BOHR = _svg(`
+
+
+
+
+
+
+
+
+
+ `);
+
+ const P_ORBITALS = _svg(`
+
+
+
+
+
+ `);
+
+ const P_PH = _svg(`
+
+ ${_grid()}
+
+
+ pH
+ V `);
+
+ const P_CHEMSANDBOX = _svg(`
+
+ ${_grid()}
+
+
+
+
+
+ A + B C + D
+
+
+
+
+
+
+
+ `);
+
+ const P_STOICHIOMETRY = _svg(`
+
+ ${_grid()}
+
+
+
+
+
+ Zn
+
+
+
+
+
+
+ 2HCl
+ →
+
+
+
+
+
+ ZnCl₂
+
+
+
+ H₂
+ ● лимит `);
+
+ /* Periodic Table — 6×4 coloured cell grid */
+ const P_PERIODIC = _svg(`
+
+ ${(function(){
+ const cols=18,rows=4,pad=6,w=(270-pad*2)/cols,h=(140-pad*2)/rows;
+ const colors=['#EF476F','#FF6B35','#FFD166','#7BF5A4','#C77DFF','#A8DADC',
+ '#7B8EF7','#06D6E0','#9B5DE5','#F15BB5','#EF476F','#FF6B35',
+ '#06D6E0','#7B8EF7','#FFD166','#C77DFF','#A8DADC','#7BF5A4'];
+ let s='';
+ for(let r=0;r=2&&c<=15)||(r===1&&c>=2&&c<=11);
+ if(!skip) s+=` `;
+ }
+ return s;
+ })()}
+ 118 элементов `);
+
+ const P_CRYSTAL = _svg(`
+
+ ${[
+ [80,40],[135,40],[190,40],
+ [55,75],[110,75],[165,75],[220,75],
+ [80,110],[135,110],[190,110]
+ ].map(([x,y],i)=>` `).join('')}
+
+
+
+
+
+
+
+
+
+
+ `);
+
+ const P_CELLDIVISION = _svg(`
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Метафаза · митоз `);
+
+ const P_PHOTOSYNTHESIS = _svg(`
+
+
+
+
+
+
+
+
+
+
+
+ H₂O
+ CO₂
+ ATP
+ G3P
+ Световые реакции · цикл Кальвина `);
+
+ const P_ANGRYBIRDS = _svg(`
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Физика полёта · импульс · разрушение `);
+
+ const P_WAVES = _svg(`${_grid()}
+
+
+
+
+ v = \u03bbf \u00b7 y = A sin(\u03c9t \u2212 kx) \u00b7 \u0441\u0442\u043e\u044f\u0447\u0438\u0435 \u0432\u043e\u043b\u043d\u044b `);
+
+ /* Radioactive decay preview */
+ const P_RADIOACTIVE = _svg(`${_grid()}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ N(t) = N₀·e⁻λt · T½ · цепочки распада `);
+
+ /* Heat Engines preview */
+ const P_HEATENGINE = _svg(`${_grid('rgba(255,255,255,0.04)')}
+
+
+
+
+
+
+
+
+
+ A
+ B
+ C
+ V
+ P
+ η = 1 − Tc/Th `);
+
+ /* Geometry (planimetry) preview */
+ const P_GEOMETRY = _svg(`${_grid('rgba(255,255,255,0.04)')}
+
+
+
+
+
+
+
+
+
+ A
+ B
+ C `);
+
+
+ /* Race sim preview — two objects on a track, x(t) lines */
+ const P_RACE = _svg(`${_grid('rgba(255,255,255,0.05)')}
+
+
+
+
+
+
+
+ встреча
+ x = x₀ + v₀t + at²/2 `);
+
+ /* Logic Circuits preview */
+ const P_LOGIC = _svg(`${_grid('rgba(255,255,255,0.04)')}
+
+ AND
+
+ XOR
+
+ AND
+
+
+
+
+
+
+
+
+
+
+ S
+ C
+ S = A⊕B · C = A∧B · Таблица истинности`);
+
+
+ /* Qualitative Analysis preview */
+ const P_QUALANALYSIS = _svg(`
+
+
+
+
+
+
+
+
+
+
+ Cl
+ Fe(III)
+ SO4
+ AgNO3
+
+
+
+ AgCl / Fe(SCN) / BaSO4`);
+
+ /* Organic Chemistry preview — benzene ring + OH group */
+ const P_ORGANIC = _svg(`
+
+ ${_grid('rgba(255,255,255,0.03)')}
+
+
+
+
+
+ C
+ C
+ C
+ C
+ C
+ C
+
+
+
+ O
+
+
+ H
+
+
+
+ C
+ Конструктор · Ряды · Качественные реакции `);
+
+ /* Solutions preview */
+ const P_SOLUTIONS = _svg(`
+
+
+
+
+
+
+ 20%
+
+
+ ω%
+ C-M
+ ν моль
+ ω = m₀/m · 100%
+ Калькулятор · Разбавление · Смешивание · S(T) `);
+
+ // Экспорт по имени P_* (для lab-glue.js)
+ window.__LabP = { P_GRAPH, P_TRANSFORM, P_TRIANGLE, P_CIRCLES, P_QUADRATIC, P_3D, P_PROB, P_NORMAL, P_TRIGCIRCLE, P_PROJECTILE, P_PENDULUM, P_COLLISION, P_CIRCUIT, P_MAGNETIC, P_FIELD, P_LENS, P_REFRACTION, P_MIRROR, P_ISOPROCESS, P_GAS, P_NEWTON, P_SANDBOX, P_HYDRO, P_KINETICS, P_EQUILIBRIUM, P_ELECTROLYSIS, P_BOHR, P_ORBITALS, P_PH, P_CHEMSANDBOX, P_STOICHIOMETRY, P_PERIODIC, P_CRYSTAL, P_CELLDIVISION, P_PHOTOSYNTHESIS, P_ANGRYBIRDS, P_WAVES, P_RADIOACTIVE, P_HEATENGINE, P_GEOMETRY, P_RACE, P_LOGIC, P_QUALANALYSIS, P_ORGANIC, P_SOLUTIONS };
+
+ // Экспорт по id симуляции (для дашборда и реестра)
window.LabPreviews = {
- opticsbench: P_LENS, circuit: P_CIRCUIT, pendulum: P_PENDULUM,
- waves: P_WAVES, isoprocess: P_ISOPROCESS, stereo: P_3D,
+ "graph": P_GRAPH,
+ "graphtransform": P_TRANSFORM,
+ "geometry": P_GEOMETRY,
+ "triangle": P_TRIANGLE,
+ "quadratic": P_QUADRATIC,
+ "stereo": P_3D,
+ "probability": P_PROB,
+ "trigcircle": P_TRIGCIRCLE,
+ "normaldist": P_NORMAL,
+ "projectile": P_PROJECTILE,
+ "pendulum": P_PENDULUM,
+ "collision": P_COLLISION,
+ "emfield": P_MAGNETIC,
+ "circuit": P_CIRCUIT,
+ "hydrostatics": P_HYDRO,
+ "dynamics": P_SANDBOX,
+ "opticsbench": P_LENS,
+ "isoprocess": P_ISOPROCESS,
+ "waves": P_WAVES,
+ "radioactive": P_RADIOACTIVE,
+ "race": P_RACE,
+ "heatengine": P_HEATENGINE,
+ "logic": P_LOGIC,
+ "molphys": P_GAS,
+ "chemistry": P_KINETICS,
+ "equilibrium": P_EQUILIBRIUM,
+ "electrolysis": P_ELECTROLYSIS,
+ "bohratom": P_BOHR,
+ "orbitals": P_ORBITALS,
+ "titration": P_PH,
+ "chemsandbox": P_CHEMSANDBOX,
+ "stoichiometry": P_STOICHIOMETRY,
+ "crystal": P_CRYSTAL,
+ "qualanalysis": P_QUALANALYSIS,
+ "periodic": P_PERIODIC,
+ "organic": P_ORGANIC,
+ "solutions": P_SOLUTIONS,
+ "celldivision": P_CELLDIVISION,
+ "photosynthesis": P_PHOTOSYNTHESIS,
+ "angrybirds": P_ANGRYBIRDS
};
})();
diff --git a/frontend/js/labs/lab-glue.js b/frontend/js/labs/lab-glue.js
index 3317a05..b32c547 100644
--- a/frontend/js/labs/lab-glue.js
+++ b/frontend/js/labs/lab-glue.js
@@ -49,725 +49,14 @@
if (window.lucide) lucide.createIcons();
}
- /* ════════════════════════════════
- CARD PREVIEW SVGs
+ /* ════════════════════════════════
+ CARD PREVIEW SVGs — вынесены в /js/lab-previews.js (единый источник).
+ Берём их по имени из window.__LabP; SIMS ниже ссылается на эти алиасы.
════════════════════════════════ */
- function _grid(fg='rgba(255,255,255,0.06)') {
- return `
-
-
-
-
-
- `;
- }
- function _axes() {
- return `
-
-
- `;
- }
- function _svg(body) {
- return `
- ${body} `;
- }
+ var __LP = window.__LabP || {};
+ var P_GRAPH = __LP.P_GRAPH, P_TRANSFORM = __LP.P_TRANSFORM, P_TRIANGLE = __LP.P_TRIANGLE, P_CIRCLES = __LP.P_CIRCLES, P_QUADRATIC = __LP.P_QUADRATIC, P_3D = __LP.P_3D, P_PROB = __LP.P_PROB, P_NORMAL = __LP.P_NORMAL, P_TRIGCIRCLE = __LP.P_TRIGCIRCLE, P_PROJECTILE = __LP.P_PROJECTILE, P_PENDULUM = __LP.P_PENDULUM, P_COLLISION = __LP.P_COLLISION, P_CIRCUIT = __LP.P_CIRCUIT, P_MAGNETIC = __LP.P_MAGNETIC, P_FIELD = __LP.P_FIELD, P_LENS = __LP.P_LENS, P_REFRACTION = __LP.P_REFRACTION, P_MIRROR = __LP.P_MIRROR, P_ISOPROCESS = __LP.P_ISOPROCESS, P_GAS = __LP.P_GAS, P_NEWTON = __LP.P_NEWTON, P_SANDBOX = __LP.P_SANDBOX, P_HYDRO = __LP.P_HYDRO, P_KINETICS = __LP.P_KINETICS, P_EQUILIBRIUM = __LP.P_EQUILIBRIUM, P_ELECTROLYSIS = __LP.P_ELECTROLYSIS, P_BOHR = __LP.P_BOHR, P_ORBITALS = __LP.P_ORBITALS, P_PH = __LP.P_PH, P_CHEMSANDBOX = __LP.P_CHEMSANDBOX, P_STOICHIOMETRY = __LP.P_STOICHIOMETRY, P_PERIODIC = __LP.P_PERIODIC, P_CRYSTAL = __LP.P_CRYSTAL, P_CELLDIVISION = __LP.P_CELLDIVISION, P_PHOTOSYNTHESIS = __LP.P_PHOTOSYNTHESIS, P_ANGRYBIRDS = __LP.P_ANGRYBIRDS, P_WAVES = __LP.P_WAVES, P_RADIOACTIVE = __LP.P_RADIOACTIVE, P_HEATENGINE = __LP.P_HEATENGINE, P_GEOMETRY = __LP.P_GEOMETRY, P_RACE = __LP.P_RACE, P_LOGIC = __LP.P_LOGIC, P_QUALANALYSIS = __LP.P_QUALANALYSIS, P_ORGANIC = __LP.P_ORGANIC, P_SOLUTIONS = __LP.P_SOLUTIONS;
- /* 1 — Graph */
- const P_GRAPH = _svg(`${_grid()}${_axes()}
-
- `);
-
- /* 2 — Transform: three shifted/scaled sines */
- const P_TRANSFORM = _svg(`${_grid()}${_axes()}
-
-
- `);
-
- /* 3 — Triangle geometry */
- const P_TRIANGLE = _svg(`${_grid('rgba(255,255,255,0.04)')}
-
-
-
-
-
- `);
-
- /* 4 — Inscribed/circumscribed circles */
- const P_CIRCLES = _svg(`${_grid('rgba(255,255,255,0.04)')}
-
-
-
-
- `);
-
- /* 5 — Quadratic roots: parabola crossing x-axis */
- const P_QUADRATIC = _svg(`${_grid()}${_axes()}
-
-
-
-
-
- D = b²− 4ac `);
-
- /* 6 — 3D geometry: isometric cube */
- const P_3D = _svg(`${_grid('rgba(255,255,255,0.04)')}
-
-
-
-
- V = a³ `);
-
- /* 7 — Probability: histogram bars */
- const P_PROB = _svg(`${_grid()}
-
-
-
-
-
-
-
-
- `);
-
- /* 8 — Normal distribution: bell curve */
- const P_NORMAL = _svg(`${_grid()}
-
-
-
-
- μ = 0, σ = 1 `);
-
- /* 8b — Trig circle */
- const P_TRIGCIRCLE = _svg(`${_grid('rgba(255,255,255,0.04)')}
-
-
-
-
-
-
-
-
- sin · cos · tg · ctg `);
-
- /* 9 — Projectile motion */
- const P_PROJECTILE = _svg(`${_grid('rgba(255,255,255,0.04)')}
-
-
-
-
-
-
-
-
- x = v₀cos(α)·t `);
-
- /* 10 — Pendulum */
- const P_PENDULUM = _svg(`${_grid('rgba(255,255,255,0.04)')}
-
-
-
-
-
-
- T = 2π√(l/g) `);
-
- /* 11 — Collision */
- const P_COLLISION = _svg(`${_grid('rgba(255,255,255,0.04)')}
-
-
- m₁
-
-
- m₂
-
-
-
-
- `);
-
-
- /* 13 — Electric circuit */
- const P_CIRCUIT = _svg(`${_grid('rgba(255,255,255,0.04)')}
-
-
-
- R₁
-
-
- R₂
-
-
-
- I = U/R `);
-
- /* 14 — Magnetic field */
- const P_MAGNETIC = _svg(`
-
- ${_grid('rgba(155,93,229,0.06)')}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- B = μ₀I / 2πr `);
-
- /* 14 — Electric field lines */
- const P_FIELD = _svg(`${_grid('rgba(255,255,255,0.04)')}
-
- +
-
-
-
-
-
-
-
-
-
-
-
- `);
-
- /* 15 — Thin lens */
- const P_LENS = _svg(`${_grid('rgba(255,255,255,0.04)')}
-
-
-
-
-
-
-
-
- `);
-
- /* 16 — Refraction */
- const P_REFRACTION = _svg(`
-
-
-
-
-
-
-
-
-
-
- α
- β
- n₁sinα = n₂sinβ `);
-
- /* 17 — Mirrors */
- const P_MIRROR = _svg(`${_grid('rgba(255,255,255,0.04)')}
-
-
-
-
-
-
-
-
- F
-
-
-
-
-
-
-
- `);
-
- /* 18 — Isoprocesses */
- const P_ISOPROCESS = _svg(`${_grid('rgba(255,255,255,0.04)')}
-
-
-
-
-
-
-
-
-
- 2
- 1
- V
- P `);
-
- /* ── Chemistry / Molecular Physics previews ── */
- const P_GAS = _svg(`
-
-
- ${[
- [40,30,'#4CC9F0'],[70,80,'#7BF5A4'],[110,25,'#EF476F'],[150,60,'#FFD166'],[190,30,'#4CC9F0'],
- [220,90,'#EF476F'],[55,110,'#7BF5A4'],[95,65,'#4CC9F0'],[130,110,'#EF476F'],[170,40,'#FFD166'],
- [210,115,'#4CC9F0'],[240,55,'#7BF5A4'],[30,70,'#FFD166'],[80,120,'#EF476F'],[165,95,'#4CC9F0']
- ].map(([x,y,c])=>` `).join('')}
-
-
-
-
-
-
-
- PV=nRT `);
-
-
- /* ── Законы Ньютона ── */
- const P_NEWTON = _svg(`
-
-
-
-
-
- F
-
-
-
- m₂
-
-
- a = F/m · III законы Ньютона `);
-
- /* ── Песочница сил ── */
- const P_SANDBOX = _svg(`
-
- ${_grid('rgba(255,255,255,0.03)')}
-
-
- 5кг
-
- 8кг
-
-
-
-
-
-
- F₁
- F₂
- Песочница сил · F = ma `);
-
- const P_HYDRO = _svg(`
-
- ${_grid('rgba(255,255,255,0.03)')}
-
-
-
-
- P = ρgh
-
-
-
- F_A
-
-
-
-
-
-
-
-
- Δh
-
-
-
-
-
-
-
-
-
- Архимед · Паскаль · капиллярность `);
-
- /* ── coming soon chem previews (simple) ── */
- const P_KINETICS = _svg(`
-
- ${_grid()}
-
-
-
-
- [C] продукт
- [A] реагент `);
-
- const P_EQUILIBRIUM = _svg(`
-
- A + B ⇌ C + D
-
-
-
- A,B
- K
- C,D `);
-
- const P_ELECTROLYSIS = _svg(`
-
-
-
-
- ${[55,58,61,64,67,70].map(x=>` `).join('')}
- ${[210,214,218,222,226].map(x=>` `).join('')}
- −
- + `);
-
- const P_BOHR = _svg(`
-
-
-
-
-
-
-
-
-
- `);
-
- const P_ORBITALS = _svg(`
-
-
-
-
-
- `);
-
- const P_PH = _svg(`
-
- ${_grid()}
-
-
- pH
- V `);
-
- const P_CHEMSANDBOX = _svg(`
-
- ${_grid()}
-
-
-
-
-
- A + B C + D
-
-
-
-
-
-
-
- `);
-
- const P_STOICHIOMETRY = _svg(`
-
- ${_grid()}
-
-
-
-
-
- Zn
-
-
-
-
-
-
- 2HCl
- →
-
-
-
-
-
- ZnCl₂
-
-
-
- H₂
- ● лимит `);
-
- /* Periodic Table — 6×4 coloured cell grid */
- const P_PERIODIC = _svg(`
-
- ${(function(){
- const cols=18,rows=4,pad=6,w=(270-pad*2)/cols,h=(140-pad*2)/rows;
- const colors=['#EF476F','#FF6B35','#FFD166','#7BF5A4','#C77DFF','#A8DADC',
- '#7B8EF7','#06D6E0','#9B5DE5','#F15BB5','#EF476F','#FF6B35',
- '#06D6E0','#7B8EF7','#FFD166','#C77DFF','#A8DADC','#7BF5A4'];
- let s='';
- for(let r=0;r=2&&c<=15)||(r===1&&c>=2&&c<=11);
- if(!skip) s+=` `;
- }
- return s;
- })()}
- 118 элементов `);
-
- const P_CRYSTAL = _svg(`
-
- ${[
- [80,40],[135,40],[190,40],
- [55,75],[110,75],[165,75],[220,75],
- [80,110],[135,110],[190,110]
- ].map(([x,y],i)=>` `).join('')}
-
-
-
-
-
-
-
-
-
-
- `);
-
- const P_CELLDIVISION = _svg(`
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Метафаза · митоз `);
-
- const P_PHOTOSYNTHESIS = _svg(`
-
-
-
-
-
-
-
-
-
-
-
- H₂O
- CO₂
- ATP
- G3P
- Световые реакции · цикл Кальвина `);
-
- const P_ANGRYBIRDS = _svg(`
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Физика полёта · импульс · разрушение `);
-
- const P_WAVES = _svg(`${_grid()}
-
-
-
-
- v = \u03bbf \u00b7 y = A sin(\u03c9t \u2212 kx) \u00b7 \u0441\u0442\u043e\u044f\u0447\u0438\u0435 \u0432\u043e\u043b\u043d\u044b `);
-
- /* Radioactive decay preview */
- const P_RADIOACTIVE = _svg(`${_grid()}
-
-
-
-
-
-
-
-
-
-
-
-
-
- N(t) = N₀·e⁻λt · T½ · цепочки распада `);
-
- /* Heat Engines preview */
- const P_HEATENGINE = _svg(`${_grid('rgba(255,255,255,0.04)')}
-
-
-
-
-
-
-
-
-
- A
- B
- C
- V
- P
- η = 1 − Tc/Th `);
-
- /* Geometry (planimetry) preview */
- const P_GEOMETRY = _svg(`${_grid('rgba(255,255,255,0.04)')}
-
-
-
-
-
-
-
-
-
- A
- B
- C `);
-
-
- /* Race sim preview — two objects on a track, x(t) lines */
- const P_RACE = _svg(`${_grid('rgba(255,255,255,0.05)')}
-
-
-
-
-
-
-
- встреча
- x = x₀ + v₀t + at²/2 `);
-
- /* Logic Circuits preview */
- const P_LOGIC = _svg(`${_grid('rgba(255,255,255,0.04)')}
-
- AND
-
- XOR
-
- AND
-
-
-
-
-
-
-
-
-
-
- S
- C
- S = A⊕B · C = A∧B · Таблица истинности`);
-
-
- /* Qualitative Analysis preview */
- const P_QUALANALYSIS = _svg(`
-
-
-
-
-
-
-
-
-
-
- Cl
- Fe(III)
- SO4
- AgNO3
-
-
-
- AgCl / Fe(SCN) / BaSO4`);
-
- /* Organic Chemistry preview — benzene ring + OH group */
- const P_ORGANIC = _svg(`
-
- ${_grid('rgba(255,255,255,0.03)')}
-
-
-
-
-
- C
- C
- C
- C
- C
- C
-
-
-
- O
-
-
- H
-
-
-
- C
- Конструктор · Ряды · Качественные реакции `);
-
- /* Solutions preview */
- const P_SOLUTIONS = _svg(`
-
-
-
-
-
-
- 20%
-
-
- ω%
- C-M
- ν моль
- ω = m₀/m · 100%
- Калькулятор · Разбавление · Смешивание · S(T) `);
-
- const SIMS = [
+const SIMS = [
/* ── Математика ── */
{ id: 'graph', cat: 'math',
title: 'График функции',
diff --git a/frontend/lab.html b/frontend/lab.html
index abc74da..2c6ea77 100644
--- a/frontend/lab.html
+++ b/frontend/lab.html
@@ -425,6 +425,7 @@
+