${esc(c.name)}`).join(""):`
нет управления`;const I=(ins||[]).map(a=>`
${esc(a.name)}`).join("")||'
—';const O=(outs||[]).map(a=>`
${esc(a.name)}${a.target==='НИКУДА'?' ⊘':''}`).join("")||'
—';const M=(me||[]).map(x=>`
${esc(x.name)}`).join("")||'
—';return `
${C}
${I}
${id?`${id}`:''}${esc(fn)}${pct!=null?`${pct}%`:''}
${O}
${M}
`};let h=`
Паттерн: ${esc(m.business_pattern)}
`;if(m.context)h+=`
A-0 Контекст
`+box(m.context.function,m.context.controls,m.context.inputs,m.context.outputs,m.context.mechanisms,"A0");h+=`
Декомпозиция · ${m.activities.length}
`;m.activities.forEach(a=>h+=box(a.function,a.controls,a.inputs,a.outputs,a.mechanisms,a.node_id,a.completeness));if(m.arrow_issues&&m.arrow_issues.length){h+=`
Разрывы · ${m.arrow_issues.length}
`;m.arrow_issues.forEach(g=>{const col=g.severity==='critical'?'#DC2626':g.severity==='high'?'#92400E':'#1E40AF';h+=`
${esc(g.node_id)} · ${g.type}
${esc(g.title)}
${esc(g.description)}
`})}return h;}
function renderSpec(s){let h=`
AОбзор
${esc(s.overview)}
AРоли (${s.roles.length})
`;s.roles.forEach(r=>h+=`
${esc(r.name)} — ${esc(r.does)}
Доступ: ${esc(r.access)}
`);h+=`
BМодули (${s.modules.length})
`;s.modules.forEach((m,mi)=>h+=`
${esc(m.source_node)}${esc(m.name)}
${esc(m.purpose)}
${m.screens.map(x=>`${esc(x)}`).join("")}
📥 ${esc(m.inputs_data)} · 📤 ${esc(m.outputs_data)}
${m.rules.length?`
${m.rules.map(r=>`
${esc(r)}
`).join("")}
`:''}
`);h+=`
CДанные (${s.entities.length} таблиц)
`;s.entities.forEach(e=>h+=`
◆ ${esc(e.name)}${e.fields.map(f=>`
${esc(f.field)} ${esc(f.type)}
`).join("")}
${e.relations.length?`
🔗 ${e.relations.map(esc).join(" · ")}
`:''}
${esc(e.example)}
`);if(s.open_questions&&s.open_questions.length){h+=`
Уточнить перед разработкой${s.open_questions.map(q=>`
${esc(q)}
`).join("")}
`}return h;}
+async function checkAiStatus(){
+ try{
+ const r=await fetch(`${API}/api/ai-status`);const d=await r.json();
+ const b=document.getElementById('aiBanner'),t=document.getElementById('aiBannerText'),dot=document.getElementById('aiDot');
+ if(d.ok){b.style.display='none';if(dot){dot.style.background='#10B981';dot.title='AI-движок Елены: в норме';}return;}
+ if(dot){dot.style.background='#EF4444';dot.title='AI-движок Елены: недоступен';}
+ t.textContent=d.reason==='low_balance'
+ ?'⚠️ AI-движок Елены недоступен: недостаточно средств на балансе. Пополните баланс — без него Елена не строит стратегию, модель, оргструктуру, должностные и ТЗ.'
+ :'⚠️ AI-движок Елены временно недоступен (техническая ошибка). Генерация артефактов не работает.';
+ b.style.display='flex';
+ }catch(e){/* сетевой сбой — не показываем ложную тревогу */}
+}
loadProjects().then(render);
+checkAiStatus();
+setInterval(checkAiStatus,3600000); // раз в час