1<!DOCTYPE html> 2<html lang="en"> 3<head> 4<meta charset="UTF-8" /> 5<meta name="viewport" content="width=device-width, initial-scale=1.0" /> 6<title>Ecoflix Foundation | Be the change you want to see</title> 7<meta name="description" content="Ecoflix funds wildlife conservation, creates powerful storytelling, and supports outstanding NGOs on the front line." /> 8<meta name="keywords" content="wildlife conservation, conservation charity, protect endangered species, donate to conservation, wildlife NGOs, Ecoflix Foundation" /> 9<meta name="theme-color" content="#020718" /> 10<meta name="robots" content="index, follow, max-image-preview:large, max-snippet:-1, max-video-preview:-1" /> 11<meta name="author" content="Ecoflix Foundation" /> 12<link rel="canonical" href="https://www.ecoflix.com/" /> 13 14<!-- Open Graph --> 15<meta property="og:site_name" content="Ecoflix Foundation" /> 16<meta property="og:title" content="Ecoflix Foundation | Be the change you want to see" /> 17<meta property="og:description" content="Ecoflix funds wildlife conservation, creates powerful storytelling, and supports outstanding NGOs on the front line." /> 18<meta property="og:type" content="website" /> 19<meta property="og:url" content="https://www.ecoflix.com/" /> 20<meta property="og:image" content="https://www.ecoflix.com/assets/og-cover.png" /> 21<meta property="og:image:secure_url" content="https://www.ecoflix.com/assets/og-cover.png" /> 22<meta property="og:image:type" content="image/png" /> 23<meta property="og:image:width" content="1200" /> 24<meta property="og:image:height" content="630" /> 25<meta property="og:image:alt" content="Ecoflix Foundation â be the change you want to see." /> 26<meta property="og:locale" content="en_GB" /> 27 28<!-- Twitter / X --> 29<meta name="twitter:card" content="summary_large_image" /> 30<meta name="twitter:site" content="@ecoflixofficial" /> 31<meta name="twitter:creator" content="@ecoflixofficial" /> 32<meta name="twitter:title" content="Ecoflix Foundation | Be the change you want to see" /> 33<meta name="twitter:description" content="Ecoflix funds wildlife conservation, creates powerful storytelling, and supports outstanding NGOs on the front line." /> 34<meta name="twitter:image" content="https://www.ecoflix.com/assets/og-cover.png" /> 35<meta name="twitter:image:alt" content="Ecoflix Foundation â be the change you want to see." /> 36 37<link rel="preconnect" href="https://fonts.googleapis.com" /> 38<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> 39<link rel="preconnect" href="https://images.squarespace-cdn.com" crossorigin /> 40<link href="https://fonts.googleapis.com/css2?family=Manrope:wght@400;500;700&family=Red+Hat+Display:ital,wght@0,500;0,800;0,900;1,500;1,900&display=swap" rel="stylesheet" /> 41<link rel="icon" type="image/png" href="/assets/favicon.png" /> 42 43<!-- JSON-LD: Organization + WebSite -->
44<script type="application/ld+json"> 45{ 46 "@context": "https://schema.org", 47 "@graph": [ 48 { 49 "@type": ["NGO", "Organization"], 50 "@id": "https://www.ecoflix.com/#organization", 51 "name": "Ecoflix Foundation", 52 "alternateName": "Ecoflix", 53 "url": "https://www.ecoflix.com/", 54 "logo": { 55 "@type": "ImageObject", 56 "url": "https://www.ecoflix.com/assets/logo.png", 57 "width": 2500, 58 "height": 923 59 }, 60 "image": "https://www.ecoflix.com/assets/og-cover.png", 61 "description": "The not-for-profit foundation behind the Ecoflix channel. We fund wildlife conservation, create powerful storytelling, and support outstanding NGOs on the front line.", 62 "slogan": "Be the change you want to see.", 63 "sameAs": [ 64 "https://www.instagram.com/ecoflixofficial/", 65 "https://www.facebook.com/ecoflixofficial", 66 "https://twitter.com/ecoflixofficial", 67 "https://www.youtube.com/@ecoflixofficial", 68 "https://www.linkedin.com/company/ecoflix/", 69 "https://www.tiktok.com/@ecoflixofficial" 70 ] 71 }, 72 { 73 "@type": "WebSite", 74 "@id": "https://www.ecoflix.com/#website", 75 "url": "https://www.ecoflix.com/", 76 "name": "Ecoflix Foundation", 77 "description": "Ecoflix funds wildlife conservation, creates powerful storytelling, and supports outstanding NGOs on the front line.", 78 "inLanguage": "en-GB", 79 "publisher": { "@id": "https://www.ecoflix.com/#organization" } 80 } 81 ] 82} 83</script>
83 84 85<style> 86/* ============ Tokens ============ */ 87:root{ 88 --ink:#040506; 89 --ink-80:#0a0c11; 90 --ink-60:#11141b; 91 --ink-40:#1a1d27; 92 --line:rgba(255,255,255,.08); 93 --line-2:rgba(255,255,255,.14); 94 --bone:#f5f3ee; 95 --mist:#b9bcc7; 96 --mist-2:#6f7689; 97 --leaf:#A8F341; 98 --leaf-deep:#6CB822; 99 --leaf-glow:rgba(168,243,65,.35); 100 --sun:#f0c25f; 101 --coral:#e26a5b; 102 --display:'Red Hat Display', system-ui, sans-serif; 103 --body:'Manrope', system-ui, sans-serif; 104 --r-sm:8px; --r-md:14px; --r-lg:22px; --r-xl:32px; 105 --pad-x:clamp(24px, 5vw, 80px); 106 --pad-section:clamp(64px, 11vh, 160px); 107 /* Height of the fixed .header at rest (18px padding à 2 + ~41px content 108 + 1px border). Anything overlaid on the hero uses this to stay clear 109 of the bar â keep it in sync if the header padding/buttons change. */ 110 --header-h:78px; 111} 112 113@media (max-width:560px){ 114 :root{ 115 --pad-x:28px; 116 --pad-section:72px; 117 --header-h:66px; /* header CTA shrinks at this width */ 118 } 119} 120 121*{box-sizing:border-box;margin:0;padding:0} 122/* No global scroll-behavior:smooth â on this page (20k px of scroll-driven 123 pin-stacks) Chrome cancels long smooth animations mid-flight, which made 124 Home/End and the chapter dots appear dead. JS opts in per interaction. */ 125html{scroll-behavior:auto} 126body{ 127 background:var(--ink); 128 color:var(--bone); 129 font-family:var(--body); 130 font-size:17px; 131 line-height:1.55; 132 -webkit-font-smoothing:antialiased; 133 /* overflow-x:hidden creates a scroll container that breaks 134 position:sticky on the hero. `clip` hides x-overflow without 135 creating a scroll context. Safari 16+, Chrome 90+, Firefox 81+. */ 136 overflow-x:clip; 137 position:relative; 138} 139img{max-width:100%;display:block} 140a{color:inherit;text-decoration:none} 141button{font:inherit;color:inherit;background:none;border:0;cursor:pointer} 142h1,h2,h3,h4{font-family:var(--display);font-weight:800;line-height:1;letter-spacing:-.02em} 143::selection{background:var(--leaf);color:var(--ink)} 144 145 146/* Paw-print trail â a sequence of paws appears walking across a section */ 147.pawtrail{ 148 position:absolute;inset:0;z-index:0;pointer-events:none;overflow:hidden; 149} 150.pawtrail svg{ 151 position:absolute;width:100%;height:100%; 152 color:var(--leaf); 153} 154.pawtrail .paw{ 155 opacity:0; 156 animation:pawWalk 14s linear infinite; 157 transform-origin:center; 158} 159.pawtrail .paw:nth-child(1){animation-delay:0s} 160.pawtrail .paw:nth-child(2){animation-delay:.4s} 161.pawtrail .paw:nth-child(3){animation-delay:.8s} 162.pawtrail .paw:nth-child(4){animation-delay:1.2s} 163.pawtrail .paw:nth-child(5){animation-delay:1.6s} 164.pawtrail .paw:nth-child(6){animation-delay:2.0s} 165.pawtrail .paw:nth-child(7){animation-delay:2.4s} 166.pawtrail .paw:nth-child(8){animation-delay:2.8s} 167.pawtrail .paw:nth-child(9){animation-delay:3.2s} 168.pawtrail .paw:nth-child(10){animation-delay:3.6s} 169@keyframes pawWalk{ 170 0%, 100%{opacity:0} 171 5%{opacity:.35;transform:scale(1)} 172 25%{opacity:.22} 173 60%{opacity:0;transform:scale(.95)} 174} 175@media (prefers-reduced-motion:reduce){ 176 .pawtrail .paw{animation:none;opacity:.15} 177} 178 179/* Atmospheric parallax â drifting topographic ridges + ambient orbs. 180 Apply via .atmos as the first child of any dark section. */ 181.atmos{ 182 position:absolute;inset:0;z-index:0;pointer-events:none;overflow:hidden; 183} 184.atmos svg{position:absolute;left:0;top:0;width:200%;height:100%;opacity:.32} 185.atmos .topo path{ 186 fill:none;stroke:rgba(168,243,65,.16);stroke-width:.6; 187 animation:topoDrift 60s linear infinite; 188} 189.atmos .topo path:nth-child(2){stroke:rgba(168,243,65,.10);animation-duration:80s;animation-direction:reverse} 190.atmos .topo path:nth-child(3){stroke:rgba(185,255,166,.10);animation-duration:100s} 191.atmos .topo path:nth-child(4){stroke:rgba(168,243,65,.13);animation-duration:90s;animation-direction:reverse} 192@keyframes topoDrift{ 193 0%{transform:translateX(0)} 194 100%{transform:translateX(-50%)} 195} 196.atmos .orb{ 197 position:absolute;border-radius:50%; 198 background:radial-gradient(circle, rgba(168,243,65,.34) 0%, rgba(168,243,65,.10) 35%, transparent 65%); 199 filter:blur(40px); 200 animation:orbDrift 22s ease-in-out infinite alternate, orbBreathe 7s ease-in-out infinite; 201} 202.atmos .orb-1{width:560px;height:560px;top:-100px;left:-120px;animation-delay:0s} 203.atmos .orb-2{width:420px;height:420px;bottom:-80px;right:-100px;animation-duration:28s;background:radial-gradient(circle, rgba(42,122,59,.36) 0%, rgba(42,122,59,.10) 35%, transparent 65%)} 204.atmos .orb-3{width:320px;height:320px;top:35%;left:55%;animation-duration:36s;background:radial-gradient(circle, rgba(185,255,166,.22) 0%, transparent 60%)} 205@keyframes orbBreathe{ 206 0%,100%{opacity:.85} 207 50% {opacity:1} 208} 209@keyframes orbDrift{ 210 0%{transform:translate(0,0) scale(1)} 211 50%{transform:translate(60px,40px) scale(1.10)} 212 100%{transform:translate(-50px,-30px) scale(.92)} 213} 214@media (prefers-reduced-motion:reduce){ 215 .atmos svg, .atmos .orb{animation:none !important} 216} 217 218/* =========================================================== 219 CARD-LIFT effect â sections that follow a full-screen video 220 sit raised above it with rounded top corners and a strong 221 visible shadow + hairline highlight, so they read as a card 222 being lifted up over the footage as you scroll. Plus a 223 scroll-into-view transform for diversity in the scroll journey. 224 =========================================================== */ 225.section-lift{ 226 position:relative;z-index:2; 227 margin-top:-32px; 228 border-radius:40px 40px 0 0; 229 /* Single hairline highlight at the top edge â no heavy shadow */ 230 box-shadow:0 -1px 0 rgba(255,255,255,.06); 231 /* Pre-state for scroll-reveal */ 232 transform:translateY(32px) scale(.995); 233 transform-origin:50% 0; 234 opacity:.95; 235 transition:transform .8s cubic-bezier(.22,.9,.3,1), 236 opacity .8s cubic-bezier(.22,.9,.3,1); 237} 238.section-lift.is-revealed{ 239 transform:translateY(0) scale(1); 240 opacity:1; 241} 242/* Sections that follow a video get a slightly bigger lift signature */ 243.section-lift.lifts-strong{ 244 margin-top:-48px; 245 border-radius:56px 56px 0 0; 246 box-shadow: 247 0 -8px 24px -4px rgba(0,0,0,.30), 248 0 -1px 0 rgba(255,255,255,.08); 249} 250@media (max-width:720px){ 251 .section-lift{margin-top:-24px;border-radius:24px 24px 0 0} 252 .section-lift.lifts-strong{margin-top:-32px;border-radius:32px 32px 0 0} 253} 254@media (prefers-reduced-motion:reduce){ 255 .section-lift{transform:none;opacity:1;transition:none} 256} 257 258/* Extra bottom padding on video sections so their content (chips, 259 buttons, captions) sits well above the lift overlap from the 260 section below. */ 261.hp-promise{padding-bottom:calc(var(--pad-section) + 64px)} 262.founder-quote{padding-bottom:calc(var(--pad-section) + 64px)} 263.watch-change{padding-bottom:calc(var(--pad-section) + 64px)} 264
265/* =========================================================== 266 WATCH THE CHANGE YOU MAKE â full-bleed video section showing 267 the audience (families, classrooms, lounges, field stations). 268 =========================================================== */ 269.watch-change{ 270 position:relative;height:100vh; 271 padding:var(--pad-section) 0; 272 background:#000;text-align:center;color:var(--bone); 273 overflow:hidden;isolation:isolate; 274 display:grid;place-items:center; 275} 276.watch-change .wc-video{ 277 position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:0; 278 filter:saturate(1.15) contrast(1.05); 279} 280.watch-change .wc-overlay{ 281 position:absolute;inset:0;z-index:1;pointer-events:none; 282 background: 283 radial-gradient(70% 55% at 50% 50%, rgba(2,7,24,.25) 0%, rgba(2,7,24,.12) 50%, rgba(2,7,24,0) 80%), 284 linear-gradient(180deg, rgba(2,7,24,.2) 0%, transparent 18%, transparent 82%, rgba(2,7,24,.22) 100%), 285 radial-gradient(28% 22% at 14% 22%, rgba(168,243,65,.05), transparent 70%), 286 radial-gradient(28% 22% at 86% 78%, rgba(42,122,59,.06), transparent 70%); 287} 288.watch-change .wrap{ 289 position:relative;z-index:2; 290 display:grid;gap:clamp(18px,2.4vw,28px); 291 justify-items:center;text-align:center; 292} 293.watch-change .eyebrow{margin:0 auto} 294.watch-change .wc-headline{ 295 font-family:var(--display);font-weight:900; 296 font-size:clamp(56px,9vw,140px); 297 line-height:.92;letter-spacing:-.04em; 298 max-width:16ch;margin:0 auto;color:var(--bone); 299} 300.watch-change .wc-headline em{ 301 font-style:italic;font-weight:500; 302 303 304 color:var(--leaf);-webkit-text-fill-color:var(--leaf); 305 306} 307.watch-change .wc-supporting{ 308 max-width:58ch;margin:0 auto; 309 font-size:clamp(15px,1.4vw,19px);line-height:1.55;color:var(--bone);opacity:.95; 310} 311.watch-change .wc-actions{ 312 display:flex;flex-wrap:wrap;gap:14px;justify-content:center;align-items:center;margin-top:14px; 313} 314@media (max-width:720px){ 315 .watch-change .wc-headline{font-size:clamp(44px,11vw,68px);max-width:14ch} 316} 317 318/* =========================================================== 319 PIN-STACK â wraps a full-screen video section with the 320 content section that follows it. The video sticks to the 321 top of the viewport while the next section scrolls up over 322 it like a card being lifted into place. 323 =========================================================== */ 324.pin-stack{position:relative} 325.pin-stack > .is-pinned-bg{ 326 position:sticky;top:0;z-index:1; 327 /* Keep the existing 100vh height â sticky honours it */ 328} 329/* HERO override: the .hero-stage is the SCROLL RUNWAY (relative, 300vh) 330 and the inner .hero-pin is the sticky element (100vh). A 300vh sticky 331 element gives 0vh of stick because the element == its CB. We need the 332 element to be 100vh and the CB to be 300vh. */ 333.pin-stack > .hero-stage.is-pinned-bg{ 334 position:relative; 335} 336.pin-stack > .section-lift{ 337 /* Disable the static negative-margin overlap inside a pin-stack â 338 the sticky parent already provides the visual overlap as the 339 user scrolls past the video. */ 340 margin-top:0 !important; 341 position:relative;z-index:2; 342} 343/* Scroll-driven card lift over the hero. 344 345 How it works: 346 - .hero-stage is 400vh = 200vh scrub + 100vh cover phase. 347 - .mission has negative margin-top of -100vh so its actual document 348 position is at stageBottom - 100vh â already overlapping where the 349 hero is pinned. 350 - During scrub phase, JS holds --mission-cover-y at 100vh, pushing 351 mission DOWN by a full viewport so it sits just off the bottom of 352 screen. 353 - During cover phase, JS interpolates --mission-cover-y from 100vh 354 down to 0vh, sliding mission UP into the viewport on top of the 355 still-pinned hero. Mission's z-index 10 puts it visually above 356 the hero (z-index 1). 357 - When the cover phase completes, mission is fully covering the 358 hero. Further scroll unsticks both, and they scroll out together. */ 359.pin-stack > #mission.section-lift{ 360 margin-top:-100vh !important; 361 border-radius:64px 64px 0 0; 362 box-shadow: 363 0 -28px 60px -16px rgba(0,0,0,.65), 364 0 -14px 24px -10px rgba(0,0,0,.45), 365 0 -2px 0 rgba(255,255,255,.12); 366 z-index:10; 367 /* Sticky after the lift completes so mission stays pinned at top of 368 viewport while the compare-section card lifts up over it. The sticky 369 scope is the pin-stack; transform translateY adds the lift offset. */ 370 position:sticky;top:0; 371 /* Scroll-driven slide: JS updates --mission-cover-y every frame. 372 Falls back to 100vh (mission off-screen below) if JS doesn't run. */
373 transform:translateY(var(--mission-cover-y, 100vh)); 374 /* No transition â the JS scroll handler is the timing source. 375 Adding a transition would lag the scrub. */ 376 transition:none; 377 will-change:transform; 378} 379 380/* ============================================================ 381 COMPARE CARD-LIFT â second lift inside the same pin-stack. 382 After mission has fully covered hero (and is sticky at top of 383 viewport), compare-section slides up from below to cover 384 mission. Driven by --compare-cover-y (100vh â 0) via JS. 385 386 How it works: 387 - compare-section is sticky inside the pin-stack at top:0. 388 - It has min-height:200vh â only the first 100vh is content 389 (the actual card); the bottom 100vh is empty runway space 390 that gives the user scroll distance to drive the lift. 391 - margin-top:-80vh pulls compare up so its sticky engagement 392 point lines up with mission's. Mission's natural top is at 393 300vh from pin-stack top; compare's becomes ~300vh too. 394 - During the sticky range, JS interpolates --compare-cover-y 395 from 100vh (off-screen below viewport) to 0 (fully covering 396 mission). Compare's z-index:15 puts it above mission (z:10). 397 ============================================================ */ 398.pin-stack > .compare-section.section-lift{ 399 position:sticky;top:0; 400 margin-top:-80vh !important; 401 /* Override the static margin-top:-120px from base .compare-section */ 402 z-index:15; 403 border-radius:64px 64px 0 0; 404 box-shadow: 405 0 -28px 60px -16px rgba(0,0,0,.65), 406 0 -14px 24px -10px rgba(0,0,0,.45), 407 0 -2px 0 rgba(255,255,255,.12); 408 transform:translateY(var(--compare-cover-y, 100vh)); 409 transition:none; 410 will-change:transform; 411} 412/* Empty runway below compare inside the pin-stack â gives the user 413 scroll distance for compare's sticky to engage. Without this, the 414 pin-stack collapses and the lift has nowhere to play out. */ 415.pin-stack > .compare-runway{ 416 height:100vh;position:relative;pointer-events:none; 417} 418@media (max-width:720px){ 419 .pin-stack > .compare-section.section-lift{ 420 border-radius:40px 40px 0 0; 421 margin-top:-60vh !important; 422 } 423 .pin-stack > .compare-runway{ height:120vh } 424} 425@media (prefers-reduced-motion:reduce){ 426 .pin-stack > .compare-section.section-lift{ 427 position:relative; 428 transform:none;margin-top:0 !important; 429 } 430 .pin-stack > .compare-runway{ height:0 } 431} 432/* The IntersectionObserver-driven .is-revealed class is no longer needed 433 here because the slide is scroll-driven. Keep it as a no-op so the 434 rest of the site's .section-lift system doesn't fight us. */ 435.pin-stack > #mission.section-lift.is-revealed{transform:translateY(var(--mission-cover-y, 0))} 436 437/* Highlight along the top edge so the rounded curve catches light */ 438.pin-stack > #mission.section-lift::after{ 439 content:""; 440 position:absolute; 441 top:0;left:0;right:0; 442 height:1px; 443 background:linear-gradient(90deg, 444 transparent 0%, 445 rgba(255,255,255,.22) 20%, 446 rgba(168,243,65,.4) 50%, 447 rgba(255,255,255,.22) 80%, 448 transparent 100%); 449 pointer-events:none; 450 border-radius:64px 64px 0 0; 451 z-index:1; 452} 453@media (max-width:720px){ 454 .pin-stack > #mission.section-lift{ 455 border-radius:40px 40px 0 0; 456 } 457 .pin-stack > #mission.section-lift::after{border-radius:40px 40px 0 0} 458} 459@media (prefers-reduced-motion:reduce){ 460 .pin-stack > #mission.section-lift{ 461 transform:none;transition:none;margin-top:0 !important; 462 } 463} 464@media (prefers-reduced-motion:reduce){ 465 .pin-stack > .is-pinned-bg{position:relative} 466} 467 468/* Section-level z-index plumbing so .atmos and .bg-cartograph sit 469 strictly behind every text / card / video layer. Each section is 470 its own stacking context (isolation:isolate) so the cartograph 471 can never bleed into an adjacent section. 472 .biomes is intentionally excluded from overflow:hidden because it 473 houses a position:sticky pin â overflow on a sticky parent breaks 474 the stick behavior and produces a tall black gap. */ 475.proof, .watch-section, .promise, .biomes, .anchor, .convert, .hp-promise{position:relative;isolation:isolate}
476.anchor, .promise, .convert, .hp-promise{overflow:hidden} 477 478/* =========================================================== 479 100% PROMISE section â full-bleed video, big "100%" number, 480 trust statement headline, supporting copy, verification chips. 481 =========================================================== */ 482.hp-promise{ 483 position:relative;height:100vh; 484 padding:var(--pad-section) 0; 485 background:#000; 486 text-align:center; 487 color:var(--bone); 488 overflow:hidden;isolation:isolate; 489 display:grid;place-items:center; 490} 491.hp-promise .hp-video{ 492 position:absolute;inset:0;width:100%;height:100%;object-fit:cover; 493 z-index:0; 494 filter:saturate(1.18) contrast(1.06); 495} 496.hp-promise .hp-overlay{ 497 position:absolute;inset:0;z-index:1;pointer-events:none; 498 background: 499 /* Centred dark "stage" â pools dark behind the text in the middle 500 of the section, fades to transparent at the corners so the video 501 shows full colour at the edges. Replaces the heavy global scrim. */ 502 radial-gradient(70% 55% at 50% 50%, rgba(2,7,24,.25) 0%, rgba(2,7,24,.12) 50%, rgba(2,7,24,0) 80%), 503 /* Subtle ink edge framing so the section reads as bounded */ 504 linear-gradient(180deg, rgba(2,7,24,.22) 0%, transparent 18%, transparent 82%, rgba(2,7,24,.22) 100%), 505 /* Two on-brand green ambient hints, low opacity, off-centre */ 506 radial-gradient(28% 22% at 12% 22%, rgba(168,243,65,.05), transparent 70%), 507 radial-gradient(28% 22% at 88% 78%, rgba(42,122,59,.06), transparent 70%); 508} 509.hp-promise .wrap{ 510 position:relative;z-index:2; 511 display:grid;gap:clamp(16px,2vw,28px); 512 justify-items:center;align-items:center; 513 text-align:center; 514} 515.hp-promise .eyebrow{margin:0 auto 8px} 516.hp-promise .hp-pct{ 517 font-family:var(--display);font-weight:900; 518 font-size:clamp(96px,15vw,210px); 519 line-height:.9;letter-spacing:-.04em; 520 color:var(--bone); 521 text-shadow:0 0 80px rgba(168,243,65,.25); 522 display:flex;align-items:baseline;justify-content:center;gap:8px; 523 /* This line is wider than the 1080px .wrap, so it was overflowing to the 524 right (off-centre). Make it full-bleed and centre it in the viewport. */ 525 width:100vw;max-width:100vw;margin:0 calc(50% - 50vw); 526} 527.hp-promise .hp-pct em{ 528 font-style:italic;font-weight:500; 529 color:var(--leaf);-webkit-text-fill-color:var(--leaf); 530} 531.hp-promise .hp-headline{ 532 font-family:var(--display);font-weight:900; 533 font-size:clamp(28px,3.8vw,52px); 534 line-height:1.1;letter-spacing:-.025em; 535 max-width:26ch;margin:0 auto; 536 color:var(--bone); 537 text-shadow:none; 538} 539.hp-promise .hp-headline em{ 540 font-style:italic;font-weight:500; 541 color:var(--leaf);-webkit-text-fill-color:var(--leaf); 542} 543.hp-promise .hp-supporting{ 544 max-width:62ch;margin:0 auto; 545 font-size:clamp(15px,1.3vw,18px);line-height:1.55; 546 color:var(--bone); 547 opacity:.92; 548 text-shadow:none; 549} 550.hp-promise .hp-chips{ 551 display:flex;flex-wrap:wrap;justify-content:center;gap:10px;margin-top:12px; 552} 553.hp-promise .hp-chip{ 554 display:inline-flex;align-items:center;gap:8px; 555 padding:9px 16px;border-radius:4px; 556 background:rgba(2,7,24,.55);backdrop-filter:blur(12px); 557 -webkit-backdrop-filter:blur(12px); 558 box-shadow:inset 0 0 0 1px rgba(168,243,65,.30); 559 font-family:var(--display);font-weight:700;font-size:12px; 560 letter-spacing:.06em;color:var(--bone); 561} 562.hp-promise .hp-tick{ 563 display:inline-flex;align-items:center;justify-content:center; 564 width:16px;height:16px;border-radius:50%; 565 background:var(--leaf);color:var(--ink); 566 font-size:10px;font-weight:900; 567 box-shadow:0 0 8px var(--leaf-glow); 568} 569@media (max-width:720px){ 570 .hp-promise .hp-pct{font-size:clamp(64px,16vw,128px)} 571 .hp-promise .hp-headline{font-size:clamp(22px,5.5vw,30px);max-width:20ch} 572 .hp-promise .hp-chips{gap:6px} 573 .hp-promise .hp-chip{font-size:10px;padding:7px 12px} 574} 575.proof > .wrap, .watch-section > .wrap, .promise > .wrap{position:relative;z-index:2} 576.anchor > .wrap, .convert > .reveal-stagger, .convert > .pawtrail{position:relative;z-index:2} 577 578/* =========================================================== 579 Cartographic background illustration 580 Elegant explorer-style line art used as depth-of-field on the
581 plain-background sections (anchor, promise, convert). Sits 582 strictly behind every text and content layer, never crosses 583 section bounds (overflow + clip-path safety), and parallaxes 584 subtly on scroll via --scroll-y. 585 =========================================================== */ 586.bg-cartograph{ 587 position:absolute;inset:0;width:100%;height:100%; 588 pointer-events:none;z-index:0; /* behind everything in the section */ 589 overflow:hidden; 590 clip-path:inset(0); /* hard clip so parallax can't bleed */ 591 opacity:1; 592} 593.bg-cartograph svg{ 594 position:absolute;inset:0;width:100%;height:100%; 595 overflow:hidden; /* SVG content also clipped */ 596 /* Parallax lives on the SVG, contained by the overflow-hidden wrapper */ 597 transform:translateY(calc(var(--scroll-y, 0) * -0.06px)); 598 will-change:transform; 599} 600.bg-cartograph .bg-lat{ 601 stroke:rgba(168,243,65,.18);stroke-width:.6; 602 stroke-dasharray:3 14;fill:none; 603} 604.bg-cartograph .bg-trail{ 605 stroke:rgba(168,243,65,.45);stroke-width:1.2; 606 stroke-linecap:round;fill:none; 607} 608.bg-cartograph .bg-trail-soft{ 609 stroke:rgba(168,243,65,.30);stroke-width:.8; 610 stroke-dasharray:2 9;stroke-linecap:round;fill:none; 611} 612.bg-cartograph .bg-compass{ 613 fill:none; 614} 615.bg-cartograph .bg-compass .bg-compass-ring{ 616 stroke:rgba(168,243,65,.34);stroke-width:.8; 617} 618.bg-cartograph .bg-compass .bg-compass-tick{ 619 stroke:rgba(168,243,65,.26);stroke-width:.55; 620} 621.bg-cartograph .bg-compass .bg-compass-arrow{ 622 fill:rgba(168,243,65,.26); 623 stroke:rgba(168,243,65,.55);stroke-width:.65; 624 stroke-linejoin:round; 625} 626.bg-cartograph .bg-compass-label{ 627 fill:rgba(168,243,65,.75);stroke:none; 628 font-family:'Red Hat Display',system-ui,sans-serif; 629 font-size:11px;font-weight:800;letter-spacing:.12em; 630} 631.bg-cartograph .bg-track{ 632 fill:rgba(168,243,65,.60); 633 stroke:rgba(168,243,65,.45);stroke-width:.45; 634} 635.bg-cartograph .bg-coord-text{ 636 fill:rgba(168,243,65,.65);stroke:none; 637 font-family:'Red Hat Display',system-ui,sans-serif; 638 font-size:10px;font-weight:700;letter-spacing:.22em; 639 text-transform:uppercase; 640} 641.bg-cartograph .bg-marker{ 642 fill:none;stroke:rgba(168,243,65,.55);stroke-width:.7; 643} 644.bg-cartograph .bg-marker .bg-marker-dot{ 645 fill:rgba(168,243,65,.75);stroke:none; 646} 647/* Mirrored composition for variety in adjacent sections */ 648.bg-cartograph.is-mirror svg{transform:scaleX(-1)} 649.bg-cartograph.is-mirror .bg-compass-label{transform:scaleX(-1);transform-origin:center} 650@media (max-width:720px){ 651 .bg-cartograph{opacity:.55} 652 .bg-cartograph .bg-compass-label, .bg-cartograph .bg-coord-text{display:none} 653} 654@media (prefers-reduced-motion:reduce){ 655 .bg-cartograph{transform:none} 656} 657 658 659/* Ambient mouse-follow green glow (background atmosphere) */ 660.ambient-glow{ 661 position:fixed;top:50%;left:50%; 662 width:820px;height:820px; 663 pointer-events:none;z-index:0; 664 border-radius:50%; 665 background:radial-gradient(circle, rgba(168,243,65,.30) 0%, rgba(168,243,65,.14) 30%, rgba(168,243,65,.06) 55%, transparent 70%); 666 filter:blur(50px); 667 transform:translate(-50%, -50%); 668 mix-blend-mode:screen; 669 opacity:0; 670 transition:opacity 1.2s; 671 will-change:transform, filter; 672 animation:glowBreathe 7s ease-in-out infinite alternate; 673} 674.ambient-glow.is-on{opacity:1} 675@keyframes glowBreathe{ 676 0%{filter:blur(50px) saturate(1);transform:translate(-50%,-50%) scale(1)} 677 50%{filter:blur(60px) saturate(1.2);transform:translate(-50%,-50%) scale(1.12)} 678 100%{filter:blur(48px) saturate(1.05);transform:translate(-50%,-50%) scale(.96)} 679} 680/* On mobile or reduced-motion: auto-drift the glow gently instead of mouse-follow */ 681@media (max-width:880px){ 682 .ambient-glow{ 683 width:520px;height:520px; 684 opacity:.85; 685 animation:glowDrift 18s ease-in-out infinite alternate, glowBreathe 7s ease-in-out infinite alternate; 686 } 687} 688@keyframes glowDrift{ 689 0%{top:30%;left:25%} 690 50%{top:60%;left:75%} 691 100%{top:45%;left:20%} 692} 693@media (prefers-reduced-motion:reduce){ 694 .ambient-glow{animation:none;opacity:.5} 695} 696 697/* Skip to content (keyboard / screen reader users) */ 698.skip-link{ 699 position:absolute;
699left:12px;top:-100px;z-index:100; 700 background:var(--leaf);color:var(--ink);padding:12px 18px;border-radius:999px; 701 font-weight:700;font-size:14px; 702 transition:top .25s; 703} 704.skip-link:focus{top:12px;outline:2px solid var(--bone);outline-offset:3px} 705 706/* ============ Layout helpers ============ */ 707.wrap{max-width:1080px;margin:0 auto;padding:0 var(--pad-x);position:relative} 708.wrap-narrow{max-width:980px;margin:0 auto;padding:0 var(--pad-x)} 709.section{padding:var(--pad-section) 0} 710.eyebrow{ 711 display:inline-flex;align-items:center;gap:14px; 712 font-family:var(--body);font-size:15px;letter-spacing:.22em; 713 text-transform:uppercase;color:var(--mist);font-weight:500; 714} 715.eyebrow::before{ 716 content:"";width:8px;height:8px;border-radius:50%;flex:0 0 8px; 717 background:var(--leaf);box-shadow:0 0 0 0 var(--leaf-glow); 718 animation:pulse 2.4s ease-out infinite; 719} 720@keyframes pulse{ 721 0%{box-shadow:0 0 0 0 rgba(168,243,65,.45)} 722 70%{box-shadow:0 0 0 14px rgba(168,243,65,0)} 723 100%{box-shadow:0 0 0 0 rgba(168,243,65,0)} 724} 725 726/* ============ Buttons (refined, type-led) ============ */ 727.btn{ 728 display:inline-flex;align-items:center;gap:10px; 729 padding:14px 22px; 730 border-radius:4px; 731 font-family:var(--body);font-weight:600;font-size:14px;letter-spacing:.02em; 732 text-transform:none; 733 transition:background .2s, color .2s, box-shadow .25s; 734 position:relative; 735} 736.btn-primary{ 737 background:var(--leaf);color:var(--ink); 738 box-shadow:inset 0 0 0 1px rgba(0,0,0,.05); 739} 740.btn-primary:hover{ 741 background:#B9F764; 742 box-shadow:inset 0 0 0 1px rgba(0,0,0,.08), 0 0 0 1px rgba(168,243,65,.25); 743} 744.btn-ghost{ 745 background:transparent; 746 color:var(--bone); 747 box-shadow:inset 0 0 0 1px rgba(255,255,255,.16); 748} 749.btn-ghost:hover{ 750 background:rgba(255,255,255,.04); 751 box-shadow:inset 0 0 0 1px rgba(255,255,255,.32); 752} 753.btn .arrow{display:inline-block;transition:transform .25s cubic-bezier(.2,.7,.1,1);font-size:1.05em;line-height:1} 754.btn:hover .arrow{transform:translateX(4px)} 755 756/* Compact / quiet variant â for in-flow links acting as buttons */ 757.btn-quiet{ 758 padding:0;background:none;box-shadow:none;color:var(--bone); 759 font-weight:600;font-size:14px;letter-spacing:.01em; 760 border-bottom:1px solid rgba(255,255,255,.2); 761 border-radius:0; 762 padding-bottom:4px; 763} 764.btn-quiet:hover{color:var(--leaf);border-bottom-color:var(--leaf)} 765 766/* Compact header button (sat tighter inside the bar) */ 767.header-cta .btn{padding:10px 16px;font-size:13px} 768 769/* ============ Header / Nav ============ */ 770.header{ 771 position:fixed;top:0;left:0;right:0;z-index:50; 772 display:flex;align-items:center;justify-content:space-between; 773 padding:18px var(--pad-x); 774 transition:background .35s, backdrop-filter .35s, padding .35s, border-color .35s; 775 background:rgba(2,7,24,.72); 776 backdrop-filter:blur(14px) saturate(140%); 777 -webkit-backdrop-filter:blur(14px) saturate(140%); 778 border-bottom:1px solid var(--line); 779} 780.header.scrolled{ 781 background:rgba(2,7,24,.82); 782 border-bottom-color:var(--line); 783 padding:12px var(--pad-x); 784} 785.brand{ 786 font-family:var(--display);font-weight:900;font-size:22px; 787 letter-spacing:-.02em;display:flex;align-items:center;gap:10px;color:var(--bone); 788} 789.brand-mark{ 790 width:26px;height:26px;border-radius:6px;position:relative; 791 background:radial-gradient(60% 60% at 30% 30%, var(--leaf), var(--leaf-deep)); 792 box-shadow:0 6px 18px -6px var(--leaf-glow); 793} 794.brand-mark::after{ 795 content:"";position:absolute;inset:0;border-radius:6px; 796 background:radial-gradient(2px 2px at 70% 60%, rgba(255,255,255,.7), transparent 60%); 797} 798.nav{display:none;gap:30px;align-items:center} 799.nav a{font-size:14px;color:var(--mist);transition:color .2s} 800.nav a:hover{color:var(--bone)} 801.nav a[aria-current="page"]{color:var(--leaf)} 802/* Dropdown nav (built by /assets/nav.js) â same styling as the rest of the site */ 803.nav-enhanced{gap:8px} 804.nav-group{position:relative;display:inline-flex} 805.nav-trigger{appearance:none;border:0;background:none;cursor:pointer;font-family:var(--body);font-size:14px;font-weight:600;color:var(--mist);padding:8px 14px;border-radius:99px;display:inline-flex;align-items:center;gap:6px;transition:color .2s,background .2s;letter-spacing:0} 806.nav-trigger .nav-chev{font-size:10px;
806color:var(--mist-2);transition:transform .25s ease,color .2s;display:inline-block;line-height:1;margin-top:1px} 807.nav-trigger:hover{color:var(--bone);background:rgba(255,255,255,.04)} 808.nav-trigger:hover .nav-chev{color:var(--leaf)} 809.nav-trigger:focus-visible{outline:2px solid var(--leaf);outline-offset:2px;color:var(--bone)} 810.nav-group.is-open .nav-trigger{color:var(--bone);background:rgba(168,243,65,.08)} 811.nav-group.is-open .nav-trigger .nav-chev{transform:rotate(180deg);color:var(--leaf)} 812.nav-trigger.is-active-section{color:var(--leaf)} 813.nav-trigger.is-active-section .nav-chev{color:var(--leaf)} 814.nav-menu{position:absolute;top:calc(100% + 12px);left:0;z-index:50;min-width:240px;padding:10px 8px;border-radius:14px;background:rgba(7,13,35,.94);border:1px solid rgba(168,243,65,.22);box-shadow:0 24px 60px -16px rgba(0,0,0,.65),0 8px 20px -6px rgba(0,0,0,.45);backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);display:flex;flex-direction:column;gap:2px} 815.nav-menu::before{content:"";position:absolute;left:18px;right:18px;top:0;height:1px;background:linear-gradient(90deg,transparent,rgba(168,243,65,.6),transparent)} 816.nav-menu[hidden]{display:none} 817.nav-menu a{display:flex;align-items:center;padding:9px 14px;border-radius:9px;font-size:13.5px;color:var(--bone);letter-spacing:-.002em;text-decoration:none;transition:background .15s,color .15s} 818.nav-menu a:hover,.nav-menu a:focus-visible{background:rgba(168,243,65,.10);color:var(--leaf);outline:0} 819.nav-menu a[aria-current="page"]{background:rgba(168,243,65,.14);color:var(--leaf)} 820.nav-menu a[aria-current="page"]::before{content:"";width:5px;height:5px;border-radius:50%;background:var(--leaf);box-shadow:0 0 6px var(--leaf-glow);margin-right:8px;flex:0 0 5px} 821.nav-group:nth-last-of-type(-n+2) .nav-menu{left:auto;right:0} 822@media (max-width:1180px){.nav-enhanced{gap:4px}.nav-trigger{padding:8px 10px}} 823.header-cta{display:flex;gap:12px;align-items:center} 824.header-cta .btn-ghost{display:none} 825.menu-btn{display:flex;gap:5px;flex-direction:column;width:30px;padding:6px} 826.menu-btn span{height:1.5px;background:var(--bone);border-radius:2px;transition:.25s} 827.menu-btn.open span:nth-child(1){transform:translateY(6px) rotate(45deg)} 828.menu-btn.open span:nth-child(2){opacity:0} 829.menu-btn.open span:nth-child(3){transform:translateY(-6px) rotate(-45deg)} 830@media (min-width:1024px){ 831 .nav{display:flex} 832 .header-cta .btn-ghost{display:inline-flex} 833 .menu-btn{display:none} 834} 835@media (max-width:560px){ 836 .header-cta .btn{padding:8px 14px;font-size:12px} 837 /* "Support our work" overflows the viewport at this width â drop the 838 primary CTA from the header entirely. The sticky donate bar above 839 the header (.sdb with the "Donate $50" button) already carries a 840 donate CTA, and the burger menu exposes the same link inside. */ 841 .header-cta .btn-primary{display:none} 842 .brand img{height:28px !important} 843} 844.drawer{ 845 position:fixed;inset:0;background:var(--ink);z-index:40; 846 padding:90px var(--pad-x) 40px; 847 transform:translateY(-100%); 848 transition:transform .5s cubic-bezier(.7,0,.2,1); 849 overflow-y:auto; 850} 851.drawer.open{transform:translateY(0)} 852.drawer::before{ 853 content:"";position:absolute;inset:-20%;z-index:-1;pointer-events:none; 854 background: 855 radial-gradient(40% 30% at 25% 25%, rgba(168,243,65,.08), transparent 65%), 856 radial-gradient(40% 30% at 75% 75%, rgba(42,122,59,.10), transparent 65%); 857 filter:blur(60px); 858} 859.drawer-eyebrow{ 860 font-family:var(--body);font-size:11px;letter-spacing:.24em; 861 text-transform:uppercase;color:var(--mist);font-weight:600; 862 display:block;margin-bottom:24px; 863 opacity:0;transform:translateX(-12px);transition:opacity .4s, transform .4s;
863transition-delay:.05s; 864} 865.drawer.open .drawer-eyebrow{opacity:1;transform:translateX(0)} 866.drawer-nav{display:flex;flex-direction:column;gap:0} 867.drawer-nav a{ 868 display:flex;align-items:center;gap:18px; 869 font-family:var(--display);font-size:clamp(20px,5vw,26px);font-weight:700; 870 padding:18px 0;border-bottom:1px solid var(--line); 871 letter-spacing:-.015em;line-height:1.05;color:var(--bone); 872 opacity:0;transform:translateX(-20px); 873 transition:opacity .5s, transform .5s cubic-bezier(.7,0,.2,1), color .25s, padding-left .25s; 874} 875.drawer.open .drawer-nav a{opacity:1;transform:translateX(0)} 876.drawer.open .drawer-nav a:nth-child(1){transition-delay:.08s} 877.drawer.open .drawer-nav a:nth-child(2){transition-delay:.14s} 878.drawer.open .drawer-nav a:nth-child(3){transition-delay:.20s} 879.drawer.open .drawer-nav a:nth-child(4){transition-delay:.26s} 880.drawer.open .drawer-nav a:nth-child(5){transition-delay:.32s} 881.drawer.open .drawer-nav a:nth-child(6){transition-delay:.38s} 882.drawer.open .drawer-nav a:nth-child(7){transition-delay:.44s} 883.drawer-nav a:hover, .drawer-nav a:focus-visible{color:var(--leaf);padding-left:8px} 884.drawer-nav a:last-of-type{border-bottom:0} 885.drawer-icon{ 886 width:32px;height:32px;color:var(--leaf);flex:0 0 32px; 887 display:flex;align-items:center;justify-content:center; 888 border-radius:6px;background:rgba(168,243,65,.06); 889 box-shadow:inset 0 0 0 1px rgba(168,243,65,.2); 890 transition:background .25s, box-shadow .25s; 891} 892.drawer-nav a:hover .drawer-icon{background:rgba(168,243,65,.14);box-shadow:inset 0 0 0 1px rgba(168,243,65,.45)} 893.drawer-icon svg{width:18px;height:18px;stroke:currentColor;stroke-width:1.6;fill:none;stroke-linecap:round;stroke-linejoin:round} 894.drawer-arrow{margin-left:auto;font-size:18px;color:var(--mist-2);transition:color .25s, transform .25s} 895.drawer-nav a:hover .drawer-arrow{color:var(--leaf);transform:translateX(3px)} 896.drawer .btn{ 897 margin-top:32px;width:100%;justify-content:center;font-size:14px;padding:18px 22px; 898 opacity:0;transform:translateY(12px);transition:opacity .5s .55s, transform .5s .55s; 899} 900.drawer.open .btn{opacity:1;transform:translateY(0)} 901.drawer-footer{ 902 margin-top:32px;padding-top:24px;border-top:1px solid var(--line); 903 font-family:var(--body);font-size:12px;color:var(--mist-2); 904 letter-spacing:.02em;display:flex;align-items:center;gap:10px; 905 opacity:0;transform:translateY(8px);transition:opacity .5s .65s, transform .5s .65s; 906} 907.drawer.open .drawer-footer{opacity:1;transform:translateY(0)} 908.drawer-footer .dot{width:6px;height:6px;border-radius:50%;background:var(--leaf);box-shadow:0 0 6px var(--leaf-glow)} 909 910/* ================================================= 911 STAGE 1 â LAND: Cinematic full-bleed hero 912 ================================================= */ 913.hero-stage{ 914 /* Scroll runway. 300vh = ~133vh of video scrub + ~67vh of "cover" phase 915 where the mission card slides up to fully cover the still-pinned 916 hero. Total interactive runway = 200vh. After it, both hero and 917 mission unstick and the page resumes scrolling. The scrub/cover 918 split is computed in JS (SCRUB_END constant). Trimmed from 400vh: 919 usability testing showed the pinned hero read as "the page is stuck" 920 across every input method. */ 921 position:relative;height:300vh;background:var(--ink); 922} 923.hero-pin{ 924 /* THE pinned element. Sticks at top:0 of viewport while the user 925 scrolls through the parent .hero-stage runway. */ 926 position:sticky;top:0; 927 height:100vh;width:100%; 928 display:grid;place-items:end stretch;overflow:hidden;background:#000; 929 z-index:1; 930} 931@media (prefers-reduced-motion:reduce){ 932 .hero-stage{height:100vh} 933 .hero-pin{position:relative} 934} 935.hero-frame{ 936 position:absolute;inset:0; 937 width:100%;height:100%; 938 border-radius:0; 939 overflow:hidden;background:#000; 940} 941@media (min-width:1024px){ 942 /* Subtle inset only on desktop, becomes full-bleed as you scroll */ 943 .hero-frame{ 944 inset:var(--frame-inset,0); 945 border-radius:var(--frame-r,0px); 946 } 947} 948.hero-video{ 949 position:absolute;inset:0;width:100%;height:100%;object-fit:cover; 950 animation:none; 951 will-change:transform; 952} 953 954/* Hero nature carousel â fast cinematic crossfade */ 955.hero-carousel{position:absolute;inset:0;z-index:1;overflow:hidden;background:#000} 956.hero-carousel::after{ 957 content:"";position:absolute;inset:0;z-index:2;pointer-events:none; 958 /* Softer base overlay + gentle vignette so text reads without darkening the video */ 959 background: 960 radial-gradient(120% 80% at 50% 50%, transparent 35%, rgba(0,0,0,.07) 100%), 961 linear-gradient(180deg, rgba(0,0,0,.02) 0%, rgba(0,0,0,.05) 60%, rgba(2,7,24,.14) 100%); 962} 963.hero-carousel .hcv{ 964 position:absolute;inset:0;width:100%;height:100%;object-fit:cover; 965 opacity:0; 966 transform:scale(1.0); 967 transition:opacity 1.1s cubic-bezier(.7,0,.2,1); 968 will-change:opacity;
969 filter:saturate(1.08) contrast(1.08) brightness(.98); 970} 971.hero-carousel .hcv.is-active{ 972 opacity:1; 973 transform:scale(1.0); 974 animation:none; 975} 976@keyframes heroPan{ 977 0%{transform:scale(1.18) translate(0,0)} 978 100%{transform:scale(1.04) translate(-1.5%, -1%)} 979} 980.hero-carousel-progress{ 981 position:absolute;bottom:clamp(20px,3vh,40px);left:50%;transform:translateX(-50%);z-index:5; 982 display:flex;gap:10px; 983} 984.hero-carousel-progress span{ 985 width:32px;height:2px;border-radius:2px; 986 background:rgba(255,255,255,.25); 987 position:relative;overflow:hidden; 988 transition:background .3s; 989} 990.hero-carousel-progress span.is-active{background:rgba(255,255,255,.18)} 991.hero-carousel-progress span.is-active::after{ 992 content:"";position:absolute;left:0;top:0;bottom:0; 993 width:100%;background:var(--leaf); 994 transform-origin:left center;transform:scaleX(0); 995 animation:carouselFill 3s linear forwards; 996 box-shadow:0 0 6px var(--leaf-glow); 997} 998@keyframes carouselFill{ 999 to{transform:scaleX(1)} 1000} 1001@media (prefers-reduced-motion:reduce){ 1002 .hero-carousel .hcv{transition:none} 1003 .hero-carousel .hcv.is-active{animation:none} 1004 .hero-carousel-progress span.is-active::after{animation:none;transform:scaleX(1)} 1005} 1006 1007.hero-img-fallback{ 1008 position:absolute;inset:0; 1009 background:url('https://www.saveelephant.org/wp-content/uploads/2025/08/Lek_with_FaaMaiHerd.jpg') center/cover no-repeat; 1010 filter:saturate(.92) contrast(1.08); 1011 animation:none; 1012} 1013@keyframes slowZoom{ 1014 0%{transform:scale(1.04) translate(0,0)} 1015 100%{transform:scale(1.14) translate(-1.5%,-1%)} 1016} 1017.hero-overlay{ 1018 position:absolute;inset:0;pointer-events:none;z-index:2; 1019 background: 1020 linear-gradient(180deg, rgba(0,0,0,.1) 0%, rgba(0,0,0,0) 28%, rgba(0,0,0,0) 55%, rgba(2,7,24,.37) 100%), 1021 radial-gradient(70% 90% at 50% 45%, rgba(0,0,0,0) 0%, rgba(2,7,24,.22) 100%), 1022 radial-gradient(50% 60% at 80% 90%, rgba(168,243,65,.04), transparent 60%); 1023} 1024.hero-grain{z-index:2} 1025.hero-card-copy{z-index:3} 1026.hero-stats{z-index:3} 1027.hero-fullscreen-copy{z-index:4} 1028.hero-grain{ 1029 position:absolute;inset:0;pointer-events:none;opacity:.06;mix-blend-mode:overlay; 1030 background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 200'><filter id='n'><feTurbulence baseFrequency='1.4' numOctaves='2' stitchTiles='stitch'/></filter><rect width='100%25' height='100%25' filter='url(%23n)' opacity='.55'/></svg>"); 1031} 1032.hero-card-copy{ 1033 position:absolute; 1034 inset:0; 1035 /* Header-safe placement. The old top:40% + translateY(-50%) centring let 1036 the copy stack (whose eyebrow/subtitle/buttons reserve space even while 1037 still opacity:0 pre-reveal) ride up UNDER the fixed header on shorter 1038 viewports â the h1's top line was clipped behind the nav bar. Instead 1039 the copy is a full-bleed overlay: the top padding reserves the header 1040 zone, the larger bottom padding keeps the optical centre high (â the 1041 old 40% placement), and `safe center` packs the stack down from below 1042 the header instead of overflowing the top when it doesn't fit. */ 1043 padding:calc(var(--header-h) + 18px) var(--pad-x) max(22vh, 130px); 1044 transform:translateY(var(--title-y, 0)); 1045 z-index:3;color:var(--bone); 1046 /* --title-op is driven by the scroll-scrub script; falls back to 1 if JS off */ 1047 opacity:var(--title-op, 1); 1048 transition:opacity .15s ease, transform .15s ease; 1049 display:grid; 1050 align-content:center; /* fallback for browsers without `safe` */ 1051 align-content:safe center; 1052 /* Single centred column capped at 1080px â same content width as the 1053 old max-width:1080px card, so the headline wraps identically. */ 1054 grid-template-columns:minmax(0, 1080px); 1055 justify-content:center; 1056 gap:clamp(18px,2.4vw,28px); 1057 text-align:center; 1058 justify-items:center; 1059 /* The overlay spans the whole hero â let clicks fall through to the 1060 video/sound button everywhere except the copy itself. */ 1061 pointer-events:none; 1062} 1063.hero-card-copy > *{pointer-events:auto} 1064.hero-card-copy[data-fade-out="1"] > *{pointer-events:none} 1065 1066/* Scroll-driven sequential reveal â each element fades + slides up 1067 based on a CSS variable set by the hero-scrub script. Pattern: 1068 opacity: var(--{el}-reveal, 0) 1069 transform: translateY(calc(20px * (1 - var(--{el}-reveal, 0)))) 1070 The variables are populated in scrub() based on scroll progress. */ 1071.hero-card-copy h1{ 1072 opacity:var(--title-reveal, 1); 1073 transform:translateY(calc(20px * (1 - var(--title-reveal, 1)))); 1074 transition:opacity .15s ease, transform .15s ease; 1075} 1076.hero-card-copy .eyebrow{ 1077 opacity:var(--eyebrow-reveal, 0); 1078 transform:translateY(calc(20px * (1 - var(--eyebrow-reveal, 0)))); 1079 transition:opacity .15s ease, transform .15s ease; 1080} 1081.hero-card-copy p{ 1082 opacity:var(--subtitle-reveal, 0); 1083 transform:translateY(calc(20px * (1 - var(--subtitle-reveal, 0)))); 1084 transition:opacity .15s ease, transform .15s ease; 1085} 1086.hero-card-copy .hero-actions{ 1087 opacity:var(--buttons-reveal, 0); 1088 transform:translateY(calc(20px * (1 - var(--buttons-reveal, 0)))); 1089 transition:opacity .15s ease, transform .15s ease; 1090} 1091@media (prefers-reduced-motion:reduce){ 1092 .hero-card-copy h1, 1093 .hero-card-copy .eyebrow, 1094 .hero-card-copy p, 1095 .hero-card-copy .hero-actions{ 1096 opacity:1;transform:none;transition:none; 1097 } 1098} 1099@media (max-width:880px){ 1100 .hero-card-copy{ 1101 padding-left:24px; 1102 padding-right:24px; 1103 gap:14px; 1104 } 1105 .hero-card-copy h1{font-size:clamp(38px,9vw,60px);max-width:16ch} 1106 .hero-card-copy p{font-size:14px;max-width:42ch} 1107 .hero-actions{margin-top:4px} 1108} 1109@media (max-width:560px){ 1110 /* On narrow screens the centred eyebrow line can reach the sound 1111 toggle â start the copy below the button's band (header + 14px 1112 offset + 44px button + 8px breathing room). Only bites when the
1113 stack is too tall to centre anyway. */ 1114 .hero-card-copy{padding-top:calc(var(--header-h) + 66px)} 1115} 1116.hero-card-copy .eyebrow{margin-bottom:0} 1117.hero-card-copy h1{ 1118 font-family:var(--display);font-weight:900; 1119 /* Trimmed from clamp(48px,8vw,128px): board feedback (Jul 2026) that the 1120 hero read "too close" â the headline dominated the frame so the wildlife 1121 shot behind it couldn't be seen. Smaller headline lets the picture read. */ 1122 font-size:clamp(30px,4.5vw,69px); 1123 line-height:.92;letter-spacing:-.04em; 1124 max-width:20ch;margin:0 auto; 1125 text-shadow:none; 1126} 1127.hero-card-copy h1 em{font-style:italic;font-weight:500;color:var(--leaf);font-family:var(--display)} 1128.hero-card-copy p{ 1129 max-width:54ch;color:var(--bone); 1130 font-size:clamp(15px,1.4vw,19px);line-height:1.55; 1131 text-shadow:none; 1132 margin:0 auto; 1133} 1134.hero-actions{display:flex;gap:14px;flex-wrap:wrap;align-items:center;justify-content:center;margin-top:6px} 1135@media (max-width:560px){ 1136 .hero-actions{gap:10px} 1137 .hero-actions .btn{flex:1 1 auto;justify-content:center;min-width:140px} 1138} 1139 1140/* Short desktop windows need a different composition: the hero copy, CTAs 1141 and four impact cards cannot all occupy a shallow viewport without the 1142 headline being pushed under the masthead. Keep the promise readable here; 1143 the full impact cards remain the first content below the hero. */ 1144@media (min-width:721px) and (max-height:740px){ 1145 .hero-card-copy{ 1146 padding:calc(var(--header-h) + 10px) var(--pad-x) 36px; 1147 align-content:start; 1148 gap:10px; 1149 } 1150 .hero-card-copy h1{ 1151 font-size:clamp(36px,8vh,58px); 1152 max-width:17ch; 1153 line-height:.9; 1154 } 1155 .hero-card-copy p{max-width:50ch;font-size:14px;line-height:1.42} 1156 .hero-actions{margin-top:2px;gap:10px} 1157 .hero-actions .btn{padding:9px 13px;font-size:10px} 1158 .hero-stats,.hero-stats-eyebrow,.scroll-cue{display:none !important} 1159} 1160 1161.hero-fullscreen-copy{ 1162 position:absolute;inset:0;display:grid;place-items:center;padding:0 var(--pad-x); 1163 z-index:4;pointer-events:none;text-align:center; 1164 opacity:var(--fs-op,0);transform:translateY(var(--fs-y,20px)); 1165 transition:opacity .35s, transform .35s; 1166} 1167.hero-fullscreen-copy > div{pointer-events:auto;max-width:1080px} 1168.hero-fullscreen-copy h2{ 1169 font-family:var(--display);font-weight:900;letter-spacing:-.045em;line-height:.9; 1170 font-size:clamp(56px,12vw,200px); 1171} 1172.hero-fullscreen-copy h2 em{ 1173 font-style:italic;font-weight:500; 1174 1175 1176 color:var(--leaf);-webkit-text-fill-color:var(--leaf); 1177 1178} 1179@keyframes shine{0%{background-position:0 0}100%{background-position:200% 0}} 1180.hero-fullscreen-copy p{ 1181 margin-top:28px;color:var(--bone);font-size:clamp(15px,1.4vw,20px);max-width:48ch;margin-left:auto;margin-right:auto; 1182 text-shadow:none; 1183 line-height:1.5; 1184} 1185 1186/* Hero stats eyebrow â "What we've done so far" label above the strip. 1187 Squared 4px corners to match the rest of the site. */ 1188.hero-stats-eyebrow{ 1189 position:absolute;left:50%; 1190 bottom:calc(clamp(36px,4.5vh,64px) + 250px); 1191 /* translateY(--stats-y) animates the whole stats block (eyebrow + stats) 1192 from centered (negative offset) at scroll progress ~25% down to its 1193 natural bottom-aligned position by progress ~75%. */ 1194 transform:translateX(-50%) translateY(var(--stats-y, 0)); 1195 z-index:3; 1196 display:inline-flex;align-items:center;gap:14px; 1197 padding:14px 28px;border-radius:4px; 1198 background:rgba(2,7,24,.75);backdrop-filter:blur(14px); 1199 -webkit-backdrop-filter:blur(14px); 1200 box-shadow:inset 0 0 0 1px rgba(168,243,65,.55), 1201 0 18px 50px -16px rgba(168,243,65,.45), 1202 0 0 36px rgba(168,243,65,.15); 1203 font-family:var(--display);font-weight:800;font-size:14px; 1204 letter-spacing:.28em;text-transform:uppercase;color:var(--bone); 1205 white-space:nowrap; 1206 /* --stats-eyebrow-reveal driven by scroll-scrub script. Default 0 so 1207 it stays hidden until ~beat 4 of the cascade. */ 1208 opacity:var(--stats-eyebrow-reveal, 0); 1209 transition:opacity .15s ease, transform .15s ease; 1210} 1211.hero-stats-eyebrow .hse-dot{ 1212 width:10px;height:10px;border-radius:50%;background:var(--leaf); 1213 box-shadow:0 0 10px var(--leaf-glow), 0 0 24px rgba(168,243,65,.55); 1214 animation:hseDot 1.6s ease-in-out infinite; 1215 flex:0 0 auto; 1216} 1217.hero-stats-eyebrow .hse-text{position:relative;color:var(--leaf)} 1218@keyframes hseIn{ 1219 from{opacity:0;transform:translate(-50%,16px)} 1220 to {opacity:1;transform:translate(-50%,0)} 1221} 1222@keyframes hseDot{ 1223 0%,100%{opacity:.5;transform:scale(.85)} 1224 50%{opacity:1;transform:scale(1.2)} 1225} 1226@media (max-width:880px){ 1227 .hero-stats-eyebrow{font-size:11px;letter-spacing:.22em;padding:10px 18px;bottom:calc(clamp(28px,4vh,52px) + 340px)} 1228 .hero-stats-eyebrow .hse-dot{width:8px;height:8px} 1229} 1230/* On mobile, the hero-stats overlay collides with the title + CTA block 1231 (viewport is too short to fit both). Hide the overlay entirely â the 1232 same stats live in the impact-report page and are summarised in the 1233 sticky donate bar at the top of the page. */ 1234@media (max-width:720px){ 1235 .hero-stats, 1236 .hero-stats-eyebrow{display:none !important} 1237} 1238@media (prefers-reduced-motion:reduce){ 1239 .hero-stats-eyebrow{animation:none;opacity:1;transform:translateX(-50%)} 1240 .hero-stats-eyebrow .hse-dot{animation:none} 1241} 1242 1243/* Hero stats overlay â 4 across the bottom of the hero, sits clear of the 1244 headline / buttons stack above. On narrow screens drops to 2x2. */ 1245.hero-stats{ 1246 position:absolute; 1247 left:50%; 1248 bottom:clamp(36px,4.5vh,64px); 1249 /* same --stats-y as the eyebrow so they move as one block */ 1250 transform:translateX(-50%) translateY(var(--stats-y, 0)); 1251 width:calc(100% - clamp(96px, 16vw, 260px)); 1252 max-width:1080px; 1253 z-index:3;color:var(--bone); 1254 display:grid;grid-template-columns:repeat(4, 1fr);gap:12px; 1255 /* --stats-reveal driven by scroll-scrub script â beat 5 of the cascade */ 1256 opacity:var(--stats-reveal, 0); 1257 transition:opacity .15s ease, transform .15s ease; 1258} 1259.hstat{ 1260 padding:20px 22px 22px;border-radius:8px; 1261 text-decoration:none;color:inherit;cursor:pointer; 1262 background:rgba(2,7,24,.52);backdrop-filter:blur(14px); 1263 -webkit-backdrop-filter:blur(14px); 1264 box-shadow:inset 0 0 0 1px rgba(255,255,255,.1); 1265 display:grid;grid-template-columns:36px 1fr;gap:6px 14px;align-items:start; 1266 /* Visibility is controlled by the parent .hero-stats via --stats-op CSS 1267 variable driven by the scroll-scrub script. Removed the auto-play 1268 staggered hstatIn animation that previously fought our scroll reveal. */ 1269 opacity:1; 1270 transition:transform .35s ease, box-shadow .35s ease, background .35s ease; 1271} 1272@keyframes hstatIn{ 1273 0% {opacity:0; transform:translateY(20px) scale(.96)} 1274 100% {opacity:1; transform:translateY(0) scale(1)} 1275} 1276.hstat:hover{ 1277 transform:translateY(-4px) scale(1); 1278 background:rgba(2,7,24,.62); 1279 box-shadow:inset 0 0 0 1px rgba(168,243,65,.35), 0 16px 40px -16px rgba(168,243,65,.45); 1280} 1281@media (prefers-reduced-motion:reduce){ 1282 .hstat{animation:none;opacity:1;transform:none} 1283} 1284.hstat .hicon{ 1285 grid-row:1 / span 3; 1286 width:36px;height:36px; 1287 display:flex;align-items:center;justify-content:center; 1288 border-radius:6px;color:var(--leaf); 1289 background:rgba(168,243,65,.10); 1290 box-shadow:inset 0 0 0 1px rgba(168,243,65,.30); 1291 position:relative; 1292 margin-top:6px; 1293} 1294.hstat .hicon svg{width:22px;height:22px;filter:drop-shadow(0 2px 6px rgba(168,243,65,.35))} 1295.hstat .hicon::after{ 1296 content:"";position:absolute;inset:0;border-radius:6px;pointer-events:none; 1297 box-shadow:0 0 0 0 rgba(168,243,65,.4); 1298 animation:iconPulse 2.8s ease-out infinite; 1299} 1300.hstat:nth-child(2) .hicon::after{animation-delay:.5s} 1301.hstat:nth-child(3) .hicon::after{animation-delay:1s} 1302.hstat:nth-child(4) .hicon::after{animation-delay:1.5s} 1303.hstat .hnum{ 1304 font-family:var(--display);font-weight:900;font-size:clamp(36px,4vw,56px); 1305 line-height:1;letter-spacing:-.04em; 1306 color:var(--leaf); 1307 text-shadow:0 2px 24px rgba(168,243,65,.45), 0 0 60px rgba(168,243,65,.25); 1308 display:flex;align-items:baseline;gap:4px; 1309 animation:hnumBreathe 4.5s ease-in-out infinite; 1310} 1311.hstat:nth-child(2) .hnum{animation-delay:.6s} 1312.hstat:nth-child(3) .hnum{animation-delay:1.2s} 1313.hstat:nth-child(4) .hnum{animation-delay:1.8s} 1314@keyframes hnumBreathe{ 1315 0%,100%{text-shadow:0 2px 24px rgba(168,243,65,.45), 0 0 60px rgba(168,243,65,.25)} 1316 50%{text-shadow:0 2px 30px rgba(168,243,65,.75), 0 0 90px rgba(168,243,65,.5)} 1317} 1318@media (prefers-reduced-motion:reduce){ 1319 .hstat .hnum{animation:none} 1320} 1321.hstat .hnum em{font-style:normal;font-weight:600;color:var(--leaf);
1321opacity:.8;font-size:.55em} 1322.hstat .htitle{ 1323 font-family:var(--display);font-weight:800; 1324 font-size:clamp(17px,1.6vw,22px); 1325 line-height:1.15;letter-spacing:-.01em; 1326 color:var(--bone); 1327 margin:6px 0 0; 1328} 1329.hstat .hlbl{ 1330 margin-top:6px;font-size:12.5px;color:var(--mist); 1331 letter-spacing:.01em;line-height:1.45;font-weight:400; 1332} 1333@media (max-width:1100px){ 1334 .hero-stats{grid-template-columns:repeat(2,1fr);gap:10px;max-width:780px} 1335} 1336@media (max-width:880px){ 1337 .hero-stats{ 1338 position:absolute;left:28px;right:28px;top:auto; 1339 bottom:clamp(28px,4vh,52px); 1340 max-width:none; 1341 grid-template-columns:repeat(2,1fr);gap:8px; 1342 transform:none; 1343 } 1344 .hstat{padding:14px 14px 16px;grid-template-columns:30px 1fr;gap:4px 10px} 1345 .hstat .hicon{width:30px;height:30px;margin-top:4px} 1346 .hstat .hnum{font-size:clamp(26px,5vw,34px)} 1347 .hstat .htitle{font-size:14px;margin-top:4px} 1348 .hstat .hlbl{font-size:11px;letter-spacing:0;line-height:1.35} 1349} 1350@media (max-width:560px){ 1351 .hero-stats{grid-template-columns:repeat(2,1fr);gap:8px} 1352} 1353 1354.scroll-cue{ 1355 position:absolute;left:50%;bottom:28px;transform:translateX(-50%);z-index:5; 1356 display:flex;flex-direction:column;align-items:center;gap:8px; 1357 font-size:11px;letter-spacing:.2em;text-transform:uppercase;color:var(--mist); 1358 opacity:var(--cue-op,1);transition:opacity .3s; 1359} 1360.scroll-cue .bar{width:1px;height:44px;background:linear-gradient(180deg, transparent, var(--mist));position:relative;overflow:hidden} 1361.scroll-cue .bar::after{content:"";position:absolute;left:0;right:0;top:-40%;height:40%;background:var(--leaf);animation:slide 2s linear infinite} 1362@keyframes slide{0%{transform:translateY(0)}100%{transform:translateY(300%)}} 1363 1364/* ================================================= 1365 LIVE TICKER â sequel.co-style chip strip 1366 ================================================= */ 1367.ticker{ 1368 position:relative;background:var(--ink-80); 1369 border-top:1px solid var(--line);border-bottom:1px solid var(--line); 1370 padding:14px 0;overflow:hidden; 1371 mask-image:linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent); 1372 -webkit-mask-image:linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent); 1373} 1374.ticker-rail{display:flex;gap:18px;flex:0 0 auto;animation:tickerScroll 80s linear infinite;will-change:transform} 1375@keyframes tickerScroll{to{transform:translateX(-50%)}} 1376.ticker:hover .ticker-rail{animation-play-state:paused} 1377.tchip{ 1378 display:inline-flex;align-items:center;gap:10px;flex:0 0 auto; 1379 padding:9px 16px 9px 12px;border-radius:6px; 1380 background:rgba(255,255,255,.04);box-shadow:inset 0 0 0 1px var(--line-2); 1381 font-family:var(--body);font-size:13px;color:var(--bone);font-weight:500; 1382 white-space:nowrap;letter-spacing:-.005em; 1383} 1384@media (max-width:560px){ 1385 .tchip{padding:7px 12px 7px 10px;font-size:11.5px;gap:8px} 1386 .tchip .tlabel{font-size:9.5px} 1387 .tchip .tmeta{font-size:11px} 1388} 1389.tchip .tdot{ 1390 width:8px;height:8px;border-radius:50%;background:var(--leaf);flex:0 0 8px; 1391 box-shadow:0 0 0 0 var(--leaf-glow); 1392 animation:pulse 2.4s ease-out infinite; 1393} 1394.tchip .tlabel{ 1395 font-family:var(--display);font-weight:700;font-size:11px;letter-spacing:.16em; 1396 text-transform:uppercase;color:var(--leaf);margin-right:2px; 1397} 1398.tchip strong{color:var(--bone);font-weight:700} 1399.tchip .tmeta{color:var(--mist-2);margin-left:4px;font-size:12px} 1400.tchip.is-live{background:rgba(168,243,65,.08);box-shadow:inset 0 0 0 1px rgba(168,243,65,.25)} 1401.tchip.is-premiere{background:rgba(240,194,95,.06);box-shadow:inset 0 0 0 1px rgba(240,194,95,.2)} 1402.tchip.is-premiere .tdot{background:var(--sun);animation:none;box-shadow:0 0 12px rgba(240,194,95,.5)} 1403.tchip.is-premiere .tlabel{color:var(--sun)} 1404 1405/* ================================================= 1406 STAGE 2 â ANCHOR: cinematic mission typography 1407 ================================================= */ 1408.anchor{ 1409 position:relative;padding:clamp(100px,18vh,200px) clamp(28px,6vw,120px);text-align:center; 1410 background:var(--ink);overflow:hidden; 1411} 1412.anchor::before{ 1413 content:"";position:absolute;inset:-25%;z-index:0;pointer-events:none; 1414 background: 1415 radial-gradient(38% 32% at 28% 38%, rgba(168,243,65,.34), transparent 62%), 1416 radial-gradient(48% 38% at 78% 58%, rgba(42,122,59,.38), transparent 62%), 1417 radial-gradient(28% 22% at 50% 80%, rgba(126,225,136,.20), transparent 70%); 1418 filter:blur(70px); 1419 animation:drift 22s ease-in-out infinite alternate, glowBreathe 9s ease-in-out infinite; 1420} 1421@keyframes drift{ 1422 0% {transform:translate(0,0) scale(1)} 1423 50% {transform:translate(-3%,2%) scale(1.05)} 1424 100%{transform:translate(3%,-2%) scale(.97)} 1425} 1426@keyframes glowBreathe{ 1427 0%,100%{opacity:.82} 1428 50% {opacity:1} 1429} 1430@media (prefers-reduced-motion:reduce){ 1431 .anchor::before, .globe-section::before, .promise::before, .convert::before{animation:none} 1432} 1433.anchor .wrap{position:relative;z-index:2}
1434.anchor .eyebrow{margin-bottom:36px} 1435.anchor h2{ 1436 font-family:var(--display);font-weight:900;letter-spacing:-.035em;line-height:.92; 1437 font-size:clamp(48px,7.5vw,120px); 1438 max-width:16ch;margin:0 auto; 1439} 1440.anchor h2 em{ 1441 font-style:italic;font-weight:500; 1442 1443 1444 color:var(--leaf);-webkit-text-fill-color:var(--leaf); 1445 1446} 1447.anchor p{ 1448 margin-top:32px;max-width:60ch;margin-left:auto;margin-right:auto; 1449 color:var(--mist);font-size:clamp(17px,1.5vw,21px); 1450} 1451 1452/* ================================================= 1453 STAGE 2.5 â LIVE STATS STRIP 1454 ================================================= */ 1455.impact{ 1456 background:linear-gradient(180deg, var(--ink) 0%, var(--ink-80) 100%); 1457 border-top:1px solid var(--line);border-bottom:1px solid var(--line); 1458 position:relative;overflow:hidden; 1459} 1460.impact .wrap{position:relative;z-index:2} 1461.impact-grid{ 1462 display:grid;grid-template-columns:1fr 1fr;gap:28px 20px; 1463 padding:48px var(--pad-x); 1464 max-width:1080px;margin:0 auto; 1465} 1466@media (min-width:720px){ 1467 .impact-grid{grid-template-columns:repeat(4,1fr);gap:20px} 1468} 1469.stat-icon{ 1470 position:relative; 1471 width:40px;height:40px;color:var(--leaf); 1472 margin-bottom:18px;display:flex;align-items:center;justify-content:center; 1473 border-radius:6px;background:rgba(168,243,65,.06); 1474 box-shadow:inset 0 0 0 1px rgba(168,243,65,.18); 1475} 1476.stat-icon svg{width:26px;height:26px;filter:drop-shadow(0 2px 8px rgba(168,243,65,.35))} 1477.stat-icon::after{ 1478 content:"";position:absolute;inset:0;border-radius:6px;pointer-events:none; 1479 box-shadow:0 0 0 0 rgba(168,243,65,.35); 1480 animation:iconPulse 3s ease-out infinite; 1481} 1482.impact .reveal-stagger > *:nth-child(2) .stat-icon::after{animation-delay:.4s} 1483.impact .reveal-stagger > *:nth-child(3) .stat-icon::after{animation-delay:.8s} 1484.impact .reveal-stagger > *:nth-child(4) .stat-icon::after{animation-delay:1.2s} 1485.stat-num{ 1486 font-family:var(--display);font-weight:900;font-size:clamp(30px,3.6vw,52px); 1487 line-height:1;letter-spacing:-.04em; 1488 background:linear-gradient(180deg, var(--bone) 0%, #8c91a3 100%); 1489 -webkit-background-clip:text;background-clip:text;color:transparent; 1490 white-space:nowrap;overflow:hidden;text-overflow:clip; 1491} 1492.stat-label{color:var(--mist);margin-top:12px;font-size:14px;max-width:28ch;line-height:1.45} 1493.stat-bar{height:2px;background:var(--line);margin-top:24px;position:relative;overflow:hidden;border-radius:99px} 1494.stat-bar::after{ 1495 content:"";position:absolute;left:0;top:0;bottom:0;width:40%; 1496 background:linear-gradient(90deg, var(--leaf-deep), var(--leaf)); 1497 transform:translateX(-100%); 1498 animation:barFill 2.6s 1.2s cubic-bezier(.7,0,.2,1) forwards; 1499 box-shadow:0 0 16px var(--leaf-glow); 1500} 1501@keyframes barFill{to{transform:translateX(0)}} 1502 1503/* ================================================= 1504 PROOF SECTION â three concrete case wins 1505 ================================================= */ 1506.proof{ 1507 position:relative;padding:var(--pad-section) 0; 1508 background:var(--ink); 1509} 1510.proof .s-head{margin-bottom:40px} 1511
1512/* === Section heads with side panel â unified pattern === */ 1513.proof .s-head .row, 1514.broll-section .s-head .row{align-items:flex-start;gap:48px;flex-wrap:wrap} 1515.proof .s-head .row .row-left, 1516.broll-section .s-head .row .row-left{ 1517 flex:1 1 480px;min-width:0; 1518 display:flex;flex-direction:column;align-items:flex-start;gap:22px; 1519} 1520.proof .s-head .row .row-left h2, 1521.broll-section .s-head .row .row-left h2{margin:0} 1522.proof .s-head .row .row-left p, 1523.broll-section .s-head .row .row-left p{ 1524 margin:0;font-size:21px;line-height:1.45; 1525 max-width:46ch;color:var(--mist); 1526} 1527.proof .s-head .row .row-left .btn, 1528.proof .s-head .row .row-left .btn-quiet, 1529.broll-section .s-head .row .row-left .btn, 1530.broll-section .s-head .row .row-left .btn-quiet{margin-top:6px} 1531/* bigger H2s for these sections */ 1532.proof .s-head h2, 1533.broll-section .s-head h2{font-size:clamp(48px,6vw,88px) !important} 1534.proof .s-head .row .row-side, 1535.broll-section .s-head .row .row-side{ 1536 flex:1 1 360px;max-width:440px; 1537 display:flex;flex-direction:column;align-items:flex-end;gap:18px; 1538} 1539 1540/* === Projects section â matching head + panel === */ 1541.hscroll-pin .hscroll-head{align-items:flex-start;flex-wrap:wrap} 1542.hscroll-pin .hscroll-head-text{flex:1 1 480px;min-width:0;gap:22px} 1543.hscroll-pin .hscroll-head h2{font-size:clamp(48px,6vw,88px) !important;margin:0} 1544.hscroll-pin .hscroll-head-text p{font-size:21px !important;line-height:1.45;max-width:46ch;margin:0} 1545.hscroll-pin .hscroll-head-text .btn-ghost{margin-top:6px;align-self:flex-start} 1546.hscroll-pin .hscroll-head-side{ 1547 flex:1 1 360px;max-width:440px; 1548 display:flex;flex-direction:column;align-items:flex-end;gap:18px; 1549} 1550.projects-panel{ 1551 position:relative;width:100%; 1552 padding:22px 24px; 1553 border-radius:18px; 1554 background:linear-gradient(180deg,rgba(168,243,65,.06),rgba(168,243,65,.015)); 1555 border:1px solid rgba(168,243,65,.2); 1556 backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px); 1557 overflow:hidden; 1558} 1559.projects-panel::before{ 1560 content:"";position:absolute;left:0;top:0;bottom:0;width:3px; 1561 background:linear-gradient(180deg,var(--leaf),rgba(168,243,65,.15)); 1562} 1563.projects-panel .pp-head{ 1564 display:flex;align-items:baseline;justify-content:space-between; 1565 margin-bottom:14px; 1566} 1567.projects-panel .pp-title{ 1568 font-family:var(--body);font-weight:600; 1569 font-size:11px;letter-spacing:.22em;text-transform:uppercase; 1570 color:var(--bone);display:inline-flex;align-items:center;gap:8px; 1571} 1572.projects-panel .pp-title::before{ 1573 content:"";width:7px;height:7px;border-radius:50%; 1574 background:var(--leaf);box-shadow:0 0 0 0 var(--leaf-glow); 1575 animation:pulse 2.4s ease-out infinite; 1576} 1577.projects-panel .pp-live{ 1578 font-family:var(--display);font-weight:800; 1579 font-size:10px;letter-spacing:.22em; 1580 color:var(--leaf);text-transform:uppercase; 1581 padding:3px 8px;border-radius:999px; 1582 border:1px solid rgba(168,243,65,.4); 1583 background:rgba(168,243,65,.08); 1584} 1585.projects-panel .pp-feature{ 1586 display:block;text-decoration:none;color:inherit; 1587 padding:14px 14px 14px 16px;border-radius:12px; 1588 background:rgba(2,7,24,.42); 1589 border:1px solid rgba(168,243,65,.18); 1590 margin-bottom:14px; 1591 transition:border-color .25s ease, transform .25s ease, background .25s ease; 1592} 1593.projects-panel .pp-feature:hover{border-color:rgba(168,243,65,.5);transform:translateY(-1px);background:rgba(2,7,24,.55)} 1594.projects-panel .pp-feature .pp-label{ 1595 font-family:var(--body);font-weight:600; 1596 font-size:10px;letter-spacing:.22em;text-transform:uppercase; 1597 color:#ff8a5b;margin-bottom:6px; 1598 display:flex;align-items:center;gap:6px; 1599} 1600.projects-panel .pp-feature .pp-name{ 1601 font-family:var(--display);font-weight:700; 1602 font-size:17px;letter-spacing:-.005em;color:var(--bone); 1603 line-height:1.2;margin-bottom:6px; 1604} 1605.projects-panel .pp-feature .pp-bar{ 1606 position:relative;height:5px;border-radius:999px; 1607 background:rgba(255,255,255,.06);overflow:hidden;margin-bottom:8px; 1608} 1609.projects-panel .pp-feature .pp-fill{ 1610 position:absolute;left:0;top:0;bottom:0;width:28%; 1611 background:linear-gradient(90deg, var(--leaf), #B9F764); 1612 border-radius:999px; 1613} 1614.projects-panel .pp-feature .pp-meta{ 1615 font-size:12px;
1615color:var(--mist);letter-spacing:.02em; 1616 display:flex;justify-content:space-between; 1617} 1618.projects-panel .pp-feature .pp-meta b{color:var(--leaf);font-weight:700} 1619.projects-panel .pp-divider{ 1620 height:1px;border:0;margin:4px -4px 14px; 1621 background-image:linear-gradient(90deg, rgba(168,243,65,.04), rgba(168,243,65,.22) 50%, rgba(168,243,65,.04)); 1622} 1623.projects-panel .pp-list{display:flex;flex-direction:column;gap:12px} 1624.projects-panel .pp-row{display:flex;align-items:center;gap:14px;font-family:var(--body)} 1625.projects-panel .pp-icon{ 1626 flex:0 0 34px;width:34px;height:34px;border-radius:9px; 1627 border:1px solid rgba(168,243,65,.32); 1628 background:rgba(2,7,24,.4); 1629 display:flex;align-items:center;justify-content:center; 1630 color:var(--leaf); 1631} 1632.projects-panel .pp-icon svg{width:18px;height:18px} 1633.projects-panel .pp-num{ 1634 font-family:var(--display);font-weight:800; 1635 font-size:20px;letter-spacing:-.01em;color:var(--bone); 1636 min-width:60px;line-height:1; 1637} 1638.projects-panel .pp-num em{ 1639 font-style:normal;font-weight:600;color:var(--leaf); 1640 font-size:.62em;margin-left:2px;letter-spacing:.04em; 1641} 1642.projects-panel .pp-text{flex:1 1 auto;min-width:0;font-size:12.5px;line-height:1.35;color:var(--mist)} 1643 1644@media (max-width:880px){ 1645 .proof .s-head .row, 1646 .broll-section .s-head .row{align-items:stretch;gap:32px} 1647 .proof .s-head .row .row-left, 1648 .proof .s-head .row .row-side, 1649 .broll-section .s-head .row .row-left, 1650 .broll-section .s-head .row .row-side{flex:1 1 100%;max-width:none} 1651 .proof .s-head .row .row-side, 1652 .broll-section .s-head .row .row-side{align-items:flex-start} 1653 .hscroll-pin .hscroll-head{gap:32px} 1654 .hscroll-pin .hscroll-head-text, 1655 .hscroll-pin .hscroll-head-side{flex:1 1 100%;max-width:none} 1656 .hscroll-pin .hscroll-head-side{align-items:flex-start} 1657} 1658.impacts-panel{ 1659 position:relative;width:100%; 1660 padding:22px 24px; 1661 border-radius:18px; 1662 background:linear-gradient(180deg,rgba(168,243,65,.06),rgba(168,243,65,.015)); 1663 border:1px solid rgba(168,243,65,.2); 1664 backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px); 1665 overflow:hidden; 1666} 1667.impacts-panel::before{ 1668 content:"";position:absolute;left:0;top:0;bottom:0;width:3px; 1669 background:linear-gradient(180deg,var(--leaf),rgba(168,243,65,.15)); 1670} 1671.impacts-head{ 1672 display:flex;align-items:baseline;justify-content:space-between; 1673 margin-bottom:16px;padding-bottom:14px; 1674 border-bottom:1px dashed rgba(168,243,65,.22); 1675} 1676.impacts-title{ 1677 font-family:var(--body);font-weight:600; 1678 font-size:11px;letter-spacing:.22em;text-transform:uppercase; 1679 color:var(--bone); 1680} 1681.impacts-title b{color:var(--leaf);font-weight:600;margin-right:6px} 1682.impacts-year{ 1683 font-family:var(--display);font-weight:700; 1684 font-size:12px;letter-spacing:.18em;color:rgba(168,243,65,.85); 1685} 1686.impacts-list{display:flex;flex-direction:column;gap:14px} 1687.impact-row{ 1688 display:flex;align-items:center;gap:14px; 1689 font-family:var(--body); 1690} 1691.impact-icon{ 1692 flex:0 0 38px;width:38px;height:38px; 1693 border-radius:10px; 1694 border:1px solid rgba(168,243,65,.32); 1695 background:rgba(2,7,24,.4); 1696 display:flex;align-items:center;justify-content:center; 1697 color:var(--leaf); 1698} 1699.impact-icon svg{width:20px;height:20px} 1700.impact-num{ 1701 font-family:var(--display);font-weight:800; 1702 font-size:24px;letter-spacing:-.01em; 1703 color:var(--bone);min-width:96px;line-height:1; 1704} 1705.impact-num em{ 1706 font-style:normal;font-weight:600;color:var(--leaf); 1707 font-size:.7em;margin-left:2px;letter-spacing:.04em; 1708} 1709.impact-label{ 1710 flex:1 1 auto;min-width:0; 1711 font-size:13px;line-height:1.35;color:var(--mist); 1712} 1713@media (max-width:880px){ 1714 .proof .s-head .row{align-items:stretch} 1715 .proof .s-head .row > h2, 1716 .proof .s-head .row .row-side{flex:1 1 100%;max-width:none} 1717 .proof .s-head .row .row-side{align-items:flex-start} 1718} 1719 1720/* === Stories from the field: now on the channel side panel === */ 1721.broll-section .s-head .row{align-items:flex-start;gap:48px;flex-wrap:wrap} 1722.broll-section .s-head .row > h2{flex:1 1 480px;min-width:0} 1723.broll-section .s-head .row .row-side{ 1724 flex:1 1 360px;max-width:440px; 1725 display:flex;flex-direction:column;align-items:flex-end;
1725gap:18px; 1726} 1727.stories-panel{ 1728 position:relative;width:100%; 1729 padding:22px 24px; 1730 border-radius:18px; 1731 background:linear-gradient(180deg,rgba(168,243,65,.06),rgba(168,243,65,.015)); 1732 border:1px solid rgba(168,243,65,.2); 1733 backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px); 1734 overflow:hidden; 1735} 1736.stories-panel::before{ 1737 content:"";position:absolute;left:0;top:0;bottom:0;width:3px; 1738 background:linear-gradient(180deg,var(--leaf),rgba(168,243,65,.15)); 1739} 1740.stories-head{ 1741 display:flex;align-items:baseline;justify-content:space-between; 1742 margin-bottom:14px; 1743} 1744.stories-title{ 1745 font-family:var(--body);font-weight:600; 1746 font-size:11px;letter-spacing:.22em;text-transform:uppercase; 1747 color:var(--bone);display:inline-flex;align-items:center;gap:8px; 1748} 1749.stories-title::before{ 1750 content:"";width:7px;height:7px;border-radius:50%; 1751 background:#ff5b5b;box-shadow:0 0 0 0 rgba(255,91,91,.6); 1752 animation:liveBlip 1.6s ease-out infinite; 1753} 1754@keyframes liveBlip{ 1755 0% {box-shadow:0 0 0 0 rgba(255,91,91,.55)} 1756 100% {box-shadow:0 0 0 10px rgba(255,91,91,0)} 1757} 1758.stories-live{ 1759 font-family:var(--display);font-weight:800; 1760 font-size:10px;letter-spacing:.22em; 1761 color:#ff5b5b;text-transform:uppercase; 1762 padding:3px 8px;border-radius:999px; 1763 border:1px solid rgba(255,91,91,.5); 1764 background:rgba(255,91,91,.08); 1765} 1766.top-story{ 1767 display:block;text-decoration:none;color:inherit; 1768 padding:14px 14px 14px 16px;border-radius:12px; 1769 background:rgba(2,7,24,.42); 1770 border:1px solid rgba(168,243,65,.18); 1771 margin-bottom:14px; 1772 transition:border-color .25s ease, transform .25s ease, background .25s ease; 1773} 1774.top-story:hover{border-color:rgba(168,243,65,.5);transform:translateY(-1px);background:rgba(2,7,24,.55)} 1775.top-story .ts-label{ 1776 font-family:var(--body);font-weight:600; 1777 font-size:10px;letter-spacing:.22em;text-transform:uppercase; 1778 color:rgba(168,243,65,.85);margin-bottom:6px; 1779 display:flex;align-items:center;gap:6px; 1780} 1781.top-story .ts-title{ 1782 font-family:var(--display);font-weight:700; 1783 font-size:17px;letter-spacing:-.005em;color:var(--bone); 1784 line-height:1.2;margin-bottom:4px; 1785} 1786.top-story .ts-meta{ 1787 font-size:12px;color:var(--mist);letter-spacing:.02em; 1788} 1789.top-story .ts-meta b{color:var(--leaf);font-weight:600} 1790.stories-divider{ 1791 height:1px;background:rgba(168,243,65,.18); 1792 margin:4px -4px 14px;border:0; 1793 background-image:linear-gradient(90deg, rgba(168,243,65,.04), rgba(168,243,65,.22) 50%, rgba(168,243,65,.04)); 1794} 1795.stories-list{display:flex;flex-direction:column;gap:12px} 1796.story-row{ 1797 display:flex;align-items:center;gap:14px; 1798 font-family:var(--body); 1799} 1800.story-icon{ 1801 flex:0 0 34px;width:34px;height:34px; 1802 border-radius:9px; 1803 border:1px solid rgba(168,243,65,.32); 1804 background:rgba(2,7,24,.4); 1805 display:flex;align-items:center;justify-content:center; 1806 color:var(--leaf); 1807} 1808.story-icon svg{width:18px;height:18px} 1809.story-num{ 1810 font-family:var(--display);font-weight:800; 1811 font-size:20px;letter-spacing:-.01em; 1812 color:var(--bone);min-width:78px;line-height:1; 1813} 1814.story-num em{ 1815 font-style:normal;font-weight:600;color:var(--leaf); 1816 font-size:.62em;margin-left:2px;letter-spacing:.04em; 1817} 1818.story-label{ 1819 flex:1 1 auto;min-width:0; 1820 font-size:12.5px;line-height:1.35;color:var(--mist); 1821} 1822@media (max-width:880px){ 1823 .broll-section .s-head .row{align-items:stretch} 1824 .broll-section .s-head .row > h2, 1825 .broll-section .s-head .row .row-side{flex:1 1 100%;max-width:none} 1826 .broll-section .s-head .row .row-side{align-items:flex-start} 1827} 1828.proof-grid{display:grid;grid-template-columns:1fr;gap:18px} 1829@media (min-width:880px){.proof-grid{grid-template-columns:repeat(3,1fr);gap:22px}} 1830.pcard{ 1831 position:relative;border-radius:var(--r-lg);overflow:hidden; 1832 min-height:480px;display:flex;flex-direction:column;justify-content:space-between; 1833 padding:24px;isolation:isolate; 1834 background:var(--ink-60); 1835 transition:transform .6s cubic-bezier(.22,.9,.3,1), box-shadow .5s; 1836 box-shadow:0 30px 60px -30px rgba(0,0,0,.5), inset 0 0 0 1px rgba(255,255,255,.04); 1837 will-change:transform; 1838} 1839.pcard:hover{ 1840 transform:translateY(-12px) scale(1.015); 1841 box-shadow: 1842 0 60px 120px -30px rgba(0,0,0,.85), 1843 0 30px 60px -20px rgba(168,243,65,.30), 1844 inset 0 0 0 1px rgba(168,243,65,.55); 1845} 1846.pcard .pbg{ 1847 position:absolute;inset:0;z-index:-2;background-size:cover;background-position:center;
1848 filter:saturate(1.06) brightness(.82); 1849 transition:filter .5s, transform 1s cubic-bezier(.2,.7,.1,1); 1850} 1851.pcard .pvideo{ 1852 position:absolute;inset:0;z-index:-2;width:100%;height:100%;object-fit:cover; 1853 filter:saturate(1.06) brightness(.82); 1854 transition:filter .5s, transform 1s cubic-bezier(.2,.7,.1,1); 1855} 1856.pcard:hover .pbg, .pcard:hover .pvideo{filter:saturate(1.14) brightness(.96);transform:scale(1.08)} 1857/* brighter card image -> lean on a feathered text-shadow so copy stays legible */ 1858.pcard .pnum,.pcard .pcaption,.pcard .pdesc,.pcard .plink, 1859.pcard .coord-stamp,.pcard .coord-stamp *,.pcard .ptag,.pcard .ptag *, 1860.pcard .peyebrow{text-shadow:0 2px 16px rgba(2,7,24,.82),0 0 42px rgba(2,7,24,.6)} 1861 1862/* Internal hover animations â number shimmer, tag glow, link slide */ 1863.pcard .pnum{transition:transform .5s cubic-bezier(.22,.9,.3,1), text-shadow .5s} 1864.pcard:hover .pnum{ 1865 transform:translateX(2px) scale(1.04); 1866 text-shadow:0 0 32px rgba(168,243,65,.6), 0 4px 14px rgba(168,243,65,.35); 1867} 1868.pcard .ptag{transition:box-shadow .35s, transform .35s, background .35s} 1869.pcard:hover .ptag{ 1870 background:rgba(2,7,24,.65); 1871 box-shadow:inset 0 0 0 1px rgba(168,243,65,.55), 1872 0 10px 30px -8px rgba(168,243,65,.40); 1873 transform:translateY(-1px); 1874} 1875.pcard .plink{ 1876 position:relative;transition:color .3s, letter-spacing .35s; 1877} 1878.pcard:hover .plink{color:#D3FA9E;letter-spacing:.06em} 1879.pcard .plink::after{ 1880 content:"";position:absolute;left:0;right:0;bottom:-3px;height:1px; 1881 background:linear-gradient(90deg, var(--leaf), #D3FA9E); 1882 transform:scaleX(0);transform-origin:left; 1883 transition:transform .5s cubic-bezier(.22,.9,.3,1); 1884} 1885.pcard:hover .plink::after{transform:scaleX(1)} 1886 1887/* Ambient continuous breathing on each card's stat number (gentle glow pulse) */ 1888.pcard .pnum{animation:pcardBreathe 6s ease-in-out infinite} 1889.pcard:nth-child(2) .pnum{animation-delay:-2s} 1890.pcard:nth-child(3) .pnum{animation-delay:-4s} 1891@keyframes pcardBreathe{ 1892 0%,100%{filter:drop-shadow(0 0 12px rgba(168,243,65,.18))} 1893 50% {filter:drop-shadow(0 0 28px rgba(168,243,65,.45))} 1894} 1895 1896/* Cards themselves drift gently â soft up-down float, each on its 1897 own offset so the row breathes out of phase. Suspended in place. */ 1898.pcard{animation:pcardFloat 9s ease-in-out infinite} 1899.pcard:nth-child(2){animation-delay:-3s;animation-duration:8s} 1900.pcard:nth-child(3){animation-delay:-6s;animation-duration:10s} 1901@keyframes pcardFloat{ 1902 0%,100%{transform:translateY(0)} 1903 50% {transform:translateY(-8px)} 1904} 1905/* Hover overrides the float â explicit lift takes priority */ 1906.pcard:hover{ 1907 animation-play-state:paused; 1908} 1909 1910@media (prefers-reduced-motion:reduce){ 1911 .pcard, .pcard .pnum{animation:none;transition:none} 1912 .pcard:hover{transform:none} 1913} 1914 1915/* Dramatic scroll-in entrance for proof cards â rise with slight rotate, 1916 staggered between siblings. Triggered when .proof-grid gets .in. */ 1917.proof-grid.reveal-stagger > .pcard{ 1918 opacity:0;transform:translateY(60px) rotateX(8deg) scale(.96); 1919 transform-origin:50% 100%; 1920 transition:opacity 1s cubic-bezier(.22,.9,.3,1), 1921 transform 1.1s cubic-bezier(.22,.9,.3,1); 1922} 1923.proof-grid.reveal-stagger.in > .pcard{ 1924 opacity:1;transform:translateY(0) rotateX(0) scale(1); 1925} 1926.proof-grid.reveal-stagger.in >
1926 .pcard:nth-child(1){transition-delay:.05s} 1927.proof-grid.reveal-stagger.in > .pcard:nth-child(2){transition-delay:.18s} 1928.proof-grid.reveal-stagger.in > .pcard:nth-child(3){transition-delay:.31s} 1929.pcard::after{ 1930 content:"";position:absolute;inset:0;z-index:-1;pointer-events:none; 1931 background:linear-gradient(180deg, rgba(2,7,24,.05) 0%, rgba(2,7,24,.02) 40%, rgba(2,7,24,.11) 100%); 1932} 1933.pcard .ptag{ 1934 display:inline-flex;align-items:center;gap:8px;align-self:start; 1935 font-size:10.5px;letter-spacing:.2em;text-transform:uppercase;color:var(--bone);font-weight:600; 1936 padding:5px 10px;border-radius:3px;background:rgba(0,0,0,.5);backdrop-filter:blur(6px); 1937 box-shadow:inset 0 0 0 1px rgba(255,255,255,.1); 1938} 1939.pcard .ptag .pdot{width:6px;height:6px;border-radius:50%;background:var(--leaf);box-shadow:0 0 6px var(--leaf-glow)} 1940.pcard .picon-tr{ 1941 position:absolute;top:18px;right:18px;z-index:3; 1942 width:56px;height:56px;border-radius:8px; 1943 display:flex;align-items:center;justify-content:center; 1944 color:var(--leaf);background:rgba(2,7,24,.55);backdrop-filter:blur(14px); 1945 box-shadow:inset 0 0 0 1px rgba(168,243,65,.4); 1946} 1947.pcard .picon-tr svg{width:32px;height:32px;filter:drop-shadow(0 2px 8px rgba(168,243,65,.4))} 1948.pcard .picon-tr::after{ 1949 content:"";position:absolute;inset:0;border-radius:6px;pointer-events:none; 1950 box-shadow:0 0 0 0 rgba(168,243,65,.4); 1951 animation:iconPulse 3s ease-out infinite; 1952} 1953.pcard:nth-child(2) .picon-tr::after{animation-delay:.6s} 1954.pcard:nth-child(3) .picon-tr::after{animation-delay:1.2s} 1955.pcard .pbody{display:grid;gap:10px} 1956.pcard .pnum{ 1957 font-family:var(--display);font-weight:900;font-size:clamp(46px,5.5vw,72px); 1958 line-height:.9;letter-spacing:-.04em;color:var(--bone); 1959} 1960.pcard .pnum em{font-style:italic;font-weight:500;color:var(--leaf)} 1961.pcard .pcaption{font-family:var(--display);font-weight:700;font-size:18px;line-height:1.15;color:var(--bone);letter-spacing:-.015em;max-width:22ch} 1962.pcard .pdesc{color:var(--mist);font-size:14px;line-height:1.5;max-width:36ch} 1963.pcard .plink{ 1964 display:inline-flex;align-items:center;gap:6px; 1965 font-size:13px;font-weight:600;color:var(--bone); 1966 padding:0 0 4px 0;border-bottom:1px solid rgba(255,255,255,.25);align-self:start; 1967 transition:color .25s, border-color .25s; 1968} 1969.pcard .plink:hover{color:var(--leaf);border-bottom-color:var(--leaf)} 1970 1971/* ================================================= 1972 STAGE 3 â DISCOVER: Pinned pillars 1973 ================================================= */ 1974.pillars{position:relative;background:var(--ink-80)} 1975.pillars-head{padding:var(--pad-section) 0 30px;text-align:center} 1976.pillars-head h2{font-size:clamp(36px,4.5vw,68px);max-width:24ch;margin:18px auto 0} 1977.pillars-head h2 em{font-style:italic;font-weight:500;color:var(--leaf)} 1978.pillars-head p{max-width:62ch;margin:22px auto 0;color:var(--mist);font-size:18px} 1979 1980.pillars-grid{ 1981 position:relative; 1982 display:grid;grid-template-columns:1fr;gap:0; 1983} 1984@media (min-width:960px){ 1985 .pillars-grid{grid-template-columns:1fr 1fr;align-items:start} 1986} 1987.pillars-media{ 1988 position:relative;height:60vh;order:-1; 1989} 1990@media (min-width:960px){ 1991 .pillars-media{position:sticky;top:0;height:100vh;order:0} 1992} 1993.pillars-media .frame{ 1994 position:absolute;inset:clamp(20px,4vw,60px); 1995 border-radius:var(--r-lg);overflow:hidden;background:var(--ink); 1996 box-shadow:0 60px 100px -40px rgba(0,0,0,.6), inset 0 0 0 1px rgba(255,255,255,.06); 1997} 1998.pillars-media .slide{ 1999 position:absolute;inset:0;background-size:cover;background-position:center; 2000 opacity:0;transition:opacity .9s cubic-bezier(.2,.7,.1,1), transform 6s ease-out; 2001 transform:scale(1.04); 2002} 2003.pillars-media .slide.active{opacity:1;transform:scale(1)} 2004.pillars-media .slide::after{ 2005 content:"";position:absolute;inset:0; 2006 background:linear-gradient(180deg, rgba(0,0,0,0) 30%, rgba(2,7,24,.26) 100%); 2007} 2008.pillars-media .badge{ 2009 position:absolute;left:24px;bottom:24px;z-index:2;color:var(--bone);font-size:14px; 2010 display:flex;gap:10px;align-items:center; 2011 padding:8px 12px;border-radius:3px;background:rgba(0,0,0,.5);backdrop-filter:blur(6px); 2012 box-shadow:inset 0 0 0 1px rgba(255,255,255,.1); 2013} 2014.pillars-media .badge .dot{width:8px;height:8px;border-radius:50%;background:var(--leaf)} 2015 2016.pillars-text{display:flex;flex-direction:column} 2017.pillar{ 2018 padding:clamp(80px,12vh,140px) clamp(24px,5vw,80px); 2019 min-height:90vh;display:flex;flex-direction:column;justify-content:center;gap:18px; 2020} 2021.pillar .picon{ 2022 width:44px;height:44px;color:var(--leaf); 2023 display:flex;align-items:center;justify-content:center; 2024 border-radius:6px;background:rgba(168,243,65,.06); 2025 box-shadow:inset 0 0 0 1px rgba(168,243,65,.18); 2026 margin-bottom:18px; 2027} 2028.pillar .picon svg{width:30px;height:30px;filter:drop-shadow(0 2px 8px rgba(168,243,65,.35))} 2029@keyframes iconDraw{to{stroke-dashoffset:0}} 2030/* Looping pulse on the second stroke for active pillar */ 2031.pillar.in .picon::after{ 2032 content:"";position:absolute;width:44px;height:44px;border-radius:6px; 2033 box-shadow:0 0 0 0 rgba(168,243,65,.35); 2034 animation:iconPulse 2.8s ease-out infinite; 2035 pointer-events:none; 2036} 2037.pillar .picon{position:relative} 2038@keyframes iconPulse{ 2039 0%{box-shadow:0 0 0 0 rgba(168,243,65,.4)} 2040 70%{box-shadow:0 0 0 10px rgba(168,243,65,0)} 2041 100%{box-shadow:0 0 0 0 rgba(168,243,65,0)} 2042} 2043.pillar .num{font-family:var(--display);font-weight:900;color:var(--leaf);font-size:14px;letter-spacing:.2em} 2044.pillar h3{font-family:var(--display);font-weight:800;font-size:clamp(32px,3.4vw,52px);max-width:18ch;letter-spacing:-.02em;line-height:1.02} 2045.pillar h3 em{font-style:italic;font-weight:500;color:var(--leaf)}
2046.pillar p{color:var(--mist);font-size:18px;max-width:48ch;line-height:1.6} 2047.pillar ul{list-style:none;display:grid;gap:10px;color:var(--bone);font-size:15px;margin-top:8px} 2048.pillar ul li{padding-left:22px;position:relative} 2049.pillar ul li::before{content:"";position:absolute;left:0;top:.6em;width:10px;height:10px;border-radius:50%;background:var(--leaf);box-shadow:0 0 12px var(--leaf-glow)} 2050.pillar .cta{margin-top:6px;align-self:flex-start} 2051 2052/* ================================================= 2053 BIOME SCROLLYTELLING â pinned cinematic parallax 2054 ================================================= */ 2055.biomes{position:relative;height:300vh;background:#000} 2056.biomes-pin{position:sticky;top:0;height:100vh;width:100%;overflow:hidden;display:grid;place-items:center} 2057.biome-layer{ 2058 position:absolute;inset:0;width:100%;height:100%;object-fit:cover; 2059 opacity:0;transition:opacity 1.2s cubic-bezier(.7,0,.2,1), transform 6s linear; 2060 transform:scale(1.06); 2061 filter:saturate(.95) contrast(1.05); 2062 z-index:1; 2063} 2064.biome-layer.is-active{opacity:1;transform:scale(1)} 2065.biomes-overlay{ 2066 position:absolute;inset:0;z-index:2;pointer-events:none; 2067 background: 2068 linear-gradient(180deg, rgba(2,7,24,.06) 0%, rgba(2,7,24,0) 25%, rgba(2,7,24,0) 55%, rgba(2,7,24,.37) 100%), 2069 radial-gradient(70% 90% at 50% 45%, rgba(0,0,0,0) 0%, rgba(2,7,24,.16) 100%); 2070} 2071.biomes-grain{ 2072 position:absolute;inset:0;z-index:3;pointer-events:none;opacity:.05;mix-blend-mode:overlay; 2073 background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 200'><filter id='n'><feTurbulence baseFrequency='1.4' numOctaves='2' stitchTiles='stitch'/></filter><rect width='100%25' height='100%25' filter='url(%23n)' opacity='.55'/></svg>"); 2074} 2075.biomes-copy-wrap{ 2076 position:absolute;inset:0;z-index:4;display:grid;place-items:center; 2077 padding:0 var(--pad-x); 2078 pointer-events:none; 2079} 2080.biome-text{ 2081 position:absolute;max-width:1080px;text-align:center; 2082 padding-left:var(--pad-x);padding-right:var(--pad-x); 2083 opacity:0;transform:translateY(20px); 2084 transition:opacity .9s cubic-bezier(.2,.7,.1,1), transform .9s cubic-bezier(.2,.7,.1,1); 2085 pointer-events:none; 2086} 2087@media (max-width:720px){ 2088 .biome-text{text-align:left;align-self:end;padding-bottom:80px} 2089 .biomes-copy-wrap{place-items:end stretch} 2090} 2091.biome-text.is-active{opacity:1;transform:translateY(0);pointer-events:auto} 2092.biome-eyebrow{ 2093 display:inline-flex;align-items:center;gap:12px; 2094 font-family:var(--body);font-size:11px;letter-spacing:.22em;text-transform:uppercase; 2095 color:var(--bone);font-weight:600; 2096 padding:8px 14px;border-radius:3px; 2097 background:rgba(2,7,24,.45);backdrop-filter:blur(10px); 2098 box-shadow:inset 0 0 0 1px rgba(255,255,255,.1); 2099} 2100.biome-eyebrow .bnum{color:var(--leaf);font-family:var(--display);font-weight:800;letter-spacing:0} 2101.biome-eyebrow .bdot{width:6px;height:6px;border-radius:50%;background:var(--leaf);box-shadow:0 0 8px var(--leaf-glow);animation:pulse 2.4s ease-out infinite} 2102.biome-text h2{ 2103 font-family:var(--display);font-weight:900;letter-spacing:-.035em;line-height:.95; 2104 font-size:clamp(42px,7vw,108px);margin-top:24px; 2105 text-shadow:none; 2106 color:var(--bone); 2107} 2108.biome-text h2 em{ 2109 font-style:italic;font-weight:500; 2110 2111 2112 color:var(--leaf);-webkit-text-fill-color:var(--leaf); 2113 2114} 2115.biome-text p{ 2116 margin:22px auto 0;max-width:54ch;color:var(--bone); 2117 font-size:clamp(15px,1.3vw,18px);line-height:1.55; 2118 text-shadow:none; 2119} 2120.biome-text .b-stat{ 2121 display:inline-block;margin-top:32px;padding:12px 18px;border-radius:4px; 2122 font-family:var(--body);font-weight:600;font-size:13px;letter-spacing:.01em; 2123 background:rgba(2,7,24,.5);backdrop-filter:blur(10px); 2124 color:var(--bone); 2125 box-shadow:inset 0 0 0 1px rgba(168,243,65,.3); 2126} 2127.biome-text .b-stat strong{color:var(--leaf)} 2128 2129.biomes-progress{ 2130 position:absolute;right:clamp(20px,3vw,40px);top:50%;transform:translateY(-50%); 2131 z-index:5;display:flex;flex-direction:column;gap:18px; 2132 font-family:var(--display);font-weight:700;font-size:11px;letter-spacing:.16em; 2133} 2134.bchip{ 2135 display:flex;align-items:center;gap:10px;
2135color:var(--mist); 2136 opacity:.5;transition:opacity .4s, color .4s; 2137} 2138.bchip::before{ 2139 content:"";display:inline-block;width:24px;height:1px;background:var(--mist); 2140 transition:background .4s, width .4s; 2141} 2142.bchip.is-active{opacity:1;color:var(--bone)} 2143.bchip.is-active::before{background:var(--leaf);width:40px;box-shadow:0 0 6px var(--leaf-glow)} 2144.bchip span{white-space:nowrap} 2145@media (max-width:720px){ 2146 .biomes-progress{right:14px;gap:12px;font-size:10px} 2147 .bchip::before{width:14px} 2148 .bchip.is-active::before{width:24px} 2149 .bchip span{display:none} 2150} 2151 2152/* ================================================= 2153 STAGE 4 â BREATHE: full-bleed quote moment 2154 ================================================= */ 2155.breathe{ 2156 position:relative;min-height:80vh;display:flex;align-items:center; 2157 background:#000; 2158 isolation:isolate;overflow:hidden; 2159} 2160.breathe .breathe-video{ 2161 position:absolute;inset:0;width:100%;height:100%;object-fit:cover; 2162 z-index:-2; 2163 filter:saturate(1.05) contrast(1.05); 2164} 2165.breathe-poster{ 2166 position:absolute;inset:0;z-index:-3; 2167 background:url('https://fwi.or.id/wp-content/uploads/2023/08/DJI_0692-1.jpg') center/cover no-repeat; 2168 filter:saturate(1.05) contrast(1.05); 2169 animation:slowZoom 30s ease-in-out infinite alternate; 2170} 2171.breathe::after{ 2172 content:"";position:absolute;inset:0;z-index:-1;pointer-events:none; 2173 background: 2174 linear-gradient(180deg, rgba(2,7,24,.22), rgba(2,7,24,.35)), 2175 radial-gradient(60% 50% at 50% 50%, rgba(0,0,0,0) 30%, rgba(2,7,24,.22) 100%); 2176} 2177.breathe blockquote{ 2178 font-family:var(--display);font-weight:500;font-style:italic;font-size:clamp(28px,4vw,58px); 2179 line-height:1.15;letter-spacing:-.02em;max-width:24ch; 2180 text-shadow:none; 2181} 2182.breathe cite{ 2183 display:flex;align-items:center;gap:14px; 2184 font-style:normal;font-family:var(--body);font-weight:600;font-size:13px; 2185 letter-spacing:.18em;text-transform:uppercase;color:var(--bone);margin-top:32px; 2186} 2187.breathe cite::before{ 2188 content:"";display:inline-block;width:36px;height:1px;background:var(--leaf); 2189 box-shadow:0 0 8px var(--leaf-glow); 2190} 2191 2192/* ================================================= 2193 STAGE 5 â TRUST: Projects bento + testimonials 2194 ================================================= */ 2195.s-head{display:grid;gap:24px;margin-bottom:60px} 2196.s-head h2{font-size:clamp(36px,4.5vw,68px);font-weight:800;max-width:20ch;letter-spacing:-.025em} 2197.s-head h2 em{font-style:italic;font-weight:500;color:var(--leaf)} 2198.s-head p{max-width:60ch;color:var(--mist);font-size:18px} 2199.s-head .row{display:flex;justify-content:space-between;align-items:flex-end;flex-wrap:wrap;gap:24px} 2200 2201.proj-grid{display:grid;grid-template-columns:1fr;gap:20px} 2202@media (min-width:720px){.proj-grid{grid-template-columns:repeat(2,1fr)}} 2203@media (min-width:1100px){.proj-grid{grid-template-columns:repeat(3,1fr);gap:24px}} 2204 2205/* ================================================= 2206 HORIZONTAL SCROLL â magnesia.cz pattern 2207 Section pins for ~5 viewport-heights and the inner track 2208 translates left as the user scrolls down. Re-uses the 2209 project-card markup verbatim â adds a wrapping container. 2210 ================================================= */ 2211/* Projects section â clean responsive grid (no horizontal scroll mechanic) */ 2212.hscroll-stage{ 2213 position:relative;background:var(--ink); 2214 padding:clamp(48px,7vh,96px) 0 var(--pad-section); 2215} 2216.hscroll-pin{position:relative;display:block} 2217.hscroll-pin .hscroll-head{ 2218 padding:0 var(--pad-x); 2219 margin-bottom:48px; 2220 display:flex;justify-content:space-between;align-items:flex-start;gap:48px;flex-wrap:wrap; 2221 max-width:1080px;margin-left:auto;margin-right:auto; 2222} 2223.hscroll-pin .hscroll-head-text{flex:1 1 480px;min-width:0;display:flex;flex-direction:column;align-items:flex-start;gap:22px} 2224.hscroll-pin .hscroll-head-text .eyebrow{margin-bottom:0} 2225.hscroll-pin .hscroll-head h2{margin:0;font-size:clamp(48px,6vw,88px);font-weight:800;letter-spacing:-.025em;line-height:1} 2226.hscroll-pin .hscroll-head h2 em{font-style:italic;font-weight:500;color:var(--leaf)} 2227.hscroll-pin .hscroll-head-text p{color:var(--mist);margin:0;max-width:46ch;font-size:21px;line-height:1.45} 2228.hscroll-pin .hscroll-head-text .btn-ghost{margin-top:6px;align-self:flex-start} 2229 2230/* === "See all <span data-livestat="projects">34</span> projects" â large primary CTA ===
2231 Replaces the old small btn-ghost. Made deliberately large so it's 2232 the obvious next step when a visitor finishes the carousel. */ 2233.hp-see-all-cta{ 2234 align-self:flex-start;margin-top:14px; 2235 display:inline-flex;align-items:center;gap:14px; 2236 padding:22px 36px;border-radius:14px; 2237 font-family:var(--display);font-weight:900; 2238 font-size:clamp(18px,1.6vw,22px);letter-spacing:.005em; 2239 background:var(--leaf);color:var(--ink) !important; 2240 border:1px solid var(--leaf);text-decoration:none; 2241 box-shadow:0 16px 40px -8px rgba(168,243,65,.55), 2242 0 4px 12px rgba(0,0,0,.35); 2243 transition:transform .25s cubic-bezier(.2,.7,.2,1), 2244 box-shadow .25s, background .25s; 2245 position:relative;z-index:3; 2246} 2247.hp-see-all-cta .arrow{ 2248 display:inline-block;font-weight:900;font-size:1.15em;line-height:1; 2249 transition:transform .25s cubic-bezier(.2,.7,.2,1); 2250} 2251.hp-see-all-cta:hover{ 2252 background:#B9F764;transform:translateY(-3px); 2253 box-shadow:0 22px 52px -8px rgba(168,243,65,.7), 2254 0 8px 16px rgba(0,0,0,.4); 2255} 2256.hp-see-all-cta:hover .arrow{transform:translateX(6px)} 2257.hp-see-all-cta:active{transform:translateY(-1px) scale(.98)} 2258@media (max-width:560px){ 2259 .hp-see-all-cta{padding:18px 26px;font-size:16px;gap:10px} 2260} 2261 2262/* Bottom-of-section centered CTA + supporting line */ 2263.hp-projects-foot{ 2264 display:flex;flex-direction:column;align-items:center;gap:14px; 2265 margin:42px auto 0;max-width:780px;text-align:center; 2266 position:relative;z-index:3; 2267} 2268.hp-see-all-cta--center{align-self:center} 2269.hp-projects-foot-note{ 2270 font-family:var(--body);font-size:13px;color:var(--mist-2); 2271 letter-spacing:.04em;margin:0;line-height:1.5; 2272} 2273 2274.hscroll-pin .hscroll-head-side{ 2275 flex:1 1 360px;max-width:440px; 2276 display:flex;flex-direction:column;align-items:flex-end;gap:18px; 2277} 2278@media (max-width:880px){ 2279 .hscroll-pin .hscroll-head{gap:32px} 2280 .hscroll-pin .hscroll-head-text, 2281 .hscroll-pin .hscroll-head-side{flex:1 1 100%;max-width:none} 2282 .hscroll-pin .hscroll-head-side{align-items:flex-start} 2283} 2284 2285/* ===== Near-me geolocate strip (cartograph theme) ===== */ 2286.nearme{ 2287 position:relative; 2288 margin:8px auto 38px; 2289 max-width:calc(1080px - var(--pad-x) * 2); 2290 width:calc(100% - var(--pad-x) * 2); 2291 padding:18px 22px; 2292 display:flex;align-items:center;gap:18px;flex-wrap:wrap; 2293 background:linear-gradient(180deg, rgba(168,243,65,.05), rgba(168,243,65,.015)); 2294 border:1px solid rgba(168,243,65,.18); 2295 border-radius:16px; 2296 backdrop-filter:blur(8px); 2297 -webkit-backdrop-filter:blur(8px); 2298 font-family:var(--body); 2299} 2300.nearme::before{ 2301 content:"";position:absolute;left:0;top:0;bottom:0;width:3px; 2302 background:linear-gradient(180deg,var(--leaf),rgba(168,243,65,.2)); 2303} 2304.nearme-ring{ 2305 position:relative;width:44px;height:44px;flex:0 0 44px; 2306 border:1px solid rgba(168,243,65,.55); 2307 border-radius:50%; 2308 display:flex;align-items:center;justify-content:center; 2309} 2310.nearme-ring::before{ 2311 content:"";position:absolute;inset:6px;border-radius:50%; 2312 border:1px dashed rgba(168,243,65,.4); 2313 animation:nearmeSpin 18s linear infinite; 2314} 2315.nearme-ring svg{width:22px;height:22px;color:var(--leaf);position:relative;z-index:1} 2316@keyframes nearmeSpin{to{transform:rotate(360deg)}} 2317.nearme-label{ 2318 font-size:11px;letter-spacing:.22em;text-transform:uppercase; 2319 color:rgba(255,255,255,.6);font-weight:600; 2320 display:flex;flex-direction:column;gap:4px; 2321} 2322.nearme-label b{ 2323 font-family:var(--display);font-weight:700; 2324 font-size:16px;letter-spacing:.04em;text-transform:none;color:var(--bone); 2325} 2326.nearme-coords{ 2327 font-family:var(--display);font-weight:700; 2328 font-size:14px;letter-spacing:.16em;text-transform:uppercase; 2329 color:rgba(168,243,65,.9); 2330 padding:8px 14px;border-radius:10px; 2331 background:rgba(2,7,24,.4); 2332 border:1px solid rgba(168,243,65,.22); 2333} 2334.nearme-coords .nm-sep{color:rgba(255,255,255,.35);margin:0 6px} 2335.nearme-nearest{ 2336 flex:1 1 240px;min-width:0; 2337 font-size:14px;color:var(--mist); 2338} 2339.nearme-nearest b{color:var(--bone);font-weight:600} 2340.nearme-nearest .nm-dist{color:var(--leaf);font-weight:600} 2341.nearme-btn{ 2342 appearance:none;border:1px solid rgba(168,243,65,.45); 2343 background:rgba(168,243,65,.08);color:var(--bone); 2344 font-family:var(--display);font-weight:600; 2345 font-size:13px;letter-spacing:.16em;text-transform:uppercase; 2346 padding:11px 18px;border-radius:999px;cursor:pointer; 2347 display:inline-flex;align-items:center;gap:10px; 2348 transition:background .25s ease, border-color .25s ease, transform .25s ease; 2349} 2350.nearme-btn:hover{background:rgba(168,243,65,.15);border-color:var(--leaf);transform:translateY(-1px)} 2351.nearme-btn svg{width:14px;
2351height:14px} 2352.nm-idle, .nm-granted{ 2353 display:flex;align-items:center;gap:14px; 2354 flex:1 1 auto;justify-content:flex-end;flex-wrap:wrap; 2355 min-width:0; 2356} 2357.nm-granted{gap:18px} 2358.nearme[data-state="idle"] .nm-granted, 2359.nearme[data-state="loading"] .nm-granted, 2360.nearme[data-state="error"] .nm-granted{display:none !important} 2361.nearme[data-state="granted"] .nm-idle{display:none !important} 2362.nearme[data-state="loading"] .nearme-btn{opacity:.7;pointer-events:none} 2363.nearme[data-state="error"] .nearme-btn{border-color:rgba(255,180,90,.5);background:rgba(255,180,90,.08)} 2364.nearme-status{ 2365 font-size:12px;letter-spacing:.06em;color:rgba(255,255,255,.5); 2366 font-family:var(--body); 2367} 2368.nearme[data-state="error"] .nearme-status{color:rgba(255,180,90,.85)} 2369/* highlight ring on the nearest card */ 2370.proj-card.is-nearest{ 2371 outline:1px solid rgba(168,243,65,.55); 2372 outline-offset:6px; 2373} 2374.proj-card.is-nearest .coord-stamp{color:var(--leaf)} 2375@media (max-width:760px){ 2376 .nearme{flex-direction:column;align-items:flex-start;padding:16px 18px} 2377 .nearme-coords{font-size:12px;padding:6px 10px} 2378} 2379.hscroll-pin .hscroll-row{ 2380 padding:0 var(--pad-x); 2381 max-width:none;margin:0 auto; 2382 position:relative; 2383} 2384 2385/* === FAN-STACK 3D carousel for the homepage projects strip === 2386 Mirrors the /projects/ implementation so the homepage and the 2387 directory page share the same animation language. Each card is 2388 absolutely positioned; JS computes 3D transforms based on the 2389 signed offset from the active index. Click, drag, wheel, swipe, 2390 prev/next and dots all advance the stack. */ 2391.hscroll-pin .pcs-wrap{position:relative;margin-top:14px} 2392.hscroll-track, 2393.pcs-stage{ 2394 position:relative; 2395 height:560px; 2396 perspective:1300px; 2397 perspective-origin:50% 60%; 2398 overflow:visible; 2399 isolation:isolate; 2400 touch-action:none; 2401 /* override any prior grid/flex behaviour */ 2402 display:block !important; 2403 grid-template-columns:none !important; 2404 flex-wrap:nowrap; 2405 transform:none !important; 2406 user-select:none;-webkit-user-select:none; 2407} 2408.hscroll-track::before, 2409.pcs-stage::before{ 2410 content:"";position:absolute;left:5%;right:5%;top:20%;height:65%; 2411 background:radial-gradient(50% 60% at 50% 70%, rgba(168,243,65,.10), transparent 70%); 2412 pointer-events:none;z-index:0; 2413} 2414.hscroll-track::after, 2415.pcs-stage::after{ 2416 content:"";position:absolute;inset:8px;pointer-events:none; 2417 background: 2418 linear-gradient(rgba(168,243,65,.35), rgba(168,243,65,.35)) top left /14px 1px no-repeat, 2419 linear-gradient(rgba(168,243,65,.35), rgba(168,243,65,.35)) top left /1px 14px no-repeat, 2420 linear-gradient(rgba(168,243,65,.35), rgba(168,243,65,.35)) top right /14px 1px no-repeat, 2421 linear-gradient(rgba(168,243,65,.35), rgba(168,243,65,.35)) top right /1px 14px no-repeat, 2422 linear-gradient(rgba(168,243,65,.35), rgba(168,243,65,.35)) bottom left /14px 1px no-repeat, 2423 linear-gradient(rgba(168,243,65,.35), rgba(168,243,65,.35)) bottom left /1px 14px no-repeat, 2424 linear-gradient(rgba(168,243,65,.35), rgba(168,243,65,.35)) bottom right/14px 1px no-repeat, 2425 linear-gradient(rgba(168,243,65,.35), rgba(168,243,65,.35)) bottom right/1px 14px no-repeat; 2426 z-index:0; 2427} 2428.hscroll-track .proj-card, 2429.hscroll-track .proj-card.is-featured, 2430.pcs-stage .proj-card{ 2431 position:absolute; 2432 left:50%; 2433 bottom:30px; 2434 width:clamp(280px, 32vw, 440px); 2435 height:460px;min-height:460px; 2436 aspect-ratio:auto; 2437 margin:0; 2438 transform-origin:50% 100%; 2439 transform-style:preserve-3d; 2440 /* Slower easing reads as smoother â was .55s, now .7s with a softer 2441 curve. Plus a no-flash on the perspective transition. */ 2442 transition: 2443 transform .7s cubic-bezier(.32,.72,.32,1), 2444 opacity .35s ease, 2445 filter .45s ease, 2446 box-shadow .35s ease; 2447 will-change:transform, opacity; 2448 backface-visibility:hidden; 2449 cursor:pointer; 2450} 2451.hscroll-track .proj-card.is-active, 2452.pcs-stage .proj-card.is-active{ 2453 cursor:grab; 2454 filter:drop-shadow(0 30px 60px rgba(0,0,0,.55)); 2455} 2456.hscroll-track .proj-card.is-active:active, 2457.pcs-stage .proj-card.is-active:active{cursor:grabbing} 2458/* CTA on every card is ALWAYS clickable â was previously 2459 pointer-events:none on inactive cards, which made the side
2460 cards in the fan stack feel dead. Now the leaf pill responds 2461 on every card; the carousel scoots the card to active AND 2462 navigates because the <a href> fires natively. */ 2463.hscroll-track .proj-card .cta, 2464.pcs-stage .proj-card .cta{pointer-events:auto !important;position:relative;z-index:6} 2465 2466/* Controls (prev / counter / dots / next) */ 2467.hscroll-pin .pcs-controls{ 2468 display:flex;align-items:center;justify-content:center; 2469 gap:18px;margin-top:24px; 2470 position:relative;z-index:5; 2471} 2472.hscroll-pin .pcs-btn{ 2473 width:46px;height:46px;border-radius:50%; 2474 background:rgba(7,13,35,.6); 2475 border:1px solid var(--line-2); 2476 color:var(--bone); 2477 display:flex;align-items:center;justify-content:center; 2478 cursor:pointer;font:inherit;padding:0; 2479 transition:background .2s, border-color .2s, transform .2s, color .2s; 2480} 2481.hscroll-pin .pcs-btn:hover{ 2482 background:rgba(168,243,65,.16); 2483 border-color:rgba(168,243,65,.55); 2484 color:var(--leaf); 2485 transform:scale(1.06); 2486} 2487.hscroll-pin .pcs-btn:disabled{opacity:.3;cursor:default;transform:none} 2488.hscroll-pin .pcs-btn svg{width:18px;height:18px;stroke:currentColor;stroke-width:2.2;fill:none;stroke-linecap:round;stroke-linejoin:round} 2489.hscroll-pin .pcs-counter{ 2490 font-family:'Manrope',sans-serif; 2491 font-size:11px;letter-spacing:.22em;text-transform:uppercase; 2492 color:var(--mist-2);font-variant-numeric:tabular-nums; 2493 min-width:64px;text-align:center; 2494} 2495.hscroll-pin .pcs-counter b{color:var(--leaf);font-weight:700} 2496.hscroll-pin .pcs-dots{ 2497 display:flex;gap:7px;align-items:center; 2498 flex-wrap:wrap;justify-content:center; 2499} 2500.hscroll-pin .pcs-dot{ 2501 width:6px;height:6px;border-radius:50%; 2502 background:rgba(255,255,255,.18); 2503 border:0;padding:0;cursor:pointer; 2504 transition:background .2s, transform .2s, box-shadow .2s; 2505} 2506.hscroll-pin .pcs-dot:hover{background:rgba(255,255,255,.4)} 2507.hscroll-pin .pcs-dot.is-on{ 2508 background:var(--leaf);transform:scale(1.5); 2509 box-shadow:0 0 8px var(--leaf-glow); 2510} 2511/* First-load swipe-hint disabled â the keyframe animation set `transform` 2512 on the same element that the JS layout() updates, causing a visible 2513 jump when the animation released and JS took back over. The dot bar 2514 + drag cursor already telegraph swipeability. */ 2515@media (max-width:640px){ 2516 .hscroll-track, 2517 .pcs-stage{height:480px} 2518 .hscroll-track .proj-card, 2519 .pcs-stage .proj-card{width:min(82vw, 340px);height:420px;min-height:420px} 2520} 2521@media (prefers-reduced-motion:reduce){ 2522 .hscroll-track .proj-card, 2523 .pcs-stage .proj-card{transition:none} 2524} 2525.proj-card.is-featured .meta h3{font-size:clamp(28px,3.2vw,42px);letter-spacing:-.025em;line-height:1} 2526.proj-card.is-featured .featured-flag{ 2527 position:absolute;top:18px;left:18px;z-index:3; 2528 display:inline-flex;align-items:center;gap:8px; 2529 font-family:var(--body);font-size:10.5px;letter-spacing:.22em;text-transform:uppercase;font-weight:600; 2530 color:var(--ink);padding:6px 12px;border-radius:3px; 2531 background:var(--leaf); 2532 box-shadow:0 8px 20px -8px var(--leaf-glow); 2533} 2534.proj-card.is-featured .featured-flag svg{width:12px;height:12px;stroke:var(--ink);stroke-width:2;fill:none;stroke-linecap:round;stroke-linejoin:round} 2535.proj-card.is-featured .founder{ 2536 display:flex;align-items:center;gap:12px;margin-top:6px; 2537} 2538.proj-card.is-featured .founder-avatar{ 2539 width:42px;height:42px;border-radius:50%; 2540 background-size:cover;background-position:center;flex:0 0 42px; 2541 box-shadow:0 0 0 2px rgba(168,243,65,.4), 0 6px 18px -6px rgba(0,0,0,.6); 2542} 2543.proj-card.is-featured .founder-meta{font-family:var(--body);font-size:13px;color:var(--bone);line-height:1.3} 2544.proj-card.is-featured .founder-meta strong{display:block;color:var(--bone);font-weight:700;font-size:14px;letter-spacing:-.005em} 2545.proj-card.is-featured .founder-meta span{color:var(--mist);font-size:12px} 2546.proj-card.is-featured .quote-pull{ 2547 font-family:var(--display);font-style:italic;font-weight:500;font-size:clamp(15px,1.4vw,18px); 2548 line-height:1.4;color:var(--bone);max-width:36ch;margin-top:14px; 2549 border-left:2px solid var(--leaf);padding-left:14px; 2550 text-shadow:none; 2551} 2552.proj-card{ 2553 position:relative;border-radius:var(--r-lg);overflow:hidden; 2554 aspect-ratio:4/5;background:var(--ink-60); 2555 transition:transform .5s cubic-bezier(.2,.7,.1,1.2), box-shadow .4s; 2556 isolation:isolate; 2557 box-shadow:0 30px 60px -30px rgba(0,0,0,.6), inset 0 0 0 1px rgba(255,255,255,.04); 2558} 2559.proj-card:hover{box-shadow:0 40px 80px -30px rgba(0,0,0,.7), inset 0 0 0 1px rgba(168,243,65,.35)} 2560.proj-card .img{position:absolute;inset:0;background-size:cover;background-position:center;transition:transform 1.2s cubic-bezier(.2,.7,.1,1);filter:saturate(.95) brightness(.78)} 2561/* Static project images are the source of truth â the .img-video 2562 layer is hidden so the local image isn't overridden by the Pexels 2563 video clip on top. */ 2564.proj-card .img-video{display:none} 2565.proj-card:hover .img, 2566.proj-card:hover .img-video{transform:scale(1.06);filter:saturate(1) brightness(.85)} 2567.proj-card .shade{position:absolute;inset:0;background:linear-gradient(180deg, rgba(2,7,24,0) 18%, rgba(2,7,24,.07) 50%, rgba(2,7,24,.11) 80%, rgba(2,7,24,.12) 100%)} 2568.proj-card .spotlight{position:absolute;inset:0;pointer-events:none;opacity:0;transition:opacity .3s;
2568background:radial-gradient(280px circle at var(--mx,50%) var(--my,50%), rgba(168,243,65,.22), transparent 60%);mix-blend-mode:screen} 2569.proj-card:hover .spotlight{opacity:1} 2570.proj-card .meta{ 2571 position:absolute;inset:0; 2572 padding:24px; 2573 display:flex;flex-direction:column;justify-content:flex-end;gap:6px; 2574 z-index:2;pointer-events:none; 2575} 2576.proj-card .meta > *{pointer-events:auto} 2577 2578/* =========================================================== 2579 GLANCE-ABLE CARD REDESIGN â strip duplicate / decorative 2580 clutter and leave: single status tag · big title · NGO 2581 caption · clear CTA. The hover expand panel still carries 2582 the full detail for users who want more. 2583 =========================================================== */ 2584.proj-card .biome, /* "Asian elephant · Sanctuary care" tag */ 2585.proj-card .qstats, /* dual numeric stats row */ 2586.proj-card .miniglobe, /* corner globe icon */ 2587.proj-card .status-stripe, /* top decorative stripe */ 2588.proj-card.is-featured .featured-flag, /* "Featured project" ribbon */ 2589.proj-card.is-featured .founder, /* founder portrait + name */ 2590.proj-card.is-featured .quote-pull, /* pull quote */ 2591.proj-card.is-featured .progress{ /* progress bar â featured-only */ 2592 display:none !important; 2593} 2594 2595/* Anchor the status tag to the TOP-LEFT of the card as a frosted chip. 2596 Because .meta now spans the full card height (inset:0), top:0 here 2597 sits at the top edge of the card itself. */ 2598.proj-card .meta .tag{ 2599 position:absolute;top:18px;left:18px;right:auto;z-index:3; 2600 display:inline-flex;align-items:center;gap:11px; 2601 padding:9px 14px;border-radius:6px; 2602 background:rgba(2,7,24,.45); 2603 backdrop-filter:blur(14px) saturate(140%); 2604 -webkit-backdrop-filter:blur(14px) saturate(140%); 2605 box-shadow:inset 0 0 0 1px rgba(255,255,255,.10); 2606 font-family:var(--display);color:var(--bone); 2607 max-width:calc(100% - 36px); 2608 transition:box-shadow .3s, transform .3s, background .3s; 2609} 2610.proj-card:hover .meta .tag{ 2611 background:rgba(2,7,24,.60); 2612 box-shadow:inset 0 0 0 1px rgba(168,243,65,.45), 2613 0 10px 30px -8px rgba(168,243,65,.35); 2614 transform:translateY(-1px); 2615} 2616.proj-card.is-urgent:hover .meta .tag{ 2617 box-shadow:inset 0 0 0 1px rgba(226,106,91,.45), 2618 0 10px 30px -8px rgba(226,106,91,.40); 2619} 2620.proj-card .meta .tag .dot{ 2621 width:7px;height:7px;border-radius:50%;background:var(--leaf); 2622 box-shadow:0 0 8px var(--leaf-glow); 2623 flex:0 0 7px; 2624 animation:pinPulse 2.6s ease-out infinite; 2625} 2626/* Two-line stack: status on top, location below */ 2627.proj-card .meta .tag .tag-text{ 2628 display:flex;flex-direction:column;align-items:flex-start; 2629 line-height:1.08; 2630} 2631.proj-card .meta .tag .tag-status{ 2632 font-weight:800;font-size:11.5px;letter-spacing:.22em; 2633 text-transform:uppercase;color:var(--bone); 2634} 2635.proj-card .meta .tag .tag-location{ 2636 font-weight:600;font-size:10px;letter-spacing:.12em; 2637 text-transform:uppercase;color:var(--mist); 2638 margin-top:3px;opacity:.85; 2639 white-space:normal; 2640} 2641.proj-card.is-urgent .meta .tag{ 2642 box-shadow:inset 0 0 0 1px rgba(226,106,91,.50), 2643 0 8px 24px -8px rgba(226,106,91,.35); 2644} 2645.proj-card.is-urgent .meta .tag .dot{ 2646 background:var(--coral); 2647 box-shadow:0 0 10px rgba(226,106,91,.6), 0 0 20px rgba(226,106,91,.35); 2648} 2649 2650/* Title â large, two-line max, dominant */ 2651.proj-card .meta h3{ 2652 margin:0 0 2px; 2653 font-family:var(--display);font-weight:800; 2654 font-size:clamp(22px,2.4vw,30px); 2655 line-height:1.05;letter-spacing:-.02em;color:var(--bone); 2656 display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical; 2657 overflow:hidden; 2658} 2659/* NGO caption â small muted line under the title */ 2660.proj-card .meta .ngo{ 2661 margin:0; 2662 font-size:11.5px;letter-spacing:.18em; 2663 color:var(--mist);font-weight:700;text-transform:uppercase; 2664} 2665/* Lat/Lon coordinate lozenge â small inline pill placed ABOVE the 2666 main text of any card. Cartograph-themed: leaf-green crosshair 2667 icon, frosted dark backdrop, hairline leaf border. Reused on 2668 project cards, broll cards (Stories from the field) and pcards 2669 (Real numbers, real wins). */ 2670.coord-stamp{ 2671 align-self:flex-start;justify-self:start; 2672 display:inline-flex;align-items:center;gap:8px; 2673 padding:5px 11px;border-radius:999px; 2674 background:rgba(2,7,24,.55); 2675 border:1px solid rgba(168,243,65,.32); 2676 backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px); 2677 font-family:var(--display);font-weight:700; 2678 font-size:10.5px;letter-spacing:.14em;text-transform:uppercase; 2679 color:rgba(168,243,65,.92);line-height:1; 2680 pointer-events:none; 2681 box-shadow:0 4px 14px rgba(0,0,0,.35); 2682 margin-bottom:10px; 2683 width:fit-content; 2684}
2685.coord-stamp .cs-lat, 2686.coord-stamp .cs-lon{display:inline-flex;align-items:center} 2687.coord-stamp .cs-sep{ 2688 width:1px;height:9px;background:rgba(168,243,65,.35);display:inline-block; 2689} 2690.coord-stamp::before{ 2691 content:"";width:11px;height:11px;flex:0 0 11px; 2692 border-radius:50%; 2693 background: 2694 radial-gradient(circle, var(--leaf) 0 1.5px, transparent 2px), 2695 linear-gradient(to right, transparent calc(50% - .5px), rgba(168,243,65,.65) calc(50% - .5px), rgba(168,243,65,.65) calc(50% + .5px), transparent calc(50% + .5px)), 2696 linear-gradient(to bottom, transparent calc(50% - .5px), rgba(168,243,65,.65) calc(50% - .5px), rgba(168,243,65,.65) calc(50% + .5px), transparent calc(50% + .5px)); 2697 border:1px solid rgba(168,243,65,.45); 2698 box-sizing:border-box; 2699} 2700/* Slightly tighter for narrower contexts */ 2701.btile .coord-stamp, 2702.pcard .coord-stamp{font-size:10px;padding:4px 10px;margin-bottom:8px} 2703 2704/* CTA â bold leaf-green pill button. Was a small underlined link 2705 that visitors were missing entirely. Now reads as a proper 2706 call-to-action: filled leaf bg, ink text, rounded pill, big tap 2707 target. On hover it brightens, the arrow slides, and a soft leaf 2708 glow lights up. */ 2709.proj-card .meta .cta{ 2710 margin-top:18px;align-self:stretch;width:100%; 2711 display:flex;align-items:center;justify-content:center;gap:10px; 2712 font-family:var(--display);font-weight:900; 2713 font-size:17px;letter-spacing:.02em; 2714 padding:18px 24px;border-radius:14px; 2715 background:var(--leaf);color:var(--ink) !important; 2716 border:1px solid var(--leaf); 2717 box-shadow:0 12px 28px -8px rgba(168,243,65,.6), 2718 0 4px 10px rgba(0,0,0,.3); 2719 transition:background .25s, transform .25s, 2720 box-shadow .25s, border-color .25s; 2721 position:relative;z-index:7; 2722 text-decoration:none; 2723 /* iOS tap highlight off â keeps the visual clean on touch */ 2724 -webkit-tap-highlight-color:transparent; 2725} 2726.proj-card .meta .cta::after{ 2727 content:"â";display:inline-block; 2728 font-weight:900;font-size:18px;line-height:1; 2729 transition:transform .25s; 2730} 2731.proj-card .meta .cta > .arrow, 2732.proj-card .meta .cta > span:last-child{ display:none } /* hide any inline arrow span; we use ::after */ 2733.proj-card:hover .meta .cta, 2734.proj-card .meta .cta:hover{ 2735 background:#B9F764;color:var(--ink) !important; 2736 transform:translateY(-3px); 2737 box-shadow:0 18px 36px -8px rgba(168,243,65,.75), 2738 0 6px 14px rgba(0,0,0,.35); 2739} 2740.proj-card:hover .meta .cta::after, 2741.proj-card .meta .cta:hover::after{ transform:translateX(5px) } 2742.proj-card .meta .cta:focus-visible{ 2743 outline:2px solid var(--bone);outline-offset:3px; 2744} 2745.proj-card .meta .cta:active{ 2746 transform:translateY(-1px) scale(.98); 2747} 2748@media (max-width:560px){ 2749 .proj-card .meta .cta{ font-size:16px;padding:16px 20px } 2750} 2751 2752/* Hover-expand panel â slides up from the bottom on hover */ 2753.proj-card .expand-panel{ 2754 position:absolute;left:0;right:0;bottom:0;z-index:3; 2755 padding:24px 22px 22px; 2756 background:linear-gradient(180deg, rgba(2,7,24,.0) 0%, rgba(2,7,24,.26) 18%, rgba(2,7,24,.29) 100%); 2757 backdrop-filter:blur(8px); 2758 -webkit-backdrop-filter:blur(8px); 2759 transform:translateY(100%); 2760 transition:transform .5s cubic-bezier(.2,.7,.1,1); 2761 pointer-events:none; 2762} 2763.proj-card:hover .expand-panel{ 2764 transform:translateY(0); 2765 pointer-events:auto; 2766} 2767.proj-card .ep-eyebrow{ 2768 font-family:var(--body);font-size:10.5px;letter-spacing:.22em;text-transform:uppercase; 2769 color:var(--leaf);font-weight:700;margin-bottom:8px; 2770 display:flex;align-items:center;gap:8px; 2771} 2772.proj-card .ep-eyebrow::before{ 2773 content:"";display:inline-block;width:24px;height:1px; 2774 background:var(--leaf);box-shadow:0 0 6px var(--leaf-glow); 2775} 2776.proj-card .ep-title{ 2777 font-family:var(--display);font-weight:800;font-size:18px; 2778 letter-spacing:-.015em;line-height:1.15;color:var(--bone);margin-bottom:8px; 2779} 2780.proj-card .ep-desc{ 2781 font-size:13px;line-height:1.5;color:var(--mist);margin-bottom:12px; 2782} 2783.proj-card .ep-list{ 2784 list-style:none;display:grid;gap:6px;margin-bottom:14px; 2785 font-size:12.5px;color:var(--bone); 2786} 2787.proj-card .ep-list li{ 2788 padding-left:18px;position:relative; 2789} 2790.proj-card .ep-list li::before{ 2791 content:"";position:absolute;
2791left:0;top:8px;width:8px;height:8px; 2792 border-radius:50%;background:var(--leaf);box-shadow:0 0 6px var(--leaf-glow); 2793} 2794.proj-card .ep-cta{ 2795 display:inline-flex;align-items:center;gap:8px; 2796 padding:9px 14px;border-radius:4px; 2797 background:var(--leaf);color:var(--ink);font-weight:700;font-size:12.5px; 2798 transition:background .2s, transform .2s; 2799} 2800.proj-card .ep-cta:hover{background:#B9F764;transform:translateX(2px)} 2801.proj-card:hover .meta{opacity:0;transition:opacity .3s} 2802@media (max-width:880px), (hover:none) and (pointer:coarse){ 2803 /* On touch or small screens, show extra content always (no hover state) */ 2804 .proj-card .expand-panel{display:none} 2805} 2806.proj-card .tag{ 2807 display:inline-flex;align-items:center;gap:8px;align-self:start; 2808 font-size:10.5px;letter-spacing:.2em;text-transform:uppercase;color:var(--bone);font-weight:600; 2809 padding:5px 10px;border-radius:3px;background:rgba(255,255,255,.06);backdrop-filter:blur(8px); 2810 box-shadow:inset 0 0 0 1px rgba(255,255,255,.08); 2811} 2812.proj-card .tag .dot{width:6px;height:6px;border-radius:50%;background:var(--leaf);box-shadow:0 0 8px var(--leaf-glow)} 2813.proj-card .picon-tr{display:none} 2814.proj-card:hover .picon-tr{ 2815 background:rgba(168,243,65,.22); 2816 box-shadow:inset 0 0 0 1px rgba(168,243,65,.65), 0 16px 40px -12px rgba(0,0,0,.6); 2817 transform:rotate(-3deg) scale(1.05); 2818} 2819.proj-card .picon-tr svg{width:46px;height:46px} 2820/* Origami / low-poly animal icon â geometric polygons in leaf-green gradient */ 2821.proj-card .picon-tr.is-origami{ 2822 width:88px;height:88px;border-radius:10px;padding:0; 2823 background:linear-gradient(140deg, rgba(2,7,24,.85), rgba(7,13,35,.95)); 2824 box-shadow:inset 0 0 0 1px rgba(168,243,65,.45), 0 14px 36px -14px rgba(0,0,0,.55); 2825 overflow:visible; 2826} 2827.proj-card .picon-tr.is-origami svg{ 2828 width:62px;height:62px; 2829 filter:drop-shadow(0 6px 16px rgba(168,243,65,.35)); 2830} 2831.proj-card:hover .picon-tr.is-origami{ 2832 box-shadow:inset 0 0 0 1px rgba(168,243,65,.75), 0 20px 50px -14px var(--leaf-glow); 2833 transform:rotate(-3deg) scale(1.08); 2834} 2835.proj-card .picon-tr.is-origami::after{ 2836 content:"";position:absolute;inset:-4px;border-radius:12px;pointer-events:none; 2837 box-shadow:0 0 0 0 rgba(168,243,65,.4); 2838 animation:iconPulse 3s ease-out infinite; 2839} 2840.proj-card:nth-child(2) .picon-tr.is-origami::after{animation-delay:.5s} 2841.proj-card:nth-child(3) .picon-tr.is-origami::after{animation-delay:1s} 2842.proj-card:nth-child(4) .picon-tr.is-origami::after{animation-delay:1.5s} 2843.proj-card:nth-child(5) .picon-tr.is-origami::after{animation-delay:2s} 2844.proj-card:nth-child(6) .picon-tr.is-origami::after{animation-delay:2.5s} 2845@media (max-width:560px){ 2846 .proj-card .picon-tr.is-origami{width:68px;height:68px} 2847 .proj-card .picon-tr.is-origami svg{width:48px;height:48px} 2848} 2849@media (max-width:560px){ 2850 .proj-card .picon-tr{width:60px;height:60px;top:14px;right:14px} 2851 .proj-card .picon-tr svg{width:36px;height:36px} 2852 .proj-card .picon-tr.is-photo{width:64px;height:64px} 2853} 2854.proj-card .picon-tr svg path, 2855.proj-card .picon-tr svg circle, 2856.proj-card .picon-tr svg line, 2857.proj-card .picon-tr svg polyline{ 2858 stroke:currentColor;stroke-width:1.6;fill:none; 2859 stroke-linecap:round;stroke-linejoin:round; 2860} 2861.proj-card.in .picon-tr svg path, 2862.proj-card.in .picon-tr svg circle, 2863.proj-card.in .picon-tr svg polyline{ 2864 stroke-dasharray:100;stroke-dashoffset:100; 2865 animation:iconDraw 1.4s .25s cubic-bezier(.7,0,.2,1) forwards; 2866} 2867.proj-card .picon-tr::after{ 2868 content:"";position:absolute;inset:0;border-radius:6px;pointer-events:none; 2869 box-shadow:0 0 0 0 rgba(168,243,65,.4); 2870 animation:iconPulse 3s ease-out infinite; 2871} 2872.proj-card h3{font-size:24px;line-height:1.05;font-weight:800;letter-spacing:-.02em} 2873.proj-card .ngo{font-size:13px;color:var(--mist);margin-top:2px} 2874.proj-card .progress{display:flex;align-items:center;gap:12px;margin-top:6px;font-size:13px;color:var(--bone);font-weight:600} 2875.proj-card .progress-bar{flex:1;height:4px;background:rgba(255,255,255,.10);border-radius:99px;overflow:hidden;position:relative} 2876.proj-card .progress-bar .fill{display:block;height:100%;background:linear-gradient(90deg, var(--leaf-deep), var(--leaf));width:var(--p,0%);transform:translateX(-100%);animation:barFill 2s .4s cubic-bezier(.7,0,.2,1) forwards;box-shadow:0 0 12px var(--leaf-glow)} 2877.proj-card .cta{ 2878 display:inline-flex;align-items:center;gap:6px;font-size:13px;font-weight:600; 2879 color:var(--bone);align-self:start; 2880 padding:0 0 4px 0;border-bottom:1px solid rgba(255,255,255,.25); 2881 transition:color .25s, border-color .25s; 2882} 2883.proj-card .cta:hover{color:var(--leaf);border-bottom-color:var(--leaf)} 2884 2885/* --- RICHER CARD DIFFERENTIATION --- */ 2886/* Status accent stripe across the top of each card (colour by status) */ 2887.proj-card .status-stripe{ 2888 position:absolute;top:0;left:0;right:0;height:3px;z-index:4; 2889 background:var(--leaf); 2890 box-shadow:0 0 12px var(--leaf-glow); 2891} 2892.proj-card.is-urgent .status-stripe{background:var(--coral);box-shadow:0 0 12px rgba(226,106,91,.5)} 2893.proj-card.is-featured .status-stripe{background:var(--sun);box-shadow:0 0 12px rgba(240,194,95,.5)} 2894.proj-card .status-stripe::after{ 2895 content:"";position:absolute;
2895left:0;top:0;bottom:0;width:30%; 2896 background:linear-gradient(90deg, currentColor, transparent); 2897 opacity:.55; 2898} 2899 2900/* Biome / ecosystem tag â sits ABOVE the project title, distinct per card */ 2901.proj-card .biome{ 2902 display:inline-flex;align-items:center;gap:8px;align-self:start; 2903 font-family:var(--body);font-size:10.5px;letter-spacing:.18em;text-transform:uppercase; 2904 font-weight:600;color:var(--bone); 2905 padding:5px 10px;border-radius:3px; 2906 background:rgba(168,243,65,.10);box-shadow:inset 0 0 0 1px rgba(168,243,65,.35); 2907 backdrop-filter:blur(6px); 2908} 2909.proj-card .biome svg{width:13px;height:13px;color:var(--leaf);stroke:currentColor;stroke-width:1.7;fill:none;stroke-linecap:round;stroke-linejoin:round} 2910.proj-card .biome b{font-weight:700;color:var(--leaf);letter-spacing:.18em} 2911 2912/* Quick-stats strip â 2 micro-data points per card */ 2913.proj-card .qstats{ 2914 display:flex;gap:10px;margin-top:8px; 2915} 2916.proj-card .qstats .qs{ 2917 display:flex;flex-direction:column;gap:2px; 2918 padding:8px 10px;border-radius:5px;flex:1 1 0;min-width:0; 2919 background:rgba(2,7,24,.55);backdrop-filter:blur(6px); 2920 box-shadow:inset 0 0 0 1px rgba(255,255,255,.06); 2921} 2922.proj-card .qstats .qs b{ 2923 font-family:var(--display);font-weight:800;font-size:15px;color:var(--bone); 2924 letter-spacing:-.01em;line-height:1; 2925} 2926.proj-card .qstats .qs b em{font-style:normal;font-weight:500;color:var(--leaf);font-size:.85em} 2927.proj-card .qstats .qs span{ 2928 font-family:var(--body);font-size:10px;color:var(--mist);letter-spacing:.06em;line-height:1.3; 2929 text-transform:uppercase;font-weight:500; 2930} 2931 2932/* Mini-globe pinpoint â small globe with a pulsing dot at the project location */ 2933.proj-card .miniglobe{ 2934 position:absolute;left:18px;bottom:18px;z-index:3; 2935 width:48px;height:48px;border-radius:50%; 2936 display:flex;align-items:center;justify-content:center; 2937 background:rgba(2,7,24,.65);backdrop-filter:blur(10px); 2938 box-shadow:inset 0 0 0 1px rgba(168,243,65,.35), 0 8px 22px -8px rgba(0,0,0,.55); 2939 transition:transform .3s; 2940} 2941.proj-card:hover .miniglobe{transform:scale(1.08) rotate(8deg)} 2942.proj-card .miniglobe svg{width:32px;height:32px} 2943.proj-card .miniglobe svg circle.globe{fill:none;stroke:rgba(168,243,65,.45);stroke-width:1.4} 2944.proj-card .miniglobe svg path.lat{fill:none;stroke:rgba(168,243,65,.3);stroke-width:.8} 2945.proj-card .miniglobe svg path.lon{fill:none;stroke:rgba(168,243,65,.3);stroke-width:.8} 2946.proj-card .miniglobe svg circle.pin{ 2947 fill:var(--leaf); 2948 filter:drop-shadow(0 0 4px var(--leaf-glow)); 2949} 2950.proj-card .miniglobe svg circle.pin-ring{ 2951 fill:none;stroke:var(--leaf);stroke-width:1; 2952 transform-origin:center;transform-box:fill-box; 2953 animation:pinRing 2.4s ease-out infinite; 2954} 2955@keyframes pinRing{ 2956 0%{opacity:.8;r:2} 2957 100%{opacity:0;r:8} 2958} 2959 2960/* Move the .meta block right when miniglobe sits in the bottom-left */ 2961.proj-card .meta{left:78px} 2962.proj-card.is-featured .meta{left:24px} 2963.proj-card.is-featured .miniglobe{left:auto;right:18px;bottom:18px;top:auto;width:60px;height:60px} 2964.proj-card.is-featured .miniglobe svg{width:40px;height:40px} 2965@media (max-width:560px){ 2966 .proj-card .miniglobe{width:40px;height:40px;left:14px;bottom:14px} 2967 .proj-card .miniglobe svg{width:26px;height:26px} 2968 .proj-card .meta{left:64px} 2969} 2970 2971/* Testimonials with landscape thumbnails */ 2972.testi-grid{display:grid;grid-template-columns:1fr;gap:20px;margin-top:32px} 2973@media (min-width:720px){.testi-grid{grid-template-columns:repeat(2,1fr)}} 2974@media (min-width:1100px){.testi-grid{grid-template-columns:repeat(3,1fr)}} 2975.testi{ 2976 position:relative;border-radius:var(--r-lg);overflow:hidden; 2977 min-height:340px;padding:24px;display:flex;flex-direction:column;justify-content:flex-end;gap:18px; 2978 isolation:isolate; 2979} 2980.testi .bg{position:absolute;inset:0;background-size:cover;background-position:center;z-index:-2} 2981.testi::after{content:"";position:absolute;inset:0;z-index:-1;background:linear-gradient(180deg, rgba(2,7,24,.02) 0%, rgba(2,7,24,.11) 90%)} 2982.testi q{font-family:var(--display);font-weight:500;font-style:italic;font-size:20px;line-height:1.35;color:var(--bone);quotes:"\201C" "\201D"} 2983.testi q::before{content:open-quote;color:var(--leaf);margin-right:2px} 2984.testi q::after{content:close-quote;color:var(--leaf);margin-left:2px} 2985.testi .who{display:flex;align-items:center;gap:12px;
2985color:var(--mist);font-size:13px} 2986.testi .who strong{display:block;color:var(--bone);font-weight:700;font-size:14px} 2987 2988/* ================================================= 2989 WORLD MAP â "Where the work happens" 2990 Stylised continent shapes + 24 pulsing leaf-green pins. 2991 Not GIS-accurate by design â it's a brand visual. 2992 ================================================= */ 2993.globe-section{ 2994 position:relative;padding:var(--pad-section) 0; 2995 background:linear-gradient(180deg, var(--ink) 0%, var(--ink-80) 50%, var(--ink) 100%); 2996 overflow:hidden; 2997} 2998.globe-section::before{ 2999 content:"";position:absolute;inset:-25%;z-index:0;pointer-events:none; 3000 background: 3001 radial-gradient(34% 52% at 18% 28%, rgba(168,243,65,.22), transparent 70%), 3002 radial-gradient(44% 60% at 82% 72%, rgba(42,122,59,.26), transparent 70%), 3003 radial-gradient(24% 22% at 50% 50%, rgba(126,225,136,.16), transparent 75%); 3004 filter:blur(70px); 3005 animation:drift 26s ease-in-out infinite alternate, glowBreathe 10s ease-in-out infinite; 3006} 3007.globe-section .wrap{position:relative;z-index:1} 3008.globe-wrap{ 3009 position:relative;margin-top:40px; 3010 aspect-ratio:1000/500; 3011 background: 3012 radial-gradient(circle at center, rgba(168,243,65,.04) 0%, transparent 60%), 3013 radial-gradient(circle 1px at 50% 50%, var(--line-2) 1px, transparent 1.5px) 0 0/14px 14px; 3014 border-radius:var(--r-lg); 3015 box-shadow:inset 0 0 0 1px var(--line); 3016} 3017@media (max-width:720px){ 3018 .globe-wrap{aspect-ratio:5/4;background-size:10px 10px} 3019} 3020.globe-svg{ 3021 position:absolute;inset:0;width:100%;height:100%; 3022} 3023.globe-svg path{ 3024 fill:rgba(255,255,255,.04); 3025 stroke:rgba(168,243,65,.18); 3026 stroke-width:1; 3027 transition:fill .4s; 3028} 3029/* Continents subtly pulse to feel "alive" â colour cycle */ 3030.globe-svg .continent{ 3031 animation:contPulse 6s ease-in-out infinite; 3032 /* Draw-in: each continent strokes itself on enter */ 3033 stroke-dasharray:1600; 3034 stroke-dashoffset:1600; 3035 transition:stroke-dashoffset 2.4s cubic-bezier(.22,.9,.3,1); 3036} 3037.globe-wrap.is-visible .globe-svg .continent{stroke-dashoffset:0} 3038/* Stagger the continent stroke draws */ 3039.globe-wrap.is-visible .globe-svg .continent:nth-of-type(1){transition-delay:.
303905s} 3040.globe-wrap.is-visible .globe-svg .continent:nth-of-type(2){transition-delay:.15s} 3041.globe-wrap.is-visible .globe-svg .continent:nth-of-type(3){transition-delay:.25s} 3042.globe-wrap.is-visible .globe-svg .continent:nth-of-type(4){transition-delay:.35s} 3043.globe-wrap.is-visible .globe-svg .continent:nth-of-type(5){transition-delay:.45s} 3044.globe-wrap.is-visible .globe-svg .continent:nth-of-type(6){transition-delay:.55s} 3045.globe-wrap.is-visible .globe-svg .continent:nth-of-type(7){transition-delay:.65s} 3046.globe-wrap.is-visible .globe-svg .continent:nth-of-type(8){transition-delay:.75s} 3047.globe-wrap.is-visible .globe-svg .continent:nth-of-type(9){transition-delay:.85s} 3048.globe-wrap.is-visible .globe-svg .continent:nth-of-type(10){transition-delay:.95s} 3049.globe-wrap.is-visible .globe-svg .continent:nth-of-type(n+11){transition-delay:1.05s} 3050.globe-svg .continent:nth-child(3n){animation-delay:1.5s} 3051.globe-svg .continent:nth-child(3n+1){animation-delay:3s} 3052@keyframes contPulse{ 3053 0%,100%{fill:rgba(255,255,255,.04);stroke:rgba(168,243,65,.18)} 3054 50%{fill:rgba(168,243,65,.06);stroke:rgba(168,243,65,.28)} 3055} 3056/* Flowing dashed arcs that connect featured project pins */ 3057.globe-arcs{ 3058 position:absolute;inset:0;pointer-events:none;z-index:1; 3059 width:100%;height:100%; 3060} 3061.globe-arcs path{ 3062 fill:none;stroke:var(--leaf);stroke-width:.7; 3063 stroke-dasharray:3 8;stroke-linecap:round; 3064 opacity:0;filter:drop-shadow(0 0 4px rgba(168,243,65,.4)); 3065 animation:arcFlow 14s linear infinite; 3066 transition:opacity .8s ease; 3067} 3068.globe-wrap.is-visible .globe-arcs path{opacity:.55;transition-delay:1.4s} 3069.globe-wrap.is-visible .globe-arcs path:nth-child(2){opacity:.4;transition-delay:1.6s} 3070.globe-wrap.is-visible .globe-arcs path:nth-child(3){opacity:.45;transition-delay:1.8s} 3071.globe-wrap.is-visible .globe-arcs path:nth-child(4){opacity:.5;transition-delay:2s} 3072.globe-arcs path:nth-child(2){stroke:#D3FA9E;animation-duration:18s;animation-direction:reverse} 3073.globe-arcs path:nth-child(3){stroke:var(--sun);stroke-dasharray:2 14;animation-duration:22s} 3074.globe-arcs path:nth-child(4){stroke:var(--leaf);stroke-dasharray:4 10;animation-duration:16s;animation-direction:reverse} 3075@keyframes arcFlow{to{stroke-dashoffset:-200}} 3076@media (prefers-reduced-motion:reduce){ 3077 .globe-svg .continent{animation:none;stroke-dashoffset:0} 3078 .globe-arcs path{animation:none;opacity:.5} 3079 .donation-ping{display:none} 3080 .pin{opacity:1 !important;transform:translate(-50%,-50%) scale(1) !important} 3081} 3082.globe-svg .lat-line{ 3083 fill:none;stroke:rgba(168,243,65,.08);stroke-width:.5;stroke-dasharray:2 6; 3084 opacity:0;transition:opacity 1s ease .2s; 3085} 3086.globe-wrap.is-visible .globe-svg .lat-line{opacity:1} 3087 3088/* === 3D globe (Three.js) â replaces the flat SVG variant === */ 3089/* Hide flat layers but keep .pin buttons in the DOM so existing popup wiring continues to work. */ 3090#globeWrap.is-3d .globe-svg, 3091#globeWrap.is-3d .globe-arcs, 3092#globeWrap.is-3d .globe-scan, 3093#globeWrap.is-3d .globe-scan-flicker{ display:none !important; } 3094#globeWrap.is-3d .pin{ 3095 position:absolute !important; 3096 left:-9999px !important; top:-9999px !important; 3097 width:1px;height:1px;opacity:0;pointer-events:none; 3098 visibility:hidden; 3099} 3100.globe-canvas{ 3101 position:absolute;inset:0;width:100%;height:100%; 3102 display:block;cursor:grab;touch-action:none; 3103 border-radius:var(--r-lg); 3104} 3105.globe-canvas.is-dragging{cursor:grabbing} 3106.globe-tooltip{ 3107 position:absolute;pointer-events:none; 3108 transform:translate(14px,-50%); 3109 background:rgba(2,7,24,.92); 3110 border:1px solid rgba(168,243,65,.45); 3111 color:var(--bone); 3112 font-family:var(--body); 3113 font-size:12.5px;letter-spacing:.01em; 3114 padding:7px 11px;border-radius:8px; 3115 white-space:nowrap; 3116 opacity:0; 3117 transition:opacity .15s ease; 3118 z-index:5; 3119 box-shadow:0 10px 28px rgba(0,0,0,.55), 0 0 0 1px rgba(168,243,65,.15); 3120} 3121.globe-tooltip.is-visible{opacity:1} 3122 3123/* === Stage layout: hero globe + right rail card === */ 3124.globe-stage{ 3125 position:relative; 3126 display:grid; 3127 grid-template-columns: minmax(420px, 2.4fr) minmax(280px, 1fr); 3128 gap:64px; 3129 align-items:stretch; 3130 margin-top:48px; 3131} 3132.globe-stage .globe-wrap{ 3133 margin-top:0;aspect-ratio:1/1;width:100%;align-self:center; 3134} 3135.globe-aside{display:flex;flex-direction:column;gap:20px;align-self:center} 3136@media (max-width:1080px){ 3137 .globe-stage{grid-template-columns:1fr;gap:28px} 3138 .globe-stage .globe-wrap{aspect-ratio:1/1;max-width:640px;margin:0 auto} 3139} 3140 3141/* Right rail â project card */ 3142.globe-card{ 3143 background:rgba(7,13,35,.55); 3144 border:1px solid var(--line-2); 3145 border-radius:var(--r-md); 3146 padding:24px 22px; 3147 position:relative;overflow:hidden; 3148 backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px); 3149 min-height:300px;display:flex;flex-direction:column; 3150} 3151.globe-card::before{ 3152 content:"";position:absolute;inset:0;pointer-events:none; 3153 background:radial-gradient(120% 80% at 100% 0%, rgba(168,243,65,.08), transparent 60%); 3154} 3155.globe-card > *{position:relative} 3156.gc-empty{display:flex;flex-direction:column;justify-content:center;flex:1} 3157.globe-card.is-active .gc-empty{display:none} 3158.gc-eyebrow{ 3159 font-size:11px;letter-spacing:.22em;text-transform:uppercase;
3160 color:var(--mist-2);margin-bottom:14px; 3161} 3162.gc-empty-title{ 3163 font-family:var(--display);font-weight:800;font-size:22px;line-height:1.15; 3164 letter-spacing:-.015em;color:var(--bone);margin-bottom:12px; 3165} 3166.gc-empty-hint{font-size:13.5px;line-height:1.55;color:var(--mist)} 3167.gc-detail{display:flex;flex-direction:column;animation:gcFadeIn .35s ease both} 3168.gc-detail[hidden]{display:none} 3169.gc-img{ 3170 position:relative; 3171 width:calc(100% + 44px); 3172 margin:-24px -22px 18px; 3173 height:170px; 3174 background:#0a1320 center/cover no-repeat; 3175 border-bottom:1px solid rgba(168,243,65,.22); 3176 overflow:hidden; 3177} 3178.gc-img::after{ 3179 content:"";position:absolute;inset:0;pointer-events:none; 3180 background:linear-gradient(180deg, transparent 35%, rgba(7,13,35,.07) 78%, rgba(7,13,35,.11) 100%); 3181} 3182.gc-img::before{ 3183 content:"";position:absolute;inset:0;pointer-events:none;z-index:1; 3184 background:linear-gradient(90deg, rgba(168,243,65,.06), transparent 25%); 3185 mix-blend-mode:screen; 3186} 3187.gc-img[hidden]{display:none} 3188@keyframes gcFadeIn{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}} 3189.gc-close{ 3190 position:absolute;top:14px;right:14px; 3191 width:28px;height:28px;border-radius:50%; 3192 background:rgba(255,255,255,.06);color:var(--mist); 3193 font-size:18px;line-height:1; 3194 display:flex;align-items:center;justify-content:center; 3195 cursor:pointer;transition:background .2s, color .2s;border:0; 3196 z-index:2; 3197} 3198.gc-close:hover{background:rgba(255,255,255,.14);color:var(--bone)} 3199.gc-status{ 3200 display:inline-block;align-self:flex-start; 3201 padding:5px 11px;border-radius:999px; 3202 font-size:10.5px;letter-spacing:.16em;text-transform:uppercase;font-weight:600; 3203 background:rgba(168,243,65,.14);color:var(--leaf); 3204 border:1px solid rgba(168,243,65,.3); 3205} 3206.globe-card.is-urgent .gc-status{background:rgba(226,106,91,.14);color:var(--coral);border-color:rgba(226,106,91,.3)} 3207.globe-card.is-featured .gc-status{background:rgba(240,194,95,.14);color:var(--sun);border-color:rgba(240,194,95,.3)} 3208.gc-loc{ 3209 display:flex;align-items:center;gap:6px; 3210 font-size:12.5px;color:var(--mist);margin-top:14px;font-weight:500; 3211} 3212.gc-loc svg{width:14px;height:14px;color:var(--leaf);flex-shrink:0} 3213.gc-coords{ 3214 font-size:11px;color:var(--mist-2);letter-spacing:.04em; 3215 font-feature-settings:'tnum';margin-top:4px;margin-left:20px; 3216} 3217.gc-name{ 3218 font-family:var(--display);font-weight:800;font-size:22px;line-height:1.12; 3219 letter-spacing:-.015em;margin-top:12px;color:var(--bone); 3220} 3221.gc-ngo{ 3222 font-size:11px;letter-spacing:.16em;text-transform:uppercase; 3223 color:var(--mist-2);margin-top:8px;font-weight:600; 3224} 3225.gc-desc{font-size:13.5px;line-height:1.55;color:var(--mist);margin-top:14px} 3226.gc-stat-box{ 3227 margin-top:18px;padding-top:14px;border-top:1px solid var(--line); 3228 font-size:10.5px;color:var(--mist-2);letter-spacing:.16em;text-transform:uppercase; 3229} 3230.gc-stat-box strong{ 3231 display:block;font-family:var(--body);font-weight:600; 3232 color:var(--bone);font-size:14px;margin-top:5px; 3233 letter-spacing:0;text-transform:none;line-height:1.4; 3234} 3235.gc-cta{ 3236 display:inline-flex;align-items:center;gap:6px;align-self:flex-start; 3237 margin-top:18px;padding:11px 18px; 3238 background:var(--leaf);color:var(--ink); 3239 border-radius:999px;font-weight:700;font-size:13px; 3240 transition:transform .2s, background .2s; 3241} 3242.gc-cta:hover{transform:translateY(-1px);background:#71dd7d} 3243.gc-cta .arrow{transition:transform .2s} 3244.gc-cta:hover .arrow{transform:translateX(3px)} 3245 3246/* Hide the centred map-popup when 3D mode is active â right rail replaces it */ 3247#globe .map-popup{display:none !important} 3248 3249/* Tactical digital scan â sweeps leftâright across the map every 7s. 3250 Bright leading edge with a soft tail trailing behind. Pairs with a 3251 horizontal-line flicker overlay and a "SCANNING" status indicator. */ 3252.globe-scan{ 3253 position:absolute;inset:0;z-index:3;pointer-events:none; 3254 overflow:hidden;border-radius:var(--r-lg); 3255 opacity:0;transition:opacity 1s ease 1.5s; 3256} 3257.globe-wrap.is-visible .globe-scan{opacity:1} 3258.globe-scan-line{ 3259 position:absolute;top:0;bottom:0;left:0;width:2px; 3260 background:linear-gradient(180deg, 3261 transparent 0%, 3262 rgba(168,243,65,.45) 8%, 3263 rgba(180,255,170,1) 50%, 3264 rgba(168,243,65,.45) 92%, 3265 transparent 100%); 3266 box-shadow:0 0 14px rgba(168,243,65,.9), 0 0 32px rgba(168,243,65,.5); 3267 animation:scanSweep 7s linear infinite; 3268 will-change:transform; 3269} 3270.globe-scan-tail{ 3271 position:absolute;top:0;bottom:0;left:-22%;width:22%; 3272 background:linear-gradient(90deg, 3273 transparent 0%, 3274 rgba(168,243,65,0) 30%, 3275 rgba(168,243,65,.05) 60%, 3276 rgba(168,243,65,.14) 92%, 3277 rgba(140,235,160,.22) 100%); 3278 filter:blur(1px); 3279 animation:scanSweepTail 7s linear infinite; 3280 will-change:transform; 3281} 3282@keyframes scanSweep{ 3283 0% {transform:translateX(0)} 3284 98% {transform:translateX(calc(100cqw - 2px))} 3285 100% {transform:translateX(calc(100cqw - 2px));opacity:0}
3285 3286} 3287@keyframes scanSweepTail{ 3288 0% {transform:translateX(0);opacity:1} 3289 98% {transform:translateX(100cqw);opacity:1} 3290 100% {transform:translateX(100cqw);opacity:0} 3291} 3292.globe-wrap{container-type:inline-size} 3293 3294/* Subtle horizontal data flicker â like reading lines on a scanner */ 3295.globe-scan-flicker{ 3296 position:absolute;inset:0;z-index:2;pointer-events:none; 3297 border-radius:var(--r-lg);overflow:hidden; 3298 opacity:0;transition:opacity 1.2s ease 1.8s; 3299 background:repeating-linear-gradient( 3300 180deg, 3301 transparent 0, 3302 transparent 6px, 3303 rgba(168,243,65,.025) 6px, 3304 rgba(168,243,65,.025) 7px 3305 ); 3306 mix-blend-mode:screen; 3307} 3308.globe-wrap.is-visible .globe-scan-flicker{opacity:1;animation:scanFlicker 4.5s ease-in-out infinite} 3309@keyframes scanFlicker{ 3310 0%,100%{opacity:.55} 3311 35%{opacity:.8} 3312 70%{opacity:.4} 3313} 3314 3315/* Status chip â bottom right corner of the map */ 3316.globe-scan-status{ 3317 position:absolute;right:14px;bottom:14px;z-index:4; 3318 display:inline-flex;align-items:center;gap:8px; 3319 padding:7px 12px;border-radius:4px; 3320 background:rgba(2,7,24,.7);backdrop-filter:blur(8px); 3321 -webkit-backdrop-filter:blur(8px); 3322 box-shadow:inset 0 0 0 1px rgba(168,243,65,.35); 3323 font-family:var(--display);font-weight:700;font-size:11px; 3324 letter-spacing:.18em;color:var(--leaf); 3325 opacity:0;transition:opacity 1s ease 2.2s; 3326} 3327.globe-wrap.is-visible .globe-scan-status{opacity:1} 3328.globe-scan-status .gs-dot{ 3329 width:7px;height:7px;border-radius:50%;background:var(--leaf); 3330 box-shadow:0 0 8px var(--leaf-glow); 3331 animation:scanDot 1.4s ease-in-out infinite; 3332} 3333.globe-scan-status .gs-sep{opacity:.45} 3334.globe-scan-status .gs-val{color:var(--bone);font-weight:600} 3335@keyframes scanDot{ 3336 0%,100%{opacity:.4;transform:scale(.85)} 3337 50%{opacity:1;transform:scale(1.1)} 3338} 3339@media (prefers-reduced-motion:reduce){ 3340 .globe-scan-line, .globe-scan-tail{animation:none;display:none} 3341 .globe-scan-flicker{animation:none;opacity:.4} 3342 .globe-scan-status .gs-dot{animation:none} 3343} 3344 3345/* Donation pings â green expanding rings spawned by JS at random 3346 pin coordinates. Each lives ~1.8s then is removed from the DOM. */ 3347.donation-ping{ 3348 position:absolute;width:10px;height:10px;border-radius:50%; 3349 transform:translate(-50%,-50%); 3350 pointer-events:none;z-index:1; 3351 border:1px solid rgba(168,243,65,.85); 3352 box-shadow:0 0 14px rgba(168,243,65,.5); 3353 animation:donationPing 1.8s cubic-bezier(.22,.9,.3,1) forwards; 3354} 3355@keyframes donationPing{ 3356 0%{transform:translate(-50%,-50%) scale(.4);opacity:1;border-width:2px} 3357 100%{transform:translate(-50%,-50%) scale(7);opacity:0;border-width:.5px} 3358} 3359.pin{ 3360 position:absolute;transform:translate(-50%,-50%) scale(.2);z-index:2; 3361 opacity:0; 3362 transition:opacity .6s ease, transform .7s cubic-bezier(.34,1.56,.5,1); 3363} 3364.globe-wrap.is-visible .pin{ 3365 opacity:1;transform:translate(-50%,-50%) scale(1); 3366} 3367/* Stagger pin drops â feels like satellites landing one by one */ 3368.globe-wrap.is-visible .pin:nth-of-type(1){transition-delay:1.3s} 3369.globe-wrap.is-visible .pin:nth-of-type(2){transition-delay:1.4s} 3370.globe-wrap.is-visible .pin:nth-of-type(3){transition-delay:1.5s} 3371.globe-wrap.is-visible .pin:nth-of-type(4){transition-delay:1.6s} 3372.globe-wrap.is-visible .pin:nth-of-type(5){transition-delay:1.7s} 3373.globe-wrap.is-visible .pin:nth-of-type(6){transition-delay:1.8s} 3374.globe-wrap.is-visible .pin:nth-of-type(7){transition-delay:1.9s} 3375.globe-wrap.is-visible .pin:nth-of-type(8){transition-delay:2.0s} 3376.globe-wrap.is-visible .pin:nth-of-type(9){transition-delay:2.1s} 3377.globe-wrap.is-visible .pin:nth-of-type(10){transition-delay:2.2s} 3378.globe-wrap.is-visible .pin:nth-of-type(n+11){transition-delay:2.3s} 3379.globe-wrap.is-visible .pin:nth-of-type(n+15){transition-delay:2.4s} 3380.globe-wrap.is-visible .pin:nth-of-type(n+19){transition-delay:2.5s} 3381.pin-dot{ 3382 width:10px;height:10px;border-radius:50%;background:var(--leaf); 3383 box-shadow:0 0 0 0 var(--leaf-glow), 0 0 12px var(--leaf-glow); 3384 animation:pinPulse 2.6s ease-out infinite; 3385 display:block; 3386} 3387@media (max-width:720px){ 3388 .pin-dot{width:7px;height:7px} 3389 .pin.is-featured .pin-dot{width:10px;height:10px} 3390 .pin-label{font-size:10px;padding:3px 7px;left:14px} 3391 .pin{display:none} 3392 .pin.is-featured, .pin.is-urgent{display:block} 3393} 3394.pin.is-urgent .pin-dot{background:var(--coral);box-shadow:0 0 0 0 rgba(226,106,91,.45), 0 0 12px rgba(226,106,91,.5);animation-name:pinPulseUrgent} 3395.pin.is-featured .pin-dot{width:14px;
3395height:14px;background:var(--sun);box-shadow:0 0 0 0 rgba(240,194,95,.45), 0 0 18px rgba(240,194,95,.5);animation-name:pinPulseFeatured} 3396@keyframes pinPulse{ 3397 0%{box-shadow:0 0 0 0 rgba(168,243,65,.5), 0 0 12px var(--leaf-glow)} 3398 70%{box-shadow:0 0 0 14px rgba(168,243,65,0), 0 0 12px var(--leaf-glow)} 3399 100%{box-shadow:0 0 0 0 rgba(168,243,65,0), 0 0 12px var(--leaf-glow)} 3400} 3401@keyframes pinPulseUrgent{ 3402 0%{box-shadow:0 0 0 0 rgba(226,106,91,.5), 0 0 12px rgba(226,106,91,.5)} 3403 70%{box-shadow:0 0 0 14px rgba(226,106,91,0), 0 0 12px rgba(226,106,91,.5)} 3404 100%{box-shadow:0 0 0 0 rgba(226,106,91,0), 0 0 12px rgba(226,106,91,.5)} 3405} 3406@keyframes pinPulseFeatured{ 3407 0%{box-shadow:0 0 0 0 rgba(240,194,95,.5), 0 0 18px rgba(240,194,95,.5)} 3408 70%{box-shadow:0 0 0 18px rgba(240,194,95,0), 0 0 18px rgba(240,194,95,.5)} 3409 100%{box-shadow:0 0 0 0 rgba(240,194,95,0), 0 0 18px rgba(240,194,95,.5)} 3410} 3411.pin-label{ 3412 position:absolute;left:18px;top:-6px;white-space:nowrap; 3413 font-family:var(--body);font-size:11px;letter-spacing:.06em;color:var(--bone); 3414 padding:5px 10px;border-radius:3px;background:rgba(2,7,24,.85);backdrop-filter:blur(8px); 3415 box-shadow:inset 0 0 0 1px rgba(255,255,255,.1); 3416 opacity:0;transform:translateX(-6px);transition:opacity .25s, transform .25s; 3417 pointer-events:none; 3418} 3419.pin:hover .pin-label, .pin.is-featured .pin-label{opacity:1;transform:translateX(0)} 3420.pin.is-featured .pin-label{background:rgba(240,194,95,.15);color:var(--bone);box-shadow:inset 0 0 0 1px rgba(240,194,95,.4)} 3421 3422/* Make pins clickable and slightly bigger for the popup interaction */ 3423.pin{cursor:pointer;pointer-events:auto;padding:8px} 3424.pin:hover .pin-dot{transform:scale(1.15)} 3425.pin .pin-dot{transition:transform .2s} 3426 3427/* Map popup overlay â centred inside the .globe-wrap */ 3428.map-popup{ 3429 position:absolute;z-index:10; 3430 width:min(380px, 90vw); 3431 background:rgba(2,7,24,.96);backdrop-filter:blur(20px); 3432 -webkit-backdrop-filter:blur(20px); 3433 box-shadow:inset 0 0 0 1px rgba(168,243,65,.4), 0 30px 70px -20px rgba(0,0,0,.7); 3434 border-radius:10px;overflow:hidden; 3435 opacity:0; 3436 /* JS sets transform to translate(-50%,-50%) for centring on open */ 3437 transform:translate(-50%, calc(-50% + 8px)) scale(.96); 3438 transition:opacity .3s cubic-bezier(.2,.7,.1,1), transform .3s cubic-bezier(.2,.7,.1,1.2); 3439 pointer-events:none; 3440} 3441.map-popup.is-open{ 3442 opacity:1; 3443 transform:translate(-50%, -50%) scale(1); 3444 pointer-events:auto; 3445} 3446/* A dim layer behind the popup so the rest of the map recedes */ 3447.globe-wrap::after{ 3448 content:"";position:absolute;inset:0;z-index:9;pointer-events:none; 3449 background:rgba(2,7,24,0);transition:background .3s; 3450} 3451.globe-wrap.popup-open::after{background:rgba(2,7,24,.55);pointer-events:auto} 3452.map-popup .mp-img{ 3453 width:100%;aspect-ratio:16/9;background-size:cover;background-position:center; 3454 position:relative; 3455} 3456.map-popup .mp-img::after{ 3457 content:"";position:absolute;inset:0; 3458 background:linear-gradient(180deg, transparent 40%, rgba(2,7,24,.1) 100%); 3459} 3460.map-popup .mp-status{ 3461 position:absolute;top:10px;left:10px;z-index:2; 3462 font-family:var(--body);font-size:10px;letter-spacing:.22em;text-transform:uppercase;font-weight:600; 3463 padding:4px 10px;border-radius:3px;color:var(--bone); 3464 background:rgba(2,7,24,.65);box-shadow:inset 0 0 0 1px rgba(255,255,255,.12); 3465} 3466.map-popup.is-urgent .mp-status{color:var(--coral);box-shadow:inset 0 0 0 1px rgba(226,106,91,.5);background:rgba(226,106,91,.18)} 3467.map-popup.is-featured .mp-status{color:var(--sun);box-shadow:inset 0 0 0 1px rgba(240,194,95,.5);background:rgba(240,194,95,.18)} 3468.map-popup .mp-close{ 3469 position:absolute;top:8px;right:8px;z-index:3; 3470 width:28px;height:28px;border-radius:50%; 3471 display:flex;align-items:center;justify-content:center; 3472 background:rgba(2,7,24,.85);color:var(--bone);font-size:14px;font-weight:700; 3473 cursor:pointer;border:0; 3474 box-shadow:inset 0 0 0 1px rgba(255,255,255,.15); 3475 transition:background .2s; 3476} 3477.map-popup .mp-close:hover{background:rgba(168,243,65,.25)} 3478.map-popup .mp-body{padding:16px 18px 18px} 3479.map-popup .mp-location{ 3480 display:flex;align-items:center;gap:8px; 3481 font-family:var(--body);font-size:11px;letter-spacing:.16em;text-transform:uppercase; 3482 color:var(--leaf);font-weight:600;margin-bottom:6px; 3483} 3484.map-popup .mp-location svg{width:12px;height:12px;stroke:currentColor;stroke-width:1.6;fill:none} 3485.map-popup h3{ 3486 font-family:var(--display);font-weight:800;font-size:18px;line-height:1.2; 3487 letter-spacing:-.015em;color:var(--bone);margin-bottom:4px; 3488} 3489.map-popup .mp-ngo{font-size:12px;
3489color:var(--mist);margin-bottom:10px} 3490.map-popup p{color:var(--mist);font-size:13px;line-height:1.5;margin-bottom:14px} 3491.map-popup .mp-stat{ 3492 display:flex;align-items:center;gap:10px;margin-bottom:14px; 3493 padding:8px 10px;border-radius:6px;background:rgba(168,243,65,.06); 3494 box-shadow:inset 0 0 0 1px rgba(168,243,65,.18); 3495} 3496.map-popup .mp-stat strong{font-family:var(--display);color:var(--leaf);font-weight:800;font-size:18px;letter-spacing:-.02em} 3497.map-popup .mp-stat span{color:var(--mist);font-size:11.5px;line-height:1.3} 3498.map-popup .mp-cta{ 3499 display:inline-flex;align-items:center;gap:8px; 3500 background:var(--leaf);color:var(--ink);font-weight:700;font-size:13px; 3501 padding:10px 16px;border-radius:4px;letter-spacing:.01em; 3502 transition:background .2s, transform .2s; 3503} 3504.map-popup .mp-cta:hover{background:#B9F764;transform:translateX(2px)} 3505.map-popup .mp-cta .arrow{transition:transform .2s} 3506.map-popup .mp-cta:hover .arrow{transform:translateX(3px)} 3507 3508/* Map summary strip â counts by category */ 3509.map-summary{ 3510 display:grid;grid-template-columns:repeat(4,1fr);gap:10px;margin-top:24px; 3511} 3512@media (max-width:560px){.map-summary{grid-template-columns:repeat(2,1fr);gap:8px}} 3513.map-summary .ms{ 3514 padding:18px 18px;border-radius:8px;background:rgba(255,255,255,.025); 3515 box-shadow:inset 0 0 0 1px var(--line-2); 3516 display:grid;grid-template-columns:1fr 60px;align-items:center;column-gap:16px;row-gap:4px; 3517} 3518.map-summary .ms b{ 3519 grid-column:1;grid-row:1; 3520 font-family:var(--display);font-weight:900;font-size:30px;letter-spacing:-.02em;color:var(--bone);line-height:1; 3521} 3522.map-summary .ms span{ 3523 grid-column:1;grid-row:2; 3524 font-size:12px;color:var(--mist);letter-spacing:.06em; 3525} 3526.map-summary .ms .ms-icon{ 3527 grid-column:2;grid-row:1 / span 2; 3528 width:60px;height:60px; 3529 display:flex;align-items:center;justify-content:center; 3530 border-radius:10px;color:var(--leaf); 3531 background:rgba(168,243,65,.10); 3532 box-shadow:inset 0 0 0 1px rgba(168,243,65,.30); 3533} 3534.map-summary .ms .ms-icon svg{width:32px;height:32px;display:block} 3535.map-summary .ms.is-feature b{color:var(--sun)} 3536.map-summary .ms.is-feature .ms-icon{ 3537 color:var(--sun);background:rgba(240,194,95,.10); 3538 box-shadow:inset 0 0 0 1px rgba(240,194,95,.30); 3539} 3540.map-summary .ms.is-active b{color:var(--leaf)} 3541.map-summary .ms.is-urgent b{color:var(--coral)} 3542.map-summary .ms.is-urgent .ms-icon{ 3543 color:var(--coral);background:rgba(226,106,91,.10); 3544 box-shadow:inset 0 0 0 1px rgba(226,106,91,.30); 3545} 3546 3547.globe-legend{ 3548 display:flex;flex-wrap:wrap;align-items:center;gap:16px; 3549 margin-top:40px; 3550} 3551.globe-legend > div{ 3552 display:inline-flex;align-items:center;gap:14px; 3553 font-family:var(--display);font-weight:800;font-size:17px; 3554 letter-spacing:-.005em;color:var(--bone); 3555 padding:16px 24px;border-radius:8px; 3556 background:rgba(255,255,255,.04); 3557 box-shadow:inset 0 0 0 1px var(--line-2); 3558 transition:transform .2s; 3559} 3560.globe-legend > div:hover{transform:translateY(-1px)} 3561.globe-legend .glg-dot{ 3562 width:16px;height:16px;border-radius:50%;flex:0 0 auto; 3563 position:relative; 3564} 3565.globe-legend .glg-dot::after{ 3566 content:"";position:absolute;inset:-5px;border-radius:50%; 3567 border:1.5px solid currentColor;opacity:.4; 3568} 3569.globe-legend .glg-active{background:var(--leaf);color:var(--leaf);box-shadow:0 0 12px var(--leaf-glow)} 3570.globe-legend .glg-urgent{background:var(--coral);color:var(--coral);box-shadow:0 0 12px rgba(226,106,91,.55)} 3571.globe-legend .glg-feature{background:var(--sun);color:var(--sun);box-shadow:0 0 12px rgba(240,194,95,.55)} 3572.globe-legend > div:has(.glg-active){box-shadow:inset 0 0 0 1px rgba(168,243,65,.30);background:rgba(168,243,65,.06)} 3573.globe-legend > div:has(.glg-urgent){box-shadow:inset 0 0 0 1px rgba(226,106,91,.30);background:rgba(226,106,91,.06)} 3574.globe-legend > div:has(.glg-feature){box-shadow:inset 0 0 0 1px rgba(240,194,95,.30);background:rgba(240,194,95,.06)} 3575 3576/* ================================================= 3577 B-ROLL BURST â asymmetric video bento 3578 ================================================= */ 3579.broll-section{position:relative} 3580.broll{display:grid;grid-template-columns:1fr;
3580grid-auto-rows:240px;gap:16px;margin-top:40px} 3581@media (min-width:720px){.broll{grid-template-columns:1fr 1fr;grid-auto-rows:280px;gap:18px}} 3582@media (min-width:1100px){ 3583 .broll{ 3584 grid-template-columns:1.7fr 1fr 1fr; 3585 grid-template-rows:280px 280px; 3586 gap:20px; 3587 } 3588 .broll .b1{grid-column:1;grid-row:1 / span 2} 3589 .broll .b2{grid-column:2 / span 2;grid-row:1} 3590 .broll .b3{grid-column:2;grid-row:2} 3591 .broll .b4{grid-column:3;grid-row:2} 3592} 3593.btile{ 3594 position:relative;border-radius:var(--r-lg);overflow:hidden; 3595 background:var(--ink-60);isolation:isolate; 3596 box-shadow:0 30px 60px -30px rgba(0,0,0,.5), inset 0 0 0 1px rgba(255,255,255,.04); 3597 transition:transform .5s cubic-bezier(.2,.7,.1,1.2), box-shadow .4s; 3598} 3599.btile:hover{transform:translateY(-3px);box-shadow:0 40px 80px -30px rgba(0,0,0,.7), inset 0 0 0 1px rgba(168,243,65,.3)} 3600.btile video, .btile img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;filter:saturate(.95) brightness(.78);transition:filter .5s, transform 1s} 3601.btile:hover video, .btile:hover img{filter:saturate(1.05) brightness(.85);transform:scale(1.04)} 3602.btile::after{content:"";position:absolute;inset:0;background:linear-gradient(180deg, rgba(2,7,24,0) 35%, rgba(2,7,24,.09) 75%, rgba(2,7,24,.11) 100%);pointer-events:none} 3603/* B-roll cards now mirror the project-card pattern: 3604 top-inset two-line chip + clear "Watch on the channel" CTA */ 3605.btile{position:relative} 3606.btile .b-tag{ 3607 position:absolute;top:0;left:0;z-index:3; 3608 display:inline-flex;align-items:center;gap:11px; 3609 padding:9px 14px;border-radius:6px; 3610 background:rgba(2,7,24,.45); 3611 backdrop-filter:blur(14px) saturate(140%); 3612 -webkit-backdrop-filter:blur(14px) saturate(140%); 3613 box-shadow:inset 0 0 0 1px rgba(255,255,255,.10); 3614 font-family:var(--display);color:var(--bone); 3615 max-width:calc(100% - 40px); 3616 transition:box-shadow .3s, transform .3s, background .3s; 3617} 3618.btile:hover .b-tag{ 3619 background:rgba(2,7,24,.60); 3620 box-shadow:inset 0 0 0 1px rgba(168,243,65,.45), 3621 0 10px 30px -8px rgba(168,243,65,.35); 3622 transform:translateY(-1px); 3623} 3624.btile .b-tag .dot{ 3625 width:7px;height:7px;border-radius:50%;background:var(--leaf); 3626 box-shadow:0 0 8px var(--leaf-glow);flex:0 0 7px; 3627 animation:pinPulse 2.6s ease-out infinite; 3628} 3629.btile .b-tag .tag-text{ 3630 display:flex;flex-direction:column;align-items:flex-start;line-height:1.08; 3631} 3632.btile .b-tag .tag-status{ 3633 font-weight:800;font-size:11.5px;letter-spacing:.22em; 3634 text-transform:uppercase;color:var(--bone); 3635} 3636.btile .b-tag .tag-location{ 3637 font-weight:600;font-size:10px;letter-spacing:.12em; 3638 text-transform:uppercase;color:var(--mist); 3639 margin-top:3px;opacity:.85; 3640} 3641/* Meta wrapper spans the full card so the absolutely-positioned chip 3642 anchors to the TOP-LEFT and the title/CTA flex to the BOTTOM */ 3643.btile .b-meta{ 3644 position:absolute;inset:0; 3645 padding:22px 24px;z-index:2; 3646 display:flex;flex-direction:column;justify-content:flex-end;gap:6px; 3647 pointer-events:none; 3648} 3649.btile .b-meta > *{pointer-events:auto} 3650.btile h3{ 3651 font-family:var(--display);font-weight:800; 3652 font-size:clamp(20px,1.8vw,26px);line-height:1.05;letter-spacing:-.02em; 3653 max-width:20ch;margin:0; 3654} 3655.btile .b-sub{color:var(--mist);font-size:13.5px;max-width:34ch;margin:0} 3656.btile .b-cta{ 3657 margin-top:10px; 3658 font-family:var(--display);font-weight:700;font-size:13px; 3659 color:var(--leaf);letter-spacing:.04em; 3660 border-bottom:1px solid rgba(168,243,65,.35); 3661 padding-bottom:4px;width:fit-content; 3662 display:inline-flex;align-items:center;gap:6px; 3663 transition:color .25s, border-color .25s, transform .25s; 3664} 3665.btile .b-cta .arrow{ 3666 display:inline-flex;transition:transform .25s; 3667} 3668.btile:hover .b-cta{ 3669 color:#D3FA9E;border-bottom-color:var(--leaf); 3670} 3671.btile:hover .b-cta .arrow{transform:translateX(4px)} 3672 3673/* CTA tile (text-only, breaks the rhythm) */ 3674.btile.cta-tile{ 3675 background:linear-gradient(150deg, var(--ink-60) 0%, var(--ink-80) 100%); 3676 display:flex;flex-direction:column;justify-content:space-between;padding:24px; 3677} 3678.btile.cta-tile::after{display:none} 3679.btile.cta-tile .b-num{ 3680 font-family:var(--display);font-weight:900;font-size:clamp(48px,5vw,72px);line-height:.95;letter-spacing:-.03em; 3681 background:linear-gradient(180deg, var(--bone) 0%, #8c91a3 100%); 3682 -webkit-background-clip:text;background-clip:text;color:transparent; 3683}
3684.btile.cta-tile .b-num-label{color:var(--mist);font-size:13px;margin-top:6px} 3685.btile.cta-tile .b-cta-row{display:flex;align-items:center;justify-content:space-between;gap:14px} 3686.btile.cta-tile h3{color:var(--bone);font-size:20px;max-width:14ch} 3687.btile.cta-tile .b-arrow{ 3688 width:40px;height:40px;border-radius:4px; 3689 display:grid;place-items:center;flex:0 0 40px; 3690 background:var(--leaf);color:var(--ink);font-weight:700;font-size:18px; 3691 transition:transform .25s, background .25s; 3692} 3693.btile.cta-tile:hover .b-arrow{transform:translateX(4px);background:#B9F764} 3694 3695/* ================================================= 3696 WATCH UNIVERSE â Originals, Podcasts, Kids, News 3697 ================================================= */ 3698.watch-section{position:relative;padding:var(--pad-section) 0;background:var(--ink)} 3699.watch-grid{display:grid;grid-template-columns:1fr;gap:18px;margin-top:40px} 3700@media (min-width:720px){.watch-grid{grid-template-columns:repeat(2,1fr);gap:20px}} 3701@media (min-width:1100px){.watch-grid{grid-template-columns:repeat(4,1fr);gap:18px}} 3702.wtile{ 3703 position:relative;overflow:hidden;border-radius:var(--r-lg); 3704 min-height:340px; 3705 display:flex;flex-direction:column;justify-content:space-between; 3706 padding:24px;isolation:isolate; 3707 background:var(--ink-60); 3708 transition:transform .5s cubic-bezier(.2,.7,.1,1.2), box-shadow .4s; 3709 box-shadow:0 30px 60px -30px rgba(0,0,0,.5), inset 0 0 0 1px rgba(255,255,255,.04); 3710 color:var(--bone); 3711} 3712.wtile:hover{transform:translateY(-4px);box-shadow:0 50px 90px -30px rgba(0,0,0,.7), inset 0 0 0 1px rgba(168,243,65,.3)} 3713.wtile::before{ 3714 content:"";position:absolute;inset:0;z-index:-1; 3715 background-size:cover;background-position:center; 3716 filter:saturate(.85) brightness(.45); 3717 transition:filter .5s, transform 1s cubic-bezier(.2,.7,.1,1); 3718} 3719.wtile:hover::before{filter:saturate(1) brightness(.55);transform:scale(1.05)} 3720.wtile::after{ 3721 content:"";position:absolute;inset:0;z-index:-1; 3722 background:linear-gradient(180deg, rgba(2,7,24,.07) 0%, rgba(2,7,24,.1) 100%); 3723} 3724.wtile .wvideo{ 3725 position:absolute;inset:0;z-index:-2;width:100%;height:100%;object-fit:cover; 3726 filter:saturate(.85) brightness(.45); 3727 transition:filter .5s, transform 1s cubic-bezier(.2,.7,.1,1); 3728} 3729.wtile:hover .wvideo{filter:saturate(1) brightness(.55);transform:scale(1.05)} 3730/* Per-tile bg images */ 3731.wtile.w-originals::before{background-image:url('https://images.squarespace-cdn.com/content/v1/680b6d1bd82ab7606a6e0812/2d5133be-3f2e-4e21-8f46-fef9d53de7c4/1.png?format=1500w')} 3732.wtile.w-podcasts::before{background-image:url('https://images.squarespace-cdn.com/content/v1/680b6d1bd82ab7606a6e0812/93dc6ac0-8b38-4ff2-af21-b036a82389fd/ecoflix_Going+Wild+with+John+and+James+-+Episode+16000+x+4000.jpg?format=1500w')} 3733.wtile.w-kids::before{background-image:url('https://images.squarespace-cdn.com/content/v1/680b6d1bd82ab7606a6e0812/36022021-b843-46b1-ae63-3a304e57b601/ecoflix_elephantnaturepark_6000+x+4000.jpg?format=1500w')} 3734.wtile.w-news::before{background-image:url('https://images.squarespace-cdn.com/content/v1/680b6d1bd82ab7606a6e0812/e2176e9c-ec3a-442e-9f54-8002f1ee3db9/ecoflix_THELASTSTAND_6000+x+4000.jpg?format=1500w')} 3735 3736.wtile .wicon{ 3737 width:44px;height:44px;color:var(--leaf); 3738 display:flex;align-items:center;justify-content:center; 3739 border-radius:6px;background:rgba(168,243,65,.08); 3740 box-shadow:inset 0 0 0 1px rgba(168,243,65,.2); 3741} 3742.wtile .wicon svg{width:28px;height:28px;filter:drop-shadow(0 2px 8px rgba(168,243,65,.35))} 3743.wtile .w-eyebrow{ 3744 font-family:var(--body);font-size:11px;letter-spacing:.22em; 3745 text-transform:uppercase;color:var(--mist);font-weight:600; 3746 display:flex;align-items:center;gap:8px;margin-top:14px; 3747} 3748.wtile h3{ 3749 font-family:var(--display);font-weight:800;font-size:clamp(22px,2.2vw,30px); 3750 line-height:1.05;letter-spacing:-.02em;margin-top:8px;max-width:18ch; 3751} 3752.wtile h3 em{font-style:italic;font-weight:500;color:var(--leaf)} 3753.wtile .w-desc{color:var(--mist);font-size:14px;line-height:1.5;margin-top:10px;max-width:32ch} 3754.wtile .w-link{ 3755 display:inline-flex;align-items:center;gap:6px; 3756 font-size:13px;font-weight:600;color:var(--bone); 3757 padding-bottom:4px;border-bottom:1px solid rgba(255,255,255,.25); 3758 transition:color .25s, border-color .25s; 3759 margin-top:20px;align-self:start; 3760} 3761.wtile:hover .w-link{color:var(--leaf);border-bottom-color:var(--leaf)} 3762.wtile .w-link .arrow{transition:transform .25s} 3763.wtile:hover .w-link .arrow{transform:translateX(4px)} 3764
3765/* ================================================= 3766 STAGE 6 â SHOWCASE: featured trailer 3767 ================================================= */ 3768.feature-trailer{display:block;position:relative;border-radius:var(--r-xl);overflow:hidden;background:#000;aspect-ratio:16/9;max-width:920px;width:100%;margin:0 auto;box-shadow:0 60px 100px -40px rgba(0,0,0,.7), inset 0 0 0 1px rgba(255,255,255,.05);color:inherit;text-decoration:none} 3769.feature-trailer .poster{ 3770 position:absolute;inset:0; 3771 background:url('https://images.squarespace-cdn.com/content/v1/680b6d1bd82ab7606a6e0812/eaa71cc1-d292-4414-9d1a-baebb3020488/ecoflix_FREE_BILLY_6000+x+4000.jpg?format=2500w') center/cover no-repeat; 3772 filter:saturate(.92) contrast(1.05); 3773} 3774.feature-trailer .trailer-video{ 3775 position:absolute;inset:0;width:100%;height:100%;object-fit:cover; 3776 filter:saturate(1) contrast(1.05) brightness(.95); 3777} 3778.feature-trailer::after{content:"";position:absolute;inset:0;background:linear-gradient(180deg, rgba(0,0,0,0) 40%, rgba(0,0,0,.32) 100%), radial-gradient(60% 80% at 50% 60%, rgba(0,0,0,0) 0%, rgba(0,0,0,.16) 100%);pointer-events:none} 3779.feature-trailer .meta{position:absolute;left:clamp(28px,4vw,56px);right:clamp(28px,4vw,56px);bottom:clamp(28px,4vw,56px);z-index:2} 3780.feature-trailer .meta h3{font-size:clamp(28px,3.4vw,56px);line-height:1.02;max-width:18ch;font-weight:800;letter-spacing:-.025em} 3781.feature-trailer .meta h3 em{font-style:italic;font-weight:500;color:var(--leaf)} 3782.feature-trailer .meta p{color:var(--mist);margin-top:10px;max-width:48ch} 3783.feature-trailer .play{ 3784 position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);z-index:3; 3785 width:96px;height:96px;border-radius:50%; 3786 display:grid;place-items:center; 3787 background:rgba(255,255,255,.94);color:var(--ink); 3788 box-shadow:0 30px 60px -20px rgba(0,0,0,.6), 0 0 0 1px rgba(255,255,255,.4); 3789 transition:transform .3s, box-shadow .3s; 3790} 3791.feature-trailer .play::before{ 3792 content:"";position:absolute;inset:-10px;border-radius:50%; 3793 box-shadow:0 0 0 0 rgba(255,255,255,.3); 3794 animation:playPulse 2.6s ease-out infinite; 3795 pointer-events:none; 3796} 3797@keyframes playPulse{ 3798 0%{box-shadow:0 0 0 0 rgba(255,255,255,.35)} 3799 70%{box-shadow:0 0 0 24px rgba(255,255,255,0)} 3800 100%{box-shadow:0 0 0 0 rgba(255,255,255,0)} 3801} 3802.feature-trailer .play:hover{transform:translate(-50%,-50%) scale(1.08);box-shadow:0 40px 80px -20px rgba(0,0,0,.7), 0 0 0 1px rgba(255,255,255,.6)} 3803.feature-trailer .play::after{ 3804 content:"";display:block;border-style:solid; 3805 border-width:14px 0 14px 22px;border-color:transparent transparent transparent var(--ink); 3806 margin-left:5px; 3807} 3808 3809/* ================================================= 3810 PARTNERS marquee 3811 ================================================= */ 3812.partners{padding:var(--pad-section) 0;border-top:1px solid var(--line);border-bottom:1px solid var(--line);background:var(--ink-80)} 3813.marquee{ 3814 position:relative;display:flex;gap:48px;overflow:hidden;margin-top:50px; 3815 mask-image:linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent); 3816 -webkit-mask-image:linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent); 3817} 3818.marquee-track{display:flex;gap:48px;flex:0 0 auto;animation:scroll 50s linear infinite;will-change:transform} 3819@keyframes scroll{to{transform:translateX(-50%)}} 3820.partner{ 3821 display:inline-flex;align-items:center;justify-content:center;gap:14px; 3822 height:64px;min-width:120px;padding:0 12px; 3823 font-family:var(--display);font-weight:700;font-size:18px;color:var(--bone); 3824 white-space:nowrap;opacity:.7; 3825 transition:opacity .3s, color .3s, transform .3s; 3826 position:relative; 3827} 3828.partner img{ 3829 height:44px;width:auto;max-width:180px;object-fit:contain; 3830 filter:brightness(0) invert(1); 3831 opacity:.95; 3832 transition:filter .3s, opacity .3s; 3833} 3834.partner:hover{opacity:1;color:var(--leaf);transform:translateY(-1px)} 3835.partner:hover img{opacity:1} 3836 3837/* ================================================= 3838 100% PROMISE â value prop + watch-the-difference loop 3839 ================================================= */ 3840.promise{ 3841 position:relative;padding:var(--pad-section) 0;overflow:hidden; 3842 background:linear-gradient(180deg, var(--ink) 0%, var(--ink-80) 50%, var(--ink) 100%); 3843 isolation:isolate; 3844} 3845.promise::before{ 3846 content:"";position:absolute;inset:-25%;z-index:-1;pointer-events:none; 3847 background: 3848 radial-gradient(34% 44% at 18% 28%, rgba(168,243,65,.28), transparent 62%), 3849 radial-gradient(34% 44% at 82% 72%, rgba(42,122,59,.32), transparent 62%), 3850 radial-gradient(22% 22% at 50% 50%, rgba(126,225,136,.16), transparent 70%); 3851 filter:blur(70px); 3852 animation:drift 24s ease-in-out infinite alternate, glowBreathe 8s ease-in-out infinite; 3853} 3854.promise-grid{ 3855 display:grid;grid-template-columns:1fr;gap:48px;align-items:center; 3856} 3857@media (min-width:960px){ 3858 .promise-grid{grid-template-columns:1.05fr 1fr;gap:80px} 3859} 3860.promise-left{display:grid;gap:24px} 3861.promise-100{ 3862 font-family:var(--display);font-weight:900; 3863 font-size:clamp(96px,18vw,240px);line-height:.85;letter-spacing:-.05em; 3864 3865 3866 color:var(--leaf);-webkit-text-fill-color:var(--leaf); 3867 3868 display:flex;align-items:baseline;gap:8px; 3869} 3870.promise-100 em{ 3871 font-style:normal;font-weight:900; 3872 font-size:.42em; 3873 background:linear-gradient(180deg, var(--bone) 0%, #8c91a3 100%); 3874 -webkit-background-clip:text;background-clip:text;color:transparent; 3875 letter-spacing:-.02em; 3876 animation:none; 3877} 3878.promise-left h2{ 3879 font-family:var(--display);font-weight:800;font-size:clamp(28px,3.5vw,44px); 3880 line-height:1.05;letter-spacing:-.025em;max-width:22ch; 3881} 3882.promise-left h2 em{font-style:italic;font-weight:500;color:var(--leaf)}
3883.promise-left p{color:var(--mist);font-size:17px;line-height:1.6;max-width:48ch} 3884.promise-mini{ 3885 display:flex;flex-wrap:wrap;gap:10px 14px;margin-top:6px; 3886} 3887.promise-mini span{ 3888 display:inline-flex;align-items:center;gap:8px; 3889 font-family:var(--body);font-size:12px;letter-spacing:.06em;font-weight:500; 3890 color:var(--mist);padding:7px 12px;border-radius:3px; 3891 background:rgba(255,255,255,.03);box-shadow:inset 0 0 0 1px var(--line-2); 3892} 3893.promise-mini svg{width:14px;height:14px;stroke:var(--leaf);stroke-width:1.6;fill:none;stroke-linecap:round;stroke-linejoin:round} 3894 3895/* Right side â watch the difference / update card stack */ 3896.promise-right{position:relative;display:grid;gap:14px} 3897.promise-right .eyebrow{margin-bottom:4px} 3898.promise-right h3{ 3899 font-family:var(--display);font-weight:800;font-size:clamp(22px,2.4vw,30px); 3900 line-height:1.1;letter-spacing:-.02em;max-width:22ch; 3901} 3902.promise-right h3 em{font-style:italic;font-weight:500;color:var(--leaf)} 3903.update-stream{display:grid;gap:14px;margin-top:18px} 3904.update-card{ 3905 display:grid;grid-template-columns:64px 1fr auto;gap:16px;align-items:center; 3906 padding:16px;border-radius:8px; 3907 background:rgba(255,255,255,.025); 3908 box-shadow:inset 0 0 0 1px var(--line-2); 3909 transition:transform .35s cubic-bezier(.2,.7,.1,1.2), box-shadow .3s, background .3s; 3910} 3911.update-card:hover{ 3912 transform:translateX(4px); 3913 background:rgba(168,243,65,.04); 3914 box-shadow:inset 0 0 0 1px rgba(168,243,65,.3); 3915} 3916.update-thumb{ 3917 width:64px;height:64px;border-radius:6px;overflow:hidden; 3918 background-size:cover;background-position:center; 3919 box-shadow:inset 0 0 0 1px rgba(255,255,255,.05); 3920} 3921.update-body{display:grid;gap:4px;min-width:0} 3922.update-meta{ 3923 font-family:var(--body);font-size:10.5px;letter-spacing:.18em;text-transform:uppercase; 3924 color:var(--leaf);font-weight:600;display:flex;align-items:center;gap:8px; 3925} 3926.update-meta .ud{width:5px;height:5px;border-radius:50%;background:var(--leaf);box-shadow:0 0 6px var(--leaf-glow);animation:pulse 2.4s ease-out infinite} 3927.update-title{font-family:var(--display);font-weight:700;font-size:15px;line-height:1.25;letter-spacing:-.01em;color:var(--bone)} 3928.update-desc{color:var(--mist);font-size:13px;line-height:1.45;margin-top:2px} 3929.update-cta{ 3930 color:var(--mist-2);font-size:18px;transition:color .25s, transform .25s;align-self:center; 3931 flex:0 0 auto;display:flex;align-items:center;gap:10px; 3932} 3933.update-cta .uicon{ 3934 width:24px;height:24px;color:var(--leaf);opacity:.5; 3935 display:flex;align-items:center;justify-content:center; 3936 transition:opacity .25s; 3937} 3938.update-cta .uicon svg{width:14px;height:14px;stroke:currentColor;stroke-width:1.6;fill:none;stroke-linecap:round;stroke-linejoin:round} 3939.update-card:hover .update-cta{color:var(--leaf);transform:translateX(3px)} 3940.update-card:hover .uicon{opacity:1} 3941 3942/* ================================================= 3943 FOUNDER QUOTE â David Casselman, Ecoflix 3944 ================================================= */ 3945.founder-quote{ 3946 position:relative;padding:var(--pad-section) 0;overflow:hidden; 3947 background:#000;isolation:isolate;color:var(--bone); 3948} 3949.founder-quote .fq-video{ 3950 position:absolute;inset:0;z-index:-2;width:100%;height:100%;object-fit:cover; 3951 /* Lightened so the video reads cleanly under the quote. Was 3952 brightness(.32) + a 65-85% black overlay on top â together 3953 that suppressed the footage almost to black. Now the video 3954 stays near its true tonality and the overlay handles only 3955 a subtle darkening. */ 3956 filter:saturate(1) brightness(.95) contrast(1.05); 3957} 3958.founder-quote::after{ 3959 content:"";position:absolute;inset:0;z-index:-1;pointer-events:none; 3960 background: 3961 radial-gradient(60% 70% at 30% 40%, rgba(168,243,65,.03), transparent 65%), 3962 linear-gradient(180deg, rgba(2,7,24,.12), rgba(2,7,24,.12)); 3963} 3964.founder-quote .wrap-narrow{position:relative;z-index:1} 3965.fq-eyebrow{ 3966 display:inline-flex;align-items:center;gap:12px; 3967 font-family:var(--body);font-size:11px;letter-spacing:.26em;text-transform:uppercase; 3968 color:var(--leaf);font-weight:700;margin-bottom:32px; 3969} 3970.fq-eyebrow::before{ 3971 content:"";width:32px;height:1px;background:var(--leaf);box-shadow:0 0 6px var(--leaf-glow); 3972} 3973.fq-text{ 3974 font-family:var(--display);font-weight:500;font-style:italic; 3975 font-size:clamp(28px,4.2vw,56px);line-height:1.15;letter-spacing:-.02em; 3976 max-width:24ch;color:var(--bone); 3977 text-shadow:none; 3978} 3979.fq-text em{ 3980 font-style:italic;font-weight:500; 3981 3982 3983 color:var(--leaf);-webkit-text-fill-color:var(--leaf); 3984 3985} 3986.fq-attribution{ 3987 display:flex;align-items:center;gap:18px;margin-top:48px; 3988} 3989.fq-avatar{ 3990 width:108px;height:108px;border-radius:50%;flex:0 0 108px; 3991 background-image:url('https://ecoflix.com/wp-content/uploads/elementor/thumbs/1_APPROVED-q46rqy56t03hkwo8el10xmpqojy75v4fwtsji6e0lk.jpg'); 3992 background-size:cover;background-position:center top; 3993 box-shadow:0 0 0 2px rgba(168,243,65,.5), 0 0 0 6px rgba(168,243,65,.08), 0 14px 36px -10px rgba(0,0,0,.7); 3994} 3995.fq-meta strong{ 3996 display:block;font-family:var(--display);font-weight:800;font-size:18px; 3997 letter-spacing:-.01em;color:var(--bone); 3998} 3999.fq-meta span{ 4000 display:block;font-family:var(--body);font-size:12px;
4000color:var(--mist); 4001 letter-spacing:.18em;text-transform:uppercase;margin-top:4px;font-weight:600; 4002} 4003.fq-meta a{display:inline-flex;color:var(--leaf);font-size:13px;font-weight:600;margin-top:8px;border-bottom:1px solid rgba(168,243,65,.3);padding-bottom:2px;transition:border-color .2s} 4004.fq-meta a:hover{border-bottom-color:var(--leaf)} 4005/* Coord lozenge override inside .fq-meta â the generic 'span' rule 4006 above would otherwise cascade into the lozenge's children */ 4007.fq-meta .coord-stamp{display:inline-flex;margin:0 0 10px;letter-spacing:.14em} 4008.fq-meta .coord-stamp .cs-lat, 4009.fq-meta .coord-stamp .cs-lon{display:inline-flex;margin-top:0;letter-spacing:.14em;font-size:10.5px;color:rgba(168,243,65,.92)} 4010.fq-meta .coord-stamp .cs-sep{display:inline-block;margin-top:0;font-size:0} 4011 4012/* ================================================= 4013 TIMELINE â "How we got here" milestone spine 4014 ================================================= */ 4015.timeline-section{position:relative;padding:var(--pad-section) 0;background:linear-gradient(180deg, var(--ink-80) 0%, var(--ink) 100%)} 4016.timeline-section .s-head{margin-bottom:80px} 4017.timeline{position:relative;max-width:1080px;margin:0 auto;padding:0 var(--pad-x)} 4018.timeline::before{ 4019 content:"";position:absolute;left:50%;top:0;bottom:0;width:1px; 4020 background:linear-gradient(180deg, transparent, var(--line-2) 8%, var(--line-2) 92%, transparent); 4021 transform:translateX(-50%); 4022} 4023@media (max-width:880px){ 4024 .timeline::before{left:20px} 4025} 4026.tl-item{ 4027 position:relative;display:grid;grid-template-columns:1fr 60px 1fr;gap:0; 4028 margin-bottom:80px;align-items:start; 4029} 4030.tl-item:last-child{margin-bottom:0} 4031@media (max-width:880px){ 4032 .tl-item{grid-template-columns:40px 1fr;gap:20px;margin-bottom:60px} 4033 .tl-item .tl-side{order:2;grid-column:2} 4034 .tl-item .tl-marker{order:1;grid-column:1;justify-self:start} 4035 .tl-item .tl-spacer{display:none} 4036} 4037.tl-item .tl-side{padding:0 32px;opacity:0;transform:translateY(20px);transition:opacity .8s, transform .8s cubic-bezier(.2,.7,.1,1)} 4038.tl-item.in .tl-side{opacity:1;transform:translateY(0)} 4039.tl-item:nth-child(even) .tl-side{grid-column:1;text-align:right} 4040.tl-item:nth-child(even) .tl-spacer{grid-column:3} 4041.tl-item:nth-child(odd) .tl-spacer{grid-column:1} 4042.tl-item:nth-child(odd) .tl-side{grid-column:3;text-align:left} 4043@media (max-width:880px){ 4044 .tl-item:nth-child(even) .tl-side, 4045 .tl-item:nth-child(odd) .tl-side{text-align:left;grid-column:2} 4046} 4047.tl-marker{ 4048 grid-column:2;justify-self:center;position:relative;z-index:2; 4049 width:60px;height:60px;border-radius:50%; 4050 display:grid;place-items:center; 4051 background:var(--ink); 4052 box-shadow:inset 0 0 0 1px var(--line-2), 0 12px 30px -12px rgba(0,0,0,.6); 4053 font-family:var(--display);font-weight:800;color:var(--bone);font-size:14px;letter-spacing:-.01em; 4054 transition:box-shadow .4s, background .4s; 4055} 4056.tl-item.in .tl-marker{ 4057 box-shadow:inset 0 0 0 1px var(--leaf), 0 12px 40px -10px var(--leaf-glow); 4058 background:radial-gradient(60% 60% at 30% 30%, var(--ink-60), var(--ink)); 4059} 4060.tl-item.is-future .tl-marker{ 4061 background:radial-gradient(60% 60% at 30% 30%, var(--leaf), var(--leaf-deep)); 4062 color:var(--ink); 4063 box-shadow:0 16px 50px -10px var(--leaf-glow), inset 0 0 0 1px rgba(255,255,255,.2); 4064} 4065.tl-year{font-family:var(--display);font-weight:900;font-size:clamp(28px,3vw,42px);color:var(--bone);letter-spacing:-.025em;line-height:1} 4066.tl-year em{font-style:italic;font-weight:500;color:var(--leaf)} 4067.tl-headline{font-family:var(--display);font-weight:700;font-size:clamp(18px,1.7vw,24px);margin-top:8px;line-height:1.15;letter-spacing:-.015em;color:var(--bone)} 4068.tl-body{color:var(--mist);font-size:15px;margin-top:10px;line-height:1.55;max-width:42ch} 4069.tl-item:nth-child(even) .tl-body{margin-left:auto} 4070@media (max-width:880px){ 4071 .tl-item:nth-child(even) .tl-body{margin-left:0} 4072} 4073.tl-tags{display:flex;gap:8px;margin-top:14px;flex-wrap:wrap} 4074.tl-item:nth-child(even) .tl-tags{justify-content:flex-end} 4075@media (max-width:880px){ 4076 .tl-item:nth-child(even) .tl-tags{justify-content:flex-start} 4077} 4078.tl-tag{ 4079 font-family:var(--body);font-size:11px;letter-spacing:.14em;text-transform:uppercase; 4080 font-weight:600;
4080color:var(--mist); 4081 padding:5px 9px;border-radius:3px;background:rgba(255,255,255,.04); 4082 box-shadow:inset 0 0 0 1px var(--line-2); 4083} 4084.tl-item.is-now .tl-tag{color:var(--leaf);box-shadow:inset 0 0 0 1px rgba(168,243,65,.3);background:rgba(168,243,65,.06)} 4085.tl-item.is-future .tl-tag{color:var(--sun);box-shadow:inset 0 0 0 1px rgba(240,194,95,.3);background:rgba(240,194,95,.06)} 4086 4087/* ================================================= 4088 STAGE 7 â CONVERT: Animated paths donate CTA 4089 ================================================= */ 4090.convert{ 4091 position:relative;text-align:center; 4092 padding:clamp(120px,18vh,200px) var(--pad-x); 4093 overflow:hidden;isolation:isolate; 4094 background:var(--ink); 4095} 4096.convert::before{ 4097 content:"";position:absolute;inset:-25%;z-index:-2;pointer-events:none; 4098 background: 4099 radial-gradient(52% 42% at 50% 50%, rgba(168,243,65,.36), transparent 62%), 4100 radial-gradient(30% 28% at 20% 80%, rgba(42,122,59,.22), transparent 70%), 4101 radial-gradient(30% 28% at 80% 20%, rgba(126,225,136,.18), transparent 70%); 4102 filter:blur(60px); 4103 animation:drift 22s ease-in-out infinite alternate, glowBreathe 7s ease-in-out infinite; 4104} 4105.convert h2{font-family:var(--display);font-weight:900;font-size:clamp(44px,7.5vw,128px);max-width:18ch;margin:0 auto;line-height:.95;letter-spacing:-.03em} 4106.convert h2 em{ 4107 font-style:italic;font-weight:500; 4108 4109 4110 color:var(--leaf);-webkit-text-fill-color:var(--leaf); 4111 4112} 4113.convert p{margin:28px auto 0;max-width:54ch;color:var(--mist);font-size:18px} 4114.convert .actions{margin-top:44px;display:flex;justify-content:center;gap:18px;flex-wrap:wrap;align-items:center} 4115 4116/* ================================================= 4117 FAQ 4118 ================================================= */ 4119.faq-list{display:grid;gap:0;border-top:1px solid var(--line);margin-top:30px} 4120.faq-item{border-bottom:1px solid var(--line);padding:0} 4121.faq-item summary{ 4122 list-style:none;display:flex;align-items:center;justify-content:space-between;gap:20px; 4123 padding:24px 0;cursor:pointer; 4124} 4125.faq-item summary::-webkit-details-marker{display:none} 4126.faq-item summary::marker{content:""} 4127.faq-item summary:focus-visible{outline:2px solid var(--leaf);outline-offset:4px;border-radius:4px} 4128.faq-q{display:contents} 4129.faq-q h3{font-family:var(--display);font-size:clamp(20px,2vw,26px);font-weight:700;color:var(--bone);transition:color .25s;display:flex;align-items:center;gap:14px} 4130.faq-q h3 .qicon{ 4131 width:28px;height:28px;flex:0 0 28px; 4132 display:flex;align-items:center;justify-content:center; 4133 color:var(--leaf);border-radius:5px;background:rgba(168,243,65,.06); 4134 box-shadow:inset 0 0 0 1px rgba(168,243,65,.18); 4135 transition:background .25s, transform .35s; 4136} 4137.faq-item[open] .qicon{background:rgba(168,243,65,.14);transform:rotate(8deg)} 4138.faq-q h3 .qicon svg{width:14px;height:14px;stroke:currentColor;stroke-width:1.6;fill:none;stroke-linecap:round;stroke-linejoin:round} 4139.faq-item:hover summary .faq-q h3{color:var(--leaf)} 4140.faq-toggle{width:36px;height:36px;border-radius:50%;flex:0 0 36px;display:flex;align-items:center;justify-content:center;box-shadow:inset 0 0 0 1px var(--line-2);transition:transform .35s, background .25s;font-weight:700} 4141.faq-item[open] .faq-toggle{transform:rotate(45deg);background:var(--leaf);color:var(--ink)} 4142.faq-a{color:var(--mist);font-size:16px;line-height:1.65;padding:0 60px 24px 0} 4143 4144/* ================================================= 4145 Footer 4146 ================================================= */ 4147.footer{background:var(--ink-80);border-top:1px solid var(--line);padding:80px 0 40px;color:var(--mist);font-size:14px} 4148.footer-grid{display:grid;grid-template-columns:1fr;gap:40px} 4149@media (min-width:720px){.footer-grid{grid-template-columns:2fr 1fr 1fr 1fr}} 4150.footer h4{font-family:var(--body);font-size:12px;letter-spacing:.18em;text-transform:uppercase;color:var(--bone);font-weight:700;margin-bottom:18px} 4151.footer ul{list-style:none;display:grid;gap:10px} 4152.footer a:hover{color:var(--bone)} 4153.footer-brand p{margin-top:18px;max-width:36ch;line-height:1.6} 4154.socials{display:flex;gap:10px;margin-top:20px} 4155.socials a{width:38px;height:38px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;box-shadow:inset 0 0 0 1px var(--line-2);transition:.25s} 4156.socials a:hover{background:var(--leaf);color:var(--ink)} 4157.footer-base{margin-top:60px;padding-top:24px;border-top:1px solid var(--line);display:flex;justify-content:space-between;flex-wrap:wrap;gap:16px;font-size:13px;
4157color:var(--mist-2)} 4158.footer-stats{display:flex;flex-wrap:wrap;gap:30px;margin-top:30px;padding:20px 0;border-top:1px solid var(--line);border-bottom:1px solid var(--line)} 4159.footer-stats div{font-family:var(--display);font-size:14px;color:var(--mist)} 4160.footer-stats b{display:block;font-family:var(--display);font-size:26px;color:var(--bone);font-weight:900;line-height:1} 4161 4162/* ================================================= 4163 Word-by-word reveal (split-letter style) 4164 ================================================= */ 4165.reveal-words .word{display:inline-block;overflow:hidden;vertical-align:bottom;line-height:1.15;padding-bottom:.08em} 4166.reveal-words .word-inner{ 4167 display:inline-block; 4168 transform:translateY(110%) skewY(5deg); 4169 transition:transform 1s cubic-bezier(.7,0,.2,1); 4170 will-change:transform; 4171} 4172.reveal-words.in .word-inner{transform:translateY(0) skewY(0)} 4173.reveal-words.in .word:nth-child(1) .word-inner{transition-delay:0s} 4174.reveal-words.in .word:nth-child(2) .word-inner{transition-delay:.06s} 4175.reveal-words.in .word:nth-child(3) .word-inner{transition-delay:.12s} 4176.reveal-words.in .word:nth-child(4) .word-inner{transition-delay:.18s} 4177.reveal-words.in .word:nth-child(5) .word-inner{transition-delay:.24s} 4178.reveal-words.in .word:nth-child(6) .word-inner{transition-delay:.30s} 4179.reveal-words.in .word:nth-child(7) .word-inner{transition-delay:.36s} 4180.reveal-words.in .word:nth-child(8) .word-inner{transition-delay:.42s} 4181.reveal-words.in .word:nth-child(9) .word-inner{transition-delay:.48s} 4182.reveal-words.in .word:nth-child(10) .word-inner{transition-delay:.54s} 4183 4184/* When .reveal-words wraps text inside <em>, the parent em's 4185 background-clip:text gradient gets orphaned because the actual text 4186 is now inside .word-inner spans. Reapply the gradient onto those 4187 inner spans so leaf-green emphasis words render correctly. */ 4188.reveal-words em .word-inner{ 4189 4190 4191 color:var(--leaf);-webkit-text-fill-color:var(--leaf); 4192 4193} 4194 4195/* ================================================= 4196 Reveals 4197 ================================================= */ 4198.reveal{opacity:0;transform:translateY(36px);transition:opacity .9s, transform .9s cubic-bezier(.2,.7,.1,1)} 4199.reveal.in{opacity:1;transform:translateY(0)} 4200.reveal-stagger > *{opacity:0;transform:translateY(24px);transition:opacity .8s, transform .8s cubic-bezier(.2,.7,.1,1)} 4201.reveal-stagger.in > *{opacity:1;transform:translateY(0)} 4202.reveal-stagger.in >
4202 *:nth-child(1){transition-delay:.05s} 4203.reveal-stagger.in > *:nth-child(2){transition-delay:.15s} 4204.reveal-stagger.in > *:nth-child(3){transition-delay:.25s} 4205.reveal-stagger.in > *:nth-child(4){transition-delay:.35s} 4206.reveal-stagger.in > *:nth-child(5){transition-delay:.45s} 4207.reveal-stagger.in > *:nth-child(6){transition-delay:.55s} 4208 4209@media (prefers-reduced-motion: reduce){ 4210 *,*::before,*::after{animation:none!important;transition:none!important} 4211 .reveal,.reveal-stagger > *{opacity:1;transform:none} 4212} 4213 4214/* ============ Project detail "From the field" gallery ============ */ 4215.pd-gallery{ 4216 padding:60px var(--pad-x);max-width:1180px;margin:0 auto; 4217} 4218.pd-gallery .pdg-head{ 4219 display:flex;align-items:baseline;justify-content:space-between; 4220 margin-bottom:28px;flex-wrap:wrap;gap:14px; 4221} 4222.pd-gallery h2{ 4223 font-family:var(--display);font-weight:800; 4224 font-size:clamp(28px,3.5vw,44px);letter-spacing:-.02em; 4225 margin:0;color:var(--bone); 4226} 4227.pd-gallery h2 em{font-style:italic;font-weight:500;color:var(--leaf)} 4228.pd-gallery .pdg-meta{ 4229 font-family:var(--body);font-weight:600; 4230 font-size:11px;letter-spacing:.22em;text-transform:uppercase;color:var(--mist); 4231} 4232.pdg-grid{ 4233 display:grid;grid-template-columns:1.4fr 1fr 1fr; 4234 grid-template-rows:repeat(2, minmax(180px, 1fr)); 4235 gap:14px; 4236} 4237@media (max-width:880px){ 4238 .pdg-grid{grid-template-columns:1fr 1fr;grid-template-rows:auto} 4239} 4240@media (max-width:520px){ 4241 .pdg-grid{grid-template-columns:1fr} 4242} 4243.pdg-tile{ 4244 position:relative;overflow:hidden;border-radius:18px; 4245 background:var(--ink-60); 4246 border:1px solid rgba(255,255,255,.06); 4247 min-height:200px; 4248 transition:transform .35s cubic-bezier(.22,.9,.3,1), border-color .25s ease; 4249} 4250.pdg-tile:hover{transform:translateY(-3px);border-color:rgba(168,243,65,.45)} 4251.pdg-tile.is-feature{grid-column:1;grid-row:1 / span 2} 4252@media (max-width:880px){.pdg-tile.is-feature{grid-column:auto;grid-row:auto}} 4253.pdg-img{ 4254 position:absolute;inset:0; 4255 background-size:cover;background-position:center; 4256 transition:transform 1.2s cubic-bezier(.22,.9,.3,1), filter .35s ease; 4257 filter:saturate(.95); 4258} 4259.pdg-tile:hover .pdg-img{transform:scale(1.06);filter:saturate(1.1)} 4260.pdg-tile::after{ 4261 content:"";position:absolute;inset:0; 4262 background:linear-gradient(180deg, transparent 50%, rgba(2,7,24,.1)); 4263 pointer-events:none; 4264} 4265.pdg-cap{ 4266 position:absolute;left:18px;right:18px;bottom:16px;z-index:2; 4267 font-family:var(--display);font-weight:600;font-size:13px; 4268 color:var(--bone);letter-spacing:.01em;line-height:1.3; 4269} 4270.pdg-cap .pdg-coord{ 4271 display:block; 4272 font-size:10px;letter-spacing:.22em;text-transform:uppercase; 4273 color:rgba(168,243,65,.85);font-weight:700;margin-top:4px; 4274} 4275 4276/* NGO context card (sits in side column) */ 4277.pd-ngo-card{ 4278 margin-top:18px;padding:20px;border-radius:16px; 4279 background:rgba(2,7,24,.5); 4280 border:1px solid rgba(255,255,255,.08); 4281 display:flex;align-items:center;gap:14px; 4282} 4283.pd-ngo-card .pdng-logo{ 4284 width:54px;height:54px;border-radius:12px;flex:0 0 54px; 4285 background:rgba(255,255,255,.92);background-size:contain;background-repeat:no-repeat;background-position:center; 4286 border:1px solid rgba(255,255,255,.1); 4287} 4288.pd-ngo-card .pdng-name{ 4289 font-family:var(--display);font-weight:700;font-size:15px; 4290 color:var(--bone);margin-bottom:2px;line-height:1.2; 4291} 4292.pd-ngo-card .pdng-link{ 4293 font-family:var(--display);font-weight:600;font-size:12px; 4294 color:var(--leaf);text-decoration:none;letter-spacing:.04em; 4295} 4296.pd-ngo-card .pdng-link:hover{color:#B9F764} 4297 4298/* Partner-NGO logo strip (mission / how-we-help) */ 4299.ngo-strip{ 4300 margin:0 auto;max-width:1180px; 4301 padding:60px var(--pad-x);text-align:center; 4302} 4303.ngo-strip .ngs-label{ 4304 font-size:11px;letter-spacing:.26em;text-transform:uppercase; 4305 color:var(--mist);font-weight:600;margin-bottom:24px; 4306} 4307.ngo-strip .ngs-grid{ 4308 display:grid;grid-template-columns:repeat(6,1fr);gap:18px;align-items:center; 4309} 4310@media (max-width:880px){.ngo-strip .ngs-grid{grid-template-columns:repeat(3,1fr)}} 4311@media (max-width:520px){.ngo-strip .ngs-grid{grid-template-columns:repeat(2,1fr)}} 4312.ngo-strip .ngs-logo{ 4313 height:50px;border-radius:10px; 4314 background:rgba(255,255,255,.92); 4315 background-size:contain;background-repeat:no-repeat;background-position:center; 4316 filter:saturate(.6);opacity:.78; 4317 transition:filter .25s ease, opacity .25s ease, transform .25s ease; 4318 border:1px solid rgba(255,255,255,.05); 4319} 4320.ngo-strip .ngs-logo:hover{filter:saturate(1);opacity:1;transform:translateY(-2px)} 4321
4322/* ============ Mobile padding pass ============ */ 4323@media (max-width:760px){ 4324 /* Compare cards: shrink internal padding so content has room */ 4325 .compare-card{padding:28px 22px 24px !important} 4326 .compare-card .cc-pct{font-size:clamp(64px,18vw,108px) !important} 4327 .compare-card .cc-label{font-size:15px} 4328 .compare-vs{width:54px;height:54px;font-size:15px;margin:8px auto} 4329 4330 /* Impact calculator: tighter padding + full available width */ 4331 .impact-calc{padding:22px 20px 22px !important;margin:14px auto 0 !important;max-width:none !important} 4332 /* Eco-bridge mobile: mirror the .impact-calc mobile padding so the 4333 two cards stack at the same horizontal rhythm. */ 4334 .eco-bridge{padding:22px 20px 22px !important;margin:24px auto 12px !important;max-width:none !important} 4335 .eco-bridge-head{margin-bottom:14px !important} 4336 .eco-bridge-title{font-size:20px !important} 4337 .calc-amount{font-size:clamp(40px,14vw,64px)} 4338 .calc-impact{grid-template-columns:auto 1fr;padding:14px 14px} 4339 .calc-impact-icon{width:44px;height:44px;flex:0 0 44px} 4340 4341 /* Tonight strip: stop double-subtracting pad-x â let parent .wrap padding handle it */ 4342 .tonight-strip{width:auto !important;max-width:none !important;margin:48px 0 0 !important} 4343 .tonight-hero .th-body{padding:24px 22px} 4344 .tonight-hero .th-title{font-size:clamp(22px,5.5vw,32px) !important} 4345 4346 /* Nearme strip: same fix */ 4347 .nearme{width:auto !important;max-width:none !important;margin:8px var(--pad-x) 28px !important} 4348 4349 /* Live feed and side panels: don't constrain via outer width calc */ 4350 .live-feed{width:auto !important;max-width:none !important;margin:32px 0 0 !important;padding:18px 18px 14px} 4351 .impacts-panel,.stories-panel,.projects-panel{padding:18px 18px} 4352 4353 /* Live giving rows: line wraps cleanly */ 4354 .live-feed .lf-body{flex-wrap:wrap;gap:4px} 4355 .live-feed .lf-meta{font-size:11px;width:100%;text-align:left} 4356 4357 /* Section big headings: hold the line on size */ 4358 .pg-hero{padding:120px var(--pad-x) 48px !important} 4359 .pg-hero h1{font-size:clamp(40px,11vw,72px) !important} 4360 .pd-hero{height:auto !important;min-height:520px !important;padding:120px 0 40px} 4361 .pd-hero h1{font-size:clamp(40px,11vw,72px) !important} 4362 .pd-stats{margin-top:-24px} 4363 .pd-stat{padding:16px 14px} 4364 .pd-stat .pds-num{font-size:clamp(22px,5.5vw,28px)} 4365 .pd-body{padding:48px var(--pad-x)} 4366 .pd-side{position:static;padding:22px 20px} 4367 4368 /* Mission and how-we-help hero copy */ 4369 .mission-section{padding:48px var(--pad-x)} 4370 .mission-section h2{font-size:clamp(28px,7vw,40px)} 4371 .ways{padding:32px var(--pad-x) 80px} 4372 .way{padding:28px 22px} 4373 .way h3{font-size:clamp(22px,6vw,28px) !important} 4374 4375 /* Coord stamp on small cards: keep it tidy */ 4376 .pd-tag{font-size:10px;padding:5px 10px;letter-spacing:.14em} 4377 .pd-tags{gap:6px} 4378 4379 /* Tighter species counter on mobile */ 4380 .species-counter .sc-caption{font-size:clamp(22px,6vw,32px) !important;line-height:1.15} 4381 .species-counter .sc-sub{font-size:15px;max-width:38ch} 4382 .species-counter .sc-number{font-size:clamp(72px,20vw,128px) !important} 4383 4384 /* Compare section padding */ 4385 .compare-section{padding:64px var(--pad-x) 32px !important} 4386 .compare h3{font-size:clamp(34px,9vw,56px) !important;margin-bottom:14px} 4387 .compare-lede{font-size:16px;margin-bottom:36px} 4388 .compare-eyebrow{font-size:11px;letter-spacing:.22em;gap:8px} 4389 .compare-eyebrow::before,.compare-eyebrow::after{width:18px} 4390 .compare-foot{flex-direction:column;gap:8px;margin-top:32px} 4391 4392 /* Hp-promise: keep the headline readable */ 4393 .hp-promise{height:auto !important;min-height:90vh;padding:120px 0 80px !important} 4394 .hp-promise .hp-pct{font-size:clamp(56px,14vw,96px) !important} 4395 .hp-promise .hp-headline{font-size:clamp(20px,5.5vw,28px) !important;max-width:24ch} 4396 .hp-promise .hp-supporting{font-size:14.5px} 4397 .hp-promise .hp-chips{gap:6px;flex-wrap:wrap;justify-content:center} 4398 .hp-promise .hp-chip{font-size:10px;padding:6px 11px} 4399 4400 /* Sticky donate bar: tighter */ 4401 .sdb{padding:8px 14px} 4402 .sdb-txt{font-size:11.5px;letter-spacing:0} 4403 .sdb-mark{width:24px;height:24px;flex:0 0 24px;font-size:12px} 4404 .sdb-actions .sdb-btn{font-size:11.5px;padding:7px 12px} 4405
4406 /* Hero stat cards 2x2: tighter padding. (The old 4407 .hero-card-copy{padding-bottom:40px} clearance hack is gone â the 4408 header-safe overlay's structural bottom padding already clears more.) */ 4409 .hero-stats{margin-top:24px !important} 4410 .hero-stats-eyebrow{margin-bottom:18px !important} 4411 .hstat{padding:14px 14px !important;gap:6px !important} 4412 .hnum{font-size:clamp(28px,8vw,38px) !important} 4413 .htitle{font-size:12px !important;letter-spacing:.02em !important} 4414 .hlbl{font-size:10.5px !important;line-height:1.35 !important} 4415 /* Header on mobile: hide channel button to free space */ 4416 .header .header-cta .btn-ghost{display:none} 4417 .header .header-cta .btn-primary{padding:9px 14px;font-size:12px} 4418 4419 /* Project card padding on mobile */ 4420 .proj-card .meta{padding:18px 18px !important} 4421 .proj-card h3{font-size:clamp(22px,6vw,28px) !important} 4422 4423 /* Watch-the-change: don't crush the headline */ 4424 .watch-change .wc-headline{font-size:clamp(38px,11vw,56px) !important} 4425} 4426 4427@media (max-width:480px){ 4428 .compare-card{padding:24px 18px 22px !important} 4429 .compare-card .cc-pct{font-size:clamp(56px,18vw,84px) !important} 4430 .tonight-hero{grid-template-columns:1fr} 4431 .tonight-hero .th-media{min-height:200px} 4432 .pg-hero h1{font-size:clamp(34px,11vw,60px) !important} 4433 .pd-hero h1{font-size:clamp(34px,11vw,60px) !important} 4434 .pd-stats-inner{grid-template-columns:1fr 1fr} 4435 .pd-stat .pds-num{font-size:22px} 4436 .sdb-txt{display:none} 4437 .sdb-mark{display:none} 4438 .sdb{justify-content:flex-end} 4439} 4440 4441 4442/* ================= UX ENHANCEMENT BUNDLE ================= */ 4443 4444/* === Skip to content + focus rings === */ 4445.skip-to-content{ 4446 position:absolute;left:-9999px;top:8px;z-index:1000; 4447 background:var(--leaf);color:#020718; 4448 padding:10px 18px;border-radius:8px; 4449 font-family:var(--display);font-weight:700;font-size:13px; 4450 text-decoration:none;letter-spacing:.02em; 4451} 4452.skip-to-content:focus{left:24px;outline:3px solid #B9F764;outline-offset:2px} 4453*:focus-visible{ 4454 outline:2px solid var(--leaf); 4455 outline-offset:3px; 4456 border-radius:4px; 4457} 4458a:focus-visible,button:focus-visible, 4459.btn:focus-visible,.btn-quiet:focus-visible{ 4460 outline-offset:4px; 4461} 4462 4463/* === Back-to-top button === */ 4464.bttop{ 4465 position:fixed;right:24px;bottom:24px;z-index:55; 4466 width:46px;height:46px;border-radius:50%; 4467 display:flex;align-items:center;justify-content:center; 4468 border:1px solid rgba(168,243,65,.45); 4469 background:rgba(2,7,24,.7);color:var(--bone); 4470 backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px); 4471 cursor:pointer; 4472 opacity:0;pointer-events:none; 4473 transform:translateY(16px); 4474 transition:opacity .35s ease, transform .35s ease, background .25s ease; 4475} 4476.bttop.show{opacity:1;pointer-events:auto;transform:translateY(0)} 4477.bttop:hover{background:rgba(168,243,65,.18);transform:translateY(-2px)} 4478.bttop svg{width:18px;height:18px} 4479.bttop::before{ 4480 content:"";position:absolute;inset:6px;border-radius:50%; 4481 border:1px dashed rgba(168,243,65,.3); 4482 animation:bttopSpin 14s linear infinite; 4483} 4484@keyframes bttopSpin{to{transform:rotate(360deg)}} 4485@media (max-width:600px){ 4486 .bttop{right:14px;bottom:80px;width:40px;height:40px} 4487} 4488 4489/* === Sticky compact donate bar === */ 4490.sdb{ 4491 position:fixed;top:0;left:0;right:0;z-index:80; 4492 padding:10px 22px; 4493 background:rgba(2,7,24,.86); 4494 backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px); 4495 border-bottom:1px solid rgba(168,243,65,.18); 4496 display:flex;align-items:center;justify-content:space-between;gap:18px; 4497 transform:translateY(-110%); 4498 transition:transform .4s cubic-bezier(.22,.9,.3,1); 4499} 4500.sdb.show{transform:translateY(0)} 4501.sdb.atfoot{transform:translateY(-110%)} 4502.sdb-left{display:flex;align-items:center;gap:14px;min-width:0} 4503.sdb-mark{ 4504 width:28px;height:28px;border-radius:6px;flex:0 0 28px; 4505 background:linear-gradient(135deg, var(--leaf), #B9F764); 4506 display:flex;align-items:center;justify-content:center; 4507 color:#020718;font-family:var(--display);font-weight:900;font-size:14px; 4508} 4509.sdb-txt{ 4510 font-family:var(--body);font-size:13.5px;color:var(--bone); 4511 white-space:nowrap;overflow:hidden;text-overflow:ellipsis; 4512} 4513.sdb-txt b{color:var(--leaf);font-weight:700} 4514.sdb-actions{display:flex;gap:10px;align-items:center;flex:0 0 auto} 4515.sdb-actions .sdb-btn{ 4516 appearance:none;border:0;cursor:pointer;text-decoration:none; 4517 background:var(--leaf);color:#020718; 4518 font-family:var(--display);font-weight:700;font-size:13px; 4519 padding:9px 16px;border-radius:999px;letter-spacing:.02em; 4520 display:inline-flex;align-items:center;gap:6px; 4521 transition:transform .2s ease, background .2s ease; 4522} 4523.sdb-actions .sdb-btn:hover{background:#B9F764;transform:translateY(-1px)} 4524.sdb-actions .sdb-ghost{ 4525 background:transparent;color:var(--bone); 4526 border:1px solid rgba(255,255,255,.18); 4527} 4528.sdb-actions .sdb-ghost:hover{border-color:var(--leaf);color:var(--leaf);background:rgba(168,243,65,.05)} 4529@media (max-width:760px){ 4530 .sdb{padding:8px 14px} 4531 .sdb-txt{font-size:12px} 4532 .sdb-actions .sdb-ghost{display:none} 4533} 4534 4535/* === Chapter scroll indicator === */ 4536.chapnav{ 4537 position:fixed;right:22px;top:50%;transform:translateY(-50%); 4538 z-index:40; 4539 display:flex;flex-direction:column;gap:14px; 4540 padding:18px 12px;border-radius:999px; 4541 background:rgba(2,7,24,.42); 4542 backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px); 4543 border:1px solid rgba(168,243,65,.16); 4544 opacity:0;transition:opacity .4s ease; 4545 pointer-events:none; 4546} 4547.chapnav.show{opacity:1;pointer-events:auto} 4548.chapnav .chap-dot{ 4549 position:relative;width:10px;height:10px;border-radius:50%; 4550 background:rgba(255,255,255,.18); 4551 cursor:pointer;border:0;padding:0; 4552 transition:background .25s ease, transform .25s ease; 4553} 4554.chapnav .chap-dot:hover{background:rgba(168,243,65,.6);transform:scale(1.3)} 4555.chapnav .chap-dot.is-active{ 4556 background:var(--leaf); 4557 box-shadow:0 0 0 4px rgba(168,243,65,.18); 4558} 4559.chapnav .chap-label{ 4560 position:absolute;right:22px;top:50%;transform:translateY(-50%); 4561 background:rgba(2,7,24,.95);color:var(--bone); 4562 font-family:var(--display);font-weight:600;font-size:12px; 4563 padding:6px 12px;border-radius:6px; 4564 white-space:nowrap; 4565 border:1px solid rgba(168,243,65,.3); 4566 opacity:0;pointer-events:none; 4567 transition:opacity .2s ease, transform .2s ease; 4568} 4569.chapnav .chap-dot:hover .chap-label{opacity:1;transform:translateY(-50%) translateX(-4px)} 4570@media (max-width:880px){.chapnav{display:none}} 4571 4572/* === Cookie / privacy bar === */ 4573.cookbar{ 4574 position:fixed;left:24px;bottom:24px;z-index:55; 4575 max-width:380px; 4576 background:rgba(2,7,24,.92); 4577 border:1px solid rgba(168,243,65,.25); 4578 border-radius:14px; 4579 padding:18px 20px; 4580 font-family:var(--body); 4581 backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px); 4582 box-shadow:0 18px 48px rgba(0,0,0,.5); 4583 transform:translateY(140%);opacity:0; 4584 transition:transform .5s cubic-bezier(.22,.9,.3,1), opacity .35s ease; 4585} 4586.cookbar.show{transform:translateY(0);opacity:1} 4587.cookbar-text{font-size:13px;
4587color:var(--mist);line-height:1.45;margin-bottom:12px} 4588.cookbar-text b{color:var(--bone);font-weight:600} 4589.cookbar-actions{display:flex;gap:8px} 4590.cookbar-actions button{ 4591 appearance:none;cursor:pointer;flex:1; 4592 padding:8px 14px;border-radius:8px; 4593 font-family:var(--display);font-weight:600;font-size:12px;letter-spacing:.04em; 4594 border:1px solid rgba(255,255,255,.15);background:transparent;color:var(--bone); 4595 transition:all .2s ease; 4596} 4597.cookbar-actions .cb-accept{background:var(--leaf);color:#020718;border-color:var(--leaf)} 4598.cookbar-actions .cb-accept:hover{background:#B9F764} 4599.cookbar-actions .cb-decline:hover{border-color:var(--bone);background:rgba(255,255,255,.04)} 4600@media (max-width:600px){ 4601 .cookbar{left:14px;right:14px;bottom:14px;max-width:none} 4602} 4603 4604/* === Image shimmer placeholder === */ 4605.proj-card .img:not(.img-loaded)::before, 4606.btile .b-thumb:not(.img-loaded)::before{ 4607 content:"";position:absolute;inset:0;z-index:1; 4608 background:linear-gradient(90deg, rgba(255,255,255,0) 0%, rgba(168,243,65,.06) 50%, rgba(255,255,255,0) 100%); 4609 background-size:200% 100%; 4610 animation:shimmer 1.6s ease-in-out infinite; 4611} 4612@keyframes shimmer{ 4613 from{background-position:200% 0} 4614 to{background-position:-200% 0} 4615} 4616 4617/* === Save project (heart) === */ 4618.proj-card .save-btn{ 4619 position:absolute;top:18px;right:18px;z-index:5; 4620 width:38px;height:38px;border-radius:50%; 4621 border:1px solid rgba(255,255,255,.2); 4622 background:rgba(2,7,24,.55); 4623 backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px); 4624 display:flex;align-items:center;justify-content:center; 4625 cursor:pointer;color:var(--bone); 4626 transition:all .25s ease; 4627} 4628.proj-card .save-btn:hover{background:rgba(168,243,65,.2);border-color:rgba(168,243,65,.55);transform:scale(1.1)} 4629.proj-card .save-btn svg{width:16px;height:16px;transition:transform .25s ease, fill .25s ease;fill:transparent;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round} 4630.proj-card .save-btn.is-saved{background:rgba(255,91,91,.18);border-color:rgba(255,91,91,.5);color:#ff8a8a} 4631.proj-card .save-btn.is-saved svg{fill:#ff5b5b;stroke:#ff5b5b;animation:heartBeat .55s ease} 4632@keyframes heartBeat{ 4633 0%,100%{transform:scale(1)} 4634 30%{transform:scale(1.3)} 4635 60%{transform:scale(.95)} 4636} 4637 4638/* === Saved projects ribbon === */ 4639.saved-ribbon{ 4640 margin:0 auto 24px;max-width:calc(1080px - var(--pad-x) * 2); 4641 width:calc(100% - var(--pad-x) * 2); 4642 padding:14px 20px; 4643 border-radius:14px; 4644 background:rgba(255,91,91,.06); 4645 border:1px solid rgba(255,91,91,.25); 4646 display:flex;align-items:center;gap:14px;flex-wrap:wrap; 4647 font-family:var(--body);font-size:13.5px;color:var(--bone); 4648 opacity:0;transform:translateY(8px); 4649 transition:opacity .4s ease, transform .4s ease; 4650} 4651.saved-ribbon.show{opacity:1;transform:translateY(0)} 4652.saved-ribbon svg{width:18px;height:18px;color:#ff5b5b;flex:0 0 18px} 4653.saved-ribbon b{color:var(--bone);font-weight:700} 4654.saved-ribbon a{color:var(--leaf);text-decoration:underline;text-underline-offset:3px} 4655.saved-ribbon .sr-clear{ 4656 margin-left:auto;cursor:pointer;background:transparent;border:0; 4657 color:var(--mist);font-size:12px;font-family:var(--body); 4658} 4659.saved-ribbon .sr-clear:hover{color:var(--bone)} 4660 4661/* === Project filter chips === */ 4662.proj-filters{ 4663 display:flex;align-items:center;gap:8px;flex-wrap:wrap; 4664 margin:0 auto 18px;max-width:calc(1080px - var(--pad-x) * 2); 4665 width:calc(100% - var(--pad-x) * 2); 4666} 4667.proj-filter-label{ 4668 font-family:var(--body);font-weight:600; 4669 font-size:11px;letter-spacing:.22em;text-transform:uppercase; 4670 color:var(--mist);margin-right:6px; 4671} 4672.proj-chip{ 4673 appearance:none;cursor:pointer; 4674 padding:7px 14px;border-radius:999px; 4675 background:rgba(2,7,24,.4); 4676 border:1px solid rgba(255,255,255,.1); 4677 color:var(--bone);font-family:var(--display);font-weight:600;font-size:13px; 4678 letter-spacing:.02em; 4679 transition:all .2s ease; 4680} 4681.proj-chip:hover{border-color:rgba(168,243,65,.5);background:rgba(168,243,65,.08)} 4682.proj-chip.active{background:var(--leaf);color:#020718;border-color:var(--leaf)} 4683.proj-chip .pc-count{ 4684 display:inline-block;margin-left:6px; 4685 font-size:11px;opacity:.7;font-weight:500; 4686} 4687.proj-card.is-filtered-out{display:none} 4688 4689/* === View toggle (grid / list) === */ 4690.view-toggle{ 4691 display:inline-flex;border-radius:999px; 4692 background:rgba(2,7,24,.4);border:1px solid rgba(255,255,255,.1); 4693 padding:3px;margin-left:auto; 4694} 4695.view-toggle button{ 4696 appearance:none;cursor:pointer;border:0;background:transparent;
4697 color:var(--mist);padding:6px 14px;border-radius:999px; 4698 font-family:var(--display);font-weight:600;font-size:12px;letter-spacing:.04em; 4699 display:inline-flex;align-items:center;gap:6px; 4700 transition:all .2s ease; 4701} 4702.view-toggle button:hover{color:var(--bone)} 4703.view-toggle button.active{background:var(--leaf);color:#020718} 4704.view-toggle button svg{width:13px;height:13px} 4705.hscroll-track.view-list{ 4706 display:flex !important; 4707 flex-direction:column; 4708 gap:10px; 4709} 4710.hscroll-track.view-list .proj-card{ 4711 flex:0 0 auto;width:100%;min-height:auto; 4712 flex-direction:row;align-items:stretch; 4713 padding:0;overflow:hidden; 4714} 4715.hscroll-track.view-list .proj-card .img{ 4716 flex:0 0 180px;width:180px;height:auto;min-height:140px; 4717 position:relative; 4718} 4719.hscroll-track.view-list .proj-card .meta{ 4720 position:relative !important;inset:auto !important; 4721 flex:1 1 auto;padding:18px 22px; 4722 display:flex !important;flex-direction:column;justify-content:center; 4723} 4724.hscroll-track.view-list .proj-card .tag, 4725.hscroll-track.view-list .proj-card .coord-stamp, 4726.hscroll-track.view-list .proj-card .save-btn, 4727.hscroll-track.view-list .proj-card .img-video, 4728.hscroll-track.view-list .proj-card video{display:none !important} 4729 4730/* === Newsletter signup === */ 4731.newsletter{ 4732 position:relative; 4733 margin:80px auto 60px;max-width:760px; 4734 padding:38px 36px;border-radius:22px; 4735 background:linear-gradient(180deg,rgba(168,243,65,.08),rgba(168,243,65,.02)); 4736 border:1px solid rgba(168,243,65,.22); 4737 text-align:center;font-family:var(--body); 4738 overflow:hidden; 4739} 4740.newsletter::before{ 4741 content:"";position:absolute;inset:-30%;z-index:-1; 4742 background:radial-gradient(50% 50% at 50% 50%, rgba(168,243,65,.18), transparent 70%); 4743 filter:blur(40px);pointer-events:none; 4744} 4745.newsletter .nl-eyebrow{ 4746 font-size:11px;letter-spacing:.24em;text-transform:uppercase; 4747 color:var(--leaf);font-weight:600;margin-bottom:10px; 4748 display:inline-flex;align-items:center;gap:8px; 4749} 4750.newsletter .nl-eyebrow::before{ 4751 content:"";width:7px;height:7px;border-radius:50%; 4752 background:var(--leaf);box-shadow:0 0 0 0 var(--leaf-glow); 4753 animation:pulse 2.4s ease-out infinite; 4754} 4755.newsletter h3{ 4756 font-family:var(--display);font-weight:700; 4757 font-size:clamp(24px,3vw,36px);letter-spacing:-.01em; 4758 color:var(--bone);margin:0 0 8px; 4759} 4760.newsletter p{ 4761 font-size:15px;color:var(--mist);max-width:48ch;margin:0 auto 22px;line-height:1.5; 4762} 4763.newsletter form{ 4764 display:flex;gap:8px;max-width:520px;margin:0 auto; 4765} 4766.newsletter input[type="email"]{ 4767 flex:1 1 auto;min-width:0; 4768 padding:14px 18px;border-radius:999px; 4769 border:1px solid rgba(168,243,65,.28); 4770 background:rgba(2,7,24,.5);color:var(--bone); 4771 font-family:var(--body);font-size:14px; 4772} 4773.newsletter input[type="email"]:focus{outline:0;border-color:var(--leaf);box-shadow:0 0 0 3px rgba(168,243,65,.18)} 4774.newsletter input[type="email"]::placeholder{color:rgba(255,255,255,.35)} 4775.newsletter button[type="submit"]{ 4776 appearance:none;cursor:pointer;border:0; 4777 background:var(--leaf);color:#020718; 4778 font-family:var(--display);font-weight:700;font-size:13px; 4779 padding:0 22px;border-radius:999px;letter-spacing:.04em; 4780 display:inline-flex;align-items:center;gap:6px; 4781 white-space:nowrap; 4782 transition:background .2s ease, transform .2s ease; 4783} 4784.newsletter button[type="submit"]:hover{background:#B9F764} 4785.newsletter.is-success input, 4786.newsletter.is-success button{display:none} 4787.newsletter .nl-success{ 4788 display:none;font-size:16px;color:var(--bone); 4789 padding:12px 0; 4790} 4791.newsletter .nl-success svg{ 4792 width:38px;height:38px;color:var(--leaf); 4793 display:block;margin:0 auto 10px; 4794} 4795.newsletter.is-success .nl-success{display:block} 4796.newsletter .nl-error{ 4797 display:none;font-size:13px;color:#ff8a8a;margin-top:10px; 4798} 4799.newsletter.is-error .nl-error{display:block} 4800 4801/* === Compare us vs typical charity â hero-scale, prominent === */ 4802.compare-section{ 4803 /* Card-lift over the mission section (same visual language as 4804 missionâhero). Pulled up by 120px to overlap mission's bottom, 4805 rounded top corners, double-layer drop shadow + green hairline. 4806 overflow:hidden preserved so the atmospheric ::before doesn't leak. */ 4807 position:relative;padding:120px var(--pad-x) 48px !important; 4808 background:var(--ink);overflow:hidden; 4809 margin-top:-120px; 4810 border-radius:64px 64px 0 0; 4811 box-shadow: 4812 0 -28px 60px -16px rgba(0,0,0,.65), 4813 0 -14px 24px -10px rgba(0,0,0,.45), 4814 0 -2px 0 rgba(255,255,255,.10); 4815 z-index:6; 4816} 4817.compare-section::after{ 4818 /* Hairline highlight along the rounded top edge */ 4819 content:""; 4820 position:absolute;top:0;left:0;right:0;height:1px; 4821 background:linear-gradient(90deg, 4822 transparent 0%, 4823 rgba(255,255,255,.22) 20%, 4824 rgba(168,243,65,.4) 50%, 4825 rgba(255,255,255,.22) 80%, 4826 transparent 100%); 4827 pointer-events:none; 4828 border-radius:64px 64px 0 0; 4829 z-index:2; 4830} 4831@media (max-width:720px){ 4832 .compare-section{
4833 margin-top:-72px; 4834 border-radius:40px 40px 0 0; 4835 padding:88px var(--pad-x) 40px !important; 4836 } 4837 .compare-section::after{border-radius:40px 40px 0 0} 4838} 4839.species-section .species-counter{margin:0 auto !important} 4840.compare-section::before{ 4841 content:"";position:absolute;inset:-20%;z-index:0;pointer-events:none; 4842 background: 4843 radial-gradient(40% 35% at 75% 50%, rgba(168,243,65,.18), transparent 70%), 4844 radial-gradient(35% 30% at 25% 50%, rgba(226,106,91,.10), transparent 70%); 4845 filter:blur(60px); 4846} 4847.compare{ 4848 position:relative;z-index:1; 4849 margin:0 auto;max-width:1080px;padding:0; 4850 font-family:var(--body);text-align:center; 4851} 4852.compare-eyebrow{ 4853 display:inline-flex;align-items:center;gap:12px; 4854 font-size:13px;letter-spacing:.28em;text-transform:uppercase; 4855 color:var(--leaf);font-weight:700;margin-bottom:22px; 4856} 4857.compare-eyebrow::before, 4858.compare-eyebrow::after{ 4859 content:"";width:36px;height:1px;background:rgba(168,243,65,.55); 4860} 4861.compare h3{ 4862 font-family:var(--display);font-weight:800; 4863 font-size:clamp(40px,6vw,84px); 4864 color:var(--bone);text-align:center;margin:0 0 18px;letter-spacing:-.025em; 4865 line-height:1.02; 4866} 4867.compare h3 em{ 4868 font-style:italic;font-weight:500;color:var(--leaf); 4869} 4870.compare-lede{ 4871 max-width:62ch;margin:0 auto 56px; 4872 font-size:19px;color:var(--mist);line-height:1.5; 4873} 4874.compare-lede b{color:var(--bone);font-weight:600} 4875.compare-wrap{position:relative} 4876.compare-grid{ 4877 display:grid;grid-template-columns:1fr auto 1fr;gap:28px;align-items:stretch; 4878} 4879.compare-vs{ 4880 align-self:center;justify-self:center; 4881 z-index:2; 4882 width:70px;height:70px;border-radius:50%; 4883 display:flex;align-items:center;justify-content:center; 4884 background:linear-gradient(135deg, #0a1228, #060c1f); 4885 border:1px solid rgba(255,255,255,.12); 4886 font-family:var(--display);font-weight:800;font-size:18px; 4887 letter-spacing:.04em;color:var(--bone); 4888 box-shadow:0 18px 48px rgba(0,0,0,.5), 0 0 0 6px rgba(2,7,24,.6); 4889} 4890@media (max-width:900px){ 4891 .compare-grid{grid-template-columns:1fr;gap:18px} 4892 .compare-vs{margin:6px auto;width:56px;height:56px;font-size:15px} 4893} 4894.compare-card{ 4895 position:relative; 4896 border-radius:24px; 4897 min-height:380px; 4898 text-align:left; 4899 perspective:1200px; 4900 transition:transform .35s cubic-bezier(.22,.9,.3,1); 4901} 4902.cc-flipper{ 4903 position:relative; 4904 width:100%;height:100%;min-height:380px; 4905 transform-style:preserve-3d; 4906 transition:transform .8s cubic-bezier(.22,.9,.3,1); 4907} 4908.compare-card:hover .cc-flipper, 4909.compare-card:focus-visible .cc-flipper, 4910.compare-card:focus-within .cc-flipper{transform:rotateY(180deg)} 4911.cc-face{ 4912 position:absolute;inset:0; 4913 padding:48px 42px 42px;border-radius:24px; 4914 background:rgba(2,7,24,.55); 4915 border:1px solid rgba(255,255,255,.08); 4916 display:flex;flex-direction:column; 4917 overflow:hidden; 4918 backface-visibility:hidden; 4919 -webkit-backface-visibility:hidden; 4920} 4921.cc-back{transform:rotateY(180deg)} 4922.cc-face::before{ 4923 content:"";position:absolute;left:0;top:0;bottom:0;width:4px; 4924 background:linear-gradient(180deg,#ff7a5b,#ff5b5b); 4925} 4926.compare-card.is-us .cc-face{ 4927 background:linear-gradient(180deg,rgba(168,243,65,.14),rgba(168,243,65,.03)); 4928 border-color:rgba(168,243,65,.45); 4929 box-shadow:0 24px 60px rgba(168,243,65,.08), inset 0 0 0 1px rgba(168,243,65,.12); 4930} 4931.compare-card.is-us .cc-face::before{ 4932 background:linear-gradient(180deg,var(--leaf),rgba(168,243,65,.3)); 4933} 4934.compare-card.is-us .cc-face::after{ 4935 content:"";position:absolute;inset:-50%;z-index:-1; 4936 background:radial-gradient(40% 40% at 70% 30%, rgba(168,243,65,.25), transparent 70%); 4937 filter:blur(40px);pointer-events:none; 4938} 4939.cc-flip-hint{ 4940 position:absolute;bottom:14px;right:18px; 4941 font-size:10px;letter-spacing:.18em;text-transform:uppercase; 4942 color:var(--mist-2);font-weight:600;opacity:.55; 4943 display:inline-flex;align-items:center;gap:6px; 4944 transition:opacity .25s; 4945} 4946.cc-flip-hint .arrow{display:inline-block;transition:transform .6s} 4947.compare-card:hover .cc-flip-hint{opacity:0} 4948.compare-card .cc-back-label{ 4949 font-family:var(--display);font-weight:800; 4950 font-size:clamp(14px,1.2vw,16px); 4951 letter-spacing:.22em;text-transform:uppercase; 4952 color:rgba(255,180,150,.98);margin-bottom:26px; 4953 display:inline-flex;align-items:center;gap:12px; 4954} 4955.compare-card .cc-back-label::before{ 4956 content:"";width:8px;height:8px;border-radius:50%; 4957 background:#ff7a5b;box-shadow:0 0 10px rgba(255,122,91,.6), 0 0 20px rgba(255,122,91,.35); 4958} 4959.compare-card.is-us .cc-back-label{color:var(--leaf)} 4960.compare-card.is-us .cc-back-label::before{ 4961 background:var(--leaf);box-shadow:0 0 10px var(--leaf-glow), 0 0 20px rgba(168,243,65,.35); 4962} 4963.cc-breakdown{ 4964 list-style:none;padding:0;margin:0 0 auto; 4965 display:flex;flex-direction:column;gap:18px; 4966} 4967.cc-breakdown li{ 4968 display:flex;align-items:baseline;justify-content:space-between; 4969 gap:18px;padding-bottom:18px; 4970 border-bottom:1px solid rgba(255,255,255,.08); 4971 font-family:var(--display); 4972 font-size:clamp(15px,1.45vw,19px); 4973 font-weight:700; 4974 color:var(--bone); 4975 letter-spacing:-.005em; 4976 line-height:1.15; 4977} 4978.cc-breakdown li:last-child{border-bottom:0;padding-bottom:0} 4979.cc-breakdown b{ 4980 font-family:var(--display);font-weight:900; 4981 font-size:clamp(32px,3.6vw,46px); 4982 color:var(--bone);font-variant-numeric:tabular-nums; 4983 letter-spacing:-.025em;line-height:1; 4984 text-shadow:none; 4985} 4986.compare-card .cc-back-label + .cc-breakdown b{ 4987 color:#ff9b7b; 4988 text-shadow:0 2px 18px rgba(255,122,91,.35), 0 0 28px rgba(255,122,91,.18); 4989} 4990.compare-card.is-us .cc-breakdown b{ 4991 color:var(--leaf); 4992 text-shadow:0 2px 18px rgba(168,243,65,.45), 0 0 32px rgba(168,243,65,.22); 4993} 4994.cc-back-foot{ 4995 font-family:var(--display);font-weight:700; 4996 font-size:clamp(15px,1.35vw,18px); 4997 line-height:1.35;letter-spacing:-.005em; 4998 color:var(--bone); 4999 padding-top:22px;border-top:1px solid rgba(255,255,255,.10); 5000 margin-top:22px; 5001} 5002.compare-card.is-us .cc-back-foot{color:var(--bone)} 5003.compare-card.is-us .cc-back-foot b, 5004.compare-card.is-us .cc-back-foot strong{color:var(--leaf)} 5005@media (prefers-reduced-motion:reduce){ 5006 .cc-flipper{transition:none} 5007 .compare-card:hover .cc-flipper{transform:none} 5008} 5009.compare-card:hover{transform:translateY(-3px)} 5010.compare-card .cc-name{ 5011 font-family:var(--display);font-weight:700;font-size:14px; 5012 letter-spacing:.18em;text-transform:uppercase; 5013 color:rgba(255,180,150,.95);margin-bottom:18px; 5014 display:inline-flex;align-items:center;gap:10px; 5015} 5016.compare-card .cc-name::before{ 5017 content:"";width:10px;height:10px;border-radius:50%; 5018 background:#ff7a5b;box-shadow:0 0 14px rgba(255,122,91,.55); 5019} 5020.compare-card.is-us .cc-name{color:var(--leaf)} 5021.compare-card.is-us .cc-name::before{ 5022 background:var(--leaf); 5023 box-shadow:0 0 18px var(--leaf-glow); 5024 animation:pulse 2.4s ease-out infinite; 5025} 5026.compare-card .cc-pct{ 5027 font-family:var(--display);font-weight:900; 5028 font-size:clamp(80px,11vw,148px);line-height:.86; 5029 color:var(--bone);font-variant-numeric:tabular-nums; 5030 margin-bottom:10px;letter-spacing:-.04em; 5031} 5032.compare-card.is-us .cc-pct{ 5033 5034 5035 -webkit-text-fill-color:var(--leaf); 5036} 5037.compare-card .cc-pct-tail{font-size:.45em;
5037color:var(--mist);margin-left:6px;letter-spacing:.01em;font-weight:600} 5038.compare-card.is-us .cc-pct-tail{color:var(--leaf);-webkit-text-fill-color:var(--leaf)} 5039.compare-card .cc-label{ 5040 font-size:17px;color:var(--mist);line-height:1.5; 5041 margin-bottom:auto;padding-bottom:24px;max-width:42ch; 5042} 5043.compare-card .cc-bar{ 5044 position:relative;height:10px;border-radius:999px; 5045 background:rgba(255,255,255,.06);margin:0 0 16px; 5046 overflow:hidden; 5047} 5048.compare-card .cc-fill{ 5049 position:absolute;left:0;top:0;bottom:0; 5050 background:linear-gradient(90deg,#ff7a5b,#ff5b5b); 5051 border-radius:999px; 5052 width:61%; 5053 transition:width 1.4s cubic-bezier(.22,.9,.3,1); 5054} 5055.compare-card.is-us .cc-fill{ 5056 background:linear-gradient(90deg,var(--leaf),#D3FA9E); 5057 width:100%; 5058 box-shadow:0 0 24px rgba(168,243,65,.4); 5059} 5060.compare-card .cc-actual{ 5061 font-family:var(--display);font-weight:600; 5062 font-size:17px;color:var(--bone);letter-spacing:.01em; 5063 display:flex;align-items:baseline;gap:8px;flex-wrap:wrap; 5064} 5065.compare-card .cc-actual b{ 5066 color:var(--bone);font-weight:800;font-variant-numeric:tabular-nums; 5067 font-size:24px; 5068} 5069.compare-card.is-us .cc-actual b{color:var(--leaf)} 5070.compare-card .cc-actual span{color:var(--mist-2);font-size:14px;font-weight:500} 5071 5072.compare-foot{ 5073 margin-top:48px; 5074 display:flex;align-items:center;justify-content:center;gap:16px;flex-wrap:wrap; 5075} 5076.compare-foot .cf-note{ 5077 font-size:13px;color:var(--mist-2);letter-spacing:.04em; 5078} 5079.compare-foot .cf-source{ 5080 font-size:11px;letter-spacing:.18em;text-transform:uppercase; 5081 color:var(--mist-2);font-weight:600;opacity:.7; 5082} 5083 5084/* === Founder team strip === */ 5085.team-strip{ 5086 margin:32px auto 0;max-width:calc(1080px - var(--pad-x) * 2); 5087 width:calc(100% - var(--pad-x) * 2); 5088 position:relative; 5089} 5090.team-strip .ts-head{ 5091 display:flex;align-items:baseline;justify-content:space-between; 5092 margin-bottom:18px;flex-wrap:wrap;gap:14px; 5093} 5094.team-strip .ts-head .ts-eyebrow{ 5095 font-size:11px;letter-spacing:.24em;text-transform:uppercase; 5096 color:var(--mist);font-weight:600; 5097} 5098.team-grid{ 5099 display:grid;grid-template-columns:repeat(4,1fr);gap:14px; 5100} 5101@media (max-width:880px){.team-grid{grid-template-columns:repeat(2,1fr)}} 5102@media (max-width:520px){.team-grid{grid-template-columns:1fr}} 5103.team-card{ 5104 display:flex;flex-direction:column;gap:10px; 5105 padding:16px;border-radius:14px; 5106 background:rgba(2,7,24,.5); 5107 border:1px solid rgba(255,255,255,.06); 5108 text-decoration:none;color:inherit; 5109 transition:border-color .25s ease, transform .25s ease, background .25s ease; 5110} 5111.team-card:hover{border-color:rgba(168,243,65,.4);background:rgba(2,7,24,.65);transform:translateY(-2px)} 5112.team-avatar{ 5113 width:54px;height:54px;border-radius:50%; 5114 background:linear-gradient(135deg, rgba(168,243,65,.25), rgba(168,243,65,.05)); 5115 border:1px solid rgba(168,243,65,.35); 5116 display:flex;align-items:center;justify-content:center; 5117 font-family:var(--display);font-weight:800;font-size:18px; 5118 color:var(--leaf);letter-spacing:.04em; 5119} 5120.team-card .tm-name{ 5121 font-family:var(--display);font-weight:700;font-size:15px; 5122 color:var(--bone);letter-spacing:-.005em; 5123} 5124.team-card .tm-role{ 5125 font-size:11px;letter-spacing:.18em;text-transform:uppercase; 5126 color:var(--leaf);font-weight:600; 5127} 5128.team-card .tm-bio{ 5129 font-size:12.5px;color:var(--mist);line-height:1.4; 5130} 5131 5132/* === Press detail expander === */ 5133.press-grid > span{cursor:pointer;position:relative} 5134.press-detail{ 5135 display:none; 5136 margin:24px auto 0;max-width:680px; 5137 padding:18px 22px;border-radius:14px; 5138 background:rgba(2,7,24,.55); 5139 border:1px solid rgba(168,243,65,.2); 5140 text-align:left;font-family:var(--body); 5141 position:relative; 5142} 5143.press-detail.show{display:block;
5143animation:pdIn .35s cubic-bezier(.22,.9,.3,1) both} 5144@keyframes pdIn{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}} 5145.press-detail .pd-source{ 5146 font-size:11px;letter-spacing:.22em;text-transform:uppercase; 5147 color:var(--leaf);font-weight:600;margin-bottom:8px; 5148} 5149.press-detail blockquote{ 5150 font-family:var(--display);font-weight:500; 5151 font-size:18px;line-height:1.4;color:var(--bone); 5152 margin:0 0 8px;letter-spacing:-.005em;font-style:italic; 5153} 5154.press-detail .pd-meta{font-size:12px;color:var(--mist)} 5155 5156/* === Donation preview modal === */ 5157.dpm-backdrop{ 5158 position:fixed;inset:0;z-index:200; 5159 background:rgba(0,0,0,.7); 5160 backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px); 5161 opacity:0;pointer-events:none; 5162 transition:opacity .3s ease; 5163 display:flex;align-items:center;justify-content:center; 5164 padding:24px; 5165} 5166.dpm-backdrop.show{opacity:1;pointer-events:auto} 5167.dpm-modal{ 5168 width:100%;max-width:520px; 5169 background:linear-gradient(180deg, #0a1228, #060c1f); 5170 border:1px solid rgba(168,243,65,.3); 5171 border-radius:22px; 5172 padding:36px 32px 32px; 5173 font-family:var(--body); 5174 transform:translateY(20px) scale(.98); 5175 transition:transform .35s cubic-bezier(.22,.9,.3,1); 5176 position:relative;overflow:hidden; 5177} 5178.dpm-backdrop.show .dpm-modal{transform:translateY(0) scale(1)} 5179.dpm-modal::before{ 5180 content:"";position:absolute;inset:-30%;z-index:-1; 5181 background:radial-gradient(50% 50% at 50% 0%, rgba(168,243,65,.25), transparent 70%); 5182 filter:blur(40px);pointer-events:none; 5183} 5184.dpm-close{ 5185 position:absolute;top:14px;right:14px; 5186 width:36px;height:36px;border-radius:50%; 5187 border:1px solid rgba(255,255,255,.12); 5188 background:transparent;color:var(--bone); 5189 cursor:pointer;display:flex;align-items:center;justify-content:center; 5190 font-size:18px;line-height:1; 5191 transition:all .2s ease; 5192} 5193.dpm-close:hover{background:rgba(255,255,255,.06);border-color:rgba(255,255,255,.3)} 5194.dpm-head{text-align:center;margin-bottom:24px} 5195.dpm-head .dpm-eyebrow{ 5196 font-size:11px;letter-spacing:.24em;text-transform:uppercase; 5197 color:var(--leaf);font-weight:600;margin-bottom:10px; 5198} 5199.dpm-head h3{ 5200 font-family:var(--display);font-weight:700; 5201 font-size:26px;letter-spacing:-.01em;color:var(--bone);margin:0; 5202} 5203.dpm-amount{ 5204 text-align:center; 5205 font-family:var(--display);font-weight:800; 5206 font-size:64px;line-height:1;color:var(--bone); 5207 letter-spacing:-.025em;margin-bottom:6px; 5208 font-variant-numeric:tabular-nums; 5209} 5210.dpm-amount .dpm-curr{color:var(--leaf);font-weight:700} 5211.dpm-amount-label{ 5212 text-align:center;font-size:13px;letter-spacing:.16em; 5213 text-transform:uppercase;color:var(--mist);margin-bottom:22px; 5214} 5215.dpm-funds{ 5216 padding:18px;border-radius:14px; 5217 background:rgba(168,243,65,.06); 5218 border:1px solid rgba(168,243,65,.22); 5219 margin-bottom:22px; 5220 display:flex;align-items:center;gap:14px; 5221} 5222.dpm-funds .dpm-icon{ 5223 width:48px;height:48px;border-radius:12px;flex:0 0 48px; 5224 background:rgba(168,243,65,.14); 5225 border:1px solid rgba(168,243,65,.32); 5226 display:flex;align-items:center;justify-content:center; 5227 color:var(--leaf); 5228} 5229.dpm-funds .dpm-icon svg{width:24px;height:24px} 5230.dpm-funds-text{flex:1;min-width:0} 5231.dpm-funds-headline{ 5232 font-family:var(--display);font-weight:700;font-size:15px; 5233 color:var(--bone);margin-bottom:3px;letter-spacing:-.005em; 5234} 5235.dpm-funds-sub{font-size:12.5px;color:var(--mist);line-height:1.4} 5236.dpm-promise{ 5237 font-size:12.5px;color:var(--mist); 5238 display:flex;align-items:flex-start;gap:8px;margin-bottom:22px; 5239} 5240.dpm-promise svg{width:16px;height:16px;color:var(--leaf);flex:0 0 16px;margin-top:1px} 5241.dpm-gift-toggle{ 5242 display:flex;align-items:center;gap:10px; 5243 font-size:13px;color:var(--bone); 5244 padding:10px 0;border-top:1px solid rgba(255,255,255,.06); 5245 border-bottom:1px solid rgba(255,255,255,.06);margin-bottom:18px;cursor:pointer; 5246} 5247.dpm-gift-toggle input{accent-color:var(--leaf)} 5248.dpm-gift-fields{display:none;margin-bottom:18px;
5248animation:pdIn .3s ease both} 5249.dpm-gift-fields.show{display:block} 5250.dpm-gift-fields label{ 5251 display:block;font-size:11px;letter-spacing:.18em;text-transform:uppercase; 5252 color:var(--mist);margin-bottom:6px;font-weight:600; 5253} 5254.dpm-gift-fields input{ 5255 width:100%;padding:11px 14px;border-radius:8px; 5256 border:1px solid rgba(168,243,65,.25);background:rgba(2,7,24,.5); 5257 color:var(--bone);font-family:var(--body);font-size:13.5px;margin-bottom:10px; 5258} 5259.dpm-gift-fields input:focus{outline:0;border-color:var(--leaf)} 5260.dpm-cta{ 5261 display:block;width:100%;text-align:center;text-decoration:none; 5262 background:var(--leaf);color:#020718; 5263 font-family:var(--display);font-weight:700;font-size:15px;letter-spacing:.02em; 5264 padding:14px 22px;border-radius:999px; 5265 transition:background .2s ease, transform .2s ease; 5266} 5267.dpm-cta:hover{background:#B9F764;transform:translateY(-1px)} 5268.dpm-foot{ 5269 margin-top:14px;text-align:center;font-size:11.5px;color:var(--mist-2);letter-spacing:.04em; 5270} 5271 5272/* ================= CLIENT DEMO ADDITIONS ================= */ 5273 5274/* === 1. Live giving feed (in-page section) === */ 5275.live-feed{ 5276 position:relative; 5277 margin:48px auto 0;max-width:720px;text-align:left; 5278 padding:22px 24px 14px; 5279 border-radius:22px; 5280 background:linear-gradient(180deg,rgba(168,243,65,.06),rgba(168,243,65,.015)); 5281 border:1px solid rgba(168,243,65,.22); 5282 backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px); 5283 overflow:hidden; 5284} 5285.live-feed::before{ 5286 content:"";position:absolute;left:0;top:0;bottom:0;width:3px; 5287 background:linear-gradient(180deg,var(--leaf),rgba(168,243,65,.15)); 5288} 5289.live-feed .lf-head{ 5290 display:flex;align-items:baseline;justify-content:space-between; 5291 margin-bottom:14px;padding-bottom:12px; 5292 border-bottom:1px dashed rgba(168,243,65,.22); 5293} 5294.live-feed .lf-eyebrow{ 5295 font-family:var(--body);font-weight:600; 5296 font-size:11px;letter-spacing:.22em;text-transform:uppercase; 5297 color:var(--bone);display:inline-flex;align-items:center;gap:10px; 5298} 5299.live-feed .lf-eyebrow::before{ 5300 content:"";width:8px;height:8px;border-radius:50%; 5301 background:var(--leaf);box-shadow:0 0 0 0 var(--leaf-glow); 5302 animation:actPulse 1.8s ease-out infinite; 5303} 5304@keyframes actPulse{ 5305 0%{box-shadow:0 0 0 0 rgba(168,243,65,.55)} 5306 100%{box-shadow:0 0 0 10px rgba(168,243,65,0)} 5307} 5308.live-feed .lf-count{ 5309 font-family:var(--display);font-weight:700; 5310 font-size:12px;letter-spacing:.16em; 5311 color:rgba(168,243,65,.9);text-transform:uppercase; 5312 white-space:nowrap; 5313} 5314.live-feed .lf-count b{color:var(--bone);font-weight:800;margin-right:4px;font-variant-numeric:tabular-nums} 5315.live-feed .lf-list{ 5316 list-style:none;margin:0;padding:0; 5317 display:flex;flex-direction:column; 5318 position:relative; 5319} 5320.live-feed .lf-row{ 5321 display:flex;align-items:center;gap:14px; 5322 padding:11px 6px; 5323 border-bottom:1px solid rgba(255,255,255,.04); 5324 font-family:var(--body); 5325 transition:background .3s ease; 5326} 5327.live-feed .lf-row:last-child{border-bottom:0} 5328.live-feed .lf-row.is-new{ 5329 animation:lfRowIn .65s cubic-bezier(.22,.9,.3,1) both; 5330} 5331.live-feed .lf-row.is-new .lf-mini-dot{ 5332 animation:lfDotFlash 1.4s ease-out 1; 5333} 5334@keyframes lfRowIn{ 5335 from{opacity:0;transform:translateY(-16px);background:rgba(168,243,65,.12)} 5336 to{opacity:1;transform:translateY(0);background:transparent} 5337} 5338@keyframes lfDotFlash{ 5339 0%{box-shadow:0 0 0 0 rgba(168,243,65,.65), 0 0 14px rgba(168,243,65,.7)} 5340 100%{box-shadow:0 0 0 12px rgba(168,243,65,0), 0 0 0 rgba(168,243,65,0)} 5341} 5342.live-feed .lf-row.is-leaving{ 5343 animation:lfRowOut .5s ease-in both; 5344} 5345@keyframes lfRowOut{ 5346 to{opacity:0;transform:translateY(8px);max-height:0;padding-top:0;padding-bottom:0;border-bottom-width:0} 5347} 5348.live-feed .lf-mini-dot{ 5349 width:9px;height:9px;border-radius:50%;flex:0 0 9px; 5350 background:var(--leaf); 5351} 5352.live-feed .lf-body{ 5353 display:flex;align-items:baseline;justify-content:space-between;gap:14px; 5354 flex:1 1 auto;min-width:0;flex-wrap:wrap; 5355} 5356.live-feed .lf-line{ 5357 font-size:14px;color:var(--bone); 5358 white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0; 5359 flex:1 1 auto; 5360} 5361.live-feed .lf-line b{font-weight:700} 5362.live-feed .lf-line .lf-amt{color:var(--leaf);font-weight:800;font-variant-numeric:tabular-nums} 5363.live-feed .lf-meta{ 5364 font-size:12px;
5364color:var(--mist); 5365 letter-spacing:.02em; 5366 flex:0 0 auto;white-space:nowrap; 5367} 5368.live-feed .lf-meta .lf-when{color:rgba(255,255,255,.45);margin-left:4px} 5369.live-feed .lf-foot{ 5370 text-align:right;margin-top:10px; 5371 font-size:11px;color:var(--mist-2);letter-spacing:.06em; 5372} 5373@media (max-width:560px){ 5374 .live-feed .lf-meta{font-size:11px} 5375 .live-feed .lf-line{font-size:13px;white-space:normal} 5376} 5377 5378/* === 2. "Where your money goes" interactive slider === */ 5379.impact-calc{ 5380 /* Tightened from 56px â 18px so the ecoâNGO bridge above (which 5381 already carries its own 14px bottom margin) sits in continuous 5382 rhythm with this card rather than feeling like a separate module. */ 5383 margin:18px auto 0; 5384 max-width:720px; 5385 text-align:left; 5386 padding:28px 30px 30px; 5387 border-radius:22px; 5388 background:linear-gradient(180deg,rgba(168,243,65,.07),rgba(168,243,65,.015)); 5389 border:1px solid rgba(168,243,65,.22); 5390 backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px); 5391 position:relative;overflow:hidden; 5392} 5393.impact-calc h3{max-width:none;margin:0} 5394.impact-calc .calc-impact-headline, 5395.impact-calc .calc-impact-sub{text-align:left} 5396.impact-calc::before{ 5397 content:"";position:absolute;left:0;top:0;bottom:0;width:3px; 5398 background:linear-gradient(180deg,var(--leaf),rgba(168,243,65,.15)); 5399} 5400/* === Impact calculator â 2-col header layout === 5401 Left rail (heading + eyebrow + active-NGO chip) and right rail 5402 (BIG $50, double-stacked with "/ one-time" underneath) sit side 5403 by side at the top of the panel. Slider + presets + impact text 5404 sit full-width below. Stacks to single-column on tablet/mobile. */ 5405.calc-head{ 5406 display:grid;grid-template-columns:1.4fr auto;gap:16px 28px; 5407 align-items:center;margin-bottom:22px; 5408} 5409@media (max-width:760px){.calc-head{grid-template-columns:1fr;text-align:left}} 5410.calc-head .calc-head-left{display:flex;flex-direction:column;gap:8px;min-width:0} 5411.calc-head .calc-eyebrow{ 5412 font-family:var(--body);font-weight:600; 5413 font-size:11px;letter-spacing:.24em;text-transform:uppercase; 5414 color:rgba(168,243,65,.95); 5415} 5416.calc-head h3{ 5417 margin:0;font-family:var(--display);font-weight:800; 5418 font-size:clamp(28px,3.4vw,44px);color:var(--bone);letter-spacing:-.02em;line-height:1.05; 5419 max-width:18ch; 5420} 5421 5422/* The big right-side amount â replaces the old in-flow .calc-amount-row. 5423 Two stacked lines: huge $50, then small uppercase "/ one-time" beneath. */ 5424.calc-amount-row{ 5425 display:flex;flex-direction:column;align-items:flex-end;gap:2px; 5426 margin:0;text-align:right; 5427} 5428@media (max-width:760px){.calc-amount-row{align-items:flex-start;text-align:left;margin-top:6px}} 5429.calc-amount{ 5430 font-family:var(--display);font-weight:900; 5431 font-size:clamp(64px,9vw,116px);line-height:.85; 5432 color:var(--bone);letter-spacing:-.035em; 5433 font-variant-numeric:tabular-nums; 5434 display:inline-flex;align-items:flex-start; 5435} 5436.calc-amount .calc-curr{ 5437 color:var(--leaf);font-weight:800;font-size:.42em; 5438 margin-right:4px;margin-top:.15em;letter-spacing:0; 5439} 5440.calc-freq{ 5441 font-family:var(--display);font-weight:800; 5442 font-size:11.5px;letter-spacing:.22em; 5443 text-transform:uppercase;color:var(--leaf);padding:0; 5444 margin-top:2px; 5445} 5446.calc-freq::before{content:"/ "} 5447.calc-slider{ 5448 -webkit-appearance:none;appearance:none; 5449 width:100%;height:6px;border-radius:999px; 5450 background:linear-gradient(90deg, var(--leaf) 0%, var(--leaf) var(--p,30%), rgba(255,255,255,.08) var(--p,30%), rgba(255,255,255,.08) 100%); 5451 outline:none;margin:6px 0 22px;cursor:pointer; 5452} 5453.calc-slider::-webkit-slider-thumb{ 5454 -webkit-appearance:none;appearance:none; 5455 width:24px;height:24px;border-radius:50%; 5456 background:var(--leaf); 5457 border:3px solid #020718; 5458 box-shadow:0 0 0 4px rgba(168,243,65,.18), 0 4px 14px rgba(0,0,0,.5); 5459 cursor:grab;transition:transform .2s ease; 5460} 5461.calc-slider::-webkit-slider-thumb:active{transform:scale(1.18);cursor:grabbing} 5462.calc-slider::-moz-range-thumb{ 5463 width:24px;height:24px;border-radius:50%; 5464 background:var(--leaf);border:3px solid #020718; 5465 box-shadow:0 0 0 4px rgba(168,243,65,.18);cursor:grab; 5466} 5467.calc-presets{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:18px} 5468.calc-preset{ 5469 appearance:none;border:1px solid rgba(168,243,65,.28); 5470 background:rgba(2,7,24,.4);color:var(--bone); 5471 font-family:var(--display);font-weight:600;font-size:13px; 5472 padding:8px 14px;border-radius:999px;cursor:pointer; 5473 letter-spacing:.04em; 5474 transition:all .2s ease; 5475} 5476.calc-preset:hover{border-color:var(--leaf);background:rgba(168,243,65,.12)} 5477.calc-preset.active{background:var(--leaf);color:#020718;border-color:var(--leaf)} 5478.calc-impact{ 5479 display:grid;grid-template-columns:auto 1fr;gap:16px;align-items:center; 5480 padding:18px 18px;border-radius:14px; 5481 background:rgba(2,7,24,.45); 5482 border:1px solid rgba(168,243,65,.18); 5483 min-height:78px; 5484} 5485.calc-impact-icon{ 5486 width:54px;height:54px;border-radius:14px; 5487 display:flex;align-items:center;justify-content:center; 5488 background:rgba(168,243,65,.12); 5489 border:1px solid rgba(168,243,65,.32); 5490 color:var(--leaf);flex:0 0 54px; 5491 transition:transform .35s cubic-bezier(.22,.9,.3,1), 5492 background-image .35s ease; 5493 background-size:cover;background-position:center; 5494 position:relative;overflow:hidden; 5495} 5496.calc-impact-icon svg{width:28px;height:28px} 5497/* When the ecoâNGO bridge picks an NGO, the icon tile fills with 5498 the NGO's photo. The SVG inside is hidden so the photo reads. */ 5499.calc-impact-icon.has-ngo-photo{ 5500 background-color:rgba(2,7,24,.4); 5501 border-color:var(--leaf); 5502 box-shadow:0 0 0 1px var(--leaf), 0 6px 16px -6px rgba(168,243,65,.45); 5503} 5504.calc-impact-icon.has-ngo-photo svg{ display:none } 5505.calc-impact-icon.has-ngo-photo::after{ 5506 /* subtle inset gradient to keep the icon tile from feeling flat 5507 when filled with a photo */ 5508 content:"";position:absolute;inset:0;pointer-events:none; 5509 background:linear-gradient(180deg, rgba(0,0,0,0) 50%, rgba(0,0,0,.05)); 5510} 5511.calc-impact.bump .calc-impact-icon{transform:scale(1.12) rotate(-4deg)} 5512.calc-impact-text{display:flex;flex-direction:column;gap:4px;min-width:0} 5513.calc-impact-headline{ 5514 font-family:var(--display);font-weight:700; 5515 font-size:17px;color:var(--bone);letter-spacing:-.005em; 5516}
5517.calc-impact-sub{font-size:13px;color:var(--mist);line-height:1.4} 5518.calc-cta-row{ 5519 margin-top:16px;display:flex;align-items:center;gap:14px;flex-wrap:wrap; 5520} 5521.calc-foot{ 5522 margin-top:14px;font-size:12px;color:var(--mist-2);letter-spacing:.02em; 5523} 5524 5525/* === 3. Species-lost counter === */ 5526.species-counter{ 5527 position:relative; 5528 margin:120px auto 60px; 5529 max-width:1080px;padding:0 var(--pad-x); 5530 text-align:center;font-family:var(--body); 5531} 5532.sc-eyebrow{ 5533 display:inline-flex;align-items:center;gap:12px; 5534 font-size:14px;letter-spacing:.28em;text-transform:uppercase; 5535 color:rgba(255,120,120,.95);margin-bottom:24px;font-weight:700; 5536} 5537.sc-eyebrow::before{ 5538 content:"";width:8px;height:8px;border-radius:50%; 5539 background:#ff5b5b;box-shadow:0 0 18px rgba(255,91,91,.55); 5540 animation:scBlink 1.4s ease-out infinite; 5541} 5542@keyframes scBlink{ 5543 0%,100%{opacity:1} 5544 50%{opacity:.35} 5545} 5546.sc-number{ 5547 font-family:var(--display);font-weight:900; 5548 font-size:clamp(96px,14vw,210px);line-height:.86; 5549 color:var(--bone);letter-spacing:-.03em; 5550 font-variant-numeric:tabular-nums; 5551 background:linear-gradient(180deg,#fff,rgba(255,255,255,.55)); 5552 -webkit-background-clip:text;background-clip:text; 5553 -webkit-text-fill-color:transparent; 5554} 5555.sc-caption{ 5556 font-family:var(--display);font-weight:700; 5557 font-size:clamp(28px,4vw,56px); 5558 color:var(--bone);margin-top:22px;letter-spacing:-.015em; 5559 line-height:1.1;max-width:24ch; 5560 margin-left:auto;margin-right:auto; 5561} 5562.sc-caption em{ 5563 color:var(--leaf);font-style:italic;font-weight:500; 5564 5565 5566 color:var(--leaf);-webkit-text-fill-color:var(--leaf); 5567 5568} 5569.sc-sub{ 5570 margin-top:24px; 5571 font-size:clamp(17px,1.8vw,22px); 5572 color:var(--mist);max-width:46ch;line-height:1.5; 5573 margin-left:auto;margin-right:auto; 5574} 5575 5576/* === 4. Press / trusted-by strip === */ 5577/* "As featured in" press strip. 5578 The wordmarks are deliberately typeset in our own display font as 5579 editorial nominative references â factual attribution to outlets 5580 that have featured the Foundation. This is the appropriate way to 5581 credit press; the user can later swap in officially-licensed brand 5582 assets from each outlet's press kit if/when they obtain them. */ 5583.press-strip{ 5584 position:relative;padding:42px 0 38px;margin:0 auto; 5585 max-width:1240px; 5586 text-align:center;font-family:var(--body); 5587 border-top:1px solid rgba(255,255,255,.06); 5588 border-bottom:1px solid rgba(255,255,255,.06); 5589} 5590.press-strip .press-label{ 5591 font-size:11px;letter-spacing:.28em;text-transform:uppercase; 5592 color:var(--leaf);font-weight:700;margin-bottom:24px; 5593 display:inline-flex;align-items:center;gap:10px; 5594} 5595.press-strip .press-label::before, 5596.press-strip .press-label::after{ 5597 content:"";width:28px;height:1px; 5598 background:linear-gradient(90deg,transparent,rgba(168,243,65,.6),transparent); 5599} 5600.press-grid{ 5601 display:flex;align-items:center;justify-content:center; 5602 gap:0;flex-wrap:wrap; 5603 filter:saturate(.2) brightness(1.1);opacity:.82; 5604} 5605.press-grid > span{ 5606 font-family:var(--display);font-weight:800; 5607 font-size:clamp(16px,1.7vw,22px);letter-spacing:-.012em; 5608 color:var(--bone); 5609 transition:opacity .3s ease, filter .3s ease, color .3s ease; 5610 white-space:nowrap; 5611 display:inline-flex;align-items:center; 5612 padding:6px clamp(16px,2.4vw,32px); 5613 position:relative; 5614} 5615/* Leaf-dot separator between wordmarks (drawn after every span 5616 except the last) â gives a more "logo wall" cadence than 5617 loose spacing without reproducing any actual logo design. */ 5618.press-grid > span:not(:last-child)::after{ 5619 content:"";position:absolute;right:-3px;top:50%;transform:translateY(-50%); 5620 width:4px;height:4px;border-radius:50%; 5621 background:rgba(168,243,65,.35); 5622} 5623.press-grid > span:hover{ 5624 opacity:1;filter:saturate(1) brightness(1);color:var(--bone); 5625} 5626.press-grid em{font-style:italic;color:var(--mist);font-weight:500;margin-left:.18em} 5627 5628/* === 6. Hero sound toggle === */ 5629.hero-sound-btn{ 5630 /* Sits just below the fixed header â top:24px hid it behind the bar */ 5631 position:absolute;top:calc(var(--header-h) + 14px);right:24px;z-index:6; 5632 width:44px;height:44px;border-radius:50%; 5633 border:1px solid rgba(255,255,255,.22); 5634 background:rgba(2,7,24,.55); 5635 backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px); 5636 display:flex;align-items:center;justify-content:center; 5637 cursor:pointer;color:var(--bone); 5638 transition:background .25s ease, border-color .25s ease, transform .25s ease; 5639} 5640.hero-sound-btn:hover{background:rgba(168,243,65,.18);border-color:rgba(168,243,65,.5);transform:scale(1.06)} 5641.hero-sound-btn svg{width:18px;height:18px} 5642.hero-sound-btn .sb-off,
5643.hero-sound-btn[data-on="true"] .sb-on{display:block} 5644.hero-sound-btn .sb-on, 5645.hero-sound-btn[data-on="true"] .sb-off{display:none} 5646.hero-sound-btn::after{ 5647 content:"";position:absolute;inset:-6px;border-radius:50%; 5648 border:1px solid rgba(168,243,65,.4); 5649 opacity:0;transform:scale(.6); 5650 transition:opacity .35s ease, transform .35s ease; 5651} 5652.hero-sound-btn[data-on="true"]::after{opacity:1;transform:scale(1);animation:soundRipple 2.4s ease-out infinite} 5653@keyframes soundRipple{ 5654 0%{transform:scale(1);opacity:.7} 5655 100%{transform:scale(1.6);opacity:0} 5656} 5657 5658/* === 7. Donate-button particles === */ 5659.btn-primary{position:relative;overflow:visible} 5660.btn-primary .leafburst{ 5661 position:absolute;inset:0;pointer-events:none; 5662 overflow:visible; 5663} 5664.btn-primary .leaf-p{ 5665 position:absolute;left:50%;top:50%; 5666 width:8px;height:8px;border-radius:50% 0 50% 50%; 5667 background:var(--leaf); 5668 opacity:0;transform:translate(-50%,-50%) rotate(0); 5669} 5670.btn-primary:hover .leaf-p{ 5671 animation:leafFly 1.4s ease-out forwards; 5672} 5673@keyframes leafFly{ 5674 0%{opacity:0;transform:translate(var(--lx,-50%),var(--ly,-50%)) rotate(var(--lr,0deg)) scale(.4)} 5675 20%{opacity:.8} 5676 100%{opacity:0;transform:translate(calc(-50% + var(--ldx,40px)), calc(-50% + var(--ldy,-80px))) rotate(calc(var(--lr,0deg) + 360deg)) scale(1)} 5677} 5678 5679/* === 8. "Picks for tonight" recommendations strip === */ 5680.tonight-strip{ 5681 margin:60px auto 0; 5682 max-width:1280px; 5683 width:calc(100% - var(--pad-x) * 2); 5684 position:relative; 5685} 5686/* Special Pick of the Night â hero feature card */ 5687.tonight-hero{ 5688 position:relative;display:grid;grid-template-columns:1.15fr 1fr; 5689 gap:0;border-radius:24px;overflow:hidden; 5690 background:rgba(2,7,24,.55); 5691 border:1px solid rgba(168,243,65,.32); 5692 margin-bottom:18px; 5693 text-decoration:none;color:inherit; 5694 transition:border-color .3s ease, transform .35s cubic-bezier(.22,.9,.3,1); 5695 box-shadow:0 24px 60px rgba(0,0,0,.35), 0 0 0 1px rgba(168,243,65,.08), inset 0 0 0 1px rgba(168,243,65,.08); 5696} 5697.tonight-hero:hover{border-color:var(--leaf);transform:translateY(-2px)} 5698.tonight-hero::before{ 5699 content:"";position:absolute;inset:-30%;z-index:0;pointer-events:none; 5700 background:radial-gradient(45% 50% at 30% 50%, rgba(168,243,65,.18), transparent 70%); 5701 filter:blur(50px); 5702} 5703.tonight-hero .th-media{ 5704 position:relative;min-height:340px; 5705 background-size:cover;background-position:center; 5706 overflow:hidden; 5707} 5708.tonight-hero .th-media::after{ 5709 content:"";position:absolute;inset:0; 5710 background: 5711 linear-gradient(90deg, transparent 55%, rgba(2,7,24,.38) 100%), 5712 linear-gradient(180deg, rgba(2,7,24,.14) 0%, transparent 50%, rgba(2,7,24,.24) 100%); 5713} 5714.tonight-hero .th-play{ 5715 position:absolute;left:50%;top:50%;z-index:2; 5716 width:72px;height:72px;border-radius:50%; 5717 display:flex;align-items:center;justify-content:center; 5718 background:rgba(168,243,65,.92);color:#020718; 5719 transform:translate(-50%,-50%); 5720 box-shadow:0 12px 40px rgba(0,0,0,.6), 0 0 0 8px rgba(168,243,65,.18); 5721 transition:transform .3s ease, background .3s ease; 5722} 5723.tonight-hero:hover .th-play{background:#B9F764;transform:translate(-50%,-50%) scale(1.08)} 5724.tonight-hero .th-play svg{width:26px;height:26px;margin-left:4px} 5725.tonight-hero .th-meta-overlay{ 5726 position:absolute;left:20px;bottom:20px;z-index:2; 5727 display:flex;align-items:center;gap:10px; 5728 font-family:var(--display);font-weight:600;font-size:11px; 5729 letter-spacing:.18em;text-transform:uppercase;color:var(--bone); 5730 padding:6px 12px;border-radius:999px; 5731 background:rgba(2,7,24,.72); 5732 border:1px solid rgba(255,255,255,.14); 5733 backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px); 5734} 5735.tonight-hero .th-meta-overlay svg{width:12px;height:12px;color:var(--leaf)} 5736.tonight-hero .th-body{ 5737 position:relative;z-index:1; 5738 padding:36px 36px 32px; 5739 display:flex;flex-direction:column;justify-content:space-between;gap:18px; 5740} 5741.tonight-hero .th-special{ 5742 display:inline-flex;align-items:center;gap:10px;align-self:flex-start; 5743 font-family:var(--display);font-weight:800; 5744 font-size:11px;letter-spacing:.28em;text-transform:uppercase; 5745 color:#020718; 5746 padding:8px 14px;border-radius:999px; 5747 background:linear-gradient(135deg, var(--leaf), #D3FA9E); 5748 box-shadow:0 8px 24px rgba(168,243,65,.35); 5749}
5750.tonight-hero .th-special::before{ 5751 content:"";width:8px;height:8px;border-radius:50%;background:#020718; 5752 animation:pulse 2.2s ease-out infinite; 5753} 5754.tonight-hero .th-title{ 5755 font-family:var(--display);font-weight:800; 5756 font-size:clamp(28px,3.4vw,44px);letter-spacing:-.015em; 5757 color:var(--bone);line-height:1.05;margin:0; 5758} 5759.tonight-hero .th-title em{font-style:italic;font-weight:500;color:var(--leaf)} 5760.tonight-hero .th-desc{ 5761 font-size:15.5px;color:var(--mist);line-height:1.5;max-width:48ch;margin:0; 5762} 5763.tonight-hero .th-foot{ 5764 display:flex;align-items:center;justify-content:space-between;gap:16px;flex-wrap:wrap; 5765 padding-top:18px;border-top:1px solid rgba(255,255,255,.08); 5766} 5767.tonight-hero .th-stats{ 5768 display:flex;align-items:center;gap:18px;flex-wrap:wrap; 5769 font-family:var(--body);font-size:13px;color:var(--mist); 5770} 5771.tonight-hero .th-stats span{display:inline-flex;align-items:center;gap:6px} 5772.tonight-hero .th-stats b{color:var(--bone);font-weight:700;font-variant-numeric:tabular-nums} 5773.tonight-hero .th-cta{ 5774 display:inline-flex;align-items:center;gap:8px; 5775 font-family:var(--display);font-weight:700;font-size:14px;letter-spacing:.04em; 5776 color:#020718;background:var(--leaf); 5777 padding:11px 18px;border-radius:999px;text-decoration:none; 5778 transition:background .2s ease; 5779} 5780.tonight-hero .th-cta:hover{background:#B9F764} 5781@media (max-width:880px){ 5782 .tonight-hero{grid-template-columns:1fr} 5783 .tonight-hero .th-media{min-height:240px} 5784 .tonight-hero .th-media::after{ 5785 background: 5786 linear-gradient(180deg, rgba(2,7,24,.08) 0%, transparent 50%, rgba(2,7,24,.38) 100%); 5787 } 5788 .tonight-hero .th-body{padding:24px} 5789} 5790.tonight-strip .ts-header{ 5791 display:flex;align-items:baseline;justify-content:space-between; 5792 margin-bottom:18px;flex-wrap:wrap;gap:14px; 5793} 5794.tonight-strip .ts-eyebrow{ 5795 font-family:var(--body);font-weight:600; 5796 font-size:11px;letter-spacing:.24em;text-transform:uppercase; 5797 color:var(--bone);display:inline-flex;align-items:center;gap:10px; 5798} 5799.tonight-strip .ts-eyebrow::before{ 5800 content:"";width:8px;height:8px;border-radius:50%; 5801 background:var(--leaf);box-shadow:0 0 0 0 var(--leaf-glow); 5802 animation:pulse 2.4s ease-out infinite; 5803} 5804.tonight-strip .ts-all{ 5805 font-family:var(--display);font-weight:600;font-size:13px; 5806 color:var(--bone);text-decoration:none;letter-spacing:.04em; 5807 display:inline-flex;align-items:center;gap:6px; 5808 padding-bottom:2px;border-bottom:1px solid rgba(168,243,65,.4); 5809 transition:color .25s ease, border-color .25s ease; 5810} 5811.tonight-strip .ts-all:hover{color:var(--leaf);border-color:var(--leaf)} 5812.tonight-strip .ts-grid{ 5813 display:grid;grid-template-columns:repeat(3,1fr);gap:14px; 5814} 5815@media (max-width:760px){.tonight-strip .ts-grid{grid-template-columns:1fr}} 5816.tonight-strip .ts-card{ 5817 position:relative; 5818 display:flex;align-items:stretch;gap:14px; 5819 padding:14px;border-radius:14px; 5820 background:rgba(2,7,24,.5); 5821 border:1px solid rgba(255,255,255,.06); 5822 text-decoration:none;color:inherit; 5823 transition:border-color .25s ease, transform .25s ease, background .25s ease; 5824 overflow:hidden; 5825} 5826.tonight-strip .ts-card:hover{ 5827 border-color:rgba(168,243,65,.45);transform:translateY(-2px); 5828 background:rgba(2,7,24,.65); 5829} 5830.tonight-strip .ts-card:hover .ts-play{ 5831 transform:scale(1) translate(-50%,-50%);opacity:1; 5832} 5833.tonight-strip .ts-thumb{ 5834 flex:0 0 84px;width:84px;height:108px;border-radius:8px; 5835 background-size:cover;background-position:center; 5836 position:relative;overflow:hidden; 5837} 5838.tonight-strip .ts-thumb::after{ 5839 content:"";position:absolute;inset:0; 5840 background:linear-gradient(180deg, transparent 40%, rgba(0,0,0,.06)); 5841} 5842.tonight-strip .ts-play{ 5843 position:absolute;left:50%;top:50%;z-index:2; 5844 width:34px;height:34px;border-radius:50%; 5845 background:rgba(168,243,65,.92);color:#020718; 5846 display:flex;align-items:center;justify-content:center; 5847 transform:scale(.7) translate(-72%,-72%); 5848 transform-origin:center; 5849 transition:transform .25s ease, opacity .25s ease; 5850 opacity:.85; 5851 box-shadow:0 6px 20px rgba(0,0,0,.5); 5852} 5853.tonight-strip .ts-play svg{width:14px;height:14px;margin-left:2px} 5854.tonight-strip .ts-when{ 5855 font-family:var(--display);font-weight:700; 5856 font-size:10px;letter-spacing:.18em;text-transform:uppercase; 5857 color:var(--leaf); 5858 padding:3px 8px;border-radius:999px; 5859 border:1px solid rgba(168,243,65,.45); 5860 background:rgba(168,243,65,.1); 5861 display:inline-flex;align-items:center;gap:6px; 5862} 5863.tonight-strip .ts-badge-new{color:var(--leaf);border-color:rgba(168,243,65,.5);background:rgba(168,243,65,.1)} 5864.tonight-strip .ts-badge-trend{color:#ff9a5b;border-color:rgba(255,154,91,.5);background:rgba(255,154,91,.08)} 5865.tonight-strip .ts-badge-pick{color:#9ec4ff;border-color:rgba(158,196,255,.5);background:rgba(158,196,255,.08)} 5866.tonight-strip .ts-title{ 5867 font-family:var(--display);font-weight:700;font-size:15px; 5868 line-height:1.25;color:var(--bone);margin:8px 0 6px; 5869 display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden; 5870} 5871.tonight-strip .ts-count{ 5872 font-family:var(--body); 5873 font-size:12px;
5873color:var(--mist);letter-spacing:.02em; 5874} 5875.tonight-strip .ts-count b{color:var(--bone);font-weight:700;font-variant-numeric:tabular-nums} 5876.tonight-strip .ts-body{display:flex;flex-direction:column;justify-content:space-between;min-width:0;flex:1 1 auto} 5877 5878/* === 9. Cursor compass === */ 5879.cursor-compass{ 5880 position:fixed;top:0;left:0; 5881 width:42px;height:42px;border-radius:50%; 5882 border:1px solid rgba(168,243,65,.55); 5883 background:rgba(2,7,24,.35); 5884 backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px); 5885 pointer-events:none;z-index:30; 5886 opacity:0;transform:translate(-50%,-50%); 5887 transition:opacity .35s ease; 5888 display:flex;align-items:center;justify-content:center; 5889} 5890.cursor-compass.show{opacity:.85} 5891.cursor-compass::before{ 5892 content:"";position:absolute;inset:6px;border-radius:50%; 5893 border:1px dashed rgba(168,243,65,.3); 5894} 5895.cursor-compass .cc-needle{ 5896 width:2px;height:18px;background:linear-gradient(180deg,#ff5b5b 0 50%, var(--leaf) 50% 100%); 5897 transform-origin:center center; 5898 border-radius:2px; 5899} 5900.cursor-compass .cc-n{ 5901 position:absolute;top:-3px;left:50%;transform:translateX(-50%); 5902 font-family:var(--display);font-weight:700;font-size:8px; 5903 letter-spacing:.06em;color:rgba(168,243,65,.9); 5904} 5905 5906/* === 10. Page-visitors counter (sits under stat strip or convert CTA) === */ 5907.live-viewers{ 5908 display:inline-flex;align-items:center;gap:10px; 5909 padding:7px 14px;border-radius:999px; 5910 background:rgba(168,243,65,.08); 5911 border:1px solid rgba(168,243,65,.28); 5912 font-family:var(--body);font-size:12.5px;color:var(--bone); 5913 letter-spacing:.02em; 5914} 5915.live-viewers .lv-dot{ 5916 width:8px;height:8px;border-radius:50%;background:var(--leaf); 5917 box-shadow:0 0 0 0 rgba(168,243,65,.55); 5918 animation:lvBlip 1.6s ease-out infinite; 5919} 5920@keyframes lvBlip{ 5921 0%{box-shadow:0 0 0 0 rgba(168,243,65,.55)} 5922 100%{box-shadow:0 0 0 9px rgba(168,243,65,0)} 5923} 5924.live-viewers b{font-weight:700;color:var(--bone);font-variant-numeric:tabular-nums} 5925/* Prominent hero variant â the live-presence barometer, high on the page */ 5926.live-viewers.lv-hero{ 5927 padding:10px 18px;border-radius:999px;font-size:14px; 5928 background:rgba(168,243,65,.12);border-color:rgba(168,243,65,.45); 5929 box-shadow:0 8px 30px -10px rgba(168,243,65,.35); 5930 backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px); 5931} 5932.live-viewers.lv-hero b{font-family:var(--display);font-weight:900;font-size:19px;color:var(--leaf);margin-right:1px} 5933.live-viewers.lv-hero .lv-dot{width:9px;height:9px} 5934 5935/* ===================================================================== 5936 ECOSYSTEM CHOOSER â six animated cards in the map/tactical aesthetic. 5937 Each card has an SVG art panel + meta block. Hover lifts, scan sweeps. 5938 ===================================================================== */ 5939/* ===================================================================== 5940 ECOSYSTEM CHOOSER â compact icon pills. 5941 Matches the site's small-icon language rather than full illustration cards. 5942 ===================================================================== */ 5943.ecos-section{ 5944 position:relative;padding:var(--pad-section) var(--pad-x); 5945 background:linear-gradient(180deg, var(--ink) 0%, var(--ink-80) 50%, var(--ink) 100%); 5946 overflow:hidden; 5947} 5948.ecos-section::before{ 5949 content:"";position:absolute;inset:-25%;z-index:0;pointer-events:none; 5950 background:radial-gradient(40% 50% at 50% 50%, rgba(168,243,65,.10), transparent 70%); 5951 filter:blur(60px); 5952} 5953.ecos-section .wrap{position:relative;z-index:1;max-width:1100px;margin:0 auto} 5954 5955.ecos-strip{ 5956 display:grid; 5957 grid-template-columns:repeat(5, 1fr); 5958 gap:18px; 5959 margin-top:52px; 5960} 5961@media (max-width:1080px){.ecos-strip{grid-template-columns:repeat(3, 1fr);gap:16px}} 5962@media (max-width:560px){.ecos-strip{grid-template-columns:repeat(2, 1fr);gap:12px}} 5963 5964/* Ecosystem pills â these are the major fork in the user journey, 5965 where someone picks the wild they care about. Made bigger and 5966 more present. Hover is a hard reverse-out: leaf background, 5967 ink-coloured icon + text. The card lifts and casts a leaf-tinted 5968 glow. */ 5969.ecos-pill{ 5970 display:flex;flex-direction:column;align-items:center;text-align:center; 5971 padding:28px 16px 22px; 5972 aspect-ratio: 1 / 1.05; 5973 background:rgba(7,13,35,.5); 5974 border:1px solid rgba(168,243,65,.18); 5975 border-radius:18px; 5976 text-decoration:none;color:inherit; 5977 position:relative;overflow:hidden;isolation:isolate; 5978 transition:transform .3s cubic-bezier(.2,.7,.2,1), border-color .25s, 5979 background .35s, box-shadow .35s, color .25s; 5980} 5981/* tactical corner crosshair â all four corners, more confident */ 5982.ecos-pill::before, 5983.ecos-pill::after{ 5984 content:"";position:absolute;width:14px;
5984height:14px; 5985 border:1px solid rgba(168,243,65,.5); 5986 transition:border-color .3s, width .3s, height .3s; 5987 pointer-events:none; 5988 z-index:2; 5989} 5990.ecos-pill::before{top:10px;left:10px;border-right:0;border-bottom:0} 5991.ecos-pill::after{bottom:10px;right:10px;border-left:0;border-top:0} 5992/* hover surface â a leaf wash that swipes in from the bottom */ 5993.ecos-pill .ecos-pill-wash{ 5994 position:absolute;inset:0;z-index:-1; 5995 background:linear-gradient(0deg, var(--leaf) 0%, var(--leaf) 60%, transparent 100%); 5996 transform:translateY(100%); 5997 transition:transform .45s cubic-bezier(.2,.7,.2,1); 5998} 5999.ecos-pill:hover, 6000.ecos-pill:focus-visible{ 6001 transform:translateY(-6px); 6002 border-color:var(--leaf); 6003 box-shadow:0 18px 40px -8px rgba(168,243,65,.32), 6004 0 6px 16px -4px rgba(0,0,0,.5); 6005 color:var(--ink); 6006} 6007.ecos-pill:hover .ecos-pill-wash, 6008.ecos-pill:focus-visible .ecos-pill-wash{ 6009 transform:translateY(0); 6010} 6011.ecos-pill:hover::before, 6012.ecos-pill:hover::after, 6013.ecos-pill:focus-visible::before, 6014.ecos-pill:focus-visible::after{ 6015 border-color:var(--ink); 6016 width:18px;height:18px; 6017} 6018 6019.ecos-pill-icon{ 6020 width:64px;height:64px; 6021 color:var(--leaf); 6022 margin-bottom:18px; 6023 transition:color .3s, transform .45s cubic-bezier(.2,.7,.2,1); 6024} 6025.ecos-pill:hover .ecos-pill-icon, 6026.ecos-pill:focus-visible .ecos-pill-icon{ 6027 color:var(--ink); 6028 transform:translateY(-3px) scale(1.06); 6029} 6030.ecos-pill-icon svg{width:100%;height:100%;display:block} 6031.ecos-pill-icon svg path, 6032.ecos-pill-icon svg line, 6033.ecos-pill-icon svg circle, 6034.ecos-pill-icon svg ellipse{ 6035 stroke:currentColor;fill:none;stroke-width:1.8; 6036 stroke-linecap:round;stroke-linejoin:round; 6037 transition:stroke-width .25s; 6038} 6039.ecos-pill:hover .ecos-pill-icon svg path, 6040.ecos-pill:hover .ecos-pill-icon svg line, 6041.ecos-pill:hover .ecos-pill-icon svg circle, 6042.ecos-pill:hover .ecos-pill-icon svg ellipse{ stroke-width:2 } 6043.ecos-pill-icon .ep-fill{ 6044 fill:currentColor;fill-opacity:.18;stroke:currentColor;stroke-width:1.5; 6045 transition:fill-opacity .25s, stroke-width .25s; 6046} 6047.ecos-pill:hover .ecos-pill-icon .ep-fill{ fill-opacity:.28 } 6048 6049.ecos-pill-name{ 6050 font-family:var(--display);font-weight:800; 6051 font-size:17px;letter-spacing:-.01em;color:var(--bone); 6052 margin-bottom:7px;line-height:1.1; 6053 transition:color .25s; 6054} 6055.ecos-pill:hover .ecos-pill-name, 6056.ecos-pill:focus-visible .ecos-pill-name{ color:var(--ink) } 6057 6058.ecos-pill-count{ 6059 font-size:10.5px;letter-spacing:.2em;text-transform:uppercase; 6060 color:var(--mist-2);font-weight:700; 6061 display:inline-flex;align-items:center;gap:7px; 6062 transition:color .25s; 6063} 6064.ecos-pill-count::before{ 6065 content:"";width:6px;height:6px;border-radius:50%; 6066 background:var(--leaf);box-shadow:0 0 6px var(--leaf-glow); 6067 transition:background .25s, box-shadow .25s; 6068} 6069.ecos-pill:hover .ecos-pill-count, 6070.ecos-pill:focus-visible .ecos-pill-count{ color:rgba(2,7,24,.78) } 6071.ecos-pill:hover .ecos-pill-count::before, 6072.ecos-pill:focus-visible .ecos-pill-count::before{ 6073 background:var(--ink);box-shadow:none; 6074} 6075 6076/* The new "tap â see the projects" arrow that fades in on hover */ 6077.ecos-pill-arrow{ 6078 position:absolute;bottom:14px;right:14px; 6079 width:24px;height:24px;border-radius:50%; 6080 display:grid;place-items:center; 6081 background:rgba(168,243,65,.0);color:var(--leaf); 6082 transform:translateX(-6px);opacity:0; 6083 transition:opacity .3s, transform .3s, background .3s, color .3s; 6084 pointer-events:none;font-family:var(--display);font-weight:800;font-size:14px; 6085 z-index:3; 6086} 6087.ecos-pill:hover .ecos-pill-arrow, 6088.ecos-pill:focus-visible .ecos-pill-arrow{ 6089 opacity:1;transform:translateX(0); 6090 background:var(--ink);color:var(--leaf); 6091} 6092@media (prefers-reduced-motion:reduce){ 6093 .ecos-pill, 6094 .ecos-pill .ecos-pill-wash, 6095 .ecos-pill-icon, 6096 .ecos-pill-arrow{ transition:none } 6097} 6098 6099/* ========================================================= 6100 ECO â NGO BRIDGE â picker that sits above the donation 6101 slider. Visitor flow: 6102 1. Pick an ecosystem (6 small pills, mirrors the main 6103 ecosystems section but compact). 6104 2. The panel below expands showing NGO cards for that 6105 ecosystem. 6106 3. Click an NGO â the donation slider's impact captions 6107 re-key to that NGO's funding scale. 6108 ========================================================= */ 6109/* Sized + padded to match the .impact-calc card directly below so 6110 the two stack as one continuous module. Same max-width (720px), 6111 same horizontal padding (30px), same border-radius. The visual
6112 treatment (gradient bg + leaf hairline on the left edge) is 6113 borrowed from .impact-calc so the pair reads as a single panel. */ 6114.eco-bridge{ 6115 position:relative;margin:32px auto 14px; 6116 max-width:720px; 6117 padding:28px 30px 26px; 6118 background:linear-gradient(180deg,rgba(168,243,65,.06),rgba(168,243,65,.015)); 6119 border:1px solid rgba(168,243,65,.22); 6120 border-radius:22px; 6121 backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px); 6122 overflow:hidden;isolation:isolate; 6123} 6124.eco-bridge::before{ 6125 /* Match the leaf hairline that runs down the left edge of the 6126 impact-calc card, so the two cards visually share a spine. */ 6127 content:"";position:absolute;left:0;top:0;bottom:0;width:3px; 6128 background:linear-gradient(180deg,var(--leaf),rgba(168,243,65,.15)); 6129 z-index:1;pointer-events:none; 6130} 6131.eco-bridge::after{ 6132 /* Soft leaf glow behind the pills, kept low-opacity so the 6133 pill colour transitions read cleanly. */ 6134 content:"";position:absolute;inset:0;z-index:-1; 6135 background:radial-gradient(50% 60% at 50% 0%,rgba(168,243,65,.10),transparent 70%); 6136 pointer-events:none; 6137} 6138.eco-bridge-head{ 6139 display:flex;flex-direction:column;align-items:center;justify-content:center;gap:14px; 6140 text-align:center;margin:8px auto 28px;max-width:780px; 6141} 6142.eco-bridge-head > div{display:flex;flex-direction:column;align-items:center;gap:10px} 6143.eco-bridge-eyebrow{ 6144 display:inline-flex;align-items:center;gap:8px; 6145 font-family:var(--display);font-weight:700; 6146 font-size:11px;letter-spacing:.24em;text-transform:uppercase; 6147 color:var(--leaf); 6148} 6149.eco-bridge-eyebrow::before{ 6150 content:"";width:6px;height:6px;border-radius:50%; 6151 background:var(--leaf);box-shadow:0 0 6px var(--leaf-glow); 6152} 6153.eco-bridge-title{ 6154 font-family:var(--display);font-weight:800; 6155 font-size:clamp(34px,4.8vw,60px); 6156 letter-spacing:-.025em;line-height:1.02; 6157 color:var(--bone);margin:0; 6158} 6159.eco-bridge-title em{font-style:italic;font-weight:500;color:var(--leaf)} 6160.eco-bridge-note{ 6161 font-size:15px;color:var(--mist);max-width:54ch; 6162 font-family:var(--body);line-height:1.55;text-align:center;margin:0 auto; 6163} 6164 6165/* Compact pills row â 6 ecosystems, smaller than the main 6166 ecosystems section but recognisably the same language. */ 6167.eco-bridge-pills{ 6168 display:grid;grid-template-columns:repeat(6,1fr);gap:8px; 6169 margin-bottom:0; 6170} 6171@media (max-width:780px){ 6172 .eco-bridge-pills{grid-template-columns:repeat(3,1fr);gap:8px} 6173} 6174@media (max-width:480px){ 6175 .eco-bridge-pills{grid-template-columns:repeat(2,1fr)} 6176} 6177.eco-bridge-pill{ 6178 appearance:none;cursor:pointer; 6179 display:flex;flex-direction:column;align-items:center;gap:6px; 6180 padding:14px 10px 12px; 6181 background:rgba(7,13,35,.5); 6182 border:1px solid rgba(168,243,65,.12); 6183 border-radius:14px; 6184 color:var(--bone);text-align:center; 6185 transition:transform .2s, background .2s, border-color .2s, color .2s; 6186 position:relative;overflow:hidden; 6187} 6188.eco-bridge-pill:hover{ 6189 transform:translateY(-2px); 6190 background:rgba(7,13,35,.75); 6191 border-color:rgba(168,243,65,.42); 6192} 6193.eco-bridge-pill[aria-selected="true"]{ 6194 background:var(--leaf);color:var(--ink);border-color:var(--leaf); 6195 box-shadow:0 8px 20px -8px rgba(168,243,65,.5); 6196} 6197.eco-bridge-pill[aria-selected="true"] .ebp-count{color:rgba(2,7,24,.7)} 6198.ebp-icon{ 6199 width:30px;height:30px;color:var(--leaf); 6200 transition:color .2s, transform .25s; 6201} 6202.eco-bridge-pill[aria-selected="true"] .ebp-icon{color:var(--ink);transform:scale(1.05)} 6203.ebp-icon svg{width:100%;height:100%} 6204.ebp-icon svg path, 6205.ebp-icon svg line, 6206.ebp-icon svg circle, 6207.ebp-icon svg ellipse{ 6208 stroke:currentColor;fill:none;stroke-width:1.6; 6209 stroke-linecap:round;stroke-linejoin:round; 6210} 6211.ebp-icon .ep-fill{fill:currentColor;fill-opacity:.16;stroke:currentColor;stroke-width:1.4} 6212.ebp-name{ 6213 font-family:var(--display);font-weight:800;font-size:13px; 6214 letter-spacing:-.005em;line-height:1.1; 6215} 6216.ebp-count{ 6217 font-size:9.5px;letter-spacing:.16em;text-transform:uppercase; 6218 color:var(--mist-2);font-weight:700; 6219} 6220 6221/* Expandable panel below the pills. Hidden when nothing is 6222 selected, animates open when an ecosystem is picked. */ 6223.eco-bridge-panel{ 6224 max-height:0;opacity:0;overflow:hidden; 6225 margin-top:0;padding-top:0; 6226 transition:max-height .45s cubic-bezier(.2,.7,.2,1), 6227 opacity .25s ease, 6228 margin-top .25s ease, 6229 padding-top .25s ease; 6230} 6231.eco-bridge-panel.is-open{ 6232 max-height:520px;opacity:1; 6233 margin-top:18px;padding-top:18px; 6234 border-top:1px dashed rgba(168,243,65,.25); 6235} 6236.eco-bridge-panel-head{ 6237 display:flex;align-items:baseline;justify-content:space-between; 6238 gap:14px;margin-bottom:12px;flex-wrap:wrap; 6239} 6240.eco-bridge-panel-h{ 6241 font-family:var(--display);font-weight:800; 6242 font-size:14px;color:var(--bone); 6243} 6244.eco-bridge-panel-h em{font-style:italic;font-weight:500;color:var(--leaf)} 6245.eco-bridge-panel-link{ 6246 font-size:11px;letter-spacing:.18em;text-transform:uppercase; 6247 color:var(--leaf);font-weight:700;text-decoration:none; 6248} 6249.eco-bridge-panel-link:hover{color:#B9F764} 6250
6251.eco-bridge-ngos{ 6252 display:grid;grid-template-columns:repeat(2,1fr);gap:10px; 6253} 6254@media (max-width:640px){.eco-bridge-ngos{grid-template-columns:1fr}} 6255 6256.eco-bridge-ngo{ 6257 appearance:none;cursor:pointer;text-align:left; 6258 display:flex;align-items:center;gap:14px; 6259 padding:12px 14px; 6260 background:rgba(7,13,35,.5); 6261 border:1px solid rgba(255,255,255,.06); 6262 border-radius:14px;color:var(--bone); 6263 transition:background .2s, border-color .2s, transform .2s; 6264} 6265.eco-bridge-ngo:hover{ 6266 background:rgba(7,13,35,.75); 6267 border-color:rgba(168,243,65,.45); 6268 transform:translateY(-1px); 6269} 6270.eco-bridge-ngo[aria-pressed="true"]{ 6271 background:rgba(168,243,65,.10); 6272 border-color:var(--leaf); 6273 box-shadow:inset 0 0 0 1px var(--leaf); 6274} 6275.ebngo-photo{ 6276 flex:0 0 52px;width:52px;height:52px;border-radius:10px; 6277 background-size:cover;background-position:center; 6278 background-color:rgba(255,255,255,.04); 6279 border:1px solid rgba(255,255,255,.06); 6280} 6281.ebngo-body{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;gap:3px} 6282.ebngo-coord{ 6283 font-size:10px;letter-spacing:.14em;text-transform:uppercase; 6284 color:var(--leaf);font-weight:700;font-feature-settings:"tnum"; 6285 display:inline-flex;align-items:center;gap:5px; 6286} 6287.ebngo-coord::before{content:"â";font-size:11px;color:var(--leaf)} 6288.ebngo-name{ 6289 font-family:var(--display);font-weight:800;font-size:14px; 6290 color:var(--bone);line-height:1.15;letter-spacing:-.005em; 6291} 6292.ebngo-org{font-size:11.5px;color:var(--mist);line-height:1.3} 6293.ebngo-pick{ 6294 flex:0 0 auto; 6295 font-family:var(--display);font-weight:800;font-size:12px; 6296 letter-spacing:.04em; 6297 padding:8px 12px;border-radius:99px; 6298 background:rgba(168,243,65,.14);color:var(--leaf); 6299 border:1px solid rgba(168,243,65,.42); 6300 transition:background .2s, color .2s, border-color .2s; 6301} 6302.eco-bridge-ngo:hover .ebngo-pick{ 6303 background:var(--leaf);color:var(--ink);border-color:var(--leaf); 6304} 6305.eco-bridge-ngo[aria-pressed="true"] .ebngo-pick{ 6306 background:var(--leaf);color:var(--ink);border-color:var(--leaf); 6307} 6308.eco-bridge-ngo[aria-pressed="true"] .ebngo-pick::after{ 6309 content:" â";font-weight:900; 6310} 6311 6312/* Empty-state card when an ecosystem has no featured project yet. */ 6313.eco-bridge-empty{ 6314 padding:20px 18px;border-radius:14px; 6315 background:rgba(7,13,35,.5); 6316 border:1px dashed rgba(168,243,65,.25); 6317 color:var(--mist);font-size:13px;line-height:1.5; 6318} 6319.eco-bridge-empty a{color:var(--leaf);text-decoration:none;font-weight:700} 6320.eco-bridge-empty a:hover{color:#B9F764;text-decoration:underline} 6321 6322/* Active-NGO summary above the slider â tiny chip that names 6323 what we're currently calibrated to. */ 6324.calc-active-ngo{ 6325 display:inline-flex;align-items:center;gap:10px; 6326 padding:6px 12px;border-radius:99px; 6327 background:rgba(168,243,65,.12); 6328 border:1px solid rgba(168,243,65,.4); 6329 color:var(--bone);font-size:12px; 6330 font-family:var(--body);font-weight:600; 6331 margin-bottom:14px; 6332} 6333.calc-active-ngo::before{ 6334 content:"";width:6px;height:6px;border-radius:50%; 6335 background:var(--leaf);box-shadow:0 0 6px var(--leaf-glow); 6336} 6337.calc-active-ngo b{font-weight:800;color:var(--leaf)} 6338.calc-active-ngo button{ 6339 appearance:none;background:none;border:0;cursor:pointer; 6340 color:var(--mist);font-size:14px;line-height:1;padding:0 0 0 4px; 6341 transition:color .2s; 6342} 6343.calc-active-ngo button:hover{color:var(--bone)} 6344@media (prefers-reduced-motion:reduce){ 6345 .eco-bridge-pill,.eco-bridge-ngo,.eco-bridge-panel{transition:none} 6346} 6347 6348</style> 6349<link rel="stylesheet" href="/assets/panels.css"> 6350<link rel="stylesheet" href="/assets/i18n.css" /> 6351<style> 6352/* === Text-over-media: feathered central shadow for legibility; dark filters removed === */ 6353.hero-card-copy h1,.hero-card-copy p,.hero-card-copy .eyebrow,.wc-headline,.wc-supporting,.hp-pct,.hp-headline,.hp-sub,.hp-promise h2,.hp-promise p,.biome-text h2,.biome-text p,.biome-eyebrow,.tonight-hero h3,.tonight-hero .th-special,.pd-hero h1,.pd-hero p,.pd-hero .pd-sub,.nd-hero h1,.nd-hero .nd-eyebrow,.hgb-h,.hgb-eyebrow,.hgb-foot,.proj-card .meta h3,.proj-card .meta .ngo,.proj-card .meta .cta,.proj-card .expand-panel .ep-title,.proj-card .expand-panel .ep-desc,.proj-card .expand-panel .ep-eyebrow{text-shadow:0 2px 16px rgba(2,7,24,.72),0 0 46px rgba(2,7,24,.5) !important}
6354.hero-overlay,.hero-carousel::after,.watch-change .wc-overlay,.hp-promise .hp-overlay,.biomes-overlay,.cinema-band::after,section.cinema-band::after,.pd-hero .pd-overlay,.hero-photo::after,.hp-give-band .hgb-overlay{background:none !important} 6355/* Keep the footage vibrant while giving the desktop hero copy one calm, 6356 high-contrast reading area rather than placing fine white text straight 6357 over the busiest part of the film. */ 6358.hero-overlay{background:radial-gradient(ellipse 62% 58% at 50% 43%,rgba(2,7,24,.56),rgba(2,7,24,.26) 52%,transparent 78%),linear-gradient(180deg,rgba(2,7,24,.18),transparent 30%,transparent 68%,rgba(2,7,24,.32)) !important} 6359 6360/* ===== SITEWIDE IMAGERY DIRECTIVE â bright, vibrant, no dark wash (homepage mirror of site.css) ===== */ 6361.hero-photo,.hero-img-fallback,.hero-carousel .hcv,.hcv,.moment-img,.cta-band-bg,.fq-bg,.lever-img,.pd-bg,.pcard .pbg,.pcard .pvideo,.proj-card .img,.proj-card .img-video,.btile img,.btile video,.wtile::before,.wtile .wvideo,.pillar-media img,.op-photo-strip,.feature-trailer .poster,.feature-trailer .trailer-video,.founder-quote .fq-video,.cinema-band-video,.hp-video,.hp-promise .hp-video,.watch-change .wc-video,.biome-media,.tonight-hero .th-media video,.hgb-media{filter:saturate(1.14) brightness(1.1) !important} 6362.pcard:hover .pbg,.pcard:hover .pvideo,.btile:hover img,.btile:hover video,.proj-card:hover .img,.proj-card:hover .img-video,.wtile:hover::before,.wtile:hover .wvideo{filter:saturate(1.2) brightness(1.15) !important} 6363.hero-overlay,.hero-carousel::after,.hero-photo::after,.moment::after,.cta-band-bg::after,.cta-band::after,.fq-bg::after,.founder-quote::after,.pcard::after,.btile::after,.wtile::after,.proj-card .shade,.feature-trailer::after,.pd-hero .pd-overlay,.pd-bg::after,.watch-change .wc-overlay,.hp-promise .hp-overlay,.biomes-overlay,.cinema-band::after,.hp-give-band .hgb-overlay,.op-photo-strip::after,.nd-hero::after,.lever-img::after{background:none !important} 6364.btile h3,.btile .b-sub,.btile .b-cta,.btile .b-tag,.btile .b-tag *,.btile .coord-stamp,.btile .coord-stamp *,.moment-quote,.moment-quote b,.moment-coord,.cinema-band-caption,.cinema-band-caption *,.fq-text,.fq-text b,.fq-name,.fq-role,.fq-rule,.cta-band h2,.cta-band p,.cta-band .eyebrow,.pcard .ptag,.pcard .ptag *{text-shadow:0 2px 16px rgba(2,7,24,.72),0 0 46px rgba(2,7,24,.5) !important} 6365.cta-band h2 em{text-shadow:none !important} 6366</style> 6367<!-- Vercel Web Analytics (page views + visitors) -->
6368<script>window.va=window.va||function(){(window.vaq=window.vaq||[]).push(arguments);};</script>
vendor: 1 bytes, line 6368
6368
6369<script defer src="/_vercel/insights/script.js"></script>
6369 6370</head> 6371<body> 6372 6373<!-- Intro splash: shown only to visitors Vercel geolocates to Los Angeles, 6374 California. Everyone else sees the homepage directly. --> 6375<style> 6376#introSplash{ 6377 position:fixed;inset:0;z-index:100000; 6378 display:grid;place-items:start center;padding:clamp(72px,13.2vh,156px) 24px 24px; 6379 background:linear-gradient(180deg,rgba(4,5,6,.40),rgba(4,5,6,.34) 50%,rgba(4,5,6,.42)); 6380 opacity:0;visibility:hidden;pointer-events:none; 6381 transition:opacity .6s ease,visibility .6s ease; 6382} 6383#introSplash.is-active{opacity:1;visibility:visible;pointer-events:auto} 6384#introSplash .intro-inner{text-align:center;animation:introRise .7s ease 0s both} 6385#introSplash .intro-lead{ 6386 font-family:var(--display);font-weight:900; 6387 letter-spacing:-.02em;line-height:.92; 6388 font-size:clamp(30px,4.5vw,69px); 6389 color:var(--leaf);margin:0 auto clamp(10px,1.5vh,18px); 6390 text-shadow:0 2px 16px rgba(2,7,24,.72),0 0 46px rgba(2,7,24,.5); 6391} 6392#introSplash .intro-lead em{font-style:italic;font-weight:900;color:var(--leaf);font-family:var(--display)} 6393#introSplash .intro-logo{width:min(244px,44.4vw);height:auto;margin:0 auto;display:block;filter:drop-shadow(0 4px 22px rgba(2,7,24,.55))} 6394#introSplash .intro-actions{display:flex;align-items:center;justify-content:center;flex-wrap:wrap;gap:12px;margin-top:clamp(21px,3vh,35px)} 6395#introSplash .intro-actions .btn{padding:7.2px 11.2px;font-size:8.4px} 6396#introSplash .intro-enter{appearance:none;border:0;background:transparent;color:var(--leaf);box-shadow:inset 0 0 0 1.5px var(--leaf)} 6397#introSplash .intro-enter:hover{background:rgba(168,243,65,.12);box-shadow:inset 0 0 0 1.5px var(--leaf)} 6398#introSplash .intro-actions .btn.intro-enter:focus-visible{outline:none} 6399#introSplash .intro-actions .btn:focus-visible{outline:3px solid var(--bone);outline-offset:4px} 6400#introSplash .intro-actions .btn:disabled{cursor:default;opacity:.7} 6401#introSplash.is-leaving{opacity:0;visibility:hidden;pointer-events:none} 6402body.intro-active{overflow:hidden} 6403@media (max-width:600px){ 6404 #introSplash .intro-lead{font-size:clamp(34px,9.75vw,44px);line-height:.9;letter-spacing:-.025em} 6405 #introSplash .intro-logo{width:min(284px,53vw)} 6406 #introSplash .intro-actions{gap:9px;margin-top:clamp(14px,2vh,20px)} 6407 #introSplash .intro-actions .btn{padding:6px 9.6px;font-size:8.4px} 6408} 6409@keyframes introRise{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:translateY(0)}} 6410/* Keep the homepage chrome behind the welcome card only for Los Angeles. */ 6411#heroCard,#header,#heroSoundBtn,#scrollCue{transition:opacity .55s ease .1s} 6412body.intro-active #heroCard,body.intro-active #header, 6413body.intro-active #heroSoundBtn,body.intro-active #scrollCue{opacity:0;pointer-events:none} 6414@media (prefers-reduced-motion:reduce){ 6415 #introSplash .intro-inner{animation:none} 6416 #introSplash,#heroCard,#header,#heroSoundBtn,#scrollCue{transition:none} 6417} 6418</style> 6419<div id="introSplash" aria-hidden="true"> 6420 <div class="intro-inner"> 6421 <p class="intro-lead"><em>Welcome to the world of…</em></p> 6422 <img class="intro-logo" src="/assets/logo.png" alt="Ecoflix" width="360" height="138" /> 6423 <div class="intro-actions"> 6424 <button class="btn intro-enter" id="introEnter" type="button">Learn more <span class="arrow" aria-hidden="true">â</span></button> 6425 <button class="btn btn-ghost" id="introSoundBtn" type="button" data-on="false" aria-pressed="false"> 6426 <span id="introSoundLabel">Music on</span> 6427 </button> 6428 </div> 6429 </div> 6430</div>
6431<script> 6432(() => { 6433 const splash = document.getElementById('introSplash'); 6434 const enter = document.getElementById('introEnter'); 6435 const sound = document.getElementById('introSoundBtn'); 6436 const soundLabel = document.getElementById('introSoundLabel'); 6437 if (!splash || !enter || !sound || !soundLabel) return; 6438 6439 const heroVideo = () => document.getElementById('heroVideo'); 6440 const normalise = (value) => String(value || '').trim().toLowerCase(); 6441 const isLosAngeles = (geo) => Boolean( 6442 geo && 6443 normalise(geo.country) === 'us' && 6444 normalise(geo.region) === 'ca' && 6445 normalise(geo.city) === 'los angeles' 6446 ); 6447 const setPageInert = (isInert) => { 6448 document.body.querySelectorAll(':scope > *:not(#introSplash):not(script):not(style)').forEach((element) => { 6449 element.inert = isInert; 6450 }); 6451 }; 6452 const setSoundState = (isPlaying) => { 6453 sound.setAttribute('data-on', String(isPlaying)); 6454 sound.setAttribute('aria-pressed', String(isPlaying)); 6455 soundLabel.textContent = isPlaying ? 'Music off' : 'Music on'; 6456 }; 6457 const startMusic = () => { 6458 const video = heroVideo(); 6459 if (!video) return setSoundState(false); 6460 video.muted = false; 6461 video.volume = .4; 6462 video.play().then(() => setSoundState(true)).catch(() => setSoundState(false)); 6463 }; 6464 6465 const skipIntro = () => { 6466 setPageInert(false); 6467 document.body.classList.remove('intro-active'); 6468 document.body.classList.add('intro-complete'); 6469 splash.remove(); 6470 }; 6471 const showIntro = () => { 6472 document.body.classList.remove('intro-complete'); 6473 document.body.classList.add('intro-active'); 6474 splash.setAttribute('aria-hidden', 'false'); 6475 splash.classList.add('is-active'); 6476 setPageInert(true); 6477 if (document.readyState === 'loading') { 6478 document.addEventListener('DOMContentLoaded', () => setPageInert(true), { once:true }); 6479 } 6480 enter.focus({ preventScroll:true }); 6481 }; 6482 6483 fetch('/api/geo', { credentials:'same-origin' }) 6484 .then((response) => response.ok ? response.json() : null) 6485 .catch(() => null) 6486 .then((geo) => { 6487 if (isLosAngeles(geo)) showIntro(); 6488 else skipIntro(); 6489 }); 6490 6491 sound.addEventListener('click', () => { 6492 const video = heroVideo(); 6493 if (!video || video.muted || video.paused) return startMusic(); 6494 video.muted = true; 6495 setSoundState(false); 6496 }); 6497 enter.addEventListener('click', () => { 6498 if (enter.disabled) return; 6499 enter.disabled = true; 6500 sound.disabled = true; 6501 const video = heroVideo(); 6502 const enterSite = () => { 6503 if (video) { video.muted = true; video.volume = .4; } 6504 setPageInert(false); 6505 document.body.classList.remove('intro-active'); 6506 document.body.classList.add('intro-complete'); 6507 splash.setAttribute('aria-hidden', 'true'); 6508 splash.classList.remove('is-active'); 6509 splash.classList.add('is-leaving'); 6510 window.setTimeout(() => splash.remove(), 650); 6511 }; 6512 if (!video || video.muted || video.paused) return enterSite(); 6513 const initialVolume = video.volume; 6514 const fadeStartedAt = performance.now(); 6515 const fadeOut = (now) => { 6516 const progress = Math.min(1, (now - fadeStartedAt) / 1000); 6517 video.volume = initialVolume * (1 - progress); 6518 if (progress < 1) requestAnimationFrame(fadeOut); 6519 else enterSite(); 6520 }; 6521 requestAnimationFrame(fadeOut); 6522 }, { once:true }); 6523})(); 6524</script>
6524 6525 6526<a href="#main" class="skip-to-content">Skip to content</a> 6527<!-- Chapter scroll indicator --> 6528<nav class="chapnav" id="chapNav" aria-label="Page sections"> 6529 <button class="chap-dot" type="button" data-target="#main"> <span class="chap-label">Top</span></button> 6530 <button class="chap-dot" type="button" data-target="#mission"> <span class="chap-label">Mission</span></button> 6531 <button class="chap-dot" type="button" data-target=".proof"> <span class="chap-label">Proof</span></button> 6532 <button class="chap-dot" type="button" data-target=".watch-change"> <span class="chap-label">Watch</span></button> 6533 <button class="chap-dot" type="button" data-target="#projects"> <span class="chap-label">Projects</span></button> 6534 <button class="chap-dot" type="button" data-target="#founder-quote"> <span class="chap-label">Founder</span></button> 6535 <button class="chap-dot" type="button" data-target=".broll-section"> <span class="chap-label">Stories</span></button> 6536 <button class="chap-dot" type="button" data-target=".convert"> <span class="chap-label">Donate</span></button> 6537</nav> 6538 6539<!-- Back-to-top --> 6540<button class="bttop" id="backToTop" type="button" aria-label="Back to top"> 6541 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 19V5M5 12l7-7 7 7"/></svg> 6542</button> 6543 6544<!-- Cookie / privacy bar --> 6545<aside class="cookbar" id="cookBar" role="region" aria-label="Cookie preferences"> 6546 <div class="cookbar-text"><b>We use minimal analytics.</b> No advertising. No data sold. You're in control.</div> 6547 <div class="cookbar-actions"> 6548 <button class="cb-decline" type="button" id="cbDecline">Decline</button> 6549 <button class="cb-accept" type="button" id="cbAccept">Accept</button> 6550 </div> 6551</aside> 6552 6553<!-- Donation preview modal --> 6554<div class="dpm-backdrop" id="donateModal" role="dialog" aria-modal="true" aria-labelledby="dpmTitle" aria-hidden="true"> 6555 <div class="dpm-modal"> 6556 <button class="dpm-close" type="button" aria-label="Close" id="dpmClose">Ã</button> 6557 <div class="dpm-head"> 6558 <div class="dpm-eyebrow">Review and continue</div> 6559 <h3 id="dpmTitle">Your donation</h3> 6560 </div> 6561 <div class="dpm-amount"><span class="dpm-curr">$</span><span id="dpmAmt">50</span></div> 6562 <div class="dpm-amount-label">One-time</div> 6563 <div class="dpm-funds"> 6564 <span class="dpm-icon" aria-hidden="true" id="dpmIcon"> 6565 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 12l8-8 8 8M6 10v10h12V10"/><path d="M9 21v-6h6v6"/></svg> 6566 </span> 6567 <div class="dpm-funds-text"> 6568 <div class="dpm-funds-headline" id="dpmHeadline">A day of drone surveillance over Sumatra</div> 6569 <div class="dpm-funds-sub" id="dpmSub">Our rainforest partners map illegal logging from the air — this funds one flight.</div> 6570 </div> 6571 </div> 6572 <div class="dpm-promise"> 6573 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M9 12l2 2 4-4"/><circle cx="12" cy="12" r="10"/></svg> 6574 <span>100% reaches the partner NGO. Ecoflix takes nothing. You'll get a receipt and field-log updates.</span> 6575 </div> 6576 <label class="dpm-gift-toggle"><input type="checkbox" id="dpmGiftCk"/> Give in someone else's name</label> 6577 <div class="dpm-gift-fields" id="dpmGiftFields"> 6578 <label>Recipient name</label> 6579 <input type="text" placeholder="e.g. Anna Smith" id="dpmGiftName"/> 6580 <label>Recipient email (we'll send a card)</label> 6581 <input type="email" placeholder="[email protected]" id="dpmGiftEmail"/> 6582 </div> 6583 <a class="dpm-cta" id="dpmCta" href="/donate/">Continue to checkout <span aria-hidden="true">â</span></a> 6584 <div class="dpm-foot">Secure checkout by Stripe. 256-bit TLS · PCI DSS Level 1. Cancel anytime.</div> 6585 </div> 6586</div> 6587 6588<!-- Ambient mouse-follow green glow (desktop, motion-on only) --> 6589<div class="ambient-glow" id="ambientGlow" aria-hidden="true"></div> 6590 6591 6592<!-- ============ Header ============ --> 6593<header class="header" id="header"> 6594 <a href="/" class="brand" aria-label="Ecoflix home"><img src="/assets/logo.png" alt="Ecoflix" style="height:34px;width:auto;display:block" /></a> 6595 <nav class="nav" aria-label="Main"> 6596 <a href="/mission/">Mission</a> 6597 <a href="/how-we-help/">How we help</a> 6598 <a href="/projects/">Projects</a> 6599 <a href="/ngo-partners/">NGO Partners</a> 6600 <a href="/watch/">Watch</a> 6601 <a href="/news/">News</a> 6602 <a href="/features/">Features</a> 6603 </nav> 6604 <div class="header-cta"> 6605 <a class="btn btn-ghost" href="https://watch.ecoflix.com/" data-i18n="cta.channel">Channel <span class="arrow">â</span></a> 6606 <a class="btn btn-primary" href="/donate/" data-i18n="cta.support">Support our work</a> 6607 </div> 6608 <button class="menu-btn" id="menuBtn" aria-label="Open menu" aria-expanded="false" aria-controls="drawer"><span></span><span></span><span></span></button> 6609</header> 6610 6611<div class="drawer" id="drawer" aria-hidden="true">
6612 <span class="drawer-eyebrow">Menu</span> 6613 <nav class="drawer-nav" aria-label="Mobile"> 6614 <a href="#mission"> 6615 <span class="drawer-icon" aria-hidden="true"><svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><circle cx="12" cy="12" r="5"/><circle cx="12" cy="12" r="1.5" fill="currentColor" stroke="none"/></svg></span> 6616 Mission 6617 <span class="drawer-arrow" aria-hidden="true">â</span> 6618 </a> 6619 <a href="#how"> 6620 <span class="drawer-icon" aria-hidden="true"><svg viewBox="0 0 24 24"><path d="M3 12h4l3-7 4 14 3-7h4"/></svg></span> 6621 How we help 6622 <span class="drawer-arrow" aria-hidden="true">â</span> 6623 </a> 6624 <a href="#projects"> 6625 <span class="drawer-icon" aria-hidden="true"><svg viewBox="0 0 24 24"><path d="M12 2C8 2 5 5 5 9c0 5.5 7 13 7 13s7-7.5 7-13c0-4-3-7-7-7z"/><circle cx="12" cy="9" r="2.5"/></svg></span> 6626 Projects 6627 <span class="drawer-arrow" aria-hidden="true">â</span> 6628 </a> 6629 <a href="#watch"> 6630 <span class="drawer-icon" aria-hidden="true"><svg viewBox="0 0 24 24"><rect x="3" y="5" width="18" height="14" rx="2"/><path d="M10 9l5 3-5 3z" fill="currentColor" stroke="none"/></svg></span> 6631 Watch 6632 <span class="drawer-arrow" aria-hidden="true">â</span> 6633 </a> 6634 <a href="https://watch.ecoflix.com/"> 6635 <span class="drawer-icon" aria-hidden="true"><svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><circle cx="12" cy="12" r="3"/></svg></span> 6636 The channel 6637 <span class="drawer-arrow" aria-hidden="true">â</span> 6638 </a> 6639 <a href="/news/"> 6640 <span class="drawer-icon" aria-hidden="true"><svg viewBox="0 0 24 24"><rect x="3" y="4" width="18" height="16" rx="2"/><path d="M7 8h10M7 12h10M7 16h6"/></svg></span> 6641 News 6642 <span class="drawer-arrow" aria-hidden="true">â</span> 6643 </a> 6644 <a href="#partners"> 6645 <span class="drawer-icon" aria-hidden="true"><svg viewBox="0 0 24 24"><circle cx="8.5" cy="9" r="3"/><circle cx="16" cy="10.5" r="2.5"/><path d="M3 19c0-3 2.5-5 5.5-5s5.5 2 5.5 5"/><path d="M13.5 19c0-2.5 2-4.5 5-4.5"/></svg></span> 6646 NGO Partners 6647 <span class="drawer-arrow" aria-hidden="true">â</span> 6648 </a> 6649 </nav> 6650 <a class="btn btn-primary" href="/donate/">Support our work <span class="arrow">â</span></a> 6651 <div class="drawer-footer"><span class="dot"></span>100% of every donation reaches the project.</div> 6652</div> 6653 6654<main id="main"> 6655 6656<!-- ================================================= 6657 STAGE 1 â Scroll-expanding video hero 6658 ================================================= --> 6659<div class="pin-stack"> 6660<section class="hero-stage is-pinned-bg" id="hero"> 6661 <div class="hero-pin"> 6662 <div class="hero-frame" id="heroFrame"> 6663 <!-- 6664 HERO VIDEO 6665 Currently hot-linked from Pexels CDN as a stop-gap. Before launch: 6666 download, re-encode to all-keyframe MP4 + WebM, host in /assets/, 6667 and swap the src below. Add a smaller mobile variant via media query. 6668 Animated Ken-Burns still underneath is the no-JS / failed-load fallback. 6669 --> 6670 <!-- 6671 HERO NATURE CAROUSEL â six cinematic clips cycling on a 7s crossfade. 6672 Each video plays only when active to keep CPU/bandwidth manageable. 6673 --> 6674 <div class="hero-carousel" id="heroCarousel" aria-hidden="true"> 6675 <!-- Scroll-scrubbed hero video â playback is driven by scroll position 6676 via the hero-scrub script at end of body. Must be muted + 6677 playsinline for iOS to honour currentTime updates without a 6678 user-gesture play(). No autoplay / no loop. --> 6679 <video class="hcv is-active" id="heroVideo" data-i="0" muted loop autoplay playsinline preload="auto" disableremoteplayback 6680 poster="/assets/ecoflix-landing-page-v2-poster.jpg"> 6681 <source src="/assets/ecoflix-landing-page-v2-web.mp4" type="video/mp4" /> 6682 </video> 6683 </div> 6684 <div class="hero-img-fallback" aria-hidden="true"></div> 6685 <div class="hero-overlay" aria-hidden="true"></div> 6686 <div class="hero-grain" aria-hidden="true"></div> 6687 6688 <button class="hero-sound-btn" id="heroSoundBtn" type="button" data-on="false" aria-label="Toggle ambient sound"> 6689 <svg class="sb-off" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"/>
6689<line x1="22" y1="9" x2="16" y2="15"/><line x1="16" y1="9" x2="22" y2="15"/></svg> 6690 <svg class="sb-on" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"/><path d="M15 9a3 3 0 0 1 0 6"/><path d="M18 6a7 7 0 0 1 0 12"/></svg> 6691 </button> 6692 6693 <div class="hero-stats-eyebrow" aria-hidden="true"> 6694 <span class="hse-dot"></span> 6695 <span class="hse-text">What we've done so far</span> 6696 </div> 6697 <div class="hero-stats" id="heroStats" aria-label="Headline impact numbers"> 6698 <a class="hstat" href="/projects/"> 6699 <span class="hicon" aria-hidden="true"><svg viewBox="0 0 32 32"><polygon points="8,12 12,8 16,12 12,16" fill="url(#og-light)"/><polygon points="16,8 20,4 24,8 20,12" fill="url(#og-light)"/><polygon points="20,12 24,8 28,12 24,16" fill="url(#og-light)"/><polygon points="10,18 16,16 22,18 16,28" fill="url(#og-mid)"/><polygon points="10,18 16,16 16,28" fill="url(#og-light)" opacity=".7"/><polygon points="22,18 16,16 16,28" fill="url(#og-dark)" opacity=".7"/></svg></span> 6700 <div class="hnum"><span data-livestat="projects">34</span></div> 6701 <h3 class="htitle">Projects funded</h3> 6702 <div class="hlbl">Projects funded, each run by a partner NGO on the ground.</div></a> 6703 <a class="hstat" href="/ngo-partners/"> 6704 <span class="hicon" aria-hidden="true"><svg viewBox="0 0 32 32"><circle cx="16" cy="16" r="12" fill="url(#og-mid)"/><polygon points="16,4 22,16 16,28" fill="url(#og-light)" opacity=".75"/><polygon points="16,4 10,16 16,28" fill="url(#og-dark)" opacity=".55"/><polygon points="4,16 16,10 28,16 16,22" fill="url(#og-light)" opacity=".4"/></svg></span> 6705 <div class="hnum"><span data-livestat="ngos">64</span></div> 6706 <h3 class="htitle">NGO partners</h3> 6707 <div class="hlbl">Conservation groups on the ground across 6 continents.</div></a> 6708 <a class="hstat" href="/impact-report/"> 6709 <span class="hicon" aria-hidden="true"><svg viewBox="0 0 32 32"><polygon points="16,4 24,8 24,24 16,28 8,24 8,8" fill="url(#og-mid)"/><polygon points="16,4 24,8 16,16" fill="url(#og-light)"/><polygon points="16,4 8,8 16,16" fill="url(#og-mid)" opacity=".6"/><polygon points="16,16 24,8 24,24" fill="url(#og-dark)" opacity=".7"/><text x="16" y="22" font-family="'Red Hat Display',sans-serif" font-weight="900" font-size="14" fill="#020718" text-anchor="middle">$</text></svg></span> 6710 <div class="hnum"><span data-livestat="raised">$698K</span><em>+</em></div> 6711 <h3 class="htitle">Raised and routed</h3> 6712 <div class="hlbl">From <b class="don-stat" data-donations data-donations-usd="698000"> </b> donations. Zero deductions.</div></a> 6713 <a class="hstat" href="/how-it-works/"> 6714 <span class="hicon" aria-hidden="true"><svg viewBox="0 0 32 32"><polygon points="16,2 28,16 16,30 4,16" fill="url(#og-mid)"/><polygon points="16,2 28,16 16,16" fill="url(#og-light)"/><polygon points="16,2 4,16 16,16" fill="url(#og-mid)" opacity=".55"/><polygon points="16,30 28,16 16,16" fill="url(#og-dark)" opacity=".7"/><polyline points="9,16 14,21 23,11" fill="none" stroke="#020718" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"/></svg></span> 6715 <div class="hnum">100<em>%</em></div> 6716 <h3 class="htitle">Goes through</h3> 6717 <div class="hlbl">Every dollar reaches the project. We take nothing.</div></a> 6718 </div> 6719 6720 <div class="hero-card-copy" id="heroCard"> 6721 <span class="eyebrow" style="margin-bottom:14px;display:inline-flex;font-weight:700;color:var(--bone);font-size:13px;letter-spacing:.26em">Ecoflix is a nonprofit Foundation</span> 6722 <h1>Just by watching,<br/>you can become <em>part of the solution.</em></h1> 6723 <p>We bring you beautiful, compelling, and often urgent wildlife stories. Just share to show you care! Sharing is not just good sense: it can truly make a difference! Every step counts not just the last one.</p> 6724 <div class="hero-actions"> 6725 <a class="btn btn-primary" href="https://watch.ecoflix.com/">Watch the stories <span class="arrow">â</span></a> 6726 <a class="btn btn-ghost" href="/how-it-works/">Ways to be part of it</a> 6727 </div> 6728 </div> 6729 6730 </div> 6731 6732 <div class="scroll-cue" id="scrollCue">Scroll<div class="bar"></div></div> 6733 </div> 6734</section> 6735 6736<!-- ================================================= 6737 STAGE 2 â Anchor / mission line 6738 ================================================= --> 6739<section class="anchor section-lift lifts-strong" id="mission"> 6740 <!-- CARTOGRAPH SCENE 01 · DEPARTURE 6741 Compass-led trail leaving from the south. Tracks following. 6742 The trail exits the right edge at yâ360 so the next scene picks 6743 up the thread from a similar height. --> 6744 <div class="bg-cartograph" aria-hidden="true"> 6745 <svg viewBox="0 0 1600 900" preserveAspectRatio="xMidYMid slice"> 6746 <line class="bg-lat" x1="-50" y1="220" x2="1650" y2="220"/> 6747 <line class="bg-lat" x1="-50" y1="440" x2="1650" y2="440"/> 6748 <line class="bg-lat" x1="-50" y1="660" x2="1650" y2="660"/> 6749 <path class="bg-trail" d="M-50,820 C220,690 380,560 620,540 C870,520 1010,420 1220,360 C14
674900,310 1520,300 1700,340"/> 6750 <path class="bg-trail-soft" d="M-30,640 C200,510 420,420 700,440 C920,460 1080,360 1280,300 C1450,260 1560,220 1700,200"/> 6751 <circle class="bg-track" cx="160" cy="760" r="3.2"/> 6752 <circle class="bg-track" cx="218" cy="720" r="3"/> 6753 <circle class="bg-track" cx="282" cy="675" r="2.8"/> 6754 <circle class="bg-track" cx="356" cy="625" r="2.8"/> 6755 <circle class="bg-track" cx="438" cy="585" r="3"/> 6756 <circle class="bg-track" cx="528" cy="555" r="3.2"/> 6757 <circle class="bg-track" cx="622" cy="540" r="3"/> 6758 <g class="bg-compass" transform="translate(1380,180)"> 6759 <circle class="bg-compass-ring" r="52"/> 6760 <circle class="bg-compass-ring" r="38"/> 6761 <line class="bg-compass-tick" x1="0" y1="-56" x2="0" y2="56"/> 6762 <line class="bg-compass-tick" x1="-56" y1="0" x2="56" y2="0"/> 6763 <line class="bg-compass-tick" x1="-40" y1="-40" x2="40" y2="40"/> 6764 <line class="bg-compass-tick" x1="40" y1="-40" x2="-40" y2="40"/> 6765 <polygon class="bg-compass-arrow" points="0,-52 7,0 0,52 -7,0"/> 6766 <polygon class="bg-compass-arrow" points="-52,0 0,7 52,0 0,-7"/> 6767 <text class="bg-compass-label" x="0" y="-62" text-anchor="middle">N</text> 6768 <text class="bg-compass-label" x="64" y="4" text-anchor="middle">E</text> 6769 <text class="bg-compass-label" x="0" y="74" text-anchor="middle">S</text> 6770 <text class="bg-compass-label" x="-64" y="4" text-anchor="middle">W</text> 6771 </g> 6772 <g transform="translate(140,808)"> 6773 <text class="bg-coord-text" x="0" y="0">01 · DEPARTURE</text> 6774 </g> 6775 <!-- Cross-bearing marker (replaces previous leaf motif) --> 6776 <g class="bg-marker" transform="translate(1140,510)"> 6777 <circle r="22" fill="none"/> 6778 <circle r="3" class="bg-marker-dot"/> 6779 <line class="bg-compass-tick" x1="-30" y1="0" x2="-22" y2="0"/> 6780 <line class="bg-compass-tick" x1="22" y1="0" x2="30" y2="0"/> 6781 <line class="bg-compass-tick" x1="0" y1="-30" x2="0" y2="-22"/> 6782 <line class="bg-compass-tick" x1="0" y1="22" x2="0" y2="30"/> 6783 </g> 6784 <g class="bg-marker" transform="translate(1220,360)"> 6785 <circle r="14"/> 6786 <circle r="6" class="bg-marker-dot"/> 6787 </g> 6788 </svg> 6789 </div> 6790 <div class="wrap reveal-stagger" style="position:relative;z-index:2"> 6791 <span class="eyebrow">What we stand for</span> 6792 <h2 class="reveal-words">Watch the problem.<br/>Fund the <em>solution.</em></h2> 6793 <p>Ecoflix is a not-for-profit foundation. We make the films that put the world's most urgent wildlife stories in front of millions, then route every donation straight to the NGOs doing the work on the ground. <strong style="color:var(--leaf);font-weight:700">100% of every donation goes to the project.</strong> Then you watch the difference you made.</p> 6794 </div> 6795</section> 6796 6797<!-- ===== Compare: us vs typical charity ===== 6798 INSIDE pin-stack: card-lifts over the sticky mission section. 6799 section-lift class hooks into the scroll-driven --compare-cover-y. --> 6800<section class="compare-section section-lift"> 6801 <div class="compare reveal"> 6802 <div class="compare-eyebrow">Where the money actually goes</div> 6803 <h3>Same <span data-money="50">$50</span>.<br/><em>Very different</em> outcome.</h3> 6804 <p class="compare-lede">Most charities lose 30–40% of every donation to overhead before it reaches the field. Ecoflix runs a <b>100% pass‑through</b> model — operations are funded separately, so every cent you give reaches the partner NGO doing the work.</p> 6805 <div class="compare-wrap"> 6806 <div class="compare-grid"> 6807 <div class="compare-card" tabindex="0"> 6808 <div class="cc-flipper"> 6809 <div class="cc-face cc-front"> 6810 <div class="cc-name">Typical charity</div> 6811 <div class="cc-pct">61<span class="cc-pct-tail">%</span></div> 6812 <div class="cc-label">Of every dollar reaches the field. The rest pays for admin, marketing and fundraising overhead.</div> 6813 <div class="cc-bar"><span class="cc-fill"></span></div> 6814 <div class="cc-actual"><span>Your <span data-money="50">$50</span> =</span> <b><span data-money="30.50">$30.50</span></b> <span>on the ground</span></div> 6815 <div class="cc-flip-hint" aria-hidden="true">Hover to flip <span class="arrow">â»</span></div> 6816 </div> 6817 <div class="cc-face cc-back"> 6818 <div class="cc-back-label"><span data-money="19.50">$19.50</span> burnt before it reaches the wild</div> 6819 <ul class="cc-breakdown"> 6820 <li><span>Admin & salaries</span><b><span data-money="9.20">$9.20</span></b></li> 6821 <li><span>Fundraising</span><b><span data-money="6.80">$6.80</span></b></li> 6822 <li><span>Marketing</span><b><span data-money="3.50">$3.50</span></b></li> 6823 </ul> 6824 <p class="cc-back-foot">The line that never leaves head office.</p> 6825 </div> 6826 </div> 6827 </div> 6828 <div class="compare-vs" aria-hidden="true">VS</div> 6829 <div class="compare-card is-us" tabindex="0"> 6830 <div class="cc-flipper"> 6831 <div class="cc-face cc-front"> 6832 <div class="cc-name">
6832Ecoflix Foundation</div> 6833 <div class="cc-pct">100<span class="cc-pct-tail">%</span></div> 6834 <div class="cc-label">Every cent reaches the partner NGO running the project. Our operating costs are covered separately by founders and corporate partners.</div> 6835 <div class="cc-bar"><span class="cc-fill"></span></div> 6836 <div class="cc-actual"><span>Your <span data-money="50">$50</span> =</span> <b><span data-money="50">$50</span></b> <span>on the ground</span></div> 6837 <div class="cc-flip-hint" aria-hidden="true">Hover to flip <span class="arrow">â»</span></div> 6838 </div> 6839 <div class="cc-face cc-back"> 6840 <div class="cc-back-label">Every <span data-money="50">$50</span> lands on the ground</div> 6841 <ul class="cc-breakdown"> 6842 <li><span>Rangers, drones, patrols</span><b><span data-money="23">$23</span></b></li> 6843 <li><span>Sanctuary & rescue</span><b><span data-money="15">$15</span></b></li> 6844 <li><span>Habitat restoration</span><b><span data-money="12">$12</span></b></li> 6845 </ul> 6846 <p class="cc-back-foot"><b>100% pass‑through.</b> Our overhead is covered separately by founders and partners.</p> 6847 </div> 6848 </div> 6849 </div> 6850 </div> 6851 </div> 6852 <div class="compare-foot"> 6853 <span class="cf-note">No deductions. No processing fees on you. No tiered admin.</span> 6854 <span class="cf-source">Source: Charity Navigator sector averages, 2024</span> 6855 </div> 6856 </div> 6857</section> 6858<!-- Compare-lift runway: empty scroll space inside the pin-stack so 6859 compare-section's sticky has room to play its transform animation. 6860 Without this, the pin-stack collapses to compare's natural height 6861 and sticky never engages. --> 6862<div class="compare-runway" aria-hidden="true"></div> 6863</div><!-- /.pin-stack heroâmissionâcompare --> 6864 6865 6866<!-- ===== Share / amplify â the community megaphone ===== --> 6867<section class="share-section" aria-labelledby="share-h"> 6868 <style> 6869 .share-section{position:relative;padding:clamp(90px,13vh,170px) var(--pad-x);text-align:center;overflow:hidden;isolation:isolate;background:var(--ink)} 6870 .share-section::before{content:"";position:absolute;inset:-10% -20% 20% -20%;z-index:-1;background:radial-gradient(50% 42% at 50% 28%,rgba(168,243,65,.13),transparent 70%);filter:blur(70px);pointer-events:none} 6871 .share-section .wrap{max-width:900px;margin:0 auto;display:grid;justify-items:center;gap:clamp(16px,2vw,26px);position:relative;z-index:2} 6872 .share-section .eyebrow{margin:0 auto} 6873 .share-section h2{font-family:var(--display);font-weight:800;font-size:clamp(38px,5.4vw,80px);line-height:.98;letter-spacing:-.03em;margin:10px auto 0;max-width:15ch} 6874 .share-section h2 em{font-style:italic;font-weight:500;background:linear-gradient(120deg,var(--leaf) 0%,#D3FA9E 45%,var(--leaf) 100%);background-size:200% 100%;-webkit-background-clip:text;background-clip:text;color:transparent;-webkit-text-fill-color:transparent} 6875 .share-section .share-lede{max-width:60ch;margin:0 auto;color:var(--mist);font-size:clamp(17px,1.5vw,21px);line-height:1.6} 6876 .share-section .share-lede b{color:var(--bone);font-weight:600} 6877 .share-section .share-sub{max-width:54ch;margin:2px auto 0;color:var(--mist-2);font-size:14.5px;line-height:1.55;letter-spacing:.01em} 6878 .share-cta{display:flex;flex-direction:column;align-items:center;gap:20px;margin-top:18px} 6879 .share-row{display:flex;flex-wrap:wrap;justify-content:center;gap:12px;align-items:center} 6880 .share-btn{position:relative;display:inline-flex;align-items:center;justify-content:center;width:52px;height:52px;border-radius:50%;background:rgba(7,13,35,.6);border:1px solid rgba(255,255,255,.1);color:var(--bone);transition:transform .25s cubic-bezier(.22,.9,.3,1),border-color .25s,background .25s,color .25s;cursor:pointer} 6881 .share-btn:hover{transform:translateY(-3px);border-color:rgba(168,243,65,.5);background:rgba(168,243,65,.1);color:var(--leaf)} 6882 .share-btn:focus-visible{outline:2px solid var(--leaf);outline-offset:3px} 6883 .share-btn svg{width:20px;height:20px} 6884 .share-toast{position:absolute;bottom:calc(100% + 10px);left:50%;transform:translateX(-50%) translateY(6px);background:var(--leaf);color:var(--ink);font-family:var(--body);font-weight:700;font-size:12px;letter-spacing:.02em;padding:6px 12px;border-radius:6px;white-space:nowrap;opacity:0;pointer-events:none;transition:opacity .2s,transform .2s} 6885 .share-btn.is-copied .share-toast{opacity:1;transform:translateX(-50%) translateY(0)} 6886 @media(max-width:560px){.share-btn{width:46px;height:46px}.share-btn svg{width:18px;height:18px}} 6887 </style> 6888 <div class="bg-cartograph" aria-hidden="true"> 6889 <svg viewBox="0 0 1600 900" preserveAspectRatio="xMidYMid slice"> 6890 <line class="bg-lat" x1="-50" y1="220" x2="1650" y2="220"/> 6891 <line class="bg-lat" x1="-50" y1="680" x2="1650" y2="680"/> 6892 <path class="bg-trail" d="M-50,460 C260,380 540,540 800,460 C1060,380 1340,540 1660,460"/> 6893 <g class="bg-marker" transform="translate(800,460)"><circle r="20" fill="none"/><circle r="6" class="bg-marker-dot"/></g> 6894 </svg> 6895 </div> 6896 <div class="wrap reveal-stagger"> 6897 <span class="eyebrow">Spread the word</span> 6898 <h2 id="share-h" class="reveal-words">Share to show <em>you care.</em></h2> 6899 <p class="share-lede">A share costs nothing and travels everywhere. Every time you pass on a story, you put a wildlife cause in front of someone new, and with it the partner fighting to save it. <b>Awareness is where rescue begins</b>, and our NGOs cannot buy the reach that our community gives them for free.</p> 6900 <p class="share-sub">Every partner has its own share button on their page. The further their story travels, the more support reaches the ground.</p> 6901 <div class="share-cta"> 6902 <button class="btn btn-primary js-share-eco" type="button">Share Ecoflix <span class="arrow" aria-hidden="true">â</span></button> 6903 <div class="share-row" role="group" aria-label="Share Ecoflix"> 6904 <a class="share-btn" data-net="x" target="_blank" rel="noopener" aria-label="Share on X" href="#"><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M18.244 2H21.5l-7.5 8.57L22.5 22h-6.9l-5.4-7.06L3.9 22H.64l8.02-9.17L1.5 2h7.07l4.88 6.45L18.244 2Zm-1.21 18h1.81L7.04 3.9H5.1L17.034 20Z"/></svg></a> 6905 <a class="share-btn" data-net="facebook" target="_blank" rel="noopener" aria-label="Share on Facebook" href="#"><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M22 12.06C22 6.5 17.52 2 12 2S2 6.5 2 12.06c0 5 3.66 9.15 8.44 9.94v-7.03H7.9v-2.9h2.54V9.85c0-2.51 1.49-3.9 3.78-3.9 1.1 0 2.24.2 2.24.2v2.46h-1.26c-1.24 0-1.63.77-1.63 1.56v1.87h2.78l-.44 2.9h-2.34V22c4.78-.79 8.43-4.94 8.43-9.94Z"/></svg></a> 6906 <a class="share-btn" data-net="whatsapp" target="_blank" rel="noopener" aria-label="Share on WhatsApp" href="#"><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M12.04 2C6.58 2 2.13 6.45 2.13 11.91c0 1.75.46 3.45 1.32 4.95L2 22l5.25-1.38c1.45.79 3.08 1.21 4.79 1.21 5.46 0 9.91-4.45 9.91-9.91C21.95 6.45 17.5 2 12.04 2Zm5.8 14.04c-.24.68-1.4 1.3-1.95 1.38-.5.07-1.13.1-1.83-.11-.42-.13
6906-.96-.31-1.65-.61-2.9-1.25-4.79-4.17-4.94-4.36-.14-.19-1.18-1.57-1.18-2.99s.75-2.12 1.01-2.41c.26-.29.57-.36.76-.36l.55.01c.18.01.41-.07.64.49.24.57.82 1.99.89 2.13.07.14.12.31.02.5-.09.19-.14.31-.28.48-.14.17-.3.37-.42.5-.14.14-.29.29-.12.57.17.29.74 1.22 1.59 1.98 1.1.98 2.02 1.28 2.31 1.43.29.14.46.12.63-.07.17-.19.72-.84.91-1.13.19-.29.39-.24.64-.14.26.09 1.66.78 1.95.93.29.14.48.21.55.33.07.12.07.68-.17 1.36Z"/></svg></a> 6907 <a class="share-btn" data-net="linkedin" target="_blank" rel="noopener" aria-label="Share on LinkedIn" href="#"><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M20.45 20.45h-3.56v-5.57c0-1.33-.02-3.04-1.85-3.04-1.85 0-2.14 1.45-2.14 2.94v5.67H9.34V9h3.42v1.56h.05c.48-.9 1.64-1.85 3.37-1.85 3.6 0 4.27 2.37 4.27 5.46v6.28ZM5.34 7.43a2.07 2.07 0 1 1 0-4.14 2.07 2.07 0 0 1 0 4.14ZM7.12 20.45H3.55V9h3.57v11.45ZM22.22 0H1.77C.8 0 0 .78 0 1.74v20.52C0 23.22.8 24 1.77 24h20.45c.98 0 1.78-.78 1.78-1.74V1.74C24 .78 23.2 0 22.22 0Z"/></svg></a> 6908 <button class="share-btn js-copy-link" type="button" aria-label="Copy link"><span class="share-toast" aria-hidden="true">Link copied</span><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M10 13a5 5 0 0 0 7 0l3-3a5 5 0 0 0-7-7l-1 1"/><path d="M14 11a5 5 0 0 0-7 0l-3 3a5 5 0 0 0 7 7l1-1"/></svg></button> 6909 </div> 6910 </div> 6911 </div> 6912
6912<script> 6913 (function(){ 6914 var sec=document.querySelector('.share-section'); if(!sec) return; 6915 var url='https://www.ecoflix.com/'; 6916 var text='Just by watching, you can become part of the solution. Wildlife stories on Ecoflix, and 100% of every donation reaches the project.'; 6917 var U=encodeURIComponent(url), T=encodeURIComponent(text); 6918 var nets={ 6919 x:'https://twitter.com/intent/tweet?url='+U+'&text='+T, 6920 facebook:'https://www.facebook.com/sharer/sharer.php?u='+U, 6921 whatsapp:'https://wa.me/?text='+T+'%20'+U, 6922 linkedin:'https://www.linkedin.com/sharing/share-offsite/?url='+U 6923 }; 6924 sec.querySelectorAll('.share-btn[data-net]').forEach(function(a){ a.href=nets[a.dataset.net]||url; }); 6925 var prim=sec.querySelector('.js-share-eco'); 6926 if(prim) prim.addEventListener('click',function(){ 6927 if(navigator.share){ navigator.share({title:'Ecoflix',text:text,url:url}).catch(function(){}); } 6928 else { window.open(nets.x,'_blank','noopener'); } 6929 }); 6930 var copy=sec.querySelector('.js-copy-link'); 6931 if(copy) copy.addEventListener('click',function(){ 6932 var done=function(){ copy.classList.add('is-copied'); setTimeout(function(){copy.classList.remove('is-copied');},1600); }; 6933 if(navigator.clipboard&&navigator.clipboard.writeText){ navigator.clipboard.writeText(url).then(done).catch(done); } else { done(); } 6934 }); 6935 })(); 6936 </script>
6936 6937</section> 6938 6939 6940<!-- ===== Species lost â urgency beat after the compare section ===== --> 6941<section class="species-section" style="padding:0 var(--pad-x) 80px;background:var(--ink);position:relative;overflow:hidden"> 6942 <div class="species-counter reveal"> 6943 <div class="sc-eyebrow">IUCN Red List · 2025</div> 6944 <div class="sc-number" id="speciesNum">48,646</div> 6945 <div class="sc-caption">More than <em>1 in 4</em> assessed species is now threatened with extinction.</div> 6946 <div class="sc-sub">This is the gap your donation closes. Every dollar routes directly to NGOs holding the line on the species we still have.</div> 6947 <!-- Donate CTA at the urgency moment â turn the live count into action. --> 6948 <div class="sc-cta-row" style="margin-top:28px;display:flex;gap:12px;justify-content:center;flex-wrap:wrap"> 6949 <a class="btn btn-primary" href="/donate/">Donate now <span class="arrow">â</span></a> 6950 <a class="btn btn-ghost" href="/how-it-works/">See how it works</a> 6951 </div> 6952 </div> 6953</section> 6954 6955<!-- ================================================= 6956 PICK YOUR ECOSYSTEM â six animated SVG ecosystems. 6957 Each card is a tactical "specimen window" â line art, dot grid, 6958 coord stamp, scan sweep. Click to filter projects by ecosystem. 6959 ================================================= --> 6960<!-- ================================================= 6961 PICK YOUR ECOSYSTEM â compact icon-pill chooser. 6962 Six ecosystems as small icon pills matching the sitewide icon style. 6963 Each links to a filtered projects view (?ecosystem=<slug>). 6964 ================================================= --> 6965<section class="ecos-section" aria-label="Pick your ecosystem"> 6966 <div class="wrap"> 6967 <div class="s-head reveal" style="text-align:center;margin-left:auto;margin-right:auto"> 6968 <span class="eyebrow" style="margin:0 auto">Pick your ecosystem</span> 6969 <div class="row" style="justify-content:center"><h2 class="reveal-words" style="margin:0 auto">Find the wild <em>you care about.</em></h2></div> 6970 <p style="margin:18px auto 0;max-width:60ch">Every species lives somewhere specific. Pick the ecosystem that pulls you â see the projects.</p> 6971 </div> 6972 6973 <div class="ecos-strip reveal"> 6974 <a class="ecos-pill" href="/projects/?ecosystem=oceans" data-eco="oceans"> 6975 <span class="ecos-pill-wash" aria-hidden="true"></span> 6976 <span class="ecos-pill-icon" aria-hidden="true"> 6977 <svg viewBox="0 0 60 60"> 6978 <path d="M3 22 Q 14 17 23 22 T 41 22 T 59 22"/> 6979 <path d="M3 32 Q 14 27 23 32 T 41 32 T 59 32" opacity=".7"/> 6980 <path class="ep-fill" d="M16 42 Q 22 38 32 38 L 42 36 L 40 41 L 46 44 L 40 47 L 42 50 L 32 48 Q 22 48 16 42 Z"/> 6981 </svg> 6982 </span> 6983 <span class="ecos-pill-name">Oceans</span> 6984 <span class="ecos-pill-count">2 projects</span> 6985 <span class="ecos-pill-arrow" aria-hidden="true">â</span> 6986 </a> 6987 6988 <a class="ecos-pill" href="/projects/?ecosystem=rainforests" data-eco="rainforests"> 6989 <span class="ecos-pill-wash" aria-hidden="true"></span> 6990 <span class="ecos-pill-icon" aria-hidden="true"> 6991 <svg viewBox="0 0 60 60"> 6992 <path class="ep-fill" d="M14 52 L 14 38 L 9 38 L 17 27 L 13 27 L 19 16 L 25 27 L 21 27 L 29 38 L 24 38 L 24 52 Z"/> 6993 <path class="ep-fill" d="M29 52 L 29 42 L 22 42 L 32 28 L 27 28 L 35 14 L 43 28 L 38 28 L 47 42 L 41 42 L 41 52 Z"/> 6994 <path class="ep-fill" d="M44 52 L 44 40 L 39 40 L 47 30 L 43 30 L 49 20 L 55 30 L 51 30 L 58 40 L 54 40 L 54 52 Z"/> 6995 </svg> 6996 </span> 6997 <span class="ecos-pill-name">Rainforests</span> 6998 <span class="ecos-pill-count">9 projects</span> 6999 <span class="ecos-pill-arrow" aria-hidden="true">â</span> 7000 </a> 7001 7002 <a class="ecos-pill" href="/projects/?ecosystem=savannah" data-eco="savannah"> 7003 <span class="ecos-pill-wash" aria-hidden="true"></span> 7004 <span class="ecos-pill-icon" aria-hidden="true"> 7005 <svg viewBox="0 0 60 60"> 7006 <circle cx="44" cy="18" r="7" class="ep-fill"/> 7007 <line x1="3" y1="48" x2="57" y2="48"/> 7008 <line x1="22" y1="48" x2="22" y2="28"/> 7009 <path class="ep-fill" d="M9 26 Q 22 14 35 26 Q 30 30 22 30 Q 14 30 9 26 Z"/> 7010 <line x1="22" y1="40" x2="15" y2="44" stroke-width="1.2"/> 7011 <line x1="22" y1="40" x2="28" y2="44" stroke-width="1.2"/> 7012 </svg> 7013 </span>
7014 <span class="ecos-pill-name">Savannah</span> 7015 <span class="ecos-pill-count">5 projects</span> 7016 <span class="ecos-pill-arrow" aria-hidden="true">â</span> 7017 </a> 7018 7019 <a class="ecos-pill" href="/projects/?ecosystem=mountains" data-eco="mountains"> 7020 <span class="ecos-pill-wash" aria-hidden="true"></span> 7021 <span class="ecos-pill-icon" aria-hidden="true"> 7022 <svg viewBox="0 0 60 60"> 7023 <path class="ep-fill" d="M2 50 L 13 30 L 20 38 L 30 16 L 40 32 L 48 24 L 58 50 Z"/> 7024 <path d="M28 19 L 30 16 L 32 20" fill="rgba(255,255,255,.85)" stroke="none"/> 7025 <path d="M46 26 L 48 24 L 50 27" fill="rgba(255,255,255,.7)" stroke="none"/> 7026 </svg> 7027 </span> 7028 <span class="ecos-pill-name">Mountains</span> 7029 <span class="ecos-pill-count">2 projects</span> 7030 <span class="ecos-pill-arrow" aria-hidden="true">â</span> 7031 </a> 7032 7033 <a class="ecos-pill" href="/projects/?ecosystem=wetlands" data-eco="wetlands"> 7034 <span class="ecos-pill-wash" aria-hidden="true"></span> 7035 <span class="ecos-pill-icon" aria-hidden="true"> 7036 <svg viewBox="0 0 60 60"> 7037 <path d="M2 16 Q 18 20 26 30 T 50 44" stroke-width="2.4"/> 7038 <ellipse cx="20" cy="18" rx="5" ry="1.6" class="ep-fill"/> 7039 <line x1="11" y1="50" x2="10" y2="44"/> 7040 <line x1="14" y1="50" x2="15" y2="41"/> 7041 <line x1="46" y1="52" x2="48" y2="46"/> 7042 <line x1="50" y1="52" x2="49" y2="48"/> 7043 </svg> 7044 </span> 7045 <span class="ecos-pill-name">Wetlands</span> 7046 <span class="ecos-pill-count">1 project</span> 7047 <span class="ecos-pill-arrow" aria-hidden="true">â</span> 7048 </a> 7049 </div> 7050 </div> 7051</section> 7052 7053<!-- ================================================= 7054 THE 100% PROMISE â full-bleed video section with the key 7055 trust statement. The veterinary animal shot has been removed 7056 from the source clip at its scene boundaries. 7057 ================================================= --> 7058<div class="pin-stack"> 7059<section class="hp-promise is-pinned-bg" aria-label="100% promise"> 7060 <video class="hp-video" autoplay muted loop playsinline preload="metadata" 7061 poster="https://images.squarespace-cdn.com/content/v1/680b6d1bd82ab7606a6e0812/2d5133be-3f2e-4e21-8f46-fef9d53de7c4/1.png?format=2500w" 7062 aria-hidden="true"> 7063 <source src="assets/home_6.mp4" type="video/mp4" /> 7064 </video> 7065 <div class="hp-overlay" aria-hidden="true"></div> 7066 <!-- CARTOGRAPH · THE SEAL â official-document feel: scroll-corner 7067 brackets, certification mark, coordinate stamp --> 7068 <div class="bg-cartograph" aria-hidden="true"> 7069 <svg viewBox="0 0 1600 900" preserveAspectRatio="xMidYMid slice"> 7070 <line class="bg-lat" x1="-50" y1="120" x2="1650" y2="120"/> 7071 <line class="bg-lat" x1="-50" y1="780" x2="1650" y2="780"/> 7072 <!-- Four corner brackets, like an official document --> 7073 <g class="bg-marker"> 7074 <polyline points="120,140 120,100 160,100" fill="none"/> 7075 <polyline points="1480,140 1480,100 1440,100" fill="none"/> 7076 <polyline points="120,760 120,800 160,800" fill="none"/> 7077 <polyline points="1480,760 1480,800 1440,800" fill="none"/> 7078 </g> 7079 <!-- Certification seal â concentric rings with crosshair --> 7080 <g transform="translate(800,140)"> 7081 <circle class="bg-compass-ring" r="34"/> 7082 <circle class="bg-compass-ring" r="24"/> 7083 <line class="bg-compass-tick" x1="0" y1="-40" x2="0" y2="40"/> 7084 <line class="bg-compass-tick" x1="-40" y1="0" x2="40" y2="0"/> 7085 <line class="bg-compass-tick" x1="-28" y1="-28" x2="28" y2="28"/> 7086 <line class="bg-compass-tick" x1="28" y1="-28" x2="-28" y2="28"/> 7087 <circle r="3" class="bg-marker-dot"/> 7088 </g> 7089 <!-- Coordinate stamps --> 7090 <g transform="translate(140,60)"> 7091 <text class="bg-coord-text" x="0" y="0">02 · THE SEAL</text> 7092 </g> 7093 <g transform="translate(1320,60)"> 7094 <text class="bg-coord-text" x="0" y="0">ROUTING · VERIFIED</text> 7095 </g> 7096 <g transform="translate(140,830)"> 7097 <text class="bg-coord-text" x="0" y="0">0% PLATFORM FEE</text> 7098 </g>
7099 <g transform="translate(1330,830)"> 7100 <text class="bg-coord-text" x="0" y="0">DIRECT DISBURSEMENT</text> 7101 </g> 7102 </svg> 7103 </div> 7104 <div class="wrap reveal-stagger" style="position:relative;z-index:2"> 7105 <span class="eyebrow">The promise</span> 7106 <div class="hp-pct">Every <em><span data-money-word>dollar</span>.</em></div> 7107 <h2 class="reveal-words hp-headline">Lands with the <em>partner running the project.</em></h2> 7108 <p class="hp-supporting">No platform fee. No marketing skim. No overhead siphon. Our operating costs are covered separately by corporate partners and the Circle of Giving, so the money you give goes straight to the people doing the work on the ground.</p> 7109 <div class="hp-chips"> 7110 <span class="hp-chip"><span class="hp-tick">â</span> Direct disbursement to NGO</span> 7111 <span class="hp-chip"><span class="hp-tick">â</span> Annual audited accounts</span> 7112 <span class="hp-chip"><span class="hp-tick">â</span> Operating costs separately funded</span> 7113 </div> 7114 </div> 7115</section> 7116 7117<!-- ================================================= 7118 PROOF â concrete case wins 7119 Three campaign-level milestones with image-backed cards. 7120 ================================================= --> 7121<section class="proof section-lift lifts-strong" aria-label="Case wins"> 7122 <!-- CARTOGRAPH 02 · CASE LOG â rich treatment confined to margin bands --> 7123 <div class="bg-cartograph" aria-hidden="true"> 7124 <svg viewBox="0 0 1600 900" preserveAspectRatio="xMidYMid slice"> 7125 <line class="bg-lat" x1="-50" y1="120" x2="1650" y2="120"/> 7126 <line class="bg-lat" x1="-50" y1="780" x2="1650" y2="780"/> 7127 <!-- Top-margin trail flowing from left to right (above the cards) --> 7128 <path class="bg-trail" d="M-40,90 C260,40 480,110 720,60 C940,20 1180,90 1660,40"/> 7129 <path class="bg-trail-soft" d="M-40,160 C200,200 460,140 700,170 C920,195 1160,160 1660,180"/> 7130 <!-- Animal tracks following the trail --> 7131 <circle class="bg-track" cx="120" cy="70" r="3.2"/> 7132 <circle class="bg-track" cx="200" cy="58" r="3"/> 7133 <circle class="bg-track" cx="280" cy="68" r="2.8"/> 7134 <circle class="bg-track" cx="360" cy="78" r="2.8"/> 7135 <circle class="bg-track" cx="440" cy="84" r="3"/> 7136 <circle class="bg-track" cx="520" cy="86" r="3.2"/> 7137 <!-- Three case-marker pins, all in the top margin --> 7138 <g class="bg-marker" transform="translate(720,60)"> 7139 <circle r="13"/><circle r="4.5" class="bg-marker-dot"/> 7140 </g> 7141 <g class="bg-marker" transform="translate(1000,46)"> 7142 <circle r="11"/><circle r="4" class="bg-marker-dot"/> 7143 </g> 7144 <g class="bg-marker" transform="translate(1280,68)"> 7145 <circle r="11"/><circle r="4" class="bg-marker-dot"/> 7146 </g> 7147 <!-- Top-right full compass with N/E/S/W labels --> 7148 <g class="bg-compass" transform="translate(1490,140)"> 7149 <circle class="bg-compass-ring" r="46"/> 7150 <circle class="bg-compass-ring" r="34"/> 7151 <line class="bg-compass-tick" x1="0" y1="-50" x2="0" y2="50"/> 7152 <line class="bg-compass-tick" x1="-50" y1="0" x2="50" y2="0"/> 7153 <line class="bg-compass-tick" x1="-36" y1="-36" x2="36" y2="36"/> 7154 <line class="bg-compass-tick" x1="36" y1="-36" x2="-36" y2="36"/> 7155 <polygon class="bg-compass-arrow" points="0,-46 5,0 0,46 -5,0"/> 7156 <polygon class="bg-compass-arrow" points="-46,0 0,5 46,0 0,-5"/> 7157 <text class="bg-compass-label" x="0" y="-56" text-anchor="middle">N</text> 7158 <text class="bg-compass-label" x="58" y="4" text-anchor="middle">E</text> 7159 <text class="bg-compass-label" x="0" y="68" text-anchor="middle">S</text> 7160 <text class="bg-compass-label" x="-58" y="4" text-anchor="middle">W</text> 7161 </g> 7162 <!-- Vertical scale ruler in left margin (replaces previous leaf motif) --> 7163 <g transform="translate(70,360)"> 7164 <line class="bg-compass-tick" x1="0" y1="0" x2="0" y2="180" stroke-width="1"/> 7165 <line class="bg-compass-tick" x1="-6" y1="0" x2="6" y2="0" stroke-width="1"/> 7166 <line class="bg-compass-tick" x1="-3" y1="30" x2="3" y2="30"/> 7167 <line class="bg-compass-tick" x1="-4" y1="60" x2="4" y2="60"/> 7168 <line class="bg-compass-tick" x1="-3" y1="90" x2="3" y2="90"/> 7169 <line class="bg-compass-tick" x1="-4" y1="120" x2="4" y2="120"/> 7170 <line class="bg-compass-tick" x1="-3" y1="150" x2="3" y2="150"/> 7171 <line class="bg-compass-tick" x1="-6" y1="180" x2="6" y2="180" stroke-width="1"/> 7172 <text class="bg-coord-text" x="14" y="4">0</text> 7173 <text class="bg-coord-text" x="14" y="184">300M</text> 7174 </g> 7175 <!-- Bottom-margin scale + section label + secondary coord text --> 7176 <g transform="translate(140,820)"> 7177 <line class="bg-compass-tick" x1="0" y1="0" x2="180" y2="0" stroke-width="1"/> 7178 <line class="bg-compass-tick" x1="0" y1="-5" x2="0" y2="5" stroke-width="1"/> 7179 <line class="bg-compass-tick" x1="60" y1="-3" x2="60" y2="3"/> 7180 <line class="bg-compass-tick" x1="120" y1="-3" x2="120" y2="3"/> 7181 <line class="bg-compass-tick" x1="180" y1="-5" x2="180" y2="5" stroke-width="1"/> 7182 <text class="bg-coord-text" x="0" y="-12">02 · CASE LOG</text> 7183 <text class="bg-coord-text" x="160" y="-12">3 FIELD CASES</text> 7184 </g> 7185 </svg> 7186 </div> 7187 <div class="atmos" aria-hidden="true">
7188 <div class="orb orb-1"></div><div class="orb orb-2"></div><div class="orb orb-3"></div> 7189 <svg class="topo" viewBox="0 0 1600 600" preserveAspectRatio="none" style="display:none"> 7190 <path d="M0,420 C200,360 400,440 600,400 S1000,360 1200,420 1600,380 1800,420 2200,360 2400,400 S2800,360 3200,420"/> 7191 <path d="M0,300 C200,260 400,340 600,300 S1000,260 1200,300 1600,260 1800,300 2200,260 2400,300 S2800,260 3200,300"/> 7192 <path d="M0,200 C200,160 400,240 600,200 S1000,160 1200,200 1600,160 1800,200 2200,160 2400,200 S2800,160 3200,200"/> 7193 <path d="M0,500 C200,460 400,540 600,500 S1000,460 1200,500 1600,460 1800,500 2200,460 2400,500 S2800,460 3200,500"/> 7194 </svg> 7195 </div> 7196 <div class="wrap"> 7197 <div class="s-head reveal"> 7198 <span class="eyebrow">Proof of concept</span> 7199 <div class="row"> 7200 <div class="row-left"> 7201 <h2 class="reveal-words">Real numbers. <em>Real wins.</em></h2> 7202 <p>Three campaigns, three results. The same model running across all <span data-livestat="projects">34</span> projects.</p> 7203 <a class="btn-quiet" href="/projects/">See every project</a> 7204 </div> 7205 <div class="row-side"> 7206 <aside class="impacts-panel" aria-label="Impact so far"> 7207 <div class="impacts-head"> 7208 <span class="impacts-title"><b>â¢</b> The impact so far</span> 7209 <span class="impacts-year">To date</span> 7210 </div> 7211 <div class="impacts-list"> 7212 <div class="impact-row"> 7213 <span class="impact-icon" aria-hidden="true"> 7214 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 1v22M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"/></svg> 7215 </span> 7216 <span class="impact-num"><span data-livestat="raised">$698K</span><em>raised</em></span> 7217 <span class="impact-label">100% routed straight to NGO partners.</span> 7218 </div> 7219 <div class="impact-row"> 7220 <span class="impact-icon" aria-hidden="true"> 7221 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 21h18M5 21V8l7-5 7 5v13M9 21v-6h6v6"/></svg> 7222 </span> 7223 <span class="impact-num"><span data-livestat="projects">34</span><em>projects</em></span> 7224 <span class="impact-label">Backed to date, each run by a partner NGO.</span> 7225 </div> 7226 <div class="impact-row"> 7227 <span class="impact-icon" aria-hidden="true"> 7228 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2c-3 4-3 7 0 10s3 6 0 10c-3-4-3-7 0-10s3-6 0-10z"/><path d="M5 13c2 1 3 3 3 6M19 13c-2 1-3 3-3 6"/></svg> 7229 </span> 7230 <span class="impact-num"><span data-livestat="ngos">64</span><em>NGOs</em></span> 7231 <span class="impact-label">Partner organizations on the ground.</span> 7232 </div> 7233 <div class="impact-row"> 7234 <span class="impact-icon" aria-hidden="true"> 7235 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="9" cy="8" r="3"/><circle cx="17" cy="10" r="2.5"/><path d="M3 21c0-3.3 2.7-6 6-6s6 2.7 6 6"/><path d="M14.5 21c0-2.5 2-4.5 4.5-4.5s2.5 0 2.5 0"/></svg> 7236 </span> 7237 <span class="impact-num">6<em>continents</em></span> 7238 <span class="impact-label">Everywhere the partners work, bar Antarctica.</span> 7239 </div> 7240 </div> 7241 </aside> 7242 </div> 7243 </div> 7244 </div> 7245 7246 <div class="proof-grid reveal-stagger"> 7247 <article class="pcard"> 7248 <div class="pbg" style="background-image:url('/assets/projects/a-free-life-for-thailands-rescued-elephants-hd.jpg')" role="img" aria-label="Rescued elephants at a Thailand sanctuary"></div>
7249 <span class="picon-tr" aria-hidden="true" title="Elephant"><svg viewBox="0 0 64 64"><polygon points="10,38 30,22 46,24 56,34 56,46 48,52 38,52 38,44 28,44 28,52 18,52 10,46" fill="url(#og-mid)"/><polygon points="30,22 46,24 38,32" fill="url(#og-light)" opacity=".9"/><polygon points="10,38 30,22 28,44" fill="url(#og-dark)" opacity=".85"/><polygon points="46,24 56,34 50,38" fill="url(#og-light)" opacity=".75"/><polygon points="56,34 56,46 48,40" fill="url(#og-dark)"/><polygon points="42,20 52,18 50,30 40,28" fill="url(#og-light)"/><polygon points="54,38 60,42 58,52 50,48" fill="url(#og-mid)"/><polygon points="58,52 50,48 54,54" fill="url(#og-dark)"/><circle cx="46" cy="30" r="1.6" fill="#020718"/></svg></span> 7250 <span class="ptag"><span class="pdot"></span>Save Elephant Foundation · Thailand</span> 7251 <div class="pbody"> 7252 <span class="coord-stamp" aria-hidden="true"><span class="cs-lat">18.93°N</span><span class="cs-sep"></span><span class="cs-lon">98.62°E</span></span> 7253 <div class="pnum"><span>$127K<em>+</em></span></div> 7254 <div class="pcaption">Routed to elephant rescue and lifetime sanctuary care.</div> 7255 <p class="pdesc">Rescue, rehabilitation and lifetime care for working and circus elephants, funded directly by Ecoflix donors.</p> 7256 <a class="plink" href="/projects/a-free-life-for-thailands-rescued-elephants/">See the project â</a> 7257 </div> 7258 </article> 7259 7260 <article class="pcard"> 7261 <div class="pbg" style="background-image:url('/assets/ngo/the-gorilla-organization/hero-hd.jpg')" role="img" aria-label="Gorilla in the forest â Cross River gorilla habitat"></div> 7262 <span class="picon-tr" aria-hidden="true" title="Forest"><svg viewBox="0 0 64 64"><polygon points="32,4 22,20 32,18 42,20" fill="url(#og-light)"/><polygon points="32,4 32,18 22,20" fill="url(#og-mid)" opacity=".7"/><polygon points="32,4 32,18 42,20" fill="url(#og-dark)" opacity=".7"/><polygon points="32,16 18,32 32,30 46,32" fill="url(#og-light)"/><polygon points="32,16 32,30 18,32" fill="url(#og-mid)" opacity=".8"/><polygon points="32,16 32,30 46,32" fill="url(#og-dark)" opacity=".8"/><polygon points="32,28 12,48 32,46 52,48" fill="url(#og-light)"/><polygon points="32,28 32,46 12,48" fill="url(#og-mid)" opacity=".85"/><polygon points="32,28 32,46 52,48" fill="url(#og-dark)" opacity=".85"/><polygon points="28,46 36,46 36,58 28,58" fill="url(#og-deep)"/><polygon points="28,46 36,46 32,52" fill="url(#og-dark)" opacity=".6"/></svg></span> 7263 <span class="ptag"><span class="pdot"></span>African Conservation Foundation · Cameroon</span> 7264 <div class="pbody"> 7265 <span class="coord-stamp" aria-hidden="true"><span class="cs-lat">6.00°N</span><span class="cs-sep"></span><span class="cs-lon">9.20°E</span></span> 7266 <div class="pnum"><span><300<em></em></span></div> 7267 <div class="pcaption">Cross River gorillas left in the wild.</div> 7268 <p class="pdesc">Community rangers, habitat protection and population monitoring for one of the rarest apes on Earth, across Cameroon.</p> 7269 <a class="plink" href="/projects/saving-the-cross-river-gorilla/">See the project â</a> 7270 </div> 7271 </article> 7272 7273 <article class="pcard"> 7274 <div class="pbg" style="background-image:url('/assets/projects/standing-with-wildlife-rangers-hd.jpg')" role="img" aria-label="Wildlife rangers in the field"></div> 7275 <span class="picon-tr" aria-hidden="true" title="Lion"><svg viewBox="0 0 64 64"><polygon points="32,2 36,12 28,12" fill="url(#og-mid)"/><polygon points="54,8 50,18 44,12" fill="url(#og-mid)"/><polygon points="62,32 52,36 52,28" fill="url(#og-mid)"/><polygon points="54,56 44,52 50,46" fill="url(#og-mid)"/><polygon points="32,62 28,52 36,52" fill="url(#og-mid)"/><polygon points="10,56 20,52 14,46" fill="url(#og-mid)"/><polygon points="2,32 12,28 12,36" fill="url(#og-mid)"/><polygon points="10,8 14,18 20,12" fill="url(#og-mid)"/><polygon points="32,8 52,18 56,32 50,50 32,56 14,50 8,32 12,18" fill="url(#og-dark)"/><polygon points="32,8 52,18 56,32 38,28" fill="url(#og-mid)" opacity=".55"/>
7275<polygon points="32,8 12,18 8,32 26,28" fill="url(#og-deep)" opacity=".7"/><polygon points="20,22 32,18 44,22 46,38 38,48 26,48 18,38" fill="url(#og-light)"/><polygon points="32,18 44,22 46,38 36,32" fill="url(#og-mid)" opacity=".7"/><polygon points="32,18 20,22 18,38 28,32" fill="url(#og-mid)" opacity=".5"/><polygon points="26,36 38,36 36,44 28,44" fill="url(#og-deep)"/><circle cx="26" cy="30" r="1.6" fill="#020718"/><circle cx="38" cy="30" r="1.6" fill="#020718"/></svg></span> 7276 <span class="ptag"><span class="pdot"></span>Over and Above Africa · Africa</span> 7277 <div class="pbody"> 7278 <span class="coord-stamp" aria-hidden="true"><span class="cs-lat">2.15°S</span><span class="cs-sep"></span><span class="cs-lon">34.69°E</span></span> 7279 <div class="pnum"><span>$12K<em>+</em></span></div> 7280 <div class="pcaption">Routed to frontline ranger support through partner programmes.</div> 7281 <p class="pdesc">Boots, kit, fuel, medical, salaries. The unglamorous line items that keep species alive in the field.</p> 7282 <a class="plink" href="/projects/frontline-support-for-africas-wildlife/">See the project â</a> 7283 </div> 7284 </article> 7285 </div> 7286 </div> 7287</section> 7288</div><!-- /.pin-stack hp-promiseâproof --> 7289 7290<!-- ================================================= 7291 WATCH THE CHANGE YOU MAKE â full-bleed video of families, 7292 classrooms, lounges, field stations watching Ecoflix. The 7293 audience that watches becomes the audience that funds. 7294 User will supply the video â swap the <source> below when 7295 the file lands in assets/. 7296 ================================================= --> 7297<div class="pin-stack"> 7298<section class="watch-change is-pinned-bg" aria-label="Watch the change you make"> 7299 <video class="wc-video" autoplay muted loop playsinline preload="metadata" 7300 poster="https://images.squarespace-cdn.com/content/v1/680b6d1bd82ab7606a6e0812/eaa71cc1-d292-4414-9d1a-baebb3020488/ecoflix_FREE_BILLY_6000+x+4000.jpg?format=2500w" 7301 aria-hidden="true"> 7302 <source src="assets/watch-change.mp4" type="video/mp4" /> 7303 </video> 7304 <div class="wc-overlay" aria-hidden="true"></div> 7305 <!-- CARTOGRAPH · TRANSMISSION â broadcast waves, no leaf vein --> 7306 <div class="bg-cartograph" aria-hidden="true"> 7307 <svg viewBox="0 0 1600 900" preserveAspectRatio="xMidYMid slice"> 7308 <line class="bg-lat" x1="-50" y1="120" x2="1650" y2="120"/> 7309 <line class="bg-lat" x1="-50" y1="780" x2="1650" y2="780"/> 7310 <!-- Concentric broadcast rings (top-right) â radio transmission --> 7311 <g transform="translate(1400,200)"> 7312 <circle class="bg-compass-ring" r="22" fill="none"/> 7313 <circle class="bg-compass-ring" r="48" fill="none" stroke-dasharray="3 7"/> 7314 <circle class="bg-compass-ring" r="78" fill="none" stroke-dasharray="2 12" stroke-opacity=".5"/> 7315 <circle r="3" class="bg-marker-dot"/> 7316 </g> 7317 <!-- Trail across bottom margin --> 7318 <path class="bg-trail" d="M-40,820 C260,780 540,840 800,800 C1060,760 1340,830 1660,790"/> 7319 <path class="bg-trail-soft" d="M-40,860 C260,840 540,870 800,850 C1060,830 1340,860 1660,840"/> 7320 <!-- Tracks following bottom trail --> 7321 <circle class="bg-track" cx="180" cy="808" r="3"/> 7322 <circle class="bg-track" cx="260" cy="804" r="3"/> 7323 <circle class="bg-track" cx="340" cy="808" r="3"/> 7324 <!-- Map pin (broadcast tower) --> 7325 <g class="bg-marker" transform="translate(800,800)"> 7326 <circle r="12"/><circle r="4" class="bg-marker-dot"/> 7327 </g> 7328 <!-- Compass bottom-left --> 7329 <g class="bg-compass" transform="translate(160,200)"> 7330 <circle class="bg-compass-ring" r="42"/> 7331 <circle class="bg-compass-ring" r="30"/> 7332 <line class="bg-compass-tick" x1="0" y1="-46" x2="0" y2="46"/> 7333 <line class="bg-compass-tick" x1="-46" y1="0" x2="46" y2="0"/> 7334 <line class="bg-compass-tick" x1="-33" y1="-33" x2="33" y2="33"/> 7335 <line class="bg-compass-tick" x1="33" y1="-33" x2="-33" y2="33"/> 7336 <polygon class="bg-compass-arrow" points="0,-42 5,0 0,42 -5,0"/> 7337 <polygon class="bg-compass-arrow" points="-42,0 0,5 42,0 0,-5"/> 7338 <text class="bg-compass-label" x="0" y="-52" text-anchor="middle">N</text> 7339 <text class="bg-compass-label" x="54" y="4" text-anchor="middle">E</text> 7340 <text class="bg-compass-label" x="0" y="64" text-anchor="middle">S</text> 7341 <text class="bg-compass-label" x="-54" y="4" text-anchor="middle">W</text> 7342 </g> 7343 <!-- Coordinate stamps --> 7344 <g transform="translate(140,60)"> 7345 <text class="bg-coord-text" x="0" y="0">TRANSMISSION · ON AIR</text> 7346 </g> 7347 <g transform="translate(1320,60)"> 7348 <text class="bg-coord-text" x="0" y="0">REACH · MILLIONS</text> 7349 </g> 7350 </svg> 7351 </div> 7352 <div class="wrap reveal-stagger" style="position:relative;z-index:2"> 7353 <span class="eyebrow">The channel</span> 7354 <h2 class="reveal-words wc-headline">Watch the <em>change you make.</em></h2> 7355 <p class="wc-supporting">
7355Every donation surfaces as a story on the channel. Families, classrooms, lounges and field stations â the audience that watches becomes the audience that funds.</p> 7356 <div class="wc-actions"> 7357 <a class="btn btn-primary" href="https://watch.ecoflix.com/">Open the channel <span class="arrow">â</span></a> 7358 <a class="btn btn-ghost" href="/donate/">Donate now</a> 7359 </div> 7360 </div> 7361</section> 7362 7363<!-- 7364 ORIGAMI ICON GRADIENTS 7365 Shared SVG defs used by every project-card origami animal icon. 7366 Light-side / dark-side gradients build the faceted paper-fold look. 7367 ================================================= --> 7368<svg width="0" height="0" style="position:absolute" aria-hidden="true"> 7369 <defs> 7370 <linearGradient id="og-light" x1="0" y1="0" x2="1" y2="1"> 7371 <stop offset="0%" stop-color="#D3FA9E"/> 7372 <stop offset="100%" stop-color="#A8F341"/> 7373 </linearGradient> 7374 <linearGradient id="og-mid" x1="0" y1="0" x2="1" y2="1"> 7375 <stop offset="0%" stop-color="#A8F341"/> 7376 <stop offset="100%" stop-color="#6CB822"/> 7377 </linearGradient> 7378 <linearGradient id="og-dark" x1="0" y1="0" x2="1" y2="1"> 7379 <stop offset="0%" stop-color="#6CB822"/> 7380 <stop offset="100%" stop-color="#0d1530"/> 7381 </linearGradient> 7382 <linearGradient id="og-deep" x1="0" y1="0" x2="1" y2="1"> 7383 <stop offset="0%" stop-color="#172040"/> 7384 <stop offset="100%" stop-color="#020718"/> 7385 </linearGradient> 7386 </defs> 7387</svg> 7388 7389<!-- ================================================= 7390 STAGE 5a â Projects (horizontal scroll, magnesia.cz pattern) 7391 Section pins for ~6 card-heights and the track slides left 7392 as the user scrolls down. Falls back to vertical grid on 7393 mobile / reduced-motion via CSS media queries. 7394 ================================================= --> 7395<section class="hscroll-stage section-lift lifts-strong" id="projects" aria-label="Projects you can fund"> 7396 <!-- CARTOGRAPH 03 · DIRECTORY â rich top-and-bottom margin treatment --> 7397 <div class="bg-cartograph" aria-hidden="true"> 7398 <svg viewBox="0 0 1600 900" preserveAspectRatio="xMidYMid slice"> 7399 <line class="bg-lat" x1="-50" y1="100" x2="1650" y2="100"/> 7400 <line class="bg-lat" x1="-50" y1="220" x2="1650" y2="220" stroke-dasharray="2 18"/> 7401 <line class="bg-lat" x1="-50" y1="800" x2="1650" y2="800"/> 7402 <!-- Top-margin gentle trail --> 7403 <path class="bg-trail" d="M-40,160 C220,80 460,180 700,140 C940,100 1180,180 1660,120"/> 7404 <path class="bg-trail-soft" d="M-40,60 C260,100 520,40 760,80 C1000,120 1240,60 1660,90"/> 7405 <!-- Animal tracks along the top trail --> 7406 <circle class="bg-track" cx="180" cy="142" r="3"/> 7407 <circle class="bg-track" cx="260" cy="128" r="3"/> 7408 <circle class="bg-track" cx="340" cy="118" r="3"/> 7409 <circle class="bg-track" cx="420" cy="116" r="3"/> 7410 <!-- Subdivided scale ruler in top-left margin --> 7411 <g transform="translate(140,40)"> 7412 <line class="bg-compass-tick" x1="0" y1="0" x2="320" y2="0" stroke-width="1"/> 7413 <line class="bg-compass-tick" x1="0" y1="-7" x2="0" y2="7" stroke-width="1"/> 7414 <line class="bg-compass-tick" x1="40" y1="-3" x2="40" y2="3"/> 7415 <line class="bg-compass-tick" x1="80" y1="-4" x2="80" y2="4"/> 7416 <line class="bg-compass-tick" x1="120" y1="-3" x2="120" y2="3"/> 7417 <line class="bg-compass-tick" x1="160" y1="-5" x2="160" y2="5"/> 7418 <line class="bg-compass-tick" x1="200" y1="-3" x2="200" y2="3"/> 7419 <line class="bg-compass-tick" x1="240" y1="-4" x2="240" y2="4"/> 7420 <line class="bg-compass-tick" x1="280" y1="-3" x2="280" y2="3"/> 7421 <line class="bg-compass-tick" x1="320" y1="-7" x2="320" y2="7" stroke-width="1"/> 7422 <text class="bg-coord-text" x="0" y="-12">DIRECTORY · 06 OF 24</text> 7423 </g> 7424 <!-- Top-right full compass with N/E/S/W --> 7425 <g class="bg-compass" transform="translate(1490,120)"> 7426 <circle class="bg-compass-ring" r="44"/> 7427 <circle class="bg-compass-ring" r="32"/> 7428 <line class="bg-compass-tick" x1="0" y1="-48" x2="0" y2="48"/> 7429 <line class="bg-compass-tick" x1="-48" y1="0" x2="48" y2="0"/> 7430 <line class="bg-compass-tick" x1="-34" y1="-34" x2="34" y2="34"/> 7431 <line class="bg-compass-tick" x1="34" y1="-34" x2="-34" y2="34"/> 7432 <polygon class="bg-compass-arrow" points="0,-44 5,0 0,44 -5,0"/> 7433 <polygon class="bg-compass-arrow" points="-44,0 0,5 44,0 0,-5"/> 7434 <text class="bg-compass-label" x="0" y="-54" text-anchor="middle">N</text> 7435 <text class="bg-compass-label" x="56" y="4" text-anchor="middle">E</text> 7436 <text class="bg-compass-label" x="0" y="66" text-anchor="middle">S</text> 7437 <text class="bg-compass-label" x="-56" y="4" text-anchor="middle">W</text> 7438 </g> 7439 <!-- Vertical degree-tick scale in right margin (replaces leaf motif) --> 7440 <g transform="translate(1530,380)"> 7441 <line class="bg-compass-tick" x1="0" y1="0" x2="0" y2="160" stroke-width="1"/> 7442 <line class="bg-compass-tick" x1="-6" y1="0" x2="6" y2="0" stroke-width="1"/> 7443 <line class="bg-compass-tick" x1="-3" y1="32" x2="3" y2="32"/> 7444 <line class="bg-compass-tick" x1="-4" y1="64" x2="4" y2="64"/> 7445 <line class="bg-compass-tick" x1="-3" y1="96" x2="3" y2="96"/> 7446 <line class="bg-compass-tick" x1="-4" y1="128" x2="4" y2="128"/> 7447 <line class="bg-compass-tick" x1="-6" y1="160" x2="6" y2="160" stroke-width="1"/> 7448 <text class="bg-coord-text" x="-58" y="4">N</text> 7449 <text class="bg-coord-text" x="-58" y="164">S</text> 7450 </g> 7451 <!-- Bottom-margin trail curving the other way + tracks --> 7452 <path class="bg-trail-soft" d="M-40,840 C260,800 520,860 760,810 C1000,770 1240,830 1660,810"/> 7453 <circle class="bg-track" cx="1140" cy="820" r="3"/> 7454 <circle class="bg-track" cx="1220" cy="812" r="3"/> 7455 <circle class="bg-track" cx="1300" cy="804" r="3"/> 7456 <circle class="bg-track" cx="1380" cy="808" r="3"/> 7457 <!-- Bottom margin labels --> 7458 <g transform="translate(140,855)"> 7459 <text class="bg-coord-text" x="0" y="0">03 · DIRECTORY</text> 7460 </g> 7461 <g transform="translate(1310,855)"> 7462 <text class="bg-coord-text" x="0" y="0">34 PROJECTS · 6 CONTINENTS</text> 7463 </g> 7464 </svg> 7465 </div> 7466 <div class="hscroll-pin" style="position:relative;z-index:2"> 7467 <div class="hscroll-head reveal"> 7468 <div class="hscroll-head-text">
7469 <span class="eyebrow">Active projects</span> 7470 <h2 class="reveal-words">Projects you can <em>fund right now.</em></h2> 7471 <p>Each project lives on its partner NGO's own Ecoflix page. Pick one, give what you can, follow the progress.</p> 7472 <a class="btn btn-primary btn-jumbo hp-see-all-cta" href="/projects/"> 7473 See all <span data-livestat="projects">34</span> projects 7474 <span class="arrow" aria-hidden="true">â</span> 7475 </a> 7476 </div> 7477 <div class="hscroll-head-side"> 7478 <aside class="projects-panel" aria-label="Projects activity this week"> 7479 <div class="pp-head"> 7480 <span class="pp-title">Projects this week</span> 7481 <span class="pp-live">Live</span> 7482 </div> 7483 7484 <a class="pp-feature" href="/projects/xudumela/" aria-label="Featured project: Xudumela"> 7485 <div class="pp-label"> 7486 <svg width="11" height="11" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M13 2 3 14h7l-1 8 11-14h-7l1-6z"/></svg> 7487 Featured project 7488 </div> 7489 <div class="pp-name">Turning a Hunting Ground into a Reserve</div> 7490 <div class="pp-bar"><span class="pp-fill" data-livestat="fundbar:xudumela" style="width:60%"></span></div> 7491 <div class="pp-meta"><span><b data-livestat="fundpct:xudumela">60</b>% funded</span><span>Okavango Delta</span></div> 7492 </a> 7493 7494 <hr class="pp-divider"/> 7495 7496 <div class="pp-list"> 7497 <div class="pp-row"> 7498 <span class="pp-icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><polyline points="3 17 9 11 13 15 21 7"/><polyline points="15 7 21 7 21 13"/></svg></span> 7499 <span class="pp-num" data-livestat="active">23<em>live</em></span> 7500 <span class="pp-text">Active campaigns taking donations now.</span> 7501 </div> 7502 <div class="pp-row"> 7503 <span class="pp-icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2c2 4 6 6 6 11a6 6 0 0 1-12 0c0-3 2-5 3-7 1 2 2 3 3 4 0-3 0-6 0-8z"/></svg></span> 7504 <span class="pp-num" data-livestat="urgent">2<em>urgent</em></span> 7505 <span class="pp-text">Campaigns flagged urgent by their partner NGO.</span> 7506 </div> 7507 <div class="pp-row"> 7508 <span class="pp-icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M5 13l4 4L19 7"/></svg></span> 7509 <span class="pp-num" data-livestat="completed">11<em>done</em></span> 7510 <span class="pp-text">Projects funded through to completion.</span> 7511 </div> 7512 <div class="pp-row"> 7513 <span class="pp-icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M3 12h18M12 3c3 3 3 15 0 18M12 3c-3 3-3 15 0 18"/></svg></span> 7514 <span class="pp-num">6<em>cont.</em></span> 7515 <span class="pp-text">Continents currently in play.</span> 7516 </div> 7517 </div> 7518 </aside> 7519 </div> 7520 </div> 7521 7522 <!-- The "Where are you? / Find the project closest to you / Locate me" 7523 widget that lived here has been removed. The new homepage section 7524 "Where you fit in" (further down the page) already shows the 7525 visitor's location + nearest partner NGOs in a richer, no-click 7526 experience â no need for a duplicate locate-me block here. --> 7527 7528 <!-- Saved-projects recall ribbon (hidden until localStorage has entries) --> 7529 <div class="saved-ribbon" id="savedRibbon" role="status" hidden> 7530 <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M12 21s-7-4.5-9.5-9C1 9 3 5 7 5c2 0 4 1 5 3 1-2 3-3 5-3 4 0 6 4 4.5 7-2.5 4.5-9.5 9-9.5 9z"/></svg>
7531 <span><b>Welcome back.</b> The <span class="sr-count">2</span> projects you saved are still active.</span> 7532 <button type="button" class="sr-clear" id="srClear">Clear saved</button> 7533 </div> 7534 7535 <!-- Filter chips + view toggle --> 7536 <div class="proj-filters" id="projFilters" role="group" aria-label="Filter projects"> 7537 <span class="proj-filter-label">Filter</span> 7538 <button class="proj-chip active" data-filter="all" type="button">All <span class="pc-count">(6)</span></button> 7539 <button class="proj-chip" data-filter="urgent" type="button">Urgent</button> 7540 <button class="proj-chip" data-filter="africa" type="button">Africa</button> 7541 <button class="proj-chip" data-filter="asia" type="button">Asia</button> 7542 <button class="proj-chip" data-filter="americas" type="button">Americas</button> 7543 <button class="proj-chip" data-filter="europe" type="button">Europe</button> 7544 <button class="proj-chip" data-filter="saved" type="button">Saved <span class="pc-count" id="savedCount">(0)</span></button> 7545 <div class="view-toggle" role="group" aria-label="View toggle"> 7546 <button class="vt-grid active" type="button" data-view="grid" aria-label="Grid view"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/></svg>Grid</button> 7547 <button class="vt-list" type="button" data-view="list" aria-label="List view"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><circle cx="4" cy="6" r="1.5"/><circle cx="4" cy="12" r="1.5"/><circle cx="4" cy="18" r="1.5"/></svg>List</button> 7548 </div> 7549 </div> 7550 7551 <div class="hscroll-row"> 7552 <div class="pcs-wrap" id="hpProjectsCarousel"> 7553 <div class="hscroll-track reveal-stagger pcs-stage" id="hscrollTrack" tabindex="0" data-fresh="1" aria-label="Featured projects â drag to swipe or use arrow keys"> 7554 <article class="proj-card js-tilt is-featured" data-lat="18.93" data-lon="98.62" data-name="A Free Life for Thailand's Rescued Elephants" data-region="asia" data-id="a-free-life-for-thailands-rescued-elephants"> 7555 <span class="status-stripe" aria-hidden="true"></span> 7556 <div class="img" style="background-image:url('/assets/projects/a-free-life-for-thailands-rescued-elephants-hd.jpg')"></div> 7557 <div class="shade"></div> 7558 <div class="spotlight"></div> 7559 <span class="miniglobe" aria-label="Chiang Mai, Thailand"> 7560 <svg viewBox="0 0 32 32"> 7561 <circle class="globe" cx="16" cy="16" r="13"/> 7562 <path class="lat" d="M3 16 H29"/> 7563 <path class="lon" d="M16 3 Q22 16 16 29 Q10 16 16 3"/> 7564 <circle class="pin-ring" cx="22" cy="13" r="2"/> 7565 <circle class="pin" cx="22" cy="13" r="2"/> 7566 </svg> 7567 </span> 7568 <span class="featured-flag" aria-label="Featured project"><svg viewBox="0 0 24 24"><path d="M12 2l2.4 6.6 6.6.5-5 4.4 1.6 6.5L12 16.7 6.4 20l1.6-6.5-5-4.4 6.6-.5z" fill="currentColor" stroke="none"/></svg>Featured project</span> 7569 <span class="picon-tr is-origami" aria-hidden="true" title="Elephant â Save Elephant Foundation"> 7570 <svg viewBox="0 0 64 64"> 7571 <!-- Origami elephant: body, head, trunk, ear, legs as faceted triangles --> 7572 <polygon points="10,38 30,22 46,24 56,34 56,46 48,52 38,52 38,44 28,44 28,52 18,52 10,46" fill="url(#og-mid)"/> 7573 <polygon points="30,22 46,24 38,32" fill="url(#og-light)" opacity=".9"/> 7574 <polygon points="10,38 30,22 28,44" fill="url(#og-dark)" opacity=".85"/> 7575 <polygon points="46,24 56,34 50,38" fill="url(#og-light)" opacity=".75"/> 7576 <polygon points="56,34 56,46 48,40" fill="url(#og-dark)"/> 7577 <!-- Ear flap --> 7578 <polygon points="42,20 52,18 50,30 40,28" fill="url(#og-light)"/> 7579 <polygon points="42,20 50,30 40,28" fill="url(#og-mid)" opacity=".6"/> 7580 <!-- Trunk --> 7581 <polygon points="54,38 60,42 58,52 50,48" fill="url(#og-mid)"/> 7582 <polygon points="58,52 50,48 54,54" fill="url(#og-dark)"/> 7583 <!-- Eye --> 7584 <circle cx="46" cy="30" r="1.6" fill="#020718"/> 7585 </svg> 7586 </span> 7587 <div class="meta">
7588 <span class="biome"><svg viewBox="0 0 24 24"><path d="M12 2C8 2 5 5 5 9c0 5.5 7 13 7 13s7-7.5 7-13c0-4-3-7-7-7z"/><circle cx="12" cy="9" r="2.5"/></svg><b>Asian elephant</b> · Sanctuary care</span> 7589 <span class="tag"><span class="dot"></span><span class="tag-text"><b class="tag-status">Active</b><span class="tag-location">Chiang Mai, Thailand</span></span></span> 7590 <span class="coord-stamp" aria-hidden="true"><span class="cs-lat">18.93°N</span><span class="cs-sep"></span><span class="cs-lon">98.62°E</span></span> 7591 <h3>A Free Life for Thailand's Rescued Elephants</h3> 7592 <div class="ngo">Save Elephant Foundation</div> 7593 <div class="qstats"> 7594 <div class="qs"><b>$127K<em>+</em></b><span>Routed by Ecoflix</span></div> 7595 <div class="qs"><b>100<em>%</em></b><span>To the partner</span></div> 7596 </div> 7597 <div class="founder"> 7598 <div class="founder-avatar" style="background-image:url('https://www.saveelephant.org/wp-content/uploads/2022/02/Lek-With-Elephants.jpg')"></div> 7599 <div class="founder-meta"><strong>Lek Chailert</strong><span>Founder, Save Elephant Foundation</span></div> 7600 </div> 7601 <p class="quote-pull">"Ecoflix gave us a real audience. People didn't just watch our story, they paid for the next chapter."</p> 7602 <div class="progress"><span data-livestat="fund:a-free-life-for-thailands-rescued-elephants">72% funded</span><div class="progress-bar"><span class="fill" data-livestat="fundvar:a-free-life-for-thailands-rescued-elephants" style="--p:72%"></span></div></div> 7603 <a class="cta" href="/projects/a-free-life-for-thailands-rescued-elephants/">Support this project â</a> 7604 </div> 7605 <div class="expand-panel"> 7606 <div class="ep-eyebrow">What your donation funds</div> 7607 <div class="ep-title">Daily care for over 100 rescued elephants in Chiang Mai.</div> 7608 <p class="ep-desc">Lek Chailert's sanctuary takes elephants out of logging, circus and trekking work. Lifetime care, no riding, no chains.</p> 7609 <ul class="ep-list"> 7610 <li>Daily medical and mahout salaries</li> 7611 <li>Hay, pumpkins and produce</li> 7612 <li>Sanctuary security and expansion</li> 7613 <li>Rescue operations across Asia</li> 7614 </ul> 7615 <a class="ep-cta" href="/projects/a-free-life-for-thailands-rescued-elephants/">Open the project <span>â</span></a> 7616 </div> 7617 </article> 7618 <article class="proj-card js-tilt" data-lat="34.47" data-lon="-118.20" data-name="A Forest Home for Rescued Wolves" data-region="americas" data-id="a-forest-home-for-rescued-wolves"> 7619 <span class="status-stripe" aria-hidden="true"></span> 7620 <div class="img" style="background-image:url('/assets/projects/a-forest-home-for-rescued-wolves-hd.jpg')"></div> 7621 <div class="shade"></div> 7622 <div class="spotlight"></div> 7623 <span class="miniglobe" aria-label="Acton, California, USA"> 7624 <svg viewBox="0 0 32 32"> 7625 <circle class="globe" cx="16" cy="16" r="13"/> 7626 <path class="lat" d="M3 16 H29"/> 7627 <path class="lon" d="M16 3 Q22 16 16 29 Q10 16 16 3"/> 7628 <circle class="pin-ring" cx="9" cy="13" r="2"/> 7629 <circle class="pin" cx="9" cy="13" r="2"/> 7630 </svg> 7631 </span> 7632 <span class="picon-tr is-origami" aria-hidden="true" title="Wolf â Wolf Connection"> 7633 <svg viewBox="0 0 64 64"> 7634 <!-- Origami wolf head: pointed ears, faceted face, snout --> 7635 <polygon points="14,10 22,6 24,22" fill="url(#og-light)"/> 7636 <polygon points="22,6 24,22 18,18" fill="url(#og-mid)"/> 7637 <polygon points="50,10 42,6 40,22" fill="url(#og-light)"/> 7638 <polygon points="42,6 40,22 46,18" fill="url(#og-mid)"/> 7639 <!-- Head main facets --> 7640 <polygon points="14,10 32,18 50,10 52,38 42,52 22,52 12,38" fill="url(#og-mid)"/> 7641 <polygon points="32,18 50,10 52,38 42,38" fill="url(#og-light)" opacity=".75"/> 7642 <polygon points="32,18 14,10 12,38 22,38" fill="url(#og-dark)" opacity=".85"/> 7643 <!-- Snout --> 7644 <polygon points="22,38 42,38 38,50 26,50" fill="url(#og-deep)"/> 7645 <polygon points="26,50 38,50 32,56" fill="url(#og-dark)"/> 7646 <!-- Eyes --> 7647 <circle cx="24" cy="32" r="2" fill="#D3FA9E"/> 7648 <circle cx="40" cy="32" r="2" fill="#D3FA9E"/> 7649 <circle cx="24" cy="32" r="1" fill="#020718"/> 7650 <circle cx="40" cy="32" r="1" fill="#020718"/> 7651 </svg> 7652 </span> 7653 <div class="meta">
7654 <span class="biome"><svg viewBox="0 0 24 24"><path d="M20.5 14a9 9 0 1 1-10.5-11 7 7 0 0 0 10.5 11z"/></svg><b>Grey wolf</b> · Sanctuary + education</span> 7655 <span class="tag"><span class="dot"></span><span class="tag-text"><b class="tag-status">Active</b><span class="tag-location">California, USA</span></span></span> 7656 <span class="coord-stamp" aria-hidden="true"><span class="cs-lat">34.47°N</span><span class="cs-sep"></span><span class="cs-lon">118.20°W</span></span> 7657 <h3>A Forest Home for Rescued Wolves</h3> 7658 <div class="ngo">Wolf Connection</div> 7659 <div class="qstats"> 7660 <div class="qs"><b>$25K<em>+</em></b><span>Routed by Ecoflix</span></div> 7661 <div class="qs"><b>100<em>%</em></b><span>To the partner</span></div> 7662 </div> 7663 <a class="cta" href="/projects/a-forest-home-for-rescued-wolves/">Support this project â</a> 7664 </div> 7665 <div class="expand-panel"> 7666 <div class="ep-eyebrow">What your donation funds</div> 7667 <div class="ep-title">Lifetime care + youth leadership programmes.</div> 7668 <p class="ep-desc">Wolves rescued from captivity become ambassadors. At-risk young people learn leadership through working with them.</p> 7669 <ul class="ep-list"> 7670 <li>Feed, medical and shelter</li> 7671 <li>Wolf-assisted youth therapy</li> 7672 <li>Public education on co-existence</li> 7673 <li>Sanctuary land expansion</li> 7674 </ul> 7675 <a class="ep-cta" href="/projects/a-forest-home-for-rescued-wolves/">Open the project <span>â</span></a> 7676 </div> 7677 </article> 7678 <article class="proj-card js-tilt is-urgent" data-lat="6.0" data-lon="9.2" data-name="Saving the Cross River Gorilla" data-region="africa" data-id="saving-the-cross-river-gorilla"> 7679 <span class="status-stripe" aria-hidden="true"></span> 7680 <div class="img" style="background-image:url('/assets/projects/saving-the-cross-river-gorilla-hd.jpg')"></div> 7681 <div class="shade"></div> 7682 <div class="spotlight"></div> 7683 <span class="miniglobe" aria-label="Cross River, Cameroon"> 7684 <svg viewBox="0 0 32 32"> 7685 <circle class="globe" cx="16" cy="16" r="13"/> 7686 <path class="lat" d="M3 16 H29"/> 7687 <path class="lon" d="M16 3 Q22 16 16 29 Q10 16 16 3"/> 7688 <circle class="pin-ring" cx="22" cy="17" r="2" style="stroke:var(--coral)"/> 7689 <circle class="pin" cx="22" cy="17" r="2" style="fill:var(--coral);filter:drop-shadow(0 0 4px rgba(226,106,91,.6))"/> 7690 </svg> 7691 </span> 7692 <span class="picon-tr is-origami" aria-hidden="true" title="Forest â African Conservation Foundation"> 7693 <svg viewBox="0 0 64 64"> 7694 <!-- Origami pine tree: three faceted tiers + trunk --> 7695 <polygon points="32,4 22,20 32,18 42,20" fill="url(#og-light)"/> 7696 <polygon points="32,4 32,18 22,20" fill="url(#og-mid)" opacity=".7"/> 7697 <polygon points="32,4 32,18 42,20" fill="url(#og-dark)" opacity=".7"/> 7698 <polygon points="32,16 18,32 32,30 46,32" fill="url(#og-light)"/> 7699 <polygon points="32,16 32,30 18,32" fill="url(#og-mid)" opacity=".8"/> 7700 <polygon points="32,16 32,30 46,32" fill="url(#og-dark)" opacity=".8"/> 7701 <polygon points="32,28 12,48 32,46 52,48" fill="url(#og-light)"/> 7702 <polygon points="32,28 32,46 12,48" fill="url(#og-mid)" opacity=".85"/> 7703 <polygon points="32,28 32,46 52,48" fill="url(#og-dark)" opacity=".85"/> 7704 <!-- Trunk --> 7705 <polygon points="28,46 36,46 36,58 28,58" fill="url(#og-deep)"/> 7706 <polygon points="28,46 36,46 32,52" fill="url(#og-dark)" opacity=".6"/> 7707 </svg> 7708 </span> 7709 <div class="meta"> 7710 <span class="biome" style="background:rgba(226,106,91,.10);box-shadow:inset 0 0 0 1px rgba(226,106,91,.35)"><svg viewBox="0 0 24 24" style="color:var(--coral)"><path d="M12 2 6 10h3l-3 5h3l-3 5h12l-3-5h3l-3-5h3z"/></svg><b style="color:var(--coral)">Cross River gorilla</b> · Critically endangered</span>
7711 <span class="tag"><span class="dot"></span><span class="tag-text"><b class="tag-status">Urgent</b><span class="tag-location">Cameroon</span></span></span> 7712 <span class="coord-stamp" aria-hidden="true"><span class="cs-lat">0.79°S</span><span class="cs-sep"></span><span class="cs-lon">113.92°E</span></span> 7713 <h3>Saving the Cross River Gorilla</h3> 7714 <div class="ngo">African Conservation Foundation</div> 7715 <div class="qstats"> 7716 <div class="qs"><b><300<em></em></b><span>Left in the wild</span></div> 7717 <div class="qs"><b>100<em>%</em></b><span>To the partner</span></div> 7718 </div> 7719 <a class="cta" href="/projects/saving-the-cross-river-gorilla/">Support this project â</a> 7720 </div> 7721 <div class="expand-panel"> 7722 <div class="ep-eyebrow">What your donation funds</div> 7723 <div class="ep-title">Community-led protection for the rarest gorilla on Earth.</div> 7724 <p class="ep-desc">Fewer than 300 Cross River gorillas remain. The African Conservation Foundation rallies communities across Cameroon to protect them.</p> 7725 <ul class="ep-list"> 7726 <li>Community ranger patrols</li> 7727 <li>Habitat protection and corridors</li> 7728 <li>Local livelihoods and education</li> 7729 <li>Population monitoring</li> 7730 </ul> 7731 <a class="ep-cta" href="/projects/saving-the-cross-river-gorilla/">Open the project <span>â</span></a> 7732 </div> 7733 </article> 7734 <article class="proj-card js-tilt" data-lat="27.18" data-lon="78.02" data-name="Freedom for India's Bears & Elephants" data-region="asia" data-id="freedom-for-indias-bears-and-elephants"> 7735 <span class="status-stripe" aria-hidden="true"></span> 7736 <div class="img" style="background-image:url('/assets/projects/freedom-for-indias-bears-and-elephants-hd.jpg')"></div> 7737 <div class="shade"></div> 7738 <div class="spotlight"></div> 7739 <span class="miniglobe" aria-label="Agra, India"> 7740 <svg viewBox="0 0 32 32"> 7741 <circle class="globe" cx="16" cy="16" r="13"/> 7742 <path class="lat" d="M3 16 H29"/> 7743 <path class="lon" d="M16 3 Q22 16 16 29 Q10 16 16 3"/> 7744 <circle class="pin-ring" cx="10" cy="11" r="2"/> 7745 <circle class="pin" cx="10" cy="11" r="2"/> 7746 </svg> 7747 </span> 7748 <span class="picon-tr is-origami" aria-hidden="true" title="Bear â Wildlife SOS"> 7749 <svg viewBox="0 0 64 64"> 7750 <!-- Origami bear: two ears, head, snout --> 7751 <polygon points="10,12 18,8 22,18 14,22" fill="url(#og-light)"/> 7752 <polygon points="10,12 18,8 14,16" fill="url(#og-mid)" opacity=".75"/> 7753 <polygon points="54,12 46,8 42,18 50,22" fill="url(#og-light)"/> 7754 <polygon points="54,12 46,8 50,16" fill="url(#og-mid)" opacity=".75"/> 7755 <!-- Head main --> 7756 <polygon points="14,20 32,14 50,20 54,40 48,52 32,56 16,52 10,40" fill="url(#og-mid)"/> 7757 <polygon points="32,14 50,20 54,40 38,32" fill="url(#og-light)" opacity=".7"/> 7758 <polygon points="32,14 14,20 10,40 26,32" fill="url(#og-dark)" opacity=".8"/> 7759 <!-- Snout --> 7760 <polygon points="22,36 42,36 44,48 20,48" fill="url(#og-deep)"/> 7761 <polygon points="22,36 32,42 20,48" fill="url(#og-dark)"/> 7762 <polygon points="42,36 32,42 44,48" fill="url(#og-dark)" opacity=".6"/> 7763 <!-- Eyes + nose --> 7764 <circle cx="22" cy="30" r="1.6" fill="#020718"/> 7765 <circle cx="42" cy="30" r="1.6" fill="#020718"/> 7766 <polygon points="30,40 34,40 32,44" fill="#020718"/> 7767 </svg> 7768 </span> 7769 <div class="meta"> 7770 <span class="biome"><svg viewBox="0 0 24 24"><circle cx="8" cy="9" r="3"/><circle cx="16" cy="9" r="3"/><path d="M5 16c0-4 3-6 7-6s7 2 7 6c0 3-3 5-7 5s-7-2-7-5z"/></svg><b>Sloth bear</b> · Rescue & sanctuary</span> 7771 <span class="tag"><span class="dot"></span><span class="tag-text"><b class="tag-status">Active</b><span class="tag-location">Agra, India</span></span></span>
7772 <span class="coord-stamp" aria-hidden="true"><span class="cs-lat">27.18°N</span><span class="cs-sep"></span><span class="cs-lon">78.02°E</span></span> 7773 <h3>Freedom for India's Bears & Elephants</h3> 7774 <div class="ngo">Wildlife SOS</div> 7775 <div class="qstats"> 7776 <div class="qs"><b>$10K<em>+</em></b><span>Routed by Ecoflix</span></div> 7777 <div class="qs"><b>100<em>%</em></b><span>To the partner</span></div> 7778 </div> 7779 <a class="cta" href="/projects/freedom-for-indias-bears-and-elephants/">Support this project â</a> 7780 </div> 7781 <div class="expand-panel"> 7782 <div class="ep-eyebrow">What your donation funds</div> 7783 <div class="ep-title">A life of dignity for rescued bears and elephants.</div> 7784 <p class="ep-desc">Wildlife SOS runs the world's largest sloth-bear rescue centre and gives abused elephants and leopards a refuge in India.</p> 7785 <ul class="ep-list"> 7786 <li>Daily care and veterinary support</li> 7787 <li>Rescue operations across India</li> 7788 <li>Sanctuary and enclosure upkeep</li> 7789 <li>Community anti-poaching work</li> 7790 </ul> 7791 <a class="ep-cta" href="/projects/freedom-for-indias-bears-and-elephants/">Open the project <span>â</span></a> 7792 </div> 7793 </article> 7794 <article class="proj-card js-tilt" data-lat="45.18" data-lon="-61.78" data-name="Building North America's First Whale Sanctuary" data-region="americas" data-id="building-north-americas-first-whale-sanctuary"> 7795 <span class="status-stripe" aria-hidden="true"></span> 7796 <div class="img" style="background-image:url('/assets/projects/building-north-americas-first-whale-sanctuary-hd.jpg')"></div> 7797 <div class="shade"></div> 7798 <div class="spotlight"></div> 7799 <span class="miniglobe" aria-label="Port Hilford Bay, Nova Scotia, Canada"> 7800 <svg viewBox="0 0 32 32"> 7801 <circle class="globe" cx="16" cy="16" r="13"/> 7802 <path class="lat" d="M3 16 H29"/> 7803 <path class="lon" d="M16 3 Q22 16 16 29 Q10 16 16 3"/> 7804 <circle class="pin-ring" cx="11" cy="18" r="1.5"/> 7805 <circle class="pin" cx="11" cy="18" r="1.5"/> 7806 <circle class="pin-ring" cx="21" cy="14" r="1.5" style="animation-delay:.8s"/> 7807 <circle class="pin" cx="21" cy="14" r="1.5"/> 7808 <circle class="pin-ring" cx="17" cy="22" r="1.5" style="animation-delay:1.6s"/> 7809 <circle class="pin" cx="17" cy="22" r="1.5"/> 7810 </svg> 7811 </span> 7812 <span class="picon-tr is-origami" aria-hidden="true" title="Whale â The Whale Sanctuary Project"> 7813 <svg viewBox="0 0 64 64"> 7814 <!-- Origami orca / whale: body, head, fluke tail --> 7815 <polygon points="4,30 16,18 36,16 50,24 56,32 50,40 36,46 16,44 4,34" fill="url(#og-mid)"/> 7816 <polygon points="16,18 36,16 50,24 36,28 22,26" fill="url(#og-light)" opacity=".8"/> 7817 <polygon points="4,30 22,26 16,44 4,34" fill="url(#og-dark)" opacity=".85"/> 7818 <polygon points="50,24 56,32 50,40 36,38" fill="url(#og-dark)" opacity=".7"/> 7819 <!-- Belly patch (orca-style) --> 7820 <polygon points="22,32 36,32 32,42 24,42" fill="url(#og-light)" opacity=".8"/> 7821 <!-- Fluke / tail --> 7822 <polygon points="56,32 62,22 60,32 62,42" fill="url(#og-mid)"/> 7823 <polygon points="56,32 62,22 60,32" fill="url(#og-light)" opacity=".8"/> 7824 <polygon points="56,32 60,32 62,42" fill="url(#og-dark)"/> 7825 <!-- Dorsal --> 7826 <polygon points="36,16 40,8 44,16" fill="url(#og-deep)"/> 7827 <!-- Eye --> 7828 <circle cx="14" cy="28" r="1.6" fill="#D3FA9E"/> 7829 <circle cx="14" cy="28" r="0.8" fill="#020718"/> 7830 </svg> 7831 </span> 7832 <div class="meta"> 7833 <span class="biome"><svg viewBox="0 0 24 24"><path d="M2 12c4-7 16-7 20 0M2 16c4-7 16-7 20 0M2 8c4-7 16-7 20 0"/></svg><b>Whales & belugas</b> · Seaside sanctuary</span>
7834 <span class="tag"><span class="dot"></span><span class="tag-text"><b class="tag-status">Active</b><span class="tag-location">Nova Scotia, Canada</span></span></span> 7835 <span class="coord-stamp" aria-hidden="true"><span class="cs-lat">45.18°N</span><span class="cs-sep"></span><span class="cs-lon">61.78°W</span></span> 7836 <h3>Building North America's First Whale Sanctuary</h3> 7837 <div class="ngo">The Whale Sanctuary Project</div> 7838 <div class="qstats"> 7839 <div class="qs"><b>$25K<em>+</em></b><span>Routed by Ecoflix</span></div> 7840 <div class="qs"><b>100<em>%</em></b><span>To the partner</span></div> 7841 </div> 7842 <a class="cta" href="/projects/building-north-americas-first-whale-sanctuary/">Support this project â</a> 7843 </div> 7844 <div class="expand-panel"> 7845 <div class="ep-eyebrow">What your donation funds</div> 7846 <div class="ep-title">North America's first seaside sanctuary for whales.</div> 7847 <p class="ep-desc">A netted stretch of open ocean in Nova Scotia where orcas and belugas retired from tanks can finally live in the sea.</p> 7848 <ul class="ep-list"> 7849 <li>Sanctuary netting and infrastructure</li> 7850 <li>Marine-mammal veterinary care</li> 7851 <li>Site operations and monitoring</li> 7852 <li>Retirement of captive cetaceans</li> 7853 </ul> 7854 <a class="ep-cta" href="/projects/building-north-americas-first-whale-sanctuary/">Open the project <span>â</span></a> 7855 </div> 7856 </article> 7857 <article class="proj-card js-tilt" data-lat="-2.15" data-lon="34.69" data-name="Frontline Support for Africa's Wildlife" data-region="africa" data-id="frontline-support-for-africas-wildlife"> 7858 <span class="status-stripe" aria-hidden="true"></span> 7859 <div class="img" style="background-image:url('/assets/projects/frontline-support-for-africas-wildlife-hd.jpg')"></div> 7860 <div class="shade"></div> 7861 <div class="spotlight"></div> 7862 <span class="miniglobe" aria-label="Africa"> 7863 <svg viewBox="0 0 32 32"> 7864 <circle class="globe" cx="16" cy="16" r="13"/> 7865 <path class="lat" d="M3 16 H29"/> 7866 <path class="lon" d="M16 3 Q22 16 16 29 Q10 16 16 3"/> 7867 <circle class="pin-ring" cx="18" cy="18" r="2"/> 7868 <circle class="pin" cx="18" cy="18" r="2"/> 7869 </svg> 7870 </span> 7871 <span class="picon-tr is-origami" aria-hidden="true" title="Lion â Over and Above Africa"> 7872 <svg viewBox="0 0 64 64"> 7873 <!-- Origami lion: starburst mane around faceted face --> 7874 <!-- Mane points (8 petals around the face) --> 7875 <polygon points="32,2 36,12 28,12" fill="url(#og-mid)"/> 7876 <polygon points="54,8 50,18 44,12" fill="url(#og-mid)"/> 7877 <polygon points="62,32 52,36 52,28" fill="url(#og-mid)"/> 7878 <polygon points="54,56 44,52 50,46" fill="url(#og-mid)"/> 7879 <polygon points="32,62 28,52 36,52" fill="url(#og-mid)"/> 7880 <polygon points="10,56 20,52 14,46" fill="url(#og-mid)"/> 7881 <polygon points="2,32 12,28 12,36" fill="url(#og-mid)"/> 7882 <polygon points="10,8 14,18 20,12" fill="url(#og-mid)"/> 7883 <!-- Mane disc --> 7884 <polygon points="32,8 52,18 56,32 50,50 32,56 14,50 8,32 12,18" fill="url(#og-dark)"/> 7885 <polygon points="32,8 52,18 56,32 38,28" fill="url(#og-mid)" opacity=".55"/> 7886 <polygon points="32,8 12,18 8,32 26,28" fill="url(#og-deep)" opacity=".7"/> 7887 <!-- Face --> 7888 <polygon points="20,22 32,18 44,22 46,38 38,48 26,48 18,38" fill="url(#og-light)"/> 7889 <polygon points="32,18 44,22 46,38 36,32" fill="url(#og-mid)" opacity=".7"/> 7890 <polygon points="32,18 20,22 18,38 28,32" fill="url(#og-mid)" opacity=".5"/> 7891 <!-- Snout --> 7892 <polygon points="26,36 38,36 36,44 28,44" fill="url(#og-deep)"/> 7893 <polygon points="28,44 36,44 32,48" fill="url(#og-dark)"/> 7894 <!-- Eyes + nose --> 7895 <circle cx="26" cy="30" r="1.6" fill="#020718"/> 7896 <circle cx="38" cy="30" r="1.6" fill="#020718"/> 7897 <polygon points="30,38 34,38 32,42" fill="#020718"/> 7898 </svg> 7899 </span> 7900 <div class="meta">
7901 <span class="biome"><svg viewBox="0 0 24 24"><path d="M12 2l2 5 5 1-4 4 1 5-4-3-4 3 1-5-4-4 5-1z"/></svg><b>African savanna</b> · Frontline protection</span> 7902 <span class="tag"><span class="dot"></span><span class="tag-text"><b class="tag-status">Active</b><span class="tag-location">Africa</span></span></span> 7903 <span class="coord-stamp" aria-hidden="true"><span class="cs-lat">1.50°S</span><span class="cs-sep"></span><span class="cs-lon">35.14°E</span></span> 7904 <h3>Frontline Support for Africa's Wildlife</h3> 7905 <div class="ngo">Over and Above Africa</div> 7906 <div class="qstats"> 7907 <div class="qs"><b>$1K<em>+</em></b><span>Routed by Ecoflix</span></div> 7908 <div class="qs"><b>100<em>%</em></b><span>To the partner</span></div> 7909 </div> 7910 <a class="cta" href="/projects/frontline-support-for-africas-wildlife/">Support this project â</a> 7911 </div> 7912 <div class="expand-panel"> 7913 <div class="ep-eyebrow">What your donation funds</div> 7914 <div class="ep-title">Boots, kit, fuel and salaries for frontline rangers.</div> 7915 <p class="ep-desc">Over and Above Africa funds the small, frontline projects that protect Africa's wildlife and the communities who live alongside them.</p> 7916 <ul class="ep-list"> 7917 <li>Ranger training and gear</li> 7918 <li>Family stipends + medical cover</li> 7919 <li>Anti-poaching vehicles + fuel</li> 7920 <li>Camera-trap and patrol networks</li> 7921 </ul> 7922 <a class="ep-cta" href="/projects/frontline-support-for-africas-wildlife/">Open the project <span>â</span></a> 7923 </div> 7924 </article> 7925 </div><!-- /.pcs-stage --> 7926 7927 <div class="pcs-controls"> 7928 <button class="pcs-btn pcs-btn-prev" type="button" aria-label="Previous project"> 7929 <svg viewBox="0 0 24 24"><path d="M15 18l-6-6 6-6"/></svg> 7930 </button> 7931 <div class="pcs-counter" id="hpPcsCounter"><b>01</b> / 06</div> 7932 <div class="pcs-dots" id="hpPcsDots"></div> 7933 <button class="pcs-btn pcs-btn-next" type="button" aria-label="Next project"> 7934 <svg viewBox="0 0 24 24"><path d="M9 18l6-6-6-6"/></svg> 7935 </button> 7936 </div> 7937 7938 <!-- Bottom-of-section CTA â same prominence as the top CTA, so a 7939 visitor scrolling past the carousel always has a clear next 7940 step without having to click any individual fan-stack card. --> 7941 <div class="hp-projects-foot"> 7942 <a class="btn btn-primary hp-see-all-cta hp-see-all-cta--center" href="/projects/"> 7943 Show me all <span data-livestat="projects">34</span> projects 7944 <span class="arrow" aria-hidden="true">â</span> 7945 </a> 7946 <p class="hp-projects-foot-note"> 7947 Browse every active project on one page · filter by region or species · 100% pass-through 7948 </p> 7949 </div> 7950 7951 </div><!-- /.pcs-wrap --> 7952 </div> 7953 </div> 7954</section> 7955</div><!-- /.pin-stack watch-changeâprojects --> 7956 7957<!-- ================================================= 7958 INTERSTITIAL DONATE BAND â cinematic full-bleed prompt 7959 between the featured-projects carousel and the world map. 7960 Full-bleed nature photo behind, big bold italic centred 7961 headline, leaf coord stamp underneath, amount-preview tiles 7962 and a primary + ghost CTA. Same cinema-band pattern the 7963 user signed off on throughout the site. 7964 ================================================= --> 7965<section class="hp-give-band" aria-label="Pick a project and fund it"> 7966 <!-- Looping ambient video background. muted + playsinline so it 7967 autoplays on mobile; preload=metadata keeps initial payload 7968 light. Poster (Unsplash, free commercial license) covers 7969 first-paint before the video buffers. --> 7970 <video class="hgb-video" autoplay muted loop playsinline preload="metadata" 7971 poster="https://images.unsplash.com/photo-1547036967-23d11aacaee0?w=1600&q=70&auto=format&fit=crop" 7972 aria-hidden="true"> 7973 <source src="/assets/scroll.mp4" type="video/mp4" /> 7974 </video> 7975 <div class="hgb-overlay" aria-hidden="true"></div> 7976 <div class="bg-cartograph hgb-cart" aria-hidden="true"><svg viewBox="0 0 1600 600" preserveAspectRatio="xMidYMid slice"></svg></div> 7977 7978 <div class="wrap" style="position:relative;z-index:3"> 7979 <div class="hgb-inner reveal">
7980 <span class="hgb-eyebrow"><span class="hgb-dot"></span>Pick one. Fund it.</span> 7981 <h2 class="hgb-h">Every project here<br/><em>needs you this week.</em></h2> 7982 <div class="hgb-coord" aria-hidden="true">â Live · <span data-livestat="projects">34</span> projects · 6 continents</div> 7983 7984 <!-- Amount-preview tiles. Each is a single-line "what it 7985 funds" tease at four price-points, drawn so the 7986 magnitude of giving is visible BEFORE the slider. --> 7987 <div class="hgb-tiles"> 7988 <a class="hgb-tile" href="/donate/?amount=50"> 7989 <span class="hgb-tile-amount" data-money="50">$50</span> 7990 <span class="hgb-tile-line">A day on the ground</span> 7991 </a> 7992 <a class="hgb-tile" href="/donate/?amount=250"> 7993 <span class="hgb-tile-amount" data-money="250">$250</span> 7994 <span class="hgb-tile-line">A ranger's week</span> 7995 </a> 7996 <a class="hgb-tile" href="/donate/?amount=500"> 7997 <span class="hgb-tile-amount" data-money="500">$500</span> 7998 <span class="hgb-tile-line">A sanctuary fortnight</span> 7999 </a> 8000 <a class="hgb-tile" href="/donate/?amount=1000"> 8001 <span class="hgb-tile-amount" data-money="1000">$1,000</span> 8002 <span class="hgb-tile-line">A full rescue</span> 8003 </a> 8004 </div> 8005 8006 <div class="hgb-actions"> 8007 <a class="btn btn-primary hgb-cta" href="/donate/">Donate now <span class="arrow">â</span></a> 8008 <a class="btn btn-ghost" href="/circle-of-giving/">Or give monthly</a> 8009 </div> 8010 <span class="hgb-foot"><span class="hgb-dot"></span>100% reaches the field. We take nothing.</span> 8011 </div> 8012 </div> 8013</section> 8014<style> 8015 /* Cinematic interstitial donate band â sits between the 8016 projects carousel and the globe section. */ 8017 .hp-give-band{ 8018 position:relative;padding:120px var(--pad-x) 110px; 8019 overflow:hidden;isolation:isolate; 8020 text-align:center; 8021 /* min-height makes the band feel like a hero moment */ 8022 min-height:560px;display:flex;align-items:center; 8023 } 8024 /* Full-bleed video layer â replaces the static photo. object-fit 8025 cover so the video always fills the band edge-to-edge regardless 8026 of intrinsic aspect ratio. Slight saturate+contrast bump to 8027 match the original photo tonality. */ 8028 .hp-give-band .hgb-video{ 8029 position:absolute;inset:0;z-index:0;pointer-events:none; 8030 width:100%;height:100%;object-fit:cover;object-position:center; 8031 filter:saturate(1.05) contrast(1.05); 8032 } 8033 @media (max-width:880px){ 8034 .hp-give-band{ padding:80px var(--pad-x);min-height:480px } 8035 } 8036 /* Dark gradient overlay â heavier in the band's centre where the 8037 headline sits so we don't need a text-shadow on the type. 8038 Heavy stacked text-shadows produce an ugly smear behind type 8039 and must never be used anywhere on the site. The overlay 8040 handles legibility instead. */ 8041 .hp-give-band .hgb-overlay{ 8042 position:absolute;inset:0;z-index:1;pointer-events:none; 8043 background: 8044 radial-gradient(70% 70% at 50% 55%, rgba(2,7,24,.22), transparent 70%), 8045 radial-gradient(60% 60% at 50% 50%, rgba(168,243,65,.04), transparent 70%), 8046 linear-gradient(180deg, rgba(2,7,24,.22) 0%, rgba(2,7,24,.22) 50%, rgba(2,7,24,.36) 100%); 8047 } 8048 .hp-give-band .hgb-cart{ position:absolute;inset:0;z-index:2;pointer-events:none;opacity:.5 } 8049 8050 .hp-give-band .hgb-inner{ 8051 position:relative;z-index:3; 8052 max-width:880px;margin:0 auto; 8053 display:flex;flex-direction:column;align-items:center;gap:0; 8054 } 8055 8056 .hgb-eyebrow{ 8057 display:inline-flex;align-items:center;gap:10px; 8058 padding:6px 14px;border-radius:99px; 8059 background:rgba(2,7,24,.55);border:1px solid rgba(168,243,65,.45); 8060 font-family:var(--display);font-weight:800; 8061 font-size:11px;letter-spacing:.26em;text-transform:uppercase; 8062 color:var(--leaf);margin-bottom:24px; 8063 backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px); 8064 } 8065 .hgb-eyebrow .hgb-dot{ 8066 width:6px;height:6px;border-radius:50%; 8067 background:var(--leaf);box-shadow:0 0 8px var(--leaf-glow); 8068 animation:hgbPulse 1.8s ease-in-out infinite; 8069 } 8070 @keyframes hgbPulse{0%,100%{transform:scale(1);opacity:1}50%{transform:scale(1.4);opacity:.65}} 8071 8072 .hgb-h{ 8073 font-family:var(--display);font-weight:800;font-style:italic; 8074 font-size:clamp(40px,6.4vw,84px); 8075 line-height:1;letter-spacing:-.025em; 8076 color:var(--bone);margin:0 0 22px; 8077 /* No text-shadow. The .hgb-overlay radial darkens the centre 8078 enough for legibility â stacked drop shadows on type are 8079 banned site-wide. */ 8080 } 8081 .hgb-h em{ 8082 font-style:italic;font-weight:500; 8083 8084 8085 color:var(--leaf);-webkit-text-fill-color:var(--leaf); 8086 8087 } 8088 .hgb-coord{ 8089 font-family:var(--body);font-weight:700; 8090 font-size:11px;letter-spacing:.26em;text-transform:uppercase; 8091 color:var(--leaf);margin-bottom:36px; 8092 } 8093 8094 /* Amount preview tiles â visible before the slider/donate page */ 8095 .hgb-tiles{ 8096 display:grid;grid-template-columns:repeat(4,1fr); 8097 gap:10px;width:100%;max-width:720px; 8098 margin:0 auto 32px; 8099 } 8100 @media (max-width:680px){ 8101 .hgb-tiles{grid-template-columns:repeat(2,1fr)} 8102 } 8103 .hgb-tile{ 8104 display:flex;flex-direction:column;align-items:center;gap:4px; 8105 padding:18px 12px 16px; 8106 background:rgba(2,7,24,.55); 8107 border:1px solid rgba(168,243,65,.32); 8108 border-radius:14px; 8109 text-decoration:none;color:var(--bone); 8110 backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px); 8111 transition:transform .25s cubic-bezier(.2,.7,.2,1), border-color .25s, background .25s, box-shadow .3s; 8112 } 8113 .hgb-tile:hover{ 8114 transform:translateY(-3px); 8115 border-color:var(--leaf); 8116 background:rgba(2,7,24,.75); 8117 box-shadow:0 14px 30px -10px rgba(168,243,65,.35); 8118 } 8119 .hgb-tile-amount{ 8120 font-family:var(--display);font-weight:800; 8121 font-size:28px;letter-spacing:-.02em;color:var(--leaf); 8122 font-variant-numeric:tabular-nums; 8123 line-height:1; 8124 } 8125 .hgb-tile-line{ 8126 font-family:var(--display);font-weight:600; 8127 font-size:11px;letter-spacing:.16em;text-transform:uppercase;
8128 color:var(--mist); 8129 } 8130 .hgb-tile:hover .hgb-tile-line{ color:var(--bone) } 8131 8132 .hgb-actions{ 8133 display:inline-flex;flex-wrap:wrap;align-items:center;justify-content:center; 8134 gap:14px;margin-bottom:20px; 8135 } 8136 .hgb-cta{ 8137 padding:14px 22px !important; 8138 font-size:15px !important; 8139 box-shadow:0 12px 30px -8px rgba(168,243,65,.55), 8140 0 4px 14px rgba(0,0,0,.4); 8141 } 8142 8143 .hgb-foot{ 8144 display:inline-flex;align-items:center;gap:8px; 8145 font-family:var(--display);font-weight:800; 8146 font-size:11px;letter-spacing:.22em;text-transform:uppercase; 8147 color:var(--bone); 8148 } 8149 .hgb-foot .hgb-dot{ 8150 width:5px;height:5px;border-radius:50%; 8151 background:var(--leaf);box-shadow:0 0 6px var(--leaf-glow); 8152 animation:none; 8153 } 8154 8155 @media (prefers-reduced-motion:reduce){ 8156 /* Hide the looping video and fall back to the poster image â 8157 users who've opted out of motion shouldn't see autoplay. */ 8158 .hp-give-band .hgb-video{display:none} 8159 .hp-give-band{ 8160 background-image:url('https://images.unsplash.com/photo-1547036967-23d11aacaee0?w=1600&q=70&auto=format&fit=crop'); 8161 background-size:cover;background-position:center; 8162 } 8163 .hgb-eyebrow .hgb-dot{animation:none} 8164 .hgb-h em{animation:none} 8165 .hgb-tile{transition:none} 8166 } 8167</style> 8168 8169<!-- ================================================= 8170 WORLD MAP â "Where the work happens" 8171 Stylised continents (not GIS-accurate) + 24 project pins. 8172 Replace with a real geographic SVG (Natural Earth, etc.) post-launch 8173 if you want cartographic precision. 8174 ================================================= --> 8175<section class="globe-section section-lift" id="globe"> 8176 <div class="wrap"> 8177 <div class="s-head reveal" style="text-align:center;margin-left:auto;margin-right:auto;margin-bottom:0"> 8178 <span class="eyebrow" style="margin:0 auto">The map</span> 8179 <div class="row" style="justify-content:center"><h2 class="reveal-words" style="margin:0 auto">Where the work <em>actually happens.</em></h2></div> 8180 <p style="margin:18px auto 0"><span data-livestat="projects">34</span> projects, <span data-livestat="ngos">64</span> partner NGOs, 6 continents. Every pin is a place where your donation lands.</p> 8181 </div> 8182 8183 <div class="globe-stage"> 8184 <div class="globe-wrap reveal is-3d" id="globeWrap"> 8185 <!-- 3D Three.js globe â auto-rotates, drag to spin, hover pin for label, click for popup --> 8186 <canvas class="globe-canvas" id="globe3d" aria-label="Interactive 3D map of partner NGO project locations"></canvas> 8187 <div class="globe-tooltip" id="globe3dTooltip" role="status" aria-hidden="true"></div> 8188 <!-- Tactical digital scan effect â leading edge sweeps leftâright --> 8189 <div class="globe-scan" aria-hidden="true"> 8190 <div class="globe-scan-tail"></div> 8191 <div class="globe-scan-line"></div> 8192 </div> 8193 <div class="globe-scan-flicker" aria-hidden="true"></div> 8194 <div class="globe-scan-status" aria-hidden="true"> 8195 <span class="gs-dot"></span> 8196 <span class="gs-label">SCANNING</span> 8197 <span class="gs-sep">·</span> 8198 <span class="gs-val">64 PARTNERS</span> 8199 </div> 8200 <svg class="globe-svg" viewBox="0 0 1000 500" preserveAspectRatio="xMidYMid meet" aria-hidden="true"> 8201 <!-- Latitude reference lines --> 8202 <line class="lat-line" x1="0" y1="125" x2="1000" y2="125"/> 8203 <line class="lat-line" x1="0" y1="250" x2="1000" y2="250"/> 8204 <line class="lat-line" x1="0" y1="375" x2="1000" y2="375"/> 8205 <!-- Simplified continent silhouettes --> 8206 <!-- North America -->
8207 <path class="continent" d="M 90 90 L 170 80 L 240 95 L 285 130 L 300 175 L 285 215 L 235 225 L 195 215 L 140 200 L 105 165 L 85 130 Z"/> 8208 <!-- Greenland --> 8209 <path class="continent" d="M 310 70 L 365 65 L 395 85 L 395 130 L 360 135 L 315 115 Z"/> 8210 <!-- Central America --> 8211 <path class="continent" d="M 240 225 L 270 215 L 285 240 L 270 260 L 245 250 Z"/> 8212 <!-- South America --> 8213 <path class="continent" d="M 270 260 L 320 255 L 345 290 L 340 345 L 320 410 L 285 440 L 265 430 L 255 380 L 260 315 Z"/> 8214 <!-- Europe --> 8215 <path class="continent" d="M 460 95 L 530 90 L 555 105 L 555 145 L 510 165 L 470 160 L 450 130 Z"/> 8216 <!-- Africa --> 8217 <path class="continent" d="M 475 175 L 555 175 L 590 215 L 600 275 L 580 335 L 545 370 L 510 360 L 480 315 L 470 255 L 465 210 Z"/> 8218 <!-- Middle East --> 8219 <path class="continent" d="M 560 155 L 615 160 L 625 200 L 605 220 L 565 215 Z"/> 8220 <!-- Asia --> 8221 <path class="continent" d="M 555 80 L 700 80 L 800 100 L 850 130 L 830 175 L 770 200 L 720 215 L 660 215 L 625 195 L 615 160 L 610 120 L 575 100 Z"/> 8222 <!-- Southeast Asia / India --> 8223 <path class="continent" d="M 690 215 L 740 215 L 765 245 L 750 270 L 720 270 L 695 250 Z"/> 8224 <!-- Indonesia / Philippines --> 8225 <path class="continent" d="M 780 270 L 850 270 L 870 285 L 855 305 L 800 305 L 780 290 Z"/> 8226 <!-- Japan --> 8227 <path class="continent" d="M 860 155 L 885 150 L 895 185 L 875 195 L 855 175 Z"/> 8228 <!-- Australia --> 8229 <path class="continent" d="M 790 320 L 870 320 L 895 345 L 880 380 L 830 385 L 790 375 L 775 350 Z"/> 8230 <!-- New Zealand --> 8231 <path class="continent" d="M 910 385 L 935 390 L 935 410 L 915 415 Z"/> 8232 <!-- Antarctica strip --> 8233 <path class="continent" d="M 120 460 L 880 460 L 900 480 L 110 480 Z" style="opacity:.5"/> 8234 </svg> 8235 8236 <!-- 8237 Animated connection arcs â flowing dashed lines between featured 8238 project pins. Coordinates roughly match the .pin left/top % so 8239 the arcs trace migration-style paths between the locations. 8240 --> 8241 <svg class="globe-arcs" viewBox="0 0 1000 500" preserveAspectRatio="none" aria-hidden="true"> 8242 <!-- Wolf Connection (CA) â Elephant Nature Park (Thailand) --> 8243 <path d="M 200 195 Q 500 50 755 275"/> 8244 <!-- Going Wild (Kenya) â Elephant Nature Park (Thailand) --> 8245 <path d="M 555 260 Q 660 200 755 275"/> 8246 <!-- Going Wild (Kenya) â The Last Stand (Indonesia) --> 8247 <path d="M 555 260 Q 690 380 820 290"/> 8248 <!-- Elephant Nature Park â The Last Stand --> 8249 <path d="M 755 275 Q 790 320 820 290"/> 8250 </svg> 8251 8252 <!-- 8253 Project pins. Each is a button that opens .map-popup with its data. 8254 Positions are approximate, mapped from lat/lon onto the stylised map 8255 (lon -180..180 â 0..100%, lat 90..-90 â 0..100%). 8256 data-* attributes populate the popup on click. 8257 --> 8258 8259 8260 <button class="pin" type="button" 8261 data-name="The Orangutan Project" 8262 data-ngo="Orangutan protection" 8263 data-where="Indonesia (Borneo & Sumatra)" 8264 data-coords="0.50°S · 102.00°E" 8265 data-status="active" 8266 data-stat="" 8267 data-desc="Protecting wild orangutans and their rainforest habitat across Borneo and Sumatra." 8268 data-img="/assets/ngo/the-orangutan-project/hero-hd.jpg" 8269 data-href="/ngo/the-orangutan-project/"> 8270 <span class="pin-dot"></span><span class="pin-label">The Orangutan Project</span> 8271 </button> 8272 <button class="pin" type="button" 8273 data-name="Friends of Bonobos" 8274 data-ngo="Bonobo rescue & rewilding" 8275 data-where="DR Congo / USA" 8276 data-coords="4.32°S · 15.31°E" 8277 data-status="active" 8278 data-stat="" 8279 data-desc="Rescuing orphaned bonobos and protecting their forests in the DR Congo." 8280 data-img="/assets/ngo/friends-of-bonobos/hero-hd.jpg" 8281 data-href="/ngo/friends-of-bonobos/">
8282 <span class="pin-dot"></span><span class="pin-label">Friends of Bonobos</span> 8283 </button> 8284 <button class="pin" type="button" 8285 data-name="Leap for Lucy" 8286 data-ngo="Captive elephant advocacy" 8287 data-where="Canada (Edmonton)" 8288 data-coords="53.55°N · 113.49°W" 8289 data-status="active" 8290 data-stat="" 8291 data-desc="Advocating for Lucy, a lone elephant in Edmonton, and captive elephant welfare." 8292 data-img="/assets/ngo/leap-for-lucy/hero-hd.jpg" 8293 data-href="/ngo/leap-for-lucy/"> 8294 <span class="pin-dot"></span><span class="pin-label">Leap for Lucy</span> 8295 </button> 8296 <button class="pin" type="button" 8297 data-name="Free All Captive Elephants" 8298 data-ngo="Captive elephant freedom" 8299 data-where="USA (North America)" 8300 data-coords="34.05°N · 118.24°W" 8301 data-status="active" 8302 data-stat="" 8303 data-desc="Campaigning to release elephants from captivity into sanctuary." 8304 data-img="/assets/ngo/free-all-captive-elephants/hero-hd.jpg" 8305 data-href="/ngo/free-all-captive-elephants/"> 8306 <span class="pin-dot"></span><span class="pin-label">Free All Captive Elephants</span> 8307 </button> 8308 <button class="pin" type="button" 8309 data-name="Alaqua Animal Refuge" 8310 data-ngo="Animal rescue & sanctuary" 8311 data-where="USA (Florida)" 8312 data-coords="30.50°N · 86.13°W" 8313 data-status="active" 8314 data-stat="" 8315 data-desc="A no-kill refuge in Florida rescuing and rehoming abused and neglected animals." 8316 data-img="/assets/ngo/alaqua-animal-refuge/hero-hd.jpg" 8317 data-href="/ngo/alaqua-animal-refuge/"> 8318 <span class="pin-dot"></span><span class="pin-label">Alaqua Animal Refuge</span> 8319 </button> 8320 <button class="pin" type="button" 8321 data-name="Amazon Watch" 8322 data-ngo="Indigenous-led protection" 8323 data-where="Amazon Basin (South America)" 8324 data-coords="3.47°S · 62.22°W" 8325 data-status="active" 8326 data-stat="" 8327 data-desc="Defending the rights of Indigenous peoples and the Amazon against industrial destruction." 8328 data-img="/assets/ngo/amazon-watch/hero-hd.jpg" 8329 data-href="/ngo/amazon-watch/"> 8330 <span class="pin-dot"></span><span class="pin-label">Amazon Watch</span> 8331 </button> 8332 <button class="pin" type="button" 8333 data-name="Gibbon Conservation Society" 8334 data-ngo="Gibbon conservation" 8335 data-where="Malaysia" 8336 data-coords="3.14°N · 101.69°E" 8337 data-status="active" 8338 data-stat="" 8339 data-desc="Protecting Malaysiaâs wild gibbons through research, rescue and habitat protection." 8340 data-img="/assets/ngo/gibbon-conservation-society/hero-hd.jpg" 8341 data-href="/ngo/gibbon-conservation-society/"> 8342 <span class="pin-dot"></span><span class="pin-label">Gibbon Conservation Society</span> 8343 </button> 8344 <button class="pin" type="button" 8345 data-name="Whale Sanctuary" 8346 data-ngo="Whale & dolphin sanctuary" 8347 data-where="Port Hilford Bay, Nova Scotia, Canada / Global" 8348 data-coords="45.18°N · 61.78°W" 8349 data-status="active" 8350 data-stat="" 8351 data-desc="Creating a seaside sanctuary for whales and dolphins retired from captivity." 8352 data-img="/assets/ngo/whale-sanctuary/hero-hd.jpg" 8353 data-href="/ngo/whale-sanctuary/"> 8354 <span class="pin-dot"></span><span class="pin-label">Whale Sanctuary</span> 8355 </button> 8356 <button class="pin" type="button" 8357 data-name="Wild For Life Foundation" 8358 data-ngo="Equine & wildlife rescue" 8359 data-where="USA" 8360 data-coords="34.39°N · 118.54°W" 8361 data-status="active" 8362 data-stat="" 8363 data-desc="Rescuing horses and wildlife and combating animal cruelty and trafficking." 8364 data-img="/assets/ngo/wild-for-life-foundation/hero-hd.jpg" 8365 data-href="/ngo/wild-for-life-foundation/"> 8366 <span class="pin-dot"></span><span class="pin-label">Wild For Life Foundation</span> 8367 </button> 8368 <button class="pin" type="button" 8369 data-name="Animal Academy" 8370 data-ngo="Animal welfare & education" 8371 data-where="Spain (Fuerteventura)" 8372 data-coords="28.36°N · 14.05°W" 8373 data-status="active" 8374 data-stat="" 8375 data-desc="Promoting animal welfare and rescue on Fuerteventura through care and education." 8376 data-img="/assets/ngo/animal-academy/hero-hd.jpg" 8377 data-href="/ngo/animal-academy/">
8378 <span class="pin-dot"></span><span class="pin-label">Animal Academy</span> 8379 </button> 8380 <button class="pin" type="button" 8381 data-name="Jakarta Animal Aid Network" 8382 data-ngo="Wildlife rescue & welfare" 8383 data-where="Indonesia" 8384 data-coords="6.21°S · 106.85°E" 8385 data-status="active" 8386 data-stat="" 8387 data-desc="Rescuing captive and trafficked wildlife and improving animal welfare across Indonesia." 8388 data-img="/assets/ngo/jakarta-animal-aid-network/hero-hd.jpg" 8389 data-href="/ngo/jakarta-animal-aid-network/"> 8390 <span class="pin-dot"></span><span class="pin-label">Jakarta Animal Aid Network</span> 8391 </button> 8392 <button class="pin" type="button" 8393 data-name="Trunks Up" 8394 data-ngo="Elephant sanctuary support" 8395 data-where="Thailand / USA" 8396 data-coords="18.79°N · 98.98°E" 8397 data-status="active" 8398 data-stat="" 8399 data-desc="Supporting ethical elephant sanctuaries and the mahouts who care for them in Thailand." 8400 data-img="/assets/ngo/trunks-up/hero-hd.jpg" 8401 data-href="/ngo/trunks-up/"> 8402 <span class="pin-dot"></span><span class="pin-label">Trunks Up</span> 8403 </button> 8404 <button class="pin" type="button" 8405 data-name="Wildlife SOS" 8406 data-ngo="Wildlife rescue" 8407 data-where="India" 8408 data-coords="28.61°N · 77.20°E" 8409 data-status="active" 8410 data-stat="" 8411 data-desc="Rescuing and rehabilitating Indiaâs wildlife, including bears, elephants and leopards." 8412 data-img="/assets/ngo/wildlife-sos/hero-hd.jpg" 8413 data-href="/ngo/wildlife-sos/"> 8414 <span class="pin-dot"></span><span class="pin-label">Wildlife SOS</span> 8415 </button> 8416 <button class="pin" type="button" 8417 data-name="In Defense of Animals" 8418 data-ngo="Animal rights advocacy" 8419 data-where="USA / India / South Korea" 8420 data-coords="37.97°N · 122.53°W" 8421 data-status="active" 8422 data-stat="" 8423 data-desc="Protecting animals, people and the environment through campaigns, rescue and advocacy." 8424 data-img="/assets/ngo/in-defense-of-animals/hero-hd.jpg" 8425 data-href="/ngo/in-defense-of-animals/"> 8426 <span class="pin-dot"></span><span class="pin-label">In Defense of Animals</span> 8427 </button> 8428 <button class="pin" type="button" 8429 data-name="Danau Girang Field Centre" 8430 data-ngo="Field research & conservation" 8431 data-where="Malaysia (Sabah, Borneo)" 8432 data-coords="5.41°N · 118.04°E" 8433 data-status="active" 8434 data-stat=""
8435 data-desc="A research field centre studying and protecting wildlife in Sabahâs Kinabatangan floodplain." 8436 data-img="/assets/ngo/danau-girang-field-centre/hero-hd.jpg" 8437 data-href="/ngo/danau-girang-field-centre/"> 8438 <span class="pin-dot"></span><span class="pin-label">Danau Girang Field Centre</span> 8439 </button> 8440 <button class="pin" type="button" 8441 data-name="Neptune's Pirates" 8442 data-ngo="Marine direct action" 8443 data-where="United Kingdom / Global" 8444 data-coords="51.51°N · 0.13°W" 8445 data-status="active" 8446 data-stat="" 8447 data-desc="Taking direct action to defend marine wildlife and confront ocean exploitation." 8448 data-img="/assets/ngo/neptune-s-pirates/hero-hd.jpg" 8449 data-href="/ngo/neptune-s-pirates/"> 8450 <span class="pin-dot"></span><span class="pin-label">Neptune's Pirates</span> 8451 </button> 8452 <button class="pin" type="button" 8453 data-name="Tusk Trust" 8454 data-ngo="African conservation" 8455 data-where="Africa (20+ countries)" 8456 data-coords="1.29°S · 36.82°E" 8457 data-status="active" 8458 data-stat="" 8459 data-desc="Funding wildlife conservation and community initiatives across 20+ African countries." 8460 data-img="/assets/ngo/tusk-trust/hero-hd.jpg" 8461 data-href="/ngo/tusk-trust/"> 8462 <span class="pin-dot"></span><span class="pin-label">Tusk Trust</span> 8463 </button> 8464 <button class="pin" type="button" 8465 data-name="Whitley Fund For Nature" 8466 data-ngo="Grassroots conservation funding" 8467 data-where="Global South â 84 countries" 8468 data-coords="51.51°N · 0.13°W" 8469 data-status="active" 8470 data-stat="" 8471 data-desc="Supporting grassroots conservation leaders across the Global South." 8472 data-img="/assets/ngo/whitley-fund-for-nature/hero-hd.jpg" 8473 data-href="/ngo/whitley-fund-for-nature/"> 8474 <span class="pin-dot"></span><span class="pin-label">Whitley Fund For Nature</span> 8475 </button> 8476 <button class="pin" type="button" 8477 data-name="Beaver Trust" 8478 data-ngo="Beaver restoration" 8479 data-where="UK" 8480 data-coords="50.40°N · 4.90°W" 8481 data-status="active" 8482 data-stat="" 8483 data-desc="Restoring beavers and their wetlands to revive Britainâs rivers and landscapes." 8484 data-img="/assets/ngo/beaver-trust/hero-hd.jpg" 8485 data-href="/ngo/beaver-trust/"> 8486 <span class="pin-dot"></span><span class="pin-label">Beaver Trust</span> 8487 </button> 8488 <button class="pin" type="button" 8489 data-name="Humane World for Animals" 8490 data-ngo="Global animal protection" 8491 data-where="Global (50+ countries)" 8492 data-coords="38.90°N · 77.04°W" 8493 data-status="active" 8494 data-stat="" 8495 data-desc="Working worldwide to end cruelty and protect animals across 50+ countries." 8496 data-img="/assets/ngo/humane-world-for-animals/hero-hd.jpg" 8497 data-href="/ngo/humane-world-for-animals/"> 8498 <span class="pin-dot"></span><span class="pin-label">Humane World for Animals</span> 8499 </button> 8500 <button class="pin" type="button" 8501 data-name="Ocean Conservancy" 8502 data-ngo="Ocean protection" 8503 data-where="Global (HQ Washington, D.C., USA)" 8504 data-coords="38.90°N · 77.04°W" 8505 data-status="active" 8506 data-stat="" 8507 data-desc="Working for a healthy ocean and tackling plastic pollution and climate threats." 8508 data-img="/assets/ngo/ocean-conservancy/hero-hd.jpg" 8509 data-href="/ngo/ocean-conservancy/"> 8510 <span class="pin-dot"></span><span class="pin-label">Ocean Conservancy</span> 8511 </button> 8512 <button class="pin" type="button" 8513 data-name="Earth League International" 8514 data-ngo="Wildlife crime intelligence" 8515 data-where="" 8516 data-coords="34.05°N · 118.24°W" 8517 data-status="active" 8518 data-stat="" 8519 data-desc="Investigating and disrupting transnational wildlife and environmental crime." 8520 data-img="/assets/ngo/earth-league-international/hero-hd.jpg" 8521 data-href="/ngo/earth-league-international/">
8522 <span class="pin-dot"></span><span class="pin-label">Earth League International</span> 8523 </button> 8524 <button class="pin" type="button" 8525 data-name="The Gorilla Organization" 8526 data-ngo="Gorilla protection" 8527 data-where="Africa" 8528 data-coords="1.40°S · 29.50°E" 8529 data-status="active" 8530 data-stat="" 8531 data-desc="Protecting the worldâs last wild gorillas and the habitats they depend on." 8532 data-img="/assets/ngo/the-gorilla-organization/hero-hd.jpg" 8533 data-href="/ngo/the-gorilla-organization/"> 8534 <span class="pin-dot"></span><span class="pin-label">The Gorilla Organization</span> 8535 </button> 8536 <button class="pin" type="button" 8537 data-name="Save Elephant Foundation" 8538 data-ngo="Elephant rescue & sanctuary" 8539 data-where="Thailand" 8540 data-coords="19.21°N · 98.86°E" 8541 data-status="active" 8542 data-stat="" 8543 data-desc="Rescuing elephants and promoting ethical care; home of Elephant Nature Park, Thailand." 8544 data-img="/assets/ngo/save-elephant-foundation/hero-hd.jpg" 8545 data-href="/ngo/save-elephant-foundation/"> 8546 <span class="pin-dot"></span><span class="pin-label">Save Elephant Foundation</span> 8547 </button> 8548 <button class="pin" type="button" 8549 data-name="International Primate Protection League" 8550 data-ngo="Primate protection" 8551 data-where="USA (Summerville, South Carolina)" 8552 data-coords="33.02°N · 80.18°W" 8553 data-status="active" 8554 data-stat="" 8555 data-desc="Protecting primates worldwide and providing sanctuary for gibbons in the US." 8556 data-img="/assets/ngo/international-primate-protection-league/hero-hd.jpg" 8557 data-href="/ngo/international-primate-protection-league/"> 8558 <span class="pin-dot"></span><span class="pin-label">International Primate Protection League</span> 8559 </button> 8560 <button class="pin" type="button" 8561 data-name="Liberia Chimpanzee Rescue & Protection (LCRP)" 8562 data-ngo="Chimpanzee sanctuary" 8563 data-where="Liberia" 8564 data-coords="6.30°N · 10.80°W" 8565 data-status="active" 8566 data-stat="" 8567 data-desc="Caring for rescued chimpanzees and protecting wild populations in Liberia." 8568 data-img="/assets/ngo/liberia-chimpanzee-rescue-protection-lcrp/hero-hd.jpg" 8569 data-href="/ngo/liberia-chimpanzee-rescue-protection-lcrp/"> 8570 <span class="pin-dot"></span><span class="pin-label">Liberia Chimpanzee Rescue & Protection (LCRP)</span> 8571 </button> 8572 <button class="pin" type="button" 8573 data-name="Kalahari Research And Conservation Trust" 8574 data-ngo="Predator & ecosystem research" 8575 data-where="Botswana" 8576 data-coords="21.00°S · 24.00°E" 8577 data-status="active" 8578 data-stat="" 8579 data-desc="Researching and conserving wildlife and ecosystems in Botswanaâs Kalahari." 8580 data-img="/assets/ngo/kalahari-research-and-conservation-trust/hero-hd.jpg" 8581 data-href="/ngo/kalahari-research-and-conservation-trust/"> 8582 <span class="pin-dot"></span><span class="pin-label">Kalahari Research And Conservation Trust</span> 8583 </button> 8584 <button class="pin" type="button" 8585 data-name="Civet Project" 8586 data-ngo="Civet welfare & research" 8587 data-where="" 8588 data-coords="51.51°N · 0.13°W" 8589 data-status="active" 8590 data-stat="" 8591 data-desc="Researching and protecting civets and challenging their exploitation." 8592 data-img="/assets/ngo/civet-project/hero-hd.jpg" 8593 data-href="/ngo/civet-project/"> 8594 <span class="pin-dot"></span><span class="pin-label">Civet Project</span> 8595 </button> 8596 <button class="pin" type="button" 8597 data-name="Limbe Wildlife Centre (LWC)" 8598 data-ngo="Primate rescue & rehab" 8599 data-where="Cameroon" 8600 data-coords="4.02°N · 9.21°E" 8601 data-status="active" 8602 data-stat="" 8603 data-desc="Rescuing and rehabilitating primates and other wildlife in Cameroon." 8604 data-img="/assets/ngo/limbe-wildlife-centre-lwc/hero-hd.jpg" 8605 data-href="/ngo/limbe-wildlife-centre-lwc/">
8606 <span class="pin-dot"></span><span class="pin-label">Limbe Wildlife Centre (LWC)</span> 8607 </button> 8608 <button class="pin" type="button" 8609 data-name="Born Free" 8610 data-ngo="Wild animal welfare" 8611 data-where="UK (international)" 8612 data-coords="51.06°N · 0.33°W" 8613 data-status="active" 8614 data-stat="" 8615 data-desc="Keeping wildlife in the wild and ending the keeping of wild animals in captivity." 8616 data-img="/assets/ngo/born-free/hero-hd.jpg" 8617 data-href="/ngo/born-free/"> 8618 <span class="pin-dot"></span><span class="pin-label">Born Free</span> 8619 </button> 8620 <button class="pin" type="button" 8621 data-name="Over and Above Africa" 8622 data-ngo="African wildlife protection" 8623 data-where="Africa (HQ USA)" 8624 data-coords="2.15°S · 34.69°E" 8625 data-status="active" 8626 data-stat="" 8627 data-desc="Funding anti-poaching and community projects to protect Africaâs wildlife." 8628 data-img="/assets/ngo/over-and-above-africa/hero-hd.jpg" 8629 data-href="/ngo/over-and-above-africa/"> 8630 <span class="pin-dot"></span><span class="pin-label">Over and Above Africa</span> 8631 </button> 8632 <button class="pin" type="button" 8633 data-name="Gentle Giants Elephants" 8634 data-ngo="Elephant welfare" 8635 data-where="" 8636 data-coords="18.85°N · 98.97°E" 8637 data-status="active" 8638 data-stat="" 8639 data-desc="Dedicated to the care and protection of elephants." 8640 data-img="/assets/ngo/gentle-giants-elephants/hero-hd.jpg" 8641 data-href="/ngo/gentle-giants-elephants/"> 8642 <span class="pin-dot"></span><span class="pin-label">Gentle Giants Elephants</span> 8643 </button> 8644 <button class="pin" type="button" 8645 data-name="Ventana Wildlife Society" 8646 data-ngo="Condor recovery" 8647 data-where="USA (central California)" 8648 data-coords="36.60°N · 121.90°W" 8649 data-status="active" 8650 data-stat="" 8651 data-desc="Restoring native wildlife, including the California condor, on the central coast." 8652 data-img="/assets/ngo/ventana-wildlife-society/hero-hd.jpg" 8653 data-href="/ngo/ventana-wildlife-society/"> 8654 <span class="pin-dot"></span><span class="pin-label">Ventana Wildlife Society</span> 8655 </button> 8656 <button class="pin" type="button" 8657 data-name="Wolf Connection" 8658 data-ngo="Wolfdog rescue & youth" 8659 data-where="USA (California)" 8660 data-coords="34.47°N · 118.20°W" 8661 data-status="active" 8662 data-stat="" 8663 data-desc="Rescuing wolfdogs and running youth empowerment programmes in California." 8664 data-img="/assets/ngo/wolf-connection/hero-hd.jpg" 8665 data-href="/ngo/wolf-connection/"> 8666 <span class="pin-dot"></span><span class="pin-label">Wolf Connection</span> 8667 </button> 8668 <button class="pin" type="button" 8669 data-name="Conservation Without Borders" 8670 data-ngo="Migratory species & flyways" 8671 data-where="" 8672 data-coords="51.06°N · 1.31°W" 8673 data-status="active" 8674 data-stat="" 8675 data-desc="Following migratory species to inspire conservation across borders." 8676 data-img="/assets/ngo/conservation-without-borders/hero-hd.jpg" 8677 data-href="/ngo/conservation-without-borders/"> 8678 <span class="pin-dot"></span><span class="pin-label">Conservation Without Borders</span> 8679 </button> 8680 <button class="pin" type="button" 8681 data-name="International Elephant Project" 8682 data-ngo="Sumatran wildlife protection" 8683 data-where="Indonesia (Borneo & Sumatra)" 8684 data-coords="0.50°S · 102.00°E" 8685 data-status="active" 8686 data-stat="" 8687 data-desc="Protecting elephants, orangutans and tigers and their habitat in Indonesia." 8688 data-img="/assets/ngo/international-elephant-project/hero-hd.jpg" 8689 data-href="/ngo/international-elephant-project/"> 8690 <span class="pin-dot"></span><span class="pin-label">International Elephant Project</span> 8691 </button> 8692 <button class="pin" type="button" 8693 data-name="Tacugama" 8694 data-ngo="Chimpanzee sanctuary" 8695 data-where="Sierra Leone" 8696 data-coords="8.40°N · 13.16°W" 8697 data-status="active" 8698 data-stat="" 8699 data-desc="Sierra Leoneâs chimpanzee sanctuary, rescuing and rehabilitating chimps near Freetown." 8700 data-img="/assets/ngo/tacugama/hero-hd.jpg" 8701 data-href="/ngo/tacugama/">
8702 <span class="pin-dot"></span><span class="pin-label">Tacugama</span> 8703 </button> 8704 <button class="pin" type="button" 8705 data-name="UOCEAN" 8706 data-ngo="Ocean clean-up & education" 8707 data-where="UK (33 countries)" 8708 data-coords="51.51°N · 0.13°W" 8709 data-status="active" 8710 data-stat="" 8711 data-desc="Mobilising communities to clean coastlines and protect the ocean." 8712 data-img="/assets/ngo/uocean/hero-hd.jpg" 8713 data-href="/ngo/uocean/"> 8714 <span class="pin-dot"></span><span class="pin-label">UOCEAN</span> 8715 </button> 8716 <button class="pin" type="button" 8717 data-name="Ecosystem Restoration Communities" 8718 data-ngo="Community-led restoration" 8719 data-where="Global (HQ Netherlands)" 8720 data-coords="52.13°N · 5.29°E" 8721 data-status="active" 8722 data-stat="" 8723 data-desc="Restoring degraded ecosystems through a global network of community projects." 8724 data-img="/assets/ngo/ecosystem-restoration-communities/hero-hd.jpg" 8725 data-href="/ngo/ecosystem-restoration-communities/"> 8726 <span class="pin-dot"></span><span class="pin-label">Ecosystem Restoration Communities</span> 8727 </button> 8728 <button class="pin" type="button" 8729 data-name="Wild Futures" 8730 data-ngo="Primate welfare & sanctuary" 8731 data-where="UK" 8732 data-coords="50.37°N · 4.43°W" 8733 data-status="active" 8734 data-stat="" 8735 data-desc="Protecting primates and their habitats; home to The Monkey Sanctuary in Cornwall." 8736 data-img="/assets/ngo/wild-futures/hero-hd.jpg" 8737 data-href="/ngo/wild-futures/"> 8738 <span class="pin-dot"></span><span class="pin-label">Wild Futures</span> 8739 </button> 8740 <button class="pin" type="button" 8741 data-name="The Orang Utan Republik Foundation" 8742 data-ngo="Orangutan education" 8743 data-where="Indonesia" 8744 data-coords="3.59°N · 98.67°E" 8745 data-status="active" 8746 data-stat="" 8747 data-desc="Saving orangutans through education and habitat protection in Sumatra." 8748 data-img="/assets/ngo/the-orang-utan-republik-foundation/hero-hd.jpg" 8749 data-href="/ngo/the-orang-utan-republik-foundation/"> 8750 <span class="pin-dot"></span><span class="pin-label">The Orang Utan Republik Foundation</span> 8751 </button> 8752 <button class="pin" type="button" 8753 data-name="The Wildlife Habitat Trust" 8754 data-ngo="Habitat protection" 8755 data-where="Kenya" 8756 data-coords="1.29°S · 36.82°E" 8757 data-status="active" 8758 data-stat="" 8759 data-desc="Protecting and restoring wildlife habitat in Kenya." 8760 data-img="/assets/ngo/the-wildlife-habitat-trust/hero-hd.jpg" 8761 data-href="/ngo/the-wildlife-habitat-trust/"> 8762 <span class="pin-dot"></span><span class="pin-label">The Wildlife Habitat Trust</span> 8763 </button> 8764 <button class="pin" type="button" 8765 data-name="International Tiger Project" 8766 data-ngo="Tiger & habitat protection" 8767 data-where="Indonesia and South-East Asia (HQ Australia)" 8768 data-coords="0.50°S · 101.40°E" 8769 data-status="active" 8770 data-stat="" 8771 data-desc="Protecting wild tigers and rainforest habitat across Indonesia and Southeast Asia." 8772 data-img="/assets/ngo/international-tiger-project/hero-hd.jpg" 8773 data-href="/ngo/international-tiger-project/"> 8774 <span class="pin-dot"></span><span class="pin-label">International Tiger Project</span> 8775 </button> 8776 <button class="pin" type="button" 8777 data-name="Boomer's Buddies Rescue" 8778 data-ngo="Animal rescue" 8779 data-where="USA (Malibu, California)" 8780 data-coords="34.03°N · 118.69°W" 8781 data-status="active" 8782 data-stat="" 8783 data-desc="Rescuing and rehoming animals in need in Southern California." 8784 data-img="/assets/ngo/boomer-s-buddies-rescue/hero-hd.jpg" 8785 data-href="/ngo/boomer-s-buddies-rescue/"> 8786 <span class="pin-dot"></span><span class="pin-label">Boomer's Buddies Rescue</span> 8787 </button> 8788 <button class="pin" type="button" 8789 data-name="Performing Animal Welfare Society (PAWS)" 8790 data-ngo="Captive wildlife sanctuary" 8791 data-where="USA (California)" 8792 data-coords="38.20°N · 120.68°W" 8793 data-status="active" 8794 data-stat="" 8795 data-desc="Providing sanctuary to abused and abandoned captive wildlife, including elephants." 8796 data-img="/assets/ngo/performing-animal-welfare-society-paws/hero-hd.jpg" 8797 data-href="/ngo/performing-animal-welfare-society-paws/">
8798 <span class="pin-dot"></span><span class="pin-label">Performing Animal Welfare Society (PAWS)</span> 8799 </button> 8800 <button class="pin" type="button" 8801 data-name="IFAW" 8802 data-ngo="Animal rescue & conservation" 8803 data-where="Global (40+ countries)" 8804 data-coords="38.90°N · 77.04°W" 8805 data-status="active" 8806 data-stat="" 8807 data-desc="Rescuing animals and restoring habitats in more than 40 countries worldwide." 8808 data-img="/assets/ngo/ifaw/hero-hd.jpg" 8809 data-href="/ngo/ifaw/"> 8810 <span class="pin-dot"></span><span class="pin-label">IFAW</span> 8811 </button> 8812 <button class="pin" type="button" 8813 data-name="Cambodia Wildlife Sanctuary (CWS)" 8814 data-ngo="Wildlife rescue & sanctuary" 8815 data-where="Cambodia" 8816 data-coords="11.55°N · 104.92°E" 8817 data-status="active" 8818 data-stat="" 8819 data-desc="Protecting rescued wildlife and forest habitat in Cambodia." 8820 data-img="/assets/ngo/cambodia-wildlife-sanctuary-cws/hero-hd.jpg" 8821 data-href="/ngo/cambodia-wildlife-sanctuary-cws/"> 8822 <span class="pin-dot"></span><span class="pin-label">Cambodia Wildlife Sanctuary (CWS)</span> 8823 </button> 8824 <button class="pin" type="button" 8825 data-name="The Earth Organization" 8826 data-ngo="Conservation & education" 8827 data-where="" 8828 data-coords="34.84°N · 119.15°W" 8829 data-status="active" 8830 data-stat="" 8831 data-desc="Promoting wildlife conservation and environmental restoration." 8832 data-img="/assets/ngo/the-earth-organization/hero-hd.jpg" 8833 data-href="/ngo/the-earth-organization/"> 8834 <span class="pin-dot"></span><span class="pin-label">The Earth Organization</span> 8835 </button> 8836 <button class="pin" type="button" 8837 data-name="Wolf Conservation Center" 8838 data-ngo="Wolf recovery" 8839 data-where="USA (South Salem, NY)" 8840 data-coords="41.26°N · 73.58°W" 8841 data-status="active" 8842 data-stat="" 8843 data-desc="Protecting and recovering endangered wolves through education and breeding programmes." 8844 data-img="/assets/ngo/wolf-conservation-center/hero-hd.jpg" 8845 data-href="/ngo/wolf-conservation-center/"> 8846 <span class="pin-dot"></span><span class="pin-label">Wolf Conservation Center</span> 8847 </button> 8848 <button class="pin" type="button" 8849 data-name="Mercy For Animals" 8850 data-ngo="Farmed animal protection" 8851 data-where="International" 8852 data-coords="34.05°N · 118.24°W" 8853 data-status="active" 8854 data-stat="" 8855 data-desc="Working to end industrial animal agriculture and protect farmed animals." 8856 data-img="/assets/ngo/mercy-for-animals/hero-hd.jpg" 8857 data-href="/ngo/mercy-for-animals/"> 8858 <span class="pin-dot"></span><span class="pin-label">Mercy For Animals</span> 8859 </button> 8860 <button class="pin" type="button" 8861 data-name="Lady Freethinker" 8862 data-ngo="Animal cruelty investigations" 8863 data-where="" 8864 data-coords="34.05°N · 118.24°W" 8865 data-status="active" 8866 data-stat="" 8867 data-desc="Exposing and ending animal cruelty through investigations and campaigns." 8868 data-img="/assets/ngo/lady-freethinker/hero-hd.jpg" 8869 data-href="/ngo/lady-freethinker/"> 8870 <span class="pin-dot"></span><span class="pin-label">Lady Freethinker</span> 8871 </button> 8872 <button class="pin" type="button" 8873 data-name="Endangered Species Protection Agency" 8874 data-ngo="Endangered species protection" 8875 data-where="" 8876 data-coords="51.51°N · 0.14°W" 8877 data-status="active" 8878 data-stat="" 8879 data-desc="Working to protect endangered species from extinction." 8880 data-img="/assets/ngo/endangered-species-protection-agency/hero-hd.jpg" 8881 data-href="/ngo/endangered-species-protection-agency/"> 8882 <span class="pin-dot"></span><span class="pin-label">Endangered Species Protection Agency</span> 8883 </button> 8884 <button class="pin" type="button" 8885 data-name="Defend (formerly National Park Rescue)" 8886 data-ngo="Anti-poaching" 8887 data-where="Africa" 8888 data-coords="18.00°S · 29.00°E" 8889 data-status="active" 8890 data-stat="" 8891 data-desc="Protecting national parks and wildlife from poaching across Africa." 8892 data-img="/assets/ngo/defend-formerly-national-park-rescue/hero-hd.jpg" 8893 data-href="/ngo/defend-formerly-national-park-rescue/">
8894 <span class="pin-dot"></span><span class="pin-label">Defend (formerly National Park Rescue)</span> 8895 </button> 8896 <button class="pin" type="button" 8897 data-name="Hopefield Animal Sanctuary" 8898 data-ngo="Animal sanctuary" 8899 data-where="UK (Essex)" 8900 data-coords="51.62°N · 0.31°E" 8901 data-status="active" 8902 data-stat="" 8903 data-desc="Caring for rescued and neglected animals in Essex." 8904 data-img="/assets/ngo/hopefield-animal-sanctuary/hero-hd.jpg" 8905 data-href="/ngo/hopefield-animal-sanctuary/"> 8906 <span class="pin-dot"></span><span class="pin-label">Hopefield Animal Sanctuary</span> 8907 </button> 8908 <button class="pin" type="button" 8909 data-name="Gorilla Foundation" 8910 data-ngo="Great ape welfare" 8911 data-where="USA (California)" 8912 data-coords="37.43°N · 122.25°W" 8913 data-status="active" 8914 data-stat="" 8915 data-desc="Advancing great ape conservation and welfare; known for Koko the gorilla." 8916 data-img="/assets/ngo/gorilla-foundation/hero-hd.jpg" 8917 data-href="/ngo/gorilla-foundation/"> 8918 <span class="pin-dot"></span><span class="pin-label">Gorilla Foundation</span> 8919 </button> 8920 <button class="pin" type="button" 8921 data-name="Connected Planet Foundation" 8922 data-ngo="African ecosystem protection" 8923 data-where="Kenya, South Africa (Maasai Mara, Kruger)" 8924 data-coords="1.50°S · 35.14°E" 8925 data-status="active" 8926 data-stat="" 8927 data-desc="Protecting iconic landscapes and wildlife in Kenya and South Africa." 8928 data-img="/assets/ngo/connected-planet-foundation/hero-hd.jpg" 8929 data-href="/ngo/connected-planet-foundation/"> 8930 <span class="pin-dot"></span><span class="pin-label">Connected Planet Foundation</span> 8931 </button> 8932 <button class="pin" type="button" 8933 data-name="Last Chance To Paint" 8934 data-ngo="Art for conservation" 8935 data-where="UK (international)" 8936 data-coords="51.51°N · 0.13°W" 8937 data-status="active" 8938 data-stat="" 8939 data-desc="Using art to connect communities with endangered wildlife and rainforests." 8940 data-img="/assets/ngo/last-chance-to-paint/hero-hd.jpg" 8941 data-href="/ngo/last-chance-to-paint/"> 8942 <span class="pin-dot"></span><span class="pin-label">Last Chance To Paint</span> 8943 </button> 8944 <button class="pin" type="button" 8945 data-name="Ape Alliance" 8946 data-ngo="Great ape coalition" 8947 data-where="UK (international coalition)" 8948 data-coords="52.20°N · 0.12°E" 8949 data-status="active" 8950 data-stat="" 8951 data-desc="An international coalition working to conserve apes and their habitats." 8952 data-img="/assets/ngo/ape-alliance/hero-hd.jpg" 8953 data-href="/ngo/ape-alliance/"> 8954 <span class="pin-dot"></span><span class="pin-label">Ape Alliance</span> 8955 </button> 8956 <button class="pin" type="button" 8957 data-name="Elephant Guardians of Los Angeles" 8958 data-ngo="Elephant advocacy" 8959 data-where="USA (Los Angeles, California)" 8960 data-coords="34.05°N · 118.24°W" 8961 data-status="active" 8962 data-stat="" 8963 data-desc="Advocating for captive elephants and their release to sanctuary." 8964 data-img="/assets/ngo/elephant-guardians-of-los-angeles/hero.jpg" 8965 data-href="/ngo/elephant-guardians-of-los-angeles/"> 8966 <span class="pin-dot"></span><span class="pin-label">Elephant Guardians of Los Angeles</span> 8967 </button> 8968 <button class="pin" type="button" 8969 data-name="Chimp Haven" 8970 data-ngo="Chimpanzee sanctuary" 8971 data-where="USA (Shreveport, Louisiana)" 8972 data-coords="32.36°N · 93.86°W" 8973 data-status="active" 8974 data-stat="" 8975 data-desc="The US national chimpanzee sanctuary, giving retired research chimps a home." 8976 data-img="/assets/ngo/chimp-haven/hero-hd.jpg" 8977 data-href="/ngo/chimp-haven/"> 8978 <span class="pin-dot"></span><span class="pin-label">Chimp Haven</span> 8979 </button> 8980 <button class="pin" type="button" 8981 data-name="Horstmann Vulture Conservation Trust" 8982 data-ngo="Vulture conservation" 8983 data-where="" 8984 data-coords="51.51°N · 0.13°W" 8985 data-status="active" 8986 data-stat="" 8987 data-desc="Protecting threatened vultures through captive breeding and conservation." 8988 data-img="/assets/ngo/horstmann-vulture-conservation-trust/hero-hd.jpg" 8989 data-href="/ngo/horstmann-vulture-conservation-trust/">
8990 <span class="pin-dot"></span><span class="pin-label">Horstmann Vulture Conservation Trust</span> 8991 </button> 8992 <button class="pin" type="button" 8993 data-name="African Conservation Foundation" 8994 data-ngo="African biodiversity" 8995 data-where="Africa (multi-country)" 8996 data-coords="3.85°N · 11.50°E" 8997 data-status="active" 8998 data-stat="" 8999 data-desc="Protecting Africaâs endangered wildlife and habitats through local partnerships." 9000 data-img="/assets/ngo/african-conservation-foundation/hero-hd.jpg" 9001 data-href="/ngo/african-conservation-foundation/"> 9002 <span class="pin-dot"></span><span class="pin-label">African Conservation Foundation</span> 9003 </button> 9004 <button class="pin" type="button" 9005 data-name="The Thin Green Line" 9006 data-ngo="Ranger support" 9007 data-where="Global (60+ countries; HQ Australia)" 9008 data-coords="37.81°S · 144.96°E" 9009 data-status="active" 9010 data-stat="" 9011 data-desc="Supporting wildlife rangers and the families of those killed in the line of duty." 9012 data-img="/assets/ngo/the-thin-green-line/hero-hd.jpg" 9013 data-href="/ngo/the-thin-green-line/"> 9014 <span class="pin-dot"></span><span class="pin-label">The Thin Green Line</span> 9015 </button> 9016 <button class="pin" type="button" 9017 data-name="RESQ CT" 9018 data-ngo="Animal rescue & rehab" 9019 data-where="" 9020 data-coords="18.52°N · 73.86°E" 9021 data-status="active" 9022 data-stat="" 9023 data-desc="Rescuing and treating wildlife and domestic animals in need across India." 9024 data-img="/assets/ngo/resq-ct/hero-hd.jpg" 9025 data-href="/ngo/resq-ct/"> 9026 <span class="pin-dot"></span><span class="pin-label">RESQ CT</span> 9027 </button> 9028 <button class="pin" type="button" 9029 data-name="A Free Life for Thailand's Rescued Elephants" 9030 data-ngo="Save Elephant Foundation" 9031 data-where="Chiang Mai, Thailand" 9032 data-coords="19.21°N · 98.86°E" 9033 data-status="project-active" 9034 data-stat="Active project" 9035 data-desc="Ecoflix's support of more than $127,000 has helped the Save Elephant Foundation rescue elephants from logging and trekking camps, giving them a free, dignified life to roam, bathe and form herds again at Elephant Nature Park in northern Thailand." 9036 data-img="https://ecoflix.com/wp-content/uploads/2023/03/Screenshot2021-10-27at10.32.45.png" 9037 data-href="/projects/a-free-life-for-thailands-rescued-elephants/"> 9038 <span class="pin-dot"></span><span class="pin-label">A Free Life for Thailand's Rescued Elephants</span> 9039 </button> 9040 <button class="pin" type="button" 9041 data-name="An Arctic Sanctuary for Captive Whales" 9042 data-ngo="Norwegian Whale Reserve" 9043 data-where="Hammerfest, Norway" 9044 data-coords="70.66°N · 23.68°E" 9045 data-status="project-active" 9046 data-stat="Active project" 9047 data-desc="More than $43,000 from Ecoflix is helping the Norwegian Whale Reserve create an Arctic fjord sanctuary, so whales held for years in tanks can feel wild, open water around them once more." 9048 data-img="https://static.wixstatic.com/media/1d67c4_8304600ef09f44cda98a044497c01b9d~mv2.jpg" 9049 data-href="/projects/an-arctic-sanctuary-for-captive-whales/"> 9050 <span class="pin-dot"></span><span class="pin-label">An Arctic Sanctuary for Captive Whales</span> 9051 </button> 9052 <button class="pin" type="button" 9053 data-name="Building North America's First Whale Sanctuary" 9054 data-ngo="The Whale Sanctuary Project" 9055 data-where="Port Hilford Bay, Nova Scotia, Canada" 9056 data-coords="45.13°N · 61.77°W" 9057 data-status="project-active" 9058 data-stat="Active project" 9059 data-desc="Ecoflix's $25,000 donation is helping build North America's first seaside whale sanctuary in Nova Scotia, where orcas and belugas retired from tanks can finally live in a netted stretch of open ocean." 9060 data-img="https://ecoflix.com/wp-content/uploads/2023/03/WhaleSanctuaryProjectSiteRender28nosailboat2Ctexted29.png" 9061 data-href="/projects/building-north-americas-first-whale-sanctuary/">
9062 <span class="pin-dot"></span><span class="pin-label">Building North America's First Whale Sanctuary</span> 9063 </button> 9064 <button class="pin" type="button" 9065 data-name="Returning Orphaned Orangutans to the Wild" 9066 data-ngo="Orangutan Foundation International" 9067 data-where="Central Kalimantan, Borneo, Indonesia" 9068 data-coords="2.73°S · 111.70°E" 9069 data-status="project-active" 9070 data-stat="Active project" 9071 data-desc="A $25,000 gift from Ecoflix supports Orangutan Foundation International as it rescues orphaned orangutans and returns them to protected Bornean rainforest through the legendary Camp Leakey." 9072 data-img="https://orangutan.org/wp-content/uploads/2023/12/2016-03_CampLeakeyDrone_faj_004_wm_small_2.jpg" 9073 data-href="/projects/returning-orphaned-orangutans-to-the-wild/"> 9074 <span class="pin-dot"></span><span class="pin-label">Returning Orphaned Orangutans to the Wild</span> 9075 </button> 9076 <button class="pin" type="button" 9077 data-name="A Forest Home for Rescued Wolves" 9078 data-ngo="Wolf Connection" 9079 data-where="Acton, California, USA" 9080 data-coords="34.47°N · 118.20°W" 9081 data-status="project-active" 9082 data-stat="Active project" 9083 data-desc="A $25,000 gift from Ecoflix gave rescued wolves and wolfdogs a 165-acre forest home at Wolf Connection in California, and helped fund the youth programmes that heal at-risk young people alongside the animals." 9084 data-img="https://ecoflix.com/wp-content/uploads/2023/04/GemmaSponsorCore2020.jpg" 9085 data-href="/projects/a-forest-home-for-rescued-wolves/"> 9086 <span class="pin-dot"></span><span class="pin-label">A Forest Home for Rescued Wolves</span> 9087 </button> 9088 <button class="pin" type="button" 9089 data-name="Field Ecology & Wildlife Surveys" 9090 data-ngo="AES Applied Ecology Solutions" 9091 data-where="United Kingdom" 9092 data-coords="52.48°N · 1.90°W" 9093 data-status="project-active" 9094 data-stat="Active project" 9095 data-desc="(Internal) UK ecological-survey consultancy commissioned for field/conservation work â not a public-facing partner." 9096 data-img="" 9097 data-href="/projects/field-ecology-and-wildlife-surveys/"> 9098 <span class="pin-dot"></span><span class="pin-label">Field Ecology & Wildlife Surveys</span> 9099 </button> 9100 <button class="pin" type="button" 9101 data-name="Returning Russia's Orphaned Lynx to the Wild" 9102 data-ngo="ABCR Lynx Rehabilitation Center (ANO)" 9103 data-where="Kirzhachsky District, Vladimir Region, Russia" 9104 data-coords="56.15°N · 38.87°E" 9105 data-status="project-active" 9106 data-stat="Active project" 9107 data-desc="Ecoflix's $12,000 donation supports Russia's only lynx rehabilitation centre, ABCR, which rescues orphaned and caged lynx and patiently prepares them to return â wild and wary â to the forests of Vladimir." 9108 data-img="https://news.ecoflix.com/wp-content/uploads/2022/03/LynxRehabilitationCenterABCR.jpg" 9109 data-href="/projects/returning-russias-orphaned-lynx-to-the-wild/"> 9110 <span class="pin-dot"></span><span class="pin-label">Returning Russia's Orphaned Lynx to the Wild</span> 9111 </button> 9112 <button class="pin" type="button" 9113 data-name="Standing with Wildlife Rangers" 9114 data-ngo="Guardians of the Wild" 9115 data-where="Africa" 9116 data-coords="1.00°S · 37.00°E" 9117 data-status="project-active" 9118 data-stat="Active project" 9119 data-desc="Supports rangers and endangered-species protection." 9120 data-img="" 9121 data-href="/projects/standing-with-wildlife-rangers/"> 9122 <span class="pin-dot"></span><span class="pin-label">Standing with Wildlife Rangers</span> 9123 </button> 9124 <button class="pin" type="button" 9125 data-name="Freedom for India's Bears & Elephants" 9126 data-ngo="Wildlife SOS" 9127 data-where="Agra, India" 9128 data-coords="27.18°N · 78.02°E" 9129 data-status="project-active" 9130 data-stat="Active project" 9131 data-desc="More than $10,000 from Ecoflix supports Wildlife SOS in India, home to the world'
9131s largest sloth-bear rescue centre and a refuge where abused elephants and leopards are given a life of dignity." 9132 data-img="https://ecoflix.com/wp-content/uploads/2023/03/EMMA26Maya_EVENINGWALK_ELEPHANTNov21.jpg" 9133 data-href="/projects/freedom-for-indias-bears-and-elephants/"> 9134 <span class="pin-dot"></span><span class="pin-label">Freedom for India's Bears & Elephants</span> 9135 </button> 9136 <button class="pin" type="button" 9137 data-name="Rewilding the Amazon's Big Cats" 9138 data-ngo="Friends of Hoja Nueva" 9139 data-where="Madre de Dios, Peru" 9140 data-coords="12.59°S · 69.19°W" 9141 data-status="project-active" 9142 data-stat="Active project" 9143 data-desc="Ecoflix's $10,000 of support helps Friends of Hoja Nueva guard over 3,000 hectares of Peruvian Amazon and run the country's first big-cat rewilding centre, returning rescued jaguars, pumas and ocelots to the wild." 9144 data-img="https://hojanueva.org/wp-content/uploads/2023/10/Wildcat_Emmy-News-and-Documentary_Win__1x1_cat-1024x1024.jpg" 9145 data-href="/projects/rewilding-the-amazons-big-cats/"> 9146 <span class="pin-dot"></span><span class="pin-label">Rewilding the Amazon's Big Cats</span> 9147 </button> 9148 <button class="pin" type="button" 9149 data-name="Bringing Congo's Wildlife Traffickers to Justice" 9150 data-ngo="Conserv Congo ASBL" 9151 data-where="Kinshasa, DR Congo" 9152 data-coords="4.32°S · 15.31°E" 9153 data-status="project-urgent" 9154 data-stat="Urgent project" 9155 data-desc="A $6,600 gift from Ecoflix backs Conserv Congo as it takes on the traffickers behind Central Africa's wildlife crime, rescuing trafficked animals and bringing poaching kingpins to justice across the Congo Basin." 9156 data-img="https://conservcongo.net/" 9157 data-href="/projects/bringing-congos-wildlife-traffickers-to-justice/"> 9158 <span class="pin-dot"></span><span class="pin-label">Bringing Congo's Wildlife Traffickers to Justice</span> 9159 </button> 9160 <button class="pin" type="button" 9161 data-name="Saving the Singing Apes" 9162 data-ngo="Gibbon Conservation Center" 9163 data-where="Santa Clarita, California, USA" 9164 data-coords="34.41°N · 118.54°W" 9165 data-status="project-active" 9166 data-stat="Active project" 9167 data-desc="Ecoflix's $2,500 donation supports the Gibbon Conservation Center in California, home to one of the world's most important populations of these endangered singing apes." 9168 data-img="https://gibboncenter.org/" 9169 data-href="/projects/saving-the-singing-apes/"> 9170 <span class="pin-dot"></span><span class="pin-label">Saving the Singing Apes</span> 9171 </button> 9172 <button class="pin" type="button" 9173 data-name="A Forever Home for Rescued Wild Animals" 9174 data-ngo="Animal Tracks" 9175 data-where="Agua Dulce, California, USA" 9176 data-coords="34.50°N · 118.32°W" 9177 data-status="project-active" 9178 data-stat="Active project" 9179 data-desc="A $1,000 gift from Ecoflix supports Animal Tracks, a California sanctuary giving rescued exotic animals a permanent home and using their stories to teach conservation." 9180 data-img="https://static.wixstatic.com/media/fdac05_2a2c21b19a724a52ae69cc2137722daa~mv2.jpg" 9181 data-href="/projects/a-forever-home-for-rescued-wild-animals/"> 9182 <span class="pin-dot"></span><span class="pin-label">A Forever Home for Rescued Wild Animals</span> 9183 </button> 9184 <button class="pin" type="button" 9185 data-name="A Future for Samburu's Girls" 9186 data-ngo="Samburu Girls Foundation" 9187 data-where="Samburu County, Kenya" 9188 data-coords="1.17°N · 37.53°E" 9189 data-status="project-active" 9190 data-stat="Active project" 9191 data-desc="Ecoflix's $1,000 donation supports the Samburu Girls Foundation as it rescues girls from child marriage and FGM in northern Kenya and sends them to school." 9192 data-img="https://samburugirls.foundation/" 9193 data-href="/projects/a-future-for-samburus-girls/">
9194 <span class="pin-dot"></span><span class="pin-label">A Future for Samburu's Girls</span> 9195 </button> 9196 <button class="pin" type="button" 9197 data-name="Frontline Support for Africa's Wildlife" 9198 data-ngo="Over and Above Africa" 9199 data-where="Marina del Rey, California, USA (projects in Africa)" 9200 data-coords="2.15°S · 34.69°E" 9201 data-status="project-active" 9202 data-stat="Active project" 9203 data-desc="A $1,000 gift from Ecoflix helps Over and Above Africa fund the small, frontline projects that protect Africa's wildlife and the communities who live alongside them." 9204 data-img="https://ecoflix.com/wp-content/uploads/Elephants.jpg" 9205 data-href="/projects/frontline-support-for-africas-wildlife/"> 9206 <span class="pin-dot"></span><span class="pin-label">Frontline Support for Africa's Wildlife</span> 9207 </button> 9208 <button class="pin" type="button" 9209 data-name="Helping Borneo's People & Elephants Coexist" 9210 data-ngo="Elephant Protection Society (Seratu Aatai)" 9211 data-where="Sabah, Borneo, Malaysia" 9212 data-coords="5.41°N · 118.04°E" 9213 data-status="project-active" 9214 data-stat="Active project" 9215 data-desc="Ecoflix's support helps Seratu Aatai, the Elephant Protection Society, foster peaceful coexistence between Borneo's villages and its endangered elephants." 9216 data-img="https://static.wixstatic.com/media/fef3ea_cee5c7c232c44aa684de89a68d9666e3~mv2.jpg" 9217 data-href="/projects/helping-borneos-people-and-elephants-coexist/"> 9218 <span class="pin-dot"></span><span class="pin-label">Helping Borneo's People & Elephants Coexist</span> 9219 </button> 9220 <button class="pin" type="button" 9221 data-name="Keeping Wild Animals Wild" 9222 data-ngo="Born Free Foundation" 9223 data-where="Horsham, West Sussex, UK" 9224 data-coords="51.06°N · 0.33°W" 9225 data-status="project-active" 9226 data-stat="Active project" 9227 data-desc="Ecoflix supports the Born Free Foundation as it works worldwide to keep wild animals wild â rescuing individuals from captivity and campaigning against their exploitation." 9228 data-img="https://ecoflix.com/wp-content/uploads/2023/03/Born_Free-Black-LAN_1-1024x536.png" 9229 data-href="/projects/keeping-wild-animals-wild/"> 9230 <span class="pin-dot"></span><span class="pin-label">Keeping Wild Animals Wild</span> 9231 </button> 9232 <button class="pin" type="button" 9233 data-name="Saving the Cross River Gorilla" 9234 data-ngo="African Conservation Foundation" 9235 data-where="Cameroon (UK charity)" 9236 data-coords="6.00°N · 9.40°E" 9237 data-status="project-active" 9238 data-stat="Active project" 9239 data-desc="Ecoflix supports the African Conservation Foundation as it rallies communities across Cameroon to protect the Cross River gorilla, one of the rarest apes on Earth." 9240 data-img="https://ecoflix.com/wp-content/uploads/2023/03/p3dm-in-south-west-cameroon.jpg" 9241 data-href="/projects/saving-the-cross-river-gorilla/"> 9242 <span class="pin-dot"></span><span class="pin-label">Saving the Cross River Gorilla</span> 9243 </button> 9244 <button class="pin" type="button" 9245 data-name="Freeing Lucy the Elephant" 9246 data-ngo="LEAP for Lucy" 9247 data-where="Edmonton, Canada" 9248 data-coords="53.55°N · 113.49°W" 9249 data-status="project-urgent" 9250 data-stat="Urgent project" 9251 data-desc="Ecoflix backs LEAP for Lucy â the campaign to move Lucy, a lone, ageing elephant, from a cold Canadian zoo to a sanctuary where she can finally live among her own kind." 9252 data-img="https://ecoflix.com/wp-content/uploads/2023/03/92de7f_c52bcfad8ddd4889a80e35753b295a067Emv2_d_2421_1800_s_2-1024x762.png" 9253 data-href="/projects/freeing-lucy-the-elephant/"> 9254 <span class="pin-dot"></span><span class="pin-label">Freeing Lucy the Elephant</span> 9255 </button> 9256 <button class="pin" type="button" 9257 data-name="Rescuing Africa's National Parks" 9258 data-ngo="National Park Rescue" 9259 data-where="Africa (UK charity)" 9260 data-coords="13.13°S · 27.85°E" 9261 data-status="project-active" 9262 data-stat="Active project" 9263 data-desc="Ecoflix supports National Park Rescue, which puts rangers and frontline protection into African national parks on the brink of collapse." 9264 data-img="https://ecoflix.com/wp-content/uploads/2023/03/Image-1.jpg" 9265 data-href="/projects/rescuing-africas-national-parks/">
9266 <span class="pin-dot"></span><span class="pin-label">Rescuing Africa's National Parks</span> 9267 </button> 9268 <button class="pin" type="button" 9269 data-name="Global Rescue for Animals in Crisis" 9270 data-ngo="International Fund for Animal Welfare (IFAW)" 9271 data-where="Massachusetts, USA (global)" 9272 data-coords="41.66°N · 70.30°W" 9273 data-status="project-active" 9274 data-stat="Active project" 9275 data-desc="Ecoflix supports IFAW, a global force rescuing animals from disasters and trafficking and protecting the wild places they depend on." 9276 data-img="https://ecoflix.com/wp-content/uploads/2023/03/325362_124A8929_MMRR_2021-09-17_PointOfRocksLandingBeach-Brewster-CapeCod-MA_4CommonDolphinsMassStranding-Rescue_AndreaSpence_5D_EDITED.jpg" 9277 data-href="/projects/global-rescue-for-animals-in-crisis/"> 9278 <span class="pin-dot"></span><span class="pin-label">Global Rescue for Animals in Crisis</span> 9279 </button> 9280 <button class="pin" type="button" 9281 data-name="Rebuilding Borneo's Wildlife Corridors" 9282 data-ngo="Danau Girang Field Centre" 9283 data-where="Sabah, Borneo, Malaysia" 9284 data-coords="5.41°N · 118.04°E" 9285 data-status="project-active" 9286 data-stat="Active project" 9287 data-desc="Ecoflix backs the Danau Girang Field Centre in Borneo, building wildlife corridors and replanting rainforest so orangutans, elephants and clouded leopards can move and thrive again." 9288 data-img="https://ecoflix.com/wp-content/uploads/2023/03/Kinabatanganriverandoxbowlake_aerial.jpg" 9289 data-href="/projects/rebuilding-borneos-wildlife-corridors/"> 9290 <span class="pin-dot"></span><span class="pin-label">Rebuilding Borneo's Wildlife Corridors</span> 9291 </button> 9292 <button class="pin" type="button" 9293 data-name="Turning a Hunting Ground into a Reserve" 9294 data-ngo="Xudumela Conservancy" 9295 data-where="Okavango Delta, Botswana" 9296 data-coords="19.27°S · 22.85°E" 9297 data-status="project-active" 9298 data-stat="Active project" 9299 data-desc="A 1,750-acre stretch of the southern Okavango Delta, converted from a hunting reserve into a working conservation sanctuary. Guest nights fund anti-poaching patrols through the Connect Trust." 9300 data-img="https://xudumela-full.vercel.app/assets/images/Drone-Shot-of-Camp-from-South.jpg" 9301 data-href="/projects/xudumela/"> 9302 <span class="pin-dot"></span><span class="pin-label">Turning a Hunting Ground into a Reserve</span> 9303 </button> 9304 <button class="pin" type="button" 9305 data-name="Championing Independent Conservation Film" 9306 data-ngo="TCIFF Inc" 9307 data-where="" 9308 data-coords="40.71°N · 74.01°W" 9309 data-status="project-completed" 9310 data-stat="Completed project" 9311 data-desc="Ecoflix sponsored an independent film festival spotlighting conservation-minded film-making and emerging storytellers." 9312 data-img="" 9313 data-href="/projects/championing-independent-conservation-film/"> 9314 <span class="pin-dot"></span><span class="pin-label">Championing Independent Conservation Film</span> 9315 </button> 9316 <button class="pin" type="button" 9317 data-name="Wildlife Stories on the Public Airwaves" 9318 data-ngo="Australian Broadcasting Corp" 9319 data-where="Australia" 9320 data-coords="33.87°S · 151.21°E" 9321 data-status="project-completed" 9322 data-stat="Completed project" 9323 data-desc="Ecoflix's partnership with the ABC helped carry wildlife and conservation programming to a national broadcast audience." 9324 data-img="" 9325 data-href="/projects/wildlife-stories-on-the-public-airwaves/"> 9326 <span class="pin-dot"></span><span class="pin-label">Wildlife Stories on the Public Airwaves</span> 9327 </button> 9328 <button class="pin" type="button" 9329 data-name="Getting Wildlife Films to the World" 9330 data-ngo="Flame Distribution Ltd" 9331 data-where="Australia" 9332 data-coords="33.87°S · 151.21°E" 9333 data-status="project-completed" 9334 data-stat="Completed project" 9335 data-desc="Ecoflix worked with distributor Flame Distribution to carry wildlife and conservation programming onto screens
9335worldwide." 9336 data-img="" 9337 data-href="/projects/getting-wildlife-films-to-the-world/"> 9338 <span class="pin-dot"></span><span class="pin-label">Getting Wildlife Films to the World</span> 9339 </button> 9340 <button class="pin" type="button" 9341 data-name="'It's Up To Us': Animating the Fight for the Planet" 9342 data-ngo="Unanico Ltd" 9343 data-where="London, UK" 9344 data-coords="51.51°N · 0.13°W" 9345 data-status="project-completed" 9346 data-stat="Completed project" 9347 data-desc="Ecoflix supported Unanico's animated film It's Up To Us, narrated by Leona Lewis and built on King Charles III's Terra Carta, calling on audiences to put nature, people and planet first." 9348 data-img="" 9349 data-href="/projects/its-up-to-us-animating-the-fight-for-the-planet/"> 9350 <span class="pin-dot"></span><span class="pin-label">'It's Up To Us': Animating the Fight for the Planet</span> 9351 </button> 9352 <button class="pin" type="button" 9353 data-name="African Stories of People, Nature & Survival" 9354 data-ngo="Taye Balogun" 9355 data-where="" 9356 data-coords="9.08°N · 7.40°E" 9357 data-status="project-completed" 9358 data-stat="Completed project" 9359 data-desc="Ecoflix backed award-winning Nigerian film-maker Taye Balogun, whose documentaries spotlight ecological protection, indigenous knowledge and the communities on the front line of change across Africa." 9360 data-img="" 9361 data-href="/projects/african-stories-of-people-nature-and-survival/"> 9362 <span class="pin-dot"></span><span class="pin-label">African Stories of People, Nature & Survival</span> 9363 </button> 9364 <button class="pin" type="button" 9365 data-name="Free Billy: One Elephant's Fight for Sanctuary" 9366 data-ngo="Marshall Corwin" 9367 data-where="United Kingdom" 9368 data-coords="51.51°N · 0.13°W" 9369 data-status="project-completed" 9370 data-stat="Completed project" 9371 data-desc="Ecoflix backed filmmaker Marshall Corwin to tell Billy's story: a wild-born elephant held at LA Zoo for decades, and the campaign to win him a place at a sanctuary. In May 2025 the zoo moved Billy and Tina to Tulsa Zoo rather than a sanctuary, so the fight for his retirement continues." 9372 data-img="" 9373 data-href="/projects/free-billy-one-elephants-fight-for-sanctuary/"> 9374 <span class="pin-dot"></span><span class="pin-label">Free Billy: One Elephant's Fight for Sanctuary</span> 9375 </button> 9376 <button class="pin" type="button" 9377 data-name="When the Ocean Turns Black: Preventing Peru's Oil Spills" 9378 data-ngo="Levy Yamamori Ran" 9379 data-where="" 9380 data-coords="11.90°S · 77.13°W" 9381 data-status="project-completed" 9382 data-stat="Completed project" 9383 data-desc="Ecoflix backed film-maker Ran Levy-Yamamori, whose film When the Ocean Turns Black follows his journey to Peru to understand and help prevent the oil spills devastating its coastline and marine life." 9384 data-img="" 9385 data-href="/projects/when-the-ocean-turns-black-preventing-perus-oil-spills/"> 9386 <span class="pin-dot"></span><span class="pin-label">When the Ocean Turns Black: Preventing Peru's Oil Spills</span> 9387 </button> 9388 <button class="pin" type="button" 9389 data-name="Developing the Next Wave of Nature Films" 9390 data-ngo="Screenstory Ltd" 9391 data-where="United Kingdom" 9392 data-coords="51.51°N · 0.13°W" 9393 data-status="project-completed" 9394 data-stat="Completed project" 9395 data-desc="Ecoflix backed Screenstory, a natural-history and specialist-factual company developing new environmental films for global audiences." 9396 data-img="" 9397 data-href="/projects/developing-the-next-wave-of-nature-films/"> 9398 <span class="pin-dot"></span><span class="pin-label">Developing the Next Wave of Nature Films</span> 9399 </button> 9400 <button class="pin" type="button" 9401 data-name="Eye to Eye with the Ocean's Giants" 9402 data-ngo="André Musgrove" 9403 data-where="Bahamas" 9404 data-coords="24.70°N · 77.90°W" 9405 data-status="project-completed" 9406 data-stat="Completed project" 9407 data-desc="Ecoflix backed Bahamian underwater film-maker André Musgrove, whose breath-hold storytelling brings audiences face to face with sharks and ocean giants, building the case to protect them." 9408 data-img=""
9409 data-href="/projects/eye-to-eye-with-the-oceans-giants/"> 9410 <span class="pin-dot"></span><span class="pin-label">Eye to Eye with the Ocean's Giants</span> 9411 </button> 9412 <button class="pin" type="button" 9413 data-name="Scoring the Stories of Nature" 9414 data-ngo="Downbeat Music Management" 9415 data-where="" 9416 data-coords="51.51°N · 0.13°W" 9417 data-status="project-completed" 9418 data-stat="Completed project" 9419 data-desc="Ecoflix supported Downbeat to give its conservation films their emotional voice through original music." 9420 data-img="" 9421 data-href="/projects/scoring-the-stories-of-nature/"> 9422 <span class="pin-dot"></span><span class="pin-label">Scoring the Stories of Nature</span> 9423 </button> 9424 <button class="pin" type="button" 9425 data-name="The Tigers of Scotland: Saving the Wildcat" 9426 data-ngo="Wild Tiger Films" 9427 data-where="London, UK" 9428 data-coords="57.12°N · 4.71°W" 9429 data-status="project-completed" 9430 data-stat="Completed project" 9431 data-desc="Ecoflix supported Wild Tiger Films, makers of The Tigers of Scotland, telling the story of Britain's critically endangered wildcat." 9432 data-img="" 9433 data-href="/projects/the-tigers-of-scotland-saving-the-wildcat/"> 9434 <span class="pin-dot"></span><span class="pin-label">The Tigers of Scotland: Saving the Wildcat</span> 9435 </button> 9436 </div> 9437 9438 <aside class="globe-aside globe-aside-right reveal"> 9439 <div class="globe-card" id="globeCard" aria-live="polite"> 9440 <div class="gc-empty"> 9441 <span class="gc-eyebrow">Select a pin</span> 9442 <h4 class="gc-empty-title">Every donation lands somewhere specific.</h4> 9443 <p class="gc-empty-hint">Click any pin on the globe to see which NGO it funds, what work is happening on the ground, and how to support it directly.</p> 9444 </div> 9445 <div class="gc-detail" hidden> 9446 <button class="gc-close" id="gcClose" type="button" aria-label="Close detail">×</button> 9447 <div class="gc-img" id="gcImg" hidden aria-hidden="true"></div> 9448 <span class="gc-status" id="gcStatus">Active campaign</span> 9449 <div class="gc-loc"> 9450 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2C8 2 5 5 5 9c0 5.5 7 13 7 13s7-7.5 7-13c0-4-3-7-7-7z"/><circle cx="12" cy="9" r="2.5"/></svg> 9451 <span id="gcWhere">â</span> 9452 </div> 9453 <div class="gc-coords" id="gcCoords">â</div> 9454 <h3 class="gc-name" id="gcName">â</h3> 9455 <div class="gc-ngo" id="gcNgo">â</div> 9456 <p class="gc-desc" id="gcDesc">â</p> 9457 <div class="gc-stat-box"><span>On the ground</span><strong id="gcStat">â</strong></div> 9458 <a class="gc-cta" id="gcCta" href="/projects/">Support this project <span class="arrow">â</span></a> 9459 </div> 9460 </div> 9461 </aside> 9462 </div><!-- /globe-stage --> 9463 9464 <!-- Reusable popup, populated by JS on pin click --> 9465 <div class="map-popup" id="mapPopup" role="dialog" aria-modal="false" aria-hidden="true"> 9466 <div class="mp-img" id="mpImg"></div> 9467 <span class="mp-status" id="mpStatus">Active</span> 9468 <button class="mp-close" id="mpClose" type="button" aria-label="Close popup">Ã</button> 9469 <div class="mp-body"> 9470 <div class="mp-location"><svg viewBox="0 0 24 24"><path d="M12 2C8 2 5 5 5 9c0 5.5 7 13 7 13s7-7.5 7-13c0-4-3-7-7-7z" stroke-linecap="round" stroke-linejoin="round"/><circle cx="12" cy="9" r="2.5" stroke-linecap="round" stroke-linejoin="round"/></svg><span id="mpWhere">â</span><span style="color:var(--mist-2);margin-left:auto;font-weight:500" id="mpCoords">â</span></div> 9471 <h3 id="mpName">â</h3> 9472 <div class="mp-ngo" id="mpNgo">â</div> 9473 <p id="mpDesc">â</p> 9474 <div class="mp-stat"><strong id="mpStat">â</strong></div> 9475 <a class="mp-cta" id="mpCta" href="/projects/">Support this project <span class="arrow">â</span></a> 9476 </div> 9477 </div> 9478 9479 <div class="globe-legend"> 9480 <div><span class="glg-dot glg-feature"></span> Featured project</div> 9481 <div><span class="glg-dot glg-active"></span> Active campaign</div> 9482 <div><span class="glg-dot glg-urgent"></span> Urgent funding need</div> 9483 <div style="margin-left:auto;
9483color:var(--mist-2);font-size:12px;letter-spacing:.02em">Tap a pin for project detail</div> 9484 </div> 9485 9486 <div class="map-summary"> 9487 <div class="ms is-feature"> 9488 <b>4</b><span>Featured</span> 9489 <span class="ms-icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 3l2.6 6.4L21 10l-5 4.4L17.4 21 12 17.7 6.6 21 8 14.4 3 10l6.4-.6z"/></svg></span> 9490 </div> 9491 <div class="ms is-active"> 9492 <b>20</b><span>Active campaigns</span> 9493 <span class="ms-icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12h4l2-6 4 12 2-6h6"/></svg></span> 9494 </div> 9495 <div class="ms is-urgent"> 9496 <b>1</b><span>Urgent funding</span> 9497 <span class="ms-icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3L2 21h20z"/><line x1="12" y1="10" x2="12" y2="15"/><line x1="12" y1="18" x2="12.01" y2="18"/></svg></span> 9498 </div> 9499 <div class="ms"> 9500 <b>6</b><span>Continents</span> 9501 <span class="ms-icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M3 12h18"/><path d="M12 3a14 14 0 010 18"/><path d="M12 3a14 14 0 000 18"/></svg></span> 9502 </div> 9503 </div> 9504 </div> 9505</section> 9506 9507<!-- ================================================= 9508 WHERE YOU FIT IN â navigator's dispatch slip 9509 Not another globe. A compact cartographic flourish that 9510 answers two questions: "what are my coordinates" and 9511 "which partner NGOs are nearest to me, in which direction". 9512 Built like a vintage field-log card: big coordinate stamp, 9513 a small compass rose with spokes radiating toward each of 9514 the closest NGOs, and a typed bearings list. 9515 Data: /api/geo (Vercel edge IP geo, no permission prompt) 9516 /assets/ngos.json (27 partner NGOs, real lat/lon) 9517 ================================================= --> 9518<section class="wyf-section section-lift" id="wyf" aria-labelledby="wyfH"> 9519 <style> 9520 .wyf-section{ 9521 position:relative;padding:90px var(--pad-x) 100px;overflow:hidden;isolation:isolate; 9522 background:linear-gradient(180deg,var(--ink),#050b1f); 9523 } 9524 .wyf-section::before{ 9525 content:"";position:absolute;inset:-15% -5%;z-index:-1; 9526 background:radial-gradient(40% 50% at 25% 30%,rgba(168,243,65,.10),transparent 70%), 9527 radial-gradient(35% 45% at 78% 70%,rgba(168,243,65,.06),transparent 70%); 9528 filter:blur(60px);pointer-events:none; 9529 } 9530 /* Faint cartograph latitudes/meridians across the whole section */ 9531 .wyf-bg{position:absolute;inset:0;z-index:-1;pointer-events:none;opacity:.55} 9532 .wyf-bg .bg-lat{stroke:rgba(168,243,65,.10);stroke-width:1;stroke-dasharray:2 18;fill:none} 9533 .wyf-bg .bg-trail-soft{stroke:rgba(168,243,65,.06);stroke-width:1;fill:none} 9534 9535 .wyf-head{text-align:center;max-width:760px;margin:0 auto 44px;position:relative;z-index:2} 9536 .wyf-head .eyebrow{display:inline-flex;margin:0 auto 14px} 9537 .wyf-head h2{font-family:var(--display);font-weight:800;font-size:clamp(32px,4.6vw,56px);line-height:1.02;letter-spacing:-.025em;margin:0 0 14px;color:var(--bone)} 9538 .wyf-head h2 em{font-style:italic;font-weight:500;color:var(--leaf);-webkit-text-fill-color:var(--leaf);} 9539 .wyf-head p{font-size:16.5px;color:var(--mist);line-height:1.6;max-width:58ch;margin:0 auto} 9540 9541 /* === Dispatch slip â outer card === 9542 3-col on desktop: coords/compass · NGOs by bearing · wild places. 9543 Stacks gracefully on smaller screens. */ 9544 .wyf-slip{ 9545 position:relative;max-width:1280px;margin:0 auto; 9546 display:grid;grid-template-columns:minmax(260px,320px) 1fr 1fr; 9547 gap:0;align-items:stretch; 9548 background: 9549 linear-gradient(180deg,rgba(2,7,24,.85),rgba(2,7,24,.95)), 9550 repeating-linear-gradient(0deg, transparent 0 23px, rgba(168,243,65,.04) 23px 24px); 9551 border:1px solid rgba(168,243,65,.32); 9552 border-radius:20px;overflow:hidden; 9553 box-shadow:0 30px 80px rgba(0,0,0,.45), inset 0 0 0 1px rgba(255,255,255,.02); 9554 } 9555 @media (max-width:1080px){.wyf-slip{grid-template-columns:minmax(260px,320px) 1fr}} 9556 @media (max-width:780px){.wyf-slip{grid-template-columns:1fr}} 9557 /* Punched-card corner cut: pseudo-elements add two notched corners */ 9558 .wyf-slip::before, .wyf-slip::after{ 9559 content:"";position:absolute;width:18px;height:18px; 9560 background:#050b1f;border-radius:50%; 9561 border:1px solid rgba(168,243,65,.32); 9562 } 9563 .wyf-slip::before{top:-10px;left:50%;transform:translateX(-50%)} 9564 .wyf-slip::after{bottom:-10px;left:50%;transform:translateX(-50%)} 9565 9566 /* === Left side â coordinates + compass === */ 9567 .wyf-coords-card{ 9568 position:relative;padding:30px 28px; 9569 display:flex;flex-direction:column;gap:18px; 9570 border-right:1px dashed rgba(168,243,65,.22); 9571 } 9572 @media (max-width:780px){.wyf-coords-card{border-right:none;border-bottom:1px dashed rgba(168,243,65,.22)}} 9573 .wyf-station{ 9574 display:inline-flex;align-items:center;gap:8px; 9575 font-family:var(--display);font-weight:700;font-size:10.5px; 9576 letter-spacing:.22em;text-transform:uppercase;color:var(--leaf); 9577 } 9578 .wyf-station::before{content:"â"} 9579 .wyf-where{ 9580 font-family:var(--display);font-weight:800;font-size:clamp(20px,2.4vw,28px); 9581 line-height:1.15;letter-spacing:-.01em;color:var(--bone); 9582 min-height:1.2em; 9583 } 9584 .wyf-where .flag{margin-right:6px;font-size:.85em;vertical-align:1px} 9585 9586 /* The coordinate stamp â the hero element */ 9587 .wyf-stamp{ 9588 display:flex;flex-direction:column;gap:6px; 9589 padding:18px 0;border-top:1px dashed rgba(168,243,65,.22); 9590 border-bottom:1px dashed rgba(168,243,65,.22); 9591 } 9592 .wyf-stamp-row{ 9593 display:flex;align-items:baseline;justify-content:space-between;gap:14px; 9594 font-feature-settings:"tnum"; 9595 } 9596 .wyf-stamp-row .lbl{ 9597 font-family:var(--display);font-weight:700;font-size:10px; 9598 letter-spacing:.24em;text-transform:uppercase;
9598color:var(--mist-2); 9599 flex:0 0 auto; 9600 } 9601 .wyf-stamp-row .val{ 9602 font-family:var(--display);font-weight:900;font-size:clamp(22px,3.2vw,32px); 9603 letter-spacing:-.005em;color:var(--bone);line-height:1; 9604 text-align:right;font-variant-numeric:tabular-nums; 9605 } 9606 .wyf-stamp-row .val .dir{color:var(--leaf);font-weight:700;font-size:.7em;margin-left:6px;vertical-align:1px;letter-spacing:.04em} 9607 9608 /* Mini globe â orthographic projection centred on the visitor's 9609 lat/lon. Replaces the previous abstract compass rose. */ 9610 .wyf-globe{ 9611 align-self:center;width:220px;height:220px;position:relative; 9612 } 9613 .wyf-globe svg{width:100%;height:100%;display:block;overflow:visible} 9614 .wyf-globe .globe-disc{fill:url(#wyfGlobeShade)} 9615 .wyf-globe .globe-ring{fill:none;stroke:rgba(168,243,65,.55);stroke-width:1.2} 9616 .wyf-globe .glob-lat, 9617 .wyf-globe .glob-lon{fill:none;stroke:rgba(168,243,65,.22);stroke-width:.8;stroke-dasharray:2 4} 9618 .wyf-globe .ngo-dot{ 9619 fill:var(--leaf); 9620 filter:drop-shadow(0 0 4px rgba(168,243,65,.75)); 9621 opacity:.92;transition:r .2s ease; 9622 } 9623 .wyf-globe .ngo-dot.is-nearest{ 9624 fill:#D3FA9E; 9625 filter:drop-shadow(0 0 6px rgba(216,255,144,1)); 9626 animation:wyf-dot-pulse 2.2s ease-in-out infinite; 9627 } 9628 .wyf-globe .ngo-arc{ 9629 fill:none;stroke:rgba(168,243,65,.32);stroke-width:.9; 9630 stroke-dasharray:3 4;stroke-linecap:round; 9631 animation:wyf-spin 8s linear infinite; 9632 } 9633 .wyf-globe .you-glow{fill:rgba(216,255,144,.30);animation:wyf-pulse 2.2s ease-in-out infinite} 9634 .wyf-globe .you-ring{fill:none;stroke:#D3FA9E;stroke-width:1.2;opacity:.7;animation:wyf-ring 2.2s ease-in-out infinite} 9635 .wyf-globe .you-pin{fill:#fff;stroke:#020718;stroke-width:1.2;filter:drop-shadow(0 0 6px rgba(216,255,144,1))} 9636 @keyframes wyf-spin{to{stroke-dashoffset:-30}} 9637 @keyframes wyf-pulse{0%,100%{r:10;opacity:.25}50%{r:14;opacity:.5}} 9638 @keyframes wyf-ring{0%{r:8;opacity:.9}100%{r:22;opacity:0}} 9639 @keyframes wyf-dot-pulse{0%,100%{r:5;opacity:.95}50%{r:7;opacity:1}} 9640 @media (prefers-reduced-motion: reduce){ 9641 .wyf-globe .ngo-arc, 9642 .wyf-globe .ngo-dot.is-nearest, 9643 .wyf-globe .you-glow, 9644 .wyf-globe .you-ring{animation:none} 9645 } 9646 .wyf-compass-foot{ 9647 font-family:var(--display);font-weight:700;font-size:10px;letter-spacing:.22em; 9648 text-transform:uppercase;color:var(--mist-2);text-align:center;margin-top:4px; 9649 } 9650 .wyf-compass-foot b{color:var(--leaf);font-weight:800} 9651 9652 /* === Right side â bearings list === */ 9653 .wyf-bearings{ 9654 padding:30px 28px;display:flex;flex-direction:column;gap:0;min-width:0; 9655 } 9656 /* Proper section-scale column header â eyebrow over big display 9657 headline over subtitle, like the rest of the site's hero stacks. */ 9658 .wyf-bearings-head, .wyf-parks-head{ 9659 display:flex;flex-direction:column;gap:6px; 9660 padding-bottom:18px;margin-bottom:14px; 9661 border-bottom:1px dashed rgba(168,243,65,.22); 9662 font-family:var(--display); 9663 } 9664 .wyf-bearings-head .eyebrow, .wyf-parks-head .eyebrow{ 9665 display:inline-flex;align-items:center;gap:8px; 9666 font-weight:700;font-size:10px;letter-spacing:.24em; 9667 text-transform:uppercase;color:var(--leaf); 9668 } 9669 .wyf-bearings-head .eyebrow::before, .wyf-parks-head .eyebrow::before{ 9670 content:"";width:6px;height:6px;border-radius:50%;background:var(--leaf); 9671 box-shadow:0 0 6px var(--leaf-glow); 9672 } 9673 .wyf-bearings-head h3, .wyf-parks-head h3{ 9674 font-weight:800;font-size:clamp(22px,2.4vw,30px); 9675 line-height:1.04;letter-spacing:-.02em;color:var(--bone);margin:0; 9676 } 9677 .wyf-bearings-head h3 em, .wyf-parks-head h3 em{ 9678 font-style:italic;font-weight:500;color:var(--leaf); 9679 } 9680 .wyf-bearings-head .sub, .wyf-parks-head .sub{ 9681 font-family:var(--body);font-size:12.5px;color:var(--mist-2); 9682 letter-spacing:.005em;line-height:1.4; 9683 } 9684 /* Legacy .count chip from the previous design â keep but restyle so 9685 any leftover JS that writes to it still has a sensible target. */ 9686 .wyf-bearings-head .count, .wyf-parks-head .count{ 9687 font-family:var(--body);font-size:11.5px;
9687color:var(--mist-2); 9688 letter-spacing:.04em;text-transform:none;font-weight:500; 9689 } 9690 /* Stack-of-cards layout â each .wyf-bearings-row is a self-contained 9691 grid; this container just stacks them vertically. */ 9692 .wyf-bearings-table{ 9693 display:flex;flex-direction:column;gap:0; 9694 font-family:var(--display); 9695 } 9696 /* The bearings list is now a stack of cards, not a 3-col grid table. 9697 Each card has a NUMBER chip + name+location + distance + bearing. 9698 The FIRST card ("Nearest one") gets a featured treatment. */ 9699 .wyf-bearings-row{ 9700 position:relative;display:grid; 9701 grid-template-columns:auto 1fr auto; 9702 grid-template-areas: 9703 "rank name dist" 9704 "rank meta dist"; 9705 gap:2px 14px;align-items:center; 9706 padding:14px 4px;border-bottom:1px dashed rgba(168,243,65,.12); 9707 color:inherit;text-decoration:none; 9708 transition:background .2s ease, transform .15s ease; 9709 border-radius:10px; 9710 } 9711 .wyf-bearings-row:hover, .wyf-bearings-row.is-active{ 9712 background:rgba(168,243,65,.06); 9713 } 9714 .wyf-bearings-row:hover .bear-arrow{transform:translateY(-1px)} 9715 /* Rank chip (01, 02, 03â¦) */ 9716 .wyf-bearings-row .rank{ 9717 grid-area:rank; 9718 width:30px;height:30px;flex:0 0 30px;border-radius:8px; 9719 display:flex;align-items:center;justify-content:center; 9720 background:rgba(168,243,65,.08);color:var(--leaf); 9721 box-shadow:inset 0 0 0 1px rgba(168,243,65,.30); 9722 font-family:var(--display);font-weight:900;font-size:11px; 9723 letter-spacing:.04em;font-feature-settings:"tnum"; 9724 } 9725 /* NGO name = the headline of the card */ 9726 .wyf-bearings-row .who{ 9727 grid-area:name;min-width:0; 9728 } 9729 .wyf-bearings-row .who .nm{ 9730 display:block;font-family:var(--display);font-weight:800;font-size:16px; 9731 color:var(--bone);letter-spacing:-.005em;line-height:1.2; 9732 white-space:nowrap;overflow:hidden;text-overflow:ellipsis; 9733 } 9734 /* Bearing + location underline as subtitle */ 9735 .wyf-bearings-row .meta{ 9736 grid-area:meta;display:flex;align-items:center;gap:8px;min-width:0; 9737 font-family:var(--body);font-size:11.5px;color:var(--mist); 9738 font-feature-settings:"tnum";line-height:1.3; 9739 } 9740 .wyf-bearings-row .meta .bear-arrow{ 9741 width:18px;height:18px;flex:0 0 18px;border-radius:50%; 9742 display:flex;align-items:center;justify-content:center; 9743 background:rgba(168,243,65,.10);color:var(--leaf); 9744 box-shadow:inset 0 0 0 1px rgba(168,243,65,.30); 9745 } 9746 .wyf-bearings-row .meta .bear-arrow svg{width:10px;height:10px;transition:transform .3s cubic-bezier(.2,.7,.2,1)} 9747 .wyf-bearings-row .meta .bear-card{ 9748 font-family:var(--display);font-weight:700;color:var(--leaf); 9749 font-size:11px;letter-spacing:.18em;text-transform:uppercase; 9750 } 9751 .wyf-bearings-row .meta .bear-deg{color:var(--mist-2);font-weight:500;font-size:10.5px;letter-spacing:.05em} 9752 .wyf-bearings-row .meta .wh{ 9753 color:var(--mist-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis; 9754 flex:1;min-width:0;font-family:var(--body); 9755 } 9756 .wyf-bearings-row .meta .sep{color:var(--mist-2);opacity:.5} 9757 /* Distance column */ 9758 .wyf-bearings-row .dist{ 9759 grid-area:dist;align-self:center;text-align:right; 9760 font-family:var(--display);font-weight:900;font-size:15px;color:var(--leaf); 9761 font-variant-numeric:tabular-nums;letter-spacing:-.005em; 9762 min-width:64px; 9763 } 9764 .wyf-bearings-row .dist .u{ 9765 display:block;color:var(--mist-2);font-weight:600;font-size:9.5px; 9766 letter-spacing:.16em;text-transform:uppercase;margin-top:1px; 9767 } 9768 9769 /* Featured first row â pulled forward visually */ 9770 .wyf-bearings-row.is-featured{ 9771 background:linear-gradient(180deg,rgba(168,243,65,.10),rgba(168,243,65,.02)); 9772 border:1px solid rgba(168,243,65,.30); 9773 padding:18px 14px;margin-bottom:6px; 9774 box-shadow:inset 0 0 0 1px rgba(168,243,65,.04), 0 8px 24px rgba(0,0,0,.25); 9775 } 9776 .wyf-bearings-row.is-featured .rank{ 9777 width:36px;height:36px;flex:0 0 36px;border-radius:10px;font-size:12.5px; 9778 background:rgba(168,243,65,.15);box-shadow:inset 0 0 0 1px rgba(168,243,65,.55); 9779 } 9780 .wyf-bearings-row.is-featured .who .nm{font-size:20px;font-weight:900;letter-spacing:-.01em} 9781 .wyf-bearings-row.is-featured .dist{font-size:20px} 9782 .wyf-bearings-row.is-featured .rank::after{ 9783 content:"NEAREST";position:absolute;top:6px;right:14px; 9784 font-family:var(--display);font-weight:800;font-size:9px; 9785 letter-spacing:.22em;color:var(--leaf); 9786 padding:3px 8px;border-radius:999px; 9787 background:rgba(2,7,24,.6);border:1px solid rgba(168,243,65,.40); 9788 } 9789 .wyf-bearings-foot{ 9790 margin-top:18px;display:flex;align-items:center;justify-content:space-between; 9791 gap:14px;flex-wrap:wrap;padding-top:14px;border-top:1px dashed rgba(168,243,65,.22); 9792 } 9793 .wyf-bearings-foot .note{font-size:12px;
9793color:var(--mist-2);letter-spacing:.02em} 9794 .wyf-bearings-foot .note b{color:var(--bone);font-weight:600} 9795 .wyf-bearings-foot .more{ 9796 display:inline-flex;align-items:center;gap:6px; 9797 font-family:var(--display);font-weight:800;font-size:11.5px; 9798 letter-spacing:.18em;text-transform:uppercase;color:var(--leaf); 9799 text-decoration:none;padding-bottom:2px; 9800 border-bottom:1px solid rgba(168,243,65,.45); 9801 transition:gap .2s ease, color .2s ease; 9802 } 9803 .wyf-bearings-foot .more:hover{gap:12px;color:#D3FA9E} 9804 9805 .wyf-loading{font-size:12.5px;color:var(--mist-2);font-family:var(--display);font-weight:600;letter-spacing:.04em;display:inline-flex;align-items:center;gap:8px} 9806 .wyf-loading::before{content:"";width:8px;height:8px;border-radius:50%;background:var(--leaf);animation:wyf-blink 1.2s ease-in-out infinite} 9807 @keyframes wyf-blink{0%,100%{opacity:1}50%{opacity:.35}} 9808 9809 /* === Third column â wild places near you === */ 9810 .wyf-parks{ 9811 padding:30px 28px;display:flex;flex-direction:column;gap:0;min-width:0; 9812 border-left:1px dashed rgba(168,243,65,.22); 9813 } 9814 @media (max-width:1080px){ 9815 .wyf-parks{ 9816 border-left:none;border-top:1px dashed rgba(168,243,65,.22); 9817 grid-column:1 / -1; 9818 } 9819 } 9820 .wyf-parks-head{ 9821 display:flex;align-items:baseline;justify-content:space-between;gap:14px; 9822 padding-bottom:14px;margin-bottom:6px; 9823 border-bottom:1px dashed rgba(168,243,65,.22); 9824 font-family:var(--display);font-weight:700;font-size:10.5px; 9825 letter-spacing:.22em;text-transform:uppercase;color:var(--leaf); 9826 } 9827 .wyf-parks-head .count{color:var(--mist-2)} 9828 .wyf-parks-list{display:flex;flex-direction:column;gap:0;list-style:none;padding:0;margin:0} 9829 /* Park rows mirror the bearings-row "card" style: flag tile + rank, 9830 big park name as headline, type chip + wildlife as subtitle, 9831 distance on the right. First row gets the featured treatment. */ 9832 .wyf-park-row{ 9833 position:relative;display:grid; 9834 grid-template-columns:auto auto 1fr auto; 9835 grid-template-areas: 9836 "flag rank name dist" 9837 "flag rank tag dist" 9838 ". . wild wild"; 9839 gap:2px 12px;align-items:center; 9840 padding:14px 4px;border-bottom:1px dashed rgba(168,243,65,.12); 9841 border-radius:10px; 9842 transition:background .2s ease; 9843 } 9844 .wyf-park-row:last-child{border-bottom:none} 9845 .wyf-park-row:hover, .wyf-park-row.is-active{background:rgba(168,243,65,.06)} 9846 .wyf-park-row .pk-flag{ 9847 grid-area:flag;align-self:center; 9848 width:36px;height:36px;flex:0 0 36px;border-radius:10px; 9849 display:flex;align-items:center;justify-content:center; 9850 background:rgba(168,243,65,.10);box-shadow:inset 0 0 0 1px rgba(168,243,65,.30); 9851 font-size:18px;line-height:1; 9852 } 9853 .wyf-park-row .pk-rank{ 9854 grid-area:rank;align-self:center; 9855 font-family:var(--display);font-weight:900;font-size:11px; 9856 letter-spacing:.04em;color:var(--leaf);font-variant-numeric:tabular-nums; 9857 } 9858 .wyf-park-row .pk-name{ 9859 grid-area:name; 9860 font-family:var(--display);font-weight:800;font-size:15.5px;color:var(--bone); 9861 letter-spacing:-.005em;line-height:1.2;text-decoration:none; 9862 white-space:nowrap;overflow:hidden;text-overflow:ellipsis; 9863 min-width:0;align-self:end; 9864 } 9865 .wyf-park-row .pk-name:hover{color:var(--leaf)} 9866 .wyf-park-row .pk-tag{ 9867 grid-area:tag;align-self:start; 9868 font-family:var(--display);font-weight:700;font-size:9.5px;letter-spacing:.18em; 9869 text-transform:uppercase;color:var(--leaf); 9870 } 9871 .wyf-park-row .pk-wild{ 9872 grid-area:wild; 9873 font-family:var(--body);font-size:12px;color:var(--mist);margin-top:6px; 9874 padding-top:6px;border-top:1px dashed rgba(168,243,65,.10); 9875 line-height:1.4; 9876 } 9877 .wyf-park-row .pk-wild-lbl{ 9878 font-family:var(--display);font-weight:700;font-size:9.5px;letter-spacing:.20em; 9879 text-transform:uppercase;color:var(--mist-2);margin-right:6px; 9880 } 9881 .wyf-park-row .pk-dist{ 9882 grid-area:dist;align-self:center;text-align:right; 9883 font-family:var(--display);font-weight:900;font-size:15px;color:var(--leaf); 9884 font-variant-numeric:tabular-nums;letter-spacing:-.005em;min-width:64px; 9885 } 9886 .wyf-park-row .pk-dist .u{ 9887 display:block;
9887color:var(--mist-2);font-weight:600;font-size:9.5px; 9888 letter-spacing:.16em;text-transform:uppercase;margin-top:1px; 9889 } 9890 9891 /* Featured first park â pulled forward like the NGO featured row */ 9892 .wyf-park-row.is-featured{ 9893 background:linear-gradient(180deg,rgba(168,243,65,.10),rgba(168,243,65,.02)); 9894 border:1px solid rgba(168,243,65,.30); 9895 padding:18px 14px;margin-bottom:6px; 9896 box-shadow:inset 0 0 0 1px rgba(168,243,65,.04), 0 8px 24px rgba(0,0,0,.25); 9897 } 9898 .wyf-park-row.is-featured .pk-flag{ 9899 width:44px;height:44px;flex:0 0 44px;border-radius:12px;font-size:22px; 9900 background:rgba(168,243,65,.15);box-shadow:inset 0 0 0 1px rgba(168,243,65,.55); 9901 } 9902 .wyf-park-row.is-featured .pk-name{font-size:19px;font-weight:900;letter-spacing:-.01em} 9903 .wyf-park-row.is-featured .pk-dist{font-size:19px} 9904 .wyf-parks-foot{ 9905 margin-top:14px;padding-top:14px;border-top:1px dashed rgba(168,243,65,.22); 9906 font-size:11.5px;color:var(--mist-2);font-style:italic;line-height:1.5; 9907 } 9908 .wyf-parks-foot b{color:var(--bone);font-weight:600;font-style:normal} 9909 </style> 9910 9911 <!-- Faint cartograph background lines --> 9912 <svg class="wyf-bg" viewBox="0 0 1600 900" preserveAspectRatio="xMidYMid slice" aria-hidden="true"> 9913 <line class="bg-lat" x1="-50" y1="220" x2="1650" y2="220"/> 9914 <line class="bg-lat" x1="-50" y1="680" x2="1650" y2="680"/> 9915 <path class="bg-trail-soft" d="M-40,460 C260,360 540,560 800,460 C1060,360 1340,560 1660,460"/> 9916 </svg> 9917 9918 <div class="wyf-head"> 9919 <span class="eyebrow">Where you fit in</span> 9920 <h2 id="wyfH">You're at <em><span id="wyfHeadCoords">â · â</span></em>.</h2> 9921 <p>Drawn from your IP, never stored. Below: the five partner NGOs nearest to you, with their cardinal bearing â like a navigator's log.</p> 9922 </div> 9923 9924 <article class="wyf-slip" aria-labelledby="wyfH"> 9925 <!-- LEFT: coordinates + compass --> 9926 <div class="wyf-coords-card"> 9927 <span class="wyf-station">Dispatch · Station</span> 9928 <h3 class="wyf-where" id="wyfWhere"><span class="wyf-loading">Reading your location</span></h3> 9929 9930 <div class="wyf-stamp" aria-live="polite"> 9931 <div class="wyf-stamp-row"><span class="lbl">Lat</span><span class="val" id="wyfLat">â</span></div> 9932 <div class="wyf-stamp-row"><span class="lbl">Lon</span><span class="val" id="wyfLon">â</span></div> 9933 </div> 9934 9935 <!-- Mini globe â orthographic projection centred on the visitor's 9936 lat/lon. The visible hemisphere shows a stylized sphere with 9937 leaf graticule + the 5 nearest NGOs projected as dots. 9938 Replaces the previous abstract compass. --> 9939 <div class="wyf-globe" aria-hidden="true"> 9940 <svg viewBox="0 0 220 220"> 9941 <defs> 9942 <radialGradient id="wyfGlobeShade" cx="35%" cy="30%" r="75%"> 9943 <stop offset="0%" stop-color="rgba(168,243,65,.14)"/> 9944 <stop offset="55%" stop-color="rgba(11,18,42,.55)"/> 9945 <stop offset="100%" stop-color="rgba(2,7,24,.95)"/> 9946 </radialGradient> 9947 </defs> 9948 <!-- The visible hemisphere disc â looks like a 3D sphere. --> 9949 <circle class="globe-disc" cx="110" cy="110" r="100"/> 9950 <!-- Graticule (latitude + longitude curves) drawn live by JS, 9951 so it bends correctly when re-centred on the visitor. --> 9952 <g id="wyfGlobeGraticule"></g> 9953 <!-- NGO dots projected onto the visible hemisphere. --> 9954 <g id="wyfGlobeNgos"></g> 9955 <!-- Outer ring --> 9956 <circle class="globe-ring" cx="110" cy="110" r="100"/> 9957 <!-- You-are-here pin in the centre â pulses softly. --> 9958 <circle class="you-glow" cx="110" cy="110" r="10"/> 9959 <circle class="you-ring" cx="110" cy="110" r="8"/> 9960 <circle class="you-pin" cx="110" cy="110" r="4"/> 9961 </svg> 9962 </div> 9963 <div class="wyf-compass-foot">Mini globe · <b id="wyfNearLabel">5 nearest</b></div> 9964 </div> 9965 9966 <!-- MIDDLE: bearings list â nearest Ecoflix partner NGOs --> 9967 <div class="wyf-bearings"> 9968 <header class="wyf-bearings-head">
9969 <span class="eyebrow">Nearest · by bearing</span> 9970 <h3>The NGOs <em>around you.</em></h3> 9971 <span class="sub" id="wyfCount">Five Ecoflix partners within reach, ranked closest first.</span> 9972 </header> 9973 9974 <div class="wyf-bearings-table" id="wyfRows" role="list"> 9975 <!-- rows injected by JS --> 9976 </div> 9977 9978 <div class="wyf-bearings-foot"> 9979 <span class="note"><b><span data-livestat="ngos">27</span> partner NGOs</b> across six continents. Every donation routes to one of them.</span> 9980 <a class="more" href="/ngo-partners/">View all <span aria-hidden="true">â</span></a> 9981 </div> 9982 </div> 9983 9984 <!-- RIGHT: wild places to visit â nearest national parks, reserves 9985 and sanctuaries (a fun "could you visit?" lane) --> 9986 <div class="wyf-parks"> 9987 <header class="wyf-parks-head"> 9988 <span class="eyebrow">Wild places · by distance</span> 9989 <h3>Where to <em>see the wild.</em></h3> 9990 <span class="sub" id="wyfParksCount">Five national parks & reserves near you â what they're famous for.</span> 9991 </header> 9992 9993 <ul class="wyf-parks-list" id="wyfParksList" role="list"> 9994 <!-- rows injected by JS --> 9995 </ul> 9996 9997 <p class="wyf-parks-foot"> 9998 81 protected areas across 41 countries â the kind of place an 9999 Ecoflix film is usually shot in. Plan a visit, then come home 10000 and <b>fund the rangers who keep it wild</b>. 10001 </p> 10002 </div> 10003 </article> 10004 10005
10005<script> 10006 (function(){ 10007 var $headCoords = document.getElementById('wyfHeadCoords'); 10008 var $where = document.getElementById('wyfWhere'); 10009 var $lat = document.getElementById('wyfLat'); 10010 var $lon = document.getElementById('wyfLon'); 10011 var $rows = document.getElementById('wyfRows'); 10012 var $count = document.getElementById('wyfCount'); 10013 var $nearLbl = document.getElementById('wyfNearLabel'); 10014 var $globeNgos = document.getElementById('wyfGlobeNgos'); 10015 var $globeGrat = document.getElementById('wyfGlobeGraticule'); 10016 var $parksList = document.getElementById('wyfParksList'); 10017 var $parksCount = document.getElementById('wyfParksCount'); 10018 if (!$rows || !$globeNgos) return; 10019 10020 // ---- Helpers ---- 10021 var rad = Math.PI / 180; 10022 var SVGNS = 'http://www.w3.org/2000/svg'; 10023 function el(tag, attrs){ var n = document.createElementNS(SVGNS, tag); for (var k in attrs) n.setAttribute(k, attrs[k]); return n; } 10024 function escapeHtml(s){ return String(s||'').replace(/[&<>"']/g, function(c){ return ({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c]); }); } 10025 10026 function distKm(a, b){ 10027 var R = 6371; 10028 var dLat = (b.lat - a.lat) * rad; 10029 var dLon = (b.lon - a.lon) * rad; 10030 var s = Math.sin(dLat/2)*Math.sin(dLat/2) 10031 + Math.cos(a.lat*rad)*Math.cos(b.lat*rad)*Math.sin(dLon/2)*Math.sin(dLon/2); 10032 return R * 2 * Math.atan2(Math.sqrt(s), Math.sqrt(1-s)); 10033 } 10034 function bearing(a, b){ 10035 var Ï1 = a.lat * rad, Ï2 = b.lat * rad; 10036 var Îλ = (b.lon - a.lon) * rad; 10037 var y = Math.sin(Îλ) * Math.cos(Ï2); 10038 var x = Math.cos(Ï1)*Math.sin(Ï2) - Math.sin(Ï1)*Math.cos(Ï2)*Math.cos(Îλ); 10039 return (Math.atan2(y, x) * 180/Math.PI + 360) % 360; 10040 } 10041 var COMPASS = ['N','NNE','NE','ENE','E','ESE','SE','SSE','S','SSW','SW','WSW','W','WNW','NW','NNW']; 10042 function cardinal(deg){ return COMPASS[Math.round(deg/22.5) % 16]; } 10043 10044 function fmtCoord(d, kind){ 10045 if (!isFinite(d)) return 'â'; 10046 var abs = Math.abs(d); 10047 var deg = Math.floor(abs); 10048 var min = Math.floor((abs - deg) * 60); 10049 var sec = Math.round(((abs - deg) * 60 - min) * 60); 10050 var dir = kind === 'lat' ? (d >= 0 ? 'N' : 'S') : (d >= 0 ? 'E' : 'W'); 10051 return deg + '°' + String(min).padStart(2,'0') + "'" + String(sec).padStart(2,'0') + '"<span class="dir">' + dir + '</span>'; 10052 } 10053 function fmtCoordPlain(d, kind){ 10054 if (!isFinite(d)) return 'â'; 10055 var dir = kind === 'lat' ? (d >= 0 ? 'N' : 'S') : (d >= 0 ? 'E' : 'W'); 10056 return Math.abs(d).toFixed(2) + '° ' + dir; 10057 } 10058 function fmtKm(km){ 10059 if (!isFinite(km)) return 'â'; 10060 if (km < 1) return '<span>' + Math.round(km*1000) + '</span><span class="u">m</span>'; 10061 if (km < 100) return '<span>' + km.toFixed(1) + '</span><span class="u">km</span>'; 10062 return '<span>' + Math.round(km).toLocaleString('en-US') + '</span><span class="u">km</span>'; 10063 } 10064 10065 // === Mini-globe geometry =========================================== 10066 // Orthographic projection centred on the visitor. The visible 10067 // hemisphere is a circle of radius R; (lat, lon) â (x, y) inside it. 10068 // Points on the far hemisphere are hidden (cosc <= 0). 10069 var GLOBE_CX = 110, GLOBE_CY = 110, GLOBE_R = 96; 10070 function projectOrtho(lat, lon, centreLat, centreLon){ 10071 var phi = lat * rad, phi0 = centreLat * rad; 10072 var lam = (lon - centreLon) * rad; 10073 var cosc = Math.sin(phi0)*Math.sin(phi) + Math.cos(phi0)*Math.cos(phi)*M
10073ath.cos(lam); 10074 if (cosc <= 0) return null; // far hemisphere 10075 var x = Math.cos(phi) * Math.sin(lam); 10076 var y = Math.cos(phi0)*Math.sin(phi) - Math.sin(phi0)*Math.cos(phi)*Math.cos(lam); 10077 return { x: GLOBE_CX + x * GLOBE_R, y: GLOBE_CY - y * GLOBE_R, cosc: cosc }; 10078 } 10079 10080 // Draw graticule (latitude rings + longitude meridians) for a given 10081 // centre. Re-runs whenever the visitor's position changes (e.g. on 10082 // first geo response). 100-pt polyline approximation per curve. 10083 function drawGraticule(centreLat, centreLon){ 10084 if (!$globeGrat) return; 10085 $globeGrat.innerHTML = ''; 10086 function polyline(points){ 10087 var path = points.map(function(p, i){ return (i ? 'L' : 'M') + p.x.toFixed(1) + ' ' + p.y.toFixed(1); }).join(' '); 10088 return path; 10089 } 10090 // 5 latitude rings every 30° 10091 [-60,-30,0,30,60].forEach(function(lat){ 10092 var pts = []; 10093 for (var l = -180; l <= 180; l += 6){ 10094 var p = projectOrtho(lat, l, centreLat, centreLon); 10095 if (p) pts.push(p); 10096 } 10097 if (pts.length > 2) $globeGrat.appendChild(el('path', { class:'glob-lat', d: polyline(pts) })); 10098 }); 10099 // 6 longitude meridians every 30° 10100 for (var lon = -180; lon < 180; lon += 30){ 10101 var pts = []; 10102 for (var lat = -90; lat <= 90; lat += 3){ 10103 var p = projectOrtho(lat, lon, centreLat, centreLon); 10104 if (p) pts.push(p); 10105 } 10106 if (pts.length > 2) $globeGrat.appendChild(el('path', { class:'glob-lon', d: polyline(pts) })); 10107 } 10108 } 10109 10110 // Wait for i18n.js to publish window.__ECOFLIX_COUNTRY__ (sometimes 10111 // it boots slightly after us). Resolves either when the locale-ready 10112 // event fires or after a short timeout. 10113 function waitForI18n(timeoutMs){ 10114 return new Promise(function(resolve){ 10115 if (window.__ECOFLIX_COUNTRY__) return resolve(); 10116 var done = false; 10117 function finish(){ if (done) return; done = true; resolve(); } 10118 window.addEventListener('ecoflix:locale-ready', finish, { once: true }); 10119 setTimeout(finish, timeoutMs || 600); 10120 }); 10121 } 10122 10123 // ---- Boot ---- 10124 async function boot(){
10125 var ngosPromise = fetch('/assets/ngos.json').then(function(r){ return r.json(); }).catch(function(){ return null; }); 10126 var parksPromise = fetch('/assets/parks.json').then(function(r){ return r.json(); }).catch(function(){ return null; }); 10127 var geoPromise = fetch('/api/geo').then(function(r){ return r.json(); }).catch(function(){ return null; }); 10128 10129 var ngosData = await ngosPromise; 10130 var parksData = await parksPromise; 10131 var ngos = (ngosData && ngosData.ngos) || []; 10132 var parks = (parksData && parksData.parks) || []; 10133 if (!ngos.length){ 10134 $count.textContent = 'NGO data unavailable'; 10135 return; 10136 } 10137 10138 var you = null, label = '', flag = '', isApprox = false; 10139 var geo = await geoPromise; 10140 // Wait briefly for i18n if we're going to need the fallback 10141 await waitForI18n(800); 10142 10143 if (geo && geo.ok){ 10144 you = { lat: geo.lat, lon: geo.lon }; 10145 if (geo.city) label += geo.city; 10146 if (geo.country) label += (label ? ', ' : '') + geo.country; 10147 var info = (window.__ECOFLIX_COUNTRY__ && window.__ECOFLIX_COUNTRY__()) || null; 10148 flag = info ? info.flag : ''; 10149 } else { 10150 var fb = window.__ECOFLIX_COUNTRY__ && window.__ECOFLIX_COUNTRY__(); 10151 if (fb){ 10152 you = { lat: fb.lat, lon: fb.lon }; 10153 label = fb.name; 10154 flag = fb.flag; 10155 isApprox = true; 10156 } 10157 } 10158 10159 // Hard fallback: if we still don't know where the visitor is, 10160 // centre on Greenwich (0°N, 0°E) so the section still has 10161 // content â first 5 NGOs and first 5 parks in distance order 10162 // from there. Better than an empty card. 10163 if (!you){ 10164 you = { lat: 51.48, lon: 0 }; 10165 label = 'Showing default view'; 10166 isApprox = true; 10167 } 10168 10169 // Render the "where you are" line + coordinate stamp + hero coords 10170 $where.innerHTML = (flag ? '<span class="flag">' + flag + '</span>' : '') + escapeHtml(label || 'Detected'); 10171 $lat.innerHTML = fmtCoord(you.lat, 'lat'); 10172 $lon.innerHTML = fmtCoord(you.lon, 'lon'); 10173 $headCoords.textContent = fmtCoordPlain(you.lat, 'lat') + ' · ' + fmtCoordPlain(you.lon, 'lon'); 10174 10175 // Compute distance + bearing to every NGO, sort by distance, take top 5 10176 var ranked = ngos.map(function(n){ 10177 return { n: n, km: distKm(you, n), bear: bearing(you, n) }; 10178 }).sort(function(a, b){ return a.km - b.km }); 10179 10180 var top = ranked.slice(0, 5); 10181 // Richer subtitle than the previous "5 within reach" â name the 10182 // closest one and its distance so the header pulls double-duty. 10183 if ($count){ 10184 var nearest = top[0]; 10185 if (nearest && isFinite(nearest.km)){ 10186 var distLbl = nearest.km < 1 10187 ? Math.round(nearest.km * 1000) + ' m' 10188 : (nearest.km < 100 ? nearest.km.toFixed(1) : Math.round(nearest.km).toLocaleString('en-US')) + ' km'; 10189 $count.textContent = top.length + ' partners · closest is ' + (nearest.n.ngo || nearest.n.name) + ' (' + distLbl + ')'; 10190 } else { 10191 $count.textContent = top.length + ' partners within reach.'; 10192 } 10193 } 10194 if ($nearLbl) $nearLbl.textContent = top.length + ' nearest'; 10195 10196 // === Draw the mini-globe ============================================ 10197 // Re-render the graticule centred on the visitor, then project 10198 // every partner NGO onto the visible hemisphere. NGOs on the far 10199 // side are simply not drawn (the visitor would have to spin the 10200 // earth to see them). The 5 nearest are drawn brighter + pulsing. 10201 drawGraticule(you.lat, you.lon); 10202 $globeNgos.innerHTML = ''; 10203 var nearestIds = {}; 10204 top.forEach(function(x){ nearestIds[x.n.id] = true; }); 10205 ngos.forEach(function(n){ 10206 var p = projectOrtho(n.lat, n.lon, you.lat, you.lon); 10207 if (!p) return; 10208 var isNear = nearestIds[n.id]; 10209 $globeNgos.appendChild(el('circle', { 10210 class: 'ngo-dot' + (isNear ? ' is-nearest' : ''), 10211 cx: p.x.toFixed(1), cy: p.y.toFixed(1), 10212 r: isNear ? 5 : 3, 10213 'data-id': n.id, 10214 })); 10215 }); 10216 // Draw subtle great-circle hints to each of the 5 nearest NGOs
10217 top.forEach(function(x){ 10218 var dest = projectOrtho(x.n.lat, x.n.lon, you.lat, you.lon); 10219 if (!dest) return; 10220 // Quadratic arc from centre (visitor) to the dot 10221 var mx = (GLOBE_CX + dest.x) / 2; 10222 var my = (GLOBE_CY + dest.y) / 2 - Math.min(28, Math.abs(dest.x - GLOBE_CX) * 0.25); 10223 var d = 'M ' + GLOBE_CX + ' ' + GLOBE_CY + 10224 ' Q ' + mx.toFixed(1) + ' ' + my.toFixed(1) + 10225 ' ' + dest.x.toFixed(1) + ' ' + dest.y.toFixed(1); 10226 $globeNgos.appendChild(el('path', { class:'ngo-arc', d:d, 'data-id': x.n.id })); 10227 }); 10228 10229 // Build the bearings list rows (rank · name · meta · distance). 10230 // First row is "featured" with bigger type and a NEAREST stamp. 10231 $rows.innerHTML = top.map(function(x, i){ 10232 var n = x.n; 10233 var card = cardinal(x.bear); 10234 var ang = Math.round(x.bear); 10235 var featuredClass = (i === 0) ? ' is-featured' : ''; 10236 return '' + 10237 '<a class="wyf-bearings-row' + featuredClass + '" href="' + escapeHtml(n.href || '/ngo-partners/') + '" data-id="' + escapeHtml(n.id) + '" role="listitem">' + 10238 ' <span class="rank">' + String(i+1).padStart(2,'0') + '</span>' + 10239 ' <span class="who"><span class="nm">' + escapeHtml(n.ngo || n.name) + '</span></span>' + 10240 ' <span class="meta">' + 10241 ' <span class="bear-arrow"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" style="transform:rotate(' + ang + 'deg)"><path d="M12 19V5M5 12l7-7 7 7"/></svg></span>' + 10242 ' <span class="bear-card">' + card + '</span>' + 10243 ' <span class="bear-deg">' + ang + '°</span>' + 10244 ' <span class="sep">·</span>' + 10245 ' <span class="wh">' + escapeHtml(n.where || n.name) + '</span>' + 10246 ' </span>' + 10247 ' <span class="dist">' + fmtKm(x.km) + '</span>' + 10248 '</a>'; 10249 }).join(''); 10250 10251 // Hover row â brighten the matching NGO dot on the mini globe + tint row 10252 Array.prototype.forEach.call($rows.querySelectorAll('.wyf-bearings-row'), function(row){ 10253 row.addEventListener('mouseenter', function(){ 10254 var id = row.getAttribute('data-id'); 10255 Array.prototype.forEach.call($globeNgos.querySelectorAll('[data-id]'), function(s){ 10256 if (s.getAttribute('data-id') === id){ 10257 if (s.tagName === 'circle') { s.setAttribute('r','7'); s.setAttribute('fill','#fff'); } 10258 if (s.tagName === 'path') { s.setAttribute('stroke','#D3FA9E'); s.setAttribute('stroke-width','1.6'); } 10259 } 10260 }); 10261 row.classList.add('is-active'); 10262 }); 10263 row.addEventListener('mouseleave', function(){ 10264 Array.prototype.forEach.call($globeNgos.querySelectorAll('[data-id]'), function(s){ 10265 if (s.tagName === 'circle') { 10266 s.removeAttribute('fill'); 10267 s.setAttribute('r', s.classList.contains('is-nearest') ? '5' : '3'); 10268 } 10269 if (s.tagName === 'path') { s.removeAttribute('stroke'); s.removeAttribute('stroke-width'); } 10270 }); 10271 row.classList.remove('is-active'); 10272 }); 10273 }); 10274 10275 // === Third column: nearest national parks / reserves / sanctuaries === 10276 if (parks.length && $parksList){ 10277 var rankedParks = parks.map(function(p){ 10278 return { p: p, km: distKm(you, p) }; 10279 }).sort(function(a, b){ return a.km - b.km }); 10280 var topParks = rankedParks.slice(0, 5); 10281 10282 if ($parksCount){ 10283 var nearestPark = topParks[0]; 10284 if (nearestPark && isFinite(nearestPark.km)){ 10285 var pkDist = nearestPark.km < 1 10286 ? Math.round(nearestPark.km * 1000) + ' m' 10287 : (nearestPark.km < 100 ? nearestPark.km.toFixed(1) : Math.round(nearestPark.km).toLocaleString('en-US')) + ' km'; 10288 $parksCount.textContent = topParks.length + ' parks · closest is ' + nearestPark.p.name + ' (' + pkDist + ')'; 10289 } else { 10290 $parksCount.textContent = topParks.length + ' parks within reach.'; 10291 } 10292 } 10293 10294 $parksList.innerHTML = topParks.map(function(x, i){ 10295 var p = x.p;
10296 // Wikipedia search link as a tasteful "learn more" target. 10297 var href = 'https://en.wikipedia.org/wiki/Special:Search?search=' + encodeURIComponent(p.name); 10298 var featuredClass = (i === 0) ? ' is-featured' : ''; 10299 return '' + 10300 '<li class="wyf-park-row' + featuredClass + '" data-id="' + escapeHtml(p.id) + '">' + 10301 ' <span class="pk-flag" aria-hidden="true">' + (p.flag || '') + '</span>' + 10302 ' <span class="pk-rank">' + String(i+1).padStart(2,'0') + '</span>' + 10303 ' <a class="pk-name" href="' + href + '" target="_blank" rel="noopener">' + escapeHtml(p.name) + '</a>' + 10304 ' <span class="pk-tag">' + escapeHtml(p.type || '') + '</span>' + 10305 ' <span class="pk-dist">' + fmtKm(x.km) + '</span>' + 10306 ' <span class="pk-wild" title="' + escapeHtml(p.wildlife || '') + '"><span class="pk-wild-lbl">You\'ll see</span> ' + escapeHtml(p.wildlife || '') + '</span>' + 10307 '</li>'; 10308 }).join(''); 10309 } 10310 } 10311 10312 if ('requestIdleCallback' in window){ 10313 requestIdleCallback(boot, { timeout: 1800 }); 10314 } else { 10315 setTimeout(boot, 600); 10316 } 10317 })(); 10318 </script>
10318 10319</section> 10320 10321<!-- ================================================= 10322 B-ROLL BURST â asymmetric video bento 10323 Hot-linked from Pexels CDN as a stop-gap. Before launch: 10324 download, re-encode short loops (5-8s, all-keyframe), host in /assets/. 10325 ================================================= --> 10326<section class="section broll-section section-lift" style="position:relative;overflow:hidden;isolation:isolate"> 10327 <!-- CARTOGRAPH 05 · FIELD NOTES â rich treatment, dual compasses + trail --> 10328 <div class="bg-cartograph" aria-hidden="true"> 10329 <svg viewBox="0 0 1600 900" preserveAspectRatio="xMidYMid slice"> 10330 <line class="bg-lat" x1="-50" y1="120" x2="1650" y2="120"/> 10331 <line class="bg-lat" x1="-50" y1="780" x2="1650" y2="780"/> 10332 <!-- Top-margin trail rising to the right --> 10333 <path class="bg-trail" d="M-40,170 C220,140 380,90 620,80 C840,72 1040,110 1280,80 C1420,62 1500,80 1660,60"/> 10334 <path class="bg-trail-soft" d="M-40,80 C220,40 480,100 720,60 C940,28 1180,80 1660,50" stroke-dasharray="2 12"/> 10335 <!-- Animal tracks along the trail (concentrated in left margin) --> 10336 <circle class="bg-track" cx="220" cy="148" r="3.2"/> 10337 <circle class="bg-track" cx="298" cy="124" r="3"/> 10338 <circle class="bg-track" cx="376" cy="106" r="2.8"/> 10339 <circle class="bg-track" cx="458" cy="92" r="3"/> 10340 <!-- A map-pin waypoint along the top trail --> 10341 <g class="bg-marker" transform="translate(620,80)"> 10342 <circle r="12"/><circle r="4.5" class="bg-marker-dot"/> 10343 </g> 10344 <g class="bg-marker" transform="translate(1280,80)"> 10345 <circle r="10"/><circle r="4" class="bg-marker-dot"/> 10346 </g> 10347 <!-- Top-RIGHT full compass with N/E/S/W (moved from top-left for variety) --> 10348 <g class="bg-compass" transform="translate(1490,210)"> 10349 <circle class="bg-compass-ring" r="44"/> 10350 <circle class="bg-compass-ring" r="30"/> 10351 <line class="bg-compass-tick" x1="0" y1="-48" x2="0" y2="48"/> 10352 <line class="bg-compass-tick" x1="-48" y1="0" x2="48" y2="0"/> 10353 <line class="bg-compass-tick" x1="-34" y1="-34" x2="34" y2="34"/> 10354 <line class="bg-compass-tick" x1="34" y1="-34" x2="-34" y2="34"/> 10355 <polygon class="bg-compass-arrow" points="0,-44 5,0 0,44 -5,0"/> 10356 <polygon class="bg-compass-arrow" points="-44,0 0,5 44,0 0,-5"/> 10357 <text class="bg-compass-label" x="0" y="-54" text-anchor="middle">N</text> 10358 <text class="bg-compass-label" x="55" y="4" text-anchor="middle">E</text> 10359 <text class="bg-compass-label" x="0" y="64" text-anchor="middle">S</text> 10360 <text class="bg-compass-label" x="-55" y="4" text-anchor="middle">W</text> 10361 </g> 10362 <!-- Bottom-LEFT secondary compass (smaller, degree-tick style) --> 10363 <g class="bg-compass" transform="translate(160,810)"> 10364 <circle class="bg-compass-ring" r="28"/> 10365 <circle class="bg-compass-ring" r="18"/> 10366 <line class="bg-compass-tick" x1="0" y1="-32" x2="0" y2="-22"/> 10367 <line class="bg-compass-tick" x1="22" y1="0" x2="32" y2="0"/> 10368 <line class="bg-compass-tick" x1="0" y1="22" x2="0" y2="32"/> 10369 <line class="bg-compass-tick" x1="-32" y1="0" x2="-22" y2="0"/> 10370 <line class="bg-compass-tick" x1="16" y1="-16" x2="22" y2="-22"/> 10371 <line class="bg-compass-tick" x1="-16" y1="-16" x2="-22" y2="-22"/> 10372 <line class="bg-compass-tick" x1="16" y1="16" x2="22" y2="22"/> 10373 <line class="bg-compass-tick" x1="-16" y1="16" x2="-22" y2="22"/> 10374 <circle r="2.5" class="bg-marker-dot"/> 10375 </g> 10376 <!-- Topo contour rings in left margin (replaces leaf motif) --> 10377 <g transform="translate(80,470)"> 10378 <circle class="bg-compass-ring" r="34" fill="none"/> 10379 <circle class="bg-compass-ring" r="22" fill="none" stroke-dasharray="3 7"/> 10380 <circle class="bg-compass-ring" r="12" fill="none" stroke-dasharray="2 6"/> 10381 <circle r="2.5" class="bg-marker-dot"/> 10382 </g> 10383 <!-- Bottom-margin trail (subtle, opposite direction) --> 10384 <path class="bg-trail-soft" d="M-40,860 C220,820 480,840 760,820 C1000,800 1240,840 1660,830"/> 10385 <circle class="bg-track" cx="950" cy="828" r="3"/> 10386 <circle class="bg-track" cx="1030" cy="822" r="3"/> 10387 <circle class="bg-track" cx="1110" cy="826" r="3"/> 10388 <!-- Bottom labels --> 10389 <g transform="translate(280,856)"> 10390 <text class="bg-coord-text" x="0" y="0">05 · FIELD NOTES</text> 10391 </g> 10392 <g transform="translate(1180,856)"> 10393 <text class="bg-coord-text" x="0" y="0">4 CLIPS · IN PRODUCTION</text> 10394 </g> 10395 </svg> 10396 </div> 10397 <div class="wrap" style="position:relative;z-index:2"> 10398 <div class="s-head reveal"> 10399 <div class="row"> 10400 <div class="row-left"> 10401 <h2 class="reveal-words">Stories from <em>the field.</em></h2> 10402 <p>Glimpses of the work in motion. Each one ties to a real project you can back on this site.</p> 10403 <a class="btn btn-ghost" href="/projects/">See all projects <span class="arrow">â</span></a> 10404 </div> 10405 <div class="row-side"> 10406 <aside class="stories-panel" aria-label="On the channel right now"> 10407 <div class="stories-head">
10408 <span class="stories-title">On the channel right now</span> 10409 <span class="stories-live">Live</span> 10410 </div> 10411 10412 <a class="top-story" href="https://watch.ecoflix.com/programs/free-billy" target="_blank" rel="noopener" aria-label="Top story: Free Billy"> 10413 <div class="ts-label"> 10414 <svg width="11" height="11" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><polygon points="12,2 14.6,9.2 22,9.6 16.3,14.4 18.2,21.6 12,17.6 5.8,21.6 7.7,14.4 2,9.6 9.4,9.2"/></svg> 10415 Top story 10416 </div> 10417 <div class="ts-title">Free Billy</div> 10418 <div class="ts-meta">Ecoflix Original · the fight to free one elephant</div> 10419 </a> 10420 10421 <hr class="stories-divider"/> 10422 10423 <div class="stories-list"> 10424 <div class="story-row"> 10425 <span class="story-icon" aria-hidden="true"> 10426 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="2.5" y="5" width="19" height="14" rx="2"/><polygon points="10.5,9 15.5,12 10.5,15" fill="currentColor" stroke="none"/></svg> 10427 </span> 10428 <span class="story-num">120+<em>films & series</em></span> 10429 <span class="story-label">Streaming on watch.ecoflix.com.</span> 10430 </div> 10431 <div class="story-row"> 10432 <span class="story-icon" aria-hidden="true"> 10433 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg> 10434 </span> 10435 <span class="story-num">200+<em>hrs</em></span> 10436 <span class="story-label">Of conservation cinema on the channel.</span> 10437 </div> 10438 <div class="story-row"> 10439 <span class="story-icon" aria-hidden="true"> 10440 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M1 12s4-7 11-7 11 7 11 7-4 7-11 7S1 12 1 12z"/><circle cx="12" cy="12" r="3.5"/></svg> 10441 </span> 10442 <span class="story-num">35+<em>Originals</em></span> 10443 <span class="story-label">Made with the NGOs doing the work.</span> 10444 </div> 10445 <div class="story-row"> 10446 <span class="story-icon" aria-hidden="true"> 10447 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="4" width="18" height="16" rx="2"/><line x1="3" y1="10" x2="21" y2="10"/><circle cx="8" cy="14.5" r="1.4" fill="currentColor" stroke="none"/></svg> 10448 </span> 10449 <span class="story-num">3<em>new</em></span> 10450 <span class="story-label">Episodes dropping this week.</span> 10451 </div> 10452 </div> 10453 </aside> 10454 </div> 10455 </div> 10456 </div> 10457 <div class="broll reveal-stagger"> 10458 <article class="btile b1"> 10459 <img src="/assets/ngo/the-gorilla-organization/hero-hd.jpg" alt="Gorilla in the forest â Cross River gorilla habitat in Cameroon" loading="lazy" /> 10460 <div class="b-meta"> 10461 <span class="b-tag"><span class="dot"></span><span class="tag-text"><b class="tag-status">Active</b><span class="tag-location">Cameroon</span></span></span> 10462 <span class="coord-stamp" aria-hidden="true"><span class="cs-lat">6.00°N</span><span class="cs-sep"></span><span class="cs-lon">9.40°E</span></span> 10463 <h3>Saving the Cross River gorilla.</h3> 10464 <p class="b-sub">Community rangers and habitat protection for one of Africa's rarest apes.</p> 10465 <a class="b-cta" href="/projects/saving-the-cross-river-gorilla/">See the project <span class="arrow">â</span></a> 10466 </div> 10467 </article> 10468 10469 <article class="btile b2"> 10470 <img src="/assets/projects/standing-with-wildlife-rangers-hd.jpg" alt="Wildlife rangers on patrol in East Africa" loading="lazy" /> 10471 <div class="b-meta">
10472 <span class="b-tag"><span class="dot"></span><span class="tag-text"><b class="tag-status">Active</b><span class="tag-location">East Africa</span></span></span> 10473 <span class="coord-stamp" aria-hidden="true"><span class="cs-lat">2.15°S</span><span class="cs-sep"></span><span class="cs-lon">34.69°E</span></span> 10474 <h3>Ranger training, on the ground.</h3> 10475 <p class="b-sub">Over and Above Africa â boots, kit and rangers on the front line.</p> 10476 <a class="b-cta" href="/projects/frontline-support-for-africas-wildlife/">See the project <span class="arrow">â</span></a> 10477 </div> 10478 </article> 10479 10480 <article class="btile b3"> 10481 <img src="/assets/projects/a-free-life-for-thailands-rescued-elephants-hd.jpg" alt="Rescued elephants at Elephant Nature Park, Thailand" loading="lazy" /> 10482 <div class="b-meta"> 10483 <span class="b-tag"><span class="dot"></span><span class="tag-text"><b class="tag-status">Active</b><span class="tag-location">Thailand</span></span></span> 10484 <span class="coord-stamp" aria-hidden="true"><span class="cs-lat">19.21°N</span><span class="cs-sep"></span><span class="cs-lon">98.86°E</span></span> 10485 <h3>Rescue and rehabilitation.</h3> 10486 <p class="b-sub">Save Elephant Foundation, <span data-livestat="fund:a-free-life-for-thailands-rescued-elephants">51% funded</span>.</p> 10487 <a class="b-cta" href="/projects/a-free-life-for-thailands-rescued-elephants/">See the project <span class="arrow">â</span></a> 10488 </div> 10489 </article> 10490 10491 <a class="btile cta-tile b4" href="/projects/"> 10492 <div> 10493 <div class="b-num"><span data-livestat="projects">34</span></div> 10494 <div class="b-num-label">Projects across 6 continents</div> 10495 </div> 10496 <div class="b-cta-row"> 10497 <h3>Pick one. Fund it. Follow the work.</h3> 10498 <span class="b-arrow" aria-hidden="true">â</span> 10499 </div> 10500 </a> 10501 </div> 10502 10503 <!-- Picks for tonight â on-demand recommendations --> 10504 <div class="tonight-strip reveal-stagger" aria-label="Picks for tonight"> 10505 <div class="ts-header"> 10506 <span class="ts-eyebrow">Picks for tonight</span> 10507 <a class="ts-all" href="https://watch.ecoflix.com/">See the full library <span class="arrow">â</span></a> 10508 </div> 10509 10510 <!-- Special pick of the night â hero feature --> 10511 <a class="tonight-hero" href="https://watch.ecoflix.com/programs/free-billy" target="_blank" rel="noopener" aria-label="Staff pick: Free Billy"> 10512 <div class="th-media" style="background-image:url('/assets/watch/free-billy.jpg')"> 10513 <span class="th-play" aria-hidden="true"> 10514 <svg viewBox="0 0 24 24" fill="currentColor"><polygon points="8,5 19,12 8,19"/></svg> 10515 </span> 10516 <span class="th-meta-overlay"> 10517 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/></svg> 10518 4K · HDR · Subtitles 10519 </span> 10520 </div> 10521 <div class="th-body"> 10522 <span class="th-special" aria-hidden="true">Staff pick</span> 10523 <h3 class="th-title">Free <em>Billy.</em></h3> 10524 <p class="th-desc">The story of Billy, a wild-born elephant held at LA Zoo for decades, and the campaign for his retirement to a sanctuary. In 2025 he was moved to another zoo instead, so the fight goes on. An Ecoflix-backed film about turning viewers into advocates.</p> 10525 <div class="th-foot"> 10526 <div class="th-stats"> 10527 <span>Ecoflix Original</span> 10528 <span>Documentary</span> 10529 <span>Dir. Marshall Corwin</span> 10530 </div> 10531 <span class="th-cta">Watch now <span aria-hidden="true">→</span></span> 10532 </div> 10533 </div> 10534 </a> 10535 10536 <div class="ts-grid"> 10537 <a class="ts-card" href="https://watch.ecoflix.com/programs/silverback" target="_blank" rel="noopener"> 10538 <div class="ts-thumb" style="background-image:url('/assets/projects/saving-the-cross-river-gorilla-hd.jpg')">
10539 <span class="ts-play" aria-hidden="true"><svg viewBox="0 0 24 24" fill="currentColor"><polygon points="8,5 19,12 8,19"/></svg></span> 10540 </div> 10541 <div class="ts-body"> 10542 <div> 10543 <div class="ts-when ts-badge-new">Documentary</div> 10544 <div class="ts-title">The Silverback</div> 10545 </div> 10546 <div class="ts-count"><b>15 min</b> · Ecoflix Original</div> 10547 </div> 10548 </a> 10549 <a class="ts-card" href="https://watch.ecoflix.com/programs/remaking-wolf-connection" target="_blank" rel="noopener"> 10550 <div class="ts-thumb" style="background-image:url('/assets/watch/wolf-connection.jpg')"> 10551 <span class="ts-play" aria-hidden="true"><svg viewBox="0 0 24 24" fill="currentColor"><polygon points="8,5 19,12 8,19"/></svg></span> 10552 </div> 10553 <div class="ts-body"> 10554 <div> 10555 <div class="ts-when ts-badge-trend">Ecoflix Original</div> 10556 <div class="ts-title">Remaking Wolf Connection</div> 10557 </div> 10558 <div class="ts-count"><b>28 min</b> · California, USA</div> 10559 </div> 10560 </a> 10561 <a class="ts-card" href="https://watch.ecoflix.com/programs/over-and-above-africa" target="_blank" rel="noopener"> 10562 <div class="ts-thumb" style="background-image:url('/assets/watch/over-and-above-africa.jpg')"> 10563 <span class="ts-play" aria-hidden="true"><svg viewBox="0 0 24 24" fill="currentColor"><polygon points="8,5 19,12 8,19"/></svg></span> 10564 </div> 10565 <div class="ts-body"> 10566 <div> 10567 <div class="ts-when ts-badge-pick">Staff pick</div> 10568 <div class="ts-title">Over and Above Africa</div> 10569 </div> 10570 <div class="ts-count"><b>Partner film</b> · Over and Above Africa</div> 10571 </div> 10572 </a> 10573 </div> 10574 </div> 10575 </div> 10576</section> 10577 10578 10579<!-- ================================================= 10580 FOUNDER QUOTE â David Casselman 10581 Background video uses the cached forest aerial so it benefits from 10582 the cache and always falls back to its poster image if the MP4 10583 hot-link fails. 10584 ================================================= --> 10585<div class="pin-stack"> 10586<section class="founder-quote is-pinned-bg" id="founder-quote" aria-label="Founder's note" style="isolation:isolate"> 10587 <!-- Founder-quote ambient video â local /assets/aaa.mp4 (replaces 10588 the previous Pexels CDN clip). Muted + playsinline so iOS/ 10589 Android both autoplay; preload=metadata keeps initial payload 10590 light. Unsplash dark forest still hotlinked as poster for 10591 first-paint before the local file is decoded. --> 10592 <video class="fq-video" autoplay muted loop playsinline preload="metadata" 10593 poster="https://images.unsplash.com/photo-1441974231531-c6227db76b6e?w=1600&q=70&auto=format&fit=crop" 10594 data-rate="0.5" 10595 aria-hidden="true"> 10596 <source src="/assets/aaa.mp4" type="video/mp4" /> 10597 </video> 10598 <!-- CARTOGRAPH 08 · FOUNDER'S LOG â restrained-but-rich layer sitting on 10599 top of the darkened video overlay --> 10600 <div class="bg-cartograph" aria-hidden="true" style="opacity:.55"> 10601 <svg viewBox="0 0 1600 900" preserveAspectRatio="xMidYMid slice"> 10602 <line class="bg-lat" x1="-50" y1="80" x2="1650" y2="80"/> 10603 <line class="bg-lat" x1="-50" y1="820" x2="1650" y2="820"/> 10604 <!-- Top-margin trail (subtle) --> 10605 <path class="bg-trail" d="M-40,140 C260,90 540,160 800,120 C1060,80 1340,150 1660,110"/> 10606 <path class="bg-trail-soft" d="M-40,40 C260,80 540,30 760,60 C1000,90 1240,40 1660,70"/> 10607 <!-- A few animal tracks --> 10608 <circle class="bg-track" cx="220" cy="124" r="3"/> 10609 <circle class="bg-track" cx="300" cy="118" r="3"/> 10610 <circle class="bg-track" cx="380" cy="114" r="3"/> 10611 <!-- Map pin where trail crosses --> 10612 <g class="bg-marker" transform="translate(800,120)"> 10613 <circle r="12"/><circle r="4" class="bg-marker-dot"/> 10614 </g> 10615 <!-- Top-right full compass with N/E/S/W --> 10616 <g class="bg-compass" transform="translate(1490,200)"> 10617 <circle class="bg-compass-ring" r="42"/> 10618 <circle class="bg-compass-ring" r="30"/> 10619 <line class="bg-compass-tick" x1="0" y1="-46" x2="0" y2="46"/> 10620 <line class="bg-compass-tick" x1="-46" y1="0" x2="46" y2="0"/> 10621 <line class="bg-compass-tick" x1="-33" y1="-33" x2="33" y2="33"/> 10622 <line class="bg-compass-tick" x1="33" y1="-33" x2="-33" y2="33"/> 10623 <polygon class="bg-compass-arrow" points="0,-42 5,0 0,42 -5,0"/> 10624 <polygon class="bg-compass-arrow" points="-42,0 0,5 42,0 0,-5"/> 10625 <text class="bg-compass-label" x="0" y="-52" text-anchor="middle">N</text> 10626 <text class="bg-compass-label" x="54" y="4" text-anchor="middle">E</text> 10627 <text class="bg-compass-label" x="0" y="64" text-anchor="middle">S</text> 10628 <text class="bg-compass-label" x="-54" y="4" text-anchor="middle">W</text> 10629 </g> 10630 <!-- Topo contour rings in left margin (replaces leaf motif) --> 10631 <g transform="translate(80,520)"> 10632 <circle class="bg-compass-ring" r="34" fill="none"/> 10633 <circle class="bg-compass-ring" r="22" fill="none" stroke-dasharray="3 7"/> 10634 <circle class="bg-compass-ring" r="12" fill="none" stroke-dasharray="2 6"/> 10635 <circle r="2.5" class="bg-marker-dot"/> 10636 </g> 10637 <!-- Coordinate stamps --> 10638 <g transform="translate(140,60)"> 10639 <text class="bg-coord-text" x="0" y="0">08 · FOUNDER'S LOG</text> 10640 </g> 10641 <g transform="translate(140,860)"> 10642 <text class="bg-coord-text" x="0" y="0">CHIANG MAI · 18.78°N 98.97°E</text> 10643 </g> 10644 <g transform="translate(1340,860)"> 10645 <text class="bg-coord-text" x="0" y="0">ENTRY 027</text> 10646 </g> 10647 </svg> 10648 </div> 10649 <div class="wrap-narrow"> 10650 <span class="fq-eyebrow">A note from the founder</span> 10651 <blockquote class="fq-text">"Everyone can make a difference, every <em>day.</em> We need to act together, literally, to <em>save the world.</em>"</blockquote> 10652 <div class="fq-attribution"> 10653 <div class="fq-avatar" aria-hidden="true"></div> 10654 <div class="fq-meta">
10655 <span class="coord-stamp" aria-hidden="true"><span class="cs-lat">34.16°N</span><span class="cs-sep"></span><span class="cs-lon">118.66°W</span></span> 10656 <strong>David B. Casselman</strong> 10657 <span>Founder, Ecoflix Foundation</span> 10658 <a href="/team/david-b-casselman/">Read his story â</a> 10659 </div> 10660 </div> 10661 10662 </div> 10663</section> 10664 10665 10666<!-- ================================================= 10667 STAGE 7 â Animated paths donate CTA 10668 ================================================= --> 10669<section class="convert section-lift lifts-strong"> 10670 <!-- CARTOGRAPH SCENE 03 · DESTINATION 10671 Trail enters from the left at yâ420 (where scene 02 exited) and 10672 converges with three other routes onto a single crosshair hub. 10673 X marks the spot â this is where the donor arrives. --> 10674 <div class="bg-cartograph" aria-hidden="true"> 10675 <svg viewBox="0 0 1600 900" preserveAspectRatio="xMidYMid slice"> 10676 <line class="bg-lat" x1="-50" y1="200" x2="1650" y2="200"/> 10677 <line class="bg-lat" x1="-50" y1="450" x2="1650" y2="450"/> 10678 <line class="bg-lat" x1="-50" y1="700" x2="1650" y2="700"/> 10679 <!-- Four converging routes into the central hub at (800,450) --> 10680 <path class="bg-trail" d="M-50,420 C160,440 360,455 560,452 C700,450 760,450 800,450"/> 10681 <path class="bg-trail-soft" d="M-50,820 C200,780 380,640 560,580 C680,540 740,490 800,450"/> 10682 <path class="bg-trail-soft" d="M1650,80 C1380,140 1180,260 1000,340 C900,390 850,420 800,450"/> 10683 <path class="bg-trail-soft" d="M1650,820 C1400,800 1180,720 1000,620 C900,560 850,500 800,450"/> 10684 <!-- Crosshair hub â X marks the spot --> 10685 <g transform="translate(800,450)"> 10686 <circle class="bg-compass-ring" r="60" fill="none"/> 10687 <circle class="bg-compass-ring" r="92" fill="none" stroke-dasharray="3 7"/> 10688 <circle class="bg-compass-ring" r="130" fill="none" stroke-dasharray="2 14" stroke-opacity=".5"/> 10689 <line class="bg-compass-tick" x1="-80" y1="0" x2="-50" y2="0" stroke-width="1"/> 10690 <line class="bg-compass-tick" x1="50" y1="0" x2="80" y2="0" stroke-width="1"/> 10691 <line class="bg-compass-tick" x1="0" y1="-80" x2="0" y2="-50" stroke-width="1"/> 10692 <line class="bg-compass-tick" x1="0" y1="50" x2="0" y2="80" stroke-width="1"/> 10693 <line class="bg-compass-tick" x1="-30" y1="-30" x2="30" y2="30" stroke-width=".8"/> 10694 <line class="bg-compass-tick" x1="30" y1="-30" x2="-30" y2="30" stroke-width=".8"/> 10695 <circle class="bg-marker-dot" r="8"/> 10696 </g> 10697 <!-- Waypoints along the four routes --> 10698 <g class="bg-marker" transform="translate(300,432)"> 10699 <circle r="8"/><circle r="3" class="bg-marker-dot"/> 10700 </g> 10701 <g class="bg-marker" transform="translate(560,452)"> 10702 <circle r="8"/><circle r="3" class="bg-marker-dot"/> 10703 </g> 10704 <g class="bg-marker" transform="translate(280,690)"> 10705 <circle r="7"/><circle r="3" class="bg-marker-dot"/> 10706 </g> 10707 <g class="bg-marker" transform="translate(1200,240)"> 10708 <circle r="7"/><circle r="3" class="bg-marker-dot"/> 10709 </g> 10710 <g class="bg-marker" transform="translate(1280,700)"> 10711 <circle r="7"/><circle r="3" class="bg-marker-dot"/> 10712 </g> 10713 <!-- Compass bottom-left --> 10714 <g class="bg-compass" transform="translate(180,800)"> 10715 <circle class="bg-compass-ring" r="42"/> 10716 <circle class="bg-compass-ring" r="30"/> 10717 <line class="bg-compass-tick" x1="0" y1="-46" x2="0" y2="46"/> 10718 <line class="bg-compass-tick" x1="-46" y1="0" x2="46" y2="0"/> 10719 <line class="bg-compass-tick" x1="-33" y1="-33" x2="33" y2="33"/> 10720 <line class="bg-compass-tick" x1="33" y1="-33" x2="-33" y2="33"/> 10721 <polygon class="bg-compass-arrow" points="0,-42 5,0 0,42 -5,0"/> 10722 <polygon class="bg-compass-arrow" points="-42,0 0,5 42,0 0,-5"/> 10723 <text class="bg-compass-label" x="0" y="-52" text-anchor="middle">N</text> 10724 <text class="bg-compass-label" x="54" y="4" text-anchor="middle">E</text> 10725 <text class="bg-compass-label" x="0" y="64" text-anchor="middle">S</text> 10726 <text class="bg-compass-label" x="-54" y="4" text-anchor="middle">W</text> 10727 </g> 10728 <g transform="translate(1340,820)"> 10729 <text class="bg-coord-text" x="0" y="0">09 · DESTINATION</text> 10730 </g> 10731 </svg> 10732 </div> 10733 <div class="pawtrail" aria-hidden="true"> 10734 <svg viewBox="0 0 1600 600" preserveAspectRatio="none"> 10735 <g class="paw" transform="translate(120 480) rotate(-12)"><ellipse cx="0" cy="6" rx="9" ry="11"/><circle cx="-10" cy="-9" r="4.5"/><circle cx="-3" cy="-14" r="4.5"/><circle cx="6" cy="-14" r="4.5"/><circle cx="12" cy="-9" r="4.5"/></g> 10736 <g class="paw" transform="translate(260 420) rotate(8)"><ellipse cx="0" cy="6" rx="9" ry="11"/><circle cx="-10" cy="-9" r="4.5"/><circle cx="-3" cy="-14" r="4.5"/><circle cx="6" cy="-14" r="4.5"/><circle cx="12" cy="-9" r="4.5"/></g> 10737 <g class="paw" transform="translate(420 360) rotate(-6)"><ellipse cx="0" cy="6" rx="9" ry="11"/><circle cx="-10" cy="-9" r="4.5"/><circle cx="-3" cy="-14" r="4.5"/><circle cx="6" cy="-14" r="4.5"/><circle cx="12" cy="-9" r="4.5"/></g> 10738 <g class="paw" transform="translate(580 300) rotate(10)"><ellipse cx="0" cy="6" rx="9" ry="11"/><circle cx="-10" cy="-9" r="4.5"/><circle cx="-3" cy="-14" r="4.5"/><circle cx="6" cy="-14" r="4.5"/><circle cx="12" cy="-9" r="4.5"/></g> 10739 <g class="paw" transform="translate(760 250) rotate(-5)"><ellipse cx="0" cy="6" rx="9" ry="11"/><circle cx="-10" cy="-9" r="4.5"/><circle cx="-3" cy="-14" r="4.5"/><circle cx="6" cy="-14" r="4.5"/><circle cx="12" cy="-9" r="4.5"/></g> 10740 <g class="paw" transform="translate(940 230) rotate(8)"><ellipse cx="0" cy="6" rx="9" ry="11"/><circle cx="-10" cy="-9" r="4.5"/><circle cx="-3" cy="-14" r="4.5"/><circle cx="6" cy="-14" r="4.5"/><circle cx="12" cy="-9" r="4.5"/></g> 10741 <g class="paw" transform="translate(1120 280) rotate(-8)"><ellipse cx="0" cy="6" rx="9" ry="11"/><circle cx="-10" cy="-9" r="4.5"/><circle cx="-3" cy="-14" r="4.5"/><circle cx="6" cy="-14" r="4.5"/><circle cx="12" cy="-9" r="4.5"/></g> 10742 <g class="paw" transform="translate(1300 350) rotate(6)"><ellipse cx="0" cy="6" rx="9" ry="11"/><circle cx="-10" cy="-9" r="4.5"/><circle cx="-3" cy="-14" r="4.5"/><circle cx="6" cy="-14" r="4.5"/><circle cx="12" cy="-9" r="4.5"/></g> 10743 <g class="paw" transform="translate(1450 420) rotate(-4)"><ellipse cx="0" cy="6" rx="9" ry="11"/><circle cx="-10" cy="-9" r="4.5"/><circle cx="-3" cy="-14" r="4.5"/><circle cx="6" cy="-14" r="4.5"/><circle cx="12" cy="-9" r="4.5"/></g> 10744 <g class="paw" transform="translate(1560 500) rotate(8)"><ellipse cx="0" cy="6" rx="9" ry="11"/><circle cx="-10" cy="-9" r="4.5"/><circle cx="-3" cy="-14" r="4.5"/><circle cx="6" cy="-14" r="4.5"/><circle cx="12" cy="-9" r="4.5"/></g> 10745 </svg> 10746 </div> 10747 10748 <div class="reveal-stagger" style="position:relative;z-index:1"> 10749 <span class="eyebrow" style="display:inline-flex;margin-bottom:24px;color:var(--bone)">Be part of the solution</span> 10750 <h2 class="reveal-words">This is <em>the bit</em>
10750 where you turn up.</h2> 10751 <p>Every donation lands directly with the NGO running the project. You'll get progress updates from the field, and you'll see your contribution surface as a story on the channel. 100% goes through. And you don't have to give to help: sharing spreads the word, and awareness is part of the solution.</p> 10752 <div class="actions"> 10753 <a class="btn btn-primary" href="/donate/">Donate now <span class="arrow">â</span></a> 10754 <button class="btn share-cta" type="button" data-share data-share-url="https://www.ecoflix.com/" data-share-text="You don't have to donate to help wildlife â share to show you care. Awareness is part of the solution."><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/><line x1="8.6" y1="13.5" x2="15.4" y2="17.5"/><line x1="15.4" y1="6.5" x2="8.6" y2="10.5"/></svg> Share to show your support</button> 10755 <a class="btn-quiet" href="/circle-of-giving/">Join the Circle of Giving</a> 10756 </div> 10757 10758 10759 <!-- ========================================================= 10760 ECO â NGO BRIDGE â picker that lets a visitor choose the 10761 ecosystem they care about, then a specific NGO inside it. 10762 Selecting an NGO re-keys the impact slider below so each
10763 dollar amount reads in that NGO's language. Mirrors the 10764 main ecosystems section so it feels familiar. 10765 ========================================================= --> 10766 <div class="eco-bridge" id="ecoBridge"> 10767 <div class="eco-bridge-head"> 10768 <div> 10769 <span class="eco-bridge-eyebrow">Or pick what you fund</span> 10770 <h3 class="eco-bridge-title">Choose <em>where it lands.</em></h3> 10771 </div> 10772 <p class="eco-bridge-note">Pick an ecosystem, then a project. The slider re-keys to that project â every amount reads in their language.</p> 10773 </div> 10774 <div class="eco-bridge-pills" role="tablist" aria-label="Pick an ecosystem"> 10775 <button class="eco-bridge-pill" type="button" role="tab" data-eco="oceans" aria-selected="false"> 10776 <span class="ebp-icon" aria-hidden="true"><svg viewBox="0 0 60 60"><path d="M3 22 Q 14 17 23 22 T 41 22 T 59 22"/><path d="M3 32 Q 14 27 23 32 T 41 32 T 59 32" opacity=".7"/><path class="ep-fill" d="M16 42 Q 22 38 32 38 L 42 36 L 40 41 L 46 44 L 40 47 L 42 50 L 32 48 Q 22 48 16 42 Z"/></svg></span> 10777 <span class="ebp-name">Oceans</span> 10778 <span class="ebp-count">1 project</span> 10779 </button> 10780 <button class="eco-bridge-pill" type="button" role="tab" data-eco="rainforests" aria-selected="false"> 10781 <span class="ebp-icon" aria-hidden="true"><svg viewBox="0 0 60 60"><path class="ep-fill" d="M14 52 L 14 38 L 9 38 L 17 27 L 13 27 L 19 16 L 25 27 L 21 27 L 29 38 L 24 38 L 24 52 Z"/><path class="ep-fill" d="M29 52 L 29 42 L 22 42 L 32 28 L 27 28 L 35 14 L 43 28 L 38 28 L 47 42 L 41 42 L 41 52 Z"/><path class="ep-fill" d="M44 52 L 44 40 L 39 40 L 47 30 L 43 30 L 49 20 L 55 30 L 51 30 L 58 40 L 54 40 L 54 52 Z"/></svg></span> 10782 <span class="ebp-name">Rainforests</span> 10783 <span class="ebp-count">2 projects</span> 10784 </button> 10785 <button class="eco-bridge-pill" type="button" role="tab" data-eco="savannah" aria-selected="false"> 10786 <span class="ebp-icon" aria-hidden="true"><svg viewBox="0 0 60 60"><circle cx="44" cy="18" r="7" class="ep-fill"/><line x1="3" y1="48" x2="57" y2="48"/><line x1="22" y1="48" x2="22" y2="28"/><path class="ep-fill" d="M9 26 Q 22 14 35 26 Q 30 30 22 30 Q 14 30 9 26 Z"/><line x1="22" y1="40" x2="15" y2="44" stroke-width="1.2"/><line x1="22" y1="40" x2="28" y2="44" stroke-width="1.2"/></svg></span> 10787 <span class="ebp-name">Savannah</span> 10788 <span class="ebp-count">1 project</span> 10789 </button> 10790 <button class="eco-bridge-pill" type="button" role="tab" data-eco="mountains" aria-selected="false"> 10791 <span class="ebp-icon" aria-hidden="true"><svg viewBox="0 0 60 60"><path class="ep-fill" d="M2 50 L 13 30 L 20 38 L 30 16 L 40 32 L 48 24 L 58 50 Z"/><path d="M28 19 L 30 16 L 32 20" fill="rgba(255,255,255,.85)" stroke="none"/><path d="M46 26 L 48 24 L 50 27" fill="rgba(255,255,255,.7)" stroke="none"/></svg></span> 10792 <span class="ebp-name">Mountains</span> 10793 <span class="ebp-count">2 projects</span> 10794 </button> 10795 <button class="eco-bridge-pill" type="button" role="tab" data-eco="wetlands" aria-selected="false"> 10796 <span class="ebp-icon" aria-hidden="true"><svg viewBox="0 0 60 60"><path d="M2 16 Q 18 20 26 30 T 50 44" stroke-width="2.4"/><ellipse cx="20" cy="18" rx="5" ry="1.6" class="ep-fill"/><line x1="11" y1="50" x2="10" y2="44"/><line x1="14" y1="50" x2="15" y2="41"/><line x1="46" y1="52" x2="48" y2="46"/><line x1="50" y1="52" x2="49" y2="48"/></svg></span> 10797 <span class="ebp-name">Wetlands</span> 10798 <span class="ebp-count">See all</span> 10799 </button> 10800 <button class="eco-bridge-pill" type="button" role="tab" data-eco="polar" aria-selected="false"> 10801 <span class="ebp-icon" aria-hidden="true"><svg viewBox="0 0 60 60"><path d="M2 16 Q 20 6 32 14 Q 48 20 58 10" stroke-width="1.8"/><path d="M2 24 Q 20 16 32 22 Q 48 28 58 20" opacity=".5"/><path class="ep-fill" d="M2 50 L 10 38 L 18 46 L 26 36 L 36 44 L 46 36 L 58 50 Z"/><line x1="20" y1="38" x2="22" y2="50" opacity=".6"/><line x1="40" y1="38" x2="38" y2="50" opacity=".6"/></svg></span>
10802 <span class="ebp-name">Polar</span> 10803 <span class="ebp-count">See all</span> 10804 </button> 10805 </div> 10806 <!-- Populated by the bridge script when an ecosystem is picked. --> 10807 <div class="eco-bridge-panel" id="ecoBridgePanel" role="region" aria-live="polite"></div> 10808 </div> 10809 10810 <!-- Where your money goes â interactive impact slider --> 10811 <aside class="impact-calc" id="impactCalc" aria-label="What your donation funds"> 10812 <div class="calc-head"> 10813 <!-- LEFT rail: heading + eyebrow + active-NGO chip --> 10814 <div class="calc-head-left"> 10815 <span class="calc-eyebrow">Where your money goes</span> 10816 <h3>See what your gift <em style="font-style:italic;font-weight:500;color:var(--leaf)">funds.</em></h3> 10817 <!-- Active NGO chip: shows up once the bridge above picks one, 10818 with a clear-button to revert to the generic tiers. --> 10819 <div class="calc-active-ngo" id="calcActiveNgo" hidden> 10820 Funding <b id="calcActiveNgoName"></b> 10821 <button type="button" id="calcActiveNgoClear" aria-label="Clear NGO selection">Ã</button> 10822 </div> 10823 </div> 10824 <!-- RIGHT rail: BIG amount, double-stacked with frequency below --> 10825 <div class="calc-amount-row"> 10826 <div class="calc-amount"><span class="calc-curr">$</span><span id="calcVal">50</span></div> 10827 <div class="calc-freq">one-time</div> 10828 </div> 10829 </div> 10830 <input type="range" min="5" max="1000" step="5" value="50" class="calc-slider" id="calcSlider" style="--p:4.5%" aria-label="Donation amount"> 10831 <div class="calc-presets" id="calcPresets"> 10832 <button class="calc-preset" data-v="10" type="button"><span data-money="10">$10</span></button> 10833 <button class="calc-preset active" data-v="50" type="button"><span data-money="50">$50</span></button> 10834 <button class="calc-preset" data-v="100" type="button"><span data-money="100">$100</span></button> 10835 <button class="calc-preset" data-v="250" type="button"><span data-money="250">$250</span></button> 10836 <button class="calc-preset" data-v="500" type="button"><span data-money="500">$500</span></button> 10837 <button class="calc-preset" data-v="1000" type="button"><span data-money="1000">$1,000</span></button> 10838 </div> 10839 <div class="calc-impact" id="calcImpact"> 10840 <span class="calc-impact-icon" id="calcImpactIcon" aria-hidden="true"> 10841 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12c0-5 4-9 9-9s9 4 9 9-4 9-9 9-9-4-9-9z"/><path d="M8 12c0-2 1-5 4-5s4 3 4 5-1 5-4 5-4-3-4-5z"/></svg> 10842 </span> 10843 <div class="calc-impact-text"> 10844 <div class="calc-impact-headline" id="calcHeadline">A day of drone surveillance over Sumatra</div> 10845 <div class="calc-impact-sub" id="calcSub">Fuel, pilots, post-flight mapping. Our rainforest partners run daily flights â this funds one.</div> 10846 </div> 10847 </div> 10848 <div class="calc-cta-row"> 10849 <a class="btn btn-primary" href="/donate/" id="calcCta">Donate <span id="calcCtaAmt">$50</span> <span class="arrow">â</span></a> 10850 <span class="calc-foot">100% reaches the project. We take nothing.</span> 10851 </div> 10852 </aside> 10853 10854 <!-- Live giving â real-time donations feed --> 10855 10856 </div> 10857 </section> 10858</div><!-- /.pin-stack founder-quoteâconvert --> 10859 10860<!-- ===== Newsletter signup ===== --> 10861<section class="newsletter-section" style="padding:0 var(--pad-x);background:var(--ink)"> 10862 <div class="newsletter reveal" id="newsletter"> 10863 <div class="nl-eyebrow">The field log</div> 10864 <h3>Get the work in your inbox.</h3> 10865 <p>Monthly. Field updates from the NGOs you support, new releases on the channel, projects launching next. No spam, ever.</p> 10866 <form id="nlForm" novalidate> 10867 <input type="email" id="nlEmail" placeholder="[email protected]" autocomplete="email" required aria-label="Email address"/> 10868 <button type="submit">Subscribe <span class="arrow">â</span></button> 10869 </form> 10870 <div class="nl-error">Please enter a valid email address.</div> 10871 <div class="nl-success"> 10872 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M8 12l3 3 5-6"/></svg> 10873 Welcome to the field log. First update lands next month. 10874 </div> 10875 </div> 10876</section> 10877 10878</main> 10879 10880<!-- ================================================= 10881 Footer 10882 ================================================= --> 10883<footer class="footer" style="position:relative;overflow:hidden;isolation:isolate"> 10884 <!-- CARTOGRAPH 10 · END LOG â final entry with full treatment: 10885 trail + tracks + full compass + leaf + horizon ruler + sign-off --> 10886 <div class="bg-cartograph" aria-hidden="true"> 10887 <svg viewBox="0 0 1600 900" preserveAspectRatio="xMidYMid slice">
10888 <line class="bg-lat" x1="-50" y1="120" x2="1650" y2="120"/> 10889 <line class="bg-lat" x1="-50" y1="780" x2="1650" y2="780"/> 10890 <!-- Top-margin signature trail --> 10891 <path class="bg-trail" d="M-40,180 C260,160 540,220 800,180 C1060,140 1340,200 1660,170"/> 10892 <path class="bg-trail-soft" d="M-40,260 C220,300 460,260 700,280 C940,300 1180,260 1660,290"/> 10893 <!-- Animal tracks along the trail --> 10894 <circle class="bg-track" cx="220" cy="172" r="3"/> 10895 <circle class="bg-track" cx="300" cy="178" r="3"/> 10896 <circle class="bg-track" cx="380" cy="186" r="3"/> 10897 <circle class="bg-track" cx="460" cy="194" r="3"/> 10898 <!-- Way-finished pins along the bottom contour --> 10899 <g class="bg-marker" transform="translate(280,804)"> 10900 <circle r="10"/><circle r="3.5" class="bg-marker-dot"/> 10901 </g> 10902 <g class="bg-marker" transform="translate(780,800)"> 10903 <circle r="12"/><circle r="4" class="bg-marker-dot"/> 10904 </g> 10905 <g class="bg-marker" transform="translate(1280,804)"> 10906 <circle r="10"/><circle r="3.5" class="bg-marker-dot"/> 10907 </g> 10908 <!-- Top-right full compass --> 10909 <g class="bg-compass" transform="translate(1490,220)"> 10910 <circle class="bg-compass-ring" r="42"/> 10911 <circle class="bg-compass-ring" r="30"/> 10912 <line class="bg-compass-tick" x1="0" y1="-46" x2="0" y2="46"/> 10913 <line class="bg-compass-tick" x1="-46" y1="0" x2="46" y2="0"/> 10914 <line class="bg-compass-tick" x1="-33" y1="-33" x2="33" y2="33"/> 10915 <line class="bg-compass-tick" x1="33" y1="-33" x2="-33" y2="33"/> 10916 <polygon class="bg-compass-arrow" points="0,-42 5,0 0,42 -5,0"/> 10917 <polygon class="bg-compass-arrow" points="-42,0 0,5 42,0 0,-5"/> 10918 <text class="bg-compass-label" x="0" y="-52" text-anchor="middle">N</text> 10919 <text class="bg-compass-label" x="54" y="4" text-anchor="middle">E</text> 10920 <text class="bg-compass-label" x="0" y="64" text-anchor="middle">S</text> 10921 <text class="bg-compass-label" x="-54" y="4" text-anchor="middle">W</text> 10922 </g> 10923 <!-- Horizon ruler in top-left margin --> 10924 <g transform="translate(140,80)"> 10925 <line class="bg-compass-tick" x1="0" y1="0" x2="320" y2="0" stroke-width="1"/> 10926 <line class="bg-compass-tick" x1="0" y1="-6" x2="0" y2="6" stroke-width="1"/> 10927 <line class="bg-compass-tick" x1="40" y1="-3" x2="40" y2="3"/> 10928 <line class="bg-compass-tick" x1="80" y1="-3" x2="80" y2="3"/> 10929 <line class="bg-compass-tick" x1="120" y1="-3" x2="120" y2="3"/> 10930 <line class="bg-compass-tick" x1="160" y1="-4" x2="160" y2="4"/> 10931 <line class="bg-compass-tick" x1="200" y1="-3" x2="200" y2="3"/> 10932 <line class="bg-compass-tick" x1="240" y1="-3" x2="240" y2="3"/> 10933 <line class="bg-compass-tick" x1="280" y1="-3" x2="280" y2="3"/> 10934 <line class="bg-compass-tick" x1="320" y1="-6" x2="320" y2="6" stroke-width="1"/> 10935 </g> 10936 <!-- Leaf vein in left margin --> 10937 <!-- Topo contour rings (sign-off mark, replaces leaf motif) --> 10938 <g transform="translate(80,520)"> 10939 <circle class="bg-compass-ring" r="38" fill="none"/> 10940 <circle class="bg-compass-ring" r="26" fill="none" stroke-dasharray="3 8"/> 10941 <circle class="bg-compass-ring" r="14" fill="none" stroke-dasharray="2 7"/> 10942 <circle r="2.5" class="bg-marker-dot"/> 10943 </g> 10944 <!-- Closing-entry coordinate stamps --> 10945 <g transform="translate(140,60)"> 10946 <text class="bg-coord-text" x="0" y="0">10 · END LOG</text> 10947 </g> 10948 <g transform="translate(1280,60)"> 10949 <text class="bg-coord-text" x="0" y="0">DONATE TODAY · PROTECT TOMORROW</text> 10950 </g> 10951 <!-- Signature contour curve along the bottom --> 10952 <path class="bg-trail-soft" d="M-50,820 C260,790 540,810 860,800 C1140,790 1380,810 1700,800"/> 10953 </svg> 10954 </div> 10955 <div class="wrap" style="position:relative;z-index:2"> 10956 <div class="footer-grid"> 10957 <div class="footer-brand"> 10958 <a href="/" class="brand" aria-label="Ecoflix home"><img src="/assets/logo.png" alt="Ecoflix" style="height:34px;width:auto;display:block" /></a> 10959 <p style="font-family:var(--display);font-style:italic;font-size:18px;color:var(--bone);margin-top:14px">Be part of the solution.</p> 10960 <p>The not-for-profit foundation behind the channel. Funding the people doing the work on the ground.</p> 10961 <div class="socials" aria-label="Social"> 10962 <a href="https://www.instagram.com/ecoflixofficial/" aria-label="Instagram">
10962<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="18" height="18" rx="5"/><circle cx="12" cy="12" r="4"/><circle cx="17.5" cy="6.5" r="1" fill="currentColor"/></svg></a> 10963 <a href="https://www.facebook.com/ecoflixofficial" aria-label="Facebook"><svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor"><path d="M13 22v-9h3l.5-4H13V6.5c0-1 .3-1.7 1.8-1.7H17V1.4C16.6 1.3 15.3 1.2 14 1.2c-2.8 0-4.7 1.7-4.7 4.9V9H6v4h3.3v9H13z"/></svg></a> 10964 <a href="https://twitter.com/ecoflixofficial" aria-label="X"><svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><path d="M18.244 2H21.5l-7.55 8.63L23 22h-6.79l-5.32-6.97L4.76 22H1.5l8.08-9.24L1 2h6.91l4.81 6.36L18.244 2zm-2.38 18h1.88L7.21 4H5.21l10.65 16z"/></svg></a> 10965 <a href="https://www.tiktok.com/@ecoflixofficial" aria-label="TikTok"><svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><path d="M19.6 7c-1.9 0-3.6-.8-4.8-2.1-.6-.6-1-1.4-1.2-2.3h-3.3v11.5c0 1.4-1.1 2.5-2.5 2.5s-2.5-1.1-2.5-2.5 1.1-2.5 2.5-2.5c.3 0 .5 0 .8.1V8.4c-.3 0-.5-.1-.8-.1-3.2 0-5.8 2.6-5.8 5.8s2.6 5.8 5.8 5.8 5.8-2.6 5.8-5.8V9.4c1.4 1 3.1 1.5 4.9 1.5V7.5L19.6 7z"/></svg></a> 10966 <a href="https://www.linkedin.com/company/ecoflix/" aria-label="LinkedIn"><svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><path d="M20.45 20.45h-3.55v-5.57c0-1.33-.03-3.04-1.85-3.04-1.85 0-2.14 1.45-2.14 2.94v5.67H9.36V9h3.4v1.56h.05c.47-.9 1.63-1.85 3.36-1.85 3.6 0 4.27 2.37 4.27 5.45v6.29zM5.34 7.43a2.06 2.06 0 1 1 0-4.13 2.06 2.06 0 0 1 0 4.13zM7.12 20.45H3.55V9h3.57v11.45zM22.23 0H1.77C.79 0 0 .77 0 1.72v20.56C0 23.23.79 24 1.77 24h20.46c.98 0 1.77-.77 1.77-1.72V1.72C24 .77 23.21 0 22.23 0z"/></svg></a> 10967 <a href="https://www.youtube.com/@ecoflixofficial" aria-label="YouTube"><svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor"><path d="M23 7.2c-.3-1.1-1.1-2-2.2-2.2C18.6 4.5 12 4.5 12 4.5s-6.6 0-8.8.5c-1.1.3-2 1.1-2.2 2.2C.5 9.4.5 12 .5 12s0 2.6.5 4.8c.3 1.1 1.1 2 2.2 2.2 2.2.5 8.8.5 8.8.5s6.6 0 8.8-.5c1.1-.3 2-1.1 2.2-2.2.5-2.2.5-4.8.5-4.8s0-2.6-.5-4.8zM9.8 16.2V7.8L15.5 12l-5.7 4.2z"/></svg></a> 10968 </div> 10969 </div> 10970 <div> 10971 <h4 data-i18n="footer.foundation">Foundation</h4> 10972 <ul> 10973 <li><a href="/mission/">Mission</a></li> 10974 <li><a href="/history/">Our story</a></li> 10975 <li><a href="/ngo-partners/">NGO Partners</a></li> 10976 <li><a href="/projects/">Conservation Projects</a></li> 10977 <li><a href="/partners/">Corporate Partners</a></li> 10978 <li><a href="/team/">Team</a></li> 10979 <li><a href="/ngo-portal/">NGO partner sign-in â</a></li> 10980 </ul> 10981 </div> 10982 <div> 10983 <h4 data-i18n="footer.give">Give</h4> 10984 <ul> 10985 <li><a href="/donate/">Donate</a></li> 10986 <li><a href="/circle-of-giving/">Circle of Giving</a></li> 10987 <li><a href="/gift-memberships/">Gift memberships</a></li> 10988 <li><a href="/partners/">Become a partner</a></li> 10989 </ul> 10990 </div> 10991 <div> 10992 <h4>Watch and read</h4> 10993 <ul> 10994 <li><a href="https://watch.ecoflix.com/category/ecoflix-originals">Ecoflix Originals</a></li> 10995 <li><a href="https://watch.ecoflix.com/category/podcasts">Podcasts</a></li> 10996 <li><a href="https://watch.ecoflix.com/category/stuff-for-kids">Stuff for kids</a></li> 10997 <li><a href="/news/">Ecoflix News</a></li> 10998 <li><a href="/podcasts/">Podcasts</a></li> 10999 <li><a href="/distribution/">Distribution & advertising</a></li> 11000 <li><a href="https://watch.ecoflix.com/">Channel home</a></li> 11001 </ul> 11002 </div> 11003 </div> 11004 11005 <div class="footer-stats"> 11006 <div><b><span data-livestat="raised">$698K</span>+</b>Deployed to partners</div> 11007 <div><b>6</b>Continents in play</div> 11008 <div><b data-livestat="ngos">64</b>NGO partners</div> 11009 <div><b data-livestat="projects">34</b>Projects funded</div> 11010 </div> 11011 11012 <!-- Charity registration block â formal disclosure of both legal 11013 entities behind the Ecoflix Foundation. Mirrors the ecoflix.com 11014 footer charity info so visitors see the same registration 11015 numbers and addresses across both properties. --> 11016 <div class="footer-charity"> 11017 <div class="fc-col"> 11018 <div class="fc-eyebrow"><span class="fc-flag" aria-hidden="true">ðºð¸</span> Registered in the United States</div> 11019 <div class="fc-body"> 11020 <strong>Ecoflix Foundation Inc.</strong> · 501(c)(3) not-for-profit · EIN <b>65-1212560</b><br/> 11021 24730 Long Valley Road, Hidden Hills, Los Angeles, CA 91302, USA 11022 </div> 11023 </div> 11024 <div class="fc-col"> 11025 <div class="fc-eyebrow"><span class="fc-flag" aria-hidden="true">ð¬ð§</span> Registered in the United Kingdom</div> 11026 <div class="fc-body"> 11027 <strong>Ecoflix Foundation UK</strong> · Registered charity <b>1200441</b><br/> 11028 Aston House, Redburn Road, Newcastle Upon Tyne, NE5 1NB, United Kingdom 11029 </div> 11030 </div> 11031 <div class="fc-col fc-col-note"> 11032 <div class="fc-eyebrow">100% pass-through</div> 11033 <div class="fc-body"> 11034 All donations route directly to partner NGOs. Ecoflix Foundation's 11035 operating costs are covered separately by founders and corporate 11036 partners â no deductions are taken from donor gifts. 11037 </div> 11038 </div> 11039 </div> 11040 11041 <div class="footer-base"> 11042 <div>© <span id="yr"></span> Ecoflix Foundation. All rights reserved.</div> 11043 <div> 11044 <a href="/privacy/">Privacy</a> <a href="/terms/">Terms</a> 11045 <a href="/cookies/">Cookies</a> <a href="/news/">Press</a> 11046 <a href="mailto:[email protected]">[email protected]</a> 11047 </div> 11048 </div> 11049 </div> 11050</footer> 11051 11052<!-- Footer charity block styling lives in /assets/site.css now â 11053 it was here originally but moved to the shared stylesheet 11054 so every page can render the same disclosure without 11055 duplicating ~40 lines of CSS per file. --> 11056
11057<script> 11058/* ====== Year ====== */ 11059document.getElementById('yr').textContent = new Date().getFullYear(); 11060 11061/* ====== Ambient mouse-follow green glow ====== */ 11062(() => { 11063 const glow = document.getElementById('ambientGlow'); 11064 if (!glow) return; 11065 const finePointer = window.matchMedia('(hover:hover) and (pointer:fine)').matches; 11066 const reduceMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches; 11067 if (!finePointer || reduceMotion) return; 11068 11069 let tx = window.innerWidth / 2, ty = window.innerHeight / 3; 11070 let gx = tx, gy = ty; 11071 let running = false; 11072 11073 document.addEventListener('mousemove', (e) => { 11074 tx = e.clientX; ty = e.clientY; 11075 if (!glow.classList.contains('is-on')) glow.classList.add('is-on'); 11076 if (!running) { running = true; requestAnimationFrame(frame); } 11077 }); 11078 11079 function frame(){ 11080 // slow easing for an ambient drift, not a snappy cursor 11081 gx += (tx - gx) * 0.05; 11082 gy += (ty - gy) * 0.05; 11083 glow.style.transform = `translate(${gx}px, ${gy}px) translate(-50%, -50%)`; 11084 if (Math.abs(tx - gx) > 0.5 || Math.abs(ty - gy) > 0.5) { 11085 requestAnimationFrame(frame); 11086 } else { 11087 running = false; 11088 } 11089 } 11090})(); 11091 11092/* ====== Header scroll state + parallax CSS variable for cartograph art ====== */ 11093const header = document.getElementById('header'); 11094const docEl = document.documentElement; 11095const onScroll = () => { 11096 header.classList.toggle('scrolled', window.scrollY > 24); 11097 // Expose scroll position to CSS so the .bg-cartograph illustrations 11098 // parallax up slightly as the user scrolls (subtle depth-of-field). 11099 docEl.style.setProperty('--scroll-y', String(window.scrollY)); 11100}; 11101onScroll(); 11102window.addEventListener('scroll', onScroll, { passive:true }); 11103 11104/* ====== Mobile drawer ====== */ 11105const menuBtn = document.getElementById('menuBtn'); 11106const drawer = document.getElementById('drawer'); 11107function setDrawer(open){ 11108 menuBtn.classList.toggle('open', open); 11109 drawer.classList.toggle('open', open); 11110 drawer.setAttribute('aria-hidden', String(!open)); 11111 menuBtn.setAttribute('aria-expanded', String(open)); 11112 menuBtn.setAttribute('aria-label', open ? 'Close menu' : 'Open menu'); 11113 document.body.style.overflow = open ? 'hidden' : ''; 11114} 11115menuBtn?.addEventListener('click', () => setDrawer(!menuBtn.classList.contains('open'))); 11116drawer?.querySelectorAll('a').forEach(a => a.addEventListener('click', () => setDrawer(false))); 11117document.addEventListener('keydown', (e) => { 11118 if (e.key === 'Escape' && menuBtn.classList.contains('open')) setDrawer(false); 11119}); 11120 11121/* ====== Hero (single-viewport static, no scroll-scrub) ====== */ 11122const heroCard = document.getElementById('heroCard'); 11123const scrollCue = document.getElementById('scrollCue'); 11124const reducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches; 11125 11126if (heroCard) heroCard.style.setProperty('--card-copy-op', 1); 11127if (scrollCue) scrollCue.style.setProperty('--cue-op', 1); 11128 11129// Honour reduced-motion: pause every autoplay video, leave the poster in view. 11130if (reducedMotion) { 11131 document.querySelectorAll('video[autoplay]').forEach(v => { 11132 v.removeAttribute('autoplay'); 11133 v.pause(); 11134 }); 11135} 11136 11137/* ====== IntersectionObserver reveals ====== */ 11138const io = new IntersectionObserver((entries) => { 11139 entries.forEach(e => { 11140 if (e.isIntersecting) { 11141 e.target.classList.add('in'); 11142 io.unobserve(e.target); 11143 } 11144 }); 11145}, { threshold: 0.12, rootMargin: '0px 0px -8% 0px' }); 11146 11147document.querySelectorAll('.reveal, .reveal-stagger').forEach(el => io.observe(el)); 11148 11149/* Section card-lift trigger â adds .is-revealed to each .section-lift 11150 when its top edge enters the viewport, animating the rise + scale */ 11151const liftIO = new IntersectionObserver((entries) => { 11152 entries.forEach(e => { 11153 if (e.isIntersecting) { 11154 e.target.classList.add('is-revealed'); 11155 liftIO.unobserve(e.target); 11156 } 11157 }); 11158}, { threshold: 0.04, rootMargin: '0px 0px -2% 0px' }); 11159document.querySelectorAll('.section-lift').forEach(el => liftIO.observe(el)); 11160 11161/* ====== Hero single clip â kick off playback, no carousel rotation ====== */ 11162(() => { 11163 const carousel = document.getElementById('heroCarousel'); 11164 if (!carousel) return; 11165 const video = carousel.querySelector('.hcv'); 11166 if (!video) return; 11167 video.play().catch(() => {/* autoplay policy may block â fine, will play on first interaction */}); 11168})(); 11169 11170/* Project cards now render as a static grid â horizontal-scroll driver removed. */ 11171 11172/* ====== Word-by-word reveals on big cinematic headlines ====== */ 11173(() => { 11174 function wrapWords(el){ 11175 const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT, null); 11176 const nodes = []; 11177 while (walker.nextNode()) nodes.push(walker.currentNode);
11178 nodes.forEach(node => { 11179 if (!node.textContent.trim()) return; 11180 const parts = node.textContent.split(/(\s+)/); 11181 const frag = document.createDocumentFragment(); 11182 parts.forEach(p => { 11183 if (/\S/.test(p)) { 11184 const wrap = document.createElement('span'); 11185 wrap.className = 'word'; 11186 const inner = document.createElement('span'); 11187 inner.className = 'word-inner'; 11188 inner.textContent = p; 11189 wrap.appendChild(inner); 11190 frag.appendChild(wrap); 11191 } else if (p.length) { 11192 frag.appendChild(document.createTextNode(p)); 11193 } 11194 }); 11195 node.parentNode.replaceChild(frag, node); 11196 }); 11197 } 11198 document.querySelectorAll('.reveal-words').forEach(wrapWords); 11199 11200 if (reducedMotion) { 11201 document.querySelectorAll('.reveal-words').forEach(el => el.classList.add('in')); 11202 } else { 11203 const wIO = new IntersectionObserver((entries) => { 11204 entries.forEach(e => { 11205 if (e.isIntersecting) { 11206 e.target.classList.add('in'); 11207 wIO.unobserve(e.target); 11208 } 11209 }); 11210 }, { threshold: 0.3 }); 11211 document.querySelectorAll('.reveal-words').forEach(el => wIO.observe(el)); 11212 } 11213})(); 11214 11215/* ====== Timeline + pillar icon reveals (per-item, once only) ====== */ 11216const tlIO = new IntersectionObserver((entries) => { 11217 entries.forEach(e => { 11218 if (e.isIntersecting) { 11219 e.target.classList.add('in'); 11220 tlIO.unobserve(e.target); 11221 } 11222 }); 11223}, { threshold: 0.25, rootMargin: '0px 0px -10% 0px' }); 11224document.querySelectorAll('.tl-item, .pillar, .proj-card').forEach(el => tlIO.observe(el)); 11225 11226/* ====== World map popups ====== */ 11227(() => { 11228 const wrap = document.querySelector('.globe-wrap'); 11229 const popup = document.getElementById('mapPopup'); 11230 if (!wrap || !popup) return; 11231 const mpImg = document.getElementById('mpImg'); 11232 const mpStatus = document.getElementById('mpStatus'); 11233 const mpWhere = document.getElementById('mpWhere'); 11234 const mpCoords = document.getElementById('mpCoords'); 11235 const mpName = document.getElementById('mpName'); 11236 const mpNgo = document.getElementById('mpNgo'); 11237 const mpDesc = document.getElementById('mpDesc'); 11238 const mpStat = document.getElementById('mpStat'); 11239 const mpCta = document.getElementById('mpCta'); 11240 const mpClose = document.getElementById('mpClose'); 11241 11242 function close(){ 11243 popup.classList.remove('is-open'); 11244 popup.setAttribute('aria-hidden', 'true'); 11245 wrap.classList.remove('popup-open'); 11246 } 11247 function openFor(pin){ 11248 const d = pin.dataset; 11249 // Populate 11250 mpImg.style.backgroundImage = d.img ? `url('${d.img}')` : 'none'; 11251 mpImg.style.display = d.img ? 'block' : 'none'; 11252 mpStatus.textContent = d.status === 'urgent' ? 'Urgent' : d.status === 'featured' ? 'Featured' : 'Active'; 11253 mpWhere.textContent = d.where || 'â'; 11254 mpCoords.textContent = d.coords || ''; 11255 mpName.textContent = d.name || 'â'; 11256 mpNgo.textContent = d.ngo || ''; 11257 mpDesc.textContent = d.desc || ''; 11258 mpStat.textContent = d.stat || ''; 11259 mpCta.setAttribute('href', d.href || '#'); 11260 popup.classList.remove('is-urgent', 'is-featured'); 11261 if (d.status === 'urgent') popup.classList.add('is-urgent'); 11262 if (d.status === 'featured') popup.classList.add('is-featured'); 11263 11264 // Centre the popup in the middle of the map (size/position via CSS class) 11265 const wrapRect = wrap.getBoundingClientRect(); 11266 const popupW = Math.min(380, wrapRect.width - 32); 11267 popup.style.width = popupW + 'px'; 11268 popup.style.left = '50%'; 11269 popup.style.top = '50%'; 11270 // Clear any inline transform so CSS .is-open transition takes over 11271 popup.style.transform = ''; 11272 wrap.classList.add('popup-open'); 11273 11274 popup.classList.add('is-open'); 11275 popup.setAttribute('aria-hidden', 'false'); 11276 } 11277 11278 wrap.querySelectorAll('.pin').forEach(pin => { 11279 pin.addEventListener('click', (e) => { 11280 e.stopPropagation(); 11281 openFor(pin); 11282 }); 11283 }); 11284 mpClose.addEventListener('click', close); 11285 document.addEventListener('click', (e) => { 11286 if (!popup.classList.contains('is-open')) return; 11287 if (popup.contains(e.target)) return; 11288 if (e.target.closest('.pin')) return; 11289 close(); 11290 }); 11291 document.addEventListener('keydown', (e) => { if (e.key === 'Escape') close(); }); 11292})(); 11293 11294/* ====== Number counters ====== */ 11295const easeOut = t => 1 - Math.pow(1 - t, 3); 11296function animateCount(el) { 11297 const to = parseInt(el.dataset.to, 10); 11298 const prefix = el.dataset.prefix || ''; 11299 const suffix = el.dataset.suffix || ''; 11300 const dur = 1800; 11301 const start = performance.now(); 11302 const tick = (now) => { 11303 const t = Math.min(1, (now - start) / dur); 11304 const v = Math.floor(easeOut(t) * to);
11305 el.textContent = prefix + v.toLocaleString() + suffix; 11306 if (t < 1) requestAnimationFrame(tick); 11307 else el.textContent = prefix + to.toLocaleString() + suffix; 11308 }; 11309 requestAnimationFrame(tick); 11310} 11311const countIO = new IntersectionObserver((entries) => { 11312 entries.forEach(e => { 11313 if (e.isIntersecting) { 11314 animateCount(e.target); 11315 countIO.unobserve(e.target); 11316 } 11317 }); 11318}, { threshold: 0.4 }); 11319document.querySelectorAll('.count').forEach(el => countIO.observe(el)); 11320 11321/* ====== Pillars pinned-side slide swap ====== */ 11322const pillars = [...document.querySelectorAll('.pillar')]; 11323const slides = [...document.querySelectorAll('.pillars-media .slide')]; 11324const badgeText = document.getElementById('pillarBadgeText'); 11325const pillarLabels = [ 11326 'Pillar 01 · The Channel', 11327 'Pillar 02 · NGO Pages', 11328 'Pillar 03 · The Audience', 11329 'Pillar 04 · Direct Action' 11330]; 11331const pillarIO = new IntersectionObserver((entries) => { 11332 entries.forEach(e => { 11333 if (e.isIntersecting) { 11334 const idx = parseInt(e.target.dataset.i, 10); 11335 slides.forEach(s => s.classList.toggle('active', parseInt(s.dataset.i,10) === idx)); 11336 badgeText.textContent = pillarLabels[idx]; 11337 } 11338 }); 11339}, { threshold: 0.5, rootMargin: '-25% 0px -25% 0px' }); 11340pillars.forEach(p => pillarIO.observe(p)); 11341 11342/* ====== Project card spotlight + tilt ====== */ 11343document.querySelectorAll('.proj-card.js-tilt').forEach(card => { 11344 card.addEventListener('mousemove', (e) => { 11345 if (card.closest('.pcs-panels')) return; // panels mode owns layout 11346 const r = card.getBoundingClientRect(); 11347 const x = ((e.clientX - r.left) / r.width) * 100; 11348 const y = ((e.clientY - r.top) / r.height) * 100; 11349 card.style.setProperty('--mx', x + '%'); 11350 card.style.setProperty('--my', y + '%'); 11351 const tiltX = (50 - y) * 0.05; 11352 const tiltY = (x - 50) * 0.05; 11353 card.style.transform = `perspective(1000px) rotateX(${tiltX}deg) rotateY(${tiltY}deg) translateZ(0)`; 11354 }); 11355 card.addEventListener('mouseleave', () => { 11356 if (card.closest('.pcs-panels')) return; // panels mode owns layout 11357 card.style.transform = ''; 11358 card.style.setProperty('--mx', '50%'); 11359 card.style.setProperty('--my', '50%'); 11360 }); 11361}); 11362 11363/* ====== Biome scrollytelling cross-fade ====== */ 11364(() => { 11365 const section = document.querySelector('.biomes'); 11366 if (!section) return; 11367 const layers = [...section.querySelectorAll('.biome-layer')]; 11368 const texts = [...section.querySelectorAll('.biome-text')]; 11369 const chips = [...section.querySelectorAll('.bchip')]; 11370 const n = layers.length; 11371 let currentIdx = -1; 11372 11373 function setActive(idx){ 11374 if (idx === currentIdx) return; 11375 currentIdx = idx; 11376 layers.forEach((l, i) => { 11377 const active = i === idx; 11378 l.classList.toggle('is-active', active); 11379 if (active) l.play().catch(() => {}); 11380 else l.pause(); 11381 }); 11382 texts.forEach((t, i) => t.classList.toggle('is-active', i === idx)); 11383 chips.forEach((c, i) => c.classList.toggle('is-active', i === idx)); 11384 } 11385 11386 function onScroll(){ 11387 const r = section.getBoundingClientRect(); 11388 const total = section.offsetHeight - window.innerHeight; 11389 const progress = Math.max(0, Math.min(1, -r.top / total)); 11390 // Map progress to biome index. Each biome owns 1/n of the scroll. 11391 const idx = Math.min(n - 1, Math.floor(progress * n)); 11392 setActive(idx); 11393 } 11394 11395 if (reducedMotion) { 11396 setActive(0); 11397 } else { 11398 onScroll(); 11399 window.addEventListener('scroll', onScroll, { passive:true }); 11400 window.addEventListener('resize', onScroll); 11401 } 11402})(); 11403 11404/* ====== Pause off-screen videos (saves CPU / bandwidth) ====== */ 11405if (!reducedMotion && 'IntersectionObserver' in window) { 11406 const videoIO = new IntersectionObserver((entries) => { 11407 entries.forEach(e => { 11408 const v = e.target; 11409 if (e.isIntersecting) { 11410 v.play().catch(() => {/* autoplay policy may block â ignore */}); 11411 } else { 11412 v.pause(); 11413 } 11414 }); 11415 }, { threshold: 0.1 }); 11416 document.querySelectorAll('.btile video, .hero-video, .pvideo, .wvideo, .fq-video, .img-video, .trailer-video').forEach(v => videoIO.observe(v)); 11417} 11418 11419/* FAQ accordion is now native <details>/<summary> â no JS needed. */ 11420 11421/* ====== World map activation ====== 11422 Adds .is-visible to the globe when it enters the viewport (triggers
11423 the staggered draw-in for continents, arcs and pins). Then runs an 11424 ambient donation-ping loop: every ~1.6s a green expanding ring 11425 appears at a random pin location, like a real-time donation feed. */ 11426(function activateGlobe(){ 11427 const wrap = document.getElementById('globeWrap'); 11428 if (!wrap) return; 11429 11430 let activated = false; 11431 const io = new IntersectionObserver((entries) => { 11432 entries.forEach(e => { 11433 if (e.isIntersecting && !activated){ 11434 activated = true; 11435 wrap.classList.add('is-visible'); 11436 // Wait for pins to land, then start the ambient pings 11437 setTimeout(startPings, 2800); 11438 } 11439 }); 11440 }, { threshold: 0.25 }); 11441 io.observe(wrap); 11442 11443 function startPings(){ 11444 if (window.matchMedia('(prefers-reduced-motion:reduce)').matches) return; 11445 const pins = Array.from(wrap.querySelectorAll('.pin')); 11446 if (!pins.length) return; 11447 let lastIdx = -1; 11448 11449 function spawn(){ 11450 // Don't spawn while the popup is open â the page is in focus mode 11451 if (wrap.classList.contains('popup-open')) { 11452 setTimeout(spawn, 1800); 11453 return; 11454 } 11455 // Pick a pin distinct from the last one 11456 let idx; 11457 do { 11458 idx = Math.floor(Math.random() * pins.length); 11459 } while (idx === lastIdx && pins.length > 1); 11460 lastIdx = idx; 11461 11462 const pin = pins[idx]; 11463 const ping = document.createElement('div'); 11464 ping.className = 'donation-ping'; 11465 // Featured/urgent pins get a hotter ring to match their dot 11466 if (pin.classList.contains('is-urgent')){ 11467 ping.style.borderColor = 'rgba(226,106,91,.85)'; 11468 ping.style.boxShadow = '0 0 14px rgba(226,106,91,.55)'; 11469 } else if (pin.classList.contains('is-featured')){ 11470 ping.style.borderColor = 'rgba(240,194,95,.85)'; 11471 ping.style.boxShadow = '0 0 14px rgba(240,194,95,.55)'; 11472 } 11473 ping.style.left = pin.style.left; 11474 ping.style.top = pin.style.top; 11475 wrap.appendChild(ping); 11476 setTimeout(() => ping.remove(), 1900); 11477 11478 // Stagger 1.2â2.4s between pings for natural rhythm 11479 const next = 1200 + Math.random() * 1200; 11480 setTimeout(spawn, next); 11481 } 11482 spawn(); 11483 } 11484})(); 11485 11486/* ====== Smooth anchor (header offset) ====== */ 11487document.querySelectorAll('a[href^="#"]').forEach(a => { 11488 a.addEventListener('click', (e) => { 11489 const id = a.getAttribute('href'); 11490 if (id.length > 1) { 11491 const target = document.querySelector(id); 11492 if (target) { 11493 e.preventDefault(); 11494 const top = target.getBoundingClientRect().top + window.scrollY - 70; 11495 window.scrollTo({ top, behavior: 'smooth' }); 11496 } 11497 } 11498 }); 11499}); 11500 11501/* ===== Geolocate: find the nearest project ===== */ 11502(function(){ 11503 const strip = document.getElementById('nearMe'); 11504 if (!strip) return; 11505 const btn = document.getElementById('nearMeBtn'); 11506 const btnLabel = strip.querySelector('.nm-btn-label'); 11507 const userLatEl = strip.querySelector('.nm-user-lat'); 11508 const userLonEl = strip.querySelector('.nm-user-lon'); 11509 const nearestNameEl = strip.querySelector('.nm-nearest-name'); 11510 const nearestDistEl = strip.querySelector('.nm-dist'); 11511 const headlineEl = strip.querySelector('.nm-headline'); 11512 const idleHeadline = headlineEl.textContent; 11513 11514 function setState(s){ strip.setAttribute('data-state', s); } 11515 11516 function fmtCoord(v, posLabel, negLabel){ 11517 const dir = v >= 0 ? posLabel : negLabel; 11518 return Math.abs(v).toFixed(2) + '°' + dir; 11519 } 11520 function haversine(lat1, lon1, lat2, lon2){ 11521 const R = 6371; // km 11522 const toRad = x => x * Math.PI / 180; 11523 const dLat = toRad(lat2 - lat1); 11524 const dLon = toRad(lon2 - lon1); 11525 const a = Math.sin(dLat/2)**2 + 11526 Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) * 11527 Math.sin(dLon/2)**2; 11528 return 2 * R * Math.asin(Math.sqrt(a)); 11529 } 11530 11531 function findNearest(userLat, userLon){ 11532 const cards = Array.from(document.querySelectorAll('.proj-card[data-lat][data-lon]')); 11533 let best = null; 11534 cards.forEach(c => { 11535 const lat = parseFloat(c.dataset.lat); 11536 const lon = parseFloat(c.dataset.lon); 11537 if (Number.isNaN(lat) || Number.isNaN(lon)) return; 11538 const d = haversine(userLat, userLon, lat, lon); 11539 if (!best || d < best.dist) best = { card: c, dist: d, name: c.dataset.name || 'Project' }; 11540 }); 11541 return best; 11542 } 11543 11544 function applyResult(userLat, userLon){ 11545 userLatEl.textContent = fmtCoord(userLat, 'N', 'S'); 11546 userLonEl.textContent = fmtCoord(userLon, 'E', 'W'); 11547 const nearest = findNearest(userLat, userLon); 11548 if (nearest){
11549 nearestNameEl.textContent = nearest.name; 11550 const km = nearest.dist; 11551 const niceDist = km < 1 11552 ? '< 1 km away' 11553 : km < 10 11554 ? km.toFixed(1) + ' km away' 11555 : Math.round(km).toLocaleString() + ' km away'; 11556 nearestDistEl.textContent = niceDist; 11557 // mark the card 11558 document.querySelectorAll('.proj-card.is-nearest').forEach(el => el.classList.remove('is-nearest')); 11559 nearest.card.classList.add('is-nearest'); 11560 headlineEl.textContent = 'Your nearest project'; 11561 } 11562 setState('granted'); 11563 } 11564 11565 function handleError(err){ 11566 setState('error'); 11567 btnLabel.textContent = 'Try again'; 11568 headlineEl.textContent = idleHeadline; 11569 const status = strip.querySelector('.nearme-status'); 11570 if (status){ 11571 if (err && err.code === 1) status.textContent = 'Location blocked. You can re-enable it in your browser settings.'; 11572 else if (err && err.code === 3) status.textContent = 'Took too long â try again?'; 11573 else status.textContent = 'Couldnât pin your location. Try again?'; 11574 } 11575 } 11576 11577 btn.addEventListener('click', () => { 11578 if (!('geolocation' in navigator)){ 11579 handleError({ code: 0 }); 11580 return; 11581 } 11582 setState('loading'); 11583 btnLabel.textContent = 'Locatingâ¦'; 11584 navigator.geolocation.getCurrentPosition( 11585 pos => applyResult(pos.coords.latitude, pos.coords.longitude), 11586 err => handleError(err), 11587 { enableHighAccuracy:false, timeout:10000, maximumAge:300000 } 11588 ); 11589 }); 11590})(); 11591 11592/* ================= CLIENT DEMO MODULES ================= */ 11593 11594 11595/* === 2. Impact calculator === */ 11596(function(){ 11597 const slider = document.getElementById('calcSlider'); 11598 if (!slider) return; 11599 const valEl = document.getElementById('calcVal'); 11600 const headlineEl = document.getElementById('calcHeadline'); 11601 const subEl = document.getElementById('calcSub'); 11602 const iconEl = document.getElementById('calcImpactIcon'); 11603 const impactWrap = document.getElementById('calcImpact'); 11604 const ctaAmtEl = document.getElementById('calcCtaAmt'); 11605 const ctaEl = document.getElementById('calcCta'); 11606 const presets = document.querySelectorAll('#calcPresets .calc-preset'); 11607 11608 // Tiers: each defines a threshold (amount) and the impact copy + icon 11609 const tiers = [ 11610 { up:9, icon:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2v20M4 8c4 0 4 6 8 6s4-6 8-6"/></svg>', 11611 h:'A ranger meal in Kenya', 11612 s:'A hot meal at the end of a 12-hour patrol. Small but it keeps people in the field.' }, 11613 { up:24, icon:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="9" r="4"/><path d="M3 21c0-5 4-9 9-9s9 4 9 9"/></svg>', 11614 h:'Two days of school workshops', 11615 s:'Curriculum and teacher packs for a class learning what conservation actually does.' }, 11616 { up:74, icon:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 12l8-8 8 8M6 10v10h12V10"/><path d="M9 20v-6h6v6"/></svg>', 11617 h:'A day of drone surveillance over Sumatra', 11618 s:'Our rainforest partners map illegal logging from the air â this funds one flight.' }, 11619 { up:199, icon:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 21h18M5 21V8l7-5 7 5v13M9 21v-6h6v6"/></svg>', 11620 h:'A week of sanctuary care for one elephant', 11621 s:'Food, vet checks, mahout salary. Save Elephant Foundation runs the largest sanctuary in Thailand.' }, 11622 { up:499, icon:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="9" cy="8" r="3"/><circle cx="17" cy="9" r="2.5"/><path d="M3 21c0-3 2.5-6 6-6s6 3 6 6"/><path d="M14 21c0-2 2-4 4-4s4 2 4 4"/></svg>', 11623 h:'A herder fence in Nepal', 11624 s:'Solar-powered livestock fences stop snow leopards being killed in retaliation by herders.' }, 11625 { up:999, icon:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2c-3 5-3 9 0 12s3 6 0 8"/><path d="M5 11c2 1 3 3 3 5M19 11c-2 1-3 3-3 5"/></svg>', 11626 h:'A month of ranger pay, kit and fuel', 11627 s:'Boots, salary, vehicle, radio. A full ranger paid in the field for 30 days.' }, 11628 { up:Infinity, icon:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2L3 7v6c0 5 4 9 9 9s9-4 9-9V7l-9-5z"/><path d="M9 12l2 2 4-4"/></svg>', 11629 h:'An acre of old-growth forest protected', 11630 s:'Legal challenge, ranger patrol, drone mapping. The full stack to defend a chunk of forest.' }, 11631 ]; 11632 11633 // Active tier set. Defaults to the generic ones above; swapped by 11634 // the ecoâNGO bridge when a specific project is picked. Exposed via 11635 // window.__setImpactTiers so any sibling script can update it. 11636 let activeTiers = tiers; 11637 11638 function pick(v){ 11639 for (const t of activeTiers){ if (v <= t.up) return t; } 11640 return activeTiers[activeTiers.length-1]; 11641 } 11642 // Format an amount in the visitor's local currency if the i18n layer 11643 // has booted, else fall back to plain USD. Returns the full display 11644 // string including symbol â e.g. "$50", "â¬50", "Â¥7,800". 11645 function fmtMoney(n){ 11646 if (window.__ECOFLIX_FORMAT__ && window.__ECOFLIX_LOCALE__ 11647 && window.__ECOFLIX_LOCALE__.currency !== 'USD'){ 11648 return window.__ECOFLIX_FORMAT__(n); 11649 }
11650 return '$' + Number(n).toLocaleString('en-US'); 11651 } 11652 11653 // Cache the STABLE parent (.calc-amount div) â its children get replaced 11654 // on every update, so we can't hold a reference to #calcVal directly 11655 // (after the first update it's orphaned, breaking subsequent slider drags). 11656 const amtWrap = valEl ? valEl.parentElement : document.querySelector('.calc-amount'); 11657 11658 function update(v, fromPreset){ 11659 const n = parseInt(v,10); 11660 const display = fmtMoney(n); 11661 // Big amount in the picker â replace inner HTML of the stable wrapper 11662 // so the leaf-coloured currency prefix flows naturally for any symbol. 11663 if (amtWrap){ 11664 // Split formatted string into "symbol" + "number" so we can keep the 11665 // existing leaf-coloured currency prefix style. 11666 const m = display.match(/^([^\d-]+)?(.+)$/); 11667 const sym = (m && m[1]) || ''; 11668 const num = (m && m[2]) || display; 11669 amtWrap.innerHTML = '<span class="calc-curr">' + sym + '</span><span id="calcVal">' + num + '</span>'; 11670 } 11671 ctaAmtEl.textContent = display; 11672 const t = pick(n); 11673 headlineEl.textContent = t.h; 11674 subEl.textContent = t.s; 11675 iconEl.innerHTML = t.icon; 11676 // slider fill % 11677 const pct = ((n - parseInt(slider.min,10)) / (parseInt(slider.max,10) - parseInt(slider.min,10))) * 100; 11678 slider.style.setProperty('--p', pct.toFixed(1) + '%'); 11679 // bump animation 11680 impactWrap.classList.remove('bump'); void impactWrap.offsetWidth; impactWrap.classList.add('bump'); 11681 // preset active state 11682 presets.forEach(b => b.classList.toggle('active', parseInt(b.dataset.v,10) === n)); 11683 } 11684 slider.addEventListener('input', e => update(e.target.value)); 11685 presets.forEach(b => b.addEventListener('click', () => { slider.value = b.dataset.v; update(b.dataset.v, true); })); 11686 update(slider.value); 11687 11688 // Re-render when the i18n layer publishes the visitor's currency. 11689 window.addEventListener('ecoflix:locale-ready', function(){ update(slider.value); }); 11690 11691 // Public hook for the ecoâNGO bridge to swap the tier set in/out. 11692 // Pass `null` (or no arg) to revert to the generic tiers. 11693 window.__setImpactTiers = function(newTiers, ngoName, ngoHref, ngoPhoto){ 11694 activeTiers = (newTiers && newTiers.length) ? newTiers : tiers; 11695 update(slider.value); 11696 11697 // When an NGO is active, swap the generic icon square for the 11698 // NGO's photo. The SVG inside iconEl is hidden via the 11699 // .has-ngo-photo class so the photo fills the tile. 11700 if (iconEl){ 11701 if (newTiers && ngoPhoto){ 11702 iconEl.classList.add('has-ngo-photo'); 11703 iconEl.style.backgroundImage = "url('" + ngoPhoto + "')"; 11704 } else { 11705 iconEl.classList.remove('has-ngo-photo'); 11706 iconEl.style.backgroundImage = ''; 11707 } 11708 } 11709 11710 const chip = document.getElementById('calcActiveNgo'); 11711 const chipName = document.getElementById('calcActiveNgoName'); 11712 if (chip){ 11713 if (newTiers && ngoName){ 11714 chip.hidden = false; 11715 if (chipName) chipName.textContent = ngoName; 11716 } else { 11717 chip.hidden = true; 11718 } 11719 } 11720 // Make the donate CTA route to the project page when an NGO is 11721 // active â preserves the user's chosen amount as a query param. 11722 if (ctaEl){ 11723 const n = parseInt(slider.value,10); 11724 if (newTiers && ngoHref){ 11725 ctaEl.setAttribute('href', ngoHref + '?amount=' + n); 11726 ctaEl.dataset.ngoMode = '1'; 11727 } else { 11728 ctaEl.setAttribute('href', '/donate/'); 11729 delete ctaEl.dataset.ngoMode; 11730 } 11731 } 11732 }; 11733})(); 11734 11735/* === 2b. Eco â NGO bridge === 11736 Connects the ecosystem pills above the donation card to the 11737 impact-calc tiers. Picking an ecosystem expands a panel of 11738 NGOs in that ecosystem; picking an NGO re-keys the slider 11739 captions via window.__setImpactTiers. */ 11740(function(){ 11741 const bridge = document.getElementById('ecoBridge'); 11742 if (!bridge) return; 11743 const pillsEl = bridge.querySelector('.eco-bridge-pills'); 11744 const panel = document.getElementById('ecoBridgePanel'); 11745 const pills = Array.from(bridge.querySelectorAll('.eco-bridge-pill')); 11746 if (!pillsEl || !panel) return; 11747 11748 // A compact, reusable icon set so every NGO tier has visual variety 11749 // without bloating the per-NGO data.
11750 const ICN = { 11751 meal: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 11h16M5 11a7 7 0 0 0 14 0M9 7V3M12 7V3M15 7V3"/></svg>', 11752 kit: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="7" width="18" height="13" rx="2"/><path d="M8 7V5a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/><path d="M3 13h18"/></svg>', 11753 drone: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="6" height="6" rx="1"/><path d="M4 4l5 5M20 4l-5 5M4 20l5-5M20 20l-5-5"/><circle cx="4" cy="4" r="1.5"/><circle cx="20" cy="4" r="1.5"/><circle cx="4" cy="20" r="1.5"/><circle cx="20" cy="20" r="1.5"/></svg>', 11754 paw: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><ellipse cx="12" cy="16" rx="5" ry="4"/><circle cx="6" cy="9" r="2"/><circle cx="18" cy="9" r="2"/><circle cx="9" cy="5" r="1.8"/><circle cx="15" cy="5" r="1.8"/></svg>', 11755 person: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="8" r="3.5"/><path d="M4 21c0-4 4-7 8-7s8 3 8 7"/></svg>', 11756 house: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 11l9-8 9 8M5 10v10h14V10M10 20v-5h4v5"/></svg>', 11757 shield: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2L3 6v7c0 5 4 9 9 9s9-4 9-9V6l-9-4z"/><path d="M9 12l2 2 4-4"/></svg>', 11758 boat: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 16c2 2 4 2 6 0s4-2 6 0 4 2 6 0"/><path d="M5 14l1-5h12l1 5"/><path d="M12 9V3"/><path d="M12 3l4 3-4 1-4-1 4-3z"/></svg>' 11759 }; 11760 11761 // Generic last-resort tier the slider always falls back to when 11762 // an NGO has nothing custom set for the very-high end of the 11763 // slider's range. 11764 const TOP = { up: Infinity }; 11765 11766 // âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ 11767 // NGO catalogue. Each NGO entry includes a 7-tier impact ladder 11768 // matched to the slider's range (5..1000). All copy is original 11769 // editorial â plain factual sentences about each project's 11770 // operating units (meals, patrol days, rescues, etc.). 11771 // âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ 11772 const ngosByEco = { 11773 oceans: [{ 11774 id: 'building-north-americas-first-whale-sanctuary', name: 'Building North America\'s First Whale Sanctuary', 11775 org: 'Whale Sanctuary Project · Nova Scotia, Canada', 11776 coord: '44.7°N · 63.6°W', 11777 photo: '/assets/projects/frontline-support-for-africas-wildlife-hd.jpg', 11778 href: '/projects/building-north-americas-first-whale-sanctuary/', 11779 tiers: [ 11780 { up: 9, icon:ICN.boat, h:'One hour of acoustic whale monitoring', s:'Hydrophone time on the migration corridor â data goes straight to researchers.' }, 11781 { up: 24, icon:ICN.kit, h:'A day of marine-debris removal', s:'A volunteer crew clears one stretch of feeding bay before the next pod arrives.' }, 11782 { up: 74, icon:ICN.boat, h:'A day of patrol-boat fuel', s:'The sanctuary perimeter, watched. Illegal incursions intercepted.' }, 11783 { up: 199, icon:ICN.shield,h:'A week of sanctuary security', s:'Cameras, fencing checks, water-quality monitoring. The basics, kept basic.' }, 11784 { up: 499, icon:ICN.person,h:'A month of marine-mammal vet support', s:'On-call vets keep recovering cetaceans on track through the difficult weeks.' }, 11785 { up: 999, icon:ICN.paw, h:'A full cetacean rescue intake', s:'From the rescue boat to quarantine to first health screen. The hardest 72 hours.' }, 11786 { up:Infinity,icon:ICN.house,h:'A month of full sanctuary operations', s:'Site, crew, vets, power. The whole operation, kept running for thirty days.' }, 11787 ] 11788 }], 11789 rainforests: [{ 11790 id: 'returning-orphaned-orangutans-to-the-wild', name: 'Returning Orphaned Orangutans to the Wild', 11791 org: 'Orangutan Foundation International · Borneo, Indonesia', 11792 coord: '0.79°S · 113.92°E', 11793 photo: '/assets/projects/frontline-support-for-africas-wildlife-hd.jpg', 11794 href: '/projects/returning-orphaned-orangutans-to-the-wild/', 11795 tiers: [ 11796 { up: 9, icon:ICN.person,h:'Five patrol-hours in a logging hotspot', s:'On-the-ground ranger time. Cheap, but it keeps trees standing.' }, 11797 { up: 24, icon:ICN.drone, h:'Half a day of drone surveillance', s:'Aerial mapping flags concession violations before bulldozers move in.' }, 11798 { up: 74, icon:ICN.drone, h:'A day of drone surveillance over Sumatra',s:'Forest Watch maps illegal logging from the air daily â this funds one flight.' }, 11799 { up: 199, icon:ICN.paw, h:'A week feeding the rescue centre', s:'Rescued orangutans rehabbed before being released back to the canopy.' }, 11800 { up: 499, icon:ICN.kit, h:'A trail camera deployed for a year', s:'Round-the-clock footage of the species the loggers never wanted us to see.' }, 11801 { up: 999, icon:ICN.shield,h:'A month of one ranger in the field', s:'Boots, salary, fuel, radio. One forest defender at full operating tempo.' }, 11802 { up:Infinity,icon:ICN.house,h:'A hectare leased and patrolled for a year',s:'Legal lease + ranger patrol + drone monitoring â for one whole hectare.' }, 11803 ] 11804 }, {
11805 id: 'a-free-life-for-thailands-rescued-elephants', name: 'A Free Life for Thailand\'s Rescued Elephants', 11806 org: 'Save Elephant Foundation · Chiang Mai, Thailand', 11807 coord: '18.93°N · 98.62°E', 11808 photo: '/assets/projects/frontline-support-for-africas-wildlife-hd.jpg', 11809 href: '/projects/a-free-life-for-thailands-rescued-elephants/', 11810 tiers: [ 11811 { up: 9, icon:ICN.meal, h:"A morning's pumpkins for the herd", s:'Each rescued elephant eats around 250 kg a day. This is the first round.' }, 11812 { up: 24, icon:ICN.person,h:'A day of mahout salary', s:'The keepers who walk the elephants out and back, every day.' }, 11813 { up: 74, icon:ICN.kit, h:"A vet's site visit", s:'On-call vets keep working elephants alive long after their owners give up.' }, 11814 { up: 199, icon:ICN.house,h:'A week of sanctuary care for one elephant',s:"Food, vet checks, mahout salary. Lek's sanctuary, end to end." }, 11815 { up: 499, icon:ICN.boat, h:'A rescue convoy from upcountry', s:'Trailer hire, fuel, escort, intake. One elephant out of work and into care.' }, 11816 { up: 999, icon:ICN.shield,h:'A month of full sanctuary operations', s:'Over 100 rescued elephants â all their meals, vets and mahouts, for thirty days.' }, 11817 { up:Infinity,icon:ICN.house,h:'A new sanctuary acre', s:'More land for the rescue, more space for elephants to be elephants again.' }, 11818 ] 11819 }], 11820 savannah: [{ 11821 id: 'frontline-support-for-africas-wildlife', name: 'Frontline Support for Africa\'s Wildlife', 11822 org: 'Over and Above Africa · Africa', 11823 coord: '1.50°S · 35.14°E', 11824 photo: '/assets/projects/frontline-support-for-africas-wildlife-hd.jpg', 11825 href: '/projects/frontline-support-for-africas-wildlife/', 11826 tiers: [ 11827 { up: 9, icon:ICN.meal, h:"A ranger's daily rations", s:'A hot meal at the end of a 12-hour patrol. Small but it keeps people in the field.' }, 11828 { up: 24, icon:ICN.kit, h:"A full day's patrol kit", s:'Boots, water, GPS, snare-clippers â the kit one ranger walks out with.' }, 11829 { up: 74, icon:ICN.shield,h:'100 km of anti-snare sweeps', s:'A patrol drives the conservancy boundary pulling snares before they catch anything.' }, 11830 { up: 199, icon:ICN.person,h:"A week's training for one new ranger", s:'Recruitment, kit, field training. The pipeline that keeps rangers in post.' }, 11831 { up: 499, icon:ICN.person,h:'A month of community-scout salary', s:'Local people, employed locally, patrolling their own communities.' }, 11832 { up: 999, icon:ICN.shield,h:'A week of a full anti-poaching unit', s:'Six rangers, one vehicle, full kit, seven days. The full anti-poaching response.' }, 11833 { up:Infinity,icon:ICN.boat,h:'A conservancy-wide patrol vehicle', s:'4Ã4, radios, full kit. The vehicle that covers ground other rangers canât reach.' }, 11834 ] 11835 }], 11836 mountains: [{ 11837 id: 'freedom-for-indias-bears-and-elephants', name: 'Freedom for India\'s Bears & Elephants', 11838 org: 'Wildlife SOS · Agra, India', 11839 coord: '53.78°N · 122.78°W', 11840 photo: '/assets/projects/frontline-support-for-africas-wildlife-hd.jpg', 11841 href: '/projects/freedom-for-indias-bears-and-elephants/', 11842 tiers: [ 11843 { up: 9, icon:ICN.kit, h:'20 bear-smart pamphlets in a community', s:'Education is the cheapest way to keep bears alive.' }, 11844 { up: 24, icon:ICN.house, h:'A bear-proof food cache for a campsite', s:'One latch keeps one bear from learning that humans equal food.' }, 11845 { up: 74, icon:ICN.person,h:'A community workshop on coexistence', s:'A facilitator, materials, dinner â for the families living closest to the bears.' }, 11846 { up: 199, icon:ICN.boat, h:'Relocating one habituated bear', s:'Trap, transport, telemetry. Out of the suburb, back into wild.' }, 11847 { up: 499, icon:ICN.shield,h:'A bear-aversion deterrent kit', s:'Non-lethal noise, scent and visual deterrents for a community in conflict.' }, 11848 { up: 999, icon:ICN.person,h:'A school year of bear-smart curriculum', s:'Five schools, one full year. The next generation grows up bear-smart.' }, 11849 { up:Infinity,icon:ICN.house,h:'A conflict-bear emergency response fund',s:'When a bear gets into a town, this is what gets it back out alive.' }, 11850 ] 11851 }, {
11852 id: 'a-forest-home-for-rescued-wolves', name: 'A Forest Home for Rescued Wolves', 11853 org: 'Wolf Connection · Acton, California, USA', 11854 coord: '34.47°N · 118.20°W', 11855 photo: '/assets/projects/frontline-support-for-africas-wildlife-hd.jpg', 11856 href: '/projects/a-forest-home-for-rescued-wolves/', 11857 tiers: [ 11858 { up: 9, icon:ICN.meal, h:'A day of food for one sanctuary wolf', s:'Each wolf eats around 4 kg of raw a day. This is one of those days.' }, 11859 { up: 24, icon:ICN.paw, h:"A week's enrichment program", s:'New scents, new toys, new puzzles. Sanctuary life kept interesting.' }, 11860 { up: 74, icon:ICN.person,h:'A youth program session at the sanctuary',s:'At-risk youth spend a day with the pack. The change is documented.' }, 11861 { up: 199, icon:ICN.kit, h:'A vet visit for the pack', s:'Bloodwork, vaccines, dental â one full day of veterinary attention.' }, 11862 { up: 499, icon:ICN.shield,h:'Rescuing one wolf-dog from a kill list', s:'Transport, intake, quarantine, first month of care.' }, 11863 { up: 999, icon:ICN.house, h:'A month of full sanctuary operations', s:'Wolves, staff, vets, programs. The whole site, kept running for thirty days.' }, 11864 { up:Infinity,icon:ICN.house,h:'A new pack enclosure', s:'Land, fencing, shelter, water â a permanent home for a new pack.' }, 11865 ] 11866 }], 11867 wetlands: [], polar: [] 11868 }; 11869 11870 function buildNgoCardHTML(ngo){ 11871 // Photo block uses background-image so failed loads don't show a broken icon. 11872 const photoStyle = ngo.photo ? "background-image:url('" + ngo.photo + "')" : ''; 11873 return ( 11874 '<button class="eco-bridge-ngo" type="button" data-ngo="' + ngo.id + '" aria-pressed="false">' + 11875 '<span class="ebngo-photo" style="' + photoStyle + '" aria-hidden="true"></span>' + 11876 '<span class="ebngo-body">' + 11877 '<span class="ebngo-coord">' + ngo.coord + '</span>' + 11878 '<span class="ebngo-name">' + ngo.name + '</span>' + 11879 '<span class="ebngo-org">' + ngo.org + '</span>' + 11880 '</span>' + 11881 '<span class="ebngo-pick">Pick</span>' + 11882 '</button>' 11883 ); 11884 } 11885 function buildEmptyHTML(ecoSlug){ 11886 return ( 11887 '<div class="eco-bridge-empty">' + 11888 'No featured project here yet â but we partner with NGOs across this ecosystem. ' + 11889 '<a href="/ngo-partners/?ecosystem=' + ecoSlug + '">See every partner in ' + ecoSlug + ' â</a>' + 11890 '</div>' 11891 ); 11892 } 11893 11894 function renderPanel(ecoSlug){ 11895 const list = ngosByEco[ecoSlug] || []; 11896 const headLabel = ecoSlug.charAt(0).toUpperCase() + ecoSlug.slice(1); 11897 11898 let inner = '<div class="eco-bridge-panel-head">' + 11899 '<span class="eco-bridge-panel-h">Projects in <em>' + headLabel + '</em></span>' + 11900 '<a class="eco-bridge-panel-link" href="/ngo-partners/?ecosystem=' + ecoSlug + '">See all â</a>' + 11901 '</div>'; 11902 11903 if (list.length){ 11904 inner += '<div class="eco-bridge-ngos">' + list.map(buildNgoCardHTML).join('') + '</div>'; 11905 } else { 11906 inner += buildEmptyHTML(ecoSlug); 11907 } 11908 11909 panel.innerHTML = inner; 11910 11911 // Wire NGO buttons inside the freshly-rendered panel. 11912 panel.querySelectorAll('.eco-bridge-ngo').forEach(btn => { 11913 btn.addEventListener('click', () => selectNgo(ecoSlug, btn.dataset.ngo, btn)); 11914 }); 11915 } 11916 11917 function selectEco(ecoSlug){ 11918 pills.forEach(p => p.setAttribute('aria-selected', p.dataset.eco === ecoSlug ? 'true' : 'false')); 11919 renderPanel(ecoSlug); 11920 panel.classList.add('is-open'); 11921 } 11922 11923 function selectNgo(ecoSlug, ngoId, btnEl){ 11924 const ngo = (ngosByEco[ecoSlug] || []).find(n => n.id === ngoId); 11925 if (!ngo) return; 11926 11927 // Mark this NGO card pressed; clear siblings. 11928 panel.querySelectorAll('.eco-bridge-ngo').forEach(b => { 11929 b.setAttribute('aria-pressed', b === btnEl ? 'true' : 'false'); 11930 }); 11931 11932 // Re-key the impact-calc tiers + photo to this NGO. 11933 if (typeof window.__setImpactTiers === 'function'){ 11934 window.__setImpactTiers(ngo.tiers, ngo.name, ngo.href, ngo.photo); 11935 } 11936 11937 // Scroll the slider into view so the change is visible. 11938 const impactCalc = document.getElementById('impactCalc'); 11939 if (impactCalc){ 11940 impactCalc.scrollIntoView({ behavior:'smooth', block:'center' }); 11941 } 11942 } 11943 11944 // Wire pill clicks.
11945 pills.forEach(p => { 11946 p.addEventListener('click', () => { 11947 const eco = p.dataset.eco; 11948 // Click again on the active pill = collapse / reset. 11949 if (p.getAttribute('aria-selected') === 'true'){ 11950 p.setAttribute('aria-selected','false'); 11951 panel.classList.remove('is-open'); 11952 panel.innerHTML = ''; 11953 if (typeof window.__setImpactTiers === 'function') window.__setImpactTiers(null); 11954 return; 11955 } 11956 selectEco(eco); 11957 }); 11958 }); 11959 11960 // Clear-button on the active-NGO chip resets the slider tiers. 11961 const clearBtn = document.getElementById('calcActiveNgoClear'); 11962 if (clearBtn){ 11963 clearBtn.addEventListener('click', () => { 11964 panel.querySelectorAll('.eco-bridge-ngo').forEach(b => b.setAttribute('aria-pressed','false')); 11965 if (typeof window.__setImpactTiers === 'function') window.__setImpactTiers(null); 11966 }); 11967 } 11968})(); 11969 11970/* === 3. Species-lost counter === */ 11971(function(){ 11972 const el = document.getElementById('speciesNum'); 11973 if (!el) return; 11974 // IUCN Red List 2025: 48,646 of 172,620 assessed species threatened with 11975 // extinction (~28%). Static, sourced figure â count-up reveal only, no live tick. 11976 const target = 48646; 11977 // Trigger when section becomes visible 11978 const io = new IntersectionObserver(entries => { 11979 entries.forEach(e => { 11980 if (e.isIntersecting){ 11981 // count-up reveal: animate from 0 to the figure over 1.4s 11982 const dur = 1400; const t0 = performance.now(); 11983 function step(now){ 11984 const k = Math.min(1, (now - t0) / dur); 11985 const eased = 1 - Math.pow(1 - k, 3); 11986 el.textContent = Math.round(target * eased).toLocaleString(); 11987 if (k < 1) requestAnimationFrame(step); 11988 else el.textContent = target.toLocaleString(); 11989 } 11990 requestAnimationFrame(step); 11991 io.unobserve(e.target); 11992 } 11993 }); 11994 }, { threshold: .3 }); 11995 io.observe(el); 11996})(); 11997 11998/* === 5. Press strip reveal (no extra JS needed; reveal handled by IO) === */ 11999
12000/* === 6. Hero sound toggle === */ 12001(function(){ 12002 const btn = document.getElementById('heroSoundBtn'); 12003 if (!btn) return; 12004 const vid = document.querySelector('.hero-carousel .hcv'); 12005 if (!vid) return; 12006 btn.addEventListener('click', () => { 12007 const on = btn.getAttribute('data-on') === 'true'; 12008 if (on){ 12009 vid.muted = true; 12010 btn.setAttribute('data-on','false'); 12011 btn.setAttribute('aria-label','Turn sound on'); 12012 } else { 12013 vid.muted = false; 12014 try { vid.volume = 0.6; vid.play(); } catch(e){} 12015 btn.setAttribute('data-on','true'); 12016 btn.setAttribute('aria-label','Turn sound off'); 12017 } 12018 }); 12019})(); 12020 12021/* === 7. Donate-button leaf burst === */ 12022(function(){ 12023 document.querySelectorAll('.btn-primary').forEach(btn => { 12024 if (btn.querySelector('.leafburst')) return; 12025 const wrap = document.createElement('span'); 12026 wrap.className = 'leafburst'; 12027 wrap.setAttribute('aria-hidden','true'); 12028 const N = 8; 12029 for (let k = 0; k < N; k++){ 12030 const leaf = document.createElement('span'); 12031 leaf.className = 'leaf-p'; 12032 const angle = (Math.PI * 2 * k) / N + (Math.random() * 0.6); 12033 const dist = 50 + Math.random() * 38; 12034 const dx = Math.cos(angle) * dist; 12035 const dy = Math.sin(angle) * dist - 30; 12036 leaf.style.setProperty('--ldx', dx.toFixed(1) + 'px'); 12037 leaf.style.setProperty('--ldy', dy.toFixed(1) + 'px'); 12038 leaf.style.setProperty('--lr', (Math.random()*120 - 60).toFixed(0) + 'deg'); 12039 leaf.style.animationDelay = (k * 0.04).toFixed(2) + 's'; 12040 wrap.appendChild(leaf); 12041 } 12042 btn.appendChild(wrap); 12043 }); 12044})(); 12045 12046/* === 8. Picks for tonight â purely declarative, no JS needed === */ 12047 12048/* === 9. Cursor compass on dark sections === */ 12049(function(){ 12050 if (matchMedia('(pointer:coarse)').matches) return; // skip touch devices 12051 const cc = document.createElement('div'); 12052 cc.className = 'cursor-compass'; 12053 cc.innerHTML = '<span class="cc-n">N</span><span class="cc-needle"></span>'; 12054 document.body.appendChild(cc); 12055 const needle = cc.querySelector('.cc-needle'); 12056 12057 let mx = 0, my = 0, rx = 0, ry = 0; 12058 let active = false; 12059 let lastMove = 0; 12060 document.addEventListener('mousemove', e => { 12061 mx = e.clientX; my = e.clientY; 12062 lastMove = Date.now(); 12063 // Determine if we're over a dark section. Use elementFromPoint and walk up 12064 const node = document.elementFromPoint(mx, my); 12065 if (!node) return; 12066 const dark = node.closest('.broll-section, .proof, .convert, .hp-promise, .anchor, .watch-change, .founder-quote, .hscroll-stage, footer'); 12067 const hover = node.closest('a, button, [role="button"], input, textarea, select'); 12068 active = !!dark && !hover; 12069 cc.classList.toggle('show', active); 12070 }); 12071 function raf(){ 12072 rx += (mx - rx) * 0.22; 12073 ry += (my - ry) * 0.22; 12074 cc.style.transform = `translate(${rx}px, ${ry}px) translate(-50%,-50%)`; 12075 // rotate needle based on cursor velocity direction (subtle) 12076 const angle = (Math.sin(Date.now() / 1800) * 18); // slow drift like real compass 12077 needle.style.transform = `rotate(${angle.toFixed(2)}deg)`; 12078 requestAnimationFrame(raf); 12079 } 12080 requestAnimationFrame(raf); 12081})(); 12082 12083/* === 10. Live viewers + donation momentum === */ 12084/* Driven sitewide by /assets/social-proof.js ([data-lv] + [data-donations]). */ 12085 12086/* ================= UX ENHANCEMENT MODULES ================= */ 12087 12088/* === Back-to-top + sticky donate bar + chapter nav (scroll-driven) === */ 12089(function(){ 12090 const bttop = document.getElementById('backToTop'); 12091 const sdb = document.getElementById('stickyDonate'); 12092 const chapNav = document.getElementById('chapNav'); 12093 const chapDots = chapNav ? Array.from(chapNav.querySelectorAll('.chap-dot')) : []; 12094 12095 function onScroll(){ 12096 const y = window.scrollY; 12097 const vh = window.innerHeight; 12098 const docH = document.documentElement.scrollHeight; 12099 12100 // Back-to-top 12101 if (bttop) bttop.classList.toggle('show', y > vh * 0.8); 12102 12103 // Sticky donate bar â show after hero 12104 if (sdb){ 12105 const past = y > vh * 0.65; 12106 const nearFoot = (y + vh) > (docH - 200); 12107 sdb.classList.toggle('show', past && !nearFoot); 12108 sdb.classList.toggle('atfoot', nearFoot); 12109 } 12110 12111 // Chapter nav â show after intro 12112 if (chapNav) chapNav.classList.toggle('show', y > vh * 0.4); 12113 12114 // Highlight current chapter
12115 chapDots.forEach(dot => { 12116 const target = document.querySelector(dot.dataset.target); 12117 if (!target) return; 12118 const r = target.getBoundingClientRect(); 12119 const isInView = r.top < vh * 0.4 && r.bottom > vh * 0.2; 12120 dot.classList.toggle('is-active', isInView); 12121 }); 12122 } 12123 12124 // Smooth only for short hops: Chrome cancels long smooth animations on this 12125 // scroll-driven page, leaving the user stranded mid-runway. Long jumps go 12126 // instant; the force-reveal net below makes the destination render. 12127 function goTo(top){ 12128 const dist = Math.abs(top - window.scrollY); 12129 window.scrollTo({ top, behavior: dist > window.innerHeight * 2.5 ? 'auto' : 'smooth' }); 12130 setTimeout(forceRevealInView, 60); 12131 } 12132 12133 if (bttop) bttop.addEventListener('click', () => goTo(0)); 12134 12135 // Layout (not visual) document position. Sections inside pin-stacks are 12136 // position:sticky and transform-translated, so getBoundingClientRect() 12137 // reports where they're PINNED (usually right where you already are) and 12138 // scrolling to it goes nowhere. offsetTop up the offsetParent chain gives 12139 // the true scroll destination instead. 12140 function docTop(el){ 12141 let t = 0; 12142 for (let n = el; n; n = n.offsetParent) t += n.offsetTop; 12143 return t; 12144 } 12145 12146 // Safety net for jump navigation (dots, End/Home/PageDown, anchors): 12147 // the IntersectionObserver reveals unobserve after first fire, so any 12148 // section jumped PAST stays at opacity 0 â a black screen. Force
12148-reveal 12149 // whatever is actually in the viewport after any scroll settles. 12150 function forceRevealInView(){ 12151 const vh = window.innerHeight; 12152 document.querySelectorAll('.reveal:not(.in), .reveal-stagger:not(.in)').forEach(el => { 12153 const r = el.getBoundingClientRect(); 12154 if (r.top < vh && r.bottom > 0) el.classList.add('in'); 12155 }); 12156 document.querySelectorAll('.section-lift:not(.is-revealed)').forEach(el => { 12157 const r = el.getBoundingClientRect(); 12158 if (r.top < vh && r.bottom > 0) el.classList.add('is-revealed'); 12159 }); 12160 } 12161 let revealIdle = null; 12162 window.addEventListener('scroll', () => { 12163 clearTimeout(revealIdle); 12164 revealIdle = setTimeout(forceRevealInView, 150); 12165 }, { passive:true }); 12166 window.addEventListener('scrollend', forceRevealInView); 12167 12168 if (chapNav){ 12169 chapDots.forEach(dot => { 12170 dot.addEventListener('click', () => { 12171 const target = document.querySelector(dot.dataset.target); 12172 if (!target) return; 12173 goTo(Math.max(0, docTop(target) - 60)); 12174 }); 12175 }); 12176 } 12177 12178 window.addEventListener('scroll', onScroll, { passive:true }); 12179 onScroll(); 12180 forceRevealInView(); 12181})(); 12182 12183/* === Sticky donate-bar buttons === */ 12184(function(){ 12185 const calcBtn = document.getElementById('sdbCalcBtn'); 12186 const donateBtn = document.getElementById('sdbDonateBtn'); 12187 if (calcBtn){ 12188 calcBtn.addEventListener('click', () => { 12189 const calc = document.getElementById('impactCalc'); 12190 if (!calc) return; 12191 const top = calc.getBoundingClientRect().top + window.scrollY - 80; 12192 window.scrollTo({ top, behavior:'smooth' }); 12193 }); 12194 } 12195 if (donateBtn){ 12196 donateBtn.addEventListener('click', () => { 12197 // Open donation preview modal pre-filled to $50 12198 window.dispatchEvent(new CustomEvent('open-donate-modal', { detail:{ amount:50 } })); 12199 }); 12200 } 12201})(); 12202 12203/* === Cookie / privacy bar === */ 12204(function(){ 12205 const bar = document.getElementById('cookBar'); 12206 if (!bar) return; 12207 const KEY = 'ecoflix.cookies'; 12208 if (localStorage.getItem(KEY)) return; // already chosen 12209 setTimeout(() => bar.classList.add('show'), 1800); 12210 function close(choice){ 12211 bar.classList.remove('show'); 12212 localStorage.setItem(KEY, choice); 12213 setTimeout(() => bar.remove(), 500); 12214 } 12215 document.getElementById('cbAccept').addEventListener('click', () => close('accepted')); 12216 document.getElementById('cbDecline').addEventListener('click', () => close('declined')); 12217})(); 12218 12219/* === Image shimmer === */ 12220(function(){ 12221 document.querySelectorAll('.proj-card .img').forEach(img => { 12222 // Try to detect when bg image is loaded 12223 const url = img.style.backgroundImage.match(/url\(['"]?([^'"]+)['"]?\)/); 12224 if (!url) { img.classList.add('img-loaded'); return; } 12225 const tmp = new Image(); 12226 tmp.onload = () => img.classList.add('img-loaded'); 12227 tmp.onerror = () => img.classList.add('img-loaded'); 12228 tmp.src = url[1]; 12229 }); 12230})(); 12231 12232/* === Save projects (heart) + filter + view toggle + recall ribbon === */ 12233(function(){ 12234 const KEY = 'ecoflix.savedProjects'; 12235 function load(){ 12236 try { return JSON.parse(localStorage.getItem(KEY) || '[]'); } 12237 catch(e){ return []; } 12238 } 12239 function save(list){ localStorage.setItem(KEY, JSON.stringify(list)); } 12240 12241 let saved = load(); 12242 const cards = Array.from(document.querySelectorAll('.proj-card[data-id]')); 12243 if (!cards.length) return; 12244 12245 // Inject heart button into each card (top-right; respects existing coord-stamp) 12246 cards.forEach(card => { 12247 const id = card.dataset.id; 12248 const btn = document.createElement('button'); 12249 btn.className = 'save-btn'; 12250 btn.type = 'button'; 12251 btn.setAttribute('aria-label', 'Save project'); 12252 btn.innerHTML = '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 21s-7-4.5-9.5-9C1 9 3 5 7 5c2 0 4 1 5 3 1-2 3-3 5-3 4 0 6 4 4.5 7-2.5 4.5-9.5 9-9.5 9z"/></svg>'; 12253 if (saved.includes(id)) btn.classList.add('is-saved'); 12254 btn.addEventListener('click', (e) => { 12255 e.preventDefault(); e.stopPropagation(); 12256 saved = load(); 12257 if (saved.includes(id)){ 12258 saved = saved.filter(s => s !== id); 12259 btn.classList.remove('is-saved'); 12260 btn.setAttribute('aria-label', 'Save project'); 12261 } else { 12262 saved.push(id); 12263 btn.classList.add('is-saved'); 12264 btn.setAttribute('aria-label', 'Unsave project'); 12265 } 12266 save(saved); 12267 updateSavedCount(); 12268 refilter(); 12269 }); 12270 // Coord-stamp lives at bottom-right; heart at top-right. No collision. 12271 card.appendChild(btn); 12272 }); 12273 12274 // Saved count chip + recall ribbon 12275 const savedCountEl = document.getElementById('savedCount'); 12276 const ribbon = document.getElementById('savedRibbon'); 12277 function updateSavedCount(){ 12278 if (savedCountEl) savedCountEl.textContent = '(' + saved.length + ')'; 12279 if (ribbon){ 12280 if (saved.length > 0){ 12281 ribbon.hidden = false;
12282 ribbon.querySelector('.sr-count').textContent = saved.length; 12283 requestAnimationFrame(() => ribbon.classList.add('show')); 12284 } else { 12285 ribbon.classList.remove('show'); 12286 setTimeout(() => { ribbon.hidden = true; }, 400); 12287 } 12288 } 12289 } 12290 updateSavedCount(); 12291 12292 document.getElementById('srClear')?.addEventListener('click', () => { 12293 saved = []; 12294 save(saved); 12295 document.querySelectorAll('.save-btn.is-saved').forEach(b => b.classList.remove('is-saved')); 12296 updateSavedCount(); 12297 refilter(); 12298 }); 12299 12300 // Filter chips 12301 const chips = document.querySelectorAll('.proj-chip'); 12302 let activeFilter = 'all'; 12303 function refilter(){ 12304 cards.forEach(card => { 12305 let show = true; 12306 if (activeFilter === 'urgent'){ 12307 show = card.classList.contains('is-urgent'); 12308 } else if (activeFilter === 'saved'){ 12309 show = saved.includes(card.dataset.id); 12310 } else if (activeFilter !== 'all'){ 12311 show = card.dataset.region === activeFilter; 12312 } 12313 card.classList.toggle('is-filtered-out', !show); 12314 }); 12315 } 12316 chips.forEach(chip => { 12317 chip.addEventListener('click', () => { 12318 chips.forEach(c => c.classList.remove('active')); 12319 chip.classList.add('active');
12320 activeFilter = chip.dataset.filter; 12321 refilter(); 12322 }); 12323 }); 12324 12325 // View toggle 12326 const track = document.getElementById('hscrollTrack'); 12327 document.querySelectorAll('.view-toggle button').forEach(b => { 12328 b.addEventListener('click', () => { 12329 document.querySelectorAll('.view-toggle button').forEach(x => x.classList.remove('active')); 12330 b.classList.add('active'); 12331 if (track){ 12332 track.classList.toggle('view-list', b.dataset.view === 'list'); 12333 } 12334 }); 12335 }); 12336})(); 12337 12338/* === Compare bars â animate on reveal === */ 12339(function(){ 12340 const compare = document.querySelector('.compare'); 12341 if (!compare) return; 12342 const io = new IntersectionObserver(entries => { 12343 entries.forEach(e => { 12344 if (e.isIntersecting){ 12345 compare.querySelectorAll('.cc-fill').forEach(f => { 12346 const target = f.parentElement.parentElement.classList.contains('is-us') ? '100%' : '61%'; 12347 // force the transition to play by going from 0 to target 12348 f.style.width = '0'; 12349 requestAnimationFrame(() => { setTimeout(() => f.style.width = target, 120); }); 12350 }); 12351 io.unobserve(compare); 12352 } 12353 }); 12354 }, { threshold: .3 }); 12355 io.observe(compare); 12356})(); 12357 12358/* === Newsletter signup === */ 12359(function(){ 12360 const form = document.getElementById('nlForm'); 12361 if (!form) return; 12362 const wrap = document.getElementById('newsletter'); 12363 const input = document.getElementById('nlEmail'); 12364 form.addEventListener('submit', (e) => { 12365 e.preventDefault(); 12366 wrap.classList.remove('is-error'); 12367 const v = (input.value || '').trim(); 12368 const ok = /^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(v); 12369 if (!ok){ wrap.classList.add('is-error'); input.focus(); return; } 12370 wrap.classList.add('is-success'); 12371 try { localStorage.setItem('ecoflix.newsletter', v); } catch(e){} 12372 // Send to the CMS subscriber list (+ welcome sequence). Fire-and-forget: 12373 // the success state above is shown regardless of network result. 12374 fetch('/api/email/subscribe', { 12375 method:'POST', headers:{'Content-Type':'application/json'}, 12376 body: JSON.stringify({ email: v, source: 'newsletter-home' }) 12377 }).catch(function(){}); 12378 }); 12379})(); 12380 12381/* === Donation preview modal === */ 12382(function(){ 12383 const modal = document.getElementById('donateModal'); 12384 if (!modal) return; 12385 const close = document.getElementById('dpmClose'); 12386 const amtEl = document.getElementById('dpmAmt'); 12387 const headlineEl = document.getElementById('dpmHeadline'); 12388 const subEl = document.getElementById('dpmSub'); 12389 const iconEl = document.getElementById('dpmIcon'); 12390 const cta = document.getElementById('dpmCta'); 12391 const giftCk = document.getElementById('dpmGiftCk'); 12392 const giftFields = document.getElementById('dpmGiftFields'); 12393 12394 const tiers = [ 12395 { up:9, icon:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2v20M4 8c4 0 4 6 8 6s4-6 8-6"/></svg>', h:'A ranger meal in Kenya', s:'A hot meal at the end of a 12-hour patrol.' }, 12396 { up:24, icon:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="9" r="4"/><path d="M3 21c0-5 4-9 9-9s9 4 9 9"/></svg>', h:'Two days of school workshops', s:'Curriculum and teacher packs for a class.' }, 12397 { up:74, icon:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 12l8-8 8 8M6 10v10h12V10"/><path d="M9 21v-6h6v6"/></svg>', h:'A day of drone surveillance over Sumatra', s:'Our rainforest partners map illegal logging from the air â this funds one flight.' }, 12398 { up:199, icon:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 21h18M5 21V8l7-5 7 5v13"/></svg>', h:'A week of sanctuary care for one elephant', s:'Food, vet checks, mahout salary. Save Elephant Foundation in Thailand.' }, 12399 { up:499, icon:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="9" cy="8" r="3"/><circle cx="17" cy="9" r="2.5"/><path d="M3 21c0-3 2.5-6 6-6s6 3 6 6"/></svg>', h:'A herder fence in Nepal', s:'Stops snow leopards being killed in retaliation by herders.' }, 12400 { up:999, icon:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2c-3 5-3 9 0 12s3 6 0 8"/></svg>', h:'A month of ranger pay, kit and fuel', s:'A full ranger paid in the field for 30 days.' }, 12401 { up:Infinity, icon:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2L3 7v6c0 5 4 9 9 9s9-4 9-9V7l-9-5z"/><path d="M9 12l2 2 4-4"/></svg>', h:'An acre of old-growth forest protected', s:'Legal challenge, ranger patrol, drone mapping.' }, 12402 ]; 12403 12404 function setAmount(n){
12405 amtEl.textContent = n.toLocaleString(); 12406 const t = tiers.find(x => n <= x.up) || tiers[tiers.length-1]; 12407 headlineEl.textContent = t.h; 12408 subEl.textContent = t.s; 12409 iconEl.innerHTML = t.icon; 12410 } 12411 12412 function open(amount){ 12413 setAmount(amount || 50); 12414 modal.classList.add('show'); 12415 modal.setAttribute('aria-hidden','false'); 12416 document.body.style.overflow = 'hidden'; 12417 } 12418 function closeModal(){ 12419 modal.classList.remove('show'); 12420 modal.setAttribute('aria-hidden','true'); 12421 document.body.style.overflow = ''; 12422 } 12423 12424 close.addEventListener('click', closeModal); 12425 modal.addEventListener('click', e => { if (e.target === modal) closeModal(); }); 12426 document.addEventListener('keydown', e => { if (e.key === 'Escape' && modal.classList.contains('show')) closeModal(); }); 12427 giftCk.addEventListener('change', () => giftFields.classList.toggle('show', giftCk.checked)); 12428 12429 // Legacy: the open-donate-modal event used to pre-flight donors in a 12430 // preview modal before sending them to Givebutter. We now have a full 12431 // Stripe checkout at /donate/, so this event handler instead navigates 12432 // straight there, passing the chosen amount through as ?amount=. The 12433 // preview modal is left in the DOM (unmounted) in case any deep-link 12434 // ever wants to re-enable it, but it is no longer triggered by buttons. 12435 window.addEventListener('open-donate-modal', e => { 12436 const amount = (e.detail && e.detail.amount) || 50; 12437 window.location.href = '/donate/?amount=' + encodeURIComponent(amount) + '#pick'; 12438 }); 12439 12440 // NOTE: the "intercept .btn-primary â open modal" pattern has been 12441 // removed. Every Donate button on the page now points directly at 12442 // /donate/, where the real Stripe Payment Element / Express Checkout 12443 // (Apple Pay, Google Pay, Link) lives. There is no modal pre-flight 12444 // anymore â donors land on the checkout in one click. 12445})(); 12446</script>
12446 12447 12448<!-- ===== 3D Globe (Three.js) ===== -->
12449<script type="importmap"> 12450{ 12451 "imports": { 12452 "three": "/assets/three.module.js" 12453 } 12454} 12455</script>
vendor: 1 bytes, line 12455
12455
12456<script type="module" src="/assets/globe.js"></script>
vendor: 1 bytes, line 12456
12456
12457<script src="/assets/i18n.js" defer></script>
12457 12458 12459<!-- Hero video â scroll-scrubbed playback. 12460 Scroll position through the .hero-stage runway drives video.currentTime. 12461 The video itself doesn't play; the browser seeks to the matching frame. 12462 NO eager fallback â always wire the scrub; if seek silently fails the 12463 hero just stays on the first frame, which is fine (better than killing 12464 the runway and getting an unsynced loop). -->
12465<script> 12466(function(){ 12467 const stage = document.getElementById('hero'); 12468 const video = document.getElementById('heroVideo'); 12469 if (!stage || !video) return; 12470 12471 // Honour the reduced-motion preference: just play the video as a loop and 12472 // collapse the runway. This is the ONLY scenario where we kill the scrub. 12473 if (matchMedia('(prefers-reduced-motion: reduce)').matches){ 12474 video.loop = true; 12475 video.autoplay = true; 12476 video.play?.().catch(() => {}); 12477 return; 12478 } 12479 12480 // Prime the video so iOS will render frames from currentTime jumps. 12481 // Some mobile browsers won't paint a frame from a seek until play() 12482 // has been called at least once. We play() then immediately pause(). 12483 // If autoplay is blocked, that's fine â desktop seeks still work. 12484 let primed = false; 12485 function prime(){ 12486 if (primed) return; 12487 primed = true; 12488 video.loop = true; // autoscroll removed: hero video auto-plays on a loop 12489 video.play?.().catch(() => {}); 12490 } 12491 // Prime on first user interaction (covers iOS autoplay restrictions) 12492 ['scroll','touchstart','pointerdown','keydown'].forEach(ev => { 12493 window.addEventListener(ev, prime, { passive:true, once:true }); 12494 }); 12495 // Also try at metadata-ready 12496 if (video.readyState >= 1) prime(); 12497 else video.addEventListener('loadedmetadata', prime, { once:true }); 12498 12499 // Eager-fetch the file so seekable populates quickly. Vercel + most 12500 // CDNs serve byte-range requests, populating seekable as data arrives. 12501 function warmFetch(){ 12502 fetch(video.currentSrc || video.src, { method:'GET', cache:'force-cache' }) 12503 .catch(() => {}); 12504 } 12505 warmFetch(); 12506 12507 // Hero choreography: 12508 // - Video scrub: 0..SCRUB_END of total runway 12509 // - Cover phase: SCRUB_END..1.0 of total runway â mission card 12510 // slides up from below to fully cover the hero. 12511 // - Title + CTAs: visible throughout 12512 // - Stats box: slides in mid-scrub (25%..55% of scrub progress) 12513 // 12514 // The total runway is 300vh (hero-stage 400vh â 100vh viewport). 12515 // SCRUB_END = 2/3 means scrub occupies 200vh and cover occupies 100vh. 12516 const SCRUB_END = 2/3; 12517 12518 const pin = stage.querySelector('.hero-pin'); 12519 const pinStack = stage.parentElement; // .pin-stack â holds --mission-cover-y 12520 12521 function clamp01(x){ return x < 0 ? 0 : x > 1 ? 1 : x; } 12522 function easeOutCubic(t){ return 1 - Math.pow(1 - t, 3); } 12523 function easeInOutCubic(t){ 12524 return t < 0.5 ? 4*t*t*t : 1 - Math.pow(-2*t + 2, 3)/2; 12525 } 12526 12527 function choreograph(scrubP){ 12528 // Reveal sequence â in the order the user annotated: 12529 // 1. Title (h1) visible from page load 12530 // 2. Eyebrow reveals at scrubP 0.05 â 0.15 12531 // 3. Subtitle + buttons reveal at scrubP 0.15 â 0.30 12532 // 4. Stats eyebrow reveals at scrubP 0.32 â 0.45 12533 // 5. Stats panel slides in + fades at scrubP 0.45 â 0.65 12534 const reveal = (start, len) => clamp01((scrubP - start) / len); 12535 const titleReveal = 1; // visible from start 12536 const eyebrowReveal = reveal(0.05, 0.10); 12537 const subtitleReveal = reveal(0.15, 0.10); 12538 const buttonsReveal = reveal(0.22, 0.10); 12539 const statsEyebrowReveal= reveal(0.32, 0.10); 12540 const statsReveal = reveal(0.45, 0.18); 12541 12542 // Stats slide: starts +30vh below natural position when statsReveal=0, 12543 // settles to 0vh as statsReveal completes. 12544 const slideT = clamp01((scrubP - 0.45) / 0.18); 12545 const statsY = (30 * (1 - easeOutCubic(slideT))).toFixed(2) + 'vh'; 12546 12547 pin.style.setProperty('--title-reveal', titleReveal); 12548 pin.style.setProperty('--eyebrow-reveal', eyebrowReveal.toFixed(3)); 12549 pin.style.setProperty('--subtitle-reveal', subtitleReveal.toFixed(3)); 12550 pin.style.setProperty('--buttons-reveal', buttonsReveal.toFixed(3)); 12551 pin.style.setProperty('--stats-eyebrow-reveal', statsEyebrowReveal.toFixed(3)); 12552 pin.style.setProperty('--stats-reveal', statsReveal.toFixed(3)); 12553 pin.style.setProperty('--stats-y', statsY); 12554 } 12555 12556 let queued = false; 12557 function scrub(){ 12558 if (queued) return; 12559 queued = true; 12560 requestAnimationFrame(() => { 12561 queued = false;
12562 const rect = stage.getBoundingClientRect(); 12563 const stageTop = rect.top + window.scrollY; 12564 const runway = stage.offsetHeight - window.innerHeight; 12565 if (runway <= 0) return; 12566 const totalP = clamp01((window.scrollY - stageTop) / runway); 12567 12568 // Split into scrub + cover progress 12569 const scrubP = clamp01(totalP / SCRUB_END); 12570 const coverP = clamp01((totalP - SCRUB_END) / (1 - SCRUB_END)); 12571 12572 // Title / stats choreography uses scrub progress only 12573 choreograph(scrubP); 12574 12575 // Mission cover: slides up from 100vh (below viewport) to 0 12576 // (settled over the hero) during the cover phase. EaseInOutCubic 12577 // gives a soft start and soft landing. 12578 const eased = easeInOutCubic(coverP); 12579 const coverY = (100 * (1 - eased)).toFixed(2) + 'vh'; 12580 pinStack?.style.setProperty('--mission-cover-y', coverY); 12581 12582 // COMPARE CARD-LIFT â second lift inside the same pin-stack. 12583 // Triggers AFTER the hero-stage runway (i.e., once mission cover 12584 // is complete and mission is sticky at top:0). The compare-section 12585 // slides up from 100vh (below viewport) to 0 (covering mission) 12586 // over the next 100vh of scroll past stageBottom. 12587 // 12588 // stageBottom = stageTop + runway = where totalP saturates at 1. 12589 const compareLiftStart = stageTop + runway; 12590 const compareLiftLen = window.innerHeight; // 100vh of scroll 12591 const compareP = clamp01( 12592 (window.scrollY - compareLiftStart) / compareLiftLen 12593 ); 12594 const easedC = easeInOutCubic(compareP); 12595 const compareY = (100 * (1 - easedC)).toFixed(2) + 'vh'; 12596 pinStack?.style.setProperty('--compare-cover-y', compareY); 12597 12598 // Autoscroll removed: the hero video auto-plays on a loop and is no 12599 // longer scrubbed by scroll position. (Seeking intentionally disabled.) 12600 }); 12601 } 12602 window.addEventListener('scroll', scrub, { passive: true }); 12603 window.addEventListener('resize', scrub); 12604 // First paint 12605 if (video.readyState >= 1) scrub(); 12606 else video.addEventListener('loadedmetadata', scrub, { once:true }); 12607 video.addEventListener('progress', scrub); // re-seek as more data buffers 12608 video.addEventListener('canplay', scrub); 12609})(); 12610</script>
12610 12611 12612<!-- ============================================================ 12613 Card-wide click â project detail page. 12614 The cards already have a CTA link inside, but the rest of the 12615 card surface was dead. This makes the whole card navigable 12616 without breaking the carousel drag interaction: 12617 - On pointerdown: record start position. 12618 - On pointermove: if moved > 8px, mark as drag (suppress click). 12619 - On click: if no drag, navigate to /projects/{slug}/. 12620 Some data-ids on the cards don't exactly match the project 12621 folder slug (e.g. "wolf-connection" lives at 12622 /projects/wolf-connection-sanctuary/) â handled by the map below. 12623 ============================================================ -->
12624<script> 12625(function(){ 12626 const track = document.getElementById('hscrollTrack'); 12627 if (!track) return; 12628 const slugMap = {}; 12629 function resolveHref(card){ 12630 const id = card.dataset.id; 12631 if (!id) return null; 12632 return '/projects/' + (slugMap[id] || id) + '/'; 12633 } 12634 12635 // Click-to-navigate â radically simplified after the fan-stack 12636 // carousel + per-card drag tracking + re-centre handler were all 12637 // fighting each other and producing "clicks that sometimes work". 12638 // 12639 // New rule: ANY click on a card body navigates to that card's 12640 // project page, full stop. The carousel's stage-level 12641 // pointerdown/move handler still tracks drag distance in 12642 // window.__pcsDragMoved â we just consult it here to suppress 12643 // clicks that finished a swipe. 12644 track.querySelectorAll('.proj-card').forEach(card => { 12645 card.setAttribute('role', 'link'); 12646 card.setAttribute('tabindex', '0'); 12647 const href = resolveHref(card); 12648 if (href) card.setAttribute('data-href', href); 12649 card.style.cursor = 'pointer'; 12650 12651 card.addEventListener('click', e => { 12652 // Native links/buttons inside the card (the leaf CTA pill, 12653 // the save heart) keep their own behaviour. Just stop the 12654 // event from bubbling into the carousel handler that would 12655 // otherwise re-centre. 12656 if (e.target.closest('a, button')) { 12657 e.stopPropagation(); 12658 return; 12659 } 12660 // Cancel if the user just finished a swipe gesture 12661 if ((window.__pcsDragMoved || 0) > 8) { 12662 window.__pcsDragMoved = 0; 12663 return; 12664 } 12665 const dest = card.getAttribute('data-href'); 12666 if (!dest) return; 12667 e.stopImmediatePropagation(); 12668 e.preventDefault(); 12669 window.location.href = dest; 12670 }, true); // CAPTURE phase so we beat the carousel's re-centre handler 12671 12672 // Keyboard activation 12673 card.addEventListener('keydown', e => { 12674 if (e.key === 'Enter' || e.key === ' ') { 12675 e.preventDefault(); 12676 const dest = card.getAttribute('data-href'); 12677 if (dest) window.location.href = dest; 12678 } 12679 }); 12680 }); 12681})(); 12682</script>
12682 12683 12684<!-- Homepage projects fan-stack carousel (mirrors /projects/) --> 12685<!-- Fan-stack engine disabled â replaced by the expanding-panels engine in 12686 /assets/panels.js (loaded below). -->
12687<script> 12688(function(){ 12689 return; /* DISABLED: superseded by /assets/panels.js expanding-panels mode */ 12690 const stage = document.getElementById('hscrollTrack'); 12691 if (!stage) return; 12692 const wrap = document.getElementById('hpProjectsCarousel'); 12693 if (!wrap) return; 12694 const allCards = Array.from(stage.querySelectorAll('.proj-card')); 12695 if (!allCards.length) return; 12696 12697 const prevBtn = wrap.querySelector('.pcs-btn-prev'); 12698 const nextBtn = wrap.querySelector('.pcs-btn-next'); 12699 const dotsEl = document.getElementById('hpPcsDots'); 12700 const counter = document.getElementById('hpPcsCounter'); 12701 12702 const MAX_VISIBLE_PAIR = 3; 12703 const SPREAD_DEG = 32; 12704 const OVERLAP = 0.55; 12705 const DEPTH_PX = 110; 12706 const TILT_X = 9; 12707 const ACTIVE_LIFT = 20; 12708 const ACTIVE_SCALE = 1.03; 12709 const INACTIVE_SCALE = 0.93; 12710 12711 let visible = allCards.filter(c => !c.classList.contains('is-filtered-out')); 12712 let active = 0; 12713 let dragging = null; 12714 let lastDragMoved = 0; 12715 12716 function getCardWidth(){ return stage.querySelector('.proj-card')?.offsetWidth || 400; } 12717 function pad2(n){ return String(n).padStart(2, '0'); } 12718 12719 function signedOffset(i, len){ 12720 const raw = i - active; 12721 if (len <= 1) return raw; 12722 const alt = raw > 0 ? raw - len : raw + len; 12723 return Math.abs(alt) < Math.abs(raw) ? alt : raw; 12724 } 12725 12726 function layout(){ 12727 const len = visible.length; 12728 const maxOff = MAX_VISIBLE_PAIR; 12729 const step = maxOff > 0 ? SPREAD_DEG / maxOff : 0; 12730 const space = getCardWidth() * (1 - OVERLAP); 12731 if (!len){ 12732 allCards.forEach(c => { c.style.opacity='0'; c.style.pointerEvents='none'; }); 12733 if (counter) counter.innerHTML = '<b>0</b> / 0'; 12734 if (dotsEl) dotsEl.innerHTML = ''; 12735 return; 12736 } 12737 allCards.forEach(c => { c.style.display = ''; }); 12738 visible.forEach((card, i) => { 12739 const off = signedOffset(i, len); 12740 const abs = Math.abs(off); 12741 if (abs > maxOff){ 12742 card.style.opacity = '0'; 12743 card.style.pointerEvents = 'none'; 12744 card.style.zIndex = '0'; 12745 card.style.transform = `translate(-50%, 0) translate3d(0, 0, -600px) scale(0.7)`; 12746 card.classList.remove('is-active'); 12747 return; 12748 } 12749 const x = off * space; 12750 const rotateZ = off * step; 12751 const z = -abs * DEPTH_PX; 12752 const y = abs * 6; 12753 const rotateX = off === 0 ? 0 : TILT_X; 12754 const scale = off === 0 ? ACTIVE_SCALE : INACTIVE_SCALE; 12755 const lift = off === 0 ? -ACTIVE_LIFT : 0; 12756 card.style.opacity = '1'; 12757 card.style.pointerEvents = ''; 12758 card.style.zIndex = String(100 - abs); 12759 card.style.transform = `translate(-50%, 0) translate3d(${x}px, ${y + lift}px, ${z}px) rotateX(${rotateX}deg) rotateZ(${rotateZ}deg) scale(${scale})`; 12760 card.classList.toggle('is-active', off === 0); 12761 }); 12762 if (counter) counter.innerHTML = `<b>${pad2(active + 1)}</b> / ${pad2(len)}`; 12763 if (dotsEl){ 12764 if (dotsEl.children.length !== len){ 12765 dotsEl.innerHTML = ''; 12766 visible.forEach((_, i) => { 12767 const b = document.createElement('button'); 12768 b.className = 'pcs-dot' + (i === active ? ' is-on' : ''); 12769 b.type = 'button'; 12770 b.setAttribute('aria-label', `Go to project ${i + 1}`); 12771 b.addEventListener('click', () => { active = i; layout(); }); 12772 dotsEl.appendChild(b); 12773 }); 12774 } else { 12775 [...dotsEl.children].forEach((d, i) => d.classList.toggle('is-on', i === active)); 12776 } 12777 } 12778 if (prevBtn) prevBtn.disabled = len < 2; 12779 if (nextBtn) nextBtn.disabled = len < 2; 12780 } 12781 12782 function goPrev(){ if (visible.length < 2) return; active = (active - 1 + visible.length) % visible.length; stage.removeAttribute('data-fresh'); layout(); } 12783 function goNext(){ if (visible.length < 2) return; active = (active + 1) % visible.length; stage.removeAttribute('data-fresh'); layout(); } 12784 12785 prevBtn?.addEventListener('click', goPrev); 12786 nextBtn?.addEventListener('click', goNext); 12787 12788 // Previous "click a non-active card â re-centre it (don't navigate)" 12789 // behaviour has been removed. It was the root cause of the visitor's 12790 // "clicks don't seem to work" complaint: users would click a card 12791 // expecting to go to its project page, but the carousel would silently 12792 // re-centre it instead. Now every card click navigates straight to the 12793 // project page (handled by the per-card script above). The prev/next 12794 // arrows and dot pagination remain the way to flip through cards 12795 // without leaving the homepage. 12796 12797 // Pointer drag/swipe from anywhere on the stage (mouse + touch) 12798 function onDown(e){ 12799 if (e.button && e.button !== 0) return; 12800 if (e.target.closest('.pcs-btn, .pcs-dot')) return; 12801 dragging = { startX: e.clientX, lastX: e.clientX, t0: performance.now(), moved: 0 }; 12802 try { stage.setPointerCapture(e.pointerId); } catch(_){} 12803 } 12804 function onMove(e){ 12805 if (!dragging) return; 12806 dragging.lastX = e.clientX; 12807 dragging.moved = Math.max(dragging.moved, Math.abs(e.clientX - dragging.startX)); 12808 } 12809 function onUp(e){ 12810 if (!dragging) return; 12811 const dx = (e.clientX || dragging.lastX) - dragging.startX; 12812 const dt = performance.now() - dragging.t0 || 1; 12813 const v = (dx / dt) * 1000; 12814 const threshold = Math.min(140, getCardWidth() * 0.18); 12815 try { stage.releasePointerCapture(e.pointerId); } catch(_){} 12816 lastDragMoved = dragging.moved; 12817 // Publish to a global the per-card click handler reads, so it can 12818 // skip "click â navigate" when the click is really the end of a swipe. 12819 window.__pcsDragMoved = dragging.moved; 12820 setTimeout(() => { window.__pcsDragMoved = 0; }, 250); 12821 if (dx > threshold || v > 600) goPrev(); 12822 else if (dx < -threshold || v < -600) goNext(); 12823 setTimeout(() => { dragging = null; }, 50); 12824 } 12825 stage.addEventListener('pointerdown', onDown); 12826 stage.addEventListener('pointermove', onMove); 12827 stage.addEventListener('pointerup', onUp); 12828 stage.addEventListener('pointercancel', () => { dragging = null; }); 12829 12830 // Mouse wheel â advance cards. Cooldown-gated so a hard scroll burst 12831 // can't fire 3+ goNext()'s back-to-back. 12832 // 12833 // CRITICAL: only intercept the page scroll when the gesture is 12834 // CLEARLY horizontal (touchpad sideways swipe, shift+wheel). Most 12835 // visitors use a mouse with a vertical-only wheel, so we MUST let 12836 // those events propagate to the page â otherwise scrolling past 12837 // this section feels stuck. Listener is passive by default; we 12838 // only flip to a preventDefault-capable listener if the dominant 12839 // axis is X. 12840 let wheelBuffer = 0, wheelTimer = null; 12841 let lastWheelStepAt = 0; 12842 const WHEEL_STEP = 140; // higher = less twitchy 12843 const WHEEL_COOLDOWN = 420; // ms between consecutive steps 12844 stage.addEventListener('wheel', e => { 12845 const ax = Math.abs(e.deltaX); 12846 const ay = Math.abs(e.deltaY); 12847 // Horizontal-dominant gesture? Treat as carousel control. 12848 // Threshold (ax > ay * 1.2) avoids hijacking near-vertical drifts. 12849 const horizontal = ax > ay * 1.2 && ax > 4; 12850 if (!horizontal) return; // â let the page scroll vertically 12851 e.preventDefault(); 12852 const delta = e.deltaX; 12853 wheelBuffer += delta; 12854 const now = performance.now(); 12855 if (now - lastWheelStepAt >= WHEEL_COOLDOWN){ 12856 if (wheelBuffer >= WHEEL_STEP){ goNext(); wheelBuffer = 0; lastWheelStepAt = now; } 12857 else if (wheelBuffer <= -WHEEL_STEP){ goPrev(); wheelBuffer = 0; lastWheelStepAt = now; } 12858 } 12859 clearTimeout(wheelTimer); 12860 wheelTimer = setTimeout(() => { wheelBuffer = 0; }, 260); 12861 }, { passive: false }); 12862 12863 stage.addEventListener('keydown', e => { 12864 if (e.key === 'ArrowLeft') { e.preventDefault(); goPrev(); } 12865 if (e.key === 'ArrowRight') { e.preventDefault(); goNext(); } 12866 }); 12867 12868 // Filter chips on the homepage projects strip (if any) â re-collect after refilter 12869 document.querySelectorAll('.proj-chip').forEach(chip => { 12870 chip.addEventListener('click', () => { 12871 setTimeout(() => { 12872 visible = allCards.filter(c => !c.classList.contains('is-filtered-out')); 12873 active = Math.min(active, Math.max(0, visible.length - 1)); 12874 if (dotsEl) dotsEl.innerHTML = ''; 12875 layout(); 12876 }, 0); 12877 }); 12878 }); 12879 12880 let raf; 12881 window.addEventListener('resize', () => { cancelAnimationFrame(raf); raf = requestAnimationFrame(layout); }); 12882 setTimeout(() => stage.removeAttribute('data-fresh'), 2400); 12883 layout(); 12884})(); 12885</script>
12885 12886 12887<!-- Expanding-panels engine for the featured-projects carousel -->
12888<script src="/assets/panels.js" defer></script>
12888 12889 12890 12891<!-- Live homepage stats: figures tagged [data-livestat] are filled from the data 12892 bundles so they stay truthful. 100% pass-through claims are policy, left as-is. -->
12893<script> 12894(function(){ 12895 function compactMoney(n){ n=Math.round(n); 12896 if(n>=1e6) return '$'+(n/1e6).toFixed(1).replace(/\.0$/,'')+'M'; 12897 if(n>=1e3) return '$'+Math.round(n/1e3)+'K'; 12898 return '$'+n.toLocaleString(); } 12899 Promise.all([ 12900 fetch('/assets/projects.json').then(function(r){return r.json();}).catch(function(){return null;}), 12901 fetch('/assets/ngos.json').then(function(r){return r.json();}).catch(function(){return null;}), 12902 fetch('/assets/ecosystems.json').then(function(r){return r.json();}).catch(function(){return null;}) 12903 ]).then(function(res){ 12904 var pj=res[0], ng=res[1], ecomap=res[2]||{}; 12905 var vals={}; 12906 var shown=[]; 12907 if(pj && pj.projects){ shown=pj.projects.filter(function(p){return p.show!==false;}); 12908 // Counts and money are canonical: computed over ALL projects, matching 12909 // the donate page and the projects directory. `show:false` only hides a 12910 // project's card from featured slots â it must never shrink the totals, 12911 // or the site contradicts itself (the old 33/$687K vs 34/$698K bug). 12912 vals.projects=pj.projects.length; 12913 vals.raised=compactMoney(pj.projects.reduce(function(s,p){return s+(Number(p.funding_usd)||0);},0)); 12914 vals.active=pj.projects.filter(function(p){return p.lifecycle==='Active'||p.lifecycle==='Urgent';}).length; 12915 vals.urgent=pj.projects.filter(function(p){return p.lifecycle==='Urgent';}).length; 12916 vals.completed=pj.projects.filter(function(p){return p.lifecycle==='Completed';}).length; } 12917 if(ng && ng.ngos){ vals.ngos=ng.ngos.length; } 12918 function pctFor(slug){ var p=shown.find(function(x){return x.id===slug;}); 12919 if(!p || !p.target_usd) return null; 12920 return Math.max(0,Math.min(100,Math.round((Number(p.funding_usd)||0)/Number(p.target_usd)*100))); } 12921 document.querySelectorAll('[data-livestat]').forEach(function(el){ 12922 var v=el.getAttribute('data-livestat'); 12923 if(vals[v]!=null){ el.textContent=vals[v]; return; } 12924 if(v.indexOf('fund:')===0){ var p=pctFor(v.slice(5)); if(p!=null) el.textContent=p+'% funded'; } 12925 else if(v.indexOf('fundpct:')===0){ var p=pctFor(v.slice(8)); if(p!=null) el.textContent=p; } 12926 else if(v.indexOf('fundbar:')===0){ var p=pctFor(v.slice(8)); if(p!=null) el.style.width=p+'%'; } 12927 else if(v.indexOf('fundvar:')===0){ var p=pctFor(v.slice(8)); if(p!=null) el.style.setProperty('--p', p+'%'); } 12928 }); 12929 // "Find the wild" ecosystem tiles: count PROJECTS per ecosystem from the 12930 // curated mapping (so the tile count matches the /projects/?ecosystem= 12931 // filter). Hide any tile that has no projects. 12932 document.querySelectorAll('.ecos-pill[data-eco]').forEach(function(tile){ 12933 var ids=ecomap[tile.getAttribute('data-eco')]; var n=Array.isArray(ids)?ids.length:0; 12934 var span=tile.querySelector('.ecos-pill-count'); 12935 if(!n){ tile.style.display='none'; return; } 12936 if(span) span.textContent=n+(n===1?' project':' projects'); 12937 }); 12938 // EcoâNGO bridge: count partner NGOs by environment facet (unchanged). 12939 if(ng && ng.ngos){ 12940 var envc={}; ng.ngos.forEach(function(x){ (x.environment||[]).forEach(function(e){ envc[e]=(envc[e]||0)+1; }); }); 12941 var ECO={oceans:'Oceans',rainforests:'Rainforests',savannah:'Savannah',mountains:'Mountains',wetlands:'Wetlands',polar:'Polar',forests:'Forests'}; 12942 document.querySelectorAll('.eco-bridge-pill[data-eco]').forEach(function(tile){ 12943 var env=ECO[tile.getAttribute('data-eco')]; var c=env?(envc[env]||0):0; 12944 var span=tile.querySelector('.ebp-count'); 12945 if(span){ if(c){ span.textContent=c+' partners'; span.style.display=''; } else { span.style.display='none'; } } 12946 }); 12947 } 12948 }); 12949})(); 12950</script>
12950 12951
12951<script src="/assets/nav.js" defer></script>
vendor: 1 bytes, line 12951
12951
12952<script src="/assets/social-proof.js" defer></script>
vendor: 1 bytes, line 12952
12952
12953<script src="/assets/share.js" defer></script>
12953 12954</body> 12955</html>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.