Initial commit: project setup and all features implemented
This commit is contained in:
25
.github/copilot-instructions.md
vendored
Normal file
25
.github/copilot-instructions.md
vendored
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
# Premium React TypeScript Web App Setup
|
||||||
|
|
||||||
|
## Project Configuration
|
||||||
|
|
||||||
|
- Framework: React 18+ with TypeScript
|
||||||
|
- Build Tool: Vite
|
||||||
|
- Styling: Tailwind CSS with luxury design system
|
||||||
|
- Architecture: Component-based with modular structure
|
||||||
|
|
||||||
|
## Setup Progress
|
||||||
|
|
||||||
|
- [x] Created workspace directory
|
||||||
|
- [x] Created copilot-instructions.md
|
||||||
|
- [ ] Scaffold React TypeScript project with Vite
|
||||||
|
- [ ] Configure Tailwind CSS with luxury color palette
|
||||||
|
- [ ] Setup base styles and animations
|
||||||
|
- [ ] Create all components
|
||||||
|
- [ ] Test and finalize
|
||||||
|
|
||||||
|
## Design System Notes
|
||||||
|
|
||||||
|
- Luxury color palette with deep-forest, luxury-gold, cream
|
||||||
|
- Typography: Playfair Display + Montserrat
|
||||||
|
- Premium aesthetic with backdrop blur effects
|
||||||
|
- Component-based architecture with proper responsive design
|
||||||
24
.gitignore
vendored
Normal file
24
.gitignore
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
node_modules
|
||||||
|
dist
|
||||||
|
dist-ssr
|
||||||
|
*.local
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.idea
|
||||||
|
.DS_Store
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
||||||
69
README.md
Normal file
69
README.md
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
# React + TypeScript + Vite
|
||||||
|
|
||||||
|
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
|
||||||
|
|
||||||
|
Currently, two official plugins are available:
|
||||||
|
|
||||||
|
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) for Fast Refresh
|
||||||
|
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
|
||||||
|
|
||||||
|
## Expanding the ESLint configuration
|
||||||
|
|
||||||
|
If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:
|
||||||
|
|
||||||
|
```js
|
||||||
|
export default defineConfig([
|
||||||
|
globalIgnores(['dist']),
|
||||||
|
{
|
||||||
|
files: ['**/*.{ts,tsx}'],
|
||||||
|
extends: [
|
||||||
|
// Other configs...
|
||||||
|
|
||||||
|
// Remove tseslint.configs.recommended and replace with this
|
||||||
|
tseslint.configs.recommendedTypeChecked,
|
||||||
|
// Alternatively, use this for stricter rules
|
||||||
|
tseslint.configs.strictTypeChecked,
|
||||||
|
// Optionally, add this for stylistic rules
|
||||||
|
tseslint.configs.stylisticTypeChecked,
|
||||||
|
|
||||||
|
// Other configs...
|
||||||
|
],
|
||||||
|
languageOptions: {
|
||||||
|
parserOptions: {
|
||||||
|
project: ['./tsconfig.node.json', './tsconfig.app.json'],
|
||||||
|
tsconfigRootDir: import.meta.dirname,
|
||||||
|
},
|
||||||
|
// other options...
|
||||||
|
},
|
||||||
|
},
|
||||||
|
])
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules:
|
||||||
|
|
||||||
|
```js
|
||||||
|
// eslint.config.js
|
||||||
|
import reactX from 'eslint-plugin-react-x'
|
||||||
|
import reactDom from 'eslint-plugin-react-dom'
|
||||||
|
|
||||||
|
export default defineConfig([
|
||||||
|
globalIgnores(['dist']),
|
||||||
|
{
|
||||||
|
files: ['**/*.{ts,tsx}'],
|
||||||
|
extends: [
|
||||||
|
// Other configs...
|
||||||
|
// Enable lint rules for React
|
||||||
|
reactX.configs['recommended-typescript'],
|
||||||
|
// Enable lint rules for React DOM
|
||||||
|
reactDom.configs.recommended,
|
||||||
|
],
|
||||||
|
languageOptions: {
|
||||||
|
parserOptions: {
|
||||||
|
project: ['./tsconfig.node.json', './tsconfig.app.json'],
|
||||||
|
tsconfigRootDir: import.meta.dirname,
|
||||||
|
},
|
||||||
|
// other options...
|
||||||
|
},
|
||||||
|
},
|
||||||
|
])
|
||||||
|
```
|
||||||
23
eslint.config.js
Normal file
23
eslint.config.js
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import js from '@eslint/js'
|
||||||
|
import globals from 'globals'
|
||||||
|
import reactHooks from 'eslint-plugin-react-hooks'
|
||||||
|
import reactRefresh from 'eslint-plugin-react-refresh'
|
||||||
|
import tseslint from 'typescript-eslint'
|
||||||
|
import { defineConfig, globalIgnores } from 'eslint/config'
|
||||||
|
|
||||||
|
export default defineConfig([
|
||||||
|
globalIgnores(['dist']),
|
||||||
|
{
|
||||||
|
files: ['**/*.{ts,tsx}'],
|
||||||
|
extends: [
|
||||||
|
js.configs.recommended,
|
||||||
|
tseslint.configs.recommended,
|
||||||
|
reactHooks.configs['recommended-latest'],
|
||||||
|
reactRefresh.configs.vite,
|
||||||
|
],
|
||||||
|
languageOptions: {
|
||||||
|
ecmaVersion: 2020,
|
||||||
|
globals: globals.browser,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
])
|
||||||
17
index.html
Normal file
17
index.html
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<!-- Preconnects and fonts -->
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:wght@400;500;600;700;800;900&family=Montserrat:wght@300;400;500;600;700;800;900&display=swap" rel="stylesheet" />
|
||||||
|
<title>Vite + React + TS</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="root"></div>
|
||||||
|
<script type="module" src="/src/main.tsx"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
4508
package-lock.json
generated
Normal file
4508
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
33
package.json
Normal file
33
package.json
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
{
|
||||||
|
"name": "pennyzo-web-app",
|
||||||
|
"private": true,
|
||||||
|
"version": "0.0.0",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite",
|
||||||
|
"build": "tsc -b && vite build",
|
||||||
|
"lint": "eslint .",
|
||||||
|
"preview": "vite preview"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"react": "^19.1.1",
|
||||||
|
"react-dom": "^19.1.1",
|
||||||
|
"react-router-dom": "^7.9.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@eslint/js": "^9.36.0",
|
||||||
|
"@types/react": "^19.1.13",
|
||||||
|
"@types/react-dom": "^19.1.9",
|
||||||
|
"@vitejs/plugin-react": "^5.0.3",
|
||||||
|
"autoprefixer": "^10.4.21",
|
||||||
|
"eslint": "^9.36.0",
|
||||||
|
"eslint-plugin-react-hooks": "^5.2.0",
|
||||||
|
"eslint-plugin-react-refresh": "^0.4.20",
|
||||||
|
"globals": "^16.4.0",
|
||||||
|
"postcss": "^8.5.6",
|
||||||
|
"tailwindcss": "^3.4.17",
|
||||||
|
"typescript": "~5.8.3",
|
||||||
|
"typescript-eslint": "^8.44.0",
|
||||||
|
"vite": "^7.1.7"
|
||||||
|
}
|
||||||
|
}
|
||||||
6
postcss.config.js
Normal file
6
postcss.config.js
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
export default {
|
||||||
|
plugins: {
|
||||||
|
tailwindcss: {},
|
||||||
|
autoprefixer: {},
|
||||||
|
},
|
||||||
|
};
|
||||||
1
public/vite.svg
Normal file
1
public/vite.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
||||||
|
After Width: | Height: | Size: 1.5 KiB |
42
src/App.css
Normal file
42
src/App.css
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
#root {
|
||||||
|
max-width: 1280px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 2rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
height: 6em;
|
||||||
|
padding: 1.5em;
|
||||||
|
will-change: filter;
|
||||||
|
transition: filter 300ms;
|
||||||
|
}
|
||||||
|
.logo:hover {
|
||||||
|
filter: drop-shadow(0 0 2em #646cffaa);
|
||||||
|
}
|
||||||
|
.logo.react:hover {
|
||||||
|
filter: drop-shadow(0 0 2em #61dafbaa);
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes logo-spin {
|
||||||
|
from {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-reduced-motion: no-preference) {
|
||||||
|
a:nth-of-type(2) .logo {
|
||||||
|
animation: logo-spin infinite 20s linear;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
padding: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.read-the-docs {
|
||||||
|
color: #888;
|
||||||
|
}
|
||||||
55
src/App.tsx
Normal file
55
src/App.tsx
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom';
|
||||||
|
import LandingPage from './pages/LandingPage';
|
||||||
|
import LoginPage from './pages/LoginPage';
|
||||||
|
import ForgotPasswordPage from './pages/ForgotPasswordPage';
|
||||||
|
|
||||||
|
function App() {
|
||||||
|
return (
|
||||||
|
<Router>
|
||||||
|
<div className="relative min-h-screen bg-deep-forest overflow-hidden">
|
||||||
|
{/* Background System - Fixed layers with proper z-index */}
|
||||||
|
<div
|
||||||
|
aria-hidden="true"
|
||||||
|
role="presentation"
|
||||||
|
className="pointer-events-none fixed inset-0 z-0 bg-pennyzo bg-cover bg-fixed bg-center"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
aria-hidden="true"
|
||||||
|
role="presentation"
|
||||||
|
className="pointer-events-none fixed inset-0 z-[1] bg-gradient-to-br from-deep-forest/70 via-deep-forest/50 to-rich-brown/40"
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Animated Background Elements - Decorative only */}
|
||||||
|
<div
|
||||||
|
aria-hidden="true"
|
||||||
|
role="presentation"
|
||||||
|
className="pointer-events-none fixed top-1/4 left-1/4 z-[2] w-96 h-96 bg-luxury-gold/5 rounded-full blur-3xl animate-float"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
aria-hidden="true"
|
||||||
|
role="presentation"
|
||||||
|
className="pointer-events-none fixed bottom-1/4 right-1/4 z-[2] w-80 h-80 bg-bronze/5 rounded-full blur-3xl animate-float"
|
||||||
|
style={{ animationDelay: '2s' }}
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
aria-hidden="true"
|
||||||
|
role="presentation"
|
||||||
|
className="pointer-events-none fixed top-1/2 left-1/2 z-[2] w-64 h-64 bg-brass/5 rounded-full blur-3xl animate-float -translate-x-1/2 -translate-y-1/2"
|
||||||
|
style={{ animationDelay: '4s' }}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Main Content - Highest z-index for interactivity */}
|
||||||
|
<main className="relative z-10 min-h-screen">
|
||||||
|
<Routes>
|
||||||
|
<Route path="/" element={<Navigate to="/login" replace />} />
|
||||||
|
<Route path="/home" element={<LandingPage />} />
|
||||||
|
<Route path="/login" element={<LoginPage />} />
|
||||||
|
<Route path="/forgot-password" element={<ForgotPasswordPage />} />
|
||||||
|
</Routes>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
</Router>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default App;
|
||||||
BIN
src/assets/bg pennyzo.png
Normal file
BIN
src/assets/bg pennyzo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 MiB |
1
src/assets/react.svg
Normal file
1
src/assets/react.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="35.93" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 228"><path fill="#00D8FF" d="M210.483 73.824a171.49 171.49 0 0 0-8.24-2.597c.465-1.9.893-3.777 1.273-5.621c6.238-30.281 2.16-54.676-11.769-62.708c-13.355-7.7-35.196.329-57.254 19.526a171.23 171.23 0 0 0-6.375 5.848a155.866 155.866 0 0 0-4.241-3.917C100.759 3.829 77.587-4.822 63.673 3.233C50.33 10.957 46.379 33.89 51.995 62.588a170.974 170.974 0 0 0 1.892 8.48c-3.28.932-6.445 1.924-9.474 2.98C17.309 83.498 0 98.307 0 113.668c0 15.865 18.582 31.778 46.812 41.427a145.52 145.52 0 0 0 6.921 2.165a167.467 167.467 0 0 0-2.01 9.138c-5.354 28.2-1.173 50.591 12.134 58.266c13.744 7.926 36.812-.22 59.273-19.855a145.567 145.567 0 0 0 5.342-4.923a168.064 168.064 0 0 0 6.92 6.314c21.758 18.722 43.246 26.282 56.54 18.586c13.731-7.949 18.194-32.003 12.4-61.268a145.016 145.016 0 0 0-1.535-6.842c1.62-.48 3.21-.974 4.76-1.488c29.348-9.723 48.443-25.443 48.443-41.52c0-15.417-17.868-30.326-45.517-39.844Zm-6.365 70.984c-1.4.463-2.836.91-4.3 1.345c-3.24-10.257-7.612-21.163-12.963-32.432c5.106-11 9.31-21.767 12.459-31.957c2.619.758 5.16 1.557 7.61 2.4c23.69 8.156 38.14 20.213 38.14 29.504c0 9.896-15.606 22.743-40.946 31.14Zm-10.514 20.834c2.562 12.94 2.927 24.64 1.23 33.787c-1.524 8.219-4.59 13.698-8.382 15.893c-8.067 4.67-25.32-1.4-43.927-17.412a156.726 156.726 0 0 1-6.437-5.87c7.214-7.889 14.423-17.06 21.459-27.246c12.376-1.098 24.068-2.894 34.671-5.345a134.17 134.17 0 0 1 1.386 6.193ZM87.276 214.515c-7.882 2.783-14.16 2.863-17.955.675c-8.075-4.657-11.432-22.636-6.853-46.752a156.923 156.923 0 0 1 1.869-8.499c10.486 2.32 22.093 3.988 34.498 4.994c7.084 9.967 14.501 19.128 21.976 27.15a134.668 134.668 0 0 1-4.877 4.492c-9.933 8.682-19.886 14.842-28.658 17.94ZM50.35 144.747c-12.483-4.267-22.792-9.812-29.858-15.863c-6.35-5.437-9.555-10.836-9.555-15.216c0-9.322 13.897-21.212 37.076-29.293c2.813-.98 5.757-1.905 8.812-2.773c3.204 10.42 7.406 21.315 12.477 32.332c-5.137 11.18-9.399 22.249-12.634 32.792a134.718 134.718 0 0 1-6.318-1.979Zm12.378-84.26c-4.811-24.587-1.616-43.134 6.425-47.789c8.564-4.958 27.502 2.111 47.463 19.835a144.318 144.318 0 0 1 3.841 3.545c-7.438 7.987-14.787 17.08-21.808 26.988c-12.04 1.116-23.565 2.908-34.161 5.309a160.342 160.342 0 0 1-1.76-7.887Zm110.427 27.268a347.8 347.8 0 0 0-7.785-12.803c8.168 1.033 15.994 2.404 23.343 4.08c-2.206 7.072-4.956 14.465-8.193 22.045a381.151 381.151 0 0 0-7.365-13.322Zm-45.032-43.861c5.044 5.465 10.096 11.566 15.065 18.186a322.04 322.04 0 0 0-30.257-.006c4.974-6.559 10.069-12.652 15.192-18.18ZM82.802 87.83a323.167 323.167 0 0 0-7.227 13.238c-3.184-7.553-5.909-14.98-8.134-22.152c7.304-1.634 15.093-2.97 23.209-3.984a321.524 321.524 0 0 0-7.848 12.897Zm8.081 65.352c-8.385-.936-16.291-2.203-23.593-3.793c2.26-7.3 5.045-14.885 8.298-22.6a321.187 321.187 0 0 0 7.257 13.246c2.594 4.48 5.28 8.868 8.038 13.147Zm37.542 31.03c-5.184-5.592-10.354-11.779-15.403-18.433c4.902.192 9.899.29 14.978.29c5.218 0 10.376-.117 15.453-.343c-4.985 6.774-10.018 12.97-15.028 18.486Zm52.198-57.817c3.422 7.8 6.306 15.345 8.596 22.52c-7.422 1.694-15.436 3.058-23.88 4.071a382.417 382.417 0 0 0 7.859-13.026a347.403 347.403 0 0 0 7.425-13.565Zm-16.898 8.101a358.557 358.557 0 0 1-12.281 19.815a329.4 329.4 0 0 1-23.444.823c-7.967 0-15.716-.248-23.178-.732a310.202 310.202 0 0 1-12.513-19.846h.001a307.41 307.41 0 0 1-10.923-20.627a310.278 310.278 0 0 1 10.89-20.637l-.001.001a307.318 307.318 0 0 1 12.413-19.761c7.613-.576 15.42-.876 23.31-.876H128c7.926 0 15.743.303 23.354.883a329.357 329.357 0 0 1 12.335 19.695a358.489 358.489 0 0 1 11.036 20.54a329.472 329.472 0 0 1-11 20.722Zm22.56-122.124c8.572 4.944 11.906 24.881 6.52 51.026c-.344 1.668-.73 3.367-1.15 5.09c-10.622-2.452-22.155-4.275-34.23-5.408c-7.034-10.017-14.323-19.124-21.64-27.008a160.789 160.789 0 0 1 5.888-5.4c18.9-16.447 36.564-22.941 44.612-18.3ZM128 90.808c12.625 0 22.86 10.235 22.86 22.86s-10.235 22.86-22.86 22.86s-22.86-10.235-22.86-22.86s10.235-22.86 22.86-22.86Z"></path></svg>
|
||||||
|
After Width: | Height: | Size: 4.0 KiB |
230
src/components/AboutSection.tsx
Normal file
230
src/components/AboutSection.tsx
Normal file
@@ -0,0 +1,230 @@
|
|||||||
|
import React, { useEffect, useState, useRef } from 'react';
|
||||||
|
|
||||||
|
const AboutSection: React.FC = () => {
|
||||||
|
const [isVisible, setIsVisible] = useState(false);
|
||||||
|
const [activeTab, setActiveTab] = useState(0);
|
||||||
|
const sectionRef = useRef<HTMLElement>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const observer = new IntersectionObserver(
|
||||||
|
([entry]) => {
|
||||||
|
if (entry.isIntersecting) {
|
||||||
|
setIsVisible(true);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ threshold: 0.1 }
|
||||||
|
);
|
||||||
|
|
||||||
|
if (sectionRef.current) {
|
||||||
|
observer.observe(sectionRef.current);
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => observer.disconnect();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const tabs = [
|
||||||
|
{
|
||||||
|
title: 'Our Mission',
|
||||||
|
content: {
|
||||||
|
heading: 'Revolutionizing Digital Excellence',
|
||||||
|
description: 'We are dedicated to creating premium digital experiences that transform how businesses operate and succeed in the modern world.',
|
||||||
|
points: [
|
||||||
|
'Delivering cutting-edge technology solutions',
|
||||||
|
'Maintaining the highest standards of quality',
|
||||||
|
'Providing exceptional customer experiences',
|
||||||
|
'Driving innovation across all industries'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Our Vision',
|
||||||
|
content: {
|
||||||
|
heading: 'Shaping the Future of Technology',
|
||||||
|
description: 'To become the global leader in premium technology solutions, empowering businesses worldwide with innovative tools and services.',
|
||||||
|
points: [
|
||||||
|
'Leading technological advancement',
|
||||||
|
'Creating sustainable business value',
|
||||||
|
'Building long-term partnerships',
|
||||||
|
'Setting industry standards'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Our Values',
|
||||||
|
content: {
|
||||||
|
heading: 'Excellence in Everything We Do',
|
||||||
|
description: 'Our core values guide every decision we make and every solution we create, ensuring consistent quality and integrity.',
|
||||||
|
points: [
|
||||||
|
'Unwavering commitment to quality',
|
||||||
|
'Transparency in all interactions',
|
||||||
|
'Innovation-driven approach',
|
||||||
|
'Customer success as our priority'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const achievements = [
|
||||||
|
{ number: '500K+', label: 'Happy Customers', icon: '👥' },
|
||||||
|
{ number: '99.9%', label: 'Uptime Guarantee', icon: '⚡' },
|
||||||
|
{ number: '150+', label: 'Countries Served', icon: '🌍' },
|
||||||
|
{ number: '50+', label: 'Awards Won', icon: '🏆' }
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section
|
||||||
|
ref={sectionRef}
|
||||||
|
id="about"
|
||||||
|
className="relative py-24 lg:py-32 overflow-hidden"
|
||||||
|
>
|
||||||
|
{/* Background Elements */}
|
||||||
|
<div className="absolute inset-0 bg-gradient-to-b from-rich-brown/10 to-deep-forest/20"></div>
|
||||||
|
<div className="absolute top-20 left-10 w-80 h-80 bg-luxury-gold/5 rounded-full blur-3xl animate-float"></div>
|
||||||
|
<div className="absolute bottom-20 right-10 w-64 h-64 bg-brass/5 rounded-full blur-3xl animate-float" style={{ animationDelay: '3s' }}></div>
|
||||||
|
|
||||||
|
<div className="relative z-10 max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
|
{/* Section Header */}
|
||||||
|
<div className={`text-center mb-20 transition-all duration-1000 ${isVisible ? 'animate-fadeInUp' : 'opacity-0'}`}>
|
||||||
|
<div className="inline-block px-6 py-2 bg-gradient-to-r from-luxury-gold/20 to-brass/20 border border-luxury-gold/30 rounded-full text-luxury-gold font-montserrat font-medium text-sm backdrop-blur-sm mb-6">
|
||||||
|
🎯 About Premium
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 className="font-playfair text-4xl sm:text-5xl lg:text-6xl font-bold text-cream tracking-tight mb-6">
|
||||||
|
Crafting
|
||||||
|
<span className="block text-transparent bg-clip-text bg-gradient-to-r from-luxury-gold via-brass to-bronze">
|
||||||
|
Excellence
|
||||||
|
</span>
|
||||||
|
<span className="block">Since 2020</span>
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<p className="font-montserrat text-lg sm:text-xl text-cream/90 max-w-3xl mx-auto leading-relaxed">
|
||||||
|
We're passionate about creating extraordinary digital experiences that
|
||||||
|
drive business success and exceed customer expectations.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Main Content Grid */}
|
||||||
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-16 items-center mb-20">
|
||||||
|
{/* Tab Navigation & Content */}
|
||||||
|
<div className={`transition-all duration-1000 ${isVisible ? 'animate-fadeInLeft' : 'opacity-0'}`}>
|
||||||
|
{/* Tab Navigation */}
|
||||||
|
<div className="flex flex-col sm:flex-row gap-2 mb-8 bg-gradient-to-br from-deep-forest/40 to-rich-brown/20 backdrop-blur-2xl rounded-2xl p-2">
|
||||||
|
{tabs.map((tab, index) => (
|
||||||
|
<button
|
||||||
|
key={tab.title}
|
||||||
|
onClick={() => setActiveTab(index)}
|
||||||
|
className={`flex-1 px-6 py-3 rounded-xl font-elegant-sans font-medium transition-all duration-300 focus:outline-none focus:ring-2 focus:ring-luxury-gold/50 ${
|
||||||
|
activeTab === index
|
||||||
|
? 'bg-luxury-gold text-deep-forest shadow-luxury'
|
||||||
|
: 'text-cream/70 hover:text-cream hover:bg-luxury-gold/10'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{tab.title}
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Tab Content */}
|
||||||
|
<div className="bg-gradient-to-br from-deep-forest/40 to-rich-brown/20 backdrop-blur-2xl border border-luxury-gold/20 rounded-3xl p-8">
|
||||||
|
<h3 className="font-luxury-serif text-3xl font-bold text-cream mb-4">
|
||||||
|
{tabs[activeTab].content.heading}
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<p className="font-elegant-sans text-cream/80 text-lg leading-relaxed mb-6">
|
||||||
|
{tabs[activeTab].content.description}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<ul className="space-y-3">
|
||||||
|
{tabs[activeTab].content.points.map((point, index) => (
|
||||||
|
<li key={index} className="flex items-center space-x-3">
|
||||||
|
<div className="w-2 h-2 bg-luxury-gold rounded-full flex-shrink-0"></div>
|
||||||
|
<span className="font-elegant-sans text-cream/90">
|
||||||
|
{point}
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Achievement Stats */}
|
||||||
|
<div className={`transition-all duration-1000 ${isVisible ? 'animate-fadeInRight' : 'opacity-0'}`}>
|
||||||
|
<div className="grid grid-cols-2 gap-6">
|
||||||
|
{achievements.map((achievement, index) => (
|
||||||
|
<div
|
||||||
|
key={achievement.label}
|
||||||
|
className="bg-gradient-to-br from-deep-forest/40 to-rich-brown/20 backdrop-blur-2xl border border-luxury-gold/20 rounded-3xl p-8 text-center hover:scale-105 transition-all duration-300 hover:shadow-luxury"
|
||||||
|
style={{ animationDelay: `${index * 200}ms` }}
|
||||||
|
>
|
||||||
|
<div className="text-4xl mb-3">{achievement.icon}</div>
|
||||||
|
<div className="font-luxury-serif text-3xl font-bold text-luxury-gold mb-2">
|
||||||
|
{achievement.number}
|
||||||
|
</div>
|
||||||
|
<div className="font-elegant-sans text-cream/80 text-sm">
|
||||||
|
{achievement.label}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Team Highlights */}
|
||||||
|
<div className="mt-8 bg-gradient-to-br from-deep-forest/40 to-rich-brown/20 backdrop-blur-2xl border border-luxury-gold/20 rounded-3xl p-8">
|
||||||
|
<h4 className="font-luxury-serif text-2xl font-bold text-cream mb-4">
|
||||||
|
World-Class Team
|
||||||
|
</h4>
|
||||||
|
<p className="font-elegant-sans text-cream/80 mb-6">
|
||||||
|
Our diverse team of experts brings decades of combined experience
|
||||||
|
in technology, design, and business strategy.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="flex items-center space-x-4">
|
||||||
|
{/* Team Avatar Stack */}
|
||||||
|
<div className="flex -space-x-2">
|
||||||
|
{[1, 2, 3, 4, 5].map((_, index) => (
|
||||||
|
<div
|
||||||
|
key={index}
|
||||||
|
className="w-10 h-10 bg-gradient-to-br from-luxury-gold to-brass rounded-full border-2 border-deep-forest flex items-center justify-center text-deep-forest font-bold text-sm"
|
||||||
|
>
|
||||||
|
{String.fromCharCode(65 + index)}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
<div className="w-10 h-10 bg-gradient-to-br from-bronze to-luxury-gold rounded-full border-2 border-deep-forest flex items-center justify-center text-deep-forest font-bold text-xs">
|
||||||
|
50+
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div className="font-elegant-sans text-cream font-semibold">
|
||||||
|
Expert Team
|
||||||
|
</div>
|
||||||
|
<div className="font-elegant-sans text-cream/70 text-sm">
|
||||||
|
50+ Professionals
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Call to Action */}
|
||||||
|
<div className={`text-center transition-all duration-1000 ${isVisible ? 'animate-fadeInUp' : 'opacity-0'}`} style={{ animationDelay: '800ms' }}>
|
||||||
|
<div className="bg-gradient-to-r from-luxury-gold/10 to-brass/10 border border-luxury-gold/30 rounded-3xl p-12 backdrop-blur-2xl">
|
||||||
|
<h3 className="font-luxury-serif text-3xl sm:text-4xl font-bold text-cream mb-4">
|
||||||
|
Ready to Join Our Success Story?
|
||||||
|
</h3>
|
||||||
|
<p className="font-elegant-sans text-cream/80 text-lg mb-8 max-w-2xl mx-auto">
|
||||||
|
Discover how our premium platform can transform your business and
|
||||||
|
help you achieve extraordinary results.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<button className="min-w-[220px] bg-gradient-to-r from-luxury-gold to-brass text-deep-forest font-elegant-sans font-bold px-8 py-4 rounded-full hover:scale-105 hover:shadow-luxury-lg transition-all duration-300 focus:outline-none focus:ring-2 focus:ring-luxury-gold/50">
|
||||||
|
Start Your Journey
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AboutSection;
|
||||||
183
src/components/FeaturesSection.tsx
Normal file
183
src/components/FeaturesSection.tsx
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
import React, { useEffect, useState, useRef } from 'react';
|
||||||
|
|
||||||
|
const FeaturesSection: React.FC = () => {
|
||||||
|
const [isVisible, setIsVisible] = useState(false);
|
||||||
|
const sectionRef = useRef<HTMLElement>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const observer = new IntersectionObserver(
|
||||||
|
([entry]) => {
|
||||||
|
if (entry.isIntersecting) {
|
||||||
|
setIsVisible(true);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ threshold: 0.1 }
|
||||||
|
);
|
||||||
|
|
||||||
|
if (sectionRef.current) {
|
||||||
|
observer.observe(sectionRef.current);
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => observer.disconnect();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const features = [
|
||||||
|
{
|
||||||
|
icon: (
|
||||||
|
<svg className="w-8 h-8" fill="currentColor" viewBox="0 0 20 20">
|
||||||
|
<path fillRule="evenodd" d="M12.316 3.051a1 1 0 01.633 1.265l-4 12a1 1 0 11-1.898-.632l4-12a1 1 0 011.265-.633zM5.707 6.293a1 1 0 010 1.414L3.414 10l2.293 2.293a1 1 0 11-1.414 1.414l-3-3a1 1 0 010-1.414l3-3a1 1 0 011.414 0zm8.586 0a1 1 0 011.414 0l3 3a1 1 0 010 1.414l-3 3a1 1 0 11-1.414-1.414L16.586 10l-2.293-2.293a1 1 0 010-1.414z" clipRule="evenodd" />
|
||||||
|
</svg>
|
||||||
|
),
|
||||||
|
title: 'Advanced Technology',
|
||||||
|
description: 'Cutting-edge solutions powered by the latest innovations in technology, ensuring peak performance and reliability.',
|
||||||
|
highlights: ['AI-Powered', 'Real-time Processing', 'Cloud-Native']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: (
|
||||||
|
<svg className="w-8 h-8" fill="currentColor" viewBox="0 0 20 20">
|
||||||
|
<path fillRule="evenodd" d="M2.166 4.999A11.954 11.954 0 0010 1.944 11.954 11.954 0 0017.834 5c.11.65.166 1.32.166 2.001 0 5.225-3.34 9.67-8 11.317C5.34 16.67 2 12.225 2 7c0-.682.057-1.35.166-2.001zm11.541 3.708a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clipRule="evenodd" />
|
||||||
|
</svg>
|
||||||
|
),
|
||||||
|
title: 'Enterprise Security',
|
||||||
|
description: 'Bank-level security protocols protect your data with end-to-end encryption and multi-layer authentication systems.',
|
||||||
|
highlights: ['256-bit Encryption', 'Multi-Factor Auth', 'SOC 2 Compliant']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: (
|
||||||
|
<svg className="w-8 h-8" fill="currentColor" viewBox="0 0 20 20">
|
||||||
|
<path d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||||
|
</svg>
|
||||||
|
),
|
||||||
|
title: 'Premium Support',
|
||||||
|
description: 'Dedicated support team available 24/7 with average response time under 2 minutes for premium customers.',
|
||||||
|
highlights: ['24/7 Availability', '< 2min Response', 'Dedicated Team']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: (
|
||||||
|
<svg className="w-8 h-8" fill="currentColor" viewBox="0 0 20 20">
|
||||||
|
<path fillRule="evenodd" d="M11.49 3.17c-.38-1.56-2.6-1.56-2.98 0a1.532 1.532 0 01-2.286.948c-1.372-.836-2.942.734-2.106 2.106.54.886.061 2.042-.947 2.287-1.561.379-1.561 2.6 0 2.978a1.532 1.532 0 01.947 2.287c-.836 1.372.734 2.942 2.106 2.106a1.532 1.532 0 012.287.947c.379 1.561 2.6 1.561 2.978 0a1.533 1.533 0 012.287-.947c1.372.836 2.942-.734 2.106-2.106a1.533 1.533 0 01.947-2.287c1.561-.379 1.561-2.6 0-2.978a1.532 1.532 0 01-.947-2.287c.836-1.372-.734-2.942-2.106-2.106a1.532 1.532 0 01-2.287-.947zM10 13a3 3 0 100-6 3 3 0 000 6z" clipRule="evenodd" />
|
||||||
|
</svg>
|
||||||
|
),
|
||||||
|
title: 'Smart Analytics',
|
||||||
|
description: 'Comprehensive insights and analytics dashboard providing real-time metrics and predictive intelligence.',
|
||||||
|
highlights: ['Real-time Data', 'Predictive AI', 'Custom Reports']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: (
|
||||||
|
<svg className="w-8 h-8" fill="currentColor" viewBox="0 0 20 20">
|
||||||
|
<path fillRule="evenodd" d="M3 4a1 1 0 011-1h4a1 1 0 010 2H6.414l2.293 2.293a1 1 0 11-1.414 1.414L5 6.414V8a1 1 0 01-2 0V4zm9 1a1 1 0 010-2h4a1 1 0 011 1v4a1 1 0 01-2 0V6.414l-2.293 2.293a1 1 0 11-1.414-1.414L13.586 5H12zm-9 7a1 1 0 012 0v1.586l2.293-2.293a1 1 0 111.414 1.414L6.414 15H8a1 1 0 010 2H4a1 1 0 01-1-1v-4zm13-1a1 1 0 011 1v4a1 1 0 01-1 1h-4a1 1 0 010-2h1.586l-2.293-2.293a1 1 0 111.414-1.414L15.586 13H14a1 1 0 01-1-1z" clipRule="evenodd" />
|
||||||
|
</svg>
|
||||||
|
),
|
||||||
|
title: 'Scalable Platform',
|
||||||
|
description: 'Infinitely scalable architecture that grows with your business, handling millions of transactions seamlessly.',
|
||||||
|
highlights: ['Auto-scaling', 'Load Balancing', '99.9% Uptime']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: (
|
||||||
|
<svg className="w-8 h-8" fill="currentColor" viewBox="0 0 20 20">
|
||||||
|
<path fillRule="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" clipRule="evenodd" />
|
||||||
|
</svg>
|
||||||
|
),
|
||||||
|
title: 'Easy Integration',
|
||||||
|
description: 'Simple API integration with comprehensive documentation and SDKs for all major programming languages.',
|
||||||
|
highlights: ['REST API', 'SDKs Available', 'Quick Setup']
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section
|
||||||
|
ref={sectionRef}
|
||||||
|
id="features"
|
||||||
|
className="relative py-24 lg:py-32 overflow-hidden"
|
||||||
|
>
|
||||||
|
{/* Background Elements */}
|
||||||
|
<div className="absolute inset-0 bg-gradient-to-b from-deep-forest/20 to-rich-brown/10"></div>
|
||||||
|
<div className="absolute top-32 right-10 w-72 h-72 bg-luxury-gold/5 rounded-full blur-3xl"></div>
|
||||||
|
<div className="absolute bottom-32 left-10 w-96 h-96 bg-bronze/5 rounded-full blur-3xl"></div>
|
||||||
|
|
||||||
|
<div className="relative z-10 max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
|
{/* Section Header */}
|
||||||
|
<div className={`text-center mb-20 transition-all duration-1000 ${isVisible ? 'animate-fadeInUp' : 'opacity-0'}`}>
|
||||||
|
<div className="inline-block px-6 py-2 bg-gradient-to-r from-luxury-gold/20 to-brass/20 border border-luxury-gold/30 rounded-full text-luxury-gold font-montserrat font-medium text-sm backdrop-blur-sm mb-6">
|
||||||
|
✨ Premium Features
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 className="font-playfair text-4xl sm:text-5xl lg:text-6xl font-bold text-cream tracking-tight mb-6">
|
||||||
|
Exceptional
|
||||||
|
<span className="block text-transparent bg-clip-text bg-gradient-to-r from-luxury-gold via-brass to-bronze">
|
||||||
|
Capabilities
|
||||||
|
</span>
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<p className="font-montserrat text-lg sm:text-xl text-cream/90 max-w-3xl mx-auto leading-relaxed">
|
||||||
|
Discover powerful features designed to elevate your experience and deliver
|
||||||
|
unmatched results with enterprise-grade reliability and premium support.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Features Grid */}
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8 lg:gap-12">
|
||||||
|
{features.map((feature, index) => (
|
||||||
|
<div
|
||||||
|
key={feature.title}
|
||||||
|
className={`group bg-gradient-to-br from-deep-forest/40 to-rich-brown/20 backdrop-blur-2xl border border-luxury-gold/20 rounded-3xl p-8 hover:scale-105 hover:shadow-luxury-lg hover:border-luxury-gold/40 transition-all duration-500 animate-fadeInUp`}
|
||||||
|
style={{ animationDelay: `${index * 150}ms` }}
|
||||||
|
>
|
||||||
|
{/* Icon */}
|
||||||
|
<div className="w-16 h-16 bg-gradient-to-br from-luxury-gold/20 to-brass/20 rounded-2xl flex items-center justify-center text-luxury-gold mb-6 group-hover:scale-110 transition-transform duration-300">
|
||||||
|
{feature.icon}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Content */}
|
||||||
|
<h3 className="font-playfair text-2xl font-bold text-cream mb-4">
|
||||||
|
{feature.title}
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<p className="font-montserrat text-cream/90 leading-relaxed mb-6">
|
||||||
|
{feature.description}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{/* Highlights */}
|
||||||
|
<div className="space-y-2">
|
||||||
|
{feature.highlights.map((highlight, highlightIndex) => (
|
||||||
|
<div key={highlightIndex} className="flex items-center space-x-2">
|
||||||
|
<div className="w-1.5 h-1.5 bg-luxury-gold rounded-full"></div>
|
||||||
|
<span className="font-montserrat text-sm text-cream/80">
|
||||||
|
{highlight}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Hover Effect */}
|
||||||
|
<div className="absolute inset-0 bg-gradient-to-br from-luxury-gold/10 to-transparent rounded-3xl opacity-0 group-hover:opacity-100 transition-opacity duration-500 pointer-events-none"></div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Bottom CTA */}
|
||||||
|
<div className={`text-center mt-20 transition-all duration-1000 ${isVisible ? 'animate-fadeInUp' : 'opacity-0'}`} style={{ animationDelay: '900ms' }}>
|
||||||
|
<div className="bg-gradient-to-br from-deep-forest/60 to-rich-brown/40 backdrop-blur-2xl border border-luxury-gold/30 rounded-3xl p-12">
|
||||||
|
<h3 className="font-playfair text-3xl sm:text-4xl font-bold text-cream mb-4">
|
||||||
|
Ready to Experience Premium?
|
||||||
|
</h3>
|
||||||
|
<p className="font-montserrat text-cream/80 text-lg mb-8 max-w-2xl mx-auto">
|
||||||
|
Join thousands of satisfied customers who trust our platform for their most important projects.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="flex flex-col sm:flex-row gap-4 justify-center">
|
||||||
|
<button className="min-w-[200px] bg-gradient-to-r from-luxury-gold to-brass text-deep-forest font-montserrat font-bold px-8 py-4 rounded-full hover:scale-105 hover:shadow-luxury-lg transition-all duration-300 focus:outline-none focus:ring-2 focus:ring-luxury-gold/50">
|
||||||
|
Get Started Now
|
||||||
|
</button>
|
||||||
|
<button className="min-w-[200px] border-2 border-luxury-gold/50 text-luxury-gold font-montserrat font-semibold px-8 py-4 rounded-full hover:bg-luxury-gold/10 hover:border-luxury-gold hover:scale-105 transition-all duration-300 backdrop-blur-sm focus:outline-none focus:ring-2 focus:ring-luxury-gold/50">
|
||||||
|
Learn More
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default FeaturesSection;
|
||||||
218
src/components/Footer.tsx
Normal file
218
src/components/Footer.tsx
Normal file
@@ -0,0 +1,218 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
const Footer: React.FC = () => {
|
||||||
|
const currentYear = new Date().getFullYear();
|
||||||
|
|
||||||
|
const footerSections = [
|
||||||
|
{
|
||||||
|
title: 'Product',
|
||||||
|
links: [
|
||||||
|
{ label: 'Features', href: '#features' },
|
||||||
|
{ label: 'Premium Plans', href: '#pricing' },
|
||||||
|
{ label: 'Enterprise', href: '#enterprise' },
|
||||||
|
{ label: 'API Documentation', href: '#docs' },
|
||||||
|
{ label: 'Security', href: '#security' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Company',
|
||||||
|
links: [
|
||||||
|
{ label: 'About Us', href: '#about' },
|
||||||
|
{ label: 'Careers', href: '#careers' },
|
||||||
|
{ label: 'Press Kit', href: '#press' },
|
||||||
|
{ label: 'Partner Program', href: '#partners' },
|
||||||
|
{ label: 'Blog', href: '#blog' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Support',
|
||||||
|
links: [
|
||||||
|
{ label: 'Help Center', href: '#help' },
|
||||||
|
{ label: 'Contact Us', href: '#contact' },
|
||||||
|
{ label: 'System Status', href: '#status' },
|
||||||
|
{ label: 'Premium Support', href: '#premium-support' },
|
||||||
|
{ label: 'Community', href: '#community' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Legal',
|
||||||
|
links: [
|
||||||
|
{ label: 'Privacy Policy', href: '#privacy' },
|
||||||
|
{ label: 'Terms of Service', href: '#terms' },
|
||||||
|
{ label: 'Cookie Policy', href: '#cookies' },
|
||||||
|
{ label: 'GDPR', href: '#gdpr' },
|
||||||
|
{ label: 'Compliance', href: '#compliance' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const socialLinks = [
|
||||||
|
{
|
||||||
|
name: 'Twitter',
|
||||||
|
href: '#twitter',
|
||||||
|
icon: (
|
||||||
|
<svg className="w-6 h-6" fill="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path d="M8.29 20.251c7.547 0 11.675-6.253 11.675-11.675 0-.178 0-.355-.012-.53A8.348 8.348 0 0022 5.92a8.19 8.19 0 01-2.357.646 4.118 4.118 0 001.804-2.27 8.224 8.224 0 01-2.605.996 4.107 4.107 0 00-6.993 3.743 11.65 11.65 0 01-8.457-4.287 4.106 4.106 0 001.27 5.477A4.072 4.072 0 012.8 9.713v.052a4.105 4.105 0 003.292 4.022 4.095 4.095 0 01-1.853.07 4.108 4.108 0 003.834 2.85A8.233 8.233 0 012 18.407a11.616 11.616 0 006.29 1.84" />
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'LinkedIn',
|
||||||
|
href: '#linkedin',
|
||||||
|
icon: (
|
||||||
|
<svg className="w-6 h-6" 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.433a2.062 2.062 0 01-2.063-2.065 2.064 2.064 0 112.063 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>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'GitHub',
|
||||||
|
href: '#github',
|
||||||
|
icon: (
|
||||||
|
<svg className="w-6 h-6" fill="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z" />
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Discord',
|
||||||
|
href: '#discord',
|
||||||
|
icon: (
|
||||||
|
<svg className="w-6 h-6" fill="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path d="M20.317 4.3698a19.7913 19.7913 0 00-4.8851-1.5152.0741.0741 0 00-.0785.0371c-.211.3753-.4447.8648-.6083 1.2495-1.8447-.2762-3.68-.2762-5.4868 0-.1636-.3933-.4058-.8742-.6177-1.2495a.077.077 0 00-.0785-.037 19.7363 19.7363 0 00-4.8852 1.515.0699.0699 0 00-.0321.0277C.5334 9.0458-.319 13.5799.0992 18.0578a.0824.0824 0 00.0312.0561c2.0528 1.5076 4.0413 2.4228 5.9929 3.0294a.0777.0777 0 00.0842-.0276c.4616-.6304.8731-1.2952 1.226-1.9942a.076.076 0 00-.0416-.1057c-.6528-.2476-1.2743-.5495-1.8722-.8923a.077.077 0 01-.0076-.1277c.1258-.0943.2517-.1923.3718-.2914a.0743.0743 0 01.0776-.0105c3.9278 1.7933 8.18 1.7933 12.0614 0a.0739.0739 0 01.0785.0095c.1202.099.246.1981.3728.2924a.077.077 0 01-.0066.1276 12.2986 12.2986 0 01-1.873.8914.0766.0766 0 00-.0407.1067c.3604.698.7719 1.3628 1.225 1.9932a.076.076 0 00.0842.0286c1.961-.6067 3.9495-1.5219 6.0023-3.0294a.077.077 0 00.0313-.0552c.5004-5.177-.8382-9.6739-3.5485-13.6604a.061.061 0 00-.0312-.0286zM8.02 15.3312c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9555-2.4189 2.157-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419-.0002 1.3332-.9555 2.4189-2.1569 2.4189zm7.9748 0c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9554-2.4189 2.1569-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.9554 2.4189-2.1568 2.4189Z" />
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<footer id="contact" className="relative bg-gradient-to-b from-deep-forest/40 to-deep-forest border-t border-luxury-gold/20">
|
||||||
|
{/* Background Elements */}
|
||||||
|
<div className="absolute inset-0 bg-luxury-texture bg-cover bg-fixed bg-center opacity-10"></div>
|
||||||
|
<div className="absolute top-0 left-1/4 w-64 h-64 bg-luxury-gold/5 rounded-full blur-3xl"></div>
|
||||||
|
<div className="absolute bottom-0 right-1/4 w-80 h-80 bg-bronze/5 rounded-full blur-3xl"></div>
|
||||||
|
|
||||||
|
<div className="relative z-10 max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
|
{/* Newsletter Section */}
|
||||||
|
<div className="py-16 border-b border-luxury-gold/20">
|
||||||
|
<div className="max-w-4xl mx-auto text-center">
|
||||||
|
<h3 className="font-playfair text-3xl sm:text-4xl font-bold text-cream mb-4">
|
||||||
|
Stay Updated with Premium
|
||||||
|
</h3>
|
||||||
|
<p className="font-montserrat text-lg text-cream/80 mb-8">
|
||||||
|
Get exclusive insights, feature updates, and premium content delivered to your inbox.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="flex flex-col sm:flex-row max-w-md mx-auto gap-4">
|
||||||
|
<input
|
||||||
|
type="email"
|
||||||
|
placeholder="Enter your email"
|
||||||
|
className="flex-1 px-6 py-4 bg-deep-forest/60 border border-luxury-gold/30 rounded-full text-cream placeholder-cream/50 focus:outline-none focus:border-luxury-gold focus:ring-2 focus:ring-luxury-gold/20 backdrop-blur-sm"
|
||||||
|
/>
|
||||||
|
<button className="px-8 py-4 bg-gradient-to-r from-luxury-gold to-brass text-deep-forest font-montserrat font-bold rounded-full hover:scale-105 transition-all duration-300 shadow-luxury focus:outline-none focus:ring-2 focus:ring-luxury-gold/50">
|
||||||
|
Subscribe
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Main Footer Content */}
|
||||||
|
<div className="py-16">
|
||||||
|
<div className="grid grid-cols-1 lg:grid-cols-6 gap-12">
|
||||||
|
{/* Brand Section */}
|
||||||
|
<div className="lg:col-span-2">
|
||||||
|
<div className="flex items-center space-x-3 mb-6">
|
||||||
|
<div className="w-12 h-12 bg-gradient-to-br from-luxury-gold to-bronze rounded-xl flex items-center justify-center">
|
||||||
|
<svg className="w-7 h-7 text-deep-forest" fill="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path d="M12 2L2 7v10c0 5.55 3.84 9.74 9 10.5 5.16-.76 9-4.95 9-10.5V7l-10-5z" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<span className="font-playfair text-3xl font-bold text-cream">
|
||||||
|
Premium
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p className="font-montserrat text-cream/80 mb-8 leading-relaxed">
|
||||||
|
Creating exceptional digital experiences that drive business success and exceed customer expectations since 2020.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{/* Social Links */}
|
||||||
|
<div className="flex space-x-4">
|
||||||
|
{socialLinks.map((social) => (
|
||||||
|
<a
|
||||||
|
key={social.name}
|
||||||
|
href={social.href}
|
||||||
|
className="w-12 h-12 bg-gradient-to-br from-deep-forest/60 to-rich-brown/40 border border-luxury-gold/20 rounded-xl flex items-center justify-center text-luxury-gold hover:text-cream hover:bg-luxury-gold/20 hover:scale-110 transition-all duration-300 backdrop-blur-sm"
|
||||||
|
aria-label={social.name}
|
||||||
|
>
|
||||||
|
{social.icon}
|
||||||
|
</a>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Footer Links */}
|
||||||
|
{footerSections.map((section) => (
|
||||||
|
<div key={section.title}>
|
||||||
|
<h4 className="font-playfair text-xl font-bold text-cream mb-6">
|
||||||
|
{section.title}
|
||||||
|
</h4>
|
||||||
|
<ul className="space-y-3">
|
||||||
|
{section.links.map((link) => (
|
||||||
|
<li key={link.label}>
|
||||||
|
<a
|
||||||
|
href={link.href}
|
||||||
|
className="font-montserrat text-cream/70 hover:text-luxury-gold transition-colors duration-300 hover:underline"
|
||||||
|
>
|
||||||
|
{link.label}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Bottom Section */}
|
||||||
|
<div className="py-8 border-t border-luxury-gold/20">
|
||||||
|
<div className="flex flex-col md:flex-row justify-between items-center space-y-4 md:space-y-0">
|
||||||
|
{/* Copyright */}
|
||||||
|
<div className="font-montserrat text-cream/60">
|
||||||
|
© {currentYear} Premium. All rights reserved.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Additional Links */}
|
||||||
|
<div className="flex items-center space-x-8">
|
||||||
|
<a href="#sitemap" className="font-montserrat text-cream/60 hover:text-luxury-gold transition-colors duration-300">
|
||||||
|
Sitemap
|
||||||
|
</a>
|
||||||
|
<a href="#accessibility" className="font-montserrat text-cream/60 hover:text-luxury-gold transition-colors duration-300">
|
||||||
|
Accessibility
|
||||||
|
</a>
|
||||||
|
<div className="flex items-center space-x-2 text-cream/60">
|
||||||
|
<div className="w-2 h-2 bg-green-400 rounded-full animate-pulse"></div>
|
||||||
|
<span className="font-montserrat text-sm">All systems operational</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Back to Top Button */}
|
||||||
|
<div className="absolute -top-6 right-8">
|
||||||
|
<button
|
||||||
|
onClick={() => window.scrollTo({ top: 0, behavior: 'smooth' })}
|
||||||
|
className="w-12 h-12 bg-gradient-to-br from-luxury-gold to-brass text-deep-forest rounded-full shadow-luxury hover:scale-110 transition-all duration-300 focus:outline-none focus:ring-2 focus:ring-luxury-gold/50"
|
||||||
|
aria-label="Back to top"
|
||||||
|
>
|
||||||
|
<svg className="w-6 h-6 mx-auto" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 10l7-7m0 0l7 7m-7-7v18" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Footer;
|
||||||
138
src/components/Header.tsx
Normal file
138
src/components/Header.tsx
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
import React, { useState, useEffect } from 'react';
|
||||||
|
|
||||||
|
const Header: React.FC = () => {
|
||||||
|
const [isMenuOpen, setIsMenuOpen] = useState(false);
|
||||||
|
const [isScrolled, setIsScrolled] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const handleScroll = () => {
|
||||||
|
setIsScrolled(window.scrollY > 50);
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener('scroll', handleScroll);
|
||||||
|
return () => window.removeEventListener('scroll', handleScroll);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const navLinks = [
|
||||||
|
{ label: 'Home', href: '/home' },
|
||||||
|
{ label: 'Agents', href: '/#agents' },
|
||||||
|
{ label: 'Solutions', href: '/#solutions' },
|
||||||
|
{ label: 'Contact', href: '/#contact' }
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<header
|
||||||
|
className={`fixed top-0 left-0 right-0 z-50 transition-all duration-300 ${
|
||||||
|
isScrolled
|
||||||
|
? 'bg-deep-forest/90 backdrop-blur-xl border-b-2 border-luxury-gold/40 shadow-luxury'
|
||||||
|
: 'bg-deep-forest/20 backdrop-blur-md'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<nav className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
|
<div className="flex justify-between items-center h-20">
|
||||||
|
{/* Logo */}
|
||||||
|
<div className="flex-shrink-0 animate-fadeInLeft">
|
||||||
|
<a
|
||||||
|
href="/home"
|
||||||
|
className="flex items-center space-x-3 group"
|
||||||
|
aria-label="Pennyzo Web Home"
|
||||||
|
>
|
||||||
|
<div className="relative">
|
||||||
|
<div className="w-10 h-10 bg-gradient-to-br from-luxury-gold to-bronze rounded-lg flex items-center justify-center group-hover:scale-110 transition-transform duration-300 shadow-lg">
|
||||||
|
<span className="text-deep-forest font-playfair text-xl font-bold">P</span>
|
||||||
|
</div>
|
||||||
|
<div className="absolute -top-1 -right-1 w-3 h-3 bg-luxury-gold rounded-full animate-pulse opacity-75"></div>
|
||||||
|
</div>
|
||||||
|
<span className="font-playfair text-2xl font-bold text-cream group-hover:text-luxury-gold transition-colors duration-300">
|
||||||
|
Pennyzo Web
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Desktop Navigation */}
|
||||||
|
<div className="hidden md:flex items-center space-x-8">
|
||||||
|
{navLinks.map((link) => (
|
||||||
|
<a
|
||||||
|
key={link.label}
|
||||||
|
href={link.href}
|
||||||
|
className="relative font-montserrat font-medium text-cream hover:text-luxury-gold transition-all duration-300 group py-2 px-3 rounded-lg hover:bg-luxury-gold/10 backdrop-blur-sm border border-transparent hover:border-luxury-gold/30"
|
||||||
|
>
|
||||||
|
{link.label}
|
||||||
|
<span className="absolute bottom-0 left-0 w-0 h-0.5 bg-luxury-gold transition-all duration-300 group-hover:w-full"></span>
|
||||||
|
</a>
|
||||||
|
))}
|
||||||
|
|
||||||
|
{/* CTA Button */}
|
||||||
|
<a
|
||||||
|
href="/login"
|
||||||
|
className="min-w-[140px] bg-gradient-to-r from-luxury-gold to-brass text-deep-forest font-montserrat font-bold px-6 py-3 rounded-full hover:from-brass hover:to-bronze hover:scale-105 transition-all duration-300 shadow-luxury hover:shadow-xl focus:outline-none focus:ring-2 focus:ring-luxury-gold/50 border border-luxury-gold/30"
|
||||||
|
>
|
||||||
|
Get Started
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Mobile menu button */}
|
||||||
|
<div className="md:hidden">
|
||||||
|
<button
|
||||||
|
onClick={() => setIsMenuOpen(!isMenuOpen)}
|
||||||
|
className="relative w-10 h-10 bg-deep-forest/50 backdrop-blur-sm border border-luxury-gold/20 rounded-lg flex items-center justify-center hover:bg-luxury-gold/10 transition-colors duration-300 focus:outline-none focus:ring-2 focus:ring-luxury-gold/50"
|
||||||
|
aria-label="Toggle navigation menu"
|
||||||
|
aria-expanded={isMenuOpen}
|
||||||
|
>
|
||||||
|
<div className="w-6 h-6 relative">
|
||||||
|
<span
|
||||||
|
className={`absolute block w-full h-0.5 bg-luxury-gold rounded transition-transform duration-300 ${
|
||||||
|
isMenuOpen ? 'top-3 rotate-45' : 'top-1'
|
||||||
|
}`}
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
className={`absolute block w-full h-0.5 bg-luxury-gold rounded top-3 transition-opacity duration-300 ${
|
||||||
|
isMenuOpen ? 'opacity-0' : 'opacity-100'
|
||||||
|
}`}
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
className={`absolute block w-full h-0.5 bg-luxury-gold rounded transition-transform duration-300 ${
|
||||||
|
isMenuOpen ? 'top-3 -rotate-45' : 'top-5'
|
||||||
|
}`}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Mobile Navigation Menu */}
|
||||||
|
<div
|
||||||
|
className={`md:hidden transition-all duration-300 ${
|
||||||
|
isMenuOpen
|
||||||
|
? 'max-h-64 opacity-100 border-t border-luxury-gold/20 mt-4 pt-4'
|
||||||
|
: 'max-h-0 opacity-0 overflow-hidden'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<div className="bg-gradient-to-br from-deep-forest/95 to-rich-brown/85 backdrop-blur-xl rounded-2xl p-6 space-y-4 shadow-2xl border border-luxury-gold/20">
|
||||||
|
{navLinks.map((link, index) => (
|
||||||
|
<a
|
||||||
|
key={link.label}
|
||||||
|
href={link.href}
|
||||||
|
onClick={() => setIsMenuOpen(false)}
|
||||||
|
className={`block font-montserrat font-medium text-cream hover:text-luxury-gold transition-all duration-300 py-3 px-4 rounded-lg hover:bg-luxury-gold/10 border border-transparent hover:border-luxury-gold/30 animate-fadeInUp`}
|
||||||
|
style={{ animationDelay: `${index * 100}ms` }}
|
||||||
|
>
|
||||||
|
{link.label}
|
||||||
|
</a>
|
||||||
|
))}
|
||||||
|
|
||||||
|
<a
|
||||||
|
href="/login"
|
||||||
|
className="block w-full mt-4 bg-gradient-to-r from-luxury-gold to-brass text-deep-forest font-montserrat font-bold px-6 py-3 rounded-full hover:from-brass hover:to-bronze transition-all duration-300 shadow-luxury hover:shadow-xl focus:outline-none focus:ring-2 focus:ring-luxury-gold/50 border border-luxury-gold/30 text-center"
|
||||||
|
onClick={() => setIsMenuOpen(false)}
|
||||||
|
>
|
||||||
|
Get Started
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Header;
|
||||||
145
src/components/HeroSection.tsx
Normal file
145
src/components/HeroSection.tsx
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
|
||||||
|
const HeroSection: React.FC = () => {
|
||||||
|
const [isVisible, setIsVisible] = useState(false);
|
||||||
|
const [activeUsers, setActiveUsers] = useState(2947);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setIsVisible(true);
|
||||||
|
|
||||||
|
// Simulate live counter updates
|
||||||
|
const interval = setInterval(() => {
|
||||||
|
setActiveUsers(prev => prev + Math.floor(Math.random() * 3));
|
||||||
|
}, 3000);
|
||||||
|
|
||||||
|
return () => clearInterval(interval);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const stats = [
|
||||||
|
{ label: 'Active Agents', value: '50', suffix: '+' },
|
||||||
|
{ label: 'Business Solutions', value: '12', suffix: '+' },
|
||||||
|
{ label: 'Success Rate', value: '99.8', suffix: '%' },
|
||||||
|
{ label: 'Companies Served', value: '500', suffix: '+' }
|
||||||
|
];
|
||||||
|
|
||||||
|
const scrollToNext = () => {
|
||||||
|
const nextSection = document.getElementById('features');
|
||||||
|
nextSection?.scrollIntoView({ behavior: 'smooth' });
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section
|
||||||
|
id="home"
|
||||||
|
className="relative min-h-screen flex items-center justify-center overflow-hidden bg-luxury-texture bg-cover bg-fixed bg-center"
|
||||||
|
>
|
||||||
|
{/* Background Overlays */}
|
||||||
|
<div className="absolute inset-0 bg-gradient-to-br from-deep-forest/60 via-deep-forest/40 to-rich-brown/30"></div>
|
||||||
|
|
||||||
|
{/* Animated Background Elements */}
|
||||||
|
<div className="absolute top-20 left-10 w-64 h-64 bg-luxury-gold/10 rounded-full blur-3xl animate-float"></div>
|
||||||
|
<div className="absolute bottom-32 right-16 w-96 h-96 bg-brass/10 rounded-full blur-3xl animate-float" style={{ animationDelay: '2s' }}></div>
|
||||||
|
<div className="absolute top-1/2 left-1/3 w-48 h-48 bg-bronze/10 rounded-full blur-3xl animate-float" style={{ animationDelay: '4s' }}></div>
|
||||||
|
|
||||||
|
<div className="relative z-10 max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
|
||||||
|
{/* Main Hero Content */}
|
||||||
|
<div className={`transition-all duration-1000 ${isVisible ? 'animate-fadeInUp' : 'opacity-0'}`}>
|
||||||
|
<div className="mb-8">
|
||||||
|
<span className="inline-block px-6 py-3 bg-gradient-to-r from-luxury-gold/30 to-brass/30 border border-luxury-gold/50 rounded-full text-luxury-gold font-montserrat font-semibold text-base backdrop-blur-sm shadow-luxury">
|
||||||
|
🚀 Pennyzo Web - Next-Gen Business Solutions
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h1 className="font-playfair text-6xl sm:text-7xl lg:text-8xl xl:text-9xl font-bold text-cream tracking-tight mb-8 leading-[0.95]">
|
||||||
|
<span className="block">Multiagent Mastery</span>
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
<p className="font-montserrat text-xl sm:text-2xl lg:text-3xl text-cream/90 max-w-5xl mx-auto mb-12 leading-relaxed font-medium">
|
||||||
|
Harness the power of specialized AI agents to transform your business
|
||||||
|
operations. From HR management to financial analytics - unlock
|
||||||
|
unprecedented efficiency and growth.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{/* CTA Buttons */}
|
||||||
|
<div className="flex flex-col sm:flex-row gap-6 justify-center items-center mb-16">
|
||||||
|
<button className="min-w-[240px] bg-gradient-to-r from-luxury-gold to-brass text-deep-forest font-montserrat font-bold px-10 py-5 rounded-full text-lg hover:scale-105 hover:shadow-luxury-lg transition-all duration-300 focus:outline-none focus:ring-2 focus:ring-luxury-gold/50 shadow-luxury">
|
||||||
|
Explore AI Agents
|
||||||
|
</button>
|
||||||
|
<button className="min-w-[240px] border-2 border-luxury-gold/60 text-luxury-gold font-montserrat font-bold px-10 py-5 rounded-full text-lg hover:bg-luxury-gold/20 hover:border-luxury-gold hover:scale-105 transition-all duration-300 backdrop-blur-sm focus:outline-none focus:ring-2 focus:ring-luxury-gold/50 shadow-luxury-inner">
|
||||||
|
Watch Demo
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Stats Grid */}
|
||||||
|
<div className="grid grid-cols-2 lg:grid-cols-4 gap-8 max-w-6xl mx-auto mb-16">
|
||||||
|
{stats.map((stat, index) => (
|
||||||
|
<div
|
||||||
|
key={stat.label}
|
||||||
|
className={`bg-gradient-to-br from-deep-forest/60 to-rich-brown/40 backdrop-blur-2xl border-2 border-luxury-gold/30 rounded-3xl p-8 hover:scale-105 hover:border-luxury-gold/50 transition-all duration-300 animate-fadeInUp shadow-luxury`}
|
||||||
|
style={{ animationDelay: `${index * 200}ms` }}
|
||||||
|
>
|
||||||
|
<div className="text-3xl sm:text-4xl font-playfair font-bold text-luxury-gold mb-3">
|
||||||
|
{stat.value}{stat.suffix}
|
||||||
|
</div>
|
||||||
|
<div className="text-base font-montserrat font-medium text-cream/90">
|
||||||
|
{stat.label}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Trust Indicators */}
|
||||||
|
<div className="flex flex-wrap justify-center items-center gap-8 mb-16">
|
||||||
|
<div className="flex items-center space-x-2 text-cream/60">
|
||||||
|
<svg className="w-5 h-5 text-luxury-gold" fill="currentColor" viewBox="0 0 20 20">
|
||||||
|
<path fillRule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clipRule="evenodd" />
|
||||||
|
</svg>
|
||||||
|
<span className="font-montserrat text-sm">Enterprise Security</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center space-x-2 text-cream/60">
|
||||||
|
<svg className="w-5 h-5 text-luxury-gold" fill="currentColor" viewBox="0 0 20 20">
|
||||||
|
<path fillRule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clipRule="evenodd" />
|
||||||
|
</svg>
|
||||||
|
<span className="font-montserrat text-sm">24/7 Premium Support</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center space-x-2 text-cream/60">
|
||||||
|
<svg className="w-5 h-5 text-luxury-gold" fill="currentColor" viewBox="0 0 20 20">
|
||||||
|
<path fillRule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clipRule="evenodd" />
|
||||||
|
</svg>
|
||||||
|
<span className="font-montserrat text-sm">Satisfaction Guaranteed</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Scroll Indicator */}
|
||||||
|
<div className="absolute bottom-8 left-1/2 transform -translate-x-1/2 animate-bounce">
|
||||||
|
<button
|
||||||
|
onClick={scrollToNext}
|
||||||
|
className="flex flex-col items-center space-y-2 text-luxury-gold/70 hover:text-luxury-gold transition-colors duration-300 focus:outline-none"
|
||||||
|
aria-label="Scroll to features section"
|
||||||
|
>
|
||||||
|
<span className="font-montserrat text-sm">Discover More</span>
|
||||||
|
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 14l-7 7m0 0l-7-7m7 7V3" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Live Status Indicator */}
|
||||||
|
<div className="absolute top-24 right-4 sm:right-8 bg-gradient-to-br from-deep-forest/80 to-rich-brown/60 backdrop-blur-xl border border-luxury-gold/20 rounded-2xl p-4 animate-fadeInRight">
|
||||||
|
<div className="flex items-center space-x-3">
|
||||||
|
<div className="relative">
|
||||||
|
<div className="w-3 h-3 bg-green-400 rounded-full animate-pulse"></div>
|
||||||
|
<div className="absolute inset-0 w-3 h-3 bg-green-400 rounded-full animate-ping opacity-75"></div>
|
||||||
|
</div>
|
||||||
|
<div className="text-sm">
|
||||||
|
<div className="font-montserrat font-semibold text-cream">Live Now</div>
|
||||||
|
<div className="font-montserrat text-cream/70">{activeUsers.toLocaleString()} active</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default HeroSection;
|
||||||
176
src/components/LiveCounter.tsx
Normal file
176
src/components/LiveCounter.tsx
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
import React, { useState, useEffect } from 'react';
|
||||||
|
|
||||||
|
interface LiveCounterProps {
|
||||||
|
initialUsers?: number;
|
||||||
|
initialRevenue?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const LiveCounter: React.FC<LiveCounterProps> = ({
|
||||||
|
initialUsers = 2947,
|
||||||
|
initialRevenue = 157523
|
||||||
|
}) => {
|
||||||
|
const [isVisible, setIsVisible] = useState(false);
|
||||||
|
const [users, setUsers] = useState(initialUsers);
|
||||||
|
const [revenue, setRevenue] = useState(initialRevenue);
|
||||||
|
const [isExpanded, setIsExpanded] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Show widget after a delay
|
||||||
|
const timer = setTimeout(() => setIsVisible(true), 2000);
|
||||||
|
|
||||||
|
// Update counters periodically
|
||||||
|
const interval = setInterval(() => {
|
||||||
|
setUsers(prev => prev + Math.floor(Math.random() * 3) + 1);
|
||||||
|
setRevenue(prev => prev + Math.floor(Math.random() * 100) + 25);
|
||||||
|
}, 4000);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
clearTimeout(timer);
|
||||||
|
clearInterval(interval);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const formatNumber = (num: number) => {
|
||||||
|
if (num >= 1000000) {
|
||||||
|
return (num / 1000000).toFixed(1) + 'M';
|
||||||
|
}
|
||||||
|
if (num >= 1000) {
|
||||||
|
return (num / 1000).toFixed(1) + 'K';
|
||||||
|
}
|
||||||
|
return num.toString();
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!isVisible) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={`fixed bottom-6 left-6 z-40 transition-all duration-500 transform ${
|
||||||
|
isVisible ? 'translate-y-0 opacity-100' : 'translate-y-12 opacity-0'
|
||||||
|
}`}>
|
||||||
|
{/* Main Widget */}
|
||||||
|
<div className={`bg-gradient-to-br from-deep-forest/95 to-rich-brown/90 backdrop-blur-xl border-2 border-luxury-gold/40 rounded-2xl shadow-luxury-lg transition-all duration-500 ${
|
||||||
|
isExpanded ? 'w-80 sm:w-96' : 'w-48 h-16'
|
||||||
|
}`}>
|
||||||
|
|
||||||
|
{!isExpanded ? (
|
||||||
|
/* Collapsed State */
|
||||||
|
<button
|
||||||
|
onClick={() => setIsExpanded(true)}
|
||||||
|
className="w-full h-full flex items-center justify-between px-4 text-luxury-gold hover:text-cream transition-colors duration-300 focus:outline-none focus:ring-2 focus:ring-luxury-gold/50 rounded-2xl group"
|
||||||
|
aria-label="Expand live stats"
|
||||||
|
>
|
||||||
|
<div className="flex items-center space-x-3">
|
||||||
|
<div className="relative">
|
||||||
|
<div className="w-3 h-3 bg-green-400 rounded-full animate-pulse"></div>
|
||||||
|
<div className="absolute inset-0 w-3 h-3 bg-green-400 rounded-full animate-ping opacity-75"></div>
|
||||||
|
</div>
|
||||||
|
<span className="font-playfair font-semibold text-cream text-sm">
|
||||||
|
Live Activity
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="font-montserrat font-bold text-luxury-gold text-lg">
|
||||||
|
{formatNumber(users)}
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
) : (
|
||||||
|
/* Expanded State */
|
||||||
|
<div className="p-6">
|
||||||
|
{/* Header */}
|
||||||
|
<div className="flex items-center justify-between mb-6">
|
||||||
|
<div className="flex items-center space-x-3">
|
||||||
|
<div className="relative">
|
||||||
|
<div className="w-3 h-3 bg-green-400 rounded-full animate-pulse"></div>
|
||||||
|
<div className="absolute inset-0 w-3 h-3 bg-green-400 rounded-full animate-ping opacity-75"></div>
|
||||||
|
</div>
|
||||||
|
<span className="font-playfair font-semibold text-cream text-lg">
|
||||||
|
Live Activity
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Stats */}
|
||||||
|
<div className="space-y-4">
|
||||||
|
{/* Active Users */}
|
||||||
|
<div className="flex items-center justify-between bg-gradient-to-r from-luxury-gold/10 to-transparent rounded-xl p-3">
|
||||||
|
<div className="flex items-center space-x-3">
|
||||||
|
<div className="w-10 h-10 bg-gradient-to-br from-luxury-gold/30 to-brass/30 rounded-xl flex items-center justify-center">
|
||||||
|
<svg className="w-5 h-5 text-luxury-gold" fill="currentColor" viewBox="0 0 20 20">
|
||||||
|
<path d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<span className="font-montserrat font-semibold text-cream text-sm">
|
||||||
|
Active Users
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="font-playfair font-bold text-luxury-gold text-xl">
|
||||||
|
{formatNumber(users)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Revenue */}
|
||||||
|
<div className="flex items-center justify-between bg-gradient-to-r from-bronze/10 to-transparent rounded-xl p-3">
|
||||||
|
<div className="flex items-center space-x-3">
|
||||||
|
<div className="w-10 h-10 bg-gradient-to-br from-bronze/30 to-luxury-gold/30 rounded-xl flex items-center justify-center">
|
||||||
|
<svg className="w-5 h-5 text-bronze" fill="currentColor" viewBox="0 0 20 20">
|
||||||
|
<path fillRule="evenodd" d="M4 4a2 2 0 00-2 2v4a2 2 0 002 2V6h10a2 2 0 00-2-2H4zm2 6a2 2 0 012-2h8a2 2 0 012 2v4a2 2 0 01-2 2H8a2 2 0 01-2-2v-4zm6 4a2 2 0 100-4 2 2 0 000 4z" clipRule="evenodd" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<span className="font-montserrat font-semibold text-cream text-sm">
|
||||||
|
Revenue Today
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="font-playfair font-bold text-luxury-gold text-xl">
|
||||||
|
${formatNumber(revenue)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Progress Bar */}
|
||||||
|
<div className="pt-2">
|
||||||
|
<div className="flex justify-between items-center mb-3">
|
||||||
|
<span className="font-montserrat font-medium text-cream/80 text-sm">
|
||||||
|
Daily Goal Progress
|
||||||
|
</span>
|
||||||
|
<span className="font-playfair text-luxury-gold text-sm font-bold">
|
||||||
|
87%
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="w-full bg-deep-forest/60 rounded-full h-3 border border-luxury-gold/20">
|
||||||
|
<div
|
||||||
|
className="bg-gradient-to-r from-luxury-gold via-brass to-bronze h-3 rounded-full relative overflow-hidden shadow-luxury-inner"
|
||||||
|
style={{ width: '87%' }}
|
||||||
|
>
|
||||||
|
<div className="absolute inset-0 bg-gradient-to-r from-transparent via-white/20 to-transparent animate-shimmer"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Quick Actions */}
|
||||||
|
<div className="flex space-x-2 mt-6 pt-4 border-t border-luxury-gold/30">
|
||||||
|
<button className="flex-1 bg-luxury-gold/20 border border-luxury-gold/40 text-luxury-gold font-montserrat font-semibold px-4 py-3 rounded-xl text-sm hover:bg-luxury-gold/30 hover:scale-105 transition-all duration-300 focus:outline-none focus:ring-2 focus:ring-luxury-gold/50">
|
||||||
|
View Details
|
||||||
|
</button>
|
||||||
|
<button className="flex-1 bg-deep-forest/80 border border-cream/30 text-cream/90 font-montserrat font-semibold px-4 py-3 rounded-xl text-sm hover:bg-cream/10 hover:text-cream hover:scale-105 transition-all duration-300 focus:outline-none focus:ring-2 focus:ring-cream/20">
|
||||||
|
Export Data
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Corner Close Button (replaces old red badge) */}
|
||||||
|
{isExpanded && (
|
||||||
|
<button
|
||||||
|
onClick={() => setIsExpanded(false)}
|
||||||
|
aria-label="Close live stats"
|
||||||
|
className="absolute -top-3 -right-3 w-8 h-8 bg-red-500 hover:bg-red-600 text-white rounded-full flex items-center justify-center shadow-lg transition-transform duration-200 hover:scale-110 focus:outline-none focus:ring-2 focus:ring-red-400/50"
|
||||||
|
>
|
||||||
|
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default LiveCounter;
|
||||||
173
src/index.css
Normal file
173
src/index.css
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
@tailwind base;
|
||||||
|
@tailwind components;
|
||||||
|
@tailwind utilities;
|
||||||
|
|
||||||
|
/* Base styles */
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Gradient text utility (cross-browser) */
|
||||||
|
.text-gradient {
|
||||||
|
background-clip: text;
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
color: transparent;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
scroll-behavior: smooth;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: 'Montserrat', sans-serif;
|
||||||
|
background-color: #072C21;
|
||||||
|
color: #F5F2E9;
|
||||||
|
line-height: 1.6;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Typography */
|
||||||
|
h1, h2, h3, h4, h5, h6 {
|
||||||
|
font-family: 'Playfair Display', serif;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1.2;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Custom scrollbar */
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
width: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-track {
|
||||||
|
background: #072C21;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb {
|
||||||
|
background: #C59D59;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: #D4AF37;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Custom animations */
|
||||||
|
@keyframes fadeInUp {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(30px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeInLeft {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateX(-30px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeInRight {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateX(30px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes shimmer {
|
||||||
|
0% {
|
||||||
|
background-position: -200px 0;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
background-position: calc(200px + 100%) 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Utility classes */
|
||||||
|
.animate-fadeInUp {
|
||||||
|
animation: fadeInUp 0.8s ease-out forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
.animate-fadeInLeft {
|
||||||
|
animation: fadeInLeft 0.8s ease-out forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
.animate-fadeInRight {
|
||||||
|
animation: fadeInRight 0.8s ease-out forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
.animate-shimmer {
|
||||||
|
animation: shimmer 2s infinite linear;
|
||||||
|
background: linear-gradient(to right, transparent 0%, rgba(197, 157, 89, 0.4) 50%, transparent 100%);
|
||||||
|
background-size: 200px 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Focus styles for accessibility */
|
||||||
|
.focus-visible:focus {
|
||||||
|
outline: 2px solid #C59D59;
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Selection styling */
|
||||||
|
::selection {
|
||||||
|
background-color: rgba(197, 157, 89, 0.3);
|
||||||
|
color: #F5F2E9;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Backdrop blur fix for Firefox */
|
||||||
|
@supports not (backdrop-filter: blur(10px)) {
|
||||||
|
.backdrop-blur-sm {
|
||||||
|
background-color: rgba(7, 44, 33, 0.8);
|
||||||
|
}
|
||||||
|
.backdrop-blur-md {
|
||||||
|
background-color: rgba(7, 44, 33, 0.85);
|
||||||
|
}
|
||||||
|
.backdrop-blur-lg {
|
||||||
|
background-color: rgba(7, 44, 33, 0.9);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Loading state */
|
||||||
|
.loading {
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
background: linear-gradient(90deg, transparent, rgba(197, 157, 89, 0.4), transparent);
|
||||||
|
transform: translateX(-100%);
|
||||||
|
animation: loading 1.5s infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes loading {
|
||||||
|
0% {
|
||||||
|
transform: translateX(-100%);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: translateX(100%);
|
||||||
|
}
|
||||||
|
}
|
||||||
10
src/main.tsx
Normal file
10
src/main.tsx
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import { StrictMode } from 'react'
|
||||||
|
import { createRoot } from 'react-dom/client'
|
||||||
|
import './index.css'
|
||||||
|
import App from './App.tsx'
|
||||||
|
|
||||||
|
createRoot(document.getElementById('root')!).render(
|
||||||
|
<StrictMode>
|
||||||
|
<App />
|
||||||
|
</StrictMode>,
|
||||||
|
)
|
||||||
264
src/pages/ForgotPasswordPage.tsx
Normal file
264
src/pages/ForgotPasswordPage.tsx
Normal file
@@ -0,0 +1,264 @@
|
|||||||
|
import React, { useState, useEffect } from 'react';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
|
const ForgotPasswordPage: React.FC = () => {
|
||||||
|
const [email, setEmail] = useState('');
|
||||||
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
const [isSuccess, setIsSuccess] = useState(false);
|
||||||
|
const [magicEffect, setMagicEffect] = useState(0);
|
||||||
|
|
||||||
|
// Animate magic effects
|
||||||
|
useEffect(() => {
|
||||||
|
const interval = setInterval(() => {
|
||||||
|
setMagicEffect(prev => (prev + 1) % 8);
|
||||||
|
}, 600);
|
||||||
|
return () => clearInterval(interval);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleResetPassword = (e: React.FormEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
setIsLoading(true);
|
||||||
|
setTimeout(() => {
|
||||||
|
setIsLoading(false);
|
||||||
|
setIsSuccess(true);
|
||||||
|
}, 3000);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="min-h-screen flex items-center justify-center px-4 relative overflow-hidden">
|
||||||
|
{/* Mystical Background */}
|
||||||
|
<div className="fixed inset-0 opacity-15">
|
||||||
|
<div className="absolute inset-0" style={{
|
||||||
|
backgroundImage: `
|
||||||
|
radial-gradient(circle at 25% 25%, rgba(197, 157, 89, 0.2) 0%, transparent 50%),
|
||||||
|
radial-gradient(circle at 75% 75%, rgba(205, 127, 50, 0.2) 0%, transparent 50%),
|
||||||
|
radial-gradient(circle at 50% 50%, rgba(212, 175, 55, 0.1) 0%, transparent 70%)
|
||||||
|
`
|
||||||
|
}}></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Floating Magic Particles */}
|
||||||
|
<div className="fixed inset-0 pointer-events-none">
|
||||||
|
{[...Array(20)].map((_, i) => (
|
||||||
|
<div
|
||||||
|
key={i}
|
||||||
|
className="absolute animate-bounce"
|
||||||
|
style={{
|
||||||
|
left: `${Math.random() * 100}%`,
|
||||||
|
top: `${Math.random() * 100}%`,
|
||||||
|
animationDelay: `${Math.random() * 4}s`,
|
||||||
|
animationDuration: `${3 + Math.random() * 2}s`
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className="w-2 h-2 bg-luxury-gold rounded-full opacity-60"></div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="max-w-6xl w-full grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||||
|
{/* Wizard Character Side */}
|
||||||
|
<div className="flex flex-col items-center space-y-8 order-2 lg:order-1">
|
||||||
|
{/* Animated Wizard */}
|
||||||
|
<div className="relative">
|
||||||
|
<div className="w-80 h-80 bg-gradient-to-br from-deep-forest/60 to-rich-brown/40 rounded-3xl border-4 border-luxury-gold/30 backdrop-blur-xl flex items-center justify-center relative overflow-hidden">
|
||||||
|
{/* Wizard Container */}
|
||||||
|
<div className="relative w-64 h-64">
|
||||||
|
{/* Wizard Base */}
|
||||||
|
<div className={`absolute inset-0 transition-all duration-300 ${magicEffect % 2 === 0 ? 'scale-100' : 'scale-105'}`}>
|
||||||
|
{/* Robes */}
|
||||||
|
<div className="absolute bottom-4 left-1/2 transform -translate-x-1/2 w-28 h-36 bg-gradient-to-b from-bronze to-deep-forest rounded-t-full border-2 border-luxury-gold/50"></div>
|
||||||
|
|
||||||
|
{/* Head */}
|
||||||
|
<div className="absolute bottom-32 left-1/2 transform -translate-x-1/2 w-16 h-16 bg-gradient-to-b from-champagne to-pearl rounded-full border-2 border-luxury-gold/50"></div>
|
||||||
|
|
||||||
|
{/* Wizard Hat */}
|
||||||
|
<div className="absolute bottom-40 left-1/2 transform -translate-x-1/2 w-18 h-16 bg-gradient-to-b from-deep-forest to-rich-brown rounded-t-full border-2 border-luxury-gold/50 relative">
|
||||||
|
<div className="absolute top-2 left-1/2 transform -translate-x-1/2 w-8 h-2 bg-luxury-gold rounded-full"></div>
|
||||||
|
{/* Hat tip */}
|
||||||
|
<div className="absolute -top-8 left-1/2 transform -translate-x-1/2 w-6 h-8 bg-gradient-to-t from-deep-forest to-rich-brown rounded-t-full border border-luxury-gold/30"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Glowing Eyes */}
|
||||||
|
<div className="absolute bottom-36 left-1/2 transform -translate-x-1/2">
|
||||||
|
<div className={`w-3 h-3 bg-luxury-gold rounded-full absolute -left-2 transition-all duration-500 ${magicEffect % 4 === 0 ? 'animate-pulse shadow-lg shadow-luxury-gold' : ''}`}></div>
|
||||||
|
<div className={`w-3 h-3 bg-luxury-gold rounded-full absolute left-2 transition-all duration-500 ${magicEffect % 4 === 0 ? 'animate-pulse shadow-lg shadow-luxury-gold' : ''}`}></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Arms with Staff */}
|
||||||
|
<div className="absolute bottom-16 left-4 w-6 h-20 bg-gradient-to-b from-rich-brown to-deep-forest rounded-full border border-luxury-gold/30"></div>
|
||||||
|
<div className={`absolute bottom-16 right-2 w-6 h-20 bg-gradient-to-b from-rich-brown to-deep-forest rounded-full border border-luxury-gold/30 transform transition-transform duration-300 ${magicEffect % 2 === 0 ? 'rotate-12' : '-rotate-6'}`}></div>
|
||||||
|
|
||||||
|
{/* Magic Staff */}
|
||||||
|
<div className={`absolute bottom-8 right-0 w-2 h-32 bg-gradient-to-b from-bronze to-rich-brown transform transition-all duration-300 ${magicEffect % 2 === 0 ? 'rotate-12 scale-110' : '-rotate-6'}`}>
|
||||||
|
{/* Staff Crystal */}
|
||||||
|
<div className={`absolute -top-4 left-1/2 transform -translate-x-1/2 w-6 h-6 bg-luxury-gold rounded-full transition-all duration-300 ${magicEffect % 4 === 0 ? 'animate-pulse scale-125 shadow-lg shadow-luxury-gold' : ''}`}></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Beard */}
|
||||||
|
<div className="absolute bottom-28 left-1/2 transform -translate-x-1/2 w-12 h-8 bg-gradient-to-b from-platinum to-cream rounded-b-full border border-luxury-gold/30"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Magic Sparkles */}
|
||||||
|
{magicEffect % 3 === 0 && (
|
||||||
|
<div className="absolute inset-0">
|
||||||
|
{[...Array(8)].map((_, i) => (
|
||||||
|
<div
|
||||||
|
key={i}
|
||||||
|
className="absolute w-1 h-1 bg-luxury-gold rounded-full animate-ping"
|
||||||
|
style={{
|
||||||
|
left: `${20 + Math.random() * 60}%`,
|
||||||
|
top: `${20 + Math.random() * 60}%`,
|
||||||
|
animationDelay: `${i * 0.2}s`
|
||||||
|
}}
|
||||||
|
></div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Magic Aura */}
|
||||||
|
<div className={`absolute inset-0 bg-gradient-to-r from-luxury-gold/20 to-bronze/20 rounded-3xl transition-opacity duration-500 ${magicEffect % 4 === 0 ? 'opacity-100 animate-pulse' : 'opacity-40'}`}></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Wizard Speech Bubble */}
|
||||||
|
<div className="bg-gradient-to-br from-deep-forest/80 to-rich-brown/60 backdrop-blur-xl rounded-2xl p-6 border-2 border-luxury-gold/30 relative max-w-sm">
|
||||||
|
<div className="absolute -top-2 left-8 w-4 h-4 bg-gradient-to-br from-deep-forest/80 to-rich-brown/60 rotate-45 border-t-2 border-l-2 border-luxury-gold/30"></div>
|
||||||
|
<p className="font-montserrat text-cream text-center italic">
|
||||||
|
{isSuccess
|
||||||
|
? "✨ The spell has been cast! Check your email for the magic recovery link!"
|
||||||
|
: "🔮 Fear not, traveler! I shall help you recover your lost credentials with ancient magic!"
|
||||||
|
}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Reset Password Form Side */}
|
||||||
|
<div className="order-1 lg:order-2">
|
||||||
|
<div className="bg-gradient-to-br from-deep-forest/60 to-rich-brown/40 backdrop-blur-2xl rounded-3xl border-2 border-luxury-gold/30 p-8 shadow-luxury-xl">
|
||||||
|
{/* Header */}
|
||||||
|
<div className="text-center mb-8">
|
||||||
|
<div className="flex items-center justify-center space-x-3 mb-4">
|
||||||
|
<div className="w-12 h-12 bg-gradient-to-br from-luxury-gold to-bronze rounded-xl flex items-center justify-center">
|
||||||
|
<span className="font-playfair text-2xl font-bold text-deep-forest">🔮</span>
|
||||||
|
</div>
|
||||||
|
<h1 className="font-playfair text-4xl font-bold text-cream">Password Recovery</h1>
|
||||||
|
</div>
|
||||||
|
<p className="font-montserrat text-cream/80 text-lg">
|
||||||
|
Pennyzo Web - Multiagent Business Solutions
|
||||||
|
</p>
|
||||||
|
<div className="mt-4 inline-block px-4 py-2 bg-gradient-to-r from-luxury-gold/20 to-brass/20 rounded-full border border-luxury-gold/30">
|
||||||
|
<span className="font-montserrat text-luxury-gold text-sm font-medium">Recovery Mode</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{!isSuccess ? (
|
||||||
|
<>
|
||||||
|
{/* Reset Form */}
|
||||||
|
<form onSubmit={handleResetPassword} className="space-y-6">
|
||||||
|
<div>
|
||||||
|
<label className="block font-montserrat text-cream font-medium mb-2">
|
||||||
|
🎯 Enter Your Email Address
|
||||||
|
</label>
|
||||||
|
<p className="font-montserrat text-cream/60 text-sm mb-4">
|
||||||
|
We'll send you a password reset link to restore your account access.
|
||||||
|
</p>
|
||||||
|
<input
|
||||||
|
type="email"
|
||||||
|
value={email}
|
||||||
|
onChange={(e) => setEmail(e.target.value)}
|
||||||
|
className="w-full px-4 py-3 bg-deep-forest/60 border-2 border-luxury-gold/30 rounded-xl text-cream placeholder-cream/50 focus:border-luxury-gold focus:outline-none focus:ring-2 focus:ring-luxury-gold/20 transition-all duration-300"
|
||||||
|
placeholder="Enter your email address"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Action Button */}
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
disabled={isLoading}
|
||||||
|
className="w-full bg-gradient-to-r from-luxury-gold to-brass text-deep-forest font-montserrat font-bold py-4 rounded-xl hover:scale-105 hover:shadow-luxury-lg transition-all duration-300 focus:outline-none focus:ring-2 focus:ring-luxury-gold/50 disabled:opacity-50 disabled:cursor-not-allowed"
|
||||||
|
>
|
||||||
|
{isLoading ? (
|
||||||
|
<div className="flex items-center justify-center space-x-2">
|
||||||
|
<div className="w-5 h-5 border-2 border-deep-forest border-t-transparent rounded-full animate-spin"></div>
|
||||||
|
<span>Sending reset link...</span>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
'Send Reset Link'
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{/* Back to Login */}
|
||||||
|
<div className="mt-8 text-center">
|
||||||
|
<Link
|
||||||
|
to="/login"
|
||||||
|
className="inline-flex items-center space-x-2 font-montserrat text-luxury-gold hover:text-brass transition-colors duration-300"
|
||||||
|
>
|
||||||
|
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 19l-7-7m0 0l7-7m0 7h18" />
|
||||||
|
</svg>
|
||||||
|
<span>⚔️ Return to Login Portal</span>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
/* Success State */
|
||||||
|
<div className="text-center space-y-6">
|
||||||
|
<div className="w-20 h-20 bg-gradient-to-br from-luxury-gold to-brass rounded-full flex items-center justify-center mx-auto mb-6 animate-pulse">
|
||||||
|
<svg className="w-10 h-10 text-deep-forest" fill="currentColor" viewBox="0 0 20 20">
|
||||||
|
<path fillRule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clipRule="evenodd" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h2 className="font-playfair text-2xl font-bold text-cream mb-4">
|
||||||
|
✅ Request Successful
|
||||||
|
</h2>
|
||||||
|
<p className="font-montserrat text-cream/80 leading-relaxed mb-6">
|
||||||
|
We've sent a password reset link to <span className="text-luxury-gold font-semibold">{email}</span>.
|
||||||
|
Check your inbox and follow the instructions to restore your account.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="bg-gradient-to-r from-luxury-gold/10 to-bronze/10 rounded-xl p-4 border border-luxury-gold/20">
|
||||||
|
<p className="font-montserrat text-sm text-cream/80">
|
||||||
|
💡 <strong>Tip:</strong> If you don't see the email, check your spam folder or try again in a few minutes.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Link
|
||||||
|
to="/login"
|
||||||
|
className="inline-block w-full bg-gradient-to-r from-luxury-gold to-brass text-deep-forest font-montserrat font-bold py-4 rounded-xl hover:scale-105 hover:shadow-luxury-lg transition-all duration-300 focus:outline-none focus:ring-2 focus:ring-luxury-gold/50"
|
||||||
|
>
|
||||||
|
⚡ Return to Login Portal
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Help Section */}
|
||||||
|
{!isSuccess && (
|
||||||
|
<div className="mt-8 bg-gradient-to-r from-luxury-gold/10 to-bronze/10 rounded-xl p-4 border border-luxury-gold/20">
|
||||||
|
<h3 className="font-montserrat font-semibold text-luxury-gold mb-2">🆘 Need More Help?</h3>
|
||||||
|
<div className="font-montserrat text-sm text-cream/80 space-y-1">
|
||||||
|
<p>• Make sure you entered the correct email address</p>
|
||||||
|
<p>• Check if you have an account with Pennyzo Web</p>
|
||||||
|
<p>• Contact our support team if issues persist</p>
|
||||||
|
</div>
|
||||||
|
<Link
|
||||||
|
to="/home"
|
||||||
|
className="inline-block mt-3 text-luxury-gold hover:text-brass text-sm underline transition-colors duration-300"
|
||||||
|
>
|
||||||
|
🏠 Return to Pennyzo Web Homepage
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ForgotPasswordPage;
|
||||||
265
src/pages/LandingPage.tsx
Normal file
265
src/pages/LandingPage.tsx
Normal file
@@ -0,0 +1,265 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
import Header from '../components/Header';
|
||||||
|
import Footer from '../components/Footer';
|
||||||
|
import LiveCounter from '../components/LiveCounter';
|
||||||
|
|
||||||
|
const LandingPage: React.FC = () => {
|
||||||
|
const agents = [
|
||||||
|
{
|
||||||
|
id: 'hr',
|
||||||
|
name: 'HR Command',
|
||||||
|
icon: '👥',
|
||||||
|
description: 'Intelligent Human Resources management with automated recruitment, performance tracking, and employee analytics.',
|
||||||
|
features: ['Smart Recruitment', 'Performance Analytics', 'Payroll Automation', 'Employee Engagement'],
|
||||||
|
color: 'from-luxury-gold to-brass'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'finance',
|
||||||
|
name: 'Finance Sage',
|
||||||
|
icon: '💰',
|
||||||
|
description: 'Advanced financial management with real-time reporting, budget optimization, and predictive analytics.',
|
||||||
|
features: ['Real-time Reports', 'Budget Planning', 'Risk Analysis', 'Automated Invoicing'],
|
||||||
|
color: 'from-bronze to-luxury-gold'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'project',
|
||||||
|
name: 'Project Sensei',
|
||||||
|
icon: '📊',
|
||||||
|
description: 'Comprehensive project management with intelligent task allocation and deadline optimization.',
|
||||||
|
features: ['Smart Planning', 'Resource Allocation', 'Timeline Optimization', 'Team Collaboration'],
|
||||||
|
color: 'from-brass to-bronze'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'crm',
|
||||||
|
name: 'CRM Ninja',
|
||||||
|
icon: '🤝',
|
||||||
|
description: 'Customer relationship mastery with automated lead scoring and personalized engagement strategies.',
|
||||||
|
features: ['Lead Scoring', 'Sales Pipeline', 'Customer Analytics', 'Automated Outreach'],
|
||||||
|
color: 'from-luxury-gold to-champagne'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'ops',
|
||||||
|
name: 'Operations Dojo',
|
||||||
|
icon: '⚙️',
|
||||||
|
description: 'Operational excellence through intelligent workflow automation and process optimization.',
|
||||||
|
features: ['Workflow Automation', 'Process Mining', 'Quality Control', 'Supply Chain'],
|
||||||
|
color: 'from-bronze to-rich-brown'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'analytics',
|
||||||
|
name: 'Analytics Oracle',
|
||||||
|
icon: '📈',
|
||||||
|
description: 'Business intelligence powered by AI-driven insights and predictive modeling capabilities.',
|
||||||
|
features: ['Predictive Models', 'Data Visualization', 'Custom Dashboards', 'Trend Analysis'],
|
||||||
|
color: 'from-brass to-luxury-gold'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const stats = [
|
||||||
|
{ value: '500K+', label: 'Active Users' },
|
||||||
|
{ value: '2.5M+', label: 'Tasks Automated' },
|
||||||
|
{ value: '150+', label: 'Countries' },
|
||||||
|
{ value: '99.9%', label: 'Uptime' }
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Header />
|
||||||
|
|
||||||
|
{/* Hero Section */}
|
||||||
|
<section className="relative min-h-screen flex items-center justify-center pt-20 overflow-hidden">
|
||||||
|
<div className="relative z-10 max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
|
||||||
|
<div className="mb-8">
|
||||||
|
<div className="inline-block px-8 py-3 bg-gradient-to-r from-luxury-gold/20 to-brass/20 border-2 border-luxury-gold/30 rounded-full text-luxury-gold font-montserrat font-medium text-lg backdrop-blur-sm mb-8">
|
||||||
|
🚀 Pennyzo Web - Next-Gen Business Solutions
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h1 className="font-playfair text-5xl sm:text-6xl lg:text-8xl xl:text-9xl font-bold text-cream tracking-tight mb-8 leading-[0.95]">
|
||||||
|
<span className="block">Multiagent</span>
|
||||||
|
<span className="block">Mastery</span>
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
<p className="font-montserrat text-xl sm:text-2xl lg:text-3xl text-cream/80 max-w-5xl mx-auto mb-12 leading-relaxed">
|
||||||
|
Harness the power of specialized AI agents to transform your business operations.
|
||||||
|
From HR management to financial analytics - unlock unprecedented efficiency and growth.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="flex flex-col sm:flex-row gap-6 justify-center items-center mb-16">
|
||||||
|
<Link
|
||||||
|
to="/login"
|
||||||
|
className="min-w-[250px] bg-gradient-to-r from-luxury-gold to-brass text-deep-forest font-montserrat font-bold px-10 py-5 rounded-full hover:scale-105 hover:shadow-luxury-lg transition-all duration-300 focus:outline-none focus:ring-2 focus:ring-luxury-gold/50 text-lg"
|
||||||
|
>
|
||||||
|
⚡ Enter the Pennyzo Realm
|
||||||
|
</Link>
|
||||||
|
<button className="min-w-[250px] border-2 border-luxury-gold/50 text-luxury-gold font-montserrat font-semibold px-10 py-5 rounded-full hover:bg-luxury-gold/10 hover:border-luxury-gold hover:scale-105 transition-all duration-300 backdrop-blur-sm focus:outline-none focus:ring-2 focus:ring-luxury-gold/50 text-lg">
|
||||||
|
🎯 Watch Demo
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Stats */}
|
||||||
|
<div className="grid grid-cols-2 lg:grid-cols-4 gap-8 max-w-4xl mx-auto">
|
||||||
|
{stats.map((stat) => (
|
||||||
|
<div
|
||||||
|
key={stat.label}
|
||||||
|
className="bg-gradient-to-br from-deep-forest/40 to-rich-brown/20 backdrop-blur-2xl border border-luxury-gold/20 rounded-2xl p-6 hover:scale-105 transition-all duration-300"
|
||||||
|
>
|
||||||
|
<div className="text-3xl sm:text-4xl font-playfair font-bold text-luxury-gold mb-2">
|
||||||
|
{stat.value}
|
||||||
|
</div>
|
||||||
|
<div className="text-sm font-montserrat text-cream/70">
|
||||||
|
{stat.label}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Agents Showcase */}
|
||||||
|
<section className="relative py-24 lg:py-32">
|
||||||
|
<div className="relative z-10 max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
|
<div className="text-center mb-20">
|
||||||
|
<div className="inline-block px-6 py-2 bg-gradient-to-r from-luxury-gold/20 to-brass/20 border border-luxury-gold/30 rounded-full text-luxury-gold font-montserrat font-medium text-sm backdrop-blur-sm mb-6">
|
||||||
|
🤖 AI-Powered Agent Arsenal
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 className="font-playfair text-4xl sm:text-5xl lg:text-6xl font-bold text-cream tracking-tight mb-6">
|
||||||
|
Your Business
|
||||||
|
<span className="block text-transparent bg-clip-text bg-gradient-to-r from-luxury-gold via-brass to-bronze">
|
||||||
|
Dream Team
|
||||||
|
</span>
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<p className="font-montserrat text-lg sm:text-xl text-cream/80 max-w-3xl mx-auto leading-relaxed">
|
||||||
|
Meet your specialized AI agents, each trained to excel in specific business domains.
|
||||||
|
Together, they form an unstoppable force for digital transformation.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||||
|
{agents.map((agent) => (
|
||||||
|
<div
|
||||||
|
key={agent.id}
|
||||||
|
className="group bg-gradient-to-br from-deep-forest/40 to-rich-brown/20 backdrop-blur-2xl border border-luxury-gold/20 rounded-3xl p-8 hover:scale-105 hover:shadow-luxury-lg hover:border-luxury-gold/40 transition-all duration-500"
|
||||||
|
>
|
||||||
|
{/* Agent Icon */}
|
||||||
|
<div className={`w-20 h-20 bg-gradient-to-br ${agent.color} rounded-2xl flex items-center justify-center text-4xl mb-6 group-hover:scale-110 transition-transform duration-300`}>
|
||||||
|
{agent.icon}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 className="font-playfair text-2xl font-bold text-cream mb-4">
|
||||||
|
{agent.name}
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<p className="font-montserrat text-cream/80 leading-relaxed mb-6">
|
||||||
|
{agent.description}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{/* Features */}
|
||||||
|
<div className="space-y-3 mb-6">
|
||||||
|
{agent.features.map((feature, featureIndex) => (
|
||||||
|
<div key={featureIndex} className="flex items-center space-x-3">
|
||||||
|
<div className="w-2 h-2 bg-luxury-gold rounded-full flex-shrink-0"></div>
|
||||||
|
<span className="font-montserrat text-sm text-cream/90">
|
||||||
|
{feature}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Action Button */}
|
||||||
|
<button className={`w-full bg-gradient-to-r ${agent.color} text-deep-forest font-montserrat font-semibold px-6 py-3 rounded-xl hover:scale-105 transition-all duration-300 focus:outline-none focus:ring-2 focus:ring-luxury-gold/50`}>
|
||||||
|
Deploy {agent.name}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Why Choose Pennyzo */}
|
||||||
|
<section className="relative py-24 lg:py-32 bg-gradient-to-b from-deep-forest/20 to-rich-brown/10">
|
||||||
|
<div className="relative z-10 max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
|
<div className="text-center mb-20">
|
||||||
|
<h2 className="font-playfair text-4xl sm:text-5xl lg:text-6xl font-bold text-cream tracking-tight mb-6">
|
||||||
|
Why Choose
|
||||||
|
<span className="block text-transparent bg-clip-text bg-gradient-to-r from-luxury-gold via-brass to-bronze">
|
||||||
|
Pennyzo Web?
|
||||||
|
</span>
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-16 items-center">
|
||||||
|
<div className="space-y-8">
|
||||||
|
{[
|
||||||
|
{
|
||||||
|
title: 'Unified Intelligence',
|
||||||
|
description: 'All agents work together seamlessly, sharing insights and optimizing cross-functional operations.',
|
||||||
|
icon: '🧠'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Enterprise-Grade Security',
|
||||||
|
description: 'Bank-level encryption and compliance standards protect your sensitive business data.',
|
||||||
|
icon: '🔒'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Scalable Architecture',
|
||||||
|
description: 'From startups to enterprises, our platform grows with your business needs.',
|
||||||
|
icon: '📈'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '24/7 AI Support',
|
||||||
|
description: 'Our agents never sleep, providing round-the-clock optimization and monitoring.',
|
||||||
|
icon: '🌟'
|
||||||
|
}
|
||||||
|
].map((benefit, index) => (
|
||||||
|
<div key={index} className="flex items-start space-x-4">
|
||||||
|
<div className="w-12 h-12 bg-gradient-to-br from-luxury-gold/20 to-brass/20 rounded-xl flex items-center justify-center text-2xl flex-shrink-0">
|
||||||
|
{benefit.icon}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3 className="font-playfair text-xl font-bold text-cream mb-2">
|
||||||
|
{benefit.title}
|
||||||
|
</h3>
|
||||||
|
<p className="font-montserrat text-cream/80">
|
||||||
|
{benefit.description}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="bg-gradient-to-br from-deep-forest/60 to-rich-brown/40 backdrop-blur-2xl rounded-3xl border border-luxury-gold/30 p-12">
|
||||||
|
<h3 className="font-playfair text-3xl font-bold text-cream mb-6 text-center">
|
||||||
|
Ready to Transform Your Business?
|
||||||
|
</h3>
|
||||||
|
<p className="font-montserrat text-cream/80 text-lg mb-8 text-center">
|
||||||
|
Join thousands of businesses already leveraging the power of multiagent AI solutions.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="space-y-4">
|
||||||
|
<Link
|
||||||
|
to="/login"
|
||||||
|
className="block w-full bg-gradient-to-r from-luxury-gold to-brass text-deep-forest font-montserrat font-bold py-4 rounded-xl hover:scale-105 hover:shadow-luxury-lg transition-all duration-300 focus:outline-none focus:ring-2 focus:ring-luxury-gold/50 text-center"
|
||||||
|
>
|
||||||
|
🚀 Start Free Trial
|
||||||
|
</Link>
|
||||||
|
|
||||||
|
<button className="w-full border-2 border-luxury-gold/50 text-luxury-gold font-montserrat font-semibold py-4 rounded-xl hover:bg-luxury-gold/10 hover:border-luxury-gold transition-all duration-300 focus:outline-none focus:ring-2 focus:ring-luxury-gold/50">
|
||||||
|
📞 Schedule Demo
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<Footer />
|
||||||
|
<LiveCounter initialUsers={2847} initialRevenue={156789} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default LandingPage;
|
||||||
227
src/pages/LoginPage.tsx
Normal file
227
src/pages/LoginPage.tsx
Normal file
@@ -0,0 +1,227 @@
|
|||||||
|
import React, { useState, useEffect } from 'react';
|
||||||
|
import { Link, useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
|
const LoginPage: React.FC = () => {
|
||||||
|
const [email, setEmail] = useState('');
|
||||||
|
const [password, setPassword] = useState('');
|
||||||
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
const [characterFrame, setCharacterFrame] = useState(0);
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
// Animate character sprite
|
||||||
|
useEffect(() => {
|
||||||
|
const interval = setInterval(() => {
|
||||||
|
setCharacterFrame(prev => (prev + 1) % 4);
|
||||||
|
}, 800);
|
||||||
|
return () => clearInterval(interval);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleDemoLogin = () => {
|
||||||
|
setEmail('demo@pennyzo.com');
|
||||||
|
setPassword('demo123');
|
||||||
|
setIsLoading(true);
|
||||||
|
setTimeout(() => {
|
||||||
|
setIsLoading(false);
|
||||||
|
navigate('/home');
|
||||||
|
}, 2000);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleLogin = (e: React.FormEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
setIsLoading(true);
|
||||||
|
setTimeout(() => {
|
||||||
|
setIsLoading(false);
|
||||||
|
navigate('/home');
|
||||||
|
}, 2000);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="min-h-screen flex items-center justify-center px-4 relative overflow-hidden">
|
||||||
|
{/* Retro Grid Background */}
|
||||||
|
<div className="fixed inset-0 opacity-20">
|
||||||
|
<div className="absolute inset-0" style={{
|
||||||
|
backgroundImage: `
|
||||||
|
linear-gradient(rgba(197, 157, 89, 0.1) 1px, transparent 1px),
|
||||||
|
linear-gradient(90deg, rgba(197, 157, 89, 0.1) 1px, transparent 1px)
|
||||||
|
`,
|
||||||
|
backgroundSize: '40px 40px'
|
||||||
|
}}></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Floating Particles */}
|
||||||
|
<div className="fixed inset-0 pointer-events-none">
|
||||||
|
{[...Array(15)].map((_, i) => (
|
||||||
|
<div
|
||||||
|
key={i}
|
||||||
|
className="absolute w-1 h-1 bg-luxury-gold rounded-full animate-pulse"
|
||||||
|
style={{
|
||||||
|
left: `${Math.random() * 100}%`,
|
||||||
|
top: `${Math.random() * 100}%`,
|
||||||
|
animationDelay: `${Math.random() * 3}s`,
|
||||||
|
animationDuration: `${2 + Math.random() * 3}s`
|
||||||
|
}}
|
||||||
|
></div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="max-w-6xl w-full grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||||
|
{/* Character Side */}
|
||||||
|
<div className="flex flex-col items-center space-y-8 order-2 lg:order-1">
|
||||||
|
{/* Animated Character */}
|
||||||
|
<div className="relative">
|
||||||
|
<div className="w-80 h-80 bg-gradient-to-br from-deep-forest/60 to-rich-brown/40 rounded-3xl border-4 border-luxury-gold/30 backdrop-blur-xl flex items-center justify-center relative overflow-hidden">
|
||||||
|
{/* Character Container */}
|
||||||
|
<div className="relative w-64 h-64">
|
||||||
|
{/* Character Base (Samurai/Ninja style) */}
|
||||||
|
<div className={`absolute inset-0 transition-all duration-200 ${characterFrame % 2 === 0 ? 'scale-100' : 'scale-105'}`}>
|
||||||
|
{/* Body */}
|
||||||
|
<div className="absolute bottom-8 left-1/2 transform -translate-x-1/2 w-24 h-32 bg-gradient-to-b from-rich-brown to-deep-forest rounded-t-3xl border-2 border-luxury-gold/50"></div>
|
||||||
|
|
||||||
|
{/* Head */}
|
||||||
|
<div className="absolute bottom-32 left-1/2 transform -translate-x-1/2 w-16 h-16 bg-gradient-to-b from-champagne to-pearl rounded-full border-2 border-luxury-gold/50"></div>
|
||||||
|
|
||||||
|
{/* Hat/Helmet */}
|
||||||
|
<div className="absolute bottom-40 left-1/2 transform -translate-x-1/2 w-20 h-12 bg-gradient-to-b from-deep-forest to-rich-brown rounded-t-full border-2 border-luxury-gold/50"></div>
|
||||||
|
|
||||||
|
{/* Eyes */}
|
||||||
|
<div className="absolute bottom-36 left-1/2 transform -translate-x-1/2">
|
||||||
|
<div className={`w-2 h-2 bg-luxury-gold rounded-full absolute -left-2 transition-all duration-300 ${characterFrame % 4 === 0 ? 'animate-pulse' : ''}`}></div>
|
||||||
|
<div className={`w-2 h-2 bg-luxury-gold rounded-full absolute left-2 transition-all duration-300 ${characterFrame % 4 === 0 ? 'animate-pulse' : ''}`}></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Arms */}
|
||||||
|
<div className={`absolute bottom-20 left-3 w-6 h-16 bg-gradient-to-b from-rich-brown to-deep-forest rounded-full border border-luxury-gold/30 transform transition-transform duration-200 ${characterFrame % 2 === 0 ? 'rotate-12' : 'rotate-0'}`}></div>
|
||||||
|
<div className={`absolute bottom-20 right-3 w-6 h-16 bg-gradient-to-b from-rich-brown to-deep-forest rounded-full border border-luxury-gold/30 transform transition-transform duration-200 ${characterFrame % 2 === 0 ? '-rotate-12' : 'rotate-0'}`}></div>
|
||||||
|
|
||||||
|
{/* Sword */}
|
||||||
|
<div className={`absolute bottom-12 right-1 w-1 h-24 bg-gradient-to-b from-platinum to-luxury-gold transform transition-all duration-200 ${characterFrame % 2 === 0 ? 'rotate-45 scale-110' : 'rotate-30'}`}></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Action Lines */}
|
||||||
|
{characterFrame === 1 && (
|
||||||
|
<div className="absolute inset-0">
|
||||||
|
<div className="absolute top-8 left-4 w-12 h-0.5 bg-luxury-gold opacity-70 animate-pulse"></div>
|
||||||
|
<div className="absolute top-16 right-6 w-8 h-0.5 bg-luxury-gold opacity-50 animate-pulse"></div>
|
||||||
|
<div className="absolute bottom-24 left-8 w-10 h-0.5 bg-luxury-gold opacity-60 animate-pulse"></div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Power Aura */}
|
||||||
|
<div className="absolute inset-0 bg-gradient-to-r from-luxury-gold/10 to-bronze/10 rounded-3xl animate-pulse"></div>
|
||||||
|
|
||||||
|
{/* Floating Orbs */}
|
||||||
|
<div className="absolute top-4 right-4 w-3 h-3 bg-luxury-gold rounded-full animate-bounce" style={{ animationDelay: '0s' }}></div>
|
||||||
|
<div className="absolute top-8 left-6 w-2 h-2 bg-bronze rounded-full animate-bounce" style={{ animationDelay: '0.5s' }}></div>
|
||||||
|
<div className="absolute bottom-8 right-8 w-2 h-2 bg-brass rounded-full animate-bounce" style={{ animationDelay: '1s' }}></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Character Speech Bubble */}
|
||||||
|
<div className="bg-gradient-to-br from-deep-forest/80 to-rich-brown/60 backdrop-blur-xl rounded-2xl p-6 border-2 border-luxury-gold/30 relative max-w-sm">
|
||||||
|
<div className="absolute -top-2 left-8 w-4 h-4 bg-gradient-to-br from-deep-forest/80 to-rich-brown/60 rotate-45 border-t-2 border-l-2 border-luxury-gold/30"></div>
|
||||||
|
<p className="font-montserrat text-cream text-center italic">
|
||||||
|
"Welcome. Sign in with your credentials to continue."
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Login Form Side */}
|
||||||
|
<div className="order-1 lg:order-2">
|
||||||
|
<div className="bg-gradient-to-br from-deep-forest/60 to-rich-brown/40 backdrop-blur-2xl rounded-3xl border-2 border-luxury-gold/30 p-8 shadow-luxury-xl">
|
||||||
|
{/* Header */}
|
||||||
|
<div className="text-center mb-8">
|
||||||
|
<div className="flex items-center justify-center space-x-3 mb-4">
|
||||||
|
<div className="w-12 h-12 bg-gradient-to-br from-luxury-gold to-bronze rounded-xl flex items-center justify-center">
|
||||||
|
<span className="font-playfair text-2xl font-bold text-deep-forest">P</span>
|
||||||
|
</div>
|
||||||
|
<h1 className="font-playfair text-4xl font-bold text-cream">Pennyzo Web</h1>
|
||||||
|
</div>
|
||||||
|
<p className="font-montserrat text-cream/80 text-lg">Multiagent Business Solutions</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Login Form */}
|
||||||
|
<form onSubmit={handleLogin} className="space-y-6">
|
||||||
|
<div>
|
||||||
|
<label className="block font-montserrat text-cream font-medium mb-2">
|
||||||
|
Email Address
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="email"
|
||||||
|
value={email}
|
||||||
|
onChange={(e) => setEmail(e.target.value)}
|
||||||
|
className="w-full px-4 py-3 bg-deep-forest/60 border-2 border-luxury-gold/30 rounded-xl text-cream placeholder-cream/50 focus:border-luxury-gold focus:outline-none focus:ring-2 focus:ring-luxury-gold/20 transition-all duration-300"
|
||||||
|
placeholder="Enter your email"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label className="block font-montserrat text-cream font-medium mb-2">
|
||||||
|
Password
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="password"
|
||||||
|
value={password}
|
||||||
|
onChange={(e) => setPassword(e.target.value)}
|
||||||
|
className="w-full px-4 py-3 bg-deep-forest/60 border-2 border-luxury-gold/30 rounded-xl text-cream placeholder-cream/50 focus:border-luxury-gold focus:outline-none focus:ring-2 focus:ring-luxury-gold/20 transition-all duration-300"
|
||||||
|
placeholder="Enter your password"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Action Buttons */}
|
||||||
|
<div className="space-y-4">
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
disabled={isLoading}
|
||||||
|
className="w-full bg-gradient-to-r from-luxury-gold to-brass text-deep-forest font-montserrat font-bold py-4 rounded-xl hover:scale-105 hover:shadow-luxury-lg transition-all duration-300 focus:outline-none focus:ring-2 focus:ring-luxury-gold/50 disabled:opacity-50 disabled:cursor-not-allowed"
|
||||||
|
>
|
||||||
|
{isLoading ? (
|
||||||
|
<div className="flex items-center justify-center space-x-2">
|
||||||
|
<div className="w-5 h-5 border-2 border-deep-forest border-t-transparent rounded-full animate-spin"></div>
|
||||||
|
<span>Signing in...</span>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
'Sign in'
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={handleDemoLogin}
|
||||||
|
className="w-full border-2 border-luxury-gold/50 text-luxury-gold font-montserrat font-semibold py-4 rounded-xl hover:bg-luxury-gold/10 hover:border-luxury-gold hover:scale-105 transition-all duration-300 focus:outline-none focus:ring-2 focus:ring-luxury-gold/50"
|
||||||
|
>
|
||||||
|
Demo Login
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Links */}
|
||||||
|
<div className="text-center space-y-4">
|
||||||
|
<Link
|
||||||
|
to="/forgot-password"
|
||||||
|
className="block font-montserrat text-luxury-gold hover:text-brass transition-colors duration-300 underline"
|
||||||
|
>
|
||||||
|
Forgot Password?
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{/*
|
||||||
|
Demo Credentials Info (commented out per request)
|
||||||
|
<div className="mt-8 bg-gradient-to-r from-luxury-gold/10 to-bronze/10 rounded-xl p-4 border border-luxury-gold/20">
|
||||||
|
<h3 className="font-montserrat font-semibold text-luxury-gold mb-2">Demo Credentials</h3>
|
||||||
|
<div className="font-montserrat text-sm text-cream/80 space-y-1">
|
||||||
|
<p>Email: <span className="text-luxury-gold">demo@pennyzo.com</span></p>
|
||||||
|
<p>Password: <span className="text-luxury-gold">demo123</span></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
*/}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default LoginPage;
|
||||||
1
src/vite-env.d.ts
vendored
Normal file
1
src/vite-env.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/// <reference types="vite/client" />
|
||||||
73
tailwind.config.js
Normal file
73
tailwind.config.js
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
/** @type {import('tailwindcss').Config} */
|
||||||
|
export default {
|
||||||
|
content: [
|
||||||
|
"./index.html",
|
||||||
|
"./src/**/*.{js,ts,jsx,tsx}",
|
||||||
|
],
|
||||||
|
theme: {
|
||||||
|
extend: {
|
||||||
|
colors: {
|
||||||
|
// Legacy elegance
|
||||||
|
'deep-navy': '#0A192F',
|
||||||
|
'brass': '#D4AF37',
|
||||||
|
'off-white': '#F8F8F8',
|
||||||
|
'light-gray': '#CCD6F6',
|
||||||
|
|
||||||
|
// Luxury palette
|
||||||
|
'luxury-gold': '#C59D59',
|
||||||
|
'cream': '#F5F2E9',
|
||||||
|
'forest-green': '#0F4C3C',
|
||||||
|
'deep-forest': '#072C21',
|
||||||
|
'rich-brown': '#886D4C',
|
||||||
|
|
||||||
|
// Sophistication accents
|
||||||
|
'champagne': '#F7E7CE',
|
||||||
|
'bronze': '#CD7F32',
|
||||||
|
'pearl': '#F8F6F3',
|
||||||
|
'charcoal': '#36454F',
|
||||||
|
'platinum': '#E5E4E2'
|
||||||
|
},
|
||||||
|
fontFamily: {
|
||||||
|
'playfair': ['Playfair Display', 'serif'],
|
||||||
|
'montserrat': ['Montserrat', 'sans-serif'],
|
||||||
|
// Legacy font names (keep for backward compatibility)
|
||||||
|
'luxury-serif': ['Playfair Display', 'Cormorant Garamond', 'serif'],
|
||||||
|
'elegant-sans': ['Montserrat', 'Lato', 'sans-serif']
|
||||||
|
},
|
||||||
|
backgroundImage: {
|
||||||
|
'luxury-texture': "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=\"%23C59D59\" fill-opacity=\"0.05\"%3E%3Ccircle cx=\"7\" cy=\"7\" r=\"7\"/%3E%3Ccircle cx=\"53\" cy=\"7\" r=\"7\"/%3E%3Ccircle cx=\"7\" cy=\"53\" r=\"7\"/%3E%3Ccircle cx=\"53\" cy=\"53\" r=\"7\"/%3E%3C/g%3E%3C/g%3E%3C/svg%3E')",
|
||||||
|
'pennyzo': "url('/src/assets/bg pennyzo.png')",
|
||||||
|
},
|
||||||
|
boxShadow: {
|
||||||
|
'luxury': '0 25px 50px -12px rgba(197, 157, 89, 0.25)',
|
||||||
|
'luxury-lg': '0 35px 60px -15px rgba(197, 157, 89, 0.35)',
|
||||||
|
'luxury-xl': '0 40px 80px -20px rgba(197, 157, 89, 0.4)',
|
||||||
|
'luxury-inner': 'inset 0 2px 4px 0 rgba(197, 157, 89, 0.1)'
|
||||||
|
},
|
||||||
|
backdropBlur: {
|
||||||
|
'3xl': '64px',
|
||||||
|
'4xl': '128px'
|
||||||
|
},
|
||||||
|
animation: {
|
||||||
|
'pulse-slow': 'pulse 3s cubic-bezier(0.4, 0, 0.6, 1) infinite',
|
||||||
|
'float': 'float 6s ease-in-out infinite',
|
||||||
|
'gradient-shift': 'gradient-shift 8s ease-in-out infinite',
|
||||||
|
},
|
||||||
|
keyframes: {
|
||||||
|
float: {
|
||||||
|
'0%, 100%': { transform: 'translateY(0px)' },
|
||||||
|
'50%': { transform: 'translateY(-20px)' }
|
||||||
|
},
|
||||||
|
'gradient-shift': {
|
||||||
|
'0%, 100%': {
|
||||||
|
background: 'linear-gradient(45deg, #C59D59, #D4AF37, #CD7F32)'
|
||||||
|
},
|
||||||
|
'50%': {
|
||||||
|
background: 'linear-gradient(45deg, #CD7F32, #C59D59, #D4AF37)'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
plugins: [],
|
||||||
|
}
|
||||||
27
tsconfig.app.json
Normal file
27
tsconfig.app.json
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
||||||
|
"target": "ES2022",
|
||||||
|
"useDefineForClassFields": true,
|
||||||
|
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
||||||
|
"module": "ESNext",
|
||||||
|
"skipLibCheck": true,
|
||||||
|
|
||||||
|
/* Bundler mode */
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"allowImportingTsExtensions": true,
|
||||||
|
"verbatimModuleSyntax": true,
|
||||||
|
"moduleDetection": "force",
|
||||||
|
"noEmit": true,
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
|
||||||
|
/* Linting */
|
||||||
|
"strict": true,
|
||||||
|
"noUnusedLocals": true,
|
||||||
|
"noUnusedParameters": true,
|
||||||
|
"erasableSyntaxOnly": true,
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
"noUncheckedSideEffectImports": true
|
||||||
|
},
|
||||||
|
"include": ["src"]
|
||||||
|
}
|
||||||
7
tsconfig.json
Normal file
7
tsconfig.json
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"files": [],
|
||||||
|
"references": [
|
||||||
|
{ "path": "./tsconfig.app.json" },
|
||||||
|
{ "path": "./tsconfig.node.json" }
|
||||||
|
]
|
||||||
|
}
|
||||||
25
tsconfig.node.json
Normal file
25
tsconfig.node.json
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
|
||||||
|
"target": "ES2023",
|
||||||
|
"lib": ["ES2023"],
|
||||||
|
"module": "ESNext",
|
||||||
|
"skipLibCheck": true,
|
||||||
|
|
||||||
|
/* Bundler mode */
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"allowImportingTsExtensions": true,
|
||||||
|
"verbatimModuleSyntax": true,
|
||||||
|
"moduleDetection": "force",
|
||||||
|
"noEmit": true,
|
||||||
|
|
||||||
|
/* Linting */
|
||||||
|
"strict": true,
|
||||||
|
"noUnusedLocals": true,
|
||||||
|
"noUnusedParameters": true,
|
||||||
|
"erasableSyntaxOnly": true,
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
"noUncheckedSideEffectImports": true
|
||||||
|
},
|
||||||
|
"include": ["vite.config.ts"]
|
||||||
|
}
|
||||||
7
vite.config.ts
Normal file
7
vite.config.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import { defineConfig } from 'vite'
|
||||||
|
import react from '@vitejs/plugin-react'
|
||||||
|
|
||||||
|
// https://vite.dev/config/
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [react()],
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user