Align site copy and structure with client foundation brief

Add About, Mission, What We Do, Events, and Contact pages; update hero, footer, nav, EIN 33-4887159, and [email protected]; warm cream/beige palette and faith-centered messaging for LA County outreach.

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
defiQUG
2026-05-26 21:02:02 -07:00
co-authored by Cursor
parent 33aab0d3de
commit c9948dff4a
16 changed files with 758 additions and 286 deletions
+6 -6
View File
@@ -7,21 +7,21 @@
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Miracles In Motion | 501(c)3 Non-Profit Organization</title>
<meta name="description" content="Miracles In Motion is a 501(c)3 non-profit organization dedicated to creating positive change in our community through compassionate action and support." />
<title>Miracles in Motion Foundation | Faith • Hope • Community • Restoration</title>
<meta name="description" content="Restoring hope through compassion, community, and faith. Serving Los Angeles County with outreach, emergency assistance, and advocacy for families in crisis." />
<meta name="keywords" content="non-profit, charity, 501c3, miracles in motion, community support, donations, volunteers" />
<!-- Open Graph Meta Tags -->
<meta property="og:title" content="Miracles In Motion | 501(c)3 Non-Profit Organization" />
<meta property="og:description" content="Creating positive change in our community through compassionate action and support." />
<meta property="og:title" content="Miracles in Motion Foundation" />
<meta property="og:description" content="Restoring hope through compassion, community, and faith." />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://mim4u.org" />
<meta property="og:image" content="/og-image.png" />
<!-- Twitter Card Meta Tags -->
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="Miracles In Motion | 501(c)3 Non-Profit Organization" />
<meta name="twitter:description" content="Creating positive change in our community through compassionate action and support." />
<meta name="twitter:title" content="Miracles in Motion Foundation" />
<meta name="twitter:description" content="Restoring hope through compassion, community, and faith." />
<meta name="twitter:image" content="/og-image.png" />
<!-- Favicon and Web App Manifest -->
Binary file not shown.
+25
View File
@@ -35,6 +35,31 @@
<changefreq>monthly</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://mim4u.org/#/about</loc>
<changefreq>monthly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://mim4u.org/#/mission</loc>
<changefreq>monthly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://mim4u.org/#/what-we-do</loc>
<changefreq>monthly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://mim4u.org/#/events</loc>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
</url>
<url>
<loc>https://mim4u.org/#/contact</loc>
<changefreq>monthly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://mim4u.org/#/brand</loc>
<changefreq>monthly</changefreq>
+87 -91
View File
@@ -67,6 +67,16 @@ import MimChatAgent from './components/MimChatAgent'
import { Navigation } from './components/Navigation'
import { Footer } from './components/Footer'
import { BrandAssetsPage } from './pages/BrandPage'
import {
AboutPage,
ContactPage,
EventsPage,
MissionPage,
StoriesIntroBlock,
WhatWeDoPage,
} from './pages/foundation'
import { WhoWeServe } from './components/home/WhoWeServe'
import { SITE, WHAT_WE_DO } from './content/siteContent'
/**
* Miracles in Motion — Complete Non-Profit Website
@@ -590,11 +600,6 @@ interface FeatureCardProps {
body: string
}
interface StatProps {
label: string
value: number
}
interface SectionHeaderProps {
eyebrow?: string
title: string
@@ -788,6 +793,7 @@ function HomePage() {
return (
<>
<Hero />
<WhoWeServe />
<PartnerMarquee />
<Programs />
<Impact />
@@ -813,7 +819,7 @@ function Hero() {
<section ref={containerRef} className="relative isolate overflow-hidden min-h-screen flex items-center">
{/* Enhanced 3D Background Layers */}
<motion.div
className="absolute inset-0 bg-gradient-to-br from-primary-50/30 via-white to-secondary-50/30 dark:from-gray-900/30 dark:via-gray-800/30 dark:to-gray-900/30"
className="absolute inset-0 bg-gradient-to-br from-[var(--mim-cream)] via-white to-secondary-50/40 dark:from-gray-900/30 dark:via-gray-800/30 dark:to-gray-900/30"
style={{ y: backgroundY }}
>
<FloatingParticles />
@@ -846,19 +852,21 @@ function Hero() {
>
<div className="lg:col-span-7">
<ParallaxContainer depth={0.3}>
<p className="text-sm font-medium tracking-wide text-secondary-700 dark:text-secondary-300">
{SITE.tagline}
</p>
<motion.h1
initial={{ opacity: 0, y: 12 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.6 }}
className="text-balance text-4xl font-bold tracking-tight sm:text-5xl md:text-6xl transform-gpu"
className="mt-3 text-balance font-serif text-4xl font-bold tracking-tight sm:text-5xl md:text-6xl transform-gpu"
style={{ transformStyle: 'preserve-3d' }}
>
Equipping kids for success
<span className="relative whitespace-pre gradient-text"> school supplies, clothing, & more</span>
{SITE.brandMessage}
</motion.h1>
<p className="mt-5 max-w-xl text-lg leading-7 text-neutral-700 dark:text-neutral-300">
Miracles in Motion is a nonprofit providing students with the essentials they need to thrive: backpacks and notebooks, uniforms and shoes, and the everything-else fund for urgent needs.
Bringing hope, compassion, and support to individuals and families facing lifes most difficult moments through faith, community outreach, and compassionate care in Los Angeles County.
</p>
<div className="mt-8 flex flex-wrap items-center gap-3">
<Magnetic>
@@ -869,14 +877,14 @@ function Hero() {
<a href="#/volunteers" className="btn-secondary">
Volunteer <ArrowRight className="ml-1 h-4 w-4" />
</a>
<a href="#/stories" className="rounded-full border border-transparent px-4 py-2 text-sm text-neutral-700 underline-offset-4 hover:underline dark:text-neutral-300">
Read stories
<a href="#/about" className="rounded-full border border-transparent px-4 py-2 text-sm text-neutral-700 underline-offset-4 hover:underline dark:text-neutral-300">
About us
</a>
</div>
<ul className="mt-8 flex flex-wrap items-center gap-x-6 gap-y-2 text-sm text-neutral-600 dark:text-neutral-400">
<li className="flex items-center gap-2"><CheckCircle2 className="h-4 w-4 text-emerald-500"/> 501(c)(3) public charity</li>
<li className="flex items-center gap-2"><CheckCircle2 className="h-4 w-4 text-emerald-500"/> Donations tax-deductible</li>
<li className="flex items-center gap-2"><CheckCircle2 className="h-4 w-4 text-emerald-500"/> Community-driven impact</li>
<li className="flex items-center gap-2"><CheckCircle2 className="h-4 w-4 text-secondary-600"/> {SITE.legalStatus}</li>
<li className="flex items-center gap-2"><CheckCircle2 className="h-4 w-4 text-secondary-600"/> EIN {SITE.ein}</li>
<li className="flex items-center gap-2"><CheckCircle2 className="h-4 w-4 text-secondary-600"/> Los Angeles County</li>
</ul>
</ParallaxContainer>
</div>
@@ -1028,10 +1036,10 @@ function HeroShowcase() {
<div className="relative mx-auto max-w-sm lg:max-w-md xl:max-w-lg">
<div className="absolute -inset-6 -z-10 rounded-3xl bg-gradient-to-tr from-primary-500/15 via-secondary-500/15 to-secondary-600/15 blur-2xl" />
<div className="grid grid-cols-2 gap-3 sm:gap-4">
<TiltCard icon={Backpack} title="School Supplies" desc="Backpacks, notebooks, calculators" />
<TiltCard icon={Shirt} title="School Clothing" desc="Uniforms, shoes, coats" />
<TiltCard icon={Sparkles} title="Everything Else" desc="Glasses, fees, emergencies" />
<TiltCard icon={Users} title="Family Support" desc="Referrals & wraparound care" />
<TiltCard icon={Users} title="Community Outreach" desc="Direct support for families in need" />
<TiltCard icon={Heart} title="Crisis & Relief" desc="Fire, disaster, and emergency assistance" />
<TiltCard icon={Shield} title="Advocacy & Navigation" desc="Resources, referrals, and compassionate care" />
<TiltCard icon={Sparkles} title="Hope & Restoration" desc="Faith-rooted support when it matters most" />
</div>
</div>
)
@@ -1117,11 +1125,12 @@ function PartnerMarquee() {
}
function Programs() {
const items = [
{ icon: Backpack, title: "School Supplies", body: "Backpacks, notebooks, art kits, calculators—ready for day one." },
{ icon: Shirt, title: "School Clothing", body: "Uniforms, shoes, coats, and seasonal essentials in all sizes." },
{ icon: Sparkles, title: "Everything Else", body: "Glasses, test fees, activity passes, hygiene kits—fast relief when needed." },
]
const icons = [Users, Heart, HomeIcon, Globe, Shield, Star] as const
const items = WHAT_WE_DO.slice(0, 3).map((p, idx) => ({
icon: icons[idx] ?? Heart,
title: p.title,
body: p.body,
}))
return (
<section id="programs" className="relative py-20 overflow-hidden">
@@ -1149,7 +1158,7 @@ function Programs() {
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 relative z-10">
<ParallaxContainer depth={0.2}>
<SectionHeader eyebrow="What we do" title="Practical, student-first programs" subtitle="Flexible help that meets families where they are." />
<SectionHeader eyebrow="What we do" title="Compassionate support when it matters most" subtitle="Outreach, advocacy, emergency assistance, and resource navigation for vulnerable populations." />
</ParallaxContainer>
<div className="mt-10 grid gap-6 md:grid-cols-3">
{items.map((i, idx) => (
@@ -1158,6 +1167,11 @@ function Programs() {
</ParallaxContainer>
))}
</div>
<div className="mt-10 text-center">
<a href="#/what-we-do" className="btn-secondary">
See all programs <ArrowRight className="ml-1 inline h-4 w-4" />
</a>
</div>
</div>
</section>
)
@@ -1216,11 +1230,11 @@ function FeatureCard({ icon: Icon, title, body }: FeatureCardProps) {
}
function Impact() {
const stats = [
{ label: "Students equipped", value: 4200 },
{ label: "Schools partnered", value: 38 },
{ label: "Avg. response time (hrs)", value: 24 },
{ label: "Counties served", value: 6 },
const pillars = [
{ label: "Community outreach", desc: "Direct support for underserved families" },
{ label: "Emergency assistance", desc: "Crisis, fire, and disaster relief" },
{ label: "Advocacy & navigation", desc: "Connecting people to hope and resources" },
{ label: "Faith & restoration", desc: "Dignity, empathy, and compassionate care" },
]
return (
@@ -1251,41 +1265,38 @@ function Impact() {
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 relative z-10">
<ParallaxContainer depth={0.2}>
<SectionHeader eyebrow="Impact" title="Every gift moves a student forward" subtitle="Transparent, measurable outcomes powered by local partnerships." />
<SectionHeader eyebrow="Our heart" title="Healing begins when people feel seen" subtitle={SITE.closingLine} />
</ParallaxContainer>
<div className="mt-12 grid gap-6 sm:grid-cols-2 lg:grid-cols-4">
{stats.map((s, i) => (
{pillars.map((s, i) => (
<ParallaxContainer key={i} depth={0.3 + i * 0.05}>
<motion.div
initial={{ opacity: 0, y: 30, rotateX: -15 }}
whileInView={{ opacity: 1, y: 0, rotateX: 0 }}
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.8, delay: i * 0.15 }}
whileHover={{
scale: 1.05,
rotateY: 8,
z: 60,
boxShadow: "0 25px 50px -12px rgba(0, 0, 0, 0.25)"
}}
style={{ transformStyle: 'preserve-3d' }}
className="card h-full text-center"
>
<Stat label={s.label} value={s.value} />
<div className="font-semibold tracking-tight text-primary-800 dark:text-primary-100">{s.label}</div>
<p className="mt-2 text-sm text-neutral-600 dark:text-neutral-400">{s.desc}</p>
</motion.div>
</ParallaxContainer>
))}
</div>
<div className="mt-10 grid items-center gap-6 rounded-2xl border border-emerald-500/20 bg-emerald-500/10 p-6 sm:grid-cols-2">
<div className="text-sm text-emerald-900 dark:text-emerald-100">
<div className="font-medium">Where your donation goes</div>
<ul className="mt-3 space-y-2">
<li className="flex items-center gap-2"><span className="h-1.5 w-1.5 rounded-full bg-emerald-500"/> 85% programs 10% ops 5% fundraising</li>
<li className="flex items-center gap-2"><span className="h-1.5 w-1.5 rounded-full bg-emerald-500"/> Average grant: $48 for supplies; $72 for clothing</li>
</ul>
<div className="mt-10 grid items-center gap-6 rounded-2xl border border-secondary-300/30 bg-secondary-50/50 p-6 sm:grid-cols-2 dark:border-secondary-700/30 dark:bg-secondary-900/20">
<div className="text-sm text-primary-900 dark:text-primary-100">
<div className="font-medium">Your gift restores hope</div>
<p className="mt-3 leading-relaxed">
Donations support outreach, emergency assistance, wellness support, and resource navigation for women, families, survivors, and communities in crisis throughout Los Angeles County.
</p>
</div>
<div className="flex items-center justify-end">
<a href="#/impact" className="btn-primary">
See the impact report <ArrowRight className="ml-2 h-4 w-4" />
<div className="flex flex-wrap items-center justify-end gap-3">
<a href="#/donate" className="btn-primary">
Donate <ArrowRight className="ml-2 h-4 w-4" />
</a>
<a href="#/stories" className="btn-secondary">
Stories of hope
</a>
</div>
</div>
@@ -1294,32 +1305,6 @@ function Impact() {
)
}
function Stat({ label, value }: StatProps) {
return (
<div className="card text-center">
<div className="absolute -right-10 -top-10 h-28 w-28 rounded-full bg-gradient-to-br from-primary-500/20 to-secondary-600/20 blur-2xl" />
<div className="text-4xl font-semibold tracking-tight">
<AnimatedNumber value={value} />
</div>
<div className="mt-2 text-sm text-neutral-600 dark:text-neutral-300">{label}</div>
</div>
)
}
function AnimatedNumber({ value }: { value: number }) {
const mv = useMotionValue(0)
const spring = useSpring(mv, { stiffness: 90, damping: 15 })
const rounded = useTransform(spring, (latest) => Math.floor(latest).toLocaleString())
useEffect(() => {
mv.set(0)
const timeout = setTimeout(() => mv.set(value), 150)
return () => clearTimeout(timeout)
}, [value, mv])
return <motion.span>{rounded}</motion.span>
}
function HowItWorks() {
const steps = [
{ title: "Referral", body: "A school counselor, social worker, or parent submits a simple request." },
@@ -1583,10 +1568,10 @@ function CTA() {
<h3 className="font-medium tracking-tight">Prefer offline?</h3>
<ul className="mt-3 space-y-2 text-sm text-white/90">
<li className="flex items-center gap-2"><MapPin className="h-4 w-4"/> 20274 Via Medici, Porter Ranch, CA 91326</li>
<li className="flex items-center gap-2"><Mail className="h-4 w-4"/> [email protected]</li>
<li className="flex items-center gap-2"><Mail className="h-4 w-4"/> {SITE.email}</li>
<li className="flex items-center gap-2"><Phone className="h-4 w-4"/> (818) 491-6884</li>
</ul>
<p className="mt-3 text-xs text-white/80">Miracles in Motion is a 501(c)(3). EIN 88-1234567.</p>
<p className="mt-3 text-xs text-white/80">{SITE.legalStatus}. EIN {SITE.ein}.</p>
</div>
</div>
</div>
@@ -1995,7 +1980,7 @@ function DonatePage() {
<span>Secure 256-bit SSL encryption</span>
</div>
<p className="text-xs text-neutral-500 dark:text-neutral-500 mt-2">
You'll receive an email receipt for your tax records. Donations are tax-deductible to the extent allowed by law. EIN 12-3456789.
You'll receive an email receipt for your tax records. Donations are tax-deductible to the extent allowed by law. EIN {SITE.ein}.
</p>
</div>
</div>
@@ -2012,7 +1997,7 @@ function DonatePage() {
</div>
</div>
<p className="text-sm text-neutral-700 dark:text-neutral-300 mb-3">
Many employers will match your charitable donation. Check with your HR department and provide our EIN: 12-3456789.
Many employers will match your charitable donation. Check with your HR department and provide our EIN: {SITE.ein}.
</p>
<a href="#" className="inline-flex items-center gap-2 text-sm text-primary-600 dark:text-primary-400 hover:text-primary-700 dark:hover:text-primary-300 focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2 rounded">
<ExternalLink className="h-4 w-4" />
@@ -2115,8 +2100,8 @@ function DonatePage() {
</div>
<div className="flex items-center gap-2">
<Mail className="h-4 w-4 text-primary-600 dark:text-primary-400" />
<a href="mailto:[email protected]" className="text-primary-600 dark:text-primary-400 hover:text-primary-700 dark:hover:text-primary-300">
contact@mim4u.org
<a href={SITE.emailHref} className="text-primary-600 dark:text-primary-400 hover:text-primary-700 dark:hover:text-primary-300">
{SITE.email}
</a>
</div>
</div>
@@ -2230,13 +2215,14 @@ function SponsorsPage() {
function StoriesPage() {
const stories = [
{ title: "Ready on Day One", tag: "Supplies", body: "A 3rd grader received a backpack and art kit, returning to class with pride.", by: "Ms. Lee, Teacher" },
{ title: "Warm for Winter", tag: "Clothing", body: "A high schooler got a coat and shoes before a cold snap—attendance rebounded.", by: "School Social Worker" },
{ title: "Glasses for Growth", tag: "Everything Else", body: "A student's new glasses improved reading in two weeks.", by: "Counselor" },
{ title: "A family found hope again", tag: "Outreach", body: "After a fire displaced their home, a mother and children received emergency support and compassionate guidance through recovery.", by: "Community partner" },
{ title: "Strength after hardship", tag: "Advocacy", body: "A survivor connected with resources and encouragement — reminded that she matters and brighter days are ahead.", by: "Volunteer" },
{ title: "Community showed up", tag: "Events", body: "Neighbors and volunteers came together at an outreach event to serve families with supplies, prayer, and heartfelt support.", by: "Event volunteer" },
]
return (
<PageShell title="Stories" icon={BookOpenText} eyebrow="Impact in motion" cta={<a href="#/testimonies" className="btn-secondary">Read testimonies</a>}>
<PageShell title="Stories of Hope" icon={BookOpenText} eyebrow="Hope in motion" cta={<a href="#/testimonies" className="btn-secondary">Read testimonies</a>}>
<StoriesIntroBlock />
<div className="grid gap-6 md:grid-cols-3">
{stories.map((s, i) => (
<article key={i} className="card">
@@ -2289,7 +2275,7 @@ function ImpactReportPage() {
<PageShell title="Impact Report" icon={BarChart3} eyebrow="Our impact in numbers" cta={<a href="#/donate" className="btn-primary">Donate to support more students</a>}>
<div className="max-w-4xl mx-auto space-y-8">
<p className="text-lg text-neutral-700 dark:text-neutral-300">
Miracles in Motion provides essential supplies, clothing, and support to students in need. Below is a summary of our impact. For the full report or data requests, contact <a className="underline" href="mailto:[email protected]">contact@mim4u.org</a>.
Miracles in Motion Foundation serves vulnerable individuals and families across Los Angeles County. For impact updates or data requests, contact <a className="underline" href={SITE.emailHref}>{SITE.email}</a>.
</p>
<div className="grid gap-6 sm:grid-cols-2 lg:grid-cols-4">
<div className="card text-center">
@@ -2365,7 +2351,7 @@ function LegalPage() {
<p>We aim to meet WCAG 2.1 AA standards. If you encounter accessibility barriers, email <a className="underline" href="mailto:[email protected]">access@miraclesinmotion.org</a>.</p>
</PolicySection>
<PolicySection id="financials" title="Financials & 990">
<p>Miracles in Motion is a 501(c)(3) nonprofit. EIN 12-3456789. Annual reports and Form 990s are available upon request or linked here when published.</p>
<p>{SITE.name} is a {SITE.legalStatus.toLowerCase()}. EIN {SITE.ein}. Annual reports and Form 990s are available upon request or linked here when published.</p>
</PolicySection>
<PolicySection id="sponsorship-terms" title="Sponsorship Terms & Logo Use">
<ul className="list-disc pl-5 space-y-2">
@@ -4558,7 +4544,7 @@ function AppContent() {
// Update document title based on current route
useEffect(() => {
document.title = currentPath === "/"
? "Miracles in Motion — Essentials for Every Student"
? `${SITE.name}${SITE.brandMessage}`
: `Miracles in Motion — ${currentPath.replace("/", "").replace(/-/g, " ").replace(/\b\w/g, (m) => m.toUpperCase())}`
}, [currentPath])
@@ -4579,6 +4565,16 @@ function AppContent() {
return <LegalPage />
case '/brand':
return <BrandAssetsPage />
case '/about':
return <AboutPage />
case '/mission':
return <MissionPage />
case '/what-we-do':
return <WhatWeDoPage />
case '/events':
return <EventsPage />
case '/contact':
return <ContactPage />
case '/impact':
return <ImpactReportPage />
case '/request-assistance':
+84 -26
View File
@@ -1,62 +1,120 @@
import {
Facebook,
Globe,
Instagram,
} from 'lucide-react'
import { Facebook, Globe, Instagram, Mail } from 'lucide-react'
import { SITE } from '../content/siteContent'
import { LogoMark } from './ui/LogoMark'
export function Footer() {
return (
<footer className="relative mt-24 border-t border-white/30 bg-white/50 backdrop-blur dark:border-white/10 dark:bg-white/5">
<footer className="relative mt-24 border-t border-secondary-200/60 bg-[var(--mim-cream)]/90 backdrop-blur dark:border-white/10 dark:bg-white/5">
<div className="mx-auto max-w-7xl px-4 py-12 sm:px-6 lg:px-8">
<div className="grid gap-8 lg:grid-cols-4">
<div className="lg:col-span-2">
<div className="footer-brand-block">
<LogoMark variant="footer" />
<p className="footer-tagline">Essentials for every student</p>
<p className="footer-tagline">{SITE.tagline}</p>
</div>
<p className="mt-4 max-w-md text-sm text-neutral-600 dark:text-neutral-400">
A 501(c)(3) nonprofit providing students with school supplies, clothing, and emergency support to help them succeed.
<p className="mt-4 max-w-md text-sm leading-relaxed text-neutral-700 dark:text-neutral-300">
{SITE.brandMessage}
</p>
<p className="mt-3 text-sm text-neutral-600 dark:text-neutral-400">{SITE.serviceArea}</p>
<div className="mt-4 flex gap-4">
<a href="#" className="text-neutral-600 hover:text-primary-600 dark:text-neutral-400">
<a href="#" className="text-neutral-600 hover:text-primary-600 dark:text-neutral-400" aria-label="Facebook">
<Facebook className="h-5 w-5" />
</a>
<a href="#" className="text-neutral-600 hover:text-primary-600 dark:text-neutral-400">
<a href="#" className="text-neutral-600 hover:text-primary-600 dark:text-neutral-400" aria-label="Instagram">
<Instagram className="h-5 w-5" />
</a>
<a href="#" className="text-neutral-600 hover:text-primary-600 dark:text-neutral-400">
<a href="#" className="text-neutral-600 hover:text-primary-600 dark:text-neutral-400" aria-label="Website">
<Globe className="h-5 w-5" />
</a>
</div>
</div>
<div>
<h3 className="font-semibold">Get Involved</h3>
<ul className="mt-4 space-y-2 text-sm">
<li><a href="#/donate" className="navlink">Donate</a></li>
<li><a href="#/volunteers" className="navlink">Volunteer</a></li>
<li><a href="#/sponsors" className="navlink">Corporate Partnerships</a></li>
<li><a href="#/stories" className="navlink">Success Stories</a></li>
<li>
<a href="#/donate" className="navlink">
Donate
</a>
</li>
<li>
<a href="#/volunteers" className="navlink">
Volunteer
</a>
</li>
<li>
<a href="#/events" className="navlink">
Community Events
</a>
</li>
<li>
<a href="#/stories" className="navlink">
Stories of Hope
</a>
</li>
</ul>
</div>
<div>
<h3 className="font-semibold">Organization</h3>
<h3 className="font-semibold">About</h3>
<ul className="mt-4 space-y-2 text-sm">
<li><a href="#/testimonies" className="navlink">Testimonials</a></li>
<li><a href="#/brand" className="navlink">Brand assets</a></li>
<li><a href="#/legal" className="navlink">Legal & Policies</a></li>
<li><a href="mailto:[email protected]" className="navlink">Contact Us</a></li>
<li><a href="tel:+18184916884" className="navlink">(818) 491-6884</a></li>
<li>
<a href="#/about" className="navlink">
About Us
</a>
</li>
<li>
<a href="#/mission" className="navlink">
Our Mission
</a>
</li>
<li>
<a href="#/what-we-do" className="navlink">
What We Do
</a>
</li>
<li>
<a href="#/contact" className="navlink">
Contact Us
</a>
</li>
<li>
<a href={SITE.emailHref} className="navlink inline-flex items-center gap-1">
<Mail className="h-3.5 w-3.5" aria-hidden />
{SITE.email}
</a>
</li>
<li>
<a href="#/request-assistance" className="navlink">
Request assistance
</a>
</li>
<li>
<a href="#/legal" className="navlink">
Legal & Policies
</a>
</li>
</ul>
</div>
</div>
<div className="mt-8 border-t border-white/30 pt-8 text-center text-xs text-neutral-500 dark:border-white/10 dark:text-neutral-400">
<p>© 2025 Miracles in Motion. All rights reserved. EIN: 88-1234567</p>
<p className="mt-1">501(c)(3) nonprofit organization. Donations are tax-deductible to the extent allowed by law.</p>
<div className="mt-8 border-t border-secondary-200/50 pt-8 text-center text-xs text-neutral-600 dark:border-white/10 dark:text-neutral-400">
<p className="font-medium text-neutral-800 dark:text-neutral-200">{SITE.name}</p>
<p className="mt-1">{SITE.legalStatus}</p>
<p className="mt-1">
EIN:{' '}
<a href={`tel:${SITE.ein.replace(/-/g, '')}`} className="underline">
{SITE.ein}
</a>
</p>
<p className="mt-2">
© {new Date().getFullYear()} {SITE.shortName}. All rights reserved. Donations may be
tax-deductible to the extent allowed by law.
</p>
</div>
</div>
</footer>
)
}
export default Footer
export default Footer
+76 -73
View File
@@ -1,15 +1,8 @@
import React, { useEffect } from 'react'
import { motion } from 'framer-motion'
import {
Heart,
Menu,
Moon,
SunMedium,
X,
} from 'lucide-react'
import { Heart, Menu, Moon, SunMedium, X } from 'lucide-react'
import { NAV_LINKS } from '../content/siteContent'
import { trackEvent } from '../utils/analytics'
// Import UI components
import { Magnetic, LogoMark } from './ui'
interface NavProps {
@@ -20,12 +13,10 @@ interface NavProps {
}
export function Navigation({ darkMode, setDarkMode, mobileMenuOpen, setMobileMenuOpen }: NavProps) {
// Close mobile menu when route changes
useEffect(() => {
setMobileMenuOpen(false)
}, [window.location.hash])
}, [window.location.hash, setMobileMenuOpen])
// Handle keyboard navigation
const handleKeyDown = (e: React.KeyboardEvent, action: () => void) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault()
@@ -33,39 +24,51 @@ export function Navigation({ darkMode, setDarkMode, mobileMenuOpen, setMobileMen
}
}
const navLinkClass =
'navlink focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2 rounded text-sm lg:text-[0.9375rem]'
return (
<>
<nav className="mim-site-nav mx-auto flex w-full max-w-7xl items-center justify-between px-4 py-3 sm:px-6 lg:px-8 lg:py-4" role="navigation" aria-label="Main navigation">
<div className="flex items-center gap-3">
<a
href="#/"
className="nav-brand-link focus:outline-none"
aria-label="Miracles in Motion Foundation — Home"
>
<LogoMark variant="nav" />
<span className="sr-only">Essentials for every student</span>
</a>
<nav
className="mim-site-nav mx-auto flex w-full max-w-7xl items-center justify-between gap-2 px-4 py-3 sm:px-6 lg:px-8 lg:py-4"
role="navigation"
aria-label="Main navigation"
>
<a
href="#/"
className="nav-brand-link shrink-0 focus:outline-none"
aria-label="Miracles in Motion Foundation — Home"
>
<LogoMark variant="nav" />
</a>
<div className="hidden items-center gap-4 xl:gap-5 lg:flex">
{NAV_LINKS.map((link) => (
<a
key={link.href}
className={navLinkClass}
href={link.href}
aria-label={link.ariaLabel}
onClick={
link.href === '#/volunteers'
? () => trackEvent('cta_clicked', { button: 'volunteer', location: 'nav' })
: undefined
}
>
{link.label}
</a>
))}
</div>
{/* Desktop Navigation */}
<div className="hidden items-center gap-6 md:flex">
<a className="navlink focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2 rounded" href="#/stories" aria-label="Read success stories">Stories</a>
<a className="navlink focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2 rounded" href="#/testimonies" aria-label="View testimonies">Testimonies</a>
<a className="navlink focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2 rounded" href="#/volunteers" aria-label="Volunteer opportunities" onClick={() => trackEvent('cta_clicked', { button: 'volunteer', location: 'nav' })}>Volunteers</a>
<a className="navlink focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2 rounded" href="#/sponsors" aria-label="Corporate partnerships">Corporate</a>
<a className="navlink focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2 rounded" href="#/request-assistance" aria-label="Request assistance">Get Help</a>
<a className="navlink focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2 rounded" href="#/portals" aria-label="Portal login">Portals</a>
</div>
{/* Desktop Actions */}
<div className="hidden md:flex items-center gap-3">
<div className="hidden items-center gap-3 lg:flex">
<Magnetic>
<a
href="#/donate"
className="btn-primary focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500"
aria-label="Make a donation"
>
<Heart className="mr-2 h-4 w-4" aria-hidden="true" /> Donate
<Heart className="mr-2 h-4 w-4" aria-hidden />
Donate
</a>
</Magnetic>
<button
@@ -75,73 +78,73 @@ export function Navigation({ darkMode, setDarkMode, mobileMenuOpen, setMobileMen
className="group rounded-full border border-neutral-200/70 bg-white/70 p-2 shadow-sm transition hover:scale-105 hover:bg-white dark:border-white/10 dark:bg-white/10 dark:hover:bg-white/15 focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2"
>
{darkMode ? (
<SunMedium className="h-5 w-5 transition group-hover:rotate-12" aria-hidden="true" />
<SunMedium className="h-5 w-5 transition group-hover:rotate-12" aria-hidden />
) : (
<Moon className="h-5 w-5 transition group-hover:-rotate-12" aria-hidden="true" />
<Moon className="h-5 w-5 transition group-hover:-rotate-12" aria-hidden />
)}
</button>
</div>
{/* Mobile Actions */}
<div className="flex md:hidden items-center gap-2">
<div className="flex items-center gap-2 lg:hidden">
<Magnetic>
<a
href="#/donate"
className="btn-primary text-sm px-3 py-2 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500"
className="btn-primary px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500"
aria-label="Make a donation"
>
<Heart className="h-4 w-4" aria-hidden="true" />
<Heart className="h-4 w-4" aria-hidden />
</a>
</Magnetic>
<button
aria-label={darkMode ? 'Switch to light mode' : 'Switch to dark mode'}
onClick={() => setDarkMode(!darkMode)}
className="rounded-full border border-neutral-200/70 bg-white/70 p-2 shadow-sm transition hover:scale-105 hover:bg-white dark:border-white/10 dark:bg-white/10 dark:hover:bg-white/15 focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2"
className="rounded-full border border-neutral-200/70 bg-white/70 p-2 shadow-sm transition hover:scale-105 dark:border-white/10 dark:bg-white/10"
>
{darkMode ? (
<SunMedium className="h-4 w-4" aria-hidden="true" />
) : (
<Moon className="h-4 w-4" aria-hidden="true" />
)}
{darkMode ? <SunMedium className="h-4 w-4" aria-hidden /> : <Moon className="h-4 w-4" aria-hidden />}
</button>
<button
aria-label={mobileMenuOpen ? 'Close navigation menu' : 'Open navigation menu'}
onClick={() => setMobileMenuOpen(!mobileMenuOpen)}
onKeyDown={(e) => handleKeyDown(e, () => setMobileMenuOpen(!mobileMenuOpen))}
className="rounded-full border border-neutral-200/70 bg-white/70 p-2 shadow-sm transition hover:scale-105 hover:bg-white dark:border-white/10 dark:bg-white/10 dark:hover:bg-white/15 focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2"
className="rounded-full border border-neutral-200/70 bg-white/70 p-2 shadow-sm dark:border-white/10 dark:bg-white/10"
aria-expanded={mobileMenuOpen}
aria-controls="mobile-menu"
>
{mobileMenuOpen ? (
<X className="h-5 w-5" aria-hidden="true" />
) : (
<Menu className="h-5 w-5" aria-hidden="true" />
)}
{mobileMenuOpen ? <X className="h-5 w-5" aria-hidden /> : <Menu className="h-5 w-5" aria-hidden />}
</button>
</div>
</nav>
{/* Mobile Menu */}
<motion.div
id="mobile-menu"
className="md:hidden"
className="lg:hidden"
initial={false}
animate={{
height: mobileMenuOpen ? 'auto' : 0,
opacity: mobileMenuOpen ? 1 : 0
}}
exit={{ height: 0, opacity: 0 }}
animate={{ height: mobileMenuOpen ? 'auto' : 0, opacity: mobileMenuOpen ? 1 : 0 }}
transition={{ duration: 0.2 }}
style={{ overflow: 'hidden' }}
>
<div className="border-t border-neutral-200/50 bg-white/95 px-4 py-3 backdrop-blur dark:border-white/10 dark:bg-black/90">
<div className="space-y-3">
<a className="block py-2 text-sm font-medium rounded focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2" href="#/stories">Stories</a>
<a className="block py-2 text-sm font-medium rounded focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2" href="#/testimonies">Testimonies</a>
<a className="block py-2 text-sm font-medium rounded focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2" href="#/volunteers" onClick={() => trackEvent('cta_clicked', { button: 'volunteer', location: 'nav_mobile' })}>Volunteers</a>
<a className="block py-2 text-sm font-medium rounded focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2" href="#/sponsors">Corporate</a>
<a className="block py-2 text-sm font-medium rounded focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2" href="#/request-assistance">Get Help</a>
<a className="block py-2 text-sm font-medium rounded focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2" href="#/portals">Portals</a>
<div className="border-t border-secondary-200/50 bg-[var(--mim-cream)]/95 px-4 py-3 backdrop-blur dark:border-white/10 dark:bg-black/90">
<div className="space-y-1">
<a className="block rounded py-2 text-sm font-medium" href="#/">
Home
</a>
{NAV_LINKS.map((link) => (
<a
key={link.href}
className="block rounded py-2 text-sm font-medium focus-visible:ring-2 focus-visible:ring-primary-500"
href={link.href}
>
{link.label}
</a>
))}
<a className="block rounded py-2 text-sm font-medium" href="#/donate">
Donate
</a>
<a
className="block rounded py-2 text-sm text-neutral-600 dark:text-neutral-400"
href="#/request-assistance"
>
Request assistance
</a>
</div>
</div>
</motion.div>
@@ -149,4 +152,4 @@ export function Navigation({ darkMode, setDarkMode, mobileMenuOpen, setMobileMen
)
}
export default Navigation
export default Navigation
+4 -3
View File
@@ -15,8 +15,9 @@ interface SEOHeadProps {
}
export function SEOHead({
title = 'Miracles in Motion - Empowering Students with Essential Support',
description = 'A 501(c)(3) nonprofit providing students with school supplies, clothing, and emergency support to help them succeed in school and life.',
title = 'Miracles in Motion Foundation — Restoring hope through compassion, community, and faith',
description =
'A California nonprofit bringing hope, compassion, and support to individuals and families in crisis throughout Los Angeles County — community outreach, emergency assistance, advocacy, and faith-rooted care.',
image = '/og-image.png',
url = 'https://mim4u.org',
type = 'website',
@@ -100,7 +101,7 @@ export function SEOHead({
"@type": "ContactPoint",
"telephone": "+1-818-491-6884",
"contactType": "customer service",
"email": "contact@mim4u.org"
"email": "info@faithforwardmiracles.org"
},
"address": {
"@type": "PostalAddress",
+25 -40
View File
@@ -3,72 +3,57 @@ import { render } from '@testing-library/react'
import { screen } from '@testing-library/dom'
import '@testing-library/jest-dom'
import { Footer } from '../Footer'
import { SITE } from '../../content/siteContent'
// Mock the LogoMark component
vi.mock('../ui/LogoMark', () => ({
LogoMark: () => <div data-testid="logo-mark">Logo</div>
LogoMark: () => <div data-testid="logo-mark">Logo</div>,
}))
describe('Footer Component', () => {
it('renders footer with logo and brand information', () => {
render(<Footer />)
expect(screen.getByTestId('logo-mark')).toBeInTheDocument()
expect(screen.getByText('Miracles in Motion')).toBeInTheDocument()
expect(screen.getByText('Essentials for every student')).toBeInTheDocument()
expect(screen.getByText(SITE.tagline)).toBeInTheDocument()
expect(screen.getByText(SITE.brandMessage)).toBeInTheDocument()
})
it('renders organization description', () => {
it('renders service area', () => {
render(<Footer />)
expect(screen.getByText(/A 501\(c\)\(3\) nonprofit providing students/)).toBeInTheDocument()
})
it('renders social media links', () => {
render(<Footer />)
const socialLinks = screen.getAllByRole('link')
const socialIcons = socialLinks.filter((link: HTMLElement) =>
link.getAttribute('href') === '#'
)
expect(socialIcons).toHaveLength(3) // Facebook, Instagram, Globe
expect(screen.getByText(/Los Angeles County/)).toBeInTheDocument()
})
it('renders Get Involved section with correct links', () => {
render(<Footer />)
expect(screen.getByText('Get Involved')).toBeInTheDocument()
expect(screen.getByRole('link', { name: 'Donate' })).toHaveAttribute('href', '#/donate')
expect(screen.getByRole('link', { name: 'Volunteer' })).toHaveAttribute('href', '#/volunteers')
expect(screen.getByRole('link', { name: 'Corporate Partnerships' })).toHaveAttribute('href', '#/sponsors')
expect(screen.getByRole('link', { name: 'Success Stories' })).toHaveAttribute('href', '#/stories')
expect(screen.getByRole('link', { name: 'Community Events' })).toHaveAttribute('href', '#/events')
expect(screen.getByRole('link', { name: 'Stories of Hope' })).toHaveAttribute('href', '#/stories')
})
it('renders Organization section with correct links', () => {
it('renders About section with contact email', () => {
render(<Footer />)
expect(screen.getByText('Organization')).toBeInTheDocument()
expect(screen.getByRole('link', { name: 'Testimonials' })).toHaveAttribute('href', '#/testimonies')
expect(screen.getByRole('link', { name: 'Legal & Policies' })).toHaveAttribute('href', '#/legal')
expect(screen.getByRole('link', { name: 'Contact Us' })).toHaveAttribute('href', 'mailto:[email protected]')
expect(screen.getByRole('link', { name: '(818) 491-6884' })).toHaveAttribute('href', 'tel:+18184916884')
expect(screen.getByText('About')).toBeInTheDocument()
expect(screen.getByRole('link', { name: SITE.email })).toHaveAttribute('href', SITE.emailHref)
expect(screen.getByRole('link', { name: 'About Us' })).toHaveAttribute('href', '#/about')
expect(screen.getByRole('link', { name: 'Our Mission' })).toHaveAttribute('href', '#/mission')
})
it('renders copyright information', () => {
it('renders legal and EIN', () => {
render(<Footer />)
expect(screen.getByText(/© 2025 Miracles in Motion. All rights reserved./)).toBeInTheDocument()
expect(screen.getByText(/501\(c\)\(3\) nonprofit organization./)).toBeInTheDocument()
expect(screen.getByText(SITE.name)).toBeInTheDocument()
expect(screen.getByText(SITE.legalStatus)).toBeInTheDocument()
expect(screen.getByText(new RegExp(SITE.ein))).toBeInTheDocument()
})
it('has proper accessibility structure', () => {
render(<Footer />)
const footer = screen.getByRole('contentinfo')
expect(footer).toBeInTheDocument()
const headings = screen.getAllByRole('heading', { level: 3 })
expect(headings).toHaveLength(2) // "Get Involved" and "Organization"
expect(screen.getByRole('contentinfo')).toBeInTheDocument()
expect(screen.getAllByRole('heading', { level: 3 })).toHaveLength(2)
})
})
})
+18 -44
View File
@@ -4,10 +4,9 @@ import { screen, fireEvent } from '@testing-library/dom'
import '@testing-library/jest-dom'
import { Navigation } from '../Navigation'
// Mock the UI components
vi.mock('../ui', () => ({
LogoMark: () => <div data-testid="logo-mark">Logo</div>,
Magnetic: ({ children }: { children: React.ReactNode }) => <div>{children}</div>
Magnetic: ({ children }: { children: React.ReactNode }) => <div>{children}</div>,
}))
describe('Navigation Component', () => {
@@ -15,7 +14,7 @@ describe('Navigation Component', () => {
darkMode: false,
setDarkMode: vi.fn(),
mobileMenuOpen: false,
setMobileMenuOpen: vi.fn()
setMobileMenuOpen: vi.fn(),
}
beforeEach(() => {
@@ -26,64 +25,39 @@ describe('Navigation Component', () => {
render(<Navigation {...mockProps} />)
expect(screen.getByTestId('logo-mark')).toBeInTheDocument()
expect(
screen.getByLabelText('Miracles in Motion Foundation — Home')
).toBeInTheDocument()
expect(screen.getByText('Essentials for every student')).toHaveClass('sr-only')
expect(screen.getByLabelText('Miracles in Motion Foundation — Home')).toBeInTheDocument()
})
it('renders desktop navigation links', () => {
it('renders primary navigation links', () => {
render(<Navigation {...mockProps} />)
expect(screen.getByLabelText('Read success stories')).toBeInTheDocument()
expect(screen.getByLabelText('View testimonies')).toBeInTheDocument()
expect(screen.getByLabelText('About us')).toBeInTheDocument()
expect(screen.getByLabelText('Our programs and services')).toBeInTheDocument()
expect(screen.getByLabelText('Stories of hope')).toBeInTheDocument()
expect(screen.getByLabelText('Community events')).toBeInTheDocument()
expect(screen.getByLabelText('Volunteer opportunities')).toBeInTheDocument()
expect(screen.getByLabelText('Corporate partnerships')).toBeInTheDocument()
expect(screen.getByLabelText('Request assistance')).toBeInTheDocument()
expect(screen.getByLabelText('Portal login')).toBeInTheDocument()
expect(screen.getByLabelText('Contact us')).toBeInTheDocument()
})
it('toggles dark mode when button is clicked', () => {
render(<Navigation {...mockProps} />)
const darkModeButtons = screen.getAllByLabelText('Switch to dark mode')
fireEvent.click(darkModeButtons[0])
fireEvent.click(screen.getAllByLabelText('Switch to dark mode')[0])
expect(mockProps.setDarkMode).toHaveBeenCalledWith(true)
})
it('toggles mobile menu when hamburger button is clicked', () => {
render(<Navigation {...mockProps} />)
const mobileMenuButton = screen.getByLabelText('Open navigation menu')
fireEvent.click(mobileMenuButton)
fireEvent.click(screen.getByLabelText('Open navigation menu'))
expect(mockProps.setMobileMenuOpen).toHaveBeenCalledWith(true)
})
it('displays mobile menu when mobileMenuOpen is true', () => {
render(<Navigation {...mockProps} mobileMenuOpen={true} />)
const storiesLinks = screen.getAllByText('Stories')
expect(storiesLinks).toHaveLength(2) // One in desktop nav, one in mobile nav
expect(screen.getByText('Testimonies')).toBeInTheDocument()
expect(screen.getByText('Volunteers')).toBeInTheDocument()
})
it('handles keyboard navigation correctly', () => {
render(<Navigation {...mockProps} />)
const darkModeButton = screen.getAllByLabelText('Switch to dark mode')[0]
fireEvent.keyDown(darkModeButton, { key: 'Enter', code: 'Enter' })
expect(mockProps.setDarkMode).toHaveBeenCalledWith(true)
expect(screen.getAllByText('Stories').length).toBeGreaterThanOrEqual(1)
expect(screen.getByText('Events')).toBeInTheDocument()
expect(screen.getByText('Contact')).toBeInTheDocument()
})
it('displays correct icon based on dark mode state', () => {
const { rerender } = render(<Navigation {...mockProps} darkMode={false} />)
expect(screen.getAllByLabelText('Switch to dark mode')).toHaveLength(2)
rerender(<Navigation {...mockProps} darkMode={true} />)
expect(screen.getAllByLabelText('Switch to light mode')).toHaveLength(2)
})
})
})
+41
View File
@@ -0,0 +1,41 @@
import { Heart } from 'lucide-react'
import { INTRO, POPULATIONS_SERVED, SITE } from '../../content/siteContent'
export function WhoWeServe() {
return (
<section className="relative py-20 mim-warm-section">
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
<div className="section-header mx-auto max-w-3xl text-center">
<div className="section-eyebrow">{SITE.tagline}</div>
<h2 className="section-title">Hope for those who need it most</h2>
<p className="section-subtitle">{INTRO.lead}</p>
</div>
<p className="mx-auto mt-6 max-w-3xl text-center text-neutral-700 dark:text-neutral-300">
{INTRO.belief}
</p>
<div className="mt-12 grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
{POPULATIONS_SERVED.map((item) => (
<div
key={item}
className="flex items-start gap-3 rounded-2xl border border-secondary-200/50 bg-white/80 p-4 shadow-sm dark:border-white/10 dark:bg-white/5"
>
<Heart
className="mt-0.5 h-5 w-5 shrink-0 text-secondary-500"
aria-hidden
/>
<span className="text-sm leading-relaxed text-neutral-800 dark:text-neutral-200">
{item}
</span>
</div>
))}
</div>
<p className="mx-auto mt-10 max-w-2xl text-center text-sm text-neutral-600 dark:text-neutral-400">
{INTRO.scope}
</p>
</div>
</section>
)
}
+115
View File
@@ -0,0 +1,115 @@
/** Client-approved copy and contact — single source of truth for the public site. */
export const SITE = {
name: 'Miracles in Motion Foundation',
shortName: 'Miracles in Motion',
tagline: 'Faith • Hope • Community • Restoration',
brandMessage: 'Restoring hope through compassion, community, and faith.',
email: '[email protected]',
emailHref: 'mailto:[email protected]',
ein: '33-4887159',
legalStatus: 'California Nonprofit Public Benefit Corporation',
serviceArea:
'Serving Los Angeles County with a vision to expand throughout California and beyond.',
closingLine: 'Because miracles still happen every day.',
} as const
export const NAV_LINKS = [
{ href: '#/about', label: 'About', ariaLabel: 'About us' },
{ href: '#/what-we-do', label: 'What We Do', ariaLabel: 'Our programs and services' },
{ href: '#/stories', label: 'Stories', ariaLabel: 'Stories of hope' },
{ href: '#/events', label: 'Events', ariaLabel: 'Community events' },
{ href: '#/volunteers', label: 'Volunteer', ariaLabel: 'Volunteer opportunities' },
{ href: '#/contact', label: 'Contact', ariaLabel: 'Contact us' },
] as const
export const INTRO = {
lead:
'Miracles in Motion Foundation was created to bring hope, compassion, and support to individuals and families facing lifes most difficult moments.',
body:
'Founded through lived experience, resilience, and faith, our mission is rooted in helping those who feel unheard, overlooked, or alone during times of crisis and hardship.',
belief:
'At Miracles in Motion Foundation, we believe healing begins when people feel seen, valued, and supported.',
scope:
'Our organization focuses on community outreach, emergency assistance, wellness support, advocacy, resource navigation, and compassionate care for vulnerable populations throughout Los Angeles County — with a vision of expanding our impact across California and beyond.',
restoration:
'We believe that even during the hardest seasons of life, restoration is possible.',
} as const
export const POPULATIONS_SERVED = [
'Women and single mothers',
'Teen mothers and youth',
'Families in crisis',
'Survivors of domestic violence',
'Individuals experiencing homelessness',
'Families affected by disasters and fire emergencies',
'Underserved communities needing hope, guidance, and support',
] as const
export const MISSION = {
statement:
'Our mission is to restore hope, provide compassionate support, and empower individuals and families facing crisis, hardship, trauma, and instability through community outreach, advocacy, emergency assistance, and life-changing resources.',
dedication:
'We are dedicated to serving vulnerable populations with dignity, empathy, and faith while helping create pathways toward healing, stability, and restoration.',
} as const
export const WHY_WE_STARTED = {
lead:
'Miracles in Motion Foundation was born from real-life experiences with hardship, survival, rebuilding, and faith.',
body:
'We understand the emotional weight families carry during times of crisis — whether facing homelessness, domestic violence, disaster recovery, financial instability, or personal struggles that leave people feeling hopeless and alone.',
reminder: 'This foundation was built to remind people that they matter.',
goal:
'Our goal is not only to provide resources, but to restore dignity, hope, human connection, and the belief that brighter days are still ahead.',
} as const
export const VISION = {
lead:
'We envision a future where individuals and families facing hardship are met with compassion instead of judgment, support instead of silence, and hope instead of despair.',
body:
'Our vision is to build stronger communities where healing, restoration, and opportunity are accessible to everyone.',
} as const
export const WHAT_WE_DO = [
{
title: 'Community Outreach',
body: 'Providing direct support and outreach to underserved individuals and families in need.',
},
{
title: 'Crisis & Fire Relief Support',
body: 'Helping families impacted by emergencies, displacement, natural disasters, and fire-related hardships.',
},
{
title: 'Support for Women & Families',
body: 'Offering guidance, resources, and compassionate support for mothers, children, and families navigating difficult life situations.',
},
{
title: 'Homelessness Support & Resource Navigation',
body: 'Connecting individuals and families with resources, referrals, and supportive services.',
},
{
title: 'Domestic Violence Advocacy',
body: 'Supporting survivors with compassion, encouragement, and access to community resources.',
},
{
title: 'Youth & Teen Mother Support',
body: 'Empowering young mothers and youth through mentorship, encouragement, and community support.',
},
] as const
export const STORIES_OF_HOPE = {
lead:
'At Miracles in Motion Foundation, every outreach event, every family served, and every act of kindness represents a story of hope.',
body:
'From supporting families during difficult seasons to providing resources during times of crisis, we believe real change happens when communities come together with compassion and purpose.',
closing:
'This is more than a nonprofit organization — it is a movement built on faith, resilience, and the belief that lives can be transformed through love and support.',
} as const
export const EVENTS = {
lead:
'Community events are where compassion meets action — outreach gatherings, resource fairs, and seasonal support drives throughout Los Angeles County.',
body:
'Check back for upcoming dates, or contact us to partner on an outreach event or volunteer day.',
ctaVolunteer: '#/volunteers',
ctaContact: '#/contact',
} as const
+33
View File
@@ -18,6 +18,9 @@
--mim-brand-green-mid: #2d6b5c;
--mim-brand-gold: #c5a059;
--mim-brand-gold-bright: #d4af37;
--mim-cream: #faf8f5;
--mim-warm-beige: #f5f0e8;
--mim-warm-white: #fffefb;
--mim-focus-ring: var(--mim-brand-gold);
--mim-shadow-brand: rgba(26, 60, 52, 0.28);
--mim-shadow-gold: rgba(197, 160, 89, 0.32);
@@ -49,6 +52,36 @@
body {
font-family: "Inter", ui-sans-serif, system-ui, sans-serif;
font-feature-settings: 'rlig' 1, 'calt' 1;
background-color: var(--mim-cream);
background-image: linear-gradient(
180deg,
var(--mim-warm-white) 0%,
var(--mim-cream) 40%,
var(--mim-warm-beige) 100%
);
background-attachment: fixed;
}
.dark body,
body.dark {
background: #0a0f0e;
background-image: none;
}
.mim-warm-section {
background: linear-gradient(
180deg,
rgba(250, 248, 245, 0.6) 0%,
rgba(245, 240, 232, 0.9) 100%
);
}
.dark .mim-warm-section {
background: transparent;
}
.foundation-page .section-title {
font-family: "Playfair Display", Georgia, serif;
}
::-webkit-scrollbar {
+2 -2
View File
@@ -55,8 +55,8 @@ export function BrandAssetsPage() {
</li>
<li>
Questions:{' '}
<a className="underline" href="mailto:contact@mim4u.org">
contact@mim4u.org
<a className="underline" href="mailto:info@faithforwardmiracles.org">
info@faithforwardmiracles.org
</a>
</li>
</ul>
+1 -1
View File
@@ -362,7 +362,7 @@ const TrustBadges: React.FC = () => (
<div className="mt-6 pt-4 border-t border-gray-200 dark:border-gray-700">
<p className="text-xs text-gray-500">
EIN: 12-3456789 All donations are tax-deductible to the fullest extent allowed by law.
EIN: 33-4887159 All donations are tax-deductible to the fullest extent allowed by law.
</p>
</div>
</Card>
+233
View File
@@ -0,0 +1,233 @@
import type { ReactNode } from 'react'
import { ArrowRight, Calendar, Heart, Mail, MapPin, Users } from 'lucide-react'
import {
EVENTS,
INTRO,
MISSION,
POPULATIONS_SERVED,
SITE,
STORIES_OF_HOPE,
VISION,
WHAT_WE_DO,
WHY_WE_STARTED,
} from '../../content/siteContent'
function PageIntro({
eyebrow,
title,
children,
}: {
eyebrow: string
title: string
children: ReactNode
}) {
return (
<div className="foundation-page mx-auto max-w-4xl px-4 py-12 sm:px-6 lg:px-8">
<p className="section-eyebrow">{eyebrow}</p>
<h1 className="section-title mt-2">{title}</h1>
<div className="mt-6 space-y-4 text-base leading-relaxed text-neutral-700 dark:text-neutral-300">
{children}
</div>
</div>
)
}
function ContentCard({ title, children }: { title: string; children: ReactNode }) {
return (
<section className="card">
<h2 className="font-serif text-xl font-semibold tracking-tight text-primary-800 dark:text-primary-100">
{title}
</h2>
<div className="mt-3 space-y-3 text-sm leading-relaxed text-neutral-700 dark:text-neutral-300">
{children}
</div>
</section>
)
}
export function AboutPage() {
return (
<div className="pb-16">
<PageIntro eyebrow={SITE.tagline} title="About Us">
<p className="text-lg font-medium text-primary-800 dark:text-primary-100">{SITE.brandMessage}</p>
<p>{INTRO.lead}</p>
<p>{INTRO.body}</p>
<p>{INTRO.belief}</p>
<p>{INTRO.scope}</p>
<p className="font-medium italic text-primary-700 dark:text-secondary-300">{INTRO.restoration}</p>
<p className="text-secondary-700 dark:text-secondary-400">{SITE.closingLine}</p>
</PageIntro>
<div className="mx-auto max-w-4xl space-y-6 px-4 sm:px-6 lg:px-8">
<ContentCard title="Who we serve">
<ul className="list-disc space-y-2 pl-5">
{POPULATIONS_SERVED.map((item) => (
<li key={item}>{item}</li>
))}
</ul>
</ContentCard>
<ContentCard title="Why we started">
<p>{WHY_WE_STARTED.lead}</p>
<p>{WHY_WE_STARTED.body}</p>
<p className="font-medium">{WHY_WE_STARTED.reminder}</p>
<p>{WHY_WE_STARTED.goal}</p>
</ContentCard>
<div className="flex flex-wrap gap-3">
<a href="#/mission" className="btn-primary">
Our mission <ArrowRight className="ml-1 h-4 w-4" />
</a>
<a href="#/what-we-do" className="btn-secondary">
What we do
</a>
</div>
</div>
</div>
)
}
export function MissionPage() {
return (
<div className="pb-16" id="mission">
<PageIntro eyebrow="Our purpose" title="Our Mission">
<p>{MISSION.statement}</p>
<p>{MISSION.dedication}</p>
</PageIntro>
<div className="mx-auto max-w-4xl space-y-6 px-4 sm:px-6 lg:px-8">
<ContentCard title="Our vision">
<p>{VISION.lead}</p>
<p>{VISION.body}</p>
</ContentCard>
<a href="#/donate" className="btn-primary inline-flex">
<Heart className="mr-2 h-4 w-4" /> Support our mission
</a>
</div>
</div>
)
}
export function WhatWeDoPage() {
return (
<div className="pb-16">
<PageIntro eyebrow="Programs & services" title="What We Do">
<p>
Compassionate, practical support for vulnerable individuals and families from outreach and
advocacy to emergency relief and resource navigation.
</p>
</PageIntro>
<div className="mx-auto grid max-w-4xl gap-6 px-4 sm:px-6 sm:grid-cols-2 lg:px-8">
{WHAT_WE_DO.map((item) => (
<article key={item.title} className="card card-hover">
<h2 className="font-semibold tracking-tight text-primary-800 dark:text-primary-100">
{item.title}
</h2>
<p className="mt-2 text-sm leading-relaxed text-neutral-700 dark:text-neutral-300">
{item.body}
</p>
</article>
))}
</div>
<div className="mx-auto mt-10 max-w-4xl px-4 text-center sm:px-6 lg:px-8">
<a href="#/request-assistance" className="btn-secondary mr-3">
Request assistance
</a>
<a href="#/volunteers" className="btn-primary">
<Users className="mr-2 inline h-4 w-4" /> Volunteer
</a>
</div>
</div>
)
}
export function EventsPage() {
return (
<div className="pb-16">
<PageIntro eyebrow="Community" title="Community Events">
<p>{EVENTS.lead}</p>
<p>{EVENTS.body}</p>
</PageIntro>
<div className="mx-auto max-w-4xl px-4 sm:px-6 lg:px-8">
<div className="card flex flex-col items-center gap-4 py-12 text-center">
<Calendar className="h-12 w-12 text-secondary-500" aria-hidden />
<p className="max-w-md text-sm text-neutral-600 dark:text-neutral-400">
Event listings will be posted here as dates are confirmed. We welcome volunteers and
community partners.
</p>
<div className="flex flex-wrap justify-center gap-3">
<a href={EVENTS.ctaVolunteer} className="btn-primary">
Volunteer
</a>
<a href={EVENTS.ctaContact} className="btn-secondary">
Contact us
</a>
</div>
</div>
</div>
</div>
)
}
export function ContactPage() {
return (
<div className="pb-16">
<PageIntro eyebrow="Reach out" title="Contact Us">
<p>
We would love to hear from you whether you need support, want to volunteer, or hope to
partner with our foundation.
</p>
</PageIntro>
<div className="mx-auto max-w-4xl space-y-6 px-4 sm:px-6 lg:px-8">
<div className="card space-y-4">
<div className="flex items-start gap-3">
<Mail className="mt-0.5 h-5 w-5 shrink-0 text-primary-600 dark:text-secondary-400" />
<div>
<div className="font-medium">Email</div>
<a className="text-primary-700 underline dark:text-secondary-300" href={SITE.emailHref}>
{SITE.email}
</a>
</div>
</div>
<div className="flex items-start gap-3">
<MapPin className="mt-0.5 h-5 w-5 shrink-0 text-primary-600 dark:text-secondary-400" />
<div>
<div className="font-medium">Service area</div>
<p className="text-sm text-neutral-700 dark:text-neutral-300">{SITE.serviceArea}</p>
</div>
</div>
</div>
<div className="flex flex-wrap gap-3">
<a href={SITE.emailHref} className="btn-primary">
<Mail className="mr-2 h-4 w-4" /> Send email
</a>
<a href="#/request-assistance" className="btn-secondary">
Request assistance
</a>
<a href="#/donate" className="btn-secondary">
Donate
</a>
</div>
<p className="text-center text-xs text-neutral-500 dark:text-neutral-400">
{SITE.name} · {SITE.legalStatus} · EIN {SITE.ein}
</p>
</div>
</div>
)
}
export function StoriesIntroBlock() {
return (
<div className="card mb-8 border-secondary-200/60 bg-secondary-50/40 dark:border-secondary-800/40 dark:bg-secondary-900/20">
<p>{STORIES_OF_HOPE.lead}</p>
<p className="mt-3">{STORIES_OF_HOPE.body}</p>
<p className="mt-3 italic text-primary-800 dark:text-primary-100">{STORIES_OF_HOPE.closing}</p>
</div>
)
}
+8
View File
@@ -0,0 +1,8 @@
export {
AboutPage,
ContactPage,
EventsPage,
MissionPage,
StoriesIntroBlock,
WhatWeDoPage,
} from './FoundationPages'