Nonprofit — Environmental Landing
A complete environmental climate nonprofit landing page for a fictional reforestation charity. It pairs a full-bleed nature hero with count-up cause stats, four restoration program cards, an interactive impact-map teaser with clickable site pins, a petition pledge with an animated signature thermometer, a transparency breakdown with allocation bars and trust badges, partners, and a frequency-aware donate widget that translates dollars into trees. Forest green, ocean blue and earth tones; scroll reveals; fully responsive vanilla JS.
MCP
Code
:root {
/* Environmental palette — forest green + ocean blue + earth tones */
--brand: #1c6b4a; /* forest green */
--brand-d: #134e36;
--ocean: #0e6b8e; /* ocean blue */
--ocean-d: #0a4f6b;
--accent: #e07a2e; /* earth/urgent amber */
--accent-d: #c5631c;
--earth: #9a6b3f; /* warm earth */
--leaf: #5fae6b;
--ink: #16241c;
--ink-2: #3c4a40;
--muted: #6c7a6f;
--bg: #f4f7f1; /* misty green-white */
--bg-2: #eaf1e7;
--surface: #ffffff;
--line: rgba(22, 36, 28, 0.10);
--line-2: rgba(22, 36, 28, 0.18);
--ok: #2f9e6f;
--warn: #d98a2b;
--danger: #d4503e;
--r-sm: 8px;
--r-md: 14px;
--r-lg: 22px;
--sh-sm: 0 2px 8px rgba(19, 78, 54, 0.08);
--sh-md: 0 14px 36px rgba(19, 78, 54, 0.12);
--sh-lg: 0 28px 70px rgba(10, 60, 50, 0.20);
--maxw: 1160px;
--font-head: "Space Grotesk", system-ui, -apple-system, sans-serif;
--font-body: "Inter", system-ui, -apple-system, sans-serif;
}
* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
margin: 0;
font-family: var(--font-body);
color: var(--ink);
background: var(--bg);
line-height: 1.6;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
img { max-width: 100%; display: block; }
h1, h2, h3, h4 { font-family: var(--font-head); line-height: 1.12; margin: 0; letter-spacing: -0.02em; }
p { margin: 0; }
a { color: inherit; text-decoration: none; }
.wrap { width: 100%; max-width: var(--maxw); margin: 0 auto; padding: 0 22px; }
.skip {
position: absolute; left: -999px; top: 0; z-index: 200;
background: var(--brand); color: #fff; padding: 10px 16px; border-radius: 0 0 var(--r-sm) 0;
}
.skip:focus { left: 0; }
/* ---------- Buttons ---------- */
.btn {
display: inline-flex; align-items: center; justify-content: center; gap: 8px;
font-family: var(--font-head); font-weight: 600; font-size: 0.95rem;
padding: 11px 20px; border-radius: 999px; border: 1.5px solid transparent;
cursor: pointer; transition: transform .15s ease, box-shadow .2s ease, background .2s ease, color .2s ease;
white-space: nowrap;
}
.btn:active { transform: translateY(1px) scale(0.99); }
.btn-lg { padding: 14px 26px; font-size: 1.02rem; }
.btn-block { width: 100%; }
.btn-accent { background: var(--accent); color: #fff; box-shadow: 0 8px 20px rgba(224,122,46,0.32); }
.btn-accent:hover { background: var(--accent-d); transform: translateY(-2px); box-shadow: 0 12px 26px rgba(224,122,46,0.4); }
.btn-brand { background: var(--brand); color: #fff; }
.btn-brand:hover { background: var(--brand-d); }
.btn-ghost { background: transparent; color: var(--ink); }
.btn-ghost:hover { background: var(--bg-2); }
.btn-outline { background: rgba(255,255,255,0.85); color: var(--brand-d); border-color: var(--line-2); }
.btn-outline:hover { background: #fff; border-color: var(--brand); transform: translateY(-2px); }
/* ---------- Nav ---------- */
.nav {
position: sticky; top: 0; z-index: 100;
background: rgba(244,247,241,0.82);
backdrop-filter: saturate(150%) blur(12px);
border-bottom: 1px solid transparent;
transition: border-color .25s ease, box-shadow .25s ease, background .25s ease;
}
.nav.scrolled { border-bottom-color: var(--line); box-shadow: var(--sh-sm); background: rgba(244,247,241,0.94); }
.nav-inner { display: flex; align-items: center; gap: 18px; height: 68px; }
.brand { display: inline-flex; align-items: center; gap: 9px; font-family: var(--font-head); font-weight: 700; }
.brand-mark { display: grid; place-items: center; width: 34px; height: 34px; border-radius: 10px; background: linear-gradient(135deg, var(--brand), var(--ocean)); color: #fff; }
.brand-name { font-size: 1.2rem; color: var(--ink); }
.brand-name span { color: var(--brand); }
.brand-name.big { font-size: 1.5rem; color: #eaf6ec; }
.brand-name.big span { color: var(--leaf); }
.nav-links { display: flex; gap: 4px; margin-left: 14px; }
.nav-links a { padding: 8px 13px; border-radius: 999px; font-weight: 500; font-size: 0.94rem; color: var(--ink-2); transition: background .2s, color .2s; }
.nav-links a:hover { background: var(--bg-2); color: var(--brand-d); }
.nav-cta { display: flex; gap: 8px; margin-left: auto; }
.nav-toggle { display: none; margin-left: auto; background: none; border: 0; cursor: pointer; padding: 8px; flex-direction: column; gap: 5px; }
.nav-toggle span { display: block; width: 24px; height: 2px; background: var(--ink); border-radius: 2px; transition: transform .25s, opacity .2s; }
.nav-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }
/* ---------- Hero ---------- */
.hero { position: relative; overflow: hidden; padding-bottom: 40px; }
.hero-photo {
position: absolute; inset: 0; z-index: 0;
background:
radial-gradient(70% 90% at 80% 10%, rgba(95,174,107,0.35), transparent 60%),
linear-gradient(160deg, #1c6b4a 0%, #0e6b8e 55%, #134e36 100%);
}
.hero-grad {
position: absolute; inset: 0;
background:
radial-gradient(40% 60% at 20% 80%, rgba(224,122,46,0.22), transparent 65%),
linear-gradient(to bottom, rgba(244,247,241,0) 55%, rgba(244,247,241,0.96) 100%);
}
.photo-cap {
position: absolute; left: 22px; bottom: 24px; z-index: 1;
font-size: 0.74rem; color: rgba(255,255,255,0.78); letter-spacing: 0.01em;
background: rgba(10,60,50,0.35); padding: 5px 10px; border-radius: 999px; backdrop-filter: blur(4px);
}
.hero-inner { position: relative; z-index: 2; padding: 78px 22px 30px; max-width: 820px; }
.eyebrow {
display: inline-flex; align-items: center; gap: 8px;
background: rgba(255,255,255,0.16); color: #fff; border: 1px solid rgba(255,255,255,0.28);
padding: 6px 14px; border-radius: 999px; font-size: 0.82rem; font-weight: 600; backdrop-filter: blur(6px);
}
.pulse { width: 8px; height: 8px; border-radius: 50%; background: var(--accent); box-shadow: 0 0 0 0 rgba(224,122,46,0.7); animation: pulse 1.8s infinite; }
@keyframes pulse { 0% { box-shadow: 0 0 0 0 rgba(224,122,46,0.6); } 70% { box-shadow: 0 0 0 10px rgba(224,122,46,0); } 100% { box-shadow: 0 0 0 0 rgba(224,122,46,0); } }
.hero h1 { color: #fff; font-size: clamp(2.3rem, 6vw, 4rem); font-weight: 700; margin: 18px 0 0; text-shadow: 0 2px 30px rgba(10,40,30,0.3); }
.hero h1 em { font-style: normal; color: var(--accent); }
.hero .lead { color: rgba(255,255,255,0.92); font-size: clamp(1.02rem, 2vw, 1.2rem); max-width: 600px; margin-top: 18px; }
.hero-actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 26px; }
.hero-stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; margin-top: 44px; }
.hstat {
background: rgba(255,255,255,0.92); border: 1px solid rgba(255,255,255,0.6);
border-radius: var(--r-md); padding: 16px 14px; box-shadow: var(--sh-sm); backdrop-filter: blur(6px);
}
.hstat strong { display: block; font-family: var(--font-head); font-size: clamp(1.4rem, 3vw, 2rem); font-weight: 700; color: var(--brand-d); }
.hstat span { font-size: 0.82rem; color: var(--ink-2); }
/* ---------- Sections / bands ---------- */
.band { padding: 84px 0; }
.band-soft { background: var(--bg-2); }
.section-head { max-width: 680px; margin: 0 auto 46px; text-align: center; }
.kicker { display: inline-block; font-family: var(--font-head); font-weight: 600; font-size: 0.78rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--brand); margin-bottom: 12px; }
.kicker.light { color: var(--leaf); }
.section-head h2 { font-size: clamp(1.7rem, 4vw, 2.6rem); color: var(--ink); }
.section-head p { color: var(--ink-2); margin-top: 14px; font-size: 1.04rem; }
/* ---------- Impact grid ---------- */
.impact-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 18px; }
.impact-card {
background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg);
padding: 26px 22px; box-shadow: var(--sh-sm); transition: transform .25s ease, box-shadow .25s ease, border-color .25s;
}
.impact-card:hover { transform: translateY(-6px); box-shadow: var(--sh-md); border-color: rgba(95,174,107,0.5); }
.impact-ico { font-size: 1.9rem; display: inline-block; margin-bottom: 10px; }
.impact-card h3 { font-size: 1.25rem; color: var(--brand-d); }
.impact-card p { color: var(--ink-2); margin-top: 8px; font-size: 0.95rem; }
/* ---------- Programs ---------- */
.program-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 20px; }
.program {
background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg);
overflow: hidden; box-shadow: var(--sh-sm); display: flex; flex-direction: column;
transition: transform .25s ease, box-shadow .25s ease;
}
.program:hover { transform: translateY(-6px); box-shadow: var(--sh-md); }
.program-photo { position: relative; aspect-ratio: 4 / 3; }
.p-forest { background: linear-gradient(150deg, #2a8a5c, #134e36); }
.p-ocean { background: linear-gradient(150deg, #1488ad, #0a4f6b); }
.p-earth { background: linear-gradient(150deg, #b07a3e, #6e4a24); }
.p-sky { background: linear-gradient(150deg, #3fa3a0, #1c6b4a); }
.program-photo .tag {
position: absolute; left: 12px; top: 12px;
background: rgba(255,255,255,0.92); color: var(--ink); font-weight: 600;
font-size: 0.74rem; padding: 5px 11px; border-radius: 999px;
}
.program-body { padding: 18px 18px 20px; display: flex; flex-direction: column; flex: 1; }
.program-body h3 { font-size: 1.2rem; color: var(--ink); }
.program-body > p { color: var(--ink-2); margin-top: 7px; font-size: 0.93rem; }
.dotted { list-style: none; padding: 0; margin: 14px 0 16px; display: grid; gap: 6px; }
.dotted li { position: relative; padding-left: 18px; font-size: 0.88rem; color: var(--ink-2); }
.dotted li::before { content: ""; position: absolute; left: 0; top: 8px; width: 7px; height: 7px; border-radius: 50%; background: var(--leaf); }
.link-arrow { margin-top: auto; font-family: var(--font-head); font-weight: 600; color: var(--brand); font-size: 0.92rem; transition: gap .2s, color .2s; }
.link-arrow:hover { color: var(--accent-d); }
/* ---------- Map ---------- */
.map-layout { display: grid; grid-template-columns: 1fr 1.1fr; gap: 44px; align-items: center; }
.map-copy h2 { font-size: clamp(1.7rem, 4vw, 2.4rem); margin-top: 6px; }
.map-copy > p { color: var(--ink-2); margin-top: 14px; }
.map-legend { display: flex; flex-wrap: wrap; gap: 16px; margin: 20px 0; font-size: 0.86rem; color: var(--ink-2); }
.map-legend span { display: inline-flex; align-items: center; gap: 7px; }
.dot { width: 11px; height: 11px; border-radius: 50%; display: inline-block; }
.dot-forest { background: var(--leaf); }
.dot-ocean { background: #2ba6d0; }
.dot-earth { background: var(--earth); }
.map-detail {
border: 1px solid var(--line); border-radius: var(--r-md); padding: 16px 18px; background: var(--surface);
box-shadow: var(--sh-sm); min-height: 92px; display: flex; flex-direction: column; gap: 4px;
transition: border-color .25s, box-shadow .25s;
}
.map-detail.active { border-color: rgba(95,174,107,0.6); box-shadow: var(--sh-md); }
.map-detail strong { font-family: var(--font-head); font-size: 1.05rem; color: var(--brand-d); }
.map-detail span { color: var(--ink-2); font-size: 0.9rem; }
.map-detail .meta { display: flex; gap: 16px; margin-top: 6px; font-size: 0.82rem; color: var(--muted); }
.map-detail .meta b { color: var(--ink); }
.map-stage { display: flex; justify-content: center; }
.map-svg-wrap { position: relative; width: 100%; max-width: 520px; }
.map-svg { width: 100%; height: auto; border-radius: 18px; box-shadow: var(--sh-md); }
.map-svg .land { fill: #1f7a52; stroke: rgba(255,255,255,0.12); stroke-width: 1; }
.pin {
position: absolute; width: 20px; height: 20px; border-radius: 50%; transform: translate(-50%, -50%);
border: 3px solid #fff; cursor: pointer; padding: 0;
box-shadow: 0 4px 10px rgba(0,0,0,0.3); transition: transform .2s ease;
animation: bob 2.6s ease-in-out infinite;
}
.pin::after { content: ""; position: absolute; inset: -8px; border-radius: 50%; border: 2px solid currentColor; opacity: 0; }
.pin:hover, .pin.active { transform: translate(-50%, -50%) scale(1.35); z-index: 3; }
.pin.active::after { opacity: 0.6; animation: ring 1.4s ease-out infinite; }
.pin-forest { background: var(--leaf); color: var(--leaf); }
.pin-ocean { background: #2ba6d0; color: #2ba6d0; }
.pin-earth { background: var(--earth); color: var(--earth); }
@keyframes bob { 0%,100% { margin-top: 0; } 50% { margin-top: -5px; } }
@keyframes ring { 0% { transform: scale(0.7); opacity: 0.7; } 100% { transform: scale(1.8); opacity: 0; } }
.pin-key { position: absolute; right: 12px; bottom: 12px; font-size: 0.74rem; color: rgba(255,255,255,0.85); background: rgba(10,60,50,0.4); padding: 4px 10px; border-radius: 999px; }
/* ---------- Pledge ---------- */
.band-pledge { background: linear-gradient(160deg, #134e36, #0a4f6b); color: #fff; position: relative; overflow: hidden; }
.band-pledge::before { content: ""; position: absolute; inset: 0; background: radial-gradient(50% 70% at 90% 0%, rgba(95,174,107,0.25), transparent 60%); }
.pledge-layout { position: relative; display: grid; grid-template-columns: 1.2fr 0.9fr; gap: 44px; align-items: center; }
.pledge-copy h2 { color: #fff; font-size: clamp(1.7rem, 4vw, 2.4rem); margin-top: 6px; }
.pledge-copy > p { color: rgba(255,255,255,0.85); margin-top: 12px; }
.thermo { height: 16px; border-radius: 999px; background: rgba(255,255,255,0.18); margin-top: 22px; overflow: hidden; border: 1px solid rgba(255,255,255,0.2); }
.thermo-fill { height: 100%; border-radius: 999px; background: linear-gradient(90deg, var(--leaf), var(--accent)); width: 0; transition: width 1.4s cubic-bezier(.2,.8,.2,1); }
.thermo-label { margin-top: 10px; font-size: 0.92rem; color: rgba(255,255,255,0.85); }
.thermo-label strong { color: #fff; font-size: 1.05rem; }
.pledge-form { background: var(--surface); color: var(--ink); border-radius: var(--r-lg); padding: 24px; box-shadow: var(--sh-lg); display: grid; gap: 14px; }
.field { display: grid; gap: 6px; }
.field span { font-size: 0.85rem; font-weight: 600; color: var(--ink-2); }
.field input { font: inherit; padding: 11px 13px; border: 1.5px solid var(--line-2); border-radius: var(--r-sm); background: #fff; transition: border-color .2s, box-shadow .2s; }
.field input:focus { outline: none; border-color: var(--brand); box-shadow: 0 0 0 3px rgba(28,107,74,0.15); }
.field input.invalid { border-color: var(--danger); box-shadow: 0 0 0 3px rgba(212,80,62,0.14); }
.check { display: flex; gap: 9px; align-items: flex-start; font-size: 0.85rem; color: var(--ink-2); cursor: pointer; }
.check input { margin-top: 3px; accent-color: var(--brand); width: 16px; height: 16px; }
.form-note { font-size: 0.76rem; color: var(--muted); text-align: center; }
/* ---------- Transparency ---------- */
.trans-layout { display: grid; grid-template-columns: 1.1fr 0.9fr; gap: 40px; align-items: center; }
.alloc { display: grid; gap: 20px; }
.alloc-row { display: grid; grid-template-columns: 1fr; gap: 7px; }
.alloc-label { font-weight: 600; color: var(--ink); font-size: 0.96rem; }
.bar { height: 14px; background: var(--bg-2); border-radius: 999px; overflow: hidden; }
.bar-fill { display: block; height: 100%; width: 0; border-radius: 999px; transition: width 1.3s cubic-bezier(.2,.8,.2,1); }
.bf-1 { background: linear-gradient(90deg, var(--brand), var(--leaf)); }
.bf-2 { background: linear-gradient(90deg, var(--ocean), #2ba6d0); }
.bf-3 { background: linear-gradient(90deg, var(--earth), var(--accent)); }
.alloc-pct { font-family: var(--font-head); font-weight: 700; color: var(--brand-d); font-size: 0.9rem; justify-self: end; margin-top: -26px; }
.alloc-row { position: relative; }
.badges { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.badge { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); padding: 16px; box-shadow: var(--sh-sm); display: grid; gap: 3px; transition: transform .2s, box-shadow .2s; }
.badge strong { font-family: var(--font-head); color: var(--brand-d); font-size: 1.02rem; }
.badge span { font-size: 0.8rem; color: var(--ink-2); }
.badge-link:hover { transform: translateY(-3px); box-shadow: var(--sh-md); border-color: var(--brand); }
/* ---------- Partners ---------- */
.partner-row { display: flex; flex-wrap: wrap; justify-content: center; gap: 14px 28px; margin-bottom: 40px; }
.partner { font-family: var(--font-head); font-weight: 600; font-size: 1.05rem; color: var(--muted); opacity: 0.85; padding: 10px 18px; border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--surface); transition: color .2s, opacity .2s, transform .2s; }
.partner:hover { color: var(--brand-d); opacity: 1; transform: translateY(-2px); }
.quote { max-width: 760px; margin: 0 auto; text-align: center; }
.quote blockquote { font-family: var(--font-head); font-size: clamp(1.2rem, 2.6vw, 1.65rem); line-height: 1.4; color: var(--ink); margin: 0; }
.quote figcaption { margin-top: 16px; color: var(--ink-2); font-size: 0.95rem; }
.quote figcaption strong { color: var(--brand-d); }
/* ---------- Donate ---------- */
.donate { padding: 80px 0; background: var(--bg-2); }
.donate-inner { display: grid; grid-template-columns: 1fr 0.95fr; gap: 48px; align-items: center; }
.donate-copy h2 { font-size: clamp(1.8rem, 4.5vw, 2.8rem); color: var(--ink); }
.donate-copy p { color: var(--ink-2); margin-top: 14px; font-size: 1.06rem; max-width: 420px; }
.donate-card { background: var(--surface); border-radius: var(--r-lg); padding: 26px; box-shadow: var(--sh-lg); border: 1px solid var(--line); }
.freq { display: flex; gap: 6px; background: var(--bg-2); padding: 5px; border-radius: 999px; margin-bottom: 18px; }
.freq-btn { flex: 1; border: 0; background: transparent; padding: 10px; border-radius: 999px; font-family: var(--font-head); font-weight: 600; color: var(--ink-2); cursor: pointer; transition: background .2s, color .2s, box-shadow .2s; }
.freq-btn.is-active { background: var(--surface); color: var(--brand-d); box-shadow: var(--sh-sm); }
.amounts { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; margin-bottom: 16px; }
.amt {
font-family: var(--font-head); font-weight: 700; font-size: 1.05rem; color: var(--ink);
background: var(--surface); border: 1.5px solid var(--line-2); border-radius: var(--r-md);
padding: 14px 8px; cursor: pointer; transition: border-color .2s, background .2s, transform .15s, color .2s;
}
.amt:hover { border-color: var(--brand); transform: translateY(-2px); }
.amt.is-active { border-color: var(--brand); background: rgba(28,107,74,0.08); color: var(--brand-d); }
.amt-custom { display: flex; align-items: center; gap: 4px; grid-column: span 3; padding: 8px 14px; }
.amt-custom span { color: var(--muted); }
.amt-custom input { font: inherit; font-weight: 700; border: 0; outline: none; background: transparent; width: 100%; color: var(--ink); }
.impact-line { text-align: center; font-size: 0.95rem; color: var(--ink-2); margin: 6px 0 16px; }
.impact-line strong { color: var(--brand-d); }
/* ---------- Footer ---------- */
.footer { background: #0f3528; color: #d5e6dc; padding: 60px 0 24px; }
.footer-grid { display: grid; grid-template-columns: 1.4fr 1fr 1fr 1.2fr; gap: 36px; }
.footer-brand p { color: rgba(213,230,220,0.7); margin-top: 12px; font-size: 0.92rem; max-width: 280px; }
.socials { display: flex; gap: 10px; margin-top: 16px; }
.socials a { width: 38px; height: 38px; display: grid; place-items: center; border-radius: 50%; background: rgba(255,255,255,0.08); color: #eaf6ec; transition: background .2s, transform .2s; }
.socials a:hover { background: var(--brand); transform: translateY(-2px); }
.footer-col h4 { font-size: 0.82rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--leaf); margin-bottom: 14px; }
.footer-col a { display: block; color: rgba(213,230,220,0.78); padding: 5px 0; font-size: 0.92rem; transition: color .2s; }
.footer-col a:hover { color: #fff; }
.subscribe { display: flex; gap: 8px; margin-bottom: 10px; }
.subscribe input { flex: 1; min-width: 0; font: inherit; padding: 10px 12px; border-radius: var(--r-sm); border: 1px solid rgba(255,255,255,0.18); background: rgba(255,255,255,0.06); color: #fff; }
.subscribe input::placeholder { color: rgba(213,230,220,0.5); }
.subscribe input:focus { outline: none; border-color: var(--leaf); }
.tiny { font-size: 0.8rem; color: rgba(213,230,220,0.6); }
.footer-base { display: flex; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-top: 44px; padding-top: 20px; border-top: 1px solid rgba(255,255,255,0.1); font-size: 0.82rem; color: rgba(213,230,220,0.6); }
/* ---------- Toast ---------- */
.toast {
position: fixed; left: 50%; bottom: 28px; transform: translate(-50%, 30px);
background: var(--ink); color: #fff; padding: 13px 20px; border-radius: 999px;
font-size: 0.92rem; font-weight: 500; box-shadow: var(--sh-lg); z-index: 300;
opacity: 0; pointer-events: none; transition: opacity .3s, transform .3s; max-width: 90vw;
}
.toast.show { opacity: 1; transform: translate(-50%, 0); }
.toast.ok { background: var(--brand-d); }
/* ---------- Reveal ---------- */
.reveal { opacity: 0; transform: translateY(22px); transition: opacity .7s ease, transform .7s cubic-bezier(.2,.8,.2,1); }
.reveal.in { opacity: 1; transform: none; }
/* ---------- Responsive ---------- */
@media (max-width: 920px) {
.impact-grid, .program-grid { grid-template-columns: repeat(2, 1fr); }
.map-layout, .pledge-layout, .trans-layout, .donate-inner { grid-template-columns: 1fr; }
.hero-stats { grid-template-columns: repeat(2, 1fr); }
.footer-grid { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 760px) {
.nav-links, .nav-cta { display: none; }
.nav-toggle { display: flex; }
.nav.open .nav-links {
display: flex; position: absolute; top: 68px; left: 0; right: 0; flex-direction: column;
background: var(--surface); padding: 14px; gap: 4px; box-shadow: var(--sh-md); border-bottom: 1px solid var(--line);
}
.nav.open .nav-cta { display: flex; position: absolute; top: 100%; left: 0; right: 0; padding: 0 14px 16px; background: var(--surface); }
.nav.open .nav-cta .btn { flex: 1; }
}
@media (max-width: 520px) {
.band { padding: 60px 0; }
.impact-grid, .program-grid, .footer-grid { grid-template-columns: 1fr; }
.badges { grid-template-columns: 1fr; }
.hero-inner { padding-top: 56px; }
.hero h1 { font-size: clamp(2rem, 9vw, 2.6rem); }
.footer-base { flex-direction: column; }
.amounts { grid-template-columns: repeat(2, 1fr); }
.amt-custom { grid-column: span 2; }
}
@media (prefers-reduced-motion: reduce) {
* { animation: none !important; scroll-behavior: auto !important; }
.reveal { opacity: 1; transform: none; transition: none; }
}(function () {
"use strict";
/* ---------- Toast helper ---------- */
var toastEl = document.getElementById("toast");
var toastTimer;
function toast(msg, ok) {
if (!toastEl) return;
toastEl.textContent = msg;
toastEl.classList.toggle("ok", !!ok);
toastEl.classList.add("show");
clearTimeout(toastTimer);
toastTimer = setTimeout(function () { toastEl.classList.remove("show"); }, 3200);
}
/* ---------- Sticky nav shadow ---------- */
var nav = document.getElementById("nav");
function onScroll() {
if (window.scrollY > 12) nav.classList.add("scrolled");
else nav.classList.remove("scrolled");
}
window.addEventListener("scroll", onScroll, { passive: true });
onScroll();
/* ---------- Mobile nav ---------- */
var toggle = document.getElementById("navToggle");
toggle.addEventListener("click", function () {
var open = nav.classList.toggle("open");
toggle.setAttribute("aria-expanded", open ? "true" : "false");
toggle.setAttribute("aria-label", open ? "Close menu" : "Open menu");
});
document.getElementById("navLinks").addEventListener("click", function (e) {
if (e.target.tagName === "A") {
nav.classList.remove("open");
toggle.setAttribute("aria-expanded", "false");
}
});
/* ---------- Scroll reveal ---------- */
var revealEls = document.querySelectorAll(".reveal");
if ("IntersectionObserver" in window) {
var io = new IntersectionObserver(function (entries) {
entries.forEach(function (en) {
if (en.isIntersecting) {
en.target.classList.add("in");
io.unobserve(en.target);
}
});
}, { threshold: 0.15 });
revealEls.forEach(function (el, i) {
el.style.transitionDelay = (Math.min(i % 4, 3) * 70) + "ms";
io.observe(el);
});
} else {
revealEls.forEach(function (el) { el.classList.add("in"); });
}
/* ---------- Animated count-up stats ---------- */
function easeOut(t) { return 1 - Math.pow(1 - t, 3); }
function animateCount(el) {
var target = parseFloat(el.getAttribute("data-target")) || 0;
var suffix = el.getAttribute("data-suffix") || "";
var dur = 1600, start = null;
function step(ts) {
if (start === null) start = ts;
var p = Math.min((ts - start) / dur, 1);
var val = Math.round(target * easeOut(p));
el.textContent = val.toLocaleString("en-US") + suffix;
if (p < 1) requestAnimationFrame(step);
}
requestAnimationFrame(step);
}
var counts = document.querySelectorAll(".count");
if ("IntersectionObserver" in window) {
var cio = new IntersectionObserver(function (entries) {
entries.forEach(function (en) {
if (en.isIntersecting) { animateCount(en.target); cio.unobserve(en.target); }
});
}, { threshold: 0.4 });
counts.forEach(function (el) { cio.observe(el); });
} else {
counts.forEach(animateCount);
}
/* ---------- Transparency bars + thermometer (animate on view) ---------- */
var thermoFill = document.getElementById("thermoFill");
// bars carry their target width inline in markup; reset to 0 then restore on view
var transBars = document.querySelectorAll(".bar-fill");
var widths = [];
transBars.forEach(function (b) { widths.push(b.style.width); b.style.width = "0%"; });
function runBars() {
transBars.forEach(function (b, i) { b.style.width = widths[i]; });
}
if ("IntersectionObserver" in window && transBars.length) {
var bio = new IntersectionObserver(function (entries) {
entries.forEach(function (en) {
if (en.isIntersecting) { runBars(); bio.disconnect(); }
});
}, { threshold: 0.3 });
bio.observe(transBars[0].closest(".alloc"));
} else { runBars(); }
/* Thermometer animates toward signature ratio */
var PLEDGE_GOAL = 500000;
var pledgeCount = 341902;
var pledgeCountEl = document.getElementById("pledgeCount");
function updateThermo() {
var pct = Math.min((pledgeCount / PLEDGE_GOAL) * 100, 100);
if (thermoFill) thermoFill.style.width = pct.toFixed(1) + "%";
if (pledgeCountEl) pledgeCountEl.textContent = pledgeCount.toLocaleString("en-US");
}
if (thermoFill) {
var tio = new IntersectionObserver(function (entries) {
entries.forEach(function (en) {
if (en.isIntersecting) { updateThermo(); tio.disconnect(); }
});
}, { threshold: 0.3 });
tio.observe(thermoFill.closest(".thermo"));
}
/* ---------- Impact map pins ---------- */
var SITES = {
atlantic: {
name: "Atlantic Forest Corridor",
place: "Bahia, Brazil",
desc: "Reconnecting jungle fragments for jaguars and tapirs.",
hectares: "8,420 ha", canopy: "+41%", lead: "Crew lead: Beatriz Mendes"
},
sundarbans: {
name: "Sundarbans Mangrove Shield",
place: "Bay of Bengal",
desc: "Storm-buffering mangroves protecting coastal villages.",
hectares: "1,840 ha", canopy: "+33%", lead: "Crew lead: Rafiq Hossain"
},
rift: {
name: "Rift Valley Soil Renewal",
place: "Nakuru, Kenya",
desc: "Agroforestry restoring eroded smallholder farmland.",
hectares: "5,610 ha", canopy: "+22%", lead: "Crew lead: Wanjiru Kamau"
},
carpathia: {
name: "Carpathian Old-Growth",
place: "Romania",
desc: "Protecting Europe's last temperate rainforest.",
hectares: "3,200 ha", canopy: "+29%", lead: "Crew lead: Andrei Popescu"
}
};
var detail = document.getElementById("mapDetail");
var pins = document.querySelectorAll(".pin");
pins.forEach(function (pin) {
pin.setAttribute("aria-label", "View restoration site");
pin.addEventListener("click", function () {
pins.forEach(function (p) { p.classList.remove("active"); });
pin.classList.add("active");
var s = SITES[pin.getAttribute("data-site")];
if (!s || !detail) return;
detail.classList.add("active");
detail.innerHTML =
'<strong>' + s.name + '</strong>' +
'<span>' + s.place + ' — ' + s.desc + '</span>' +
'<span class="meta"><span>Restored <b>' + s.hectares + '</b></span>' +
'<span>Canopy <b>' + s.canopy + '</b></span></span>' +
'<span class="meta"><span>' + s.lead + '</span></span>';
});
});
/* ---------- Donate widget ---------- */
var freqBtns = document.querySelectorAll(".freq-btn");
var amtBtns = document.querySelectorAll(".amt[data-amt]");
var customAmt = document.getElementById("customAmt");
var impactLine = document.getElementById("impactLine");
var donateAmtLabel = document.getElementById("donateAmtLabel");
var donateForm = document.getElementById("donateForm");
var state = { freq: "once", amount: 60 };
function renderDonate() {
var trees = Math.max(1, Math.round(state.amount));
var per = state.freq === "monthly" ? "/mo" : "";
if (donateAmtLabel) donateAmtLabel.textContent = "$" + state.amount + per;
if (impactLine) {
impactLine.innerHTML = "Your $" + state.amount +
(state.freq === "monthly" ? " monthly" : "") +
" plants about <strong>" + trees.toLocaleString("en-US") + " trees</strong> 🌱";
}
}
freqBtns.forEach(function (b) {
b.addEventListener("click", function () {
freqBtns.forEach(function (x) { x.classList.remove("is-active"); x.setAttribute("aria-selected", "false"); });
b.classList.add("is-active"); b.setAttribute("aria-selected", "true");
state.freq = b.getAttribute("data-freq");
renderDonate();
});
});
amtBtns.forEach(function (b) {
b.addEventListener("click", function () {
amtBtns.forEach(function (x) { x.classList.remove("is-active"); });
b.classList.add("is-active");
if (customAmt) customAmt.value = "";
state.amount = parseInt(b.getAttribute("data-amt"), 10);
renderDonate();
});
});
if (customAmt) {
customAmt.addEventListener("input", function () {
var v = parseInt(customAmt.value, 10);
if (v > 0) {
amtBtns.forEach(function (x) { x.classList.remove("is-active"); });
state.amount = v;
renderDonate();
}
});
}
if (donateForm) {
donateForm.addEventListener("submit", function (e) {
e.preventDefault();
if (!state.amount || state.amount < 1) { toast("Please choose a donation amount."); return; }
toast("Thank you! Your $" + state.amount + (state.freq === "monthly" ? "/mo" : "") + " gift is illustrative only 🌍", true);
});
}
renderDonate();
/* ---------- Pledge form ---------- */
var pledgeForm = document.getElementById("pledgeForm");
if (pledgeForm) {
pledgeForm.addEventListener("submit", function (e) {
e.preventDefault();
var name = document.getElementById("pName");
var email = document.getElementById("pEmail");
var emailOk = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email.value.trim());
var nameOk = name.value.trim().length >= 2;
name.classList.toggle("invalid", !nameOk);
email.classList.toggle("invalid", !emailOk);
if (!nameOk || !emailOk) { toast("Please add your name and a valid email."); return; }
pledgeCount += 1;
updateThermo();
toast("Pledge signed — thank you, " + name.value.trim().split(" ")[0] + "! 🌱", true);
pledgeForm.reset();
});
["pName", "pEmail"].forEach(function (id) {
var el = document.getElementById(id);
el.addEventListener("input", function () { el.classList.remove("invalid"); });
});
}
/* ---------- Footer subscribe ---------- */
var subForm = document.getElementById("subForm");
if (subForm) {
subForm.addEventListener("submit", function (e) {
e.preventDefault();
var em = document.getElementById("subEmail");
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(em.value.trim())) { toast("Enter a valid email to subscribe."); return; }
toast("You're on the list! Welcome to the movement 🌍", true);
subForm.reset();
});
}
})();<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Terraroot — Restoring Earth, One Root at a Time</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=Space+Grotesk:wght@500;600;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="nav" id="nav">
<div class="wrap nav-inner">
<a class="brand" href="#top" aria-label="Terraroot home">
<span class="brand-mark" aria-hidden="true">
<svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22V12"/><path d="M12 12c0-4 3-7 7-7-0 4-3 7-7 7Z"/><path d="M12 14c0-3-2-5-5-5 0 3 2 5 5 5Z"/></svg>
</span>
<span class="brand-name">Terra<span>root</span></span>
</a>
<nav class="nav-links" id="navLinks" aria-label="Primary">
<a href="#impact">Impact</a>
<a href="#programs">Programs</a>
<a href="#map">Map</a>
<a href="#transparency">Transparency</a>
<a href="#partners">Partners</a>
</nav>
<div class="nav-cta">
<a class="btn btn-ghost" href="#pledge">Take the pledge</a>
<a class="btn btn-accent" href="#donate">Donate</a>
</div>
<button class="nav-toggle" id="navToggle" aria-expanded="false" aria-controls="navLinks" aria-label="Open menu">
<span></span><span></span><span></span>
</button>
</div>
</header>
<main id="main">
<!-- HERO -->
<section class="hero" id="top">
<div class="hero-photo" aria-hidden="true">
<div class="hero-grad"></div>
<span class="photo-cap">Reforestation crew, Atlantic Forest corridor — Bahia, Brazil</span>
</div>
<div class="wrap hero-inner">
<span class="eyebrow reveal"><span class="pulse" aria-hidden="true"></span> Climate Emergency — Acting Now</span>
<h1 class="reveal">The planet can heal.<br />We just have to <em>show up.</em></h1>
<p class="lead reveal">Terraroot restores degraded land, protects watersheds, and helps frontline communities build a livable climate future. Every gift plants resilience that compounds for decades.</p>
<div class="hero-actions reveal">
<a class="btn btn-accent btn-lg" href="#donate">Fund restoration</a>
<a class="btn btn-outline btn-lg" href="#map">Explore the map</a>
</div>
<div class="hero-stats reveal" role="list">
<div class="hstat" role="listitem">
<strong class="count" data-target="4218640" data-suffix="">0</strong>
<span>Trees planted</span>
</div>
<div class="hstat" role="listitem">
<strong class="count" data-target="31840" data-suffix=" ha">0</strong>
<span>Land restored</span>
</div>
<div class="hstat" role="listitem">
<strong class="count" data-target="186000" data-suffix=" t">0</strong>
<span>CO₂ drawn down</span>
</div>
<div class="hstat" role="listitem">
<strong class="count" data-target="74" data-suffix="">0</strong>
<span>Community partners</span>
</div>
</div>
</div>
</section>
<!-- IMPACT BAND -->
<section class="band" id="impact">
<div class="wrap">
<div class="section-head">
<span class="kicker">Why it works</span>
<h2>Restoration that pays the planet back</h2>
<p>We don't just plant — we measure survival rates, biodiversity return, and water table recovery. Transparency is the root system of trust.</p>
</div>
<div class="impact-grid">
<article class="impact-card reveal">
<span class="impact-ico" aria-hidden="true">🌳</span>
<h3>94% survival rate</h3>
<p>Native-species mixes and 3-year community stewardship keep saplings alive through their fragile first seasons.</p>
</article>
<article class="impact-card reveal">
<span class="impact-ico" aria-hidden="true">💧</span>
<h3>22 watersheds protected</h3>
<p>Restored riparian buffers filter runoff and return year-round flow to streams that 90,000 people depend on.</p>
</article>
<article class="impact-card reveal">
<span class="impact-ico" aria-hidden="true">🐦</span>
<h3>+38% biodiversity</h3>
<p>Camera traps and bioacoustic surveys show returning species within five years of canopy recovery.</p>
</article>
<article class="impact-card reveal">
<span class="impact-ico" aria-hidden="true">🤝</span>
<h3>2,900 green jobs</h3>
<p>Local nurseries, planting crews and rangers — restoration is also an economy for the people who live there.</p>
</article>
</div>
</div>
</section>
<!-- PROGRAMS -->
<section class="band band-soft" id="programs">
<div class="wrap">
<div class="section-head">
<span class="kicker">What we do</span>
<h2>Four programs, one living system</h2>
<p>Pick the front line that moves you. Each program is independently audited and reports impact every quarter.</p>
</div>
<div class="program-grid">
<article class="program reveal">
<div class="program-photo p-forest" aria-hidden="true"><span class="tag">Reforestation</span></div>
<div class="program-body">
<h3>Living Corridors</h3>
<p>Reconnecting fragmented forests so wildlife can migrate, breed and adapt as the climate shifts.</p>
<ul class="dotted">
<li>1.2M native trees per year</li>
<li>Seed banks with 140 species</li>
</ul>
<a class="link-arrow" href="#donate">Support corridors →</a>
</div>
</article>
<article class="program reveal">
<div class="program-photo p-ocean" aria-hidden="true"><span class="tag">Blue carbon</span></div>
<div class="program-body">
<h3>Mangrove Shield</h3>
<p>Replanting coastal mangroves that store carbon, break storm surges and rebuild fisheries.</p>
<ul class="dotted">
<li>1,840 ha of coastline</li>
<li>4× carbon density of forest</li>
</ul>
<a class="link-arrow" href="#donate">Support mangroves →</a>
</div>
</article>
<article class="program reveal">
<div class="program-photo p-earth" aria-hidden="true"><span class="tag">Regenerative</span></div>
<div class="program-body">
<h3>Soil Renewal</h3>
<p>Training smallholder farmers in agroforestry that locks carbon in living soil and lifts yields.</p>
<ul class="dotted">
<li>5,600 farms enrolled</li>
<li>+27% average income</li>
</ul>
<a class="link-arrow" href="#donate">Support farmers →</a>
</div>
</article>
<article class="program reveal">
<div class="program-photo p-sky" aria-hidden="true"><span class="tag">Advocacy</span></div>
<div class="program-body">
<h3>Climate Voices</h3>
<p>Putting frontline communities in the rooms where land and water policy is decided.</p>
<ul class="dotted">
<li>11 policy wins in 2025</li>
<li>340k petition signatures</li>
</ul>
<a class="link-arrow" href="#pledge">Add your voice →</a>
</div>
</article>
</div>
</div>
</section>
<!-- IMPACT MAP TEASER -->
<section class="band" id="map">
<div class="wrap map-layout">
<div class="map-copy">
<span class="kicker">Live impact map</span>
<h2>See restoration happening, region by region</h2>
<p>Tap a site to preview canopy recovery, hectares restored and the local crew leading the work. The full interactive atlas updates from field sensors weekly.</p>
<div class="map-legend">
<span><i class="dot dot-forest"></i> Forest corridor</span>
<span><i class="dot dot-ocean"></i> Mangrove</span>
<span><i class="dot dot-earth"></i> Farmland</span>
</div>
<div class="map-detail" id="mapDetail" aria-live="polite">
<strong>Select a site</strong>
<span>Pick any pin on the map to load its progress.</span>
</div>
</div>
<div class="map-stage">
<div class="map-svg-wrap">
<svg viewBox="0 0 320 240" class="map-svg" role="img" aria-label="Stylised world map with restoration sites">
<rect x="0" y="0" width="320" height="240" rx="18" fill="url(#sea)"/>
<defs>
<linearGradient id="sea" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#0e4b6e"/><stop offset="1" stop-color="#0a3a57"/>
</linearGradient>
</defs>
<path class="land" d="M30 70 Q60 40 95 55 Q130 65 120 100 Q110 140 70 150 Q40 155 30 120 Z"/>
<path class="land" d="M150 60 Q190 40 230 60 Q270 80 255 120 Q240 160 200 150 Q160 140 150 100 Z"/>
<path class="land" d="M210 165 Q240 155 270 175 Q290 195 265 210 Q235 220 215 200 Z"/>
<button class="pin pin-forest" style="left:24%;top:48%" data-site="atlantic"></button>
<button class="pin pin-ocean" style="left:62%;top:60%" data-site="sundarbans"></button>
<button class="pin pin-earth" style="left:74%;top:78%" data-site="rift"></button>
<button class="pin pin-forest" style="left:54%;top:38%" data-site="carpathia"></button>
</svg>
<span class="pin-key">Tap a pin →</span>
</div>
</div>
</div>
</section>
<!-- PLEDGE / PETITION -->
<section class="band band-pledge" id="pledge">
<div class="wrap pledge-layout">
<div class="pledge-copy">
<span class="kicker light">Petition</span>
<h2>Pledge to protect 30% of land & sea by 2030</h2>
<p>Add your name to the global call. We deliver signatures directly to negotiators ahead of the next climate summit.</p>
<div class="thermo" aria-hidden="true">
<div class="thermo-fill" id="thermoFill" style="width:0%"></div>
</div>
<p class="thermo-label"><strong id="pledgeCount">341,902</strong> of <span>500,000</span> signatures</p>
</div>
<form class="pledge-form" id="pledgeForm" novalidate>
<label class="field">
<span>Full name</span>
<input type="text" name="name" id="pName" autocomplete="name" placeholder="Your name" required />
</label>
<label class="field">
<span>Email</span>
<input type="email" name="email" id="pEmail" autocomplete="email" placeholder="[email protected]" required />
</label>
<label class="check">
<input type="checkbox" id="pConsent" />
<span>Send me monthly impact updates (no spam, unsubscribe anytime).</span>
</label>
<button type="submit" class="btn btn-accent btn-block">Sign the pledge</button>
<p class="form-note">Illustrative form — nothing is submitted anywhere.</p>
</form>
</div>
</section>
<!-- TRANSPARENCY -->
<section class="band" id="transparency">
<div class="wrap">
<div class="section-head">
<span class="kicker">Where your gift goes</span>
<h2>87¢ of every dollar reaches the ground</h2>
<p>Audited annually and rated highly for transparency. Here's the honest breakdown.</p>
</div>
<div class="trans-layout">
<div class="alloc">
<div class="alloc-row">
<span class="alloc-label">Programs & field work</span>
<div class="bar"><i style="width:87%" class="bar-fill bf-1"></i></div>
<span class="alloc-pct">87%</span>
</div>
<div class="alloc-row">
<span class="alloc-label">Operations</span>
<div class="bar"><i style="width:8%" class="bar-fill bf-2"></i></div>
<span class="alloc-pct">8%</span>
</div>
<div class="alloc-row">
<span class="alloc-label">Fundraising</span>
<div class="bar"><i style="width:5%" class="bar-fill bf-3"></i></div>
<span class="alloc-pct">5%</span>
</div>
</div>
<div class="badges">
<div class="badge"><strong>★ 4-star</strong><span>Charity transparency rating 2025</span></div>
<div class="badge"><strong>Tax-deductible</strong><span>EIN 47-0192834 (fictional)</span></div>
<div class="badge"><strong>Verra verified</strong><span>Carbon claims independently audited</span></div>
<a class="badge badge-link" href="#"><strong>Annual report ↗</strong><span>Download the 2025 PDF</span></a>
</div>
</div>
</div>
</section>
<!-- PARTNERS -->
<section class="band band-soft" id="partners">
<div class="wrap">
<div class="section-head">
<span class="kicker">In good company</span>
<h2>Backed by people & partners worldwide</h2>
</div>
<div class="partner-row">
<span class="partner">EverGreen Fund</span>
<span class="partner">Blue Horizon Co.</span>
<span class="partner">Helio Foundation</span>
<span class="partner">Cedar & Pine</span>
<span class="partner">Rainfall Labs</span>
<span class="partner">Northwind Trust</span>
</div>
<figure class="quote reveal">
<blockquote>"Terraroot is the rare organization that lets you watch your donation turn into a living forest. The data is open, the people are real, the impact is undeniable."</blockquote>
<figcaption><strong>Dr. Amara Okonkwo</strong> · Ecologist & longtime donor</figcaption>
</figure>
</div>
</section>
<!-- DONATE CTA -->
<section class="donate" id="donate">
<div class="wrap donate-inner">
<div class="donate-copy">
<h2>Plant the future today</h2>
<p>Pick an amount and see your impact instantly. Monthly gifts let us plan restoration years ahead.</p>
</div>
<form class="donate-card" id="donateForm" novalidate>
<div class="freq" role="tablist" aria-label="Donation frequency">
<button type="button" class="freq-btn is-active" data-freq="once" role="tab" aria-selected="true">One-time</button>
<button type="button" class="freq-btn" data-freq="monthly" role="tab" aria-selected="false">Monthly</button>
</div>
<div class="amounts" id="amounts">
<button type="button" class="amt" data-amt="25">$25</button>
<button type="button" class="amt is-active" data-amt="60">$60</button>
<button type="button" class="amt" data-amt="120">$120</button>
<button type="button" class="amt" data-amt="250">$250</button>
<label class="amt amt-custom">
<span aria-hidden="true">$</span>
<input type="number" id="customAmt" min="1" inputmode="numeric" placeholder="Other" aria-label="Custom amount" />
</label>
</div>
<p class="impact-line" id="impactLine">Your $60 plants about <strong>60 trees</strong> 🌱</p>
<button type="submit" class="btn btn-accent btn-block btn-lg">Donate <span id="donateAmtLabel">$60</span></button>
<p class="form-note">🔒 Illustrative demo — no real payment is processed.</p>
</form>
</div>
</section>
</main>
<footer class="footer">
<div class="wrap footer-grid">
<div class="footer-brand">
<span class="brand-name big">Terra<span>root</span></span>
<p>Restoring earth, one root at a time. A fictional environmental nonprofit for UI demonstration.</p>
<div class="socials" aria-label="Social links">
<a href="#" aria-label="Newsletter">✉</a>
<a href="#" aria-label="Instagram">◎</a>
<a href="#" aria-label="Bluesky">≈</a>
<a href="#" aria-label="YouTube">►</a>
</div>
</div>
<nav class="footer-col" aria-label="Programs">
<h4>Programs</h4>
<a href="#programs">Living Corridors</a>
<a href="#programs">Mangrove Shield</a>
<a href="#programs">Soil Renewal</a>
<a href="#programs">Climate Voices</a>
</nav>
<nav class="footer-col" aria-label="Organization">
<h4>Organization</h4>
<a href="#transparency">Transparency</a>
<a href="#partners">Partners</a>
<a href="#impact">Our impact</a>
<a href="#">Careers</a>
</nav>
<div class="footer-col">
<h4>Stay in the loop</h4>
<form class="subscribe" id="subForm" novalidate>
<input type="email" id="subEmail" placeholder="Email address" aria-label="Email address" required />
<button type="submit" class="btn btn-brand">Join</button>
</form>
<p class="tiny">We restore land in 14 countries.</p>
</div>
</div>
<div class="wrap footer-base">
<span>© 2026 Terraroot (fictional). All rights reserved.</span>
<span>Registered environmental charity · Tax-deductible</span>
</div>
</footer>
<div class="toast" id="toast" role="status" aria-live="polite"></div>
<script src="script.js"></script>
</body>
</html>Environmental Landing
A full multi-section landing page for Terraroot, a fictional environmental nonprofit restoring degraded land and watersheds. The hero overlays a warm forest-to-ocean gradient “photograph” with a captioned field placeholder, an urgent climate-emergency eyebrow, and a row of headline impact stats — trees planted, hectares restored, CO₂ drawn down, community partners — that count up from zero the first time they scroll into view. Below it, an impact band, four restoration program cards, and an interactive map teaser sit on alternating sand and misty-green backgrounds.
The page is genuinely interactive. The stylised world map carries animated pins you can click to load each site’s hectares restored, canopy recovery and crew lead into a live detail panel. A petition section drives an animated signature thermometer that ticks upward when you sign the (illustrative) pledge form, with inline validation. The transparency section animates allocation bars on reveal alongside trust badges (charity rating, tax-deductible, third-party carbon verification). The donate widget lets you switch between one-time and monthly giving, pick or type an amount, and watch the impact line recalculate dollars into trees in real time — with a small toast() confirming each action.
Everything is self-contained: Google Fonts via <link>, semantic landmarks, aria labels, keyboard-usable buttons and inputs, WCAG-minded contrast, a working mobile nav, scroll-reveal via IntersectionObserver, and a prefers-reduced-motion fallback. No frameworks, no build step — just HTML, CSS and vanilla JS that works down to ~360px.
Illustrative UI only — fictional organization, not a real charity or donation system.