Files
cbp-calculator/index.html
T
2026-07-10 15:00:52 +00:00

740 lines
24 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!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>