function qtyTxt(f,g){
var u=f.ml?'мл':'г',v;
if(f.id==='egg')return Math.ceil(g/50)+' шт.';
v=g < 100?Math.ceil(g/5)*5:Math.ceil(g/10)*10;
if(v>=1000)return fmt(v/1000,v%1000?2:0).replace(/0$/,'').replace(/,$/,'')+(f.ml?' л':' кг');
return v+' '+u+(f.pc&&g>=f.pc*0.6?' (≈ '+Math.ceil(g/f.pc)+' шт.)':'');
}
function shopList(P){
var out=[];
SHOPGR.forEach(function(gr){
var ids=Object.keys(P.shop).filter(function(id){return shopCat(FOOD[id])===gr[0];}).sort(function(a,b){return rn(FOOD[a]) < rn(FOOD[b])?-1:1;});
if(ids.length)out.push({n:gr[1],items:ids.map(function(id){return {id:id,t:rn(FOOD[id])+': '+qtyTxt(FOOD[id],P.shop[id])};})});
});
return out;
}
function shopHtml(P){
var L=shopList(P),h='\x3ch4 class="nl-h">Список покупок на '+(S.days===1?'1 день':(S.days===3?'3 дня':'неделю'))+'\x3c/h4>';
h+='\x3cp class="nl-small">Список собран по меню выше и меняется вместе с ним. Это вес продуктов, которые идут в блюда: на очистку овощей и разделку мяса берите с небольшим запасом. Отметьте то, что уже есть дома, и скопируйте остальное.\x3c/p>\x3cdiv class="nl-box nl-shop">';
L.forEach(function(g){
h+='\x3cdiv class="nl-shg">\x3ch5>'+g.n+'\x3c/h5>'+g.items.map(function(it){return '\x3clabel class="nl-sl">\x3cinput type="checkbox" data-have="'+it.id+'"'+(S.have[it.id]?' checked':'')+'>\x3cspan>'+it.t+'\x3c/span>\x3c/label>';}).join('')+'\x3c/div>';
});
h+='\x3c/div>\x3cdiv class="nl-actions" style="margin-top:12px">\x3cbutton type="button" class="nl-btn2" data-copy="shop">Скопировать список\x3c/button>\x3cbutton type="button" class="nl-btn2" data-copy="shopshare">Отправить список\x3c/button>\x3c/div>';
return h;
}
function tlGrid(pct){
var lo=[],mid=[],ok=[];
MIC.forEach(function(mm,j){if(pct[j] < 80)lo.push(j);else if(pct[j] < 100)mid.push(j);else ok.push(j);});
function grp(cls,title,sub,arr){
return '\x3cdiv class="nl-tl-c '+cls+'">\x3cdiv class="nl-tl-h">\x3ci class="nl-dot">\x3c/i>\x3cb>'+title+'\x3c/b>\x3cem>'+arr.length+'\x3c/em>\x3c/div>\x3cp class="nl-small" style="margin:2px 0 0">'+sub+'\x3c/p>'+(arr.length?'\x3cul>'+arr.map(function(j){return '\x3cli>\x3cspan>'+MIC[j].n+'\x3c/span>\x3cb class="nl-st '+cls+'">'+pct[j]+'%\x3c/b>\x3c/li>';}).join('')+'\x3c/ul>':'\x3cp class="nl-small" style="margin:8px 0 0">Нет\x3c/p>')+'\x3c/div>';
}
return {lo:lo,mid:mid,ok:ok,h:'\x3cdiv class="nl-tl">'+grp('lo','Мало','меньше 80% нормы',lo)+grp('mid','Почти хватает','80–99% нормы',mid)+grp('ok','Достаточно','100% нормы и выше',ok)+'\x3c/div>'};
}
function allowedFoods(){
return ORDER.filter(function(id){var f=FOOD[id];return f.u&&f.rec&&!isBlocked(f,S.bt,S.bp);}).map(function(id){return FOOD[id];});
}
function bestSrc(j,n){
return allowedFoods().map(function(f){var g=pgOf(f);return {f:f,g:g,v:S.mn[j]>0?f.m[j]*g/100*f.x/S.mn[j]:0};}).filter(function(o){return o.v>=0.05;}).sort(function(a,b){return b.v-a.v;}).slice(0,n);
}
var SUPPSET={D:1,Om:1,Fe:1,Ca:1,I:1,B12:1,Zn:1};
var SUPP={
D:{t:'Из еды витамин D почти не получить: даже рыба и яйцо дают лишь малую часть суточной нормы.',w:'витамин D3 (холекальциферол)',l:'уровень 25(OH)D в крови и сезон года. Малышу на грудном вскармливании витамин D дают отдельно по назначению педиатра.'},
Om:{t:'ДГК из грудного молока нужна мозгу и зрению малыша. Основной источник жирная морская рыба около 2 раз в неделю (лосось, скумбрия, сардина). Растительные продукты дают другую форму омега-3, которая плохо превращается в ДГК.',w:'рыбий жир или масло из водорослей (ДГК)',l:'форму препарата и срок приёма.'},
Fe:{t:'После родов запасы железа часто снижены. Железо лучше всего усваивается из мяса и рыбы; крупы и бобовые ешьте с овощами и ягодами, богатыми витамином C, а чай и кофе пейте отдельно от еды.',w:'препарат железа только по назначению врача',l:'гемоглобин, ферритин вместе с СРБ и СОЭ, железо в сыворотке и трансферрин. Без анализов железо не принимайте: избыток вреден.'},
Ca:{t:'При кормлении кальция нужно больше обычного (до 1 400 мг). Без молочного покрыть норму едой трудно: зелень, бобовые и кунжут дают его меньше и усваиваются хуже.',w:'кальций вместе с витамином D или продукты, обогащённые кальцием',l:'форму, срок приёма и уровень витамина D. Кальций принимайте отдельно от железа.'},
I:{t:'При кормлении йода нужно почти вдвое больше обычного: он нужен щитовидной железе малыша. Расчёт сделан без соли, поэтому в меню его мало.',w:'йодированная соль в готовых блюдах, препарат йода подбирает врач',l:'нужна ли добавка. При болезнях щитовидной железы йод без врача принимать нельзя.'},
B12:{t:'Витамин B12 есть почти только в продуктах животного происхождения. Если мама его недополучает, в молоке его тоже мало.',w:'витамин B12',l:'уровень B12 в крови и состав рациона.'},
Zn:{t:'Цинк лучше всего усваивается из мяса, из растительных продуктов хуже.',w:'цинк по решению врача',l:'рацион, симптомы и нужен ли анализ.'}
};
function vitHtml(P){
var g=tlGrid(P.pct),h='\x3ch4 class="nl-h">Витамины и минералы в меню\x3c/h4>',sup,oth;
h+='\x3cp class="nl-small">Какую долю суточной нормы даёт меню'+(S.days>1?' в среднем за день':'')+'. Нормы для кормящей мамы: МР 2.3.1.0253-21, норма для женщин плюс прибавка на лактацию'+(S.bf < 1?', прибавка уменьшена пропорционально доле грудного молока':'')+'.'+(S.days===1?' Один день мало говорит о питании в целом: точнее оценка по меню на неделю.':'')+'\x3c/p>'+g.h;
sup=g.lo.concat(g.mid).filter(function(j){return SUPPSET[MIC[j].id]&&P.pct[j] < 90;}).sort(function(a,b){return P.pct[a]-P.pct[b];});
oth=g.lo.filter(function(j){return !SUPPSET[MIC[j].id];});
if(sup.length){
h+='\x3ch5 style="margin-top:16px">Что трудно добрать едой\x3c/h5>';
sup.forEach(function(j){
var mm=MIC[j],s=SUPP[mm.id],t=s.t;
if(mm.id==='Om'&&!S.fishOk)t='Рыба исключена, поэтому омега-3 из еды почти не поступает. '+t;
if(mm.id==='Ca'&&S.bt.milk)t='Молоко исключено. '+t;
h+='\x3cdiv class="nl-note o">\x3cb>'+mm.n+': в меню '+P.pct[j]+'% нормы\x3c/b>'+t+'\x3cbr>\x3ci>Что обычно принимают:\x3c/i> '+s.w+'.\x3cbr>\x3ci>Что обсудить с врачом:\x3c/i> '+s.l+'\x3c/div>';
});
}else{
h+='\x3cdiv class="nl-note g">\x3cb>Основное добирается едой\x3c/b>При таком меню основные витамины и минералы близки к норме. Нужна ли добавка в вашем случае, решает врач по анализам.\x3c/div>';
}
if(oth.length)h+='\x3cp class="nl-small" style="margin-top:10px">Ниже 80% нормы ещё: '+oth.map(function(j){var s=bestSrc(j,3);return MIC[j].n.toLowerCase()+' ('+P.pct[j]+'%'+(s.length?', чем добрать: '+s.map(function(o){return shortN(o.f);}).join(', '):'')+')';}).join('; ')+'. Это добирается едой: соберите другое меню или замените блюда на те, где есть эти продукты.\x3c/p>';
h+='\x3cdiv class="nl-warn" style="font-size:14px!important">\x3cb>Важно.\x3c/b> Дозировку мы не называем: её подбирает врач по анализам. При грудном вскармливании добавки принимайте только по согласованию с врачом. Железо, витамин A и витамин D в избытке вредны.\x3c/div>';
h+=vsHtml();
return h;
}
function vsHtml(){
var first=-1,opts='';
MIC.forEach(function(mm,j){var p=S.P.pct[j];if(first < 0&&p < 100)first=j;opts+='\x3coption value="'+j+'">'+mm.n+' (в меню '+p+'% нормы)\x3c/option>';});
S.vsDef=first < 0?0:first;
return '\x3ch5 style="margin-top:18px">Выберите витамин или минерал: чем его добрать\x3c/h5>\x3clabel class="nl-l" for="nl-vs">Витамин или минерал\x3c/label>\x3cselect id="nl-vs">'+opts+'\x3c/select>\x3cdiv class="nl-vo" id="nl-vo" aria-live="polite">\x3c/div>';
}
function showVs(){
var sel=el('nl-vs'),box=el('nl-vo'),j,mm,list,h,cur;
if(!sel||!box||!S||!S.P)return;
j=parseInt(sel.value,10);mm=MIC[j];cur=S.P.pct[j];
list=bestSrc(j,8);
h='\x3cp>\x3cb>'+mm.n+'.\x3c/b> Меню даёт в среднем '+fv(S.P.avg.m[j])+' из '+fv(S.mn[j])+' '+mm.u+' в день ('+cur+'% нормы).';
h+='\x3c/p>';
if(list.length&&mm.id!=='D'){
h+='\x3cp class="nl-small" style="margin-bottom:4px">Лучшие источники среди разрешённых продуктов (одна обычная порция готового продукта):\x3c/p>\x3cul>'+list.map(function(o){
return '\x3cli>\x3cb>'+o.f.n+'\x3c/b>: около '+o.g+(o.f.ml?' мл':' г')+' даёт '+Math.round(o.v*100)+'% суточной нормы'+''+'\x3c/li>';
}).join('')+'\x3c/ul>';
}else{
h+='\x3cp>Хороших пищевых источников нет: едой этот показатель почти не покрыть.\x3c/p>';
}
if(SUPPSET[mm.id]&&cur < 90)h+='\x3cp>\x3cb>Едой этого добрать трудно: обсудите с врачом, нужна ли добавка.\x3c/b> Дозировку подбирает врач.\x3c/p>';
else if(cur < 100)h+='\x3cp>Это можно закрыть едой: замените одно-два блюда на те, где есть продукты из списка.\x3c/p>';
box.innerHTML=h;
}
function zoneHtml(openSet){
var P=evalPlan();
return menuHtml(P,openSet)+shopHtml(P)+vitHtml(P);
}
function rerenderZone(){
var openSet={},z=el('nl-mz'),v=el('nl-vs'),vv=v?v.value:null;
[].forEach.call(root.querySelectorAll('.nl-day2[data-day]'),function(dt){if(dt.open)openSet[dt.getAttribute('data-day')]=1;});
z.innerHTML=zoneHtml(openSet);
if(el('nl-vs'))el('nl-vs').value=vv!=null?vv:String(S.vsDef);
showVs();
}
function render(){
var out=el('nl-out'),h='';
h+='\x3cdiv class="nl-cards">\x3cdiv class="nl-card">\x3cb>'+sp(S.kN)+'\x3c/b>\x3cspan>ккал в сутки\x3c/span>\x3c/div>\x3cdiv class="nl-card">\x3cb>'+sp(S.pN)+' г\x3c/b>\x3cspan>белки ('+fmt(S.pN/S.w,1)+' г/кг)\x3c/span>\x3c/div>\x3cdiv class="nl-card">\x3cb>'+sp(S.fN)+' г\x3c/b>\x3cspan>жиры\x3c/span>\x3c/div>\x3cdiv class="nl-card">\x3cb>'+sp(S.cN)+' г\x3c/b>\x3cspan>углеводы\x3c/span>\x3c/div>\x3cdiv class="nl-card">\x3cb>'+fmt(S.N.wLo,1)+'–'+fmt(S.N.wHi,1)+' л\x3c/b>\x3cspan>воды и напитков в сутки\x3c/span>\x3c/div>\x3c/div>';
h+='\x3cp class="nl-small" style="margin-top:12px">Ваша норма без кормления около '+sp(S.N.base)+' ккал (формула Миффлина–Сан Жеора с учётом активности). На кормление добавлено '+sp(S.N.add)+' ккал'+(S.bf < 1?' с поправкой на долю грудного молока':'')+'.'+(S.N.floor?' Расчётная норма получилась ниже '+sp(MIN_KCAL)+' ккал, поэтому взято '+sp(MIN_KCAL)+': жёсткое ограничение калорий при кормлении не нужно.':'')+' Белок: большее из 1,3 г на кг массы тела и середины 12–15% калорий. Жиры около 31% калорий, остальное углеводы. Нормы: МР 2.3.1.0253-21.\x3c/p>';
h+='\x3cdiv id="nl-mz">'+zoneHtml(null)+'\x3c/div>';
h+='\x3cdiv class="nl-actions">\x3cbutton type="button" class="nl-btn2" data-copy="sum">Скопировать итог, чтобы сохранить\x3c/button>\x3c/div>';
out.innerHTML=h;
if(el('nl-vs'))el('nl-vs').value=String(S.vsDef);
showVs();
}
function menuText(){
var P=S.P,t='МЕНЮ ('+(S.mode==='simple'?'простое':'посложнее')+(S.rep?', ужин как обед':'')+') ДЛЯ КОРМЯЩЕЙ МАМЫ, '+fmt(S.w,0)+' кг\nНорма: '+sp(S.kN)+' ккал, белки '+sp(S.pN)+' г, жиры '+sp(S.fN)+' г, углеводы '+sp(S.cN)+' г в сутки\nГраммы продуктов до приготовления (крупы сухие, мясо сырое)\n';
P.days.forEach(function(d,i){
t+='\n'+dayName(i).toUpperCase()+' ('+sp(d.tot.k)+' ккал, белок '+fmt(d.tot.p,0)+' г)\n';
d.meals.forEach(function(ml){
if(!ml.xs.length)return;
var sl=SLOTS.filter(function(s){return s.id===ml.slot;})[0];
ml.xs.forEach(function(x){t+=sl.n+': '+x.d.n+' ('+sp(x.k)+' ккал, Б '+fmt(x.p,1)+' г): '+x.items.map(function(it){return rn(it.f).split(' (')[0].toLowerCase()+' '+Math.round(it.g)+(it.f.ml?' мл':' г');}).join(', ')+'\n';});
});
});
return plain(t+'\n'+shopText(false));
}
function shopText(onlyNeed){
var L=shopList(S.P),t='СПИСОК ПОКУПОК ('+(S.days===1?'на 1 день':(S.days===3?'на 3 дня':'на неделю'))+')\n';
L.forEach(function(g){
var it=g.items.filter(function(x){return !(onlyNeed&&S.have[x.id]);});
if(it.length)t+='\n'+g.n+':\n'+it.map(function(x){return '- '+x.t;}).join('\n')+'\n';
});
return plain(t);
}
function summaryText(){
var P=S.P,low=[],t='ИТОГ ПО ПИТАНИЮ КОРМЯЩЕЙ МАМЫ\nВозраст '+Math.round(S.age)+' лет, вес '+fmt(S.w,1)+' кг, рост '+fmt(S.h,0)+' см\n';
var ex=[];AL.forEach(function(a){if(S.btRaw[a[0]])ex.push(a[1].toLowerCase());});
t+='Исключено из меню: '+(ex.length?ex.join(', '):'ничего')+'\n';
t+='Меню: '+(S.mode==='simple'?'простое':'посложнее')+(S.tmax?', блюда не дольше '+S.tmax+' минут':'')+(S.rep?', ужин как обед':'')+'\n';
t+='Норма в сутки: '+sp(S.kN)+' ккал, белки '+sp(S.pN)+' г, жиры '+sp(S.fN)+' г, углеводы '+sp(S.cN)+' г, жидкость '+fmt(S.N.wLo,1)+'-'+fmt(S.N.wHi,1)+' л\n';
MIC.forEach(function(mm,j){if(P.pct[j] < 80)low.push(mm.n+' '+P.pct[j]+'%');});
t+='\nМеню ('+S.days+' дн.): в среднем '+sp(P.avg.k)+' ккал, белки '+fmt(P.avg.p,1)+' г в день\n';
t+='Ниже 80% нормы в меню: '+(low.length?low.join(', '):'нет')+'\n';
t+='\nРасчёт ориентировочный, не является диагнозом и не заменяет консультацию врача.\n';
return plain(t);
}
function copyText(t,btn,lab){
if(!btn.getAttribute('data-orig'))btn.setAttribute('data-orig',btn.textContent);
function done(){btn.textContent=lab||'Скопировано';setTimeout(function(){btn.textContent=btn.getAttribute('data-orig');},2000);}
function fb(){var ta=document.createElement('textarea');ta.value=t;ta.style.position='fixed';ta.style.opacity='0';document.body.appendChild(ta);ta.select();try{document.execCommand('copy');done();}catch(e){}document.body.removeChild(ta);}
if(navigator.clipboard&&navigator.clipboard.writeText){navigator.clipboard.writeText(t).then(done,fb);}else{fb();}
}
function calc(){
var err=el('nl-err'),out=el('nl-out');
err.textContent='';out.hidden=true;el('nl-stale').hidden=true;S=null;
var a=num(el('nl-age').value),w=num(el('nl-w').value),h=num(el('nl-h').value);
if(isNaN(a)||isNaN(w)||isNaN(h)){err.textContent='Заполните возраст, вес и рост.';return;}
if(a < 14||a>55||w < 35||w>200||h < 130||h>210){err.textContent='Проверьте возраст (14–55 лет), вес (кг) и рост (см).';return;}
var stage=el('nl-stage').value,bf=parseFloat(el('nl-bf').value),pal=parseFloat(el('nl-act').value);
var N=norms(a,w,h,pal,stage,bf),mn=microNorm(a,bf);
S={age:a,w:w,h:h,stage:stage,bf:bf,N:N,mn:mn,kN:N.k,pN:Math.round(N.pT),fN:Math.round(N.fat),cN:Math.round(N.carb),
bt:blockedTags(),btRaw:rawTags(),bp:NOBP,mode:el('nl-mode').value,tmax:parseInt(el('nl-time').value,10)||0,rep:el('nl-rep').checked,days:parseInt(el('nl-days').value,10)||7,seed:1,have:{}};
prepAvail();
if(!S.avail.b.length&&!S.avail.l.length){err.textContent='При выбранных исключениях и времени готовки не осталось подходящих блюд. Уберите часть ограничений.';S=null;return;}
buildPlan();
out.hidden=false;
render();
try{var rm=window.matchMedia&&window.matchMedia('(prefers-reduced-motion: reduce)').matches;out.scrollIntoView({behavior:rm?'auto':'smooth',block:'start'});}catch(e){}
}
function markStale(e){
var t=e.target;
if(!S||!t||(t.closest&&t.closest('#nl-out')))return;
el('nl-stale').hidden=false;
}
function resetAll(){
[].forEach.call(root.querySelectorAll('input[type=checkbox]'),function(cb){cb.checked=false;});
el('nl-age').value='';el('nl-stage').value='a';el('nl-bf').value='1';el('nl-act').value='1.6';el('nl-days').value='7';el('nl-mode').value='simple';el('nl-time').value='0';el('nl-w').value='';el('nl-h').value='';
el('nl-out').hidden=true;el('nl-stale').hidden=true;el('nl-err').textContent='';S=null;
refresh();
}
buildUI();
refresh();
function fillProfile(p){
if(!p)return;
[['nl-age',p.age],['nl-w',p.w],['nl-h',p.h]].forEach(function(x){var e=el(x[0]);if(e&&!e.value&&x[1])e.value=String(x[1]).replace('.',',');});
['stage','bf','act'].forEach(function(k){var e=el('nl-'+k);if(e&&p[k]!=null&&!e.dataset.touched)e.value=String(p[k]);});
}
['nl-stage','nl-bf','nl-act'].forEach(function(id){el(id).addEventListener('change',function(){this.dataset.touched='1';});});
try{fillProfile(window.stopAllergiaMom);}catch(e){}
window.addEventListener('stop-allergia-mom',function(ev){try{fillProfile(ev.detail);}catch(e){}});
el('nl-btn').addEventListener('click',calc);
el('nl-reset').addEventListener('click',resetAll);
root.addEventListener('change',markStale);
root.addEventListener('input',markStale);
root.addEventListener('change',function(e){
var t=e.target;
if(!t)return;
if(t.name==='nl-al'){refresh();return;}
if(t.hasAttribute&&t.hasAttribute('data-have')&&S){S.have[t.getAttribute('data-have')]=t.checked;return;}
if(t.id==='nl-vs'){showVs();}
});
root.addEventListener('click',function(e){
var t=e.target;
if(!t||t.nodeType!==1||!t.closest||!S)return;
var sw=t.closest('[data-swap]');
if(sw){
var p=sw.getAttribute('data-swap').split('|'),c=S.plan[+p[0]].cells[+p[1]];
c.i=(c.i+1)%c.ids.length;
var y=sw.getBoundingClientRect().top;
rerenderZone();
var nb=root.querySelector('[data-swap="'+p[0]+'|'+p[1]+'"]');
if(nb){try{var dy=nb.getBoundingClientRect().top-y;if(Math.abs(dy)>2)window.scrollBy(0,dy);}catch(er){}nb.focus();}
return;
}
var ac=t.closest('[data-act]');
if(ac&&ac.getAttribute('data-act')==='reshuffle'){S.seed++;buildPlan();rerenderZone();return;}
var cp=t.closest('[data-copy]');
if(!cp)return;
var k=cp.getAttribute('data-copy');
if(k==='menu')copyText(menuText(),cp,'Скопировано. Вставьте в заметки или WhatsApp');
else if(k==='shop')copyText(shopText(true),cp);
else if(k==='shopshare'){if(navigator.share){navigator.share({title:'Список покупок',text:shopText(true)}).catch(function(){});}else copyText(shopText(true),cp,'Скопировано: вставьте в сообщение');}
else copyText(summaryText(),cp,'Скопировано. Вставьте в заметки или WhatsApp');
});
})();