l3onchri commited on
Commit
92f5427
·
0 Parent(s):

Initial commit: Synapse OS v1.0

Browse files
Files changed (16) hide show
  1. .gitignore +26 -0
  2. DEPLOY.md +45 -0
  3. Dockerfile +18 -0
  4. README.md +16 -0
  5. eslint.config.js +29 -0
  6. index.html +28 -0
  7. package-lock.json +0 -0
  8. package.json +38 -0
  9. public/vite.svg +1 -0
  10. server.js +37 -0
  11. src/App.jsx +0 -0
  12. src/assets/react.svg +1 -0
  13. src/index.css +615 -0
  14. src/lib/supabase.js +8 -0
  15. src/main.jsx +16 -0
  16. vite.config.js +7 -0
.gitignore ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Logs
2
+ logs
3
+ *.log
4
+ npm-debug.log*
5
+ yarn-debug.log*
6
+ yarn-error.log*
7
+ pnpm-debug.log*
8
+ lerna-debug.log*
9
+
10
+ node_modules
11
+ dist
12
+ dist-ssr
13
+ *.local
14
+ .env
15
+ .env.server
16
+
17
+ # Editor directories and files
18
+ .vscode/*
19
+ !.vscode/extensions.json
20
+ .idea
21
+ .DS_Store
22
+ *.suo
23
+ *.ntvs*
24
+ *.njsproj
25
+ *.sln
26
+ *.sw?
DEPLOY.md ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Deploy Synapse OS
2
+
3
+ Poiché l'applicazione ha due componenti (Frontend React e Backend Stripe Node.js), la soluzione migliore e gratuita è usare due servizi separati.
4
+
5
+ ## 1. Backend (Stripe Server) -> Hugging Face Spaces
6
+ Il servizio pagamenti vive qui.
7
+
8
+ 1. Vai su [Hugging Face Spaces](https://huggingface.co/spaces) -> **Create new Space**.
9
+ * **Space Name**: `synapse-backend` (o simile).
10
+ * **SDK**: **Docker** (Molto importante! Non scegliere "Static" o "Gradio").
11
+ * **License**: MIT.
12
+ 2. Clona il repo dello Space sul tuo PC o usa l'interfaccia web "Files" per caricare SOLO questi 3 file:
13
+ * `server.js`
14
+ * `package.json`
15
+ * `Dockerfile` (l'ho appena creato per te)
16
+ 3. Vai su **Settings** dello Space -> **Variables and secrets**.
17
+ * Crea un **New Secret**: `STRIPE_SECRET_KEY` con valore `sk_test_...` (prendilo dal tuo .env).
18
+ 4. Attendi che lo Space diventi "Running". Copia l'URL in alto (es. `https://huggingface.co/spaces/tuonome/synapse-backend` -> che diventa un link diretto tipo `https://tuonome-synapse-backend.hf.space`).
19
+
20
+ **Importante**: L'URL API sarà `https://[TUO-SPACE].hf.space/create-payment-intent`. Usalo nel passaggio sotto.
21
+
22
+ ## 2. Frontend (React Site) -> Vercel / Netlify
23
+ Il sito web vero e proprio.
24
+
25
+ 1. Nel file `src/App.jsx`, cerca la riga dove facciamo la `fetch` al server locale:
26
+ ```javascript
27
+ // MODIFICA QUESTO:
28
+ fetch('http://localhost:4242/create-payment-intent', ...)
29
+
30
+ // CON QUESTO (L'URL che ti ha dato Render):
31
+ fetch('https://synapse-backend.onrender.com/create-payment-intent', ...)
32
+ ```
33
+ 2. Crea un repo GitHub "synapse-frontend".
34
+ 3. Vai su [Vercel](https://vercel.com) -> Add New Project.
35
+ 4. Collega il repo.
36
+ 5. Inserisci le Variabili d'Ambiente (da `.env`):
37
+ * `VITE_SUPABASE_URL`
38
+ * `VITE_SUPABASE_ANON_KEY`
39
+ * `VITE_STRIPE_PUBLISHABLE_KEY`
40
+ * `VITE_OPENROUTER_API_KEY`
41
+ * `VITE_YOUTUBE_API_KEY`
42
+ 6. Deploy.
43
+
44
+ ## Alternativa Rapida (Solo Frontend)
45
+ Se non vuoi deployare il server, i pagamenti NON funzioneranno online, ma tutto il resto (AI, Auth) sì. In quel caso basta fare il punto 2 su Vercel.
Dockerfile ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM node:18
2
+
3
+ WORKDIR /app
4
+
5
+ # Copy package files
6
+ COPY package.json ./
7
+
8
+ # Install ONLY dependencies needed for the server
9
+ RUN npm install express cors stripe dotenv
10
+
11
+ # Copy server code
12
+ COPY server.js .
13
+
14
+ # Expose Hugging Face default port
15
+ EXPOSE 7860
16
+
17
+ # Run the server
18
+ CMD ["node", "server.js"]
README.md ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # React + Vite
2
+
3
+ This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
4
+
5
+ Currently, two official plugins are available:
6
+
7
+ - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) (or [oxc](https://oxc.rs) when used in [rolldown-vite](https://vite.dev/guide/rolldown)) for Fast Refresh
8
+ - [@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
9
+
10
+ ## React Compiler
11
+
12
+ The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation).
13
+
14
+ ## Expanding the ESLint configuration
15
+
16
+ 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.
eslint.config.js ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import js from '@eslint/js'
2
+ import globals from 'globals'
3
+ import reactHooks from 'eslint-plugin-react-hooks'
4
+ import reactRefresh from 'eslint-plugin-react-refresh'
5
+ import { defineConfig, globalIgnores } from 'eslint/config'
6
+
7
+ export default defineConfig([
8
+ globalIgnores(['dist']),
9
+ {
10
+ files: ['**/*.{js,jsx}'],
11
+ extends: [
12
+ js.configs.recommended,
13
+ reactHooks.configs.flat.recommended,
14
+ reactRefresh.configs.vite,
15
+ ],
16
+ languageOptions: {
17
+ ecmaVersion: 2020,
18
+ globals: globals.browser,
19
+ parserOptions: {
20
+ ecmaVersion: 'latest',
21
+ ecmaFeatures: { jsx: true },
22
+ sourceType: 'module',
23
+ },
24
+ },
25
+ rules: {
26
+ 'no-unused-vars': ['error', { varsIgnorePattern: '^[A-Z_]' }],
27
+ },
28
+ },
29
+ ])
index.html ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!doctype html>
2
+ <html lang="it">
3
+
4
+ <head>
5
+ <meta charset="UTF-8" />
6
+ <link rel="icon" type="image/svg+xml" href="/vite.svg" />
7
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
8
+ <title>SYNAPSE OS — The Ultimate Student Interface</title>
9
+ <meta name="description"
10
+ content="L'interfaccia neurale definitiva per lo studio. Synapse OS trasforma qualsiasi argomento in conoscenza cristallina attraverso l'intelligenza artificiale." />
11
+ <meta name="keywords"
12
+ content="studio, AI, intelligenza artificiale, apprendimento, scuola, università, neural, synapse" />
13
+ <meta name="theme-color" content="#030014" />
14
+
15
+ <!-- Google Fonts: Inter (Black) + JetBrains Mono -->
16
+ <link rel="preconnect" href="https://fonts.googleapis.com">
17
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
18
+ <link
19
+ href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;900&family=JetBrains+Mono:wght@400;500;600&display=swap"
20
+ rel="stylesheet">
21
+ </head>
22
+
23
+ <body>
24
+ <div id="root"></div>
25
+ <script type="module" src="/src/main.jsx"></script>
26
+ </body>
27
+
28
+ </html>
package-lock.json ADDED
The diff for this file is too large to render. See raw diff
 
package.json ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "landing-page",
3
+ "private": true,
4
+ "version": "0.0.0",
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "vite",
8
+ "build": "vite build",
9
+ "lint": "eslint .",
10
+ "preview": "vite preview",
11
+ "server": "node server.js"
12
+ },
13
+ "dependencies": {
14
+ "@stripe/react-stripe-js": "^5.6.0",
15
+ "@stripe/stripe-js": "^8.7.0",
16
+ "@supabase/supabase-js": "^2.93.3",
17
+ "cors": "^2.8.6",
18
+ "dotenv": "^17.2.3",
19
+ "express": "^5.2.1",
20
+ "react": "^19.2.0",
21
+ "react-dom": "^19.2.0",
22
+ "stripe": "^20.3.0"
23
+ },
24
+ "devDependencies": {
25
+ "@eslint/js": "^9.39.1",
26
+ "@tailwindcss/vite": "^4.1.18",
27
+ "@types/react": "^19.2.5",
28
+ "@types/react-dom": "^19.2.3",
29
+ "@vitejs/plugin-react": "^5.1.1",
30
+ "eslint": "^9.39.1",
31
+ "eslint-plugin-react-hooks": "^7.0.1",
32
+ "eslint-plugin-react-refresh": "^0.4.24",
33
+ "globals": "^16.5.0",
34
+ "lucide-react": "^0.563.0",
35
+ "tailwindcss": "^4.1.18",
36
+ "vite": "^7.2.4"
37
+ }
38
+ }
public/vite.svg ADDED
server.js ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import express from 'express';
2
+ import cors from 'cors';
3
+ import Stripe from 'stripe';
4
+ import dotenv from 'dotenv';
5
+
6
+ dotenv.config();
7
+
8
+ const app = express();
9
+ const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);
10
+
11
+ app.use(cors());
12
+ app.use(express.json());
13
+
14
+ app.post('/create-payment-intent', async (req, res) => {
15
+ try {
16
+ const paymentIntent = await stripe.paymentIntents.create({
17
+ amount: 999, // €9.99
18
+ currency: 'eur',
19
+ automatic_payment_methods: {
20
+ enabled: true,
21
+ },
22
+ });
23
+
24
+ res.send({
25
+ clientSecret: paymentIntent.client_secret,
26
+ });
27
+ } catch (e) {
28
+ res.status(400).send({
29
+ error: {
30
+ message: e.message,
31
+ }
32
+ });
33
+ }
34
+ });
35
+
36
+ const PORT = process.env.PORT || 4242;
37
+ app.listen(PORT, () => console.log(`Node server listening on port ${PORT}!`));
src/App.jsx ADDED
The diff for this file is too large to render. See raw diff
 
src/assets/react.svg ADDED
src/index.css ADDED
@@ -0,0 +1,615 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @import "tailwindcss";
2
+
3
+ /* ============================================
4
+ SYNAPSE OS - Neural Glass Design System
5
+ ============================================ */
6
+
7
+ :root {
8
+ /* Deep Space Palette */
9
+ --synapse-void: #030014;
10
+ --synapse-deep: #020617;
11
+ --synapse-surface: #0f172a;
12
+
13
+ /* Neon Accent Colors */
14
+ --synapse-violet: #8B5CF6;
15
+ --synapse-violet-glow: rgba(139, 92, 246, 0.5);
16
+ --synapse-cyan: #06B6D4;
17
+ --synapse-cyan-glow: rgba(6, 182, 212, 0.5);
18
+ --synapse-rose: #F43F5E;
19
+ --synapse-rose-glow: rgba(244, 63, 94, 0.5);
20
+
21
+ /* Neutral */
22
+ --synapse-zinc: #e4e4e7;
23
+ --synapse-dark: #18181b;
24
+
25
+ /* Fonts */
26
+ --font-display: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
27
+ --font-mono: 'JetBrains Mono', 'Courier New', monospace;
28
+ }
29
+
30
+ /* ============================================
31
+ BASE STYLES
32
+ ============================================ */
33
+
34
+ @layer base {
35
+ * {
36
+ margin: 0;
37
+ padding: 0;
38
+ box-sizing: border-box;
39
+ }
40
+
41
+ html {
42
+ scroll-behavior: smooth;
43
+ }
44
+
45
+ body {
46
+ font-family: var(--font-display);
47
+ background: radial-gradient(ellipse at 50% 0%, var(--synapse-surface) 0%, var(--synapse-deep) 50%, var(--synapse-void) 100%);
48
+ color: var(--synapse-zinc);
49
+ overflow-x: hidden;
50
+ line-height: 1.6;
51
+ min-height: 100vh;
52
+ }
53
+
54
+ /* Digital Noise Overlay */
55
+ body::before {
56
+ content: '';
57
+ position: fixed;
58
+ top: 0;
59
+ left: 0;
60
+ width: 100%;
61
+ height: 100%;
62
+ pointer-events: none;
63
+ z-index: 9999;
64
+ opacity: 0.03;
65
+ background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)'/%3E%3C/svg%3E");
66
+ }
67
+
68
+ /* Scrollbar */
69
+ ::-webkit-scrollbar {
70
+ width: 4px;
71
+ }
72
+
73
+ ::-webkit-scrollbar-track {
74
+ background: var(--synapse-void);
75
+ }
76
+
77
+ ::-webkit-scrollbar-thumb {
78
+ background: linear-gradient(180deg, var(--synapse-violet), var(--synapse-cyan));
79
+ border-radius: 2px;
80
+ }
81
+
82
+ /* Selection */
83
+ ::selection {
84
+ background: var(--synapse-violet);
85
+ color: white;
86
+ }
87
+ }
88
+
89
+ /* ============================================
90
+ TYPOGRAPHY
91
+ ============================================ */
92
+
93
+ .font-display {
94
+ font-family: var(--font-display);
95
+ }
96
+
97
+ .font-mono {
98
+ font-family: var(--font-mono);
99
+ }
100
+
101
+ .text-headline {
102
+ font-family: var(--font-display);
103
+ font-weight: 900;
104
+ letter-spacing: -0.03em;
105
+ line-height: 1.05;
106
+ }
107
+
108
+ .text-terminal {
109
+ font-family: var(--font-mono);
110
+ font-weight: 500;
111
+ font-size: 0.75rem;
112
+ text-transform: uppercase;
113
+ letter-spacing: 0.1em;
114
+ color: rgba(255, 255, 255, 0.5);
115
+ }
116
+
117
+ /* ============================================
118
+ GLASSMORPHISM 2.0
119
+ ============================================ */
120
+
121
+ @layer utilities {
122
+ .glass {
123
+ background: rgba(255, 255, 255, 0.03);
124
+ backdrop-filter: blur(20px);
125
+ -webkit-backdrop-filter: blur(20px);
126
+ border: 1px solid rgba(255, 255, 255, 0.08);
127
+ }
128
+
129
+ .glass-strong {
130
+ background: rgba(255, 255, 255, 0.06);
131
+ backdrop-filter: blur(40px);
132
+ -webkit-backdrop-filter: blur(40px);
133
+ border: 1px solid rgba(255, 255, 255, 0.12);
134
+ }
135
+
136
+ .glass-panel {
137
+ background: linear-gradient(135deg, rgba(255, 255, 255, 0.05) 0%, rgba(255, 255, 255, 0.02) 100%);
138
+ backdrop-filter: blur(30px);
139
+ -webkit-backdrop-filter: blur(30px);
140
+ border: 1px solid rgba(255, 255, 255, 0.1);
141
+ box-shadow:
142
+ 0 8px 32px rgba(0, 0, 0, 0.3),
143
+ inset 0 1px 0 rgba(255, 255, 255, 0.1);
144
+ }
145
+
146
+ /* Spotlight border effect */
147
+ .glass-spotlight {
148
+ position: relative;
149
+ background: rgba(255, 255, 255, 0.03);
150
+ backdrop-filter: blur(20px);
151
+ -webkit-backdrop-filter: blur(20px);
152
+ border: 1px solid rgba(255, 255, 255, 0.08);
153
+ transition: all 0.3s ease;
154
+ }
155
+
156
+ .glass-spotlight:hover {
157
+ border-color: rgba(139, 92, 246, 0.4);
158
+ box-shadow:
159
+ 0 0 30px rgba(139, 92, 246, 0.15),
160
+ 0 8px 32px rgba(0, 0, 0, 0.3);
161
+ }
162
+
163
+ /* ============================================
164
+ GRADIENTS & COLORS
165
+ ============================================ */
166
+
167
+ .gradient-text {
168
+ background: linear-gradient(135deg, var(--synapse-violet) 0%, var(--synapse-cyan) 100%);
169
+ -webkit-background-clip: text;
170
+ -webkit-text-fill-color: transparent;
171
+ background-clip: text;
172
+ }
173
+
174
+ .gradient-bg {
175
+ background: linear-gradient(135deg, var(--synapse-violet) 0%, var(--synapse-cyan) 100%);
176
+ }
177
+
178
+ .gradient-border {
179
+ position: relative;
180
+ background: var(--synapse-void);
181
+ }
182
+
183
+ .gradient-border::before {
184
+ content: '';
185
+ position: absolute;
186
+ inset: 0;
187
+ padding: 1px;
188
+ border-radius: inherit;
189
+ background: linear-gradient(135deg, var(--synapse-violet), var(--synapse-cyan));
190
+ -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
191
+ mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
192
+ -webkit-mask-composite: xor;
193
+ mask-composite: exclude;
194
+ }
195
+
196
+ /* ============================================
197
+ GLOW EFFECTS
198
+ ============================================ */
199
+
200
+ .glow-violet {
201
+ box-shadow:
202
+ 0 0 20px var(--synapse-violet-glow),
203
+ 0 0 40px rgba(139, 92, 246, 0.3),
204
+ 0 0 60px rgba(139, 92, 246, 0.15);
205
+ }
206
+
207
+ .glow-cyan {
208
+ box-shadow:
209
+ 0 0 20px var(--synapse-cyan-glow),
210
+ 0 0 40px rgba(6, 182, 212, 0.3);
211
+ }
212
+
213
+ .glow-rose {
214
+ box-shadow:
215
+ 0 0 20px var(--synapse-rose-glow),
216
+ 0 0 40px rgba(244, 63, 94, 0.3);
217
+ }
218
+
219
+ .text-glow {
220
+ text-shadow:
221
+ 0 0 20px var(--synapse-violet-glow),
222
+ 0 0 40px rgba(139, 92, 246, 0.3),
223
+ 0 0 80px rgba(6, 182, 212, 0.2);
224
+ }
225
+
226
+ .text-glow-cyan {
227
+ text-shadow:
228
+ 0 0 20px var(--synapse-cyan-glow),
229
+ 0 0 40px rgba(6, 182, 212, 0.3);
230
+ }
231
+
232
+ /* ============================================
233
+ COLOR UTILITIES
234
+ ============================================ */
235
+
236
+ .text-violet {
237
+ color: var(--synapse-violet);
238
+ }
239
+
240
+ .text-cyan {
241
+ color: var(--synapse-cyan);
242
+ }
243
+
244
+ .text-rose {
245
+ color: var(--synapse-rose);
246
+ }
247
+
248
+ .text-zinc {
249
+ color: var(--synapse-zinc);
250
+ }
251
+
252
+ .bg-void {
253
+ background-color: var(--synapse-void);
254
+ }
255
+
256
+ .bg-dark {
257
+ background-color: var(--synapse-dark);
258
+ }
259
+
260
+ .border-violet {
261
+ border-color: var(--synapse-violet);
262
+ }
263
+
264
+ .border-cyan {
265
+ border-color: var(--synapse-cyan);
266
+ }
267
+
268
+ /* ============================================
269
+ ANIMATIONS
270
+ ============================================ */
271
+
272
+ .animate-float {
273
+ animation: float 6s ease-in-out infinite;
274
+ }
275
+
276
+ .animate-pulse-slow {
277
+ animation: pulse-slow 4s ease-in-out infinite;
278
+ }
279
+
280
+ .animate-pulse-glow {
281
+ animation: pulse-glow 2s ease-in-out infinite;
282
+ }
283
+
284
+ .animate-shimmer {
285
+ animation: shimmer 2s linear infinite;
286
+ background-size: 200% 100%;
287
+ }
288
+
289
+ .animate-typewriter {
290
+ overflow: hidden;
291
+ border-right: 2px solid var(--synapse-cyan);
292
+ white-space: nowrap;
293
+ animation:
294
+ typing 3.5s steps(40, end),
295
+ blink-caret 0.75s step-end infinite;
296
+ }
297
+
298
+ .animate-scan {
299
+ animation: scan 8s linear infinite;
300
+ }
301
+
302
+ .animate-ripple {
303
+ animation: ripple 0.6s ease-out;
304
+ }
305
+
306
+ .animate-node-pulse {
307
+ animation: node-pulse 3s ease-in-out infinite;
308
+ }
309
+
310
+ /* Fade In Up */
311
+ .fade-in-up {
312
+ opacity: 0;
313
+ transform: translateY(40px);
314
+ transition: all 0.8s cubic-bezier(0.16, 1, 0.3, 1);
315
+ }
316
+
317
+ .fade-in-up.visible {
318
+ opacity: 1;
319
+ transform: translateY(0);
320
+ }
321
+
322
+ /* Stagger delays */
323
+ .delay-100 {
324
+ animation-delay: 100ms;
325
+ }
326
+
327
+ .delay-200 {
328
+ animation-delay: 200ms;
329
+ }
330
+
331
+ .delay-300 {
332
+ animation-delay: 300ms;
333
+ }
334
+
335
+ .delay-400 {
336
+ animation-delay: 400ms;
337
+ }
338
+
339
+ .delay-500 {
340
+ animation-delay: 500ms;
341
+ }
342
+ }
343
+
344
+ /* ============================================
345
+ KEYFRAME ANIMATIONS
346
+ ============================================ */
347
+
348
+ @keyframes float {
349
+
350
+ 0%,
351
+ 100% {
352
+ transform: translateY(0px);
353
+ }
354
+
355
+ 50% {
356
+ transform: translateY(-20px);
357
+ }
358
+ }
359
+
360
+ @keyframes pulse-slow {
361
+
362
+ 0%,
363
+ 100% {
364
+ opacity: 1;
365
+ }
366
+
367
+ 50% {
368
+ opacity: 0.5;
369
+ }
370
+ }
371
+
372
+ @keyframes pulse-glow {
373
+
374
+ 0%,
375
+ 100% {
376
+ box-shadow:
377
+ 0 0 20px var(--synapse-violet-glow),
378
+ 0 0 40px rgba(139, 92, 246, 0.2);
379
+ }
380
+
381
+ 50% {
382
+ box-shadow:
383
+ 0 0 30px var(--synapse-violet-glow),
384
+ 0 0 60px rgba(139, 92, 246, 0.4),
385
+ 0 0 80px rgba(6, 182, 212, 0.2);
386
+ }
387
+ }
388
+
389
+ @keyframes shimmer {
390
+ 0% {
391
+ background-position: -200% 0;
392
+ }
393
+
394
+ 100% {
395
+ background-position: 200% 0;
396
+ }
397
+ }
398
+
399
+ @keyframes typing {
400
+ from {
401
+ width: 0;
402
+ }
403
+
404
+ to {
405
+ width: 100%;
406
+ }
407
+ }
408
+
409
+ @keyframes blink-caret {
410
+
411
+ from,
412
+ to {
413
+ border-color: transparent;
414
+ }
415
+
416
+ 50% {
417
+ border-color: var(--synapse-cyan);
418
+ }
419
+ }
420
+
421
+ @keyframes scan {
422
+ 0% {
423
+ transform: translateY(-100%);
424
+ }
425
+
426
+ 100% {
427
+ transform: translateY(100vh);
428
+ }
429
+ }
430
+
431
+ @keyframes ripple {
432
+ 0% {
433
+ transform: scale(0);
434
+ opacity: 0.5;
435
+ }
436
+
437
+ 100% {
438
+ transform: scale(4);
439
+ opacity: 0;
440
+ }
441
+ }
442
+
443
+ @keyframes node-pulse {
444
+
445
+ 0%,
446
+ 100% {
447
+ transform: scale(1);
448
+ opacity: 0.8;
449
+ }
450
+
451
+ 50% {
452
+ transform: scale(1.2);
453
+ opacity: 1;
454
+ }
455
+ }
456
+
457
+ @keyframes hud-flicker {
458
+
459
+ 0%,
460
+ 100% {
461
+ opacity: 1;
462
+ }
463
+
464
+ 92% {
465
+ opacity: 1;
466
+ }
467
+
468
+ 93% {
469
+ opacity: 0.3;
470
+ }
471
+
472
+ 94% {
473
+ opacity: 1;
474
+ }
475
+
476
+ 96% {
477
+ opacity: 0.5;
478
+ }
479
+
480
+ 97% {
481
+ opacity: 1;
482
+ }
483
+ }
484
+
485
+ @keyframes border-glow {
486
+
487
+ 0%,
488
+ 100% {
489
+ border-color: rgba(139, 92, 246, 0.3);
490
+ }
491
+
492
+ 50% {
493
+ border-color: rgba(139, 92, 246, 0.6);
494
+ }
495
+ }
496
+
497
+ /* ============================================
498
+ 3D PERSPECTIVE SYSTEM
499
+ ============================================ */
500
+
501
+ .perspective-container {
502
+ perspective: 1000px;
503
+ perspective-origin: center;
504
+ }
505
+
506
+ .preserve-3d {
507
+ transform-style: preserve-3d;
508
+ }
509
+
510
+ .card-3d {
511
+ transition: transform 0.5s cubic-bezier(0.16, 1, 0.3, 1);
512
+ }
513
+
514
+ .card-3d:hover {
515
+ transform: translateZ(20px) rotateX(2deg) rotateY(-2deg);
516
+ }
517
+
518
+ /* ============================================
519
+ HUD ELEMENTS
520
+ ============================================ */
521
+
522
+ .hud-line {
523
+ position: absolute;
524
+ background: linear-gradient(90deg, transparent 0%, var(--synapse-violet) 50%, transparent 100%);
525
+ height: 1px;
526
+ opacity: 0.3;
527
+ }
528
+
529
+ .hud-corner {
530
+ position: absolute;
531
+ width: 20px;
532
+ height: 20px;
533
+ border-color: rgba(139, 92, 246, 0.4);
534
+ border-style: solid;
535
+ }
536
+
537
+ .hud-corner-tl {
538
+ top: 20px;
539
+ left: 20px;
540
+ border-width: 1px 0 0 1px;
541
+ }
542
+
543
+ .hud-corner-tr {
544
+ top: 20px;
545
+ right: 20px;
546
+ border-width: 1px 1px 0 0;
547
+ }
548
+
549
+ .hud-corner-bl {
550
+ bottom: 20px;
551
+ left: 20px;
552
+ border-width: 0 0 1px 1px;
553
+ }
554
+
555
+ .hud-corner-br {
556
+ bottom: 20px;
557
+ right: 20px;
558
+ border-width: 0 1px 1px 0;
559
+ }
560
+
561
+ /* ============================================
562
+ INTERACTIVE ELEMENTS
563
+ ============================================ */
564
+
565
+ .btn-neon {
566
+ position: relative;
567
+ overflow: hidden;
568
+ transition: all 0.3s ease;
569
+ }
570
+
571
+ .btn-neon::before {
572
+ content: '';
573
+ position: absolute;
574
+ inset: 0;
575
+ background: linear-gradient(135deg, rgba(255, 255, 255, 0.1) 0%, transparent 100%);
576
+ opacity: 0;
577
+ transition: opacity 0.3s ease;
578
+ }
579
+
580
+ .btn-neon:hover::before {
581
+ opacity: 1;
582
+ }
583
+
584
+ .btn-neon:active {
585
+ transform: scale(0.98);
586
+ }
587
+
588
+ /* Input HUD Style */
589
+ .input-hud {
590
+ background: rgba(0, 0, 0, 0.4);
591
+ border: 1px solid rgba(139, 92, 246, 0.3);
592
+ transition: all 0.3s ease;
593
+ }
594
+
595
+ .input-hud:focus {
596
+ border-color: var(--synapse-violet);
597
+ box-shadow:
598
+ 0 0 20px var(--synapse-violet-glow),
599
+ inset 0 0 20px rgba(139, 92, 246, 0.05);
600
+ outline: none;
601
+ }
602
+
603
+ /* ============================================
604
+ RESPONSIVE UTILITIES
605
+ ============================================ */
606
+
607
+ @media (max-width: 768px) {
608
+ .text-headline {
609
+ letter-spacing: -0.02em;
610
+ }
611
+
612
+ .hud-corner {
613
+ display: none;
614
+ }
615
+ }
src/lib/supabase.js ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ import { createClient } from '@supabase/supabase-js';
2
+
3
+ const supabaseUrl = import.meta.env.VITE_SUPABASE_URL;
4
+ const supabaseAnonKey = import.meta.env.VITE_SUPABASE_ANON_KEY;
5
+
6
+ export const supabase = supabaseUrl && supabaseAnonKey
7
+ ? createClient(supabaseUrl, supabaseAnonKey)
8
+ : null;
src/main.jsx ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { StrictMode } from 'react'
2
+ import { createRoot } from 'react-dom/client'
3
+ import './index.css'
4
+ import App from './App.jsx'
5
+
6
+ // Add Inter font
7
+ const link = document.createElement('link');
8
+ link.href = 'https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&display=swap';
9
+ link.rel = 'stylesheet';
10
+ document.head.appendChild(link);
11
+
12
+ createRoot(document.getElementById('root')).render(
13
+ <StrictMode>
14
+ <App />
15
+ </StrictMode>,
16
+ )
vite.config.js ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ import { defineConfig } from 'vite'
2
+ import react from '@vitejs/plugin-react'
3
+ import tailwindcss from '@tailwindcss/vite'
4
+
5
+ export default defineConfig({
6
+ plugins: [react(), tailwindcss()],
7
+ })