Files
cbp-calculator/index.html
T

2848 lines
118 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>Crypto Team Build Network — ClickBaitPays Training Hub</title>
<meta name="description" content="Join the Crypto Team Build Network on ClickBaitPays. Click ads, earn crypto, build together. Use our profit calculator to model your ladder strategy.">
<meta name="keywords" content="ClickBaitPays, crypto, earn crypto, click ads, team build, referral, profit calculator, CBP ladder">
<!-- Open Graph / Social Preview -->
<meta property="og:type" content="website">
<meta property="og:url" content="https://cbp-calculator.saasy.top/">
<meta property="og:title" content="Crypto Team Build Network — ClickBaitPays Profit Calculator">
<meta property="og:description" content="Click ads. Earn crypto. Build together. Model your CBP ladder strategy with our profit calculator and join the team.">
<meta property="og:image" content="https://cbp-calculator.saasy.top/hero-banner.jpg">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta property="og:image:alt" content="Crypto Team Build Network — Join Our CBP Team">
<!-- Twitter Card -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="Crypto Team Build Network — ClickBaitPays Profit Calculator">
<meta name="twitter:description" content="Click ads. Earn crypto. Build together. Model your CBP ladder strategy with our profit calculator.">
<meta name="twitter:image" content="https://cbp-calculator.saasy.top/hero-banner.jpg">
<!-- Canonical -->
<link rel="canonical" href="https://cbp-calculator.saasy.top/">
<style>
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700;800&family=Orbitron:wght@600;700;900&display=swap');
:root {
--bg: #080015;
--card: #140532;
--card-hover: #1e0a4a;
--border: rgba(0,229,255,0.12);
--accent: #00e5ff;
--accent-glow: rgba(0,229,255,0.3);
--accent-magenta: #ff00ff;
--accent-magenta-glow: rgba(255,0,255,0.3);
--green: #00d68f;
--green-dim: rgba(0,214,143,0.12);
--red: #ff6b6b;
--yellow: #ffd93d;
--orange: #ff9f43;
--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; }
html { scroll-behavior: smooth; }
body {
font-family: var(--font);
background: var(--bg);
color: var(--text);
min-height: 100vh;
}
/* ══════════════════════════════════════════════════════════
HERO SECTION — Above the fold
══════════════════════════════════════════════════════════ */
.hero {
min-height: auto;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 32px 20px 48px;
position: relative;
overflow: hidden;
background:
radial-gradient(ellipse at 20% 50%, rgba(0,229,255,0.08) 0%, transparent 60%),
radial-gradient(ellipse at 80% 20%, rgba(255,0,255,0.05) 0%, transparent 50%),
var(--bg);
}
/* Decorative grid lines */
.hero::before {
content: '';
position: absolute;
inset: 0;
background-image:
linear-gradient(rgba(0,229,255,0.04) 1px, transparent 1px),
linear-gradient(90deg, rgba(0,229,255,0.04) 1px, transparent 1px);
background-size: 60px 60px;
pointer-events: none;
}
.hero-content {
position: relative;
z-index: 1;
max-width: 920px;
width: 100%;
text-align: center;
}
/* Hero banner image */
.hero-banner-img {
margin-bottom: 28px;
width: 100%;
max-width: 900px;
margin-left: auto;
margin-right: auto;
}
.hero-banner-img a {
display: block;
}
.hero-banner-img img {
width: 100%;
height: auto;
border-radius: 16px;
box-shadow: 0 4px 40px rgba(0,229,255,0.12);
display: block;
}
/* CTA buttons */
.hero-ctas {
display: flex;
gap: 14px;
justify-content: center;
flex-wrap: wrap;
margin-bottom: 48px;
}
.hero-btn {
display: inline-flex;
align-items: center;
gap: 10px;
padding: 16px 36px;
border-radius: var(--radius);
font-size: 1.05rem;
font-weight: 700;
text-decoration: none;
transition: all .2s;
cursor: pointer;
border: none;
font-family: var(--font);
}
.hero-btn-primary {
background: linear-gradient(135deg,#f59e0b,#eab308);
color: #0f1117;
box-shadow: 0 0 30px rgba(245,158,11,0.35);
font-weight: 700;
}
.hero-btn-primary:hover {
background: linear-gradient(135deg,#fbbf24,#f59e0b);
transform: translateY(-2px);
box-shadow: 0 0 45px rgba(245,158,11,0.5);
}
.hero-btn-secondary {
background: rgba(255,255,255,0.06);
color: var(--text);
border: 1.5px solid rgba(255,255,255,0.2);
backdrop-filter: blur(4px);
}
.hero-btn-secondary:hover {
background: rgba(255,255,255,0.12);
border-color: rgba(255,255,255,0.4);
transform: translateY(-2px);
}
/* Mobile-only hero QR code */
.hero-qr-mobile {
display: none;
text-align: center;
margin: 10px auto 22px;
}
.hero-qr-mobile img {
width: 150px;
height: 150px;
border-radius: 12px;
border: 2px solid var(--border);
}
.hero-qr-label {
font-size: 0.78rem;
color: var(--text-secondary);
margin-top: 6px;
}
@media (max-width: 767px) {
.hero-qr-mobile {
display: block;
}
}
/* How it works — 4 steps */
.steps-row {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 14px;
max-width: 750px;
margin: 0 auto 40px;
}
/* Step cards — needs more visual weight */
.step-card {
background: rgba(20,5,50,0.6);
border: 1px solid rgba(0,229,255,0.12);
border-radius: var(--radius);
padding: 20px 14px;
text-align: center;
transition: border-color 0.2s, transform 0.2s;
position: relative;
}
.step-card:hover {
border-color: rgba(0,229,255,0.3);
box-shadow: 0 0 15px rgba(0,229,255,0.1);
transform: translateY(-2px);
}
.step-num {
display: inline-flex;
align-items: center;
justify-content: center;
width: 32px;
height: 32px;
border-radius: 50%;
background: rgba(0,229,255,0.15);
color: #00e5ff;
font-weight: 800;
font-size: 0.85rem;
margin-bottom: 10px;
}
.step-card h4 {
font-size: 0.82rem;
font-weight: 700;
margin-bottom: 4px;
color: #e4e6f0;
}
.step-card p {
font-size: 0.72rem;
color: var(--text-muted);
line-height: 1.4;
}
/* Team callout banner */
.team-callout {
display: flex;
align-items: center;
justify-content: center;
gap: 16px;
flex-wrap: wrap;
background: linear-gradient(135deg, rgba(0,229,255,0.08), rgba(255,0,255,0.04));
border: 1px solid rgba(0,229,255,0.2);
border-radius: var(--radius);
padding: 18px 24px;
margin: 0 auto 32px;
max-width: 620px;
text-align: center;
}
.team-callout .callout-icon {
font-size: 1.6rem;
}
.team-callout .callout-text {
font-size: 0.95rem;
line-height: 1.5;
}
.team-callout .callout-text strong {
color: var(--text);
}
.team-callout a {
color: var(--accent);
font-weight: 700;
text-decoration: none;
white-space: nowrap;
border-bottom: 2px solid var(--accent);
transition: opacity 0.2s;
}
.team-callout a:hover {
opacity: 0.8;
}
/* Quick stat pills */
.stat-pills {
display: flex;
gap: 12px;
justify-content: center;
flex-wrap: wrap;
margin-bottom: 20px;
}
.stat-pill {
background: var(--card);
border: 1px solid var(--border);
border-radius: 100px;
padding: 10px 20px;
display: flex;
align-items: center;
gap: 10px;
font-size: 0.85rem;
}
.stat-pill .stat-val {
font-weight: 700;
color: var(--green);
font-size: 1rem;
}
.stat-pill .stat-val.accent {
color: var(--accent);
}
.stat-pill .stat-label {
color: var(--text-dim);
font-size: 0.78rem;
}
/* Hero footer link row */
.hero-links {
display: flex;
gap: 20px;
justify-content: center;
flex-wrap: wrap;
font-size: 0.82rem;
}
.hero-links a {
color: var(--text-muted);
text-decoration: none;
transition: color 0.2s;
display: inline-flex;
align-items: center;
gap: 6px;
}
.hero-links a:hover {
color: var(--accent);
}
.hero-links .sep {
color: var(--border);
}
/* Scroll hint */
.scroll-hint {
margin-top: 40px;
color: var(--text-muted);
font-size: 0.78rem;
display: flex;
flex-direction: column;
align-items: center;
gap: 6px;
cursor: pointer;
transition: color 0.2s;
border: none;
background: none;
font-family: var(--font);
}
.scroll-hint:hover {
color: var(--text-dim);
}
.scroll-hint .arrow {
font-size: 1.2rem;
animation: bounce 2s infinite;
}
@keyframes bounce {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(6px); }
}
/* ══════════════════════════════════════════════════════════
CALCULATOR SECTION — Collapsible
══════════════════════════════════════════════════════════ */
.calculator-section {
display: none;
padding: 16px;
}
.calculator-section.expanded {
display: block;
}
.section-divider {
display: flex;
align-items: center;
gap: 16px;
max-width: 1200px;
margin: 0 auto 20px;
padding: 0 4px;
}
.section-divider .line {
flex: 1;
height: 1px;
background: linear-gradient(90deg, transparent, var(--border), transparent);
}
.section-divider .label {
font-size: 0.72rem;
text-transform: uppercase;
letter-spacing: 1px;
color: var(--text-muted);
white-space: nowrap;
}
.calc-container {
max-width: 1200px;
margin: 0 auto;
}
/* ══════════════════════════════════════════════════════════
LEGACY STYLES (from original calculator, preserved)
══════════════════════════════════════════════════════════ */
.header {
text-align: center;
padding: 30px 16px 24px;
}
.header h1 {
font-size: 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: 6px;
font-size: 0.9rem;
}
.cta-bar {
display: flex;
justify-content: center;
gap: 12px;
margin-top: 16px;
flex-wrap: wrap;
}
.cta-btn {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 12px 28px;
border-radius: var(--radius);
font-size: 1rem;
font-weight: 600;
text-decoration: none;
transition: all .2s;
cursor: pointer;
border: none;
font-family: var(--font);
}
.cta-btn-primary {
background: linear-gradient(135deg,#f59e0b,#eab308);
color: #0f1117;
box-shadow: 0 0 20px rgba(245,158,11,0.3);
font-weight: 700;
}
.cta-btn-primary:hover {
background: linear-gradient(135deg,#fbbf24,#f59e0b);
transform: translateY(-1px);
box-shadow: 0 0 30px rgba(245,158,11,0.45);
}
.cta-btn-secondary {
background: var(--card);
color: var(--text);
border: 1px solid var(--border);
}
.cta-btn-secondary:hover {
background: var(--card-hover);
border-color: var(--accent);
}
.controls {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 12px;
background: var(--card);
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 20px;
margin-bottom: 20px;
}
.control-group {
display: flex;
flex-direction: column;
gap: 5px;
min-width: 0;
}
.control-group select, .control-group input {
width: 100%;
min-width: 0;
max-width: 100%;
}
.checkbox-row, .shared-link-row, .qr-row, .sub-hint {
min-width: 0;
max-width: 100%;
}
.control-group label {
font-size: 0.72rem;
font-weight: 600;
color: var(--text-dim);
text-transform: uppercase;
letter-spacing: 0.5px;
}
.control-group .fixed-value {
font-size: 1.1rem;
font-weight: 600;
color: var(--green);
padding: 8px 0;
}
.control-group .fixed-value .note {
font-size: 0.7rem;
font-weight: 400;
color: var(--text-muted);
}
.control-group input, .control-group select {
background: var(--bg);
border: 1px solid var(--border);
border-radius: var(--radius-sm);
padding: 9px 12px;
color: var(--text);
font-size: 0.9rem;
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; }
.checkbox-group {
display: flex;
align-items: center;
gap: 8px;
padding: 0;
}
.checkbox-group label {
font-size: 0.82rem;
font-weight: 400;
text-transform: none;
letter-spacing: 0;
color: var(--text);
white-space: normal;
}
.checkbox-group input[type="checkbox"] {
width: 16px;
height: 16px;
accent-color: var(--accent);
}
.checkbox-row {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 12px 24px;
background: var(--bg);
border: 1px solid var(--border);
border-radius: var(--radius-sm);
padding: 10px 14px;
margin-bottom: 0;
grid-column: 1 / -1;
}
.tg-link {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 6px 14px;
border-radius: var(--radius-sm);
background: linear-gradient(135deg, #1e96c8, #37aee2);
color: #fff;
text-decoration: none;
font-size: 0.82rem;
font-weight: 600;
transition: opacity 0.2s;
white-space: nowrap;
}
.tg-link:hover { opacity: 0.85; }
.tabs {
display: flex;
gap: 4px;
background: var(--card);
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 4px;
margin-bottom: 18px;
overflow-x: auto;
}
.tab-btn {
flex: 1;
padding: 9px 14px;
border: none;
border-radius: 8px;
background: transparent;
color: var(--text-dim);
font-size: 0.82rem;
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 { display: none; }
.results.active { display: block; }
.summary-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
gap: 10px;
margin-bottom: 20px;
}
.summary-card {
background: var(--card);
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 16px;
text-align: center;
}
.summary-card .label {
font-size: 0.68rem;
text-transform: uppercase;
letter-spacing: 0.5px;
color: var(--text-dim);
font-weight: 600;
}
.summary-card .value {
font-size: 1.5rem;
font-weight: 700;
margin-top: 5px;
}
.summary-card .value.green { color: var(--green); }
.summary-card .value.accent { color: var(--accent); }
.summary-card .value.yellow { color: var(--yellow); }
.summary-card .value.orange { color: var(--orange); }
.summary-card .sub {
font-size: 0.75rem;
color: var(--text-muted);
margin-top: 3px;
}
.chart-wrap {
background: var(--card);
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 20px;
margin-bottom: 20px;
overflow: hidden;
}
.chart-wrap h3 {
font-size: 0.85rem;
font-weight: 600;
color: var(--text-dim);
text-transform: uppercase;
letter-spacing: 0.5px;
margin-bottom: 16px;
}
#chartContainer, #chartContainer2, #chartContainer3 {
width: 100%;
height: 320px;
position: relative;
}
#profitChart, #timelineChart, #compareChart {
width: 100%;
height: 100%;
}
.table-wrap {
background: var(--card);
border: 1px solid var(--border);
border-radius: var(--radius);
overflow-x: auto;
margin-bottom: 18px;
}
.table-wrap .table-title {
padding: 14px 18px 0;
font-size: 0.82rem;
font-weight: 600;
color: var(--text-dim);
text-transform: uppercase;
letter-spacing: 0.5px;
}
table {
width: 100%;
border-collapse: collapse;
font-size: 0.84rem;
}
thead th {
text-align: left;
padding: 12px 18px;
font-size: 0.7rem;
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: 10px 18px;
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); }
.legend {
display: flex;
gap: 16px;
padding: 0 18px 12px;
flex-wrap: wrap;
}
.legend-item {
display: flex;
align-items: center;
gap: 6px;
font-size: 0.75rem;
color: var(--text-dim);
}
.legend-dot {
width: 10px;
height: 10px;
border-radius: 3px;
flex-shrink: 0;
}
.legend-dot.green { background: var(--green); }
.legend-dot.accent { background: var(--accent); }
.legend-dot.yellow { background: var(--yellow); }
.legend-dot.orange { background: var(--orange); }
.scenario-row { cursor: pointer; transition: background 0.15s; }
.scenario-row:hover { background: var(--card-hover) !important; }
.scenario-row.active-row { background: rgba(108,92,231,0.15) !important; }
.shared-link-row {
display: flex;
gap: 4px;
}
.shared-link-row input {
flex: 1;
min-width: 0;
font-size: 0.78rem;
font-family: monospace;
color: var(--accent);
background: var(--bg);
border: 1px solid var(--border);
border-radius: var(--radius-sm);
padding: 7px 10px;
outline: none;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.copy-sm-btn {
background: var(--accent);
color: #fff;
border: none;
padding: 7px 14px;
border-radius: var(--radius-sm);
cursor: pointer;
font-size: 0.78rem;
font-weight: 600;
white-space: nowrap;
transition: opacity 0.2s;
}
.copy-sm-btn:hover { opacity: 0.85; }
.copy-sm-btn.copied { background: var(--green); }
.sub-hint {
font-size: 0.68rem;
color: var(--text-muted);
margin-top: 4px;
}
.plan-section {
background: var(--card);
border: 1px solid var(--border);
border-radius: var(--radius);
margin: 16px 0 20px;
overflow: hidden;
}
.plan-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 16px;
background: var(--card-hover);
border-bottom: 1px solid var(--border);
font-weight: 600;
font-size: 0.85rem;
}
.copy-btn {
background: var(--accent);
color: #fff;
border: none;
padding: 5px 14px;
border-radius: var(--radius-sm);
cursor: pointer;
font-size: 0.78rem;
font-weight: 600;
transition: opacity 0.2s;
}
.copy-btn:hover { opacity: 0.85; }
.copy-btn.copied { background: var(--green); }
.plan-output {
padding: 16px;
margin: 0;
font-size: 0.82rem;
line-height: 1.6;
color: var(--text);
white-space: pre-wrap;
font-family: var(--font);
max-height: 500px;
overflow-y: auto;
}
.calc-footer {
text-align: center;
padding: 24px 0 10px;
color: var(--text-muted);
font-size: 0.75rem;
}
.calc-footer a {
color: var(--accent);
text-decoration: none;
}
.calc-footer a:hover {
text-decoration: underline;
}
/* ══════════════════════════════════════════════════════════
ROI DASHBOARD
ROI DASHBOARD
══════════════════════════════════════════════════════════ */
.roi-dashboard {
max-width: 720px;
margin: 0 auto;
padding: 10px 0;
}
.roi-dashboard h3 {
color: var(--accent);
font-size: 1.2rem;
margin: 0 0 4px;
}
.roi-subtitle {
font-size: 0.85rem;
color: var(--text-secondary);
margin: 0 0 20px;
}
.roi-inputs {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 12px;
margin-bottom: 20px;
}
@media (max-width: 560px) {
.roi-inputs { grid-template-columns: 1fr; }
}
.roi-field label {
display: block;
font-size: 0.78rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.06em;
color: var(--text-secondary);
margin-bottom: 5px;
}
.roi-field input,
.roi-field select {
width: 100%;
padding: 10px 12px;
border-radius: var(--radius-sm);
border: 1px solid var(--border);
background: var(--bg);
color: var(--text);
font-size: 0.95rem;
font-family: inherit;
box-sizing: border-box;
}
.roi-field select {
cursor: pointer;
}
.roi-field input:focus,
.roi-field select:focus {
outline: none;
border-color: var(--accent);
box-shadow: 0 0 0 2px rgba(108,92,231,0.2);
}
.roi-stats {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 12px;
margin-bottom: 24px;
}
@media (max-width: 600px) {
.roi-stats { grid-template-columns: repeat(2, 1fr); }
}
.roi-stat-card {
background: var(--card);
border: 1px solid var(--border);
border-radius: var(--radius-sm);
padding: 14px 12px;
text-align: center;
}
.roi-stat-label {
font-size: 0.72rem;
text-transform: uppercase;
letter-spacing: 0.07em;
color: var(--text-secondary);
margin-bottom: 6px;
}
.roi-stat-value {
font-size: 1.5rem;
font-weight: 700;
color: var(--accent);
}
.roi-stat-bar {
height: 5px;
background: var(--border);
border-radius: 3px;
margin-top: 10px;
overflow: hidden;
}
.roi-bar-fill {
height: 100%;
width: 0%;
background: linear-gradient(90deg, #6c5ce7, #a78bfa);
border-radius: 3px;
transition: width 0.4s ease;
}
.roi-phase-tracker {
margin-bottom: 24px;
}
.roi-phase-title {
font-size: 0.92rem;
font-weight: 600;
color: var(--text);
margin-bottom: 12px;
}
.roi-ladder {
display: flex;
flex-wrap: wrap;
gap: 6px;
}
.roi-ladder-step {
padding: 6px 14px;
border-radius: 20px;
font-size: 0.82rem;
font-weight: 600;
background: var(--bg);
border: 1px solid var(--border);
color: var(--text-muted);
opacity: 0.5;
}
.roi-location-badge {
background: linear-gradient(135deg,rgba(99,102,241,0.15),rgba(139,92,246,0.15));
border: 1px solid rgba(99,102,241,0.3);
border-radius: 8px;
padding: 8px 14px;
margin-bottom: 12px;
font-size: 0.9rem;
color: #e2e8f0;
display: inline-block;
}
.roi-location-badge span {
color: #818cf8;
font-weight: 600;
}
}
.roi-ladder-step.active {
background: rgba(108,92,231,0.2);
border-color: var(--accent);
color: var(--accent);
opacity: 1;
}
.roi-ladder-step.endgame {
border-color: #fbbf24;
color: #fbbf24;
opacity: 0.6;
}
.roi-ladder-step.endgame.active {
background: rgba(251,191,36,0.15);
border-color: #fbbf24;
color: #fbbf24;
opacity: 1;
}
.roi-ladder-step.passed {
opacity: 0.7;
color: #34d399;
border-color: #34d399;
}
.roi-milestones {
margin-bottom: 20px;
}
.roi-milestone-list {
display: flex;
flex-direction: column;
gap: 8px;
}
.roi-milestone-item {
display: flex;
align-items: center;
gap: 12px;
padding: 10px 14px;
background: var(--card);
border: 1px solid var(--border);
border-radius: var(--radius-sm);
font-size: 0.88rem;
}
.roi-milestone-icon {
font-size: 1.3rem;
flex-shrink: 0;
}
.roi-milestone-info {
flex: 1;
}
.roi-milestone-info .label {
font-weight: 600;
color: var(--text);
}
.roi-milestone-info .sub {
font-size: 0.8rem;
color: var(--text-secondary);
}
.roi-milestone-checked .milestone-check {
color: #34d399;
}
.roi-milestone-check {
font-size: 1.1rem;
flex-shrink: 0;
}
/* ══════════════════════════════════════════════════════════
RESPONSIVE
══════════════════════════════════════════════════════════ */
@media (max-width: 768px) {
.hero {
padding: 30px 16px 50px;
min-height: calc(100vh - 20px);
}
.hero h1 {
font-size: 1.9rem;
}
.hero-ctas {
flex-direction: column;
align-items: center;
}
.hero-btn {
width: 100%;
max-width: 340px;
justify-content: center;
padding: 14px 24px;
}
.steps-row {
grid-template-columns: repeat(2, 1fr);
gap: 10px;
}
.stat-pills {
flex-direction: column;
align-items: center;
}
.stat-pill {
width: 100%;
max-width: 300px;
justify-content: center;
}
.header h1 { font-size: 1.4rem; }
.controls { grid-template-columns: 1fr 1fr; gap: 10px; padding: 14px; }
.checkbox-row { gap: 8px; padding: 8px 10px; }
.summary-grid { grid-template-columns: repeat(2, 1fr); }
.summary-card .value { font-size: 1.15rem; }
.tabs { flex-wrap: wrap; }
.tab-btn { flex: 1 1 30%; min-width: 0; font-size: 0.75rem; padding: 7px 10px; }
table { font-size: 0.74rem; }
thead th, tbody td { padding: 8px 10px; }
#chartContainer, #chartContainer2, #chartContainer3 { height: 240px; }
.hero-links { flex-direction: column; align-items: center; gap: 10px; }
.hero-links .sep { display: none; }
}
@media (max-width: 480px) {
.controls { grid-template-columns: 1fr; }
.tab-btn { flex: 1 1 45%; }
}
</style>
</head>
<body>
<!-- ══════════════════════════════════════════════════════════
HERO SECTION — Above the fold
══════════════════════════════════════════════════════════ -->
<section class="hero" id="heroSection">
<div class="hero-content">
<!-- Hero banner image -->
<div class="hero-banner-img">
<a id="bannerRefLink" href="https://clickbaitpays.me/?ref=cryptoteambuild" target="_blank" rel="noopener">
<picture>
<source srcset="/hero-banner-mobile.jpg" media="(max-width: 767px)">
<img src="/hero-banner.jpg" alt="Join the Crypto Team Build Network — Build the ClickBaitPays team project with us" />
</picture>
</a>
<script>
(function(){
var ref = new URLSearchParams(window.location.search).get('ref');
if (ref) document.getElementById('bannerRefLink').href = 'https://clickbaitpays.me/?ref=' + encodeURIComponent(ref);
})();
</script>
</div>
<!-- CTA + Login side-by-side -->
<div class="hero-ctas">
<a class="hero-btn hero-btn-primary" id="heroSignupBtn" href="https://clickbaitpays.me/?ref=cryptoteambuild" target="_blank" rel="noopener">🚀 Join the Team — Sign Up on ClickBaitPays</a>
<button class="hero-btn hero-btn-secondary" id="heroCalcBtn">
🧮 Try the Profit Calculator
</button>
<a href="https://clickbaitpays.me/login.php" target="_blank" rel="noopener" class="hero-btn hero-btn-secondary">🔐 Log into ClickBaitPays</a>
<button class="hero-btn hero-btn-secondary" id="heroGuideBtn">📖 Sponsor Guide</button>
</div>
<div id="sponsorNudge" style="display:none;margin:10px auto 0;max-width:640px;background:rgba(255,180,0,0.08);border:1px solid rgba(255,180,0,0.35);border-radius:8px;padding:10px 14px;font-size:0.82rem;line-height:1.5;color:var(--text-muted);">
⚠️ This sponsor hasn't added their ClickBaitPays username in CryptoTeamBuild yet, so the sign-up button credits the team account for now. <strong>Sponsors:</strong> log into CryptoTeamBuild → Downline Builder → ClickBaitPays → enter your ClickBaitPays username, and your links fix themselves.
</div>
<!-- Mobile-only QR for on-the-spot recruiting -->
<div class="hero-qr-mobile">
<img id="heroQrCode" src="https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=https://cbp-calculator.saasy.top?ref=cryptoteambuild" alt="QR Code">
<div class="hero-qr-label">📱 Scan to join with my referral</div>
</div>
<!-- 4-Step How It Works -->
<div class="steps-row">
<div class="step-card">
<div class="step-num">1</div>
<h4>Sign Up</h4>
<p>Create your free ClickBaitPays account under our team</p>
</div>
<div class="step-card">
<div class="step-num">2</div>
<h4>Deposit</h4>
<p>Add funds to purchase ad campaigns — starting as low as $14</p>
</div>
<div class="step-card">
<div class="step-num">3</div>
<h4>Click Ads</h4>
<p>View 3–20 ads per day (takes ~5 minutes)</p>
</div>
<div class="step-card">
<div class="step-num">4</div>
<h4>Get Paid</h4>
<p>Every ~19 days you earn more than the campaign cost — reinvest and scale</p>
</div>
</div>
<!-- Team Telegram callout -->
<div class="team-callout">
<span class="callout-icon">🏆</span>
<span class="callout-text">
This is bigger than one program — when you join, you become part of the
<strong>Crypto Team Build Network</strong>: a team that builds together,
keeps you connected to your sponsor, and rewards you for showing up.
</span>
<!-- inline color: .team-callout a (accent cyan) out-specifies .hero-btn-primary's dark text -->
<a class="hero-btn hero-btn-primary hub-link" href="https://ctbrewards.saasy.top/" target="_blank" rel="noopener" style="flex-shrink:0;color:#0f1117;text-decoration:none;">🏆 Learn More — Join the Team Hub</a>
</div>
<!-- Quick Stat Pills -->
<div class="stat-pills">
<div class="stat-pill">
<span class="stat-val">$14</span>
<span class="stat-label">min start cost</span>
</div>
<div class="stat-pill">
<span class="stat-val">~19 days</span>
<span class="stat-label">per cycle</span>
</div>
<div class="stat-pill">
<span class="stat-val">$840</span>
<span class="stat-label">net / 19d with 1× L7</span>
</div>
<div class="stat-pill">
<span class="stat-val accent">$2,520</span>
<span class="stat-label">net / 19d with 3× L7</span>
</div>
</div>
<!-- Footer links -->
<div class="hero-links">
<a href="https://clickbaitpays.me/docs/getting_started_guide.pdf" target="_blank" rel="noopener">
📄 Getting Started Guide (PDF)
</a>
<span class="sep">•</span>
<a class="hub-link" href="https://ctbrewards.saasy.top/" target="_blank" rel="noopener">
💬 Join the Team Hub
</a>
<span class="sep">•</span>
<a href="https://clickbaitpays.me/login.php" target="_blank" rel="noopener">
🔐 Log into ClickBaitPays
</a>
<span class="sep">•</span>
<span style="color:var(--text-muted);font-size:0.78rem;">
⚠️ You're buying ad campaigns, not investments — earnings come from viewing ads
</span>
</div>
<!-- Scroll hint -->
<button class="scroll-hint" id="scrollHint" onclick="scrollToCalculator()">
<span class="arrow">↓</span>
<span>Full calculator &amp; breakdown below</span>
</button>
</div>
</section>
<!-- ══════════════════════════════════════════════════════════
CALCULATOR SECTION — Collapsible
══════════════════════════════════════════════════════════ -->
<div class="calculator-section" id="calculatorSection">
<div class="section-divider">
<span class="line"></span>
<span class="label">📊 Calculator &amp; Training Tools</span>
<span class="line"></span>
</div>
<div class="calc-container">
<div class="header">
<h1>CBP What-If Calculator</h1>
<p>Full ladder modeling — profit timeline, referral earnings, and scenario comparison</p>
<div class="cta-bar" id="calcCtaBar">
<a class="cta-btn cta-btn-primary" id="calcSignupBtn" href="#" target="_blank" rel="noopener">
🚀 Sign Up with My Referral Link
</a>
<script>
(function(){
var ref = new URLSearchParams(window.location.search).get('ref');
if (ref) document.getElementById('calcSignupBtn').href = 'https://clickbaitpays.me/?ref=' + encodeURIComponent(ref);
})();
</script>
<button class="cta-btn cta-btn-secondary" onclick="copyCalculatorLink()">
📄 Copy Calculator Link
</button>
<button class="cta-btn cta-btn-secondary" onclick="scrollToHero()">
🔝 Back to Overview
</button>
<a class="cta-btn cta-btn-secondary" href="https://clickbaitpays.me/login.php" target="_blank" rel="noopener" style="text-decoration:none;">
🔐 Log into ClickBaitPays
</a>
</div>
</div>
<div class="controls">
<div class="control-group">
<label>Number of people</label>
<input type="number" id="numPeople" value="0" min="0" max="100">
</div>
<div class="control-group">
<label>Your referral commission</label>
<div class="fixed-value">10% <span class="note">(fixed, not variable)</span></div>
<input type="hidden" id="commissionPct" value="10">
</div>
<div class="control-group">
<label>You gift up to level</label>
<select id="giftLevel">
<option value="0" selected>None (no gift)</option>
<option value="1">Level 1 ($14)</option>
<option value="2">Level 2 ($98)</option>
<option value="3">Level 3 ($263)</option>
<option value="4">Level 4 ($593)</option>
<option value="5">Level 5 ($1,253)</option>
</select>
</div>
<div class="control-group">
<label>They self-fund through level</label>
<select id="selfFundLevel">
<option value="0" selected>None (gift only)</option>
<option value="1">Level 1 ($14)</option>
<option value="2">Level 2 ($98)</option>
<option value="3">Level 3 ($263)</option>
<option value="4">Level 4 ($593)</option>
<option value="5">Level 5 ($1,253)</option>
</select>
</div>
<div class="control-group">
<label>Strategy</label>
<select id="strategyMode">
<option value="accelerate" selected>🚀 Accelerate — reinvest everything, fastest to 3× L7</option>
<option value="pocket">💰 Pocket along the way — keep part of each profit</option>
<option value="frontload">⚡ Front-load — pocket 50% until L6, then 25% (same arrival as flat 25%)</option>
<option value="park">🏝 Park &amp; collect — stop at a level, pocket it all</option>
</select>
</div>
<div class="control-group" id="pocketPctGroup" style="display:none">
<label>Pocket how much of each cycle's profit?</label>
<select id="pocketPct">
<option value="25">25% — mostly reinvest</option>
<option value="50" selected>50% — half and half</option>
<option value="75">75% — mostly pocket (slow climb)</option>
</select>
</div>
<div class="control-group" id="parkPhaseGroup" style="display:none">
<label>Park at which level?</label>
<select id="parkPhase"></select>
</div>
<div class="control-group">
<label>💵 Extra cash to inject now (optional)</label>
<input type="number" id="boostFunds" min="0" step="10" placeholder="e.g. 300" style="width:100%;padding:10px 12px;border:1px solid var(--border);border-radius:8px;background:var(--bg-card);color:var(--text-primary);font-size:0.95rem;">
<div class="sub-hint">The Boost Planner below finds the best campaign combo those dollars can buy</div>
</div>
<div class="checkbox-row">
<div class="checkbox-group">
<input type="checkbox" id="showReferral">
<label for="showReferral">Show referral earnings (my 10%)</label>
</div>
<div class="checkbox-group">
<input type="checkbox" id="alreadyJoined">
<label for="alreadyJoined">Already joined (skip signup language)</label>
</div>
<a class="tg-link hub-link" href="https://ctbrewards.saasy.top/" target="_blank" rel="noopener">
💬 Team Hub
</a>
</div>
<div class="control-group" style="grid-column: 1 / -1;">
<label>Share this link <span style="font-weight:400;color:var(--text-muted);text-transform:none;letter-spacing:0;font-size:0.68rem;">(sends the plan as-is)</span></label>
<div style="max-width:520px;width:100%;margin:0 auto;">
<div class="shared-link-row">
<input type="text" id="sharedLink" readonly>
<button class="copy-sm-btn" id="copyLinkBtn" onclick="copySharedLink()">📄 Copy</button>
</div>
<div class="sub-hint">The referral opens the calculator with your username pre-loaded</div>
<div class="qr-row" style="margin-top: 12px; text-align: center;">
<img id="refQrCode" src="https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=https://cbp-calculator.saasy.top?ref=cryptoteambuild" alt="QR Code" style="width:160px;height:160px;border-radius:12px;border:2px solid var(--border);">
<div style="font-size:12px;color:var(--text-secondary);margin-top:6px;">📱 Scan to open calculator</div>
</div>
</div>
</div>
</div>
<div id="shareablePlan" class="plan-section">
<div class="plan-header">
<span>📋 Referral Plan Preview</span>
<button class="copy-btn" id="copyPlanBtn" onclick="copyPlan()">📄 Copy Plan</button>
</div>
<pre id="planOutput" class="plan-output"></pre>
</div>
<div class="tabs">
<button class="tab-btn active" data-tab="overview">📊 Overview</button>
<button class="tab-btn" data-tab="timeline">📈 Profit Timeline</button>
<button class="tab-btn" data-tab="ladder">🪜 Full Ladder</button>
<button class="tab-btn" data-tab="comparison">⚖️ Compare</button>
<button class="tab-btn" data-tab="guide">📖 Sponsor Guide</button>
<button class="tab-btn" data-tab="progress">💰 My Progress</button>
</div>
<div class="results active" id="tab-overview">
<div class="summary-grid" id="summaryCards"></div>
<div class="table-wrap" id="boostWrap" style="display:none">
<div class="table-title">💵 Boost Planner — what your extra cash can do</div>
<div class="legend"><div class="legend-item" id="boostSubtitle"></div></div>
<table><thead><tr>
<th>Move</th><th class="num">Upfront cost</th><th class="num">Profit/cycle after</th>
<th>Time to 3× L7</th><th>vs. just banking it</th>
</tr></thead><tbody id="boostBody"></tbody></table>
<div class="sub-hint" style="margin-top:8px" id="boostNote"></div>
</div>
<div class="chart-wrap">
<h3>📈 Cumulative Profit Over Time</h3>
<div id="chartContainer"><canvas id="profitChart"></canvas></div>
</div>
<div class="table-wrap" id="overviewPhaseWrap">
<div class="table-title">📍 Phase-by-Phase Journey</div>
<div class="legend">
<div class="legend-item"><div class="legend-dot green"></div> ROI achieved</div>
<div class="legend-item"><div class="legend-dot accent"></div> Endgame (3× L7)</div>
</div>
<table><thead><tr>
<th>Phase</th><th class="num">Cycles</th><th>Timeline</th>
<th class="num">Their Gross Payout</th>
<th class="num">Their Net Profit</th>
<th class="num referral-col" id="headerYourCut">Sponsor's 10%</th>
<th class="num referral-col" id="headerCumulative">Sponsor's Cumulative</th>
</tr></thead><tbody id="overviewBody"></tbody></table>
</div>
</div>
<div class="results" id="tab-timeline">
<div class="chart-wrap">
<h3>📈 Monthly Profit Progression</h3>
<div id="chartContainer2"><canvas id="timelineChart"></canvas></div>
</div>
<div class="table-wrap">
<div class="table-title">📅 Month-by-Month Breakdown</div>
<table><thead><tr>
<th>Month</th><th>Active Phase</th>
<th class="num">Their Profit This Month</th>
<th class="num referral-col" id="headerTimelineComm">Sponsor's Commission/Month</th>
<th class="num referral-col" id="headerTimelineCum">Sponsor's Cumulative</th>
</tr></thead><tbody id="timelineBody"></tbody></table>
</div>
</div>
<div class="results" id="tab-ladder">
<div class="table-wrap">
<div class="table-title">🪜 Complete Ladder — All Levels</div>
<table><thead><tr>
<th>Level</th><th>Activation Fee</th><th class="num">Campaign Cost</th>
<th class="num">Total Prerequisite</th><th class="num">Payout (After 10% Fee)</th>
<th class="num">Net Profit/Cycle</th><th class="num">Clicks/Day</th><th class="num">CPC</th>
</tr></thead><tbody id="ladderBody"></tbody></table>
</div>
<div class="table-wrap">
<div class="table-title">🪜 Your Ladder Progression (based on starting position)</div>
<table><thead><tr>
<th>Step</th><th>Required Capital</th><th class="num">Investment</th>
<th class="num">Return</th><th class="num">Profit</th>
<th class="num">Cycles</th><th>Est. Time</th>
</tr></thead><tbody id="ladderProgressionBody"></tbody></table>
</div>
</div>
<div class="results" id="tab-comparison">
<div class="table-wrap">
<div class="table-title">⚖️ All Scenarios Side by Side (per person)</div>
<table><thead><tr>
<th>Scenario</th><th class="num">Sponsor Covers</th><th class="num">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 at 3× L7</th>
</tr></thead><tbody id="comparisonBody"></tbody></table>
</div>
<div class="chart-wrap">
<h3>⚖️ Scenario Comparison — Year 1 Earnings by Start</h3>
<div id="chartContainer3"><canvas id="compareChart"></canvas></div>
</div>
</div>
<div class="results" id="tab-progress">
<div class="roi-dashboard">
<h3>💰 Your Personal ROI Dashboard</h3>
<p class="roi-subtitle">Track your progress from first deposit to 3× L7 endgame. All figures in USDT.</p>
<!-- Input Row -->
<div class="roi-inputs">
<div class="roi-field">
<label>Total Deposited (out-of-pocket)</label>
<input type="number" id="roiDeposits" placeholder="e.g. 450" step="10" min="0">
</div>
<div class="roi-field">
<label>Total Earnings (all-time, incl. pending)</label>
<input type="number" id="roiTotalEarned" placeholder="e.g. 371.33" step="0.01" min="0">
<small style="color:var(--text-muted);font-size:0.72rem;display:block;margin-top:3px;">From stats → Earnings → In Earned Wallets + Total Earned</small>
</div>
<div class="roi-field">
<label>Campaign Phase</label>
<select id="roiPhase">
<option value="" selected disabled>Select your phase...</option>
<option value="l1">L1 Only</option>
<option value="l2l1">L2 + L1</option>
<option value="l3l1">L3 + L1</option>
<option value="l4">L4 Only</option>
<option value="l4l3">L4 + L3 Hybrid</option>
<option value="l5">L5 Only</option>
<option value="l5l3">L5 + L3 Hybrid</option>
<option value="l6">L6 Only</option>
<option value="l6l3">L6 + L3 Hybrid</option>
<option value="l7solo">L7 Solo</option>
<option value="l7x3">3× L7 Endgame</option>
</select>
</div>
<div class="roi-field">
<label>Cycles Completed This Phase</label>
<input type="number" id="roiCyclesDone" placeholder="e.g. 2" step="1" min="0">
</div>
</div>
<!-- Stats Cards Row -->
<div class="roi-stats">
<div class="roi-stat-card" id="roiStatROI">
<div class="roi-stat-label">ROI</div>
<div class="roi-stat-value">—</div>
<div class="roi-stat-bar"><div class="roi-bar-fill" id="roiBarROI"></div></div>
</div>
<div class="roi-stat-card" id="roiStatRecouped">
<div class="roi-stat-label">Recouped</div>
<div class="roi-stat-value">—</div>
</div>
<div class="roi-stat-card" id="roiStatRemaining">
<div class="roi-stat-label">To Breakeven</div>
<div class="roi-stat-value">—</div>
</div>
<div class="roi-stat-card" id="roiStatPhase">
<div class="roi-stat-label">Phase Progress</div>
<div class="roi-stat-value">—</div>
<div class="roi-stat-bar"><div class="roi-bar-fill" id="roiBarPhase"></div></div>
</div>
</div>
<!-- Phase Tracker -->
<div class="roi-phase-tracker">
<div class="roi-phase-title">🪜 Your Ladder — Where You Are vs Endgame</div>
<div class="roi-location-badge" id="roiLocationBadge">📌 You are here — <span id="roiHerePhase">—</span></div>
<div class="roi-ladder" id="roiLadder">
<div class="roi-ladder-step" data-phase="l1">L1</div>
<div class="roi-ladder-step" data-phase="l2l1">L2+L1</div>
<div class="roi-ladder-step" data-phase="l3l1">L3+L1</div>
<div class="roi-ladder-step" data-phase="l4">L4</div>
<div class="roi-ladder-step" data-phase="l4l3">L4+L3</div>
<div class="roi-ladder-step" data-phase="l5">L5</div>
<div class="roi-ladder-step" data-phase="l5l3">L5+L3</div>
<div class="roi-ladder-step" data-phase="l6">L6</div>
<div class="roi-ladder-step" data-phase="l6l3">L6+L3</div>
<div class="roi-ladder-step" data-phase="l7solo">L7</div>
<div class="roi-ladder-step endgame" data-phase="l7x3">🏆 3× L7</div>
</div>
</div>
<!-- Milestones -->
<div class="roi-milestones">
<div class="roi-phase-title">🏁 Milestones</div>
<div class="roi-milestone-list" id="roiMilestones"></div>
</div>
</div>
</div>
<div class="results" id="tab-guide">
<div style="max-width:680px;margin:0 auto;padding:8px 0;">
<h3 style="margin:0 0 10px;color:var(--accent);font-size:1.15rem;">📖 How to Use This Calculator as a Sponsor</h3>
<div style="background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-sm);padding:16px;margin-bottom:16px;">
<strong style="color:var(--accent);">🧍‍♂️ Live Demo Mode (for their eyes)</strong>
<p style="margin:6px 0 0;font-size:0.88rem;line-height:1.5;">Set the gift and self-fund levels, then copy the share link. When they open it, the calculator loads with those exact settings — they see the plan you built for them. No account needed.</p>
</div>
<div style="background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-sm);padding:16px;margin-bottom:16px;">
<strong style="color:var(--accent);">🎁 Gifting vs Self-Fund</strong>
<p style="margin:6px 0 0;font-size:0.88rem;line-height:1.5;">
<strong>Gift mode</strong> (default): "You gift up to Level X" — the plan says you covered those levels for them. Great for family.<br>
<strong>Self-fund mode</strong>: "They self-fund through Level X" — they pay for those levels themselves. Great for friends or social posts.<br>
Use both together for hybrid offers: e.g. gift L1-L3, they self-fund L4.
</p>
</div>
<div style="background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-sm);padding:16px;margin-bottom:16px;">
<strong style="color:var(--accent);">🧭 Strategy: match the plan to their budget &amp; goals</strong>
<p style="margin:6px 0 0;font-size:0.88rem;line-height:1.5;">
<strong>🚀 Accelerate</strong> (default): every profit reinvests — fastest path to 3× L7. Best for people who want the endgame and don't need cash along the way.<br>
<strong>💰 Pocket along the way</strong>: they keep 25/50/75% of each cycle's profit as spending money and bank the rest. The climb honestly slows down — the timeline and tables update to show it — but they see real money the whole way. Best for people who need proof it pays before they trust the climb.<br>
<strong>⚡ Front-load</strong>: pocket 50% of each cycle until L6, then tighten to 25% for the expensive late jumps. Because early upgrades are funded by the payout roll anyway, this arrives at 3× L7 on nearly the same date as flat 25% while paying roughly double during the early grind — usually the best effort-to-reward line for someone actively working the clicks. The share link remembers this choice too.<br>
<strong>🏝 Park &amp; collect</strong>: stop at a level on purpose and pocket the whole profit every cycle (e.g. L4+L3 ≈ $213/mo). Best for tight budgets who may never fund an L7 — and you still earn your 10% on every one of their cycles, forever.<br>
The share link remembers the strategy, so the plan they open is the plan you chose for them.
</p>
</div>
<div style="background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-sm);padding:16px;margin-bottom:16px;">
<strong style="color:var(--accent);">✅ Already Joined (PIF)</strong>
<p style="margin:6px 0 0;font-size:0.88rem;line-height:1.5;">Check "Already joined" if someone signed up already and you transferred funds to their account. The plan strips all signup language and tells them to purchase the campaign themselves.</p>
</div>
<div style="background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-sm);padding:16px;margin-bottom:16px;">
<strong style="color:var(--accent);">📤 Sharing</strong>
<p style="margin:6px 0 0;font-size:0.88rem;line-height:1.5;">
<strong>Link:</strong> The "Share this link" box copies a URL with your username pre-loaded. Send it in any chat.<br>
<strong>QR:</strong> Scan the QR code on mobile to open it yourself. Or screenshot it for in-person sharing.<br>
<strong>Plan text:</strong> The "Copy Plan" button copies the full message — paste it directly into Telegram, WhatsApp, or SMS.
</p>
</div>
<div style="background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-sm);padding:16px;margin-bottom:16px;">
<strong style="color:var(--accent);">💬 The Team Hub</strong>
<p style="margin:6px 0 0;font-size:0.88rem;line-height:1.5;">
The team now runs through the CTB Rewards hub — your referrals join through YOUR hub invite link (it keeps them connected to you as their sponsor in Crypto Team Build), and it's where you connect with the team and help your people:<br>
<a class="hub-link" href="https://ctbrewards.saasy.top/" target="_blank" rel="noopener" style="color:var(--accent);font-weight:600;">ctbrewards.saasy.top</a><br>
<span style="color:var(--text-muted);font-size:0.82rem;">Tip: add your ClickBaitPays username to the ClickBaitPays entry in your CryptoTeamBuild Downline Builder — then every calculator link you share automatically carries BOTH your ClickBaitPays referral and your hub invite.</span>
</p>
</div>
<div style="background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-sm);padding:16px;">
<strong style="color:var(--accent);">📌 Quick Tips</strong>
<ul style="margin:6px 0 0;font-size:0.88rem;line-height:1.6;padding-left:18px;">
<li>Set the calculator controls <em>before</em> copying the share link — it captures your settings, including the strategy</li>
<li>Toggle "Show referral earnings" on to show them how you get paid too (builds trust)</li>
<li>The plan auto-updates as you change settings — no refresh needed</li>
<li>Use the comparison tab to show them different start options side by side (it always compares on the Accelerate path, apples to apples)</li>
<li>Your referral link at the bottom stays the same regardless of settings</li>
</ul>
</div>
</div>
</div>
<div class="calc-footer">
Built exclusively for the Crypto Team Build Network • All figures in USDT • 10% withdrawal fee already factored into payouts •<br>
Referral link: <a id="footerRefLink" href="https://clickbaitpays.me/?ref=cryptoteambuild" target="_blank" rel="noopener">https://clickbaitpays.me/?ref=cryptoteambuild</a> • <a class="hub-link" href="https://ctbrewards.saasy.top/" target="_blank" rel="noopener">💬 Team Hub</a>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js@4"></script>
<script>
// ══════════════════════════════════════════════════════════════════════
// CBP CALCULATOR — Full logic (unchanged from original)
// ══════════════════════════════════════════════════════════════════════
const LEVELS = [
{ level: 1, act: 1, camp: 13, total: 14, payout: 17.17, clicks: 3, cpc: 0.48, netProfit: 4.17 },
{ level: 2, act: 7, camp: 77, total: 84, payout: 101.74, clicks: 3, cpc: 2.83, netProfit: 24.74 },
{ level: 3, act: 15, camp: 150, total: 165, payout: 194.40, clicks: 3, cpc: 5.40, netProfit: 44.40 },
{ level: 4, act: 30, camp: 300, total: 330, payout: 388.80, clicks: 5, cpc: 6.48, netProfit: 88.80 },
{ level: 5, act: 60, camp: 600, total: 660, payout: 777.60, clicks: 6, cpc: 10.80, netProfit: 177.60 },
{ level: 6, act: 120, camp: 1200, total: 1320, payout: 1555.20,clicks: 10, cpc: 12.96, netProfit: 355.20 },
{ level: 7, act: 240, camp: 2400, total: 2640, payout: 3240.00,clicks: 20, cpc: 13.50, netProfit: 840.00 },
];
// NOTE: cycles/months are NOT stored here — they are DERIVED per starting
// scenario by computePlan() below. Hand-tuned counts kept drifting from the
// money math (removed 2026-07-30). Payout/profit/reinvest are PDF-verified.
const HYBRIDS = {
'L1-only': { label: 'L1 Only', reinvest: 13, payout: 17.17, profit: 4.17, daysPer: 19 },
'L2+L1': { label: 'L2 + L1', reinvest: 90, payout: 118.91, profit: 28.91, daysPer: 19 },
'L3+L1': { label: 'L3 + L1', reinvest: 163, payout: 211.57, profit: 48.57, daysPer: 19 },
'L4+L3': { label: 'L4 + L3', reinvest: 450, payout: 583.20, profit: 133.20,daysPer: 19 },
'L5+L4': { label: 'L5 + L4', reinvest: 900, payout: 1166.40,profit: 266.40,daysPer: 19 },
'L6': { label: 'L6', reinvest: 1200, payout: 1555.20,profit: 355.20,daysPer: 19 },
'L7': { label: 'Single L7', reinvest: 2400, payout: 3240.00,profit: 840.00,daysPer: 19 },
'3xL7': { label: '3× L7 Endgame', reinvest: 7200, payout: 9720, profit: 2520, daysPer: 19 },
};
// Solo-climb cycle counts derived with the same reserve model (roll the
// final payout; L7 extra lanes are campaign-only).
const LADDER_STEPS = [
{ step: 'L4 Funded', capital: 300, invest: 300, ret: 388.80, profit: 88.80, cycles: 5, months: 3.1 },
{ step: 'L5 Ready', capital: 660, invest: 660, ret: 777.60, profit: 177.60,cycles: 5, months: 3.1 },
{ step: 'L6 Ready', capital: 1320, invest: 1320, ret: 1555.20,profit: 355.20,cycles: 5, months: 3.1 },
{ step: 'L7 Ready', capital: 2640, invest: 2640, ret: 3240.00,profit: 840.00,cycles: 6, months: 3.8 },
{ step: '3× L7 Endgame',capital: 7200, invest: 7200, ret: 9720, profit: 2520, cycles: 0, months: 0 },
];
const THREE_L7_YOUR_CUT = 972;
// ── Derived phase engine ────────────────────────────────────────────────────
// The reserve model (agreed with Marty 2026-07-30): recycle the campaigns that
// carry into the next phase, bank every profit as reserves, and on the upgrade
// cycle roll the full payout (skipping re-buys of campaigns being dropped)
// into the next phase's buy-in. Reserves carry across phases. Activation is a
// one-time per-level unlock; extra lanes of an activated level (3x L7) cost
// campaign only. Timeline is honest: cycles x 19 days.
const PHASE_SLOTS = {
'L1-only': [1], 'L2+L1': [2, 1], 'L3+L1': [3, 1], 'L4+L3': [4, 3],
'L5+L4': [5, 4], 'L6': [6], 'L7': [7], '3xL7': [7, 7, 7],
};
// pocketPct: number (flat) or the string 'frontload' = 50% below L6, 25%
// from L6 up (Marty 2026-07-31: take the money early when thresholds are
// cheap, tighten for the expensive late jumps — same arrival as flat 25%).
function pocketPctFor(pocketPct, phaseKey) {
if (pocketPct !== 'frontload') return pocketPct;
return Math.max(...PHASE_SLOTS[phaseKey]) >= 6 ? 25 : 50;
}
function computePlan(phases, pocketPct = 0) {
const plan = {};
let bal = 0;
const activated = new Set();
for (let lv = 1; lv <= Math.max(...PHASE_SLOTS[phases[0]]); lv++) activated.add(lv);
for (let i = 0; i < phases.length; i++) {
const k = phases[i];
const p = HYBRIDS[k];
if (k === '3xL7') { plan[k] = { cycles: 1, months: 0.63 }; break; }
if (i === phases.length - 1) {
// Parked terminal: they stop climbing here and collect indefinitely.
plan[k] = { cycles: 1, months: 0.63, parked: true };
break;
}
const nextSlots = [...PHASE_SLOTS[phases[i + 1]]];
const carried = [];
for (const lv of PHASE_SLOTS[k]) {
const j = nextSlots.indexOf(lv);
if (j !== -1) { carried.push(lv); nextSlots.splice(j, 1); }
}
let cost = 0;
for (const lv of nextSlots) {
const L = LEVELS[lv - 1];
cost += L.camp + (activated.has(lv) ? 0 : L.act);
activated.add(lv);
}
const carriedCamp = carried.reduce((sum, lv) => sum + LEVELS[lv - 1].camp, 0);
let cycles = 0;
while (cycles < 500) {
cycles++;
if (bal + p.payout - carriedCamp >= cost) { bal += p.payout - carriedCamp - cost; break; }
bal += p.profit * (1 - pocketPctFor(pocketPct, k) / 100);
}
plan[k] = { cycles, months: Math.round(cycles * p.daysPer / 30.4 * 10) / 10 };
}
return plan;
}
// Per-sequence phase info: PDF-verified money constants + derived cycles/months.
function phaseInfo(phases, pocketPct = 0) {
const plan = computePlan(phases, pocketPct);
const out = {};
for (const k of phases) out[k] = { ...HYBRIDS[k], ...plan[k] };
return out;
}
// ── Boost Planner (Marty 2026-07-31) ───────────────────────────────────────
// "I have extra cash right now — what's the best combination of campaigns to
// buy?" Slots rule confirmed by Marty: any level mix, up to 3 simultaneous
// campaigns, no sequential requirement. The planner enumerates every
// affordable add-on combo for the free slots, runs each through a generic
// lane simulator that follows the SAME reserve rules as computePlan (bank
// profits, recycle carried campaigns, roll the full payout on the upgrade
// cycle, activation once per level), and ranks by time to 3× L7. The
// baseline ("just bank it") gets the same cash as reserves, so the
// comparison is honest: buying lanes has to BEAT banking to win.
const LEVEL_TO_PHASE = { 1:'L1-only', 2:'L2+L1', 3:'L3+L1', 4:'L4+L3', 5:'L5+L4', 6:'L6', 7:'L7' };
function laneStats(lanes) {
let payout = 0, profit = 0, camp = 0;
for (const lv of lanes) {
const L = LEVELS[lv - 1];
payout += L.payout; profit += L.netProfit; camp += L.camp;
}
return { payout, profit, camp };
}
// Simulate from an arbitrary lane set + starting reserve to 3×L7.
// Mirrors computePlan's rules exactly; capped for safety.
function boostSim(startLanes, bal0, pocketPct = 0) {
let lanes = [...startLanes].sort((a, b) => b - a);
let bal = bal0;
let cycles = 0;
const activated = new Set(lanes);
const path = [lanes.join('+')];
let guard = 0;
while (!(lanes.length === 3 && lanes.every(l => l === 7)) && guard++ < 40) {
const maxLane = Math.max(...lanes);
const targetKey = maxLane >= 7 ? '3xL7' : LEVEL_TO_PHASE[maxLane + 1];
const targetSlots = targetKey === '3xL7' ? [7, 7, 7] : [...PHASE_SLOTS[targetKey]];
// Carried lanes: current campaigns that keep running in the target phase.
const remaining = [...targetSlots];
const carried = [];
for (const lv of lanes) {
const j = remaining.indexOf(lv);
if (j !== -1) { carried.push(lv); remaining.splice(j, 1); }
}
let cost = 0;
for (const lv of remaining) {
const L = LEVELS[lv - 1];
cost += L.camp + (activated.has(lv) ? 0 : L.act);
activated.add(lv);
}
const s = laneStats(lanes);
const carriedCamp = carried.reduce((sum, lv) => sum + LEVELS[lv - 1].camp, 0);
let spin = 0;
while (spin++ < 500) {
cycles++;
if (bal + s.payout - carriedCamp >= cost) { bal += s.payout - carriedCamp - cost; break; }
bal += s.profit * (1 - (pocketPct === 'frontload' ? (Math.max(...lanes) >= 6 ? 25 : 50) : pocketPct) / 100);
}
lanes = targetSlots.sort((a, b) => b - a);
path.push(targetKey);
}
cycles += 1; // the first 3×L7 endgame cycle (matches computePlan's 3xL7 entry)
return { cycles, months: Math.round(cycles * 19 / 30.4 * 10) / 10, path };
}
// Every add-on combo (multiset of levels, up to the free slots) affordable
// within `budget`. Activation charged once per newly-activated level.
function enumerateBoostCombos(currentLanes, budget) {
const freeSlots = 3 - currentLanes.length;
const activated = new Set();
for (let lv = 1; lv <= Math.max(...currentLanes); lv++) activated.add(lv);
const combos = [];
const walk = (startLv, picked) => {
if (picked.length > 0) {
const seen = new Set(activated);
let cost = 0;
for (const lv of picked) {
const L = LEVELS[lv - 1];
cost += L.camp + (seen.has(lv) ? 0 : L.act);
seen.add(lv);
}
if (cost <= budget) combos.push({ lanes: [...picked], cost });
}
if (picked.length >= freeSlots) return;
for (let lv = startLv; lv >= 1; lv--) walk(lv, [...picked, lv]);
};
walk(7, []);
return combos;
}
// Rank every affordable move for `extra` dollars from the current phase.
function boostPlan(phaseKey, extra, pocketPct = 0) {
const currentLanes = [...PHASE_SLOTS[phaseKey]];
const baseline = boostSim(currentLanes, extra, pocketPct);
const options = enumerateBoostCombos(currentLanes, extra).map(c => {
const lanes = [...currentLanes, ...c.lanes];
const sim = boostSim(lanes, extra - c.cost, pocketPct);
return { ...c, lanes, sim, profitPerCycle: laneStats(lanes).profit };
});
options.sort((a, b) => a.sim.cycles - b.sim.cycles || a.cost - b.cost);
return { baseline, currentLanes, options };
}
function renderBoost(phaseKey, mode, pocketPct) {
const wrap = document.getElementById('boostWrap');
if (!wrap) return;
const amount = parseInt(document.getElementById('boostFunds')?.value) || 0;
if (amount <= 0 || phaseKey === '3xL7') { wrap.style.display = 'none'; return; }
wrap.style.display = '';
const plan = boostPlan(phaseKey, amount, pocketPct);
const cur = plan.currentLanes.map(l => 'L' + l).join(' + ');
document.getElementById('boostSubtitle').textContent =
`$${amount.toLocaleString()} extra while running ${cur} — every affordable combo, simulated to 3× L7`;
const money = n => '$' + n.toLocaleString(undefined, { maximumFractionDigits: 0 });
const rows = [];
const base = plan.baseline;
const deltaTxt = sim => {
const d = base.cycles - sim.cycles;
if (d <= 0) return d === 0 ? 'same speed' : `${-d} cycle${d === -1 ? '' : 's'} slower`;
const mo = Math.round(d * 19 / 30.4 * 10) / 10;
return `${d} cycle${d === 1 ? '' : 's'} (~${mo} mo) faster`;
};
rows.push(`<tr><td>🏦 Bank it (no new campaigns)</td><td class="num">$0</td>` +
`<td class="num">${money(laneStats(plan.currentLanes).profit)}</td>` +
`<td>${base.cycles} cycles · ~${base.months} mo</td><td>—</td></tr>`);
plan.options.slice(0, 5).forEach((o, i) => {
const label = 'Add ' + o.lanes.slice(plan.currentLanes.length).map(l => 'L' + l).join(' + ');
const best = i === 0 && o.sim.cycles < base.cycles;
rows.push(`<tr${best ? ' style="background:rgba(74,222,128,.07)"' : ''}>` +
`<td>${best ? '⭐ ' : ''}${label}</td><td class="num">${money(o.cost)}</td>` +
`<td class="num">${money(o.profitPerCycle)}</td>` +
`<td>${o.sim.cycles} cycles · ~${o.sim.months} mo</td><td>${deltaTxt(o.sim)}</td></tr>`);
});
document.getElementById('boostBody').innerHTML = rows.join('');
document.getElementById('boostNote').textContent =
'Rules per the program: up to 3 campaigns at once, any level mix — no need to climb sequentially. ' +
'Activation is charged once per level; unspent cash goes into reserves either way. ' +
(mode === 'park' ? 'Shown on the climb-to-endgame basis; if you park, the best combo is simply the highest profit/cycle you can afford.' :
mode === 'pocket' ? `Simulated with your ${pocketPct}% pocket setting.` :
mode === 'frontload' ? 'Simulated with the front-load setting: pocket 50% until L6, then 25%.' :
'Simulated in Accelerate mode, same reserve math as the rest of the calculator.');
}
function getLevelCost(upTo) {
if (upTo <= 0) return 0;
return LEVELS.slice(0, upTo).reduce((s, l) => s + l.total, 0);
}
function getEffectiveStart(gift, selfF) {
return Math.max(gift, selfF);
}
function getPhaseSequence(effectiveStart) {
if (effectiveStart >= 7) return ['L7','3xL7'];
if (effectiveStart >= 6) return ['L6','L7','3xL7'];
if (effectiveStart >= 5) return ['L5+L4','L6','L7','3xL7'];
if (effectiveStart >= 4) return ['L4+L3','L5+L4','L6','L7','3xL7'];
if (effectiveStart >= 3) return ['L3+L1','L4+L3','L5+L4','L6','L7','3xL7'];
if (effectiveStart >= 2) return ['L2+L1','L3+L1','L4+L3','L5+L4','L6','L7','3xL7'];
return ['L1-only','L2+L1','L3+L1','L4+L3','L5+L4','L6','L7','3xL7'];
}
function estimateMonths(phases, pocketPct = 0) {
const PI = phaseInfo(phases, pocketPct);
let totalDays = 0;
for (const k of phases) {
if (k === '3xL7' || PI[k].parked) break;
totalDays += PI[k].cycles * PI[k].daysPer;
}
return Math.round(totalDays / 30.4 * 10) / 10;
}
function estimateYear1Cum(phases, commPct, giftLevel, pocketPct = 0) {
// Includes endgame (or parked-level) cycles that land inside year 1.
const PI = phaseInfo(phases, pocketPct);
let cum = 0;
let daysLeft = 365;
for (const k of phases) {
const p = PI[k];
const yourCut = p.payout * (commPct / 100);
if (k === '3xL7' || p.parked) {
cum += Math.max(0, Math.floor(daysLeft / p.daysPer)) * yourCut;
break;
}
const cyclesFit = Math.min(p.cycles, Math.floor(daysLeft / p.daysPer));
cum += cyclesFit * yourCut;
daysLeft -= cyclesFit * p.daysPer;
if (daysLeft <= 0) break;
}
return Math.round(cum);
}
function buildMonthlyTimeline(phases, commPct, pocketPct = 0) {
// One row per 19-day cycle, stamped with the real calendar month it lands
// in (the old version advanced a full month per cycle — 60% too slow).
const PI = phaseInfo(phases, pocketPct);
const months = [];
let cumComm = 0, days = 0;
for (const k of phases) {
const p = PI[k];
const yourCut = p.payout * (commPct / 100);
const terminal = k === '3xL7' || p.parked;
const n = terminal ? 10 : p.cycles;
for (let c = 0; c < n; c++) {
days += p.daysPer;
cumComm += yourCut;
months.push({ m: Math.ceil(days / 30.4), phase: c === 0 ? p.label : '', prof: Math.round(p.profit), comm: Math.round(yourCut), cumComm: Math.round(cumComm) });
}
if (terminal || days > 913) break;
}
return months;
}
function buildSCENARIOS() {
const levels = [
{ giftLvl: 1, selfLvl: 0, id: 'gift1', label: 'L1 Gift ($14)', yourCost: 14 },
{ giftLvl: 0, selfLvl: 1, id: 'self1', label: 'Self L1 ($14)', yourCost: 0 },
{ giftLvl: 2, selfLvl: 0, id: 'gift2', label: 'L1-L2 Gift ($98)', yourCost: 98 },
{ giftLvl: 0, selfLvl: 2, id: 'self2', label: 'Self L2 ($98)', yourCost: 0 },
{ giftLvl: 3, selfLvl: 0, id: 'gift3', label: 'L1-L3 Gift ($263)', yourCost: 263},
{ giftLvl: 0, selfLvl: 3, id: 'self3', label: 'Self L3 ($263)', yourCost: 0 },
{ giftLvl: 4, selfLvl: 0, id: 'gift4', label: 'L1-L4 Gift ($593)', yourCost: 593},
{ giftLvl: 0, selfLvl: 4, id: 'self4', label: 'Self L4 ($593)', yourCost: 0 },
{ giftLvl: 5, selfLvl: 0, id: 'gift5', label: 'L1-L5 Gift ($1,253)', yourCost:1253},
{ giftLvl: 0, selfLvl: 5, id: 'self5', label: 'Self L5 ($1,253)', yourCost: 0 },
];
return levels.map(s => {
const eff = Math.max(s.giftLvl, s.selfLvl);
const phases = getPhaseSequence(eff);
const t = Math.round(estimateMonths(phases));
const y = estimateYear1Cum(phases, 10, s.giftLvl);
const PI = phaseInfo(phases);
const eg = phases.filter(k => k !== '3xL7')
.reduce((sum, k) => sum + PI[k].payout * 0.10 * PI[k].cycles, 0);
// Monthly passive at 3x L7: $972/cycle x (30.4/19) cycles per month.
return { ...s, time: t, yr1: Math.round(y), totalEG: Math.round(eg), monthly: Math.round(THREE_L7_YOUR_CUT * 30.4 / 19) };
});
}
const SCENARIOS = buildSCENARIOS();
let chart1 = null, chart2 = null, chart3 = null;
function updateAll() {
const numPeople = parseInt(document.getElementById('numPeople').value) || 0;
const commPct = parseFloat(document.getElementById('commissionPct').value) || 10;
const giftLevel = parseInt(document.getElementById('giftLevel').value);
const selfLevel = parseInt(document.getElementById('selfFundLevel').value);
const showRef = document.getElementById('showReferral').checked;
const mode = document.getElementById('strategyMode').value;
const pocketPct = mode === 'pocket' ? (parseInt(document.getElementById('pocketPct').value) || 50)
: mode === 'frontload' ? 'frontload' : 0;
document.getElementById('pocketPctGroup').style.display = mode === 'pocket' ? '' : 'none';
document.getElementById('parkPhaseGroup').style.display = mode === 'park' ? '' : 'none';
const mult = commPct / 10;
const giftCost = getLevelCost(giftLevel);
const selfCost = getLevelCost(selfLevel);
const effective = getEffectiveStart(giftLevel, selfLevel);
let phases = getPhaseSequence(effective);
renderBoost(phases[0], mode, pocketPct);
// Park & collect: keep the park-level select in sync with the sequence,
// then truncate the journey at the chosen level (terminal = collect there).
const parkSel = document.getElementById('parkPhase');
const climb = phases.filter(k => k !== '3xL7');
if (parkSel.dataset.seq !== climb.join(',')) {
const keep = parkSel.dataset.want || parkSel.value;
parkSel.dataset.seq = climb.join(',');
parkSel.innerHTML = climb.map(k => `<option value="${k}">${HYBRIDS[k].label} — $${HYBRIDS[k].profit.toFixed(2)}/cycle profit</option>`).join('');
parkSel.value = [...parkSel.options].some(o => o.value === keep) ? keep : climb[climb.length - 1];
delete parkSel.dataset.want;
}
if (mode === 'park') phases = phases.slice(0, phases.indexOf(parkSel.value) + 1);
const PI = phaseInfo(phases, pocketPct);
const endKey = phases[phases.length - 1];
const totalMonths = estimateMonths(phases, pocketPct);
const yr1Cum = estimateYear1Cum(phases, commPct, giftLevel, pocketPct) * numPeople;
const yr1PerPerson = estimateYear1Cum(phases, commPct, giftLevel, pocketPct);
const totalEG = Math.round(phases.filter(k => k !== '3xL7' && !PI[k].parked)
.reduce((s, k) => s + PI[k].payout * (commPct / 100) * PI[k].cycles, 0) * 10) / 10;
// True monthly (cycles are 19 days): per-cycle cut x 30.4/19.
const endCutPerCycle = PI[endKey].parked ? PI[endKey].payout * (commPct / 100) : THREE_L7_YOUR_CUT * mult;
const monthlyPassive = Math.round(endCutPerCycle * 30.4 / 19 * numPeople);
const pocketedTotal = Math.round(phases.filter(k => k !== '3xL7' && !PI[k].parked)
.reduce((s, k) => s + PI[k].profit * (pocketPctFor(pocketPct, k) / 100) * PI[k].cycles, 0));
let totalToEGPerPerson = 0;
for (const k of phases) {
if (k === '3xL7' || PI[k].parked) break;
totalToEGPerPerson += PI[k].payout * (commPct / 100) * PI[k].cycles;
}
totalToEGPerPerson = Math.round(totalToEGPerPerson * 100) / 100;
let roiText = 'N/A', roiSub = '';
if (giftCost > 0) {
// Day-accurate: accumulate real elapsed days across the derived plan
// (the old formula assumed one cycle per prior phase).
let cumCheck = 0, daysAcc = 0;
outer: for (const k of phases) {
const p = PI[k];
const yourCut = p.payout * (commPct / 100);
const n = (k === '3xL7' || p.parked) ? 60 : p.cycles;
for (let i = 0; i < n; i++) {
daysAcc += p.daysPer;
cumCheck += yourCut;
if (cumCheck >= giftCost) {
roiText = `~${Math.round(daysAcc / 30.4 * 10) / 10} months`;
roiSub = `during ${p.label}`;
break outer;
}
}
}
}
const summaryHtml = `
<div class="summary-card">
<div class="label">Sponsor Covers</div>
<div class="value accent">$${giftCost.toLocaleString()}</div>
<div class="sub">${numPeople > 1 ? `× ${numPeople} = $${(giftCost * numPeople).toLocaleString()}` : ''}</div>
</div>
<div class="summary-card">
<div class="label">Your Cost</div>
<div class="value yellow">$${selfCost.toLocaleString()}</div>
<div class="sub">per person</div>
</div>
<div class="summary-card">
<div class="label">${mode === 'park' ? 'Time to Park Level' : 'Time to 3× L7'}</div>
<div class="value orange" style="font-size:1.3rem">~${totalMonths} months</div>
</div>
${(mode === 'pocket' || mode === 'frontload') ? `
<div class="summary-card">
<div class="label">Pocketed Along the Way</div>
<div class="value yellow">$${pocketedTotal.toLocaleString()}</div>
<div class="sub">${pocketPct === 'frontload' ? "50% early, 25% from L6" : pocketPct + "% of each cycle&#39;s profit"}</div>
</div>` : ''}
${mode === 'park' ? `
<div class="summary-card">
<div class="label">Their Income at Park</div>
<div class="value green">$${Math.round(HYBRIDS[endKey].profit * 30.4 / 19).toLocaleString()}/mo</div>
<div class="sub">${HYBRIDS[endKey].label}, pocketing every cycle</div>
</div>` : ''}
${numPeople > 0 ? `
<div class="summary-card">
<div class="label">Year 1 Referral Earnings</div>
<div class="value green">$${yr1Cum.toLocaleString()}</div>
<div class="sub">${numPeople > 1 ? `$${yr1PerPerson.toLocaleString()} / person` : ''}</div>
</div>` : ''}
<div class="summary-card">
<div class="label">ROI on Gift</div>
<div class="value green">${roiText}</div>
<div class="sub">${roiSub || (giftCost > 0 ? '' : 'no gift cost')}</div>
</div>
${numPeople > 0 ? `
<div class="summary-card">
<div class="label">Monthly Passive (${mode === 'park' ? 'at park' : '3× L7'})</div>
<div class="value green">$${monthlyPassive.toLocaleString()}</div>
<div class="sub">${numPeople > 1 ? `$${Math.round(monthlyPassive / numPeople).toLocaleString()} / person` : 'per month'}</div>
</div>` : ''}
`;
document.getElementById('summaryCards').innerHTML = summaryHtml;
let cumRunning = 0;
let roiCum = 0;
let roiHit = false;
let roiRow = ''; // phase key where ROI was achieved
let rows = '';
for (const k of phases) {
const p = PI[k];
const yourCut = p.payout * (commPct / 100);
const cyclesNum = (k === '3xL7' || p.parked) ? 1 : p.cycles;
// Track cumulative payout (always accumulates — this is the total to sponsor)
cumRunning += yourCut * cyclesNum;
// Track ROI separately (only when there's a gift cost)
if (!roiHit && giftCost > 0) {
roiCum += yourCut * cyclesNum;
if (roiCum >= giftCost) {
roiHit = true;
roiRow = k;
}
}
const cls = (k === '3xL7' || p.parked) ? 'endgame' : (k === roiRow ? 'highlight' : '');
// Phase totals (x cycles) so every money column matches the Cycles column;
// per-cycle values here kept getting read as phase totals (Marty 07-30).
rows += `<tr class="${cls}">
<td>${p.label}</td>
<td class="num">${(k === '3xL7' || p.parked) ? 'every 19d' : `${cyclesNum}×`}</td>
<td>${(k === '3xL7' || p.parked) ? (p.parked ? '🏝 parked' : 'ongoing') : `~${p.months} months`}</td>
<td class="num">$${(p.payout * cyclesNum).toFixed(2)}</td>
<td class="num">$${(p.profit * cyclesNum).toFixed(2)}</td>
<td class="num green-text referral-col">$${(yourCut * cyclesNum).toFixed(2)}</td>
<td class="num referral-col">$${cumRunning.toFixed(2)}</td>
</tr>`;
}
document.getElementById('overviewBody').innerHTML = rows;
const chartData = [];
let chartCum = 0;
let chartDays = 0;
for (const k of phases) {
const p = PI[k];
const yourCut = p.payout * (commPct / 100);
const cycles = (k === '3xL7' || p.parked) ? 10 : p.cycles;
for (let i = 0; i < cycles; i++) {
chartDays += p.daysPer;
chartCum += yourCut;
chartData.push({ m: Math.ceil(chartDays / 30.4), cum: Math.round(chartCum * 100) / 100 });
}
if (k === '3xL7' || p.parked) break;
}
const chartLabels = chartData.map(d => `M${d.m}`);
const chartValues = chartData.map(d => d.cum);
// Build referral dataset separately to avoid nested backtick issues
let referralDataset = null;
if (numPeople > 0) {
const label = numPeople > 1 ? `Total (${numPeople} people) Cumulative Referral Earnings` : 'Your Cumulative Referral Earnings';
const data = numPeople > 1 ? chartValues.map(v => v * numPeople) : chartValues;
referralDataset = {
label: label,
data: data,
borderColor: '#6c5ce7',
backgroundColor: 'rgba(108,92,231,0.1)',
fill: true,
tension: 0.3,
pointRadius: 3,
pointHoverRadius: 5,
};
}
if (chart1) { chart1.destroy(); chart1 = null; }
if (chart2) { chart2.destroy(); chart2 = null; }
if (chart3) { chart3.destroy(); chart3 = null; }
const datasets = [
{
label: 'Their Profit',
data: chartValues,
borderColor: '#00d2ff',
backgroundColor: 'rgba(0,210,255,0.1)',
fill: true,
tension: 0.3,
pointRadius: 3,
pointHoverRadius: 5,
},
referralDataset,
].filter(Boolean);
const ctx1 = document.getElementById('profitChart').getContext('2d');
chart1 = new Chart(ctx1, {
type: 'line',
data: {
labels: chartLabels,
datasets: datasets,
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: { labels: { color: '#8a8fa8', font: { size: 11 } } },
tooltip: { callbacks: { label: ctx => '$' + ctx.parsed.y.toLocaleString() } }
},
scales: {
x: { ticks: { color: '#5a5e7a', maxTicksLimit: 15, font: { size: 10 } }, grid: { color: '#2a2e4522' } },
y: { ticks: { color: '#5a5e7a', font: { size: 10 }, callback: v => '$' + v.toLocaleString() }, grid: { color: '#2a2e4522' } }
}
}
});
const monthly = buildMonthlyTimeline(phases, commPct);
const actualPeople = Math.max(numPeople, 1);
let tRows = '';
let runningCum = 0;
for (const m of monthly) {
runningCum += m.comm * actualPeople;
tRows += `<tr>
<td>Month ${m.m}</td>
<td>${m.phase}</td>
<td class="num">$${m.prof.toLocaleString()}</td>
<td class="num green-text referral-col">$${(m.comm * actualPeople).toLocaleString()}</td>
<td class="num referral-col">$${runningCum.toLocaleString()}</td>
</tr>`;
}
document.getElementById('timelineBody').innerHTML = tRows;
// Referral-column visibility — must run AFTER both tables render, or the
// freshly built cells ignore the toggle while the headers obey it (the
// blank-headers-over-populated-columns bug, 2026-07-30).
const showRefCols = (numPeople > 0) && showRef;
for (const el of document.querySelectorAll('.referral-col')) {
el.style.display = showRefCols ? '' : 'none';
}
const ctx2 = document.getElementById('timelineChart').getContext('2d');
chart2 = new Chart(ctx2, {
type: 'bar',
data: {
labels: monthly.map(m => `M${m.m}`),
datasets: [
{
label: 'Their Profit',
data: monthly.map(m => m.prof),
backgroundColor: 'rgba(0,214,143,0.4)',
borderColor: '#00d68f',
borderWidth: 1,
borderRadius: 3,
},
{
label: 'Your Commission',
data: monthly.map(m => m.comm * actualPeople),
backgroundColor: 'rgba(108,92,231,0.5)',
borderColor: '#6c5ce7',
borderWidth: 1,
borderRadius: 3,
}
]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: { labels: { color: '#8a8fa8', font: { size: 11 } } },
tooltip: { callbacks: { label: ctx => '$' + ctx.parsed.y.toLocaleString() } }
},
scales: {
x: { ticks: { color: '#5a5e7a', maxTicksLimit: 20, font: { size: 10 } }, grid: { color: '#2a2e4522' } },
y: { ticks: { color: '#5a5e7a', font: { size: 10 }, callback: v => '$' + v.toLocaleString() }, grid: { color: '#2a2e4522' } }
}
}
});
let lRows = '';
for (const l of LEVELS) {
lRows += `<tr>
<td>Level ${l.level}</td>
<td>$${l.act}</td>
<td class="num">$${l.camp}</td>
<td class="num">$${l.total}</td>
<td class="num green-text">$${l.payout.toFixed(2)}</td>
<td class="num">$${l.netProfit.toFixed(2)}</td>
<td class="num">${l.clicks}</td>
<td class="num">$${l.cpc.toFixed(2)}</td>
</tr>`;
}
document.getElementById('ladderBody').innerHTML = lRows;
const ladderStart = effective;
let lpRows = '';
let started = false;
for (const s of LADDER_STEPS) {
const stepNum = LADDER_STEPS.indexOf(s) + 4;
if (stepNum <= ladderStart && ladderStart < 7) continue;
started = true;
const yourCut = s.ret * (commPct / 100);
lpRows += `<tr>
<td>${s.step}</td>
<td>$${s.capital.toLocaleString()}</td>
<td class="num">$${s.invest.toLocaleString()}</td>
<td class="num green-text">$${s.ret.toFixed(2)}</td>
<td class="num">$${s.profit.toFixed(2)}</td>
<td class="num">${s.cycles > 0 ? s.cycles + '×' : 'ongoing'}</td>
<td>${s.months > 0 ? `~${s.months} months` : 'forever'}</td>
</tr>`;
}
if (!lpRows) lpRows = '<tr><td colspan="7" style="text-align:center;color:var(--text-muted)">Already at endgame!</td></tr>';
document.getElementById('ladderProgressionBody').innerHTML = lpRows;
let cRows = '';
for (const s of SCENARIOS) {
const adj = mult;
cRows += `<tr class="scenario-row ${s.id === `gift${giftLevel}` || s.id === `self${selfLevel}` ? 'active-row' : ''}">
<td>${s.label}</td>
<td class="num">$${s.yourCost.toLocaleString()}</td>
<td class="num">$${s.yourCost.toLocaleString()}</td>
<td class="num">~${s.time} months</td>
<td class="num">$${Math.round(s.yr1 * adj * actualPeople).toLocaleString()}</td>
<td class="num">$${Math.round(s.totalEG * adj * actualPeople).toLocaleString()}</td>
<td class="num">$${Math.round(s.monthly * adj * actualPeople).toLocaleString()}/mo</td>
</tr>`;
}
document.getElementById('comparisonBody').innerHTML = cRows;
// Update the referral plan preview
generatePlan();
const ctx3 = document.getElementById('compareChart').getContext('2d');
const compareLabels = SCENARIOS.map(s => s.label.replace('$', '').replace('(', '').replace(')', ''));
const compareData = SCENARIOS.map(s => Math.round(s.yr1 * mult * actualPeople));
chart3 = new Chart(ctx3, {
type: 'bar',
data: {
labels: compareLabels,
datasets: [{
label: `Year 1 Earnings (${actualPeople} person${actualPeople > 1 ? 's' : ''})`,
data: compareData,
backgroundColor: compareData.map((v, i) => {
const ids = [`gift${giftLevel}`, `self${selfLevel}`];
return ids.includes(SCENARIOS[i].id) ? 'rgba(108,92,231,0.7)' : 'rgba(90,94,122,0.3)';
}),
borderColor: compareData.map((v, i) => {
const ids = [`gift${giftLevel}`, `self${selfLevel}`];
return ids.includes(SCENARIOS[i].id) ? '#6c5ce7' : '#5a5e7a';
}),
borderWidth: 1,
borderRadius: 4,
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
indexAxis: 'y',
plugins: {
legend: { display: false },
tooltip: { callbacks: { label: ctx => '$' + ctx.parsed.x.toLocaleString() + ' / yr' } }
},
scales: {
x: { ticks: { color: '#5a5e7a', font: { size: 9 }, callback: v => '$' + v.toLocaleString() }, grid: { color: '#2a2e4522' } },
y: { ticks: { color: '#8a8fa8', font: { size: 9 } }, grid: { display: false } }
}
}
});
}
// ─── Event Wiring ──────────────────────────────────────────
['numPeople','commissionPct','giftLevel','selfFundLevel','showReferral','alreadyJoined','strategyMode','pocketPct','parkPhase','boostFunds'].forEach(id => {
const el = document.getElementById(id);
el.addEventListener('input', updateAll);
el.addEventListener('change', updateAll);
});
// 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');
setTimeout(() => { if (chart1) chart1.resize(); if (chart2) chart2.resize(); if (chart3) chart3.resize(); }, 50);
});
});
// ─── Load URL params (gift, self) into controls ────────
(function loadURLParams() {
const p = new URLSearchParams(window.location.search);
const gift = p.get('gift');
const self = p.get('self');
if (gift) {
const el = document.getElementById('giftLevel');
if (el && [...el.options].some(o => o.value === gift)) el.value = gift;
}
if (self) {
const el = document.getElementById('selfFundLevel');
if (el && [...el.options].some(o => o.value === self)) el.value = self;
}
const mode = p.get('mode');
if (mode === 'pocket' || mode === 'frontload' || mode === 'park') {
document.getElementById('strategyMode').value = mode;
const pk = p.get('pk');
if (pk && [...document.getElementById('pocketPct').options].some(o => o.value === pk))
document.getElementById('pocketPct').value = pk;
const park = p.get('park');
if (park) document.getElementById('parkPhase').dataset.want = park;
}
const boost = p.get('boost');
if (boost && /^\d{1,6}$/.test(boost)) document.getElementById('boostFunds').value = boost;
})();
// ─── CTB Identity (sponsor alignment) ───────────────────────
// One member, two usernames: their Crypto Team Build username and their
// ClickBaitPays username (the affiliateid on their CTB downline-builder
// entry for program #73). member-program-link.php resolves either direction.
// Share links may carry ?ctb=<ctb-username> (canonical) or the legacy
// ?ref=<cbp-username>; both end up fully resolved here.
// MUST be declared before updateAll(): the ROI storage key reads IDENT
// during the first paint (TDZ crash caught live 2026-08-01).
const CTB_LOOKUP_URL = 'https://cryptoteambuild.com/api/member-program-link.php';
const HUB_BASE = 'https://ctbrewards.saasy.top';
const IDENT = { cbp: getRefFromURL() || 'cryptoteambuild', ctb: '', fallback: false };
updateAll();
// ─── URL Param Helpers ──────────────────────────────────────
function getRefFromURL() {
const p = new URLSearchParams(window.location.search);
return p.get('ref') || '';
}
function getCbpUser() { return IDENT.cbp; }
function hubUrl() {
return IDENT.ctb ? `${HUB_BASE}/invite/${encodeURIComponent(IDENT.ctb)}` : HUB_BASE + '/';
}
function updateHubLinks() {
document.querySelectorAll('a.hub-link').forEach(a => { a.href = hubUrl(); });
const footerRef = document.getElementById('footerRefLink');
if (footerRef) {
footerRef.href = `https://clickbaitpays.me/?ref=${getCbpUser()}`;
footerRef.textContent = `https://clickbaitpays.me/?ref=${getCbpUser()}`;
}
}
function showSponsorNudge() {
const el = document.getElementById('sponsorNudge');
if (el) el.style.display = 'block';
}
async function resolveIdentity() {
const p = new URLSearchParams(window.location.search);
const ctbParam = (p.get('ctb') || '').trim();
try {
// Members mix the two usernames up constantly, so each param tries its
// own direction FIRST, then rescues by trying the other (a CTB username
// pasted into ?ref=, or a CBP username pasted into ?ctb=, both resolve).
if (ctbParam) {
const r = await fetch(`${CTB_LOOKUP_URL}?ctb=${encodeURIComponent(ctbParam)}`).then(x => x.json());
if (r.found) {
IDENT.cbp = r.cbpUsername;
IDENT.ctb = r.ctbUsername;
} else {
const rv = await fetch(`${CTB_LOOKUP_URL}?cbp=${encodeURIComponent(ctbParam)}`).then(x => x.json());
if (rv.found) {
IDENT.cbp = rv.cbpUsername;
IDENT.ctb = rv.ctbUsername;
} else {
// No ClickBaitPays entry in their downline builder: CBP signups fall
// back to the team account, but the hub link still aligns them in CTB.
IDENT.ctb = ctbParam;
IDENT.fallback = true;
}
}
} else {
// Legacy/current ?ref= links (or the default): reverse-resolve the CTB
// username so the Team Hub invite personalizes to the same sponsor.
const r = await fetch(`${CTB_LOOKUP_URL}?cbp=${encodeURIComponent(IDENT.cbp)}`).then(x => x.json());
if (r.found) {
IDENT.ctb = r.ctbUsername;
} else {
// Rescue: the ?ref= value may actually BE a CTB username (Marty hit
// this live 2026-08-01 with ?ref=<ctb-username>). Forward-resolve it
// and adopt the member's real ClickBaitPays ref for the signup links.
const f = await fetch(`${CTB_LOOKUP_URL}?ctb=${encodeURIComponent(IDENT.cbp)}`).then(x => x.json());
if (f.found) {
IDENT.cbp = f.cbpUsername;
IDENT.ctb = f.ctbUsername;
}
}
}
} catch (e) {
// Lookup unreachable: defaults stand, nothing breaks.
}
updateHeroSignupBtn();
updateSharedLinkBox();
updateHubLinks();
if (IDENT.fallback) showSponsorNudge();
}
function getBaseUrl() {
let url = window.location.href.split('?')[0];
if (url.endsWith('/')) url = url.slice(0, -1);
return url;
}
function getShareUrl(refUser) {
const u = refUser || getCbpUser();
const gift = document.getElementById('giftLevel').value;
const self = document.getElementById('selfFundLevel').value;
let url = getBaseUrl() + '?ref=' + encodeURIComponent(u);
// Carry the CTB identity when known — keeps the hub invite and any future
// lookups aligned even if the CBP entry changes later. ref= stays for
// resilience (works even when the lookup endpoint is unreachable).
if (IDENT.ctb) url += '&ctb=' + encodeURIComponent(IDENT.ctb);
if (gift !== '0') url += '&gift=' + gift;
if (self !== '0') url += '&self=' + self;
const modeSel = document.getElementById('strategyMode');
if (modeSel && modeSel.value !== 'accelerate') {
url += '&mode=' + modeSel.value;
if (modeSel.value === 'pocket') url += '&pk=' + document.getElementById('pocketPct').value;
if (modeSel.value === 'park') url += '&park=' + encodeURIComponent(document.getElementById('parkPhase').value);
}
const boostEl = document.getElementById('boostFunds');
const boostVal = boostEl ? parseInt(boostEl.value) || 0 : 0;
if (boostVal > 0) url += '&boost=' + boostVal;
return url;
}
function updateSharedLinkBox() {
const refUser = getCbpUser();
const shareUrl = getShareUrl(refUser);
document.getElementById('sharedLink').value = shareUrl;
const signupBtn = document.getElementById('calcSignupBtn');
if (signupBtn) signupBtn.href = `https://clickbaitpays.me/?ref=${refUser}`;
const bannerLink = document.getElementById('bannerRefLink');
if (bannerLink) bannerLink.href = `https://clickbaitpays.me/?ref=${refUser}`;
const qrImg = document.getElementById('refQrCode');
if (qrImg) qrImg.src = `https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=${encodeURIComponent(shareUrl)}`;
const heroQr = document.getElementById('heroQrCode');
if (heroQr) heroQr.src = `https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=${encodeURIComponent(shareUrl)}`;
}
function copySharedLink() {
const input = document.getElementById('sharedLink');
const btn = document.getElementById('copyLinkBtn');
input.select();
navigator.clipboard.writeText(input.value).then(() => {
btn.textContent = '✅ Copied!';
btn.classList.add('copied');
setTimeout(() => { btn.textContent = '📄 Copy'; btn.classList.remove('copied'); }, 2000);
});
}
function copyCalculatorLink() {
const refUser = getCbpUser();
const url = getShareUrl(refUser);
navigator.clipboard.writeText(url).then(() => {
const btn = document.querySelector('.cta-btn-secondary');
btn.textContent = '✅ Copied!';
setTimeout(() => { btn.innerHTML = '📄 Copy Calculator Link'; }, 2000);
});
}
// ─── Hero / Calculator Section Toggling ────────────────────
function openCalculator() {
document.getElementById('calculatorSection').classList.add('expanded');
document.getElementById('heroSection').style.minHeight = 'auto';
updateSharedLinkBox();
}
function scrollToCalculator() {
openCalculator();
setTimeout(() => {
document.getElementById('calculatorSection').scrollIntoView({ behavior: 'smooth', block: 'start' });
}, 100);
}
function scrollToHero() {
document.getElementById('heroSection').scrollIntoView({ behavior: 'smooth', block: 'start' });
}
// Hero CTA button
document.getElementById('heroCalcBtn').addEventListener('click', scrollToCalculator);
// Sponsor Guide straight from the hero (it was buried as the 5th tab —
// Marty 2026-07-30). Also deep-linkable via ?guide=1 for the Telegram pin.
function openGuide() {
openCalculator();
setTimeout(() => {
const btn = document.querySelector('.tab-btn[data-tab="guide"]');
if (btn) btn.click();
document.querySelector('.tabs').scrollIntoView({ behavior: 'smooth', block: 'start' });
}, 120);
}
document.getElementById('heroGuideBtn').addEventListener('click', openGuide);
// Hero signup button — same logic as calculator signup
function updateHeroSignupBtn() {
// #heroSignupBtn was removed in a redesign; unguarded .href crashed init()
// on every load (and killed updateSharedLinkBox below it). Guard it.
const refUser = getCbpUser();
const btn = document.getElementById('heroSignupBtn');
if (btn) btn.href = `https://clickbaitpays.me/?ref=${refUser}`;
}
// Auto-open calculator if ?calc=1 in URL
(function init() {
const params = new URLSearchParams(window.location.search);
const refUser = params.get('ref') || 'cryptoteambuild';
if (params.get('calc') === '1') {
openCalculator();
}
if (params.get('guide') === '1') {
openGuide();
}
updateHeroSignupBtn();
updateSharedLinkBox();
// Async: resolve the CTB↔ClickBaitPays identity pair and personalize the
// hub links + signup refs when the lookup lands. Defaults already painted
// above, so a slow/failed lookup degrades gracefully to cryptoteambuild.
resolveIdentity();
})();
// ─── Shareable Plan Generator ───────────────────────────────
// One narrative line per phase, in the ONE strategy the sponsor chose —
// replaces the old dual pocket/accelerate blocks (Marty 2026-07-30).
function phasePlanLine(k, i, PI, mode, pocketPct) {
const p = PI[k];
if (p.parked) {
const perMo = Math.round(p.profit * 30.4 / 19);
return `**Phase ${i + 1}: ${p.label} — PARK HERE** 🏝\nRun these campaigns on repeat, every ~19 days, and pocket the ~$${p.profit.toFixed(2)} profit each cycle — about $${perMo.toLocaleString()}/month of spending money for a few minutes of clicking a day. No more reinvesting, no more climbing. This is your income level.`;
}
const base = `**Phase ${i + 1}: ${p.label}**\n${p.cycles} cycles, ~${p.months} months — $${p.payout.toFixed(2)}/cycle payout`;
if (mode === 'pocket' || mode === 'frontload') {
const pk = p.profit * pocketPctFor(pocketPct, k) / 100;
const totalPk = Math.round(pk * p.cycles * 100) / 100;
return `${base}\nPocket ~$${pk.toFixed(2)} of each cycle's ~$${p.profit.toFixed(2)} profit (about $${totalPk.toFixed(2)} in your pocket across this phase) and bank the rest toward the next level. The timeline above already accounts for the slower climb.`;
}
return `${base}\nReinvest everything — each cycle's ~$${p.profit.toFixed(2)} profit goes straight into reserves until the next level unlocks. Fastest path there is.`;
}
function generatePlan() {
const numPeople = parseInt(document.getElementById('numPeople').value) || 0;
const giftLevel = parseInt(document.getElementById('giftLevel').value);
const selfLevel = parseInt(document.getElementById('selfFundLevel').value);
const refUser = getCbpUser();
const refLink = getShareUrl(refUser);
const hubLink = hubUrl();
const giftCost = getLevelCost(giftLevel);
const selfCost = getLevelCost(selfLevel);
const effective = getEffectiveStart(giftLevel, selfLevel);
const mode = document.getElementById('strategyMode').value;
const pocketPct = mode === 'pocket' ? (parseInt(document.getElementById('pocketPct').value) || 50)
: mode === 'frontload' ? 'frontload' : 0;
let phases = getPhaseSequence(effective);
if (mode === 'park') phases = phases.slice(0, phases.indexOf(document.getElementById('parkPhase').value) + 1);
const PI = phaseInfo(phases, pocketPct);
const endKey = phases[phases.length - 1];
const totalMonths = estimateMonths(phases, pocketPct);
const endgameBlock = PI[endKey].parked
? `**The destination: ${PI[endKey].label}** 🏝\nYou stop climbing here on purpose — roughly $${Math.round(HYBRIDS[endKey].profit * 30.4 / 19).toLocaleString()}/month pocketed, indefinitely, for a few minutes of clicking a day. (Want more later? The calculator link above shows the full climb to 3× L7 whenever you're ready.)`
: `**Phase ${phases.filter(x => x !== '3xL7').length + 1}: 3× L7 Endgame** 🎯\nAll three L7 campaigns running at once\n$9,720.00/cycle payout → ~$4,032/month${(mode === 'pocket' || mode === 'frontload') ? ' — and from here it is ALL pocket money' : ' passive'}\nThis is the finish line${(mode === 'pocket' || mode === 'frontload') ? `\n\n(CBP has a $10 minimum withdrawal and a 10% fee on external-wallet withdrawals — pocketed money accumulates in your balance until you cash out.)` : ''}`;
const roadmapHeading = PI[endKey].parked
? `Your roadmap to ~$${Math.round(HYBRIDS[endKey].profit * 30.4 / 19).toLocaleString()}/month pocket income:`
: `Your full roadmap to $4,032/month:`;
const timeLine = PI[endKey].parked
? `Estimated time to your park level: ~${totalMonths} months`
: `Estimated time to the 3× L7 endgame: ~${totalMonths} months`;
const quickMonthly = PI[endKey].parked
? `• Monthly at park (${HYBRIDS[endKey].label}): ~$${Math.round(HYBRIDS[endKey].profit * 30.4 / 19).toLocaleString()}/mo pocketed`
: `• Monthly at 3× L7: ~$4,032/mo passive`;
const alreadyJoined = document.getElementById('alreadyJoined').checked;
updateSharedLinkBox();
let pifSteps = '';
if (giftCost > 0) {
let firstPayoutGuidance = '';
if (giftLevel >= 3) {
firstPayoutGuidance = `Your L2 and L3 are already activated and ready. Once that first L1 payout clears (~$17.17), put it toward buying the L2 campaign ($${LEVELS[1].camp}). Run L2 alongside L1 for a few cycles and you'll stack up toward L3 quickly.`;
} else if (giftLevel >= 2) {
firstPayoutGuidance = `Both campaigns are already running from day one. Once those first payouts clear (~$17.17 + $101.74), you'll have ~$118.91 to work with — reinvest in L2 + L1 again and the system feeds itself from here.`;
} else {
firstPayoutGuidance = `Once that first L1 payout clears (~$17.17), you can buy L1 again and run it back-to-back. Stack a few cycles and you'll have enough for L2 activation ($${LEVELS[1].total}).`;
}
const firstPhase = phases.filter(k => k !== '3xL7')[0];
const fp = HYBRIDS[firstPhase];
pifSteps = `\n**Before we start — connect with me first:**\n\nHere's how this works. When you're ready to get started:\n\n1. Join my team hub: ${hubLink} — signing up through that exact link connects you to me as your sponsor\n2. The hub runs on Telegram, so message me once you're in — say **${refUser} sent me** so I know who you are\n3. I'll confirm you're my referral and transfer your Level 1 and Level 2 funds right then\n\n**Once the funds hit your account:**\n\n${giftLevel >= 2 ? `\n**Level 1 setup:**\n• Go to **"Activate Earnings"** → buy the Level 1 activation ($${LEVELS[0].act})\n• Go to **"Buy Ad Campaigns"** → purchase the Level 1 campaign ($${LEVELS[0].camp})\n\n**Level 2 setup:**\n• Go to **"Activate Earnings"** → buy the Level 2 activation ($${LEVELS[1].act})\n• Go to **"Buy Ad Campaigns"** → purchase the Level 2 campaign ($${LEVELS[1].camp})\n\n**Start clicking!** 3 ads per day for each campaign — both run together from day one. L1 pays out ~$${LEVELS[0].payout} and L2 pays out ~$${LEVELS[1].payout} after 12 days.` : `\n4. Go to **"Activate Earnings"** → buy the Level 1 activation ($${LEVELS[0].act}) if you don't already have it\n5. Go to **"Buy Ad Campaigns"** → purchase the Level 1 campaign ($${LEVELS[0].camp})\n6. Start clicking! ${LEVELS[0].clicks} ads per day for 12 days — the campaign pays out ~$${LEVELS[0].payout} after`}\n\n**What to do with that first payout:**\n\n${firstPayoutGuidance}\n\nFrom there, you follow the roadmap below — the system feeds itself, no new money needed.`;
}
let rawPlan = alreadyJoined
? `📋 Your ClickBaitPays Plan — Full Roadmap\n\nSo what's ClickBaitPays? It's an ad platform where you run small ad campaigns, click a few ads each day, and every ~19 days you get paid more than the campaign cost. You reinvest those payouts into bigger campaigns and scale up. It's simple, takes a few minutes a day, and you can do it from your phone.\n\nHere's a calculator I put together so you can play with the numbers yourself: ${refLink}\n\nCome back to that link anytime — it'll walk you through what's possible and the best plan forward as you grow.\n\n${giftCost > 0 ? `${pifSteps}` : ''}\n\n${roadmapHeading}\n\n${phases.filter(k => k !== '3xL7').map((k, i) => phasePlanLine(k, i, PI, mode, pocketPct)).join('\n\n')}\n\n${endgameBlock}\n\n${selfCost > 0 ? `**Your total self-fund: $${selfCost}**${selfCost > giftCost ? ` (you cover $${(selfCost - giftCost).toLocaleString()} after sponsor's gift)` : ''}` : ''}\n\nNo new money needed after the start — just run the cycles and follow the phases above.\n\nAs a side note — I also earn 10% of everything you get paid through this system, so eventually I'll get my gift back. But that's not why I'm doing this. I genuinely just want to pay it forward and help you get started. You win, I win — we both win together.\n\nConnect with the team and get help any time in the team hub: ${hubLink}\n\n${timeLine}\n\nQuick Stats\n${quickMonthly}\n• Each campaign cycle: 19 days\n• Min daily clicks: 3-20 (depending on level)\n• Reward per ad click: $0.48 - $13.50\n\nYour Referral Link\n${refLink}\n\nGood luck — the system works if you work the system. 💪`
: `📋 Your ClickBaitPays Plan\n\nSo what's ClickBaitPays? It's an ad platform where you run small ad campaigns, click a few ads each day, and every ~19 days you get paid more than the campaign cost. You reinvest those payouts into bigger campaigns and scale up. It's simple, takes a few minutes a day, and you can do it from your phone.\n\nHere's a calculator I put together so you can play with the numbers yourself: ${refLink}\n\nAfter you sign up, come back to that link — it'll walk you through what's possible and the best plan forward as you grow.\n\n${giftCost > 0 ? `With me as your sponsor, I'm covering **$${giftCost}** to get you started through Level ${giftLevel} (L${giftLevel === 1 ? '1 only' : `1-L${giftLevel}`}). You owe nothing for this — it's funded up front, and you keep 100% of your earnings.` : `I haven't pre-funded any levels on my end — you'll be building entirely on your own using the link below.`}\n\n${giftCost > 0 ? pifSteps : ''}\n\n${roadmapHeading}\n\n${phases.filter(k => k !== '3xL7').map((k, i) => phasePlanLine(k, i, PI, mode, pocketPct)).join('\n\n')}\n\n${endgameBlock}\n\n${selfCost > 0 ? `**Your total self-fund: $${selfCost}**${selfCost > giftCost ? ` (you cover $${(selfCost - giftCost).toLocaleString()} after sponsor's gift)` : ''}` : ''}\n\nNo new money needed after the start — just run the cycles and follow the phases above.\n\nAs a side note — I also earn 10% of everything you get paid through this system, so eventually I'll get my gift back. But that's not why I'm doing this. I genuinely just want to pay it forward and help you get started. You win, I win — we both win together.\n\nConnect with the team and get help any time in the team hub: ${hubLink}\n\n${timeLine}\n\nQuick Stats\n${quickMonthly}\n• Each campaign cycle: 19 days\n• Min daily clicks: 3-20 (depending on level)\n• Reward per ad click: $0.48 - $13.50\n\nYour Referral Link\n${refLink}\n\nUse this link to sign up — it's how your sponsor tracks your progress. If you have questions, reach out to them directly.\n\nGood luck — the system works if you work the system. 💪`;
document.getElementById('planOutput').innerHTML = rawPlan.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>');
document.getElementById('planOutput').dataset.rawPlan = rawPlan;
}
function copyPlan() {
const el = document.getElementById('planOutput');
const rawPlan = el.dataset.rawPlan || el.textContent;
navigator.clipboard.writeText(rawPlan).then(() => {
const btn = document.getElementById('copyPlanBtn');
btn.textContent = '✅ Copied!';
btn.classList.add('copied');
setTimeout(() => { btn.textContent = '📄 Copy Plan'; btn.classList.remove('copied'); }, 2000);
}).catch(() => {
const range = document.createRange();
range.selectNodeContents(el);
const sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
});
}
['numPeople','giftLevel','selfFundLevel','showReferral','alreadyJoined'].forEach(id => {
const el = document.getElementById(id);
el.addEventListener('input', generatePlan);
el.addEventListener('change', generatePlan);
});
setTimeout(generatePlan, 100);
setTimeout(updateAll, 100);
// ─── ROI Dashboard ──────────────────────────────────────
function updateROI() {
const deposits = parseFloat(document.getElementById('roiDeposits').value) || 0;
const earned = parseFloat(document.getElementById('roiTotalEarned').value) || 0;
const phase = document.getElementById('roiPhase').value;
const cyclesDone = parseInt(document.getElementById('roiCyclesDone').value) || 0;
// If no inputs provided, show placeholder state
const hasInput = document.getElementById('roiDeposits').value.trim() !== '' || document.getElementById('roiTotalEarned').value.trim() !== '';
if (!hasInput) {
document.getElementById('roiStatROI').querySelector('.roi-stat-value').textContent = '—';
document.getElementById('roiStatRecouped').querySelector('.roi-stat-value').textContent = '—';
document.getElementById('roiStatRemaining').querySelector('.roi-stat-value').textContent = '—';
document.getElementById('roiBarROI').style.width = '0%';
document.getElementById('roiStatPhase').querySelector('.roi-stat-value').textContent = '—';
document.getElementById('roiBarPhase').style.width = '0%';
document.querySelectorAll('.roi-ladder-step').forEach(el => el.classList.remove('active', 'passed'));
document.getElementById('roiMilestones').innerHTML = '<div style="color:var(--text-muted);font-size:0.85rem;padding:10px 0;">Enter your numbers above to see your progress 🚀</div>';
saveROIData(deposits, earned, phase, cyclesDone);
return;
}
// Phase data: [cycles_this_phase, cycles_needed_for_next, profit_per_cycle, next_phase_label]
// Cycle counts derived with the reserve model (from $0 reserves at phase
// start, roll-the-final-payout); needsCapital = the actual incremental
// buy-in of the next phase (carried campaigns excluded).
const PHASE_DATA = {
l1: { cycles: 21, profitPer: 1.72, nextLabel: 'L2+L1', needsCapital: 84 },
l2l1: { cycles: 4, profitPer: 11.89, nextLabel: 'L3+L1', needsCapital: 165 },
l3l1: { cycles: 7, profitPer: 21.16, nextLabel: 'L4+L3', needsCapital: 330 },
l4: { cycles: 5, profitPer: 58.32, nextLabel: 'L5 Only', needsCapital: 660 },
l4l3: { cycles: 4, profitPer: 133.20, nextLabel: 'L5+L3', needsCapital: 660 },
l5: { cycles: 5, profitPer: 116.64, nextLabel: 'L6 Only', needsCapital: 1320 },
l5l3: { cycles: 4, profitPer: 222.00, nextLabel: 'L6+L3', needsCapital: 1320 },
l6: { cycles: 5, profitPer: 155.52, nextLabel: 'L7 Solo', needsCapital: 2640 },
l6l3: { cycles: 4, profitPer: 399.60, nextLabel: 'L7 Solo', needsCapital: 2640 },
l7solo: { cycles: 6, profitPer: 840.00, nextLabel: '3× L7 Endgame', needsCapital: 4800 },
l7x3: { cycles: 999, profitPer: 2520.00, nextLabel: null, needsCapital: 0 },
};
// ROI stats — no cap, show over 100% when earned > deposited
const roiPct = deposits > 0 ? (earned / deposits) * 100 : 0;
const recouped = Math.min(earned, deposits);
const remaining = Math.max(deposits - earned, 0);
document.getElementById('roiStatROI').querySelector('.roi-stat-value').textContent = roiPct.toFixed(1) + '%';
// Green when past breakeven
const roiEl = document.getElementById('roiStatROI').querySelector('.roi-stat-value');
if (roiPct >= 100) {
roiEl.style.color = '#22c55e';
} else {
roiEl.style.color = '';
}
document.getElementById('roiStatRecouped').querySelector('.roi-stat-value').textContent = '$' + recouped.toFixed(2);
document.getElementById('roiStatRemaining').querySelector('.roi-stat-value').textContent = remaining > 0 ? '$' + remaining.toFixed(2) : '+$' + Math.abs(remaining).toFixed(2);
document.getElementById('roiBarROI').style.width = Math.min(roiPct, 100) + '%';
// Update label to reflect profit mode
document.getElementById('roiStatRemaining').querySelector('.roi-stat-label').textContent = remaining > 0 ? 'To Breakeven' : 'Pure Profit';
// Phase progress
const pd = PHASE_DATA[phase];
let phasePct = 0;
let phaseLabel = '';
if (phase === 'l7x3') {
phasePct = 100;
phaseLabel = '🏆 Endgame Reached';
} else {
phasePct = Math.min((cyclesDone / pd.cycles) * 100, 100);
phaseLabel = `Cycle ${cyclesDone} of ${pd.cycles}`;
}
document.getElementById('roiStatPhase').querySelector('.roi-stat-value').textContent = phaseLabel;
document.getElementById('roiBarPhase').style.width = phasePct + '%';
// Ladder visualization
const ladderOrder = ['l1','l2l1','l3l1','l4','l4l3','l5','l5l3','l6','l6l3','l7solo','l7x3'];
const phaseIndex = ladderOrder.indexOf(phase);
// Location badge
const phaseNames = {
l1:'L1 Only', l2l1:'L2 + L1', l3l1:'L3 + L1', l4:'L4 Only',
l4l3:'L4 + L3 Hybrid', l5:'L5 Only', l5l3:'L5 + L3 Hybrid',
l6:'L6 Only', l6l3:'L6 + L3 Hybrid', l7solo:'L7 Solo', l7x3:'3× L7 Endgame'
};
document.getElementById('roiHerePhase').textContent = phase && phaseNames[phase] ? phaseNames[phase] : '—';
document.querySelectorAll('.roi-ladder-step').forEach(el => {
el.classList.remove('active', 'passed');
const idx = ladderOrder.indexOf(el.dataset.phase);
if (idx < phaseIndex) el.classList.add('passed');
else if (idx === phaseIndex) el.classList.add('active');
});
// Milestones
const milestones = [];
if (earned >= 112.50) milestones.push({ icon: '✅', label: '25% ROI Recouped', sub: 'Quarter of your capital back' });
if (earned >= 225) milestones.push({ icon: '✅', label: '50% ROI Recouped', sub: 'Half your capital is back' });
if (earned >= 337.50) milestones.push({ icon: '✅', label: '75% ROI Recouped', sub: 'Three quarters there' });
if (earned >= deposits) milestones.push({ icon: '💰', label: '100% ROI — Breakeven!', sub: 'Everything from here is pure profit' });
if (phase === 'l5l3' || phaseIndex > ladderOrder.indexOf('l5l3'))
milestones.push({ icon: '🏅', label: 'L5 Active', sub: 'You reached the serious scaling tier' });
if (phase === 'l6l3' || phaseIndex > ladderOrder.indexOf('l6l3'))
milestones.push({ icon: '🏅', label: 'L6 Active', sub: 'Double-digit clicks/day territory' });
if (phase === 'l7solo' || phaseIndex > ladderOrder.indexOf('l7solo'))
milestones.push({ icon: '🌟', label: 'L7 — The Big One', sub: '$840/cycle profit, $270/day clicks' });
if (phase === 'l7x3')
milestones.push({ icon: '🏆', label: '3× L7 Endgame', sub: '$2,520/cycle profit — the machine is running' });
// Add next phase preview
if (pd.nextLabel && cyclesDone >= pd.cycles) {
milestones.push({
icon: '🚀',
label: `Ready for ${pd.nextLabel}`,
sub: `You need ~$${pd.needsCapital.toLocaleString()} in available funds to start`
});
}
// Show unearned milestones as dimmed
const allMilestones = [
{ icon: '🔘', label: '25% ROI Recouped', sub: '$112.50', earned: earned >= 112.50 },
{ icon: '🔘', label: '50% ROI Recouped', sub: '$225.00', earned: earned >= 225 },
{ icon: '🔘', label: '75% ROI Recouped', sub: '$337.50', earned: earned >= 337.50 },
{ icon: '💰', label: '100% ROI — Breakeven', sub: `$${deposits.toFixed(2)}`, earned: earned >= deposits },
];
// Add over-100% profit milestone if they're past breakeven
if (roiPct > 100) {
allMilestones.push({ icon: '📈', label: `Profit: ${(roiPct - 100).toFixed(1)}% Beyond Breakeven`, sub: `+$${(earned - deposits).toFixed(2)} pure profit`, earned: true });
}
if (phase === 'l7x3') {
allMilestones.push({ icon: '🏆', label: '3× L7 Endgame Reached', sub: '$2,520/cycle passive', earned: true });
} else if (pd.nextLabel) {
allMilestones.push({ icon: '🚀', label: `Ready for ${pd.nextLabel}`, sub: `Need ~$${pd.needsCapital.toLocaleString()}`, earned: cyclesDone >= pd.cycles });
}
document.getElementById('roiMilestones').innerHTML = allMilestones.map(m => `
<div class="roi-milestone-item${m.earned ? ' roi-milestone-checked' : ''}" style="${m.earned ? '' : 'opacity:0.5;'}">
<span class="roi-milestone-check" style="font-size:1.1rem;flex-shrink:0;">${m.icon}</span>
<div class="roi-milestone-info">
<div class="label">${m.label}</div>
<div class="sub">${m.sub}</div>
</div>
</div>
`).join('');
// Save to localStorage
saveROIData(deposits, earned, phase, cyclesDone);
}
// ─── localStorage persistence ──────────────────────────
function getROIStorageKey() {
const ref = getCbpUser();
return 'cbp_roi_' + ref;
}
function saveROIData(deposits, earned, phase, cyclesDone) {
const key = getROIStorageKey();
const data = { deposits, earned, phase, cyclesDone };
try { localStorage.setItem(key, JSON.stringify(data)); } catch(e) {}
}
function loadROIData() {
const key = getROIStorageKey();
try {
const raw = localStorage.getItem(key);
if (raw) return JSON.parse(raw);
} catch(e) {}
return null;
}
// Wire up ROI inputs
['roiDeposits','roiTotalEarned','roiPhase','roiCyclesDone'].forEach(id => {
const el = document.getElementById(id);
el.addEventListener('input', updateROI);
el.addEventListener('change', updateROI);
});
// Load saved data on page load
const saved = loadROIData();
if (saved) {
document.getElementById('roiDeposits').value = saved.deposits || '';
document.getElementById('roiTotalEarned').value = saved.earned || '';
if (saved.phase) document.getElementById('roiPhase').value = saved.phase;
document.getElementById('roiCyclesDone').value = saved.cyclesDone !== undefined ? saved.cyclesDone : '';
}
// Initial render on page load
setTimeout(() => {
updateSharedLinkBox();
updateROI();
}, 150);
</script>
</body>
</html>