diff --git a/frontend/biochem.html b/frontend/biochem.html
index a6dec9b..eb94541 100644
--- a/frontend/biochem.html
+++ b/frontend/biochem.html
@@ -1925,21 +1925,53 @@ function renderBalanceChallenge(data) {
wrap.style.display = '';
const reactants = data.reactants || [];
const products = data.products || [];
- const count = reactants.length + products.length;
+ wrap._reactants = reactants;
+ wrap._products = products;
let html = '
';
+ // живая поэлементная проверка сохранения атомов
+ html += '';
wrap.innerHTML = html;
+ updateBalanceFeedback();
+}
+
+// Живой счётчик атомов слева/справа по каждому элементу (через BIO.parseFormula)
+function updateBalanceFeedback() {
+ const wrap = document.getElementById('bp-chal-balance');
+ const fb = document.getElementById('bal-feedback');
+ if (!wrap || !fb || !window.BIO) return;
+ const reactants = wrap._reactants || [], products = wrap._products || [];
+ const coefs = Array.from(wrap.querySelectorAll('.bal-coef')).map(i => parseInt(i.value) || 0);
+ const sideCounts = (formulas, offset) => {
+ const tot = {};
+ formulas.forEach((f, i) => {
+ const k = coefs[offset + i] || 0;
+ const c = BIO.parseFormula(f);
+ for (const el in c) tot[el] = (tot[el] || 0) + c[el] * k;
+ });
+ return tot;
+ };
+ const L = sideCounts(reactants, 0);
+ const R = sideCounts(products, reactants.length);
+ const els = [...new Set([...Object.keys(L), ...Object.keys(R)])].sort();
+ let allOk = els.length > 0;
+ fb.innerHTML = els.map(el => {
+ const l = L[el] || 0, r = R[el] || 0, ok = l === r;
+ if (!ok) allOk = false;
+ const col = ok ? '#4ade80' : '#f87171';
+ return `${el}: ${l}=${r} ${ok ? '✓' : '✗'}`;
+ }).join('') + (allOk ? 'сбалансировано' : '');
}
// Keyboard shortcuts