Compare commits

..

13 Commits

Author SHA1 Message Date
99f92eaa7b feat: dark-mode styling across pages (about, events, members, orphanage, contact, gallery); adjust cards, headings, copy colors 2025-08-08 23:41:53 +02:00
0f86f8f615 style: increase light-mode nav text contrast (text-gray-900), adjust borders/shadow; mobile/desktop parity 2025-08-08 23:35:49 +02:00
725a3e8e3a style: header/menu dark-mode styles (desktop/mobile), subtle border/backdrop; improved link colors for dark 2025-08-08 23:33:38 +02:00
ba9bb6dfe0 feat: homepage dark-mode styling (body dark bg/text, cards/badges/headers), fix SVG attrs; type fixes in HomeGallery 2025-08-08 23:31:24 +02:00
c8c550a00b feat: site-wide dark mode (Tailwind class strategy); ThemeToggle island in header; persist preference; adjust brand-surface for dark 2025-08-08 23:26:13 +02:00
a0ab66189a style: modernize headers for About/Events/Members/Orphanage/Contact/Gallery using brand-surface; simplify copy; fix date sort; unify CTA 2025-08-08 23:21:55 +02:00
3c74d71e22 docs: add ACCESSIBILITY_AUDIT, SECURITY_PRIVACY_AUDIT, PRODUCT_BRIEF with file-specific actions; a11y: add skip link, lang+hreflang, ARIA for menu/carousel/dialog/form; noValidate+honeypot 2025-08-08 23:00:09 +02:00
910253c8f4 Renaming home back to index 2025-06-27 22:20:59 +00:00
45fc361eb4 Remove index.astro file: eliminate the homepage layout and associated components, streamlining the project structure. 2025-06-27 23:24:53 +02:00
091324ca51 Refactor event, gallery, and members pages: replace Astro.glob with import.meta.glob for eager loading of content, ensuring better performance and handling of optional chaining for frontmatter properties. 2025-06-27 23:18:07 +02:00
31e72ecfce Fix typo in About Us section: added missing period for improved readability. 2025-06-27 23:08:25 +02:00
1656b95a33 Update Tailwind CSS configuration: adjust plugins array formatting for consistency. 2025-06-27 22:53:27 +02:00
9f6fa46227 Refactor project structure: update Astro configuration, integrate Tailwind CSS, enhance ContactForm with validation, and improve layout for various pages. Add new Donate and Orphanage pages, and implement responsive design adjustments across components. 2025-06-27 22:49:11 +02:00
34 changed files with 4251 additions and 5041 deletions

148
ACCESSIBILITY_AUDIT.md Normal file
View File

@@ -0,0 +1,148 @@
### Omoluabi Accessibility Audit (WCAG 2.2 AA)
Scope: Current Astro site as of this commit. Focus on perceivable, operable, understandable, and robust criteria for Nigerians in NL and Dutch partners.
---
### Executive summary
- **Overall**: Solid semantic base with clear landmarks in `src/layouts/BaseLayout.astro`. Reduced-motion support exists in `src/styles/global.css`. Key gaps: language/i18n markup, skip links, menu ARIA, carousel semantics, form error/ARIA, dialog semantics, and strict CSP readiness.
- **Risk**: Medium → High for navigation/keyboard and language; Low → Medium for contrast on image/gradient backgrounds.
---
### High-priority issues (fix now)
1) Missing skip link + focus target
- File: `src/layouts/BaseLayout.astro`
- Snippet (add just inside `<body>` and set `id` on `<main>`):
```astro
<a href="#main" class="sr-only focus:not-sr-only focus:fixed focus:top-2 focus:left-2 focus:z-50 focus:bg-white focus:text-black focus:px-3 focus:py-2 focus:rounded">
Skip to main content
</a>
...
<main id="main" tabindex="-1">
<slot />
</main>
```
- Rationale: Allows keyboard users to bypass repeated navigation (WCAG 2.4.1, 2.4.3).
2) Page language + `hreflang`
- File: `src/layouts/BaseLayout.astro`
- Snippet (top `<html>` and `<head>`):
```astro
<html lang={Astro.props.lang ?? 'en'}>
<head>
...
<link rel="alternate" hrefLang="en" href="/en/" />
<link rel="alternate" hrefLang="nl" href="/nl/" />
<link rel="alternate" hrefLang="x-default" href="/" />
```
- Rationale: Correct language for screen readers and localized SEO (WCAG 3.1.1, 3.1.2).
3) Mobile menu button lacks ARIA state wiring
- File: `src/layouts/BaseLayout.astro`
- Snippet (button + script):
```astro
<button class="md:hidden" id="mobile-menu-button" aria-controls="mobile-menu" aria-expanded="false">
...
</button>
```
```html
<script>
document.addEventListener('DOMContentLoaded', () => {
const mobileMenuButton = document.getElementById('mobile-menu-button');
const mobileMenu = document.getElementById('mobile-menu');
if (mobileMenuButton && mobileMenu) {
mobileMenuButton.addEventListener('click', () => {
const isHidden = mobileMenu.classList.toggle('hidden');
mobileMenuButton.setAttribute('aria-expanded', String(!isHidden));
});
}
});
</script>
```
- Rationale: Communicates expanded/collapsed state for assistive tech (WCAG 4.1.2).
4) Carousel semantics and controls
- File: `src/components/HeroCarousel.jsx`
- Snippet:
```jsx
<div
className="relative w-full max-w-6xl mx-auto rounded-2xl overflow-hidden shadow-2xl bg-white"
role="region"
aria-roledescription="carousel"
aria-label="Featured content"
>
{slides.map((slide, index) => (
<div
key={index}
role="group"
aria-roledescription="slide"
aria-label={`${index + 1} of ${slides.length}`}
className={...}
>
...
</div>
))}
<button aria-pressed={!isPlaying} aria-label={isPlaying ? 'Pause slideshow' : 'Play slideshow'}>...</button>
</div>
```
- Rationale: Conveys carousel/slide semantics; exposes play/pause state (WCAG 1.4.2, 2.2.2, 4.1.2).
5) Contact form ARIA and honeypot
- File: `src/components/ContactForm.jsx`
- Snippet:
```jsx
const [hp, setHp] = useState('');
...
<form onSubmit={handleSubmit} noValidate ...>
<div className="hidden" aria-hidden="true">
<label htmlFor="website">Website</label>
<input id="website" name="website" value={hp} onChange={(e)=>setHp(e.target.value)} tabIndex={-1} autoComplete="off" />
</div>
<input aria-invalid={Boolean(errors.name)} aria-describedby={errors.name ? 'name-error' : undefined} ... />
{errors.name && <p id="name-error" className="...">{errors.name}</p>}
```
- Rationale: Accessible errors association and simple anti-bot (WCAG 3.3.1/3.3.3).
6) Lightbox dialog semantics
- File: `src/components/Lightbox.jsx`
- Snippet:
```jsx
<div
className="fixed inset-0 ..."
role="dialog"
aria-modal="true"
aria-label="Image viewer"
onClick={onClose}
>
```
- Rationale: Dialog semantics and modality (WCAG 1.3.1, 2.4.3, 4.1.2).
7) Inline styles and data-URI backgrounds limit strict CSP
- Files: `src/pages/about.astro`, `src/pages/donate.astro`, `src/pages/orphanage.astro`
- Fix: Extract inline `style="background: ..."` to named CSS classes in `src/styles/main.css` (e.g., `.bg-flag-nl-ng`, `.pattern-overlay`) and reference via `class` only. Move inline `<script>` in layout to a module file and import with `type="module"` and `nonce`.
- Rationale: Enables strict non-`unsafe-inline` CSP (security and robustness).
---
### Medium-priority issues
- **Contrast over imagery/gradients**: Ensure minimum overlay like `bg-black/60` behind text; avoid fully transparent gradient text for body copy. Files: `src/pages/index.astro`, `src/pages/about.astro`, `HeroCarousel.jsx`.
- **Focus visibility baseline**: Add base `:focus-visible` style in `src/styles/global.css` to ensure consistent visible focus.
- **Image dimensions**: Add `width`/`height` on `<img>` where known to prevent CLS.
---
### Suggested global utilities
- File: `src/styles/global.css`
```css
:focus-visible { outline: 2px solid var(--nigerian-green); outline-offset: 2px; }
[role="button"], a, button, input, select, textarea { -webkit-tap-highlight-color: transparent; }
```
---
### Verification plan (to add in CI)
- Playwright + `@axe-core/playwright`: nav landmarks, skip link focus, keyboard-only menu, form labels/errors, dialog semantics.
- Lighthouse budgets: LCP < 2.0s, CLS < 0.05, TTI < 3.5s; run on PR and fail if exceeded.
- Spot-check color contrast with axe; prohibit text over images without overlay.

42
PRODUCT_BRIEF.md Normal file
View File

@@ -0,0 +1,42 @@
## Product Brief — Omoluabi (NL)
### Audience
- Nigerians living in the Netherlands (families, youth, professionals)
- Dutch institutions and partners
- Donors and volunteers
### Objectives
- Community growth and engagement (events, programs, volunteering)
- Cultural education and representation
- Fundraising for programs and orphanage
- Trust through accessibility, privacy, and transparency
### KPIs / Success metrics
- Monthly active visitors (MAU) and returning visitors
- Event registrations and attendance rate
- Volunteer sign-ups and inquiries
- Donations volume via iDEAL/cards (Mollie)
- Newsletter subscriptions (double opt-in)
- Accessibility: axe violations = 0 on core templates; Lighthouse: LCP < 2.0s, CLS < 0.05
### Value proposition
A fast, inclusive, bilingual (EN/NL) hub connecting the Nigerian diaspora and Dutch partners, showcasing culture, programs, and ways to contributebuilt privacy-first and accessible by default.
---
### Gap report (current site)
- **Internationalization**: No locale-aware routing or page `lang`; no language switcher. Impact: accessibility, SEO, Dutch partners.
- **Accessibility**: Missing skip links; inconsistent focus; carousel lacks semantics; form errors lack ARIA; dialog lacks `role="dialog"`. Impact: keyboard and screen reader users.
- **Security/Privacy**: Google Fonts import; inline scripts/styles block strict CSP; no headers/CSP; forms not server-validated; no anti-abuse. Impact: GDPR risk and security posture.
- **Donations**: UI-only progress bar, no payments backend; no iDEAL/cards. Impact: fundraising.
- **Analytics**: None; decision pending (Plausible/Matomo). Impact: insight and optimization.
- **Content model**: Content lives in Markdown ad-hoc; lacks structured collections for posts/programs/team/partners; no Zod schemas.
- **Images/Performance**: Static `<img>` without `width/height` and `<picture>`; risky contrast over images; potential CLS.
---
### Prioritized roadmap (Now/Next/Later)
- **Now (this sprint)**: Implement headers/CSP-ready refactors, a11y fixes (skip link, menu ARIA, carousel/dialog semantics, focus baseline), self-host fonts, scaffold content collections with Zod, propose IA and i18n routing.
- **Next**: Implement i18n routes (`/en/`, `/nl/`), language switcher, interactive events calendar with filters and ICS export, server forms (contact/volunteer/partner), Plausible EU.
- **Later**: Mollie donation flow, Leaflet map for events/partners, PWA, program directory, newsletter double opt-in, Lighthouse/axe CI.

121
SECURITY_PRIVACY_AUDIT.md Normal file
View File

@@ -0,0 +1,121 @@
### Security & Privacy Audit (EU/GDPR)
Scope: Current Astro site; no server endpoints yet; React islands used. Aim: strict security headers, EU analytics, consent only if needed, secrets hygiene, safe forms, and payment integration readiness.
---
### Executive summary
- **Strengths**: Static-first Astro; no server auth; minimal third parties.
- **Gaps**: External Google Fonts (tracking and CSP issues), inline scripts/styles, no security headers configured, forms lack server validation/rate-limiting/CSRF, no cookie/consent model, no analytics choice, donation flow not integrated with EU processor.
---
### Action checklist (priority)
1) Remove Google Fonts; self-host Inter variable
- File: `src/styles/global.css`
- Replace `@import` from Google with self-hosted font. Steps:
- Add `public/fonts/inter/Inter-Variable.woff2`.
- Add to `src/styles/global.css`:
```css
@font-face {
font-family: 'Inter';
src: url('/fonts/inter/Inter-Variable.woff2') format('woff2-variations');
font-weight: 100 900; font-style: normal; font-display: swap;
}
```
- Rationale: Privacy, performance, CSP friendliness.
2) Security headers
- Option A: Static hosting `_headers` (e.g., Netlify/Vercel):
```text
/*
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: geolocation=(), microphone=(), camera=(), payment=()
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp; report-to="default"
Cross-Origin-Resource-Policy: same-origin
Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-PLACEHOLDER'; style-src 'self' 'nonce-PLACEHOLDER'; img-src 'self' data:; font-src 'self' data:; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self'
```
- Option B: Nginx snippet (`nginx.conf.example`):
```nginx
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header X-Content-Type-Options nosniff;
add_header Referrer-Policy "strict-origin-when-cross-origin";
add_header Permissions-Policy "geolocation=(), microphone=(), camera=(), payment=()";
add_header Cross-Origin-Opener-Policy "same-origin";
add_header Cross-Origin-Embedder-Policy "require-corp";
add_header Cross-Origin-Resource-Policy "same-origin";
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'nonce-$request_id'; style-src 'self' 'nonce-$request_id'; img-src 'self' data:; font-src 'self' data:; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self'";
```
- Rationale: Baseline browser protections; strict CSP with nonces for inline modules.
3) Inline → external scripts/styles to satisfy CSP
- Files: `src/layouts/BaseLayout.astro` (inline `<script>`), several pages with inline `style="background..."`.
- Fix: Move JS to `src/scripts/navigation.ts` and import with `<script type="module" src="/scripts/navigation.js" nonce={Astro.props.nonce} />`; extract inline styles into classes in `src/styles/main.css`.
4) Forms: server validation, CSRF, rate-limit, honeypot
- Add endpoint example: `src/pages/api/contact.ts`
```ts
import type { APIRoute } from 'astro';
import { z } from 'zod';
const ContactSchema = z.object({
name: z.string().min(1),
email: z.string().email(),
subject: z.string().min(1),
message: z.string().min(1),
website: z.string().max(0).optional(), // honeypot
});
export const POST: APIRoute = async ({ request }) => {
try {
const data = await request.json();
const parsed = ContactSchema.safeParse(data);
if (!parsed.success) return new Response(JSON.stringify({ ok:false }), { status: 400 });
// TODO: rate-limit via IP + UA (e.g., in-memory or KV), CSRF via double-submit token header
// TODO: send via Postmark/Resend EU region
return new Response(JSON.stringify({ ok:true }), { status: 200 });
} catch {
return new Response(JSON.stringify({ ok:false }), { status: 400 });
}
};
```
- Rationale: GDPR-friendly collection, safe error responses, anti-abuse measures.
5) Payments: Mollie integration plan
- Use server-only handlers for payment creation and webhook signature verification. Store nothing beyond required payment IDs; no card data. Configure allowlisted endpoints in CSP `connect-src` for Mollie API only when enabled.
6) Analytics: Plausible (EU) or Matomo (self-host)
- Recommendation: **Plausible EU** with cookieless, events limited to pageview + donate/volunteer conversions. If consent model needed later, implement prior to enabling cookies.
7) Secrets and environment hygiene
- Use `import.meta.env` and never expose secrets without `*_PUBLIC` prefix. Add `.env.example`:
```env
PUBLIC_SITE_URL=
NODE_ENV=development
# Analytics
PUBLIC_PLAUSIBLE_DOMAIN=
PUBLIC_PLAUSIBLE_SRC=
# Payments (server-only)
MOLLIE_API_KEY=
MOLLIE_WEBHOOK_SECRET=
# Email provider
POSTMARK_TOKEN=
```
8) Logging and retention
- Adopt structured logs without PII; error IDs returned to client; retain logs 3090 days; no access logs with IP persisted beyond ops needs; document in Privacy Policy.
9) DPIA-lite
- Data categories: contact form (identifiers and message body), newsletter (email), donation (processor-hosted, no card data). Lawful basis: consent/legitimate interest. No special category data processed. Document processor agreements (Plausible EU, Postmark EU region, Mollie EU).
---
### Next steps
- Implement headers and CSP; refactor inline code.
- Add API routes with Zod and anti-abuse; wire contact form to server.
- Choose analytics (Plausible EU) and configure opt-in text in footer.
- Prepare Mollie sandbox integration and webhook.

View File

@@ -1,11 +1,13 @@
// @ts-check // astro.config.mjs
import { defineConfig } from 'astro/config'; import { defineConfig } from 'astro/config';
import tailwind from '@astrojs/tailwind';
import react from '@astrojs/react';
import tailwindcss from '@tailwindcss/vite';
// https://astro.build/config
export default defineConfig({ export default defineConfig({
vite: { integrations: [
plugins: [tailwindcss()] react(),
} tailwind({
applyBaseStyles: false, // Prevents conflicts with custom styles
})
],
}); });

1905
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -9,9 +9,17 @@
"astro": "astro" "astro": "astro"
}, },
"dependencies": { "dependencies": {
"@astrojs/react": "^4.3.0",
"@tailwindcss/vite": "^4.1.10", "@tailwindcss/vite": "^4.1.10",
"astro": "^5.9.4", "@types/react": "^19.1.8",
"daisyui": "^5.0.43", "@types/react-dom": "^19.1.6",
"tailwindcss": "^4.1.10" "astro": "^5.12.9",
"keen-slider": "^6.8.6",
"react": "^19.1.0",
"react-dom": "^19.1.0",
"tailwindcss": "^3.4.17"
},
"devDependencies": {
"@astrojs/tailwind": "^6.0.2"
} }
} }

View File

@@ -1,57 +0,0 @@
---
import '../styles/main.css';
// About section for homepage
---
<section class="section about-section">
<div class="container">
<div class="about-grid">
<div class="about-image">
<div class="about-image-frame"></div>
<div class="about-image-container">
<img src="/images/whoAreWe.webp" alt="About Omoluabi Association" />
</div>
</div>
<div class="about-content">
<h2 style="font-family: 'Poppins', sans-serif; font-size: 2.5rem; font-weight: 700; color: #16a34a; margin: 0;">
<div class="about-line"></div>
About Us
</h2>
<h3 style="font-size: 1.5rem; font-weight: 700; margin-bottom: 1rem; color: #16a34a; display: flex; align-items: center; gap: 0.5rem;">
<span style="font-size: 2rem;">🌟</span>
WHO ARE WE?
</h3>
<div style="color: #374151; line-height: 1.6; margin-bottom: 2rem;">
<p style="font-size: 1.125rem; margin-bottom: 1rem;">
The <strong style="color: #16a34a;">Omoluabi Association</strong> in the Royal Kingdom of The Netherlands (OAN) is a pan-Yoruba Association with well-bred, selective, like-minded individuals of enviable character as our members.
</p>
<p style="margin-bottom: 1rem;">
Our association extends beyond Yorubas or Nigerians only we welcome culturally motivated Netherlanders who share our values and vision for community building.
</p>
<p>
Our association is a non profit, non religious, non partisan, non ethnic and socio cultural organization that focuses on showcasing the Yoruba cultural heritages, norms, values and traditions to the western world, most especially in Holland.
</p>
</div>
<div class="about-stats">
<div class="stat-card">
<div class="stat-number" style="color: #16a34a;">2018</div>
<div class="stat-label">Established</div>
</div>
<div class="stat-card">
<div class="stat-number" style="color: #f59e0b;">500+</div>
<div class="stat-label">Members</div>
</div>
<div class="stat-card">
<div class="stat-number" style="color: #dc2626;">50+</div>
<div class="stat-label">Events</div>
</div>
</div>
<div class="badges">
<span class="badge badge-green">Non-Profit</span>
<span class="badge badge-gold">Cultural Heritage</span>
<span class="badge badge-red">Community Focus</span>
<span class="badge badge-blue">Inclusive</span>
</div>
</div>
</div>
</div>
</section>

View File

@@ -1,61 +0,0 @@
---
// Contact Form Component - Static version
---
<form class="max-w-xl mx-auto bg-base-100 p-8 rounded-xl shadow-lg" id="contactForm" autocomplete="off">
<div class="mb-4">
<label for="name" class="block font-bold mb-1">Name</label>
<input type="text" id="name" name="name" class="input input-bordered w-full" required autocomplete="off" />
</div>
<div class="mb-4">
<label for="email" class="block font-bold mb-1">Email</label>
<input type="email" id="email" name="email" class="input input-bordered w-full" required autocomplete="off" />
</div>
<div class="mb-4">
<label for="subject" class="block font-bold mb-1">Subject</label>
<input type="text" id="subject" name="subject" class="input input-bordered w-full" required autocomplete="off" />
</div>
<div class="mb-4">
<label for="message" class="block font-bold mb-1">Message</label>
<textarea id="message" name="message" class="textarea textarea-bordered w-full" rows="5" required></textarea>
</div>
<!-- Honeypot field for spam protection -->
<div style="display: none;">
<label for="honey">Do not fill this out</label>
<input type="text" id="honey" name="honey" tabindex="-1" autocomplete="off" />
</div>
<button type="submit" class="btn btn-primary w-full">Send Message</button>
<div id="status" class="mt-4 text-center text-sm text-success" style="display: none;"></div>
</form>
<script>
document.addEventListener('DOMContentLoaded', function() {
const form = document.getElementById('contactForm') as HTMLFormElement;
const statusDiv = document.getElementById('status') as HTMLDivElement;
if (!form || !statusDiv) return;
form.addEventListener('submit', async function(e) {
e.preventDefault();
// Honeypot check
const honeyField = form.querySelector('#honey') as HTMLInputElement;
if (honeyField && honeyField.value !== "") {
showStatus("Spam detected.");
return;
}
showStatus("Sending...");
// Placeholder: would POST to /api/contact
setTimeout(() => {
showStatus("Message sent (placeholder, not yet implemented).");
}, 1000);
});
function showStatus(message: string) {
statusDiv.textContent = message;
statusDiv.style.display = 'block';
}
});
</script>

View File

@@ -0,0 +1,147 @@
import React, { useState } from 'react';
export default function ContactForm() {
const [formData, setFormData] = useState({
name: '',
email: '',
subject: '',
message: '',
});
const [errors, setErrors] = useState({});
const [isSubmitting, setIsSubmitting] = useState(false);
const [submitMessage, setSubmitMessage] = useState(null);
const [hp, setHp] = useState('');
const validate = () => {
let newErrors = {};
if (!formData.name) newErrors.name = 'Name is required';
if (!formData.email) {
newErrors.email = 'Email is required';
} else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(formData.email)) {
newErrors.email = 'Invalid email address';
}
if (!formData.subject) newErrors.subject = 'Subject is required';
if (!formData.message) newErrors.message = 'Message is required';
return newErrors;
};
const handleChange = (e) => {
const { name, value } = e.target;
setFormData({ ...formData, [name]: value });
// Clear error for the field as user types
if (errors[name]) {
setErrors({ ...errors, [name]: null });
}
};
const handleSubmit = async (e) => {
e.preventDefault();
setIsSubmitting(true);
setSubmitMessage(null);
const validationErrors = validate();
setErrors(validationErrors);
if (Object.keys(validationErrors).length === 0) {
try {
// Simulate API call
await new Promise(resolve => setTimeout(resolve, 1000));
console.log('Form data submitted:', formData);
setSubmitMessage({ type: 'success', text: 'Your message has been sent successfully!' });
setFormData({ name: '', email: '', subject: '', message: '' }); // Clear form
} catch (error) {
setSubmitMessage({ type: 'error', text: 'There was an error sending your message. Please try again later.' });
} finally {
setIsSubmitting(false);
}
} else {
setIsSubmitting(false);
setSubmitMessage({ type: 'error', text: 'Please correct the errors in the form.' });
}
};
return (
<form onSubmit={handleSubmit} className="bg-white p-8 rounded-xl shadow-lg border border-gray-200 max-w-2xl mx-auto" noValidate>
<div className="hidden" aria-hidden="true">
<label htmlFor="website">Website</label>
<input id="website" name="website" value={hp} onChange={(e)=>setHp(e.target.value)} tabIndex={-1} autoComplete="off" />
</div>
<h2 className="text-3xl font-bold text-center text-nigerian-green-700 mb-8">Send Us a Message</h2>
{submitMessage && (
<div className={`p-4 mb-4 rounded-lg text-center ${submitMessage.type === 'success' ? 'bg-green-100 text-green-700' : 'bg-red-100 text-red-700'}`}>
{submitMessage.text}
</div>
)}
<div className="mb-5">
<label htmlFor="name" className="block text-gray-700 text-sm font-bold mb-2">Name</label>
<input
type="text"
id="name"
name="name"
value={formData.name}
onChange={handleChange}
aria-invalid={Boolean(errors.name)}
aria-describedby={errors.name ? 'name-error' : undefined}
className={`shadow appearance-none border rounded-lg w-full py-3 px-4 text-gray-700 leading-tight focus:outline-none focus:ring-2 focus:ring-nigerian-green-500 ${errors.name ? 'border-red-500' : 'border-gray-300'}`}
placeholder="Your Name"
/>
{errors.name && <p id="name-error" className="text-red-500 text-xs italic mt-2">{errors.name}</p>}
</div>
<div className="mb-5">
<label htmlFor="email" className="block text-gray-700 text-sm font-bold mb-2">Email</label>
<input
type="email"
id="email"
name="email"
value={formData.email}
onChange={handleChange}
className={`shadow appearance-none border rounded-lg w-full py-3 px-4 text-gray-700 leading-tight focus:outline-none focus:ring-2 focus:ring-nigerian-green-500 ${errors.email ? 'border-red-500' : 'border-gray-300'}`}
placeholder="your.email@example.com"
/>
{errors.email && <p className="text-red-500 text-xs italic mt-2">{errors.email}</p>}
</div>
<div className="mb-5">
<label htmlFor="subject" className="block text-gray-700 text-sm font-bold mb-2">Subject</label>
<input
type="text"
id="subject"
name="subject"
value={formData.subject}
onChange={handleChange}
className={`shadow appearance-none border rounded-lg w-full py-3 px-4 text-gray-700 leading-tight focus:outline-none focus:ring-2 focus:ring-nigerian-green-500 ${errors.subject ? 'border-red-500' : 'border-gray-300'}`}
placeholder="Subject of your message"
/>
{errors.subject && <p className="text-red-500 text-xs italic mt-2">{errors.subject}</p>}
</div>
<div className="mb-6">
<label htmlFor="message" className="block text-gray-700 text-sm font-bold mb-2">Message</label>
<textarea
id="message"
name="message"
rows="6"
value={formData.message}
onChange={handleChange}
className={`shadow appearance-none border rounded-lg w-full py-3 px-4 text-gray-700 leading-tight focus:outline-none focus:ring-2 focus:ring-nigerian-green-500 ${errors.message ? 'border-red-500' : 'border-gray-300'}`}
placeholder="Your message..."
></textarea>
{errors.message && <p className="text-red-500 text-xs italic mt-2">{errors.message}</p>}
</div>
<div className="flex items-center justify-center">
<button
type="submit"
className="bg-gradient-to-r from-nigerian-green-500 to-kente-gold-500 hover:from-nigerian-green-600 hover:to-kente-gold-600 text-white font-bold py-3 px-8 rounded-lg focus:outline-none focus:shadow-outline transition-all duration-300 transform hover:scale-105"
disabled={isSubmitting}
>
{isSubmitting ? 'Sending...' : 'Send Message'}
</button>
</div>
</form>
);
}

View File

@@ -0,0 +1,85 @@
import React, { useState, useEffect } from 'react';
const MONTHLY_GOAL = 5000; // €5000 monthly goal
export default function DonationProgressBar() {
const [currentAmount, setCurrentAmount] = useState(0);
const [lastResetDate, setLastResetDate] = useState(null);
useEffect(() => {
// Load data from localStorage
const storedAmount = localStorage.getItem('omoluabi_donation_amount');
const storedResetDate = localStorage.getItem('omoluabi_donation_last_reset');
let amount = storedAmount ? parseFloat(storedAmount) : 0;
let resetDate = storedResetDate ? new Date(storedResetDate) : null;
const now = new Date();
const firstDayOfCurrentMonth = new Date(now.getFullYear(), now.getMonth(), 1);
// Check if it's a new month or if resetDate is not set
if (!resetDate || resetDate.getMonth() !== now.getMonth() || resetDate.getFullYear() !== now.getFullYear()) {
// Reset for the new month
amount = 0;
resetDate = firstDayOfCurrentMonth;
localStorage.setItem('omoluabi_donation_amount', amount.toString());
localStorage.setItem('omoluabi_donation_last_reset', resetDate.toISOString());
}
setCurrentAmount(amount);
setLastResetDate(resetDate);
}, []);
const percentage = Math.min(100, (currentAmount / MONTHLY_GOAL) * 100);
// This function is for demonstration purposes. In a real app, donations would come from a payment gateway.
const handleDonate = (amount) => {
setCurrentAmount(prevAmount => {
const newAmount = prevAmount + amount;
localStorage.setItem('omoluabi_donation_amount', newAmount.toString());
return newAmount;
});
};
return (
<div className="bg-white p-6 rounded-xl shadow-lg border border-gray-200">
<h2 className="text-2xl font-bold text-center mb-4 text-nigerian-green-700">Monthly Donation Goal</h2>
<p className="text-center text-gray-600 mb-6">Help us reach our goal to support our initiatives!</p>
<div className="w-full bg-gray-200 rounded-full h-4 mb-4 overflow-hidden">
<div
className="h-4 rounded-full bg-gradient-to-r from-nigerian-green-500 to-kente-gold-500 transition-all duration-1000 ease-out"
style={{ width: `${percentage}%` }}
></div>
</div>
<div className="flex justify-between items-center mb-6">
<span className="text-lg font-semibold text-gray-800">{currentAmount.toLocaleString()}</span>
<span className="text-lg font-semibold text-gray-800">{MONTHLY_GOAL.toLocaleString()}</span>
</div>
<div className="text-center text-sm text-gray-500 mb-6">
{percentage.toFixed(1)}% of the goal reached this month.
</div>
<div className="grid grid-cols-2 sm:grid-cols-3 gap-3 mb-6">
{[10, 25, 50, 100, 250, 500].map(amount => (
<button
key={amount}
onClick={() => handleDonate(amount)}
className="bg-nigerian-green-100 text-nigerian-green-700 font-semibold py-2 px-4 rounded-lg hover:bg-nigerian-green-200 transition-colors duration-200 shadow-sm"
>
Donate {amount}
</button>
))}
</div>
<button
onClick={() => handleDonate(100)} // Example: default donation
className="w-full bg-gradient-to-r from-ankara-red-500 to-kente-gold-500 text-white font-bold py-3 rounded-lg shadow-md hover:shadow-lg transform hover:scale-105 transition-all duration-300"
>
Make a Custom Donation
</button>
</div>
);
}

View File

@@ -0,0 +1,82 @@
import React, { useState, useEffect } from 'react';
export default function EventFilterSearch({ events }) {
const [searchTerm, setSearchTerm] = useState('');
const [selectedCategory, setSelectedCategory] = useState('All');
const [filteredEvents, setFilteredEvents] = useState(events);
const categories = ['All', ...new Set(events.map(event => event.frontmatter.category))];
useEffect(() => {
let tempEvents = events;
// Filter by category
if (selectedCategory !== 'All') {
tempEvents = tempEvents.filter(event => event.frontmatter.category === selectedCategory);
}
// Filter by search term
if (searchTerm) {
tempEvents = tempEvents.filter(event =>
event.frontmatter.title.toLowerCase().includes(searchTerm.toLowerCase()) ||
event.frontmatter.description.toLowerCase().includes(searchTerm.toLowerCase())
);
}
setFilteredEvents(tempEvents);
}, [searchTerm, selectedCategory, events]);
return (
<div className="container mx-auto px-4 py-8">
<div className="flex flex-col md:flex-row gap-4 mb-8">
{/* Search Input */}
<input
type="text"
placeholder="Search events..."
className="flex-grow p-3 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-nigerian-green-500"
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
/>
{/* Category Filter */}
<select
className="p-3 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-nigerian-green-500"
value={selectedCategory}
onChange={(e) => setSelectedCategory(e.target.value)}
>
{categories.map(category => (
<option key={category} value={category}>{category}</option>
))}
</select>
</div>
{/* Event List */}
<section className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
{filteredEvents.length > 0 ? (
filteredEvents.map(event => (
<article key={event.url} className="card bg-base-100 shadow-lg rounded-xl overflow-hidden transform transition-transform duration-300 hover:scale-105 hover:shadow-xl">
<figure className="relative h-48 w-full overflow-hidden">
<img src={event.frontmatter.image} alt={event.frontmatter.title} className="w-full h-full object-cover" />
<div className="absolute inset-0 bg-gradient-to-t from-black/60 to-transparent"></div>
<span className="absolute bottom-3 left-3 badge badge-secondary bg-kente-gold-500 text-white px-3 py-1 rounded-full text-sm font-semibold">{event.frontmatter.category}</span>
</figure>
<div className="card-body p-6">
<h2 className="card-title text-xl font-bold text-nigerian-green-700 mb-2">{event.frontmatter.title}</h2>
<p className="text-sm text-gray-600 mb-3">{new Date(event.frontmatter.date).toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' })}</p>
<p className="text-gray-700 leading-relaxed text-sm mb-4">{event.frontmatter.description}</p>
<a href={event.url} className="inline-flex items-center text-nigerian-green-600 hover:text-nigerian-green-800 font-semibold transition-colors duration-200">
Read More
<svg xmlns="http://www.w3.org/2000/svg" className="h-4 w-4 ml-1" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M9 5l7 7-7 7" />
</svg>
</a>
</div>
</article>
))
) : (
<p className="text-center text-gray-500 text-lg col-span-full">No events found matching your criteria.</p>
)}
</section>
</div>
);
}

View File

@@ -1,109 +0,0 @@
---
import '../styles/main.css';
// Events section for homepage
---
<section class="section" style="background: white;">
<div class="container">
<div style="text-align: center; margin-bottom: 3rem;">
<h2 class="section-title">
Upcoming <span style="color: #16a34a;">Events</span>
</h2>
<p class="section-subtitle">
Join us in celebrating our rich cultural heritage and building stronger community bonds
</p>
<div class="section-divider"></div>
</div>
<div style="display: grid; grid-template-columns: 1fr; gap: 2rem;">
<!-- Featured Event (Large) -->
<div style="display: grid; grid-template-columns: 1fr; gap: 2rem;">
<article style="
background: white;
border-radius: 1rem;
box-shadow: 0 10px 25px rgba(0,0,0,0.1);
overflow: hidden;
transition: all 0.3s ease;
position: relative;
group: hover;
" onmouseover="this.style.transform='translateY(-4px)'; this.style.boxShadow='0 20px 40px rgba(0,0,0,0.15)'"
onmouseout="this.style.transform='translateY(0)'; this.style.boxShadow='0 10px 25px rgba(0,0,0,0.1)'">
<div style="position: relative;">
<img src="/images/placeholder-event1.jpg" alt="Nigerian Cultural Festival" style="
width: 100%;
height: 20rem;
object-fit: cover;
" />
<div style="
position: absolute;
inset: 0;
background: linear-gradient(to top, rgba(0,0,0,0.6), transparent);
"></div>
<div style="
position: absolute;
top: 1rem;
left: 1rem;
background: #f59e0b;
color: white;
padding: 0.5rem 1rem;
border-radius: 20px;
font-weight: 600;
font-size: 0.875rem;
">
Cultural Festival
</div>
<div style="
position: absolute;
top: 1rem;
right: 1rem;
background: rgba(255,255,255,0.9);
color: #16a34a;
padding: 0.5rem 1rem;
border-radius: 20px;
font-weight: 600;
font-size: 0.875rem;
">
Dec 15, 2024
</div>
</div>
<div style="padding: 2rem;">
<h3 style="
font-size: 1.5rem;
font-weight: 700;
margin-bottom: 0.75rem;
color: #111827;
">
Nigerian Cultural Festival 2024
</h3>
<p style="color: #6b7280; margin-bottom: 1rem; line-height: 1.6;">
Join us for a spectacular celebration of Nigerian culture featuring traditional music, dance, authentic cuisine, and art exhibitions. A perfect opportunity to connect with our heritage and community.
</p>
<div style="display: flex; align-items: center; justify-content: between; flex-wrap: wrap; gap: 1rem;">
<div style="display: flex; align-items: center; gap: 0.5rem; color: #9ca3af; font-size: 0.875rem;">
<span>📍</span>
<span>Amsterdam Community Center</span>
</div>
<div style="display: flex; align-items: center; gap: 0.5rem; color: #9ca3af; font-size: 0.875rem;">
<span>🕒</span>
<span>14:00 - 22:00</span>
</div>
<button style="
background: #16a34a;
color: white;
padding: 0.5rem 1rem;
border-radius: 8px;
border: none;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
margin-left: auto;
" onmouseover="this.style.background='#15803d'"
onmouseout="this.style.background='#16a34a'">
Learn More
</button>
</div>
</div>
</article>
</div>
<!-- You can add more events here as needed -->
</div>
</div>
</section>

View File

@@ -1,71 +1,75 @@
--- ---
// Footer.astro - Modern Nigerian-themed footer with custom CSS // Footer.astro - Modern Nigerian-themed footer
--- ---
<footer class="footer"> <footer class="bg-gradient-to-br from-gray-900 via-gray-800 to-gray-900 text-white relative overflow-hidden">
<!-- Background Pattern --> <!-- Background Pattern -->
<div class="footer-bg-pattern"></div> <div class="absolute inset-0 opacity-5">
<div class="absolute inset-0" style="background-image: url('data:image/svg+xml,%3Csvg width=\"60\" height=\"60\" viewBox=\"0 0 60 60\" xmlns=\"http://www.w3.org/2000/svg\"%3E%3Cg fill=\"none\" fill-rule=\"evenodd\"%3E%3Cg fill=\"%23ffffff\" fill-opacity=\"0.1\"%3E%3Cpath d=\"M36 34v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zm0-30V0h-2v4h-4v2h4v4h2V6h4V4h-4zM6 34v-4H4v4H0v2h4v4h2v-4h4v-2H6zM6 4V0H4v4H0v2h4v4h2V6h4V4H6z\"/%3E%3C/g%3E%3C/g%3E%3C/svg%3E');"></div>
</div>
<!-- Decorative Top Border --> <!-- Decorative Top Border -->
<div class="footer-top-border"></div> <div class="h-2 bg-gradient-to-r from-nigerian-green-500 via-kente-gold-500 to-ankara-red-500"></div>
<div class="footer-container"> <div class="container mx-auto px-4 py-16 relative z-10">
<div class="footer-grid"> <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-12">
<!-- Brand Section --> <!-- Brand Section -->
<div class="footer-brand"> <div class="lg:col-span-2">
<div class="footer-logo-section"> <div class="flex items-center gap-4 mb-6">
<!-- Logo --> <!-- Logo -->
<div class="footer-logo-container"> <div class="relative">
<div class="footer-logo-flag"> <div class="w-16 h-16 rounded-full bg-gradient-to-r from-nigerian-green-500 via-white to-nigerian-green-500 p-0.5 shadow-xl">
<div class="footer-logo-inner"> <div class="w-full h-full rounded-full bg-gray-800 flex items-center justify-center">
<div class="footer-logo-symbol"> <div class="w-12 h-12 rounded-full bg-gradient-to-br from-nigerian-green-500 to-kente-gold-500 flex items-center justify-center">
<span>O</span> <span class="text-white font-bold text-xl">O</span>
</div> </div>
</div> </div>
</div> </div>
<div class="footer-logo-accent"></div> <div class="absolute -top-1 -right-1 w-5 h-5 bg-kente-gold-400 rounded-full animate-pulse"></div>
</div> </div>
<div class="footer-brand-text"> <div>
<h3 class="footer-brand-title">Omoluabi Association</h3> <h3 class="font-headline text-3xl font-bold bg-gradient-to-r from-nigerian-green-400 to-kente-gold-400 bg-clip-text text-transparent">
<p class="footer-brand-subtitle">Building Bridges, Celebrating Heritage</p> Omoluabi Foundation
</h3>
<p class="text-gray-400 text-sm">Building Bridges, Celebrating Heritage</p>
</div> </div>
</div> </div>
<p class="footer-description"> <p class="text-gray-300 leading-relaxed mb-6 max-w-md">
Connecting Nigerian hearts in the Netherlands through culture, community, and compassion. Connecting Nigerian hearts in the Netherlands through culture, community, and compassion.
Together, we preserve our heritage while embracing our future. Together, we preserve our heritage while embracing our future.
</p> </p>
<!-- Nigerian Flag Colors Accent --> <!-- Nigerian Flag Colors Accent -->
<div class="footer-flag-section"> <div class="flex items-center gap-4 mb-6">
<div class="footer-flag"> <div class="flex gap-1">
<div class="flag-stripe flag-green"></div> <div class="w-4 h-6 bg-nigerian-green-500 rounded-sm"></div>
<div class="flag-stripe flag-white"></div> <div class="w-4 h-6 bg-white rounded-sm"></div>
<div class="flag-stripe flag-green"></div> <div class="w-4 h-6 bg-nigerian-green-500 rounded-sm"></div>
</div> </div>
<span class="footer-flag-text">Proudly Nigerian 🇳🇬 in the Netherlands 🇳🇱</span> <span class="text-sm text-gray-400">Proudly Nigerian 🇳🇬 in the Netherlands 🇳🇱</span>
</div> </div>
<!-- Social Media Links --> <!-- Social Media Links -->
<div class="footer-social"> <div class="flex gap-4">
<a href="#" class="social-link social-twitter"> <a href="#" class="group bg-gray-800 hover:bg-nigerian-green-500 p-3 rounded-full transition-all duration-300 transform hover:scale-110 hover:rotate-6">
<svg class="social-icon" fill="currentColor" viewBox="0 0 24 24"> <svg class="w-5 h-5 group-hover:text-white transition-colors" fill="currentColor" viewBox="0 0 24 24">
<path d="M24 4.557c-.883.392-1.832.656-2.828.775 1.017-.609 1.798-1.574 2.165-2.724-.951.564-2.005.974-3.127 1.195-.897-.957-2.178-1.555-3.594-1.555-3.179 0-5.515 2.966-4.797 6.045-4.091-.205-7.719-2.165-10.148-5.144-1.29 2.213-.669 5.108 1.523 6.574-.806-.026-1.566-.247-2.229-.616-.054 2.281 1.581 4.415 3.949 4.89-.693.188-1.452.232-2.224.084.626 1.956 2.444 3.379 4.6 3.419-2.07 1.623-4.678 2.348-7.29 2.04 2.179 1.397 4.768 2.212 7.548 2.212 9.142 0 14.307-7.721 13.995-14.646.962-.695 1.797-1.562 2.457-2.549z"/> <path d="M24 4.557c-.883.392-1.832.656-2.828.775 1.017-.609 1.798-1.574 2.165-2.724-.951.564-2.005.974-3.127 1.195-.897-.957-2.178-1.555-3.594-1.555-3.179 0-5.515 2.966-4.797 6.045-4.091-.205-7.719-2.165-10.148-5.144-1.29 2.213-.669 5.108 1.523 6.574-.806-.026-1.566-.247-2.229-.616-.054 2.281 1.581 4.415 3.949 4.89-.693.188-1.452.232-2.224.084.626 1.956 2.444 3.379 4.6 3.419-2.07 1.623-4.678 2.348-7.29 2.04 2.179 1.397 4.768 2.212 7.548 2.212 9.142 0 14.307-7.721 13.995-14.646.962-.695 1.797-1.562 2.457-2.549z"/>
</svg> </svg>
</a> </a>
<a href="#" class="social-link social-facebook"> <a href="#" class="group bg-gray-800 hover:bg-kente-gold-500 p-3 rounded-full transition-all duration-300 transform hover:scale-110 hover:rotate-6">
<svg class="social-icon" fill="currentColor" viewBox="0 0 24 24"> <svg class="w-5 h-5 group-hover:text-white transition-colors" fill="currentColor" viewBox="0 0 24 24">
<path d="M22.46 6c-.77.35-1.6.58-2.46.69.88-.53 1.56-1.37 1.88-2.38-.83.5-1.75.85-2.72 1.05C18.37 4.5 17.26 4 16 4c-2.35 0-4.27 1.92-4.27 4.29 0 .34.04.67.11.98C8.28 9.09 5.11 7.38 3 4.79c-.37.63-.58 1.37-.58 2.15 0 1.49.75 2.81 1.91 3.56-.71 0-1.37-.2-1.95-.5v.03c0 2.08 1.48 3.82 3.44 4.21a4.22 4.22 0 0 1-1.93.07 4.28 4.28 0 0 0 4 2.98 8.521 8.521 0 0 1-5.33 1.84c-.34 0-.68-.02-1.02-.06C3.44 20.29 5.7 21 8.12 21 16 21 20.33 14.46 20.33 8.79c0-.19 0-.37-.01-.56.84-.6 1.56-1.36 2.14-2.23z"/> <path d="M22.46 6c-.77.35-1.6.58-2.46.69.88-.53 1.56-1.37 1.88-2.38-.83.5-1.75.85-2.72 1.05C18.37 4.5 17.26 4 16 4c-2.35 0-4.27 1.92-4.27 4.29 0 .34.04.67.11.98C8.28 9.09 5.11 7.38 3 4.79c-.37.63-.58 1.37-.58 2.15 0 1.49.75 2.81 1.91 3.56-.71 0-1.37-.2-1.95-.5v.03c0 2.08 1.48 3.82 3.44 4.21a4.22 4.22 0 0 1-1.93.07 4.28 4.28 0 0 0 4 2.98 8.521 8.521 0 0 1-5.33 1.84c-.34 0-.68-.02-1.02-.06C3.44 20.29 5.7 21 8.12 21 16 21 20.33 14.46 20.33 8.79c0-.19 0-.37-.01-.56.84-.6 1.56-1.36 2.14-2.23z"/>
</svg> </svg>
</a> </a>
<a href="#" class="social-link social-instagram"> <a href="#" class="group bg-gray-800 hover:bg-ankara-red-500 p-3 rounded-full transition-all duration-300 transform hover:scale-110 hover:rotate-6">
<svg class="social-icon" fill="currentColor" viewBox="0 0 24 24"> <svg class="w-5 h-5 group-hover:text-white transition-colors" fill="currentColor" viewBox="0 0 24 24">
<path d="M12.017 0C5.396 0 .029 5.367.029 11.987c0 5.079 3.158 9.417 7.618 11.174-.105-.949-.199-2.403.041-3.439.219-.937 1.406-5.957 1.406-5.957s-.359-.72-.359-1.781c0-1.663.967-2.911 2.168-2.911 1.024 0 1.518.769 1.518 1.688 0 1.029-.653 2.567-.992 3.992-.285 1.193.6 2.165 1.775 2.165 2.128 0 3.768-2.245 3.768-5.487 0-2.861-2.063-4.869-5.008-4.869-3.41 0-5.409 2.562-5.409 5.199 0 1.033.394 2.143.889 2.741.097.118.112.221.083.343-.09.375-.293 1.199-.334 1.363-.053.225-.172.271-.402.165-1.495-.69-2.433-2.878-2.433-4.646 0-3.776 2.748-7.252 7.92-7.252 4.158 0 7.392 2.967 7.392 6.923 0 4.135-2.607 7.462-6.233 7.462-1.214 0-2.357-.629-2.75-1.378l-.748 2.853c-.271 1.043-1.002 2.35-1.492 3.146C9.57 23.812 10.763 24.009 12.017 24.009c6.624 0 11.99-5.367 11.99-11.988C24.007 5.367 18.641.001.012.001z"/> <path d="M12.017 0C5.396 0 .029 5.367.029 11.987c0 5.079 3.158 9.417 7.618 11.174-.105-.949-.199-2.403.041-3.439.219-.937 1.406-5.957 1.406-5.957s-.359-.72-.359-1.781c0-1.663.967-2.911 2.168-2.911 1.024 0 1.518.769 1.518 1.688 0 1.029-.653 2.567-.992 3.992-.285 1.193.6 2.165 1.775 2.165 2.128 0 3.768-2.245 3.768-5.487 0-2.861-2.063-4.869-5.008-4.869-3.41 0-5.409 2.562-5.409 5.199 0 1.033.394 2.143.889 2.741.097.118.112.221.083.343-.09.375-.293 1.199-.334 1.363-.053.225-.172.271-.402.165-1.495-.69-2.433-2.878-2.433-4.646 0-3.776 2.748-7.252 7.92-7.252 4.158 0 7.392 2.967 7.392 6.923 0 4.135-2.607 7.462-6.233 7.462-1.214 0-2.357-.629-2.75-1.378l-.748 2.853c-.271 1.043-1.002 2.35-1.492 3.146C9.57 23.812 10.763 24.009 12.017 24.009c6.624 0 11.99-5.367 11.99-11.988C24.007 5.367 18.641.001.012.001z"/>
</svg> </svg>
</a> </a>
<a href="#" class="social-link social-linkedin"> <a href="#" class="group bg-gray-800 hover:bg-adire-blue-500 p-3 rounded-full transition-all duration-300 transform hover:scale-110 hover:rotate-6">
<svg class="social-icon" fill="currentColor" viewBox="0 0 24 24"> <svg class="w-5 h-5 group-hover:text-white transition-colors" fill="currentColor" viewBox="0 0 24 24">
<path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/> <path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/>
</svg> </svg>
</a> </a>
@@ -73,74 +77,96 @@
</div> </div>
<!-- Quick Links --> <!-- Quick Links -->
<div class="footer-section"> <div>
<h4 class="footer-section-title"> <h4 class="font-headline text-xl font-bold mb-6 text-white flex items-center gap-2">
<span class="footer-section-accent"></span> <span class="w-1 h-6 bg-gradient-to-b from-nigerian-green-400 to-kente-gold-400 rounded-full"></span>
Quick Links Quick Links
</h4> </h4>
<nav class="footer-nav"> <nav class="space-y-3">
<a href="/home" class="footer-nav-link">Home</a> <a href="/" class="block text-gray-300 hover:text-nigerian-green-400 transition-colors duration-200 hover:translate-x-1 transform">
<a href="/events" class="footer-nav-link">Events</a> Home
<a href="/members" class="footer-nav-link">Members</a> </a>
<a href="/orphanage" class="footer-nav-link">Orphanage</a> <a href="/events" class="block text-gray-300 hover:text-nigerian-green-400 transition-colors duration-200 hover:translate-x-1 transform">
<a href="/contact" class="footer-nav-link">Contact</a> Events
<a href="/join" class="footer-nav-link footer-nav-cta">Join Us →</a> </a>
<a href="/members" class="block text-gray-300 hover:text-nigerian-green-400 transition-colors duration-200 hover:translate-x-1 transform">
Members
</a>
<a href="/orphanage" class="block text-gray-300 hover:text-nigerian-green-400 transition-colors duration-200 hover:translate-x-1 transform">
Orphanage
</a>
<a href="/gallery" class="block text-gray-300 hover:text-nigerian-green-400 transition-colors duration-200 hover:translate-x-1 transform">
Gallery
</a>
<a href="/contact" class="block text-gray-300 hover:text-nigerian-green-400 transition-colors duration-200 hover:translate-x-1 transform">
Contact
</a>
<a href="/join" class="block text-kente-gold-400 hover:text-kente-gold-300 transition-colors duration-200 hover:translate-x-1 transform font-semibold">
Join Us →
</a>
</nav> </nav>
</div> </div>
<!-- Contact Info --> <!-- Contact Info -->
<div class="footer-section"> <div>
<h4 class="footer-section-title"> <h4 class="font-headline text-xl font-bold mb-6 text-white flex items-center gap-2">
<span class="footer-section-accent footer-section-accent-alt"></span> <span class="w-1 h-6 bg-gradient-to-b from-ankara-red-400 to-nigerian-green-400 rounded-full"></span>
Get in Touch Get in Touch
</h4> </h4>
<div class="footer-contact"> <div class="space-y-4">
<div class="contact-item"> <div class="flex items-start gap-3">
<div class="contact-icon contact-location"> <div class="bg-nigerian-green-500/20 p-2 rounded-lg mt-1">
<svg class="contact-icon-svg" fill="currentColor" viewBox="0 0 20 20"> <svg class="w-4 h-4 text-nigerian-green-400" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M5.05 4.05a7 7 0 119.9 9.9L10 18.9l-4.95-4.95a7 7 0 010-9.9zM10 11a2 2 0 100-4 2 2 0 000 4z" clip-rule="evenodd"></path> <path fill-rule="evenodd" d="M5.05 4.05a7 7 0 119.9 9.9L10 18.9l-4.95-4.95a7 7 0 010-9.9zM10 11a2 2 0 100-4 2 2 0 000 4z" clip-rule="evenodd"></path>
</svg> </svg>
</div> </div>
<div class="contact-text"> <div>
<p>Amsterdam, Netherlands<br/>Various locations across NL</p> <p class="text-gray-300 text-sm leading-relaxed">
Amsterdam, Netherlands<br/>
Various locations across NL
</p>
</div> </div>
</div> </div>
<div class="contact-item"> <div class="flex items-start gap-3">
<div class="contact-icon contact-phone"> <div class="bg-kente-gold-500/20 p-2 rounded-lg mt-1">
<svg class="contact-icon-svg" fill="currentColor" viewBox="0 0 20 20"> <svg class="w-4 h-4 text-kente-gold-400" fill="currentColor" viewBox="0 0 20 20">
<path d="M2 3a1 1 0 011-1h2.153a1 1 0 01.986.836l.74 4.435a1 1 0 01-.54 1.06l-1.548.773a11.037 11.037 0 006.105 6.105l.774-1.548a1 1 0 011.059-.54l4.435.74a1 1 0 01.836.986V17a1 1 0 01-1 1h-2C7.82 18 2 12.18 2 5V3z"></path> <path d="M2 3a1 1 0 011-1h2.153a1 1 0 01.986.836l.74 4.435a1 1 0 01-.54 1.06l-1.548.773a11.037 11.037 0 006.105 6.105l.774-1.548a1 1 0 011.059-.54l4.435.74a1 1 0 01.836.986V17a1 1 0 01-1 1h-2C7.82 18 2 12.18 2 5V3z"></path>
</svg> </svg>
</div> </div>
<div class="contact-text"> <div>
<p>+31 (0) 123 456 789</p> <p class="text-gray-300 text-sm">
+31 (0) 123 456 789
</p>
</div> </div>
</div> </div>
<div class="contact-item"> <div class="flex items-start gap-3">
<div class="contact-icon contact-email"> <div class="bg-ankara-red-500/20 p-2 rounded-lg mt-1">
<svg class="contact-icon-svg" fill="currentColor" viewBox="0 0 20 20"> <svg class="w-4 h-4 text-ankara-red-400" fill="currentColor" viewBox="0 0 20 20">
<path d="M2.003 5.884L10 9.882l7.997-3.998A2 2 0 0016 4H4a2 2 0 00-1.997 1.884z"></path> <path d="M2.003 5.884L10 9.882l7.997-3.998A2 2 0 0016 4H4a2 2 0 00-1.997 1.884z"></path>
<path d="M18 8.118l-8 4-8-4V14a2 2 0 002 2h12a2 2 0 002-2V8.118z"></path> <path d="M18 8.118l-8 4-8-4V14a2 2 0 002 2h12a2 2 0 002-2V8.118z"></path>
</svg> </svg>
</div> </div>
<div class="contact-text"> <div>
<p>info@omoluabi.nl</p> <p class="text-gray-300 text-sm">
info@omoluabi.nl
</p>
</div> </div>
</div> </div>
</div> </div>
<!-- Newsletter Signup --> <!-- Newsletter Signup -->
<div class="footer-newsletter"> <div class="mt-8 p-4 bg-gray-800/50 rounded-xl border border-gray-700">
<h5 class="newsletter-title">Stay Updated</h5> <h5 class="font-semibold mb-3 text-white">Stay Updated</h5>
<div class="newsletter-form"> <div class="flex gap-2">
<input <input
type="email" type="email"
placeholder="Your email" placeholder="Your email"
class="newsletter-input" class="flex-1 px-3 py-2 bg-gray-700 border border-gray-600 rounded-lg text-sm text-white placeholder-gray-400 focus:border-nigerian-green-400 focus:outline-none"
/> />
<button class="newsletter-button"> <button class="bg-nigerian-green-500 hover:bg-nigerian-green-600 px-4 py-2 rounded-lg transition-colors duration-200">
<svg class="newsletter-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <svg class="w-4 h-4 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 19l9 2-9-18-9 18 9-2zm0 0v-8"></path> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 19l9 2-9-18-9 18 9-2zm0 0v-8"></path>
</svg> </svg>
</button> </button>
@@ -150,510 +176,34 @@
</div> </div>
<!-- Bottom Section --> <!-- Bottom Section -->
<div class="footer-bottom"> <div class="border-t border-gray-700 mt-12 pt-8">
<div class="footer-bottom-content"> <div class="flex flex-col md:flex-row justify-between items-center gap-4">
<!-- Copyright --> <!-- Copyright -->
<div class="footer-copyright"> <div class="text-gray-400 text-sm">
<span>&copy; {new Date().getFullYear()} Omoluabi Association Netherlands. </span> <span>&copy; {new Date().getFullYear()} Omoluabi Foundation Netherlands. </span>
<span class="copyright-heart">Made with ❤️ </span> <span class="text-nigerian-green-400">Made with ❤️ </span>
<span>for the Nigerian community.</span> <span>for the Nigerian community.</span>
</div> </div>
<!-- Additional Links --> <!-- Additional Links -->
<div class="footer-links"> <div class="flex gap-6 text-sm">
<a href="/privacy" class="footer-link">Privacy Policy</a> <a href="/privacy" class="text-gray-400 hover:text-white transition-colors">Privacy Policy</a>
<a href="/terms" class="footer-link">Terms of Service</a> <a href="/terms" class="text-gray-400 hover:text-white transition-colors">Terms of Service</a>
<a href="/sitemap" class="footer-link">Sitemap</a> <a href="/sitemap" class="text-gray-400 hover:text-white transition-colors">Sitemap</a>
</div> </div>
</div> </div>
<!-- Cultural Quote --> <!-- Cultural Quote -->
<div class="footer-quote"> <div class="mt-6 text-center">
<p class="quote-text">"Omoluabi ni wa" - We are people of good character</p> <p class="text-gray-500 italic text-sm">
<div class="quote-stars"> "Omoluabi ni wa" - We are people of good character
<span class="star star-green">🌟</span> </p>
<span class="star star-gold">🌟</span> <div class="flex justify-center mt-2 gap-1">
<span class="star star-red">🌟</span> <span class="text-nigerian-green-400">🌟</span>
<span class="text-kente-gold-400">🌟</span>
<span class="text-ankara-red-400">🌟</span>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</footer> </footer>
<style>
/* Footer Styles */
.footer {
background: linear-gradient(135deg, #111827 0%, #1f2937 50%, #111827 100%);
color: white;
position: relative;
overflow: hidden;
}
.footer-bg-pattern {
position: absolute;
inset: 0;
opacity: 0.05;
background-image: url("data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%23ffffff' fill-opacity='0.1'%3E%3Cpath d='M36 34v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zm0-30V0h-2v4h-4v2h4v4h2V6h4V4h-4zM6 34v-4H4v4H0v2h4v4h2v-4h4v-2H6zM6 4V0H4v4H0v2h4v4h2V6h4V4H6z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
}
.footer-top-border {
height: 8px;
background: linear-gradient(90deg, #16a34a, #f59e0b, #dc2626);
}
.footer-container {
max-width: 1200px;
margin: 0 auto;
padding: 4rem 2rem;
position: relative;
z-index: 10;
}
.footer-grid {
display: grid;
grid-template-columns: 1fr;
gap: 3rem;
}
@media (min-width: 768px) {
.footer-grid {
grid-template-columns: 1fr 1fr;
}
}
@media (min-width: 1024px) {
.footer-grid {
grid-template-columns: 2fr 1fr 1fr;
}
}
/* Brand Section */
.footer-brand {
grid-column: 1 / -1;
}
@media (min-width: 1024px) {
.footer-brand {
grid-column: 1 / 2;
}
}
.footer-logo-section {
display: flex;
align-items: center;
gap: 1rem;
margin-bottom: 1.5rem;
}
.footer-logo-container {
position: relative;
}
.footer-logo-flag {
width: 4rem;
height: 4rem;
border-radius: 50%;
background: linear-gradient(45deg, #16a34a, #ffffff, #16a34a);
padding: 2px;
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3);
}
.footer-logo-inner {
width: 100%;
height: 100%;
border-radius: 50%;
background: #1f2937;
display: flex;
align-items: center;
justify-content: center;
}
.footer-logo-symbol {
width: 3rem;
height: 3rem;
border-radius: 50%;
background: linear-gradient(135deg, #16a34a, #f59e0b);
display: flex;
align-items: center;
justify-content: center;
}
.footer-logo-symbol span {
color: white;
font-weight: bold;
font-size: 1.25rem;
}
.footer-logo-accent {
position: absolute;
top: -4px;
right: -4px;
width: 1.25rem;
height: 1.25rem;
background: #f59e0b;
border-radius: 50%;
animation: pulse 2s infinite;
}
.footer-brand-text {
display: flex;
flex-direction: column;
}
.footer-brand-title {
font-family: 'Poppins', sans-serif;
font-size: 1.875rem;
font-weight: 700;
background: linear-gradient(45deg, #16a34a, #f59e0b);
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
margin-bottom: 0.25rem;
}
.footer-brand-subtitle {
color: #9ca3af;
font-size: 0.875rem;
}
.footer-description {
color: #d1d5db;
line-height: 1.7;
margin-bottom: 1.5rem;
max-width: 24rem;
}
.footer-flag-section {
display: flex;
align-items: center;
gap: 1rem;
margin-bottom: 1.5rem;
}
.footer-flag {
display: flex;
gap: 1px;
}
.flag-stripe {
width: 1rem;
height: 1.5rem;
border-radius: 2px;
}
.flag-green {
background: #16a34a;
}
.flag-white {
background: white;
}
.footer-flag-text {
font-size: 0.875rem;
color: #9ca3af;
}
.footer-social {
display: flex;
gap: 1rem;
}
.social-link {
background: #374151;
padding: 0.75rem;
border-radius: 50%;
transition: all 0.3s ease;
transform: scale(1);
display: flex;
align-items: center;
justify-content: center;
}
.social-link:hover {
transform: scale(1.1) rotate(6deg);
}
.social-twitter:hover {
background: #16a34a;
}
.social-facebook:hover {
background: #f59e0b;
}
.social-instagram:hover {
background: #dc2626;
}
.social-linkedin:hover {
background: #2563eb;
}
.social-icon {
width: 1.25rem;
height: 1.25rem;
color: #9ca3af;
transition: color 0.3s ease;
}
.social-link:hover .social-icon {
color: white;
}
/* Footer Sections */
.footer-section {
display: flex;
flex-direction: column;
}
.footer-section-title {
font-family: 'Poppins', sans-serif;
font-size: 1.25rem;
font-weight: 700;
margin-bottom: 1.5rem;
color: white;
display: flex;
align-items: center;
gap: 0.5rem;
}
.footer-section-accent {
width: 4px;
height: 1.5rem;
background: linear-gradient(180deg, #16a34a, #f59e0b);
border-radius: 2px;
}
.footer-section-accent-alt {
background: linear-gradient(180deg, #dc2626, #16a34a);
}
.footer-nav {
display: flex;
flex-direction: column;
gap: 0.75rem;
}
.footer-nav-link {
color: #d1d5db;
text-decoration: none;
transition: all 0.2s ease;
transform: translateX(0);
}
.footer-nav-link:hover {
color: #16a34a;
transform: translateX(4px);
}
.footer-nav-cta {
color: #f59e0b;
font-weight: 600;
}
.footer-nav-cta:hover {
color: #f59e0b;
}
/* Contact Section */
.footer-contact {
display: flex;
flex-direction: column;
gap: 1rem;
margin-bottom: 2rem;
}
.contact-item {
display: flex;
align-items: flex-start;
gap: 0.75rem;
}
.contact-icon {
padding: 0.5rem;
border-radius: 8px;
margin-top: 2px;
}
.contact-location {
background: rgba(22, 163, 74, 0.2);
}
.contact-phone {
background: rgba(245, 158, 11, 0.2);
}
.contact-email {
background: rgba(220, 38, 38, 0.2);
}
.contact-icon-svg {
width: 1rem;
height: 1rem;
}
.contact-location .contact-icon-svg {
color: #16a34a;
}
.contact-phone .contact-icon-svg {
color: #f59e0b;
}
.contact-email .contact-icon-svg {
color: #dc2626;
}
.contact-text p {
color: #d1d5db;
font-size: 0.875rem;
line-height: 1.5;
}
/* Newsletter */
.footer-newsletter {
padding: 1rem;
background: rgba(55, 65, 81, 0.5);
border-radius: 12px;
border: 1px solid #4b5563;
}
.newsletter-title {
font-weight: 600;
margin-bottom: 0.75rem;
color: white;
}
.newsletter-form {
display: flex;
gap: 0.5rem;
}
.newsletter-input {
flex: 1;
padding: 0.5rem 0.75rem;
background: #374151;
border: 1px solid #4b5563;
border-radius: 8px;
font-size: 0.875rem;
color: white;
}
.newsletter-input::placeholder {
color: #9ca3af;
}
.newsletter-input:focus {
border-color: #16a34a;
outline: none;
}
.newsletter-button {
background: #16a34a;
padding: 0.5rem 1rem;
border-radius: 8px;
border: none;
cursor: pointer;
transition: background-color 0.2s ease;
}
.newsletter-button:hover {
background: #15803d;
}
.newsletter-icon {
width: 1rem;
height: 1rem;
color: white;
}
/* Bottom Section */
.footer-bottom {
border-top: 1px solid #4b5563;
margin-top: 3rem;
padding-top: 2rem;
}
.footer-bottom-content {
display: flex;
flex-direction: column;
gap: 1rem;
align-items: center;
}
@media (min-width: 768px) {
.footer-bottom-content {
flex-direction: row;
justify-content: space-between;
}
}
.footer-copyright {
color: #9ca3af;
font-size: 0.875rem;
text-align: center;
}
@media (min-width: 768px) {
.footer-copyright {
text-align: left;
}
}
.copyright-heart {
color: #16a34a;
}
.footer-links {
display: flex;
gap: 1.5rem;
font-size: 0.875rem;
}
.footer-link {
color: #9ca3af;
text-decoration: none;
transition: color 0.2s ease;
}
.footer-link:hover {
color: white;
}
.footer-quote {
margin-top: 1.5rem;
text-align: center;
}
.quote-text {
color: #6b7280;
font-style: italic;
font-size: 0.875rem;
margin-bottom: 0.5rem;
}
.quote-stars {
display: flex;
justify-content: center;
gap: 0.25rem;
}
.star-green {
color: #16a34a;
}
.star-gold {
color: #f59e0b;
}
.star-red {
color: #dc2626;
}
/* Animations */
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.5; }
}
</style>

View File

@@ -1,101 +1,106 @@
--- ---
import '../styles/main.css';
// Header.astro - Updated with better navigation and active states // Header.astro - Updated with better navigation and active states
--- ---
<header class="header"> <header class="fixed top-0 left-0 right-0 z-50 bg-white/95 backdrop-blur-lg border-b border-gray-200/50 shadow-lg">
<div class="header-content"> <div class="max-w-7xl mx-auto px-4">
<!-- Top bar with cultural elements --> <!-- Top bar with cultural elements -->
<div class="header-top-bar"> <div class="hidden md:flex items-center justify-between py-2 text-sm border-b border-gray-100">
<div class="header-top-left"> <div class="flex items-center gap-4 text-gray-600">
<div class="header-info-item"> <div class="flex items-center gap-2">
<svg class="header-icon header-icon-green" fill="currentColor" viewBox="0 0 20 20"> <svg class="w-4 h-4 text-green-600" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M5.05 4.05a7 7 0 119.9 9.9L10 18.9l-4.95-4.95a7 7 0 010-9.9zM10 11a2 2 0 100-4 2 2 0 000 4z" clip-rule="evenodd"></path> <path fill-rule="evenodd" d="M5.05 4.05a7 7 0 119.9 9.9L10 18.9l-4.95-4.95a7 7 0 010-9.9zM10 11a2 2 0 100-4 2 2 0 000 4z" clip-rule="evenodd"></path>
</svg> </svg>
<span>Netherlands</span> <span>Netherlands</span>
</div> </div>
<div class="header-info-item"> <div class="flex items-center gap-2">
<svg class="header-icon header-icon-amber" fill="currentColor" viewBox="0 0 20 20"> <svg class="w-4 h-4 text-amber-600" fill="currentColor" viewBox="0 0 20 20">
<path d="M2 3a1 1 0 011-1h2.153a1 1 0 01.986.836l.74 4.435a1 1 0 01-.54 1.06l-1.548.773a11.037 11.037 0 006.105 6.105l.774-1.548a1 1 0 011.059-.54l4.435.74a1 1 0 01.836.986V17a1 1 0 01-1 1h-2C7.82 18 2 12.18 2 5V3z"></path> <path d="M2 3a1 1 0 011-1h2.153a1 1 0 01.986.836l.74 4.435a1 1 0 01-.54 1.06l-1.548.773a11.037 11.037 0 006.105 6.105l.774-1.548a1 1 0 011.059-.54l4.435.74a1 1 0 01.836.986V17a1 1 0 01-1 1h-2C7.82 18 2 12.18 2 5V3z"></path>
</svg> </svg>
<span>+31 (0) 123 456 789</span> <span>+31 (0) 123 456 789</span>
</div> </div>
</div> </div>
<div class="header-top-right"> <div class="flex items-center gap-1">
<span class="flag-emoji">🇳🇬</span> <span class="text-gray-500">🇳🇬</span>
<span class="header-heritage-text">Celebrating Nigerian Heritage</span> <span class="font-semibold text-green-700">Celebrating Nigerian Heritage</span>
<span class="flag-emoji">🇳🇱</span> <span class="text-gray-500">🇳🇱</span>
</div> </div>
</div> </div>
<!-- Main navigation --> <!-- Main navigation -->
<nav class="header-nav"> <nav class="flex items-center justify-between py-4">
<!-- Logo --> <!-- Logo -->
<a href="/home" class="header-logo"> <a href="/" class="flex items-center gap-3 group">
<div class="logo-container"> <div class="relative">
<!-- Nigerian flag inspired logo --> <!-- Nigerian flag inspired logo -->
<div class="logo-flag"> <div class="w-12 h-12 rounded-full bg-gradient-to-r from-green-500 via-white to-green-500 p-0.5 shadow-lg group-hover:shadow-xl transition-all duration-300">
<div class="logo-inner"> <div class="w-full h-full rounded-full bg-white flex items-center justify-center">
<div class="logo-symbol"> <div class="w-8 h-8 rounded-full bg-gradient-to-br from-green-500 to-amber-500 flex items-center justify-center">
<span>O</span> <span class="text-white font-bold text-sm">O</span>
</div> </div>
</div> </div>
</div> </div>
<!-- Floating accent --> <!-- Floating accent -->
<div class="logo-accent"></div> <div class="absolute -top-1 -right-1 w-4 h-4 bg-amber-400 rounded-full animate-bounce"></div>
</div> </div>
<div class="logo-text"> <div class="flex flex-col">
<span class="logo-title">Omoluabi</span> <span class="font-bold text-2xl bg-gradient-to-r from-green-600 to-amber-600 bg-clip-text text-transparent">
<span class="logo-subtitle">Association</span> Omoluabi
</span>
<span class="text-sm text-gray-600 font-medium -mt-1">Foundation</span>
</div> </div>
</a> </a>
<!-- Desktop Navigation --> <!-- Desktop Navigation -->
<div class="header-desktop-nav"> <div class="hidden lg:flex items-center gap-1">
<a href="/home" class="nav-link"> <a href="/" class="nav-link px-4 py-2 rounded-lg font-medium text-gray-700 hover:text-green-600 hover:bg-green-50 transition-all duration-200 relative group">
Home Home
<span class="nav-underline"></span> <span class="absolute bottom-0 left-0 w-0 h-0.5 bg-green-600 group-hover:w-full transition-all duration-300"></span>
</a> </a>
<a href="/about" class="nav-link"> <a href="/about" class="nav-link px-4 py-2 rounded-lg font-medium text-gray-700 hover:text-green-600 hover:bg-green-50 transition-all duration-200 relative group">
About About
<span class="nav-underline"></span> <span class="absolute bottom-0 left-0 w-0 h-0.5 bg-green-600 group-hover:w-full transition-all duration-300"></span>
</a> </a>
<a href="/events" class="nav-link"> <a href="/events" class="nav-link px-4 py-2 rounded-lg font-medium text-gray-700 hover:text-green-600 hover:bg-green-50 transition-all duration-200 relative group">
Events Events
<span class="nav-underline"></span> <span class="absolute bottom-0 left-0 w-0 h-0.5 bg-green-600 group-hover:w-full transition-all duration-300"></span>
</a> </a>
<a href="/members" class="nav-link"> <a href="/members" class="nav-link px-4 py-2 rounded-lg font-medium text-gray-700 hover:text-green-600 hover:bg-green-50 transition-all duration-200 relative group">
Members Members
<span class="nav-underline"></span> <span class="absolute bottom-0 left-0 w-0 h-0.5 bg-green-600 group-hover:w-full transition-all duration-300"></span>
</a> </a>
<a href="/orphanage" class="nav-link"> <a href="/orphanage" class="nav-link px-4 py-2 rounded-lg font-medium text-gray-700 hover:text-green-600 hover:bg-green-50 transition-all duration-200 relative group">
Orphanage Orphanage
<span class="nav-underline"></span> <span class="absolute bottom-0 left-0 w-0 h-0.5 bg-green-600 group-hover:w-full transition-all duration-300"></span>
</a> </a>
<a href="/contact" class="nav-link"> <a href="/gallery" class="nav-link px-4 py-2 rounded-lg font-medium text-gray-700 hover:text-green-600 hover:bg-green-50 transition-all duration-200 relative group">
Gallery
<span class="absolute bottom-0 left-0 w-0 h-0.5 bg-green-600 group-hover:w-full transition-all duration-300"></span>
</a>
<a href="/contact" class="nav-link px-4 py-2 rounded-lg font-medium text-gray-700 hover:text-green-600 hover:bg-green-50 transition-all duration-200 relative group">
Contact Contact
<span class="nav-underline"></span> <span class="absolute bottom-0 left-0 w-0 h-0.5 bg-green-600 group-hover:w-full transition-all duration-300"></span>
</a> </a>
</div> </div>
<!-- CTA Buttons --> <!-- CTA Buttons -->
<div class="header-cta"> <div class="flex items-center gap-3">
<a href="/donate" class="btn btn-donate"> <a href="/donate" class="inline-flex items-center px-6 py-2 bg-gradient-to-r from-red-500 to-red-600 text-white rounded-lg shadow-lg hover:shadow-xl hover:from-red-600 hover:to-red-700 transition-all duration-200 font-medium">
<svg class="btn-icon" fill="currentColor" viewBox="0 0 20 20"> <svg class="w-4 h-4 mr-2" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M3.172 5.172a4 4 0 015.656 0L10 6.343l1.172-1.171a4 4 0 115.656 5.656L10 17.657l-6.828-6.829a4 4 0 010-5.656z" clip-rule="evenodd"></path> <path fill-rule="evenodd" d="M3.172 5.172a4 4 0 015.656 0L10 6.343l1.172-1.171a4 4 0 115.656 5.656L10 17.657l-6.828-6.829a4 4 0 010-5.656z" clip-rule="evenodd"></path>
</svg> </svg>
Donate Donate
</a> </a>
<a href="/join" class="btn btn-join"> <a href="/join" class="inline-flex items-center px-6 py-2 bg-gradient-to-r from-amber-500 to-amber-600 text-white rounded-lg shadow-lg hover:shadow-xl hover:from-amber-600 hover:to-amber-700 transition-all duration-200 font-medium">
<svg class="btn-icon" fill="currentColor" viewBox="0 0 20 20"> <svg class="w-4 h-4 mr-2" fill="currentColor" viewBox="0 0 20 20">
<path d="M8 9a3 3 0 100-6 3 3 0 000 6zM8 11a6 6 0 016 6H2a6 6 0 016-6zM16 7a1 1 0 10-2 0v1h-1a1 1 0 100 2h1v1a1 1 0 102 0v-1h1a1 1 0 100-2h-1V7z"></path> <path d="M8 9a3 3 0 100-6 3 3 0 000 6zM8 11a6 6 0 016 6H2a6 6 0 016-6zM16 7a1 1 0 10-2 0v1h-1a1 1 0 100 2h1v1a1 1 0 102 0v-1h1a1 1 0 100-2h-1V7z"></path>
</svg> </svg>
Join Us Join Us
</a> </a>
<!-- Mobile menu button --> <!-- Mobile menu button -->
<button class="mobile-menu-btn" id="mobile-menu-btn"> <button class="lg:hidden p-2 rounded-lg hover:bg-gray-100 transition-colors duration-200" onclick="toggleMobileMenu()">
<svg class="mobile-menu-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"></path> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"></path>
</svg> </svg>
</button> </button>
@@ -104,24 +109,27 @@ import '../styles/main.css';
</div> </div>
<!-- Mobile Navigation --> <!-- Mobile Navigation -->
<div id="mobile-menu" class="mobile-menu mobile-menu-hidden"> <div id="mobile-menu" class="lg:hidden hidden bg-white border-t border-gray-200 shadow-lg">
<div class="mobile-menu-content"> <div class="max-w-7xl mx-auto px-4 py-4 space-y-2">
<a href="/home" class="mobile-nav-link"> <a href="/" class="block px-4 py-3 rounded-lg font-medium text-gray-700 hover:text-green-600 hover:bg-green-50 transition-all duration-200">
🏠 Home 🏠 Home
</a> </a>
<a href="/about" class="mobile-nav-link"> <a href="/about" class="block px-4 py-3 rounded-lg font-medium text-gray-700 hover:text-green-600 hover:bg-green-50 transition-all duration-200">
About About
</a> </a>
<a href="/events" class="mobile-nav-link"> <a href="/events" class="block px-4 py-3 rounded-lg font-medium text-gray-700 hover:text-green-600 hover:bg-green-50 transition-all duration-200">
📅 Events 📅 Events
</a> </a>
<a href="/members" class="mobile-nav-link"> <a href="/members" class="block px-4 py-3 rounded-lg font-medium text-gray-700 hover:text-green-600 hover:bg-green-50 transition-all duration-200">
👥 Members 👥 Members
</a> </a>
<a href="/orphanage" class="mobile-nav-link"> <a href="/orphanage" class="block px-4 py-3 rounded-lg font-medium text-gray-700 hover:text-green-600 hover:bg-green-50 transition-all duration-200">
🏠 Orphanage 🏠 Orphanage
</a> </a>
<a href="/contact" class="mobile-nav-link"> <a href="/gallery" class="block px-4 py-3 rounded-lg font-medium text-gray-700 hover:text-green-600 hover:bg-green-50 transition-all duration-200">
🖼️ Gallery
</a>
<a href="/contact" class="block px-4 py-3 rounded-lg font-medium text-gray-700 hover:text-green-600 hover:bg-green-50 transition-all duration-200">
📞 Contact 📞 Contact
</a> </a>
</div> </div>
@@ -130,537 +138,30 @@ import '../styles/main.css';
<script> <script>
function toggleMobileMenu() { function toggleMobileMenu() {
console.log('toggleMobileMenu function called');
const menu = document.getElementById('mobile-menu'); const menu = document.getElementById('mobile-menu');
console.log('Menu element:', menu); menu.classList.toggle('hidden');
if (menu) {
const wasHidden = menu.classList.contains('mobile-menu-hidden');
menu.classList.toggle('mobile-menu-hidden');
const isNowHidden = menu.classList.contains('mobile-menu-hidden');
console.log('Menu was hidden:', wasHidden, 'Menu is now hidden:', isNowHidden);
console.log('Menu classes:', menu.className);
} else {
console.log('Menu element not found!');
} }
}
// Initialize mobile menu functionality
document.addEventListener('DOMContentLoaded', function() {
console.log('DOM loaded, setting up mobile menu');
// Add click event to mobile menu button
const mobileMenuBtn = document.getElementById('mobile-menu-btn');
console.log('Mobile menu button:', mobileMenuBtn);
if (mobileMenuBtn) {
mobileMenuBtn.addEventListener('click', function(e) {
console.log('Mobile menu button clicked!');
e.preventDefault();
toggleMobileMenu();
});
}
// Close mobile menu when clicking outside
document.addEventListener('click', function(event) {
const mobileMenu = document.getElementById('mobile-menu');
const mobileMenuBtn = document.getElementById('mobile-menu-btn');
if (mobileMenu && mobileMenuBtn &&
!mobileMenu.contains(event.target as Node) &&
!mobileMenuBtn.contains(event.target as Node)) {
mobileMenu.classList.add('mobile-menu-hidden');
}
});
// Close mobile menu when clicking on a mobile nav link
const mobileNavLinks = document.querySelectorAll('.mobile-nav-link');
mobileNavLinks.forEach(link => {
link.addEventListener('click', function() {
const menu = document.getElementById('mobile-menu');
if (menu) {
menu.classList.add('mobile-menu-hidden');
}
});
});
// Add active state to current page // Add active state to current page
document.addEventListener('DOMContentLoaded', function() {
const currentPath = window.location.pathname; const currentPath = window.location.pathname;
const navLinks = document.querySelectorAll('.nav-link'); const navLinks = document.querySelectorAll('.nav-link');
// Desktop navigation active state
navLinks.forEach(link => { navLinks.forEach(link => {
const href = link.getAttribute('href'); const href = link.getAttribute('href');
if (href && (href === currentPath || (currentPath !== '/home' && href !== '/home' && currentPath.startsWith(href)))) { if (href === currentPath || (currentPath !== '/' && href !== '/' && currentPath.startsWith(href))) {
link.classList.add('nav-link-active'); link.classList.add('text-green-600', 'bg-green-50');
const underline = link.querySelector('.nav-underline'); const underline = link.querySelector('span');
if (underline) { if (underline) {
underline.classList.add('nav-underline-active'); underline.classList.add('w-full');
} }
} }
}); });
// Mobile navigation active state
mobileNavLinks.forEach(link => {
const href = link.getAttribute('href');
if (href && (href === currentPath || (currentPath !== '/home' && href !== '/home' && currentPath.startsWith(href)))) {
link.classList.add('mobile-nav-link-active');
}
});
}); });
</script> </script>
<style> <style>
/* Header Styles */ /* Add some breathing room for fixed header */
.header {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 50;
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(10px);
border-bottom: 1px solid rgba(229, 229, 229, 0.5);
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.header-content {
max-width: 1200px;
margin: 0 auto;
padding: 0 2rem;
}
/* Top Bar */
.header-top-bar {
display: none;
align-items: center;
justify-content: space-between;
padding: 0.5rem 0;
border-bottom: 1px solid rgba(229, 229, 229, 0.5);
font-size: 0.875rem;
}
@media (min-width: 768px) {
.header-top-bar {
display: flex;
}
}
.header-top-left {
display: flex;
align-items: center;
gap: 1rem;
color: #6b7280;
}
.header-info-item {
display: flex;
align-items: center;
gap: 0.5rem;
}
.header-icon {
width: 1rem;
height: 1rem;
}
.header-icon-green {
color: #16a34a;
}
.header-icon-amber {
color: #f59e0b;
}
.header-top-right {
display: flex;
align-items: center;
gap: 0.25rem;
}
.flag-emoji {
color: #6b7280;
}
.header-heritage-text {
font-weight: 600;
color: #16a34a;
}
/* Main Navigation */
.header-nav {
display: flex;
align-items: center;
justify-content: space-between;
padding: 1rem 0;
gap: 1rem;
}
/* Logo */
.header-logo {
display: flex;
align-items: center;
gap: 0.75rem;
text-decoration: none;
color: inherit;
flex-shrink: 0;
}
.logo-container {
position: relative;
}
.logo-flag {
width: 3rem;
height: 3rem;
border-radius: 50%;
background: linear-gradient(45deg, #16a34a, #ffffff, #16a34a);
padding: 2px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
transition: all 0.3s ease;
}
@media (max-width: 768px) {
.logo-flag {
width: 2.5rem;
height: 2.5rem;
}
}
.header-logo:hover .logo-flag {
box-shadow: 0 8px 12px rgba(0, 0, 0, 0.15);
}
.logo-inner {
width: 100%;
height: 100%;
border-radius: 50%;
background: white;
display: flex;
align-items: center;
justify-content: center;
}
.logo-symbol {
width: 2rem;
height: 2rem;
border-radius: 50%;
background: linear-gradient(135deg, #16a34a, #f59e0b);
display: flex;
align-items: center;
justify-content: center;
}
@media (max-width: 768px) {
.logo-symbol {
width: 1.5rem;
height: 1.5rem;
}
}
.logo-symbol span {
color: white;
font-weight: bold;
font-size: 0.875rem;
}
@media (max-width: 768px) {
.logo-symbol span {
font-size: 0.75rem;
}
}
.logo-accent {
position: absolute;
top: -4px;
right: -4px;
width: 1rem;
height: 1rem;
background: #f59e0b;
border-radius: 50%;
animation: bounce 2s infinite;
}
@media (max-width: 768px) {
.logo-accent {
width: 0.75rem;
height: 0.75rem;
top: -2px;
right: -2px;
}
}
.logo-text {
display: flex;
flex-direction: column;
}
.logo-title {
font-family: 'Poppins', sans-serif;
font-size: 1.5rem;
font-weight: 700;
background: linear-gradient(45deg, #16a34a, #f59e0b);
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
@media (max-width: 768px) {
.logo-title {
font-size: 1.25rem;
}
}
.logo-subtitle {
font-size: 0.875rem;
color: #6b7280;
font-weight: 500;
margin-top: -0.25rem;
}
@media (max-width: 768px) {
.logo-subtitle {
font-size: 0.75rem;
}
}
/* Desktop Navigation */
.header-desktop-nav {
display: none;
align-items: center;
gap: 0.25rem;
}
@media (min-width: 1024px) {
.header-desktop-nav {
display: flex;
}
}
.nav-link {
position: relative;
padding: 0.5rem 1rem;
border-radius: 8px;
font-weight: 500;
color: #374151;
text-decoration: none;
transition: all 0.2s ease;
overflow: hidden;
}
.nav-link:hover {
color: #16a34a;
background: rgba(22, 163, 74, 0.1);
}
.nav-link-active {
color: #16a34a;
background: rgba(22, 163, 74, 0.1);
}
.nav-underline {
position: absolute;
bottom: 0;
left: 0;
width: 0;
height: 2px;
background: #16a34a;
transition: width 0.3s ease;
}
.nav-link:hover .nav-underline,
.nav-underline-active {
width: 100%;
}
/* CTA Buttons */
.header-cta {
display: flex;
align-items: center;
gap: 0.75rem;
flex-shrink: 0;
}
@media (max-width: 768px) {
.header-cta {
gap: 0.5rem;
}
}
.btn {
display: inline-flex;
align-items: center;
padding: 0.5rem 1.5rem;
border-radius: 8px;
font-weight: 500;
text-decoration: none;
transition: all 0.2s ease;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
white-space: nowrap;
}
@media (max-width: 768px) {
.btn {
padding: 0.5rem 1rem;
font-size: 0.875rem;
}
}
.btn:hover {
box-shadow: 0 8px 12px rgba(0, 0, 0, 0.15);
}
.btn-icon {
width: 1rem;
height: 1rem;
margin-right: 0.5rem;
}
@media (max-width: 768px) {
.btn-icon {
width: 0.875rem;
height: 0.875rem;
margin-right: 0.25rem;
}
}
.btn-donate {
background: linear-gradient(45deg, #ef4444, #dc2626);
color: white;
}
.btn-donate:hover {
background: linear-gradient(45deg, #dc2626, #b91c1c);
}
.btn-join {
background: linear-gradient(45deg, #f59e0b, #d97706);
color: white;
}
.btn-join:hover {
background: linear-gradient(45deg, #d97706, #b45309);
}
/* Mobile Menu Button */
.mobile-menu-btn {
display: none;
padding: 0.5rem;
border-radius: 8px;
background: none;
border: none;
cursor: pointer;
transition: background-color 0.2s ease;
flex-shrink: 0;
}
@media (max-width: 1023px) {
.mobile-menu-btn {
display: block;
}
}
.mobile-menu-btn:hover {
background: rgba(0, 0, 0, 0.05);
}
.mobile-menu-icon {
width: 1.5rem;
height: 1.5rem;
}
/* Mobile Menu */
.mobile-menu {
display: none;
background: white;
border-top: 1px solid rgba(229, 229, 229, 0.5);
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.mobile-menu:not(.mobile-menu-hidden) {
display: block;
}
@media (min-width: 1024px) {
.mobile-menu {
display: none !important;
}
}
.mobile-menu-content {
max-width: 1200px;
margin: 0 auto;
padding: 1rem 2rem;
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.mobile-nav-link {
display: block;
padding: 0.75rem 1rem;
border-radius: 8px;
font-weight: 500;
color: #374151;
text-decoration: none;
transition: all 0.2s ease;
}
.mobile-nav-link:hover {
color: #16a34a;
background: rgba(22, 163, 74, 0.1);
}
.mobile-nav-link-active {
color: #16a34a;
background: rgba(22, 163, 74, 0.1);
font-weight: 600;
}
/* Mobile-specific adjustments */
@media (max-width: 768px) {
.header-content {
padding: 0 1rem;
}
.header-nav {
padding: 0.75rem 0;
}
/* Hide desktop buttons on mobile */
.btn {
display: none;
}
/* Show mobile menu button */
.mobile-menu-btn {
display: block;
}
}
@media (min-width: 769px) and (max-width: 1023px) {
/* On tablets, show buttons but make them smaller */
.btn {
padding: 0.5rem 1rem;
font-size: 0.875rem;
}
}
/* Animations */
@keyframes bounce {
0%, 20%, 53%, 80%, 100% {
transform: translate3d(0, 0, 0);
}
40%, 43% {
transform: translate3d(0, -8px, 0);
}
70% {
transform: translate3d(0, -4px, 0);
}
90% {
transform: translate3d(0, -2px, 0);
}
}
/* Body padding for fixed header */
body { body {
padding-top: 120px; padding-top: 120px;
} }
@@ -670,4 +171,26 @@ import '../styles/main.css';
padding-top: 80px; padding-top: 80px;
} }
} }
/* Ensure smooth transitions */
.nav-link {
position: relative;
overflow: hidden;
}
/* Custom bounce animation */
@keyframes bounce {
0%, 20%, 53%, 80%, 100% {
transform: translate3d(0,0,0);
}
40%, 43% {
transform: translate3d(0,-8px,0);
}
70% {
transform: translate3d(0,-4px,0);
}
90% {
transform: translate3d(0,-2px,0);
}
}
</style> </style>

View File

@@ -0,0 +1,225 @@
import { useState, useEffect } from "react";
const slides = [
{
image: "/images/hero1.jpg",
alt: "Nigerian community gathering",
title: "Celebrating Nigerian Culture",
subtitle: "in the Heart of Netherlands",
description: "Join our vibrant community events that showcase the rich traditions, music, and cuisine of Nigeria while building lasting friendships.",
cta: "Join Our Events",
theme: "green"
},
{
image: "/images/hero2.jpg",
alt: "Children at orphanage",
title: "Supporting Our Future",
subtitle: "Orphanage Outreach Program",
description: "Making a real difference in the lives of children through education, healthcare, and providing hope for a brighter tomorrow.",
cta: "Learn More",
theme: "gold"
},
{
image: "/images/hero3.jpg",
alt: "Nigerian textiles and art",
title: "Proud Heritage",
subtitle: "United in Our Mission",
description: "Preserving and promoting Nigerian arts, crafts, and cultural traditions while fostering integration in Dutch society.",
cta: "Explore Culture",
theme: "red"
},
];
const themeColors = {
green: {
primary: "from-green-600 to-green-800",
secondary: "from-green-500 to-green-700",
accent: "bg-green-500",
text: "text-green-600"
},
gold: {
primary: "from-yellow-500 to-orange-600",
secondary: "from-yellow-400 to-orange-500",
accent: "bg-yellow-500",
text: "text-yellow-600"
},
red: {
primary: "from-red-600 to-red-800",
secondary: "from-red-500 to-red-700",
accent: "bg-red-500",
text: "text-red-600"
}
};
export default function HeroCarousel() {
const [currentSlide, setCurrentSlide] = useState(0);
const [isPlaying, setIsPlaying] = useState(true);
useEffect(() => {
if (!isPlaying) return;
const interval = setInterval(() => {
setCurrentSlide((prev) => (prev + 1) % slides.length);
}, 6000);
return () => clearInterval(interval);
}, [isPlaying]);
const nextSlide = () => {
setCurrentSlide((prev) => (prev + 1) % slides.length);
};
const prevSlide = () => {
setCurrentSlide((prev) => (prev - 1 + slides.length) % slides.length);
};
const goToSlide = (index) => {
setCurrentSlide(index);
};
return (
<div className="relative w-full max-w-6xl mx-auto rounded-2xl overflow-hidden shadow-2xl bg-white"
role="region" aria-roledescription="carousel" aria-label="Featured content">
{/* Main Carousel Container */}
<div className="relative h-[600px] overflow-hidden">
{slides.map((slide, index) => {
const theme = themeColors[slide.theme];
return (
<div
key={index}
className={`absolute inset-0 transition-all duration-1000 ease-in-out ${
index === currentSlide
? 'opacity-100 translate-x-0'
: index < currentSlide
? 'opacity-0 -translate-x-full'
: 'opacity-0 translate-x-full'
}`}
role="group"
aria-roledescription="slide"
aria-label={`${index + 1} of ${slides.length}`}
>
{/* Background Image */}
<div className="absolute inset-0">
<img
src={slide.image}
alt={slide.alt}
className="w-full h-full object-cover"
/>
<div className={`absolute inset-0 bg-gradient-to-r ${theme.primary} opacity-80`}></div>
<div className="absolute inset-0 bg-gradient-to-t from-black/50 via-transparent to-transparent"></div>
</div>
{/* Content */}
<div className="relative z-10 h-full flex items-center">
<div className="container mx-auto px-8">
<div className="max-w-2xl text-white">
{/* Animated Content */}
<div className={`transition-all duration-1000 delay-300 ${
index === currentSlide ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-8'
}`}>
<div className="flex items-center gap-3 mb-4">
<div className={`w-2 h-12 ${theme.accent} rounded-full`}></div>
<span className="text-sm font-semibold uppercase tracking-wider opacity-90">
Omoluabi Foundation
</span>
</div>
<h1 className="text-5xl md:text-6xl font-bold mb-2 leading-tight">
{slide.title}
</h1>
<h2 className="text-2xl md:text-3xl font-light mb-6 text-yellow-200">
{slide.subtitle}
</h2>
<p className="text-lg md:text-xl mb-8 leading-relaxed opacity-90 max-w-xl">
{slide.description}
</p>
<div className="flex flex-col sm:flex-row gap-4">
<button className="bg-white dark:bg-gray-900 dark:text-white text-gray-900 px-8 py-4 rounded-xl font-bold hover:bg-gray-100 dark:hover:bg-gray-800 transition-all duration-300 transform hover:scale-105 shadow-lg">
{slide.cta}
</button>
<button className="border-2 border-white text-white px-8 py-4 rounded-xl font-bold hover:bg-white hover:text-gray-900 dark:hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
Learn More
</button>
</div>
</div>
</div>
</div>
</div>
{/* Decorative Elements */}
<div className="absolute top-10 right-10 w-32 h-32 border-2 border-white/20 rounded-full animate-spin" style={{animationDuration: '20s'}}></div>
<div className="absolute bottom-10 left-10 w-24 h-24 border-2 border-white/20 rounded-full animate-bounce"></div>
</div>
);
})}
</div>
{/* Navigation Arrows */}
<button
onClick={prevSlide}
className="absolute left-4 top-1/2 -translate-y-1/2 bg-white/20 backdrop-blur-sm hover:bg-white/30 text-white p-3 rounded-full transition-all duration-300 hover:scale-110 group"
aria-label="Previous slide"
>
<svg className="w-6 h-6 group-hover:-translate-x-1 transition-transform" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
</svg>
</button>
<button
onClick={nextSlide}
className="absolute right-4 top-1/2 -translate-y-1/2 bg-white/20 backdrop-blur-sm hover:bg-white/30 text-white p-3 rounded-full transition-all duration-300 hover:scale-110 group"
aria-label="Next slide"
>
<svg className="w-6 h-6 group-hover:translate-x-1 transition-transform" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
</svg>
</button>
{/* Slide Indicators */}
<div className="absolute bottom-6 left-1/2 -translate-x-1/2 flex gap-3">
{slides.map((_, index) => (
<button
key={index}
onClick={() => goToSlide(index)}
className={`w-3 h-3 rounded-full transition-all duration-300 ${
index === currentSlide
? 'bg-white scale-125'
: 'bg-white/50 hover:bg-white/75'
}`}
aria-label={`Go to slide ${index + 1}`}
/>
))}
</div>
{/* Play/Pause Button */}
<button
onClick={() => setIsPlaying(!isPlaying)}
className="absolute top-4 right-4 bg-white/20 backdrop-blur-sm hover:bg-white/30 text-white p-2 rounded-full transition-all duration-300 hover:scale-110"
aria-label={isPlaying ? "Pause slideshow" : "Play slideshow"}
aria-pressed={!isPlaying}
>
{isPlaying ? (
<svg className="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
<path fillRule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zM7 8a1 1 0 012 0v4a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v4a1 1 0 102 0V8a1 1 0 00-1-1z" clipRule="evenodd" />
</svg>
) : (
<svg className="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
<path fillRule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM9.555 7.168A1 1 0 008 8v4a1 1 0 001.555.832l3-2a1 1 0 000-1.664l-3-2z" clipRule="evenodd" />
</svg>
)}
</button>
{/* Progress Bar */}
<div className="absolute bottom-0 left-0 right-0 h-1 bg-white/20">
<div
className="h-full bg-gradient-to-r from-yellow-400 to-red-500 transition-all duration-100"
style={{
width: `${((currentSlide + 1) / slides.length) * 100}%`
}}
/>
</div>
</div>
);
}

View File

@@ -1,34 +0,0 @@
---
import '../styles/main.css';
// Hero section for homepage
---
<section class="hero">
<div class="floating-element floating-1"></div>
<div class="floating-element floating-2"></div>
<div class="floating-element floating-3"></div>
<div class="hero-content">
<h1 class="hero-title">
<span class="hero-title-shine">Welcome to<br/>
Omoluabi Association</span>
</h1>
<p class="hero-subtitle">
<strong>Bridging cultures, Building communities</strong><br/>
Supporting Nigerians in the Netherlands with unity, heritage, and hope
</p>
<div class="hero-symbols">
<span>🇳🇬</span>
<span style="color: #f59e0b;">•</span>
<span>🤝</span>
<span style="color: #f59e0b;">•</span>
<span>🇳🇱</span>
</div>
<div class="hero-cta">
<a href="/join" class="btn" style="background: white; color: #16a34a; padding: 1rem 2rem; font-size: 1.125rem;">
👥 Join Our Community
</a>
<a href="/events" class="btn btn-outline" style="padding: 1rem 2rem; font-size: 1.125rem;">
📅 View Events
</a>
</div>
</div>
</section>

View File

@@ -2,13 +2,24 @@
const gallery = await Astro.glob('../../content/gallery/gallery-sample.md'); const gallery = await Astro.glob('../../content/gallery/gallery-sample.md');
const images = gallery[0]?.frontmatter.images || []; const images = gallery[0]?.frontmatter.images || [];
--- ---
<section class="max-w-6xl mx-auto my-20"> <section class="max-w-6xl mx-auto my-20 px-4">
<h2 class="text-2xl font-headline font-bold mb-6 text-primary text-center">Gallery</h2> <h2 class="text-3xl font-headline font-bold mb-6 text-nigerian-green-700 dark:text-kente-gold-400 text-center">Our Photo Gallery</h2>
<p class="text-center text-lg text-gray-600 dark:text-gray-300 mb-10">
A glimpse into our vibrant community and cultural celebrations.
</p>
<div class="grid grid-cols-2 md:grid-cols-4 gap-4"> <div class="grid grid-cols-2 md:grid-cols-4 gap-4">
{images.map((img, idx) => ( {images.slice(0, 4).map((img: string, idx: number) => (
<div class="rounded-lg overflow-hidden shadow-md bg-base-100" key={idx}> <div class="rounded-lg overflow-hidden shadow-md bg-white dark:bg-gray-800">
<img src={img} alt={`Gallery photo ${idx + 1}`} class="w-full h-40 object-cover hover:scale-105 transition-transform duration-200 cursor-pointer" /> <img src={img} alt={`Gallery photo ${idx + 1}`} class="w-full h-40 object-cover hover:scale-105 transition-transform duration-200 cursor-pointer" />
</div> </div>
))} ))}
</div> </div>
<div class="text-center mt-10">
<a href="/gallery" class="inline-flex items-center px-6 py-3 bg-gradient-to-r from-nigerian-green-500 to-kente-gold-500 text-white rounded-lg shadow-lg hover:shadow-xl hover:from-nigerian-green-600 hover:to-kente-gold-600 transition-all duration-200 font-medium">
View Full Gallery
<svg class="w-5 h-5 ml-2" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M4 3a2 2 0 00-2 2v10a2 2 0 002 2h12a2 2 0 002-2V5a2 2 0 00-2-2H4zm12 12H4l4-8 3 6 2-4 3 6z" clip-rule="evenodd"></path>
</svg>
</a>
</div>
</section> </section>

View File

@@ -0,0 +1,58 @@
import React, { useState } from 'react';
import Lightbox from './Lightbox.jsx'; // Assuming Lightbox component will be created
export default function ImageGallery({ images }) {
const [isOpen, setIsOpen] = useState(false);
const [currentImageIndex, setCurrentImageIndex] = useState(0);
const openLightbox = (index) => {
setCurrentImageIndex(index);
setIsOpen(true);
};
const closeLightbox = () => {
setIsOpen(false);
};
const goToNext = () => {
setCurrentImageIndex((prevIndex) => (prevIndex + 1) % images.length);
};
const goToPrev = () => {
setCurrentImageIndex((prevIndex) => (prevIndex - 1 + images.length) % images.length);
};
return (
<div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
{images.map((image, index) => (
<div
key={index}
className="relative overflow-hidden rounded-lg shadow-md cursor-pointer group"
onClick={() => openLightbox(index)}
>
<img
src={image}
alt={`Gallery image ${index + 1}`}
className="w-full h-48 object-cover transform transition-transform duration-300 group-hover:scale-110"
/>
<div className="absolute inset-0 bg-black bg-opacity-40 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity duration-300">
<svg className="w-10 h-10 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path>
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"></path>
</svg>
</div>
</div>
))}
{isOpen && (
<Lightbox
images={images}
currentIndex={currentImageIndex}
onClose={closeLightbox}
onNext={goToNext}
onPrev={goToPrev}
/>
)}
</div>
);
}

View File

@@ -0,0 +1,69 @@
import React, { useEffect } from 'react';
export default function Lightbox({ images, currentIndex, onClose, onNext, onPrev }) {
useEffect(() => {
const handleKeyDown = (e) => {
if (e.key === 'Escape') {
onClose();
} else if (e.key === 'ArrowRight') {
onNext();
} else if (e.key === 'ArrowLeft') {
onPrev();
}
};
document.addEventListener('keydown', handleKeyDown);
return () => {
document.removeEventListener('keydown', handleKeyDown);
};
}, [onClose, onNext, onPrev]);
if (!images || images.length === 0) return null;
return (
<div className="fixed inset-0 z-[9999] bg-black bg-opacity-90 flex items-center justify-center p-4" onClick={onClose}
role="dialog" aria-modal="true" aria-label="Image viewer">
<div className="relative max-w-5xl max-h-full" onClick={(e) => e.stopPropagation()}> {/* Prevent closing when clicking on image */}
<img
src={images[currentIndex]}
alt={`Gallery image ${currentIndex + 1}`}
className="max-w-full max-h-[80vh] object-contain rounded-lg shadow-xl"
/>
{/* Close Button */}
<button
className="absolute top-4 right-4 text-white text-3xl p-2 rounded-full bg-white/20 hover:bg-white/40 transition-colors duration-200"
onClick={onClose}
aria-label="Close Lightbox"
>
&times;
</button>
{/* Navigation Buttons */}
{images.length > 1 && (
<>
<button
className="absolute left-4 top-1/2 -translate-y-1/2 text-white text-4xl p-2 rounded-full bg-white/20 hover:bg-white/40 transition-colors duration-200"
onClick={onPrev}
aria-label="Previous Image"
>
&lsaquo;
</button>
<button
className="absolute right-4 top-1/2 -translate-y-1/2 text-white text-4xl p-2 rounded-full bg-white/20 hover:bg-white/40 transition-colors duration-200"
onClick={onNext}
aria-label="Next Image"
>
&rsaquo;
</button>
</>
)}
{/* Image Counter */}
<div className="absolute bottom-4 left-1/2 -translate-x-1/2 text-white text-lg bg-black/50 px-4 py-2 rounded-full">
{currentIndex + 1} / {images.length}
</div>
</div>
</div>
);
}

View File

@@ -0,0 +1,42 @@
import { useEffect, useState } from 'react';
export default function ThemeToggle() {
const [isDark, setIsDark] = useState(false);
useEffect(() => {
const stored = localStorage.getItem('omoluabi_theme');
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
const initial = stored ? stored === 'dark' : prefersDark;
setIsDark(initial);
document.documentElement.classList.toggle('dark', initial);
}, []);
const toggle = () => {
const next = !isDark;
setIsDark(next);
document.documentElement.classList.toggle('dark', next);
localStorage.setItem('omoluabi_theme', next ? 'dark' : 'light');
};
return (
<button
onClick={toggle}
className="inline-flex items-center gap-2 px-3 py-2 rounded-lg border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors"
aria-label="Toggle color theme"
>
{isDark ? (
<>
<svg xmlns="http://www.w3.org/2000/svg" className="h-4 w-4" fill="currentColor" viewBox="0 0 24 24"><path d="M21.64 13a1 1 0 0 0-1.05-.14 8 8 0 1 1-9.45-9.45 1 1 0 0 0-.14-2A10 10 0 1 0 23 14a1 1 0 0 0-1.36-1z"/></svg>
<span className="text-sm">Dark</span>
</>
) : (
<>
<svg xmlns="http://www.w3.org/2000/svg" className="h-4 w-4" fill="currentColor" viewBox="0 0 24 24"><path d="M6.76 4.84l-1.8-1.79-1.41 1.41 1.79 1.8 1.42-1.42zm10.45 14.32l1.79 1.8 1.41-1.41-1.8-1.79-1.4 1.4zM12 4a1 1 0 0 1 1 1v2a1 1 0 1 1-2 0V5a1 1 0 0 1 1-1zm0 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8zm8-5h-2a1 1 0 1 1 0-2h2a1 1 0 1 1 0 2zM4 13H2a1 1 0 1 1 0-2h2a1 1 0 1 1 0 2zm2.76 6.36l-1.42 1.42-1.79-1.8 1.41-1.41 1.8 1.79zM19.78 4.46l-1.41-1.41-1.8 1.79 1.41 1.41 1.8-1.79z"/></svg>
<span className="text-sm">Light</span>
</>
)}
</button>
);
}

View File

@@ -1,41 +1,170 @@
--- ---
// Base layout for all pages // src/layouts/BaseLayout.astro
import Header from '../components/Header.astro'; import '../styles/global.css';
import Footer from '../components/Footer.astro'; import '../styles/main.css';
import ThemeToggle from '../components/ThemeToggle.jsx';
export interface Props {
title?: string;
description?: string;
lang?: string;
}
const { title = "Omoluabi Association Netherlands", description = "Preserving Nigerian culture and heritage in the Netherlands" } = Astro.props;
--- ---
<html lang="en">
<!DOCTYPE html>
<html lang={Astro.props.lang ?? 'en'}>
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Omoluabi Association</title> <title>{title}</title>
<meta name="description" content="Supporting Nigerians in the Netherlands" /> <meta name="description" content={description} />
<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="alternate" hreflang="en" href="/en/" />
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Poppins:wght@400;500;600;700;800&display=swap" rel="stylesheet"> <link rel="alternate" hreflang="nl" href="/nl/" />
<slot name="head" /> <link rel="alternate" hreflang="x-default" href="/" />
</head> </head>
<body style="
font-family: 'Inter', system-ui, sans-serif; <body class="bg-gray-50 dark:bg-gray-900 text-gray-900 dark:text-gray-100">
margin: 0; <a href="#main" class="sr-only focus:not-sr-only focus:fixed focus:top-2 focus:left-2 focus:z-50 focus:bg-white focus:text-black focus:px-3 focus:py-2 focus:rounded">
padding: 0; Skip to main content
background: linear-gradient(135deg, #fafafa 0%, #f0fdf4 100%); </a>
min-height: 100vh; <!-- Navigation Header -->
display: flex; <header class="bg-white dark:bg-gray-900/95 backdrop-blur shadow-md sticky top-0 z-50 border-b border-gray-200 dark:border-white/10">
flex-direction: column; <nav class="container mx-auto px-4 py-4">
padding-top: 80px; <div class="flex items-center justify-between">
"> <!-- Logo -->
<Header /> <div class="flex items-center space-x-2">
<main style="flex: 1;"> <div class="w-10 h-10 bg-gradient-to-br from-nigerian-green-500 to-kente-gold-500 rounded-full flex items-center justify-center">
<span class="text-white font-bold text-lg">O</span>
</div>
<div>
<div class="font-headline font-bold text-xl text-nigerian-green-700">Omoluabi</div>
<div class="text-sm text-gray-600">Foundation</div>
</div>
</div>
<!-- Desktop Navigation -->
<div class="hidden md:flex items-center space-x-8">
<a href="/" class="text-gray-900 dark:text-gray-200 hover:text-nigerian-green-700 dark:hover:text-kente-gold-400 transition-colors">Home</a>
<a href="/about" class="text-gray-900 dark:text-gray-200 hover:text-nigerian-green-700 dark:hover:text-kente-gold-400 transition-colors">About</a>
<a href="/events" class="text-gray-900 dark:text-gray-200 hover:text-nigerian-green-700 dark:hover:text-kente-gold-400 transition-colors">Events</a>
<a href="/members" class="text-gray-900 dark:text-gray-200 hover:text-nigerian-green-700 dark:hover:text-kente-gold-400 transition-colors">Members</a>
<a href="/orphanage" class="text-gray-900 dark:text-gray-200 hover:text-nigerian-green-700 dark:hover:text-kente-gold-400 transition-colors">Orphanage</a>
<a href="/gallery" class="text-gray-900 dark:text-gray-200 hover:text-nigerian-green-700 dark:hover:text-kente-gold-400 transition-colors">Gallery</a>
<a href="/contact" class="text-gray-900 dark:text-gray-200 hover:text-nigerian-green-700 dark:hover:text-kente-gold-400 transition-colors">Contact</a>
</div>
<!-- Right side controls -->
<div class="hidden md:flex items-center space-x-4">
<astro-island>
<ThemeToggle client:load />
</astro-island>
<a href="/donate" class="btn bg-gradient-to-r from-ankara-red-500 to-kente-gold-500 text-white hover:shadow-lg">
❤️ Donate
</a>
<a href="/join" class="btn bg-gradient-to-r from-nigerian-green-500 to-kente-gold-500 text-white hover:shadow-lg">
⭐ Join Us
</a>
</div>
<!-- Mobile menu button -->
<button class="md:hidden text-gray-900 dark:text-gray-200" id="mobile-menu-button" aria-controls="mobile-menu" aria-expanded="false">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"></path>
</svg>
</button>
</div>
<!-- Mobile menu -->
<div class="md:hidden hidden" id="mobile-menu">
<div class="mt-2 rounded-lg bg-white dark:bg-gray-800 shadow-lg ring-1 ring-gray-900/5 dark:ring-white/10 pt-4 pb-2 space-y-2">
<a href="/" class="block px-3 py-2 text-gray-900 dark:text-gray-200 hover:text-nigerian-green-700 dark:hover:text-kente-gold-400">Home</a>
<a href="/about" class="block px-3 py-2 text-gray-900 dark:text-gray-200 hover:text-nigerian-green-700 dark:hover:text-kente-gold-400">About</a>
<a href="/events" class="block px-3 py-2 text-gray-900 dark:text-gray-200 hover:text-nigerian-green-700 dark:hover:text-kente-gold-400">Events</a>
<a href="/members" class="block px-3 py-2 text-gray-900 dark:text-gray-200 hover:text-nigerian-green-700 dark:hover:text-kente-gold-400">Members</a>
<a href="/orphanage" class="block px-3 py-2 text-gray-900 dark:text-gray-200 hover:text-nigerian-green-700 dark:hover:text-kente-gold-400">Orphanage</a>
<a href="/gallery" class="block px-3 py-2 text-gray-900 dark:text-gray-200 hover:text-nigerian-green-700 dark:hover:text-kente-gold-400">Gallery</a>
<a href="/contact" class="block px-3 py-2 text-gray-900 dark:text-gray-200 hover:text-nigerian-green-700 dark:hover:text-kente-gold-400">Contact</a>
<div class="pt-4 space-y-2">
<a href="/donate" class="block btn bg-gradient-to-r from-ankara-red-500 to-kente-gold-500 text-white text-center">❤️ Donate</a>
<a href="/join" class="block btn bg-gradient-to-r from-nigerian-green-500 to-kente-gold-500 text-white text-center">⭐ Join Us</a>
</div>
</div>
</div>
</nav>
</header>
<!-- Main Content -->
<main id="main" tabindex="-1">
<slot /> <slot />
</main> </main>
<Footer />
<!-- Footer -->
<footer class="bg-gray-900 text-white py-12">
<div class="container">
<div class="grid grid-cols-1 md:grid-cols-4 gap-8">
<div class="md:col-span-2">
<div class="flex items-center space-x-2 mb-4">
<div class="w-10 h-10 bg-gradient-to-br from-nigerian-green-500 to-kente-gold-500 rounded-full flex items-center justify-center">
<span class="text-white font-bold text-lg">O</span>
</div>
<div>
<div class="font-headline font-bold text-xl">Omoluabi Foundation</div>
<div class="text-sm text-gray-400">Netherlands</div>
</div>
</div>
<p class="text-gray-300 mb-4">
Preserving Nigerian culture and heritage while building stronger communities in the Netherlands.
</p>
</div>
<div>
<h3 class="font-semibold mb-4">Quick Links</h3>
<ul class="space-y-2 text-sm">
<li><a href="/about" class="text-gray-300 hover:text-white transition-colors">About Us</a></li>
<li><a href="/events" class="text-gray-300 hover:text-white transition-colors">Events</a></li>
<li><a href="/members" class="text-gray-300 hover:text-white transition-colors">Members</a></li>
<li><a href="/orphanage" class="text-gray-300 hover:text-white transition-colors">Orphanage</a></li>
</ul>
</div>
<div>
<h3 class="font-semibold mb-4">Contact Info</h3>
<ul class="space-y-2 text-sm text-gray-300">
<li>📍 Amsterdam, Netherlands</li>
<li>📞 +31 (0) 123 456 789</li>
<li>📧 info@omoluabi.nl</li>
</ul>
</div>
</div>
<div class="border-t border-gray-800 mt-8 pt-8 text-center text-sm text-gray-400">
<p>&copy; 2024 Omoluabi Association Netherlands. All rights reserved.</p>
</div>
</div>
</footer>
<!-- Scripts -->
<script>
document.addEventListener('DOMContentLoaded', () => {
const mobileMenuButton = document.getElementById('mobile-menu-button');
const mobileMenu = document.getElementById('mobile-menu');
if (mobileMenuButton && mobileMenu) {
mobileMenuButton.addEventListener('click', () => {
const isHidden = mobileMenu.classList.toggle('hidden');
mobileMenuButton.setAttribute('aria-expanded', String(!isHidden));
});
}
const observerOptions = { threshold: 0.1, rootMargin: '0px 0px -50px 0px' };
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => { if (entry.isIntersecting) { entry.target.classList.add('visible'); } });
}, observerOptions);
document.querySelectorAll('[data-animate-on-scroll]').forEach(el => observer.observe(el));
});
</script>
</body> </body>
</html> </html>
<style>
@media (min-width: 768px) {
body {
padding-top: 120px !important;
}
}
</style>

View File

@@ -1,606 +1,254 @@
--- ---
// About page for Omoluabi Association with modern design import BaseLayout from '../layouts/BaseLayout.astro';
import Header from '../components/Header.astro';
import Footer from '../components/Footer.astro';
--- ---
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>About - Omoluabi Association</title>
<meta name="description" content="Learn about Omoluabi Association, our mission, values, and the dedicated team behind our community initiatives." />
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body { <BaseLayout>
font-family: 'Inter', system-ui, sans-serif; <!-- Clean header -->
background: linear-gradient(135deg, #fafafa 0%, #f0fdf4 100%); <section class="brand-surface relative py-20 px-4 text-center text-white overflow-hidden" data-animate-on-scroll="fade-in">
min-height: 100vh; <div class="relative z-10 max-w-4xl mx-auto">
line-height: 1.6; <div class="flex items-center justify-center gap-2 mb-4 text-sm text-white/90">
} <a href="/" class="hover:underline">Home</a>
<span class="opacity-60">/</span>
/* Main Content */ <span>About</span>
.main-content {
padding-top: 5rem;
}
/* Page Header */
.page-header {
background: linear-gradient(135deg, #16a34a 0%, #f59e0b 50%, #dc2626 100%);
color: white;
padding: 4rem 2rem;
text-align: center;
position: relative;
overflow: hidden;
}
.page-header::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-image: url("data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%23ffffff' fill-opacity='0.05'%3E%3Cpath d='M36 34v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zm0-30V0h-2v4h-4v2h4v4h2V6h4V4h-4zM6 34v-4H4v4H0v2h4v4h2v-4h4v-2H6zM6 4V0H4v4H0v2h4v4h2V6h4V4H6z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
pointer-events: none;
}
.page-header-content {
max-width: 1200px;
margin: 0 auto;
position: relative;
z-index: 10;
}
.about-title {
font-size: 3.5rem;
font-weight: 700;
margin-bottom: 1rem;
position: relative;
z-index: 1;
}
.page-subtitle {
font-size: 1.25rem;
opacity: 0.9;
max-width: 600px;
margin: 0 auto;
position: relative;
z-index: 1;
}
@keyframes textShine {
0% { background-position: 0% 50%; }
100% { background-position: 100% 50%; }
}
/* Content Sections */
.content-section {
padding: 4rem 2rem;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
.section-title {
font-size: 2.5rem;
font-weight: 700;
text-align: center;
margin-bottom: 1rem;
color: #16a34a;
}
.section-subtitle {
font-size: 1.125rem;
text-align: center;
color: #6b7280;
margin-bottom: 3rem;
max-width: 600px;
margin-left: auto;
margin-right: auto;
}
/* Mission & Vision */
.mission-vision-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 3rem;
margin-bottom: 4rem;
}
.mission-card, .vision-card {
background: white;
padding: 2.5rem;
border-radius: 1rem;
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
text-align: center;
position: relative;
overflow: hidden;
}
.mission-card::before, .vision-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 4px;
}
.mission-card::before {
background: linear-gradient(90deg, #16a34a, #f59e0b);
}
.vision-card::before {
background: linear-gradient(90deg, #f59e0b, #dc2626);
}
.card-icon {
font-size: 3rem;
margin-bottom: 1rem;
}
.card-title {
font-size: 1.5rem;
font-weight: 700;
margin-bottom: 1rem;
color: #111827;
}
.card-content {
color: #6b7280;
line-height: 1.7;
}
/* Values Section */
.values-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 2rem;
margin-bottom: 4rem;
}
.value-card {
background: white;
padding: 2rem;
border-radius: 1rem;
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.1);
text-align: center;
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.value-card:hover {
transform: translateY(-5px);
box-shadow: 0 15px 30px rgba(0, 0, 0, 0.15);
}
.value-icon {
font-size: 2.5rem;
margin-bottom: 1rem;
}
.value-title {
font-size: 1.25rem;
font-weight: 600;
margin-bottom: 0.75rem;
color: #111827;
}
.value-description {
color: #6b7280;
line-height: 1.6;
}
/* Team Section */
.team-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 2rem;
margin-bottom: 4rem;
}
.team-member {
background: white;
border-radius: 1rem;
overflow: hidden;
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.1);
transition: transform 0.3s ease;
}
.team-member:hover {
transform: translateY(-5px);
}
.member-image {
width: 100%;
height: 200px;
object-fit: cover;
}
.member-info {
padding: 1.5rem;
text-align: center;
}
.member-name {
font-size: 1.25rem;
font-weight: 600;
margin-bottom: 0.5rem;
color: #111827;
}
.member-role {
color: #16a34a;
font-weight: 500;
margin-bottom: 0.75rem;
}
.member-bio {
color: #6b7280;
font-size: 0.875rem;
line-height: 1.5;
}
/* Stats Section */
.stats-section {
background: linear-gradient(135deg, #16a34a 0%, #f59e0b 100%);
color: white;
padding: 4rem 2rem;
text-align: center;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 2rem;
max-width: 800px;
margin: 0 auto;
}
.stat-item {
text-align: center;
}
.stat-number {
font-size: 3rem;
font-weight: 800;
margin-bottom: 0.5rem;
display: block;
}
.stat-label {
font-size: 1.125rem;
opacity: 0.9;
}
/* Timeline */
.timeline {
position: relative;
max-width: 800px;
margin: 0 auto;
}
.timeline::before {
content: '';
position: absolute;
left: 50%;
top: 0;
bottom: 0;
width: 2px;
background: #e5e7eb;
transform: translateX(-50%);
}
.timeline-item {
position: relative;
margin-bottom: 3rem;
}
.timeline-item:nth-child(odd) .timeline-content {
margin-left: 0;
margin-right: 50%;
padding-right: 2rem;
text-align: right;
}
.timeline-item:nth-child(even) .timeline-content {
margin-left: 50%;
margin-right: 0;
padding-left: 2rem;
text-align: left;
}
.timeline-dot {
position: absolute;
left: 50%;
top: 0;
width: 1rem;
height: 1rem;
background: #16a34a;
border-radius: 50%;
transform: translateX(-50%);
border: 3px solid white;
box-shadow: 0 0 0 3px #e5e7eb;
}
.timeline-content {
background: white;
padding: 1.5rem;
border-radius: 0.5rem;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
.timeline-year {
font-weight: 700;
color: #16a34a;
margin-bottom: 0.5rem;
}
.timeline-title {
font-weight: 600;
margin-bottom: 0.5rem;
color: #111827;
}
.timeline-description {
color: #6b7280;
font-size: 0.875rem;
}
/* Responsive Design */
@media (max-width: 768px) {
.page-title {
font-size: 2.5rem;
}
.mission-vision-grid {
grid-template-columns: 1fr;
gap: 2rem;
}
.timeline::before {
left: 1rem;
}
.timeline-item:nth-child(odd) .timeline-content,
.timeline-item:nth-child(even) .timeline-content {
margin-left: 3rem;
margin-right: 0;
padding-left: 1rem;
padding-right: 0;
text-align: left;
}
.timeline-dot {
left: 1rem;
}
}
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.5; }
}
</style>
</head>
<body>
<Header />
<!-- Main Content -->
<main class="main-content">
<!-- Page Header -->
<header class="page-header">
<div class="page-header-content">
<h1 class="about-title">About Omoluabi</h1>
<p class="page-subtitle">Discover our story, mission, and the values that drive our community forward</p>
</div> </div>
</header>
<!-- Mission & Vision --> <h1 class="font-headline text-5xl md:text-6xl font-extrabold mb-4 leading-tight">About Us</h1>
<section class="content-section"> <p class="text-lg md:text-xl opacity-90 max-w-2xl mx-auto leading-relaxed">
We connect <span class="font-semibold">Nigerian culture</span> with
<span class="font-semibold">Dutch society</span>—supporting families
and building opportunities across the Netherlands.
</p>
<div class="mt-6 flex items-center justify-center gap-3">
<span class="inline-flex items-center gap-2 text-sm bg-white/10 px-3 py-1 rounded-full border border-white/20">🇳🇬 Nigeria</span>
<span class="inline-flex items-center gap-2 text-sm bg-white/10 px-3 py-1 rounded-full border border-white/20">🇳🇱 Netherlands</span>
</div>
</div>
</section>
<!-- Main About Section -->
<section class="section bg-white dark:bg-gray-900" data-animate-on-scroll="fade-in">
<div class="container"> <div class="container">
<div class="mission-vision-grid"> <div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
<div class="mission-card"> <div class="relative lg:order-2">
<div class="card-icon">🎯</div> <img src="/images/whoAreWe.webp" alt="Omoluabi Association Members" class="w-full h-96 object-cover rounded-2xl shadow-xl" />
<h2 class="card-title">Our Mission</h2> </div>
<p class="card-content"> <div class="lg:order-1">
To promote and preserve Yoruba cultural heritage while fostering unity, education, and community development among Nigerians in the Netherlands and beyond. <h2 class="font-headline text-3xl md:text-4xl font-bold text-gray-900 dark:text-white mb-4">Omoluabi Association in the Netherlands (OAN)</h2>
<p class="text-gray-700 dark:text-gray-300 leading-relaxed text-lg mb-4">The <strong class="text-nigerian-green-600 dark:text-nigerian-green-400">Omoluabi Association</strong> is a panYoruba, communityled organization welcoming everyone who shares our values.</p>
<p class="text-gray-700 dark:text-gray-300 leading-relaxed text-lg mb-4">Founded on <strong class="text-kente-gold-600 dark:text-kente-gold-300">May 1, 2018</strong>, we preserve culture, support families, and build bridges with Dutch institutions.</p>
<div class="grid grid-cols-2 sm:grid-cols-4 gap-4 mt-6">
<div class="text-center p-4 bg-gray-50 dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700"><div class="text-2xl font-bold text-nigerian-green-600">2018</div><div class="text-sm text-gray-600 dark:text-gray-300">Established</div></div>
<div class="text-center p-4 bg-gray-50 dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700"><div class="text-2xl font-bold text-kente-gold-600">500+</div><div class="text-sm text-gray-600 dark:text-gray-300">Members</div></div>
<div class="text-center p-4 bg-gray-50 dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700"><div class="text-2xl font-bold text-ankara-red-600">50+</div><div class="text-sm text-gray-600 dark:text-gray-300">Events</div></div>
<div class="text-center p-4 bg-gray-50 dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700"><div class="text-2xl font-bold text-adire-blue-600">€50K+</div><div class="text-sm text-gray-600 dark:text-gray-300">Raised</div></div>
</div>
</div>
</div>
</div>
</section>
<!-- WHO ARE WE Section -->
<section class="section bg-white dark:bg-gray-900" data-animate-on-scroll="fade-in">
<div class="container">
<div class="text-center mb-12">
<h2 class="font-headline text-4xl font-bold text-gray-900 dark:text-white mb-3">Who are we?</h2>
<p class="text-lg text-gray-600 dark:text-gray-300 max-w-2xl mx-auto">The meaning and values behind the name “Omoluabi”.</p>
</div>
<div class="bg-gradient-to-r from-nigerian-green-50 via-kente-gold-50 to-ankara-red-50 dark:from-gray-800 dark:via-gray-800 dark:to-gray-800 p-8 rounded-2xl mb-12 shadow-inner">
<div class="text-center mb-6">
<h3 class="font-headline text-2xl font-bold text-nigerian-green-700 dark:text-nigerian-green-400 mb-4">
🌟 The Meaning of "Omoluabi"
</h3>
<p class="text-xl text-gray-800 dark:text-gray-200 leading-relaxed">
Omoluabi is a Yoruba word that signifies <strong class="text-kente-gold-600 dark:text-kente-gold-300">"WELL BRED INDIVIDUAL"</strong> (Omtrent het gedrag)
</p> </p>
</div> </div>
<div class="vision-card">
<div class="card-icon">🌟</div> <p class="text-gray-700 dark:text-gray-300 leading-relaxed text-lg text-center">
<h2 class="card-title">Our Vision</h2> This choice of name was unilaterally agreed upon by all our members to bear as an association. The attributes associated with this dignifying name represent the core values we uphold and embody in our daily lives.
<p class="card-content"> </p>
To be the leading cultural organization that bridges Nigerian heritage with Dutch society, creating a vibrant, inclusive community that celebrates diversity and mutual understanding. </div>
<div>
<h3 class="font-headline text-2xl font-bold text-gray-900 dark:text-white mb-6 text-center">Our values</h3>
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">
{[
['Ọ̀rọ̀ sísọ','Careful spoken words'],
['Ìtẹríba','Respect'],
['Irera eni sile','Humility'],
['Inú rere','Think good about others'],
['Òtítọ́','Truth'],
['Ìwà','Good character'],
['Akínkanjú','Bravery'],
['Isẹ́ sísẹ','Hard working'],
['Ọpọlọ pípé','Highly intelligent']
].map(([title,subtitle]) => (
<div class="p-4 rounded-lg border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 shadow-sm">
<div class="font-semibold text-gray-900 dark:text-white">{title}</div>
<div class="text-gray-600 dark:text-gray-300 text-sm">({subtitle})</div>
</div>
))}
</div>
</div>
</section>
<!-- Mission & Vision Section -->
<section class="section bg-gray-50 dark:bg-gray-900" data-animate-on-scroll="fade-in">
<div class="container">
<div class="text-center mb-12">
<h2 class="font-headline text-4xl font-bold text-gray-900 dark:text-white mb-3">Mission & Vision</h2>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
<div class="bg-white dark:bg-gray-800 p-6 rounded-xl shadow-md border-l-4 border-nigerian-green-500 hover:shadow-lg transition-all duration-200">
<span class="text-3xl mb-3 block">🎯</span>
<h3 class="font-semibold text-xl text-gray-900 dark:text-white mb-2">Motto</h3>
<p class="text-gray-700 dark:text-gray-300 leading-relaxed">
To promote, enhance and exhibit the Yoruba cultural heritage globally with a starting point in The Netherlands.
</p>
</div>
<div class="bg-white dark:bg-gray-800 p-6 rounded-xl shadow-md border-l-4 border-kente-gold-500 hover:shadow-lg transition-all duration-200">
<span class="text-3xl mb-3 block">🤝</span>
<h3 class="font-semibold text-xl text-gray-900 dark:text-white mb-2">Aims and Objectives</h3>
<p class="text-gray-700 dark:text-gray-300 leading-relaxed">
To promote and defend our traditions, values, norms and culture in the western world.
</p>
</div>
<div class="bg-white dark:bg-gray-800 p-6 rounded-xl shadow-md border-l-4 border-ankara-red-500 hover:shadow-lg transition-all duration-200">
<span class="text-3xl mb-3 block">❤️</span>
<h3 class="font-semibold text-xl text-gray-900 dark:text-white mb-2">Our Mission</h3>
<p class="text-gray-700 dark:text-gray-300 leading-relaxed">
To cherish, uphold, and project the honor and dignity of Yoruba culture, language and tradition in Africa and Diaspora.
</p>
</div>
<div class="bg-white dark:bg-gray-800 p-6 rounded-xl shadow-md border-l-4 border-adire-blue-500 hover:shadow-lg transition-all duration-200">
<span class="text-3xl mb-3 block">💡</span>
<h3 class="font-semibold text-xl text-gray-900 dark:text-white mb-2">Our Vision</h3>
<p class="text-gray-700 dark:text-gray-300 leading-relaxed">
To harmonize all resources and strength of our people towards development (cultural, social and economical).
</p>
</div>
<div class="bg-white dark:bg-gray-800 p-6 rounded-xl shadow-md border-l-4 border-nigerian-green-500 hover:shadow-lg transition-all duration-200">
<span class="text-3xl mb-3 block">🎭</span>
<h3 class="font-semibold text-xl text-gray-900 dark:text-white mb-2">Activities</h3>
<p class="text-gray-700 dark:text-gray-300 leading-relaxed">
Promoting cultural heritage, cultural development of Yoruba land, and teaching our children local languages (Yoruba).
</p>
</div>
<div class="bg-white dark:bg-gray-800 p-6 rounded-xl shadow-md border-l-4 border-kente-gold-500 hover:shadow-lg transition-all duration-200">
<span class="text-3xl mb-3 block">🗣️</span>
<h3 class="font-semibold text-xl text-gray-900 dark:text-white mb-2">Slogan</h3>
<p class="text-gray-700 dark:text-gray-300 leading-relaxed">
"ASA WAA! TIWA N TIWA A WA GAN GAN LAWA, WON KO NI FI ELO MIRAN SE WA"
</p> </p>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<!-- Core Values --> <!-- Leadership Section -->
<section class="content-section" style="background: #f9fafb;"> <section class="section bg-white" data-animate-on-scroll="fade-in">
<div class="container"> <div class="container">
<h2 class="section-title">Our Core Values</h2> <div class="text-center mb-12">
<p class="section-subtitle">The principles that guide everything we do</p> <h2 class="font-headline text-4xl font-bold text-gray-900 mb-4">
Meet Our <span class="text-nigerian-green-700">Leadership</span>
</h2>
<p class="text-lg text-gray-600 max-w-2xl mx-auto">
Dedicated leaders guiding our community with wisdom and vision
</p>
<div class="w-24 h-1 bg-gradient-to-r from-nigerian-green-500 to-kente-gold-500 mx-auto rounded-full mt-6"></div>
</div>
<div class="values-grid"> <div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-8">
<div class="value-card"> <div class="bg-white rounded-xl shadow-md overflow-hidden hover:shadow-lg transition-all duration-200">
<div class="value-icon">🤝</div> <div class="w-full h-48 bg-gray-200 flex items-center justify-center text-gray-400 text-sm">Image Placeholder</div>
<h3 class="value-title">Unity</h3> <div class="p-4 text-center">
<p class="value-description">Bringing people together across cultures, backgrounds, and experiences to build stronger communities.</p> <h3 class="font-bold text-lg text-gray-900">Chief (Mrs) Elisabeth Dara King</h3>
<p class="text-sm text-gray-600">Convener & Founder</p>
</div> </div>
<div class="value-card">
<div class="value-icon">🏛️</div>
<h3 class="value-title">Heritage</h3>
<p class="value-description">Preserving and celebrating our rich Yoruba cultural traditions and passing them to future generations.</p>
</div> </div>
<div class="value-card">
<div class="value-icon">📚</div> <div class="bg-white rounded-xl shadow-md overflow-hidden hover:shadow-lg transition-all duration-200">
<h3 class="value-title">Education</h3> <div class="w-full h-48 bg-gray-200 flex items-center justify-center text-gray-400 text-sm">Image Placeholder</div>
<p class="value-description">Promoting learning and knowledge sharing about Nigerian culture, history, and contemporary issues.</p> <div class="p-4 text-center">
<h3 class="font-bold text-lg text-gray-900">Omoluabi Bashorun Micheal Oladosu</h3>
<p class="text-sm text-gray-600">Coordinator</p>
</div> </div>
<div class="value-card">
<div class="value-icon">❤️</div>
<h3 class="value-title">Service</h3>
<p class="value-description">Serving our community through charitable activities, support programs, and cultural initiatives.</p>
</div> </div>
<div class="value-card">
<div class="value-icon">🌍</div> <div class="bg-white rounded-xl shadow-md overflow-hidden hover:shadow-lg transition-all duration-200">
<h3 class="value-title">Inclusivity</h3> <div class="w-full h-48 bg-gray-200 flex items-center justify-center text-gray-400 text-sm">Image Placeholder</div>
<p class="value-description">Welcoming all who share our values, regardless of ethnicity, religion, or background.</p> <div class="p-4 text-center">
<h3 class="font-bold text-lg text-gray-900">Omoluabi Engr Kayode O. Opadola</h3>
<p class="text-sm text-gray-600">Secretary</p>
</div> </div>
<div class="value-card">
<div class="value-icon">🚀</div>
<h3 class="value-title">Innovation</h3>
<p class="value-description">Embracing new ideas and approaches to cultural preservation and community building.</p>
</div> </div>
<div class="bg-white rounded-xl shadow-md overflow-hidden hover:shadow-lg transition-all duration-200">
<div class="w-full h-48 bg-gray-200 flex items-center justify-center text-gray-400 text-sm">Image Placeholder</div>
<div class="p-4 text-center">
<h3 class="font-bold text-lg text-gray-900">Omoluabi Otunba Bambo T. O Larry</h3>
<p class="text-sm text-gray-600">General Secretary</p>
</div>
</div>
<div class="bg-white rounded-xl shadow-md overflow-hidden hover:shadow-lg transition-all duration-200">
<div class="w-full h-48 bg-gray-200 flex items-center justify-center text-gray-400 text-sm">Image Placeholder</div>
<div class="p-4 text-center">
<h3 class="font-bold text-lg text-gray-900">Omoluabi Ogedengbe Oluwagbemiga Dada</h3>
<p class="text-sm text-gray-600">Member</p>
</div>
</div>
<div class="bg-white rounded-xl shadow-md overflow-hidden hover:shadow-lg transition-all duration-200">
<div class="w-full h-48 bg-gray-200 flex items-center justify-center text-gray-400 text-sm">Image Placeholder</div>
<div class="p-4 text-center">
<h3 class="font-bold text-lg text-gray-900">Omoluabi Omoba Johnson Adesida</h3>
<p class="text-sm text-gray-600">Media Director</p>
</div>
</div>
</div>
<div class="text-center mt-12">
<a href="/members" class="inline-flex items-center px-8 py-3 bg-gradient-to-r from-nigerian-green-500 to-kente-gold-500 text-white rounded-lg shadow-lg hover:shadow-xl hover:from-nigerian-green-600 hover:to-kente-gold-600 transition-all duration-200 font-medium">
👥 View All Members
<svg class="w-5 h-5 ml-2" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M10 9a3 3 0 100-6 3 3 0 000 6zm-7 9a7 7 0 1114 0H3z" clip-rule="evenodd"></path>
</svg>
</a>
</div> </div>
</div> </div>
</section> </section>
<!-- Our Story --> <!-- CTA Section -->
<section class="content-section"> <section class="section brand-surface text-white text-center relative overflow-hidden" data-animate-on-scroll="fade-in">
<div class="container"> <div class="absolute top-10 left-10 w-32 h-32 bg-white/10 rounded-full animate-float"></div>
<h2 class="section-title">Our Story</h2> <div class="absolute bottom-10 right-10 w-24 h-24 bg-white/10 rounded-full animate-float animation-delay-1s"></div>
<p class="section-subtitle">From humble beginnings to a thriving community</p>
<div class="timeline"> <div class="container relative z-10">
<div class="timeline-item"> <h2 class="font-headline text-4xl md:text-5xl font-bold mb-6 leading-tight">
<div class="timeline-dot"></div> Ready to join our community?
<div class="timeline-content"> </h2>
<div class="timeline-year">2018</div>
<h3 class="timeline-title">Association Established</h3> <p class="text-lg md:text-xl opacity-90 max-w-3xl mx-auto mb-8">
<p class="timeline-description">A group of passionate Nigerians came together to form the Omoluabi Association, with the vision of preserving Yoruba culture in the Netherlands.</p> Become part of a vibrant community dedicated to preserving Nigerian culture and building stronger connections in the Netherlands.
</div> </p>
</div>
<div class="timeline-item"> <div class="flex flex-col sm:flex-row gap-4 items-center justify-center">
<div class="timeline-dot"></div> <a href="/join" class="btn btn-lg bg-white text-nigerian-green-600 hover:bg-gray-100 shadow-xl hover:shadow-2xl">
<div class="timeline-content"> 👥 Join Us Today
<div class="timeline-year">2019</div> </a>
<h3 class="timeline-title">First Cultural Festival</h3> <a href="/contact" class="btn btn-lg bg-transparent border-2 border-white text-white hover:bg-white/20">
<p class="timeline-description">Successfully organized our first major cultural event, bringing together over 200 community members to celebrate Nigerian heritage.</p> 📞 Contact Us
</div> </a>
</div>
<div class="timeline-item">
<div class="timeline-dot"></div>
<div class="timeline-content">
<div class="timeline-year">2020</div>
<h3 class="timeline-title">Community Support Programs</h3>
<p class="timeline-description">Launched various support programs for Nigerian families, including language classes, cultural workshops, and community outreach.</p>
</div>
</div>
<div class="timeline-item">
<div class="timeline-dot"></div>
<div class="timeline-content">
<div class="timeline-year">2021</div>
<h3 class="timeline-title">Partnership Expansion</h3>
<p class="timeline-description">Formed partnerships with Dutch cultural organizations and educational institutions to promote cross-cultural understanding.</p>
</div>
</div>
<div class="timeline-item">
<div class="timeline-dot"></div>
<div class="timeline-content">
<div class="timeline-year">2022</div>
<h3 class="timeline-title">Youth Programs Launch</h3>
<p class="timeline-description">Introduced specialized programs for Nigerian youth, including mentorship, career guidance, and cultural identity workshops.</p>
</div>
</div>
<div class="timeline-item">
<div class="timeline-dot"></div>
<div class="timeline-content">
<div class="timeline-year">2023</div>
<h3 class="timeline-title">International Recognition</h3>
<p class="timeline-description">Received recognition from the Nigerian Embassy and Dutch cultural organizations for our contributions to community development.</p>
</div>
</div>
<div class="timeline-item">
<div class="timeline-dot"></div>
<div class="timeline-content">
<div class="timeline-year">2024</div>
<h3 class="timeline-title">Future Forward</h3>
<p class="timeline-description">Continuing to grow and expand our programs, with plans for a cultural center and enhanced educational initiatives.</p>
</div>
</div>
</div> </div>
</div> </div>
</section> </section>
</BaseLayout>
<!-- Impact Stats -->
<section class="stats-section">
<div class="container">
<h2 class="section-title" style="color: white; margin-bottom: 3rem;">Our Impact</h2>
<div class="stats-grid">
<div class="stat-item">
<span class="stat-number">500+</span>
<div class="stat-label">Community Members</div>
</div>
<div class="stat-item">
<span class="stat-number">50+</span>
<div class="stat-label">Events Organized</div>
</div>
<div class="stat-item">
<span class="stat-number">1000+</span>
<div class="stat-label">Lives Touched</div>
</div>
<div class="stat-item">
<span class="stat-number">6</span>
<div class="stat-label">Years of Service</div>
</div>
</div>
</div>
</section>
<!-- Leadership Team -->
<section class="content-section" style="background: #f9fafb;">
<div class="container">
<h2 class="section-title">Our Leadership Team</h2>
<p class="section-subtitle">Meet the dedicated individuals guiding our organization</p>
<div class="team-grid">
<div class="team-member">
<img src="/images/members/member1.jpg" alt="President" class="member-image" />
<div class="member-info">
<h3 class="member-name">Chief Adebayo Ogunlesi</h3>
<div class="member-role">President & Founder</div>
<p class="member-bio">A passionate advocate for Nigerian culture with over 20 years of experience in community development and cultural preservation.</p>
</div>
</div>
<div class="team-member">
<img src="/images/members/member2.jpg" alt="Vice President" class="member-image" />
<div class="member-info">
<h3 class="member-name">Dr. Folake Adebayo</h3>
<div class="member-role">Vice President</div>
<p class="member-bio">An educator and cultural scholar dedicated to promoting Nigerian heritage through educational programs and community engagement.</p>
</div>
</div>
<div class="team-member">
<img src="/images/members/member3.jpg" alt="Secretary" class="member-image" />
<div class="member-info">
<h3 class="member-name">Mrs. Bisi Johnson</h3>
<div class="member-role">General Secretary</div>
<p class="member-bio">A community organizer with expertise in event planning and cultural programming, ensuring smooth operations of all activities.</p>
</div>
</div>
<div class="team-member">
<img src="/images/members/member4.jpg" alt="Treasurer" class="member-image" />
<div class="member-info">
<h3 class="member-name">Mr. Tunde Williams</h3>
<div class="member-role">Treasurer</div>
<p class="member-bio">A financial professional committed to ensuring transparency and proper management of the association's resources.</p>
</div>
</div>
</div>
</div>
</section>
</main>
<Footer />
</body>
</html>

View File

@@ -1,485 +1,58 @@
--- ---
import Header from '../components/Header.astro'; import BaseLayout from '../layouts/BaseLayout.astro';
import Footer from '../components/Footer.astro'; import ContactForm from '../components/ContactForm.jsx';
import ContactForm from '../components/ContactForm.astro';
import '../styles/main.css';
--- ---
<html lang="en"> <BaseLayout>
<head> <!-- Page Header (modern) -->
<meta charset="utf-8" /> <section class="brand-surface relative py-20 px-4 text-center text-white overflow-hidden" data-animate-on-scroll="fade-in">
<link rel="icon" type="image/svg+xml" href="/favicon.svg" /> <div class="relative z-10 max-w-4xl mx-auto">
<meta name="viewport" content="width=device-width" /> <div class="flex items-center justify-center gap-2 mb-4 text-sm text-white/90">
<meta name="generator" content={Astro.generator} /> <a href="/" class="hover:underline">Home</a>
<title>Contact Us - Omoluabi Association</title> <span class="opacity-60">/</span>
<meta name="description" content="Get in touch with Omoluabi Association. We'd love to hear from you and answer any questions you may have." /> <span>Contact</span>
</head> </div>
<body> <h1 class="font-headline text-5xl md:text-6xl font-extrabold mb-4 leading-tight">Contact Us</h1>
<Header /> <p class="text-lg md:text-xl opacity-90 max-w-2xl mx-auto">Wed love to hear from you. Use the form or our details below.</p>
<main class="contact-page">
<!-- Hero Section -->
<section class="contact-hero">
<div class="container">
<h1 class="contact-title">Get in Touch</h1>
<p class="contact-subtitle">We'd love to hear from you! Reach out to us for any questions, support, or to get involved with our community.</p>
</div> </div>
</section> </section>
<!-- Contact Information Section --> <section class="section bg-white dark:bg-gray-900" data-animate-on-scroll="fade-in">
<section class="contact-info-section">
<div class="container"> <div class="container">
<div class="contact-info-grid"> <ContactForm client:load />
<div class="contact-info-card">
<div class="contact-icon">📍</div>
<h3>Visit Us</h3>
<p>Amsterdam, Netherlands</p>
<p>We're located in the heart of Amsterdam, serving the Nigerian community and beyond.</p>
</div> </div>
<div class="contact-info-card"> </section>
<div class="contact-icon">📞</div>
<h3>Call Us</h3> <section class="section bg-gray-50 dark:bg-gray-900" data-animate-on-scroll="fade-in">
<p>+31 (0) 123 456 789</p> <div class="container">
<p>Available Monday to Friday, 9:00 AM - 6:00 PM CET</p> <div class="text-center mb-12">
<h2 class="font-headline text-4xl font-bold text-gray-900 dark:text-white mb-4">
Our <span class="text-nigerian-green-700">Contact</span> Details
</h2>
<p class="text-lg text-gray-600 dark:text-gray-300 max-w-2xl mx-auto">
Feel free to reach out to us through any of the following channels.
</p>
<div class="w-24 h-1 bg-gradient-to-r from-nigerian-green-500 to-kente-gold-500 mx-auto rounded-full mt-6"></div>
</div> </div>
<div class="contact-info-card">
<div class="contact-icon">✉️</div> <div class="grid grid-cols-1 md:grid-cols-3 gap-8 text-center">
<h3>Email Us</h3> <div class="bg-white dark:bg-gray-800 p-6 rounded-xl shadow-md border border-gray-200 dark:border-gray-700" data-animate-on-scroll="slide-up">
<p>info@omoluabi-association.nl</p> <div class="text-4xl text-nigerian-green-500 mb-4">📍</div>
<p>We typically respond within 24 hours during business days.</p> <h3 class="font-semibold text-xl text-gray-900 dark:text-white mb-2">Our Location</h3>
<p class="text-gray-700 dark:text-gray-300">Amsterdam, Netherlands</p>
<p class="text-gray-700 dark:text-gray-300">Various locations across NL</p>
</div> </div>
<div class="contact-info-card"> <div class="bg-white dark:bg-gray-800 p-6 rounded-xl shadow-md border border-gray-200 dark:border-gray-700" data-animate-on-scroll="slide-up" style="transition-delay: 0.1s;">
<div class="contact-icon">🕒</div> <div class="text-4xl text-kente-gold-500 mb-4">📞</div>
<h3>Office Hours</h3> <h3 class="font-semibold text-xl text-gray-900 dark:text-white mb-2">Phone Number</h3>
<p>Monday - Friday</p> <p class="text-gray-700 dark:text-gray-300">+31 (0) 123 456 789</p>
<p>9:00 AM - 6:00 PM CET</p> </div>
<div class="bg-white dark:bg-gray-800 p-6 rounded-xl shadow-md border border-gray-200 dark:border-gray-700" data-animate-on-scroll="slide-up" style="transition-delay: 0.2s;">
<div class="text-4xl text-ankara-red-500 mb-4">📧</div>
<h3 class="font-semibold text-xl text-gray-900 dark:text-white mb-2">Email Address</h3>
<p class="text-gray-700 dark:text-gray-300">info@omoluabi.nl</p>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
</BaseLayout>
<!-- Contact Form Section -->
<section class="contact-form-section">
<div class="container">
<div class="contact-form-container">
<div class="form-intro">
<h2 class="form-title">Send Us a Message</h2>
<p class="form-subtitle">Fill out the form below and we'll get back to you as soon as possible. All fields marked with * are required.</p>
</div>
<ContactForm />
</div>
</div>
</section>
<!-- FAQ Section -->
<section class="faq-section">
<div class="container">
<h2 class="section-title">Frequently Asked Questions</h2>
<div class="faq-grid">
<div class="faq-item">
<h3 class="faq-question">How can I become a member?</h3>
<p class="faq-answer">You can become a member by filling out our membership application form and paying the annual membership fee. Contact us for more details about the application process.</p>
</div>
<div class="faq-item">
<h3 class="faq-question">How can I donate to the orphanage?</h3>
<p class="faq-answer">You can donate through our secure online donation system, bank transfer, or by contacting us directly. All donations go directly to supporting the children in our care.</p>
</div>
<div class="faq-item">
<h3 class="faq-question">Can I volunteer with the association?</h3>
<p class="faq-answer">Yes! We welcome volunteers for various activities including events, fundraising, and orphanage support. Please contact us to discuss available opportunities.</p>
</div>
<div class="faq-item">
<h3 class="faq-question">Do you organize cultural events?</h3>
<p class="faq-answer">Yes, we regularly organize cultural events, celebrations, and community gatherings to promote Nigerian heritage and bring our community together.</p>
</div>
</div>
</div>
</section>
<!-- Map Section -->
<section class="map-section">
<div class="container">
<h2 class="section-title">Find Us</h2>
<div class="map-container">
<div class="map-placeholder">
<span>Interactive Map</span>
<p>Amsterdam, Netherlands</p>
</div>
</div>
</div>
</section>
<!-- Social Media Section -->
<section class="social-section">
<div class="container">
<h2 class="section-title">Connect With Us</h2>
<p class="social-subtitle">Follow us on social media to stay updated with our latest news, events, and community activities.</p>
<div class="social-links">
<a href="#" class="social-link">
<span class="social-icon">📘</span>
<span>Facebook</span>
</a>
<a href="#" class="social-link">
<span class="social-icon">📷</span>
<span>Instagram</span>
</a>
<a href="#" class="social-link">
<span class="social-icon">🐦</span>
<span>Twitter</span>
</a>
<a href="#" class="social-link">
<span class="social-icon">💼</span>
<span>LinkedIn</span>
</a>
</div>
</div>
</section>
</main>
<Footer />
<style>
/* Contact Page Styles */
.contact-page {
min-height: 100vh;
background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%);
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 0 2rem;
}
/* Hero Section */
.contact-hero {
background: linear-gradient(135deg, #16a34a 0%, #15803d 100%);
color: white;
padding: 6rem 0 4rem;
text-align: center;
position: relative;
overflow: hidden;
}
.contact-hero::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="grain" width="100" height="100" patternUnits="userSpaceOnUse"><circle cx="25" cy="25" r="1" fill="white" opacity="0.1"/><circle cx="75" cy="75" r="1" fill="white" opacity="0.1"/><circle cx="50" cy="10" r="0.5" fill="white" opacity="0.1"/><circle cx="10" cy="60" r="0.5" fill="white" opacity="0.1"/><circle cx="90" cy="40" r="0.5" fill="white" opacity="0.1"/></pattern></defs><rect width="100" height="100" fill="url(%23grain)"/></svg>');
opacity: 0.3;
}
.contact-title {
font-size: 3.5rem;
font-weight: 700;
margin-bottom: 1rem;
position: relative;
z-index: 1;
}
.contact-subtitle {
font-size: 1.25rem;
opacity: 0.9;
max-width: 600px;
margin: 0 auto;
position: relative;
z-index: 1;
}
/* Contact Info Section */
.contact-info-section {
padding: 4rem 0;
}
.contact-info-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 2rem;
}
.contact-info-card {
background: white;
padding: 2.5rem;
border-radius: 20px;
text-align: center;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
border: 1px solid rgba(22, 163, 74, 0.1);
transition: all 0.3s ease;
}
.contact-info-card:hover {
transform: translateY(-5px);
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);
}
.contact-icon {
font-size: 3rem;
margin-bottom: 1rem;
}
.contact-info-card h3 {
font-size: 1.5rem;
font-weight: 600;
color: #16a34a;
margin-bottom: 1rem;
}
.contact-info-card p {
color: #6b7280;
line-height: 1.6;
margin-bottom: 0.5rem;
}
.contact-info-card p:last-child {
margin-bottom: 0;
font-size: 0.9rem;
opacity: 0.8;
}
/* Contact Form Section */
.contact-form-section {
padding: 4rem 0;
background: white;
}
.contact-form-container {
max-width: 800px;
margin: 0 auto;
}
.form-intro {
text-align: center;
margin-bottom: 3rem;
}
.form-title {
font-size: 2.5rem;
font-weight: 600;
color: #16a34a;
margin-bottom: 1rem;
}
.form-subtitle {
font-size: 1.1rem;
color: #6b7280;
max-width: 500px;
margin: 0 auto;
}
/* FAQ Section */
.faq-section {
padding: 4rem 0;
}
.section-title {
font-size: 2.5rem;
font-weight: 600;
color: #16a34a;
text-align: center;
margin-bottom: 3rem;
}
.faq-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 2rem;
}
.faq-item {
background: white;
padding: 2rem;
border-radius: 15px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
border: 1px solid rgba(22, 163, 74, 0.1);
transition: all 0.3s ease;
}
.faq-item:hover {
transform: translateY(-3px);
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);
}
.faq-question {
font-size: 1.25rem;
font-weight: 600;
color: #16a34a;
margin-bottom: 1rem;
}
.faq-answer {
color: #6b7280;
line-height: 1.6;
}
/* Map Section */
.map-section {
padding: 4rem 0;
background: white;
}
.map-section .section-title {
margin-bottom: 2rem;
}
.map-container {
max-width: 800px;
margin: 0 auto;
}
.map-placeholder {
width: 100%;
height: 400px;
background: linear-gradient(135deg, #e5e7eb 0%, #d1d5db 100%);
border-radius: 20px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
color: #6b7280;
border: 2px dashed #9ca3af;
}
.map-placeholder span {
font-size: 1.5rem;
font-weight: 600;
margin-bottom: 0.5rem;
}
.map-placeholder p {
font-size: 1.1rem;
}
/* Social Section */
.social-section {
padding: 4rem 0;
background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);
color: white;
}
.social-section .section-title {
color: white;
margin-bottom: 1rem;
}
.social-subtitle {
text-align: center;
font-size: 1.1rem;
opacity: 0.9;
margin-bottom: 3rem;
max-width: 600px;
margin-left: auto;
margin-right: auto;
}
.social-links {
display: flex;
justify-content: center;
gap: 2rem;
flex-wrap: wrap;
}
.social-link {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.5rem;
padding: 1.5rem;
background: rgba(255, 255, 255, 0.1);
border-radius: 15px;
text-decoration: none;
color: white;
transition: all 0.3s ease;
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.2);
}
.social-link:hover {
background: rgba(255, 255, 255, 0.2);
transform: translateY(-5px);
}
.social-icon {
font-size: 2rem;
}
.social-link span:last-child {
font-weight: 500;
}
/* Responsive Design */
@media (max-width: 768px) {
.contact-title {
font-size: 2.5rem;
}
.contact-subtitle {
font-size: 1.1rem;
}
.contact-info-grid {
grid-template-columns: 1fr;
gap: 1.5rem;
}
.contact-info-card {
padding: 2rem;
}
.form-title {
font-size: 2rem;
}
.section-title {
font-size: 2rem;
}
.faq-grid {
grid-template-columns: 1fr;
gap: 1.5rem;
}
.social-links {
gap: 1rem;
}
.social-link {
padding: 1rem;
}
}
@media (max-width: 480px) {
.container {
padding: 0 1rem;
}
.contact-hero {
padding: 4rem 0 3rem;
}
.contact-title {
font-size: 2rem;
}
.contact-info-card {
padding: 1.5rem;
}
.faq-item {
padding: 1.5rem;
}
.map-placeholder {
height: 300px;
}
.social-links {
flex-direction: column;
align-items: center;
}
}
</style>
</body>
</html>

View File

@@ -0,0 +1,82 @@
---
import BaseLayout from '../layouts/BaseLayout.astro';
import DonationProgressBar from '../components/DonationProgressBar.jsx';
---
<BaseLayout>
<!-- Page Header -->
<section class="relative py-16 px-4 text-center text-white overflow-hidden nigerian-flag-bg" data-animate-on-scroll="fade-in">
<div class="absolute inset-0 opacity-10" style="background-image: url('data:image/svg+xml,%3Csvg width="60" height="60" viewBox="0 0 60 60" xmlns="http://www.w3.org/2000/svg"%3E%3Cg fill="none" fill-rule="evenodd"%3E%3Cg fill="%23ffffff" fill-opacity="0.1"%3E%3Cpath d="M36 34v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zm0-30V0h-2v4h-4v2h4v4h2V6h4V4h-4zM6 34v-4H4v4H0v2h4v4h2v-4h4v-2H6zM6 4V0H4v4H0v2h4v4h2V6h4V4H6z"/%3E%3C/g%3E%3C/g%3E%3C/svg%3E');"></div>
<div class="relative z-10 max-w-4xl mx-auto">
<div class="flex items-center justify-center gap-2 mb-4 text-sm">
<a href="/" class="text-white/80 hover:text-white transition-colors">🏠 Home</a>
<span class="text-white/60">•</span>
<span>Donate</span>
<span class="ml-4"><span class="dutch-flag-badge"><span class="stripe red"></span><span class="stripe white"></span><span class="stripe blue"></span></span></span>
</div>
<h1 class="font-headline text-5xl md:text-6xl font-extrabold mb-4 leading-tight bg-clip-text text-transparent bg-gradient-to-r from-white to-gray-200 animate-text-shine">
Support Our Mission
</h1>
<p class="text-lg md:text-xl opacity-90 max-w-2xl mx-auto">
Your generous contributions empower us to continue our work in preserving Nigerian culture, supporting our community, and making a difference in the lives of those in need.
</p>
</div>
</section>
<section class="section" data-animate-on-scroll="fade-in">
<div class="container">
<div class="grid grid-cols-1 md:grid-cols-2 gap-10 items-start">
<div data-animate-on-scroll="slide-up">
<h2 class="text-2xl font-headline font-bold text-nigerian-green-600 mb-4">Why Your Donation Matters</h2>
<p class="text-gray-700 leading-relaxed mb-4">
Every donation, no matter the size, directly impacts our programs and initiatives. From cultural events that bring our community together to vital support for our orphanage, your generosity fuels our mission.
</p>
<ul class="list-disc list-inside text-gray-700 space-y-2 mb-6">
<li>Preserving and promoting Nigerian cultural heritage.</li>
<li>Organizing community events and welfare programs.</li>
<li>Providing essential support to the orphanage.</li>
<li>Empowering Nigerian youth in the Netherlands.</li>
</ul>
<p class="text-gray-700 leading-relaxed">
We are committed to transparency and accountability. All funds are carefully managed and directed towards areas where they can make the most significant impact.
</p>
</div>
<div class="sticky top-24" data-animate-on-scroll="slide-up" style="transition-delay: 0.1s;">
<DonationProgressBar client:load />
</div>
</div>
</div>
</section>
<section class="section bg-gray-50" data-animate-on-scroll="fade-in">
<div class="container">
<div class="text-center mb-12">
<h2 class="font-headline text-4xl font-bold text-kente-gold-700 mb-4">
Other Ways to Support
</h2>
<p class="text-lg text-gray-600 max-w-2xl mx-auto">
There are many ways you can contribute to our cause and make a difference.
</p>
<div class="w-24 h-1 bg-gradient-to-r from-kente-gold-500 to-nigerian-green-500 mx-auto rounded-full mt-6"></div>
</div>
<div class="flex flex-wrap justify-center gap-6">
<div class="bg-white p-6 rounded-xl shadow-md border border-gray-200 flex-1 min-w-[280px] max-w-[350px]" data-animate-on-scroll="slide-up">
<h3 class="text-xl font-semibold text-adire-blue-600 mb-3">Volunteer Your Time</h3>
<p class="text-gray-700 mb-4">
Lend a hand at our events or administrative tasks. Your skills are valuable!
</p>
<a href="/contact" class="text-adire-blue-500 hover:underline font-medium">Learn More →</a>
</div>
<div class="bg-white p-6 rounded-xl shadow-md border border-gray-200 flex-1 min-w-[280px] max-w-[350px]" data-animate-on-scroll="slide-up" style="transition-delay: 0.1s;">
<h3 class="text-xl font-semibold text-ankara-red-600 mb-3">Become a Member</h3>
<p class="text-gray-700 mb-4">
Join our association and be part of a vibrant community.
</p>
<a href="/join" class="text-ankara-red-500 hover:underline font-medium">Join Us →</a>
</div>
</div>
</div>
</section>
</BaseLayout>

View File

@@ -1,448 +1,29 @@
--- ---
// Events page for Omoluabi Association import BaseLayout from '../layouts/BaseLayout.astro';
import Header from '../components/Header.astro'; import EventFilterSearch from '../components/EventFilterSearch.jsx';
import Footer from '../components/Footer.astro';
// Get all event files const eventFiles = Object.values(await import.meta.glob('../../content/events/*.md', { eager: true })) as any[];
const events = await Astro.glob('../../content/events/*.md'); const events = eventFiles;
const sortedEvents = events.sort((a: any, b: any) => new Date(b.frontmatter.date).getTime() - new Date(a.frontmatter.date).getTime()); const sortedEvents = events.sort((a, b) => new Date(b.frontmatter?.date || 0).getTime() - new Date(a.frontmatter?.date || 0).getTime());
// Separate upcoming and past events
const now = new Date();
const upcomingEvents = sortedEvents.filter((event: any) => new Date(event.frontmatter.date).getTime() >= now.getTime());
const pastEvents = sortedEvents.filter((event: any) => new Date(event.frontmatter.date).getTime() < now.getTime());
--- ---
<!DOCTYPE html> <BaseLayout>
<html lang="en"> <!-- Page Header (modern) -->
<head> <section class="brand-surface relative py-20 px-4 text-center text-white overflow-hidden" data-animate-on-scroll="fade-in">
<meta charset="UTF-8" /> <div class="relative z-10 max-w-4xl mx-auto">
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <div class="flex items-center justify-center gap-2 mb-4 text-sm text-white/90">
<title>Events - Omoluabi Association</title> <a href="/" class="hover:underline">Home</a>
<meta name="description" content="See our upcoming and past events at Omoluabi Association." /> <span class="opacity-60">/</span>
<style> <span>Events</span>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Inter', system-ui, sans-serif;
background: linear-gradient(135deg, #fafafa 0%, #f0fdf4 100%);
min-height: 100vh;
line-height: 1.6;
}
/* Page Header */
.page-header {
background: linear-gradient(135deg, #16a34a 0%, #f59e0b 50%, #dc2626 100%);
color: white;
padding: 4rem 2rem;
text-align: center;
position: relative;
overflow: hidden;
}
.page-header::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-image: url("data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%23ffffff' fill-opacity='0.05'%3E%3Cpath d='M36 34v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zm0-30V0h-2v4h-4v2h4v4h2V6h4V4h-4zM6 34v-4H4v4H0v2h4v4h2v-4h4v-2H6zM6 4V0H4v4H0v2h4v4h2V6h4V4H6z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
pointer-events: none;
}
.page-header-content {
max-width: 1200px;
margin: 0 auto;
position: relative;
z-index: 10;
}
.page-title {
font-size: 3.5rem;
font-weight: 800;
margin-bottom: 1rem;
background: linear-gradient(90deg, #ffffff, #e0e7ff, #8b5cf6, #e0e7ff, #ffffff);
background-size: 300% auto;
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
animation: textShine 4s linear infinite;
}
.page-subtitle {
font-size: 1.25rem;
opacity: 0.9;
max-width: 600px;
margin: 0 auto;
}
@keyframes textShine {
0% { background-position: 0% 50%; }
100% { background-position: 100% 50%; }
}
/* Content Sections */
.content-section {
padding: 4rem 2rem;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
.section-title {
font-size: 2.5rem;
font-weight: 700;
text-align: center;
margin-bottom: 1rem;
color: #16a34a;
}
.section-subtitle {
font-size: 1.125rem;
text-align: center;
color: #6b7280;
margin-bottom: 3rem;
max-width: 600px;
margin-left: auto;
margin-right: auto;
}
/* Events Grid */
.events-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
gap: 2rem;
margin-bottom: 4rem;
}
.event-card {
background: white;
border-radius: 1rem;
overflow: hidden;
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.1);
transition: transform 0.3s ease, box-shadow 0.3s ease;
position: relative;
}
.event-card:hover {
transform: translateY(-5px);
box-shadow: 0 15px 30px rgba(0, 0, 0, 0.15);
}
.event-image {
width: 100%;
height: 200px;
object-fit: cover;
background: linear-gradient(45deg, #16a34a, #f59e0b);
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 3rem;
}
.event-badge {
position: absolute;
top: 1rem;
right: 1rem;
background: #f59e0b;
color: white;
padding: 0.5rem 1rem;
border-radius: 20px;
font-weight: 600;
font-size: 0.875rem;
}
.event-badge.upcoming {
background: #16a34a;
}
.event-badge.past {
background: #6b7280;
}
.event-content {
padding: 1.5rem;
}
.event-meta {
display: flex;
align-items: center;
gap: 1rem;
margin-bottom: 1rem;
flex-wrap: wrap;
}
.event-category {
background: rgba(22, 163, 74, 0.1);
color: #16a34a;
padding: 0.25rem 0.75rem;
border-radius: 15px;
font-size: 0.875rem;
font-weight: 500;
}
.event-date {
color: #6b7280;
font-size: 0.875rem;
display: flex;
align-items: center;
gap: 0.25rem;
}
.event-title {
font-size: 1.25rem;
font-weight: 600;
margin-bottom: 0.75rem;
color: #111827;
line-height: 1.3;
}
.event-description {
color: #6b7280;
margin-bottom: 1rem;
line-height: 1.6;
}
.event-details {
background: #f9fafb;
padding: 1rem;
border-radius: 0.5rem;
margin-bottom: 1rem;
}
.event-detail {
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 0.5rem;
font-size: 0.875rem;
color: #374151;
}
.event-detail:last-child {
margin-bottom: 0;
}
.event-detail-icon {
color: #16a34a;
font-size: 1rem;
}
.event-content-full {
color: #6b7280;
font-size: 0.875rem;
line-height: 1.6;
margin-top: 1rem;
padding-top: 1rem;
border-top: 1px solid #e5e7eb;
}
/* Empty State */
.empty-state {
text-align: center;
padding: 4rem 2rem;
background: white;
border-radius: 1rem;
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.1);
}
.empty-icon {
font-size: 4rem;
margin-bottom: 1rem;
opacity: 0.5;
}
.empty-title {
font-size: 1.5rem;
font-weight: 600;
margin-bottom: 0.5rem;
color: #374151;
}
.empty-description {
color: #6b7280;
margin-bottom: 2rem;
}
.cta-button {
display: inline-flex;
align-items: center;
gap: 0.5rem;
background: linear-gradient(45deg, #16a34a, #f59e0b);
color: white;
padding: 0.75rem 1.5rem;
border-radius: 8px;
text-decoration: none;
font-weight: 600;
transition: all 0.3s ease;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.cta-button:hover {
transform: translateY(-2px);
box-shadow: 0 8px 12px rgba(0, 0, 0, 0.15);
}
/* Responsive Design */
@media (max-width: 768px) {
.page-title {
font-size: 2.5rem;
}
.events-grid {
grid-template-columns: 1fr;
gap: 1.5rem;
}
.content-section {
padding: 2rem 1rem;
}
}
.events-title {
font-size: 3.5rem;
font-weight: 700;
margin-bottom: 1rem;
position: relative;
z-index: 1;
}
</style>
</head>
<body>
<Header />
<!-- Main Content -->
<main>
<!-- Page Header -->
<header class="page-header">
<div class="page-header-content">
<h1 class="page-title">Our Events</h1>
<p class="page-subtitle">Join us for cultural celebrations, community gatherings, and special programs</p>
</div> </div>
</header> <h1 class="font-headline text-5xl md:text-6xl font-extrabold mb-4 leading-tight">Events</h1>
<p class="text-lg md:text-xl opacity-90 max-w-2xl mx-auto">Find community gatherings, cultural celebrations, and programs across the Netherlands.</p>
<!-- Upcoming Events -->
<section class="content-section">
<div class="container">
<h2 class="section-title">Upcoming Events</h2>
<p class="section-subtitle">Mark your calendar for these exciting upcoming events</p>
{upcomingEvents.length > 0 ? (
<div class="events-grid">
{upcomingEvents.map((event: any) => (
<article class="event-card">
<div class="event-badge upcoming">Upcoming</div>
<div class="event-image">
📅
</div>
<div class="event-content">
<div class="event-meta">
<span class="event-category">{event.frontmatter.category}</span>
<span class="event-date">
📅 {new Date(event.frontmatter.date).toLocaleDateString('en-US', {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric'
})}
</span>
</div>
<h3 class="event-title">{event.frontmatter.title}</h3>
<p class="event-description">{event.frontmatter.description}</p>
<div class="event-content-full">
{event.compiledContent()}
</div>
</div>
</article>
))}
</div>
) : (
<div class="empty-state">
<div class="empty-icon">📅</div>
<h3 class="empty-title">No Upcoming Events</h3>
<p class="empty-description">We're currently planning our next events. Check back soon or contact us to stay updated!</p>
<a href="/contact" class="cta-button">
📞 Contact Us
</a>
</div>
)}
</div> </div>
</section> </section>
<!-- Past Events --> <section class="section bg-white dark:bg-gray-900" data-animate-on-scroll="fade-in">
<section class="content-section" style="background: #f9fafb;">
<div class="container"> <div class="container">
<h2 class="section-title">Past Events</h2> <EventFilterSearch events={sortedEvents} client:load />
<p class="section-subtitle">Relive the memories of our previous successful events</p>
{pastEvents.length > 0 ? (
<div class="events-grid">
{pastEvents.map((event: any) => (
<article class="event-card">
<div class="event-badge past">Past Event</div>
<div class="event-image">
🎉
</div>
<div class="event-content">
<div class="event-meta">
<span class="event-category">{event.frontmatter.category}</span>
<span class="event-date">
📅 {new Date(event.frontmatter.date).toLocaleDateString('en-US', {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric'
})}
</span>
</div>
<h3 class="event-title">{event.frontmatter.title}</h3>
<p class="event-description">{event.frontmatter.description}</p>
<div class="event-content-full">
{event.compiledContent()}
</div>
</div>
</article>
))}
</div>
) : (
<div class="empty-state">
<div class="empty-icon">📚</div>
<h3 class="empty-title">No Past Events</h3>
<p class="empty-description">This is where we'll showcase our past events and achievements.</p>
</div>
)}
</div> </div>
</section> </section>
</BaseLayout>
<!-- Call to Action -->
<section class="content-section" style="background: linear-gradient(135deg, #16a34a 0%, #f59e0b 100%); color: white; text-align: center;">
<div class="container">
<h2 style="font-size: 2.5rem; font-weight: 700; margin-bottom: 1rem;">
Want to Stay Updated?
</h2>
<p style="font-size: 1.125rem; margin-bottom: 2rem; opacity: 0.9;">
Join our community to receive updates about upcoming events and cultural activities
</p>
<div style="display: flex; gap: 1rem; justify-content: center; flex-wrap: wrap;">
<a href="/join" class="cta-button" style="background: white; color: #16a34a;">
👥 Join Our Community
</a>
<a href="/contact" class="cta-button" style="background: transparent; color: white; border: 2px solid white;">
📞 Contact Us
</a>
</div>
</div>
</section>
</main>
<Footer />
</body>
</html>

19
src/pages/gallery.astro Normal file
View File

@@ -0,0 +1,19 @@
---
import BaseLayout from '../layouts/BaseLayout.astro';
import ImageGallery from '../components/ImageGallery.jsx';
const galleryFiles = Object.values(await import.meta.glob('../../content/gallery/gallery-sample.md', { eager: true })) as any[];
const images = galleryFiles[0]?.frontmatter?.images || [];
---
<BaseLayout>
<section class="brand-surface relative py-20 px-4 text-center text-white overflow-hidden" data-animate-on-scroll="fade-in">
<div class="relative z-10 max-w-4xl mx-auto">
<h1 class="font-headline text-5xl md:text-6xl font-extrabold mb-4 leading-tight">Gallery</h1>
<p class="text-lg md:text-xl opacity-90 max-w-2xl mx-auto">Moments of culture, community, and celebration.</p>
</div>
</section>
<section class="max-w-6xl mx-auto py-12 px-4 bg-white dark:bg-gray-900">
<ImageGallery images={images} client:load />
</section>
</BaseLayout>

View File

@@ -1,31 +0,0 @@
---
// Standalone homepage with no external dependencies
import '../styles/main.css';
import Header from '../components/Header.astro';
import Footer from '../components/Footer.astro';
import HeroSection from '../components/HeroSection.astro';
import AboutSection from '../components/AboutSection.astro';
import EventsSection from '../components/EventsSection.astro';
---
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Omoluabi Association</title>
<meta name="description" content="Welcome to Omoluabi Association - Promoting Nigerian heritage and supporting our community in the Netherlands." />
<!-- Removed font imports, now handled globally -->
</head>
<body>
<Header />
<!-- Main Content -->
<main class="main-content">
<HeroSection />
<AboutSection />
<EventsSection />
</main>
<Footer />
</body>
</html>

View File

@@ -1,8 +1,216 @@
--- ---
// Redirect to home page import BaseLayout from '../layouts/BaseLayout.astro';
import HeroCarousel from '../components/HeroCarousel.jsx';
import HomeGallery from '../components/HomeGallery.astro';
--- ---
<meta http-equiv="refresh" content="0; url=/home" />
<script> <BaseLayout>
window.location.href = '/home'; <HeroCarousel client:load />
</script>
<p>Redirecting to <a href="/home">home page</a>...</p> <!-- About Section -->
<section class="section about-section" data-animate-on-scroll="fade-in">
<div class="container">
<div class="grid grid-cols-1 md:grid-cols-2 gap-12 items-center">
<div class="relative">
<div class="absolute inset-0 bg-gradient-to-br from-kente-gold-500 to-ankara-red-500 rounded-2xl transform rotate-2 opacity-90 dark:opacity-60"></div>
<div class="relative bg-white dark:bg-gray-800 p-2 rounded-2xl shadow-xl transform -rotate-1">
<img src="/images/whoAreWe.webp" alt="About Omoluabi Association" class="w-full h-80 object-cover rounded-xl" />
<div class="absolute -top-4 -right-4 bg-nigerian-green-500 text-white px-4 py-2 rounded-full font-bold shadow-lg animate-bounce-gentle">Est. 2018</div>
</div>
</div>
<div>
<h2 class="font-headline text-4xl font-bold text-nigerian-green-700 dark:text-kente-gold-400 mb-4 flex items-center gap-3">
<div class="w-2 h-10 bg-gradient-to-b from-nigerian-green-500 to-kente-gold-500 rounded-full"></div>
About Us
</h2>
<h3 class="text-2xl font-semibold text-kente-gold-600 dark:text-kente-gold-400 mb-4 flex items-center gap-2">
<span class="text-3xl">🌟</span>
WHO ARE WE?
</h3>
<div class="text-gray-700 dark:text-gray-200 leading-relaxed text-lg mb-6">
<p class="mb-4">
The <strong class="text-nigerian-green-600 dark:text-nigerian-green-400">Omoluabi Association</strong> in the Royal Kingdom of The Netherlands (OAN) is a pan-Yoruba Association with well-bred, selective, like-minded individuals of enviable character as our members.
</p>
<p class="mb-4">
Our association extends beyond Yorubas or Nigerians only we welcome culturally motivated Netherlanders who share our values and vision for community building.
</p>
<p>
Our association is a non profit, non religious, non partisan, non ethnic and socio cultural organization that focuses on showcasing the Yoruba cultural heritages, norms, values and traditions to the western world, most especially in Holland.
</p>
</div>
<div class="grid grid-cols-1 sm:grid-cols-3 gap-4 mb-6">
<div class="bg-white dark:bg-gray-800 p-4 rounded-lg shadow-md text-center">
<div class="text-2xl font-bold text-nigerian-green-600">2018</div>
<div class="text-sm text-gray-600 dark:text-gray-300">Established</div>
</div>
<div class="bg-white dark:bg-gray-800 p-4 rounded-lg shadow-md text-center">
<div class="text-2xl font-bold text-kente-gold-600">500+</div>
<div class="text-sm text-gray-600 dark:text-gray-300">Members</div>
</div>
<div class="bg-white dark:bg-gray-800 p-4 rounded-lg shadow-md text-center">
<div class="text-2xl font-bold text-ankara-red-600">50+</div>
<div class="text-sm text-gray-600 dark:text-gray-300">Events</div>
</div>
</div>
<div class="flex flex-wrap gap-2">
<span class="badge badge-lg bg-nigerian-green-100 dark:bg-nigerian-green-600/20 text-nigerian-green-700 dark:text-nigerian-green-300">Non-Profit</span>
<span class="badge badge-lg bg-kente-gold-100 dark:bg-kente-gold-600/20 text-kente-gold-700 dark:text-kente-gold-300">Cultural Heritage</span>
<span class="badge badge-lg bg-ankara-red-100 dark:bg-ankara-red-600/20 text-ankara-red-700 dark:text-ankara-red-300">Community Focus</span>
<span class="badge badge-lg bg-adire-blue-100 dark:bg-adire-blue-600/20 text-adire-blue-700 dark:text-adire-blue-300">Inclusive</span>
</div>
</div>
</div>
</div>
</section>
<!-- Events Section -->
<section class="section bg-gray-50 dark:bg-gray-900" data-animate-on-scroll="fade-in">
<div class="container">
<div class="text-center mb-12">
<h2 class="font-headline text-4xl font-bold text-nigerian-green-700 dark:text-kente-gold-400 mb-4">
Upcoming <span class="text-kente-gold-700 dark:text-kente-gold-300">Events</span>
</h2>
<p class="text-lg text-gray-600 dark:text-gray-300 max-w-2xl mx-auto">
Join us in celebrating our rich cultural heritage and building stronger community bonds.
</p>
<div class="w-24 h-1 bg-gradient-to-r from-nigerian-green-500 to-kente-gold-500 mx-auto rounded-full mt-6"></div>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
<!-- Example Event Card 1 -->
<article class="card bg-white shadow-xl rounded-xl overflow-hidden transform transition-transform duration-300 hover:scale-105 hover:shadow-2xl">
<figure class="relative h-56 w-full overflow-hidden">
<img src="/images/hero1.jpg" alt="Cultural Night" class="w-full h-full object-cover" />
<div class="absolute inset-0 bg-gradient-to-t from-black/70 to-transparent"></div>
<span class="absolute bottom-3 left-3 badge badge-secondary bg-kente-gold-500 text-white px-3 py-1 rounded-full text-sm font-semibold">Cultural</span>
<span class="absolute top-3 right-3 bg-white/90 text-nigerian-green-700 px-3 py-1 rounded-full text-sm font-semibold">Dec 15, 2024</span>
</figure>
<div class="card-body p-6">
<h3 class="card-title text-xl font-bold text-nigerian-green-700 mb-2">Omoluabi Cultural Night</h3>
<p class="text-gray-700 leading-relaxed text-sm mb-4">
Experience the richness of Yoruba culture with music, dance, and traditional cuisine.
</p>
<div class="flex items-center justify-between text-sm text-gray-500">
<div class="flex items-center gap-1">
<svg class="w-4 h-4 text-nigerian-green-500" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M5.05 4.05a7 7 0 119.9 9.9L10 18.9l-4.95-4.95a7 7 0 010-9.9zM10 11a2 2 0 100-4 2 2 0 000 4z" clip-rule="evenodd"></path></svg>
<span>Amsterdam</span>
</div>
<a href="/events" class="inline-flex items-center text-kente-gold-600 hover:text-kente-gold-800 font-semibold transition-colors duration-200">
Details
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 ml-1" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" /></svg>
</a>
</div>
</div>
</article>
<!-- Example Event Card 2 -->
<article class="card bg-white shadow-xl rounded-xl overflow-hidden transform transition-transform duration-300 hover:scale-105 hover:shadow-2xl">
<figure class="relative h-56 w-full overflow-hidden">
<img src="/images/hero2.jpg" alt="Women Ambassador" class="w-full h-full object-cover" />
<div class="absolute inset-0 bg-gradient-to-t from-black/70 to-transparent"></div>
<span class="absolute bottom-3 left-3 badge badge-secondary bg-adire-blue-500 text-white px-3 py-1 rounded-full text-sm font-semibold">Community</span>
<span class="absolute top-3 right-3 bg-white/90 text-nigerian-green-700 px-3 py-1 rounded-full text-sm font-semibold">Jan 20, 2025</span>
</figure>
<div class="card-body p-6">
<h3 class="card-title text-xl font-bold text-nigerian-green-700 mb-2">Women Ambassador Program</h3>
<p class="text-gray-700 leading-relaxed text-sm mb-4">
Empowering Nigerian women in the Netherlands through leadership and community building.
</p>
<div class="flex items-center justify-between text-sm text-gray-500">
<div class="flex items-center gap-1">
<svg class="w-4 h-4 text-nigerian-green-500" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M5.05 4.05a7 7 0 119.9 9.9L10 18.9l-4.95-4.95a7 7 0 010-9.9zM10 11a2 2 0 100-4 2 2 0 000 4z" clip-rule="evenodd"></path></svg>
<span>Rotterdam</span>
</div>
<a href="/events" class="inline-flex items-center text-kente-gold-600 hover:text-kente-gold-800 font-semibold transition-colors duration-200">
Details
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 ml-1" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" /></svg>
</a>
</div>
</div>
</article>
<!-- Example Event Card 3 -->
<article class="card bg-white shadow-xl rounded-xl overflow-hidden transform transition-transform duration-300 hover:scale-105 hover:shadow-2xl">
<figure class="relative h-56 w-full overflow-hidden">
<img src="/images/hero3.jpg" alt="COVID Relief" class="w-full h-full object-cover" />
<div class="absolute inset-0 bg-gradient-to-t from-black/70 to-transparent"></div>
<span class="absolute bottom-3 left-3 badge badge-secondary bg-ankara-red-500 text-white px-3 py-1 rounded-full text-sm font-semibold">Charity</span>
<span class="absolute top-3 right-3 bg-white/90 text-nigerian-green-700 px-3 py-1 rounded-full text-sm font-semibold">Feb 10, 2025</span>
</figure>
<div class="card-body p-6">
<h3 class="card-title text-xl font-bold text-nigerian-green-700 mb-2">COVID-19 Relief Initiative</h3>
<p class="text-gray-700 leading-relaxed text-sm mb-4">
Providing support and resources to families affected by the pandemic in Nigeria.
</p>
<div class="flex items-center justify-between text-sm text-gray-500">
<div class="flex items-center gap-1">
<svg class="w-4 h-4 text-nigerian-green-500" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M5.05 4.05a7 7 0 119.9 9.9L10 18.9l-4.95-4.95a7 7 0 010-9.9zM10 11a2 2 0 100-4 2 2 0 000 4z" clip-rule="evenodd"></path></svg>
<span>Online Event</span>
</div>
<a href="/events" class="inline-flex items-center text-kente-gold-600 hover:text-kente-gold-800 font-semibold transition-colors duration-200">
Details
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 ml-1" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" /></svg>
</a>
</div>
</div>
</article>
</div>
<div class="text-center mt-12">
<a href="/events" class="inline-flex items-center px-8 py-3 bg-gradient-to-r from-nigerian-green-500 to-kente-gold-500 text-white rounded-lg shadow-lg hover:shadow-xl hover:from-nigerian-green-600 hover:to-kente-gold-600 transition-all duration-200 font-medium">
View All Events
<svg class="w-5 h-5 ml-2" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M6 2a1 1 0 00-1 1v1H4a2 2 0 00-2 2v10a2 2 0 002 2h12a2 2 0 002-2V6a2 2 0 00-2-2h-1V3a1 1 0 10-2 0v1H7V3a1 1 0 00-1-1zm0 5a1 1 0 000 2h8a1 1 0 100-2H6z" clip-rule="evenodd"></path>
</svg>
</a>
</div>
</div>
</section>
<!-- Donation Section -->
<section class="section brand-surface text-white text-center relative overflow-hidden" data-animate-on-scroll="fade-in">
<div class="absolute top-10 left-10 w-32 h-32 bg-white/10 rounded-full animate-float"></div>
<div class="absolute bottom-10 right-10 w-24 h-24 bg-white/10 rounded-full animate-float animation-delay-1s"></div>
<div class="container relative z-10">
<div class="flex items-center justify-center gap-3 mb-4">
<span class="text-5xl">❤️</span>
<h3 class="text-2xl font-bold">Support Our Mission</h3>
<div class="flex gap-1 text-kente-gold-300">
<span>★</span><span>★</span><span>★</span>
</div>
</div>
<h2 class="font-headline text-5xl font-bold mb-6 leading-tight">
Support Our <span class="text-kente-gold-200">Community Programs</span>
</h2>
<p class="text-lg opacity-90 leading-relaxed max-w-3xl mx-auto mb-8">
Your generous contribution helps us preserve Nigerian culture, support community members, and create lasting impact in the Netherlands.
</p>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-6 mb-10 max-w-md mx-auto">
<div class="bg-white/20 backdrop-blur-sm p-4 rounded-lg text-center">
<div class="text-3xl font-bold">€50K+</div>
<div class="text-sm opacity-90">Raised This Year</div>
</div>
<div class="bg-white/20 backdrop-blur-sm p-4 rounded-lg text-center">
<div class="text-3xl font-bold">200+</div>
<div class="text-sm opacity-90">Families Helped</div>
</div>
</div>
<a href="/donate" class="btn btn-lg bg-white text-ankara-red-600 hover:bg-gray-100 shadow-xl hover:shadow-2xl">
❤️ Donate now
</a>
</div>
</section>
<!-- Gallery Section -->
<HomeGallery />
</BaseLayout>

View File

@@ -1,410 +1,38 @@
--- ---
import Header from '../components/Header.astro'; import BaseLayout from '../layouts/BaseLayout.astro';
import Footer from '../components/Footer.astro'; const memberFiles = Object.values(await import.meta.glob('../../content/members/members-sample.md', { eager: true })) as any[];
import '../styles/main.css'; const intro = memberFiles[0]?.frontmatter?.intro || '';
const members = memberFiles[0]?.frontmatter?.members || [];
const membersData = await Astro.glob('../../content/members/members-sample.md');
const intro = membersData[0]?.frontmatter.intro || '';
const members = membersData[0]?.frontmatter.members || [];
--- ---
<html lang="en"> <BaseLayout>
<head> <!-- Page Header (modern) -->
<meta charset="utf-8" /> <section class="brand-surface relative py-20 px-4 text-center text-white overflow-hidden" data-animate-on-scroll="fade-in">
<link rel="icon" type="image/svg+xml" href="/favicon.svg" /> <div class="relative z-10 max-w-4xl mx-auto">
<meta name="viewport" content="width=device-width" /> <div class="flex items-center justify-center gap-2 mb-4 text-sm text-white/90">
<meta name="generator" content={Astro.generator} /> <a href="/" class="hover:underline">Home</a>
<title>Members - Omoluabi Association</title> <span class="opacity-60">/</span>
<meta name="description" content="Meet our dedicated members and learn about membership benefits at Omoluabi Association." /> <span>Members</span>
</head> </div>
<body> <h1 class="font-headline text-5xl md:text-6xl font-extrabold mb-4 leading-tight">Our Members</h1>
<Header /> <p class="text-lg md:text-xl opacity-90 max-w-2xl mx-auto">Dedicated people at the heart of Omoluabi.</p>
<main class="members-page">
<!-- Hero Section -->
<section class="members-hero">
<div class="container">
<h1 class="members-title">Meet Our Members</h1>
<p class="members-subtitle">Dedicated individuals working together to promote Nigerian heritage and community welfare</p>
</div> </div>
</section> </section>
<!-- Benefits Section --> <section class="max-w-3xl mx-auto mt-8 mb-12 bg-white dark:bg-gray-800 rounded-xl shadow p-6" data-animate-on-scroll="fade-in">
<section class="benefits-section"> <h2 class="text-xl font-bold mb-4 text-nigerian-green-700 dark:text-kente-gold-400">Membership Benefits/Welfare Packages</h2>
<div class="container"> <div class="text-gray-700 dark:text-gray-300 whitespace-pre-line">{intro}</div>
<div class="benefits-card">
<h2 class="benefits-title">Membership Benefits & Welfare Packages</h2>
<div class="benefits-content">
{intro.split('\n').map((line: string, index: number) => {
if (line.trim()) {
return <p class="benefit-item">{line.trim()}</p>;
}
return null;
})}
</div>
</div>
</div>
</section> </section>
<!-- Members Grid --> <section class="max-w-6xl mx-auto mb-20" data-animate-on-scroll="fade-in">
<section class="members-grid-section"> <div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-8 px-4">
<div class="container"> {Array.isArray(members) && members.map((member: any) => (
<h2 class="members-grid-title">Our Leadership Team</h2> <div class="card bg-white dark:bg-gray-800 shadow-lg rounded-xl flex flex-col items-center p-4 transform transition-transform duration-300 hover:scale-105 hover:shadow-xl">
<div class="members-grid"> <img src={member.image} alt={member.name} class="w-40 h-40 object-cover rounded-lg mb-4" />
{members.map((member: any) => ( <h3 class="font-bold text-lg text-gray-900 dark:text-white mb-1">{member.name}</h3>
<div class="member-card"> <p class="text-sm text-gray-600 dark:text-gray-300">{member.role}</p>
<div class="member-image-container">
<img src={member.image} alt={member.name} class="member-image" />
<div class="member-overlay">
<div class="member-role">{member.role}</div>
</div>
</div>
<div class="member-info">
<h3 class="member-name">{member.name}</h3>
<p class="member-role-text">{member.role}</p>
</div>
</div> </div>
))} ))}
</div> </div>
</div>
</section> </section>
</BaseLayout>
<!-- Join CTA Section -->
<section class="join-cta-section">
<div class="container">
<div class="join-cta-card">
<h2 class="join-cta-title">Join Our Community</h2>
<p class="join-cta-text">Become a member and enjoy exclusive benefits while contributing to our mission of promoting Nigerian heritage and community welfare.</p>
<div class="join-cta-buttons">
<a href="/join" class="btn btn-primary">Join Us</a>
<a href="/contact" class="btn btn-secondary">Contact Us</a>
</div>
</div>
</div>
</section>
</main>
<Footer />
<style>
/* Members Page Styles */
.members-page {
min-height: 100vh;
background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%);
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 0 2rem;
}
/* Hero Section */
.members-hero {
background: linear-gradient(135deg, #16a34a 0%, #15803d 100%);
color: white;
padding: 6rem 0 4rem;
text-align: center;
position: relative;
overflow: hidden;
}
.members-hero::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="grain" width="100" height="100" patternUnits="userSpaceOnUse"><circle cx="25" cy="25" r="1" fill="white" opacity="0.1"/><circle cx="75" cy="75" r="1" fill="white" opacity="0.1"/><circle cx="50" cy="10" r="0.5" fill="white" opacity="0.1"/><circle cx="10" cy="60" r="0.5" fill="white" opacity="0.1"/><circle cx="90" cy="40" r="0.5" fill="white" opacity="0.1"/></pattern></defs><rect width="100" height="100" fill="url(%23grain)"/></svg>');
opacity: 0.3;
}
.members-title {
font-size: 3.5rem;
font-weight: 700;
margin-bottom: 1rem;
position: relative;
z-index: 1;
}
.members-subtitle {
font-size: 1.25rem;
opacity: 0.9;
max-width: 600px;
margin: 0 auto;
position: relative;
z-index: 1;
}
/* Benefits Section */
.benefits-section {
padding: 4rem 0;
}
.benefits-card {
background: white;
border-radius: 20px;
padding: 3rem;
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
border: 1px solid rgba(22, 163, 74, 0.1);
}
.benefits-title {
font-size: 2rem;
font-weight: 600;
color: #16a34a;
margin-bottom: 2rem;
text-align: center;
}
.benefits-content {
display: flex;
flex-direction: column;
gap: 1rem;
}
.benefit-item {
font-size: 1.1rem;
line-height: 1.6;
color: #374151;
padding: 1rem;
background: #f8fafc;
border-radius: 12px;
border-left: 4px solid #16a34a;
transition: all 0.3s ease;
}
.benefit-item:hover {
background: #f0f9ff;
transform: translateX(5px);
}
/* Members Grid Section */
.members-grid-section {
padding: 4rem 0;
background: white;
}
.members-grid-title {
font-size: 2.5rem;
font-weight: 600;
color: #16a34a;
text-align: center;
margin-bottom: 3rem;
}
.members-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 2rem;
margin-top: 2rem;
}
.member-card {
background: white;
border-radius: 20px;
overflow: hidden;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
transition: all 0.3s ease;
border: 1px solid rgba(22, 163, 74, 0.1);
}
.member-card:hover {
transform: translateY(-10px);
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);
}
.member-image-container {
position: relative;
overflow: hidden;
height: 250px;
}
.member-image {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.3s ease;
}
.member-card:hover .member-image {
transform: scale(1.1);
}
.member-overlay {
position: absolute;
bottom: 0;
left: 0;
right: 0;
background: linear-gradient(transparent, rgba(0, 0, 0, 0.7));
padding: 1rem;
transform: translateY(100%);
transition: transform 0.3s ease;
}
.member-card:hover .member-overlay {
transform: translateY(0);
}
.member-role {
color: white;
font-weight: 500;
font-size: 0.9rem;
}
.member-info {
padding: 1.5rem;
text-align: center;
}
.member-name {
font-size: 1.25rem;
font-weight: 600;
color: #16a34a;
margin-bottom: 0.5rem;
}
.member-role-text {
color: #6b7280;
font-weight: 500;
}
/* Join CTA Section */
.join-cta-section {
padding: 4rem 0;
background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);
}
.join-cta-card {
background: white;
border-radius: 20px;
padding: 3rem;
text-align: center;
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
}
.join-cta-title {
font-size: 2.5rem;
font-weight: 600;
color: #16a34a;
margin-bottom: 1rem;
}
.join-cta-text {
font-size: 1.1rem;
color: #6b7280;
margin-bottom: 2rem;
max-width: 600px;
margin-left: auto;
margin-right: auto;
}
.join-cta-buttons {
display: flex;
gap: 1rem;
justify-content: center;
flex-wrap: wrap;
}
.btn {
display: inline-flex;
align-items: center;
padding: 0.75rem 2rem;
border-radius: 12px;
font-weight: 600;
text-decoration: none;
transition: all 0.3s ease;
font-size: 1rem;
}
.btn-primary {
background: linear-gradient(45deg, #16a34a, #15803d);
color: white;
box-shadow: 0 4px 15px rgba(22, 163, 74, 0.3);
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(22, 163, 74, 0.4);
}
.btn-secondary {
background: white;
color: #16a34a;
border: 2px solid #16a34a;
}
.btn-secondary:hover {
background: #16a34a;
color: white;
transform: translateY(-2px);
}
/* Responsive Design */
@media (max-width: 768px) {
.members-title {
font-size: 2.5rem;
}
.members-subtitle {
font-size: 1.1rem;
}
.benefits-card {
padding: 2rem;
}
.benefits-title {
font-size: 1.5rem;
}
.members-grid-title {
font-size: 2rem;
}
.members-grid {
grid-template-columns: 1fr;
gap: 1.5rem;
}
.join-cta-title {
font-size: 2rem;
}
.join-cta-buttons {
flex-direction: column;
align-items: center;
}
.btn {
width: 100%;
max-width: 250px;
justify-content: center;
}
}
@media (max-width: 480px) {
.container {
padding: 0 1rem;
}
.members-hero {
padding: 4rem 0 3rem;
}
.members-title {
font-size: 2rem;
}
.benefits-card {
padding: 1.5rem;
}
.join-cta-card {
padding: 2rem;
}
}
</style>
</body>
</html>

View File

@@ -1,626 +1,89 @@
--- ---
import Header from '../components/Header.astro'; import BaseLayout from '../layouts/BaseLayout.astro';
import Footer from '../components/Footer.astro';
import '../styles/main.css';
--- ---
<html lang="en"> <BaseLayout>
<head> <!-- Page Header (modern) -->
<meta charset="utf-8" /> <section class="brand-surface relative py-20 px-4 text-center text-white overflow-hidden" data-animate-on-scroll="fade-in">
<link rel="icon" type="image/svg+xml" href="/favicon.svg" /> <div class="relative z-10 max-w-4xl mx-auto">
<meta name="viewport" content="width=device-width" /> <div class="flex items-center justify-center gap-2 mb-4 text-sm text-white/90">
<meta name="generator" content={Astro.generator} /> <a href="/" class="hover:underline">Home</a>
<title>Orphanage Project - Omoluabi Association</title> <span class="opacity-60">/</span>
<meta name="description" content="Learn about our orphanage project and how you can help support vulnerable children in Nigeria." /> <span>Orphanage</span>
</head>
<body>
<Header />
<main class="orphanage-page">
<!-- Hero Section -->
<section class="orphanage-hero">
<div class="container">
<h1 class="orphanage-title">Our Orphanage Project</h1>
<p class="orphanage-subtitle">Providing hope, care, and education to vulnerable children in Nigeria</p>
<div class="hero-stats">
<div class="stat-item">
<span class="stat-number">50+</span>
<span class="stat-label">Children Cared For</span>
</div>
<div class="stat-item">
<span class="stat-number">5</span>
<span class="stat-label">Years of Service</span>
</div>
<div class="stat-item">
<span class="stat-number">100%</span>
<span class="stat-label">Education Funded</span>
</div>
</div> </div>
<h1 class="font-headline text-5xl md:text-6xl font-extrabold mb-4 leading-tight">Our Orphanage Program</h1>
<p class="text-lg md:text-xl opacity-90 max-w-2xl mx-auto">How we support children with care, education, and hope.</p>
</div> </div>
</section> </section>
<!-- Mission Section --> <section class="section bg-white dark:bg-gray-900" data-animate-on-scroll="fade-in">
<section class="mission-section">
<div class="container"> <div class="container">
<div class="mission-content"> <div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
<div class="mission-text"> <div data-animate-on-scroll="slide-up">
<h2 class="section-title">Our Mission</h2> <h2 class="font-headline text-3xl font-bold text-nigerian-green-700 dark:text-kente-gold-400 mb-4">About the Orphanage</h2>
<p class="mission-description"> <p class="text-gray-700 dark:text-gray-300 leading-relaxed mb-4">
Through our orphanage project, we provide a safe haven for vulnerable children who have lost their parents or been abandoned. The Omoluabi Foundation is proud to support [Orphanage Name], a safe haven for orphaned and vulnerable children in Nigeria. Our partnership ensures that these children receive the care, education, and support they need to thrive.
Our goal is to give these children not just shelter and food, but also love, education, and the opportunity to build a better future.
</p> </p>
<div class="mission-features"> <p class="text-gray-700 dark:text-gray-300 leading-relaxed mb-4">
<div class="feature-item"> At [Orphanage Name], children are provided with nutritious meals, comfortable shelter, access to quality education, and essential healthcare. Beyond basic needs, we strive to create a loving and nurturing environment where each child can develop their potential and build a hopeful future.
<div class="feature-icon">🏠</div> </p>
<h3>Safe Shelter</h3> <ul class="list-disc list-inside text-gray-700 space-y-2">
<p>Providing a secure and nurturing environment for children to grow and thrive.</p> <li>Providing safe and nurturing environment.</li>
</div> <li>Ensuring access to quality education.</li>
<div class="feature-item"> <li>Offering healthcare and nutritional support.</li>
<div class="feature-icon">📚</div> <li>Fostering personal growth and development.</li>
<h3>Quality Education</h3> </ul>
<p>Ensuring every child has access to proper education and learning opportunities.</p>
</div>
<div class="feature-item">
<div class="feature-icon">❤️</div>
<h3>Loving Care</h3>
<p>Surrounding children with love, support, and positive role models.</p>
</div>
</div>
</div>
<div class="mission-image">
<div class="image-placeholder">
<span>Orphanage Image</span>
</div> </div>
<div class="relative" data-animate-on-scroll="slide-up" style="transition-delay: 0.1s;">
<img src="/images/hero2.jpg" alt="Orphanage Children" class="w-full h-96 object-cover rounded-2xl shadow-xl" />
<div class="absolute -bottom-4 -left-4 bg-kente-gold-500 text-white px-4 py-2 rounded-full font-bold shadow-lg">Hope for the Future</div>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<!-- Impact Section --> <section class="section bg-gray-50 dark:bg-gray-900" data-animate-on-scroll="fade-in">
<section class="impact-section">
<div class="container"> <div class="container">
<h2 class="section-title">Our Impact</h2> <div class="text-center mb-12">
<div class="impact-grid"> <h2 class="font-headline text-4xl font-bold text-gray-900 dark:text-white mb-4">
<div class="impact-card"> How You Can <span class="text-kente-gold-700">Help</span>
<div class="impact-icon">🎓</div> </h2>
<h3>Education Success</h3> <p class="text-lg text-gray-600 dark:text-gray-300 max-w-2xl mx-auto">
<p>15 children have successfully completed their primary education and are now in secondary school.</p> Your support makes a direct and meaningful impact on the lives of these children.
</p>
<div class="w-24 h-1 bg-gradient-to-r from-kente-gold-500 to-nigerian-green-500 mx-auto rounded-full mt-6"></div>
</div> </div>
<div class="impact-card">
<div class="impact-icon">🏥</div> <div class="grid grid-cols-1 md:grid-cols-2 gap-8">
<h3>Healthcare Access</h3> <div class="bg-white dark:bg-gray-800 p-6 rounded-xl shadow-md border border-gray-200 dark:border-gray-700" data-animate-on-scroll="slide-up">
<p>All children receive regular medical check-ups and access to healthcare when needed.</p> <h3 class="font-semibold text-xl text-nigerian-green-700 mb-3">Make a Donation</h3>
<p class="text-gray-700 dark:text-gray-300 mb-4">
Financial contributions are crucial for covering daily operational costs, food, education, and medical expenses.
</p>
<a href="/donate" class="text-nigerian-green-500 hover:underline font-medium">Donate Now →</a>
</div> </div>
<div class="impact-card"> <div class="bg-white dark:bg-gray-800 p-6 rounded-xl shadow-md border border-gray-200 dark:border-gray-700" data-animate-on-scroll="slide-up" style="transition-delay: 0.1s;">
<div class="impact-icon">👨‍👩‍👧‍👦</div> <h3 class="font-semibold text-xl text-kente-gold-700 mb-3">Sponsor a Child</h3>
<h3>Family Reunification</h3> <p class="text-gray-700 dark:text-gray-300 mb-4">
<p>8 children have been successfully reunited with extended family members.</p> Provide ongoing support for a child's specific needs, including education and personal development.
</p>
<a href="/contact" class="text-kente-gold-500 hover:underline font-medium">Learn About Sponsorship →</a>
</div> </div>
<div class="impact-card"> <div class="bg-white dark:bg-gray-800 p-6 rounded-xl shadow-md border border-gray-200 dark:border-gray-700" data-animate-on-scroll="slide-up" style="transition-delay: 0.2s;">
<div class="impact-icon">🌟</div> <h3 class="font-semibold text-xl text-ankara-red-700 mb-3">Volunteer Your Time</h3>
<h3>Life Skills</h3> <p class="text-gray-700 dark:text-gray-300 mb-4">
<p>Children learn essential life skills including cooking, cleaning, and personal responsibility.</p> If you are in Nigeria, consider volunteering directly at the orphanage to assist with daily activities.
</p>
<a href="/contact" class="text-ankara-red-500 hover:underline font-medium">Volunteer Today →</a>
</div>
<div class="bg-white dark:bg-gray-800 p-6 rounded-xl shadow-md border border-gray-200 dark:border-gray-700" data-animate-on-scroll="slide-up" style="transition-delay: 0.3s;">
<h3 class="font-semibold text-xl text-adire-blue-700 mb-3">Spread the Word</h3>
<p class="text-gray-700 dark:text-gray-300 mb-4">
Share our mission with your friends, family, and social networks to help us reach more supporters.
</p>
<a href="#" class="text-adire-blue-500 hover:underline font-medium">Share Now →</a>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
</BaseLayout>
<!-- How to Help Section -->
<section class="help-section">
<div class="container">
<h2 class="section-title">How You Can Help</h2>
<div class="help-options">
<div class="help-card">
<div class="help-icon">💰</div>
<h3>Financial Donations</h3>
<p>Your monetary contributions help us provide food, shelter, education, and healthcare for the children.</p>
<a href="/donate" class="help-btn">Donate Now</a>
</div>
<div class="help-card">
<div class="help-icon">📦</div>
<h3>Material Donations</h3>
<p>We accept clothing, books, toys, and other essential items for the children.</p>
<a href="/contact" class="help-btn">Contact Us</a>
</div>
<div class="help-card">
<div class="help-icon">🤝</div>
<h3>Volunteer</h3>
<p>Share your time and skills by volunteering at our orphanage or helping with fundraising events.</p>
<a href="/contact" class="help-btn">Get Involved</a>
</div>
</div>
</div>
</section>
<!-- Gallery Section -->
<section class="gallery-section">
<div class="container">
<h2 class="section-title">Life at Our Orphanage</h2>
<div class="gallery-grid">
<div class="gallery-item">
<div class="gallery-placeholder">
<span>Children Learning</span>
</div>
</div>
<div class="gallery-item">
<div class="gallery-placeholder">
<span>Play Time</span>
</div>
</div>
<div class="gallery-item">
<div class="gallery-placeholder">
<span>Meal Time</span>
</div>
</div>
<div class="gallery-item">
<div class="gallery-placeholder">
<span>Study Time</span>
</div>
</div>
</div>
</div>
</section>
<!-- CTA Section -->
<section class="cta-section">
<div class="container">
<div class="cta-card">
<h2 class="cta-title">Make a Difference Today</h2>
<p class="cta-text">Every donation, no matter how small, makes a real difference in the lives of these children. Join us in our mission to provide hope and opportunity.</p>
<div class="cta-buttons">
<a href="/donate" class="btn btn-primary">Donate Now</a>
<a href="/contact" class="btn btn-secondary">Learn More</a>
</div>
</div>
</div>
</section>
</main>
<Footer />
<style>
/* Orphanage Page Styles */
.orphanage-page {
min-height: 100vh;
background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%);
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 0 2rem;
}
/* Hero Section */
.orphanage-hero {
background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);
color: white;
padding: 6rem 0 4rem;
text-align: center;
position: relative;
overflow: hidden;
}
.orphanage-hero::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="grain" width="100" height="100" patternUnits="userSpaceOnUse"><circle cx="25" cy="25" r="1" fill="white" opacity="0.1"/><circle cx="75" cy="75" r="1" fill="white" opacity="0.1"/><circle cx="50" cy="10" r="0.5" fill="white" opacity="0.1"/><circle cx="10" cy="60" r="0.5" fill="white" opacity="0.1"/><circle cx="90" cy="40" r="0.5" fill="white" opacity="0.1"/></pattern></defs><rect width="100" height="100" fill="url(%23grain)"/></svg>');
opacity: 0.3;
}
.orphanage-title {
font-size: 3.5rem;
font-weight: 700;
margin-bottom: 1rem;
position: relative;
z-index: 1;
}
.orphanage-subtitle {
font-size: 1.25rem;
opacity: 0.9;
max-width: 600px;
margin: 0 auto 3rem;
position: relative;
z-index: 1;
}
.hero-stats {
display: flex;
justify-content: center;
gap: 3rem;
flex-wrap: wrap;
position: relative;
z-index: 1;
}
.stat-item {
text-align: center;
}
.stat-number {
display: block;
font-size: 2.5rem;
font-weight: 700;
margin-bottom: 0.5rem;
}
.stat-label {
font-size: 1rem;
opacity: 0.9;
}
/* Mission Section */
.mission-section {
padding: 4rem 0;
}
.mission-content {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 4rem;
align-items: center;
}
.section-title {
font-size: 2.5rem;
font-weight: 600;
color: #16a34a;
margin-bottom: 1.5rem;
}
.mission-description {
font-size: 1.1rem;
line-height: 1.7;
color: #374151;
margin-bottom: 2rem;
}
.mission-features {
display: flex;
flex-direction: column;
gap: 1.5rem;
}
.feature-item {
display: flex;
align-items: flex-start;
gap: 1rem;
}
.feature-icon {
font-size: 2rem;
flex-shrink: 0;
}
.feature-item h3 {
font-size: 1.25rem;
font-weight: 600;
color: #16a34a;
margin-bottom: 0.5rem;
}
.feature-item p {
color: #6b7280;
line-height: 1.6;
}
.mission-image {
display: flex;
justify-content: center;
align-items: center;
}
.image-placeholder {
width: 100%;
height: 300px;
background: linear-gradient(135deg, #e5e7eb 0%, #d1d5db 100%);
border-radius: 20px;
display: flex;
align-items: center;
justify-content: center;
color: #6b7280;
font-size: 1.1rem;
border: 2px dashed #9ca3af;
}
/* Impact Section */
.impact-section {
padding: 4rem 0;
background: white;
}
.impact-section .section-title {
text-align: center;
margin-bottom: 3rem;
}
.impact-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 2rem;
}
.impact-card {
background: white;
padding: 2rem;
border-radius: 20px;
text-align: center;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
border: 1px solid rgba(22, 163, 74, 0.1);
transition: all 0.3s ease;
}
.impact-card:hover {
transform: translateY(-5px);
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);
}
.impact-icon {
font-size: 3rem;
margin-bottom: 1rem;
}
.impact-card h3 {
font-size: 1.25rem;
font-weight: 600;
color: #16a34a;
margin-bottom: 1rem;
}
.impact-card p {
color: #6b7280;
line-height: 1.6;
}
/* Help Section */
.help-section {
padding: 4rem 0;
}
.help-section .section-title {
text-align: center;
margin-bottom: 3rem;
}
.help-options {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 2rem;
}
.help-card {
background: white;
padding: 2.5rem;
border-radius: 20px;
text-align: center;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
border: 1px solid rgba(22, 163, 74, 0.1);
transition: all 0.3s ease;
}
.help-card:hover {
transform: translateY(-5px);
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);
}
.help-icon {
font-size: 3rem;
margin-bottom: 1rem;
}
.help-card h3 {
font-size: 1.5rem;
font-weight: 600;
color: #16a34a;
margin-bottom: 1rem;
}
.help-card p {
color: #6b7280;
line-height: 1.6;
margin-bottom: 2rem;
}
.help-btn {
display: inline-block;
padding: 0.75rem 2rem;
background: linear-gradient(45deg, #16a34a, #15803d);
color: white;
text-decoration: none;
border-radius: 12px;
font-weight: 600;
transition: all 0.3s ease;
}
.help-btn:hover {
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(22, 163, 74, 0.4);
}
/* Gallery Section */
.gallery-section {
padding: 4rem 0;
background: white;
}
.gallery-section .section-title {
text-align: center;
margin-bottom: 3rem;
}
.gallery-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 1.5rem;
}
.gallery-item {
aspect-ratio: 1;
border-radius: 15px;
overflow: hidden;
}
.gallery-placeholder {
width: 100%;
height: 100%;
background: linear-gradient(135deg, #e5e7eb 0%, #d1d5db 100%);
display: flex;
align-items: center;
justify-content: center;
color: #6b7280;
font-size: 1rem;
border: 2px dashed #9ca3af;
}
/* CTA Section */
.cta-section {
padding: 4rem 0;
background: linear-gradient(135deg, #16a34a 0%, #15803d 100%);
}
.cta-card {
background: white;
border-radius: 20px;
padding: 3rem;
text-align: center;
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
}
.cta-title {
font-size: 2.5rem;
font-weight: 600;
color: #16a34a;
margin-bottom: 1rem;
}
.cta-text {
font-size: 1.1rem;
color: #6b7280;
margin-bottom: 2rem;
max-width: 600px;
margin-left: auto;
margin-right: auto;
}
.cta-buttons {
display: flex;
gap: 1rem;
justify-content: center;
flex-wrap: wrap;
}
.btn {
display: inline-flex;
align-items: center;
padding: 0.75rem 2rem;
border-radius: 12px;
font-weight: 600;
text-decoration: none;
transition: all 0.3s ease;
font-size: 1rem;
}
.btn-primary {
background: linear-gradient(45deg, #16a34a, #15803d);
color: white;
box-shadow: 0 4px 15px rgba(22, 163, 74, 0.3);
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(22, 163, 74, 0.4);
}
.btn-secondary {
background: white;
color: #16a34a;
border: 2px solid #16a34a;
}
.btn-secondary:hover {
background: #16a34a;
color: white;
transform: translateY(-2px);
}
/* Responsive Design */
@media (max-width: 768px) {
.orphanage-title {
font-size: 2.5rem;
}
.orphanage-subtitle {
font-size: 1.1rem;
}
.hero-stats {
gap: 2rem;
}
.stat-number {
font-size: 2rem;
}
.mission-content {
grid-template-columns: 1fr;
gap: 2rem;
}
.section-title {
font-size: 2rem;
}
.help-options {
grid-template-columns: 1fr;
}
.cta-title {
font-size: 2rem;
}
.cta-buttons {
flex-direction: column;
align-items: center;
}
.btn {
width: 100%;
max-width: 250px;
justify-content: center;
}
}
@media (max-width: 480px) {
.container {
padding: 0 1rem;
}
.orphanage-hero {
padding: 4rem 0 3rem;
}
.orphanage-title {
font-size: 2rem;
}
.hero-stats {
flex-direction: column;
gap: 1.5rem;
}
.help-card {
padding: 2rem;
}
.cta-card {
padding: 2rem;
}
}
</style>
</body>
</html>

View File

@@ -1,26 +1,25 @@
/* src/styles/global.css */
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Poppins:wght@400;500;600;700;800&family=Noto+Serif:wght@400;600;700&display=swap'); @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Poppins:wght@400;500;600;700;800&family=Noto+Serif:wght@400;600;700&display=swap');
@import "tailwindcss/base";
@import "tailwindcss/components";
@import "tailwindcss/utilities";
/* Root Variables for Nigerian Theme */ @tailwind base;
@tailwind components;
@tailwind utilities;
/* CSS Variables */
:root { :root {
--nigerian-green: #16a34a; --nigerian-green: #16a34a;
--nigerian-white: #ffffff;
--kente-gold: #f59e0b; --kente-gold: #f59e0b;
--adire-blue: #2563eb;
--ankara-red: #dc2626; --ankara-red: #dc2626;
--earth-brown: #a18072; --adire-blue: #2563eb;
/* Dutch Flag Colors */
--dutch-red: #21468b;
--dutch-white: #ffffff;
--dutch-blue: #1e4785;
} }
html { /* Dark theme tokens */
scroll-behavior: smooth; .dark {
} --dutch-white: #0b0f14;
body {
font-family: 'Inter', system-ui, sans-serif;
background: linear-gradient(135deg, #fafafa 0%, #f0fdf4 100%);
min-height: 100vh;
} }
/* Custom scrollbar */ /* Custom scrollbar */
@@ -41,357 +40,138 @@ body {
background: #15803d; background: #15803d;
} }
/* Smooth hover transitions */ /* Smooth scrolling */
* { html {
transition: all 0.2s ease-in-out; scroll-behavior: smooth;
} }
/* Nigerian pattern overlay */ /* Animation keyframes */
.nigerian-pattern {
position: relative;
}
.nigerian-pattern::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-image: url("data:image/svg+xml,%3Csvg width='40' height='40' viewBox='0 0 40 40' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='%23f59e0b' fill-opacity='0.03'%3E%3Cpath d='M20 20c0 11.046-8.954 20-20 20v-40c11.046 0 20 8.954 20 20zM40 20c0 11.046-8.954 20-20 20v-40c11.046 0 20 8.954 20 20z'/%3E%3C/g%3E%3C/svg%3E");
pointer-events: none;
}
/* Enhanced button styles */
.btn {
border-radius: 12px;
font-weight: 600;
letter-spacing: 0.025em;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
position: relative;
overflow: hidden;
padding: 0.75rem 1.5rem;
border: none;
cursor: pointer;
display: inline-flex;
align-items: center;
justify-content: center;
text-decoration: none;
}
.btn-primary {
background: var(--nigerian-green);
color: white;
}
.btn-secondary {
background: var(--kente-gold);
color: white;
}
.btn-accent {
background: var(--ankara-red);
color: white;
}
.btn::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
transition: left 0.5s;
}
.btn:hover::before {
left: 100%;
}
.btn:hover {
transform: translateY(-2px);
box-shadow: 0 10px 25px -3px rgba(0, 0, 0, 0.1);
}
.btn-lg {
padding: 1rem 2rem;
font-size: 1.125rem;
}
/* Card enhancements */
.card {
border-radius: 16px;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
border: 1px solid rgba(229, 229, 229, 0.8);
background: white;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
}
.card:hover {
transform: translateY(-4px);
box-shadow: 0 20px 40px -12px rgba(0, 0, 0, 0.15);
}
.card-body {
padding: 1.5rem;
}
/* Input styling */
.input, .textarea {
border-radius: 12px;
border: 2px solid #e5e5e5;
transition: all 0.3s ease;
padding: 0.75rem 1rem;
width: 100%;
background: white;
}
.input:focus, .textarea:focus {
border-color: var(--nigerian-green);
box-shadow: 0 0 0 3px rgba(22, 163, 74, 0.1);
outline: none;
}
/* Badge styling */
.badge {
border-radius: 20px;
font-weight: 600;
letter-spacing: 0.025em;
padding: 0.5rem 1rem;
font-size: 0.875rem;
display: inline-flex;
align-items: center;
}
.badge-primary {
background: var(--nigerian-green);
color: white;
}
.badge-secondary {
background: var(--kente-gold);
color: white;
}
.badge-lg {
padding: 0.75rem 1.25rem;
font-size: 1rem;
}
/* Hero text animations */
@keyframes textShine { @keyframes textShine {
0% { background-position: -200% center; } 0% { background-position: -200% center; }
100% { background-position: 200% center; } 100% { background-position: 200% center; }
} }
.text-shine {
background: linear-gradient(90deg, var(--nigerian-green), var(--kente-gold), var(--ankara-red), var(--nigerian-green));
background-size: 200% auto;
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
animation: textShine 3s linear infinite;
}
/* Animations */
@keyframes float { @keyframes float {
0%, 100% { transform: translateY(0px); } 0%, 100% { transform: translateY(0px); }
50% { transform: translateY(-10px); } 50% { transform: translateY(-10px); }
} }
@keyframes slideUp {
0% { transform: translateY(30px); opacity: 0; }
100% { transform: translateY(0px); opacity: 1; }
}
@keyframes fadeIn {
0% { opacity: 0; }
100% { opacity: 1; }
}
@keyframes bounceGentle { @keyframes bounceGentle {
0%, 100% { transform: translateY(0px); } 0%, 20%, 53%, 80%, 100% { transform: translateY(0); }
50% { transform: translateY(-5px); } 40%, 43% { transform: translateY(-10px); }
70% { transform: translateY(-5px); }
90% { transform: translateY(-2px); }
}
/* Animation classes */
.animate-text-shine {
background: linear-gradient(90deg, #ffffff, #e0e7ff, #8b5cf6, #e0e7ff, #ffffff);
background-size: 300% auto;
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
animation: textShine 8s linear infinite; /* Changed from 4s to 8s */
} }
.animate-float { .animate-float {
animation: float 6s ease-in-out infinite; animation: float 6s ease-in-out infinite;
} }
.animate-slide-up {
animation: slideUp 0.8s ease-out;
}
.animate-fade-in {
animation: fadeIn 1s ease-out;
}
.animate-bounce-gentle { .animate-bounce-gentle {
animation: bounceGentle 2s ease-in-out infinite; animation: bounceGentle 2s infinite;
} }
/* Color utilities */ .animation-delay-1s {
.text-nigerian-green { color: var(--nigerian-green); } animation-delay: 1s;
.text-kente-gold { color: var(--kente-gold); }
.text-ankara-red { color: var(--ankara-red); }
.text-primary { color: var(--nigerian-green); }
.text-secondary { color: var(--kente-gold); }
.text-accent { color: var(--ankara-red); }
.bg-nigerian-green { background-color: var(--nigerian-green); }
.bg-kente-gold { background-color: var(--kente-gold); }
.bg-ankara-red { background-color: var(--ankara-red); }
.bg-primary { background-color: var(--nigerian-green); }
.bg-secondary { background-color: var(--kente-gold); }
.bg-accent { background-color: var(--ankara-red); }
/* Gradient backgrounds */
.bg-nigerian-gradient {
background: linear-gradient(135deg, var(--nigerian-green) 0%, var(--kente-gold) 100%);
} }
.bg-cultural-gradient { /* Layout classes */
background: linear-gradient(135deg, var(--nigerian-green) 0%, var(--kente-gold) 25%, var(--ankara-red) 75%, var(--nigerian-green) 100%); @layer components {
} .section {
@apply py-16;
}
/* Section padding utility */ .container {
.section-padding { @apply max-w-7xl mx-auto px-4 sm:px-6 lg:px-8;
padding: 5rem 1rem; }
}
@media (max-width: 768px) { /* Card components */
.section-padding { .card {
padding: 3rem 1rem; @apply bg-white rounded-xl shadow-lg overflow-hidden;
}
.card-body {
@apply p-6;
}
.card-title {
@apply text-xl font-bold mb-2;
}
/* Button components */
.btn {
@apply inline-flex items-center px-6 py-3 rounded-lg font-medium transition-all duration-200 cursor-pointer;
}
.btn-lg {
@apply px-8 py-4 text-lg;
}
/* Badge components */
.badge {
@apply inline-flex items-center px-3 py-1 rounded-full text-sm font-medium;
}
.badge-lg {
@apply px-4 py-2;
} }
} }
/* Grid utilities */ /* Custom utility classes */
.container { @layer utilities {
width: 100%; .text-shadow-lg {
max-width: 1200px; text-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
margin: 0 auto; }
padding: 0 1rem;
.backdrop-blur-xs {
backdrop-filter: blur(2px);
}
} }
/* Typography */ /* Animation utilities */
.font-headline { font-family: 'Poppins', system-ui, sans-serif; } [data-animate-on-scroll] {
.font-body { font-family: 'Inter', system-ui, sans-serif; } opacity: 0;
.font-cultural { font-family: 'Noto Serif', serif; } transform: translateY(30px);
transition: all 0.6s ease;
/* Text sizes */
.text-xs { font-size: 0.75rem; }
.text-sm { font-size: 0.875rem; }
.text-base { font-size: 1rem; }
.text-lg { font-size: 1.125rem; }
.text-xl { font-size: 1.25rem; }
.text-2xl { font-size: 1.5rem; }
.text-3xl { font-size: 1.875rem; }
.text-4xl { font-size: 2.25rem; }
.text-5xl { font-size: 3rem; }
.text-6xl { font-size: 3.75rem; }
.text-7xl { font-size: 4.5rem; }
/* Font weights */
.font-light { font-weight: 300; }
.font-normal { font-weight: 400; }
.font-medium { font-weight: 500; }
.font-semibold { font-weight: 600; }
.font-bold { font-weight: 700; }
/* Spacing utilities */
.p-4 { padding: 1rem; }
.p-6 { padding: 1.5rem; }
.p-8 { padding: 2rem; }
.px-4 { padding-left: 1rem; padding-right: 1rem; }
.py-4 { padding-top: 1rem; padding-bottom: 1rem; }
.m-4 { margin: 1rem; }
.mb-4 { margin-bottom: 1rem; }
.mb-6 { margin-bottom: 1.5rem; }
.mb-8 { margin-bottom: 2rem; }
.mt-8 { margin-top: 2rem; }
.mt-12 { margin-top: 3rem; }
.mt-16 { margin-top: 4rem; }
.mt-20 { margin-top: 5rem; }
/* Layout utilities */
.flex { display: flex; }
.grid { display: grid; }
.block { display: block; }
.inline-flex { display: inline-flex; }
.items-center { align-items: center; }
.justify-center { justify-content: center; }
.justify-between { justify-content: space-between; }
.gap-4 { gap: 1rem; }
.gap-6 { gap: 1.5rem; }
.gap-8 { gap: 2rem; }
.gap-12 { gap: 3rem; }
/* Grid utilities */
.grid-cols-1 { grid-template-columns: repeat(1, minmax(0, 1fr)); }
.grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (min-width: 768px) {
.md\\:grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.md\\:grid-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
} }
@media (min-width: 1024px) { [data-animate-on-scroll].visible {
.lg\\:grid-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); } opacity: 1;
.lg\\:col-span-2 { grid-column: span 2 / span 2; } transform: translateY(0);
} }
/* Positioning */ /* Responsive design adjustments */
.relative { position: relative; } @media (max-width: 768px) {
.absolute { position: absolute; } .section {
.fixed { position: fixed; } @apply py-8;
.top-0 { top: 0; } }
.left-0 { left: 0; }
.right-0 { right: 0; }
.bottom-0 { bottom: 0; }
.inset-0 { top: 0; right: 0; bottom: 0; left: 0; }
.z-10 { z-index: 10; }
.z-50 { z-index: 50; }
/* Width and height */ .hero-title-shine {
.w-full { width: 100%; } font-size: 2.5rem !important;
.h-full { height: 100%; } }
.min-h-screen { min-height: 100vh; } }
.max-w-2xl { max-width: 42rem; }
.max-w-3xl { max-width: 48rem; }
.max-w-4xl { max-width: 56rem; }
.max-w-5xl { max-width: 64rem; }
.max-w-6xl { max-width: 72rem; }
.mx-auto { margin-left: auto; margin-right: auto; }
/* Rounded corners */ /* Reduced motion support */
.rounded-lg { border-radius: 0.5rem; } @media (prefers-reduced-motion: reduce) {
.rounded-xl { border-radius: 0.75rem; } .animate-text-shine,
.rounded-2xl { border-radius: 1rem; } .animate-float,
.rounded-full { border-radius: 9999px; } .animate-bounce-gentle {
animation: none;
}
/* Shadows */ * {
.shadow-lg { box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); } transition-duration: 0.01ms !important;
.shadow-xl { box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04); } animation-duration: 0.01ms !important;
.shadow-2xl { box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25); } animation-iteration-count: 1 !important;
}
/* Transforms */ }
.transform { transform: translateX(var(--tw-translate-x, 0)) translateY(var(--tw-translate-y, 0)) rotate(var(--tw-rotate, 0)) skewX(var(--tw-skew-x, 0)) skewY(var(--tw-skew-y, 0)) scaleX(var(--tw-scale-x, 1)) scaleY(var(--tw-scale-y, 1)); }
.hover\\:scale-105:hover { --tw-scale-x: 1.05; --tw-scale-y: 1.05; }
.hover\\:-translate-y-2:hover { --tw-translate-y: -0.5rem; }
/* Text alignment */
.text-center { text-align: center; }
.text-left { text-align: left; }
/* Overflow */
.overflow-hidden { overflow: hidden; }
/* Background opacity */
.bg-opacity-80 { background-color: rgba(var(--tw-bg-opacity-value, 1), 0.8); }
.bg-opacity-90 { background-color: rgba(var(--tw-bg-opacity-value, 1), 0.9); }
/* Object fit */
.object-cover { object-fit: cover; }
.object-contain { object-fit: contain; }

View File

@@ -1,323 +1,5 @@
/* Custom CSS for Omoluabi Foundation */ /* Custom CSS for Omoluabi Foundation */
/* Import Google Fonts */
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700;800&display=swap');
/* Global Font Settings */
* {
font-family: 'Poppins', sans-serif;
}
/* Hero Section */
.hero {
min-height: 100vh;
background: linear-gradient(135deg, #16a34a 0%, #f59e0b 50%, #dc2626 100%);
display: flex;
align-items: center;
justify-content: center;
position: relative;
overflow: hidden;
color: white;
text-align: center;
}
.hero::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-image: url("data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%23ffffff' fill-opacity='0.05'%3E%3Cpath d='M36 34v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zm0-30V0h-2v4h-4v2h4v4h2V6h4V4h-4zM6 34v-4H4v4H0v2h4v4h2v-4h4v-2H6zM6 4V0H4v4H0v2h4v4h2V6h4V4H6z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
pointer-events: none;
}
.hero-content {
max-width: 1200px;
margin: 0 auto;
padding: 0 2rem;
position: relative;
z-index: 10;
}
.hero-title {
font-family: 'Poppins', sans-serif;
font-size: 4rem;
font-weight: 800;
margin-bottom: 1.5rem;
line-height: 1.1;
}
.hero-subtitle {
font-size: 1.5rem;
margin-bottom: 2rem;
max-width: 48rem;
margin-left: auto;
margin-right: auto;
font-weight: 300;
line-height: 1.6;
}
.hero-symbols {
display: flex;
align-items: center;
justify-content: center;
gap: 1rem;
margin-bottom: 3rem;
font-size: 2rem;
}
.hero-symbols span:nth-child(odd) {
animation: bounce 2s ease-in-out infinite;
}
.hero-symbols span:nth-child(2) {
animation-delay: 0.5s;
}
.hero-symbols span:nth-child(4) {
animation-delay: 1s;
}
.hero-cta {
display: flex;
flex-direction: column;
gap: 1rem;
align-items: center;
justify-content: center;
}
/* Floating Elements */
.floating-element {
position: absolute;
border-radius: 50%;
animation: float 6s ease-in-out infinite;
}
.floating-1 {
top: 5rem;
left: 2.5rem;
width: 4rem;
height: 4rem;
background: rgba(245, 158, 11, 0.3);
}
.floating-2 {
top: 10rem;
right: 5rem;
width: 3rem;
height: 3rem;
background: rgba(220, 38, 38, 0.3);
animation-delay: 1s;
}
.floating-3 {
bottom: 8rem;
left: 25%;
width: 5rem;
height: 5rem;
background: rgba(37, 99, 235, 0.3);
animation-delay: 2s;
}
/* Section Styles */
.section {
padding: 5rem 2rem;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
.section-title {
font-family: 'Poppins', sans-serif;
font-size: 2.5rem;
font-weight: 700;
text-align: center;
margin-bottom: 1rem;
color: #111827;
}
.section-subtitle {
font-size: 1.25rem;
color: #6b7280;
text-align: center;
max-width: 42rem;
margin: 0 auto 3rem;
}
.section-divider {
width: 6rem;
height: 0.25rem;
background: linear-gradient(to right, #16a34a, #f59e0b);
border-radius: 25px;
margin: 0 auto 3rem;
}
/* About Section */
.about-section {
background: linear-gradient(135deg, #f9fafb 0%, #f0fdf4 100%);
position: relative;
}
.about-grid {
display: grid;
grid-template-columns: 1fr;
gap: 3rem;
align-items: center;
}
.about-image {
position: relative;
}
.about-image-frame {
position: absolute;
inset: -1rem;
background: linear-gradient(45deg, #f59e0b, #dc2626);
border-radius: 1rem;
transform: rotate(1deg);
}
.about-image-container {
position: relative;
background: white;
padding: 0.5rem;
border-radius: 1rem;
box-shadow: 0 25px 50px rgba(0, 0, 0, 0.15);
transform: rotate(-1deg);
transition: transform 0.5s ease;
}
.about-image-container:hover {
transform: rotate(0deg);
}
.about-image img {
width: 100%;
height: 24rem;
object-fit: cover;
border-radius: 0.75rem;
}
.about-line {
width: 0.5rem;
height: 3rem;
background: linear-gradient(to bottom, #16a34a, #f59e0b);
border-radius: 25px;
}
.about-stats {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1rem;
margin: 2rem 0;
}
.stat-card {
text-align: center;
padding: 1rem;
background: white;
border-radius: 0.75rem;
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
transition: all 0.3s ease;
}
.stat-card:hover {
transform: translateY(-4px);
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);
}
.stat-number {
font-size: 1.5rem;
font-weight: 700;
margin-bottom: 0.25rem;
}
.stat-label {
font-size: 0.875rem;
color: #6b7280;
}
.badges {
display: flex;
flex-wrap: wrap;
gap: 0.75rem;
}
.badge {
padding: 0.5rem 1rem;
border-radius: 20px;
font-weight: 600;
font-size: 0.875rem;
border: 1px solid;
}
.badge-green {
background: rgba(22, 163, 74, 0.1);
color: #16a34a;
border-color: rgba(22, 163, 74, 0.2);
}
.badge-gold {
background: rgba(245, 158, 11, 0.1);
color: #f59e0b;
border-color: rgba(245, 158, 11, 0.2);
}
.badge-red {
background: rgba(220, 38, 38, 0.1);
color: #dc2626;
border-color: rgba(220, 38, 38, 0.2);
}
.badge-blue {
background: rgba(37, 99, 235, 0.1);
color: #2563eb;
border-color: rgba(37, 99, 235, 0.2);
}
/* Main Content */
.main-content {
padding-top: 5rem;
}
/* Button Styles */
.btn {
padding: 0.75rem 1.5rem;
border-radius: 8px;
font-weight: 600;
text-decoration: none;
border: none;
cursor: pointer;
transition: all 0.3s ease;
display: inline-flex;
align-items: center;
gap: 0.5rem;
}
.btn-primary {
background: #16a34a;
color: white;
}
.btn-secondary {
background: #f59e0b;
color: white;
}
.btn-outline {
background: transparent;
color: white;
border: 2px solid white;
}
.btn:hover {
transform: translateY(-2px);
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);
}
/* Hero Section Background Pattern */ /* Hero Section Background Pattern */
.hero-pattern { .hero-pattern {
background-image: url("data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%23ffffff' fill-opacity='0.05'%3E%3Cpath d='M36 34v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zm0-30V0h-2v4h-4v2h4v4h2V6h4V4h-4zM6 34v-4H4v4H0v2h4v4h2v-4h4v-2H6zM6 4V0H4v4H0v2h4v4h2V6h4V4H6z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E"); background-image: url("data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%23ffffff' fill-opacity='0.05'%3E%3Cpath d='M36 34v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zm0-30V0h-2v4h-4v2h4v4h2V6h4V4h-4zM6 34v-4H4v4H0v2h4v4h2v-4h4v-2H6zM6 4V0H4v4H0v2h4v4h2V6h4V4H6z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
@@ -337,7 +19,7 @@
background-clip: text; background-clip: text;
-webkit-background-clip: text; -webkit-background-clip: text;
-webkit-text-fill-color: transparent; -webkit-text-fill-color: transparent;
animation: textShine 20s linear infinite; animation: textShine 4s linear infinite;
text-shadow: 0 0 30px rgba(255, 255, 255, 0.3); text-shadow: 0 0 30px rgba(255, 255, 255, 0.3);
} }
@@ -375,21 +57,6 @@
} }
} }
@keyframes bounce {
0%, 20%, 53%, 80%, 100% {
transform: translateY(0);
}
40%, 43% {
transform: translateY(-10px);
}
70% {
transform: translateY(-5px);
}
90% {
transform: translateY(-2px);
}
}
@keyframes pulse { @keyframes pulse {
0%, 100% { 0%, 100% {
opacity: 1; opacity: 1;
@@ -544,11 +211,29 @@
box-shadow: 0 0 20px rgba(22, 163, 74, 0.6); box-shadow: 0 0 20px rgba(22, 163, 74, 0.6);
} }
/* Nigerian Flag Colors */ /* Nigerian Flag Background (vertical stripes) */
.nigerian-gradient { .nigerian-flag-bg {
background: linear-gradient(90deg, #16a34a 0%, #ffffff 50%, #16a34a 100%); background: linear-gradient(90deg, var(--nigerian-green) 0%, var(--nigerian-green) 33.33%, #fff 33.33%, #fff 66.66%, var(--nigerian-green) 66.66%, var(--nigerian-green) 100%);
} }
/* Dutch Flag Badge (horizontal stripes) */
.dutch-flag-badge {
width: 48px;
height: 16px;
border-radius: 3px;
overflow: hidden;
display: inline-block;
box-shadow: 0 1px 4px rgba(0,0,0,0.08);
border: 1px solid #eee;
}
.dutch-flag-badge .stripe {
height: 33.33%;
width: 100%;
}
.dutch-flag-badge .red { background: var(--dutch-red); }
.dutch-flag-badge .white { background: #fff; }
.dutch-flag-badge .blue { background: var(--dutch-blue); }
/* Kente Pattern Inspired Background */ /* Kente Pattern Inspired Background */
.kente-pattern { .kente-pattern {
background-image: background-image:
@@ -676,35 +361,53 @@
} }
} }
/* Responsive Design */ /* Nigerian + Dutch Flag Combined Gradient */
@media (min-width: 768px) { .combined-flag-gradient {
.hero-title { background: linear-gradient(90deg, var(--nigerian-green) 0%, var(--dutch-white) 20%, var(--dutch-red) 40%, var(--dutch-white) 60%, var(--dutch-blue) 80%, var(--nigerian-green) 100%);
font-size: 5rem;
} }
.hero-cta { /* Subtle brand surface (used for CTA sections) */
flex-direction: row; .brand-surface {
background: radial-gradient(1200px 600px at 20% 20%, rgba(10,10,10,0.08), rgba(10,10,10,0) 60%),
linear-gradient(135deg, rgba(12, 84, 36, 0.95) 0%, rgba(29, 78, 216, 0.90) 100%);
color: #fff;
} }
.about-grid { .dark .brand-surface {
grid-template-columns: 1fr 1fr; background: radial-gradient(1200px 600px at 20% 20%, rgba(255,255,255,0.04), rgba(255,255,255,0) 60%),
} linear-gradient(135deg, rgba(6, 59, 21, 0.95) 0%, rgba(23, 37, 84, 0.95) 100%);
} }
@media (max-width: 767px) { /* Combined Flag Button */
.hero-title { .btn-combined-flag {
font-size: 2.5rem; background: linear-gradient(135deg, var(--nigerian-green) 0%, var(--dutch-red) 33%, var(--dutch-white) 66%, var(--dutch-blue) 100%);
color: white;
border: none;
padding: 0.75rem 1.5rem;
border-radius: 0.75rem;
font-weight: 600;
transition: all 0.3s ease;
position: relative;
overflow: hidden;
} }
.hero-subtitle { .btn-combined-flag::before {
font-size: 1.25rem; content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(135deg, var(--dutch-blue) 0%, var(--dutch-white) 50%, var(--nigerian-green) 100%);
transition: left 0.3s ease;
z-index: -1;
} }
.section { .btn-combined-flag:hover::before {
padding: 3rem 1rem; left: 0;
} }
.main-content { .btn-combined-flag:hover {
padding-top: 4rem; transform: translateY(-2px);
} box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2);
} }

3
tailwind-input.css Normal file
View File

@@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

View File

@@ -1,56 +1,40 @@
// tailwind.config.mjs // tailwind.config.mjs
/** @type {import('tailwindcss').Config} */ /** @type {import('tailwindcss').Config} */
export default { export default {
darkMode: 'class',
content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'], content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],
theme: { theme: {
extend: { extend: {
fontFamily: {
'sans': ['Inter', 'system-ui', 'sans-serif'],
'headline': ['Poppins', 'system-ui', 'sans-serif'],
'serif': ['Noto Serif', 'serif'],
},
colors: { colors: {
// Nigerian flag colors as primary palette
'nigerian-green': { 'nigerian-green': {
50: '#f0fdf4', 50: '#f0fdf4',
100: '#dcfce7', 100: '#dcfce7',
200: '#bbf7d0', 200: '#bbf7d0',
300: '#86efac', 300: '#86efac',
400: '#4ade80', 400: '#4ade80',
500: '#22c55e', 500: '#16a34a', // Primary Nigerian green
600: '#16a34a', 600: '#15803d',
700: '#15803d', 700: '#166534',
800: '#166534', 800: '#14532d',
900: '#14532d', 900: '#14532d',
}, },
'nigerian-white': {
50: '#ffffff',
100: '#fefefe',
200: '#fafafa',
300: '#f5f5f5',
400: '#efefef',
500: '#e5e5e5',
},
// Rich cultural colors inspired by Nigerian textiles
'kente-gold': { 'kente-gold': {
50: '#fffbeb', 50: '#fffbeb',
100: '#fef3c7', 100: '#fef3c7',
200: '#fde68a', 200: '#fde68a',
300: '#fcd34d', 300: '#fcd34d',
400: '#fbbf24', 400: '#fbbf24',
500: '#f59e0b', 500: '#f59e0b', // Primary gold
600: '#d97706', 600: '#d97706',
700: '#b45309', 700: '#b45309',
800: '#92400e', 800: '#92400e',
900: '#78350f', 900: '#78350f',
}, },
'adire-blue': {
50: '#eff6ff',
100: '#dbeafe',
200: '#bfdbfe',
300: '#93c5fd',
400: '#60a5fa',
500: '#3b82f6',
600: '#2563eb',
700: '#1d4ed8',
800: '#1e40af',
900: '#1e3a8a',
},
'ankara-red': { 'ankara-red': {
50: '#fef2f2', 50: '#fef2f2',
100: '#fee2e2', 100: '#fee2e2',
@@ -58,227 +42,46 @@ export default {
300: '#fca5a5', 300: '#fca5a5',
400: '#f87171', 400: '#f87171',
500: '#ef4444', 500: '#ef4444',
600: '#dc2626', 600: '#dc2626', // Primary red
700: '#b91c1c', 700: '#b91c1c',
800: '#991b1b', 800: '#991b1b',
900: '#7f1d1d', 900: '#7f1d1d',
}, },
'earth-brown': { 'adire-blue': {
50: '#fdf8f6', 50: '#eff6ff',
100: '#f2e8e5', 100: '#dbeafe',
200: '#eaddd7', 200: '#bfdbfe',
300: '#e0cfc5', 300: '#93c5fd',
400: '#d2bab0', 400: '#60a5fa',
500: '#bfa094', 500: '#3b82f6',
600: '#a18072', 600: '#2563eb', // Primary blue
700: '#977669', 700: '#1d4ed8',
800: '#846358', 800: '#1e40af',
900: '#43302b', 900: '#1e3a8a',
}
}, },
fontFamily: {
'headline': ['Poppins', 'system-ui', 'sans-serif'],
'body': ['Inter', 'system-ui', 'sans-serif'],
'cultural': ['Noto Serif', 'serif'],
},
backgroundImage: {
'nigerian-pattern': `url("data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%23f59e0b' fill-opacity='0.05'%3E%3Cpath d='M36 34v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zm0-30V0h-2v4h-4v2h4v4h2V6h4V4h-4zM6 34v-4H4v4H0v2h4v4h2v-4h4v-2H6zM6 4V0H4v4H0v2h4v4h2V6h4V4H6z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E")`,
'kente-gradient': 'linear-gradient(135deg, #f59e0b 0%, #dc2626 25%, #16a34a 50%, #2563eb 75%, #f59e0b 100%)',
'hero-overlay': 'linear-gradient(135deg, rgba(22, 163, 74, 0.9) 0%, rgba(245, 158, 11, 0.8) 100%)',
}, },
animation: { animation: {
'text-shine': 'text-shine 8s linear infinite', // Changed from 4s to 8s
'float': 'float 6s ease-in-out infinite', 'float': 'float 6s ease-in-out infinite',
'slide-up': 'slideUp 0.8s ease-out', 'bounce-gentle': 'bounce-gentle 2s infinite',
'fade-in': 'fadeIn 1s ease-out',
'bounce-gentle': 'bounceGentle 2s ease-in-out infinite',
}, },
keyframes: { keyframes: {
float: { 'text-shine': {
'0%': { 'background-position': '-200% center' },
'100%': { 'background-position': '200% center' },
},
'float': {
'0%, 100%': { transform: 'translateY(0px)' }, '0%, 100%': { transform: 'translateY(0px)' },
'50%': { transform: 'translateY(-10px)' }, '50%': { transform: 'translateY(-10px)' },
}, },
slideUp: { 'bounce-gentle': {
'0%': { transform: 'translateY(30px)', opacity: '0' }, '0%, 20%, 53%, 80%, 100%': { transform: 'translateY(0)' },
'100%': { transform: 'translateY(0px)', opacity: '1' }, '40%, 43%': { transform: 'translateY(-10px)' },
}, '70%': { transform: 'translateY(-5px)' },
fadeIn: { '90%': { transform: 'translateY(-2px)' },
'0%': { opacity: '0' },
'100%': { opacity: '1' },
},
bounceGentle: {
'0%, 100%': { transform: 'translateY(0px)' },
'50%': { transform: 'translateY(-5px)' },
}
},
boxShadow: {
'nigerian': '0 10px 25px -3px rgba(22, 163, 74, 0.1), 0 4px 6px -2px rgba(22, 163, 74, 0.05)',
'kente': '0 10px 25px -3px rgba(245, 158, 11, 0.2), 0 4px 6px -2px rgba(245, 158, 11, 0.1)',
}
}, },
}, },
daisyui: {
themes: [
{
omoluabi: {
"primary": "#16a34a", // Nigerian green
"secondary": "#f59e0b", // Kente gold
"accent": "#dc2626", // Ankara red
"neutral": "#fafafa", // Clean white base
"base-100": "#ffffff", // Pure white
"base-200": "#f5f5f5", // Light gray
"base-300": "#e5e5e5", // Medium gray
"info": "#2563eb", // Adire blue
"success": "#22c55e", // Success green
"warning": "#f59e0b", // Warning gold
"error": "#dc2626", // Error red
}, },
}, },
], plugins: [ ],
}, }
plugins: [require("daisyui")],
}
/* Updated global.css */
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Poppins:wght@400;500;600;700;800&family=Noto+Serif:wght@400;600;700&display=swap');
@import "tailwindcss";
html {
scroll-behavior: smooth;
}
body {
font-family: 'Inter', system-ui, sans-serif;
background: linear-gradient(135deg, #fafafa 0%, #f0fdf4 100%);
min-height: 100vh;
}
/* Custom scrollbar */
::-webkit-scrollbar {
width: 8px;
}
::-webkit-scrollbar-track {
background: #f1f1f1;
}
::-webkit-scrollbar-thumb {
background: #16a34a;
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: #15803d;
}
/* Smooth hover transitions */
* {
transition: all 0.2s ease-in-out;
}
/* Nigerian pattern overlay */
.nigerian-pattern {
position: relative;
}
.nigerian-pattern::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-image: url("data:image/svg+xml,%3Csvg width='40' height='40' viewBox='0 0 40 40' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='%23f59e0b' fill-opacity='0.03'%3E%3Cpath d='M20 20c0 11.046-8.954 20-20 20v-40c11.046 0 20 8.954 20 20zM40 20c0 11.046-8.954 20-20 20v-40c11.046 0 20 8.954 20 20z'/%3E%3C/g%3E%3C/svg%3E");
pointer-events: none;
}
/* Enhanced button styles */
.btn {
border-radius: 12px;
font-weight: 600;
letter-spacing: 0.025em;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
position: relative;
overflow: hidden;
}
.btn::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
transition: left 0.5s;
}
.btn:hover::before {
left: 100%;
}
.btn:hover {
transform: translateY(-2px);
box-shadow: 0 10px 25px -3px rgba(0, 0, 0, 0.1);
}
/* Card enhancements */
.card {
border-radius: 16px;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
border: 1px solid rgba(229, 229, 229, 0.8);
}
.card:hover {
transform: translateY(-4px);
box-shadow: 0 20px 40px -12px rgba(0, 0, 0, 0.1);
}
/* Input styling */
.input, .textarea {
border-radius: 12px;
border: 2px solid #e5e5e5;
transition: all 0.3s ease;
}
.input:focus, .textarea:focus {
border-color: #16a34a;
box-shadow: 0 0 0 3px rgba(22, 163, 74, 0.1);
}
/* Badge styling */
.badge {
border-radius: 20px;
font-weight: 600;
letter-spacing: 0.025em;
}
/* Hero text animations */
@keyframes textShine {
0% { background-position: -200% center; }
100% { background-position: 200% center; }
}
.text-shine {
background: linear-gradient(90deg, #16a34a, #f59e0b, #dc2626, #16a34a);
background-size: 200% auto;
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
animation: textShine 3s linear infinite;
}
/* Loading animations */
.animate-pulse-slow {
animation: pulse 3s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
/* Custom spacing utilities */
.section-padding {
padding: 5rem 1rem;
}
@media (max-width: 768px) {
.section-padding {
padding: 3rem 1rem;
}
}