summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoshanCyriac <roshancyriac.k@gmail.com>2025-07-09 17:21:38 +0530
committerRoshanCyriac <roshancyriac.k@gmail.com>2025-07-09 17:21:38 +0530
commit816a8d16a1454a6c0dc4d1fc61b8cdff781473d5 (patch)
tree568c2bab21be0174d483f960e7c14cceba39ced2
initial
-rw-r--r--.gitignore24
-rw-r--r--README.md12
-rw-r--r--eslint.config.js29
-rw-r--r--index.html18
-rw-r--r--package-lock.json2618
-rw-r--r--package.json34
-rw-r--r--src/App.css147
-rw-r--r--src/App.jsx106
-rw-r--r--src/ProjectCard.jsx25
-rw-r--r--src/ProjectsSection.jsx41
-rw-r--r--src/ProjectsSection.module.css80
-rw-r--r--src/components/CommandPalette.jsx136
-rw-r--r--src/components/MatrixRain.jsx76
-rw-r--r--src/components/Navigation.jsx36
-rw-r--r--src/components/RetroTerminal.jsx98
-rw-r--r--src/components/RetroTerminal.module.css104
-rw-r--r--src/components/ScrollAnimations.jsx102
-rw-r--r--src/components/Terminal.jsx121
-rw-r--r--src/index.css683
-rw-r--r--src/main.jsx10
-rw-r--r--src/pages/About.jsx302
-rw-r--r--src/pages/Contact.jsx336
-rw-r--r--src/pages/Events.jsx325
-rw-r--r--src/pages/Home.jsx58
-rw-r--r--src/pages/Projects.jsx309
-rw-r--r--src/pages/Resources.jsx323
-rw-r--r--src/pages/Team.jsx257
-rw-r--r--vite.config.js7
28 files changed, 6417 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..a547bf3
--- /dev/null
+++ b/.gitignore
@@ -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?
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..7059a96
--- /dev/null
+++ b/README.md
@@ -0,0 +1,12 @@
+# React + 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 using TypeScript with type-aware lint rules enabled. Check out the [TS template](https://github.com/vitejs/vite/tree/main/packages/create-vite/template-react-ts) for information on how to integrate TypeScript and [`typescript-eslint`](https://typescript-eslint.io) in your project.
diff --git a/eslint.config.js b/eslint.config.js
new file mode 100644
index 0000000..cee1e2c
--- /dev/null
+++ b/eslint.config.js
@@ -0,0 +1,29 @@
+import js from '@eslint/js'
+import globals from 'globals'
+import reactHooks from 'eslint-plugin-react-hooks'
+import reactRefresh from 'eslint-plugin-react-refresh'
+import { defineConfig, globalIgnores } from 'eslint/config'
+
+export default defineConfig([
+ globalIgnores(['dist']),
+ {
+ files: ['**/*.{js,jsx}'],
+ extends: [
+ js.configs.recommended,
+ reactHooks.configs['recommended-latest'],
+ reactRefresh.configs.vite,
+ ],
+ languageOptions: {
+ ecmaVersion: 2020,
+ globals: globals.browser,
+ parserOptions: {
+ ecmaVersion: 'latest',
+ ecmaFeatures: { jsx: true },
+ sourceType: 'module',
+ },
+ },
+ rules: {
+ 'no-unused-vars': ['error', { varsIgnorePattern: '^[A-Z_]' }],
+ },
+ },
+])
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..af158ce
--- /dev/null
+++ b/index.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<html lang="en">
+ <head>
+ <meta charset="UTF-8" />
+
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <meta name="description" content="FOSSEE Club - Free and Open Source Software for Education" />
+ <meta name="keywords" content="FOSSEE, Open Source, Linux, Programming, Education" />
+ <title>FOSSEE Club - Free and Open Source Software for Education</title>
+ <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=Fira+Code:wght@300;400;500;600;700&family=JetBrains+Mono:wght@100;200;300;400;500;600;700;800&display=swap" rel="stylesheet">
+ </head>
+ <body>
+ <div id="root"></div>
+ <script type="module" src="/src/main.jsx"></script>
+ </body>
+</html>
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..3e6e28c
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,2618 @@
+{
+ "name": "fossee-club",
+ "version": "1.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "fossee-club",
+ "version": "1.0.0",
+ "dependencies": {
+ "framer-motion": "^12.23.0",
+ "lucide-react": "^0.468.0",
+ "react": "^19.1.0",
+ "react-dom": "^19.1.0",
+ "react-router-dom": "^6.28.0",
+ "react-syntax-highlighter": "^15.5.0",
+ "react-type-animation": "^3.2.0",
+ "xterm": "^5.3.0"
+ },
+ "devDependencies": {
+ "@eslint/js": "^9.30.1",
+ "@types/react": "^19.1.8",
+ "@types/react-dom": "^19.1.6",
+ "@types/react-syntax-highlighter": "^15.5.11",
+ "@vitejs/plugin-react": "^4.6.0",
+ "eslint": "^9.30.1",
+ "eslint-plugin-react-hooks": "^5.2.0",
+ "eslint-plugin-react-refresh": "^0.4.20",
+ "globals": "^16.3.0",
+ "vite": "^4.4.9"
+ }
+ },
+ "node_modules/@ampproject/remapping": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
+ "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/code-frame": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
+ "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.27.1",
+ "js-tokens": "^4.0.0",
+ "picocolors": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/compat-data": {
+ "version": "7.28.0",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.0.tgz",
+ "integrity": "sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/core": {
+ "version": "7.28.0",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.0.tgz",
+ "integrity": "sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==",
+ "dev": true,
+ "dependencies": {
+ "@ampproject/remapping": "^2.2.0",
+ "@babel/code-frame": "^7.27.1",
+ "@babel/generator": "^7.28.0",
+ "@babel/helper-compilation-targets": "^7.27.2",
+ "@babel/helper-module-transforms": "^7.27.3",
+ "@babel/helpers": "^7.27.6",
+ "@babel/parser": "^7.28.0",
+ "@babel/template": "^7.27.2",
+ "@babel/traverse": "^7.28.0",
+ "@babel/types": "^7.28.0",
+ "convert-source-map": "^2.0.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.3",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/babel"
+ }
+ },
+ "node_modules/@babel/generator": {
+ "version": "7.28.0",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.0.tgz",
+ "integrity": "sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/parser": "^7.28.0",
+ "@babel/types": "^7.28.0",
+ "@jridgewell/gen-mapping": "^0.3.12",
+ "@jridgewell/trace-mapping": "^0.3.28",
+ "jsesc": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets": {
+ "version": "7.27.2",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz",
+ "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/compat-data": "^7.27.2",
+ "@babel/helper-validator-option": "^7.27.1",
+ "browserslist": "^4.24.0",
+ "lru-cache": "^5.1.1",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-globals": {
+ "version": "7.28.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz",
+ "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-imports": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz",
+ "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==",
+ "dev": true,
+ "dependencies": {
+ "@babel/traverse": "^7.27.1",
+ "@babel/types": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-transforms": {
+ "version": "7.27.3",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.3.tgz",
+ "integrity": "sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.27.1",
+ "@babel/helper-validator-identifier": "^7.27.1",
+ "@babel/traverse": "^7.27.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-plugin-utils": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz",
+ "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-string-parser": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
+ "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz",
+ "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-option": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz",
+ "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helpers": {
+ "version": "7.27.6",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.6.tgz",
+ "integrity": "sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==",
+ "dev": true,
+ "dependencies": {
+ "@babel/template": "^7.27.2",
+ "@babel/types": "^7.27.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.28.0",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.0.tgz",
+ "integrity": "sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.28.0"
+ },
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-jsx-self": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz",
+ "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-jsx-source": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz",
+ "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/runtime": {
+ "version": "7.27.6",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.6.tgz",
+ "integrity": "sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/template": {
+ "version": "7.27.2",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz",
+ "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.27.1",
+ "@babel/parser": "^7.27.2",
+ "@babel/types": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse": {
+ "version": "7.28.0",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.0.tgz",
+ "integrity": "sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.27.1",
+ "@babel/generator": "^7.28.0",
+ "@babel/helper-globals": "^7.28.0",
+ "@babel/parser": "^7.28.0",
+ "@babel/template": "^7.27.2",
+ "@babel/types": "^7.28.0",
+ "debug": "^4.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.28.0",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.0.tgz",
+ "integrity": "sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-string-parser": "^7.27.1",
+ "@babel/helper-validator-identifier": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.18.20",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz",
+ "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-arm64": {
+ "version": "0.18.20",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz",
+ "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-x64": {
+ "version": "0.18.20",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz",
+ "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.18.20",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz",
+ "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/darwin-x64": {
+ "version": "0.18.20",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz",
+ "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.18.20",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz",
+ "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/freebsd-x64": {
+ "version": "0.18.20",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz",
+ "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-arm": {
+ "version": "0.18.20",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz",
+ "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-arm64": {
+ "version": "0.18.20",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz",
+ "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-ia32": {
+ "version": "0.18.20",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz",
+ "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.18.20",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz",
+ "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-mips64el": {
+ "version": "0.18.20",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz",
+ "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-ppc64": {
+ "version": "0.18.20",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz",
+ "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-riscv64": {
+ "version": "0.18.20",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz",
+ "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-s390x": {
+ "version": "0.18.20",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz",
+ "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-x64": {
+ "version": "0.18.20",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz",
+ "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/netbsd-x64": {
+ "version": "0.18.20",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz",
+ "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/openbsd-x64": {
+ "version": "0.18.20",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz",
+ "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/sunos-x64": {
+ "version": "0.18.20",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz",
+ "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-arm64": {
+ "version": "0.18.20",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz",
+ "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-ia32": {
+ "version": "0.18.20",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz",
+ "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.18.20",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz",
+ "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@eslint-community/eslint-utils": {
+ "version": "4.7.0",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz",
+ "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==",
+ "dev": true,
+ "dependencies": {
+ "eslint-visitor-keys": "^3.4.3"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
+ }
+ },
+ "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint-community/regexpp": {
+ "version": "4.12.1",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz",
+ "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==",
+ "dev": true,
+ "engines": {
+ "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@eslint/config-array": {
+ "version": "0.21.0",
+ "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz",
+ "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==",
+ "dev": true,
+ "dependencies": {
+ "@eslint/object-schema": "^2.1.6",
+ "debug": "^4.3.1",
+ "minimatch": "^3.1.2"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/config-helpers": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.0.tgz",
+ "integrity": "sha512-ViuymvFmcJi04qdZeDc2whTHryouGcDlaxPqarTD0ZE10ISpxGUVZGZDx4w01upyIynL3iu6IXH2bS1NhclQMw==",
+ "dev": true,
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/core": {
+ "version": "0.14.0",
+ "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.14.0.tgz",
+ "integrity": "sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg==",
+ "dev": true,
+ "dependencies": {
+ "@types/json-schema": "^7.0.15"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/eslintrc": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz",
+ "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==",
+ "dev": true,
+ "dependencies": {
+ "ajv": "^6.12.4",
+ "debug": "^4.3.2",
+ "espree": "^10.0.1",
+ "globals": "^14.0.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^4.1.0",
+ "minimatch": "^3.1.2",
+ "strip-json-comments": "^3.1.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint/eslintrc/node_modules/globals": {
+ "version": "14.0.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
+ "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@eslint/js": {
+ "version": "9.30.1",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.30.1.tgz",
+ "integrity": "sha512-zXhuECFlyep42KZUhWjfvsmXGX39W8K8LFb8AWXM9gSV9dQB+MrJGLKvW6Zw0Ggnbpw0VHTtrhFXYe3Gym18jg==",
+ "dev": true,
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://eslint.org/donate"
+ }
+ },
+ "node_modules/@eslint/object-schema": {
+ "version": "2.1.6",
+ "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz",
+ "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==",
+ "dev": true,
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/plugin-kit": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.3.tgz",
+ "integrity": "sha512-1+WqvgNMhmlAambTvT3KPtCl/Ibr68VldY2XY40SL1CE0ZXiakFR/cbTspaF5HsnpDMvcYYoJHfl4980NBjGag==",
+ "dev": true,
+ "dependencies": {
+ "@eslint/core": "^0.15.1",
+ "levn": "^0.4.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/plugin-kit/node_modules/@eslint/core": {
+ "version": "0.15.1",
+ "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.1.tgz",
+ "integrity": "sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA==",
+ "dev": true,
+ "dependencies": {
+ "@types/json-schema": "^7.0.15"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@humanfs/core": {
+ "version": "0.19.1",
+ "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
+ "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==",
+ "dev": true,
+ "engines": {
+ "node": ">=18.18.0"
+ }
+ },
+ "node_modules/@humanfs/node": {
+ "version": "0.16.6",
+ "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz",
+ "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==",
+ "dev": true,
+ "dependencies": {
+ "@humanfs/core": "^0.19.1",
+ "@humanwhocodes/retry": "^0.3.0"
+ },
+ "engines": {
+ "node": ">=18.18.0"
+ }
+ },
+ "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz",
+ "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==",
+ "dev": true,
+ "engines": {
+ "node": ">=18.18"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12.22"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/retry": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz",
+ "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=18.18"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.12",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz",
+ "integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.0",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.5.4",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz",
+ "integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==",
+ "dev": true
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.29",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz",
+ "integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
+ "node_modules/@remix-run/router": {
+ "version": "1.23.0",
+ "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.0.tgz",
+ "integrity": "sha512-O3rHJzAQKamUz1fvE0Qaw0xSFqsA/yafi2iqeE0pvdFtCO1viYx8QL6f3Ln/aCCTLxs68SLf0KPM9eSeM8yBnA==",
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@rolldown/pluginutils": {
+ "version": "1.0.0-beta.19",
+ "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.19.tgz",
+ "integrity": "sha512-3FL3mnMbPu0muGOCaKAhhFEYmqv9eTfPSJRJmANrCwtgK8VuxpsZDGK+m0LYAGoyO8+0j5uRe4PeyPDK1yA/hA==",
+ "dev": true
+ },
+ "node_modules/@types/babel__core": {
+ "version": "7.20.5",
+ "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
+ "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/parser": "^7.20.7",
+ "@babel/types": "^7.20.7",
+ "@types/babel__generator": "*",
+ "@types/babel__template": "*",
+ "@types/babel__traverse": "*"
+ }
+ },
+ "node_modules/@types/babel__generator": {
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz",
+ "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__template": {
+ "version": "7.4.4",
+ "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
+ "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
+ "dev": true,
+ "dependencies": {
+ "@babel/parser": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__traverse": {
+ "version": "7.20.7",
+ "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.7.tgz",
+ "integrity": "sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.20.7"
+ }
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
+ "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
+ "dev": true
+ },
+ "node_modules/@types/hast": {
+ "version": "2.3.10",
+ "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.10.tgz",
+ "integrity": "sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw==",
+ "dependencies": {
+ "@types/unist": "^2"
+ }
+ },
+ "node_modules/@types/json-schema": {
+ "version": "7.0.15",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
+ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
+ "dev": true
+ },
+ "node_modules/@types/react": {
+ "version": "19.1.8",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.8.tgz",
+ "integrity": "sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g==",
+ "dev": true,
+ "dependencies": {
+ "csstype": "^3.0.2"
+ }
+ },
+ "node_modules/@types/react-dom": {
+ "version": "19.1.6",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.6.tgz",
+ "integrity": "sha512-4hOiT/dwO8Ko0gV1m/TJZYk3y0KBnY9vzDh7W+DH17b2HFSOGgdj33dhihPeuy3l0q23+4e+hoXHV6hCC4dCXw==",
+ "dev": true,
+ "peerDependencies": {
+ "@types/react": "^19.0.0"
+ }
+ },
+ "node_modules/@types/react-syntax-highlighter": {
+ "version": "15.5.13",
+ "resolved": "https://registry.npmjs.org/@types/react-syntax-highlighter/-/react-syntax-highlighter-15.5.13.tgz",
+ "integrity": "sha512-uLGJ87j6Sz8UaBAooU0T6lWJ0dBmjZgN1PZTrj05TNql2/XpC6+4HhMT5syIdFUUt+FASfCeLLv4kBygNU+8qA==",
+ "dev": true,
+ "dependencies": {
+ "@types/react": "*"
+ }
+ },
+ "node_modules/@types/unist": {
+ "version": "2.0.11",
+ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz",
+ "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="
+ },
+ "node_modules/@vitejs/plugin-react": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.6.0.tgz",
+ "integrity": "sha512-5Kgff+m8e2PB+9j51eGHEpn5kUzRKH2Ry0qGoe8ItJg7pqnkPrYPkDQZGgGmTa0EGarHrkjLvOdU3b1fzI8otQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/core": "^7.27.4",
+ "@babel/plugin-transform-react-jsx-self": "^7.27.1",
+ "@babel/plugin-transform-react-jsx-source": "^7.27.1",
+ "@rolldown/pluginutils": "1.0.0-beta.19",
+ "@types/babel__core": "^7.20.5",
+ "react-refresh": "^0.17.0"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "peerDependencies": {
+ "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0"
+ }
+ },
+ "node_modules/acorn": {
+ "version": "8.15.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
+ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
+ "dev": true,
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
+ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/browserslist": {
+ "version": "4.25.1",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz",
+ "integrity": "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "caniuse-lite": "^1.0.30001726",
+ "electron-to-chromium": "^1.5.173",
+ "node-releases": "^2.0.19",
+ "update-browserslist-db": "^1.1.3"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001727",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001727.tgz",
+ "integrity": "sha512-pB68nIHmbN6L/4C6MH1DokyR3bYqFwjaSs/sWDHGj4CTcFtQUQMuJftVwWkXq7mNWOybD3KhUv3oWHoGxgP14Q==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ]
+ },
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/character-entities": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz",
+ "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/character-entities-legacy": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz",
+ "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/character-reference-invalid": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz",
+ "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/comma-separated-tokens": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz",
+ "integrity": "sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true
+ },
+ "node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "dev": true
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+ "dev": true,
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/csstype": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
+ "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
+ "dev": true
+ },
+ "node_modules/debug": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
+ "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true
+ },
+ "node_modules/electron-to-chromium": {
+ "version": "1.5.180",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.180.tgz",
+ "integrity": "sha512-ED+GEyEh3kYMwt2faNmgMB0b8O5qtATGgR4RmRsIp4T6p7B8vdMbIedYndnvZfsaXvSzegtpfqRMDNCjjiSduA==",
+ "dev": true
+ },
+ "node_modules/esbuild": {
+ "version": "0.18.20",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz",
+ "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==",
+ "dev": true,
+ "hasInstallScript": true,
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "optionalDependencies": {
+ "@esbuild/android-arm": "0.18.20",
+ "@esbuild/android-arm64": "0.18.20",
+ "@esbuild/android-x64": "0.18.20",
+ "@esbuild/darwin-arm64": "0.18.20",
+ "@esbuild/darwin-x64": "0.18.20",
+ "@esbuild/freebsd-arm64": "0.18.20",
+ "@esbuild/freebsd-x64": "0.18.20",
+ "@esbuild/linux-arm": "0.18.20",
+ "@esbuild/linux-arm64": "0.18.20",
+ "@esbuild/linux-ia32": "0.18.20",
+ "@esbuild/linux-loong64": "0.18.20",
+ "@esbuild/linux-mips64el": "0.18.20",
+ "@esbuild/linux-ppc64": "0.18.20",
+ "@esbuild/linux-riscv64": "0.18.20",
+ "@esbuild/linux-s390x": "0.18.20",
+ "@esbuild/linux-x64": "0.18.20",
+ "@esbuild/netbsd-x64": "0.18.20",
+ "@esbuild/openbsd-x64": "0.18.20",
+ "@esbuild/sunos-x64": "0.18.20",
+ "@esbuild/win32-arm64": "0.18.20",
+ "@esbuild/win32-ia32": "0.18.20",
+ "@esbuild/win32-x64": "0.18.20"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint": {
+ "version": "9.30.1",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.30.1.tgz",
+ "integrity": "sha512-zmxXPNMOXmwm9E0yQLi5uqXHs7uq2UIiqEKo3Gq+3fwo1XrJ+hijAZImyF7hclW3E6oHz43Yk3RP8at6OTKflQ==",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.2.0",
+ "@eslint-community/regexpp": "^4.12.1",
+ "@eslint/config-array": "^0.21.0",
+ "@eslint/config-helpers": "^0.3.0",
+ "@eslint/core": "^0.14.0",
+ "@eslint/eslintrc": "^3.3.1",
+ "@eslint/js": "9.30.1",
+ "@eslint/plugin-kit": "^0.3.1",
+ "@humanfs/node": "^0.16.6",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@humanwhocodes/retry": "^0.4.2",
+ "@types/estree": "^1.0.6",
+ "@types/json-schema": "^7.0.15",
+ "ajv": "^6.12.4",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.6",
+ "debug": "^4.3.2",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^8.4.0",
+ "eslint-visitor-keys": "^4.2.1",
+ "espree": "^10.4.0",
+ "esquery": "^1.5.0",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^8.0.0",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "ignore": "^5.2.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.3"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://eslint.org/donate"
+ },
+ "peerDependencies": {
+ "jiti": "*"
+ },
+ "peerDependenciesMeta": {
+ "jiti": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-plugin-react-hooks": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz",
+ "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0"
+ }
+ },
+ "node_modules/eslint-plugin-react-refresh": {
+ "version": "0.4.20",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.20.tgz",
+ "integrity": "sha512-XpbHQ2q5gUF8BGOX4dHe+71qoirYMhApEPZ7sfhF/dNnOF1UXnCMGZf79SFTBO7Bz5YEIT4TMieSlJBWhP9WBA==",
+ "dev": true,
+ "peerDependencies": {
+ "eslint": ">=8.40"
+ }
+ },
+ "node_modules/eslint-scope": {
+ "version": "8.4.0",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz",
+ "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==",
+ "dev": true,
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-visitor-keys": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
+ "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
+ "dev": true,
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/espree": {
+ "version": "10.4.0",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz",
+ "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
+ "dev": true,
+ "dependencies": {
+ "acorn": "^8.15.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^4.2.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/esquery": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
+ "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
+ "dev": true,
+ "dependencies": {
+ "estraverse": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true
+ },
+ "node_modules/fault": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/fault/-/fault-1.0.4.tgz",
+ "integrity": "sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA==",
+ "dependencies": {
+ "format": "^0.2.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/file-entry-cache": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
+ "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
+ "dev": true,
+ "dependencies": {
+ "flat-cache": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
+ "node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/flat-cache": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
+ "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
+ "dev": true,
+ "dependencies": {
+ "flatted": "^3.2.9",
+ "keyv": "^4.5.4"
+ },
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/flatted": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz",
+ "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==",
+ "dev": true
+ },
+ "node_modules/format": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz",
+ "integrity": "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==",
+ "engines": {
+ "node": ">=0.4.x"
+ }
+ },
+ "node_modules/framer-motion": {
+ "version": "12.23.0",
+ "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.23.0.tgz",
+ "integrity": "sha512-xf6NxTGAyf7zR4r2KlnhFmsRfKIbjqeBupEDBAaEtVIBJX96sAon00kMlsKButSIRwPSHjbRrAPnYdJJ9kyhbA==",
+ "dependencies": {
+ "motion-dom": "^12.22.0",
+ "motion-utils": "^12.19.0",
+ "tslib": "^2.4.0"
+ },
+ "peerDependencies": {
+ "@emotion/is-prop-valid": "*",
+ "react": "^18.0.0 || ^19.0.0",
+ "react-dom": "^18.0.0 || ^19.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@emotion/is-prop-valid": {
+ "optional": true
+ },
+ "react": {
+ "optional": true
+ },
+ "react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/gensync": {
+ "version": "1.0.0-beta.2",
+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
+ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/globals": {
+ "version": "16.3.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-16.3.0.tgz",
+ "integrity": "sha512-bqWEnJ1Nt3neqx2q5SFfGS8r/ahumIakg3HcwtNlrVlwXIeNumWn/c7Pn/wKzGhf6SaW6H6uWXLqC30STCMchQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/hast-util-parse-selector": {
+ "version": "2.2.5",
+ "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz",
+ "integrity": "sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ==",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hastscript": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-6.0.0.tgz",
+ "integrity": "sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w==",
+ "dependencies": {
+ "@types/hast": "^2.0.0",
+ "comma-separated-tokens": "^1.0.0",
+ "hast-util-parse-selector": "^2.0.0",
+ "property-information": "^5.0.0",
+ "space-separated-tokens": "^1.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/highlight.js": {
+ "version": "10.7.3",
+ "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz",
+ "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/highlightjs-vue": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/highlightjs-vue/-/highlightjs-vue-1.0.0.tgz",
+ "integrity": "sha512-PDEfEF102G23vHmPhLyPboFCD+BkMGu+GuJe2d9/eH4FsCwvgBpnc9n0pGE+ffKdph38s6foEZiEjdgHdzp+IA=="
+ },
+ "node_modules/ignore": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
+ "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
+ "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
+ "dev": true,
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/is-alphabetical": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz",
+ "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/is-alphanumerical": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz",
+ "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==",
+ "dependencies": {
+ "is-alphabetical": "^1.0.0",
+ "is-decimal": "^1.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/is-decimal": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz",
+ "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-hexadecimal": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz",
+ "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true
+ },
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
+ },
+ "node_modules/js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dev": true,
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/jsesc": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
+ "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
+ "dev": true,
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/json-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+ "dev": true
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "node_modules/json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true
+ },
+ "node_modules/json5": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+ "dev": true,
+ "bin": {
+ "json5": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/keyv": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+ "dev": true,
+ "dependencies": {
+ "json-buffer": "3.0.1"
+ }
+ },
+ "node_modules/levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true
+ },
+ "node_modules/loose-envify": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "peer": true,
+ "dependencies": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ },
+ "bin": {
+ "loose-envify": "cli.js"
+ }
+ },
+ "node_modules/lowlight": {
+ "version": "1.20.0",
+ "resolved": "https://registry.npmjs.org/lowlight/-/lowlight-1.20.0.tgz",
+ "integrity": "sha512-8Ktj+prEb1RoCPkEOrPMYUN/nCggB7qAWe3a7OpMjWQkh3l2RD5wKRQ+o8Q8YuI9RG/xs95waaI/E6ym/7NsTw==",
+ "dependencies": {
+ "fault": "^1.0.0",
+ "highlight.js": "~10.7.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "node_modules/lucide-react": {
+ "version": "0.468.0",
+ "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.468.0.tgz",
+ "integrity": "sha512-6koYRhnM2N0GGZIdXzSeiNwguv1gt/FAjZOiPl76roBi3xKEXa4WmfpxgQwTTL4KipXjefrnf3oV4IsYhi4JFA==",
+ "peerDependencies": {
+ "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/motion-dom": {
+ "version": "12.22.0",
+ "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.22.0.tgz",
+ "integrity": "sha512-ooH7+/BPw9gOsL9VtPhEJHE2m4ltnhMlcGMhEqA0YGNhKof7jdaszvsyThXI6LVIKshJUZ9/CP6HNqQhJfV7kw==",
+ "dependencies": {
+ "motion-utils": "^12.19.0"
+ }
+ },
+ "node_modules/motion-utils": {
+ "version": "12.19.0",
+ "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.19.0.tgz",
+ "integrity": "sha512-BuFTHINYmV07pdWs6lj6aI63vr2N4dg0vR+td0rtrdpWOhBzIkEklZyLcvKBoEtwSqx8Jg06vUB5RS0xDiUybw=="
+ },
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "dev": true
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.11",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
+ "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true
+ },
+ "node_modules/node-releases": {
+ "version": "2.0.19",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz",
+ "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==",
+ "dev": true
+ },
+ "node_modules/object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/optionator": {
+ "version": "0.9.4",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
+ "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
+ "dev": true,
+ "dependencies": {
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0",
+ "word-wrap": "^1.2.5"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/parse-entities": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz",
+ "integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==",
+ "dependencies": {
+ "character-entities": "^1.0.0",
+ "character-entities-legacy": "^1.0.0",
+ "character-reference-invalid": "^1.0.0",
+ "is-alphanumerical": "^1.0.0",
+ "is-decimal": "^1.0.0",
+ "is-hexadecimal": "^1.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/picocolors": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+ "dev": true
+ },
+ "node_modules/postcss": {
+ "version": "8.5.6",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
+ "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "nanoid": "^3.3.11",
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.1"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/prismjs": {
+ "version": "1.30.0",
+ "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz",
+ "integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/prop-types": {
+ "version": "15.8.1",
+ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
+ "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
+ "peer": true,
+ "dependencies": {
+ "loose-envify": "^1.4.0",
+ "object-assign": "^4.1.1",
+ "react-is": "^16.13.1"
+ }
+ },
+ "node_modules/property-information": {
+ "version": "5.6.0",
+ "resolved": "https://registry.npmjs.org/property-information/-/property-information-5.6.0.tgz",
+ "integrity": "sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==",
+ "dependencies": {
+ "xtend": "^4.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/punycode": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
+ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/react": {
+ "version": "19.1.0",
+ "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz",
+ "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-dom": {
+ "version": "19.1.0",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz",
+ "integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==",
+ "dependencies": {
+ "scheduler": "^0.26.0"
+ },
+ "peerDependencies": {
+ "react": "^19.1.0"
+ }
+ },
+ "node_modules/react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
+ "peer": true
+ },
+ "node_modules/react-refresh": {
+ "version": "0.17.0",
+ "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz",
+ "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-router": {
+ "version": "6.30.1",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.1.tgz",
+ "integrity": "sha512-X1m21aEmxGXqENEPG3T6u0Th7g0aS4ZmoNynhbs+Cn+q+QGTLt+d5IQ2bHAXKzKcxGJjxACpVbnYQSCRcfxHlQ==",
+ "dependencies": {
+ "@remix-run/router": "1.23.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8"
+ }
+ },
+ "node_modules/react-router-dom": {
+ "version": "6.30.1",
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.30.1.tgz",
+ "integrity": "sha512-llKsgOkZdbPU1Eg3zK8lCn+sjD9wMRZZPuzmdWWX5SUs8OFkN5HnFVC0u5KMeMaC9aoancFI/KoLuKPqN+hxHw==",
+ "dependencies": {
+ "@remix-run/router": "1.23.0",
+ "react-router": "6.30.1"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8",
+ "react-dom": ">=16.8"
+ }
+ },
+ "node_modules/react-syntax-highlighter": {
+ "version": "15.6.1",
+ "resolved": "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-15.6.1.tgz",
+ "integrity": "sha512-OqJ2/vL7lEeV5zTJyG7kmARppUjiB9h9udl4qHQjjgEos66z00Ia0OckwYfRxCSFrW8RJIBnsBwQsHZbVPspqg==",
+ "dependencies": {
+ "@babel/runtime": "^7.3.1",
+ "highlight.js": "^10.4.1",
+ "highlightjs-vue": "^1.0.0",
+ "lowlight": "^1.17.0",
+ "prismjs": "^1.27.0",
+ "refractor": "^3.6.0"
+ },
+ "peerDependencies": {
+ "react": ">= 0.14.0"
+ }
+ },
+ "node_modules/react-type-animation": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/react-type-animation/-/react-type-animation-3.2.0.tgz",
+ "integrity": "sha512-WXTe0i3rRNKjmggPvT5ntye1QBt0ATGbijeW6V3cQe2W0jaMABXXlPPEdtofnS9tM7wSRHchEvI9SUw+0kUohw==",
+ "peerDependencies": {
+ "prop-types": "^15.5.4",
+ "react": ">= 15.0.0",
+ "react-dom": ">= 15.0.0"
+ }
+ },
+ "node_modules/refractor": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/refractor/-/refractor-3.6.0.tgz",
+ "integrity": "sha512-MY9W41IOWxxk31o+YvFCNyNzdkc9M20NoZK5vq6jkv4I/uh2zkWcfudj0Q1fovjUQJrNewS9NMzeTtqPf+n5EA==",
+ "dependencies": {
+ "hastscript": "^6.0.0",
+ "parse-entities": "^2.0.0",
+ "prismjs": "~1.27.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/refractor/node_modules/prismjs": {
+ "version": "1.27.0",
+ "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.27.0.tgz",
+ "integrity": "sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/rollup": {
+ "version": "3.29.5",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.5.tgz",
+ "integrity": "sha512-GVsDdsbJzzy4S/v3dqWPJ7EfvZJfCHiDqe80IyrF59LYuP+e6U1LJoUqeuqRbwAWoMNoXivMNeNAOf5E22VA1w==",
+ "dev": true,
+ "bin": {
+ "rollup": "dist/bin/rollup"
+ },
+ "engines": {
+ "node": ">=14.18.0",
+ "npm": ">=8.0.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/scheduler": {
+ "version": "0.26.0",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz",
+ "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA=="
+ },
+ "node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/space-separated-tokens": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz",
+ "integrity": "sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
+ },
+ "node_modules/type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/update-browserslist-db": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz",
+ "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "escalade": "^3.2.0",
+ "picocolors": "^1.1.1"
+ },
+ "bin": {
+ "update-browserslist-db": "cli.js"
+ },
+ "peerDependencies": {
+ "browserslist": ">= 4.21.0"
+ }
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/vite": {
+ "version": "4.4.9",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-4.4.9.tgz",
+ "integrity": "sha512-2mbUn2LlUmNASWwSCNSJ/EG2HuSRTnVNaydp6vMCm5VIqJsjMfbIWtbH2kDuwUVW5mMUKKZvGPX/rqeqVvv1XA==",
+ "dev": true,
+ "dependencies": {
+ "esbuild": "^0.18.10",
+ "postcss": "^8.4.27",
+ "rollup": "^3.27.1"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/vitejs/vite?sponsor=1"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ },
+ "peerDependencies": {
+ "@types/node": ">= 14",
+ "less": "*",
+ "lightningcss": "^1.21.0",
+ "sass": "*",
+ "stylus": "*",
+ "sugarss": "*",
+ "terser": "^5.4.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "lightningcss": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/word-wrap": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
+ "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/xtend": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
+ "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
+ "engines": {
+ "node": ">=0.4"
+ }
+ },
+ "node_modules/xterm": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/xterm/-/xterm-5.3.0.tgz",
+ "integrity": "sha512-8QqjlekLUFTrU6x7xck1MsPzPA571K5zNqWm0M0oroYEWVOptZ0+ubQSkQ3uxIEhcIHRujJy6emDWX4A7qyFzg==",
+ "deprecated": "This package is now deprecated. Move to @xterm/xterm instead."
+ },
+ "node_modules/yallist": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+ "dev": true
+ },
+ "node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ }
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..3df314a
--- /dev/null
+++ b/package.json
@@ -0,0 +1,34 @@
+{
+ "name": "fossee-club",
+ "private": true,
+ "version": "1.0.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "vite build",
+ "lint": "eslint .",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "framer-motion": "^12.23.0",
+ "lucide-react": "^0.468.0",
+ "react": "^19.1.0",
+ "react-dom": "^19.1.0",
+ "react-router-dom": "^6.28.0",
+ "react-syntax-highlighter": "^15.5.0",
+ "react-type-animation": "^3.2.0",
+ "xterm": "^5.3.0"
+ },
+ "devDependencies": {
+ "@eslint/js": "^9.30.1",
+ "@types/react": "^19.1.8",
+ "@types/react-dom": "^19.1.6",
+ "@types/react-syntax-highlighter": "^15.5.11",
+ "@vitejs/plugin-react": "^4.6.0",
+ "eslint": "^9.30.1",
+ "eslint-plugin-react-hooks": "^5.2.0",
+ "eslint-plugin-react-refresh": "^0.4.20",
+ "globals": "^16.3.0",
+ "vite": "^4.4.9"
+ }
+}
diff --git a/src/App.css b/src/App.css
new file mode 100644
index 0000000..ab24914
--- /dev/null
+++ b/src/App.css
@@ -0,0 +1,147 @@
+#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;
+}
+
+.terminalWindow {
+ position: fixed;
+ z-index: 9999;
+ left: 100px;
+ top: 100px;
+ width: 600px;
+ height: 400px;
+ background: #181825;
+ color: #e0e0e0;
+ font-family: 'Fira Mono', 'Consolas', 'Courier New', monospace;
+ border: 4px double #fff;
+ border-radius: 8px 8px 0 0;
+ display: flex;
+ flex-direction: column;
+ box-shadow: 0 8px 32px rgba(0,0,0,0.5);
+ overflow: hidden;
+}
+
+.terminalHeader {
+ background: linear-gradient(90deg, #22223b 80%, #6c63ff 100%);
+ color: #fff;
+ padding: 0.5em 1em;
+ font-weight: bold;
+ display: flex;
+ align-items: center;
+ cursor: move;
+ user-select: none;
+ border-bottom: 2px solid #6c63ff;
+ z-index: 2; /* Ensure header is above content */
+}
+
+.terminalTitle {
+ flex: 1;
+ letter-spacing: 2px;
+ font-size: 1.1em;
+}
+
+.closeBtn {
+ background: #ff5f56;
+ border: none;
+ color: #fff;
+ font-size: 1.2em;
+ width: 2em;
+ height: 2em;
+ border-radius: 50%;
+ cursor: pointer;
+ margin-left: 0.5em;
+ transition: background 0.2s;
+}
+.closeBtn:hover {
+ background: #ff2d00;
+}
+
+.terminalOutput {
+ flex: 1;
+ background: #181825;
+ color: #e0e0e0;
+ padding: 1em;
+ font-size: 1em;
+ overflow-y: auto;
+ border-bottom: 2px solid #6c63ff;
+ word-break: break-word;
+ z-index: 1;
+}
+
+.terminalLine {
+ white-space: pre-wrap;
+ line-height: 1.5;
+}
+
+.terminalInputBar {
+ display: flex;
+ align-items: center;
+ background: #22223b;
+ padding: 0.5em 1em;
+ border-top: 2px solid #6c63ff;
+ z-index: 1;
+}
+
+.prompt {
+ color: #6c63ff;
+ font-weight: bold;
+ margin-right: 0.5em;
+}
+
+.terminalInput {
+ flex: 1;
+ background: transparent;
+ border: none;
+ color: #e0e0e0;
+ font-family: inherit;
+ font-size: 1em;
+ outline: none;
+}
+
+.resizer {
+ position: absolute;
+ right: 0;
+ bottom: 0;
+ width: 18px;
+ height: 18px;
+ background: linear-gradient(135deg, transparent 60%, #6c63ff 100%);
+ cursor: se-resize;
+}
diff --git a/src/App.jsx b/src/App.jsx
new file mode 100644
index 0000000..0fdd0ec
--- /dev/null
+++ b/src/App.jsx
@@ -0,0 +1,106 @@
+import React, { useState, useEffect } from 'react';
+import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
+import { motion, AnimatePresence } from 'framer-motion';
+import Navigation from './components/Navigation';
+import Home from './pages/Home';
+import About from './pages/About';
+import Events from './pages/Events';
+import Projects from './pages/Projects';
+import Resources from './pages/Resources';
+import Team from './pages/Team';
+import Contact from './pages/Contact';
+import MatrixRain from './components/MatrixRain';
+import CommandPalette from './components/CommandPalette';
+import ScrollAnimations from './components/ScrollAnimations';
+import RetroTerminal from './components/RetroTerminal';
+import './App.css';
+
+function App() {
+ const [commandPaletteOpen, setCommandPaletteOpen] = useState(false);
+ const [isLoading, setIsLoading] = useState(true);
+ const [scrollDirection, setScrollDirection] = useState('down');
+ const [lastScrollY, setLastScrollY] = useState(0);
+ const [terminalOpen, setTerminalOpen] = useState(false);
+
+ useEffect(() => {
+ // Simulate loading time for terminal boot sequence
+ const timer = setTimeout(() => {
+ setIsLoading(false);
+ }, 2000);
+
+ return () => clearTimeout(timer);
+ }, []);
+
+ useEffect(() => {
+ const handleKeyDown = (e) => {
+ if (e.ctrlKey && e.key === 'k') {
+ e.preventDefault();
+ setCommandPaletteOpen(true);
+ }
+ if (e.ctrlKey && e.key === '`') {
+ e.preventDefault();
+ setTerminalOpen((open) => !open);
+ }
+ if (e.key === 'Escape') {
+ setCommandPaletteOpen(false);
+ setTerminalOpen(false);
+ }
+ };
+
+ // Scroll direction detection
+ const handleScroll = () => {
+ const currentScrollY = window.scrollY;
+ setScrollDirection(currentScrollY > lastScrollY ? 'down' : 'up');
+ setLastScrollY(currentScrollY);
+ };
+
+ window.addEventListener('keydown', handleKeyDown);
+ window.addEventListener('scroll', handleScroll);
+
+ return () => {
+ window.removeEventListener('keydown', handleKeyDown);
+ window.removeEventListener('scroll', handleScroll);
+ };
+ }, [lastScrollY]);
+
+ if (isLoading) {
+ return (
+ <div className="loading-screen">
+ <div className="terminal">
+ <div className="terminal-prompt">root@fossee:~$</div>
+ <div className="typewriter">Initializing FOSSEE Club System...</div>
+ <div className="loading mt-4"></div>
+ </div>
+ </div>
+ );
+ }
+
+ return (
+ <Router>
+ <div className="App">
+ <MatrixRain />
+ <ScrollAnimations />
+ <Navigation />
+ <RetroTerminal visible={terminalOpen} onClose={() => setTerminalOpen(false)} />
+ <AnimatePresence mode="wait">
+ <Routes>
+ <Route path="/" element={<Home />} />
+ <Route path="/about" element={<About />} />
+ <Route path="/events" element={<Events />} />
+ <Route path="/projects" element={<Projects />} />
+ <Route path="/resources" element={<Resources />} />
+ <Route path="/team" element={<Team />} />
+ <Route path="/contact" element={<Contact />} />
+ </Routes>
+ </AnimatePresence>
+
+ <CommandPalette
+ isOpen={commandPaletteOpen}
+ onClose={() => setCommandPaletteOpen(false)}
+ />
+ </div>
+ </Router>
+ );
+}
+
+export default App;
diff --git a/src/ProjectCard.jsx b/src/ProjectCard.jsx
new file mode 100644
index 0000000..e450fc2
--- /dev/null
+++ b/src/ProjectCard.jsx
@@ -0,0 +1,25 @@
+import React from 'react';
+import { motion } from 'framer-motion';
+import styles from './ProjectsSection.module.css';
+
+const ProjectCard = ({ name, year, info, link, color }) => (
+ <motion.div
+ className={styles.projectCard}
+ whileHover={{ scale: 1.05, boxShadow: '0 8px 32px rgba(0,255,174,0.2)' }}
+ initial={{ opacity: 0 }}
+ animate={{ opacity: 1 }}
+ transition={{ duration: 0.5 }}
+ style={{ borderColor: color }}
+ >
+ <div className={styles.cardHeader} style={{ background: color }}>
+ <span className={styles.cardYear}>{year}</span>
+ <span className={styles.cardName}>{name}</span>
+ </div>
+ <div className={styles.cardInfo}>{info}</div>
+ <a className={styles.cardLink} href={link} target="_blank" rel="noopener noreferrer">
+ VISIT SITE
+ </a>
+ </motion.div>
+);
+
+export default ProjectCard; \ No newline at end of file
diff --git a/src/ProjectsSection.jsx b/src/ProjectsSection.jsx
new file mode 100644
index 0000000..7524b43
--- /dev/null
+++ b/src/ProjectsSection.jsx
@@ -0,0 +1,41 @@
+import React from 'react';
+import { motion } from 'framer-motion';
+import ProjectCard from './ProjectCard';
+import styles from './ProjectsSection.module.css';
+
+const projects = [
+ {
+ name: 'PLAYBOOK JOURNAL',
+ year: 2022,
+ info: 'A collaborative playbook for cross-border journalists. Design: Loonatiks Design Crew. Tech: GatsbyJS, Canvas, MatterJS, React-Spring.',
+ link: 'https://playbook.n-ost.org/',
+ color: '#00ffae',
+ },
+ {
+ name: 'MIAO',
+ year: 2023,
+ info: 'A startup providing global users with an exceptionally entertaining experience through innovative gaming products and services.',
+ link: '#',
+ color: '#00ffae',
+ },
+];
+
+const ProjectsSection = () => (
+ <section className={styles.section}>
+ <motion.h1
+ className={styles.heading}
+ initial={{ opacity: 0, y: -50 }}
+ animate={{ opacity: 1, y: 0 }}
+ transition={{ duration: 0.8 }}
+ >
+ PROJECTS
+ </motion.h1>
+ <div className={styles.grid}>
+ {projects.map((project, idx) => (
+ <ProjectCard key={idx} {...project} />
+ ))}
+ </div>
+ </section>
+);
+
+export default ProjectsSection; \ No newline at end of file
diff --git a/src/ProjectsSection.module.css b/src/ProjectsSection.module.css
new file mode 100644
index 0000000..4741280
--- /dev/null
+++ b/src/ProjectsSection.module.css
@@ -0,0 +1,80 @@
+.section {
+ background: #000;
+ min-height: 100vh;
+ padding: 60px 0;
+ font-family: 'IBM Plex Mono', monospace;
+}
+
+.heading {
+ color: #fff;
+ font-size: 6vw;
+ letter-spacing: 0.1em;
+ text-align: left;
+ margin-bottom: 40px;
+ font-weight: 700;
+}
+
+.grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
+ gap: 40px;
+ max-width: 1200px;
+ margin: 0 auto;
+}
+
+.card {
+ background: #111;
+ border: 2px solid #00ffae;
+ border-radius: 16px;
+ padding: 32px 24px;
+ color: #fff;
+ transition: box-shadow 0.3s;
+ display: flex;
+ flex-direction: column;
+ min-height: 320px;
+ position: relative;
+}
+
+.cardHeader {
+ display: flex;
+ flex-direction: column;
+ background: #00ffae;
+ color: #000;
+ padding: 12px 16px;
+ border-radius: 8px 8px 0 0;
+ margin-bottom: 18px;
+}
+
+.cardYear {
+ font-size: 1.1rem;
+ font-weight: 600;
+ letter-spacing: 0.08em;
+}
+
+.cardName {
+ font-size: 2rem;
+ font-weight: 700;
+ letter-spacing: 0.1em;
+}
+
+.cardInfo {
+ font-size: 1rem;
+ margin-bottom: 24px;
+ color: #b2fff6;
+ flex: 1;
+}
+
+.cardLink {
+ align-self: flex-end;
+ color: #00ffae;
+ font-size: 1.1rem;
+ text-decoration: none;
+ font-weight: 700;
+ border-bottom: 2px solid #00ffae;
+ transition: color 0.2s, border-color 0.2s;
+}
+
+.cardLink:hover {
+ color: #fff;
+ border-color: #fff;
+} \ No newline at end of file
diff --git a/src/components/CommandPalette.jsx b/src/components/CommandPalette.jsx
new file mode 100644
index 0000000..decde36
--- /dev/null
+++ b/src/components/CommandPalette.jsx
@@ -0,0 +1,136 @@
+import React, { useState, useEffect, useRef } from 'react';
+import { useNavigate } from 'react-router-dom';
+import { motion, AnimatePresence } from 'framer-motion';
+import { Search, Terminal, FileText, Users, Calendar, Code, BookOpen, Mail } from 'lucide-react';
+
+const CommandPalette = ({ isOpen, onClose }) => {
+ const [query, setQuery] = useState('');
+ const [selectedIndex, setSelectedIndex] = useState(0);
+ const inputRef = useRef(null);
+ const navigate = useNavigate();
+
+ const commands = [
+ { id: 'home', label: 'Go to Home', icon: Terminal, path: '/' },
+ { id: 'about', label: 'About FOSSEE', icon: FileText, path: '/about' },
+ { id: 'events', label: 'View Events', icon: Calendar, path: '/events' },
+ { id: 'projects', label: 'Browse Projects', icon: Code, path: '/projects' },
+ { id: 'resources', label: 'Learning Resources', icon: BookOpen, path: '/resources' },
+ { id: 'team', label: 'Meet the Team', icon: Users, path: '/team' },
+ { id: 'contact', label: 'Contact Us', icon: Mail, path: '/contact' },
+ ];
+
+ const filteredCommands = commands.filter(command =>
+ command.label.toLowerCase().includes(query.toLowerCase())
+ );
+
+ useEffect(() => {
+ if (isOpen) {
+ inputRef.current?.focus();
+ setQuery('');
+ setSelectedIndex(0);
+ }
+ }, [isOpen]);
+
+ useEffect(() => {
+ const handleKeyDown = (e) => {
+ if (!isOpen) return;
+
+ switch (e.key) {
+ case 'ArrowDown':
+ e.preventDefault();
+ setSelectedIndex(prev =>
+ prev < filteredCommands.length - 1 ? prev + 1 : 0
+ );
+ break;
+ case 'ArrowUp':
+ e.preventDefault();
+ setSelectedIndex(prev =>
+ prev > 0 ? prev - 1 : filteredCommands.length - 1
+ );
+ break;
+ case 'Enter':
+ e.preventDefault();
+ if (filteredCommands[selectedIndex]) {
+ executeCommand(filteredCommands[selectedIndex]);
+ }
+ break;
+ }
+ };
+
+ document.addEventListener('keydown', handleKeyDown);
+ return () => document.removeEventListener('keydown', handleKeyDown);
+ }, [isOpen, selectedIndex, filteredCommands]);
+
+ const executeCommand = (command) => {
+ navigate(command.path);
+ onClose();
+ };
+
+ if (!isOpen) return null;
+
+ return (
+ <AnimatePresence>
+ <motion.div
+ initial={{ opacity: 0 }}
+ animate={{ opacity: 1 }}
+ exit={{ opacity: 0 }}
+ className="fixed inset-0 bg-black bg-opacity-50 z-50 flex items-center justify-center p-4"
+ onClick={onClose}
+ >
+ <motion.div
+ initial={{ scale: 0.9, opacity: 0 }}
+ animate={{ scale: 1, opacity: 1 }}
+ exit={{ scale: 0.9, opacity: 0 }}
+ className="command-palette"
+ onClick={(e) => e.stopPropagation()}
+ >
+ <div className="flex items-center mb-4">
+ <Search className="w-5 h-5 text-green mr-2" />
+ <input
+ ref={inputRef}
+ type="text"
+ placeholder="Type a command or search..."
+ value={query}
+ onChange={(e) => setQuery(e.target.value)}
+ className="flex-1 bg-transparent border-none text-green font-mono text-base outline-none"
+ />
+ </div>
+
+ <div className="space-y-1 max-h-64 overflow-y-auto">
+ {filteredCommands.length > 0 ? (
+ filteredCommands.map((command, index) => (
+ <motion.button
+ key={command.id}
+ className={`w-full text-left p-2 rounded flex items-center space-x-3 transition-colors ${
+ index === selectedIndex
+ ? 'bg-green bg-opacity-20 text-green'
+ : 'text-white hover:bg-gray hover:bg-opacity-20'
+ }`}
+ onClick={() => executeCommand(command)}
+ whileHover={{ scale: 1.02 }}
+ whileTap={{ scale: 0.98 }}
+ >
+ <command.icon className="w-4 h-4" />
+ <span>{command.label}</span>
+ </motion.button>
+ ))
+ ) : (
+ <div className="text-gray text-center py-4">
+ No commands found for "{query}"
+ </div>
+ )}
+ </div>
+
+ <div className="mt-4 pt-4 border-t border-light-gray text-xs text-gray">
+ <div className="flex justify-between">
+ <span>↑↓ Navigate • Enter Execute • Esc Close</span>
+ <span>Ctrl+K to open</span>
+ </div>
+ </div>
+ </motion.div>
+ </motion.div>
+ </AnimatePresence>
+ );
+};
+
+export default CommandPalette; \ No newline at end of file
diff --git a/src/components/MatrixRain.jsx b/src/components/MatrixRain.jsx
new file mode 100644
index 0000000..b5c2a45
--- /dev/null
+++ b/src/components/MatrixRain.jsx
@@ -0,0 +1,76 @@
+import React, { useEffect, useRef } from 'react';
+
+const MatrixRain = () => {
+ const canvasRef = useRef(null);
+
+ useEffect(() => {
+ const canvas = canvasRef.current;
+ const ctx = canvas.getContext('2d');
+
+ // Set canvas size
+ const resizeCanvas = () => {
+ canvas.width = window.innerWidth;
+ canvas.height = window.innerHeight;
+ };
+
+ resizeCanvas();
+ window.addEventListener('resize', resizeCanvas);
+
+ // Matrix characters
+ const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@#$%^&*()_+-=[]{}|;:,.<>?';
+ const charArray = chars.split('');
+
+ // Rain drops
+ const drops = [];
+ const fontSize = 14;
+ const columns = canvas.width / fontSize;
+
+ // Initialize drops
+ for (let i = 0; i < columns; i++) {
+ drops[i] = 1;
+ }
+
+ // Animation function
+ const draw = () => {
+ // Semi-transparent background to create fade effect
+ ctx.fillStyle = 'rgba(0, 0, 0, 0.05)';
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
+
+ // Draw characters
+ ctx.fillStyle = '#00ff41';
+ ctx.font = `${fontSize}px 'Fira Code'`;
+
+ for (let i = 0; i < drops.length; i++) {
+ // Random character
+ const char = charArray[Math.floor(Math.random() * charArray.length)];
+
+ // Draw character
+ ctx.fillText(char, i * fontSize, drops[i] * fontSize);
+
+ // Reset drop when it reaches bottom
+ if (drops[i] * fontSize > canvas.height && Math.random() > 0.975) {
+ drops[i] = 0;
+ }
+
+ // Move drop down
+ drops[i]++;
+ }
+ };
+
+ // Animation loop
+ const interval = setInterval(draw, 50);
+
+ return () => {
+ clearInterval(interval);
+ window.removeEventListener('resize', resizeCanvas);
+ };
+ }, []);
+
+ return (
+ <div className="matrix-rain">
+ <canvas ref={canvasRef} />
+ </div>
+ );
+};
+
+export default MatrixRain; \ No newline at end of file
diff --git a/src/components/Navigation.jsx b/src/components/Navigation.jsx
new file mode 100644
index 0000000..c3aae9a
--- /dev/null
+++ b/src/components/Navigation.jsx
@@ -0,0 +1,36 @@
+import React from 'react';
+import { Link, useLocation } from 'react-router-dom';
+
+const Navigation = () => {
+ const location = useLocation();
+
+ const navItems = [
+ { path: '/', label: 'Home' },
+ { path: '/about', label: 'About' },
+ { path: '/events', label: 'Events' },
+ { path: '/projects', label: 'Projects' },
+ { path: '/resources', label: 'Resources' },
+ { path: '/team', label: 'Team' },
+ { path: '/contact', label: 'Contact' },
+ ];
+
+ return (
+ <nav className="nav">
+ <div className="container mx-auto px-4">
+ <div className="flex justify-evenly items-center h-16 w-full">
+ {navItems.map((item) => (
+ <Link
+ key={item.path}
+ to={item.path}
+ className={`nav-link text-sm md:text-base ${location.pathname === item.path ? 'text-green' : ''}`}
+ >
+ {item.label}
+ </Link>
+ ))}
+ </div>
+ </div>
+ </nav>
+ );
+};
+
+export default Navigation; \ No newline at end of file
diff --git a/src/components/RetroTerminal.jsx b/src/components/RetroTerminal.jsx
new file mode 100644
index 0000000..f124789
--- /dev/null
+++ b/src/components/RetroTerminal.jsx
@@ -0,0 +1,98 @@
+import React, { useState, useRef, useEffect } from 'react';
+import styles from './RetroTerminal.module.css';
+
+const COMMANDS = {
+ help: 'Available commands: help, clear, about',
+ about: 'FOSSSE CUSAT Terminal. Free and Open Source Software Society, Cochin University of Science and Technology.',
+};
+
+function getPrompt() {
+ return 'fossse@cusat $ ';
+}
+
+function RetroTerminal({ visible, onClose }) {
+ const [history, setHistory] = useState([
+ 'Welcome to FOSSSE CUSAT Terminal!',
+ 'For available commands, try "help".',
+ '',
+ `Last login: ${new Date().toLocaleDateString()}, ${new Date().toLocaleTimeString()}`,
+ '',
+ getPrompt(),
+ ]);
+ const [input, setInput] = useState('');
+ const [size, setSize] = useState({ width: 600, height: 400 });
+ const terminalRef = useRef(null);
+ const outputRef = useRef(null);
+
+ useEffect(() => {
+ if (visible && outputRef.current) {
+ outputRef.current.scrollTop = outputRef.current.scrollHeight;
+ }
+ }, [history, visible]);
+
+ function handleInput(e) {
+ setInput(e.target.value);
+ }
+
+ function handleCommand(cmd) {
+ if (cmd.trim() === '') return;
+ if (cmd === 'clear') {
+ setHistory([getPrompt()]);
+ return;
+ }
+ const output = COMMANDS[cmd] || `Command not found: ${cmd}`;
+ setHistory((h) => [...h, cmd, output, '', getPrompt()]);
+ }
+
+ function handleKeyDown(e) {
+ if (e.key === 'Enter') {
+ handleCommand(input);
+ setInput('');
+ }
+ }
+
+ function handleResize(e) {
+ e.preventDefault();
+ function onMouseMove(ev) {
+ setSize((s) => ({
+ width: Math.max(400, ev.clientX - (terminalRef.current?.getBoundingClientRect().left || 0)),
+ height: Math.max(200, ev.clientY - (terminalRef.current?.getBoundingClientRect().top || 0)),
+ }));
+ }
+ function onMouseUp() {
+ window.removeEventListener('mousemove', onMouseMove);
+ window.removeEventListener('mouseup', onMouseUp);
+ }
+ window.addEventListener('mousemove', onMouseMove);
+ window.addEventListener('mouseup', onMouseUp);
+ }
+
+ if (!visible) return null;
+
+ return (
+ <div
+ ref={terminalRef}
+ className={styles.terminalWindow}
+ style={{ width: size.width, height: size.height }}
+ >
+ <div className={styles.terminalOutput} ref={outputRef}>
+ {history.map((line, i) => (
+ <div key={i} className={styles.terminalLine}>{line}</div>
+ ))}
+ </div>
+ <div className={styles.terminalInputBar}>
+ <span className={styles.prompt}>{getPrompt()}</span>
+ <input
+ className={styles.terminalInput}
+ value={input}
+ onChange={handleInput}
+ onKeyDown={handleKeyDown}
+ autoFocus
+ />
+ </div>
+ <div className={styles.resizer} onMouseDown={handleResize} />
+ </div>
+ );
+}
+
+export default RetroTerminal; \ No newline at end of file
diff --git a/src/components/RetroTerminal.module.css b/src/components/RetroTerminal.module.css
new file mode 100644
index 0000000..e5dfab2
--- /dev/null
+++ b/src/components/RetroTerminal.module.css
@@ -0,0 +1,104 @@
+.terminalWindow {
+ position: fixed;
+ z-index: 9999;
+ left: 100px;
+ top: 100px;
+ width: 600px;
+ height: 400px;
+ background: #181825;
+ color: #e0e0e0;
+ font-family: 'Fira Mono', 'Consolas', 'Courier New', monospace;
+ border: 4px double #fff;
+ border-radius: 8px 8px 0 0;
+ display: flex;
+ flex-direction: column;
+ box-shadow: 0 8px 32px rgba(0,0,0,0.5);
+ overflow: hidden;
+}
+
+.terminalHeader {
+ background: linear-gradient(90deg, #22223b 80%, #6c63ff 100%);
+ color: #fff;
+ padding: 0.5em 1em;
+ font-weight: bold;
+ display: flex;
+ align-items: center;
+ cursor: move;
+ user-select: none;
+ border-bottom: 2px solid #6c63ff;
+ z-index: 2;
+}
+
+.terminalTitle {
+ flex: 1;
+ letter-spacing: 2px;
+ font-size: 1.1em;
+}
+
+.closeBtn {
+ background: #ff5f56;
+ border: none;
+ color: #fff;
+ font-size: 1.2em;
+ width: 2em;
+ height: 2em;
+ border-radius: 50%;
+ cursor: pointer;
+ margin-left: 0.5em;
+ transition: background 0.2s;
+}
+.closeBtn:hover {
+ background: #ff2d00;
+}
+
+.terminalOutput {
+ flex: 1;
+ background: #181825;
+ color: #e0e0e0;
+ padding: 1em;
+ font-size: 1em;
+ overflow-y: auto;
+ border-bottom: 2px solid #6c63ff;
+ word-break: break-word;
+ z-index: 1;
+}
+
+.terminalLine {
+ white-space: pre-wrap;
+ line-height: 1.5;
+}
+
+.terminalInputBar {
+ display: flex;
+ align-items: center;
+ background: #22223b;
+ padding: 0.5em 1em;
+ border-top: 2px solid #6c63ff;
+ z-index: 1;
+}
+
+.prompt {
+ color: #6c63ff;
+ font-weight: bold;
+ margin-right: 0.5em;
+}
+
+.terminalInput {
+ flex: 1;
+ background: transparent;
+ border: none;
+ color: #e0e0e0;
+ font-family: inherit;
+ font-size: 1em;
+ outline: none;
+}
+
+.resizer {
+ position: absolute;
+ right: 0;
+ bottom: 0;
+ width: 18px;
+ height: 18px;
+ background: linear-gradient(135deg, transparent 60%, #6c63ff 100%);
+ cursor: se-resize;
+} \ No newline at end of file
diff --git a/src/components/ScrollAnimations.jsx b/src/components/ScrollAnimations.jsx
new file mode 100644
index 0000000..d6c2355
--- /dev/null
+++ b/src/components/ScrollAnimations.jsx
@@ -0,0 +1,102 @@
+import React, { useEffect, useRef } from 'react';
+
+const ScrollAnimations = () => {
+ const scrollProgressRef = useRef(null);
+ const particlesRef = useRef(null);
+
+ useEffect(() => {
+ // Scroll Progress Bar
+ const updateScrollProgress = () => {
+ const scrollTop = window.scrollY;
+ const docHeight = document.documentElement.scrollHeight - window.innerHeight;
+ const scrollPercent = (scrollTop / docHeight) * 100;
+
+ if (scrollProgressRef.current) {
+ scrollProgressRef.current.style.width = `${scrollPercent}%`;
+ }
+ };
+
+ // Parallax Effect
+ const handleParallax = () => {
+ const scrolled = window.pageYOffset;
+ const parallaxElements = document.querySelectorAll('.parallax-slow, .parallax-medium, .parallax-fast');
+
+ parallaxElements.forEach(element => {
+ const speed = element.classList.contains('parallax-slow') ? 0.5 :
+ element.classList.contains('parallax-medium') ? 0.3 : 0.1;
+ const yPos = -(scrolled * speed);
+ element.style.setProperty('--parallax-y', `${yPos}px`);
+ });
+ };
+
+ // Scroll Trigger Animations
+ const handleScrollTriggers = () => {
+ const triggers = document.querySelectorAll('.scroll-trigger, .scroll-fade-in, .scroll-slide-left, .scroll-slide-right, .scroll-scale-in');
+
+ triggers.forEach(trigger => {
+ const triggerTop = trigger.getBoundingClientRect().top;
+ const triggerBottom = trigger.getBoundingClientRect().bottom;
+ const windowHeight = window.innerHeight;
+
+ if (triggerTop < windowHeight * 0.8 && triggerBottom > 0) {
+ trigger.classList.add('visible', 'triggered');
+ }
+ });
+ };
+
+ // Particle System
+ const createParticle = () => {
+ if (!particlesRef.current) return;
+
+ const particle = document.createElement('div');
+ particle.className = 'particle';
+ particle.style.left = Math.random() * 100 + '%';
+ particle.style.animationDuration = (Math.random() * 4 + 4) + 's';
+ particle.style.animationDelay = Math.random() * 2 + 's';
+
+ particlesRef.current.appendChild(particle);
+
+ // Remove particle after animation
+ setTimeout(() => {
+ if (particle.parentNode) {
+ particle.parentNode.removeChild(particle);
+ }
+ }, 8000);
+ };
+
+ // Initialize particle system
+ const particleInterval = setInterval(createParticle, 2000);
+
+ // Event listeners
+ window.addEventListener('scroll', () => {
+ updateScrollProgress();
+ handleParallax();
+ handleScrollTriggers();
+ });
+
+ // Initial call
+ updateScrollProgress();
+ handleScrollTriggers();
+
+ return () => {
+ window.removeEventListener('scroll', () => {
+ updateScrollProgress();
+ handleParallax();
+ handleScrollTriggers();
+ });
+ clearInterval(particleInterval);
+ };
+ }, []);
+
+ return (
+ <>
+ {/* Scroll Progress Bar */}
+ <div ref={scrollProgressRef} className="scroll-progress"></div>
+
+ {/* Particle System */}
+ <div ref={particlesRef} className="particles"></div>
+ </>
+ );
+};
+
+export default ScrollAnimations; \ No newline at end of file
diff --git a/src/components/Terminal.jsx b/src/components/Terminal.jsx
new file mode 100644
index 0000000..db5c7b0
--- /dev/null
+++ b/src/components/Terminal.jsx
@@ -0,0 +1,121 @@
+import React, { useEffect, useRef, useState } from 'react';
+import { Terminal as XTerm } from 'xterm';
+import 'xterm/css/xterm.css';
+
+const DATA = {
+ about: `FOSS CUSAT is a community of students passionate about open source software, Linux, and programming. Our mission is to promote FOSS philosophy and provide hands-on learning opportunities at CUSAT.`,
+ projects: `Projects:\n- Open Source Club Website\n- Linux Install Fest\n- FOSS Workshops\n- Community Contributions`,
+ team: `Team:\n- Alice (Lead)\n- Bob (Dev)\n- Carol (Design)\n- Dave (Events)`,
+ resources: `Resources:\n- https://fosscusat.in/resources\n- https://fosscusat.in/docs`,
+ events: `Upcoming Events:\n- Linux Bootcamp\n- Hackathon\n- Open Source Day`,
+ contact: `Contact us at: foss@cusat.ac.in`,
+ help: `Available commands: ls, cd <section>, about, projects, team, resources, events, contact, clear, help`,
+};
+
+const SECTIONS = ['home', 'about', 'projects', 'team', 'resources', 'events', 'contact'];
+
+const PROMPT_BASE = 'foss@cusat';
+
+const Terminal = () => {
+ const xtermRef = useRef(null);
+ const termRef = useRef(null);
+ const [cwd, setCwd] = useState('home');
+
+ useEffect(() => {
+ if (!xtermRef.current) {
+ const term = new XTerm({
+ theme: {
+ background: '#161b22',
+ foreground: '#00ff41',
+ cursor: '#00ff41',
+ },
+ fontFamily: 'Fira Mono, JetBrains Mono, monospace',
+ fontSize: 16,
+ cursorBlink: true,
+ rows: 20,
+ });
+ xtermRef.current = term;
+ term.open(termRef.current);
+ term.writeln('Welcome to the FOSS CUSAT Terminal!');
+ term.writeln("Type 'help' to see available commands.\n");
+ printPrompt(term, 'home');
+
+ let input = '';
+ let currentDir = 'home';
+ term.onKey(({ key, domEvent }) => {
+ if (domEvent.key === 'Enter') {
+ term.write('\r\n');
+ handleCommand(input, term, currentDir, (newDir) => {
+ currentDir = newDir;
+ setCwd(newDir);
+ });
+ input = '';
+ setTimeout(() => printPrompt(term, currentDir), 10);
+ } else if (domEvent.key === 'Backspace') {
+ if (input.length > 0) {
+ input = input.slice(0, -1);
+ term.write('\b \b');
+ }
+ } else if (domEvent.key.length === 1) {
+ input += key;
+ term.write(key);
+ }
+ });
+ }
+ // Cleanup
+ return () => {
+ if (xtermRef.current) {
+ xtermRef.current.dispose();
+ xtermRef.current = null;
+ }
+ };
+ }, []);
+
+ function printPrompt(term, dir) {
+ term.write(`\x1b[1;32m${PROMPT_BASE}:${dir === 'home' ? '~' : '/' + dir}$ \x1b[0m`);
+ }
+
+ function handleCommand(cmd, term, currentDir, setDir) {
+ const command = cmd.trim();
+ if (!command) return;
+ if (command === 'clear') {
+ term.clear();
+ return;
+ }
+ if (command === 'ls') {
+ term.writeln(SECTIONS.join(' '));
+ return;
+ }
+ if (command.startsWith('cd ')) {
+ const target = command.slice(3).trim().toLowerCase();
+ if (SECTIONS.includes(target)) {
+ setDir(target);
+ scrollToSection(target);
+ term.writeln(`Changed directory to /${target}`);
+ } else {
+ term.writeln(`No such section: ${target}`);
+ }
+ return;
+ }
+ if (DATA[command.toLowerCase()]) {
+ term.writeln(DATA[command.toLowerCase()]);
+ } else {
+ term.writeln(`Command not found: ${command}`);
+ }
+ }
+
+ function scrollToSection(section) {
+ const el = document.getElementById(section);
+ if (el) {
+ el.scrollIntoView({ behavior: 'smooth', block: 'start' });
+ }
+ }
+
+ return (
+ <div style={{ width: '100%', maxWidth: 1000, margin: '2rem auto', background: '#161b22', borderRadius: 8, boxShadow: '0 2px 16px rgba(0,0,0,0.2)' }}>
+ <div ref={termRef} style={{ height: 500, width: '100%' }} />
+ </div>
+ );
+};
+
+export default Terminal; \ No newline at end of file
diff --git a/src/index.css b/src/index.css
new file mode 100644
index 0000000..6f725b5
--- /dev/null
+++ b/src/index.css
@@ -0,0 +1,683 @@
+@import url('https://fonts.googleapis.com/css2?family=Fira+Code:wght@300;400;500;600;700&family=JetBrains+Mono:wght@100;200;300;400;500;600;700;800&display=swap');
+
+/* Reset and base styles */
+html, body, #root {
+ height: 100%;
+ margin: 0;
+ padding: 0;
+ background: #fff;
+ color: #111;
+ font-family: 'Fira Mono', 'Consolas', 'Courier New', monospace;
+ font-size: 16px;
+ box-sizing: border-box;
+}
+
+*, *::before, *::after {
+ box-sizing: inherit;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ font-family: inherit;
+ font-weight: bold;
+ text-transform: uppercase;
+ letter-spacing: 1px;
+ margin: 0 0 0.5em 0;
+}
+
+button, input, select, textarea {
+ font-family: inherit;
+ font-size: 1em;
+ background: #fff;
+ color: #111;
+ border: 2px solid #111;
+ border-radius: 8px;
+ padding: 0.5em 1em;
+ outline: none;
+ transition: background 0.1s, color 0.1s;
+}
+
+button {
+ cursor: pointer;
+ font-weight: bold;
+ letter-spacing: 1px;
+ background: #fff;
+ border: 2px solid #111;
+ border-radius: 8px;
+ margin: 0.25em;
+}
+button:active {
+ background: #111;
+ color: #fff;
+}
+
+.card, .project-card, .modal {
+ border: 2.5px solid #111;
+ border-radius: 16px;
+ background: #fff;
+ padding: 1.5em 1em;
+ margin: 1em 0;
+ font-family: inherit;
+ box-shadow: none;
+}
+
+input[type="text"], input[type="email"] {
+ border: 2px solid #111;
+ border-radius: 8px;
+ padding: 0.5em 1em;
+ background: #fff;
+ color: #111;
+}
+
+/* Remove link underline, use black color */
+a {
+ color: #111;
+ text-decoration: none;
+ font-weight: bold;
+}
+a:hover {
+ text-decoration: underline;
+}
+
+/* Responsive grid */
+@media (max-width: 600px) {
+ html, body {
+ font-size: 15px;
+ }
+ .card, .project-card, .modal {
+ padding: 1em 0.5em;
+ border-radius: 10px;
+ }
+ button {
+ padding: 0.5em 0.7em;
+ font-size: 0.95em;
+ }
+}
+
+/* Matrix Rain Effect */
+.matrix-rain {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ pointer-events: none;
+ z-index: 1;
+ opacity: 0.1;
+}
+
+.matrix-rain canvas {
+ width: 100%;
+ height: 100%;
+}
+
+/* Main Content */
+#root {
+ position: relative;
+ z-index: 2;
+ min-height: 100vh;
+}
+
+/* Smooth Scrolling Animations */
+.scroll-fade-in {
+ opacity: 0;
+ transform: translateY(30px);
+ transition: all 0.8s ease;
+}
+
+.scroll-fade-in.visible {
+ opacity: 1;
+ transform: translateY(0);
+}
+
+.scroll-slide-left {
+ opacity: 0;
+ transform: translateX(-50px);
+ transition: all 0.8s ease;
+}
+
+.scroll-slide-left.visible {
+ opacity: 1;
+ transform: translateX(0);
+}
+
+.scroll-slide-right {
+ opacity: 0;
+ transform: translateX(50px);
+ transition: all 0.8s ease;
+}
+
+.scroll-slide-right.visible {
+ opacity: 1;
+ transform: translateX(0);
+}
+
+.scroll-scale-in {
+ opacity: 0;
+ transform: scale(0.8);
+ transition: all 0.8s ease;
+}
+
+.scroll-scale-in.visible {
+ opacity: 1;
+ transform: scale(1);
+}
+
+/* Parallax Effects */
+.parallax-bg {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 120%;
+ background: linear-gradient(45deg, var(--terminal-green) 0%, transparent 50%, var(--cyan-blue) 100%);
+ opacity: 0.05;
+ transform: translateZ(-1px) scale(2);
+ z-index: -1;
+}
+
+.parallax-slow {
+ transform: translateY(var(--parallax-y, 0px));
+ transition: transform 0.1s ease-out;
+}
+
+.parallax-medium {
+ transform: translateY(calc(var(--parallax-y, 0px) * 0.5));
+ transition: transform 0.1s ease-out;
+}
+
+.parallax-fast {
+ transform: translateY(calc(var(--parallax-y, 0px) * 0.25));
+ transition: transform 0.1s ease-out;
+}
+
+/* Floating Elements */
+.floating {
+ animation: float 6s ease-in-out infinite;
+}
+
+@keyframes float {
+ 0%, 100% { transform: translateY(0px); }
+ 50% { transform: translateY(-20px); }
+}
+
+.floating-delayed {
+ animation: float 6s ease-in-out infinite;
+ animation-delay: 2s;
+}
+
+.floating-fast {
+ animation: float 4s ease-in-out infinite;
+}
+
+/* Scroll Progress Bar */
+.scroll-progress {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 0%;
+ height: 3px;
+ background: linear-gradient(90deg, var(--terminal-green), var(--cyan-blue));
+ z-index: 1000;
+ transition: width 0.1s ease;
+}
+
+/* Terminal Styling */
+.terminal {
+ background: var(--secondary-bg);
+ border: 1px solid var(--terminal-green);
+ border-radius: 8px;
+ padding: var(--spacing-md);
+ font-family: var(--font-mono);
+ font-size: var(--font-size-base);
+ color: var(--terminal-green);
+ box-shadow: 0 0 20px rgba(0, 255, 65, 0.3);
+ position: relative;
+ overflow: hidden;
+}
+
+.terminal::before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ height: 2px;
+ background: linear-gradient(90deg, var(--terminal-green), var(--cyan-blue));
+ animation: scan 2s linear infinite;
+}
+
+@keyframes scan {
+ 0% { transform: translateX(-100%); }
+ 100% { transform: translateX(100%); }
+}
+
+/* Terminal Prompt */
+.terminal-prompt {
+ color: var(--terminal-green);
+ font-weight: 600;
+}
+
+.terminal-prompt::after {
+ content: '█';
+ animation: blink 1s infinite;
+ color: var(--terminal-green);
+}
+
+@keyframes blink {
+ 0%, 50% { opacity: 1; }
+ 51%, 100% { opacity: 0; }
+}
+
+/* Typing Animation */
+.typewriter {
+ overflow: hidden;
+ border-right: 2px solid var(--terminal-green);
+ white-space: nowrap;
+ animation: typing 3.5s steps(40, end), blink-caret 0.75s step-end infinite;
+}
+
+@keyframes typing {
+ from { width: 0; }
+ to { width: 100%; }
+}
+
+@keyframes blink-caret {
+ from, to { border-color: transparent; }
+ 50% { border-color: var(--terminal-green); }
+}
+
+/* Glitch Effect */
+.glitch {
+ position: relative;
+ animation: glitch 1s infinite;
+}
+
+.glitch::before,
+.glitch::after {
+ content: attr(data-text);
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+}
+
+.glitch::before {
+ animation: glitch-1 0.5s infinite;
+ color: var(--error-red);
+ z-index: -1;
+}
+
+.glitch::after {
+ animation: glitch-2 0.5s infinite;
+ color: var(--cyan-blue);
+ z-index: -2;
+}
+
+@keyframes glitch {
+ 0%, 100% { transform: translate(0); }
+ 20% { transform: translate(-2px, 2px); }
+ 40% { transform: translate(-2px, -2px); }
+ 60% { transform: translate(2px, 2px); }
+ 80% { transform: translate(2px, -2px); }
+}
+
+@keyframes glitch-1 {
+ 0%, 100% { transform: translate(0); }
+ 20% { transform: translate(-2px, 2px); }
+ 40% { transform: translate(-2px, -2px); }
+ 60% { transform: translate(2px, 2px); }
+ 80% { transform: translate(2px, -2px); }
+}
+
+@keyframes glitch-2 {
+ 0%, 100% { transform: translate(0); }
+ 20% { transform: translate(2px, -2px); }
+ 40% { transform: translate(2px, 2px); }
+ 60% { transform: translate(-2px, -2px); }
+ 80% { transform: translate(-2px, 2px); }
+}
+
+/* Neon Glow Effects */
+.neon-glow {
+ text-shadow:
+ 0 0 5px currentColor,
+ 0 0 10px currentColor,
+ 0 0 15px currentColor,
+ 0 0 20px currentColor;
+}
+
+.neon-glow-green {
+ color: var(--terminal-green);
+ text-shadow:
+ 0 0 5px var(--terminal-green),
+ 0 0 10px var(--terminal-green),
+ 0 0 15px var(--terminal-green),
+ 0 0 20px var(--terminal-green);
+}
+
+.neon-glow-cyan {
+ color: var(--cyan-blue);
+ text-shadow:
+ 0 0 5px var(--cyan-blue),
+ 0 0 10px var(--cyan-blue),
+ 0 0 15px var(--cyan-blue),
+ 0 0 20px var(--cyan-blue);
+}
+
+/* Button Styles */
+.btn {
+ background: transparent;
+ border: 2px solid var(--terminal-green);
+ color: var(--terminal-green);
+ padding: var(--spacing-sm) var(--spacing-lg);
+ font-family: var(--font-mono);
+ font-size: var(--font-size-base);
+ cursor: pointer;
+ transition: all var(--transition-normal);
+ position: relative;
+ overflow: hidden;
+}
+
+.btn::before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: -100%;
+ width: 100%;
+ height: 100%;
+ background: linear-gradient(90deg, transparent, rgba(0, 255, 65, 0.2), transparent);
+ transition: left var(--transition-slow);
+}
+
+.btn:hover::before {
+ left: 100%;
+}
+
+.btn:hover {
+ background: var(--terminal-green);
+ color: var(--primary-bg);
+ box-shadow: 0 0 20px rgba(0, 255, 65, 0.5);
+}
+
+/* Navigation */
+.nav {
+ background: transparent;
+ backdrop-filter: none;
+ position: sticky;
+ top: 0;
+ z-index: 100;
+ margin-bottom: 2rem;
+}
+
+.nav-link {
+ color: #111;
+ text-decoration: none;
+ padding: var(--spacing-sm) var(--spacing-md);
+ transition: all var(--transition-normal);
+ position: relative;
+ font-weight: bold;
+ text-shadow: 0 1px 4px rgba(0,0,0,0.08);
+ flex: 1;
+ text-align: center;
+}
+
+.nav-link::after {
+ content: '';
+ position: absolute;
+ bottom: 0;
+ left: 50%;
+ width: 0;
+ height: 2px;
+ background: var(--terminal-green);
+ transition: all var(--transition-normal);
+ transform: translateX(-50%);
+}
+
+.nav-link:hover::after {
+ width: 100%;
+}
+
+.nav-link:hover {
+ color: var(--terminal-green);
+}
+
+/* Section Styles */
+.section {
+ padding: var(--spacing-2xl) 0;
+ position: relative;
+}
+
+.section-title {
+ font-size: var(--font-size-3xl);
+ color: var(--terminal-green);
+ margin-bottom: var(--spacing-xl);
+ text-align: center;
+ font-weight: 600;
+}
+
+/* Card Styles */
+.card {
+ background: var(--secondary-bg);
+ border: 1px solid var(--light-gray);
+ border-radius: 8px;
+ padding: var(--spacing-lg);
+ transition: all var(--transition-normal);
+ position: relative;
+ overflow: hidden;
+}
+
+.card::before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ height: 2px;
+ background: linear-gradient(90deg, var(--terminal-green), var(--cyan-blue));
+ transform: scaleX(0);
+ transition: transform var(--transition-normal);
+}
+
+.card:hover::before {
+ transform: scaleX(1);
+}
+
+.card:hover {
+ border-color: var(--terminal-green);
+ box-shadow: 0 0 20px rgba(0, 255, 65, 0.2);
+ transform: translateY(-2px);
+}
+
+/* Interactive Scroll Elements */
+.scroll-trigger {
+ opacity: 0;
+ transform: translateY(50px);
+ transition: all 0.8s cubic-bezier(0.4, 0, 0.2, 1);
+}
+
+.scroll-trigger.triggered {
+ opacity: 1;
+ transform: translateY(0);
+}
+
+/* Particle System */
+.particles {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ pointer-events: none;
+ z-index: 1;
+}
+
+.particle {
+ position: absolute;
+ width: 2px;
+ height: 2px;
+ background: var(--terminal-green);
+ border-radius: 50%;
+ animation: particle-float 8s linear infinite;
+}
+
+@keyframes particle-float {
+ 0% {
+ transform: translateY(100vh) translateX(0);
+ opacity: 0;
+ }
+ 10% {
+ opacity: 1;
+ }
+ 90% {
+ opacity: 1;
+ }
+ 100% {
+ transform: translateY(-100px) translateX(100px);
+ opacity: 0;
+ }
+}
+
+/* Responsive Design */
+@media (max-width: 768px) {
+ .section {
+ padding: var(--spacing-xl) 0;
+ }
+
+ .section-title {
+ font-size: var(--font-size-2xl);
+}
+
+ .terminal {
+ font-size: var(--font-size-small);
+ padding: var(--spacing-sm);
+ }
+}
+
+/* Scrollbar Styling */
+::-webkit-scrollbar {
+ width: 8px;
+}
+
+::-webkit-scrollbar-track {
+ background: var(--secondary-bg);
+}
+
+::-webkit-scrollbar-thumb {
+ background: var(--terminal-green);
+ border-radius: 4px;
+}
+
+::-webkit-scrollbar-thumb:hover {
+ background: var(--matrix-green);
+}
+
+/* Selection Styling */
+::selection {
+ background: var(--terminal-green);
+ color: var(--primary-bg);
+}
+
+/* Focus Styles */
+:focus {
+ outline: 2px solid var(--terminal-green);
+ outline-offset: 2px;
+}
+
+/* Loading Animation */
+.loading {
+ display: inline-block;
+ width: 20px;
+ height: 20px;
+ border: 3px solid var(--light-gray);
+ border-radius: 50%;
+ border-top-color: var(--terminal-green);
+ animation: spin 1s ease-in-out infinite;
+}
+
+@keyframes spin {
+ to { transform: rotate(360deg); }
+}
+
+/* ASCII Art */
+.ascii-art {
+ font-family: var(--font-mono);
+ white-space: pre;
+ color: var(--terminal-green);
+ text-align: center;
+ line-height: 1.2;
+}
+
+/* Command Palette */
+.command-palette {
+ position: fixed;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ background: var(--secondary-bg);
+ border: 1px solid var(--terminal-green);
+ border-radius: 8px;
+ padding: var(--spacing-lg);
+ z-index: 1000;
+ min-width: 400px;
+ box-shadow: 0 0 30px rgba(0, 255, 65, 0.3);
+}
+
+.command-palette input {
+ width: 100%;
+ background: transparent;
+ border: none;
+ color: var(--terminal-green);
+ font-family: var(--font-mono);
+ font-size: var(--font-size-base);
+ outline: none;
+ }
+
+.command-palette input::placeholder {
+ color: var(--light-gray);
+}
+
+/* Utility Classes */
+.text-green { color: var(--terminal-green); }
+.text-cyan { color: var(--cyan-blue); }
+.text-red { color: var(--error-red); }
+.text-orange { color: var(--warning-orange); }
+.text-white { color: var(--bright-white); }
+
+.bg-dark { background: var(--primary-bg); }
+.bg-secondary { background: var(--secondary-bg); }
+.bg-gray { background: var(--dark-gray); }
+
+.border-green { border-color: var(--terminal-green); }
+.border-cyan { border-color: var(--cyan-blue); }
+
+.hidden { display: none; }
+.visible { display: block; }
+
+.flex { display: flex; }
+.flex-col { flex-direction: column; }
+.items-center { align-items: center; }
+.justify-center { justify-content: center; }
+.justify-between { justify-content: space-between; }
+
+.w-full { width: 100%; }
+.h-full { height: 100%; }
+
+.text-center { text-align: center; }
+.text-left { text-align: left; }
+.text-right { text-align: right; }
+
+.mb-1 { margin-bottom: var(--spacing-xs); }
+.mb-2 { margin-bottom: var(--spacing-sm); }
+.mb-4 { margin-bottom: var(--spacing-md); }
+.mb-8 { margin-bottom: var(--spacing-lg); }
+
+.mt-1 { margin-top: var(--spacing-xs); }
+.mt-2 { margin-top: var(--spacing-sm); }
+.mt-4 { margin-top: var(--spacing-md); }
+.mt-8 { margin-top: var(--spacing-lg); }
+
+.p-1 { padding: var(--spacing-xs); }
+.p-2 { padding: var(--spacing-sm); }
+.p-4 { padding: var(--spacing-md); }
+.p-8 { padding: var(--spacing-lg); }
diff --git a/src/main.jsx b/src/main.jsx
new file mode 100644
index 0000000..b9a1a6d
--- /dev/null
+++ b/src/main.jsx
@@ -0,0 +1,10 @@
+import { StrictMode } from 'react'
+import { createRoot } from 'react-dom/client'
+import './index.css'
+import App from './App.jsx'
+
+createRoot(document.getElementById('root')).render(
+ <StrictMode>
+ <App />
+ </StrictMode>,
+)
diff --git a/src/pages/About.jsx b/src/pages/About.jsx
new file mode 100644
index 0000000..c3b4872
--- /dev/null
+++ b/src/pages/About.jsx
@@ -0,0 +1,302 @@
+import React from 'react';
+import { motion } from 'framer-motion';
+import { Heart, Shield, Users, Globe, Code, BookOpen } from 'lucide-react';
+
+const About = () => {
+ const values = [
+ {
+ icon: Heart,
+ title: 'Open Source Advocacy',
+ description: 'We believe in the power of open source software and its ability to democratize technology.',
+ color: 'text-green'
+ },
+ {
+ icon: Shield,
+ title: 'Privacy & Security',
+ description: 'Promoting digital privacy and security through open source solutions and education.',
+ color: 'text-cyan'
+ },
+ {
+ icon: Users,
+ title: 'Community Building',
+ description: 'Creating a supportive environment where students can learn, grow, and collaborate.',
+ color: 'text-green'
+ },
+ {
+ icon: Globe,
+ title: 'Global Impact',
+ description: 'Contributing to the global open source ecosystem and making technology accessible to all.',
+ color: 'text-cyan'
+ },
+ {
+ icon: Code,
+ title: 'Hands-on Learning',
+ description: 'Providing practical experience through real-world projects and coding challenges.',
+ color: 'text-green'
+ },
+ {
+ icon: BookOpen,
+ title: 'Knowledge Sharing',
+ description: 'Fostering a culture of learning and sharing knowledge with the broader community.',
+ color: 'text-cyan'
+ }
+ ];
+
+ const timeline = [
+ {
+ year: '2020',
+ title: 'Club Founded',
+ description: 'FOSSEE Club was established with the vision of promoting open source software in education.'
+ },
+ {
+ year: '2021',
+ title: 'First Workshop',
+ description: 'Conducted our first Linux workshop, introducing students to open source operating systems.'
+ },
+ {
+ year: '2022',
+ title: 'Project Contributions',
+ description: 'Started contributing to open source projects and organizing hackathons.'
+ },
+ {
+ year: '2023',
+ title: 'Community Growth',
+ description: 'Expanded our community and established partnerships with other tech clubs.'
+ },
+ {
+ year: '2024',
+ title: 'Innovation Hub',
+ description: 'Became a hub for innovation, hosting regular events and mentoring programs.'
+ }
+ ];
+
+ return (
+ <div className="min-h-screen">
+ {/* Hero Section */}
+ <section className="section relative">
+ <div className="parallax-bg"></div>
+ <div className="container mx-auto px-4">
+ <motion.div
+ initial={{ opacity: 0, y: 50 }}
+ animate={{ opacity: 1, y: 0 }}
+ transition={{ duration: 0.8 }}
+ className="text-center mb-16 scroll-fade-in"
+ >
+ <h1 className="text-4xl md:text-6xl font-bold mb-6">
+ About <span className="text-green neon-glow-green floating">FOSSEE</span>
+ </h1>
+ <p className="text-xl text-gray max-w-4xl mx-auto">
+ We are a community of passionate students dedicated to promoting Free and Open Source Software (FOSS)
+ in education. Our mission is to empower students with the knowledge and skills needed to thrive
+ in the digital age through open source technology.
+ </p>
+ </motion.div>
+ </div>
+ </section>
+
+ {/* Mission Section */}
+ <section className="section bg-secondary relative">
+ <div className="parallax-bg"></div>
+ <div className="container mx-auto px-4">
+ <motion.div
+ initial={{ opacity: 0, y: 30 }}
+ animate={{ opacity: 1, y: 0 }}
+ transition={{ duration: 0.8, delay: 0.2 }}
+ className="max-w-4xl mx-auto scroll-trigger"
+ >
+ <h2 className="section-title">Our Mission</h2>
+ <div className="terminal floating mb-8">
+ <div className="terminal-prompt">root@fossee:~$ cat mission.txt</div>
+ <div className="text-white mt-2 whitespace-pre-wrap">
+{`FOSSEE Club Mission Statement
+================================
+
+We strive to:
+
+1. EDUCATE students about the importance and benefits of open source software
+2. EMPOWER individuals with practical skills in Linux, programming, and open source tools
+3. ENCOURAGE active participation in the global open source community
+4. ENHANCE learning through hands-on projects and real-world applications
+5. ESTABLISH a supportive network of like-minded developers and enthusiasts
+
+Our vision is to create a world where technology is accessible,
+transparent, and beneficial to all through the power of open source.`}
+ </div>
+ </div>
+ </motion.div>
+ </div>
+ </section>
+
+ {/* Values Section */}
+ <section className="section relative">
+ <div className="parallax-bg"></div>
+ <div className="container mx-auto px-4">
+ <motion.div
+ initial={{ opacity: 0, y: 30 }}
+ animate={{ opacity: 1, y: 0 }}
+ transition={{ duration: 0.8, delay: 0.4 }}
+ className="scroll-trigger"
+ >
+ <h2 className="section-title">Our Values</h2>
+ <div className="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
+ {values.map((value, index) => (
+ <motion.div
+ key={index}
+ initial={{ opacity: 0, y: 20 }}
+ animate={{ opacity: 1, y: 0 }}
+ transition={{ duration: 0.5, delay: 0.1 * index }}
+ whileHover={{ y: -5 }}
+ className={`card text-center scroll-scale-in`}
+ >
+ <value.icon className={`w-12 h-12 mx-auto mb-4 ${value.color} floating`} />
+ <h3 className="text-xl font-bold mb-2 text-green">{value.title}</h3>
+ <p className="text-gray">{value.description}</p>
+ </motion.div>
+ ))}
+ </div>
+ </motion.div>
+ </div>
+ </section>
+
+ {/* FOSS Philosophy Section */}
+ <section className="section bg-secondary relative">
+ <div className="parallax-bg"></div>
+ <div className="container mx-auto px-4">
+ <motion.div
+ initial={{ opacity: 0, y: 30 }}
+ animate={{ opacity: 1, y: 0 }}
+ transition={{ duration: 0.8, delay: 0.6 }}
+ className="max-w-4xl mx-auto scroll-trigger"
+ >
+ <h2 className="section-title">FOSS Philosophy</h2>
+ <div className="grid md:grid-cols-2 gap-8">
+ <div className="card scroll-slide-left">
+ <h3 className="text-xl font-bold mb-4 text-green">The Four Freedoms</h3>
+ <div className="space-y-3">
+ <div className="flex items-start space-x-3">
+ <span className="text-green font-bold">0.</span>
+ <p>The freedom to run the program as you wish, for any purpose.</p>
+ </div>
+ <div className="flex items-start space-x-3">
+ <span className="text-green font-bold">1.</span>
+ <p>The freedom to study how the program works, and change it to make it do what you wish.</p>
+ </div>
+ <div className="flex items-start space-x-3">
+ <span className="text-green font-bold">2.</span>
+ <p>The freedom to redistribute copies so you can help others.</p>
+ </div>
+ <div className="flex items-start space-x-3">
+ <span className="text-green font-bold">3.</span>
+ <p>The freedom to distribute copies of your modified versions to others.</p>
+ </div>
+ </div>
+ </div>
+
+ <div className="card scroll-slide-right">
+ <h3 className="text-xl font-bold mb-4 text-cyan">Why Open Source?</h3>
+ <ul className="space-y-3 text-gray">
+ <li className="flex items-start space-x-2">
+ <span className="text-green">▶</span>
+ <span>Transparency and trust in software</span>
+ </li>
+ <li className="flex items-start space-x-2">
+ <span className="text-green">▶</span>
+ <span>Community-driven development</span>
+ </li>
+ <li className="flex items-start space-x-2">
+ <span className="text-green">▶</span>
+ <span>Cost-effective solutions</span>
+ </li>
+ <li className="flex items-start space-x-2">
+ <span className="text-green">▶</span>
+ <span>Freedom from vendor lock-in</span>
+ </li>
+ <li className="flex items-start space-x-2">
+ <span className="text-green">▶</span>
+ <span>Educational opportunities</span>
+ </li>
+ <li className="flex items-start space-x-2">
+ <span className="text-green">▶</span>
+ <span>Innovation through collaboration</span>
+ </li>
+ </ul>
+ </div>
+ </div>
+ </motion.div>
+ </div>
+ </section>
+
+ {/* Timeline Section */}
+ <section className="section relative">
+ <div className="parallax-bg"></div>
+ <div className="container mx-auto px-4">
+ <motion.div
+ initial={{ opacity: 0, y: 30 }}
+ animate={{ opacity: 1, y: 0 }}
+ transition={{ duration: 0.8, delay: 0.8 }}
+ className="scroll-trigger"
+ >
+ <h2 className="section-title">Our Journey</h2>
+ <div className="max-w-4xl mx-auto">
+ <div className="relative">
+ {/* Timeline Line */}
+ <div className="absolute left-8 top-0 bottom-0 w-0.5 bg-green"></div>
+
+ {timeline.map((item, index) => (
+ <motion.div
+ key={index}
+ initial={{ opacity: 0, x: -50 }}
+ animate={{ opacity: 1, x: 0 }}
+ transition={{ duration: 0.5, delay: 0.1 * index }}
+ className="relative flex items-start mb-8 scroll-fade-in"
+ >
+ {/* Timeline Dot */}
+ <div className="absolute left-6 w-4 h-4 bg-green rounded-full border-4 border-secondary floating"></div>
+
+ {/* Content */}
+ <div className="ml-16 card flex-1">
+ <div className="flex items-center justify-between mb-2">
+ <span className="text-2xl font-bold text-green">{item.year}</span>
+ <span className="text-sm text-gray">FOSSEE Club</span>
+ </div>
+ <h3 className="text-lg font-bold mb-2 text-white">{item.title}</h3>
+ <p className="text-gray">{item.description}</p>
+ </div>
+ </motion.div>
+ ))}
+ </div>
+ </div>
+ </motion.div>
+ </div>
+ </section>
+
+ {/* Join Us Section */}
+ <section className="section bg-secondary relative">
+ <div className="parallax-bg"></div>
+ <div className="container mx-auto px-4 text-center">
+ <motion.div
+ initial={{ opacity: 0, y: 30 }}
+ animate={{ opacity: 1, y: 0 }}
+ transition={{ duration: 0.8, delay: 1 }}
+ className="scroll-trigger"
+ >
+ <h2 className="text-3xl font-bold mb-4 text-green">Join Our Community</h2>
+ <p className="text-xl text-gray mb-8 max-w-2xl mx-auto">
+ Whether you're a beginner or an experienced developer, there's a place for you in our community.
+ Together, we can build a better future through open source.
+ </p>
+ <motion.button
+ whileHover={{ scale: 1.05 }}
+ whileTap={{ scale: 0.95 }}
+ className="btn text-lg px-8 py-4 floating"
+ >
+ Become a Member
+ </motion.button>
+ </motion.div>
+ </div>
+ </section>
+ </div>
+ );
+};
+
+export default About; \ No newline at end of file
diff --git a/src/pages/Contact.jsx b/src/pages/Contact.jsx
new file mode 100644
index 0000000..6aca659
--- /dev/null
+++ b/src/pages/Contact.jsx
@@ -0,0 +1,336 @@
+import React, { useState } from 'react';
+import { motion } from 'framer-motion';
+import { Mail, MapPin, Phone, Send, Github, Linkedin, MessageSquare } from 'lucide-react';
+
+const Contact = () => {
+ const [formData, setFormData] = useState({
+ name: '',
+ email: '',
+ subject: '',
+ message: ''
+ });
+ const [isSubmitting, setIsSubmitting] = useState(false);
+ const [submitStatus, setSubmitStatus] = useState(null);
+
+ const handleInputChange = (e) => {
+ const { name, value } = e.target;
+ setFormData(prev => ({
+ ...prev,
+ [name]: value
+ }));
+ };
+
+ const handleSubmit = async (e) => {
+ e.preventDefault();
+ setIsSubmitting(true);
+
+ // Simulate form submission
+ setTimeout(() => {
+ setIsSubmitting(false);
+ setSubmitStatus('success');
+ setFormData({ name: '', email: '', subject: '', message: '' });
+
+ setTimeout(() => setSubmitStatus(null), 3000);
+ }, 2000);
+ };
+
+ const contactInfo = [
+ {
+ icon: Mail,
+ title: 'Email',
+ value: 'contact@fossee-club.org',
+ link: 'mailto:contact@fossee-club.org'
+ },
+ {
+ icon: MapPin,
+ title: 'Location',
+ value: 'Computer Science Department\nUniversity Campus',
+ link: null
+ },
+ {
+ icon: Phone,
+ title: 'Phone',
+ value: '+1 (555) 123-4567',
+ link: 'tel:+15551234567'
+ }
+ ];
+
+ const socialLinks = [
+ {
+ icon: Github,
+ title: 'GitHub',
+ url: 'https://github.com/fossee-club',
+ color: 'hover:text-green'
+ },
+ {
+ icon: Linkedin,
+ title: 'LinkedIn',
+ url: 'https://linkedin.com/company/fossee-club',
+ color: 'hover:text-cyan'
+ },
+ {
+ icon: MessageSquare,
+ title: 'Discord',
+ url: 'https://discord.gg/fossee-club',
+ color: 'hover:text-green'
+ }
+ ];
+
+ return (
+ <div className="min-h-screen">
+ {/* Hero Section */}
+ <section className="section">
+ <div className="container mx-auto px-4">
+ <motion.div
+ initial={{ opacity: 0, y: 50 }}
+ animate={{ opacity: 1, y: 0 }}
+ transition={{ duration: 0.8 }}
+ className="text-center mb-16"
+ >
+ <h1 className="text-4xl md:text-6xl font-bold mb-6">
+ Get in <span className="text-green neon-glow-green">Touch</span>
+ </h1>
+ <p className="text-xl text-gray max-w-3xl mx-auto">
+ Have questions about our club, events, or projects? We'd love to hear from you!
+ Reach out to us through any of the channels below.
+ </p>
+ </motion.div>
+ </div>
+ </section>
+
+ {/* Contact Form Section */}
+ <section className="section bg-secondary">
+ <div className="container mx-auto px-4">
+ <motion.div
+ initial={{ opacity: 0, y: 30 }}
+ animate={{ opacity: 1, y: 0 }}
+ transition={{ duration: 0.8, delay: 0.2 }}
+ className="max-w-4xl mx-auto"
+ >
+ <h2 className="section-title">Send us a Message</h2>
+ <div className="grid md:grid-cols-2 gap-8">
+ {/* Contact Form */}
+ <div className="card">
+ <form onSubmit={handleSubmit} className="space-y-4">
+ <div>
+ <label className="block text-sm font-medium text-green mb-2">
+ Name
+ </label>
+ <input
+ type="text"
+ name="name"
+ value={formData.name}
+ onChange={handleInputChange}
+ required
+ className="w-full bg-transparent border border-light-gray rounded px-3 py-2 text-white focus:border-green focus:outline-none transition-colors"
+ placeholder="Your name"
+ />
+ </div>
+
+ <div>
+ <label className="block text-sm font-medium text-green mb-2">
+ Email
+ </label>
+ <input
+ type="email"
+ name="email"
+ value={formData.email}
+ onChange={handleInputChange}
+ required
+ className="w-full bg-transparent border border-light-gray rounded px-3 py-2 text-white focus:border-green focus:outline-none transition-colors"
+ placeholder="your.email@example.com"
+ />
+ </div>
+
+ <div>
+ <label className="block text-sm font-medium text-green mb-2">
+ Subject
+ </label>
+ <input
+ type="text"
+ name="subject"
+ value={formData.subject}
+ onChange={handleInputChange}
+ required
+ className="w-full bg-transparent border border-light-gray rounded px-3 py-2 text-white focus:border-green focus:outline-none transition-colors"
+ placeholder="What's this about?"
+ />
+ </div>
+
+ <div>
+ <label className="block text-sm font-medium text-green mb-2">
+ Message
+ </label>
+ <textarea
+ name="message"
+ value={formData.message}
+ onChange={handleInputChange}
+ required
+ rows={5}
+ className="w-full bg-transparent border border-light-gray rounded px-3 py-2 text-white focus:border-green focus:outline-none transition-colors resize-none"
+ placeholder="Tell us more..."
+ />
+ </div>
+
+ <motion.button
+ type="submit"
+ disabled={isSubmitting}
+ whileHover={{ scale: 1.02 }}
+ whileTap={{ scale: 0.98 }}
+ className="btn w-full flex items-center justify-center space-x-2"
+ >
+ {isSubmitting ? (
+ <>
+ <div className="loading w-4 h-4"></div>
+ <span>Sending...</span>
+ </>
+ ) : (
+ <>
+ <Send className="w-4 h-4" />
+ <span>Send Message</span>
+ </>
+ )}
+ </motion.button>
+
+ {submitStatus === 'success' && (
+ <motion.div
+ initial={{ opacity: 0, y: 10 }}
+ animate={{ opacity: 1, y: 0 }}
+ className="text-green text-center py-2"
+ >
+ ✓ Message sent successfully!
+ </motion.div>
+ )}
+ </form>
+ </div>
+
+ {/* Contact Information */}
+ <div className="space-y-6">
+ <div>
+ <h3 className="text-xl font-bold mb-4 text-green">Contact Information</h3>
+ <div className="space-y-4">
+ {contactInfo.map((info, index) => (
+ <motion.div
+ key={index}
+ initial={{ opacity: 0, x: 20 }}
+ animate={{ opacity: 1, x: 0 }}
+ transition={{ duration: 0.5, delay: 0.1 * index }}
+ className="flex items-start space-x-3"
+ >
+ <info.icon className="w-5 h-5 text-green mt-1" />
+ <div>
+ <div className="font-medium text-white">{info.title}</div>
+ {info.link ? (
+ <a
+ href={info.link}
+ className="text-gray hover:text-green transition-colors"
+ >
+ {info.value}
+ </a>
+ ) : (
+ <div className="text-gray whitespace-pre-line">{info.value}</div>
+ )}
+ </div>
+ </motion.div>
+ ))}
+ </div>
+ </div>
+
+ <div>
+ <h3 className="text-xl font-bold mb-4 text-green">Follow Us</h3>
+ <div className="flex space-x-4">
+ {socialLinks.map((social, index) => (
+ <motion.a
+ key={index}
+ href={social.url}
+ target="_blank"
+ rel="noopener noreferrer"
+ initial={{ opacity: 0, scale: 0.8 }}
+ animate={{ opacity: 1, scale: 1 }}
+ transition={{ duration: 0.5, delay: 0.2 + 0.1 * index }}
+ whileHover={{ scale: 1.1 }}
+ whileTap={{ scale: 0.9 }}
+ className={`text-gray ${social.color} transition-colors`}
+ title={social.title}
+ >
+ <social.icon className="w-6 h-6" />
+ </motion.a>
+ ))}
+ </div>
+ </div>
+ </div>
+ </div>
+ </motion.div>
+ </div>
+ </section>
+
+ {/* FAQ Section */}
+ <section className="section">
+ <div className="container mx-auto px-4">
+ <motion.div
+ initial={{ opacity: 0, y: 30 }}
+ animate={{ opacity: 1, y: 0 }}
+ transition={{ duration: 0.8, delay: 0.4 }}
+ >
+ <h2 className="section-title">Frequently Asked Questions</h2>
+ <div className="max-w-3xl mx-auto space-y-4">
+ <motion.div
+ initial={{ opacity: 0, y: 20 }}
+ animate={{ opacity: 1, y: 0 }}
+ transition={{ duration: 0.5, delay: 0.1 }}
+ className="card"
+ >
+ <h3 className="text-lg font-bold mb-2 text-green">How do I join the FOSSEE club?</h3>
+ <p className="text-gray">
+ Simply attend one of our events or workshops! We welcome students of all skill levels.
+ You can also reach out to us through the contact form above.
+ </p>
+ </motion.div>
+
+ <motion.div
+ initial={{ opacity: 0, y: 20 }}
+ animate={{ opacity: 1, y: 0 }}
+ transition={{ duration: 0.5, delay: 0.2 }}
+ className="card"
+ >
+ <h3 className="text-lg font-bold mb-2 text-green">Do I need prior experience with Linux?</h3>
+ <p className="text-gray">
+ Not at all! We have workshops and resources for complete beginners. Our community is
+ built around learning and helping each other grow.
+ </p>
+ </motion.div>
+
+ <motion.div
+ initial={{ opacity: 0, y: 20 }}
+ animate={{ opacity: 1, y: 0 }}
+ transition={{ duration: 0.5, delay: 0.3 }}
+ className="card"
+ >
+ <h3 className="text-lg font-bold mb-2 text-green">Can I contribute to open source projects?</h3>
+ <p className="text-gray">
+ Absolutely! We help students find beginner-friendly projects and guide them through
+ their first contributions. Check out our Projects page for opportunities.
+ </p>
+ </motion.div>
+
+ <motion.div
+ initial={{ opacity: 0, y: 20 }}
+ animate={{ opacity: 1, y: 0 }}
+ transition={{ duration: 0.5, delay: 0.4 }}
+ className="card"
+ >
+ <h3 className="text-lg font-bold mb-2 text-green">What events do you organize?</h3>
+ <p className="text-gray">
+ We host workshops, hackathons, coding competitions, and networking events.
+ Check our Events page for the latest schedule and upcoming activities.
+ </p>
+ </motion.div>
+ </div>
+ </motion.div>
+ </div>
+ </section>
+ </div>
+ );
+};
+
+export default Contact; \ No newline at end of file
diff --git a/src/pages/Events.jsx b/src/pages/Events.jsx
new file mode 100644
index 0000000..c24dc19
--- /dev/null
+++ b/src/pages/Events.jsx
@@ -0,0 +1,325 @@
+import React, { useState } from 'react';
+import { motion } from 'framer-motion';
+import { Calendar, Clock, MapPin, Users, Code, BookOpen, Trophy, Zap } from 'lucide-react';
+
+const Events = () => {
+ const [activeFilter, setActiveFilter] = useState('all');
+
+ const events = [
+ {
+ id: 1,
+ title: 'Linux Fundamentals Workshop',
+ type: 'workshop',
+ date: '2024-03-15',
+ time: '10:00 AM - 2:00 PM',
+ location: 'Computer Lab 101',
+ capacity: 30,
+ registered: 25,
+ description: 'Learn the basics of Linux command line, file system, and basic administration.',
+ tags: ['Linux', 'Beginner', 'Hands-on'],
+ icon: BookOpen
+ },
+ {
+ id: 2,
+ title: 'Open Source Hackathon 2024',
+ type: 'hackathon',
+ date: '2024-04-01',
+ time: '48 Hours',
+ location: 'Innovation Center',
+ capacity: 100,
+ registered: 85,
+ description: 'Build innovative solutions using open source technologies. Prizes worth $5000.',
+ tags: ['Hackathon', 'Advanced', 'Competition'],
+ icon: Code
+ },
+ {
+ id: 3,
+ title: 'Git & GitHub Masterclass',
+ type: 'workshop',
+ date: '2024-03-22',
+ time: '2:00 PM - 5:00 PM',
+ location: 'Online',
+ capacity: 50,
+ registered: 42,
+ description: 'Master version control with Git and collaboration on GitHub.',
+ tags: ['Git', 'GitHub', 'Intermediate'],
+ icon: BookOpen
+ },
+ {
+ id: 4,
+ title: 'Coding Competition: Algorithm Challenge',
+ type: 'competition',
+ date: '2024-03-30',
+ time: '3:00 PM - 6:00 PM',
+ location: 'Main Auditorium',
+ capacity: 60,
+ registered: 58,
+ description: 'Solve algorithmic problems and compete for the top spot.',
+ tags: ['Algorithms', 'Competition', 'Advanced'],
+ icon: Trophy
+ },
+ {
+ id: 5,
+ title: 'Web Development Bootcamp',
+ type: 'workshop',
+ date: '2024-04-08',
+ time: '10:00 AM - 4:00 PM',
+ location: 'Computer Lab 102',
+ capacity: 40,
+ registered: 35,
+ description: 'Build modern web applications using React, Node.js, and open source tools.',
+ tags: ['Web Dev', 'React', 'Intermediate'],
+ icon: BookOpen
+ },
+ {
+ id: 6,
+ title: 'Lightning Talks: Open Source Projects',
+ type: 'event',
+ date: '2024-04-15',
+ time: '6:00 PM - 8:00 PM',
+ location: 'Conference Room A',
+ capacity: 80,
+ registered: 65,
+ description: 'Quick presentations on interesting open source projects and contributions.',
+ tags: ['Talks', 'Projects', 'All Levels'],
+ icon: Zap
+ }
+ ];
+
+ const filters = [
+ { id: 'all', label: 'All Events', icon: Calendar },
+ { id: 'workshop', label: 'Workshops', icon: BookOpen },
+ { id: 'hackathon', label: 'Hackathons', icon: Code },
+ { id: 'competition', label: 'Competitions', icon: Trophy },
+ { id: 'event', label: 'Events', icon: Zap }
+ ];
+
+ const filteredEvents = events.filter(event =>
+ activeFilter === 'all' || event.type === activeFilter
+ );
+
+ const getTypeColor = (type) => {
+ switch (type) {
+ case 'workshop': return 'text-green';
+ case 'hackathon': return 'text-cyan';
+ case 'competition': return 'text-orange';
+ case 'event': return 'text-green';
+ default: return 'text-white';
+ }
+ };
+
+ const getProgressPercentage = (registered, capacity) => {
+ return (registered / capacity) * 100;
+ };
+
+ return (
+ <div className="min-h-screen">
+ {/* Hero Section */}
+ <section className="section">
+ <div className="container mx-auto px-4">
+ <motion.div
+ initial={{ opacity: 0, y: 50 }}
+ animate={{ opacity: 1, y: 0 }}
+ transition={{ duration: 0.8 }}
+ className="text-center mb-16"
+ >
+ <h1 className="text-4xl md:text-6xl font-bold mb-6">
+ <span className="text-green neon-glow-green">Events</span> & Activities
+ </h1>
+ <p className="text-xl text-gray max-w-3xl mx-auto">
+ Join our exciting events, workshops, and competitions. Learn, compete, and grow with the FOSSEE community.
+ </p>
+ </motion.div>
+ </div>
+ </section>
+
+ {/* Filters Section */}
+ <section className="section bg-secondary">
+ <div className="container mx-auto px-4">
+ <motion.div
+ initial={{ opacity: 0, y: 30 }}
+ animate={{ opacity: 1, y: 0 }}
+ transition={{ duration: 0.8, delay: 0.2 }}
+ >
+ <h2 className="section-title">Browse Events</h2>
+ <div className="flex flex-wrap justify-center gap-4 mb-8">
+ {filters.map((filter) => (
+ <motion.button
+ key={filter.id}
+ whileHover={{ scale: 1.05 }}
+ whileTap={{ scale: 0.95 }}
+ onClick={() => setActiveFilter(filter.id)}
+ className={`flex items-center space-x-2 px-4 py-2 rounded border transition-colors ${
+ activeFilter === filter.id
+ ? 'border-green text-green bg-green bg-opacity-10'
+ : 'border-light-gray text-gray hover:border-green hover:text-green'
+ }`}
+ >
+ <filter.icon className="w-4 h-4" />
+ <span>{filter.label}</span>
+ </motion.button>
+ ))}
+ </div>
+ </motion.div>
+ </div>
+ </section>
+
+ {/* Events Grid */}
+ <section className="section">
+ <div className="container mx-auto px-4">
+ <motion.div
+ initial={{ opacity: 0, y: 30 }}
+ animate={{ opacity: 1, y: 0 }}
+ transition={{ duration: 0.8, delay: 0.4 }}
+ className="grid md:grid-cols-2 lg:grid-cols-3 gap-8"
+ >
+ {filteredEvents.map((event, index) => (
+ <motion.div
+ key={event.id}
+ initial={{ opacity: 0, y: 20 }}
+ animate={{ opacity: 1, y: 0 }}
+ transition={{ duration: 0.5, delay: 0.1 * index }}
+ whileHover={{ y: -5 }}
+ className="card"
+ >
+ <div className="flex items-start justify-between mb-4">
+ <event.icon className={`w-8 h-8 ${getTypeColor(event.type)}`} />
+ <span className={`text-sm px-2 py-1 rounded ${getTypeColor(event.type)} bg-opacity-10`}>
+ {event.type.toUpperCase()}
+ </span>
+ </div>
+
+ <h3 className="text-xl font-bold mb-2 text-white">{event.title}</h3>
+ <p className="text-gray mb-4">{event.description}</p>
+
+ <div className="space-y-2 mb-4">
+ <div className="flex items-center space-x-2 text-sm">
+ <Calendar className="w-4 h-4 text-green" />
+ <span className="text-gray">{event.date}</span>
+ </div>
+ <div className="flex items-center space-x-2 text-sm">
+ <Clock className="w-4 h-4 text-cyan" />
+ <span className="text-gray">{event.time}</span>
+ </div>
+ <div className="flex items-center space-x-2 text-sm">
+ <MapPin className="w-4 h-4 text-green" />
+ <span className="text-gray">{event.location}</span>
+ </div>
+ <div className="flex items-center space-x-2 text-sm">
+ <Users className="w-4 h-4 text-cyan" />
+ <span className="text-gray">{event.registered}/{event.capacity} registered</span>
+ </div>
+ </div>
+
+ {/* Progress Bar */}
+ <div className="mb-4">
+ <div className="flex justify-between text-xs mb-1">
+ <span className="text-gray">Registration</span>
+ <span className="text-green">{Math.round(getProgressPercentage(event.registered, event.capacity))}%</span>
+ </div>
+ <div className="w-full bg-light-gray rounded-full h-2">
+ <div
+ className="bg-green h-2 rounded-full transition-all duration-300"
+ style={{ width: `${getProgressPercentage(event.registered, event.capacity)}%` }}
+ ></div>
+ </div>
+ </div>
+
+ {/* Tags */}
+ <div className="flex flex-wrap gap-2 mb-4">
+ {event.tags.map((tag, tagIndex) => (
+ <span
+ key={tagIndex}
+ className="text-xs px-2 py-1 bg-green bg-opacity-10 text-green rounded"
+ >
+ {tag}
+ </span>
+ ))}
+ </div>
+
+ <motion.button
+ whileHover={{ scale: 1.02 }}
+ whileTap={{ scale: 0.98 }}
+ className="btn w-full"
+ disabled={event.registered >= event.capacity}
+ >
+ {event.registered >= event.capacity ? 'Fully Booked' : 'Register Now'}
+ </motion.button>
+ </motion.div>
+ ))}
+ </motion.div>
+
+ {filteredEvents.length === 0 && (
+ <motion.div
+ initial={{ opacity: 0 }}
+ animate={{ opacity: 1 }}
+ className="text-center py-16"
+ >
+ <Calendar className="w-16 h-16 text-gray mx-auto mb-4" />
+ <h3 className="text-xl font-bold mb-2 text-gray">No Events Found</h3>
+ <p className="text-gray">Check back later for new events or try a different filter.</p>
+ </motion.div>
+ )}
+ </div>
+ </section>
+
+ {/* Upcoming Highlights */}
+ <section className="section bg-secondary">
+ <div className="container mx-auto px-4">
+ <motion.div
+ initial={{ opacity: 0, y: 30 }}
+ animate={{ opacity: 1, y: 0 }}
+ transition={{ duration: 0.8, delay: 0.6 }}
+ >
+ <h2 className="section-title">Upcoming Highlights</h2>
+ <div className="grid md:grid-cols-2 gap-8">
+ <div className="card">
+ <div className="flex items-center space-x-4 mb-4">
+ <Trophy className="w-12 h-12 text-orange" />
+ <div>
+ <h3 className="text-xl font-bold text-white">Annual Hackathon</h3>
+ <p className="text-gray">April 1-3, 2024</p>
+ </div>
+ </div>
+ <p className="text-gray mb-4">
+ Our biggest event of the year! 48 hours of coding, innovation, and collaboration.
+ Build something amazing with open source technologies.
+ </p>
+ <motion.button
+ whileHover={{ scale: 1.05 }}
+ whileTap={{ scale: 0.95 }}
+ className="btn"
+ >
+ Learn More
+ </motion.button>
+ </div>
+
+ <div className="card">
+ <div className="flex items-center space-x-4 mb-4">
+ <BookOpen className="w-12 h-12 text-green" />
+ <div>
+ <h3 className="text-xl font-bold text-white">Linux Workshop Series</h3>
+ <p className="text-gray">Every Saturday</p>
+ </div>
+ </div>
+ <p className="text-gray mb-4">
+ Weekly hands-on workshops covering Linux administration, shell scripting,
+ and system administration. Perfect for beginners and intermediate users.
+ </p>
+ <motion.button
+ whileHover={{ scale: 1.05 }}
+ whileTap={{ scale: 0.95 }}
+ className="btn"
+ >
+ View Schedule
+ </motion.button>
+ </div>
+ </div>
+ </motion.div>
+ </div>
+ </section>
+ </div>
+ );
+};
+
+export default Events; \ No newline at end of file
diff --git a/src/pages/Home.jsx b/src/pages/Home.jsx
new file mode 100644
index 0000000..51acb03
--- /dev/null
+++ b/src/pages/Home.jsx
@@ -0,0 +1,58 @@
+import React from 'react';
+import { motion } from 'framer-motion';
+import { TypeAnimation } from 'react-type-animation';
+import Terminal from '../components/Terminal';
+
+const Home = () => {
+ const asciiArt = `
+ ███████╗ ██████╗ ███████╗███████╗ ███████╗██╗ ██╗███████╗ █████╗ ████████╗
+ ██╔════╝██╔═══██╗██╔════╝██╔════╝ ██╔════╝██║ ██║██╔════╝██╔══██╗╚══██╔══╝
+ █████╗ ██║ ██║███████╗███████╗ ██║ ██║ ██║███████╗███████║ ██║
+ ██╔══╝ ██║ ██║╚════██║╚════██║ ██║ ██║ ██║╚════██║██╔══██║ ██║
+ ██║ ╚██████╔╝███████║███████║ ╚██████╗╚██████╔╝███████║██║ ██║ ██║
+ ╚═╝ ╚═════╝ ╚══════╝╚══════╝ ╚═════╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝ ╚═╝
+ `;
+
+ return (
+ <div className="min-h-screen">
+ {/* Hero Section */}
+ <section className="section relative" id="home">
+ <div className="parallax-bg"></div>
+ <div className="container mx-auto px-4">
+ <motion.div
+ initial={{ opacity: 0, y: 50 }}
+ animate={{ opacity: 1, y: 0 }}
+ transition={{ duration: 0.8 }}
+ className="text-center mb-16"
+ >
+ <div className="ascii-art mb-8 floating">
+ {asciiArt}
+ </div>
+
+ <h1 className="text-4xl md:text-6xl font-bold mb-6 scroll-fade-in">
+ <span className="text-green neon-glow-green">FOSS CUSAT</span>
+ <br />
+ <TypeAnimation
+ sequence={[
+ 'Free and Open Source Software for Education',
+ 2000,
+ 'Empowering Students Through Open Source',
+ 2000,
+ 'Building the Future of Technology',
+ 2000,
+ ]}
+ wrapper="span"
+ speed={50}
+ className="text-cyan neon-glow-cyan"
+ repeat={Infinity}
+ />
+ </h1>
+ </motion.div>
+ </div>
+ </section>
+ <Terminal />
+ </div>
+ );
+};
+
+export default Home; \ No newline at end of file
diff --git a/src/pages/Projects.jsx b/src/pages/Projects.jsx
new file mode 100644
index 0000000..6aeabe3
--- /dev/null
+++ b/src/pages/Projects.jsx
@@ -0,0 +1,309 @@
+import React, { useState } from 'react';
+import { motion } from 'framer-motion';
+import { Code, Github, ExternalLink, Star, GitBranch, Users, Calendar } from 'lucide-react';
+
+const Projects = () => {
+ const [activeFilter, setActiveFilter] = useState('all');
+
+ const projects = [
+ {
+ id: 1,
+ title: 'FOSSEE Website',
+ description: 'Modern website for the FOSSEE club built with React and Vite. Features terminal interface and dark theme.',
+ category: 'web',
+ tech: ['React', 'Vite', 'CSS3', 'JavaScript'],
+ github: 'https://github.com/fossee-club/website',
+ live: 'https://fossee-club.org',
+ stars: 45,
+ forks: 12,
+ contributors: 8,
+ lastUpdated: '2024-03-10',
+ status: 'active'
+ },
+ {
+ id: 2,
+ title: 'Linux Command Trainer',
+ description: 'Interactive web application to learn Linux commands through hands-on exercises and challenges.',
+ category: 'education',
+ tech: ['Python', 'Flask', 'JavaScript', 'SQLite'],
+ github: 'https://github.com/fossee-club/linux-trainer',
+ live: 'https://linux-trainer.fossee.org',
+ stars: 23,
+ forks: 5,
+ contributors: 4,
+ lastUpdated: '2024-03-08',
+ status: 'active'
+ },
+ {
+ id: 3,
+ title: 'Open Source Project Finder',
+ description: 'Tool to help students find beginner-friendly open source projects to contribute to.',
+ category: 'tool',
+ tech: ['Node.js', 'Express', 'MongoDB', 'React'],
+ github: 'https://github.com/fossee-club/project-finder',
+ live: 'https://project-finder.fossee.org',
+ stars: 67,
+ forks: 15,
+ contributors: 12,
+ lastUpdated: '2024-03-05',
+ status: 'active'
+ },
+ {
+ id: 4,
+ title: 'FOSSEE Mobile App',
+ description: 'Mobile application for FOSSEE club members to stay updated with events and projects.',
+ category: 'mobile',
+ tech: ['React Native', 'Firebase', 'Redux', 'TypeScript'],
+ github: 'https://github.com/fossee-club/mobile-app',
+ live: null,
+ stars: 34,
+ forks: 8,
+ contributors: 6,
+ lastUpdated: '2024-03-01',
+ status: 'development'
+ },
+ {
+ id: 5,
+ title: 'Code Review Bot',
+ description: 'Automated code review bot for GitHub repositories with focus on open source best practices.',
+ category: 'tool',
+ tech: ['Python', 'GitHub API', 'Docker', 'PostgreSQL'],
+ github: 'https://github.com/fossee-club/code-review-bot',
+ live: null,
+ stars: 89,
+ forks: 22,
+ contributors: 15,
+ lastUpdated: '2024-02-28',
+ status: 'active'
+ },
+ {
+ id: 6,
+ title: 'Linux Distro Comparison',
+ description: 'Interactive comparison tool for different Linux distributions with detailed analysis.',
+ category: 'education',
+ tech: ['Vue.js', 'D3.js', 'Node.js', 'MongoDB'],
+ github: 'https://github.com/fossee-club/distro-compare',
+ live: 'https://distro-compare.fossee.org',
+ stars: 56,
+ forks: 11,
+ contributors: 9,
+ lastUpdated: '2024-02-25',
+ status: 'active'
+ }
+ ];
+
+ const categories = [
+ { id: 'all', label: 'All Projects', color: 'text-white' },
+ { id: 'web', label: 'Web Apps', color: 'text-green' },
+ { id: 'mobile', label: 'Mobile Apps', color: 'text-cyan' },
+ { id: 'tool', label: 'Tools', color: 'text-orange' },
+ { id: 'education', label: 'Education', color: 'text-green' }
+ ];
+
+ const filteredProjects = projects.filter(project =>
+ activeFilter === 'all' || project.category === activeFilter
+ );
+
+ const getStatusColor = (status) => {
+ switch (status) {
+ case 'active': return 'text-green';
+ case 'development': return 'text-orange';
+ case 'archived': return 'text-gray';
+ default: return 'text-white';
+ }
+ };
+
+ return (
+ <div className="min-h-screen">
+ {/* Hero Section */}
+ <section className="section">
+ <div className="container mx-auto px-4">
+ <motion.div
+ initial={{ opacity: 0, y: 50 }}
+ animate={{ opacity: 1, y: 0 }}
+ transition={{ duration: 0.8 }}
+ className="text-center mb-16"
+ >
+ <h1 className="text-4xl md:text-6xl font-bold mb-6">
+ <span className="text-green neon-glow-green">Projects</span> & Contributions
+ </h1>
+ <p className="text-xl text-gray max-w-3xl mx-auto">
+ Explore our open source projects, member contributions, and innovative solutions built by the FOSSEE community.
+ </p>
+ </motion.div>
+ </div>
+ </section>
+
+ {/* Filters Section */}
+ <section className="section bg-secondary">
+ <div className="container mx-auto px-4">
+ <motion.div
+ initial={{ opacity: 0, y: 30 }}
+ animate={{ opacity: 1, y: 0 }}
+ transition={{ duration: 0.8, delay: 0.2 }}
+ >
+ <h2 className="section-title">Browse Projects</h2>
+ <div className="flex flex-wrap justify-center gap-4 mb-8">
+ {categories.map((category) => (
+ <motion.button
+ key={category.id}
+ whileHover={{ scale: 1.05 }}
+ whileTap={{ scale: 0.95 }}
+ onClick={() => setActiveFilter(category.id)}
+ className={`flex items-center space-x-2 px-4 py-2 rounded border transition-colors ${
+ activeFilter === category.id
+ ? 'border-green text-green bg-green bg-opacity-10'
+ : 'border-light-gray text-gray hover:border-green hover:text-green'
+ }`}
+ >
+ <Code className="w-4 h-4" />
+ <span>{category.label}</span>
+ </motion.button>
+ ))}
+ </div>
+ </motion.div>
+ </div>
+ </section>
+
+ {/* Projects Grid */}
+ <section className="section">
+ <div className="container mx-auto px-4">
+ <motion.div
+ initial={{ opacity: 0, y: 30 }}
+ animate={{ opacity: 1, y: 0 }}
+ transition={{ duration: 0.8, delay: 0.4 }}
+ className="grid md:grid-cols-2 lg:grid-cols-3 gap-8"
+ >
+ {filteredProjects.map((project, index) => (
+ <motion.div
+ key={project.id}
+ initial={{ opacity: 0, y: 20 }}
+ animate={{ opacity: 1, y: 0 }}
+ transition={{ duration: 0.5, delay: 0.1 * index }}
+ whileHover={{ y: -5 }}
+ className="card"
+ >
+ <div className="flex items-start justify-between mb-4">
+ <Code className="w-8 h-8 text-green" />
+ <span className={`text-sm px-2 py-1 rounded ${getStatusColor(project.status)} bg-opacity-10`}>
+ {project.status.toUpperCase()}
+ </span>
+ </div>
+
+ <h3 className="text-xl font-bold mb-2 text-white">{project.title}</h3>
+ <p className="text-gray mb-4">{project.description}</p>
+
+ {/* Tech Stack */}
+ <div className="flex flex-wrap gap-2 mb-4">
+ {project.tech.map((tech, techIndex) => (
+ <span
+ key={techIndex}
+ className="text-xs px-2 py-1 bg-cyan bg-opacity-10 text-cyan rounded"
+ >
+ {tech}
+ </span>
+ ))}
+ </div>
+
+ {/* Stats */}
+ <div className="grid grid-cols-3 gap-4 mb-4 text-center">
+ <div className="flex items-center justify-center space-x-1">
+ <Star className="w-4 h-4 text-green" />
+ <span className="text-sm text-gray">{project.stars}</span>
+ </div>
+ <div className="flex items-center justify-center space-x-1">
+ <GitBranch className="w-4 h-4 text-cyan" />
+ <span className="text-sm text-gray">{project.forks}</span>
+ </div>
+ <div className="flex items-center justify-center space-x-1">
+ <Users className="w-4 h-4 text-green" />
+ <span className="text-sm text-gray">{project.contributors}</span>
+ </div>
+ </div>
+
+ {/* Last Updated */}
+ <div className="flex items-center space-x-2 text-sm text-gray mb-4">
+ <Calendar className="w-4 h-4" />
+ <span>Updated {project.lastUpdated}</span>
+ </div>
+
+ {/* Action Buttons */}
+ <div className="flex space-x-2">
+ <motion.a
+ href={project.github}
+ target="_blank"
+ rel="noopener noreferrer"
+ whileHover={{ scale: 1.02 }}
+ whileTap={{ scale: 0.98 }}
+ className="flex-1 btn flex items-center justify-center space-x-2"
+ >
+ <Github className="w-4 h-4" />
+ <span>View Code</span>
+ </motion.a>
+ {project.live && (
+ <motion.a
+ href={project.live}
+ target="_blank"
+ rel="noopener noreferrer"
+ whileHover={{ scale: 1.02 }}
+ whileTap={{ scale: 0.98 }}
+ className="btn flex items-center justify-center space-x-2"
+ >
+ <ExternalLink className="w-4 h-4" />
+ <span>Live Demo</span>
+ </motion.a>
+ )}
+ </div>
+ </motion.div>
+ ))}
+ </motion.div>
+
+ {filteredProjects.length === 0 && (
+ <motion.div
+ initial={{ opacity: 0 }}
+ animate={{ opacity: 1 }}
+ className="text-center py-16"
+ >
+ <Code className="w-16 h-16 text-gray mx-auto mb-4" />
+ <h3 className="text-xl font-bold mb-2 text-gray">No Projects Found</h3>
+ <p className="text-gray">Check back later for new projects or try a different filter.</p>
+ </motion.div>
+ )}
+ </div>
+ </section>
+
+ {/* Contribution Stats */}
+ <section className="section bg-secondary">
+ <div className="container mx-auto px-4">
+ <motion.div
+ initial={{ opacity: 0, y: 30 }}
+ animate={{ opacity: 1, y: 0 }}
+ transition={{ duration: 0.8, delay: 0.6 }}
+ >
+ <h2 className="section-title">Our Impact</h2>
+ <div className="grid md:grid-cols-4 gap-8">
+ <div className="text-center">
+ <div className="text-4xl font-bold text-green mb-2">15+</div>
+ <div className="text-gray">Open Source Projects</div>
+ </div>
+ <div className="text-center">
+ <div className="text-4xl font-bold text-cyan mb-2">500+</div>
+ <div className="text-gray">GitHub Stars</div>
+ </div>
+ <div className="text-center">
+ <div className="text-4xl font-bold text-green mb-2">50+</div>
+ <div className="text-gray">Active Contributors</div>
+ </div>
+ <div className="text-center">
+ <div className="text-4xl font-bold text-cyan mb-2">1000+</div>
+ <div className="text-gray">Lines of Code</div>
+ </div>
+ </div>
+ </motion.div>
+ </div>
+ </section>
+ </div>
+ );
+};
+
+export default Projects; \ No newline at end of file
diff --git a/src/pages/Resources.jsx b/src/pages/Resources.jsx
new file mode 100644
index 0000000..ad5de73
--- /dev/null
+++ b/src/pages/Resources.jsx
@@ -0,0 +1,323 @@
+import React, { useState } from 'react';
+import { motion } from 'framer-motion';
+import { BookOpen, Code, Terminal, FileText, Video, Download, ExternalLink } from 'lucide-react';
+
+const Resources = () => {
+ const [activeFilter, setActiveFilter] = useState('all');
+
+ const resources = [
+ {
+ id: 1,
+ title: 'Linux Command Line Basics',
+ description: 'Complete guide to essential Linux commands for beginners.',
+ category: 'linux',
+ type: 'tutorial',
+ difficulty: 'beginner',
+ duration: '2 hours',
+ format: 'pdf',
+ downloadUrl: '/resources/linux-basics.pdf',
+ externalUrl: 'https://linuxjourney.com',
+ icon: Terminal
+ },
+ {
+ id: 2,
+ title: 'Git & GitHub Mastery',
+ description: 'Learn version control with Git and collaboration on GitHub.',
+ category: 'git',
+ type: 'video',
+ difficulty: 'intermediate',
+ duration: '3 hours',
+ format: 'video',
+ downloadUrl: null,
+ externalUrl: 'https://youtube.com/watch?v=git-tutorial',
+ icon: Code
+ },
+ {
+ id: 3,
+ title: 'Open Source Contribution Guide',
+ description: 'Step-by-step guide to contributing to open source projects.',
+ category: 'opensource',
+ type: 'guide',
+ difficulty: 'intermediate',
+ duration: '1 hour',
+ format: 'web',
+ downloadUrl: null,
+ externalUrl: 'https://opensource.guide',
+ icon: BookOpen
+ },
+ {
+ id: 4,
+ title: 'Python for Beginners',
+ description: 'Learn Python programming from scratch with hands-on exercises.',
+ category: 'programming',
+ type: 'course',
+ difficulty: 'beginner',
+ duration: '8 hours',
+ format: 'interactive',
+ downloadUrl: '/resources/python-course.zip',
+ externalUrl: 'https://python.org/tutorial',
+ icon: Code
+ },
+ {
+ id: 5,
+ title: 'Web Development with React',
+ description: 'Build modern web applications using React and open source tools.',
+ category: 'webdev',
+ type: 'tutorial',
+ difficulty: 'advanced',
+ duration: '6 hours',
+ format: 'video',
+ downloadUrl: null,
+ externalUrl: 'https://react.dev/learn',
+ icon: Code
+ },
+ {
+ id: 6,
+ title: 'Linux System Administration',
+ description: 'Advanced Linux administration and server management.',
+ category: 'linux',
+ type: 'course',
+ difficulty: 'advanced',
+ duration: '12 hours',
+ format: 'pdf',
+ downloadUrl: '/resources/linux-admin.pdf',
+ externalUrl: 'https://linuxacademy.com',
+ icon: Terminal
+ }
+ ];
+
+ const categories = [
+ { id: 'all', label: 'All Resources', icon: BookOpen },
+ { id: 'linux', label: 'Linux', icon: Terminal },
+ { id: 'programming', label: 'Programming', icon: Code },
+ { id: 'git', label: 'Git & GitHub', icon: Code },
+ { id: 'opensource', label: 'Open Source', icon: BookOpen },
+ { id: 'webdev', label: 'Web Development', icon: Code }
+ ];
+
+ const filteredResources = resources.filter(resource =>
+ activeFilter === 'all' || resource.category === activeFilter
+ );
+
+ const getDifficultyColor = (difficulty) => {
+ switch (difficulty) {
+ case 'beginner': return 'text-green';
+ case 'intermediate': return 'text-orange';
+ case 'advanced': return 'text-red';
+ default: return 'text-white';
+ }
+ };
+
+ const getFormatIcon = (format) => {
+ switch (format) {
+ case 'pdf': return FileText;
+ case 'video': return Video;
+ case 'web': return ExternalLink;
+ case 'interactive': return Code;
+ default: return BookOpen;
+ }
+ };
+
+ return (
+ <div className="min-h-screen">
+ {/* Hero Section */}
+ <section className="section">
+ <div className="container mx-auto px-4">
+ <motion.div
+ initial={{ opacity: 0, y: 50 }}
+ animate={{ opacity: 1, y: 0 }}
+ transition={{ duration: 0.8 }}
+ className="text-center mb-16"
+ >
+ <h1 className="text-4xl md:text-6xl font-bold mb-6">
+ <span className="text-green neon-glow-green">Resources</span> & Learning
+ </h1>
+ <p className="text-xl text-gray max-w-3xl mx-auto">
+ Access our curated collection of tutorials, guides, and documentation to enhance your skills
+ in Linux, programming, and open source development.
+ </p>
+ </motion.div>
+ </div>
+ </section>
+
+ {/* Filters Section */}
+ <section className="section bg-secondary">
+ <div className="container mx-auto px-4">
+ <motion.div
+ initial={{ opacity: 0, y: 30 }}
+ animate={{ opacity: 1, y: 0 }}
+ transition={{ duration: 0.8, delay: 0.2 }}
+ >
+ <h2 className="section-title">Browse Resources</h2>
+ <div className="flex flex-wrap justify-center gap-4 mb-8">
+ {categories.map((category) => (
+ <motion.button
+ key={category.id}
+ whileHover={{ scale: 1.05 }}
+ whileTap={{ scale: 0.95 }}
+ onClick={() => setActiveFilter(category.id)}
+ className={`flex items-center space-x-2 px-4 py-2 rounded border transition-colors ${
+ activeFilter === category.id
+ ? 'border-green text-green bg-green bg-opacity-10'
+ : 'border-light-gray text-gray hover:border-green hover:text-green'
+ }`}
+ >
+ <category.icon className="w-4 h-4" />
+ <span>{category.label}</span>
+ </motion.button>
+ ))}
+ </div>
+ </motion.div>
+ </div>
+ </section>
+
+ {/* Resources Grid */}
+ <section className="section">
+ <div className="container mx-auto px-4">
+ <motion.div
+ initial={{ opacity: 0, y: 30 }}
+ animate={{ opacity: 1, y: 0 }}
+ transition={{ duration: 0.8, delay: 0.4 }}
+ className="grid md:grid-cols-2 lg:grid-cols-3 gap-8"
+ >
+ {filteredResources.map((resource, index) => (
+ <motion.div
+ key={resource.id}
+ initial={{ opacity: 0, y: 20 }}
+ animate={{ opacity: 1, y: 0 }}
+ transition={{ duration: 0.5, delay: 0.1 * index }}
+ whileHover={{ y: -5 }}
+ className="card"
+ >
+ <div className="flex items-start justify-between mb-4">
+ <resource.icon className="w-8 h-8 text-green" />
+ <span className={`text-sm px-2 py-1 rounded ${getDifficultyColor(resource.difficulty)} bg-opacity-10`}>
+ {resource.difficulty.toUpperCase()}
+ </span>
+ </div>
+
+ <h3 className="text-xl font-bold mb-2 text-white">{resource.title}</h3>
+ <p className="text-gray mb-4">{resource.description}</p>
+
+ <div className="space-y-2 mb-4">
+ <div className="flex items-center space-x-2 text-sm">
+ <BookOpen className="w-4 h-4 text-green" />
+ <span className="text-gray">{resource.type}</span>
+ </div>
+ <div className="flex items-center space-x-2 text-sm">
+ <Video className="w-4 h-4 text-cyan" />
+ <span className="text-gray">{resource.duration}</span>
+ </div>
+ </div>
+
+ {/* Action Buttons */}
+ <div className="flex space-x-2">
+ {resource.downloadUrl && (
+ <motion.a
+ href={resource.downloadUrl}
+ whileHover={{ scale: 1.02 }}
+ whileTap={{ scale: 0.98 }}
+ className="flex-1 btn flex items-center justify-center space-x-2"
+ >
+ <Download className="w-4 h-4" />
+ <span>Download</span>
+ </motion.a>
+ )}
+ {resource.externalUrl && (
+ <motion.a
+ href={resource.externalUrl}
+ target="_blank"
+ rel="noopener noreferrer"
+ whileHover={{ scale: 1.02 }}
+ whileTap={{ scale: 0.98 }}
+ className={`btn flex items-center justify-center space-x-2 ${!resource.downloadUrl ? 'flex-1' : ''}`}
+ >
+ <ExternalLink className="w-4 h-4" />
+ <span>View</span>
+ </motion.a>
+ )}
+ </div>
+ </motion.div>
+ ))}
+ </motion.div>
+
+ {filteredResources.length === 0 && (
+ <motion.div
+ initial={{ opacity: 0 }}
+ animate={{ opacity: 1 }}
+ className="text-center py-16"
+ >
+ <BookOpen className="w-16 h-16 text-gray mx-auto mb-4" />
+ <h3 className="text-xl font-bold mb-2 text-gray">No Resources Found</h3>
+ <p className="text-gray">Check back later for new resources or try a different filter.</p>
+ </motion.div>
+ )}
+ </div>
+ </section>
+
+ {/* Quick Links Section */}
+ <section className="section bg-secondary">
+ <div className="container mx-auto px-4">
+ <motion.div
+ initial={{ opacity: 0, y: 30 }}
+ animate={{ opacity: 1, y: 0 }}
+ transition={{ duration: 0.8, delay: 0.6 }}
+ >
+ <h2 className="section-title">Quick Links</h2>
+ <div className="grid md:grid-cols-2 lg:grid-cols-4 gap-6">
+ <motion.a
+ href="https://linuxjourney.com"
+ target="_blank"
+ rel="noopener noreferrer"
+ whileHover={{ y: -5 }}
+ className="card text-center"
+ >
+ <Terminal className="w-12 h-12 text-green mx-auto mb-4" />
+ <h3 className="text-lg font-bold mb-2 text-white">Linux Journey</h3>
+ <p className="text-gray text-sm">Interactive Linux learning platform</p>
+ </motion.a>
+
+ <motion.a
+ href="https://github.com"
+ target="_blank"
+ rel="noopener noreferrer"
+ whileHover={{ y: -5 }}
+ className="card text-center"
+ >
+ <Code className="w-12 h-12 text-cyan mx-auto mb-4" />
+ <h3 className="text-lg font-bold mb-2 text-white">GitHub</h3>
+ <p className="text-gray text-sm">Discover and contribute to projects</p>
+ </motion.a>
+
+ <motion.a
+ href="https://stackoverflow.com"
+ target="_blank"
+ rel="noopener noreferrer"
+ whileHover={{ y: -5 }}
+ className="card text-center"
+ >
+ <BookOpen className="w-12 h-12 text-green mx-auto mb-4" />
+ <h3 className="text-lg font-bold mb-2 text-white">Stack Overflow</h3>
+ <p className="text-gray text-sm">Programming Q&A community</p>
+ </motion.a>
+
+ <motion.a
+ href="https://opensource.guide"
+ target="_blank"
+ rel="noopener noreferrer"
+ whileHover={{ y: -5 }}
+ className="card text-center"
+ >
+ <FileText className="w-12 h-12 text-cyan mx-auto mb-4" />
+ <h3 className="text-lg font-bold mb-2 text-white">Open Source Guide</h3>
+ <p className="text-gray text-sm">How to contribute to open source</p>
+ </motion.a>
+ </div>
+ </motion.div>
+ </div>
+ </section>
+ </div>
+ );
+};
+
+export default Resources; \ No newline at end of file
diff --git a/src/pages/Team.jsx b/src/pages/Team.jsx
new file mode 100644
index 0000000..9305f07
--- /dev/null
+++ b/src/pages/Team.jsx
@@ -0,0 +1,257 @@
+import React from 'react';
+import { motion } from 'framer-motion';
+import { Users, Github, Linkedin, Mail, Code, Terminal, BookOpen, Shield } from 'lucide-react';
+
+const Team = () => {
+ const team = [
+ {
+ id: 1,
+ name: 'Alex Chen',
+ role: 'Club President',
+ bio: 'Linux enthusiast and open source advocate. Passionate about making technology accessible to everyone.',
+ avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=Alex',
+ github: 'https://github.com/alexchen',
+ linkedin: 'https://linkedin.com/in/alexchen',
+ email: 'alex@fossee-club.org',
+ skills: ['Linux', 'Python', 'DevOps'],
+ icon: Shield
+ },
+ {
+ id: 2,
+ name: 'Sarah Kim',
+ role: 'Vice President',
+ bio: 'Full-stack developer with expertise in React and Node.js. Loves mentoring new developers.',
+ avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=Sarah',
+ github: 'https://github.com/sarahkim',
+ linkedin: 'https://linkedin.com/in/sarahkim',
+ email: 'sarah@fossee-club.org',
+ skills: ['React', 'Node.js', 'TypeScript'],
+ icon: Code
+ },
+ {
+ id: 3,
+ name: 'Marcus Rodriguez',
+ role: 'Technical Lead',
+ bio: 'System administrator and security expert. Specializes in Linux server management and cybersecurity.',
+ avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=Marcus',
+ github: 'https://github.com/marcusrod',
+ linkedin: 'https://linkedin.com/in/marcusrod',
+ email: 'marcus@fossee-club.org',
+ skills: ['Linux Admin', 'Security', 'Bash'],
+ icon: Terminal
+ },
+ {
+ id: 4,
+ name: 'Emma Thompson',
+ role: 'Education Coordinator',
+ bio: 'Dedicated to creating engaging learning experiences and fostering a supportive community.',
+ avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=Emma',
+ github: 'https://github.com/emmathompson',
+ linkedin: 'https://linkedin.com/in/emmathompson',
+ email: 'emma@fossee-club.org',
+ skills: ['Teaching', 'Python', 'Git'],
+ icon: BookOpen
+ },
+ {
+ id: 5,
+ name: 'David Park',
+ role: 'Events Manager',
+ bio: 'Organizes workshops, hackathons, and community events. Passionate about bringing people together.',
+ avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=David',
+ github: 'https://github.com/davidpark',
+ linkedin: 'https://linkedin.com/in/davidpark',
+ email: 'david@fossee-club.org',
+ skills: ['Event Planning', 'JavaScript', 'Docker'],
+ icon: Users
+ },
+ {
+ id: 6,
+ name: 'Lisa Wang',
+ role: 'Outreach Coordinator',
+ bio: 'Builds partnerships with other tech communities and promotes open source values.',
+ avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=Lisa',
+ github: 'https://github.com/lisawang',
+ linkedin: 'https://linkedin.com/in/lisawang',
+ email: 'lisa@fossee-club.org',
+ skills: ['Networking', 'Python', 'Open Source'],
+ icon: Users
+ }
+ ];
+
+ const stats = [
+ { label: 'Active Members', value: '50+', icon: Users },
+ { label: 'Projects Led', value: '15+', icon: Code },
+ { label: 'Workshops Conducted', value: '25+', icon: BookOpen },
+ { label: 'Years Combined Experience', value: '50+', icon: Shield }
+ ];
+
+ return (
+ <div className="min-h-screen">
+ {/* Hero Section */}
+ <section className="section">
+ <div className="container mx-auto px-4">
+ <motion.div
+ initial={{ opacity: 0, y: 50 }}
+ animate={{ opacity: 1, y: 0 }}
+ transition={{ duration: 0.8 }}
+ className="text-center mb-16"
+ >
+ <h1 className="text-4xl md:text-6xl font-bold mb-6">
+ Meet Our <span className="text-green neon-glow-green">Team</span>
+ </h1>
+ <p className="text-xl text-gray max-w-3xl mx-auto">
+ Get to know the passionate individuals who drive the FOSSEE club forward.
+ Our team brings together diverse skills and experiences to create an amazing community.
+ </p>
+ </motion.div>
+ </div>
+ </section>
+
+ {/* Stats Section */}
+ <section className="section bg-secondary">
+ <div className="container mx-auto px-4">
+ <motion.div
+ initial={{ opacity: 0, y: 30 }}
+ animate={{ opacity: 1, y: 0 }}
+ transition={{ duration: 0.8, delay: 0.2 }}
+ >
+ <h2 className="section-title">Our Impact</h2>
+ <div className="grid md:grid-cols-4 gap-8">
+ {stats.map((stat, index) => (
+ <motion.div
+ key={index}
+ initial={{ opacity: 0, y: 20 }}
+ animate={{ opacity: 1, y: 0 }}
+ transition={{ duration: 0.5, delay: 0.1 * index }}
+ className="text-center"
+ >
+ <stat.icon className="w-12 h-12 text-green mx-auto mb-4" />
+ <div className="text-3xl font-bold text-green mb-2">{stat.value}</div>
+ <div className="text-gray">{stat.label}</div>
+ </motion.div>
+ ))}
+ </div>
+ </motion.div>
+ </div>
+ </section>
+
+ {/* Team Grid */}
+ <section className="section">
+ <div className="container mx-auto px-4">
+ <motion.div
+ initial={{ opacity: 0, y: 30 }}
+ animate={{ opacity: 1, y: 0 }}
+ transition={{ duration: 0.8, delay: 0.4 }}
+ >
+ <h2 className="section-title">Leadership Team</h2>
+ <div className="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
+ {team.map((member, index) => (
+ <motion.div
+ key={member.id}
+ initial={{ opacity: 0, y: 20 }}
+ animate={{ opacity: 1, y: 0 }}
+ transition={{ duration: 0.5, delay: 0.1 * index }}
+ whileHover={{ y: -5 }}
+ className="card text-center"
+ >
+ <div className="mb-6">
+ <img
+ src={member.avatar}
+ alt={member.name}
+ className="w-24 h-24 rounded-full mx-auto mb-4 border-2 border-green"
+ />
+ <h3 className="text-xl font-bold mb-1 text-white">{member.name}</h3>
+ <p className="text-green font-semibold mb-2">{member.role}</p>
+ <p className="text-gray text-sm mb-4">{member.bio}</p>
+ </div>
+
+ {/* Skills */}
+ <div className="flex flex-wrap justify-center gap-2 mb-6">
+ {member.skills.map((skill, skillIndex) => (
+ <span
+ key={skillIndex}
+ className="text-xs px-2 py-1 bg-cyan bg-opacity-10 text-cyan rounded"
+ >
+ {skill}
+ </span>
+ ))}
+ </div>
+
+ {/* Social Links */}
+ <div className="flex justify-center space-x-4">
+ <motion.a
+ href={member.github}
+ target="_blank"
+ rel="noopener noreferrer"
+ whileHover={{ scale: 1.1 }}
+ whileTap={{ scale: 0.9 }}
+ className="text-gray hover:text-green transition-colors"
+ title="GitHub"
+ >
+ <Github className="w-5 h-5" />
+ </motion.a>
+ <motion.a
+ href={member.linkedin}
+ target="_blank"
+ rel="noopener noreferrer"
+ whileHover={{ scale: 1.1 }}
+ whileTap={{ scale: 0.9 }}
+ className="text-gray hover:text-cyan transition-colors"
+ title="LinkedIn"
+ >
+ <Linkedin className="w-5 h-5" />
+ </motion.a>
+ <motion.a
+ href={`mailto:${member.email}`}
+ whileHover={{ scale: 1.1 }}
+ whileTap={{ scale: 0.9 }}
+ className="text-gray hover:text-green transition-colors"
+ title="Email"
+ >
+ <Mail className="w-5 h-5" />
+ </motion.a>
+ </div>
+ </motion.div>
+ ))}
+ </div>
+ </motion.div>
+ </div>
+ </section>
+
+ {/* Join Team Section */}
+ <section className="section bg-secondary">
+ <div className="container mx-auto px-4 text-center">
+ <motion.div
+ initial={{ opacity: 0, y: 30 }}
+ animate={{ opacity: 1, y: 0 }}
+ transition={{ duration: 0.8, delay: 0.6 }}
+ >
+ <h2 className="text-3xl font-bold mb-4 text-green">Join Our Team</h2>
+ <p className="text-xl text-gray mb-8 max-w-2xl mx-auto">
+ We're always looking for passionate individuals to join our leadership team.
+ If you're interested in contributing to our mission, we'd love to hear from you.
+ </p>
+ <div className="flex flex-wrap justify-center gap-4">
+ <motion.button
+ whileHover={{ scale: 1.05 }}
+ whileTap={{ scale: 0.95 }}
+ className="btn text-lg px-8 py-4"
+ >
+ Apply for Leadership
+ </motion.button>
+ <motion.button
+ whileHover={{ scale: 1.05 }}
+ whileTap={{ scale: 0.95 }}
+ className="btn text-lg px-8 py-4"
+ >
+ Become a Member
+ </motion.button>
+ </div>
+ </motion.div>
+ </div>
+ </section>
+ </div>
+ );
+};
+
+export default Team; \ No newline at end of file
diff --git a/vite.config.js b/vite.config.js
new file mode 100644
index 0000000..8b0f57b
--- /dev/null
+++ b/vite.config.js
@@ -0,0 +1,7 @@
+import { defineConfig } from 'vite'
+import react from '@vitejs/plugin-react'
+
+// https://vite.dev/config/
+export default defineConfig({
+ plugins: [react()],
+})