api-ix commited on
Commit
02ee4f9
·
verified ·
1 Parent(s): 793e290

Upload 3 files

Browse files
Files changed (3) hide show
  1. index.html +119 -18
  2. script.js +974 -0
  3. styles.css +317 -0
index.html CHANGED
@@ -1,19 +1,120 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  </html>
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width,initial-scale=1.0" />
6
+ <title>BLUE DEMON API v2</title>
7
+ <link rel="stylesheet" href="styles.css" />
8
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
9
+ <script src="https://kit.fontawesome.com/64d58efce2.js" crossorigin="anonymous"></script>
10
+ </head>
11
+
12
+ <body>
13
+ <!-- Liquid BG -->
14
+ <div class="liquid-bg">
15
+ <div class="orb orb-1"></div>
16
+ <div class="orb orb-2"></div>
17
+ <div class="orb orb-3"></div>
18
+ </div>
19
+
20
+ <!-- Header -->
21
+ <header class="header">
22
+ <div class="logo">
23
+ <i class="fas fa-skull"></i>
24
+ <span>BLUE DEMON</span>
25
+ </div>
26
+ <nav>
27
+ <a href="#apis">APIs</a>
28
+ <a href="#docs">Docs</a>
29
+ <a href="#status">Status</a>
30
+ </nav>
31
+ </header>
32
+
33
+ <!-- Hero -->
34
+ <section class="hero">
35
+ <h1 class="hero-title">
36
+ <span class="accent">BLUE</span> DEMON API
37
+ </h1>
38
+ <p class="hero-sub">Lightning-fast endpoints for everything you need.</p>
39
+ <button class="cta" onclick="scrollToSection('apis')">
40
+ <i class="fas fa-rocket"></i> Explore APIs
41
+ </button>
42
+ </section>
43
+
44
+ <!-- Live Stats -->
45
+ <section id="status" class="stats">
46
+ <div class="stat-card">
47
+ <i class="fas fa-chart-bar"></i>
48
+ <span id="req-count">--</span>
49
+ <small>requests served</small>
50
+ </div>
51
+ <div class="stat-card">
52
+ <i class="fas fa-server"></i>
53
+ <span>51</span>
54
+ <small>endpoints</small>
55
+ </div>
56
+ <div class="stat-card">
57
+ <i class="fas fa-shield-alt"></i>
58
+ <span>99.9%</span>
59
+ <small>uptime</small>
60
+ </div>
61
+ </section>
62
+
63
+ <!-- Filter + Search -->
64
+ <section id="apis" class="api-section">
65
+ <div class="controls">
66
+ <input id="search" placeholder="Search endpoints…" />
67
+ <div class="pills" id="pills">
68
+ <button class="pill active" data-cat="All">All</button>
69
+ </div>
70
+ </div>
71
+
72
+ <!-- Cards injected here -->
73
+ <div class="grid" id="grid"></div>
74
+ <button class="load-more" id="loadMore">Load more</button>
75
+ </section>
76
+
77
+ <!-- Docs -->
78
+ <section id="docs" class="docs">
79
+ <h2>Quick Start</h2>
80
+ <div class="steps">
81
+ <article>
82
+ <div class="step-icon"><i class="fas fa-code"></i></div>
83
+ <h3>1. Copy endpoint</h3>
84
+ <p>No keys needed for 90% of endpoints.</p>
85
+ </article>
86
+ <article>
87
+ <div class="step-icon"><i class="fas fa-play-circle"></i></div>
88
+ <h3>2. Paste & Run</h3>
89
+ <p>Works in browser, curl, fetch, you name it.</p>
90
+ </article>
91
+ <article>
92
+ <div class="step-icon"><i class="fas fa-rocket"></i></div>
93
+ <h3>3. Scale</h3>
94
+ <p>Built for high load & rapid prototyping.</p>
95
+ </article>
96
+ </div>
97
+ </section>
98
+
99
+ <!-- Footer -->
100
+ <footer>
101
+ <div class="social">
102
+ <a href="https://wa.me/2347041039367" title="Support"><i class="fab fa-whatsapp"></i></a>
103
+ <a href="#"><i class="fab fa-github"></i></a>
104
+ </div>
105
+ <small>&copy; 2024 BLUE DEMON API</small>
106
+ </footer>
107
+
108
+ <!-- Modal -->
109
+ <div class="modal" id="modal">
110
+ <div class="modal-backdrop"></div>
111
+ <div class="modal-card">
112
+ <button class="modal-close">&times;</button>
113
+ <h3 id="mTitle"></h3>
114
+ <div id="mBody"></div>
115
+ </div>
116
+ </div>
117
+
118
+ <script src="script.js"></script>
119
+ </body>
120
  </html>
script.js ADDED
@@ -0,0 +1,974 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // API Endpoints Data (from your original script.js)
2
+ const endpoints = [
3
+ {
4
+ name: "Anime Downloader",
5
+ path: "/api/animedl?name=solo%20leveling&episode=1",
6
+ method: "GET",
7
+ params: ["name", "episode"],
8
+ description: "Download any anime series with ease",
9
+ category: "Downloaders",
10
+ },
11
+ {
12
+ name: "All-in-one",
13
+ path: "/api/all-in-one?url=https://www.facebook.com/DeadWithDerrSter/videos/951658963655313/",
14
+ method: "GET",
15
+ params: ["url"],
16
+ description: "Download any social media video",
17
+ category: "Downloaders",
18
+ },
19
+ {
20
+ name: "Anime Quote",
21
+ path: "/api/aniquote",
22
+ method: "GET",
23
+ params: [],
24
+ description: "Get a Random quote from popular anime series",
25
+ category: "Fun",
26
+ },
27
+ {
28
+ name: "APK Downloader",
29
+ path: "/api/apkdl?q=Facebook%20lite",
30
+ method: "GET",
31
+ params: ["q"],
32
+ description: "Endpoint for app downloader",
33
+ category: "Downloaders",
34
+ },
35
+ {
36
+ name: "Calculator",
37
+ path: "/api/cal?num1=10&num2=5&operation=add",
38
+ method: "GET",
39
+ params: ["num1", "num2", "operation"],
40
+ description: "Perform basic arithmetic operations",
41
+ category: "Tools",
42
+ },
43
+ {
44
+ name: "Country",
45
+ path: "/api/country?q=Nigeria",
46
+ method: "GET",
47
+ params: ["q"],
48
+ description: "Search for countries info",
49
+ category: "Tools",
50
+ },
51
+ {
52
+ name: "Currency Converter",
53
+ path: "/api/convert?from=USD&to=EUR&amount=100",
54
+ method: "GET",
55
+ params: ["from", "to", "amount"],
56
+ description: "Convert currencies with real-time exchange rates",
57
+ category: "Tools",
58
+ },
59
+ {
60
+ name: "Dare",
61
+ path: "/api/dare",
62
+ method: "GET",
63
+ params: [],
64
+ description: "Get a Random dare challenge",
65
+ category: "Fun",
66
+ },
67
+ {
68
+ name: "Encode",
69
+ path: "/api/encode?text=Hello-world",
70
+ method: "GET",
71
+ params: ["text"],
72
+ description: "Encode text to binary",
73
+ category: "Tools",
74
+ },
75
+ {
76
+ name: "Decode",
77
+ path: "/api/decode?binary=01001000 01101001",
78
+ method: "GET",
79
+ params: ["binary"],
80
+ description: "Decode binary to text",
81
+ category: "Tools",
82
+ },
83
+ {
84
+ name: "Font",
85
+ path: "/api/font?text=Blue%20demon",
86
+ method: "GET",
87
+ params: ["text"],
88
+ description: "Generate different fonts ",
89
+ category: "Tools",
90
+ },
91
+ {
92
+ name: "Facebook",
93
+ path: "/api/fbdl?url=https://www.facebook.com/share/v/12En5xB3SQk/",
94
+ method: "GET",
95
+ params: ["url"],
96
+ description: "Facebook video downloader",
97
+ category: "Downloaders",
98
+ },
99
+ {
100
+ name: "Gpt3.5",
101
+ path: "/api/gpt3.5?prompt=hi",
102
+ method: "GET",
103
+ params: ["prompt"],
104
+ description: "advance chatbot artificial intelligence",
105
+ category: "Ai",
106
+ },
107
+ {
108
+ name: "Waifu",
109
+ path: "/api/waifu?q=",
110
+ method: "GET",
111
+ params: ["q"],
112
+ description: "Get a Random waifu image (NSFW)",
113
+ category: "Search",
114
+ },
115
+ {
116
+ name: "Hentai",
117
+ path: "/api/hentai",
118
+ method: "GET",
119
+ params: [],
120
+ description: "Get a Random hentai videos (NSFW)",
121
+ category: "Random",
122
+ },
123
+ {
124
+ name: "Mediafire",
125
+ path: "/api/mediafire?url=https://www.mediafire.com/file/2s3pdn53o12ug5a/%25E2%2588%2582%25C9%259B%25C6%25A8%25D1%2582%25D1%258F%25CA%258Bc%25D1%2582%25CE%25B9%25CF%2583%25D0%25B8%25CF%2587-2.zip/file",
126
+ method: "GET",
127
+ params: ["url"],
128
+ description: "automated mediafire downloader",
129
+ category: "Downloaders",
130
+ },
131
+ {
132
+ name: "Pinterest",
133
+ path: "/api/pinterest?q=fat%20ass",
134
+ method: "GET",
135
+ params: ["q"],
136
+ description: "Get Pinterest image via search query",
137
+ category: "Search",
138
+ },
139
+ {
140
+ name: "Text2image",
141
+ path: "/api/text2img?prompt=a%20big%20dog%20and%20a%20tiny%20cat",
142
+ method: "GET",
143
+ params: ["prompt"],
144
+ description: "Generate an HD image via text prompt",
145
+ category: "Ai",
146
+ },
147
+ {
148
+ name: "Translator",
149
+ path: "/api/translate?text=hello%20how%20are%20you&from=en&to=id",
150
+ method: "GET",
151
+ params: ["text"],
152
+ description: "Translate from any language to another",
153
+ category: "Tools",
154
+ },
155
+ {
156
+ name: "Twitter / X",
157
+ path: "/api/twitterdl?url=https://x.com/dammiedammie35/status/1897584097083400456?t=zU0X4PZDLQswYHbDCxi6Ng&s=09",
158
+ method: "GET",
159
+ params: ["url"],
160
+ description: "Twitter video downloader",
161
+ category: "Downloaders",
162
+ },
163
+ {
164
+ name: "Instagram",
165
+ path: "/api/instadl?url=https://www.instagram.com/reel/DBlb0Q8vxjD/?utm_source=ig_web_copy_link",
166
+ method: "GET",
167
+ params: ["url"],
168
+ description: "Instagram video downloader",
169
+ category: "Downloaders",
170
+ },
171
+ {
172
+ name: "Joke",
173
+ path: "/api/joke",
174
+ method: "GET",
175
+ params: [],
176
+ description: "Get a Random joke to make you laugh",
177
+ category: "Fun",
178
+ },
179
+ {
180
+ name: "NpmCheck",
181
+ path: "/api/npmcheck?package=express",
182
+ method: "GET",
183
+ params: ["package"],
184
+ description: "Check any npmpackage details",
185
+ category: "Search",
186
+ },
187
+ {
188
+ name: "Movie downloader",
189
+ path: "/api/moviedl?moviename=moana&episode=",
190
+ method: "GET",
191
+ params: ["moviename", "episode"],
192
+ description: "search and download different movies",
193
+ category: "Downloaders",
194
+ },
195
+ {
196
+ name: "lyrics",
197
+ path: "/api/lyrics?q=not%20like%20us",
198
+ method: "GET",
199
+ params: ["q"],
200
+ description: "automated lyrics search",
201
+ category: "Search",
202
+ },
203
+ {
204
+ name: "Obfuscate",
205
+ path: "/api/obf?code=console.log('hello');",
206
+ method: "GET",
207
+ params: ["code"],
208
+ description: "Obfuscate your JavaScript code",
209
+ category: "Tools",
210
+ },
211
+ {
212
+ name: "Quote",
213
+ path: "/api/quote",
214
+ method: "GET",
215
+ params: [],
216
+ description: "Get an inspirational quote to brighten your day",
217
+ category: "Fun",
218
+ },
219
+ {
220
+ name: "Rizz",
221
+ path: "/api/rizz",
222
+ method: "GET",
223
+ params: [],
224
+ description: "Get a Random pickup line to impress your crush",
225
+ category: "Fun",
226
+ },
227
+ {
228
+ name: "wallpaper",
229
+ path: "/api/wallpaper?q=naruto",
230
+ method: "GET",
231
+ params: ["q"],
232
+ description: "generates cool wallpapers",
233
+ category: "Random",
234
+ },
235
+ {
236
+ name: "Web Screenshot",
237
+ path: "/api/screenshot?url=https://api-xx-xi.hf.space/",
238
+ method: "GET",
239
+ params: ["url"],
240
+ description: "Take a screenshot of any website via url",
241
+ category: "Tools",
242
+ },
243
+ {
244
+ name: "Spotify",
245
+ path: "/api/spotifydl?url=https://open.spotify.com/track/1r3yPRzWPxM4O0S1T8X6vx?si=1NSDkaZxRjW-dDMcn14V7g",
246
+ method: "GET",
247
+ params: ["url"],
248
+ description: "Download Spotify music via link",
249
+ category: "Downloaders",
250
+ },
251
+ {
252
+ name: "short movie clips",
253
+ path: "/api/shortclip?q=moana",
254
+ method: "GET",
255
+ params: ["q"],
256
+ description: "Get clips of any movie available",
257
+ category: "Search",
258
+ },
259
+ {
260
+ name: "Thread Downloader",
261
+ path: "/api/threaddl?url=https://www.threads.net/@ekene_umenwa/post/DHL9gkgsZct?xmt=AQGzXGz-1ax86LccgoJoIaOR5xDXKhGxZwMB1HAkIr3yRw",
262
+ method: "GET",
263
+ params: ["url"],
264
+ description: "Download Thread video/images without watermark",
265
+ category: "Downloaders",
266
+ },
267
+ {
268
+ name: "TikTok Downloader",
269
+ path: "/api/tkdl?url=https://vm.tiktok.com/ZMknsbayE/",
270
+ method: "GET",
271
+ params: ["url"],
272
+ description: "Download TikTok videos without watermark",
273
+ category: "Downloaders",
274
+ },
275
+ {
276
+ name: "TikTok Downloader V2",
277
+ path: "/api/tkdl2?url=https://vm.tiktok.com/ZMknsbayE/",
278
+ method: "GET",
279
+ params: ["url"],
280
+ description: "Download TikTok videos without watermark",
281
+ category: "Downloaders",
282
+ },
283
+ {
284
+ name: "Xxx Downloader",
285
+ path: "/api/xvideos?url=https://www.xvideos.com/video.udvpliv122f/the_best_videos_of_hot_stepmom_alexa_payne",
286
+ method: "GET",
287
+ params: ["url"],
288
+ description: "Download xvidos without premium access",
289
+ category: "Downloaders",
290
+ },
291
+ {
292
+ name: "Xxx Search",
293
+ path: "/api/xxxsearch?q=big%20fat%20ass",
294
+ method: "GET",
295
+ params: ["q"],
296
+ description: "Search xvideos with ease",
297
+ category: "Search",
298
+ },
299
+ {
300
+ name: "Xnxx Search",
301
+ path: "/api/xnxxsearch?q=big%20fat%20ass",
302
+ method: "GET",
303
+ params: ["q"],
304
+ description: "Search xnxx videos with ease",
305
+ category: "Search",
306
+ },
307
+ {
308
+ name: "TinyURL",
309
+ path: "/api/tinyurl?url=https://api-x-demon-dev.hf.space",
310
+ method: "GET",
311
+ params: ["url"],
312
+ description: "Shorten long URLs for easy sharing",
313
+ category: "Tools",
314
+ },
315
+ {
316
+ name: "Truth",
317
+ path: "/api/truth",
318
+ method: "GET",
319
+ params: [],
320
+ description: "Get a Random truth question for your game night",
321
+ category: "Fun",
322
+ },
323
+ {
324
+ name: "Flirt",
325
+ path: "/api/flirt",
326
+ method: "GET",
327
+ params: [],
328
+ description: "Get a Random flirting words for your crush😉",
329
+ category: "Fun",
330
+ },
331
+ {
332
+ name: "Wachannel info",
333
+ path: "/api/wachannel?url=https://whatsapp.com/channel/0029Vah3fKtCnA7oMPTPJm1h",
334
+ method: "GET",
335
+ params: ["url"],
336
+ description: "check WhatsApp channel info via link",
337
+ category: "Tools",
338
+ },
339
+ {
340
+ name: "YouTube MP3",
341
+ path: "/api/ytmp3?url=https://youtu.be/wf_s7OIfHyw?si=yJSInCsXUVgHrH4t&qua=256",
342
+ method: "GET",
343
+ params: ["url"],
344
+ description: "Convert YouTube videos to MP3 audio",
345
+ category: "Downloaders",
346
+ },
347
+ {
348
+ name: "YouTube MP4",
349
+ path: "/api/ytmp4?url=https://youtu.be/wf_s7OIfHyw?si=yJSInCsXUVgHrH4t",
350
+ method: "GET",
351
+ params: ["url"],
352
+ description: "Download YouTube videos in MP4 format",
353
+ category: "Downloaders",
354
+ },
355
+ {
356
+ name: "YouTube Search",
357
+ path: "/api/yts?q=demon-slayers",
358
+ method: "GET",
359
+ params: ["q"],
360
+ description: "Search for YouTube videos and get detailed information",
361
+ category: "Search",
362
+ },
363
+ {
364
+ name: "cecan-china",
365
+ path: "/api/cecan-china",
366
+ method: "GET",
367
+ params: [],
368
+ description: "Get a Random Chinese women image",
369
+ category: "Random",
370
+ },
371
+ {
372
+ name: "cecan-indo",
373
+ path: "/api/cecan-indo",
374
+ method: "GET",
375
+ params: [],
376
+ description: "Get a Random Indonesian women image",
377
+ category: "Random",
378
+ },
379
+ {
380
+ name: "cecan-japan",
381
+ path: "/api/cecan-japan",
382
+ method: "GET",
383
+ params: [],
384
+ description: "Get a Random Japanese women image",
385
+ category: "Random",
386
+ },
387
+ {
388
+ name: "cecan-korea",
389
+ path: "/api/cecan-korea",
390
+ method: "GET",
391
+ params: [],
392
+ description: "Get a Random Korean women image",
393
+ category: "Random",
394
+ },
395
+ {
396
+ name: "cecan-thailand",
397
+ path: "/api/cecan-thailand",
398
+ method: "GET",
399
+ params: [],
400
+ description: "Get a Random Thai women image",
401
+ category: "Random",
402
+ },
403
+ {
404
+ name: "cecan-vietnam",
405
+ path: "/api/cecan-vietnam",
406
+ method: "GET",
407
+ params: [],
408
+ description: "Get a Random Vietnamese women image",
409
+ category: "Random",
410
+ },
411
+ ];
412
+
413
+ // Global State
414
+ let currentFilter = 'All';
415
+ let displayedEndpoints = 12;
416
+ let filteredEndpoints = [...endpoints];
417
+ let isLoading = false;
418
+
419
+ // DOM Elements
420
+ const elements = {
421
+ navToggle: document.getElementById('navToggle'),
422
+ navMenu: document.getElementById('navMenu'),
423
+ searchInput: document.getElementById('searchInput'),
424
+ searchClear: document.getElementById('searchClear'),
425
+ categoryFilters: document.getElementById('categoryFilters'),
426
+ endpointsGrid: document.getElementById('endpointsGrid'),
427
+ loadMoreBtn: document.getElementById('loadMoreBtn'),
428
+ totalRequests: document.getElementById('totalRequests'),
429
+ heroRequests: document.getElementById('heroRequests'),
430
+ demoCode: document.getElementById('demoCode'),
431
+ fab: document.getElementById('fab'),
432
+ fabMain: document.getElementById('fabMain'),
433
+ modal: document.getElementById('endpointModal'),
434
+ modalTitle: document.getElementById('modalTitle'),
435
+ modalBody: document.getElementById('modalBody'),
436
+ modalClose: document.getElementById('modalClose'),
437
+ modalBackdrop: document.getElementById('modalBackdrop'),
438
+ toastContainer: document.getElementById('toastContainer')
439
+ };
440
+
441
+ // Utility Functions
442
+ const debounce = (func, wait) => {
443
+ let timeout;
444
+ return function executedFunction(...args) {
445
+ const later = () => {
446
+ clearTimeout(timeout);
447
+ func(...args);
448
+ };
449
+ clearTimeout(timeout);
450
+ timeout = setTimeout(later, wait);
451
+ };
452
+ };
453
+
454
+ const animateNumber = (element, start, end, duration = 2000) => {
455
+ const startTime = performance.now();
456
+ const animate = (currentTime) => {
457
+ const elapsed = currentTime - startTime;
458
+ const progress = Math.min(elapsed / duration, 1);
459
+ const current = Math.floor(start + (end - start) * progress);
460
+ element.textContent = current.toLocaleString();
461
+ if (progress < 1) {
462
+ requestAnimationFrame(animate);
463
+ }
464
+ };
465
+ requestAnimationFrame(animate);
466
+ };
467
+
468
+ const showToast = (message, type = 'success') => {
469
+ const toast = document.createElement('div');
470
+ toast.className = `toast ${type}`;
471
+ toast.innerHTML = `
472
+ <i class="fas ${type === 'success' ? 'fa-check' : 'fa-exclamation-triangle'}"></i>
473
+ <span>${message}</span>
474
+ `;
475
+
476
+ elements.toastContainer.appendChild(toast);
477
+
478
+ // Show toast
479
+ setTimeout(() => toast.classList.add('show'), 100);
480
+
481
+ // Remove toast
482
+ setTimeout(() => {
483
+ toast.classList.remove('show');
484
+ setTimeout(() => {
485
+ if (toast.parentNode) {
486
+ toast.parentNode.removeChild(toast);
487
+ }
488
+ }, 300);
489
+ }, 3000);
490
+ };
491
+
492
+ // Initialize Particles
493
+ const initParticles = () => {
494
+ const particlesContainer = document.getElementById('particles');
495
+ const particleCount = 50;
496
+
497
+ for (let i = 0; i < particleCount; i++) {
498
+ const particle = document.createElement('div');
499
+ particle.className = 'particle';
500
+ particle.style.left = Math.random() * 100 + '%';
501
+ particle.style.top = Math.random() * 100 + '%';
502
+ particle.style.animationDelay = Math.random() * 6 + 's';
503
+ particle.style.animationDuration = (Math.random() * 3 + 3) + 's';
504
+ particlesContainer.appendChild(particle);
505
+ }
506
+ };
507
+
508
+ // Navigation
509
+ const initNavigation = () => {
510
+ // Mobile menu toggle
511
+ elements.navToggle.addEventListener('click', () => {
512
+ elements.navMenu.classList.toggle('active');
513
+ elements.navToggle.classList.toggle('active');
514
+ });
515
+
516
+ // Navigation links
517
+ document.querySelectorAll('.nav-link').forEach(link => {
518
+ link.addEventListener('click', (e) => {
519
+ e.preventDefault();
520
+ const targetId = link.getAttribute('data-section');
521
+ const targetElement = document.getElementById(targetId);
522
+
523
+ if (targetElement) {
524
+ const offsetTop = targetElement.offsetTop - 60;
525
+ window.scrollTo({
526
+ top: offsetTop,
527
+ behavior: 'smooth'
528
+ });
529
+
530
+ // Update active nav link
531
+ document.querySelectorAll('.nav-link').forEach(l => l.classList.remove('active'));
532
+ link.classList.add('active');
533
+
534
+ // Close mobile menu
535
+ elements.navMenu.classList.remove('active');
536
+ elements.navToggle.classList.remove('active');
537
+ }
538
+ });
539
+ });
540
+
541
+ // Update active nav on scroll
542
+ window.addEventListener('scroll', () => {
543
+ const sections = ['home', 'stats', 'endpoints', 'docs'];
544
+ let currentSection = 'home';
545
+
546
+ sections.forEach(sectionId => {
547
+ const section = document.getElementById(sectionId);
548
+ if (section) {
549
+ const rect = section.getBoundingClientRect();
550
+ if (rect.top <= 100 && rect.bottom >= 100) {
551
+ currentSection = sectionId;
552
+ }
553
+ }
554
+ });
555
+
556
+ document.querySelectorAll('.nav-link').forEach(link => {
557
+ link.classList.remove('active');
558
+ if (link.getAttribute('data-section') === currentSection) {
559
+ link.classList.add('active');
560
+ }
561
+ });
562
+ });
563
+ };
564
+
565
+ // Typewriter Effect
566
+ const initTypewriter = () => {
567
+ const code = `// Make API Request
568
+ fetch('/api/quote')
569
+ .then(response => response.json())
570
+ .then(data => {
571
+ console.log(data);
572
+ })
573
+ .catch(error => {
574
+ console.error('Error:', error);
575
+ });`;
576
+
577
+ let i = 0;
578
+ const speed = 50;
579
+
580
+ const typeWriter = () => {
581
+ if (i < code.length) {
582
+ elements.demoCode.textContent += code.charAt(i);
583
+ i++;
584
+ setTimeout(typeWriter, speed);
585
+ }
586
+ };
587
+
588
+ setTimeout(typeWriter, 1000);
589
+ };
590
+
591
+ // Fetch Request Count
592
+ const fetchRequestCount = async () => {
593
+ try {
594
+ const response = await fetch(`${window.location.origin}/api/requests`);
595
+ const data = await response.json();
596
+
597
+ if (data.success) {
598
+ // Animate numbers
599
+ animateNumber(elements.totalRequests, 0, data.request_count, 2000);
600
+ animateNumber(elements.heroRequests, 0, data.request_count, 2000);
601
+ } else {
602
+ elements.totalRequests.textContent = 'Error';
603
+ elements.heroRequests.textContent = 'Error';
604
+ }
605
+ } catch (error) {
606
+ console.error('Error fetching request count:', error);
607
+ elements.totalRequests.textContent = 'Error';
608
+ elements.heroRequests.textContent = 'Error';
609
+ }
610
+ };
611
+
612
+ // Create Category Filters
613
+ const createCategoryFilters = () => {
614
+ const categories = ['All', ...new Set(endpoints.map(endpoint => endpoint.category))];
615
+
616
+ elements.categoryFilters.innerHTML = '';
617
+
618
+ categories.forEach(category => {
619
+ const filter = document.createElement('button');
620
+ filter.className = `category-filter ${category === currentFilter ? 'active' : ''}`;
621
+ filter.textContent = category;
622
+ filter.addEventListener('click', () => filterEndpoints(category));
623
+ elements.categoryFilters.appendChild(filter);
624
+ });
625
+ };
626
+
627
+ // Filter Endpoints
628
+ const filterEndpoints = (category) => {
629
+ currentFilter = category;
630
+ displayedEndpoints = 12;
631
+
632
+ // Update active filter
633
+ document.querySelectorAll('.category-filter').forEach(filter => {
634
+ filter.classList.toggle('active', filter.textContent === category);
635
+ });
636
+
637
+ // Filter endpoints
638
+ if (category === 'All') {
639
+ filteredEndpoints = [...endpoints];
640
+ } else {
641
+ filteredEndpoints = endpoints.filter(endpoint => endpoint.category === category);
642
+ }
643
+
644
+ // Apply search filter if active
645
+ const searchTerm = elements.searchInput.value.toLowerCase().trim();
646
+ if (searchTerm) {
647
+ filteredEndpoints = filteredEndpoints.filter(endpoint =>
648
+ endpoint.name.toLowerCase().includes(searchTerm) ||
649
+ endpoint.description.toLowerCase().includes(searchTerm) ||
650
+ endpoint.category.toLowerCase().includes(searchTerm)
651
+ );
652
+ }
653
+
654
+ renderEndpoints();
655
+ };
656
+
657
+ // Search Functionality
658
+ const initSearch = () => {
659
+ const handleSearch = debounce(() => {
660
+ const searchTerm = elements.searchInput.value.toLowerCase().trim();
661
+
662
+ // Show/hide clear button
663
+ elements.searchClear.classList.toggle('visible', searchTerm.length > 0);
664
+
665
+ // Filter endpoints
666
+ if (searchTerm) {
667
+ filteredEndpoints = endpoints.filter(endpoint =>
668
+ endpoint.name.toLowerCase().includes(searchTerm) ||
669
+ endpoint.description.toLowerCase().includes(searchTerm) ||
670
+ endpoint.category.toLowerCase().includes(searchTerm)
671
+ );
672
+ } else {
673
+ // Reset to current category filter
674
+ if (currentFilter === 'All') {
675
+ filteredEndpoints = [...endpoints];
676
+ } else {
677
+ filteredEndpoints = endpoints.filter(endpoint => endpoint.category === currentFilter);
678
+ }
679
+ }
680
+
681
+ displayedEndpoints = 12;
682
+ renderEndpoints();
683
+ }, 300);
684
+
685
+ elements.searchInput.addEventListener('input', handleSearch);
686
+
687
+ // Clear search
688
+ elements.searchClear.addEventListener('click', () => {
689
+ elements.searchInput.value = '';
690
+ elements.searchClear.classList.remove('visible');
691
+ filterEndpoints(currentFilter);
692
+ });
693
+ };
694
+
695
+ // Render Endpoints
696
+ const renderEndpoints = () => {
697
+ const endpointsToShow = filteredEndpoints.slice(0, displayedEndpoints);
698
+
699
+ elements.endpointsGrid.innerHTML = '';
700
+
701
+ if (endpointsToShow.length === 0) {
702
+ elements.endpointsGrid.innerHTML = `
703
+ <div style="grid-column: 1 / -1; text-align: center; padding: 3rem; color: var(--text-secondary);">
704
+ <i class="fas fa-search" style="font-size: 3rem; margin-bottom: 1rem; opacity: 0.5;"></i>
705
+ <h3>No endpoints found</h3>
706
+ <p>Try adjusting your search or filter criteria</p>
707
+ </div>
708
+ `;
709
+ elements.loadMoreBtn.style.display = 'none';
710
+ return;
711
+ }
712
+
713
+ endpointsToShow.forEach((endpoint, index) => {
714
+ const card = createEndpointCard(endpoint, index);
715
+ elements.endpointsGrid.appendChild(card);
716
+ });
717
+
718
+ // Show/hide load more button
719
+ elements.loadMoreBtn.style.display =
720
+ filteredEndpoints.length > displayedEndpoints ? 'block' : 'none';
721
+ };
722
+
723
+ // Create Endpoint Card
724
+ const createEndpointCard = (endpoint, index) => {
725
+ const card = document.createElement('div');
726
+ card.className = 'endpoint-card';
727
+ card.style.animationDelay = `${index * 0.1}s`;
728
+
729
+ card.innerHTML = `
730
+ <div class="endpoint-header">
731
+ <div>
732
+ <h3 class="endpoint-title">${endpoint.name}</h3>
733
+ <span class="endpoint-category">${endpoint.category}</span>
734
+ </div>
735
+ </div>
736
+ <p class="endpoint-description">${endpoint.description}</p>
737
+ <div class="endpoint-meta">
738
+ <span class="method-tag">${endpoint.method}</span>
739
+ ${endpoint.params.length > 0 ?
740
+ endpoint.params.map(param => `<span class="param-tag">${param}</span>`).join('') :
741
+ '<span class="param-tag">No params</span>'
742
+ }
743
+ </div>
744
+ <div class="endpoint-actions">
745
+ <button class="action-btn action-btn-primary copy-btn" data-path="${endpoint.path}">
746
+ <i class="fas fa-copy"></i>
747
+ <span>Copy</span>
748
+ </button>
749
+ <button class="action-btn action-btn-secondary test-btn" data-path="${endpoint.path}">
750
+ <i class="fas fa-external-link-alt"></i>
751
+ <span>Test</span>
752
+ </button>
753
+ </div>
754
+ `;
755
+
756
+ // Add event listeners
757
+ const copyBtn = card.querySelector('.copy-btn');
758
+ const testBtn = card.querySelector('.test-btn');
759
+
760
+ copyBtn.addEventListener('click', (e) => {
761
+ e.stopPropagation();
762
+ const url = `${window.location.origin}${endpoint.path}`;
763
+ navigator.clipboard.writeText(url).then(() => {
764
+ showToast('URL copied to clipboard!');
765
+ });
766
+ });
767
+
768
+ testBtn.addEventListener('click', (e) => {
769
+ e.stopPropagation();
770
+ const url = `${window.location.origin}${endpoint.path}`;
771
+ window.open(url, '_blank');
772
+ });
773
+
774
+ // Card click to show modal
775
+ card.addEventListener('click', () => {
776
+ showEndpointModal(endpoint);
777
+ });
778
+
779
+ return card;
780
+ };
781
+
782
+ // Load More Endpoints
783
+ const initLoadMore = () => {
784
+ elements.loadMoreBtn.addEventListener('click', () => {
785
+ if (isLoading) return;
786
+
787
+ isLoading = true;
788
+ elements.loadMoreBtn.innerHTML = `
789
+ <i class="fas fa-spinner fa-spin"></i>
790
+ <span>Loading...</span>
791
+ `;
792
+
793
+ setTimeout(() => {
794
+ displayedEndpoints += 12;
795
+ renderEndpoints();
796
+ isLoading = false;
797
+ elements.loadMoreBtn.innerHTML = `
798
+ <i class="fas fa-plus"></i>
799
+ <span>Load More</span>
800
+ `;
801
+ }, 500);
802
+ });
803
+ };
804
+
805
+ // Modal Functions
806
+ const showEndpointModal = (endpoint) => {
807
+ elements.modalTitle.textContent = endpoint.name;
808
+ elements.modalBody.innerHTML = `
809
+ <div style="margin-bottom: 1.5rem;">
810
+ <h4 style="color: var(--text-primary); margin-bottom: 0.5rem;">Description</h4>
811
+ <p style="color: var(--text-secondary);">${endpoint.description}</p>
812
+ </div>
813
+
814
+ <div style="margin-bottom: 1.5rem;">
815
+ <h4 style="color: var(--text-primary); margin-bottom: 0.5rem;">Endpoint URL</h4>
816
+ <div class="code-block">
817
+ <code>${window.location.origin}${endpoint.path}</code>
818
+ </div>
819
+ </div>
820
+
821
+ <div style="margin-bottom: 1.5rem;">
822
+ <h4 style="color: var(--text-primary); margin-bottom: 0.5rem;">Method</h4>
823
+ <span class="method-tag">${endpoint.method}</span>
824
+ </div>
825
+
826
+ <div style="margin-bottom: 1.5rem;">
827
+ <h4 style="color: var(--text-primary); margin-bottom: 0.5rem;">Parameters</h4>
828
+ <div style="display: flex; flex-wrap: wrap; gap: 0.5rem;">
829
+ ${endpoint.params.length > 0 ?
830
+ endpoint.params.map(param => `<span class="param-tag">${param}</span>`).join('') :
831
+ '<span style="color: var(--text-secondary);">No parameters required</span>'
832
+ }
833
+ </div>
834
+ </div>
835
+
836
+ <div style="margin-bottom: 1.5rem;">
837
+ <h4 style="color: var(--text-primary); margin-bottom: 0.5rem;">Example Request</h4>
838
+ <div class="code-block">
839
+ <code>curl -X ${endpoint.method} "${window.location.origin}${endpoint.path}"</code>
840
+ </div>
841
+ </div>
842
+
843
+ <div style="display: flex; gap: 1rem; margin-top: 2rem;">
844
+ <button class="btn btn-primary" onclick="copyEndpointURL('${endpoint.path}')">
845
+ <i class="fas fa-copy"></i>
846
+ <span>Copy URL</span>
847
+ </button>
848
+ <button class="btn btn-secondary" onclick="testEndpoint('${endpoint.path}')">
849
+ <i class="fas fa-external-link-alt"></i>
850
+ <span>Test Endpoint</span>
851
+ </button>
852
+ </div>
853
+ `;
854
+
855
+ elements.modal.classList.add('active');
856
+ document.body.style.overflow = 'hidden';
857
+ };
858
+
859
+ const hideEndpointModal = () => {
860
+ elements.modal.classList.remove('active');
861
+ document.body.style.overflow = '';
862
+ };
863
+
864
+ // Global functions for modal buttons
865
+ window.copyEndpointURL = (path) => {
866
+ const url = `${window.location.origin}${path}`;
867
+ navigator.clipboard.writeText(url).then(() => {
868
+ showToast('URL copied to clipboard!');
869
+ });
870
+ };
871
+
872
+ window.testEndpoint = (path) => {
873
+ const url = `${window.location.origin}${path}`;
874
+ window.open(url, '_blank');
875
+ };
876
+
877
+ // Modal event listeners
878
+ const initModal = () => {
879
+ elements.modalClose.addEventListener('click', hideEndpointModal);
880
+ elements.modalBackdrop.addEventListener('click', hideEndpointModal);
881
+
882
+ document.addEventListener('keydown', (e) => {
883
+ if (e.key === 'Escape' && elements.modal.classList.contains('active')) {
884
+ hideEndpointModal();
885
+ }
886
+ });
887
+ };
888
+
889
+ // Floating Action Button
890
+ const initFAB = () => {
891
+ elements.fabMain.addEventListener('click', () => {
892
+ elements.fab.classList.toggle('active');
893
+ });
894
+
895
+ // FAB actions
896
+ document.querySelectorAll('.fab-action').forEach(action => {
897
+ action.addEventListener('click', () => {
898
+ const actionType = action.getAttribute('data-action');
899
+
900
+ switch (actionType) {
901
+ case 'top':
902
+ window.scrollTo({ top: 0, behavior: 'smooth' });
903
+ break;
904
+ case 'share':
905
+ if (navigator.share) {
906
+ navigator.share({
907
+ title: 'BLUE DEMON API',
908
+ text: 'Check out this awesome API platform!',
909
+ url: window.location.href
910
+ });
911
+ } else {
912
+ navigator.clipboard.writeText(window.location.href);
913
+ showToast('URL copied to clipboard!');
914
+ }
915
+ break;
916
+ case 'theme':
917
+ showToast('Theme toggle coming soon!');
918
+ break;
919
+ }
920
+
921
+ elements.fab.classList.remove('active');
922
+ });
923
+ });
924
+
925
+ // Close FAB when clicking outside
926
+ document.addEventListener('click', (e) => {
927
+ if (!elements.fab.contains(e.target)) {
928
+ elements.fab.classList.remove('active');
929
+ }
930
+ });
931
+ };
932
+
933
+ // Scroll to section function
934
+ window.scrollToSection = (sectionId) => {
935
+ const section = document.getElementById(sectionId);
936
+ if (section) {
937
+ const offsetTop = section.offsetTop - 60;
938
+ window.scrollTo({
939
+ top: offsetTop,
940
+ behavior: 'smooth'
941
+ });
942
+ }
943
+ };
944
+
945
+ // Initialize everything
946
+ const init = () => {
947
+ // Initialize components
948
+ initParticles();
949
+ initNavigation();
950
+ initTypewriter();
951
+ initSearch();
952
+ initLoadMore();
953
+ initModal();
954
+ initFAB();
955
+
956
+ // Create content
957
+ createCategoryFilters();
958
+
959
+ // Initial render
960
+ filterEndpoints('All');
961
+
962
+ // Fetch data
963
+ fetchRequestCount();
964
+
965
+ // Update request count periodically
966
+ setInterval(fetchRequestCount, 30000);
967
+ };
968
+
969
+ // Start when DOM is loaded
970
+ if (document.readyState === 'loading') {
971
+ document.addEventListener('DOMContentLoaded', init);
972
+ } else {
973
+ init();
974
+ }
styles.css ADDED
@@ -0,0 +1,317 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* ====== CSS VARIABLES ====== */
2
+ :root {
3
+ --bg: #0a0a0f;
4
+ --surface: rgba(255, 255, 255, 0.05);
5
+ --border: rgba(255, 255, 255, 0.08);
6
+ --accent: #6366f1;
7
+ --text: #ffffff;
8
+ --text2: #a1a1aa;
9
+ --radius: 16px;
10
+ --font: "Inter", sans-serif;
11
+ --mono: "JetBrains Mono", monospace;
12
+ }
13
+
14
+ /* ====== RESET ====== */
15
+ * { margin: 0; padding: 0; box-sizing: border-box; }
16
+ html { scroll-behavior: smooth; }
17
+ body {
18
+ font-family: var(--font);
19
+ background: var(--bg);
20
+ color: var(--text);
21
+ line-height: 1.6;
22
+ overflow-x: hidden;
23
+ }
24
+
25
+ /* ====== LIQUID BACKGROUND ====== */
26
+ .liquid-bg {
27
+ position: fixed;
28
+ inset: 0;
29
+ z-index: -1;
30
+ overflow: hidden;
31
+ }
32
+ .orb {
33
+ position: absolute;
34
+ border-radius: 50%;
35
+ filter: blur(80px);
36
+ opacity: .65;
37
+ animation: drift 20s infinite ease-in-out;
38
+ }
39
+ .orb-1 { width: 50vw; height: 50vw; top: -15%; left: -15%; background: #6366f1; }
40
+ .orb-2 { width: 40vw; height: 40vw; bottom: -15%; right: -15%; background: #06b6d4; }
41
+ .orb-3 { width: 30vw; height: 30vw; top: 30%; left: 30%; background: #a855f7; }
42
+
43
+ @keyframes drift {
44
+ 0% { transform: translate(0,0) scale(1); }
45
+ 50% { transform: translate(40px,-40px) scale(1.15); }
46
+ 100% { transform: translate(0,0) scale(1); }
47
+ }
48
+
49
+ /* ====== HEADER ====== */
50
+ .header {
51
+ position: sticky;
52
+ top: 0;
53
+ z-index: 10;
54
+ display: flex;
55
+ align-items: center;
56
+ justify-content: space-between;
57
+ padding: 1rem 2rem;
58
+ background: var(--surface);
59
+ backdrop-filter: blur(20px);
60
+ border-bottom: 1px solid var(--border);
61
+ }
62
+ .logo {
63
+ font-weight: 700;
64
+ font-size: 1.2rem;
65
+ display: flex;
66
+ align-items: center;
67
+ gap: .5rem;
68
+ color: var(--accent);
69
+ }
70
+ nav {
71
+ display: flex;
72
+ gap: 1.2rem;
73
+ }
74
+ nav a {
75
+ color: var(--text2);
76
+ font-weight: 500;
77
+ text-decoration: none;
78
+ transition: color .2s;
79
+ }
80
+ nav a:hover { color: var(--accent); }
81
+
82
+ /* ====== HERO ====== */
83
+ .hero {
84
+ display: flex;
85
+ flex-direction: column;
86
+ align-items: center;
87
+ justify-content: center;
88
+ text-align: center;
89
+ min-height: 50vh;
90
+ padding: 4rem 1rem;
91
+ }
92
+ .hero-title {
93
+ font-size: clamp(2.2rem, 6vw, 3.5rem);
94
+ font-weight: 800;
95
+ }
96
+ .hero-title .accent { color: var(--accent); }
97
+ .hero-sub {
98
+ margin: .75rem 0 2rem;
99
+ color: var(--text2);
100
+ }
101
+ .cta {
102
+ background: var(--accent);
103
+ color: #fff;
104
+ border: none;
105
+ padding: .9rem 2rem;
106
+ border-radius: 50px;
107
+ font-weight: 600;
108
+ cursor: pointer;
109
+ transition: transform .2s, box-shadow .2s;
110
+ }
111
+ .cta:hover { transform: translateY(-3px); box-shadow: 0 8px 25px rgba(99,102,241,.35); }
112
+
113
+ /* ====== STATS ====== */
114
+ .stats {
115
+ display: flex;
116
+ justify-content: center;
117
+ gap: 2.5rem;
118
+ padding: 2rem 1rem;
119
+ flex-wrap: wrap;
120
+ }
121
+ .stat-card {
122
+ background: var(--surface);
123
+ border: 1px solid var(--border);
124
+ border-radius: var(--radius);
125
+ padding: 1.2rem 2rem;
126
+ text-align: center;
127
+ min-width: 150px;
128
+ backdrop-filter: blur(20px);
129
+ }
130
+ .stat-card i { display: block; font-size: 1.5rem; color: var(--accent); margin-bottom: .4rem; }
131
+ .stat-card span { font-size: 1.4rem; font-weight: 700; }
132
+ .stat-card small { color: var(--text2); }
133
+
134
+ /* ====== API SECTION ====== */
135
+ .api-section { padding: 3rem 1rem; max-width: 1000px; margin: auto; }
136
+ .controls { margin-bottom: 2rem; }
137
+ #search {
138
+ width: 100%;
139
+ max-width: 400px;
140
+ margin: 0 auto 1rem;
141
+ display: block;
142
+ padding: .75rem 1rem;
143
+ border-radius: 50px;
144
+ border: 1px solid var(--border);
145
+ background: var(--surface);
146
+ color: var(--text);
147
+ }
148
+ .pills {
149
+ display: flex;
150
+ justify-content: center;
151
+ gap: .5rem;
152
+ flex-wrap: wrap;
153
+ }
154
+ .pill {
155
+ padding: .4rem 1rem;
156
+ border: 1px solid var(--border);
157
+ border-radius: 50px;
158
+ background: transparent;
159
+ color: var(--text2);
160
+ cursor: pointer;
161
+ transition: all .2s;
162
+ }
163
+ .pill.active,
164
+ .pill:hover { background: var(--accent); color: #fff; border-color: var(--accent); }
165
+
166
+ /* ====== GRID ====== */
167
+ .grid {
168
+ display: grid;
169
+ gap: 1.5rem;
170
+ grid-template-columns: repeat(auto-fill,minmax(280px,1fr));
171
+ }
172
+ .card {
173
+ background: var(--surface);
174
+ border: 1px solid var(--border);
175
+ border-radius: var(--radius);
176
+ padding: 1.5rem;
177
+ transition: transform .25s, box-shadow .25s;
178
+ cursor: pointer;
179
+ position: relative;
180
+ }
181
+ .card:hover {
182
+ transform: translateY(-5px);
183
+ box-shadow: 0 12px 30px rgba(0,0,0,.4);
184
+ }
185
+ .card h4 { margin-bottom: .5rem; font-size: 1.1rem; }
186
+ .card .cat {
187
+ display: inline-block;
188
+ font-size: .7rem;
189
+ background: var(--accent);
190
+ color: #fff;
191
+ padding: .2rem .6rem;
192
+ border-radius: 20px;
193
+ margin-bottom: .7rem;
194
+ }
195
+ .card p { font-size: .9rem; color: var(--text2); }
196
+ .card .method {
197
+ position: absolute;
198
+ top: 1rem;
199
+ right: 1rem;
200
+ font-family: var(--mono);
201
+ font-size: .7rem;
202
+ background: rgba(16,185,129,.2);
203
+ color: #10b981;
204
+ padding: .15rem .4rem;
205
+ border-radius: 4px;
206
+ }
207
+
208
+ .load-more {
209
+ display: block;
210
+ margin: 2.5rem auto 0;
211
+ padding: .75rem 2rem;
212
+ border: 1px solid var(--accent);
213
+ border-radius: 50px;
214
+ color: var(--accent);
215
+ background: transparent;
216
+ cursor: pointer;
217
+ transition: all .2s;
218
+ }
219
+ .load-more:hover { background: var(--accent); color: #fff; }
220
+
221
+ /* ====== DOCS ====== */
222
+ .docs {
223
+ background: var(--surface);
224
+ margin: 2rem 0;
225
+ padding: 3rem 1rem;
226
+ text-align: center;
227
+ }
228
+ .docs h2 { font-size: 1.8rem; margin-bottom: 2rem; }
229
+ .steps {
230
+ display: grid;
231
+ grid-template-columns: repeat(auto-fit,minmax(220px,1fr));
232
+ gap: 2rem;
233
+ max-width: 800px;
234
+ margin: auto;
235
+ }
236
+ .step-icon {
237
+ width: 60px; height: 60px;
238
+ margin: 0 auto 1rem;
239
+ border-radius: 50%;
240
+ background: var(--accent);
241
+ display: grid; place-items: center;
242
+ font-size: 1.5rem;
243
+ color: #fff;
244
+ }
245
+ article h3 { font-size: 1.1rem; margin-bottom: .5rem; }
246
+ article p { color: var(--text2); }
247
+
248
+ /* ====== FOOTER ====== */
249
+ footer {
250
+ text-align: center;
251
+ padding: 2rem 1rem;
252
+ color: var(--text2);
253
+ }
254
+ .social {
255
+ display: flex;
256
+ justify-content: center;
257
+ gap: 1rem;
258
+ margin-bottom: .8rem;
259
+ }
260
+ .social a {
261
+ color: var(--text2);
262
+ font-size: 1.3rem;
263
+ transition: color .2s;
264
+ }
265
+ .social a:hover { color: var(--accent); }
266
+
267
+ /* ====== MODAL ====== */
268
+ .modal {
269
+ position: fixed;
270
+ inset: 0;
271
+ z-index: 100;
272
+ display: grid;
273
+ place-items: center;
274
+ padding: 1rem;
275
+ background: rgba(0,0,0,.6);
276
+ backdrop-filter: blur(8px);
277
+ opacity: 0;
278
+ visibility: hidden;
279
+ transition: opacity .3s;
280
+ }
281
+ .modal.active { opacity: 1; visibility: visible; }
282
+ .modal-card {
283
+ background: var(--surface);
284
+ border: 1px solid var(--border);
285
+ border-radius: var(--radius);
286
+ width: 100%;
287
+ max-width: 450px;
288
+ max-height: 80vh;
289
+ overflow-y: auto;
290
+ padding: 2rem;
291
+ position: relative;
292
+ }
293
+ .modal-close {
294
+ position: absolute;
295
+ top: 1rem; right: 1rem;
296
+ background: none;
297
+ border: none;
298
+ font-size: 1.5rem;
299
+ color: var(--text2);
300
+ cursor: pointer;
301
+ }
302
+ .code-snippet {
303
+ background: #111;
304
+ border: 1px solid var(--border);
305
+ border-radius: 8px;
306
+ padding: 1rem;
307
+ font-family: var(--mono);
308
+ font-size: .85rem;
309
+ margin-top: 1rem;
310
+ overflow-x: auto;
311
+ }
312
+
313
+ /* ====== RESPONSIVE ====== */
314
+ @media (max-width: 600px) {
315
+ .header { padding: 1rem; }
316
+ nav { display: none; } /* simple for now */
317
+ }