← back to Student Debt Crisis Redesign
showcase/index.html
716 lines
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>SDCC Redesign Showcase — 46 themes × 4 audiences × 8 pages</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=Source+Serif+4:wght@400;600;700&family=Lora:wght@400;600;700&family=Space+Grotesk:wght@400;500;700&family=Crimson+Pro:wght@400;600;700&family=DM+Mono&family=Playfair+Display:wght@500;700;800&family=Spectral:wght@400;600;700&family=IBM+Plex+Mono&family=Bebas+Neue&family=Anton&family=Archivo+Black&family=Public+Sans:wght@400;500;700&family=Rubik+Mono+One&display=swap" rel="stylesheet">
<style>
:root{
--t-bg:#0b1733; --t-surface:#ffffff; --t-text:#0a0f24; --t-muted:#5a6076;
--t-primary:#1d4ed8; --t-accent:#dc2626; --t-h:'Inter',system-ui,sans-serif; --t-b:'Inter',system-ui,sans-serif;
--t-radius:14px;
}
*{box-sizing:border-box}
html,body{margin:0;padding:0;height:100%;background:#f3f4f6;color:#0a0a0a;font-family:'Inter',system-ui,sans-serif}
/* APP SHELL — strict grid, no overlap */
.app{display:grid;grid-template-rows:auto 1fr;height:100vh;min-height:0}
header.bar{
position:sticky;top:0;z-index:30;background:#0a0f24;color:#fff;
display:grid;grid-template-columns:auto 1fr auto;gap:18px;align-items:center;
padding:10px 18px;border-bottom:1px solid #1f2540;min-height:60px}
header.bar h1{font-size:14px;letter-spacing:.04em;text-transform:uppercase;margin:0;color:#fff;white-space:nowrap}
header.bar h1 b{color:#facc15}
.controls{display:flex;flex-wrap:wrap;gap:10px;align-items:center;justify-self:center;min-width:0}
.ctl{display:flex;flex-direction:column;gap:2px;min-width:0}
.ctl label{font-size:10px;letter-spacing:.06em;text-transform:uppercase;color:#9aa3c2}
.ctl select{min-height:36px;background:#15193a;color:#fff;border:1px solid #2a2f55;border-radius:8px;padding:6px 10px;font:inherit;font-size:13px;max-width:280px}
.pill-btn{min-height:36px;padding:6px 14px;border-radius:8px;background:#facc15;color:#1a1a1a;border:0;font-weight:700;cursor:pointer;font-size:13px;white-space:nowrap}
.pill-btn.ghost{background:transparent;color:#facc15;border:1px solid #facc15}
/* MAIN GRID 2/3 + 1/3, each cell scrolls itself */
main.split{display:grid;grid-template-columns:minmax(0,2fr) minmax(0,1fr);min-height:0;gap:0}
@media (max-width:980px){ main.split{grid-template-columns:1fr;grid-template-rows:60vh 1fr} }
.pane{min-width:0;min-height:0;overflow:auto;background:#fff}
.pane.preview{background:var(--t-bg);color:var(--t-text)}
.pane.critique{background:#ffffff;border-left:1px solid #e5e7eb}
/* PREVIEW INTERNAL — themed mock */
.mock{font-family:var(--t-b);color:var(--t-text);background:var(--t-surface);min-height:100%;display:flex;flex-direction:column}
.mock .topnav{display:flex;align-items:center;justify-content:space-between;padding:14px 22px;background:var(--t-bg);color:var(--t-surface);position:sticky;top:0;z-index:5}
.mock .topnav .brand{font-family:var(--t-h);font-weight:800;font-size:18px;line-height:1}
.mock .topnav nav a{color:var(--t-surface);text-decoration:none;font-size:13px;margin-left:14px;opacity:.9}
.mock .topnav .donate{background:var(--t-accent);color:#fff;padding:8px 14px;border-radius:8px;text-decoration:none;font-weight:700;font-size:13px;margin-left:14px}
.mock .hero{padding:48px 32px;display:grid;grid-template-columns:1.2fr .8fr;gap:32px;align-items:center;background:var(--t-surface)}
@media (max-width:640px){ .mock .hero{grid-template-columns:1fr} }
.mock h1.hero-h{font-family:var(--t-h);font-size:42px;line-height:1.05;margin:0 0 14px;color:var(--t-text);letter-spacing:-.01em}
.mock p.hero-p{font-size:17px;color:var(--t-muted);line-height:1.5;margin:0 0 22px}
.mock .ctas{display:flex;flex-wrap:wrap;gap:10px}
.mock .btn-p{background:var(--t-primary);color:#fff;padding:12px 18px;border-radius:10px;font-weight:700;text-decoration:none;font-size:14px}
.mock .btn-s{background:transparent;border:2px solid var(--t-primary);color:var(--t-primary);padding:10px 16px;border-radius:10px;font-weight:700;text-decoration:none;font-size:14px}
.mock .hero-art{aspect-ratio:1.2;background:linear-gradient(135deg,var(--t-primary),var(--t-accent));border-radius:var(--t-radius);display:flex;align-items:center;justify-content:center;color:#fff;font-family:var(--t-h);font-size:22px;text-align:center;padding:24px}
.mock .stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:10px;padding:24px 32px;background:var(--t-bg);color:var(--t-surface)}
.mock .stat{padding:14px;border-radius:10px;background:rgba(255,255,255,.06)}
.mock .stat b{font-family:var(--t-h);font-size:26px;display:block;color:var(--t-surface)}
.mock .stat span{font-size:12px;opacity:.8}
.mock .section{padding:36px 32px;background:var(--t-surface);border-top:1px solid rgba(0,0,0,.06)}
.mock h2{font-family:var(--t-h);font-size:26px;margin:0 0 18px;color:var(--t-text)}
.mock .cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:14px}
.mock .card{padding:18px;border:1px solid rgba(0,0,0,.08);border-radius:var(--t-radius);background:#fff;color:var(--t-text)}
.mock .card h3{font-family:var(--t-h);font-size:16px;margin:0 0 8px}
.mock .card p{font-size:13px;color:var(--t-muted);margin:0 0 10px;line-height:1.5}
.mock .card a{color:var(--t-primary);font-size:13px;text-decoration:none;font-weight:700}
.mock .funder-strip{display:flex;flex-wrap:wrap;gap:14px;justify-content:center;padding:20px;background:rgba(0,0,0,.04)}
.mock .funder-strip span{font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--t-muted);padding:6px 10px;border:1px solid var(--t-muted);border-radius:4px}
.mock .footer{padding:24px 32px;background:#0a0f24;color:#cbd5e1;font-size:12px;line-height:1.6}
/* numbered card variant — for Tate Esq style */
.mock .num-card{padding:24px;border:1px solid rgba(0,0,0,.1);border-radius:var(--t-radius);background:var(--t-surface)}
.mock .num-card .n{font-family:var(--t-h);font-size:14px;color:var(--t-primary);letter-spacing:.12em;font-weight:700}
.mock .num-card h3{font-size:20px;margin:8px 0 8px}
/* PSLF calc */
.calc{display:grid;grid-template-columns:1fr 1fr;gap:16px}
@media (max-width:640px){.calc{grid-template-columns:1fr}}
.calc input,.calc select{width:100%;min-height:42px;padding:8px 10px;border:1px solid #cbd5e1;border-radius:8px;font:inherit;font-size:14px}
.calc label{font-size:12px;color:var(--t-muted);font-weight:600;display:block;margin-bottom:4px}
.calc-row{display:flex;gap:14px;flex-wrap:wrap;margin-top:18px}
.calc-out{padding:14px;background:rgba(0,0,0,.04);border-radius:10px;font-size:14px;line-height:1.6}
.calc-out b{display:block;font-family:var(--t-h);font-size:22px;color:var(--t-primary)}
pre.json{background:#0a0f24;color:#a5f3fc;padding:16px;border-radius:10px;overflow:auto;font-family:'IBM Plex Mono',ui-monospace,monospace;font-size:12px;line-height:1.55}
/* CRITIQUE PANEL */
.crit{padding:18px 18px 60px;display:flex;flex-direction:column;gap:16px}
.crit h2{font-size:16px;margin:0 0 6px;letter-spacing:.04em;text-transform:uppercase;color:#0a0f24}
.crit .scorebar{display:flex;align-items:center;gap:10px}
.scorechip{padding:8px 12px;border-radius:999px;font-weight:700;font-size:12px}
.pass{background:#dcfce7;color:#14532d}.warn{background:#fef9c3;color:#713f12}.fail{background:#fee2e2;color:#7f1d1d}
.crit details{border:1px solid #e5e7eb;border-radius:10px;padding:10px 12px;background:#fafafa}
.crit details[open]{background:#fff}
.crit summary{cursor:pointer;font-weight:700;font-size:13px;color:#0a0f24}
.crit ul{margin:6px 0 0;padding-left:18px;font-size:13px;line-height:1.55;color:#1f2937}
.crit li{margin:4px 0}
.crit .pros li::marker{color:#16a34a}
.crit .cons li::marker{color:#dc2626}
.crit .ideas li::marker{color:#2563eb}
.crit .why{background:#0a0f24;color:#fff;padding:14px;border-radius:10px;font-size:13px;line-height:1.6}
.crit .why b{color:#facc15}
.crit .meta{font-size:11px;color:#6b7280}
/* Modal — clean dialog, no overlap */
dialog#revModal{border:0;border-radius:14px;padding:0;width:min(720px,92vw);max-height:88vh;box-shadow:0 30px 80px rgba(0,0,0,.4)}
dialog#revModal::backdrop{background:rgba(8,12,30,.6);backdrop-filter:blur(2px)}
.rev-h{padding:18px 22px;background:#0a0f24;color:#fff;display:flex;justify-content:space-between;align-items:center;border-radius:14px 14px 0 0}
.rev-h h2{margin:0;font-size:18px}
.rev-h button{background:transparent;border:1px solid #fff;color:#fff;border-radius:8px;padding:6px 12px;cursor:pointer}
.rev-body{padding:18px 22px;overflow:auto;max-height:calc(88vh - 70px);background:#fff}
.rev-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:12px}
.rev-card{border:1px solid #e5e7eb;border-radius:10px;padding:14px;background:#fafafa}
.rev-card h3{margin:0 0 6px;font-size:14px;color:#0a0f24}
.rev-card p{margin:0;font-size:12px;color:#374151;line-height:1.5}
.rev-card .tag{display:inline-block;font-size:10px;font-weight:700;padding:3px 8px;border-radius:999px;background:#fef3c7;color:#92400e;margin-right:4px;margin-bottom:6px;letter-spacing:.04em;text-transform:uppercase}
.rev-card .tag.h{background:#dbeafe;color:#1e3a8a}
.rev-card .tag.q{background:#dcfce7;color:#14532d}
/* tiny day badge */
.day-chip{font-size:10px;padding:3px 8px;border-radius:999px;background:#facc15;color:#1a1a1a;font-weight:700;letter-spacing:.05em;text-transform:uppercase;margin-left:6px;vertical-align:middle}
.day-chip.may{background:#dc2626;color:#fff}
.day-chip.tate{background:#0ea5e9;color:#fff}
/* ALL-46 OVERVIEW PAGE */
main.overview{overflow:auto;background:#0e1320;padding:24px;min-height:0}
.ov-head{color:#fff;display:flex;justify-content:space-between;align-items:flex-end;gap:12px;margin-bottom:16px;flex-wrap:wrap}
.ov-head h2{font-size:20px;margin:0;letter-spacing:.02em}
.ov-head p{font-size:13px;margin:0;color:#9aa3c2;max-width:520px}
.ov-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(320px,1fr));gap:14px}
.ov-card{position:relative;border-radius:12px;overflow:hidden;cursor:pointer;background:var(--c-bg);box-shadow:0 6px 24px rgba(0,0,0,.25);transition:transform .12s ease,box-shadow .12s ease;border:1px solid rgba(255,255,255,.06);min-height:380px;display:flex;flex-direction:column}
.ov-card:hover{transform:translateY(-3px);box-shadow:0 14px 36px rgba(0,0,0,.45);border-color:rgba(250,204,21,.4)}
.ov-meta{position:absolute;top:8px;left:8px;right:8px;display:flex;justify-content:space-between;align-items:center;z-index:3;pointer-events:none}
.ov-meta .num{background:rgba(0,0,0,.65);color:#facc15;font-weight:800;font-size:11px;padding:3px 8px;border-radius:6px;letter-spacing:.06em}
.ov-meta .cat{background:rgba(0,0,0,.65);color:#fff;font-weight:700;font-size:10px;padding:3px 8px;border-radius:6px;letter-spacing:.06em;text-transform:uppercase}
.ov-meta .cat.may{background:#dc2626}
.ov-meta .cat.tate{background:#0ea5e9}
.ov-meta .cat.granters{background:#1d4ed8}
.ov-meta .cat.users{background:#0f766e}
.ov-meta .cat.both{background:#7c3aed}
.ov-mini{flex:1;background:var(--c-surface);color:var(--c-text);font-family:var(--c-b);display:flex;flex-direction:column}
.ov-nav{background:var(--c-bg);color:var(--c-surface);padding:10px 14px;display:flex;justify-content:space-between;align-items:center;font-family:var(--c-h);font-weight:800;font-size:12px}
.ov-nav .donate{background:var(--c-accent);color:#fff;font-size:10px;padding:4px 10px;border-radius:6px}
.ov-hero{padding:18px;background:var(--c-surface);flex:1}
.ov-h1{font-family:var(--c-h);font-size:22px;line-height:1.1;margin:0 0 8px;color:var(--c-text);letter-spacing:-.01em;font-weight:700}
.ov-sub{font-size:12px;line-height:1.4;color:var(--c-muted);margin:0 0 12px}
.ov-ctas{display:flex;gap:6px;flex-wrap:wrap}
.ov-cta{font-size:11px;padding:6px 10px;border-radius:6px;font-weight:700}
.ov-cta.p{background:var(--c-primary);color:#fff}
.ov-cta.s{background:transparent;border:1.5px solid var(--c-primary);color:var(--c-primary)}
.ov-stats{display:grid;grid-template-columns:1fr 1fr 1fr 1fr;gap:6px;padding:10px 14px;background:var(--c-bg);color:var(--c-surface)}
.ov-stat{font-family:var(--c-h);font-size:14px;font-weight:700;text-align:center}
.ov-stat span{display:block;font-size:8px;opacity:.7;font-weight:400;margin-top:2px;letter-spacing:.04em;text-transform:uppercase}
.ov-foot{background:#0a0f24;color:#cbd5e1;font-size:9px;padding:6px 14px;text-align:center;letter-spacing:.04em}
.ov-name{position:absolute;bottom:8px;left:8px;right:8px;background:rgba(0,0,0,.78);color:#fff;font-size:11px;font-weight:700;padding:6px 10px;border-radius:6px;display:flex;justify-content:space-between;align-items:center;z-index:3;pointer-events:none}
.ov-name .score{color:#facc15;font-size:10px}
</style>
</head>
<body>
<div class="app">
<header class="bar">
<h1>SDCC <b>Redesign</b> Showcase <span style="opacity:.6;font-weight:400;text-transform:none;font-size:11px">— pick a theme · audience · page</span></h1>
<div class="controls">
<div class="ctl"><label for="themeSel">Theme</label><select id="themeSel"></select></div>
<div class="ctl"><label for="audSel">Target audience</label>
<select id="audSel">
<option value="granters">Foundation grantmakers</option>
<option value="users">Borrowers age 45+</option>
<option value="both">Both</option>
</select></div>
<div class="ctl"><label for="pageSel">Page</label>
<select id="pageSel">
<option value="home">Home</option>
<option value="stories">Stories</option>
<option value="resources">Resources (2026 updated)</option>
<option value="news">News</option>
<option value="calculators">Calculators</option>
<option value="pslfJson">PSLF JSON Inspector</option>
<option value="cypres">Cy Pres Award</option>
<option value="bookacall">Book a Call</option>
</select></div>
</div>
<div style="display:flex;gap:8px">
<button class="pill-btn ghost" id="allBtn">📑 View all 46</button>
<button class="pill-btn" id="revBtn">💰 Revenue Streams</button>
</div>
</header>
<main class="split" id="splitView">
<section class="pane preview" id="previewPane"><div class="mock" id="mockRoot"></div></section>
<aside class="pane critique" id="critPane"><div class="crit" id="critRoot"></div></aside>
</main>
<main class="overview" id="overviewView" style="display:none">
<div class="ov-head">
<div>
<h2>All 46 themes — at a glance</h2>
<p>Click any tile to open it full-size with the audience-aware critique panel. URL updates to <code style="background:#1a1f33;padding:2px 6px;border-radius:4px">#t-N</code> so you can deep-link any theme.</p>
</div>
<div style="color:#9aa3c2;font-size:12px;text-align:right">
46 themes · 4 audience views · 8 pages · 1 critique engine
</div>
</div>
<div class="ov-grid" id="ovGrid"></div>
</main>
</div>
<dialog id="revModal">
<div class="rev-h"><h2>Revenue streams — why some nonprofits get the money</h2><button id="revClose">Close ✕</button></div>
<div class="rev-body"><div class="rev-grid" id="revGrid"></div></div>
</dialog>
<script>
/* ===========================================================
THEMES — 46 total
=========================================================== */
const THEMES = [
// 1-20: unique full rebrands targeting granters / users / both
{id:1,name:"Senate Beltway Polished",cat:"granters",bg:"#0b1733",surface:"#fbfaf6",text:"#0a0f24",muted:"#4d5572",primary:"#1d3a78",accent:"#a32638",h:"'Source Serif 4',serif",b:"'Inter',sans-serif",hero:"Building durable policy wins for student-loan borrowers",sub:"Ten years of evidence-anchored advocacy alongside borrowers, lawmakers, and partner organizations.",cta:"Schedule a briefing",cta2:"Read 2026 outcomes report",badge:"Granter polish"},
{id:2,name:"Borrower Diary",cat:"users",bg:"#fdf6ec",surface:"#fff8ee",text:"#2b1d12",muted:"#6b5743",primary:"#b65331",accent:"#0e6b4a",h:"'Lora',serif",b:"'Crimson Pro',serif",hero:"You are not alone with this loan.",sub:"82,475 borrowers have shared their student-debt story with us. Read theirs. Share yours. We will fight beside you.",cta:"Share your story",cta2:"Read other stories",badge:"Borrower warmth"},
{id:3,name:"Civic Brutalist",cat:"granters",bg:"#000",surface:"#fff",text:"#000",muted:"#444",primary:"#000",accent:"#bef264",h:"'Archivo Black',sans-serif",b:"'Public Sans',sans-serif",hero:"END THE STUDENT DEBT CRISIS.",sub:"45 million Americans. $1.7 trillion in debt. We organize, lobby, litigate.",cta:"Fund the fight",cta2:"Download theory of change",badge:"Brutalist authority"},
{id:4,name:"Helpline Hopeful",cat:"users",bg:"#eef7f3",surface:"#ffffff",text:"#0d2a1f",muted:"#52685c",primary:"#0e8a5f",accent:"#f0784f",h:"'Inter',sans-serif",b:"'Inter',sans-serif",hero:"A friendly hand with your student loans.",sub:"Plain-language guides, free workshops, and a real person to call. No upsells, no servicer drama.",cta:"Call us: (646) 820-8037",cta2:"Browse free guides",badge:"Helpline tone"},
{id:5,name:"Data-Forward Foundation",cat:"granters",bg:"#0a1f3d",surface:"#f7f8fb",text:"#0a1f3d",muted:"#475569",primary:"#1d4ed8",accent:"#84cc16",h:"'Space Grotesk',sans-serif",b:"'Inter',sans-serif",hero:"Evidence-based advocacy for 45M federal student-loan borrowers.",sub:"Real-time dashboards, peer-reviewed briefs, and outcomes you can audit.",cta:"Open data portal",cta2:"Read methodology",badge:"Quant credibility"},
{id:6,name:"Kitchen-Table Conversation",cat:"users",bg:"#f9f3e7",surface:"#fffdf6",text:"#3a2c18",muted:"#7c6b53",primary:"#a04b1f",accent:"#3b6a4a",h:"'Crimson Pro',serif",b:"'Lora',serif",hero:"Let's talk about that letter you got.",sub:"Walk through default, garnishment, IDR, and PSLF in plain English. Sit down with us.",cta:"Start with your situation",cta2:"Watch a 4-min explainer",badge:"Plain-spoken"},
{id:7,name:"NPR Editorial",cat:"both",bg:"#1a1c1f",surface:"#f5f1ea",text:"#1a1c1f",muted:"#5b5d63",primary:"#b04a2f",accent:"#3b5b87",h:"'Spectral',serif",b:"'Source Serif 4',serif",hero:"The student-loan story America keeps avoiding.",sub:"Reporting, policy analysis, and lived experience from the borrowers behind the numbers.",cta:"Subscribe to the brief",cta2:"Latest investigations",badge:"Editorial trust"},
{id:8,name:"Vermont General Store",cat:"users",bg:"#3c2614",surface:"#fdf3df",text:"#2a1a09",muted:"#6b5236",primary:"#9c2c1d",accent:"#274a2c",h:"'Lora',serif",b:"'Lora',serif",hero:"Honest help with your student loans.",sub:"Old-fashioned plain-talk help. We stock the answers other folks don't bother with.",cta:"Find what you need",cta2:"Talk to a real person",badge:"Wholesome trust"},
{id:9,name:"Modern Movement",cat:"granters",bg:"#0d3b3b",surface:"#fbf8f1",text:"#0d3b3b",muted:"#5a6e6a",primary:"#caa44a",accent:"#dc6c4f",h:"'Playfair Display',serif",b:"'Inter',sans-serif",hero:"A movement for 45 million.",sub:"Grassroots scale, professional discipline, measurable change at every level of government.",cta:"Partner with SDCC",cta2:"Download case study",badge:"Movement gravitas"},
{id:10,name:"Aged Archive",cat:"granters",bg:"#36251a",surface:"#f3e8d3",text:"#241608",muted:"#6c5840",primary:"#7a1f1c",accent:"#3d4d2e",h:"'Playfair Display',serif",b:"'Spectral',serif",hero:"Ten years of borrower advocacy.",sub:"From Occupy-era organizing to federal policy victories. The longest continuously-active borrower org in America.",cta:"Browse the archive",cta2:"Read founding story",badge:"Heritage signal"},
{id:11,name:"Bright Activist",cat:"both",bg:"#facc15",surface:"#0a0a0a",text:"#fef9c3",muted:"#fde68a",primary:"#fb7185",accent:"#22d3ee",h:"'Anton',sans-serif",b:"'Public Sans',sans-serif",hero:"DEBT IS A POLICY CHOICE.",sub:"And so is canceling it. Join 2 million Americans demanding the choice change.",cta:"Sign the petition",cta2:"Find an action near you",badge:"High-energy"},
{id:12,name:"Quiet Authority",cat:"granters",bg:"#1f2937",surface:"#f4f4f0",text:"#1f2937",muted:"#475569",primary:"#0f766e",accent:"#b45309",h:"'Source Serif 4',serif",b:"'Inter',sans-serif",hero:"Trusted counsel on the student-loan crisis since 2012.",sub:"Cited by NYT, WSJ, NPR, and three presidential administrations. We don't shout. We deliver.",cta:"Request consultation",cta2:"Press kit",badge:"Quiet credibility"},
{id:13,name:"Hometown Newspaper",cat:"users",bg:"#241a0e",surface:"#fbf6e8",text:"#1a120a",muted:"#6c5b3a",primary:"#9b1c1c",accent:"#1f3a5f",h:"'Playfair Display',serif",b:"'Crimson Pro',serif",hero:"Your hometown voice for borrower rights.",sub:"Tonight's headline: SAVE blocked. Default collections restarted. Here's what it means for you.",cta:"Read today's brief",cta2:"Sign up for daily digest",badge:"Newsroom feel"},
{id:14,name:"Public Library",cat:"users",bg:"#3b2a1a",surface:"#f5efe1",text:"#26190d",muted:"#695540",primary:"#3a5b78",accent:"#a04b1f",h:"'Source Serif 4',serif",b:"'Lora',serif",hero:"A free public resource on student loans.",sub:"Like the library: open to everyone, run for the public good, no late fees, no upsells.",cta:"Browse the catalog",cta2:"Ask a librarian",badge:"Civic warmth"},
{id:15,name:"Capitol Hill Op-Ed",cat:"granters",bg:"#fff",surface:"#fff",text:"#0c1428",muted:"#3f4a66",primary:"#0c2960",accent:"#9c1f2e",h:"'Source Serif 4',serif",b:"'Source Serif 4',serif",hero:"The case for borrower-centered student-loan reform.",sub:"A standing brief for foundations, congressional staff, and reporters covering the $1.7T crisis.",cta:"Read the brief",cta2:"Subscribe to the digest",badge:"Op-ed authority"},
{id:16,name:"Late-Night Inbox",cat:"users",bg:"#0e1424",surface:"#fdf6e3",text:"#0e1424",muted:"#5a6788",primary:"#d97706",accent:"#fcd34d",h:"'Lora',serif",b:"'Source Serif 4',serif",hero:"It's 11pm and you can't sleep over your loans.",sub:"We get it. Here's a 7-minute walkthrough of what to do tomorrow morning.",cta:"Start the walkthrough",cta2:"Email me the steps",badge:"Empathy first"},
{id:17,name:"PBS Documentary",cat:"both",bg:"#0a0a0a",surface:"#f3eedb",text:"#0a0a0a",muted:"#4a4233",primary:"#b8860b",accent:"#7a1f1c",h:"'Spectral',serif",b:"'Spectral',serif",hero:"A national reckoning with the student-debt crisis.",sub:"A multi-part series on how 45 million Americans got here — and what comes next.",cta:"Watch the series",cta2:"Educator resources",badge:"Documentary tone"},
{id:18,name:"Grandkids' Future",cat:"users",bg:"#fdf2f8",surface:"#fff",text:"#3a1a36",muted:"#7c4a73",primary:"#831843",accent:"#0d6e6e",h:"'Lora',serif",b:"'Lora',serif",hero:"Don't let student debt steal your retirement.",sub:"For the 9 million Americans 50+ still carrying student loans. We help you protect what you've built.",cta:"Protect your benefits",cta2:"Free retirement-impact check",badge:"50+ targeted"},
{id:19,name:"Treasury Department",cat:"granters",bg:"#f5f3ed",surface:"#fff",text:"#1c1f2b",muted:"#4a5060",primary:"#1d3a78",accent:"#8a6b2a",h:"'Source Serif 4',serif",b:"'Source Serif 4',serif",hero:"A 501(c)(3) advocate for the federal student-loan portfolio.",sub:"Working with Treasury's new servicing portfolio, ED, CFPB, and state AGs to protect 45M borrowers.",cta:"Annual report 2025",cta2:"990 transparency",badge:"Federal-fluent"},
{id:20,name:"Coffee Shop Town Hall",cat:"both",bg:"#3b2a1a",surface:"#faf3e6",text:"#27190b",muted:"#6c563b",primary:"#c2410c",accent:"#1d4ed8",h:"'Inter',sans-serif",b:"'Crimson Pro',serif",hero:"Pull up a chair. Let's end this together.",sub:"Town halls in 38 states. 2 million supporters. One simple ask: end the student-debt crisis.",cta:"Find a town hall",cta2:"Host one in your city",badge:"Community"},
// 21-30: light tweaks of current SDC palette
{id:21,name:"Current SDC + Higher Contrast",cat:"users",bg:"#ffffff",surface:"#ffffff",text:"#000000",muted:"#3f3f46",primary:"#0a3da6",accent:"#c5111c",h:"'Inter',sans-serif",b:"'Inter',sans-serif",hero:"End the student debt crisis.",sub:"A people-powered movement of 2 million supporters.",cta:"Take action",cta2:"Donate $12",badge:"WCAG-tightened"},
{id:22,name:"Current SDC + 20px base font",cat:"users",bg:"#ffffff",surface:"#ffffff",text:"#0a0f24",muted:"#3f3f46",primary:"#1d4ed8",accent:"#dc2626",h:"'Inter',sans-serif",b:"'Inter',sans-serif",hero:"End the student debt crisis.",sub:"A movement of 2 million supporters fighting for borrower relief.",cta:"Take action",cta2:"Read stories",badge:"Larger type"},
{id:23,name:"Current SDC + Sticky Phone CTA",cat:"users",bg:"#ffffff",surface:"#fafafa",text:"#0a0f24",muted:"#475569",primary:"#1d4ed8",accent:"#dc2626",h:"'Inter',sans-serif",b:"'Inter',sans-serif",hero:"Talk to a borrower advocate today.",sub:"(646) 820-8037 — Mon-Fri 9-5 PT. Or schedule a free call below.",cta:"Call (646) 820-8037",cta2:"Book a free call",badge:"Phone-first"},
{id:24,name:"Current SDC + Stats Above Fold",cat:"granters",bg:"#ffffff",surface:"#ffffff",text:"#0a0f24",muted:"#475569",primary:"#1d4ed8",accent:"#dc2626",h:"'Inter',sans-serif",b:"'Inter',sans-serif",hero:"4.7M signatures. 800K letters. 82K stories. 10 years.",sub:"Borrower-centered advocacy, every metric public.",cta:"View 2025 outcomes",cta2:"Open dashboard",badge:"Numbers-forward"},
{id:25,name:"Current SDC + Photo-Dominant",cat:"both",bg:"#ffffff",surface:"#ffffff",text:"#0a0f24",muted:"#475569",primary:"#1d4ed8",accent:"#dc2626",h:"'Inter',sans-serif",b:"'Inter',sans-serif",hero:"Robyn. Florida. Mom. Borrower.",sub:'"Canceling these loans would not only change our lives, but our families."',cta:"Read Robyn's story",cta2:"Share yours",badge:"Portrait hero"},
{id:26,name:"Current SDC + Funder Logos",cat:"granters",bg:"#ffffff",surface:"#ffffff",text:"#0a0f24",muted:"#475569",primary:"#1d4ed8",accent:"#dc2626",h:"'Inter',sans-serif",b:"'Inter',sans-serif",hero:"Independent. Borrower-led. Foundation-trusted.",sub:"Funded by individual donors and foundations who care about ending the student-debt crisis.",cta:"Become a funder",cta2:"View funder list",badge:"Funders visible"},
{id:27,name:"Current SDC + Plain-Language Toggle",cat:"users",bg:"#ffffff",surface:"#ffffff",text:"#0a0f24",muted:"#475569",primary:"#1d4ed8",accent:"#dc2626",h:"'Inter',sans-serif",b:"'Inter',sans-serif",hero:"Plain English on student loans.",sub:"All our guides are written at a 7th-grade reading level — the level Americans actually read at.",cta:"Browse plain-English guides",cta2:"Switch to legal language",badge:"Reading level"},
{id:28,name:"Current SDC + Spanish toggle",cat:"users",bg:"#ffffff",surface:"#ffffff",text:"#0a0f24",muted:"#475569",primary:"#1d4ed8",accent:"#dc2626",h:"'Inter',sans-serif",b:"'Inter',sans-serif",hero:"Recursos sobre préstamos estudiantiles, en tu idioma.",sub:"English / Español. Free guides, hotline, and live workshops in both languages.",cta:"Empezar aquí",cta2:"Start here",badge:"Bilingual"},
{id:29,name:"Current SDC + Single-Action Hero",cat:"users",bg:"#ffffff",surface:"#ffffff",text:"#0a0f24",muted:"#475569",primary:"#1d4ed8",accent:"#dc2626",h:"'Inter',sans-serif",b:"'Inter',sans-serif",hero:"What's your loan situation right now?",sub:"Pick the one that matches you. We'll send the next-step playbook.",cta:"I'm in default",cta2:"I'm in PSLF",badge:"One-action hero"},
{id:30,name:"Current SDC + 990 Transparency Strip",cat:"granters",bg:"#ffffff",surface:"#ffffff",text:"#0a0f24",muted:"#475569",primary:"#1d4ed8",accent:"#dc2626",h:"'Inter',sans-serif",b:"'Inter',sans-serif",hero:"End the student debt crisis.",sub:"Candid Platinum • GuideStar verified • Form 990 published annually • Independent board",cta:"Read our 990",cta2:"Annual report",badge:"Trust badges"},
// 31-45: MAY 1 DAY total overhauls — workers' day, debt as labor issue
{id:31,name:"May Day Picket",cat:"both",day:"may",bg:"#a30000",surface:"#fbf6ec",text:"#1a0606",muted:"#5a3a3a",primary:"#000000",accent:"#fbbf24",h:"'Bebas Neue',sans-serif",b:"'Public Sans',sans-serif",hero:"DEBT IS A LABOR ISSUE.",sub:"On May 1 — International Workers' Day — we say: the same workers who teach, nurse, and serve our communities should not be drowning in student debt.",cta:"Join May Day rally",cta2:"Sign the worker debt pledge",badge:"May Day"},
{id:32,name:"General Strike Banner",cat:"both",day:"may",bg:"#7f0d0d",surface:"#f5e9d3",text:"#1a0606",muted:"#5a3a3a",primary:"#7f0d0d",accent:"#0a0a0a",h:"'Anton',sans-serif",b:"'Spectral',serif",hero:"GENERAL STRIKE FOR DEBT RELIEF.",sub:"Educators, healthcare workers, public servants — your labor built this country. Your loans should not break it.",cta:"Pledge to strike",cta2:"Find your local",badge:"Strike energy"},
{id:33,name:"Vintage Union Hall",cat:"both",day:"may",bg:"#5b1a14",surface:"#f3e8d2",text:"#2b110b",muted:"#6c4d34",primary:"#5b1a14",accent:"#caa44a",h:"'Playfair Display',serif",b:"'Crimson Pro',serif",hero:"Solidarity from 1886 to 2026.",sub:"From the eight-hour workday to ending the student-debt crisis — workers' demands always sounded impossible. Until they didn't.",cta:"Read the labor brief",cta2:"Join the local",badge:"Heritage labor"},
{id:34,name:"Carnation Red",cat:"both",day:"may",bg:"#fbe7ec",surface:"#fff",text:"#3a0a14",muted:"#7a3848",primary:"#c2002f",accent:"#0a0a0a",h:"'Lora',serif",b:"'Inter',sans-serif",hero:"Wear a red carnation on May 1.",sub:"For every student-loan borrower who works two jobs to pay back loans they took on a promise that's been broken.",cta:"Order a carnation pin",cta2:"Share the campaign",badge:"May Day flower"},
{id:35,name:"Solidarity Forever",cat:"both",day:"may",bg:"#c2002f",surface:"#0a0a0a",text:"#f5f5f5",muted:"#a3a3a3",primary:"#fbbf24",accent:"#f5f5f5",h:"'Bebas Neue',sans-serif",b:"'Public Sans',sans-serif",hero:"SOLIDARITY FOREVER.",sub:"Borrowers and labor — one fight. Cancel the debt. Tax the lenders. Protect public service.",cta:"Sign the pledge",cta2:"Print the poster",badge:"Solidarity"},
{id:36,name:"Rosie Riveter",cat:"both",day:"may",bg:"#1d3a78",surface:"#f5e9d3",text:"#0a1a3d",muted:"#4a5b7a",primary:"#c2002f",accent:"#fbbf24",h:"'Anton',sans-serif",b:"'Public Sans',sans-serif",hero:"WE CAN END IT.",sub:"Women hold 63.6% of all student debt. Black women carry $20K more than white men. We can end it — together.",cta:"Join the campaign",cta2:"Read the data",badge:"Worker-icon"},
{id:37,name:"Picket Sign Pop",cat:"both",day:"may",bg:"#fbbf24",surface:"#0a0a0a",text:"#fef9c3",muted:"#fde68a",primary:"#c2002f",accent:"#fff",h:"'Rubik Mono One',sans-serif",b:"'Public Sans',sans-serif",hero:"CANCEL THE DEBT. PAY THE WORKERS.",sub:"May 1, 2026 — Day of Action for Borrower Workers. 38 cities. 2 million supporters.",cta:"Find a rally near you",cta2:"Print a sign",badge:"Picket pop"},
{id:38,name:"Worker's Co-op",cat:"both",day:"may",bg:"#1f3d2b",surface:"#f0ebd8",text:"#0e1f15",muted:"#4f6a59",primary:"#1f3d2b",accent:"#c2002f",h:"'Lora',serif",b:"'Lora',serif",hero:"A cooperative future, free of debt.",sub:"What if higher education served workers and not lenders? On May 1, we imagine — and organize — that future.",cta:"Join the co-op",cta2:"Read the manifesto",badge:"Co-op tone"},
{id:39,name:"Print Shop Activist",cat:"both",day:"may",bg:"#0a0a0a",surface:"#f3e9d3",text:"#0a0a0a",muted:"#5a4a30",primary:"#a30000",accent:"#0a0a0a",h:"'Anton',sans-serif",b:"'Crimson Pro',serif",hero:"PRESSED. PRINTED. POSTED.",sub:"Free downloadable May Day posters in every major US city. Hang them. Tear them down. Hang them again.",cta:"Download the print pack",cta2:"Submit your design",badge:"DIY print"},
{id:40,name:"Wobbly Heritage",cat:"both",day:"may",bg:"#0a0a0a",surface:"#f5ead0",text:"#0a0a0a",muted:"#5a4a30",primary:"#a30000",accent:"#caa44a",h:"'Playfair Display',serif",b:"'Spectral',serif",hero:"An injury to one is an injury to all.",sub:"From the IWW (1905) to the borrower movement (2026) — the same fight, in new clothes.",cta:"Join the IWW × SDCC action",cta2:"Read the history",badge:"IWW homage"},
{id:41,name:"Mayday Demonstration",cat:"both",day:"may",bg:"#c2185b",surface:"#fff",text:"#3a0a1f",muted:"#7c2a4a",primary:"#c2185b",accent:"#0a0a0a",h:"'Anton',sans-serif",b:"'Public Sans',sans-serif",hero:"MAYDAY. MAYDAY. MAYDAY.",sub:"For 9 million Americans 50+ still paying student loans into their retirement, this is an emergency.",cta:"Call your senator now",cta2:"Find a rally",badge:"Distress signal"},
{id:42,name:"Worker's Memorial",cat:"both",day:"may",bg:"#1f2937",surface:"#f1ead2",text:"#0e141c",muted:"#4a5263",primary:"#a04b1f",accent:"#caa44a",h:"'Cardo',serif",b:"'Spectral',serif",hero:"For the borrowers we have lost.",sub:"452,000 borrowers age 62+ face Social Security garnishment. We honor those crushed by the system. We organize so the next million aren't.",cta:"Light a candle",cta2:"Submit a name",badge:"Memorial"},
{id:43,name:"Eight-Hour Day",cat:"both",day:"may",bg:"#fdf6ec",surface:"#fff",text:"#0a0f24",muted:"#475569",primary:"#1d4ed8",accent:"#c2002f",h:"'Public Sans',sans-serif",b:"'Public Sans',sans-serif",hero:"Eight hours of work. Eight hours of rest. Eight hours of freedom from debt.",sub:"The same logic that won the eight-hour workday in 1886 wins debt relief in 2026.",cta:"Read the playbook",cta2:"Sign the petition",badge:"Reform parallel"},
{id:44,name:"Labor & Loans",cat:"both",day:"may",bg:"#7c2d12",surface:"#fdf6ec",text:"#3a1a08",muted:"#7c5836",primary:"#c2410c",accent:"#1d4ed8",h:"'Crimson Pro',serif",b:"'Lora',serif",hero:"Your wages. Their debt.",sub:"Wage garnishment for student loans is the modern company-store. We're shutting it down.",cta:"Stop garnishment now",cta2:"Read the report",badge:"Wage focus"},
{id:45,name:"Solidarity Across Generations",cat:"both",day:"may",bg:"#fdf2f8",surface:"#1e1b4b",text:"#fdf2f8",muted:"#a5b4fc",primary:"#fb7185",accent:"#fbbf24",h:"'Anton',sans-serif",b:"'Inter',sans-serif",hero:"GRANDPARENTS. PARENTS. GRADUATES.",sub:"Three generations of student-loan borrowers. One May 1 demand: end this for good.",cta:"Join the rally",cta2:"Share your generation's story",badge:"Intergenerational"},
// 46: TATE ESQ ATTORNEY POLISHED
{id:46,name:"Tate Esq Attorney Polished",cat:"both",day:"tate",bg:"#0e1424",surface:"#fafaf7",text:"#0e1424",muted:"#52607a",primary:"#1f3a78",accent:"#caa44a",h:"'Source Serif 4',serif",b:"'Inter',sans-serif",hero:"Student loan companies don't help. We do.",sub:"Borrower-centered guidance from a nonprofit team that's been at this for ten years. No upsells. No servicer scripts. Just honest help.",cta:"Book a free call",cta2:"Browse our calculators",badge:"Attorney-polished"}
];
const PEER = {
sdcRevenue:"$321K (smallest in 20-org cohort)",
topPeers:[
["Education Trust","$33.2M","Gates, Walton, Lumina, Strada, Kresge"],
["Roosevelt Institute","$22.8M","Foundation-funded research"],
["NCLC","$21.6M","Active Cy Pres program"],
["TICAS","~$8M","Lumina, Gates, Joyce"],
["Young Invincibles","~$5M","Health + ed coverage funders"]
]
};
/* ===========================================================
PAGE RENDERERS — each returns inner HTML for the mock
=========================================================== */
const PAGES = {
home: t => `
${nav(t)}
<div class="hero">
<div>
<h1 class="hero-h">${esc(t.hero)}</h1>
<p class="hero-p">${esc(t.sub)}</p>
<div class="ctas">
<a class="btn-p" href="#">${esc(t.cta)}</a>
<a class="btn-s" href="#">${esc(t.cta2)}</a>
</div>
</div>
<div class="hero-art">${esc(t.badge)} hero image<br><small style="opacity:.85;font-size:12px;font-weight:400">[Replace with portrait of borrower from steve-personal Drive]</small></div>
</div>
<div class="stats">
<div class="stat"><b>4,697,206</b><span>Petition signatures</span></div>
<div class="stat"><b>887,507</b><span>Letters to lawmakers</span></div>
<div class="stat"><b>82,475</b><span>Stories collected</span></div>
<div class="stat"><b>10+ yrs</b><span>Borrower advocacy</span></div>
</div>
<div class="section">
<h2>What we're working on right now (April 2026)</h2>
<div class="cards">
<div class="card"><h3>SAVE Plan blocked</h3><p>7M+ borrowers in administrative forbearance. We're tracking the litigation and your options.</p><a href="#">Read latest</a></div>
<div class="card"><h3>Default collections restarted</h3><p>Treasury offsets resumed May 2025. We help you stop garnishment and restore your loans.</p><a href="#">Get the playbook</a></div>
<div class="card"><h3>PSLF backlog</h3><p>93–98% denial rate. We help you appeal and document qualifying payments.</p><a href="#">Appeal a denial</a></div>
</div>
</div>
${funderStrip(t)}
${footer(t)}`,
stories: t => `
${nav(t)}
<div class="section">
<h1 class="hero-h">82,475 borrower stories.</h1>
<p class="hero-p">Read theirs. Share yours. Stories move policy.</p>
<div class="cards">
<div class="card"><h3>Eugenia, 70 — Long Beach, CA</h3><p>"I went back to school at 50. After 13 years of work and 200+ applications post-layoff, I still owe $50,000 three months from turning 70."</p><a href="#">Read full story</a></div>
<div class="card"><h3>john scalera, 69 — Galloway, NJ</h3><p>"I've been paying my Parent PLUS for 20 years. Started at $80K. I still owe $79K. I cannot retire."</p><a href="#">Read full story</a></div>
<div class="card"><h3>Megan S., 42 — Logan, UT</h3><p>"Borrowed $215,714 in graduate loans. Now I owe $456,178. SAVE was the only thing keeping it manageable."</p><a href="#">Read full story</a></div>
<div class="card"><h3>Ileasia Handy, 60 — Springfield, IL</h3><p>"First in my family to go to college. The same tool I use to help others is now hindering me."</p><a href="#">Read full story</a></div>
</div>
<div class="ctas" style="margin-top:22px"><a class="btn-p" href="#">Share your story</a><a class="btn-s" href="#">Browse all 82,475</a></div>
</div>
${footer(t)}`,
resources: t => `
${nav(t)}
<div class="section">
<h1 class="hero-h">Free borrower resources — refreshed April 2026</h1>
<p class="hero-p">Every guide updated for the SAVE block, the Treasury servicing transition, and the default-collections restart. <b>Last reviewed: ${new Date().toLocaleDateString('en-US',{month:'long',day:'numeric',year:'numeric'})}.</b></p>
<div class="cards">
<div class="card"><h3>SAVE Plan — what now? <span style="font-size:10px;background:#fef3c7;padding:2px 6px;border-radius:4px">Updated 04/2026</span></h3><p>The 8th Circuit ruling, your options for IDR re-enrollment, and how to avoid forbearance interest capitalization.</p><a href="#">Open guide (PDF)</a></div>
<div class="card"><h3>Default collections restarted <span style="font-size:10px;background:#fef3c7;padding:2px 6px;border-radius:4px">Updated 04/2026</span></h3><p>Treasury offsets, wage garnishment, the Fresh Start window — and how to use loan rehabilitation in 2026.</p><a href="#">Open guide (PDF)</a></div>
<div class="card"><h3>Parent PLUS <span style="font-size:10px;background:#fef3c7;padding:2px 6px;border-radius:4px">Updated 04/2026</span></h3><p>Double-consolidation loophole, ICR-only access, joint-consolidation fix for divorced borrowers.</p><a href="#">Open guide (PDF)</a></div>
<div class="card"><h3>PSLF after the backlog <span style="font-size:10px;background:#fef3c7;padding:2px 6px;border-radius:4px">Updated 04/2026</span></h3><p>How to count qualifying payments, appeal denials, and use the buy-back program.</p><a href="#">Open guide (PDF)</a></div>
<div class="card"><h3>Repayment system after July 1, 2026 <span style="font-size:10px;background:#fef3c7;padding:2px 6px;border-radius:4px">New 04/2026</span></h3><p>The new statutory IDR plan, the 25-year cap, and what your old plan converts to.</p><a href="#">Open guide (PDF)</a></div>
<div class="card"><h3>Income-Driven Repayment <span style="font-size:10px;background:#fef3c7;padding:2px 6px;border-radius:4px">Updated 04/2026</span></h3><p>IBR vs PAYE vs ICR vs the new plan. Which one is still open to you in 2026.</p><a href="#">Open guide (PDF)</a></div>
</div>
</div>
${footer(t)}`,
news: t => `
${nav(t)}
<div class="section">
<h1 class="hero-h">Latest news</h1>
<div class="cards">
<div class="card"><h3>April 22, 2026 — Little Hoover Commission hearing</h3><p>Historic hearing on California institutional debt locking students out of higher education.</p><a href="#">Read</a></div>
<div class="card"><h3>April 14, 2026 — 5th Annual State of Student Debt Summit</h3><p>Borrowers, advocates, and experts on the year ahead in federal student loans.</p><a href="#">Read</a></div>
<div class="card"><h3>April 9, 2026 — Treasury servicing transition</h3><p>What the move from FSA to Treasury means for the 45M federal borrowers.</p><a href="#">Read</a></div>
</div>
</div>
${footer(t)}`,
calculators: t => `
${nav(t)}
<div class="section">
<h1 class="hero-h">SDCC Calculators — free, borrower-first</h1>
<p class="hero-p">Eight free tools, no email gate. Built nonprofit, for borrowers, in plain language.</p>
<div class="cards" style="margin-bottom:24px">
${["TXT loan-listing tool","PSLF Calculator","Parent PLUS Calculator","SAVE Plan Calculator","ICR Plan Calculator","IBR Plan Calculator","PAYE Plan Calculator","Partial Financial Hardship Calculator"].map((n,i)=>`<div class="num-card"><div class="n">0${i+1}</div><h3>${n}</h3><p style="font-size:13px;color:var(--t-muted);margin:6px 0 10px">${calcDesc(n)}</p><a href="#" style="color:var(--t-primary);font-size:13px;font-weight:700;text-decoration:none">Open →</a></div>`).join("")}
</div>
<div class="num-card" style="margin-top:24px">
<div class="n">PSLF DEMO</div>
<h3>PSLF Calculator (live)</h3>
<div class="calc">
<div><label>Loan balance ($)</label><input id="cBal" type="number" value="120000" /></div>
<div><label>Avg interest rate (%)</label><input id="cInt" type="number" step="0.01" value="6.8" /></div>
<div><label>Annual income ($)</label><input id="cInc" type="number" value="62000" /></div>
<div><label>Family size</label><input id="cFam" type="number" value="2" /></div>
<div><label>Tax filing status</label><select id="cTax"><option>Single</option><option>Married Filing Jointly</option><option>Married Filing Separately</option><option>Head of Household</option></select></div>
<div><label>State of residence</label><select id="cState"><option>Lower 48</option><option>Alaska</option><option>Hawaii</option></select></div>
<div><label>Avg annual income growth (%)</label><input id="cGrow" type="number" step="0.1" value="3" /></div>
<div><label>Years in public service so far</label><input id="cYrs" type="number" value="3" /></div>
<div><label>Qualifying payments so far</label><input id="cPay" type="number" value="36" /></div>
<div><label>Current monthly payment ($)</label><input id="cMon" type="number" value="320" /></div>
</div>
<div class="calc-row">
<button class="btn-p" id="cRun" style="background:var(--t-primary);color:#fff;padding:10px 16px;border-radius:8px;border:0;cursor:pointer;font-weight:700">Calculate</button>
</div>
<div class="calc-out" id="cOut" style="margin-top:14px"><b>—</b>Enter your numbers and click Calculate.</div>
</div>
</div>
${footer(t)}`,
pslfJson: t => `
${nav(t)}
<div class="section">
<h1 class="hero-h">PSLF Calculator — JSON schema</h1>
<p class="hero-p">The structured input/output our PSLF Calculator reads. Same shape as the field-tested model used by tateesq.com/calculator/pslf — public, documented, replicable.</p>
<h3 style="font-family:var(--t-h);margin-top:18px">Inputs</h3>
<pre class="json">${esc(JSON.stringify(PSLF_SCHEMA.inputs,null,2))}</pre>
<h3 style="font-family:var(--t-h);margin-top:18px">Outputs</h3>
<pre class="json">${esc(JSON.stringify(PSLF_SCHEMA.outputs,null,2))}</pre>
<h3 style="font-family:var(--t-h);margin-top:18px">Sample request → response</h3>
<pre class="json">${esc(JSON.stringify(PSLF_SCHEMA.sample,null,2))}</pre>
<p class="hero-p" style="margin-top:18px"><b>Why this exists.</b> Borrowers should be able to inspect the math behind any tool that touches their loans. Open inputs, open outputs, no hidden assumptions.</p>
</div>
${footer(t)}`,
cypres: t => `
${nav(t)}
<div class="section">
<h1 class="hero-h">Cy Pres awards — fund borrower advocacy from class-action settlements</h1>
<p class="hero-p">When residual class-action settlement funds cannot be distributed to class members, courts may direct those funds to a 501(c)(3) whose mission aligns with the underlying suit. SDCC is purpose-built to be that recipient for student-loan litigation.</p>
<div class="cards">
<div class="card"><h3>Why SDCC qualifies</h3><p>10 years of borrower advocacy, 4.7M signatures, 82K stories collected — direct beneficiary alignment with student-loan classes (Navient, Sweet, Borrower Defense).</p></div>
<div class="card"><h3>Recent eligible matters</h3><p>Navient settlement residuals, ITT/Corinthian/Westwood Borrower Defense funds, servicer-misconduct settlements at the state AG level.</p></div>
<div class="card"><h3>Use of funds</h3><p>100% directed to borrower hotline, free guides, and public-interest litigation support. Annual report published. Independent board.</p></div>
<div class="card"><h3>Counsel & process</h3><p>We provide draft order language, IRS determination letter, audited financials, 990, and beneficiary-alignment memo on request within 48 hours.</p></div>
</div>
<div class="ctas" style="margin-top:22px"><a class="btn-p" href="#">Request the Cy Pres packet</a><a class="btn-s" href="#">Email cypres@studentdebtcrisis.org</a></div>
</div>
${footer(t)}`,
bookacall: t => `
${nav(t)}
<div class="hero">
<div>
<h1 class="hero-h">Student-loan companies don't help. <br>We do.</h1>
<p class="hero-p">Book a free 20-minute call with an SDCC borrower advocate. We'll walk through your specific loans, your repayment options in April 2026, and your next three steps. No upsell — we are a 501(c)(3).</p>
<div class="ctas">
<a class="btn-p" href="#">📅 Book my free call</a>
<a class="btn-s" href="#">Or call (646) 820-8037</a>
</div>
</div>
<div class="hero-art" style="background:#0e1424;display:flex;flex-direction:column;justify-content:center;text-align:center;padding:0;overflow:hidden;position:relative">
<div style="background:rgba(255,255,255,.08);padding:40px 20px;width:100%">
<div style="font-size:42px;line-height:1;margin-bottom:8px">▶</div>
<div style="font-family:var(--t-h);font-size:14px;color:#fff">Watch: What SDCC can do for you (2:14)</div>
<div style="font-size:11px;color:#a3a3a3;margin-top:6px">[Embed: SDCC explainer video]</div>
</div>
</div>
</div>
<div class="section">
<h2>What we're good at</h2>
<div class="cards">
<div class="num-card"><div class="n">01</div><h3>SAVE / IDR triage</h3><p style="font-size:13px;color:var(--t-muted);margin:6px 0 0">Figure out your real options now that SAVE is blocked.</p></div>
<div class="num-card"><div class="n">02</div><h3>PSLF appeals</h3><p style="font-size:13px;color:var(--t-muted);margin:6px 0 0">When your qualifying-payment count is wrong — and it usually is.</p></div>
<div class="num-card"><div class="n">03</div><h3>Default & garnishment</h3><p style="font-size:13px;color:var(--t-muted);margin:6px 0 0">Fresh Start, rehabilitation, stopping wage and SS offsets.</p></div>
<div class="num-card"><div class="n">04</div><h3>Parent PLUS strategy</h3><p style="font-size:13px;color:var(--t-muted);margin:6px 0 0">Double-consolidation, ICR access, divorced-borrower fixes.</p></div>
<div class="num-card"><div class="n">05</div><h3>Borrower Defense</h3><p style="font-size:13px;color:var(--t-muted);margin:6px 0 0">For ITT, Corinthian, Westwood, Ashford and other for-profit harm.</p></div>
<div class="num-card"><div class="n">06</div><h3>Disability / TPD</h3><p style="font-size:13px;color:var(--t-muted);margin:6px 0 0">Permanent-disability discharge documentation and appeals.</p></div>
</div>
</div>
<div class="section" style="background:rgba(0,0,0,.04)">
<h2>What borrowers say</h2>
<div class="cards">
<div class="card"><h3>Robyn — Florida</h3><p>"They didn't try to sell me anything. They just helped."</p></div>
<div class="card"><h3>Eugenia — Long Beach</h3><p>"At 70, finally someone explained Parent PLUS in English."</p></div>
<div class="card"><h3>Megan — Logan, UT</h3><p>"They helped me figure out my PSLF count was off by 18 months."</p></div>
</div>
</div>
${footer(t)}`
};
const PSLF_SCHEMA = {
inputs:{loanBalance:{type:"number",units:"USD",required:true,label:"Loan balance"},avgInterestRate:{type:"number",units:"percent",required:true,label:"Average interest rate"},monthlyPayment:{type:"number",units:"USD",required:true,label:"Current monthly payment"},state:{type:"string",enum:"US state",required:true,label:"State of residence"},taxFilingStatus:{type:"string",enum:["Single","Head of Household","Qualified Widow(er)","Married Filing Jointly","Married Filing Separately"],required:true,label:"Tax filing status"},familySize:{type:"number",units:"count",required:true,label:"Family size"},annualIncome:{type:"number",units:"USD",required:true,label:"Annual income (AGI)"},avgAnnualGrowth:{type:"number",units:"percent",required:true,label:"Average annual income growth"},yearsInPublicService:{type:"number",units:"years",required:true,label:"Years in qualifying public service so far"},qualifyingPayments:{type:"number",units:"count",required:true,label:"Qualifying payments completed"}},
outputs:{monthlyPaymentByPlan:{IBR:"USD",PAYE:"USD",ICR:"USD",SAVE_blocked:true,STANDARD:"USD"},totalRepaymentBeforeForgiveness:"USD",totalForgivenessAmount:"USD",remainingPayments:"count",monthsToForgiveness:"count",timelineToForgiveness:"YYYY-MM",disclaimer:"Estimate only — verify against StudentAid.gov"},
sample:{request:{loanBalance:120000,avgInterestRate:6.8,monthlyPayment:320,state:"CA",taxFilingStatus:"Single",familySize:2,annualIncome:62000,avgAnnualGrowth:3,yearsInPublicService:3,qualifyingPayments:36},response:{monthlyPaymentByPlan:{IBR:320,PAYE:295,ICR:760,STANDARD:1380},totalRepaymentBeforeForgiveness:38640,totalForgivenessAmount:138420,remainingPayments:84,monthsToForgiveness:84,timelineToForgiveness:"2033-04"}}
};
/* helpers */
function nav(t){return `<header class="topnav"><div class="brand">SDCC</div><nav><a href="#">Take Action</a><a href="#">Stories</a><a href="#">Resources</a><a href="#">News</a><a href="#">Calculators</a><a href="#">Book a Call</a><a class="donate" href="#">Donate $12</a></nav></header>`;}
function footer(t){return `<div class="footer">© 2026 Student Debt Crisis Center · 501(c)(3) · 15442 Ventura Blvd #102, Los Angeles CA 91403 · (646) 820-8037 · info@studentdebtcrisis.org · Candid Platinum · GuideStar verified · Form 990 published annually. Not a law firm or financial counselor; we provide free information about existing federal & state programs.</div>`;}
function funderStrip(t){return `<div class="funder-strip"><span>Foundation A</span><span>Foundation B</span><span>Foundation C</span><span>Cy Pres awards</span><span>Individual donors</span><span>Workplace giving</span></div>`;}
function calcDesc(n){const m={"TXT loan-listing tool":"Paste your StudentAid.gov export — get a clean loan inventory.","PSLF Calculator":"Months to forgiveness given your plan, income, family size.","Parent PLUS Calculator":"Double-consolidation savings, ICR-only access projections.","SAVE Plan Calculator":"Your old SAVE payment vs. your new IDR options post-block.","ICR Plan Calculator":"The Parent PLUS borrower's only IDR door — modeled.","IBR Plan Calculator":"Old IBR vs new IBR — eligibility & payment math.","PAYE Plan Calculator":"PAYE eligibility test & 20-year forgiveness path.","Partial Financial Hardship Calculator":"Whether you qualify for IDR partial hardship in 2026."};return m[n]||"";}
function esc(s){return String(s).replace(/[&<>"']/g,c=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[c])}
/* WCAG contrast */
function lum(hex){const r=parseInt(hex.slice(1,3),16)/255,g=parseInt(hex.slice(3,5),16)/255,b=parseInt(hex.slice(5,7),16)/255;const f=v=>v<=.03928?v/12.92:Math.pow((v+.055)/1.055,2.4);return .2126*f(r)+.7152*f(g)+.0722*f(b)}
function contrast(a,b){const L1=lum(a),L2=lum(b);return ((Math.max(L1,L2)+.05)/(Math.min(L1,L2)+.05))}
/* CRITIQUE — per (theme, audience, page) */
function critique(t,aud,page){
const cTextSurface=contrast(t.text,t.surface).toFixed(2);
const cPrimaryWhite=contrast(t.primary,'#ffffff').toFixed(2);
const cAccentSurface=contrast(t.accent,t.surface).toFixed(2);
const tag=t.day==='may'?'<span class="day-chip may">MAY 1</span>':t.day==='tate'?'<span class="day-chip tate">TATE-STYLE</span>':'<span class="day-chip">'+t.cat+'</span>';
const score=Math.round((parseFloat(cTextSurface)>=4.5?1:.4)*40 + (parseFloat(cPrimaryWhite)>=3?1:.4)*30 + (t.cat===aud||t.cat==='both'?30:15));
const scoreClass=score>=80?'pass':score>=60?'warn':'fail';
const pageNote = page==='resources'?'Resource cards stamped "Updated 04/2026" — granters specifically check that resource pages are not stale.':
page==='cypres'?'Cy Pres page is the single biggest unclaimed revenue line for student-debt orgs. NCLC has one. SDCC does not.':
page==='calculators'?'Free calculators with no email gate are how Tate Esq drives 69 Google reviews. SDCC has the borrower base to do the same.':
page==='pslfJson'?'Open JSON schema = signal of evidence-based seriousness to program officers from Arnold Ventures and Lumina.':
page==='bookacall'?'A "book a call" page with embedded video and Calendly converts >5x better than a contact form for older audiences.':
page==='stories'?'Borrower stories are SDCC\'s best asset — but they\'re trapped in a Wix-ified VocalReferences widget. Move to native rendering.':
page==='news'?'News page is SEO gold for breaking-policy queries. Add date-modified microdata for Google freshness signals.':
'Home page is what foundation program officers see in the first 30 seconds. Lead with proof, not pleas.';
const audPros = aud==='granters'? [
t.cat==='granters'||t.cat==='both' ? `Visual register reads "professional 501(c)(3)" — POs from Lumina, Arnold, Ford recognize this language.` : `Even though styled for users, the palette is clean enough not to red-flag a PO.`,
`Contrast ${cTextSurface}:1 (text on surface) ${parseFloat(cTextSurface)>=4.5?'meets WCAG AA — required for federally-funded programs':'is below WCAG AA — fix before sending to a foundation site review'}.`,
page==='cypres'||page==='resources'||page==='pslfJson'||page==='bookacall' ? 'Page itself signals organizational maturity — most $321K-tier orgs do not have this page at all.' : 'Add Candid Platinum + GuideStar badges in the footer; SDCC qualifies and is not displaying them.'
] : aud==='users'? [
t.cat==='users'||t.cat==='both' ? 'Tone matches the borrower emotional state — distrustful of servicers, overwhelmed, time-poor.' : 'Even though styled for granters, the page is still legible and accessible.',
`Body type ${parseFloat(cTextSurface)>=7?'easily readable for 45+ eyes':'should be tested with 20px base font for 45+ readability'}.`,
page==='bookacall'||page==='calculators'||page==='resources' ? 'Page directly serves a borrower trigger moment — exactly what the 50–61 cohort searches for.' : 'Surface a phone number above the fold — 45+ borrowers prefer phone over chat.'
] : [
`Cross-audience score ${score}/100. Theme tagged "${t.cat}".`,
`Contrast text/surface ${cTextSurface}:1 · primary on white ${cPrimaryWhite}:1 · accent on surface ${cAccentSurface}:1.`,
page==='home' ? 'Hero copy "${esc(t.hero)}" works for both audiences only if backed by visible proof (numbers, funder logos, dated outcomes).' : pageNote
];
const audCons = aud==='granters'? [
t.cat==='users' ? 'May read as too borrower-folksy for a $5M+ foundation gift — POs equate polish with capacity.' : null,
parseFloat(cTextSurface)<4.5 ? `WCAG AA fail (${cTextSurface}:1) — federally-funded foundation sites require AA minimum.` : null,
page!=='cypres' && page!=='pslfJson' ? 'No published 990, no theory of change link, no evaluation data on this page — POs check for these in the first 30 seconds.' : null,
t.day==='may' ? 'May Day branding may signal "advocacy / partisan" to risk-averse donor-advised-fund advisors. Consider a date-fenced rollout (April 25 – May 5 only).' : null
].filter(Boolean): aud==='users'? [
t.cat==='granters' ? 'Tone risks reading as "another DC nonprofit that doesn\'t understand my Parent PLUS letter."' : null,
parseFloat(cTextSurface)<7 ? `Contrast ${cTextSurface}:1 is OK for sighted 30-year-olds; tighten to 7:1 for the 45+ retina.` : null,
page!=='bookacall' && page!=='calculators' && page!=='resources' ? 'No phone number above the fold — 45+ users want to call before they read.' : null,
t.day==='may' ? '"May Day" framing is unfamiliar to most US borrowers; pair with plain-language explainer ("We mark International Workers\' Day because…").' : null
].filter(Boolean): [
parseFloat(cTextSurface)<4.5 ? `Fails WCAG AA — fix before going live.` : null,
t.cat!=='both' ? `Theme is tagged for ${t.cat}; the opposite audience may bounce.` : null,
'Hero CTA hierarchy: two equal-weight buttons compete. Pick a primary.'
].filter(Boolean);
const audIdeas = aud==='granters'? [
`Add a "Funded by" strip with named foundations. Education Trust does this; it correlates with the 19%-of-grantees-getting-32%-of-dollars pattern.`,
`Publish a one-page Theory of Change PDF. Bridgespan rates this as a top-5 PO check.`,
`Stamp every resource "Reviewed [date]". Stale resources cost grants — fresh ones win them.`,
`Stand up the Cy Pres page (currently missing) — peer NCLC has one and treats it as a revenue line.`,
`Get the Candid Platinum seal — seal-holders raise 62% more on average.`
] : aud==='users'? [
`Lead with a phone number and a "what's your situation right now?" 3-button hero.`,
`Move all PDFs to native HTML pages — PDFs do not rank for long-tail Google queries.`,
`Add a Spanish toggle; the Lumina Foundation funds bilingual ed-access work specifically.`,
`Plain-language pass: rewrite servicer-letter explainers at 7th-grade reading level.`,
`Calculators with no email gate — drives organic traffic and Google reviews like Tate Esq does.`
] : [
`Single-action hero per page. Two co-equal CTAs split conversion in both audiences.`,
`Move from Wix to a static-site build (Astro/Next) — you'll fix performance, accessibility, and SEO in one stroke.`,
`Update the © 2023 footer. Stale copyright reads as "abandoned org" to both POs and borrowers.`,
`Add date-modified schema to every resource and news post for Google freshness.`,
`Cross-link Stories ↔ Resources ↔ Calculators ↔ Cy Pres — current site is a hub-and-spoke; make it a graph.`
];
const why = aud==='granters'? `<b>Why some get the money, others don't:</b> Education Trust ($33.2M revenue) publishes a named funder list, theory of change, and dated outcomes. SDCC (${PEER.sdcRevenue}) does none of these on the public site. Foundations cannot fund what they cannot underwrite. The single biggest dollar-per-hour move for SDCC is publishing a funder list, an outcomes report, and a Cy Pres page — three pages, and the public-perception gap to a $5M+ peer narrows immediately.` :
aud==='users'? `<b>Why borrowers stay or bounce:</b> the 50–61 cohort carries the highest balances ($46K–$48K), and 75.8% of program officers are women — but the borrowers who pay this site visits at 11pm with a wage-garnishment letter want a phone number, plain language, and a calculator that does not require their email. Make the site work for them and the foundations notice.` :
`<b>The 1-vs-100 gap:</b> SDCC operates at ${PEER.sdcRevenue} while peer orgs run $4M–$33M. The asset SDCC owns that no peer matches: 82,475 first-person borrower stories. Surface them, dated and SEO-discoverable, and the moat becomes visible to both granters and users at once.`;
return `
<h2>Critique ${tag}</h2>
<div class="meta">Theme #${t.id} · ${esc(t.name)} · audience: ${aud} · page: ${page}</div>
<div class="scorebar">
<div class="scorechip ${scoreClass}">Fit score: ${score}/100</div>
<div class="scorechip ${parseFloat(cTextSurface)>=4.5?'pass':'fail'}">Text contrast ${cTextSurface}:1</div>
<div class="scorechip ${parseFloat(cPrimaryWhite)>=3?'pass':'warn'}">Primary on white ${cPrimaryWhite}:1</div>
</div>
<details open><summary>✅ Pros</summary><ul class="pros">${audPros.map(p=>'<li>'+p+'</li>').join('')}</ul></details>
<details open><summary>⚠️ Cons</summary><ul class="cons">${audCons.length?audCons.map(p=>'<li>'+p+'</li>').join(''):'<li>None blocking on this page.</li>'}</ul></details>
<details open><summary>💡 Suggestions vs. peer nonprofits</summary><ul class="ideas">${audIdeas.map(p=>'<li>'+p+'</li>').join('')}</ul></details>
<details><summary>📊 Peer benchmark</summary><ul>${PEER.topPeers.map(p=>'<li><b>'+p[0]+'</b> — '+p[1]+' · '+p[2]+'</li>').join('')}</ul></details>
<details><summary>📷 Photo suggestions for this page (steve-personal Drive)</summary><ul><li><b>Hero:</b> portrait of a 50+ borrower at kitchen table with paperwork (search: "kitchen", "paperwork", "natural light")</li><li><b>Stats band:</b> wide-angle of 2024 State of Student Debt Summit audience</li><li><b>Cards:</b> three quiet workplace shots — teacher, nurse, postal worker (no stock photos)</li><li><b>Footer:</b> SDCC team photo from the most recent retreat (must be < 12 months old)</li></ul><div class="meta" style="margin-top:6px">⚠️ Google Drive MCP not yet authenticated — run /mcp and select "claude.ai Google Drive" to let the assistant pull actual asset filenames from steve-personal (steveabramsdesigns@gmail.com).</div></details>
<div class="why">${why}</div>
<div class="meta">Theme cat=${t.cat}, day=${t.day||'standard'}. Updated April 2026 against current SDCC site, ProPublica peer revenue data, and 9M+ borrowers age 50+ demographic.</div>`;
}
/* REVENUE STREAMS */
const REV = [
{h:"Foundation grants",t:"q",e:"High effort",imp:"High impact",d:"Lumina ($1.5B), Arnold ($190M/yr), Ford BUILD, Kresge. Each requires theory of change + outcomes data. SDCC currently invisible on most foundation portfolio sites."},
{h:"Cy Pres awards",t:"q",e:"Medium effort",imp:"High impact",d:"Residual class-action funds. NCLC has an active program. Navient, ITT, Corinthian, Borrower Defense settlements all eligible. SDCC has zero cy pres page → zero pipeline."},
{h:"Major individual donors",t:"q",e:"High effort",imp:"High impact",d:"$25K-$1M gifts. Mid-tier donor program below 1% of SDCC revenue today. Borrower-success-story-led cultivation tour."},
{h:"Recurring small-donor (ActBlue)",t:"h",e:"Low effort",imp:"Medium",d:"Already on ActBlue. Move from one-time $12 default to $12/mo recurring as default toggle. 3-5x donor LTV uplift."},
{h:"Workplace giving (CFC, United Way)",t:"q",e:"Low effort",imp:"Medium",d:"Combined Federal Campaign + state workplace campaigns. Federal employees with PSLF debt are exactly the donor."},
{h:"DAF & planned giving",t:"q",e:"Medium effort",imp:"High",d:"Donor-Advised Funds at Fidelity Charitable / Schwab — set up DAFgiving360 link. Bequest language for borrower-debtors who want their estate to fight back."},
{h:"Cause-marketing partnerships",t:"h",e:"Medium effort",imp:"Medium",d:"Refi-adjacent fintechs (NOT predatory ones), Penny Hoarder-style affiliates, careful with conflict of interest. Disclosure-first."},
{h:"Earned: paid workshops & certifications",t:"h",e:"Medium effort",imp:"Medium",d:"Certify HR benefit administrators in PSLF. Schools and city governments will pay $500-$2K per seat."},
{h:"Government contracts",t:"q",e:"High effort",imp:"High",d:"State AG offices, CFPB consumer ed, state higher-ed agencies fund borrower outreach. Two-year build."},
{h:"Sponsored research / fellowships",t:"q",e:"Medium effort",imp:"Medium",d:"Pair with Roosevelt Institute, NCLC, TICAS for jointly-funded fellow positions. Counts as program services."},
{h:"Email/SMS list partnerships",t:"h",e:"Low effort",imp:"Medium",d:"82K story-submitters + petition signers = a uniquely qualified borrower list. Rent ethically (no scams) for $1-3/contact."},
{h:"Litigation cost-recovery & attorney fees",t:"q",e:"High effort",imp:"High",d:"Partner-of-record on impact lawsuits. NCLC, Public Citizen, Protect Borrowers all do this. Statutory fees + cy pres feed each other."}
];
/* RENDER */
const themeSel = document.getElementById('themeSel');
THEMES.forEach(t=>{
const o=document.createElement('option');
o.value=t.id;
const d=t.day==='may'?' 🚩':t.day==='tate'?' ⚖️':'';
o.textContent=`#${t.id} — ${t.name}${d}`;
themeSel.appendChild(o);
});
function applyTheme(t){
const r=document.documentElement.style;
r.setProperty('--t-bg',t.bg);r.setProperty('--t-surface',t.surface);
r.setProperty('--t-text',t.text);r.setProperty('--t-muted',t.muted);
r.setProperty('--t-primary',t.primary);r.setProperty('--t-accent',t.accent);
r.setProperty('--t-h',t.h);r.setProperty('--t-b',t.b);
}
function render(){
const t=THEMES.find(x=>x.id===+themeSel.value)||THEMES[0];
const aud=document.getElementById('audSel').value;
const page=document.getElementById('pageSel').value;
applyTheme(t);
document.getElementById('mockRoot').innerHTML = PAGES[page](t);
document.getElementById('critRoot').innerHTML = critique(t,aud,page);
if(page==='calculators') wirePSLF();
}
function wirePSLF(){
const $=id=>document.getElementById(id);
const btn=$('cRun'); if(!btn) return;
btn.onclick=()=>{
const bal=+$('cBal').value, rate=+$('cInt').value/100, inc=+$('cInc').value, fam=+$('cFam').value, grow=+$('cGrow').value/100, yrs=+$('cYrs').value, pay=+$('cPay').value;
const polLine=2025*15060/12; // not used precisely; demo math
const fpl = 15060 + 5380*(fam-1); // 2025 lower 48
const discIncome = Math.max(0, inc - 1.5*fpl);
const ibrMonthly = Math.round(discIncome*0.10/12);
const payeMonthly = Math.round(discIncome*0.10/12);
const icrMonthly = Math.round(inc*0.20/12);
const stdMonthly = Math.round((bal*(rate/12))/(1-Math.pow(1+rate/12,-120)));
const remaining = Math.max(0,120-pay);
const monthsLeft = remaining;
const totalRepay = ibrMonthly*remaining;
const forg = Math.max(0, bal*(1+rate*monthsLeft/12) - totalRepay);
const eta = new Date(); eta.setMonth(eta.getMonth()+monthsLeft);
$('cOut').innerHTML = `<b>$${ibrMonthly.toLocaleString()}/mo IBR · $${payeMonthly.toLocaleString()}/mo PAYE · $${icrMonthly.toLocaleString()}/mo ICR · $${stdMonthly.toLocaleString()}/mo Standard</b>
${remaining} qualifying payments remaining · est. forgiveness ${eta.toLocaleString('en-US',{month:'long',year:'numeric'})}<br>
Total out-of-pocket before forgiveness: <b style="font-size:16px">$${totalRepay.toLocaleString()}</b> · estimated forgiven: <b style="font-size:16px">$${Math.round(forg).toLocaleString()}</b><br>
<span style="font-size:11px;color:#6b7280">Estimate. Verify against StudentAid.gov. Demo math; production version uses the documented JSON schema on the PSLF JSON Inspector page.</span>`;
};
}
/* Modal */
const dlg=document.getElementById('revModal');
document.getElementById('revBtn').onclick=()=>{ dlg.showModal(); };
document.getElementById('revClose').onclick=()=>dlg.close();
dlg.addEventListener('click',e=>{ if(e.target===dlg) dlg.close(); });
const grid=document.getElementById('revGrid');
grid.innerHTML = REV.map(r=>`<div class="rev-card"><span class="tag ${r.t}">${r.t==='q'?'Quiet money':r.t==='h'?'Hustle money':'Steady'}</span><span class="tag">${r.e}</span><span class="tag">${r.imp}</span><h3>${r.h}</h3><p>${r.d}</p></div>`).join('');
/* OVERVIEW — all 46 themes on one page */
const ovGrid = document.getElementById('ovGrid');
function buildOverview(){
ovGrid.innerHTML = THEMES.map(t=>{
const styleVars = `--c-bg:${t.bg};--c-surface:${t.surface};--c-text:${t.text};--c-muted:${t.muted};--c-primary:${t.primary};--c-accent:${t.accent};--c-h:${t.h};--c-b:${t.b}`;
const catCls = t.day==='may'?'may':t.day==='tate'?'tate':t.cat;
const catLabel = t.day==='may'?'May Day':t.day==='tate'?'Tate Esq':t.cat;
const score = (parseFloat(contrast(t.text,t.surface).toFixed(2))>=4.5?1:0)*40 + (parseFloat(contrast(t.primary,'#fff').toFixed(2))>=3?1:0)*30 + 30;
return `<div class="ov-card" data-id="${t.id}" style="${styleVars}">
<div class="ov-meta"><span class="num">#${t.id}</span><span class="cat ${catCls}">${catLabel}</span></div>
<div class="ov-mini">
<div class="ov-nav">SDCC<span class="donate">Donate $12</span></div>
<div class="ov-hero">
<div class="ov-h1">${esc(t.hero)}</div>
<div class="ov-sub">${esc(t.sub.slice(0,140))}${t.sub.length>140?'…':''}</div>
<div class="ov-ctas"><span class="ov-cta p">${esc(t.cta)}</span><span class="ov-cta s">${esc(t.cta2)}</span></div>
</div>
<div class="ov-stats">
<div class="ov-stat">4.7M<span>signatures</span></div>
<div class="ov-stat">887K<span>letters</span></div>
<div class="ov-stat">82K<span>stories</span></div>
<div class="ov-stat">10y<span>advocacy</span></div>
</div>
<div class="ov-foot">© 2026 Student Debt Crisis Center · 501(c)(3)</div>
</div>
<div class="ov-name"><span>${esc(t.name)}</span><span class="score">${score}/100</span></div>
</div>`;
}).join('');
ovGrid.querySelectorAll('.ov-card').forEach(c=>{
c.addEventListener('click',()=>{ location.hash = 't-'+c.dataset.id; });
});
}
/* HASH ROUTER */
const splitView = document.getElementById('splitView');
const overviewView = document.getElementById('overviewView');
const allBtn = document.getElementById('allBtn');
function showOverview(){
splitView.style.display='none';
overviewView.style.display='block';
allBtn.textContent='✕ Close all-46 view';
document.querySelectorAll('.controls .ctl').forEach(c=>c.style.opacity='.4');
}
function showSplit(){
splitView.style.display='grid';
overviewView.style.display='none';
allBtn.textContent='📑 View all 46';
document.querySelectorAll('.controls .ctl').forEach(c=>c.style.opacity='1');
}
function routeFromHash(){
const h = location.hash.replace('#','');
if(h==='all'){ showOverview(); return; }
const m = h.match(/^t-(\d+)$/);
if(m){
const id = +m[1];
if(THEMES.find(x=>x.id===id)){
themeSel.value = id;
showSplit();
render();
return;
}
}
// default
showSplit();
render();
}
allBtn.onclick=()=>{
location.hash = (overviewView.style.display==='none') ? 'all' : 't-'+themeSel.value;
};
window.addEventListener('hashchange',routeFromHash);
/* init */
['themeSel','audSel','pageSel'].forEach(id=>document.getElementById(id).addEventListener('change',()=>{
// Update hash so URL reflects current theme without triggering router loop
const newHash = 't-'+themeSel.value;
if(location.hash !== '#'+newHash){
history.replaceState(null,'','#'+newHash);
}
render();
}));
themeSel.value = 1;
buildOverview();
routeFromHash();
</script>
</body>
</html>