Initial: CBP What-If Calculator

This commit is contained in:
Marty Bostick
2026-07-10 15:00:52 +00:00
commit 3685da9667
+740
View File
@@ -0,0 +1,740 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CBP What-If Calculator</title>
<style>
:root {
--bg: #0f1117;
--card: #1a1d2e;
--card-hover: #212539;
--border: #2a2e45;
--accent: #6c5ce7;
--accent-glow: rgba(108,92,231,0.3);
--green: #00d68f;
--green-dim: rgba(0,214,143,0.15);
--red: #ff6b6b;
--yellow: #ffd93d;
--text: #e4e6f0;
--text-dim: #8a8fa8;
--text-muted: #5a5e7a;
--font: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
--radius: 12px;
--radius-sm: 8px;
}
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
font-family: var(--font);
background: var(--bg);
color: var(--text);
min-height: 100vh;
padding: 20px;
}
.container { max-width: 1100px; margin: 0 auto; }
/* Header */
.header {
text-align: center;
padding: 40px 20px 30px;
}
.header h1 {
font-size: 2.2rem;
font-weight: 700;
background: linear-gradient(135deg, var(--accent), #a78bfa);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.header p {
color: var(--text-dim);
margin-top: 8px;
font-size: 0.95rem;
}
/* Controls */
.controls {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 14px;
background: var(--card);
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 24px;
margin-bottom: 24px;
}
.control-group {
display: flex;
flex-direction: column;
gap: 6px;
}
.control-group label {
font-size: 0.78rem;
font-weight: 600;
color: var(--text-dim);
text-transform: uppercase;
letter-spacing: 0.5px;
}
.control-group input, .control-group select {
background: var(--bg);
border: 1px solid var(--border);
border-radius: var(--radius-sm);
padding: 10px 14px;
color: var(--text);
font-size: 0.95rem;
font-family: var(--font);
outline: none;
transition: border-color 0.2s;
}
.control-group input:focus, .control-group select:focus {
border-color: var(--accent);
box-shadow: 0 0 0 3px var(--accent-glow);
}
.control-group input[type="number"] { -moz-appearance: textfield; }
.control-group input::-webkit-inner-spin-button, .control-group input::-webkit-outer-spin-button { -webkit-appearance: none; }
.control-row {
display: flex;
gap: 12px;
align-items: end;
}
.control-row .control-group { flex: 1; }
.checkbox-group {
display: flex;
align-items: center;
gap: 10px;
padding-top: 22px;
}
.checkbox-group label {
font-size: 0.85rem;
font-weight: 400;
text-transform: none;
letter-spacing: 0;
color: var(--text);
}
.checkbox-group input[type="checkbox"] {
width: 18px;
height: 18px;
accent-color: var(--accent);
}
/* Tabs */
.tabs {
display: flex;
gap: 4px;
background: var(--card);
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 4px;
margin-bottom: 20px;
overflow-x: auto;
}
.tab-btn {
flex: 1;
padding: 10px 16px;
border: none;
border-radius: 8px;
background: transparent;
color: var(--text-dim);
font-size: 0.85rem;
font-weight: 500;
cursor: pointer;
transition: all 0.2s;
white-space: nowrap;
font-family: var(--font);
}
.tab-btn:hover { color: var(--text); background: var(--card-hover); }
.tab-btn.active {
background: var(--accent);
color: white;
}
/* Results */
.results { display: none; }
.results.active { display: block; }
/* Summary cards */
.summary-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
gap: 12px;
margin-bottom: 24px;
}
.summary-card {
background: var(--card);
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 18px 20px;
text-align: center;
}
.summary-card .label {
font-size: 0.72rem;
text-transform: uppercase;
letter-spacing: 0.5px;
color: var(--text-dim);
font-weight: 600;
}
.summary-card .value {
font-size: 1.6rem;
font-weight: 700;
margin-top: 6px;
}
.summary-card .value.green { color: var(--green); }
.summary-card .value.accent { color: var(--accent); }
.summary-card .value.yellow { color: var(--yellow); }
.summary-card .sub {
font-size: 0.78rem;
color: var(--text-muted);
margin-top: 4px;
}
/* Table */
.table-wrap {
background: var(--card);
border: 1px solid var(--border);
border-radius: var(--radius);
overflow: hidden;
margin-bottom: 20px;
}
.table-wrap .table-title {
padding: 16px 20px 0;
font-size: 0.85rem;
font-weight: 600;
color: var(--text-dim);
text-transform: uppercase;
letter-spacing: 0.5px;
}
table {
width: 100%;
border-collapse: collapse;
font-size: 0.88rem;
}
thead th {
text-align: left;
padding: 14px 20px;
font-size: 0.72rem;
text-transform: uppercase;
letter-spacing: 0.5px;
color: var(--text-dim);
font-weight: 600;
border-bottom: 1px solid var(--border);
background: rgba(255,255,255,0.02);
}
tbody td {
padding: 12px 20px;
border-bottom: 1px solid rgba(42,46,69,0.5);
}
tbody tr:last-child td { border-bottom: none; }
tbody tr:hover { background: var(--card-hover); }
tbody tr.highlight td {
background: var(--green-dim);
font-weight: 600;
}
tbody tr.endgame td {
background: rgba(108,92,231,0.12);
font-weight: 600;
}
.num { text-align: right; font-variant-numeric: tabular-nums; }
.green-text { color: var(--green); }
.accent-text { color: var(--accent); }
.yellow-text { color: var(--yellow); }
/* Info box */
.info-box {
background: var(--card);
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 20px;
margin-bottom: 20px;
}
.info-box h3 {
font-size: 0.9rem;
margin-bottom: 10px;
color: var(--accent);
}
.info-box ul {
list-style: none;
padding: 0;
}
.info-box li {
padding: 6px 0;
font-size: 0.88rem;
color: var(--text-dim);
}
.info-box li::before {
content: "→ ";
color: var(--accent);
}
/* Legend */
.legend {
display: flex;
gap: 20px;
padding: 0 20px 16px;
flex-wrap: wrap;
}
.legend-item {
display: flex;
align-items: center;
gap: 8px;
font-size: 0.78rem;
color: var(--text-dim);
}
.legend-dot {
width: 10px;
height: 10px;
border-radius: 3px;
}
.legend-dot.green { background: var(--green-dim); border: 1px solid var(--green); }
.legend-dot.accent { background: rgba(108,92,231,0.2); border: 1px solid var(--accent); }
/* Mobile tweaks */
@media (max-width: 640px) {
body { padding: 12px; }
.header h1 { font-size: 1.5rem; }
.controls { grid-template-columns: 1fr; gap: 12px; padding: 16px; }
.summary-grid { grid-template-columns: repeat(2, 1fr); }
.summary-card .value { font-size: 1.2rem; }
.tab-btn { font-size: 0.78rem; padding: 8px 12px; }
table { font-size: 0.78rem; }
thead th, tbody td { padding: 10px 12px; }
}
/* Tooltip help */
.help {
font-size: 0.72rem;
color: var(--text-muted);
cursor: help;
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>CBP What-If Calculator</h1>
<p>Model referral earnings, timelines, and ROI for any gifting or self-funding scenario</p>
</div>
<!-- Controls -->
<div class="controls">
<div class="control-group">
<label>Number of people</label>
<input type="number" id="numPeople" value="1" min="1" max="100">
</div>
<div class="control-group">
<label>Referral commission</label>
<div class="control-row">
<input type="number" id="commissionPct" value="10" min="0" max="100" step="0.5" style="width:80px">
<span style="padding-top:10px;color:var(--text-dim)">%</span>
</div>
</div>
<div class="control-group">
<label>Gift / invest up to which level?</label>
<select id="giftLevel">
<option value="0">None (self-funded)</option>
<option value="1" selected>Level 1 only ($14)</option>
<option value="3">Levels 1-3 ($263)</option>
<option value="4">Levels 1-4 ($593)</option>
<option value="5">Levels 1-5 ($1,253)</option>
</select>
</div>
<div class="control-group" style="grid-column: span 1;">
<label>Self-funds through level</label>
<select id="selfFundLevel">
<option value="4" selected>Level 4 ($593)</option>
<option value="5">Level 5 ($1,253)</option>
<option value="0">None (gift only)</option>
</select>
</div>
</div>
<!-- Tabs -->
<div class="tabs">
<button class="tab-btn active" data-tab="overview">📊 Overview</button>
<button class="tab-btn" data-tab="timeline">📅 Timeline</button>
<button class="tab-btn" data-tab="comparison">⚖️ Compare Scenarios</button>
</div>
<!-- Tab: Overview -->
<div class="results active" id="tab-overview">
<div class="summary-grid" id="summaryCards">
<div class="summary-card">
<div class="label">Your Cost</div>
<div class="value accent" id="yourCost">$0</div>
</div>
<div class="summary-card">
<div class="label">Their Cost</div>
<div class="value" id="theirCost" style="color:var(--yellow)">$593</div>
</div>
<div class="summary-card">
<div class="label">Time to 3× L7</div>
<div class="value" id="timeToEndgame" style="font-size:1.3rem">~11 months</div>
</div>
<div class="summary-card">
<div class="label">Year 1 Referral Earnings</div>
<div class="value green" id="year1Earnings">$0</div>
</div>
<div class="summary-card">
<div class="label">Your ROI on Gift</div>
<div class="value green" id="roiTime">N/A</div>
<div class="sub">(no gift cost)</div>
</div>
<div class="summary-card">
<div class="label">Monthly Passive (3× L7)</div>
<div class="value green" id="monthlyPassive">$0</div>
<div class="sub">per person</div>
</div>
</div>
<div class="info-box" id="phaseBox">
<h3>📍 Journey Overview</h3>
<ul id="journeySteps">
<li>Loading scenario...</li>
</ul>
</div>
</div>
<!-- Tab: Timeline -->
<div class="results" id="tab-timeline">
<div class="table-wrap">
<div class="table-title">📅 Phase-by-Phase Earnings (per person)</div>
<div class="legend">
<div class="legend-item"><div class="legend-dot green"></div> ROI achieved here</div>
<div class="legend-item"><div class="legend-dot accent"></div> Endgame — 3× L7s</div>
</div>
<table>
<thead>
<tr>
<th>Phase</th>
<th>Cycles</th>
<th>Timeline</th>
<th class="num">Their Payout / Cycle</th>
<th class="num">Your 10% / Cycle</th>
<th class="num">Cumulative to You</th>
</tr>
</thead>
<tbody id="timelineBody">
</tbody>
</table>
</div>
</div>
<!-- Tab: Comparison -->
<div class="results" id="tab-comparison">
<div class="table-wrap">
<div class="table-title">⚖️ Scenario Comparison (per person)</div>
<table>
<thead>
<tr>
<th>Scenario</th>
<th>Their Upfront Cost</th>
<th>Your Cost</th>
<th class="num">Time to 3× L7</th>
<th class="num">Year 1 Earnings</th>
<th class="num">Total to Endgame</th>
<th class="num">Monthly Passive</th>
</tr>
</thead>
<tbody id="comparisonBody">
</tbody>
</table>
</div>
</div>
<div style="text-align:center;padding:30px 0 10px;color:var(--text-muted);font-size:0.78rem;">
Built for CBP wargaming • All figures in USDT • 10% withdrawal fee already factored into payouts
</div>
</div><!-- /container -->
<script>
// ─── CORE DATA ───────────────────────────────────────────────
const LEVELS = [
{ level: 1, act: 1, camp: 13, total: 14, payout: 17.17, clicks: 3, cpc: 0.48 },
{ level: 2, act: 7, camp: 77, total: 84, payout: 101.74, clicks: 3, cpc: 2.83 },
{ level: 3, act: 15, camp: 150, total: 165, payout: 194.40, clicks: 3, cpc: 5.40 },
{ level: 4, act: 30, camp: 300, total: 330, payout: 388.80, clicks: 5, cpc: 6.48 },
{ level: 5, act: 60, camp: 600, total: 660, payout: 777.60, clicks: 6, cpc: 10.80 },
{ level: 6, act: 120, camp: 1200, total: 1320, payout: 1555.20,clicks: 10, cpc: 12.96 },
{ level: 7, act: 240, camp: 2400, total: 2640, payout: 3240.00,clicks: 20, cpc: 13.50 },
];
const THREE_L7_PER_CYCLE = 9720; // payout
const THREE_L7_YOUR_CUT = 972; // 10%
const THREE_L7_MONTHLY = 1860; // ~per person
const SCENARIOS = [
{ id: 'gift1', label: 'L1 Gift ($14)', yourCost: 14, theirCost: 14, time: 19, yr1: 430, totalEG: 3711, monthly: 1860 },
{ id: 'gift3', label: 'L1-L3 Gift ($263)', yourCost: 263, theirCost: 263, time: 14, yr1: 415, totalEG: 3686, monthly: 1860 },
{ id: 'self4', label: 'Self-funded L4 ($593)', yourCost: 0, theirCost: 593, time: 11, yr1: 1373, totalEG: 3641, monthly: 1860 },
{ id: 'self5', label: 'Self-funded L5 ($1,253)',yourCost:0, theirCost:1253, time: 7, yr1: 1680, totalEG: 3357, monthly: 1860 },
];
// ─── PHASE GENERATORS ────────────────────────────────────────
function getGiftCost(giftLevel) {
if (giftLevel === 0) return 0;
return LEVELS.slice(0, giftLevel).reduce((s, l) => s + l.total, 0);
}
function getSelfFundCost(selfLevel) {
if (selfLevel === 0) return 0;
return LEVELS.slice(0, selfLevel).reduce((s, l) => s + l.total, 0);
}
// Generate phases based on starting position
function generatePhases(giftUpTo, selfFundUpTo, commissionPct) {
const phases = [];
let cum = 0;
let roiFound = false;
const giftCost = getGiftCost(giftUpTo);
const selfCost = getSelfFundCost(selfFundUpTo);
const effectiveStart = Math.max(giftUpTo, selfFundUpTo);
// If starting at or past a level, show initial payout phase
if (effectiveStart >= 4) {
// L4+L3 hybrid
addPhase(phases, 'L4 + L3 Hybrid', 5, '~3 months', 583.20, commissionPct);
addPhase(phases, 'L5', 5, '~3 months', 777.60, commissionPct);
addPhase(phases, 'L6', 4, '~2 months', 1555.20, commissionPct);
addPhase(phases, 'Single L7', 7, '~3 months', 3240.00, commissionPct);
} else if (effectiveStart >= 3) {
addPhase(phases, 'L3 + L1 Hybrid', 4, '~2.5 months', 211.57, commissionPct);
addPhase(phases, 'L4 + L3 Hybrid', 5, '~3 months', 583.20, commissionPct);
addPhase(phases, 'L5', 5, '~3 months', 777.60, commissionPct);
addPhase(phases, 'L6', 4, '~2 months', 1555.20, commissionPct);
addPhase(phases, 'Single L7', 7, '~3 months', 3240.00, commissionPct);
} else if (effectiveStart >= 2) {
addPhase(phases, 'L2 + L1 Hybrid', 4, '~2.5 months', 118.91, commissionPct);
addPhase(phases, 'L3 + L1 Hybrid', 4, '~2.5 months', 211.57, commissionPct);
addPhase(phases, 'L4 + L3 Hybrid', 5, '~3 months', 583.20, commissionPct);
addPhase(phases, 'L5', 5, '~3 months', 777.60, commissionPct);
addPhase(phases, 'L6', 4, '~2 months', 1555.20, commissionPct);
addPhase(phases, 'Single L7', 7, '~3 months', 3240.00, commissionPct);
} else {
// Start from L1 only
addPhase(phases, 'L1 Only', 9, '~3 months', 17.17, commissionPct);
addPhase(phases, 'L2 + L1 Hybrid', 4, '~2.5 months', 118.91, commissionPct);
addPhase(phases, 'L3 + L1 Hybrid', 4, '~2.5 months', 211.57, commissionPct);
addPhase(phases, 'L4 + L3 Hybrid', 5, '~3 months', 583.20, commissionPct);
addPhase(phases, 'L5', 5, '~3 months', 777.60, commissionPct);
addPhase(phases, 'L6', 4, '~2 months', 1555.20, commissionPct);
addPhase(phases, 'Single L7', 7, '~3 months', 3240.00, commissionPct);
}
// Endgame
const totalCum = phases.reduce((s, p) => s + p.cum, 0);
phases.push({
label: '🏁 3× L7 Endgame (ongoing)',
cycles: 'every 19 days',
timeline: 'forever',
payout: THREE_L7_PER_CYCLE,
yourCut: THREE_L7_YOUR_CUT * (commissionPct / 10),
cum: totalCum,
isEndgame: true
});
return phases;
}
function addPhase(arr, label, cycles, timeline, payoutPerCycle, commPct) {
const yourCut = payoutPerCycle * (commPct / 100);
const prevCum = arr.length > 0 ? arr[arr.length - 1].cum : 0;
const phaseCum = prevCum + yourCut * cycles;
// Determine if this is a multiple-cycle phase or a fixed one
arr.push({
label,
cycles: typeof cycles === 'number' ? cycles + '×' : cycles,
timeline,
payout: payoutPerCycle,
yourCut,
cum: phaseCum
});
}
// ─── UI UPDATE ───────────────────────────────────────────────
function updateAll() {
const numPeople = parseInt(document.getElementById('numPeople').value) || 1;
const commPct = parseFloat(document.getElementById('commissionPct').value) || 10;
const giftLevel = parseInt(document.getElementById('giftLevel').value);
const selfLevel = parseInt(document.getElementById('selfFundLevel').value);
const giftCost = getGiftCost(giftLevel);
const selfCost = getSelfFundCost(selfLevel);
const totalCost = giftCost + selfCost;
const effective = Math.max(giftLevel, selfLevel);
// Determine scenario label
let scenarioLabel = '';
let timeToEndgame = '';
let yr1Estimate = 0;
let totalToEG = 0;
if (giftLevel > 0 && selfLevel > 0) {
if (giftLevel >= selfLevel) {
scenarioLabel = `Gifted L1-L${giftLevel}`;
} else {
scenarioLabel = `Gifted L1-L${giftLevel} + self-funded L1-L${selfLevel}`;
}
} else if (giftLevel > 0) {
scenarioLabel = `Gifted L1-L${giftLevel}`;
} else if (selfLevel > 0) {
scenarioLabel = `Self-funded L1-L${selfLevel}`;
} else {
scenarioLabel = 'L1 Gift only ($14)';
}
// Time estimates
const timeMap = { 0: 19, 1: 19, 2: 16, 3: 14, 4: 11, 5: 7 };
timeToEndgame = timeMap[effective] || 11;
// Year 1 estimate based on effective start
const yr1Map = { 0: 430, 1: 430, 2: 480, 3: 415, 4: 1373, 5: 1680 };
yr1Estimate = yr1Map[effective] || 0;
// Total to endgame estimate
const egMap = { 0: 3711, 1: 3711, 2: 3700, 3: 3686, 4: 3641, 5: 3357 };
totalToEG = egMap[effective] || 0;
// Adjust for commission
const multiplier = commPct / 10;
const adjYr1 = yr1Estimate * multiplier;
const adjTotalEG = totalToEG * multiplier;
const adjMonthly = THREE_L7_MONTHLY * multiplier;
const adjPerCycle = THREE_L7_YOUR_CUT * multiplier;
// ROI
let roiText = 'N/A';
let roiSub = '';
if (giftCost > 0) {
// Estimate when ROI hits based on phases
const phases = generatePhases(giftLevel, selfLevel, commPct);
let cumCheck = 0;
let roiPhase = '';
for (const p of phases) {
if (p.isEndgame) break;
const cycles = typeof p.cycles === 'string' && p.cycles.includes('×')
? parseInt(p.cycles) : 0;
for (let i = 0; i < (cycles || 1); i++) {
cumCheck += p.yourCut;
if (cumCheck >= giftCost) {
roiPhase = p.label;
break;
}
}
if (roiPhase) break;
}
if (roiPhase) {
roiText = `~${Math.ceil(giftCost / (cumCheck || 1) * 4)} months`;
roiSub = `during ${roiPhase}`;
} else {
roiText = '~5.5 months';
}
}
// ─── Overview tab ──────────────────────────────────────
document.getElementById('yourCost').textContent = '$' + giftCost.toLocaleString();
document.getElementById('theirCost').textContent = '$' + selfCost.toLocaleString();
document.getElementById('timeToEndgame').textContent = '~' + timeToEndgame + ' months';
document.getElementById('year1Earnings').textContent = '$' + (adjYr1 * numPeople).toLocaleString();
document.getElementById('roiTime').textContent = roiText;
document.getElementById('monthlyPassive').textContent = '$' + (adjMonthly * numPeople).toLocaleString();
// Journey steps
const steps = [];
const effectiveLabel = effective >= 5 ? 'L5' : effective >= 4 ? 'L4' : effective >= 3 ? 'L3' : effective >= 2 ? 'L2' : 'L1';
steps.push(`🚀 Starts at ${effectiveLabel} (gift cost: $${giftCost}, their cost: $${selfCost})`);
if (giftCost > 0) {
steps.push(`💰 Your ROI on the $${giftCost} gift: ${roiText} ${roiSub ? '(' + roiSub + ')' : ''}`);
}
steps.push(`📈 Year 1 referral earnings: $${(adjYr1 * numPeople).toLocaleString()} (${numPeople} people × $${adjYr1.toLocaleString()})`);
steps.push(`🏁 3× L7 endgame in ~${timeToEndgame} months`);
steps.push(`♻️ Ongoing: $${(adjPerCycle * numPeople).toLocaleString()} every 19 days = ~$${(adjMonthly * numPeople).toLocaleString()}/month`);
steps.push(`💵 Total earned per person to endgame: ~$${adjTotalEG.toLocaleString()}`);
document.getElementById('journeySteps').innerHTML = steps.map(s => `<li>${s}</li>`).join('');
// ─── Timeline tab ──────────────────────────────────────
const phases = generatePhases(giftLevel, selfLevel, commPct);
const tbody = document.getElementById('timelineBody');
let rows = '';
let cumRunning = 0;
let roiHit = false;
for (const p of phases) {
cumRunning += p.yourCut * (typeof p.cycles === 'string' && p.cycles.includes('×') ? parseInt(p.cycles) : 1);
const isRoi = !roiHit && giftCost > 0 && cumRunning >= giftCost;
if (isRoi) roiHit = true;
let cls = '';
if (p.isEndgame) cls = 'endgame';
else if (isRoi) cls = 'highlight';
const cycleCount = typeof p.cycles === 'string' && p.cycles.includes('×')
? parseInt(p.cycles) : 0;
const cumulative = p.isEndgame ? p.cum : p.cum;
rows += `<tr class="${cls}">
<td>${p.label}</td>
<td>${p.cycles}</td>
<td>${p.timeline}</td>
<td class="num">$${p.payout.toFixed(2)}</td>
<td class="num ${p.isEndgame ? 'accent-text' : 'green-text'}">$${p.yourCut.toFixed(2)}</td>
<td class="num">$${cumulative.toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2})}</td>
</tr>`;
}
tbody.innerHTML = rows;
// ─── Comparison tab ────────────────────────────────────
const cb = document.getElementById('comparisonBody');
let compRows = '';
for (const s of SCENARIOS) {
const adj = commPct / 10;
compRows += `<tr>
<td>${s.label}</td>
<td>$${s.theirCost.toLocaleString()}</td>
<td>$${s.yourCost.toLocaleString()}</td>
<td class="num">~${s.time} months</td>
<td class="num">$${(s.yr1 * adj * numPeople).toLocaleString()}</td>
<td class="num">$${(s.totalEG * adj * numPeople).toLocaleString()}</td>
<td class="num">$${(s.monthly * adj * numPeople).toLocaleString()}/mo</td>
</tr>`;
}
// Add current scenario
compRows += `<tr style="background:rgba(108,92,231,0.08);font-weight:600">
<td>📌 Current: ${scenarioLabel}</td>
<td>$${selfCost.toLocaleString()}</td>
<td>$${giftCost.toLocaleString()}</td>
<td class="num">~${timeToEndgame} months</td>
<td class="num">$${(adjYr1 * numPeople).toLocaleString()}</td>
<td class="num">$${(adjTotalEG * numPeople).toLocaleString()}</td>
<td class="num">$${(adjMonthly * numPeople).toLocaleString()}/mo</td>
</tr>`;
cb.innerHTML = compRows;
}
// ─── TABS ──────────────────────────────────────────────────
document.querySelectorAll('.tab-btn').forEach(btn => {
btn.addEventListener('click', () => {
document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));
document.querySelectorAll('.results').forEach(r => r.classList.remove('active'));
btn.classList.add('active');
document.getElementById('tab-' + btn.dataset.tab).classList.add('active');
});
});
// ─── EVENT WIRING ──────────────────────────────────────────
['numPeople','commissionPct','giftLevel','selfFundLevel'].forEach(id => {
document.getElementById(id).addEventListener('input', updateAll);
document.getElementById(id).addEventListener('change', updateAll);
});
// ─── INIT ──────────────────────────────────────────────────
updateAll();
</script>
</body>
</html>