Min Down:
' + downPct + '%' +
'
Min Credit: ' + cfg.minCredit + '+' +
'
Rate Premium: ' + (cfg.ratePremium > 0 ? '+' + cfg.ratePremium + '%' : 'None') + '';
}
}
function fmt(n){ return n ? '$' + Math.round(n).toLocaleString() : '—'; }
function calcMortgage(price, down, rate, term) {
var loan = price - down;
if(!loan || !rate || !term) return {loan:loan, pi:0};
var r = (rate/100)/12;
var n = term * 12;
var pi = loan * (r * Math.pow(1+r,n)) / (Math.pow(1+r,n)-1);
return {loan:loan, pi:pi};
}
function getDtiColor(pct, max) {
if(pct <= max * 0.7) return '#22c55e';
if(pct <= max * 0.85) return '#f59e0b';
if(pct <= max) return '#f97316';
return '#ef4444';
}
function calcClosing(price) {
if(!price) return {c1:0,c2:0,c3:0,c4:0,total:0};
var c1 = price * 0.0075;
var c2 = price * 0.004;
var c3 = price * 0.012;
var c4 = price * 0.003;
return {c1:c1, c2:c2, c3:c3, c4:c4, total:c1+c2+c3+c4};
}
function setVerdict(id, feDTI, beDTI, income, piti, loanCfg) {
var el = document.getElementById(id);
var maxBE = loanCfg ? loanCfg.maxBE : 43;
var maxFE = loanCfg ? loanCfg.maxFE : 28;
if(!income || !piti){
el.className='verdict v-yellow';
el.innerHTML='
💡 Enter your numbers above
Fill in your details to see your full readiness picture.
';
return;
}
if(loanCfg && loanCfg.mode === 'dscr') {
var dscrVal = parseFloat(document.getElementById('se-rental-income') ? document.getElementById('se-rental-income').value : 0) || 0;
if(dscrVal > 0 && piti > 0) {
var ratio = dscrVal / piti;
if(ratio >= 1.25) {
el.className='verdict v-green';
el.innerHTML='
✅ Strong DSCR (' + ratio.toFixed(2) + ')
Your rental income covers the mortgage well. Most lenders want 1.0 minimum — you are above that. You look strong for a DSCR loan.
';
} else if(ratio >= 1.0) {
el.className='verdict v-yellow';
el.innerHTML='
⚠️ Borderline DSCR (' + ratio.toFixed(2) + ')
You meet the minimum 1.0 DSCR threshold but just barely. Some lenders require 1.25. Consider a larger down payment to lower the payment and improve your ratio.
';
} else {
el.className='verdict v-red';
el.innerHTML='
❌ DSCR Too Low (' + ratio.toFixed(2) + ')
Rental income does not cover the mortgage. You need either a lower purchase price, larger down payment, or a property with higher rental income.
';
}
}
return;
}
if(loanCfg && loanCfg.mode === 'va') {
var vaNote = '
🏭 VA Loan — Powerful Benefit
';
if(beDTI <= 41) {
el.className='verdict v-green';
vaNote += '✅ Your DTI looks strong for a VA loan. Key advantages: $0 down payment, no monthly mortgage insurance, competitive rates, and DTI flexibility up to 60% with residual income. One-time funding fee (2.15% first use) can be rolled into the loan. This is one of the most powerful mortgage benefits available — and you earned it.
';
} else if(beDTI <= 60) {
el.className='verdict v-yellow';
vaNote += '⚠️ Your DTI is elevated but VA allows up to 60% with residual income qualification. VA lenders also look at how much money you have left over each month after all debts — not just the DTI percentage. Strong residual income can overcome a high DTI on a VA loan.
';
} else {
el.className='verdict v-red';
vaNote += '❌ Your DTI exceeds VA guidelines. Even with VA's flexibility, a back-end DTI above 60% is very difficult. Consider reducing debts or purchase price before applying.';
}
el.innerHTML = vaNote;
return;
}
if(beDTI <= maxBE * 0.85 && feDTI <= maxFE){
el.className='verdict v-green';
el.innerHTML='Your DTI ratios are healthy for a ' + (loanCfg ? loanCfg.name : '') + ' loan. Focus on your credit score, down payment seasoning, and gathering your documents. You may be closer than you think.
';
} else if(beDTI <= maxBE){
el.className='verdict v-yellow';
el.innerHTML='You may qualify for ' + (loanCfg ? loanCfg.name : 'this loan') + ' but your DTI is in the caution zone. Pay down high-interest debt, avoid new credit, and call me before you apply.
';
} else {
el.className='verdict v-red';
el.innerHTML='Your debt load exceeds the limit for this program. Try a different loan type above, or download the Credit Repair Roadmap to build a 6-12 month paydown plan.
';
}
}
function calcW2() {
var income = (parseFloat(document.getElementById('w2-income').value)||0) + (parseFloat(document.getElementById('w2-coborrower').value)||0);
var price = parseFloat(document.getElementById('w2-price').value)||0;
var down = parseFloat(document.getElementById('w2-down').value)||0;
var rate = parseFloat(document.getElementById('w2-rate').value)||0;
var term = parseInt(document.getElementById('w2-term').value)||30;
var tax = parseFloat(document.getElementById('w2-tax').value)||0;
var ins = parseFloat(document.getElementById('w2-ins').value)||0;
var hoa = parseFloat(document.getElementById('w2-hoa').value)||0;
var car = parseFloat(document.getElementById('w2-car').value)||0;
var student = parseFloat(document.getElementById('w2-student').value)||0;
var cc = parseFloat(document.getElementById('w2-cc').value)||0;
var other = parseFloat(document.getElementById('w2-other').value)||0;
var loanType = document.getElementById('w2-loantype').value;
var mip = 0;
var vaFundingFee = 0;
if(loanType === 'fha') {
var loanAmt = price - down;
mip = (loanAmt * 0.0055) / 12;
}
if(loanType === 'va') {
// VA: no down payment required, no monthly MIP
// Funding fee 2.15% first use, rolled into loan (not monthly)
// No PMI ever
if(down === 0) down = 0; // VA allows 0 down
}
var m = calcMortgage(price, down, rate, term);
var piti = m.pi + tax + ins + hoa + mip;
var totalDebt = piti + car + student + cc + other;
var feDTI = income ? (piti/income)*100 : 0;
var beDTI = income ? (totalDebt/income)*100 : 0;
var downPct = price ? (down/price)*100 : 0;
document.getElementById('w2-pi').textContent = fmt(m.pi);
document.getElementById('w2-piti').textContent = fmt(piti);
document.getElementById('w2-loan').textContent = fmt(m.loan);
document.getElementById('w2-downpct').textContent = price ? downPct.toFixed(1)+'%' : '—';
if(loanType === 'va') {
document.getElementById('w2-downpct').textContent = down > 0 ? downPct.toFixed(1)+'% (VA: $0 min)' : '$0 — VA Benefit';
}
var feColor = getDtiColor(feDTI, 28);
var beColor = getDtiColor(beDTI, loanType === 'fha' ? 50 : 45);
document.getElementById('w2-fedti-pct').textContent = income ? feDTI.toFixed(1)+'%' : '0%';
document.getElementById('w2-fedti-pct').style.color = feColor;
document.getElementById('w2-fedti-bar').style.width = Math.min(feDTI,100)+'%';
document.getElementById('w2-fedti-bar').style.background = feColor;
document.getElementById('w2-bedti-pct').textContent = income ? beDTI.toFixed(1)+'%' : '0%';
document.getElementById('w2-bedti-pct').style.color = beColor;
document.getElementById('w2-bedti-bar').style.width = Math.min(beDTI,100)+'%';
document.getElementById('w2-bedti-bar').style.background = beColor;
var w2LoanCfg = null;
if(loanType === 'fha') w2LoanCfg = {maxFE:31, maxBE:50, mode:'fha'};
if(loanType === 'va') w2LoanCfg = {maxFE:41, maxBE:60, mode:'va'};
if(loanType === 'conv') w2LoanCfg = {maxFE:28, maxBE:45, mode:'conv'};
setVerdict('w2-verdict', feDTI, beDTI, income, piti, w2LoanCfg);
// Save to localStorage for report
localStorage.setItem('drRobCalcData', JSON.stringify({
type:'w2', income:income, price:price, down:down, rate:rate, term:term,
tax:tax, ins:ins, hoa:hoa, car:car, student:student, cc:cc, other:other,
loan:loanType, feDTI:feDTI, beDTI:beDTI, pi:m.pi, piti:piti,
qualMonthly:income, totalDebt:totalDebt
}));
var c = calcClosing(price);
document.getElementById('w2-c1').textContent = fmt(c.c1);
document.getElementById('w2-c2').textContent = fmt(c.c2);
document.getElementById('w2-c3').textContent = fmt(c.c3);
document.getElementById('w2-c4').textContent = fmt(c.c4);
document.getElementById('w2-ctotal').textContent = fmt(c.total);
}
function calcSE() {
var cfg = LOAN_CONFIG[currentLoan];
var qualMonthly = 0;
if(currentLoan === 'dscr') {
// DSCR - use rental income for verdict only
var rentalIncome = parseFloat(document.getElementById('se-rental-income') ? document.getElementById('se-rental-income').value : 0)||0;
qualMonthly = rentalIncome;
document.getElementById('se-qi').textContent = 'N/A';
document.getElementById('se-qi-r').textContent = 'Rental-Based';
document.getElementById('se-qi-vs').textContent = 'DSCR: qualification based on rental income, not personal income';
} else if(currentLoan === 'asset') {
// Asset depletion - assets / (loan term months)
var assets = parseFloat(document.getElementById('se-liquid-assets') ? document.getElementById('se-liquid-assets').value : 0)||0;
var term2 = parseInt(document.getElementById('se-term').value)||30;
qualMonthly = assets / (term2 * 12);
document.getElementById('se-qi').textContent = fmt(qualMonthly);
document.getElementById('se-qi-r').textContent = fmt(qualMonthly);
document.getElementById('se-qi-vs').textContent = assets ? 'Assets divided over ' + term2 + '-year loan term' : 'Enter your liquid assets above';
} else if(currentLoan === 'bankstmt' || currentLoan === 'pl') {
// Bank statement / P&L - use direct monthly income field
var directIncome = parseFloat(document.getElementById('se-direct-income') ? document.getElementById('se-direct-income').value : 0)||0;
qualMonthly = directIncome;
document.getElementById('se-qi').textContent = fmt(qualMonthly);
document.getElementById('se-qi-r').textContent = fmt(qualMonthly);
document.getElementById('se-qi-vs').textContent = currentLoan === 'bankstmt' ? '12-24 month average monthly deposits' : 'P&L monthly net income';
} else {
// Standard - Schedule C
var y1 = parseFloat(document.getElementById('se-y1').value)||0;
var y2 = parseFloat(document.getElementById('se-y2').value)||0;
var dep = parseFloat(document.getElementById('se-dep').value)||0;
var home = parseFloat(document.getElementById('se-home').value)||0;
var loss = parseFloat(document.getElementById('se-loss').value)||0;
var mile = parseFloat(document.getElementById('se-mile').value)||0;
var avgAnnual = y2 ? (y1+y2)/2 : y1;
var addbacks = dep + home + loss + mile;
var qualAnnual = avgAnnual + addbacks;
qualMonthly = qualAnnual / 12;
var qiEl = document.getElementById('se-qi-sched') || document.getElementById('se-qi');
if(qiEl) qiEl.textContent = fmt(qualMonthly);
document.getElementById('se-qi-r').textContent = fmt(qualMonthly);
if(y1||y2) {
var diff = qualMonthly - (avgAnnual/12);
var vsEl = document.getElementById('se-qi-vs-sched') || document.getElementById('se-qi-vs');
if(vsEl) vsEl.textContent = diff > 0 ?
'After add-backs: +' + fmt(diff) + '/mo vs. tax return alone' :
'Based on ' + (y2 ? '2-year average' : 'single year') + ' net profit';
}
}
var price = parseFloat(document.getElementById('se-price').value)||0;
var down = parseFloat(document.getElementById('se-down').value)||0;
var baseRate = parseFloat(document.getElementById('se-rate').value)||0;
var term = parseInt(document.getElementById('se-term').value)||30;
var tax = parseFloat(document.getElementById('se-tax').value)||0;
var ins = parseFloat(document.getElementById('se-ins').value)||0;
var hoa = parseFloat(document.getElementById('se-hoa').value)||0;
var car = parseFloat(document.getElementById('se-car').value)||0;
var cc = parseFloat(document.getElementById('se-cc').value)||0;
var student = parseFloat(document.getElementById('se-student').value)||0;
var other = parseFloat(document.getElementById('se-other').value)||0;
var effectiveRate = baseRate + cfg.ratePremium;
var m = calcMortgage(price, down, effectiveRate, term);
var mConv = cfg.ratePremium > 0 ? calcMortgage(price, down, baseRate, term) : null;
var piti = m.pi + tax + ins + hoa;
var totalDebt = piti + car + cc + student + other;
var feDTI = 0, beDTI = 0;
if(currentLoan === 'dscr') {
feDTI = 0; beDTI = 0;
} else {
feDTI = qualMonthly ? (piti/qualMonthly)*100 : 0;
beDTI = qualMonthly ? (totalDebt/qualMonthly)*100 : 0;
}
document.getElementById('se-pi').textContent = fmt(m.pi);
document.getElementById('se-piti').textContent = fmt(piti);
document.getElementById('se-loan').textContent = fmt(m.loan);
if(cfg.ratePremium > 0 && mConv && m.pi && mConv.pi) {
document.getElementById('se-premium').textContent = '+' + fmt(m.pi - mConv.pi) + '/mo vs. conventional';
}
var feColor = getDtiColor(feDTI, cfg.maxFE);
var beColor = getDtiColor(beDTI, cfg.maxBE);
document.getElementById('se-fedti-pct').textContent = feDTI ? feDTI.toFixed(1)+'%' : '0%';
document.getElementById('se-fedti-pct').style.color = feColor;
document.getElementById('se-fedti-bar').style.width = Math.min(feDTI,100)+'%';
document.getElementById('se-fedti-bar').style.background = feColor;
document.getElementById('se-bedti-pct').textContent = beDTI ? beDTI.toFixed(1)+'%' : '0%';
document.getElementById('se-bedti-pct').style.color = beColor;
document.getElementById('se-bedti-bar').style.width = Math.min(beDTI,100)+'%';
document.getElementById('se-bedti-bar').style.background = beColor;
setVerdict('se-verdict', feDTI, beDTI, qualMonthly, piti, cfg);
// Save to localStorage for report
localStorage.setItem('drRobCalcData', JSON.stringify({
tab:'se', income:qualMonthly, price:price, down:down, rate:effectiveRate, term:term,
tax:tax, ins:ins, hoa:hoa, car:car, student:student, cc:cc, other:other,
seMode:currentLoan, feDTI:feDTI, beDTI:beDTI, pi:m.pi, piti:piti
}));
var c = calcClosing(price);
document.getElementById('se-c1').textContent = fmt(c.c1);
document.getElementById('se-c2').textContent = fmt(c.c2);
document.getElementById('se-c3').textContent = fmt(c.c3);
document.getElementById('se-c4').textContent = fmt(c.c4);
document.getElementById('se-ctotal').textContent = fmt(c.total);
// Save for report
try {
localStorage.setItem('drRobCalcData', JSON.stringify({
type:'se', income:qualMonthly, price:price, down:down, rate:effectiveRate,
piti:piti, beDTI:beDTI, feDTI:feDTI, loan:currentLoan,
qualMonthly:qualMonthly, totalDebt:totalDebt
}));
} catch(e){}
}
// ── READINESS REPORT ──────────────────────────────────────────
var lastCalcData = {};
function showReportGate(tab) {
generateReport(tab);
}
var STRIPE_REPORT_URL = 'https://buy.stripe.com/7sY9AU7OP7BfcBt3DqbfO05';
function closeReport() {
document.getElementById('reportOverlay').classList.remove('show');
document.body.style.overflow = '';
}
function fmt2(n) { return n ? '$' + Math.round(n).toLocaleString() : '$0'; }
function getColor(val, good, warn) {
if(val <= good) return 'rsc-green';
if(val <= warn) return 'rsc-yellow';
return 'rsc-red';
}
function finding(type, icon, title, text) {
var cls = type === 'good' ? 'rf-green' : type === 'warn' ? 'rf-yellow' : 'rf-red';
return '