Nonprofit — Impact Report
A warm, transparent annual impact report page for a fictional charity. Headline stat cards count up on scroll, a hover-linked donut chart breaks down where every dollar goes, and program-outcome sections reveal as you scroll with photo placeholders, beneficiary quotes and animated progress thermometers. Rounds out with an audited financial-transparency table, donor recognition, and download and share actions wired to a small toast helper. Built with vanilla HTML, CSS and JavaScript — no frameworks, fully responsive and accessible.
MCP
Code
:root {
--brand: #1f7a6d;
--brand-d: #155e54;
--accent: #e8743b;
--accent-d: #cc5d28;
--ink: #2a2722;
--ink-2: #524d44;
--muted: #7a7368;
--bg: #faf6f0;
--surface: #ffffff;
--line: rgba(42, 39, 34, 0.1);
--line-2: rgba(42, 39, 34, 0.18);
--ok: #2f9e6f;
--warn: #d98a2b;
--danger: #d4503e;
--r-sm: 8px;
--r-md: 14px;
--r-lg: 22px;
--sh-s: 0 1px 2px rgba(42, 39, 34, 0.06), 0 2px 8px rgba(42, 39, 34, 0.05);
--sh-m: 0 6px 22px rgba(42, 39, 34, 0.1);
--sh-l: 0 18px 50px rgba(42, 39, 34, 0.14);
}
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
margin: 0;
font-family: "Inter", system-ui, -apple-system, sans-serif;
color: var(--ink);
background: var(--bg);
line-height: 1.6;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
}
h1, h2, h3 {
font-family: "Fraunces", Georgia, serif;
font-weight: 600;
line-height: 1.12;
color: var(--ink);
margin: 0;
}
p { margin: 0; }
.wrap { width: min(1120px, 100% - 3rem); margin-inline: auto; }
.sr-only {
position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.skip {
position: absolute; left: -999px; top: 0; z-index: 100;
background: var(--brand); color: #fff; padding: .6rem 1rem; border-radius: 0 0 var(--r-sm) 0;
}
.skip:focus { left: 0; }
/* Buttons */
.btn {
font: inherit; font-weight: 600; cursor: pointer;
border: 1px solid transparent; border-radius: 999px;
padding: .62rem 1.15rem; transition: transform .15s, box-shadow .2s, background .2s;
}
.btn:active { transform: translateY(1px); }
.btn:focus-visible { outline: 3px solid color-mix(in srgb, var(--brand) 45%, transparent); outline-offset: 2px; }
.btn.lg { padding: .85rem 1.7rem; font-size: 1.05rem; }
.btn-donate { background: var(--accent); color: #fff; box-shadow: 0 4px 14px rgba(232, 116, 59, 0.4); }
.btn-donate:hover { background: var(--accent-d); transform: translateY(-2px); box-shadow: 0 8px 22px rgba(232, 116, 59, 0.46); }
.btn-ghost { background: var(--surface); color: var(--ink); border-color: var(--line-2); box-shadow: var(--sh-s); }
.btn-ghost:hover { border-color: var(--brand); color: var(--brand-d); transform: translateY(-2px); }
/* Topbar */
.topbar {
position: sticky; top: 0; z-index: 40;
background: color-mix(in srgb, var(--bg) 86%, transparent);
backdrop-filter: blur(10px);
border-bottom: 1px solid var(--line);
}
.topbar-in { display: flex; align-items: center; gap: 1.2rem; padding: .8rem 0; }
.brand { display: flex; align-items: center; gap: .55rem; font-weight: 700; }
.brand-mark { color: var(--brand); font-size: 1.5rem; line-height: 1; }
.brand-name { font-family: "Fraunces", serif; font-size: 1.15rem; }
.brand-name em { color: var(--brand-d); font-style: normal; font-weight: 600; }
.topnav { display: flex; gap: 1.3rem; margin-left: auto; }
.topnav a {
color: var(--ink-2); text-decoration: none; font-weight: 500; font-size: .95rem;
padding-bottom: 2px; border-bottom: 2px solid transparent; transition: color .2s, border-color .2s;
}
.topnav a:hover { color: var(--brand-d); border-color: var(--brand); }
/* Hero */
.hero {
display: grid; grid-template-columns: 1.05fr .95fr; gap: 2.6rem; align-items: center;
padding: 3.4rem 0 2.6rem;
}
.eyebrow {
display: inline-block; font-size: .78rem; font-weight: 700; letter-spacing: .09em;
text-transform: uppercase; color: var(--brand-d);
background: color-mix(in srgb, var(--brand) 12%, transparent);
padding: .3rem .7rem; border-radius: 999px; margin-bottom: 1rem;
}
.hero h1 { font-size: clamp(2.1rem, 4.6vw, 3.3rem); letter-spacing: -.02em; }
.hero h1 .hl { color: var(--brand); display: block; }
.lede { margin-top: 1.1rem; font-size: 1.12rem; color: var(--ink-2); max-width: 38ch; }
.hero-actions { display: flex; flex-wrap: wrap; gap: .8rem; margin-top: 1.7rem; }
.trust {
display: flex; flex-wrap: wrap; gap: .4rem 1.3rem; list-style: none; padding: 0;
margin: 1.6rem 0 0; font-size: .85rem; color: var(--muted); font-weight: 500;
}
/* Photo placeholders */
.photo {
position: relative; border-radius: var(--r-lg); overflow: hidden; margin: 0;
background: linear-gradient(135deg, var(--brand) 0%, var(--brand-d) 55%, #0f4a42 100%);
box-shadow: var(--sh-l);
}
.photo::after {
content: ""; position: absolute; inset: 0;
background: radial-gradient(circle at 28% 22%, rgba(255,255,255,.22), transparent 42%),
radial-gradient(circle at 80% 85%, rgba(232,116,59,.32), transparent 45%);
mix-blend-mode: screen;
}
.photo-cap {
position: absolute; left: 0; right: 0; bottom: 0; z-index: 2;
padding: 1.4rem 1.1rem .9rem; color: #fff; font-size: .85rem; font-weight: 500;
background: linear-gradient(to top, rgba(20,18,15,.72), transparent);
}
.hero-photo { aspect-ratio: 4 / 3.5; }
/* Sections */
.section { padding: 3.4rem 0; }
.sec-head { max-width: 52ch; margin-bottom: 2rem; }
.sec-head h2 { font-size: clamp(1.7rem, 3vw, 2.3rem); letter-spacing: -.015em; }
.sec-head p { margin-top: .55rem; color: var(--ink-2); }
/* Stats */
.stat-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1.1rem; }
.stat {
background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md);
padding: 1.5rem 1.3rem; box-shadow: var(--sh-s); transition: transform .2s, box-shadow .2s;
position: relative; overflow: hidden;
}
.stat::before {
content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 4px; background: var(--brand);
}
.stat:nth-child(2)::before { background: var(--accent); }
.stat:nth-child(3)::before { background: #5ba6c4; }
.stat:nth-child(4)::before { background: #c79a3b; }
.stat:hover { transform: translateY(-4px); box-shadow: var(--sh-m); }
.stat-num {
display: block; font-family: "Fraunces", serif; font-weight: 700;
font-size: clamp(2rem, 4vw, 2.7rem); color: var(--brand-d); letter-spacing: -.02em;
font-variant-numeric: tabular-nums;
}
.stat:nth-child(2) .stat-num { color: var(--accent-d); }
.stat-label { display: block; font-weight: 600; margin-top: .2rem; }
.stat-note { display: block; font-size: .82rem; color: var(--muted); margin-top: .3rem; }
/* Where money goes */
.money-grid { display: grid; grid-template-columns: 320px 1fr; gap: 2.6rem; align-items: center; }
.donut-wrap { margin: 0; display: flex; justify-content: center; }
.donut {
--gap: 0deg;
width: 280px; height: 280px; border-radius: 50%;
background: conic-gradient(
var(--brand) 0 136.8deg,
var(--accent) 136.8deg 234deg,
#5ba6c4 234deg 309.6deg,
#c79a3b 309.6deg 334.8deg,
#9b8f7e 334.8deg 349.2deg,
#cdbfa9 349.2deg 360deg
);
position: relative; box-shadow: var(--sh-m);
transition: filter .2s;
}
.donut::after {
content: ""; position: absolute; inset: 26%; background: var(--surface); border-radius: 50%;
box-shadow: inset 0 1px 4px rgba(0,0,0,.06);
}
.donut-center {
position: absolute; inset: 0; display: flex; flex-direction: column;
align-items: center; justify-content: center; z-index: 2; pointer-events: none;
text-align: center;
}
.donut-pct { font-family: "Fraunces", serif; font-weight: 700; font-size: 2.1rem; color: var(--ink); transition: color .2s; }
.donut-cap { font-size: .82rem; color: var(--muted); max-width: 11ch; }
.legend { list-style: none; margin: 0; padding: 0; display: grid; gap: .35rem; }
.legend li {
display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: .75rem;
padding: .7rem .9rem; border-radius: var(--r-sm); border: 1px solid transparent;
cursor: pointer; transition: background .15s, border-color .15s, transform .15s;
}
.legend li:hover, .legend li.active {
background: var(--surface); border-color: var(--line-2); transform: translateX(3px); box-shadow: var(--sh-s);
}
.dot { width: 14px; height: 14px; border-radius: 4px; background: var(--c); }
.lg-name { font-weight: 500; }
.lg-val { font-weight: 700; color: var(--ink-2); font-variant-numeric: tabular-nums; }
/* Programs */
.program {
display: grid; grid-template-columns: 1fr 1.15fr; gap: 2.4rem; align-items: center;
padding: 2rem 0; border-top: 1px solid var(--line);
opacity: 0; transform: translateY(24px); transition: opacity .6s ease, transform .6s ease;
}
.program.in { opacity: 1; transform: none; }
.program.flip .prog-photo { order: 2; }
.prog-photo { aspect-ratio: 4 / 3.2; }
.p-water { background: linear-gradient(135deg, #2f9e8f, #155e54); }
.p-food { background: linear-gradient(135deg, var(--accent), var(--accent-d) 70%, #8a3d18); }
.p-edu { background: linear-gradient(135deg, #5ba6c4, #2c6f8c); }
.prog-tag {
display: inline-block; font-size: .74rem; font-weight: 700; letter-spacing: .07em;
text-transform: uppercase; color: var(--brand-d);
background: color-mix(in srgb, var(--brand) 13%, transparent); padding: .28rem .7rem;
border-radius: 999px; margin-bottom: .7rem;
}
.prog-tag.tag-accent { color: var(--accent-d); background: color-mix(in srgb, var(--accent) 16%, transparent); }
.prog-tag.tag-blue { color: #2c6f8c; background: rgba(91,166,196,.18); }
.prog-body h3 { font-size: 1.55rem; letter-spacing: -.01em; }
.prog-body p { margin-top: .6rem; color: var(--ink-2); }
/* Thermometer */
.thermo { margin: 1.2rem 0; }
.thermo-bar {
height: 12px; border-radius: 999px; background: var(--line);
overflow: hidden;
}
.thermo-fill {
display: block; height: 100%; width: 0; border-radius: 999px;
background: linear-gradient(90deg, var(--brand), #34b29c);
transition: width 1.1s cubic-bezier(.2,.7,.2,1);
}
.thermo-meta { font-size: .85rem; color: var(--muted); margin-top: .45rem; }
.thermo-meta strong { color: var(--ink); }
.thermo-pct { font-weight: 700; color: var(--brand-d); }
.quote {
margin: 1.2rem 0 0; padding: 1rem 1.2rem; border-left: 3px solid var(--accent);
background: var(--surface); border-radius: 0 var(--r-md) var(--r-md) 0;
font-family: "Fraunces", serif; font-size: 1.06rem; color: var(--ink); box-shadow: var(--sh-s);
}
.quote cite { display: block; margin-top: .6rem; font-family: "Inter", sans-serif; font-style: normal;
font-size: .85rem; font-weight: 600; color: var(--muted); }
/* Finance */
.finance { background: linear-gradient(180deg, color-mix(in srgb, var(--brand) 5%, var(--bg)), var(--bg)); }
.fin-grid { display: grid; grid-template-columns: 1.4fr 1fr; gap: 2rem; align-items: start; }
.fin-table {
width: 100%; border-collapse: collapse; background: var(--surface);
border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden; box-shadow: var(--sh-s);
}
.fin-table th, .fin-table td { text-align: left; padding: .85rem 1.1rem; font-variant-numeric: tabular-nums; }
.fin-table thead th { background: color-mix(in srgb, var(--brand) 9%, var(--surface)); font-size: .8rem;
text-transform: uppercase; letter-spacing: .05em; color: var(--ink-2); }
.fin-table tbody tr { border-top: 1px solid var(--line); }
.fin-table tbody th { font-weight: 500; }
.fin-table td { font-weight: 600; }
.fin-table td.muted { color: var(--muted); font-weight: 500; }
.fin-total th, .fin-total td { background: color-mix(in srgb, var(--accent) 10%, var(--surface)); }
.fin-total td:not(.muted) { color: var(--accent-d); }
.fin-cards { display: grid; gap: 1rem; }
.fin-card {
background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md);
padding: 1.2rem 1.3rem; box-shadow: var(--sh-s);
}
.fin-card.accent { background: var(--brand); border-color: var(--brand); color: #fff; }
.fin-k { display: block; font-family: "Fraunces", serif; font-weight: 700; font-size: 1.9rem; }
.fin-l { display: block; font-size: .88rem; color: var(--muted); margin-top: .15rem; }
.fin-card.accent .fin-l { color: rgba(255,255,255,.82); }
/* Donors */
.donor-list {
list-style: none; padding: 0; margin: 0; display: flex; flex-wrap: wrap; gap: .7rem;
}
.donor-list li {
background: var(--surface); border: 1px solid var(--line); border-radius: 999px;
padding: .5rem 1.1rem; font-weight: 500; font-size: .95rem; box-shadow: var(--sh-s);
transition: transform .15s, border-color .15s;
}
.donor-list li:hover { transform: translateY(-2px); border-color: var(--accent); }
/* CTA */
.cta { padding-bottom: 3.6rem; }
.cta-card {
background: linear-gradient(135deg, var(--brand-d), var(--brand) 55%, #1d8a78);
color: #fff; border-radius: var(--r-lg); padding: 3rem 2.4rem; text-align: center;
box-shadow: var(--sh-l); position: relative; overflow: hidden;
}
.cta-card::after {
content: ""; position: absolute; inset: 0;
background: radial-gradient(circle at 85% 15%, rgba(232,116,59,.3), transparent 45%);
}
.cta-card h2 { color: #fff; font-size: clamp(1.7rem, 3.2vw, 2.4rem); position: relative; }
.cta-card p { margin-top: .6rem; color: rgba(255,255,255,.88); position: relative; max-width: 44ch; margin-inline: auto; }
.cta-actions { display: flex; flex-wrap: wrap; gap: .9rem; justify-content: center; margin-top: 1.7rem; position: relative; }
.cta .btn-ghost { background: rgba(255,255,255,.12); color: #fff; border-color: rgba(255,255,255,.4); }
.cta .btn-ghost:hover { background: rgba(255,255,255,.2); color: #fff; }
/* Footer */
.footer { background: var(--ink); color: rgba(255,255,255,.72); padding: 2rem 0; }
.footer-in { display: flex; flex-direction: column; gap: .3rem; font-size: .88rem; }
.fineprint { color: rgba(255,255,255,.45); font-size: .8rem; }
/* Toast */
.toast {
position: fixed; left: 50%; bottom: 1.6rem; transform: translate(-50%, 140%);
background: var(--ink); color: #fff; padding: .8rem 1.3rem; border-radius: 999px;
font-weight: 500; font-size: .92rem; box-shadow: var(--sh-l); z-index: 90;
transition: transform .35s cubic-bezier(.2,.8,.2,1); max-width: calc(100% - 2rem); text-align: center;
}
.toast.show { transform: translate(-50%, 0); }
/* Responsive */
@media (max-width: 900px) {
.hero { grid-template-columns: 1fr; gap: 1.8rem; }
.money-grid { grid-template-columns: 1fr; gap: 1.8rem; justify-items: center; }
.legend { width: 100%; }
.program, .program.flip { grid-template-columns: 1fr; gap: 1.3rem; }
.program.flip .prog-photo { order: 0; }
.fin-grid { grid-template-columns: 1fr; }
.stat-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 520px) {
.wrap { width: 100% - 2rem; width: calc(100% - 2rem); }
.topnav { display: none; }
.topbar-in { gap: .6rem; }
.stat-grid { grid-template-columns: 1fr 1fr; gap: .7rem; }
.stat { padding: 1.1rem 1rem; }
.donut { width: 230px; height: 230px; }
.hero-actions .btn, .cta-actions .btn { flex: 1 1 auto; }
.trust { gap: .3rem .9rem; }
}
@media (prefers-reduced-motion: reduce) {
* { animation-duration: .001ms !important; transition-duration: .001ms !important; scroll-behavior: auto; }
.program { opacity: 1; transform: none; }
}(function () {
"use strict";
/* ---- Toast helper ---- */
var toastEl = document.getElementById("toast");
var toastTimer;
function toast(msg) {
if (!toastEl) return;
toastEl.textContent = msg;
toastEl.classList.add("show");
clearTimeout(toastTimer);
toastTimer = setTimeout(function () {
toastEl.classList.remove("show");
}, 2600);
}
var reduceMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
/* ---- Animated count-up stats ---- */
function formatNum(n, suffix) {
var rounded = Math.round(n);
var out;
if (rounded >= 1000) {
out = rounded.toLocaleString("en-US");
} else {
out = String(rounded);
}
return out + (suffix || "");
}
function animateStat(el) {
var numEl = el.querySelector(".stat-num");
var target = parseFloat(el.getAttribute("data-target")) || 0;
var suffix = el.getAttribute("data-suffix") || "";
if (reduceMotion) {
numEl.textContent = formatNum(target, suffix);
return;
}
var dur = 1500;
var start = performance.now();
function tick(now) {
var p = Math.min((now - start) / dur, 1);
// easeOutCubic
var eased = 1 - Math.pow(1 - p, 3);
numEl.textContent = formatNum(target * eased, suffix);
if (p < 1) requestAnimationFrame(tick);
else numEl.textContent = formatNum(target, suffix);
}
requestAnimationFrame(tick);
}
var statsRun = false;
var statGrid = document.getElementById("statGrid");
if (statGrid && "IntersectionObserver" in window) {
var statObs = new IntersectionObserver(function (entries) {
entries.forEach(function (e) {
if (e.isIntersecting && !statsRun) {
statsRun = true;
statGrid.querySelectorAll(".stat").forEach(animateStat);
statObs.disconnect();
}
});
}, { threshold: 0.4 });
statObs.observe(statGrid);
} else if (statGrid) {
statGrid.querySelectorAll(".stat").forEach(animateStat);
}
/* ---- Section reveal for program blocks ---- */
var reveals = document.querySelectorAll(".reveal");
if ("IntersectionObserver" in window && !reduceMotion) {
var revObs = new IntersectionObserver(function (entries) {
entries.forEach(function (e) {
if (e.isIntersecting) {
e.target.classList.add("in");
revObs.unobserve(e.target);
}
});
}, { threshold: 0.18 });
reveals.forEach(function (r) { revObs.observe(r); });
} else {
reveals.forEach(function (r) { r.classList.add("in"); });
}
/* ---- Thermometer fill when in view ---- */
var thermos = document.querySelectorAll(".thermo");
function fillThermo(t) {
var pct = Math.max(0, Math.min(100, parseFloat(t.getAttribute("data-pct")) || 0));
var fill = t.querySelector(".thermo-fill");
if (fill) fill.style.width = pct + "%";
}
if ("IntersectionObserver" in window) {
var tObs = new IntersectionObserver(function (entries) {
entries.forEach(function (e) {
if (e.isIntersecting) {
fillThermo(e.target);
tObs.unobserve(e.target);
}
});
}, { threshold: 0.5 });
thermos.forEach(function (t) { tObs.observe(t); });
} else {
thermos.forEach(fillThermo);
}
/* ---- Donut + legend hover linkage ---- */
var donut = document.getElementById("donut");
var donutPct = document.getElementById("donutPct");
var donutCap = document.getElementById("donutCap");
var legend = document.getElementById("legend");
// [color, startDeg, endDeg, pct, label]
var slices = [
["var(--brand)", 0, 136.8, "38%", "Clean water programs"],
["var(--accent)", 136.8, 234, "27%", "Food & nutrition"],
["#5ba6c4", 234, 309.6, "21%", "Education & schools"],
["#c79a3b", 309.6, 334.8, "7%", "Healthcare outreach"],
["#9b8f7e", 334.8, 349.2, "4%", "Administration"],
["#cdbfa9", 349.2, 360, "3%", "Fundraising"]
];
var baseGradient = donut ? getComputedStyle(donut).background : "";
function highlightSlice(i) {
if (!donut) return;
var stops = slices.map(function (s, idx) {
var col = s[0];
// dim non-selected slices
if (i !== null && idx !== i) {
col = "color-mix(in srgb, " + s[0] + " 32%, var(--bg))";
}
return col + " " + s[1] + "deg " + s[2] + "deg";
});
donut.style.background = "conic-gradient(" + stops.join(", ") + ")";
if (i === null) {
donutPct.textContent = "100%";
donutCap.textContent = "Total raised";
donutPct.style.color = "";
} else {
donutPct.textContent = slices[i][3];
donutCap.textContent = slices[i][4];
donutPct.style.color = slices[i][0];
donut.style.filter = "saturate(1.05)";
}
}
function clearHighlight() {
if (!donut) return;
donut.style.background = "";
donut.style.filter = "";
highlightSlice(null);
legend.querySelectorAll("li").forEach(function (li) { li.classList.remove("active"); });
}
if (legend && donut) {
legend.querySelectorAll("li").forEach(function (li) {
var idx = parseInt(li.getAttribute("data-slice"), 10);
function activate() {
legend.querySelectorAll("li").forEach(function (x) { x.classList.remove("active"); });
li.classList.add("active");
highlightSlice(idx);
}
li.addEventListener("mouseenter", activate);
li.addEventListener("mouseleave", clearHighlight);
li.addEventListener("focus", activate);
li.addEventListener("blur", clearHighlight);
// keyboard / tap toggle
li.setAttribute("tabindex", "0");
li.setAttribute("role", "button");
li.addEventListener("click", function () {
if (li.classList.contains("active")) clearHighlight();
else activate();
});
li.addEventListener("keydown", function (ev) {
if (ev.key === "Enter" || ev.key === " ") {
ev.preventDefault();
li.click();
}
});
});
}
/* ---- Buttons ---- */
function bind(id, msg) {
var el = document.getElementById(id);
if (el) el.addEventListener("click", function () { toast(msg); });
}
bind("donateTop", "💛 Demo only — no real donation processed. Thank you!");
bind("donateHero", "💛 Demo only — no real donation processed. Thank you!");
bind("donateCta", "💛 Monthly giving is a demo here — but the gratitude is real!");
bind("downloadBtn", "📄 Generating 2025 Impact Report PDF… (demo)");
var shareBtn = document.getElementById("shareBtn");
if (shareBtn) {
shareBtn.addEventListener("click", function () {
var data = {
title: "Brightwell Foundation — 2025 Impact Report",
text: "See the impact: 318,420 meals served, 74 wells built, 9,260 children in school.",
url: location.href
};
if (navigator.share) {
navigator.share(data).catch(function () {});
} else if (navigator.clipboard) {
navigator.clipboard.writeText(location.href).then(function () {
toast("🔗 Link copied to clipboard");
}).catch(function () { toast("Share this report with a friend!"); });
} else {
toast("Share this report with a friend!");
}
});
}
})();<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Brightwell Foundation — 2025 Impact Report</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=Fraunces:opsz,wght@9..144,500;9..144,600;9..144,700&family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="style.css" />
</head>
<body>
<a class="skip" href="#main">Skip to content</a>
<header class="topbar">
<div class="wrap topbar-in">
<div class="brand">
<span class="brand-mark" aria-hidden="true">◑</span>
<span class="brand-name">Brightwell <em>Foundation</em></span>
</div>
<nav class="topnav" aria-label="Report sections">
<a href="#stats">Impact</a>
<a href="#money">Funds</a>
<a href="#programs">Programs</a>
<a href="#finance">Finances</a>
</nav>
<button class="btn btn-donate" id="donateTop">Donate</button>
</div>
</header>
<main id="main">
<!-- HERO -->
<section class="hero wrap">
<div class="hero-copy">
<span class="eyebrow">2025 Annual Impact Report</span>
<h1>Every gift, accounted for. <span class="hl">Every life, lifted.</span></h1>
<p class="lede">
This year, generous donors like you helped Brightwell Foundation reach
more communities than ever before. Here is exactly what your support made possible —
measured, audited, and shared in full transparency.
</p>
<div class="hero-actions">
<button class="btn btn-donate" id="donateHero">Donate now</button>
<button class="btn btn-ghost" id="downloadBtn">⬇ Download full report (PDF)</button>
</div>
<ul class="trust" aria-label="Trust badges">
<li>✓ Registered Charity #BR-44821</li>
<li>✓ Tax-deductible</li>
<li>✓ Independently audited</li>
</ul>
</div>
<figure class="hero-photo photo" data-caption="Clean-water team in Mwanza district, 2025">
<span class="photo-cap">Clean-water team in Mwanza district, 2025</span>
</figure>
</section>
<!-- STATS -->
<section id="stats" class="section wrap">
<div class="sec-head">
<h2>The year in numbers</h2>
<p>A snapshot of measurable change, verified across all field programs.</p>
</div>
<div class="stat-grid" id="statGrid">
<article class="stat" data-target="318420" data-prefix="" data-suffix="">
<span class="stat-num">0</span>
<span class="stat-label">Meals served</span>
<span class="stat-note">+22% vs 2024</span>
</article>
<article class="stat" data-target="74" data-prefix="" data-suffix="">
<span class="stat-num">0</span>
<span class="stat-label">Wells built</span>
<span class="stat-note">clean water for 41,000 people</span>
</article>
<article class="stat" data-target="9260" data-prefix="" data-suffix="">
<span class="stat-num">0</span>
<span class="stat-label">Children in school</span>
<span class="stat-note">across 38 villages</span>
</article>
<article class="stat" data-target="93" data-prefix="" data-suffix="¢">
<span class="stat-num">0</span>
<span class="stat-label">Per $1 to programs</span>
<span class="stat-note">only 7¢ on overhead</span>
</article>
</div>
</section>
<!-- WHERE MONEY GOES -->
<section id="money" class="section wrap money">
<div class="sec-head">
<h2>Where your money goes</h2>
<p>Hover or tap a slice to see how every dollar was allocated.</p>
</div>
<div class="money-grid">
<figure class="donut-wrap" aria-hidden="true">
<div class="donut" id="donut">
<div class="donut-center">
<span class="donut-pct" id="donutPct">100%</span>
<span class="donut-cap" id="donutCap">Total raised</span>
</div>
</div>
</figure>
<ul class="legend" id="legend" aria-label="Fund allocation breakdown">
<li data-slice="0"><span class="dot" style="--c:var(--brand)"></span><span class="lg-name">Clean water programs</span><span class="lg-val">38%</span></li>
<li data-slice="1"><span class="dot" style="--c:var(--accent)"></span><span class="lg-name">Food & nutrition</span><span class="lg-val">27%</span></li>
<li data-slice="2"><span class="dot" style="--c:#5ba6c4"></span><span class="lg-name">Education & schools</span><span class="lg-val">21%</span></li>
<li data-slice="3"><span class="dot" style="--c:#c79a3b"></span><span class="lg-name">Healthcare outreach</span><span class="lg-val">7%</span></li>
<li data-slice="4"><span class="dot" style="--c:#9b8f7e"></span><span class="lg-name">Administration</span><span class="lg-val">4%</span></li>
<li data-slice="5"><span class="dot" style="--c:#cdbfa9"></span><span class="lg-name">Fundraising</span><span class="lg-val">3%</span></li>
</ul>
</div>
</section>
<!-- PROGRAM OUTCOMES -->
<section id="programs" class="section wrap">
<div class="sec-head">
<h2>Program outcomes</h2>
<p>Three flagship programs, the people behind them, and the results we promised to deliver.</p>
</div>
<article class="program reveal">
<figure class="photo prog-photo p-water" data-caption="A new community well in Mwanza">
<span class="photo-cap">A new community well in Mwanza</span>
</figure>
<div class="prog-body">
<span class="prog-tag">Clean Water</span>
<h3>Wells that never run dry</h3>
<p>We completed 74 solar-pumped wells this year, cutting the average water-fetching
walk from 4 hours to under 15 minutes and freeing girls to return to school.</p>
<div class="thermo" data-pct="92" aria-label="92 percent of goal reached">
<div class="thermo-bar"><span class="thermo-fill"></span></div>
<div class="thermo-meta"><strong>74</strong> of 80 wells goal · <span class="thermo-pct">92%</span></div>
</div>
<blockquote class="quote">
“Before, I missed class to carry water. Now the well is in our village — I have not
missed a day of school in months.”
<cite>— Amara, age 12, Mwanza district</cite>
</blockquote>
</div>
</article>
<article class="program reveal flip">
<figure class="photo prog-photo p-food" data-caption="Community kitchen, harvest season">
<span class="photo-cap">Community kitchen, harvest season</span>
</figure>
<div class="prog-body">
<span class="prog-tag tag-accent">Food & Nutrition</span>
<h3>318,420 warm meals</h3>
<p>Our network of 26 community kitchens served hot, nutritious meals through the
lean season, while seed grants helped 1,140 families grow their own food.</p>
<div class="thermo" data-pct="78" aria-label="78 percent of goal reached">
<div class="thermo-bar"><span class="thermo-fill"></span></div>
<div class="thermo-meta"><strong>318k</strong> of 410k meals goal · <span class="thermo-pct">78%</span></div>
</div>
<blockquote class="quote">
“The seed grant changed everything. This is the first year we grew enough to feed our
children and still had a little to sell.”
<cite>— Joseph & Ruth Okonkwo, smallholder farmers</cite>
</blockquote>
</div>
</article>
<article class="program reveal">
<figure class="photo prog-photo p-edu" data-caption="Reading hour at Brightwell School #3">
<span class="photo-cap">Reading hour at Brightwell School #3</span>
</figure>
<div class="prog-body">
<span class="prog-tag tag-blue">Education</span>
<h3>9,260 children, learning</h3>
<p>Scholarships, school meals and twelve new classrooms kept 9,260 children enrolled —
and 88% advanced to the next grade, our highest retention on record.</p>
<div class="thermo" data-pct="88" aria-label="88 percent of goal reached">
<div class="thermo-bar"><span class="thermo-fill"></span></div>
<div class="thermo-meta"><strong>88%</strong> grade retention · <span class="thermo-pct">88%</span></div>
</div>
<blockquote class="quote">
“Our daughter is the first in our family to read. The teachers say she dreams of
becoming a nurse.”
<cite>— Fatima Bello, parent & volunteer</cite>
</blockquote>
</div>
</article>
</section>
<!-- FINANCIAL TRANSPARENCY -->
<section id="finance" class="section wrap finance">
<div class="sec-head">
<h2>Financial transparency</h2>
<p>Full-year figures, independently audited by Hartley & Crane LLP.</p>
</div>
<div class="fin-grid">
<table class="fin-table">
<caption class="sr-only">Income and expenses for fiscal year 2025</caption>
<thead>
<tr><th scope="col">Line item</th><th scope="col">2025</th><th scope="col">2024</th></tr>
</thead>
<tbody>
<tr><th scope="row">Total income</th><td>$4,812,000</td><td class="muted">$3,944,000</td></tr>
<tr><th scope="row">Program spending</th><td>$4,475,000</td><td class="muted">$3,610,000</td></tr>
<tr><th scope="row">Administration</th><td>$192,000</td><td class="muted">$201,000</td></tr>
<tr><th scope="row">Fundraising</th><td>$145,000</td><td class="muted">$133,000</td></tr>
<tr class="fin-total"><th scope="row">To programs</th><td>93¢ / $1</td><td class="muted">91¢ / $1</td></tr>
</tbody>
</table>
<aside class="fin-cards">
<div class="fin-card">
<span class="fin-k">$4.81M</span><span class="fin-l">Raised in 2025</span>
</div>
<div class="fin-card">
<span class="fin-k">12,940</span><span class="fin-l">Individual donors</span>
</div>
<div class="fin-card accent">
<span class="fin-k">93¢</span><span class="fin-l">Of every $1 to the field</span>
</div>
</aside>
</div>
</section>
<!-- DONORS -->
<section class="section wrap donors">
<div class="sec-head">
<h2>With gratitude</h2>
<p>A few of the people and partners who made this year possible.</p>
</div>
<ul class="donor-list">
<li>The Marlowe Family Trust</li>
<li>Cedar & Vine Co.</li>
<li>Anonymous (×314)</li>
<li>Greenfield Rotary Club</li>
<li>Dr. Priya Nair</li>
<li>Lakeside School PTA</li>
<li>The Okafor Foundation</li>
<li>… and 12,938 more</li>
</ul>
</section>
<!-- CTA -->
<section class="cta wrap">
<div class="cta-card">
<h2>Help us do even more in 2026</h2>
<p>Your monthly gift means a child eats, a well is built, a classroom opens. Join us.</p>
<div class="cta-actions">
<button class="btn btn-donate lg" id="donateCta">Give monthly</button>
<button class="btn btn-ghost lg" id="shareBtn">Share this report</button>
</div>
</div>
</section>
</main>
<footer class="footer">
<div class="wrap footer-in">
<p>Brightwell Foundation · Registered Charity #BR-44821 · Audited by Hartley & Crane LLP</p>
<p class="fineprint">Illustrative demo — fictional organization. No real donations are processed.</p>
</div>
</footer>
<div class="toast" id="toast" role="status" aria-live="polite"></div>
<script src="script.js"></script>
</body>
</html>Impact Report
A complete annual impact report for the fictional Brightwell Foundation, designed to read as warm, human and trustworthy. It opens with a hero and a prominent donate CTA, then a grid of headline impact statistics — meals served, wells built, children in school — that count up with an eased animation the first time they scroll into view. Trust badges (registered charity, tax-deductible, independently audited) reinforce credibility.
The “where your money goes” section pairs a CSS conic-gradient donut with an interactive
legend: hovering, tapping or keyboard-focusing a line item dims the other slices, recolors the
center label and surfaces that category’s percentage. Program outcome blocks reveal on scroll
with warm-gradient photo placeholders, beneficiary quotes and progress thermometers that fill
toward each goal. A financial-transparency table, donor recognition chips, and download and
share buttons (using the Web Share API with a clipboard fallback) round it out, all driven by a
tiny toast() helper.
Everything is self-contained vanilla HTML, CSS and JavaScript — no frameworks or build step.
It is responsive down to ~360px, respects prefers-reduced-motion, and uses semantic markup
with ARIA labels and keyboard-operable controls.
Illustrative UI only — fictional organization, not a real charity or donation system.