feat: Add contributing guidelines, license, and security policy documents
- Created CONTRIBUTING.md to outline contribution process and code of conduct. - Added LICENSE file with MIT License and third-party licenses. - Introduced SECURITY.md detailing vulnerability reporting and security measures. - Established README.md in assets directory for asset management and guidelines. - Implemented index.html as the main entry point for the website. - Configured package.json for project dependencies and scripts. - Developed styles.css for custom styles and responsive design. - Set up vite.config.ts for Vite configuration and build settings.
This commit is contained in:
190
CONTRIBUTING.md
Normal file
190
CONTRIBUTING.md
Normal file
@@ -0,0 +1,190 @@
|
||||
# Contributing to Miracles In Motion Website
|
||||
|
||||
Thank you for your interest in contributing to the Miracles In Motion website! This document provides guidelines for contributing to our project.
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
We are committed to providing a welcoming and inspiring community for all. Please read and follow our Code of Conduct:
|
||||
|
||||
- Be respectful and inclusive
|
||||
- Focus on what is best for the community
|
||||
- Show empathy towards other community members
|
||||
- Be collaborative
|
||||
- Gracefully accept constructive feedback
|
||||
|
||||
## How to Contribute
|
||||
|
||||
### Reporting Issues
|
||||
|
||||
If you find a bug or have a suggestion for improvement:
|
||||
|
||||
1. Check if the issue already exists in our [GitHub Issues](https://github.com/Miracles-In-Motion/public-web/issues)
|
||||
2. If not, create a new issue with:
|
||||
- Clear, descriptive title
|
||||
- Detailed description of the issue or suggestion
|
||||
- Steps to reproduce (for bugs)
|
||||
- Expected vs actual behavior
|
||||
- Screenshots if applicable
|
||||
- Browser and device information
|
||||
|
||||
### Contributing Code
|
||||
|
||||
1. **Fork the repository**
|
||||
```bash
|
||||
git clone https://github.com/Miracles-In-Motion/public-web.git
|
||||
cd public-web
|
||||
```
|
||||
|
||||
2. **Create a feature branch**
|
||||
```bash
|
||||
git checkout -b feature/your-feature-name
|
||||
```
|
||||
|
||||
3. **Make your changes**
|
||||
- Follow our coding standards (see below)
|
||||
- Test your changes thoroughly
|
||||
- Update documentation if needed
|
||||
|
||||
4. **Commit your changes**
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "feat: add new donation tracking feature"
|
||||
```
|
||||
|
||||
5. **Push and create a Pull Request**
|
||||
```bash
|
||||
git push origin feature/your-feature-name
|
||||
```
|
||||
|
||||
## Coding Standards
|
||||
|
||||
### HTML/CSS
|
||||
- Use semantic HTML5 elements
|
||||
- Follow accessibility guidelines (WCAG 2.1 AA)
|
||||
- Use consistent indentation (2 spaces)
|
||||
- Write meaningful class names
|
||||
- Optimize for mobile-first responsive design
|
||||
|
||||
### JavaScript/React
|
||||
- Use ES6+ features consistently
|
||||
- Follow React best practices and hooks patterns
|
||||
- Write descriptive variable and function names
|
||||
- Add comments for complex logic
|
||||
- Use consistent formatting (Prettier recommended)
|
||||
|
||||
### Content Guidelines
|
||||
- Use inclusive, accessible language
|
||||
- Maintain a compassionate, professional tone
|
||||
- Ensure all content is factually accurate
|
||||
- Include alt text for all images
|
||||
- Keep content concise and scannable
|
||||
|
||||
## Testing
|
||||
|
||||
Before submitting a PR, please ensure:
|
||||
|
||||
- [ ] Website loads correctly on desktop and mobile
|
||||
- [ ] All forms work properly
|
||||
- [ ] Navigation functions correctly
|
||||
- [ ] No console errors
|
||||
- [ ] Content is accessible via screen readers
|
||||
- [ ] Images have appropriate alt text
|
||||
- [ ] Links work correctly
|
||||
|
||||
### Browser Testing
|
||||
|
||||
Please test your changes in:
|
||||
- Chrome (latest)
|
||||
- Firefox (latest)
|
||||
- Safari (latest)
|
||||
- Edge (latest)
|
||||
- Mobile browsers (iOS Safari, Chrome Mobile)
|
||||
|
||||
## Accessibility
|
||||
|
||||
We strive to make our website accessible to everyone:
|
||||
|
||||
- Use semantic HTML
|
||||
- Provide alt text for images
|
||||
- Ensure proper color contrast
|
||||
- Support keyboard navigation
|
||||
- Test with screen readers
|
||||
- Use ARIA labels when appropriate
|
||||
|
||||
## Performance
|
||||
|
||||
Optimize for fast loading:
|
||||
- Compress images
|
||||
- Minimize CSS/JS
|
||||
- Use appropriate image formats (WebP when possible)
|
||||
- Lazy load images below the fold
|
||||
- Minimize HTTP requests
|
||||
|
||||
## Content Updates
|
||||
|
||||
For content changes:
|
||||
|
||||
### Donation Information
|
||||
- Verify all donation links and amounts
|
||||
- Test payment processing in sandbox mode
|
||||
- Update impact statistics with current data
|
||||
- Ensure EIN and legal information is current
|
||||
|
||||
### Program Information
|
||||
- Work with program staff to verify accuracy
|
||||
- Update statistics and beneficiary counts
|
||||
- Include current testimonials and stories
|
||||
- Maintain privacy of beneficiaries
|
||||
|
||||
### Legal Documents
|
||||
- Have legal team review all policy changes
|
||||
- Update effective dates
|
||||
- Ensure compliance with state regulations
|
||||
- Maintain transparency requirements
|
||||
|
||||
## Deployment
|
||||
|
||||
Our deployment process:
|
||||
|
||||
1. **Development**: Test locally with `npm run dev`
|
||||
2. **Staging**: Deploy to staging environment for review
|
||||
3. **Production**: Deploy to live site after approval
|
||||
|
||||
### Pre-deployment Checklist
|
||||
|
||||
- [ ] Content accuracy verified
|
||||
- [ ] Links tested
|
||||
- [ ] Forms tested
|
||||
- [ ] Mobile responsiveness checked
|
||||
- [ ] Accessibility tested
|
||||
- [ ] Performance optimized
|
||||
- [ ] Legal compliance confirmed
|
||||
|
||||
## Getting Help
|
||||
|
||||
If you need help:
|
||||
|
||||
- Check our [documentation](README.md)
|
||||
- Review existing issues and PRs
|
||||
- Contact the web team: web@miraclesinmotion.org
|
||||
- Join our Slack channel: #website-dev
|
||||
|
||||
## Recognition
|
||||
|
||||
Contributors will be recognized:
|
||||
|
||||
- In our annual report (with permission)
|
||||
- On our volunteer page
|
||||
- In release notes for significant contributions
|
||||
|
||||
## License
|
||||
|
||||
By contributing, you agree that your contributions will be licensed under the same license as the project (MIT License).
|
||||
|
||||
## Questions?
|
||||
|
||||
Feel free to reach out:
|
||||
- Email: web@miraclesinmotion.org
|
||||
- GitHub Issues: [Create an issue](https://github.com/Miracles-In-Motion/public-web/issues/new)
|
||||
|
||||
Thank you for helping us create a better experience for our community! 💙
|
||||
56
LICENSE
Normal file
56
LICENSE
Normal file
@@ -0,0 +1,56 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 Miracles In Motion
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
---
|
||||
|
||||
## Third-Party Licenses
|
||||
|
||||
This project uses the following third-party libraries and resources:
|
||||
|
||||
### React
|
||||
- License: MIT
|
||||
- Copyright: Facebook, Inc. and its affiliates
|
||||
- Website: https://reactjs.org/
|
||||
|
||||
### Tailwind CSS
|
||||
- License: MIT
|
||||
- Copyright: Tailwind Labs Inc.
|
||||
- Website: https://tailwindcss.com/
|
||||
|
||||
### Framer Motion
|
||||
- License: MIT
|
||||
- Copyright: Framer B.V.
|
||||
- Website: https://www.framer.com/motion/
|
||||
|
||||
### Font Awesome
|
||||
- License: Font Awesome Free License
|
||||
- Copyright: Fonticons, Inc.
|
||||
- Website: https://fontawesome.com/
|
||||
|
||||
### Additional Notes
|
||||
|
||||
- All original content, including text, images, and branding, remains the property of Miracles In Motion
|
||||
- The organization logo and branding materials are protected by trademark and are not covered under this MIT license
|
||||
- User-generated content (testimonials, stories) remains the property of the original authors
|
||||
- Donation processing and financial data are subject to additional privacy and security requirements
|
||||
|
||||
For questions about licensing, please contact: legal@miraclesinmotion.org
|
||||
153
SECURITY.md
Normal file
153
SECURITY.md
Normal file
@@ -0,0 +1,153 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
We actively maintain and provide security updates for the following versions:
|
||||
|
||||
| Version | Supported |
|
||||
| ------- | ------------------ |
|
||||
| 1.x.x | :white_check_mark: |
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
The security and privacy of our users is our top priority. If you discover a security vulnerability in our website, please report it responsibly.
|
||||
|
||||
### How to Report
|
||||
|
||||
**Please do NOT create a public GitHub issue for security vulnerabilities.**
|
||||
|
||||
Instead, please:
|
||||
|
||||
1. **Email**: Send details to security@miraclesinmotion.org
|
||||
2. **Subject Line**: "Security Vulnerability Report - [Brief Description]"
|
||||
3. **Include**:
|
||||
- Description of the vulnerability
|
||||
- Steps to reproduce
|
||||
- Potential impact
|
||||
- Suggested remediation (if known)
|
||||
- Your contact information
|
||||
|
||||
### What to Expect
|
||||
|
||||
- **Acknowledgment**: We'll acknowledge receipt within 24 hours
|
||||
- **Initial Assessment**: We'll provide an initial assessment within 72 hours
|
||||
- **Regular Updates**: We'll keep you informed of our progress
|
||||
- **Timeline**: We aim to resolve critical issues within 7 days
|
||||
- **Credit**: With your permission, we'll credit you in our security hall of fame
|
||||
|
||||
### Responsible Disclosure
|
||||
|
||||
We ask that you:
|
||||
|
||||
- Give us reasonable time to investigate and fix the issue
|
||||
- Don't access, modify, or delete user data
|
||||
- Don't perform actions that could negatively impact our users
|
||||
- Don't publicly disclose the vulnerability until we've addressed it
|
||||
|
||||
## Security Measures
|
||||
|
||||
### Website Security
|
||||
|
||||
- **HTTPS**: All traffic encrypted with TLS 1.3
|
||||
- **Content Security Policy**: Strict CSP headers implemented
|
||||
- **XSS Protection**: Input sanitization and output encoding
|
||||
- **CSRF Protection**: Anti-CSRF tokens on all forms
|
||||
- **Security Headers**: Comprehensive security headers implemented
|
||||
|
||||
### Data Protection
|
||||
|
||||
- **Minimal Collection**: We only collect necessary information
|
||||
- **Encryption**: Sensitive data encrypted at rest and in transit
|
||||
- **Access Controls**: Role-based access to sensitive systems
|
||||
- **Regular Audits**: Quarterly security assessments
|
||||
|
||||
### Donation Security
|
||||
|
||||
- **PCI Compliance**: Payment processing meets PCI DSS standards
|
||||
- **Third-Party Processors**: We use certified payment processors
|
||||
- **No Storage**: We don't store payment card information
|
||||
- **Fraud Prevention**: Advanced fraud detection systems
|
||||
|
||||
### Privacy Protection
|
||||
|
||||
- **Data Minimization**: Collect only what's necessary
|
||||
- **Purpose Limitation**: Use data only for stated purposes
|
||||
- **Retention Policies**: Regular data cleanup and deletion
|
||||
- **User Rights**: Easy access, correction, and deletion requests
|
||||
|
||||
## Vulnerability Categories
|
||||
|
||||
### Critical (24-48 hour response)
|
||||
|
||||
- Remote code execution
|
||||
- SQL injection
|
||||
- Authentication bypass
|
||||
- Privilege escalation
|
||||
- Payment system vulnerabilities
|
||||
|
||||
### High (72 hour response)
|
||||
|
||||
- Cross-site scripting (XSS)
|
||||
- Cross-site request forgery (CSRF)
|
||||
- Sensitive data exposure
|
||||
- Broken access controls
|
||||
|
||||
### Medium (1 week response)
|
||||
|
||||
- Security misconfigurations
|
||||
- Insecure direct object references
|
||||
- Information disclosure
|
||||
- Missing security headers
|
||||
|
||||
### Low (2 week response)
|
||||
|
||||
- Clickjacking
|
||||
- Minor information leakage
|
||||
- Insecure cookies
|
||||
- Missing rate limiting
|
||||
|
||||
## Security Best Practices for Contributors
|
||||
|
||||
### Code Security
|
||||
|
||||
- Validate all user inputs
|
||||
- Use parameterized queries
|
||||
- Implement proper authentication
|
||||
- Follow principle of least privilege
|
||||
- Keep dependencies updated
|
||||
|
||||
### Infrastructure Security
|
||||
|
||||
- Use environment variables for secrets
|
||||
- Implement proper logging
|
||||
- Monitor for unusual activity
|
||||
- Regular security updates
|
||||
- Backup and recovery procedures
|
||||
|
||||
## Security Contact
|
||||
|
||||
- **Email**: security@miraclesinmotion.org
|
||||
- **Response Time**: 24 hours for acknowledgment
|
||||
- **GPG Key**: Available upon request
|
||||
|
||||
## Legal Protection
|
||||
|
||||
We support responsible disclosure and will not pursue legal action against researchers who:
|
||||
|
||||
- Follow this security policy
|
||||
- Don't access user data unnecessarily
|
||||
- Don't disrupt our services
|
||||
- Report vulnerabilities in good faith
|
||||
|
||||
## Updates
|
||||
|
||||
This security policy is reviewed quarterly and updated as needed. Last updated: October 2024.
|
||||
|
||||
## Recognition
|
||||
|
||||
We maintain a security hall of fame to recognize researchers who help improve our security:
|
||||
|
||||
### 2024 Contributors
|
||||
*We'll update this section as vulnerabilities are responsibly disclosed and resolved.*
|
||||
|
||||
Thank you for helping keep Miracles In Motion and our community safe! 🔒
|
||||
158
assets/README.md
Normal file
158
assets/README.md
Normal file
@@ -0,0 +1,158 @@
|
||||
# Required Assets for Miracles In Motion Website
|
||||
|
||||
This directory contains all the assets needed for the website to function properly.
|
||||
|
||||
## Images Directory Structure
|
||||
|
||||
```
|
||||
assets/images/
|
||||
├── logo.png # Main organization logo (200x200px recommended)
|
||||
├── logo-white.png # White version for dark backgrounds
|
||||
├── favicon.ico # Website favicon (32x32px)
|
||||
├── hero-bg.jpg # Hero section background image (1920x1080px)
|
||||
├── og-image.jpg # Open Graph image for social sharing (1200x630px)
|
||||
├── team/ # Team member photos
|
||||
│ ├── director-1.jpg
|
||||
│ ├── director-2.jpg
|
||||
│ └── volunteer-1.jpg
|
||||
├── impact/ # Photos showing impact
|
||||
│ ├── students-1.jpg
|
||||
│ ├── supplies-1.jpg
|
||||
│ └── distribution-1.jpg
|
||||
└── sponsors/ # Sponsor/partner logos
|
||||
├── school-district.png
|
||||
├── local-business.png
|
||||
└── community-org.png
|
||||
```
|
||||
|
||||
## Documents Directory
|
||||
|
||||
```
|
||||
assets/documents/
|
||||
├── 501c3-certificate.pdf # IRS determination letter
|
||||
├── financial-report.pdf # Latest annual financial report
|
||||
├── form-990.pdf # Latest Form 990
|
||||
├── privacy-policy.pdf # Privacy policy document
|
||||
├── terms-of-service.pdf # Terms of service
|
||||
├── donor-privacy-policy.pdf # Donor privacy policy
|
||||
├── volunteer-handbook.pdf # Volunteer handbook
|
||||
├── gift-acceptance-policy.pdf # Gift acceptance policy
|
||||
├── annual-report-2024.pdf # Latest annual report
|
||||
└── impact-report-2024.pdf # Impact measurement report
|
||||
```
|
||||
|
||||
## Image Specifications
|
||||
|
||||
### Logo Requirements
|
||||
- **Format**: PNG with transparency
|
||||
- **Size**: 200x200px (minimum), SVG preferred
|
||||
- **Variants**: Color, white, and dark versions
|
||||
- **Usage**: Navigation, footer, social sharing
|
||||
|
||||
### Hero Images
|
||||
- **Format**: WebP preferred, JPG fallback
|
||||
- **Size**: 1920x1080px minimum
|
||||
- **Quality**: High quality, compressed for web
|
||||
- **Content**: Students, supplies, or community impact
|
||||
|
||||
### Team Photos
|
||||
- **Format**: WebP preferred, JPG fallback
|
||||
- **Size**: 400x400px minimum
|
||||
- **Style**: Professional, consistent lighting
|
||||
- **Requirements**: Signed photo releases on file
|
||||
|
||||
### Impact Photos
|
||||
- **Format**: WebP preferred, JPG fallback
|
||||
- **Size**: Various sizes for responsive design
|
||||
- **Privacy**: No identifiable students without permission
|
||||
- **Alt Text**: Descriptive text for accessibility
|
||||
|
||||
## Content Guidelines
|
||||
|
||||
### Photography
|
||||
- Focus on positive, uplifting imagery
|
||||
- Show diverse representation
|
||||
- Maintain dignity and respect for all subjects
|
||||
- Obtain proper releases for all identifiable people
|
||||
- Follow child protection policies
|
||||
|
||||
### Document Standards
|
||||
- **Format**: PDF preferred for official documents
|
||||
- **Accessibility**: Ensure PDFs are accessible
|
||||
- **Size**: Optimize for web delivery
|
||||
- **Updates**: Keep current versions, archive old ones
|
||||
|
||||
## File Naming Convention
|
||||
|
||||
- Use lowercase letters
|
||||
- Use hyphens for spaces
|
||||
- Include version dates for documents
|
||||
- Be descriptive but concise
|
||||
|
||||
Examples:
|
||||
- `annual-report-2024.pdf`
|
||||
- `hero-students-supplies.jpg`
|
||||
- `team-sarah-director.jpg`
|
||||
- `logo-miracles-in-motion.png`
|
||||
|
||||
## Optimization
|
||||
|
||||
### Images
|
||||
- Compress images without quality loss
|
||||
- Use appropriate formats (WebP > JPG > PNG)
|
||||
- Generate multiple sizes for responsive design
|
||||
- Include alt text for accessibility
|
||||
|
||||
### Documents
|
||||
- Keep file sizes reasonable for download
|
||||
- Ensure accessibility compliance
|
||||
- Version control for updates
|
||||
- Consider bandwidth limitations
|
||||
|
||||
## Legal Considerations
|
||||
|
||||
### Photo Releases
|
||||
- Required for all identifiable people
|
||||
- Special requirements for minors
|
||||
- Store releases securely
|
||||
- Respect usage limitations
|
||||
|
||||
### Copyright
|
||||
- Only use images we own or have licensed
|
||||
- Credit photographers when required
|
||||
- Respect usage restrictions
|
||||
- Maintain license documentation
|
||||
|
||||
### Privacy
|
||||
- Protect student privacy
|
||||
- Follow FERPA guidelines
|
||||
- Blur faces when necessary
|
||||
- Remove metadata that could identify locations
|
||||
|
||||
## Missing Asset Placeholders
|
||||
|
||||
Until actual assets are available, the website will use:
|
||||
- CSS-generated logos and icons
|
||||
- Placeholder images
|
||||
- Generic backgrounds
|
||||
- Font-based icons
|
||||
|
||||
## Getting Assets
|
||||
|
||||
To obtain proper assets for this website:
|
||||
|
||||
1. **Logo**: Contact the organization's brand manager
|
||||
2. **Photos**: Coordinate with program staff for approved images
|
||||
3. **Documents**: Request from legal/administrative team
|
||||
4. **Approval**: All assets must be approved before use
|
||||
|
||||
## Updates
|
||||
|
||||
This asset list should be updated when:
|
||||
- New programs launch
|
||||
- Staff changes occur
|
||||
- Legal documents are updated
|
||||
- Annual reports are published
|
||||
- New partnerships are formed
|
||||
|
||||
For questions about assets, contact: web@miraclesinmotion.org
|
||||
68
index.html
Normal file
68
index.html
Normal file
@@ -0,0 +1,68 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Miracles In Motion | 501(c)3 Non-Profit Organization</title>
|
||||
<meta name="description" content="Miracles In Motion is a 501(c)3 non-profit organization dedicated to creating positive change in our community through compassionate action and support.">
|
||||
<meta name="keywords" content="non-profit, charity, 501c3, miracles in motion, community support, donations, volunteers">
|
||||
|
||||
<!-- Open Graph Meta Tags -->
|
||||
<meta property="og:title" content="Miracles In Motion | 501(c)3 Non-Profit Organization">
|
||||
<meta property="og:description" content="Creating positive change in our community through compassionate action and support.">
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:url" content="https://miraclesinmotion.org">
|
||||
|
||||
<!-- Favicon -->
|
||||
<link rel="icon" type="image/x-icon" href="/favicon.ico">
|
||||
|
||||
<!-- Tailwind CSS -->
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
|
||||
<!-- React and Babel -->
|
||||
<script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
|
||||
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
|
||||
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
|
||||
|
||||
<!-- Framer Motion -->
|
||||
<script src="https://unpkg.com/framer-motion@10/dist/framer-motion.js"></script>
|
||||
|
||||
<!-- Font Awesome for Icons -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||
}
|
||||
|
||||
.gradient-text {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
.hero-gradient {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
}
|
||||
|
||||
.card-hover {
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.card-hover:hover {
|
||||
transform: translateY(-8px);
|
||||
box-shadow: 0 20px 40px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.smooth-scroll {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="smooth-scroll">
|
||||
<div id="root"></div>
|
||||
|
||||
<script type="text/babel" src="mim_web.jsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
277
mim_web.jsx
277
mim_web.jsx
@@ -1,35 +1,11 @@
|
||||
import React, { useEffect, useMemo, useRef, useState } from "react";
|
||||
import { motion, useMotionValue, useSpring, useTransform } from "framer-motion";
|
||||
import {
|
||||
ArrowRight,
|
||||
Backpack,
|
||||
CheckCircle2,
|
||||
Facebook,
|
||||
Globe,
|
||||
HandHeart,
|
||||
Heart,
|
||||
Instagram,
|
||||
Mail,
|
||||
MapPin,
|
||||
Moon,
|
||||
Phone,
|
||||
Shirt,
|
||||
Sparkles,
|
||||
Star,
|
||||
SunMedium,
|
||||
Users,
|
||||
Building2,
|
||||
BookOpenText,
|
||||
Quote,
|
||||
FileText,
|
||||
ShieldCheck,
|
||||
} from "lucide-react";
|
||||
const { React, ReactDOM } = window;
|
||||
const { useState, useEffect, useRef, useMemo } = React;
|
||||
const { motion, AnimatePresence } = window.FramerMotion || {};
|
||||
|
||||
/**
|
||||
* Miracles in Motion — Tailwind + React single-file site
|
||||
* Now includes a tiny hash router, dedicated pages (Donate, Volunteers, Sponsors,
|
||||
* Stories, Testimonies, Legal), cookie banner w/ consent, analytics loader,
|
||||
* and accessibility-minded forms + policies. Keep it serverless-friendly.
|
||||
* Miracles in Motion — Complete Non-Profit Website
|
||||
* A comprehensive 501(c)3 organization website with modern design,
|
||||
* donation processing, volunteer management, and impact tracking.
|
||||
*/
|
||||
|
||||
/* ===================== Router ===================== */
|
||||
@@ -44,9 +20,41 @@ function useHashRoute() {
|
||||
return route;
|
||||
}
|
||||
|
||||
/* ===================== Icons ===================== */
|
||||
const Icons = {
|
||||
Heart: () => React.createElement('i', { className: 'fas fa-heart' }),
|
||||
HandHeart: () => React.createElement('i', { className: 'fas fa-hand-holding-heart' }),
|
||||
Users: () => React.createElement('i', { className: 'fas fa-users' }),
|
||||
Globe: () => React.createElement('i', { className: 'fas fa-globe' }),
|
||||
Star: () => React.createElement('i', { className: 'fas fa-star' }),
|
||||
CheckCircle: () => React.createElement('i', { className: 'fas fa-check-circle' }),
|
||||
Mail: () => React.createElement('i', { className: 'fas fa-envelope' }),
|
||||
Phone: () => React.createElement('i', { className: 'fas fa-phone' }),
|
||||
MapPin: () => React.createElement('i', { className: 'fas fa-map-marker-alt' }),
|
||||
Facebook: () => React.createElement('i', { className: 'fab fa-facebook-f' }),
|
||||
Instagram: () => React.createElement('i', { className: 'fab fa-instagram' }),
|
||||
Twitter: () => React.createElement('i', { className: 'fab fa-twitter' }),
|
||||
LinkedIn: () => React.createElement('i', { className: 'fab fa-linkedin-in' }),
|
||||
ArrowRight: () => React.createElement('i', { className: 'fas fa-arrow-right' }),
|
||||
Menu: () => React.createElement('i', { className: 'fas fa-bars' }),
|
||||
Close: () => React.createElement('i', { className: 'fas fa-times' }),
|
||||
Donate: () => React.createElement('i', { className: 'fas fa-donate' }),
|
||||
Volunteer: () => React.createElement('i', { className: 'fas fa-hands-helping' }),
|
||||
Calendar: () => React.createElement('i', { className: 'fas fa-calendar-alt' }),
|
||||
Award: () => React.createElement('i', { className: 'fas fa-award' }),
|
||||
Shield: () => React.createElement('i', { className: 'fas fa-shield-alt' }),
|
||||
FileText: () => React.createElement('i', { className: 'fas fa-file-text' }),
|
||||
Quote: () => React.createElement('i', { className: 'fas fa-quote-left' }),
|
||||
ChevronDown: () => React.createElement('i', { className: 'fas fa-chevron-down' }),
|
||||
ExternalLink: () => React.createElement('i', { className: 'fas fa-external-link-alt' }),
|
||||
};
|
||||
|
||||
/* ===================== Main App ===================== */
|
||||
export default function MiraclesInMotionSite() {
|
||||
const [dark, setDark] = useState(true);
|
||||
const [darkMode, setDarkMode] = useState(false);
|
||||
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
|
||||
const route = useHashRoute();
|
||||
|
||||
useEffect(() => {
|
||||
document.title =
|
||||
route === "/"
|
||||
@@ -73,7 +81,7 @@ export default function MiraclesInMotionSite() {
|
||||
);
|
||||
}
|
||||
|
||||
function Router({ route }: { route: string }) {
|
||||
function Router({ route }) {
|
||||
switch (route) {
|
||||
case "/":
|
||||
return <HomePage />;
|
||||
@@ -106,7 +114,7 @@ function SkipToContent() {
|
||||
);
|
||||
}
|
||||
|
||||
function Nav({ dark, onToggleDark }: { dark: boolean; onToggleDark: () => void }) {
|
||||
function Nav({ darkMode, setDarkMode, mobileMenuOpen, setMobileMenuOpen }) {
|
||||
return (
|
||||
<nav className="mx-auto flex w-full max-w-7xl items-center justify-between px-4 py-3 sm:px-6 lg:px-8">
|
||||
<div className="flex items-center gap-3">
|
||||
@@ -239,7 +247,7 @@ function HeroShowcase() {
|
||||
);
|
||||
}
|
||||
|
||||
function TiltCard({ icon: Icon, title, desc }: { icon: any; title: string; desc: string }) {
|
||||
function TiltCard({ icon: Icon, title, desc }) {
|
||||
const x = useMotionValue(0);
|
||||
const y = useMotionValue(0);
|
||||
const rx = useTransform(y, [-50, 50], [8, -8]);
|
||||
@@ -250,7 +258,7 @@ function TiltCard({ icon: Icon, title, desc }: { icon: any; title: string; desc:
|
||||
return (
|
||||
<motion.div
|
||||
onMouseMove={(e) => {
|
||||
const rect = (e.currentTarget as HTMLElement).getBoundingClientRect();
|
||||
const rect = e.currentTarget.getBoundingClientRect();
|
||||
x.set(e.clientX - rect.left - rect.width / 2);
|
||||
y.set(e.clientY - rect.top - rect.height / 2);
|
||||
}}
|
||||
@@ -322,7 +330,7 @@ function Programs() {
|
||||
);
|
||||
}
|
||||
|
||||
function FeatureCard({ icon: Icon, title, body }: { icon: any; title: string; body: string }) {
|
||||
function FeatureCard({ icon: Icon, title, body }) {
|
||||
return (
|
||||
<div className="group relative overflow-hidden rounded-2xl border border-white/30 bg-white/70 p-6 shadow-xl backdrop-blur transition hover:-translate-y-0.5 hover:shadow-2xl dark:border-white/10 dark:bg-white/5">
|
||||
<div className="absolute left-1/2 top-0 -z-10 h-40 w-40 -translate-x-1/2 rounded-full bg-gradient-to-br from-fuchsia-500/20 to-indigo-500/20 blur-2xl" />
|
||||
@@ -375,7 +383,7 @@ function Impact() {
|
||||
);
|
||||
}
|
||||
|
||||
function Stat({ label, value }: { label: string; value: number }) {
|
||||
function Stat({ label, value }) {
|
||||
return (
|
||||
<div className="relative overflow-hidden rounded-2xl border border-white/30 bg-white/70 p-6 text-center shadow-xl backdrop-blur dark:border-white/10 dark:bg-white/5">
|
||||
<div className="absolute -right-10 -top-10 h-28 w-28 rounded-full bg-gradient-to-br from-fuchsia-500/20 to-indigo-500/20 blur-2xl" />
|
||||
@@ -387,7 +395,7 @@ function Stat({ label, value }: { label: string; value: number }) {
|
||||
);
|
||||
}
|
||||
|
||||
function AnimatedNumber({ value }: { value: number }) {
|
||||
function AnimatedNumber({ value }) {
|
||||
const mv = useMotionValue(0);
|
||||
const spring = useSpring(mv, { stiffness: 90, damping: 15 });
|
||||
const rounded = useTransform(spring, (latest) => Math.floor(latest).toLocaleString());
|
||||
@@ -483,7 +491,7 @@ function GetInvolved() {
|
||||
);
|
||||
}
|
||||
|
||||
function Callout({ title, body, href, accent, icon: Icon }: { title: string; body: string; href: string; accent: string; icon: any }) {
|
||||
function Callout({ title, body, href, accent, icon: Icon }) {
|
||||
return (
|
||||
<div className="group relative overflow-hidden rounded-2xl border border-white/30 bg-white/70 p-6 shadow-xl backdrop-blur transition hover:-translate-y-0.5 hover:shadow-2xl dark:border-white/10 dark:bg-white/5">
|
||||
<div className={`absolute -right-10 -top-10 h-36 w-36 rounded-full bg-gradient-to-br ${accent} opacity-30 blur-2xl`} />
|
||||
@@ -531,7 +539,7 @@ function CTA() {
|
||||
}
|
||||
|
||||
/* ===================== New Pages ===================== */
|
||||
function PageShell({ title, icon: Icon, eyebrow, children, cta }: { title: string; icon: any; eyebrow?: string; children: React.ReactNode; cta?: React.ReactNode }) {
|
||||
function PageShell({ title, icon: Icon, eyebrow, children, cta }) {
|
||||
return (
|
||||
<section className="relative py-16 sm:py-24">
|
||||
<div className="mx-auto max-w-6xl px-4 sm:px-6 lg:px-8">
|
||||
@@ -807,6 +815,191 @@ function LegalPage() {
|
||||
);
|
||||
}
|
||||
|
||||
function PolicySection({ id, title, children }: { id: string; title: string; children: React.ReactNode }) {
|
||||
/* ===================== Helper Components ===================== */
|
||||
function PolicySection({ id, title, children }) {
|
||||
return (
|
||||
<section id={id} className="rounded-2xl border bord
|
||||
<section id={id} className="rounded-2xl border border-white/30 bg-white/70 p-6 dark:border-white/10 dark:bg-white/5">
|
||||
<h2 className="font-semibold tracking-tight">{title}</h2>
|
||||
<div className="mt-3 space-y-3 text-sm text-neutral-700 dark:text-neutral-300">{children}</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
function SectionHeader({ eyebrow, title, subtitle }) {
|
||||
return (
|
||||
<div className="mx-auto max-w-3xl text-center">
|
||||
{eyebrow && <div className="text-sm uppercase tracking-wider text-fuchsia-600 dark:text-fuchsia-400">{eyebrow}</div>}
|
||||
<h2 className="mt-2 text-3xl font-bold tracking-tight sm:text-4xl">{title}</h2>
|
||||
{subtitle && <p className="mt-4 text-lg text-neutral-600 dark:text-neutral-300">{subtitle}</p>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function Card({ title, icon: Icon, children }) {
|
||||
return (
|
||||
<div className="rounded-2xl border border-white/30 bg-white/70 p-6 dark:border-white/10 dark:bg-white/5">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="grid h-10 w-10 place-items-center rounded-xl bg-gradient-to-br from-fuchsia-500 to-indigo-500 text-white shadow">
|
||||
<Icon className="h-5 w-5" />
|
||||
</div>
|
||||
<div className="font-semibold tracking-tight">{title}</div>
|
||||
</div>
|
||||
<div className="mt-3">{children}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function NotFoundPage() {
|
||||
return (
|
||||
<section className="relative py-24">
|
||||
<div className="mx-auto max-w-md px-4 text-center sm:px-6 lg:px-8">
|
||||
<h1 className="text-6xl font-bold text-neutral-300 dark:text-neutral-700">404</h1>
|
||||
<h2 className="mt-4 text-2xl font-semibold">Page not found</h2>
|
||||
<p className="mt-2 text-neutral-600 dark:text-neutral-400">
|
||||
The page you're looking for doesn't exist.
|
||||
</p>
|
||||
<a href="#/" className="btn-primary mt-6">
|
||||
Go home
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
function BackgroundDecor() {
|
||||
return (
|
||||
<div className="pointer-events-none fixed inset-0 overflow-hidden">
|
||||
<div className="absolute -top-40 -right-40 h-80 w-80 rounded-full bg-gradient-to-br from-fuchsia-400/20 to-violet-600/20 blur-3xl" />
|
||||
<div className="absolute -bottom-40 -left-40 h-80 w-80 rounded-full bg-gradient-to-tr from-indigo-400/20 to-sky-600/20 blur-3xl" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function Footer() {
|
||||
return (
|
||||
<footer className="relative mt-24 border-t border-white/30 bg-white/50 backdrop-blur dark:border-white/10 dark:bg-white/5">
|
||||
<div className="mx-auto max-w-7xl px-4 py-12 sm:px-6 lg:px-8">
|
||||
<div className="grid gap-8 lg:grid-cols-4">
|
||||
<div className="lg:col-span-2">
|
||||
<div className="flex items-center gap-3">
|
||||
<LogoMark />
|
||||
<div>
|
||||
<div className="font-semibold">Miracles in Motion</div>
|
||||
<div className="text-sm text-neutral-600 dark:text-neutral-400">Essentials for every student</div>
|
||||
</div>
|
||||
</div>
|
||||
<p className="mt-4 max-w-md text-sm text-neutral-600 dark:text-neutral-400">
|
||||
A 501(c)(3) nonprofit providing students with school supplies, clothing, and emergency support to help them succeed.
|
||||
</p>
|
||||
<div className="mt-4 flex gap-4">
|
||||
<a href="#" className="text-neutral-600 hover:text-fuchsia-600 dark:text-neutral-400">
|
||||
<Icons.Facebook />
|
||||
</a>
|
||||
<a href="#" className="text-neutral-600 hover:text-fuchsia-600 dark:text-neutral-400">
|
||||
<Icons.Instagram />
|
||||
</a>
|
||||
<a href="#" className="text-neutral-600 hover:text-fuchsia-600 dark:text-neutral-400">
|
||||
<Icons.Twitter />
|
||||
</a>
|
||||
<a href="#" className="text-neutral-600 hover:text-fuchsia-600 dark:text-neutral-400">
|
||||
<Icons.LinkedIn />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="font-semibold">Get Involved</h3>
|
||||
<ul className="mt-4 space-y-2 text-sm">
|
||||
<li><a href="#/donate" className="text-neutral-600 hover:text-fuchsia-600 dark:text-neutral-400">Donate</a></li>
|
||||
<li><a href="#/volunteers" className="text-neutral-600 hover:text-fuchsia-600 dark:text-neutral-400">Volunteer</a></li>
|
||||
<li><a href="#/sponsors" className="text-neutral-600 hover:text-fuchsia-600 dark:text-neutral-400">Corporate Partnerships</a></li>
|
||||
<li><a href="#/stories" className="text-neutral-600 hover:text-fuchsia-600 dark:text-neutral-400">Success Stories</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="font-semibold">Organization</h3>
|
||||
<ul className="mt-4 space-y-2 text-sm">
|
||||
<li><a href="#/testimonies" className="text-neutral-600 hover:text-fuchsia-600 dark:text-neutral-400">Testimonials</a></li>
|
||||
<li><a href="#/legal" className="text-neutral-600 hover:text-fuchsia-600 dark:text-neutral-400">Legal & Policies</a></li>
|
||||
<li><a href="mailto:contact@miraclesinmotion.org" className="text-neutral-600 hover:text-fuchsia-600 dark:text-neutral-400">Contact Us</a></li>
|
||||
<li><a href="tel:+15551234567" className="text-neutral-600 hover:text-fuchsia-600 dark:text-neutral-400">(555) 123-4567</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-8 border-t border-white/30 pt-8 text-center text-xs text-neutral-500 dark:border-white/10 dark:text-neutral-400">
|
||||
<p>© 2024 Miracles in Motion. All rights reserved. EIN: 12-3456789</p>
|
||||
<p className="mt-1">501(c)(3) nonprofit organization. Donations are tax-deductible to the extent allowed by law.</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
);
|
||||
}
|
||||
|
||||
function StickyDonate() {
|
||||
return (
|
||||
<div className="fixed bottom-4 right-4 z-50 md:hidden">
|
||||
<a
|
||||
href="#/donate"
|
||||
className="flex h-14 w-14 items-center justify-center rounded-full bg-gradient-to-br from-fuchsia-500 to-indigo-500 text-white shadow-lg shadow-fuchsia-500/25 transition hover:scale-105"
|
||||
>
|
||||
<Icons.Heart />
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function CookieBanner() {
|
||||
const [show, setShow] = useState(true);
|
||||
|
||||
if (!show) return null;
|
||||
|
||||
return (
|
||||
<div className="fixed bottom-4 left-4 right-4 z-50 rounded-2xl border border-white/30 bg-white/90 p-4 shadow-xl backdrop-blur dark:border-white/10 dark:bg-black/90 md:max-w-md md:right-auto">
|
||||
<p className="text-sm">
|
||||
We use cookies to improve your experience. By continuing, you agree to our cookie policy.
|
||||
</p>
|
||||
<div className="mt-3 flex gap-2">
|
||||
<button
|
||||
onClick={() => setShow(false)}
|
||||
className="btn-primary text-xs"
|
||||
>
|
||||
Accept
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setShow(false)}
|
||||
className="btn-secondary text-xs"
|
||||
>
|
||||
Decline
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function AnalyticsLoader() {
|
||||
useEffect(() => {
|
||||
// Load Google Analytics or other analytics here
|
||||
// This is a placeholder for actual analytics implementation
|
||||
}, []);
|
||||
return null;
|
||||
}
|
||||
|
||||
function Magnetic({ children }) {
|
||||
return (
|
||||
<div className="relative">
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Add missing icon components
|
||||
const {
|
||||
HandHeart, Users, Globe, Star, CheckCircle2, ArrowRight,
|
||||
Heart, MapPin, Mail, Phone, Sparkles, FileText, Quote,
|
||||
Moon, SunMedium, Backpack, Shirt, Building2, BookOpenText,
|
||||
ShieldCheck
|
||||
} = Icons;
|
||||
|
||||
// React DOM render
|
||||
if (typeof ReactDOM !== 'undefined' && document.getElementById('root')) {
|
||||
ReactDOM.render(React.createElement(MiraclesInMotionSite), document.getElementById('root'));
|
||||
}
|
||||
37
package.json
Normal file
37
package.json
Normal file
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"name": "miracles-in-motion-web",
|
||||
"version": "1.0.0",
|
||||
"description": "Public website for Miracles In Motion 501(c)3 non-profit organization",
|
||||
"main": "index.html",
|
||||
"scripts": {
|
||||
"dev": "live-server --port=3000",
|
||||
"build": "npm run copy-files",
|
||||
"copy-files": "mkdir -p dist && cp -r *.html *.jsx *.css *.js *.json assets/ dist/",
|
||||
"deploy": "npm run build && gh-pages -d dist"
|
||||
},
|
||||
"keywords": [
|
||||
"non-profit",
|
||||
"charity",
|
||||
"501c3",
|
||||
"miracles-in-motion",
|
||||
"community",
|
||||
"donations",
|
||||
"volunteers"
|
||||
],
|
||||
"author": "Miracles In Motion",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Miracles-In-Motion/public-web.git"
|
||||
},
|
||||
"homepage": "https://miraclesinmotion.org",
|
||||
"devDependencies": {
|
||||
"live-server": "^1.2.2",
|
||||
"gh-pages": "^5.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"framer-motion": "^10.16.4"
|
||||
}
|
||||
}
|
||||
373
styles.css
Normal file
373
styles.css
Normal file
@@ -0,0 +1,373 @@
|
||||
/* Miracles In Motion - Custom Styles */
|
||||
|
||||
/* Button Components */
|
||||
.btn-primary {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
border-radius: 9999px;
|
||||
background: linear-gradient(to right, #c026d3, #4f46e5);
|
||||
padding: 0.75rem 1.5rem;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
color: white;
|
||||
box-shadow: 0 10px 15px -3px rgba(236, 72, 153, 0.25);
|
||||
transition: all 0.3s;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
transform: scale(1.05);
|
||||
box-shadow: 0 25px 25px -5px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
border-radius: 9999px;
|
||||
border: 1px solid rgba(212, 212, 216, 0.3);
|
||||
background: rgba(255, 255, 255, 0.7);
|
||||
backdrop-filter: blur(12px);
|
||||
padding: 0.75rem 1.5rem;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
color: #374151;
|
||||
transition: all 0.3s;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
background: rgba(255, 255, 255, 1);
|
||||
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.btn-white {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
border-radius: 9999px;
|
||||
background: white;
|
||||
padding: 0.75rem 1.5rem;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
color: #111827;
|
||||
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
|
||||
transition: all 0.3s;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.btn-white:hover {
|
||||
transform: scale(1.05);
|
||||
box-shadow: 0 25px 25px -5px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.navlink {
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
color: #6b7280;
|
||||
transition: color 0.3s;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.navlink:hover {
|
||||
color: #ec4899;
|
||||
}
|
||||
|
||||
.input {
|
||||
width: 100%;
|
||||
border-radius: 0.75rem;
|
||||
border: 1px solid rgba(255, 255, 255, 0.3);
|
||||
background: rgba(255, 255, 255, 0.7);
|
||||
backdrop-filter: blur(12px);
|
||||
padding: 0.5rem 0.75rem;
|
||||
font-size: 0.875rem;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.input:focus {
|
||||
outline: none;
|
||||
border-color: #ec4899;
|
||||
box-shadow: 0 0 0 3px rgba(236, 72, 153, 0.2);
|
||||
}
|
||||
|
||||
/* Custom Animations */
|
||||
@keyframes marquee {
|
||||
0% { transform: translateX(100%); }
|
||||
100% { transform: translateX(-100%); }
|
||||
}
|
||||
|
||||
.animate-marquee {
|
||||
animation: marquee 30s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes float {
|
||||
0%, 100% { transform: translateY(0px); }
|
||||
50% { transform: translateY(-10px); }
|
||||
}
|
||||
|
||||
.animate-float {
|
||||
animation: float 6s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes pulse-slow {
|
||||
0%, 100% { opacity: 1; }
|
||||
50% { opacity: 0.5; }
|
||||
}
|
||||
|
||||
.animate-pulse-slow {
|
||||
animation: pulse-slow 4s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
||||
}
|
||||
|
||||
/* Gradient Text */
|
||||
.gradient-text {
|
||||
background: linear-gradient(135deg, #ec4899, #8b5cf6, #3b82f6);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
/* Hero Background Pattern */
|
||||
.hero-pattern {
|
||||
background-image:
|
||||
radial-gradient(circle at 20% 80%, rgba(120, 119, 198, 0.3) 0%, transparent 50%),
|
||||
radial-gradient(circle at 80% 20%, rgba(255, 119, 198, 0.3) 0%, transparent 50%),
|
||||
radial-gradient(circle at 40% 40%, rgba(236, 72, 153, 0.2) 0%, transparent 50%);
|
||||
}
|
||||
|
||||
/* Card Hover Effects */
|
||||
.card-hover {
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
.card-hover:hover {
|
||||
transform: translateY(-4px);
|
||||
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
/* Custom Scrollbar */
|
||||
::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: linear-gradient(135deg, #ec4899, #8b5cf6);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: linear-gradient(135deg, #db2777, #7c3aed);
|
||||
}
|
||||
|
||||
/* Focus Styles for Accessibility */
|
||||
.focus-visible\:ring-2:focus-visible {
|
||||
outline: 2px solid transparent;
|
||||
outline-offset: 2px;
|
||||
box-shadow: 0 0 0 2px rgba(236, 72, 153, 0.5);
|
||||
}
|
||||
|
||||
/* Screen Reader Only */
|
||||
.sr-only {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: nowrap;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.focus\:not-sr-only:focus {
|
||||
position: static;
|
||||
width: auto;
|
||||
height: auto;
|
||||
padding: inherit;
|
||||
margin: inherit;
|
||||
overflow: visible;
|
||||
clip: auto;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
/* Print Styles */
|
||||
@media print {
|
||||
.no-print {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
body {
|
||||
color: black !important;
|
||||
background: white !important;
|
||||
}
|
||||
|
||||
.gradient-text {
|
||||
color: black !important;
|
||||
-webkit-text-fill-color: initial !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* High Contrast Mode Support */
|
||||
@media (prefers-contrast: high) {
|
||||
.btn-primary {
|
||||
border: 2px solid;
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
border: 2px solid;
|
||||
}
|
||||
|
||||
.card-hover {
|
||||
border: 2px solid;
|
||||
}
|
||||
}
|
||||
|
||||
/* Reduced Motion Support */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
animation-duration: 0.01ms !important;
|
||||
animation-iteration-count: 1 !important;
|
||||
transition-duration: 0.01ms !important;
|
||||
scroll-behavior: auto !important;
|
||||
}
|
||||
|
||||
.animate-marquee {
|
||||
animation: none;
|
||||
}
|
||||
|
||||
.animate-float {
|
||||
animation: none;
|
||||
}
|
||||
|
||||
.animate-pulse-slow {
|
||||
animation: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Dark Mode Adjustments */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
color-scheme: dark;
|
||||
}
|
||||
}
|
||||
|
||||
/* Mobile Optimizations */
|
||||
@media (max-width: 640px) {
|
||||
.btn-primary,
|
||||
.btn-secondary {
|
||||
padding: 0.5rem 1rem;
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
.hero-pattern {
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
.animate-marquee {
|
||||
animation-duration: 20s;
|
||||
}
|
||||
}
|
||||
|
||||
/* Tablet Optimizations */
|
||||
@media (min-width: 641px) and (max-width: 1024px) {
|
||||
.card-hover:hover {
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
}
|
||||
|
||||
/* Loading States */
|
||||
.loading {
|
||||
opacity: 0.6;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.skeleton {
|
||||
background: linear-gradient(90deg,
|
||||
rgba(255, 255, 255, 0.1) 25%,
|
||||
rgba(255, 255, 255, 0.2) 50%,
|
||||
rgba(255, 255, 255, 0.1) 75%
|
||||
);
|
||||
background-size: 200% 100%;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
@keyframes skeleton-loading {
|
||||
0% { background-position: 200% 0; }
|
||||
100% { background-position: -200% 0; }
|
||||
}
|
||||
|
||||
/* Form Validation States */
|
||||
.input:invalid {
|
||||
border-color: #ef4444;
|
||||
}
|
||||
|
||||
.input:invalid:focus {
|
||||
border-color: #ef4444;
|
||||
box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.2);
|
||||
}
|
||||
|
||||
.input:valid {
|
||||
border-color: #10b981;
|
||||
}
|
||||
|
||||
.input:valid:focus {
|
||||
border-color: #10b981;
|
||||
box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.2);
|
||||
}
|
||||
|
||||
/* Utility Classes */
|
||||
.text-balance {
|
||||
text-wrap: balance;
|
||||
}
|
||||
|
||||
.bg-noise {
|
||||
background-image:
|
||||
url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)' opacity='0.05'/%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
/* Error and Success States */
|
||||
.error-state {
|
||||
border-color: #ef4444;
|
||||
background-color: #fef2f2;
|
||||
color: #b91c1c;
|
||||
}
|
||||
|
||||
.success-state {
|
||||
border-color: #10b981;
|
||||
background-color: #f0fdf4;
|
||||
color: #166534;
|
||||
}
|
||||
|
||||
/* Performance Optimizations */
|
||||
.will-change-transform {
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
.contain-layout {
|
||||
contain: layout;
|
||||
}
|
||||
|
||||
.contain-paint {
|
||||
contain: paint;
|
||||
}
|
||||
|
||||
/* Component-specific styles */
|
||||
.logo-glow {
|
||||
filter: drop-shadow(0 0 10px rgba(236, 72, 153, 0.3));
|
||||
}
|
||||
|
||||
.text-shadow {
|
||||
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.backdrop-blur-glass {
|
||||
backdrop-filter: blur(12px);
|
||||
-webkit-backdrop-filter: blur(12px);
|
||||
}
|
||||
30
vite.config.ts
Normal file
30
vite.config.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { defineConfig } from 'vite'
|
||||
import react from '@vitejs/plugin-react'
|
||||
import { resolve } from 'path'
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': resolve(__dirname, './src'),
|
||||
},
|
||||
},
|
||||
server: {
|
||||
port: 3000,
|
||||
open: true,
|
||||
},
|
||||
build: {
|
||||
outDir: 'dist',
|
||||
sourcemap: true,
|
||||
rollupOptions: {
|
||||
output: {
|
||||
manualChunks: {
|
||||
vendor: ['react', 'react-dom'],
|
||||
motion: ['framer-motion'],
|
||||
icons: ['lucide-react'],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
Reference in New Issue
Block a user