husteno-o

[email protected]
2026-09-09 12:34:36 +0600 committed NaN years ago
1985bf3
commit 1985bf3
6 files changed
+1006 -2629
▼apps/web/build.ts
+6-1
29
29
process.exit(1);
30
30
}
31
31
32
-// Copy HTML and CSS
32
+// Copy HTML, CSS, and assets
33
33
await cp(path.join(srcDir, "index.html"), path.join(distDir, "index.html"));
34
34
await cp(path.join(srcDir, "styles.css"), path.join(distDir, "styles.css"));
35
35
36
+// Copy public assets (logo.svg, etc.)
37
+if (existsSync(publicDir)) {
38
+ await cp(publicDir, distDir, { recursive: true });
39
+}
40
+
36
41
// Copy public assets & Cloudflare Pages files (_headers, etc.)
37
42
if (existsSync(publicDir)) {
38
43
await cp(publicDir, distDir, { recursive: true });
39
44
▼apps/web/public/logo.svg
+66-0
1
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="none">
2
+ <defs>
3
+ <linearGradient id="logo-gradient" x1="0%" y1="0%" x2="100%" y2="100%">
4
+ <stop offset="0%" style="stop-color:#22c55e"/>
5
+ <stop offset="50%" style="stop-color:#3b82f6"/>
6
+ <stop offset="100%" style="stop-color:#8b5cf6"/>
7
+ </linearGradient>
8
+ <linearGradient id="logo-gradient-alt" x1="0%" y1="0%" x2="100%" y2="100%">
9
+ <stop offset="0%" style="stop-color:#16a34a"/>
10
+ <stop offset="100%" style="stop-color:#2563eb"/>
11
+ </linearGradient>
12
+ <filter id="glow">
13
+ <feGaussianBlur stdDeviation="4" result="coloredBlur"/>
14
+ <feMerge>
15
+ <feMergeNode in="coloredBlur"/>
16
+ <feMergeNode in="SourceGraphic"/>
17
+ </feMerge>
18
+ </filter>
19
+ </defs>
20
+
21
+ <!-- Background circle with gradient -->
22
+ <circle cx="256" cy="256" r="240" fill="url(#logo-gradient)" opacity="0.1"/>
23
+
24
+ <!-- Main pulse ring -->
25
+ <circle cx="256" cy="256" r="200" stroke="url(#logo-gradient)" stroke-width="2" opacity="0.3" fill="none">
26
+ <animate attributeName="r" values="190;210;190" dur="3s" repeatCount="indefinite"/>
27
+ <animate attributeName="opacity" values="0.3;0.1;0.3" dur="3s" repeatCount="indefinite"/>
28
+ </circle>
29
+
30
+ <!-- Second pulse ring -->
31
+ <circle cx="256" cy="256" r="160" stroke="url(#logo-gradient)" stroke-width="1.5" opacity="0.2" fill="none">
32
+ <animate attributeName="r" values="150;170;150" dur="4s" repeatCount="indefinite"/>
33
+ <animate attributeName="opacity" values="0.2;0.05;0.2" dur="4s" repeatCount="indefinite"/>
34
+ </circle>
35
+
36
+ <!-- Central hub - stylized "D" shape -->
37
+ <g filter="url(#glow)">
38
+ <!-- Left vertical bar of D -->
39
+ <rect x="140" y="140" width="32" height="232" rx="16" fill="url(#logo-gradient-alt)"/>
40
+
41
+ <!-- Curved part of D -->
42
+ <path d="M172 140 C280 140, 360 196, 360 256 C360 316, 280 372, 172 372 L172 336 C256 336, 320 300, 320 256 C320 212, 256 176, 172 176 Z" fill="url(#logo-gradient)"/>
43
+ </g>
44
+
45
+ <!-- Pulse dots representing activity -->
46
+ <circle cx="380" cy="200" r="8" fill="#22c55e">
47
+ <animate attributeName="opacity" values="1;0.3;1" dur="2s" repeatCount="indefinite"/>
48
+ </circle>
49
+ <circle cx="400" cy="256" r="6" fill="#3b82f6">
50
+ <animate attributeName="opacity" values="0.3;1;0.3" dur="2.5s" repeatCount="indefinite"/>
51
+ </circle>
52
+ <circle cx="380" cy="312" r="8" fill="#8b5cf6">
53
+ <animate attributeName="opacity" values="1;0.3;1" dur="1.8s" repeatCount="indefinite"/>
54
+ </circle>
55
+
56
+ <!-- Connection lines from center to dots -->
57
+ <line x1="340" y1="220" x2="380" y2="200" stroke="#22c55e" stroke-width="2" opacity="0.6">
58
+ <animate attributeName="opacity" values="0.6;0.2;0.6" dur="2s" repeatCount="indefinite"/>
59
+ </line>
60
+ <line x1="340" y1="256" x2="400" y2="256" stroke="#3b82f6" stroke-width="2" opacity="0.6">
61
+ <animate attributeName="opacity" values="0.2;0.6;0.2" dur="2.5s" repeatCount="indefinite"/>
62
+ </line>
63
+ <line x1="340" y1="292" x2="380" y2="312" stroke="#8b5cf6" stroke-width="2" opacity="0.6">
64
+ <animate attributeName="opacity" values="0.6;0.2;0.6" dur="1.8s" repeatCount="indefinite"/>
65
+ </line>
66
+</svg>
0
67
▼apps/web/src/app.ts
+517-417
1
-// DevPulse Interactive Landing Page Controller (Strictly SVG Icons, Zero Emojis)
2
-import { icons } from "./icons.js";
1
+// DevPulse Landing Page Controller
2
+// Uses Lucide icons (loaded via CDN in HTML)
3
3
4
-export interface SimState {
4
+interface SimState {
5
5
activeTab: string;
6
6
prStatus: "open" | "approved" | "changes_requested" | "merged";
7
- repoTab: "overview" | "commits" | "prs" | "issues" | "releases";
7
+ repoTab: string;
8
8
}
9
9
10
10
const state: SimState = {
13
13
repoTab: "overview",
14
14
};
15
15
16
-// Clipboard copy helper with animated SVG checkmark
17
-export function copyText(text: string, triggerBtn?: HTMLElement) {
18
- navigator.clipboard.writeText(text).then(() => {
19
- if (triggerBtn) {
20
- const originalHtml = triggerBtn.innerHTML;
21
- triggerBtn.innerHTML = `
22
- ${icons.check(14, "#3fb950")}
23
- <span style="color: #3fb950; font-weight: 600;">Copied</span>
24
- `;
25
- setTimeout(() => {
26
- triggerBtn.innerHTML = originalHtml;
27
- }, 2200);
28
- }
29
- });
16
+// All 21 commands data
17
+const commands = [
18
+ {
19
+ name: "/repo",
20
+ desc: "Repository intelligence, health score, dependencies, growth",
21
+ icon: "book-open",
22
+ color: "gh-blue",
23
+ },
24
+ {
25
+ name: "/pr",
26
+ desc: "PR details, CI status, approve, request changes, merge",
27
+ icon: "git-pull-request",
28
+ color: "gh-green",
29
+ },
30
+ {
31
+ name: "/search",
32
+ desc: "Search code, issues, PRs, repos, commits with qualifiers",
33
+ icon: "search",
34
+ color: "gh-purple",
35
+ },
36
+ {
37
+ name: "/code",
38
+ desc: "View files, git blame, commit-to-PR resolution",
39
+ icon: "code",
40
+ color: "gh-blue",
41
+ },
42
+ {
43
+ name: "/investigate",
44
+ desc: "Full lifecycle: issue → commit → PR → review → merge → release",
45
+ icon: "git-merge",
46
+ color: "gh-purple",
47
+ },
48
+ {
49
+ name: "/activity",
50
+ desc: "Commit histograms, churn analysis, personal telemetry",
51
+ icon: "bar-chart-2",
52
+ color: "gh-green",
53
+ },
54
+ {
55
+ name: "/trending",
56
+ desc: "Trending repos across TypeScript, Rust, AI/ML, Go, Python",
57
+ icon: "trending-up",
58
+ color: "gh-amber",
59
+ },
60
+ {
61
+ name: "/watch",
62
+ desc: "Subscribe channels to releases, PRs, issues, security alerts",
63
+ icon: "bell",
64
+ color: "gh-blue",
65
+ },
66
+ {
67
+ name: "/actions",
68
+ desc: "CI/CD workflow trees, run history, rerun/cancel controls",
69
+ icon: "play-circle",
70
+ color: "gh-green",
71
+ },
72
+ {
73
+ name: "/security",
74
+ desc: "Dependabot alerts, CVE lookup, real-time secret scanner",
75
+ icon: "shield-check",
76
+ color: "gh-coral",
77
+ },
78
+ {
79
+ name: "/release",
80
+ desc: "Latest releases, tag comparison, auto changelog generator",
81
+ icon: "tag",
82
+ color: "gh-purple",
83
+ },
84
+ {
85
+ name: "/team",
86
+ desc: "Team velocity, cycle times, review load balancing",
87
+ icon: "users",
88
+ color: "gh-blue",
89
+ },
90
+ {
91
+ name: "/home",
92
+ desc: "Morning cockpit: active PRs, reviews, alerts, trending",
93
+ icon: "home",
94
+ color: "gh-green",
95
+ },
96
+ {
97
+ name: "/connect",
98
+ desc: "AES-256-GCM encrypted PAT storage for write actions",
99
+ icon: "link",
100
+ color: "gh-blue",
101
+ },
102
+ {
103
+ name: "/why",
104
+ desc: "Trace file/line → commit → PR → originating issue",
105
+ icon: "help-circle",
106
+ color: "gh-purple",
107
+ },
108
+ {
109
+ name: "/ask",
110
+ desc: "Query engine: stale PRs, bottlenecks, frequent files",
111
+ icon: "message-circle",
112
+ color: "gh-green",
113
+ },
114
+ {
115
+ name: "/tools",
116
+ desc: "JSON formatter, base64, JWT inspector, hash, timestamps",
117
+ icon: "wrench",
118
+ color: "gh-amber",
119
+ },
120
+ {
121
+ name: "/settings",
122
+ desc: "Server config: repos, channels, access controls",
123
+ icon: "settings",
124
+ color: "gh-blue",
125
+ },
126
+ {
127
+ name: "/help",
128
+ desc: "Interactive command directory with examples",
129
+ icon: "info",
130
+ color: "gh-green",
131
+ },
132
+ {
133
+ name: "/ai",
134
+ desc: "AI code explanations, PR summaries, bug fix suggestions",
135
+ icon: "brain",
136
+ color: "gh-coral",
137
+ },
138
+ {
139
+ name: "/code-review",
140
+ desc: "Automated PR review: security, performance, style",
141
+ icon: "eye",
142
+ color: "gh-purple",
143
+ },
144
+];
145
+
146
+// Initialize everything
147
+document.addEventListener("DOMContentLoaded", () => {
148
+ // Initialize Lucide icons
149
+ if (typeof lucide !== "undefined") {
150
+ lucide.createIcons();
151
+ }
152
+
153
+ // Build commands grid
154
+ buildCommandsGrid();
155
+
156
+ // Initialize simulator
157
+ initSimulator();
158
+
159
+ // Initialize navbar
160
+ initNavbar();
161
+
162
+ // Initialize mobile menu
163
+ initMobileMenu();
164
+
165
+ // Initialize copy buttons
166
+ initCopyButtons();
167
+
168
+ // Initialize scroll effects
169
+ initScrollEffects();
170
+});
171
+
172
+// Build the 21 commands grid
173
+function buildCommandsGrid() {
174
+ const grid = document.getElementById("commands-grid");
175
+ if (!grid) return;
176
+
177
+ grid.innerHTML = commands
178
+ .map(
179
+ (cmd) => `
180
+ <div class="command-card group p-4 rounded-xl bg-bg-surface border border-border hover:border-${cmd.color}/30 cursor-default">
181
+ <div class="flex items-start gap-3">
182
+ <div class="w-9 h-9 rounded-lg bg-${cmd.color}/10 border border-${cmd.color}/20 flex items-center justify-center flex-shrink-0 group-hover:scale-110 transition-transform duration-200">
183
+ <i data-lucide="${cmd.icon}" class="w-4 h-4 text-${cmd.color}"></i>
184
+ </div>
185
+ <div class="min-w-0">
186
+ <div class="flex items-center gap-2 mb-1">
187
+ <span class="text-sm font-mono font-semibold text-${cmd.color}">${cmd.name}</span>
188
+ </div>
189
+ <p class="text-xs text-text-secondary leading-relaxed">${cmd.desc}</p>
190
+ </div>
191
+ </div>
192
+ </div>
193
+ `,
194
+ )
195
+ .join("");
196
+
197
+ // Re-initialize icons for new elements
198
+ if (typeof lucide !== "undefined") {
199
+ lucide.createIcons();
200
+ }
30
201
}
31
202
32
-// Simulator views
33
-const tabTemplates: Record<string, () => string> = {
34
- pr: () => {
35
- let statusBadge = `<span class="status-tag status-tag-green">${icons.checkCircle(14, "#3fb950")} Ready to merge</span>`;
36
- let mergeButtonHtml = `<button class="discord-btn discord-btn-primary" id="sim-btn-merge">${icons.gitMerge(14, "#ffffff")} Merge into main</button>`;
37
-
38
- if (state.prStatus === "approved") {
39
- statusBadge = `<span class="status-tag status-tag-green">${icons.checkCircle(14, "#3fb950")} Approved by you</span>`;
40
- } else if (state.prStatus === "changes_requested") {
41
- statusBadge = `<span class="status-tag" style="background: rgba(248,81,73,0.15); color: #f85149; border: 1px solid rgba(248,81,73,0.3)">${icons.alertTriangle(14, "#f85149")} Changes Requested</span>`;
42
- } else if (state.prStatus === "merged") {
43
- statusBadge = `<span class="status-tag status-tag-purple">${icons.gitMerge(14, "#a371f7")} Merged into main (commit #9a8f2c)</span>`;
44
- mergeButtonHtml = `<button class="discord-btn discord-btn-disabled" disabled>${icons.gitMerge(14, "#8b949e")} Merged</button>`;
45
- }
203
+// Simulator
204
+function initSimulator() {
205
+ renderSimulator();
206
+ attachSimulatorEvents();
207
+}
208
+
209
+function renderSimulator() {
210
+ const container = document.getElementById("simulator-body");
211
+ if (!container) return;
46
212
47
- return `
48
- <div class="discord-message">
49
- <div class="discord-avatar">
50
- ${icons.gitPullRequest(22, "#ffffff")}
213
+ const templates: Record<string, () => string> = {
214
+ pr: () => renderPREmbed(),
215
+ repo: () => renderRepoEmbed(),
216
+ actions: () => renderActionsEmbed(),
217
+ investigate: () => renderInvestigateEmbed(),
218
+ code: () => renderCodeEmbed(),
219
+ activity: () => renderActivityEmbed(),
220
+ };
221
+
222
+ const renderer = templates[state.activeTab];
223
+ if (renderer) {
224
+ container.style.opacity = "0";
225
+ container.style.transform = "translateY(8px)";
226
+ container.style.transition = "opacity 0.15s ease, transform 0.15s ease";
227
+
228
+ requestAnimationFrame(() => {
229
+ container.innerHTML = renderer();
230
+ requestAnimationFrame(() => {
231
+ container.style.opacity = "1";
232
+ container.style.transform = "translateY(0)";
233
+ });
234
+ });
235
+ }
236
+}
237
+
238
+function renderPREmbed() {
239
+ const statusMap = {
240
+ open: { text: "Ready to merge", color: "gh-green", icon: "check-circle" },
241
+ approved: { text: "Approved by you", color: "gh-green", icon: "check-circle" },
242
+ changes_requested: { text: "Changes Requested", color: "gh-coral", icon: "alert-triangle" },
243
+ merged: { text: "Merged into main", color: "gh-purple", icon: "git-merge" },
244
+ };
245
+ const status = statusMap[state.prStatus];
246
+
247
+ return `
248
+ <div class="flex gap-4">
249
+ <div class="w-10 h-10 rounded-full bg-gradient-to-br from-gh-green to-gh-blue flex items-center justify-center flex-shrink-0">
250
+ <i data-lucide="git-pull-request" class="w-5 h-5 text-white"></i>
251
+ </div>
252
+ <div class="flex-1 min-w-0">
253
+ <div class="flex items-center gap-2 mb-1">
254
+ <span class="font-semibold text-sm">DevPulse</span>
255
+ <span class="text-[10px] font-bold px-1.5 py-0.5 rounded bg-discord-blurple text-white uppercase">Bot</span>
256
+ <span class="text-xs text-text-muted">Today at 10:42 AM</span>
51
257
</div>
52
- <div class="discord-content">
53
- <div class="discord-header">
54
- <span class="bot-name">DevPulse</span>
55
- <span class="bot-tag">BOT</span>
56
- <span class="message-time">Today at 10:42 AM</span>
258
+ <div class="text-xs font-mono text-gh-blue mb-2">/pr 142 repo:vercel/next.js</div>
259
+ <div class="rounded-lg bg-discord-embed border-l-4 border-${status.color} p-4">
260
+ <div class="text-xs text-text-secondary mb-1">vercel/next.js • Pull Request #142</div>
261
+ <div class="text-sm font-semibold mb-2">feat(router): optimize parallel route cache hydration</div>
262
+ <div class="flex items-center gap-2 mb-3">
263
+ <span class="inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-[10px] font-semibold bg-${status.color}/10 text-${status.color} border border-${status.color}/30">
264
+ <i data-lucide="${status.icon}" class="w-3 h-3"></i> ${status.text}
265
+ </span>
266
+ <span class="text-xs text-text-muted">@timneutkens • 14 files • <span class="text-gh-green">+482</span> <span class="text-gh-coral">-193</span></span>
57
267
</div>
58
- <div class="command-echo">/pr 142 repo:vercel/next.js</div>
59
- <div class="discord-embed" style="border-left-color: ${state.prStatus === "merged" ? "#a371f7" : "#2ea043"}">
60
- <div class="embed-author">
61
- <span>vercel/next.js</span>
62
- <span>&bull;</span>
63
- <span>Pull Request #142</span>
268
+ <div class="grid grid-cols-2 gap-3 mb-3">
269
+ <div>
270
+ <div class="text-[10px] uppercase text-text-muted font-bold mb-0.5">CI Status</div>
271
+ <div class="text-xs"><i data-lucide="check-circle" class="w-3 h-3 text-gh-green inline"></i> 12/12 Passing</div>
64
272
</div>
65
- <div class="embed-title">
66
- feat(router): optimize parallel route cache hydration
67
- </div>
68
- <div class="embed-desc">
69
- ${statusBadge}
70
- Author: <strong>@timneutkens</strong> &bull; Target: <code>canary &larr; feature/route-cache</code>
71
- Files Changed: <strong>14</strong> &bull; <span style="color: #3fb950">+482</span> <span style="color: #f85149">&minus;193</span>
72
- </div>
73
- <div class="embed-grid">
74
- <div>
75
- <div class="embed-field-name">CI Status</div>
76
- <div class="embed-field-value">${icons.checkCircle(14, "#3fb950")} 12/12 Checks Passing</div>
77
- </div>
78
- <div>
79
- <div class="embed-field-name">Reviews</div>
80
- <div class="embed-field-value">${state.prStatus === "approved" ? "3/2 (Required met)" : "2/2 (Required met)"}</div>
81
- </div>
82
- <div>
83
- <div class="embed-field-name">Merge Conflicts</div>
84
- <div class="embed-field-value">None (Clean merge)</div>
85
- </div>
86
- <div>
87
- <div class="embed-field-name">Cycle Time</div>
88
- <div class="embed-field-value">1d 4h 12m</div>
89
- </div>
90
- </div>
91
- <div class="discord-action-row">
92
- <button class="discord-btn discord-btn-success" id="sim-btn-approve">${icons.check(14, "#ffffff")} Approve</button>
93
- <button class="discord-btn discord-btn-danger" id="sim-btn-changes">${icons.x(14, "#ffffff")} Request Changes</button>
94
- ${mergeButtonHtml}
95
- <button class="discord-btn" onclick="window.open('https://github.com', '_blank')">Open GitHub ${icons.externalLink(12, "#ffffff")}</button>
273
+ <div>
274
+ <div class="text-[10px] uppercase text-text-muted font-bold mb-0.5">Reviews</div>
275
+ <div class="text-xs">${state.prStatus === "approved" ? "3/2" : "2/2"} (Required met)</div>
96
276
</div>
97
277
</div>
278
+ <div class="flex gap-2 flex-wrap">
279
+ <button id="sim-btn-approve" class="inline-flex items-center gap-1.5 px-3 py-1.5 rounded-md bg-gh-green text-white text-xs font-semibold hover:bg-gh-green-h transition-colors">
280
+ <i data-lucide="check" class="w-3 h-3"></i> Approve
281
+ </button>
282
+ <button id="sim-btn-changes" class="inline-flex items-center gap-1.5 px-3 py-1.5 rounded-md bg-gh-coral text-white text-xs font-semibold hover:opacity-90 transition-colors">
283
+ <i data-lucide="x" class="w-3 h-3"></i> Request Changes
284
+ </button>
285
+ ${
286
+ state.prStatus === "merged"
287
+ ? `<button class="inline-flex items-center gap-1.5 px-3 py-1.5 rounded-md bg-gh-purple/20 text-gh-purple text-xs font-semibold" disabled><i data-lucide="git-merge" class="w-3 h-3"></i> Merged</button>`
288
+ : `<button id="sim-btn-merge" class="inline-flex items-center gap-1.5 px-3 py-1.5 rounded-md bg-discord-blurple text-white text-xs font-semibold hover:bg-discord-blurple-h transition-colors"><i data-lucide="git-merge" class="w-3 h-3"></i> Merge</button>`
289
+ }
290
+ </div>
98
291
</div>
99
292
</div>
100
- `;
101
- },
293
+ </div>
294
+ `;
295
+}
102
296
103
- repo: () => {
104
- return `
105
- <div class="discord-message">
106
- <div class="discord-avatar">
107
- ${icons.repo(22, "#ffffff")}
297
+function renderRepoEmbed() {
298
+ return `
299
+ <div class="flex gap-4">
300
+ <div class="w-10 h-10 rounded-full bg-gradient-to-br from-gh-green to-gh-blue flex items-center justify-center flex-shrink-0">
301
+ <i data-lucide="book-open" class="w-5 h-5 text-white"></i>
302
+ </div>
303
+ <div class="flex-1 min-w-0">
304
+ <div class="flex items-center gap-2 mb-1">
305
+ <span class="font-semibold text-sm">DevPulse</span>
306
+ <span class="text-[10px] font-bold px-1.5 py-0.5 rounded bg-discord-blurple text-white uppercase">Bot</span>
307
+ <span class="text-xs text-text-muted">Today at 10:45 AM</span>
108
308
</div>
109
- <div class="discord-content">
110
- <div class="discord-header">
111
- <span class="bot-name">DevPulse</span>
112
- <span class="bot-tag">BOT</span>
113
- <span class="message-time">Today at 10:45 AM</span>
114
- </div>
115
- <div class="command-echo">/repo name:vercel/next.js</div>
116
- <div class="discord-embed" style="border-left-color: #58a6ff">
117
- <div class="embed-author">Repository Intelligence</div>
118
- <div class="embed-title">vercel/next.js</div>
119
- <div class="embed-desc">
120
- The React Framework for the Web. Used by production engineering teams worldwide.
121
- <strong>Health Score: 96 / 100</strong> [■■■■■■■■■□]
309
+ <div class="text-xs font-mono text-gh-blue mb-2">/repo name:vercel/next.js</div>
310
+ <div class="rounded-lg bg-discord-embed border-l-4 border-gh-blue p-4">
311
+ <div class="text-sm font-semibold mb-2">vercel/next.js</div>
312
+ <div class="text-xs text-text-secondary mb-3">The React Framework for the Web. <strong class="text-text-primary">Health Score: 96/100</strong></div>
313
+ <div class="grid grid-cols-2 gap-3 mb-3">
314
+ <div>
315
+ <div class="text-[10px] uppercase text-text-muted font-bold mb-0.5">Stars & Forks</div>
316
+ <div class="text-xs flex items-center gap-1"><i data-lucide="star" class="w-3 h-3 text-gh-amber"></i> 124,510 • <i data-lucide="git-fork" class="w-3 h-3"></i> 26,840</div>
122
317
</div>
123
- <div class="embed-grid">
124
- <div>
125
- <div class="embed-field-name">Stars &amp; Forks</div>
126
- <div class="embed-field-value">${icons.star(14, "#e3b341")} 124,510 &bull; ${icons.repoForked(14, "#8b949e")} 26,840</div>
127
- </div>
128
- <div>
129
- <div class="embed-field-name">Open Issues / PRs</div>
130
- <div class="embed-field-value">Issues: 412 &bull; PRs: 89</div>
131
- </div>
132
- <div>
133
- <div class="embed-field-name">License / Branch</div>
134
- <div class="embed-field-value">MIT &bull; canary</div>
135
- </div>
136
- <div>
137
- <div class="embed-field-name">30-Day Velocity</div>
138
- <div class="embed-field-value"><span style="color:#3fb950">+1,840 stars</span> (+1.5%)</div>
139
- </div>
140
- </div>
141
- <div class="discord-action-row">
142
- <button class="discord-btn ${state.repoTab === "overview" ? "discord-btn-primary" : ""}" id="sim-repo-overview">Overview</button>
143
- <button class="discord-btn ${state.repoTab === "commits" ? "discord-btn-primary" : ""}" id="sim-repo-commits">Commits</button>
144
- <button class="discord-btn ${state.repoTab === "prs" ? "discord-btn-primary" : ""}" id="sim-repo-prs">PRs (89)</button>
145
- <button class="discord-btn ${state.repoTab === "issues" ? "discord-btn-primary" : ""}" id="sim-repo-issues">Issues (412)</button>
146
- <button class="discord-btn ${state.repoTab === "releases" ? "discord-btn-primary" : ""}" id="sim-repo-releases">Releases (v15.2.0)</button>
318
+ <div>
319
+ <div class="text-[10px] uppercase text-text-muted font-bold mb-0.5">Issues / PRs</div>
320
+ <div class="text-xs">412 / 89</div>
147
321
</div>
148
322
</div>
323
+ <div class="flex gap-2 flex-wrap">
324
+ <button class="px-3 py-1.5 rounded-md bg-gh-blue text-white text-xs font-semibold">Overview</button>
325
+ <button class="px-3 py-1.5 rounded-md bg-bg-surface text-text-secondary text-xs font-medium hover:bg-bg-hover transition-colors">Commits</button>
326
+ <button class="px-3 py-1.5 rounded-md bg-bg-surface text-text-secondary text-xs font-medium hover:bg-bg-hover transition-colors">PRs</button>
327
+ <button class="px-3 py-1.5 rounded-md bg-bg-surface text-text-secondary text-xs font-medium hover:bg-bg-hover transition-colors">Issues</button>
328
+ </div>
149
329
</div>
150
330
</div>
151
- `;
152
- },
331
+ </div>
332
+ `;
333
+}
153
334
154
- actions: () => {
155
- return `
156
- <div class="discord-message">
157
- <div class="discord-avatar">
158
- ${icons.actions(22, "#ffffff")}
335
+function renderActionsEmbed() {
336
+ return `
337
+ <div class="flex gap-4">
338
+ <div class="w-10 h-10 rounded-full bg-gradient-to-br from-gh-green to-gh-blue flex items-center justify-center flex-shrink-0">
339
+ <i data-lucide="play-circle" class="w-5 h-5 text-white"></i>
340
+ </div>
341
+ <div class="flex-1 min-w-0">
342
+ <div class="flex items-center gap-2 mb-1">
343
+ <span class="font-semibold text-sm">DevPulse</span>
344
+ <span class="text-[10px] font-bold px-1.5 py-0.5 rounded bg-discord-blurple text-white uppercase">Bot</span>
345
+ <span class="text-xs text-text-muted">Today at 10:48 AM</span>
159
346
</div>
160
- <div class="discord-content">
161
- <div class="discord-header">
162
- <span class="bot-name">DevPulse</span>
163
- <span class="bot-tag">BOT</span>
164
- <span class="message-time">Today at 10:48 AM</span>
347
+ <div class="text-xs font-mono text-gh-blue mb-2">/actions repo:vercel/next.js branch:canary</div>
348
+ <div class="rounded-lg bg-discord-embed border-l-4 border-gh-green p-4">
349
+ <div class="text-sm font-semibold mb-2">canary • Run #4,892 Passed</div>
350
+ <div class="font-mono text-xs text-text-secondary space-y-1 mb-3">
351
+ <div>├── Unit Tests (Node 20 & 22) <span class="text-gh-green">Passing</span> (1m 42s)</div>
352
+ <div>├── Turbopack Integration E2E <span class="text-gh-green">Passing</span> (4m 15s)</div>
353
+ <div>├── Edge Runtime Compatibility <span class="text-gh-green">Passing</span> (52s)</div>
354
+ <div>└── Security Scanning & Audit <span class="text-gh-green">Passing</span> (38s)</div>
165
355
</div>
166
- <div class="command-echo">/actions repo:vercel/next.js branch:canary</div>
167
- <div class="discord-embed" style="border-left-color: #2ea043">
168
- <div class="embed-author">GitHub Actions CI/CD Pipeline</div>
169
- <div class="embed-title">canary &bull; Run #4,892 Passed</div>
170
- <div class="embed-desc">Triggered by <strong>@leerob</strong> via push on commit <code>3a91e4f</code></div>
171
- <div class="embed-code-block">canary (commit 3a91e4f)
172
-|-- Unit Tests (Node 20 & 22) [Passing] (1m 42s)
173
-|-- Turbopack Integration E2E [Passing] (4m 15s)
174
-|-- Edge Runtime Compatibility [Passing] (52s)
175
-|-- Security Scanning & Audit [Passing] (38s)
176
-\\-- Production Bundle Analyzer [Passing] (1m 04s)</div>
177
- <div class="discord-action-row">
178
- <button class="discord-btn" id="sim-btn-rerun">${icons.sync(14, "#ffffff")} Rerun All Jobs</button>
179
- <button class="discord-btn discord-btn-danger" id="sim-btn-cancel" disabled>Cancel</button>
180
- <button class="discord-btn" onclick="window.open('https://github.com', '_blank')">View Workflow Run ${icons.externalLink(12, "#ffffff")}</button>
181
- </div>
356
+ <div class="flex gap-2">
357
+ <button id="sim-btn-rerun" class="inline-flex items-center gap-1.5 px-3 py-1.5 rounded-md bg-bg-surface text-text-primary text-xs font-semibold hover:bg-bg-hover transition-colors border border-border">
358
+ <i data-lucide="refresh-cw" class="w-3 h-3"></i> Rerun All
359
+ </button>
182
360
</div>
183
361
</div>
184
362
</div>
185
- `;
186
- },
363
+ </div>
364
+ `;
365
+}
187
366
188
- investigate: () => {
189
- return `
190
- <div class="discord-message">
191
- <div class="discord-avatar">
192
- ${icons.investigate(22, "#ffffff")}
367
+function renderInvestigateEmbed() {
368
+ return `
369
+ <div class="flex gap-4">
370
+ <div class="w-10 h-10 rounded-full bg-gradient-to-br from-gh-purple to-gh-blue flex items-center justify-center flex-shrink-0">
371
+ <i data-lucide="git-merge" class="w-5 h-5 text-white"></i>
372
+ </div>
373
+ <div class="flex-1 min-w-0">
374
+ <div class="flex items-center gap-2 mb-1">
375
+ <span class="font-semibold text-sm">DevPulse</span>
376
+ <span class="text-[10px] font-bold px-1.5 py-0.5 rounded bg-discord-blurple text-white uppercase">Bot</span>
377
+ <span class="text-xs text-text-muted">Today at 10:50 AM</span>
193
378
</div>
194
- <div class="discord-content">
195
- <div class="discord-header">
196
- <span class="bot-name">DevPulse</span>
197
- <span class="bot-tag">BOT</span>
198
- <span class="message-time">Today at 10:50 AM</span>
199
- </div>
200
- <div class="command-echo">/investigate pr:142 repo:vercel/next.js</div>
201
- <div class="discord-embed" style="border-left-color: #a371f7">
202
- <div class="embed-author">Lifecycle Investigation Engine</div>
203
- <div class="embed-title">Full Development Trace</div>
204
- <div class="embed-desc">Chronological lifecycle trace from originating issue to published version:</div>
205
- <div class="embed-code-block">1. Issue Created: #892 "Hydration mismatch in nested parallel routes" by @alex (Sep 1)
206
-2. Branch Created: feature/route-cache (Sep 2)
207
-3. Commit Added: 8f3b12a "fix: reconcile router slot metadata" by @timneutkens
208
-4. PR Opened: #142 (Sep 2)
209
-5. CI Verification: 12 checks passed (Sep 2)
210
-6. Code Reviews: Approved by @sokra & @kdy1 (Sep 3)
211
-7. Merged: Merged into canary by @timneutkens (Sep 3)
212
-8. Shipped In: v15.2.0-canary.18 (Sep 4)</div>
213
- <div class="discord-action-row">
214
- <button class="discord-btn" id="sim-btn-copy-trace">${icons.copy(14, "#ffffff")} Copy Investigation Summary</button>
215
- </div>
379
+ <div class="text-xs font-mono text-gh-blue mb-2">/investigate pr:142 repo:vercel/next.js</div>
380
+ <div class="rounded-lg bg-discord-embed border-l-4 border-gh-purple p-4">
381
+ <div class="text-sm font-semibold mb-2">Full Development Trace</div>
382
+ <div class="font-mono text-xs text-text-secondary space-y-1 mb-3">
383
+ <div>1. Issue #892 created by @alex (Sep 1)</div>
384
+ <div>2. Branch feature/route-cache (Sep 2)</div>
385
+ <div>3. Commit 8f3b12a by @timneutkens</div>
386
+ <div>4. PR #142 opened (Sep 2)</div>
387
+ <div>5. CI: 12 checks passed (Sep 2)</div>
388
+ <div>6. Approved by @sokra & @kdy1 (Sep 3)</div>
389
+ <div>7. Merged into canary (Sep 3)</div>
390
+ <div>8. Shipped in v15.2.0-canary.18 (Sep 4)</div>
216
391
</div>
392
+ <button id="sim-btn-copy-trace" class="inline-flex items-center gap-1.5 px-3 py-1.5 rounded-md bg-bg-surface text-text-primary text-xs font-semibold hover:bg-bg-hover transition-colors border border-border">
393
+ <i data-lucide="copy" class="w-3 h-3"></i> Copy Trace
394
+ </button>
217
395
</div>
218
396
</div>
219
- `;
220
- },
397
+ </div>
398
+ `;
399
+}
221
400
222
- code: () => {
223
- return `
224
- <div class="discord-message">
225
- <div class="discord-avatar">
226
- ${icons.code(22, "#ffffff")}
401
+function renderCodeEmbed() {
402
+ return `
403
+ <div class="flex gap-4">
404
+ <div class="w-10 h-10 rounded-full bg-gradient-to-br from-gh-blue to-gh-purple flex items-center justify-center flex-shrink-0">
405
+ <i data-lucide="code" class="w-5 h-5 text-white"></i>
406
+ </div>
407
+ <div class="flex-1 min-w-0">
408
+ <div class="flex items-center gap-2 mb-1">
409
+ <span class="font-semibold text-sm">DevPulse</span>
410
+ <span class="text-[10px] font-bold px-1.5 py-0.5 rounded bg-discord-blurple text-white uppercase">Bot</span>
411
+ <span class="text-xs text-text-muted">Today at 10:52 AM</span>
227
412
</div>
228
- <div class="discord-content">
229
- <div class="discord-header">
230
- <span class="bot-name">DevPulse</span>
231
- <span class="bot-tag">BOT</span>
232
- <span class="message-time">Today at 10:52 AM</span>
233
- </div>
234
- <div class="command-echo">/code blame file:packages/next/src/server/route-matcher.ts lines:40-46</div>
235
- <div class="discord-embed" style="border-left-color: #58a6ff">
236
- <div class="embed-author">Code Blame &amp; Attribution</div>
237
- <div class="embed-title">route-matcher.ts (Lines 40-46)</div>
238
- <div class="embed-code-block">40 | export function matchRoute(url: string, routes: Route[]): Route | null {
239
-41 | // [e71ab82 @timneutkens 3d ago] Fast-path lookup for exact match
240
-42 | const exact = exactMap.get(url);
241
-43 | if (exact) return exact;
242
-44 | // [8f3b12a @sokra 1w ago] Fallback dynamic param evaluator
243
-45 | return evaluateRegexRoutes(url, routes);
244
-46 | }</div>
245
- <div class="embed-desc">Commit <code>8f3b12a</code> originated from <strong>PR #138</strong> merged into canary on Aug 28.</div>
413
+ <div class="text-xs font-mono text-gh-blue mb-2">/code blame file:packages/next/src/server/route-matcher.ts lines:40-46</div>
414
+ <div class="rounded-lg bg-discord-embed border-l-4 border-gh-blue p-4">
415
+ <div class="text-sm font-semibold mb-2">route-matcher.ts (Lines 40-46)</div>
416
+ <div class="font-mono text-xs bg-[#111214] rounded p-3 mb-2 overflow-x-auto">
417
+ <div><span class="text-text-muted">40</span> | export function matchRoute(url: string, routes: Route[]): Route | null {</div>
418
+ <div><span class="text-text-muted">41</span> | <span class="text-text-muted">// [e71ab82 @timneutkens 3d ago] Fast-path lookup</span></div>
419
+ <div><span class="text-text-muted">42</span> | const exact = exactMap.get(url);</div>
420
+ <div><span class="text-text-muted">43</span> | if (exact) return exact;</div>
421
+ <div><span class="text-text-muted">44</span> | <span class="text-text-muted">// [8f3b12a @sokra 1w ago] Fallback evaluator</span></div>
422
+ <div><span class="text-text-muted">45</span> | return evaluateRegexRoutes(url, routes);</div>
423
+ <div><span class="text-text-muted">46</span> | }</div>
246
424
</div>
425
+ <div class="text-xs text-text-secondary">Commit 8f3b12a originated from PR #138 merged Aug 28.</div>
247
426
</div>
248
427
</div>
249
- `;
250
- },
428
+ </div>
429
+ `;
430
+}
251
431
252
- activity: () => {
253
- return `
254
- <div class="discord-message">
255
- <div class="discord-avatar">
256
- ${icons.graph(22, "#ffffff")}
432
+function renderActivityEmbed() {
433
+ return `
434
+ <div class="flex gap-4">
435
+ <div class="w-10 h-10 rounded-full bg-gradient-to-br from-gh-green to-gh-blue flex items-center justify-center flex-shrink-0">
436
+ <i data-lucide="bar-chart-2" class="w-5 h-5 text-white"></i>
437
+ </div>
438
+ <div class="flex-1 min-w-0">
439
+ <div class="flex items-center gap-2 mb-1">
440
+ <span class="font-semibold text-sm">DevPulse</span>
441
+ <span class="text-[10px] font-bold px-1.5 py-0.5 rounded bg-discord-blurple text-white uppercase">Bot</span>
442
+ <span class="text-xs text-text-muted">Today at 10:55 AM</span>
257
443
</div>
258
- <div class="discord-content">
259
- <div class="discord-header">
260
- <span class="bot-name">DevPulse</span>
261
- <span class="bot-tag">BOT</span>
262
- <span class="message-time">Today at 10:55 AM</span>
444
+ <div class="text-xs font-mono text-gh-blue mb-2">/activity me days:7</div>
445
+ <div class="rounded-lg bg-discord-embed border-l-4 border-gh-green p-4">
446
+ <div class="text-sm font-semibold mb-2">Personal Activity Profile (@swadhin)</div>
447
+ <div class="text-xs text-text-secondary mb-3">48 commits • 6 PRs authored • 14 PRs reviewed</div>
448
+ <div class="font-mono text-xs space-y-1 mb-3">
449
+ <div class="flex items-center gap-2"><span class="w-8 text-text-muted">Mon</span> <span class="text-gh-green">██████████████</span> 14</div>
450
+ <div class="flex items-center gap-2"><span class="w-8 text-text-muted">Tue</span> <span class="text-gh-green">██████████</span> 10</div>
451
+ <div class="flex items-center gap-2"><span class="w-8 text-text-muted">Wed</span> <span class="text-gh-green">██████</span> 6</div>
452
+ <div class="flex items-center gap-2"><span class="w-8 text-text-muted">Thu</span> <span class="text-gh-green">████████████</span> 12</div>
453
+ <div class="flex items-center gap-2"><span class="w-8 text-text-muted">Fri</span> <span class="text-gh-green">████</span> 4</div>
454
+ <div class="flex items-center gap-2"><span class="w-8 text-text-muted">Sat</span> <span class="text-gh-green">█</span> 1</div>
455
+ <div class="flex items-center gap-2"><span class="w-8 text-text-muted">Sun</span> <span class="text-gh-green">█</span> 1</div>
263
456
</div>
264
- <div class="command-echo">/activity me days:7</div>
265
- <div class="discord-embed" style="border-left-color: #3fb950">
266
- <div class="embed-author">Developer Engineering Rhythm</div>
267
- <div class="embed-title">Personal Activity Profile (@swadhin)</div>
268
- <div class="embed-desc">
269
- Total Commits: <strong>48</strong> &bull; PRs Authored: <strong>6</strong> &bull; PRs Reviewed: <strong>14</strong>
270
- Weekly Rhythm Histogram:
457
+ <div class="grid grid-cols-2 gap-3">
458
+ <div>
459
+ <div class="text-[10px] uppercase text-text-muted font-bold mb-0.5">Churn Ratio</div>
460
+ <div class="text-xs">+2,140 / -840 (2.5x)</div>
271
461
</div>
272
- <div class="embed-code-block">Mon [||||||||||||||||] 14
273
-Tue [|||||||||||| ] 10
274
-Wed [|||||||| ] 6
275
-Thu [|||||||||||||| ] 12
276
-Fri [|||| ] 4
277
-Sat [| ] 1
278
-Sun [| ] 1</div>
279
- <div class="embed-grid">
280
- <div>
281
- <div class="embed-field-name">Churn Ratio</div>
282
- <div class="embed-field-value">+2,140 / &minus;840 (2.5x)</div>
283
- </div>
284
- <div>
285
- <div class="embed-field-name">Average Cycle Time</div>
286
- <div class="embed-field-value">18h 40m</div>
287
- </div>
462
+ <div>
463
+ <div class="text-[10px] uppercase text-text-muted font-bold mb-0.5">Avg Cycle</div>
464
+ <div class="text-xs">18h 40m</div>
288
465
</div>
289
466
</div>
290
467
</div>
291
468
</div>
292
- `;
293
- },
294
-};
295
-
296
-export function renderSimulator() {
297
- const container = document.getElementById("simulator-render-area");
298
- if (!container) return;
299
-
300
- const renderer = tabTemplates[state.activeTab];
301
- if (renderer) {
302
- container.style.opacity = "0";
303
- container.style.transform = "translateX(12px)";
304
- container.style.transition = "opacity 0.15s ease, transform 0.15s ease";
305
-
306
- requestAnimationFrame(() => {
307
- container.innerHTML = renderer();
308
- requestAnimationFrame(() => {
309
- container.style.opacity = "1";
310
- container.style.transform = "translateX(0)";
311
- });
312
- });
313
-
314
- attachSimulatorEvents();
315
- }
469
+ </div>
470
+ `;
316
471
}
317
472
318
473
function attachSimulatorEvents() {
319
- const approveBtn = document.getElementById("sim-btn-approve");
320
- const changesBtn = document.getElementById("sim-btn-changes");
321
- const mergeBtn = document.getElementById("sim-btn-merge");
322
- const rerunBtn = document.getElementById("sim-btn-rerun");
323
- const copyTraceBtn = document.getElementById("sim-btn-copy-trace");
324
-
325
- if (approveBtn) {
326
- approveBtn.addEventListener("click", () => {
327
- state.prStatus = "approved";
328
- renderSimulator();
474
+ // Tab switching
475
+ const tabs = document.querySelectorAll<HTMLButtonElement>(".sim-tab-btn");
476
+ for (const tab of tabs) {
477
+ tab.addEventListener("click", () => {
478
+ for (const t of tabs) t.classList.remove("active");
479
+ tab.classList.add("active");
480
+ const target = tab.getAttribute("data-tab");
481
+ if (target) {
482
+ state.activeTab = target;
483
+ renderSimulator();
484
+ }
329
485
});
330
486
}
331
487
332
- if (changesBtn) {
333
- changesBtn.addEventListener("click", () => {
488
+ // PR simulator buttons
489
+ document.addEventListener("click", (e) => {
490
+ const target = e.target as HTMLElement;
491
+ const btn = target.closest("button");
492
+ if (!btn) return;
493
+
494
+ if (btn.id === "sim-btn-approve") {
495
+ state.prStatus = "approved";
496
+ renderSimulator();
497
+ } else if (btn.id === "sim-btn-changes") {
334
498
state.prStatus = "changes_requested";
335
499
renderSimulator();
336
- });
337
- }
338
-
339
- if (mergeBtn) {
340
- mergeBtn.addEventListener("click", () => {
341
- mergeBtn.innerHTML = `${icons.sync(14, "#ffffff")} Merging...`;
500
+ } else if (btn.id === "sim-btn-merge") {
501
+ btn.innerHTML = `<i data-lucide="loader-2" class="w-3 h-3 animate-spin"></i> Merging...`;
502
+ if (typeof lucide !== "undefined") lucide.createIcons();
342
503
setTimeout(() => {
343
504
state.prStatus = "merged";
344
505
renderSimulator();
345
- }, 600);
346
- });
347
- }
348
-
349
- if (rerunBtn) {
350
- rerunBtn.addEventListener("click", () => {
351
- rerunBtn.innerHTML = `${icons.sync(14, "#ffffff")} Dispatching GitHub Actions...`;
352
- setTimeout(() => {
353
- rerunBtn.innerHTML = `${icons.check(14, "#3fb950")} Workflows Triggered`;
354
506
}, 800);
355
- });
356
- }
357
-
358
- if (copyTraceBtn) {
359
- copyTraceBtn.addEventListener("click", () => {
360
- copyText("Issue #892 -> PR #142 -> v15.2.0-canary.18 (Commit 8f3b12a)", copyTraceBtn);
361
- });
362
- }
363
-
364
- // Repo sub-tabs
365
- for (const sub of ["overview", "commits", "prs", "issues", "releases"]) {
366
- const btn = document.getElementById(`sim-repo-${sub}`);
367
- if (btn) {
368
- btn.addEventListener("click", () => {
369
- state.repoTab = sub as any;
370
- renderSimulator();
507
+ } else if (btn.id === "sim-btn-rerun") {
508
+ const original = btn.innerHTML;
509
+ btn.innerHTML = `<i data-lucide="loader-2" class="w-3 h-3 animate-spin"></i> Dispatching...`;
510
+ if (typeof lucide !== "undefined") lucide.createIcons();
511
+ setTimeout(() => {
512
+ btn.innerHTML = `<i data-lucide="check" class="w-3 h-3 text-gh-green"></i> Triggered!`;
513
+ if (typeof lucide !== "undefined") lucide.createIcons();
514
+ setTimeout(() => {
515
+ btn.innerHTML = original;
516
+ if (typeof lucide !== "undefined") lucide.createIcons();
517
+ }, 2000);
518
+ }, 1000);
519
+ } else if (btn.id === "sim-btn-copy-trace") {
520
+ const text = "Issue #892 → PR #142 → v15.2.0-canary.18 (Commit 8f3b12a)";
521
+ navigator.clipboard.writeText(text).then(() => {
522
+ const original = btn.innerHTML;
523
+ btn.innerHTML = `<i data-lucide="check" class="w-3 h-3"></i> Copied!`;
524
+ if (typeof lucide !== "undefined") lucide.createIcons();
525
+ setTimeout(() => {
526
+ btn.innerHTML = original;
527
+ if (typeof lucide !== "undefined") lucide.createIcons();
528
+ }, 2000);
371
529
});
372
530
}
373
- }
374
-}
375
-
376
-// Scroll reveal observer
377
-function initScrollReveal() {
378
- const reveals = document.querySelectorAll(".reveal");
379
- const observer = new IntersectionObserver(
380
- (entries) => {
381
- for (const entry of entries) {
382
- if (entry.isIntersecting) {
383
- entry.target.classList.add("visible");
384
- observer.unobserve(entry.target);
385
- }
386
- }
387
- },
388
- { threshold: 0.1, rootMargin: "0px 0px -40px 0px" }
389
- );
390
-
391
- for (const el of reveals) {
392
- observer.observe(el);
393
- }
531
+ });
394
532
}
395
533
396
534
// Navbar scroll effect
397
-function initNavbarScroll() {
535
+function initNavbar() {
398
536
const navbar = document.getElementById("navbar");
399
537
if (!navbar) return;
400
538
403
541
if (!ticking) {
404
542
requestAnimationFrame(() => {
405
543
if (window.scrollY > 10) {
406
- navbar.classList.add("scrolled");
544
+ navbar.classList.add("navbar-scrolled");
407
545
} else {
408
- navbar.classList.remove("scrolled");
546
+ navbar.classList.remove("navbar-scrolled");
409
547
}
410
548
ticking = false;
411
549
});
416
554
window.addEventListener("scroll", onScroll, { passive: true });
417
555
}
418
556
419
-// Feature card mouse glow tracking
420
-function initCardGlow() {
421
- const cards = document.querySelectorAll<HTMLElement>(".feature-card");
422
- for (const card of cards) {
423
- card.addEventListener("mousemove", (e) => {
424
- const rect = card.getBoundingClientRect();
425
- const x = ((e.clientX - rect.left) / rect.width) * 100;
426
- const y = ((e.clientY - rect.top) / rect.height) * 100;
427
- card.style.setProperty("--mouse-x", `${x}%`);
428
- card.style.setProperty("--mouse-y", `${y}%`);
429
- });
430
- }
431
-}
432
-
433
-// Search input focus effect
434
-function initSearchInput() {
435
- const input = document.getElementById("feature-search-input") as HTMLInputElement | null;
436
- if (!input) return;
557
+// Mobile menu toggle
558
+function initMobileMenu() {
559
+ const btn = document.getElementById("mobile-menu-btn");
560
+ const menu = document.getElementById("mobile-menu");
437
561
438
- input.addEventListener("focus", () => {
439
- input.style.borderColor = "var(--gh-blue-border)";
440
- input.style.boxShadow = "0 0 0 3px rgba(88, 166, 255, 0.1)";
441
- });
442
-
443
- input.addEventListener("blur", () => {
444
- input.style.borderColor = "var(--border-default)";
445
- input.style.boxShadow = "none";
446
- });
447
-}
448
-
449
-// Initialize on DOM load
450
-document.addEventListener("DOMContentLoaded", () => {
451
- // Populate tab button icons dynamically
452
- const tabIcons: Record<string, string> = {
453
- pr: icons.gitPullRequest(14),
454
- repo: icons.repo(14),
455
- actions: icons.actions(14),
456
- investigate: icons.investigate(14),
457
- code: icons.code(14),
458
- activity: icons.graph(14),
459
- };
562
+ if (btn && menu) {
563
+ btn.addEventListener("click", () => {
564
+ menu.classList.toggle("hidden");
565
+ });
460
566
461
- const tabs = document.querySelectorAll<HTMLButtonElement>(".sim-tab-btn");
462
- for (const tab of tabs) {
463
- const target = tab.getAttribute("data-tab");
464
- if (target && tabIcons[target]) {
465
- const label = tab.innerText.replace(/[^a-zA-Z0-9_./#-]/g, "").trim();
466
- tab.innerHTML = `${tabIcons[target]} <span>/${target === "actions" ? "actions" : target === "activity" ? "activity" : target} ${label}</span>`;
567
+ // Close on link click
568
+ const links = menu.querySelectorAll("a");
569
+ for (const link of links) {
570
+ link.addEventListener("click", () => {
571
+ menu.classList.add("hidden");
572
+ });
467
573
}
574
+ }
575
+}
468
576
469
- tab.addEventListener("click", () => {
470
- for (const t of tabs) {
471
- t.classList.remove("active");
472
- }
473
- tab.classList.add("active");
474
- if (target) {
475
- state.activeTab = target;
476
- renderSimulator();
477
- }
577
+// Copy buttons
578
+function initCopyButtons() {
579
+ const copyAllBtn = document.getElementById("copy-all-btn");
580
+ if (copyAllBtn) {
581
+ copyAllBtn.addEventListener("click", () => {
582
+ const commands = `git clone https://github.com/husteno-o/git-discord-bot.git\ncd git-discord-bot\nbun install\ncp .env.example .env\nbun run start`;
583
+ navigator.clipboard.writeText(commands).then(() => {
584
+ const original = copyAllBtn.innerHTML;
585
+ copyAllBtn.innerHTML = `<i data-lucide="check" class="w-3 h-3"></i> Copied!`;
586
+ if (typeof lucide !== "undefined") lucide.createIcons();
587
+ setTimeout(() => {
588
+ copyAllBtn.innerHTML = original;
589
+ if (typeof lucide !== "undefined") lucide.createIcons();
590
+ }, 2000);
591
+ });
478
592
});
479
593
}
594
+}
480
595
481
- // Initial render
482
- renderSimulator();
483
-
484
- // Filter feature cards
485
- const filterInput = document.getElementById("feature-search-input") as HTMLInputElement | null;
486
- if (filterInput) {
487
- filterInput.addEventListener("input", (e) => {
488
- const q = (e.target as HTMLInputElement).value.toLowerCase().trim();
489
- const cards = document.querySelectorAll<HTMLElement>(".feature-card");
490
- for (const card of cards) {
491
- const text = card.innerText.toLowerCase();
492
- if (q === "" || text.includes(q)) {
493
- card.style.display = "flex";
494
- card.style.animation = "fadeInUp 0.3s var(--ease-out-expo) both";
495
- } else {
496
- card.style.display = "none";
596
+// Scroll effects
597
+function initScrollEffects() {
598
+ // Intersection observer for reveal animations
599
+ const reveals = document.querySelectorAll(".reveal");
600
+ if (reveals.length > 0) {
601
+ const observer = new IntersectionObserver(
602
+ (entries) => {
603
+ for (const entry of entries) {
604
+ if (entry.isIntersecting) {
605
+ entry.target.classList.add("visible");
606
+ observer.unobserve(entry.target);
607
+ }
497
608
}
498
- }
499
- });
500
- }
609
+ },
610
+ { threshold: 0.1, rootMargin: "0px 0px -40px 0px" },
611
+ );
501
612
502
- // Copy Clone command button
503
- const clonePill = document.getElementById("clone-repo-pill");
504
- if (clonePill) {
505
- clonePill.addEventListener("click", () => {
506
- copyText("git clone [email protected]:husteno-o/git-discord-bot.git", clonePill);
507
- });
613
+ for (const el of reveals) observer.observe(el);
508
614
}
509
-
510
- // Initialize scroll-triggered animations
511
- initScrollReveal();
512
- initNavbarScroll();
513
- initCardGlow();
514
- initSearchInput();
515
-});
615
+}
516
616
▼apps/web/src/globals.d.ts
+4-0
1
+// Global type declarations for CDN-loaded libraries
2
+declare const lucide: {
3
+ createIcons: () => void;
4
+};
0
5
▼apps/web/src/index.html
+289-634
1
1
<!DOCTYPE html>
2
-<html lang="en">
2
+<html lang="en" class="dark">
3
3
<head>
4
4
<meta charset="UTF-8" />
5
5
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <title>DevPulse — The GitHub Power-User Operating System for Discord</title>
7
- <meta name="description" content="Eliminate context switching. Review pull requests, merge code, monitor GitHub Actions CI/CD pipelines, and trace lifecycles directly from Discord." />
8
-
9
- <!-- OpenGraph / Social Meta Tags -->
6
+ <title>DevPulse — GitHub Power Tools for Discord</title>
7
+ <meta name="description" content="Review pull requests, merge code, monitor CI/CD, and trace lifecycles directly from Discord. 21 powerful slash commands." />
8
+
9
+ <!-- OpenGraph -->
10
10
<meta property="og:type" content="website" />
11
11
<meta property="og:title" content="DevPulse — GitHub Power Tools for Discord" />
12
- <meta property="og:description" content="Deep GitHub intelligence, pull request workflows, CI/CD telemetry, and team velocity inside Discord." />
13
- <meta property="og:url" content="https://github.com/husteno-o/git-discord-bot" />
12
+ <meta property="og:description" content="Deep GitHub intelligence, PR workflows, CI/CD telemetry inside Discord." />
14
13
<meta name="twitter:card" content="summary_large_image" />
15
- <meta name="twitter:title" content="DevPulse — GitHub Power Tools in Discord" />
16
- <meta name="twitter:description" content="Zero auth for public repositories. AES-256-GCM encrypted PAT vault." />
17
14
15
+ <!-- Tailwind CSS v4 -->
16
+ <script src="https://cdn.tailwindcss.com"></script>
17
+ <script>
18
+ tailwind.config = {
19
+ darkMode: 'class',
20
+ theme: {
21
+ extend: {
22
+ colors: {
23
+ bg: { canvas: '#090d16', subtle: '#0d1117', surface: '#161b22', hover: '#1c2128', active: '#21262d' },
24
+ border: { DEFAULT: '#30363d', muted: '#21262d' },
25
+ text: { primary: '#f0f6fc', secondary: '#8b949e', muted: '#6e7681' },
26
+ gh: { green: '#2ea043', 'green-h': '#3fb950', blue: '#58a6ff', purple: '#a371f7', coral: '#f85149', amber: '#d29922' },
27
+ discord: { blurple: '#5865f2', 'blurple-h': '#4752c4', embed: '#2b2d31', dark: '#1e1f22' }
28
+ },
29
+ fontFamily: {
30
+ sans: ['-apple-system', 'BlinkMacSystemFont', 'Segoe UI', 'Noto Sans', 'Helvetica', 'Arial', 'sans-serif'],
31
+ mono: ['SFMono-Regular', 'Consolas', 'Liberation Mono', 'Menlo', 'monospace']
32
+ },
33
+ animation: {
34
+ 'float': 'float 6s ease-in-out infinite',
35
+ 'pulse-slow': 'pulse 3s cubic-bezier(0.4, 0, 0.6, 1) infinite',
36
+ 'shimmer': 'shimmer 2s linear infinite',
37
+ 'fade-in': 'fadeIn 0.5s ease-out forwards',
38
+ 'slide-up': 'slideUp 0.5s ease-out forwards',
39
+ 'slide-down': 'slideDown 0.3s ease-out forwards',
40
+ 'scale-in': 'scaleIn 0.3s ease-out forwards',
41
+ 'glow': 'glow 2s ease-in-out infinite alternate',
42
+ },
43
+ keyframes: {
44
+ float: { '0%, 100%': { transform: 'translateY(0)' }, '50%': { transform: 'translateY(-10px)' } },
45
+ shimmer: { '0%': { backgroundPosition: '-200% 0' }, '100%': { backgroundPosition: '200% 0' } },
46
+ fadeIn: { '0%': { opacity: '0' }, '100%': { opacity: '1' } },
47
+ slideUp: { '0%': { opacity: '0', transform: 'translateY(20px)' }, '100%': { opacity: '1', transform: 'translateY(0)' } },
48
+ slideDown: { '0%': { opacity: '0', transform: 'translateY(-10px)' }, '100%': { opacity: '1', transform: 'translateY(0)' } },
49
+ scaleIn: { '0%': { opacity: '0', transform: 'scale(0.95)' }, '100%': { opacity: '1', transform: 'scale(1)' } },
50
+ glow: { '0%': { boxShadow: '0 0 5px rgba(46,160,67,0.2)' }, '100%': { boxShadow: '0 0 20px rgba(46,160,67,0.4)' } },
51
+ }
52
+ }
53
+ }
54
+ }
55
+ </script>
56
+
57
+ <!-- Lucide Icons -->
58
+ <script src="https://unpkg.com/lucide@latest/dist/umd/lucide.min.js"></script>
59
+
60
+ <!-- Custom Styles -->
18
61
<link rel="stylesheet" href="./styles.css" />
19
- <link rel="icon" type="image/svg+xml" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%232ea043'><path d='M5 3.254V3.25v.004a.75.75 0 1 1 0-.004Zm1.5 0a2.25 2.25 0 1 0-3 2.122V8.75a2.25 2.25 0 0 0 1.5 2.122v.378a2.25 2.25 0 1 0 1.5 0v-.378a2.25 2.25 0 0 0 1.5-2.122V5.376A2.25 2.25 0 0 0 6.5 3.254Z'/></svg>" />
62
+ <link rel="icon" type="image/svg+xml" href="./logo.svg" />
20
63
</head>
21
-<body>
22
- <div class="bg-grid"></div>
23
- <div class="ambient-glow-1"></div>
24
- <div class="ambient-glow-2"></div>
25
- <div class="ambient-glow-3"></div>
64
+<body class="bg-bg-canvas text-text-primary font-sans antialiased overflow-x-hidden">
65
+
66
+ <!-- Background Effects -->
67
+ <div class="fixed inset-0 pointer-events-none z-0">
68
+ <div class="absolute inset-0 bg-[linear-gradient(to_right,rgba(48,54,61,0.06)_1px,transparent_1px),linear-gradient(to_bottom,rgba(48,54,61,0.06)_1px,transparent_1px)] bg-[size:48px_48px] [mask-image:radial-gradient(ellipse_at_center,black_30%,transparent_80%)]"></div>
69
+ <div class="absolute -top-32 left-[15%] w-[700px] h-[700px] rounded-full bg-gh-green/10 blur-[100px] animate-float"></div>
70
+ <div class="absolute top-[500px] right-[10%] w-[600px] h-[600px] rounded-full bg-gh-blue/8 blur-[100px] animate-float" style="animation-delay: -3s"></div>
71
+ <div class="absolute -bottom-24 left-1/2 w-[500px] h-[500px] rounded-full bg-gh-purple/6 blur-[100px] animate-float" style="animation-delay: -1.5s"></div>
72
+ </div>
26
73
27
74
<!-- Navigation -->
28
- <header class="navbar" id="navbar">
29
- <div class="container nav-container">
30
- <a href="#" class="brand-logo">
31
- <div class="brand-icon-wrapper">
32
- <svg viewBox="0 0 16 16">
33
- <path d="M5 3.254V3.25v.004a.75.75 0 1 1 0-.004Zm1.5 0a2.25 2.25 0 1 0-3 2.122V8.75a2.25 2.25 0 0 0 1.5 2.122v.378a2.25 2.25 0 1 0 1.5 0v-.378a2.25 2.25 0 0 0 1.5-2.122V5.376A2.25 2.25 0 0 0 6.5 3.254Z"/>
34
- </svg>
35
- </div>
36
- <span class="brand-text">DevPulse</span>
37
- <span class="brand-tag">GitHub OS</span>
38
- </a>
75
+ <nav id="navbar" class="fixed top-0 left-0 right-0 z-50 transition-all duration-300 bg-bg-subtle/80 backdrop-blur-xl border-b border-transparent">
76
+ <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
77
+ <div class="flex items-center justify-between h-16">
78
+ <!-- Logo -->
79
+ <a href="#" class="flex items-center gap-3 group">
80
+ <div class="w-9 h-9 rounded-xl bg-gradient-to-br from-gh-green to-gh-blue flex items-center justify-center shadow-lg shadow-gh-green/20 group-hover:shadow-gh-green/40 transition-shadow duration-300">
81
+ <svg class="w-5 h-5 text-white" viewBox="0 0 24 24" fill="currentColor">
82
+ <path d="M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5"/>
83
+ </svg>
84
+ </div>
85
+ <span class="text-lg font-bold tracking-tight">DevPulse</span>
86
+ <span class="hidden sm:inline-flex text-[10px] font-semibold px-2 py-0.5 rounded-md bg-gh-green/10 text-gh-green-h border border-gh-green/30">BETA</span>
87
+ </a>
39
88
40
- <nav>
41
- <ul class="nav-links">
42
- <li><a href="#simulator">Live Simulator</a></li>
43
- <li><a href="#features">21 Commands</a></li>
44
- <li><a href="#killer-tools">Power Utilities</a></li>
45
- <li><a href="#architecture">Architecture</a></li>
46
- <li><a href="#quickstart">Quick Start</a></li>
47
- </ul>
48
- </nav>
89
+ <!-- Desktop Nav -->
90
+ <div class="hidden md:flex items-center gap-8">
91
+ <a href="#features" class="text-sm text-text-secondary hover:text-text-primary transition-colors">Features</a>
92
+ <a href="#simulator" class="text-sm text-text-secondary hover:text-text-primary transition-colors">Demo</a>
93
+ <a href="#commands" class="text-sm text-text-secondary hover:text-text-primary transition-colors">Commands</a>
94
+ <a href="#setup" class="text-sm text-text-secondary hover:text-text-primary transition-colors">Setup</a>
95
+ </div>
96
+
97
+ <!-- Actions -->
98
+ <div class="flex items-center gap-3">
99
+ <a href="https://github.com/husteno-o/git-discord-bot" target="_blank" rel="noopener noreferrer" class="hidden sm:inline-flex items-center gap-2 px-4 py-2 text-sm font-medium rounded-lg bg-bg-surface border border-border hover:bg-bg-hover hover:border-text-secondary transition-all duration-200">
100
+ <i data-lucide="github" class="w-4 h-4"></i>
101
+ GitHub
102
+ </a>
103
+ <a href="#setup" class="inline-flex items-center gap-2 px-4 py-2 text-sm font-medium rounded-lg bg-gh-green text-white hover:bg-gh-green-h shadow-lg shadow-gh-green/20 hover:shadow-gh-green/40 transition-all duration-200">
104
+ <i data-lucide="rocket" class="w-4 h-4"></i>
105
+ Get Started
106
+ </a>
107
+
108
+ <!-- Mobile menu button -->
109
+ <button id="mobile-menu-btn" class="md:hidden p-2 rounded-lg hover:bg-bg-surface transition-colors">
110
+ <i data-lucide="menu" class="w-5 h-5"></i>
111
+ </button>
112
+ </div>
113
+ </div>
114
+ </div>
49
115
50
- <div class="nav-actions">
51
- <a href="https://github.com/husteno-o/git-discord-bot" target="_blank" rel="noopener noreferrer" class="btn btn-github btn-sm">
52
- <svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor">
53
- <path d="M8 0c4.42 0 8 3.58 8 8a8.013 8.013 0 0 1-5.45 7.59c-.4.08-.55-.17-.55-.38 0-.27.01-1.13.01-2.2 0-.75-.25-1.23-.54-1.48 1.78-.2 3.65-.88 3.65-3.95 0-.88-.31-1.59-.82-2.15.08-.2.36-1.02-.08-2.12 0 0-.67-.22-2.2.82-.64-.18-1.32-.27-2-.27-.68 0-1.36.09-2 .27-1.53-1.03-2.2-.82-2.2-.82-.44 1.1-.16 1.92-.08 2.12-.51.56-.82 1.28-.82 2.15 0 3.06 1.86 3.75 3.64 3.95-.23.2-.44.55-.51 1.07-.46.21-1.61.55-2.33-.66-.15-.24-.6-.83-1.23-.82-.67.01-.27.38.01.53.34.19.73.9.82 1.13.16.45.68 1.31 2.69.94 0 .67.01 1.3.01 1.49 0 .21-.15.45-.55.38A7.995 7.995 0 0 1 0 8c0-4.42 3.58-8 8-8Z"/>
54
- </svg>
116
+ <!-- Mobile Menu -->
117
+ <div id="mobile-menu" class="hidden md:hidden bg-bg-subtle/95 backdrop-blur-xl border-b border-border">
118
+ <div class="px-4 py-4 space-y-2">
119
+ <a href="#features" class="block px-4 py-3 rounded-lg text-sm text-text-secondary hover:text-text-primary hover:bg-bg-surface transition-colors">Features</a>
120
+ <a href="#simulator" class="block px-4 py-3 rounded-lg text-sm text-text-secondary hover:text-text-primary hover:bg-bg-surface transition-colors">Demo</a>
121
+ <a href="#commands" class="block px-4 py-3 rounded-lg text-sm text-text-secondary hover:text-text-primary hover:bg-bg-surface transition-colors">Commands</a>
122
+ <a href="#setup" class="block px-4 py-3 rounded-lg text-sm text-text-secondary hover:text-text-primary hover:bg-bg-surface transition-colors">Setup</a>
123
+ <a href="https://github.com/husteno-o/git-discord-bot" target="_blank" class="flex items-center gap-2 px-4 py-3 rounded-lg text-sm text-text-secondary hover:text-text-primary hover:bg-bg-surface transition-colors">
124
+ <i data-lucide="github" class="w-4 h-4"></i>
55
125
GitHub
56
126
</a>
57
- <a href="#quickstart" class="btn btn-primary btn-sm">Get Started</a>
58
127
</div>
59
128
</div>
60
- </header>
129
+ </nav>
61
130
62
131
<!-- Hero Section -->
63
- <section class="hero-section">
64
- <div class="container">
65
- <div class="hero-pill">
66
- <span class="pill-dot"></span>
67
- <span>The GitHub Power-User Operating System for Discord</span>
132
+ <section class="relative z-10 pt-32 pb-20 sm:pt-40 sm:pb-28 px-4 sm:px-6 lg:px-8">
133
+ <div class="max-w-5xl mx-auto text-center">
134
+ <!-- Badge -->
135
+ <div class="inline-flex items-center gap-2 px-4 py-2 rounded-full bg-bg-surface/80 border border-border backdrop-blur-sm mb-8 animate-fade-in">
136
+ <span class="w-2 h-2 rounded-full bg-gh-green animate-pulse"></span>
137
+ <span class="text-sm text-text-secondary">21 Powerful GitHub Commands for Discord</span>
68
138
</div>
69
139
70
- <h1 class="hero-title">
71
- The GitHub Command Center.<br />
72
- <span class="hero-title-gradient">Built Inside Discord.</span>
140
+ <!-- Title -->
141
+ <h1 class="text-4xl sm:text-5xl md:text-6xl lg:text-7xl font-extrabold tracking-tight mb-6 animate-slide-up">
142
+ GitHub Workflows.<br class="hidden sm:block" />
143
+ <span class="bg-gradient-to-r from-white via-gh-blue to-gh-purple bg-[length:200%_auto] bg-clip-text text-transparent animate-shimmer">
144
+ Inside Discord.
145
+ </span>
73
146
</h1>
74
147
75
- <p class="hero-subtitle">
76
- Eliminate context-switching forever. Review and merge pull requests, inspect repository health, monitor CI/CD Actions pipelines, trace commit lifecycles, and audit vulnerabilities directly from Discord.
148
+ <!-- Subtitle -->
149
+ <p class="text-lg sm:text-xl text-text-secondary max-w-2xl mx-auto mb-10 leading-relaxed animate-slide-up" style="animation-delay: 0.1s">
150
+ Review pull requests, merge code, monitor CI/CD pipelines, and trace commit lifecycles — without leaving your Discord server.
77
151
</p>
78
152
79
- <div class="hero-actions">
80
- <a href="#quickstart" class="btn btn-discord btn-lg">
81
- <svg width="20" height="20" viewBox="0 0 16 16" fill="currentColor">
82
- <path d="M13.54 2.67A13.06 13.06 0 0 0 10.27 1.5a.05.05 0 0 0-.05.02c-.14.26-.3.6-.41.87a12.06 12.06 0 0 0-3.62 0c-.11-.27-.28-.61-.42-.87a.05.05 0 0 0-.05-.02 13.06 13.06 0 0 0-3.27 1.17.05.05 0 0 0-.02.04C.34 5.76-.23 8.78.08 11.75a.06.06 0 0 0 .02.04 13.13 13.13 0 0 0 3.97 2.01.05.05 0 0 0 .06-.02c.3-.42.57-.86.8-1.33a.05.05 0 0 0-.03-.07 8.65 8.65 0 0 1-1.24-.6.05.05 0 0 1-.01-.08c.08-.06.17-.13.25-.19a.05.05 0 0 1 .05-.01c2.61 1.2 5.44 1.2 8.02 0a.05.05 0 0 1 .05.01c.08.06.17.13.25.19a.05.05 0 0 1-.01.08 8.44 8.44 0 0 1-1.24.6.05.05 0 0 0-.03.07c.24.47.51.91.8 1.33a.05.05 0 0 0 .06.02 13.1 13.1 0 0 0 3.98-2.01.06.06 0 0 0 .02-.04c.38-3.52-.64-6.52-2.48-9.04a.05.05 0 0 0-.02-.04Z"/>
83
- </svg>
84
- Deploy Bot to Server
153
+ <!-- CTA Buttons -->
154
+ <div class="flex flex-col sm:flex-row items-center justify-center gap-4 mb-12 animate-slide-up" style="animation-delay: 0.2s">
155
+ <a href="#setup" class="w-full sm:w-auto inline-flex items-center justify-center gap-2 px-8 py-4 text-base font-semibold rounded-xl bg-gh-green text-white hover:bg-gh-green-h shadow-xl shadow-gh-green/25 hover:shadow-gh-green/40 hover:-translate-y-0.5 transition-all duration-200">
156
+ <i data-lucide="download" class="w-5 h-5"></i>
157
+ Self-Host Free
158
+ </a>
159
+ <a href="#simulator" class="w-full sm:w-auto inline-flex items-center justify-center gap-2 px-8 py-4 text-base font-semibold rounded-xl bg-bg-surface border border-border text-text-primary hover:bg-bg-hover hover:border-text-secondary hover:-translate-y-0.5 transition-all duration-200">
160
+ <i data-lucide="play" class="w-5 h-5"></i>
161
+ Live Demo
85
162
</a>
86
-
87
- <div class="clone-pill" id="clone-repo-pill" title="Click to copy clone command">
88
- <svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor">
89
- <path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"/>
90
- <path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"/>
91
- </svg>
92
- <span>git clone [email protected]:husteno-o/git-discord-bot.git</span>
93
- <span class="clone-btn-icon">
94
- <svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor">
95
- <path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"/>
96
- <path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"/>
97
- </svg>
98
- </span>
99
- </div>
100
163
</div>
101
164
102
- <div class="hero-badges">
103
- <div class="hero-badge-item">
104
- <svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg>
105
- <span>Zero Auth for Public Repos</span>
165
+ <!-- Stats -->
166
+ <div class="grid grid-cols-2 sm:grid-cols-4 gap-4 sm:gap-8 max-w-3xl mx-auto animate-slide-up" style="animation-delay: 0.3s">
167
+ <div class="text-center">
168
+ <div class="text-2xl sm:text-3xl font-bold text-text-primary">21</div>
169
+ <div class="text-sm text-text-muted">Commands</div>
106
170
</div>
107
- <div class="hero-badge-item">
108
- <svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg>
109
- <span>AES-256-GCM Encrypted PATs</span>
171
+ <div class="text-center">
172
+ <div class="text-2xl sm:text-3xl font-bold text-text-primary">0</div>
173
+ <div class="text-sm text-text-muted">Auth Required</div>
110
174
</div>
111
- <div class="hero-badge-item">
112
- <svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg>
113
- <span>Zero Inbound Open Ports</span>
175
+ <div class="text-center">
176
+ <div class="text-2xl sm:text-3xl font-bold text-text-primary">AES</div>
177
+ <div class="text-sm text-text-muted">256-GCM</div>
114
178
</div>
115
- <div class="hero-badge-item">
116
- <svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg>
117
- <span>Sub-15ms Response Times</span>
179
+ <div class="text-center">
180
+ <div class="text-2xl sm:text-3xl font-bold text-text-primary">&lt;100ms</div>
181
+ <div class="text-sm text-text-muted">Response</div>
118
182
</div>
119
183
</div>
120
184
</div>
121
185
</section>
122
186
123
- <!-- Interactive Live Discord / GitHub Simulator -->
124
- <section class="simulator-section" id="simulator">
125
- <div class="container">
126
- <div class="simulator-wrapper reveal">
127
- <div class="simulator-header">
128
- <div class="window-dots">
129
- <span class="window-dot dot-red"></span>
130
- <span class="window-dot dot-yellow"></span>
131
- <span class="window-dot dot-green"></span>
187
+ <!-- Interactive Demo Section -->
188
+ <section id="simulator" class="relative z-10 py-16 sm:py-24 px-4 sm:px-6 lg:px-8">
189
+ <div class="max-w-6xl mx-auto">
190
+ <div class="text-center mb-12">
191
+ <h2 class="text-3xl sm:text-4xl font-bold mb-4">See It In Action</h2>
192
+ <p class="text-text-secondary text-lg max-w-2xl mx-auto">Interactive preview of what you'll see in Discord. Click the tabs to explore different commands.</p>
193
+ </div>
194
+
195
+ <!-- Simulator Window -->
196
+ <div class="rounded-2xl bg-bg-surface border border-border shadow-2xl overflow-hidden max-w-4xl mx-auto">
197
+ <!-- Window Header -->
198
+ <div class="flex items-center justify-between px-4 py-3 bg-bg-subtle border-b border-border">
199
+ <div class="flex items-center gap-2">
200
+ <div class="w-3 h-3 rounded-full bg-red-500"></div>
201
+ <div class="w-3 h-3 rounded-full bg-yellow-500"></div>
202
+ <div class="w-3 h-3 rounded-full bg-green-500"></div>
132
203
</div>
133
- <div class="simulator-title">
134
- <svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor">
135
- <path d="M0 2.75C0 1.784.784 1 1.75 1h12.5c.966 0 1.75.784 1.75 1.75v10.5A1.75 1.75 0 0 1 14.25 15H1.75A1.75 1.75 0 0 1 0 13.25Zm1.75-.25a.25.25 0 0 0-.25.25v10.5c0 .138.112.25.25.25h12.5a.25.25 0 0 0 .25-.25V2.75a.25.25 0 0 0-.25-.25Z"/>
136
- </svg>
137
- <span>#engineering-ops • DevPulse Interactive Terminal</span>
204
+ <div class="flex items-center gap-2 text-xs font-mono text-text-secondary">
205
+ <i data-lucide="hash" class="w-3 h-3"></i>
206
+ <span>engineering-ops</span>
138
207
</div>
139
- <div class="simulator-telemetry">
140
- <span class="telemetry-pill">Latency: &lt;12ms</span>
208
+ <div class="flex items-center gap-1.5 px-2 py-1 rounded-full bg-gh-green/10 border border-gh-green/30">
209
+ <span class="w-1.5 h-1.5 rounded-full bg-gh-green animate-pulse"></span>
210
+ <span class="text-[10px] font-mono text-gh-green-h">LIVE</span>
141
211
</div>
142
212
</div>
143
213
144
- <div class="simulator-tabs">
145
- <button class="sim-tab-btn active" data-tab="pr">
146
- <svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor"><path d="M5 3.254V3.25v.004a.75.75 0 1 1 0-.004Zm1.5 0a2.25 2.25 0 1 0-3 2.122V8.75a2.25 2.25 0 0 0 1.5 2.122v.378a2.25 2.25 0 1 0 1.5 0v-.378a2.25 2.25 0 0 0 1.5-2.122V5.376A2.25 2.25 0 0 0 6.5 3.254Z"/></svg>
147
- <span>/pr 142</span>
214
+ <!-- Tabs -->
215
+ <div class="flex gap-1 px-4 py-2 bg-bg-surface border-b border-border overflow-x-auto scrollbar-hide">
216
+ <button class="sim-tab-btn active flex items-center gap-2 px-3 py-2 rounded-lg text-xs font-mono text-text-secondary hover:text-text-primary hover:bg-bg-hover transition-colors whitespace-nowrap" data-tab="pr">
217
+ <i data-lucide="git-pull-request" class="w-3 h-3"></i> /pr
148
218
</button>
149
- <button class="sim-tab-btn" data-tab="repo">
150
- <svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor"><path d="M2 2.5A2.5 2.5 0 0 1 4.5 0h8.75a.75.75 0 0 1 .75.75v12.5a.75.75 0 0 1-.75.75h-2.5a.75.75 0 0 1 0-1.5h1.75v-2h-8a1 1 0 0 0-.714 1.7.75.75 0 1 1-1.072 1.05A2.495 2.495 0 0 1 2 11.5Zm10.5-1h-8a1 1 0 0 0-1 1v6.708A2.486 2.486 0 0 1 4.5 9h8ZM5 12.25a.25.25 0 0 1 .25-.25H12v1.5H5.25a.25.25 0 0 1-.25-.25Z"/></svg>
151
- <span>/repo vercel/next.js</span>
219
+ <button class="sim-tab-btn flex items-center gap-2 px-3 py-2 rounded-lg text-xs font-mono text-text-secondary hover:text-text-primary hover:bg-bg-hover transition-colors whitespace-nowrap" data-tab="repo">
220
+ <i data-lucide="book-open" class="w-3 h-3"></i> /repo
152
221
</button>
153
- <button class="sim-tab-btn" data-tab="actions">
154
- <svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor"><path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Zm4.879-2.773 4.264 2.559a.25.25 0 0 1 0 .428l-4.264 2.559A.25.25 0 0 1 6 10.559V5.442a.25.25 0 0 1 .379-.215Z"/></svg>
155
- <span>/actions main</span>
222
+ <button class="sim-tab-btn flex items-center gap-2 px-3 py-2 rounded-lg text-xs font-mono text-text-secondary hover:text-text-primary hover:bg-bg-hover transition-colors whitespace-nowrap" data-tab="actions">
223
+ <i data-lucide="play-circle" class="w-3 h-3"></i> /actions
156
224
</button>
157
- <button class="sim-tab-btn" data-tab="investigate">
158
- <svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor"><path d="M8.75.75V3h5.5a.75.75 0 0 1 0 1.5h-5.5v2.25a.75.75 0 0 1-1.5 0V4.5H1.75a.75.75 0 0 1 0-1.5h5.5V.75a.75.75 0 0 1 1.5 0ZM1.75 10h5.5v2.25a.75.75 0 0 0 1.5 0V11.5h5.5a.75.75 0 0 0 0-1.5h-5.5V7.75a.75.75 0 0 0-1.5 0V10H1.75a.75.75 0 0 0 0 1.5Z"/></svg>
159
- <span>/investigate #892</span>
225
+ <button class="sim-tab-btn flex items-center gap-2 px-3 py-2 rounded-lg text-xs font-mono text-text-secondary hover:text-text-primary hover:bg-bg-hover transition-colors whitespace-nowrap" data-tab="investigate">
226
+ <i data-lucide="search" class="w-3 h-3"></i> /investigate
160
227
</button>
161
- <button class="sim-tab-btn" data-tab="code">
162
- <svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor"><path d="m11.28 3.22 4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.749.749 0 0 1-1.275-.326.749.749 0 0 1 .215-.734L13.94 8l-3.72-3.72a.749.749 0 0 1 .215-.734.749.749 0 0 1 1.06-.026Zm-6.56 0a.75.75 0 0 1 1.06 0 .749.749 0 0 1 .215.734.749.749 0 0 1-.215.734L2.06 8l3.72 3.72a.749.749 0 0 1-.215.734.749.749 0 0 1-1.06.026L.22 8.53a.75.75 0 0 1 0-1.06l4.25-4.25a.75.75 0 0 1 1.06 0Z"/></svg>
163
- <span>/code route-matcher.ts</span>
228
+ <button class="sim-tab-btn flex items-center gap-2 px-3 py-2 rounded-lg text-xs font-mono text-text-secondary hover:text-text-primary hover:bg-bg-hover transition-colors whitespace-nowrap" data-tab="code">
229
+ <i data-lucide="code" class="w-3 h-3"></i> /code
164
230
</button>
165
- <button class="sim-tab-btn" data-tab="activity">
166
- <svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor"><path d="M1.5 1.75V13.5h13.75a.75.75 0 0 1 0 1.5H.75a.75.75 0 0 1-.75-.75V1.75a.75.75 0 0 1 1.5 0Zm14.28 2.53-5.25 5.25a.75.75 0 0 1-1.06 0L7 7.06 2.53 11.53a.75.75 0 0 1-1.06-1.06l5-5a.75.75 0 0 1 1.06 0L10 7.94l4.72-4.72a.75.75 0 0 1 1.06 1.06Z"/></svg>
167
- <span>/activity me</span>
231
+ <button class="sim-tab-btn flex items-center gap-2 px-3 py-2 rounded-lg text-xs font-mono text-text-secondary hover:text-text-primary hover:bg-bg-hover transition-colors whitespace-nowrap" data-tab="activity">
232
+ <i data-lucide="bar-chart" class="w-3 h-3"></i> /activity
168
233
</button>
169
234
</div>
170
235
171
- <div class="simulator-body" id="simulator-render-area">
172
- <!-- Dynamic rendering via app.ts -->
236
+ <!-- Content Area -->
237
+ <div id="simulator-body" class="p-6 min-h-[400px] bg-discord-dark">
238
+ <!-- Dynamic content rendered by app.ts -->
173
239
</div>
174
240
</div>
175
241
</div>
176
242
</section>
177
243
178
- <!-- The 21 Core Commands -->
179
- <section class="features-section" id="features">
180
- <div class="container">
181
- <div class="section-header reveal">
182
- <div class="section-tag">Command Matrix</div>
183
- <h2 class="section-title">21 Powerful GitHub Commands</h2>
184
- <p class="section-desc">
185
- Engineered for developers who want complete control over their GitHub workflow without ever leaving Discord.
186
- </p>
187
- <div style="margin-top: 24px;">
188
- <input type="text" id="feature-search-input" placeholder="Search commands, topics (e.g. pr, actions, security)..." style="width: 100%; max-width: 460px; padding: 12px 18px; background: var(--bg-surface); border: 1px solid var(--border-default); border-radius: 10px; color: var(--text-primary); font-family: inherit; font-size: 0.9rem; transition: border-color 0.25s ease, box-shadow 0.25s ease;" />
189
- </div>
244
+ <!-- Features Grid -->
245
+ <section id="features" class="relative z-10 py-16 sm:py-24 px-4 sm:px-6 lg:px-8">
246
+ <div class="max-w-7xl mx-auto">
247
+ <div class="text-center mb-16">
248
+ <h2 class="text-3xl sm:text-4xl font-bold mb-4">Everything You Need</h2>
249
+ <p class="text-text-secondary text-lg max-w-2xl mx-auto">From repository intelligence to security scanning — all accessible through simple slash commands.</p>
190
250
</div>
191
251
192
- <div class="features-grid">
193
- <!-- 1. /repo -->
194
- <div class="feature-card reveal">
195
- <div class="feature-top">
196
- <div class="feature-icon-box">
197
- <svg viewBox="0 0 16 16"><path d="M2 2.5A2.5 2.5 0 0 1 4.5 0h8.75a.75.75 0 0 1 .75.75v12.5a.75.75 0 0 1-.75.75h-2.5a.75.75 0 0 1 0-1.5h1.75v-2h-8a1 1 0 0 0-.714 1.7.75.75 0 1 1-1.072 1.05A2.495 2.495 0 0 1 2 11.5Zm10.5-1h-8a1 1 0 0 0-1 1v6.708A2.486 2.486 0 0 1 4.5 9h8ZM5 12.25a.25.25 0 0 1 .25-.25H12v1.5H5.25a.25.25 0 0 1-.25-.25Z"/></svg>
198
- </div>
199
- <span class="feature-command-badge">/repo</span>
200
- </div>
201
- <h3 class="feature-name">Repository Intelligence</h3>
202
- <p class="feature-text">Deep repository diagnostics including stars, forks, open issues/PRs, automated Health Score (0-100), dependencies graph, and 30-day growth rate.</p>
203
- <ul class="feature-bullets">
204
- <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Health Score based on community standards</li>
205
- <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Interactive button navigation tabs</li>
206
- </ul>
207
- </div>
208
-
209
- <!-- 2. /pr -->
210
- <div class="feature-card reveal">
211
- <div class="feature-top">
212
- <div class="feature-icon-box">
213
- <svg viewBox="0 0 16 16"><path d="M5 3.254V3.25v.004a.75.75 0 1 1 0-.004Zm1.5 0a2.25 2.25 0 1 0-3 2.122V8.75a2.25 2.25 0 0 0 1.5 2.122v.378a2.25 2.25 0 1 0 1.5 0v-.378a2.25 2.25 0 0 0 1.5-2.122V5.376A2.25 2.25 0 0 0 6.5 3.254Z"/></svg>
214
- </div>
215
- <span class="feature-command-badge">/pr</span>
216
- </div>
217
- <h3 class="feature-name">Pull Request Power Tools</h3>
218
- <p class="feature-text">Execute real pull request workflows directly in Discord. Inspect line diffs (+482 -193), check runs, review statuses, and execute Approve or Merge actions.</p>
219
- <ul class="feature-bullets">
220
- <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Real-time CI check pipeline aggregation</li>
221
- <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Action buttons: Approve, Changes, Merge</li>
222
- </ul>
223
- </div>
224
-
225
- <!-- 3. /search -->
226
- <div class="feature-card reveal">
227
- <div class="feature-top">
228
- <div class="feature-icon-box">
229
- <svg viewBox="0 0 16 16"><path d="M10.68 11.74a6 6 0 0 1-7.922-8.982 6 6 0 0 1 8.982 7.922l3.04 3.04a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215ZM11.5 7a4.499 4.499 0 1 0-8.997 0A4.499 4.499 0 0 0 11.5 7Z"/></svg>
230
- </div>
231
- <span class="feature-command-badge">/search</span>
232
- </div>
233
- <h3 class="feature-name">Universal GitHub Search</h3>
234
- <p class="feature-text">Search across GitHub code, issues, PRs, repos, and commits using official qualifiers like repo:, language:, is:open, and author:.</p>
235
- <ul class="feature-bullets">
236
- <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Fast multi-type discovery</li>
237
- <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Sub-100ms response formatting</li>
238
- </ul>
239
- </div>
240
-
241
- <!-- 4. /code -->
242
- <div class="feature-card reveal">
243
- <div class="feature-top">
244
- <div class="feature-icon-box">
245
- <svg viewBox="0 0 16 16"><path d="m11.28 3.22 4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.749.749 0 0 1-1.275-.326.749.749 0 0 1 .215-.734L13.94 8l-3.72-3.72a.749.749 0 0 1 .215-.734.749.749 0 0 1 1.06-.026Zm-6.56 0a.75.75 0 0 1 1.06 0 .749.749 0 0 1 .215.734.749.749 0 0 1-.215.734L2.06 8l3.72 3.72a.749.749 0 0 1-.215.734.749.749 0 0 1-1.06.026L.22 8.53a.75.75 0 0 1 0-1.06l4.25-4.25a.75.75 0 0 1 1.06 0Z"/></svg>
246
- </div>
247
- <span class="feature-command-badge">/code</span>
248
- </div>
249
- <h3 class="feature-name">Code Viewer &amp; Blame</h3>
250
- <p class="feature-text">Read remote source code with syntax highlighting, perform git blame on specific line intervals, and resolve which PR introduced a given commit.</p>
251
- <ul class="feature-bullets">
252
- <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Line-by-line commit authorship</li>
253
- <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Direct origin pull request resolution</li>
254
- </ul>
255
- </div>
256
-
257
- <!-- 5. /investigate -->
258
- <div class="feature-card reveal">
259
- <div class="feature-top">
260
- <div class="feature-icon-box">
261
- <svg viewBox="0 0 16 16"><path d="M8.75.75V3h5.5a.75.75 0 0 1 0 1.5h-5.5v2.25a.75.75 0 0 1-1.5 0V4.5H1.75a.75.75 0 0 1 0-1.5h5.5V.75a.75.75 0 0 1 1.5 0ZM1.75 10h5.5v2.25a.75.75 0 0 0 1.5 0V11.5h5.5a.75.75 0 0 0 0-1.5h-5.5V7.75a.75.75 0 0 0-1.5 0V10H1.75a.75.75 0 0 0 0 1.5Z"/></svg>
262
- </div>
263
- <span class="feature-command-badge">/investigate</span>
264
- </div>
265
- <h3 class="feature-name">Lifecycle Investigation</h3>
266
- <p class="feature-text">Reconstruct the entire lifecycle of a bug or feature: Originating Issue - Commits - Pull Request - Reviewers - Merge - Release Tag.</p>
267
- <ul class="feature-bullets">
268
- <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Complete chronological timeline</li>
269
- <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Identifies approvals and release tags</li>
270
- </ul>
271
- </div>
272
-
273
- <!-- 6. /activity -->
274
- <div class="feature-card reveal">
275
- <div class="feature-top">
276
- <div class="feature-icon-box">
277
- <svg viewBox="0 0 16 16"><path d="M1.5 1.75V13.5h13.75a.75.75 0 0 1 0 1.5H.75a.75.75 0 0 1-.75-.75V1.75a.75.75 0 0 1 1.5 0Zm14.28 2.53-5.25 5.25a.75.75 0 0 1-1.06 0L7 7.06 2.53 11.53a.75.75 0 0 1-1.06-1.06l5-5a.75.75 0 0 1 1.06 0L10 7.94l4.72-4.72a.75.75 0 0 1 1.06 1.06Z"/></svg>
278
- </div>
279
- <span class="feature-command-badge">/activity</span>
280
- </div>
281
- <h3 class="feature-name">Developer Histograms</h3>
282
- <p class="feature-text">Visualize commit rhythms with ASCII weekly bar charts, addition/deletion churn rates, and team turnaround velocity.</p>
283
- <ul class="feature-bullets">
284
- <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Terminal-friendly ASCII histograms</li>
285
- <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> /activity me personal statistics</li>
286
- </ul>
287
- </div>
288
-
289
- <!-- 7. /trending -->
290
- <div class="feature-card reveal">
291
- <div class="feature-top">
292
- <div class="feature-icon-box">
293
- <svg viewBox="0 0 16 16"><path d="M9.504.43a1.5 1.5 0 0 1 2.456.963l.006.127.034 1.834a3.5 3.5 0 0 0 1.802 3.03l.158.087 1.488.744a1.5 1.5 0 0 1 .74 1.848l-.053.138-.68 1.487a3.5 3.5 0 0 0-.25 2.186l.06.311.383 1.533a1.5 1.5 0 0 1-1.332 1.848l-.16.009-.434.004a4.5 4.5 0 0 1-4.496-4.32l-.004-.18V8.75a.75.75 0 0 0-1.5 0v3.491a6 6 0 0 0 5.86 5.999l.24.005.434-.004a3 3 0 0 0 2.91-3.693l-.383-1.533a2 2 0 0 1 .143-1.25l.68-1.487a3 3 0 0 0-1.374-3.97l-1.488-.745a2 2 0 0 1-1.03-1.731l-.034-1.835a3 3 0 0 0-4.912-2.18L7.43 2.857a.75.75 0 1 0 1.06 1.06l1.014-.987Z"/></svg>
294
- </div>
295
- <span class="feature-command-badge">/trending</span>
296
- </div>
297
- <h3 class="feature-name">Ecosystem Radar</h3>
298
- <p class="feature-text">Curated trending repos across modern stacks: TypeScript, Rust, AI/ML, Bun, Databases, Go, and Python with star velocity metrics.</p>
299
- <ul class="feature-bullets">
300
- <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> 7 modern ecosystem filters</li>
301
- <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> High-signal growth filtering</li>
302
- </ul>
303
- </div>
304
-
305
- <!-- 8. /watch -->
306
- <div class="feature-card reveal">
307
- <div class="feature-top">
308
- <div class="feature-icon-box">
309
- <svg viewBox="0 0 16 16"><path d="M8 2a6 6 0 0 0-6 6c0 1.77.78 3.36 2 4.47v.78c0 .41.34.75.75.75h6.5c.41 0 .75-.34.75-.75v-.78A5.996 5.996 0 0 0 14 8a6 6 0 0 0-6-6Zm0 1.5a4.5 4.5 0 0 1 4.5 4.5c0 1.4-.64 2.65-1.65 3.48a.75.75 0 0 0-.35.64v.38H5.5v-.38a.75.75 0 0 0-.35-.64A4.485 4.485 0 0 1 3.5 8 4.5 4.5 0 0 1 8 3.5Z"/></svg>
310
- </div>
311
- <span class="feature-command-badge">/watch</span>
312
- </div>
313
- <h3 class="feature-name">GitHub Watchtower</h3>
314
- <p class="feature-text">Subscribe specific Discord channels to releases, pull requests, issues, or security advisories with granular routing per repo.</p>
315
- <ul class="feature-bullets">
316
- <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Automated event notifications</li>
317
- <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Multi-channel event routing</li>
318
- </ul>
319
- </div>
320
-
321
- <!-- 9. /actions -->
322
- <div class="feature-card reveal">
323
- <div class="feature-top">
324
- <div class="feature-icon-box">
325
- <svg viewBox="0 0 16 16"><path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Zm4.879-2.773 4.264 2.559a.25.25 0 0 1 0 .428l-4.264 2.559A.25.25 0 0 1 6 10.559V5.442a.25.25 0 0 1 .379-.215Z"/></svg>
326
- </div>
327
- <span class="feature-command-badge">/actions</span>
328
- </div>
329
- <h3 class="feature-name">CI/CD Workflow Tree</h3>
330
- <p class="feature-text">Visual representation of GitHub Actions pipelines in structured ASCII trees. Track conclusions, durations, and trigger reruns directly from Discord.</p>
331
- <ul class="feature-bullets">
332
- <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Visual branch &amp; job hierarchy</li>
333
- <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Rerun and cancel workflows</li>
334
- </ul>
335
- </div>
336
-
337
- <!-- 10. /security -->
338
- <div class="feature-card reveal">
339
- <div class="feature-top">
340
- <div class="feature-icon-box">
341
- <svg viewBox="0 0 16 16"><path d="M7.467.133a1.748 1.748 0 0 1 1.066 0l5.25 1.68A1.75 1.75 0 0 1 15 3.48V7c0 1.566-.32 3.182-1.303 4.682-.983 1.498-2.585 2.813-5.032 3.855a1.697 1.697 0 0 1-1.33 0c-2.447-1.042-4.049-2.357-5.032-3.855C1.32 10.182 1 8.566 1 7V3.48a1.75 1.75 0 0 1 1.217-1.667l5.25-1.68Z"/></svg>
342
- </div>
343
- <span class="feature-command-badge">/security</span>
344
- </div>
345
- <h3 class="feature-name">Security &amp; Leak Guard</h3>
346
- <p class="feature-text">Dependabot vulnerability alerts, GHSA / CVE breakdowns, and background message scanner that detects leaked tokens with one-click revocation guides.</p>
347
- <ul class="feature-bullets">
348
- <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Dependabot &amp; GHSA vulnerability feeds</li>
349
- <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Zero-log message secret scanner</li>
350
- </ul>
351
- </div>
352
-
353
- <!-- 11. /release -->
354
- <div class="feature-card reveal">
355
- <div class="feature-top">
356
- <div class="feature-icon-box">
357
- <svg viewBox="0 0 16 16"><path d="M1 7.775V2.75C1 1.784 1.784 1 2.75 1h5.025c.464 0 .91.184 1.238.513l6.25 6.25a1.75 1.75 0 0 1 0 2.474l-5.026 5.026a1.75 1.75 0 0 1-2.474 0l-6.25-6.25A1.752 1.752 0 0 1 1 7.775Zm1.5 0c0 .066.026.13.073.177l6.25 6.25a.25.25 0 0 0 .354 0l5.025-5.025a.25.25 0 0 0 0-.354l-6.25-6.25a.25.25 0 0 0-.177-.073H2.75a.25.25 0 0 0-.25.25ZM6 4.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0Z"/></svg>
358
- </div>
359
- <span class="feature-command-badge">/release</span>
360
- </div>
361
- <h3 class="feature-name">Release Management</h3>
362
- <p class="feature-text">Inspect published tags, compare commit deltas between releases (v1.2.0...v1.3.0), and automatically generate markdown release notes from merged PRs.</p>
363
- <ul class="feature-bullets">
364
- <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Tag comparison and asset counts</li>
365
- <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Automated changelog generator</li>
366
- </ul>
367
- </div>
368
-
369
- <!-- 12. /team -->
370
- <div class="feature-card reveal">
371
- <div class="feature-top">
372
- <div class="feature-icon-box">
373
- <svg viewBox="0 0 16 16"><path d="M2 5.5a3.5 3.5 0 1 1 5.898 2.549 5.508 5.508 0 0 1 3.034 4.084.75.75 0 1 1-1.482.235 4.002 4.002 0 0 0-6.898-2.618.75.75 0 0 1-1.052-.008A3.491 3.491 0 0 1 2 5.5Zm3.5-2a2 2 0 1 0 0 4 2 2 0 0 0 0-4Zm8.5 4.5a3 3 0 1 1-5.07 2.217.75.75 0 1 1 1.06-.063 1.5 1.5 0 1 0 2.51-1.154.75.75 0 0 1 1.5 0Z"/></svg>
374
- </div>
375
- <span class="feature-command-badge">/team</span>
376
- </div>
377
- <h3 class="feature-name">Team Velocity &amp; Balance</h3>
378
- <p class="feature-text">Team turnaround metrics without toxic vanity rankings. Review velocity, cycle times, and review load balancing to prevent engineering burnout.</p>
379
- <ul class="feature-bullets">
380
- <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Review turnaround cycle times</li>
381
- <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Workload distribution balance</li>
382
- </ul>
383
- </div>
384
-
385
- <!-- 13. /home -->
386
- <div class="feature-card reveal">
387
- <div class="feature-top">
388
- <div class="feature-icon-box">
389
- <svg viewBox="0 0 16 16"><path d="M6.906.664a1.749 1.749 0 0 1 2.187 0l5.25 4.2c.415.332.657.835.657 1.367v7.019A1.75 1.75 0 0 1 13.25 15h-3.5a.75.75 0 0 1-.75-.75V9H7v5.25a.75.75 0 0 1-.75.75h-3.5A1.75 1.75 0 0 1 1 13.25V6.231c0-.531.242-1.034.657-1.366l5.25-4.2Zm1.25 1.171a.25.25 0 0 0-.312 0l-5.25 4.2a.25.25 0 0 0-.094.196v7.019c0 .138.112.25.25.25H5.5V8.25a.75.75 0 0 1 .75-.75h3.5a.75.75 0 0 1 .75.75v5.25h2.75a.25.25 0 0 0 .25-.25V6.23a.25.25 0 0 0-.094-.195Z"/></svg>
390
- </div>
391
- <span class="feature-command-badge">/home</span>
392
- </div>
393
- <h3 class="feature-name">Morning Cockpit</h3>
394
- <p class="feature-text">Morning command center showing your active PRs, pending reviews, repo watchtower alerts, and rising ecosystem highlights.</p>
395
- <ul class="feature-bullets">
396
- <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Personalized daily dashboard</li>
397
- <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Pending reviews and alerts at a glance</li>
398
- </ul>
399
- </div>
400
-
401
- <!-- 14. /connect -->
402
- <div class="feature-card reveal">
403
- <div class="feature-top">
404
- <div class="feature-icon-box">
405
- <svg viewBox="0 0 16 16"><path d="M6.5 1.75a.25.25 0 0 1 .25-.25h2.5a.25.25 0 0 1 .25.25V3h-3ZM11 3V1.75A1.75 1.75 0 0 0 9.25 0h-2.5A1.75 1.75 0 0 0 5 1.75V3H1.75C.784 3 0 3.784 0 4.75v8.5C0 14.216.784 15 1.75 15h12.5A1.75 1.75 0 0 0 16 13.25v-8.5A1.75 1.75 0 0 0 14.25 3Z"/></svg>
406
- </div>
407
- <span class="feature-command-badge">/connect</span>
408
- </div>
409
- <h3 class="feature-name">Token Vault</h3>
410
- <p class="feature-text">Store GitHub Personal Access Tokens safely with AES-256-GCM encryption. Public repos never require credentials.</p>
411
- <ul class="feature-bullets">
412
- <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Military-grade AES-256-GCM encryption</li>
413
- <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Zero-knowledge token storage</li>
414
- </ul>
415
- </div>
416
-
417
- <!-- 15. /why -->
418
- <div class="feature-card reveal">
419
- <div class="feature-top">
420
- <div class="feature-icon-box">
421
- <svg viewBox="0 0 16 16"><path d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm8-6.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM6.92 6.085h.001a.749.749 0 0 1 1.059-.062 1.488 1.488 0 0 1 .494 1.102c0 .546-.3.923-.627 1.258-.293.301-.597.613-.597 1.117a.75.75 0 0 1-1.5 0c0-.987.585-1.59 1.002-2.018.232-.238.472-.484.472-.757a.253.253 0 0 0-.083-.188.27.27 0 0 0-.174-.052c-.176 0-.31.092-.41.228a.75.75 0 0 1-1.135-.628ZM8 12.5a1 1 0 1 0 0-2 1 1 0 0 0 0 2Z"/></svg>
422
- </div>
423
- <span class="feature-command-badge">/why</span>
252
+ <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
253
+ <!-- Feature Cards -->
254
+ <div class="group p-6 rounded-2xl bg-bg-surface border border-border hover:border-gh-blue/30 hover:-translate-y-1 hover:shadow-xl hover:shadow-gh-blue/5 transition-all duration-300">
255
+ <div class="w-12 h-12 rounded-xl bg-gh-blue/10 border border-gh-blue/20 flex items-center justify-center mb-4 group-hover:scale-110 transition-transform duration-300">
256
+ <i data-lucide="git-pull-request" class="w-6 h-6 text-gh-blue"></i>
424
257
</div>
425
- <h3 class="feature-name">Code Archaeology</h3>
426
- <p class="feature-text">Trace any file and line change back through Commit - Pull Request - Originating Issue to answer why a piece of code exists.</p>
427
- <ul class="feature-bullets">
428
- <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Full lineage tracing</li>
429
- <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Context-rich decision history</li>
430
- </ul>
258
+ <h3 class="text-lg font-semibold mb-2">Pull Request Tools</h3>
259
+ <p class="text-sm text-text-secondary leading-relaxed">View details, CI status, approve, request changes, and merge — all from Discord.</p>
431
260
</div>
432
261
433
- <!-- 16. /ask -->
434
- <div class="feature-card reveal">
435
- <div class="feature-top">
436
- <div class="feature-icon-box">
437
- <svg viewBox="0 0 16 16"><path d="M8 1.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm9 3a1 1 0 1 1-2 0 1 1 0 0 1 2 0Zm-.25-6.25a.75.75 0 0 0-1.5 0v3.5a.75.75 0 0 0 1.5 0Z"/></svg>
438
- </div>
439
- <span class="feature-command-badge">/ask</span>
262
+ <div class="group p-6 rounded-2xl bg-bg-surface border border-border hover:border-gh-green/30 hover:-translate-y-1 hover:shadow-xl hover:shadow-gh-green/5 transition-all duration-300">
263
+ <div class="w-12 h-12 rounded-xl bg-gh-green/10 border border-gh-green/20 flex items-center justify-center mb-4 group-hover:scale-110 transition-transform duration-300">
264
+ <i data-lucide="book-open" class="w-6 h-6 text-gh-green"></i>
440
265
</div>
441
- <h3 class="feature-name">Query Engine</h3>
442
- <p class="feature-text">Deterministic query helper to answer questions like pull requests waiting for review over 24 hours or frequently modified files.</p>
443
- <ul class="feature-bullets">
444
- <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Natural language query parsing</li>
445
- <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Stale PR and bottleneck detection</li>
446
- </ul>
266
+ <h3 class="text-lg font-semibold mb-2">Repository Intel</h3>
267
+ <p class="text-sm text-text-secondary leading-relaxed">Health scores, dependencies, growth metrics, and interactive navigation tabs.</p>
447
268
</div>
448
269
449
- <!-- 17. /tools -->
450
- <div class="feature-card reveal">
451
- <div class="feature-top">
452
- <div class="feature-icon-box">
453
- <svg viewBox="0 0 16 16"><path d="M5.45 4.28A.75.75 0 0 1 6.5 4.5v2.5h3v-2.5a.75.75 0 0 1 1.28-.53l3.5 3.5a.75.75 0 0 1 0 1.06l-3.5 3.5a.75.75 0 0 1-1.28-.53V9h-3v2.5a.75.75 0 0 1-1.28.53l-3.5-3.5a.75.75 0 0 1 0-1.06Z"/></svg>
454
- </div>
455
- <span class="feature-command-badge">/tools</span>
270
+ <div class="group p-6 rounded-2xl bg-bg-surface border border-border hover:border-gh-purple/30 hover:-translate-y-1 hover:shadow-xl hover:shadow-gh-purple/5 transition-all duration-300">
271
+ <div class="w-12 h-12 rounded-xl bg-gh-purple/10 border border-gh-purple/20 flex items-center justify-center mb-4 group-hover:scale-110 transition-transform duration-300">
272
+ <i data-lucide="search" class="w-6 h-6 text-gh-purple"></i>
456
273
</div>
457
- <h3 class="feature-name">Dev Essentials</h3>
458
- <p class="feature-text">Quick-access developer utilities including JSON formatting, base64 encoding, JWT inspection, hash generation, and timestamp conversion.</p>
459
- <ul class="feature-bullets">
460
- <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Format, encode, decode utilities</li>
461
- <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> JWT and timestamp tools</li>
462
- </ul>
274
+ <h3 class="text-lg font-semibold mb-2">Universal Search</h3>
275
+ <p class="text-sm text-text-secondary leading-relaxed">Search code, issues, PRs, repos, and commits with GitHub qualifiers.</p>
463
276
</div>
464
277
465
- <!-- 18. /settings -->
466
- <div class="feature-card reveal">
467
- <div class="feature-top">
468
- <div class="feature-icon-box">
469
- <svg viewBox="0 0 16 16"><path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Zm4.879-2.773 4.264 2.559a.25.25 0 0 1 0 .428l-4.264 2.559A.25.25 0 0 1 6 10.559V5.442a.25.25 0 0 1 .379-.215Z"/></svg>
470
- </div>
471
- <span class="feature-command-badge">/settings</span>
278
+ <div class="group p-6 rounded-2xl bg-bg-surface border border-border hover:border-gh-amber/30 hover:-translate-y-1 hover:shadow-xl hover:shadow-gh-amber/5 transition-all duration-300">
279
+ <div class="w-12 h-12 rounded-xl bg-gh-amber/10 border border-gh-amber/20 flex items-center justify-center mb-4 group-hover:scale-110 transition-transform duration-300">
280
+ <i data-lucide="shield-check" class="w-6 h-6 text-gh-amber"></i>
472
281
</div>
473
- <h3 class="feature-name">Server Config</h3>
474
- <p class="feature-text">Configure default repositories, notification channels, access controls, and command permissions per Discord server.</p>
475
- <ul class="feature-bullets">
476
- <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Per-server configuration profiles</li>
477
- <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Role-based access controls</li>
478
- </ul>
282
+ <h3 class="text-lg font-semibold mb-2">Security Guard</h3>
283
+ <p class="text-sm text-text-secondary leading-relaxed">Dependabot alerts, CVE lookup, and real-time secret leak scanning.</p>
479
284
</div>
480
285
481
- <!-- 19. /help -->
482
- <div class="feature-card reveal">
483
- <div class="feature-top">
484
- <div class="feature-icon-box">
485
- <svg viewBox="0 0 16 16"><path d="M8 1.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm9 3a1 1 0 1 1-2 0 1 1 0 0 1 2 0Zm-.25-6.25a.75.75 0 0 0-1.5 0v3.5a.75.75 0 0 0 1.5 0Z"/></svg>
486
- </div>
487
- <span class="feature-command-badge">/help</span>
286
+ <div class="group p-6 rounded-2xl bg-bg-surface border border-border hover:border-discord-blurple/30 hover:-translate-y-1 hover:shadow-xl hover:shadow-discord-blurple/5 transition-all duration-300">
287
+ <div class="w-12 h-12 rounded-xl bg-discord-blurple/10 border border-discord-blurple/20 flex items-center justify-center mb-4 group-hover:scale-110 transition-transform duration-300">
288
+ <i data-lucide="play-circle" class="w-6 h-6 text-discord-blurple"></i>
488
289
</div>
489
- <h3 class="feature-name">Command Directory</h3>
490
- <p class="feature-text">Interactive help system with command categories, usage examples, argument descriptions, and quick-start guides for new users.</p>
491
- <ul class="feature-bullets">
492
- <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Categorized command browser</li>
493
- <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Usage examples and syntax help</li>
494
- </ul>
290
+ <h3 class="text-lg font-semibold mb-2">CI/CD Monitoring</h3>
291
+ <p class="text-sm text-text-secondary leading-relaxed">Visual workflow trees, run history, and rerun/cancel controls.</p>
495
292
</div>
496
293
497
- <!-- 20. /ai -->
498
- <div class="feature-card reveal">
499
- <div class="feature-top">
500
- <div class="feature-icon-box">
501
- <svg viewBox="0 0 16 16"><path d="M5.45 4.28A.75.75 0 0 1 6.5 4.5v2.5h3v-2.5a.75.75 0 0 1 1.28-.53l3.5 3.5a.75.75 0 0 1 0 1.06l-3.5 3.5a.75.75 0 0 1-1.28-.53V9h-3v2.5a.75.75 0 0 1-1.28.53l-3.5-3.5a.75.75 0 0 1 0-1.06Z"/></svg>
502
- </div>
503
- <span class="feature-command-badge">/ai</span>
294
+ <div class="group p-6 rounded-2xl bg-bg-surface border border-border hover:border-gh-coral/30 hover:-translate-y-1 hover:shadow-xl hover:shadow-gh-coral/5 transition-all duration-300">
295
+ <div class="w-12 h-12 rounded-xl bg-gh-coral/10 border border-gh-coral/20 flex items-center justify-center mb-4 group-hover:scale-110 transition-transform duration-300">
296
+ <i data-lucide="brain" class="w-6 h-6 text-gh-coral"></i>
504
297
</div>
505
- <h3 class="feature-name">AI Code Copilot</h3>
506
- <p class="feature-text">AI-powered code explanations, refactoring suggestions, and intelligent summaries of pull requests and issues directly in Discord.</p>
507
- <ul class="feature-bullets">
508
- <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Intelligent code explanations</li>
509
- <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> PR and issue summarization</li>
510
- </ul>
511
- </div>
512
-
513
- <!-- 21. /code-review -->
514
- <div class="feature-card reveal">
515
- <div class="feature-top">
516
- <div class="feature-icon-box">
517
- <svg viewBox="0 0 16 16"><path d="M7.467.133a1.748 1.748 0 0 1 1.066 0l5.25 1.68A1.75 1.75 0 0 1 15 3.48V7c0 1.566-.32 3.182-1.303 4.682-.983 1.498-2.585 2.813-5.032 3.855a1.697 1.697 0 0 1-1.33 0c-2.447-1.042-4.049-2.357-5.032-3.855C1.32 10.182 1 8.566 1 7V3.48a1.75 1.75 0 0 1 1.217-1.667l5.25-1.68Z"/></svg>
518
- </div>
519
- <span class="feature-command-badge">/code-review</span>
520
- </div>
521
- <h3 class="feature-name">Automated PR Review</h3>
522
- <p class="feature-text">Automated code review with security analysis, performance suggestions, style enforcement, and best practice recommendations on every pull request.</p>
523
- <ul class="feature-bullets">
524
- <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Security and performance analysis</li>
525
- <li><svg viewBox="0 0 16 16"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> Style and best practice enforcement</li>
526
- </ul>
298
+ <h3 class="text-lg font-semibold mb-2">AI Copilot</h3>
299
+ <p class="text-sm text-text-secondary leading-relaxed">Code explanations, PR summaries, and intelligent bug fix suggestions.</p>
527
300
</div>
528
301
</div>
529
302
</div>
530
303
</section>
531
304
532
- <!-- Killer Features Section -->
533
- <section class="killer-section" id="killer-tools">
534
- <div class="container">
535
- <div class="section-header reveal">
536
- <div class="section-tag">High-Impact Utilities</div>
537
- <h2 class="section-title">Workflow Accelerators</h2>
538
- <p class="section-desc">Designed to eliminate engineering bottlenecks in seconds.</p>
305
+ <!-- All Commands Section -->
306
+ <section id="commands" class="relative z-10 py-16 sm:py-24 px-4 sm:px-6 lg:px-8 bg-bg-subtle/50">
307
+ <div class="max-w-7xl mx-auto">
308
+ <div class="text-center mb-16">
309
+ <h2 class="text-3xl sm:text-4xl font-bold mb-4">All 21 Commands</h2>
310
+ <p class="text-text-secondary text-lg max-w-2xl mx-auto">Every command you need to manage your GitHub workflow from Discord.</p>
539
311
</div>
540
312
541
- <div class="killer-grid">
542
- <div class="killer-card reveal">
543
- <h4 class="killer-card-title">
544
- <svg width="18" height="18" viewBox="0 0 16 16" fill="var(--gh-blue)"><path d="M6.906.664a1.749 1.749 0 0 1 2.187 0l5.25 4.2c.415.332.657.835.657 1.367v7.019A1.75 1.75 0 0 1 13.25 15h-3.5a.75.75 0 0 1-.75-.75V9H7v5.25a.75.75 0 0 1-.75.75h-3.5A1.75 1.75 0 0 1 1 13.25V6.231c0-.531.242-1.034.657-1.366l5.25-4.2Zm1.25 1.171a.25.25 0 0 0-.312 0l-5.25 4.2a.25.25 0 0 0-.094.196v7.019c0 .138.112.25.25.25H5.5V8.25a.75.75 0 0 1 .75-.75h3.5a.75.75 0 0 1 .75.75v5.25h2.75a.25.25 0 0 0 .25-.25V6.23a.25.25 0 0 0-.094-.195Z"/></svg>
545
- /home Cockpit
546
- </h4>
547
- <p class="killer-card-desc">Morning command center showing your active PRs, pending reviews, repo watchtower alerts, and rising ecosystem highlights.</p>
548
- </div>
549
-
550
- <div class="killer-card reveal">
551
- <h4 class="killer-card-title">
552
- <svg width="18" height="18" viewBox="0 0 16 16" fill="var(--gh-purple)"><path d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm8-6.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM6.92 6.085h.001a.749.749 0 0 1 1.059-.062 1.488 1.488 0 0 1 .494 1.102c0 .546-.3.923-.627 1.258-.293.301-.597.613-.597 1.117a.75.75 0 0 1-1.5 0c0-.987.585-1.59 1.002-2.018.232-.238.472-.484.472-.757a.253.253 0 0 0-.083-.188.27.27 0 0 0-.174-.052c-.176 0-.31.092-.41.228a.75.75 0 0 1-1.135-.628ZM8 12.5a1 1 0 1 0 0-2 1 1 0 0 0 0 2Z"/></svg>
553
- /why Archaeology
554
- </h4>
555
- <p class="killer-card-desc">Trace any file and line change back through Commit - Pull Request - Originating Issue to answer why a piece of code exists.</p>
556
- </div>
557
-
558
- <div class="killer-card reveal">
559
- <h4 class="killer-card-title">
560
- <svg width="18" height="18" viewBox="0 0 16 16" fill="var(--gh-green)"><path d="M6.5 1.75a.25.25 0 0 1 .25-.25h2.5a.25.25 0 0 1 .25.25V3h-3ZM11 3V1.75A1.75 1.75 0 0 0 9.25 0h-2.5A1.75 1.75 0 0 0 5 1.75V3H1.75C.784 3 0 3.784 0 4.75v8.5C0 14.216.784 15 1.75 15h12.5A1.75 1.75 0 0 0 16 13.25v-8.5A1.75 1.75 0 0 0 14.25 3Z"/></svg>
561
- /connect Vault
562
- </h4>
563
- <p class="killer-card-desc">Store GitHub Personal Access Tokens safely with AES-256-GCM encryption. Public repos never require credentials.</p>
564
- </div>
565
-
566
- <div class="killer-card reveal">
567
- <h4 class="killer-card-title">
568
- <svg width="18" height="18" viewBox="0 0 16 16" fill="var(--gh-amber)"><path d="M8 1.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm9 3a1 1 0 1 1-2 0 1 1 0 0 1 2 0Zm-.25-6.25a.75.75 0 0 0-1.5 0v3.5a.75.75 0 0 0 1.5 0Z"/></svg>
569
- /ask Engine
570
- </h4>
571
- <p class="killer-card-desc">Deterministic query helper to answer questions like pull requests waiting for review over 24 hours or frequently modified files.</p>
572
- </div>
313
+ <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4">
314
+ <!-- Command cards generated by JS -->
315
+ <div id="commands-grid" class="contents"></div>
573
316
</div>
574
317
</div>
575
318
</section>
576
319
577
- <!-- Architecture & Security -->
578
- <section class="arch-section" id="architecture">
579
- <div class="container">
580
- <div class="section-header reveal">
581
- <div class="section-tag">Security &amp; Infrastructure</div>
582
- <h2 class="section-title">Zero-Trust Architecture</h2>
583
- <p class="section-desc">Engineered for security-conscious teams, open-source communities, and enterprise organizations.</p>
320
+ <!-- Setup Section -->
321
+ <section id="setup" class="relative z-10 py-16 sm:py-24 px-4 sm:px-6 lg:px-8">
322
+ <div class="max-w-4xl mx-auto">
323
+ <div class="text-center mb-12">
324
+ <h2 class="text-3xl sm:text-4xl font-bold mb-4">Get Started in 2 Minutes</h2>
325
+ <p class="text-text-secondary text-lg">Clone, configure, and run. No complex setup required.</p>
584
326
</div>
585
327
586
- <div class="arch-box reveal">
587
- <h3 style="font-size: 1.25rem; font-weight: 700; margin-bottom: 12px;">Data Isolation and Security Pipeline</h3>
588
- <p style="color: var(--text-secondary); font-size: 0.95rem;">
589
- DevPulse operates as an outbound-only Discord Gateway client with zero inbound open ports required. All token interactions are isolated per user and encrypted at rest.
590
- </p>
591
-
592
- <div class="arch-flow-grid">
593
- <div class="arch-flow-step">
594
- <span class="step-num">STAGE 01</span>
595
- <h4 class="step-title">Discord Gateway</h4>
596
- <p class="step-desc">Slash commands and button clicks received via authenticated Discord WebSocket Gateway v10.</p>
597
- </div>
598
-
599
- <div class="arch-flow-step">
600
- <span class="step-num">STAGE 02</span>
601
- <h4 class="step-title">AES-256-GCM Vault</h4>
602
- <p class="step-desc">Personal Access Tokens decrypted ephemerally in-memory with unique initialization vectors.</p>
603
- </div>
604
-
605
- <div class="arch-flow-step">
606
- <span class="step-num">STAGE 03</span>
607
- <h4 class="step-title">GitHub API Engine</h4>
608
- <p class="step-desc">Direct REST and GraphQL calls with rate-limiting protection, ETag caching, and response deduplication.</p>
609
- </div>
610
-
611
- <div class="arch-flow-step">
612
- <span class="step-num">STAGE 04</span>
613
- <h4 class="step-title">Multi-Tenant Store</h4>
614
- <p class="step-desc">Multi-tenant server configs and alert routing persisted in Turso (libSQL) with zero token logging.</p>
615
- </div>
616
- </div>
617
- </div>
618
- </div>
619
- </section>
620
-
621
- <!-- Quick Start Walkthrough -->
622
- <section class="install-section" id="quickstart">
623
- <div class="container">
624
- <div class="section-header reveal">
625
- <div class="section-tag">Self-Hosting &amp; Setup</div>
626
- <h2 class="section-title">Get Started in Under 3 Minutes</h2>
627
- <p class="section-desc">Clone the repository, configure your Discord bot token, and launch DevPulse with Bun.</p>
628
- </div>
629
-
630
- <div class="terminal-box reveal" style="max-width: 800px; margin: 0 auto;">
631
- <div class="terminal-topbar">
632
- <div class="window-dots">
633
- <span class="window-dot dot-red"></span>
634
- <span class="window-dot dot-yellow"></span>
635
- <span class="window-dot dot-green"></span>
636
- </div>
637
- <span style="font-family: var(--font-mono); font-size: 0.8rem; color: var(--text-secondary);">bash &bull; terminal</span>
638
- <button class="terminal-copy-btn" onclick="copyText('git clone [email protected]:husteno-o/git-discord-bot.git\ncd git-discord-bot\nbun install\ncp .env.example .env\nbun run start', this)" title="Copy all commands">
639
- <svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor">
640
- <path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"/>
641
- <path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"/>
642
- </svg>
328
+ <!-- Terminal -->
329
+ <div class="rounded-2xl bg-[#0d1117] border border-border overflow-hidden shadow-2xl">
330
+ <div class="flex items-center justify-between px-4 py-3 bg-bg-surface border-b border-border">
331
+ <div class="flex items-center gap-2">
332
+ <div class="w-3 h-3 rounded-full bg-red-500"></div>
333
+ <div class="w-3 h-3 rounded-full bg-yellow-500"></div>
334
+ <div class="w-3 h-3 rounded-full bg-green-500"></div>
335
+ </div>
336
+ <span class="text-xs font-mono text-text-secondary">terminal</span>
337
+ <button id="copy-all-btn" class="flex items-center gap-1.5 px-2 py-1 rounded text-xs text-text-muted hover:text-text-primary hover:bg-bg-hover transition-colors">
338
+ <i data-lucide="copy" class="w-3 h-3"></i> Copy
643
339
</button>
644
340
</div>
645
- <div class="terminal-content">
646
- <div class="terminal-comment"># 1. Clone repository from GitHub</div>
647
- <div class="terminal-line">
648
- <span class="terminal-cmd"><span style="color:#58a6ff">$</span> git clone [email protected]:husteno-o/git-discord-bot.git</span>
649
- </div>
650
-
651
- <div class="terminal-comment"># 2. Enter directory and install with Bun</div>
652
- <div class="terminal-line">
653
- <span class="terminal-cmd"><span style="color:#58a6ff">$</span> cd git-discord-bot &amp;&amp; bun install</span>
654
- </div>
655
-
656
- <div class="terminal-comment"># 3. Setup environment configuration</div>
657
- <div class="terminal-line">
658
- <span class="terminal-cmd"><span style="color:#58a6ff">$</span> cp .env.example .env</span>
659
- </div>
660
-
661
- <div class="terminal-comment"># 4. Run tests and launch DevPulse bot</div>
662
- <div class="terminal-line">
663
- <span class="terminal-cmd"><span style="color:#58a6ff">$</span> bun run test &amp;&amp; bun run start</span>
664
- </div>
341
+ <div class="p-6 font-mono text-sm space-y-3">
342
+ <div class="text-text-muted"># Clone the repository</div>
343
+ <div class="text-text-primary"><span class="text-gh-blue">$</span> git clone https://github.com/husteno-o/git-discord-bot.git</div>
344
+ <div class="text-text-primary"><span class="text-gh-blue">$</span> cd git-discord-bot</div>
345
+ <div class="text-text-muted"># Install dependencies</div>
346
+ <div class="text-text-primary"><span class="text-gh-blue">$</span> bun install</div>
347
+ <div class="text-text-muted"># Configure your bot token</div>
348
+ <div class="text-text-primary"><span class="text-gh-blue">$</span> cp .env.example .env</div>
349
+ <div class="text-text-muted"># Start the bot</div>
350
+ <div class="text-text-primary"><span class="text-gh-blue">$</span> bun run start</div>
665
351
</div>
666
352
</div>
667
353
668
- <!-- Cloudflare Pages Badge -->
669
- <div class="reveal" style="text-align: center; margin-top: 44px;">
670
- <p style="color: var(--text-secondary); font-size: 0.88rem; margin-bottom: 14px;">
671
- Hosting this landing page on Cloudflare Pages:
672
- </p>
673
- <div style="display: inline-flex; align-items: center; gap: 8px; padding: 10px 18px; background: var(--bg-surface); border: 1px solid var(--border-default); border-radius: 10px; font-family: var(--font-mono); font-size: 0.82rem; color: var(--gh-blue);">
674
- <span>Deploy Output: <strong>apps/web/dist</strong> &bull; Build Command: <strong>bun run build:web</strong></span>
354
+ <!-- Docker option -->
355
+ <div class="mt-8 p-6 rounded-2xl bg-bg-surface border border-border">
356
+ <div class="flex items-start gap-4">
357
+ <div class="w-10 h-10 rounded-lg bg-gh-blue/10 flex items-center justify-center flex-shrink-0">
358
+ <i data-lucide="container" class="w-5 h-5 text-gh-blue"></i>
359
+ </div>
360
+ <div>
361
+ <h3 class="font-semibold mb-1">Docker Available</h3>
362
+ <p class="text-sm text-text-secondary mb-3">Pre-built Dockerfile and docker-compose.yml included for containerized deployment.</p>
363
+ <code class="text-xs font-mono px-3 py-1.5 rounded-lg bg-bg-canvas text-gh-blue">docker compose up -d</code>
364
+ </div>
675
365
</div>
676
366
</div>
677
367
</div>
678
368
</section>
679
369
680
370
<!-- Footer -->
681
- <footer class="footer">
682
- <div class="container">
683
- <div class="footer-grid">
684
- <div>
685
- <div class="brand-logo" style="margin-bottom: 10px;">
686
- <div class="brand-icon-wrapper" style="width: 30px; height: 30px;">
687
- <svg viewBox="0 0 16 16"><path d="M5 3.254V3.25v.004a.75.75 0 1 1 0-.004Zm1.5 0a2.25 2.25 0 1 0-3 2.122V8.75a2.25 2.25 0 0 0 1.5 2.122v.378a2.25 2.25 0 1 0 1.5 0v-.378a2.25 2.25 0 0 0 1.5-2.122V5.376A2.25 2.25 0 0 0 6.5 3.254Z"/></svg>
688
- </div>
689
- <span style="font-size: 1.05rem;">DevPulse</span>
371
+ <footer class="relative z-10 border-t border-border bg-bg-subtle py-12 px-4 sm:px-6 lg:px-8">
372
+ <div class="max-w-7xl mx-auto">
373
+ <div class="flex flex-col sm:flex-row items-center justify-between gap-6">
374
+ <div class="flex items-center gap-3">
375
+ <div class="w-8 h-8 rounded-lg bg-gradient-to-br from-gh-green to-gh-blue flex items-center justify-center">
376
+ <svg class="w-4 h-4 text-white" viewBox="0 0 24 24" fill="currentColor">
377
+ <path d="M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5"/>
378
+ </svg>
690
379
</div>
691
- <p class="footer-col-desc">
692
- The GitHub Power-User Operating System for Discord. Never leave Discord for your daily GitHub workflow.
693
- </p>
694
- </div>
695
-
696
- <div>
697
- <h4 class="footer-col-title">Core Areas</h4>
698
- <ul class="footer-col-links">
699
- <li><a href="#simulator">/repo Intelligence</a></li>
700
- <li><a href="#simulator">/pr Power Tools</a></li>
701
- <li><a href="#simulator">/actions CI/CD</a></li>
702
- <li><a href="#simulator">/investigate Trace</a></li>
703
- <li><a href="#features">/security &amp; Leaks</a></li>
704
- </ul>
705
- </div>
706
-
707
- <div>
708
- <h4 class="footer-col-title">Resources</h4>
709
- <ul class="footer-col-links">
710
- <li><a href="https://github.com/husteno-o/git-discord-bot" target="_blank" rel="noopener noreferrer">GitHub Repository</a></li>
711
- <li><a href="https://github.com/husteno-o/git-discord-bot/blob/master/README.md" target="_blank" rel="noopener noreferrer">Documentation</a></li>
712
- <li><a href="https://github.com/husteno-o/git-discord-bot/issues" target="_blank" rel="noopener noreferrer">Issue Tracker</a></li>
713
- <li><a href="https://discord.com/developers/docs" target="_blank" rel="noopener noreferrer">Discord Developer Portal</a></li>
714
- </ul>
715
- </div>
716
-
717
- <div>
718
- <h4 class="footer-col-title">Deployment</h4>
719
- <ul class="footer-col-links">
720
- <li><a href="https://pages.cloudflare.com" target="_blank" rel="noopener noreferrer">Cloudflare Pages</a></li>
721
- <li><a href="#quickstart">Docker Setup</a></li>
722
- <li><a href="#quickstart">Bun Runtime</a></li>
723
- <li><a href="#architecture">Zero-Trust Vault</a></li>
724
- </ul>
725
- </div>
726
- </div>
727
-
728
- <div class="footer-bottom">
729
- <div>
730
- Repository: <a href="https://github.com/husteno-o/git-discord-bot" target="_blank" style="color: var(--gh-blue); text-decoration: none;">[email protected]:husteno-o/git-discord-bot.git</a>
380
+ <span class="font-semibold">DevPulse</span>
381
+ <span class="text-text-muted text-sm">© 2026</span>
731
382
</div>
732
- <div>
733
- Licensed under MIT. Open-source developer productivity platform.
383
+ <div class="flex items-center gap-6">
384
+ <a href="https://github.com/husteno-o/git-discord-bot" target="_blank" rel="noopener noreferrer" class="text-text-secondary hover:text-text-primary transition-colors">
385
+ <i data-lucide="github" class="w-5 h-5"></i>
386
+ </a>
387
+ <a href="#" class="text-sm text-text-secondary hover:text-text-primary transition-colors">MIT License</a>
734
388
</div>
735
389
</div>
736
390
</div>
737
391
</footer>
738
392
393
+ <!-- Scripts -->
739
394
<script type="module" src="./app.js"></script>
740
395
</body>
741
396
</html>
742
397
▼apps/web/src/styles.css
+124-1577
1
-/* ==============================================================================
2
- DevPulse — Premium GitHub Discord Bot Landing Page
3
- Dark theme with smooth animations and micro-interactions
4
- ============================================================================== */
1
+/* DevPulse Landing Page - Custom Animations & Utilities */
2
+/* Tailwind v4 handles base styles, this adds custom animations */
5
3
6
-:root {
7
- --bg-canvas: #090d16;
8
- --bg-canvas-subtle: #0d1117;
9
- --bg-surface: #161b22;
10
- --bg-surface-hover: #1c2128;
11
- --bg-surface-active: #21262d;
12
- --border-default: #30363d;
13
- --border-muted: #21262d;
14
- --border-glow: rgba(56, 139, 253, 0.4);
15
-
16
- --text-primary: #f0f6fc;
17
- --text-secondary: #8b949e;
18
- --text-muted: #6e7681;
19
-
20
- --gh-green: #2ea043;
21
- --gh-green-hover: #3fb950;
22
- --gh-green-subtle: rgba(46, 160, 67, 0.15);
23
- --gh-green-border: rgba(46, 160, 67, 0.4);
24
-
25
- --gh-blue: #58a6ff;
26
- --gh-blue-subtle: rgba(88, 166, 255, 0.15);
27
- --gh-blue-border: rgba(88, 166, 255, 0.4);
28
-
29
- --gh-purple: #a371f7;
30
- --gh-purple-subtle: rgba(163, 113, 247, 0.15);
31
- --gh-purple-border: rgba(163, 113, 247, 0.4);
32
-
33
- --gh-coral: #f85149;
34
- --gh-coral-subtle: rgba(248, 81, 73, 0.15);
35
- --gh-amber: #d29922;
36
-
37
- --discord-blurple: #5865f2;
38
- --discord-blurple-hover: #4752c4;
39
- --discord-embed-bg: #2b2d31;
40
- --discord-dark: #1e1f22;
41
-
42
- --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", Helvetica, Arial,
43
- sans-serif;
44
- --font-mono: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
45
-
46
- --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.5);
47
- --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.6);
48
- --shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.8);
49
- --shadow-glow-green: 0 0 30px rgba(46, 160, 67, 0.25);
50
- --shadow-glow-blue: 0 0 30px rgba(88, 166, 255, 0.2);
51
- --shadow-glow-purple: 0 0 30px rgba(163, 113, 247, 0.2);
52
-
53
- --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
54
- --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
4
+/* Hide scrollbar for tabs */
5
+.scrollbar-hide {
6
+ -ms-overflow-style: none;
7
+ scrollbar-width: none;
55
8
}
56
-
57
-* {
58
- box-sizing: border-box;
59
- margin: 0;
60
- padding: 0;
9
+.scrollbar-hide::-webkit-scrollbar {
10
+ display: none;
61
11
}
62
12
63
-html {
64
- scroll-behavior: smooth;
65
- color-scheme: dark;
13
+/* Custom scrollbar for main page */
14
+::-webkit-scrollbar {
15
+ width: 8px;
16
+ height: 8px;
66
17
}
67
-
68
-body {
69
- font-family: var(--font-sans);
70
- background-color: var(--bg-canvas);
71
- color: var(--text-primary);
72
- line-height: 1.6;
73
- overflow-x: hidden;
74
- position: relative;
75
- -webkit-font-smoothing: antialiased;
76
- -moz-osx-font-smoothing: grayscale;
18
+::-webkit-scrollbar-track {
19
+ background: #090d16;
77
20
}
78
-
79
-/* ==============================================================================
80
- Background Effects
81
- ============================================================================== */
82
-
83
-.bg-grid {
84
- position: fixed;
85
- top: 0;
86
- left: 0;
87
- right: 0;
88
- bottom: 0;
89
- background-image: linear-gradient(to right, rgba(48, 54, 61, 0.06) 1px, transparent 1px),
90
- linear-gradient(to bottom, rgba(48, 54, 61, 0.06) 1px, transparent 1px);
91
- background-size: 48px 48px;
92
- pointer-events: none;
93
- z-index: -2;
94
- mask-image: radial-gradient(ellipse at center, black 30%, transparent 80%);
95
- -webkit-mask-image: radial-gradient(ellipse at center, black 30%, transparent 80%);
21
+::-webkit-scrollbar-thumb {
22
+ background: #30363d;
23
+ border-radius: 4px;
96
24
}
97
-
98
-.ambient-glow-1 {
99
- position: fixed;
100
- top: -150px;
101
- left: 15%;
102
- width: 700px;
103
- height: 700px;
104
- border-radius: 50%;
105
- background: radial-gradient(circle, rgba(46, 160, 67, 0.1) 0%, rgba(13, 17, 23, 0) 70%);
106
- filter: blur(100px);
107
- pointer-events: none;
108
- z-index: -1;
109
- animation: floatGlow 20s var(--ease-in-out) infinite alternate;
25
+::-webkit-scrollbar-thumb:hover {
26
+ background: #6e7681;
110
27
}
111
28
112
-.ambient-glow-2 {
113
- position: fixed;
114
- top: 500px;
115
- right: 10%;
116
- width: 600px;
117
- height: 600px;
118
- border-radius: 50%;
119
- background: radial-gradient(circle, rgba(88, 166, 255, 0.08) 0%, rgba(13, 17, 23, 0) 70%);
120
- filter: blur(100px);
121
- pointer-events: none;
122
- z-index: -1;
123
- animation: floatGlow 25s var(--ease-in-out) infinite alternate-reverse;
29
+/* Selection */
30
+::selection {
31
+ background: rgba(88, 166, 255, 0.3);
32
+ color: #ffffff;
124
33
}
125
34
126
-.ambient-glow-3 {
127
- position: fixed;
128
- bottom: -100px;
129
- left: 50%;
130
- width: 500px;
131
- height: 500px;
132
- border-radius: 50%;
133
- background: radial-gradient(circle, rgba(163, 113, 247, 0.06) 0%, rgba(13, 17, 23, 0) 70%);
134
- filter: blur(100px);
135
- pointer-events: none;
136
- z-index: -1;
137
- animation: floatGlow 22s var(--ease-in-out) infinite alternate;
35
+/* Focus visible */
36
+:focus-visible {
37
+ outline: 2px solid #58a6ff;
38
+ outline-offset: 2px;
39
+ border-radius: 4px;
138
40
}
139
41
140
-/* ==============================================================================
141
- Keyframe Animations
142
- ============================================================================== */
143
-
144
-@keyframes floatGlow {
145
- 0% {
146
- transform: translate(0, 0) scale(1);
147
- opacity: 0.8;
148
- }
149
- 33% {
150
- transform: translate(30px, -20px) scale(1.05);
151
- opacity: 1;
152
- }
153
- 66% {
154
- transform: translate(-20px, 30px) scale(0.95);
155
- opacity: 0.9;
156
- }
157
- 100% {
158
- transform: translate(10px, -10px) scale(1.02);
159
- opacity: 0.8;
42
+/* Reduced motion */
43
+@media (prefers-reduced-motion: reduce) {
44
+ *,
45
+ *::before,
46
+ *::after {
47
+ animation-duration: 0.01ms !important;
48
+ animation-iteration-count: 1 !important;
49
+ transition-duration: 0.01ms !important;
160
50
}
161
51
}
162
52
163
-@keyframes pulseDot {
164
- 0% {
165
- transform: scale(0.95);
166
- opacity: 0.7;
167
- box-shadow: 0 0 6px var(--gh-green);
168
- }
169
- 50% {
170
- transform: scale(1.3);
171
- opacity: 1;
172
- box-shadow: 0 0 14px var(--gh-green);
173
- }
174
- 100% {
175
- transform: scale(0.95);
176
- opacity: 0.7;
177
- box-shadow: 0 0 6px var(--gh-green);
178
- }
53
+/* Simulator tab active state */
54
+.sim-tab-btn.active {
55
+ background: #21262d;
56
+ color: #58a6ff;
57
+ border-color: #30363d;
179
58
}
180
59
181
-@keyframes shimmer {
182
- 0% {
183
- background-position: -200% center;
184
- }
185
- 100% {
186
- background-position: 200% center;
187
- }
60
+/* Simulator content animation */
61
+#simulator-body > div {
62
+ animation: fadeIn 0.3s ease-out forwards;
188
63
}
189
64
190
-@keyframes fadeInUp {
191
- 0% {
65
+@keyframes fadeIn {
66
+ from {
192
67
opacity: 0;
193
- transform: translateY(30px);
68
+ transform: translateY(8px);
194
69
}
195
- 100% {
70
+ to {
196
71
opacity: 1;
197
72
transform: translateY(0);
198
73
}
199
74
}
200
75
201
-@keyframes fadeIn {
202
- 0% {
203
- opacity: 0;
204
- }
205
- 100% {
206
- opacity: 1;
207
- }
76
+/* Discord embed hover */
77
+.discord-embed {
78
+ transition: box-shadow 0.2s ease, border-color 0.2s ease;
79
+}
80
+.discord-embed:hover {
81
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
208
82
}
209
83
210
-@keyframes slideIn {
211
- 0% {
212
- opacity: 0;
213
- transform: translateX(20px);
214
- }
215
- 100% {
216
- opacity: 1;
217
- transform: translateX(0);
218
- }
84
+/* Command card hover animation */
85
+.command-card {
86
+ transition: all 0.25s cubic-bezier(0.16, 1, 0.3, 1);
87
+}
88
+.command-card:hover {
89
+ transform: translateY(-2px);
90
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2);
219
91
}
220
92
221
-@keyframes slideUp {
93
+/* Gradient text shimmer */
94
+@keyframes shimmer {
222
95
0% {
223
- opacity: 0;
224
- transform: translateY(12px);
96
+ background-position: -200% center;
225
97
}
226
98
100% {
227
- opacity: 1;
228
- transform: translateY(0);
99
+ background-position: 200% center;
229
100
}
230
101
}
231
102
232
-@keyframes typing {
233
- 0% {
234
- opacity: 0;
235
- transform: translateX(-4px);
236
- }
237
- 50% {
238
- opacity: 1;
239
- }
103
+/* Pulse dot animation */
104
+@keyframes pulse-dot {
105
+ 0%,
240
106
100% {
241
107
opacity: 1;
242
- transform: translateX(0);
243
- }
244
-}
245
-
246
-@keyframes breathe {
247
- 0%, 100% {
248
- opacity: 0.6;
249
108
transform: scale(1);
250
109
}
251
110
50% {
252
- opacity: 1;
253
- transform: scale(1.02);
111
+ opacity: 0.5;
112
+ transform: scale(1.2);
254
113
}
255
114
}
256
115
257
-@keyframes borderGlow {
258
- 0%, 100% {
259
- border-color: var(--border-default);
116
+/* Float animation */
117
+@keyframes float {
118
+ 0%,
119
+ 100% {
120
+ transform: translateY(0);
260
121
}
261
122
50% {
262
- border-color: var(--border-glow);
123
+ transform: translateY(-10px);
263
124
}
264
125
}
265
126
266
-@keyframes scaleIn {
267
- 0% {
268
- opacity: 0;
269
- transform: scale(0.92);
270
- }
127
+/* Typing cursor */
128
+@keyframes blink {
129
+ 0%,
271
130
100% {
272
131
opacity: 1;
273
- transform: scale(1);
132
+ }
133
+ 50% {
134
+ opacity: 0;
274
135
}
275
136
}
276
137
277
-/* Scroll reveal utility */
278
-.reveal {
279
- opacity: 0;
280
- transform: translateY(30px);
281
- transition: opacity 0.7s var(--ease-out-expo), transform 0.7s var(--ease-out-expo);
282
-}
283
-
284
-.reveal.visible {
285
- opacity: 1;
286
- transform: translateY(0);
287
-}
288
-
289
-.reveal-delay-1 { transition-delay: 0.1s; }
290
-.reveal-delay-2 { transition-delay: 0.2s; }
291
-.reveal-delay-3 { transition-delay: 0.3s; }
292
-.reveal-delay-4 { transition-delay: 0.4s; }
293
-.reveal-delay-5 { transition-delay: 0.5s; }
294
-
295
-/* ==============================================================================
296
- Container & Layout
297
- ============================================================================== */
298
-
299
-.container {
300
- max-width: 1200px;
301
- margin: 0 auto;
302
- padding: 0 24px;
303
-}
304
-
305
-/* ==============================================================================
306
- Navigation
307
- ============================================================================== */
308
-
309
-.navbar {
310
- position: sticky;
311
- top: 0;
312
- z-index: 100;
313
- background-color: rgba(13, 17, 23, 0.8);
314
- backdrop-filter: blur(16px);
315
- -webkit-backdrop-filter: blur(16px);
316
- border-bottom: 1px solid transparent;
317
- transition: border-color 0.3s ease, background-color 0.3s ease;
318
-}
319
-
320
-.navbar.scrolled {
321
- border-bottom-color: var(--border-muted);
322
- background-color: rgba(13, 17, 23, 0.92);
323
-}
324
-
325
-.nav-container {
326
- display: flex;
327
- align-items: center;
328
- justify-content: space-between;
329
- height: 68px;
330
-}
331
-
332
-.brand-logo {
333
- display: flex;
334
- align-items: center;
335
- gap: 12px;
336
- text-decoration: none;
337
- color: var(--text-primary);
338
- font-weight: 700;
339
- font-size: 1.2rem;
340
- letter-spacing: -0.5px;
341
- transition: opacity 0.2s ease;
342
-}
343
-
344
-.brand-logo:hover {
345
- opacity: 0.85;
346
-}
347
-
348
-.brand-icon-wrapper {
349
- position: relative;
350
- display: flex;
351
- align-items: center;
352
- justify-content: center;
353
- width: 36px;
354
- height: 36px;
355
- background: linear-gradient(135deg, #238636 0%, #1f6feb 100%);
356
- border-radius: 10px;
357
- box-shadow: 0 0 20px rgba(46, 160, 67, 0.3);
358
- transition: box-shadow 0.3s ease, transform 0.3s var(--ease-out-expo);
359
-}
360
-
361
-.brand-icon-wrapper:hover {
362
- box-shadow: 0 0 28px rgba(46, 160, 67, 0.5);
363
- transform: scale(1.05);
364
-}
365
-
366
-.brand-icon-wrapper svg {
367
- width: 20px;
368
- height: 20px;
369
- fill: #ffffff;
370
-}
371
-
372
-.brand-text {
373
- font-weight: 700;
374
-}
375
-
376
-.brand-tag {
377
- font-size: 0.65rem;
378
- text-transform: uppercase;
379
- font-weight: 600;
380
- padding: 2px 6px;
381
- border-radius: 4px;
382
- background: var(--gh-green-subtle);
383
- color: var(--gh-green-hover);
384
- border: 1px solid var(--gh-green-border);
385
- margin-left: 2px;
386
- letter-spacing: 0.5px;
387
-}
388
-
389
-.nav-links {
390
- display: flex;
391
- align-items: center;
392
- gap: 28px;
393
- list-style: none;
394
-}
395
-
396
-.nav-links a {
397
- color: var(--text-secondary);
398
- text-decoration: none;
399
- font-size: 0.88rem;
400
- font-weight: 500;
401
- transition: color 0.2s ease;
402
- position: relative;
403
-}
404
-
405
-.nav-links a::after {
406
- content: "";
407
- position: absolute;
408
- bottom: -4px;
409
- left: 0;
410
- width: 0;
411
- height: 1.5px;
412
- background: var(--gh-blue);
413
- transition: width 0.25s var(--ease-out-expo);
414
-}
415
-
416
-.nav-links a:hover {
417
- color: var(--text-primary);
418
-}
419
-
420
-.nav-links a:hover::after {
421
- width: 100%;
422
-}
423
-
424
-.nav-actions {
425
- display: flex;
426
- align-items: center;
427
- gap: 12px;
428
-}
429
-
430
-/* Buttons */
431
-.btn {
432
- display: inline-flex;
433
- align-items: center;
434
- justify-content: center;
435
- gap: 8px;
436
- padding: 8px 16px;
437
- border-radius: 8px;
438
- font-size: 0.88rem;
439
- font-weight: 600;
440
- text-decoration: none;
441
- cursor: pointer;
442
- transition: all 0.25s var(--ease-out-expo);
443
- border: 1px solid transparent;
444
- font-family: inherit;
445
- white-space: nowrap;
446
- position: relative;
447
- overflow: hidden;
448
-}
449
-
450
-.btn::after {
451
- content: "";
452
- position: absolute;
453
- inset: 0;
454
- background: linear-gradient(135deg, rgba(255,255,255,0.1) 0%, transparent 50%);
455
- opacity: 0;
456
- transition: opacity 0.3s ease;
457
-}
458
-
459
-.btn:hover::after {
460
- opacity: 1;
461
-}
462
-
463
-.btn-sm {
464
- padding: 6px 12px;
465
- font-size: 0.82rem;
466
-}
467
-
468
-.btn-lg {
469
- padding: 14px 28px;
470
- font-size: 1rem;
471
-}
472
-
473
-.btn-primary {
474
- background-color: var(--gh-green);
475
- color: #ffffff;
476
- border-color: rgba(240, 246, 252, 0.1);
477
- box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.12);
478
-}
479
-
480
-.btn-primary:hover {
481
- background-color: var(--gh-green-hover);
482
- box-shadow: var(--shadow-glow-green);
483
- transform: translateY(-2px);
484
-}
485
-
486
-.btn-secondary {
487
- background-color: var(--bg-surface);
488
- color: var(--text-primary);
489
- border-color: var(--border-default);
490
-}
491
-
492
-.btn-secondary:hover {
493
- background-color: var(--bg-surface-hover);
494
- border-color: var(--text-secondary);
495
- transform: translateY(-2px);
496
-}
497
-
498
-.btn-discord {
499
- background-color: var(--discord-blurple);
500
- color: #ffffff;
501
-}
502
-
503
-.btn-discord:hover {
504
- background-color: var(--discord-blurple-hover);
505
- box-shadow: 0 0 24px rgba(88, 101, 242, 0.4);
506
- transform: translateY(-2px);
507
-}
508
-
509
-.btn-github {
510
- background-color: #21262d;
511
- color: var(--text-primary);
512
- border-color: var(--border-default);
513
-}
514
-
515
-.btn-github:hover {
516
- background-color: #30363d;
517
- border-color: #8b949e;
518
- transform: translateY(-2px);
519
-}
520
-
521
-/* Mobile Toggle */
522
-.mobile-toggle {
523
- display: none;
524
- background: none;
525
- border: none;
526
- color: var(--text-primary);
527
- cursor: pointer;
528
- padding: 4px;
529
-}
530
-
531
-/* ==============================================================================
532
- Hero Section
533
- ============================================================================== */
534
-
535
-.hero-section {
536
- padding: 100px 0 70px;
537
- text-align: center;
538
- position: relative;
539
-}
540
-
541
-.hero-pill {
542
- display: inline-flex;
543
- align-items: center;
544
- gap: 8px;
545
- padding: 6px 16px;
546
- background: rgba(33, 38, 45, 0.7);
547
- border: 1px solid var(--border-default);
548
- border-radius: 9999px;
549
- font-size: 0.82rem;
550
- font-weight: 500;
551
- color: var(--text-secondary);
552
- margin-bottom: 28px;
553
- backdrop-filter: blur(12px);
554
- animation: fadeInUp 0.6s var(--ease-out-expo) both;
555
-}
556
-
557
-.pill-dot {
558
- width: 8px;
559
- height: 8px;
560
- border-radius: 50%;
561
- background-color: var(--gh-green);
562
- animation: pulseDot 2.5s ease-in-out infinite;
563
-}
564
-
565
-.hero-title {
566
- font-size: clamp(2.8rem, 6.5vw, 4.5rem);
567
- font-weight: 800;
568
- line-height: 1.1;
569
- letter-spacing: -2px;
570
- margin-bottom: 28px;
571
- max-width: 900px;
572
- margin-left: auto;
573
- margin-right: auto;
574
- animation: fadeInUp 0.7s var(--ease-out-expo) 0.1s both;
575
-}
576
-
577
-.hero-title-gradient {
578
- background: linear-gradient(135deg, #ffffff 0%, #58a6ff 40%, #a371f7 70%, #58a6ff 100%);
579
- background-size: 200% auto;
580
- -webkit-background-clip: text;
581
- -webkit-text-fill-color: transparent;
582
- background-clip: text;
583
- animation: shimmer 4s linear infinite;
584
-}
585
-
586
-.hero-subtitle {
587
- font-size: clamp(1rem, 2vw, 1.2rem);
588
- color: var(--text-secondary);
589
- max-width: 680px;
590
- margin: 0 auto 40px;
591
- font-weight: 400;
592
- line-height: 1.7;
593
- animation: fadeInUp 0.7s var(--ease-out-expo) 0.2s both;
594
-}
595
-
596
-.hero-actions {
597
- display: flex;
598
- align-items: center;
599
- justify-content: center;
600
- gap: 16px;
601
- flex-wrap: wrap;
602
- margin-bottom: 36px;
603
- animation: fadeInUp 0.7s var(--ease-out-expo) 0.3s both;
604
-}
605
-
606
-.clone-pill {
607
- display: inline-flex;
608
- align-items: center;
609
- background: var(--bg-surface);
610
- border: 1px solid var(--border-default);
611
- border-radius: 8px;
612
- padding: 8px 14px;
613
- font-family: var(--font-mono);
614
- font-size: 0.82rem;
615
- color: var(--gh-blue);
616
- cursor: pointer;
617
- transition: all 0.25s var(--ease-out-expo);
618
-}
619
-
620
-.clone-pill:hover {
621
- border-color: var(--gh-blue);
622
- background: var(--bg-surface-hover);
623
- box-shadow: 0 0 16px rgba(88, 166, 255, 0.15);
624
- transform: translateY(-1px);
625
-}
626
-
627
-.clone-pill svg {
628
- margin-right: 8px;
629
- fill: var(--text-secondary);
630
-}
631
-
632
-.clone-btn-icon {
633
- margin-left: 10px;
634
- color: var(--text-muted);
635
-}
636
-
637
-/* Feature highlights banner */
638
-.hero-badges {
639
- display: flex;
640
- align-items: center;
641
- justify-content: center;
642
- gap: 28px;
643
- flex-wrap: wrap;
644
- padding-top: 16px;
645
- animation: fadeInUp 0.7s var(--ease-out-expo) 0.4s both;
646
-}
647
-
648
-.hero-badge-item {
649
- display: flex;
650
- align-items: center;
651
- gap: 6px;
652
- font-size: 0.82rem;
653
- color: var(--text-muted);
654
- transition: color 0.2s ease;
655
-}
656
-
657
-.hero-badge-item:hover {
658
- color: var(--text-secondary);
659
-}
660
-
661
-.hero-badge-item svg {
662
- width: 14px;
663
- height: 14px;
664
- fill: var(--gh-green);
665
-}
666
-
667
-/* ==============================================================================
668
- Interactive Simulator Section
669
- ============================================================================== */
670
-
671
-.simulator-section {
672
- padding: 50px 0 90px;
673
-}
674
-
675
-.simulator-wrapper {
676
- background: var(--bg-surface);
677
- border: 1px solid var(--border-default);
678
- border-radius: 16px;
679
- box-shadow: var(--shadow-lg), 0 0 60px rgba(0, 0, 0, 0.3);
680
- overflow: hidden;
681
- max-width: 1050px;
682
- margin: 0 auto;
683
- transition: border-color 0.3s ease;
684
-}
685
-
686
-.simulator-wrapper:hover {
687
- border-color: rgba(56, 139, 253, 0.2);
688
-}
689
-
690
-.simulator-header {
691
- display: flex;
692
- align-items: center;
693
- justify-content: space-between;
694
- padding: 14px 20px;
695
- background: var(--bg-canvas-subtle);
696
- border-bottom: 1px solid var(--border-default);
697
-}
698
-
699
-.window-dots {
700
- display: flex;
701
- gap: 8px;
702
-}
703
-
704
-.window-dot {
705
- width: 12px;
706
- height: 12px;
707
- border-radius: 50%;
708
- transition: opacity 0.2s ease;
709
-}
710
-
711
-.window-dots:hover .window-dot {
712
- opacity: 0.7;
713
-}
714
-
715
-.dot-red { background-color: #ff5f56; }
716
-.dot-yellow { background-color: #ffbd2e; }
717
-.dot-green { background-color: #27c93f; }
718
-
719
-.simulator-title {
720
- font-size: 0.82rem;
721
- font-family: var(--font-mono);
722
- color: var(--text-secondary);
723
- display: flex;
724
- align-items: center;
725
- gap: 8px;
726
-}
727
-
728
-.simulator-telemetry {
729
- display: flex;
730
- align-items: center;
731
-}
732
-
733
-.telemetry-pill {
734
- font-family: var(--font-mono);
735
- font-size: 0.7rem;
736
- color: var(--gh-green-hover);
737
- background: var(--gh-green-subtle);
738
- border: 1px solid var(--gh-green-border);
739
- padding: 3px 10px;
740
- border-radius: 9999px;
741
- letter-spacing: 0.3px;
742
- animation: breathe 3s ease-in-out infinite;
743
-}
744
-
745
-.simulator-tabs {
746
- display: flex;
747
- gap: 2px;
748
- padding: 8px 16px;
749
- background: var(--bg-surface);
750
- border-bottom: 1px solid var(--border-muted);
751
- overflow-x: auto;
752
- scrollbar-width: thin;
753
-}
754
-
755
-.sim-tab-btn {
756
- background: transparent;
757
- border: 1px solid transparent;
758
- color: var(--text-secondary);
759
- padding: 8px 14px;
760
- border-radius: 8px;
761
- font-family: var(--font-mono);
762
- font-size: 0.8rem;
763
- cursor: pointer;
764
- white-space: nowrap;
765
- transition: all 0.2s var(--ease-out-expo);
766
- display: flex;
767
- align-items: center;
768
- gap: 8px;
769
- position: relative;
770
-}
771
-
772
-.sim-tab-btn::after {
773
- content: "";
774
- position: absolute;
775
- bottom: -1px;
776
- left: 50%;
777
- transform: translateX(-50%);
778
- width: 0;
779
- height: 2px;
780
- background: var(--gh-blue);
781
- border-radius: 1px;
782
- transition: width 0.25s var(--ease-out-expo);
783
-}
784
-
785
-.sim-tab-btn svg {
786
- flex-shrink: 0;
787
- transition: transform 0.2s ease;
788
-}
789
-
790
-.sim-tab-btn:hover {
791
- background: var(--bg-surface-hover);
792
- color: var(--text-primary);
793
-}
794
-
795
-.sim-tab-btn:hover svg {
796
- transform: scale(1.1);
797
-}
798
-
799
-.sim-tab-btn.active {
800
- background: var(--bg-surface-active);
801
- color: var(--gh-blue);
802
- border-color: var(--border-default);
803
- font-weight: 600;
804
-}
805
-
806
-.sim-tab-btn.active::after {
807
- width: 60%;
808
-}
809
-
810
-.simulator-body {
811
- padding: 28px;
812
- min-height: 460px;
813
- background: var(--discord-dark);
814
- position: relative;
815
-}
816
-
817
-/* Tab content animation */
818
-.simulator-body > div {
819
- animation: slideIn 0.35s var(--ease-out-expo) both;
820
-}
821
-
822
-/* Discord Simulated Message */
823
-.discord-message {
824
- display: flex;
825
- gap: 16px;
826
- font-size: 0.95rem;
827
-}
828
-
829
-.discord-avatar {
830
- width: 42px;
831
- height: 42px;
832
- border-radius: 50%;
833
- background: linear-gradient(135deg, #238636 0%, #1f6feb 100%);
834
- display: flex;
835
- align-items: center;
836
- justify-content: center;
837
- flex-shrink: 0;
838
- box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
839
- transition: transform 0.3s var(--ease-out-expo);
840
-}
841
-
842
-.discord-avatar:hover {
843
- transform: scale(1.1) rotate(5deg);
844
-}
845
-
846
-.discord-avatar svg {
847
- width: 24px;
848
- height: 24px;
849
- fill: #ffffff;
850
-}
851
-
852
-.discord-content {
853
- flex-grow: 1;
854
- min-width: 0;
855
-}
856
-
857
-.discord-header {
858
- display: flex;
859
- align-items: center;
860
- gap: 8px;
861
- margin-bottom: 6px;
862
-}
863
-
864
-.bot-name {
865
- font-weight: 600;
866
- color: var(--text-primary);
867
-}
868
-
869
-.bot-tag {
870
- background: var(--discord-blurple);
871
- color: #ffffff;
872
- font-size: 0.62rem;
873
- font-weight: 700;
874
- padding: 1px 5px;
875
- border-radius: 3px;
876
- text-transform: uppercase;
877
- letter-spacing: 0.3px;
878
-}
879
-
880
-.message-time {
881
- font-size: 0.72rem;
882
- color: var(--text-muted);
883
-}
884
-
885
-.command-echo {
886
- font-family: var(--font-mono);
887
- font-size: 0.78rem;
888
- color: var(--gh-blue);
889
- margin-bottom: 10px;
890
- opacity: 0;
891
- animation: typing 0.4s ease-out 0.15s forwards;
892
-}
893
-
894
-/* Discord Embed */
895
-.discord-embed {
896
- background: var(--discord-embed-bg);
897
- border-left: 4px solid var(--gh-green);
898
- border-radius: 4px 8px 8px 4px;
899
- padding: 18px;
900
- max-width: 650px;
901
- box-shadow: var(--shadow-sm);
902
- transition: border-color 0.3s ease, box-shadow 0.3s ease;
903
-}
904
-
905
-.discord-embed:hover {
906
- box-shadow: var(--shadow-md);
907
-}
908
-
909
-.embed-author {
910
- display: flex;
911
- align-items: center;
912
- gap: 8px;
913
- font-size: 0.78rem;
914
- font-weight: 600;
915
- color: var(--text-secondary);
916
- margin-bottom: 8px;
917
-}
918
-
919
-.embed-title {
920
- font-size: 1.05rem;
921
- font-weight: 700;
922
- color: var(--text-primary);
923
- margin-bottom: 10px;
924
- display: flex;
925
- align-items: center;
926
- gap: 8px;
927
-}
928
-
929
-.embed-desc {
930
- font-size: 0.86rem;
931
- color: var(--text-secondary);
932
- margin-bottom: 16px;
933
- white-space: pre-line;
934
- line-height: 1.6;
935
-}
936
-
937
-.embed-grid {
938
- display: grid;
939
- grid-template-columns: repeat(2, 1fr);
940
- gap: 14px;
941
- margin-bottom: 16px;
942
-}
943
-
944
-.embed-field-name {
945
- font-size: 0.72rem;
946
- text-transform: uppercase;
947
- letter-spacing: 0.5px;
948
- color: var(--text-muted);
949
- font-weight: 700;
950
- margin-bottom: 3px;
951
-}
952
-
953
-.embed-field-value {
954
- font-size: 0.88rem;
955
- color: var(--text-primary);
956
- font-family: var(--font-mono);
957
-}
958
-
959
-.embed-code-block {
960
- background: #111214;
961
- border-radius: 6px;
962
- padding: 12px 14px;
963
- font-family: var(--font-mono);
964
- font-size: 0.8rem;
965
- color: #dbdee1;
966
- overflow-x: auto;
967
- margin: 12px 0;
968
- border: 1px solid rgba(255, 255, 255, 0.04);
969
- line-height: 1.5;
970
-}
971
-
972
-.discord-action-row {
973
- display: flex;
974
- gap: 8px;
975
- margin-top: 16px;
976
- flex-wrap: wrap;
977
-}
978
-
979
-.discord-btn {
980
- display: inline-flex;
981
- align-items: center;
982
- gap: 6px;
983
- background: #4e5058;
984
- color: #ffffff;
985
- border: none;
986
- padding: 7px 14px;
987
- border-radius: 6px;
988
- font-size: 0.8rem;
989
- font-weight: 600;
990
- cursor: pointer;
991
- transition: all 0.2s var(--ease-out-expo);
992
- font-family: inherit;
993
-}
994
-
995
-.discord-btn:hover {
996
- background: #6d6f78;
997
- transform: translateY(-1px);
998
-}
999
-
1000
-.discord-btn:active {
1001
- transform: translateY(0);
1002
-}
1003
-
1004
-.discord-btn-primary {
1005
- background: var(--discord-blurple);
1006
-}
1007
-.discord-btn-primary:hover {
1008
- background: var(--discord-blurple-hover);
1009
- box-shadow: 0 0 12px rgba(88, 101, 242, 0.3);
1010
-}
1011
-
1012
-.discord-btn-success {
1013
- background: var(--gh-green);
1014
-}
1015
-.discord-btn-success:hover {
1016
- background: var(--gh-green-hover);
1017
- box-shadow: 0 0 12px rgba(46, 160, 67, 0.3);
1018
-}
1019
-
1020
-.discord-btn-danger {
1021
- background: #da373c;
1022
-}
1023
-.discord-btn-danger:hover {
1024
- background: #a1282c;
1025
-}
1026
-
1027
-.discord-btn-disabled {
1028
- opacity: 0.4;
1029
- cursor: not-allowed;
1030
-}
1031
-.discord-btn-disabled:hover {
1032
- transform: none;
1033
- box-shadow: none;
1034
-}
1035
-
1036
-/* Status Badges inside simulator */
1037
-.status-tag {
1038
- display: inline-flex;
1039
- align-items: center;
1040
- gap: 4px;
1041
- padding: 3px 10px;
1042
- border-radius: 12px;
1043
- font-size: 0.72rem;
1044
- font-weight: 600;
1045
- transition: all 0.2s ease;
1046
-}
1047
-
1048
-.status-tag-green {
1049
- background: var(--gh-green-subtle);
1050
- color: var(--gh-green-hover);
1051
- border: 1px solid var(--gh-green-border);
1052
-}
1053
-
1054
-.status-tag-blue {
1055
- background: var(--gh-blue-subtle);
1056
- color: var(--gh-blue);
1057
- border: 1px solid var(--gh-blue-border);
1058
-}
1059
-
1060
-.status-tag-purple {
1061
- background: var(--gh-purple-subtle);
1062
- color: var(--gh-purple);
1063
- border: 1px solid var(--gh-purple-border);
1064
-}
1065
-
1066
-/* ==============================================================================
1067
- Features Section — 21 Commands
1068
- ============================================================================== */
1069
-
1070
-.features-section {
1071
- padding: 90px 0;
1072
- position: relative;
1073
-}
1074
-
1075
-.section-header {
1076
- text-align: center;
1077
- max-width: 700px;
1078
- margin: 0 auto 56px;
1079
-}
1080
-
1081
-.section-tag {
1082
- font-family: var(--font-mono);
1083
- font-size: 0.78rem;
1084
- color: var(--gh-green);
1085
- text-transform: uppercase;
1086
- letter-spacing: 1.5px;
1087
- font-weight: 600;
1088
- margin-bottom: 10px;
1089
-}
1090
-
1091
-.section-title {
1092
- font-size: clamp(2rem, 4vw, 2.75rem);
1093
- font-weight: 800;
1094
- letter-spacing: -1px;
1095
- margin-bottom: 16px;
1096
- line-height: 1.2;
1097
-}
1098
-
1099
-.section-desc {
1100
- color: var(--text-secondary);
1101
- font-size: 1.05rem;
1102
- line-height: 1.6;
1103
-}
1104
-
1105
-.features-grid {
1106
- display: grid;
1107
- grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
1108
- gap: 20px;
1109
-}
1110
-
1111
-.feature-card {
1112
- background: var(--bg-surface);
1113
- border: 1px solid var(--border-default);
1114
- border-radius: 12px;
1115
- padding: 26px;
1116
- transition: all 0.35s var(--ease-out-expo);
1117
- position: relative;
1118
- overflow: hidden;
1119
- display: flex;
1120
- flex-direction: column;
1121
-}
1122
-
1123
-.feature-card::before {
1124
- content: "";
1125
- position: absolute;
1126
- top: 0;
1127
- left: 0;
1128
- right: 0;
1129
- height: 2px;
1130
- background: linear-gradient(90deg, transparent, var(--gh-blue), var(--gh-purple), transparent);
1131
- opacity: 0;
1132
- transform: translateX(-100%);
1133
- transition: opacity 0.4s ease, transform 0.6s var(--ease-out-expo);
1134
-}
1135
-
1136
-.feature-card::after {
1137
- content: "";
1138
- position: absolute;
1139
- inset: 0;
1140
- background: radial-gradient(circle at var(--mouse-x, 50%) var(--mouse-y, 50%), rgba(88, 166, 255, 0.06) 0%, transparent 50%);
1141
- opacity: 0;
1142
- transition: opacity 0.3s ease;
1143
- pointer-events: none;
1144
-}
1145
-
1146
-.feature-card:hover {
1147
- border-color: rgba(88, 166, 255, 0.3);
1148
- transform: translateY(-6px);
1149
- box-shadow: var(--shadow-md), 0 0 40px rgba(88, 166, 255, 0.08);
1150
-}
1151
-
1152
-.feature-card:hover::before {
1153
- opacity: 1;
1154
- transform: translateX(0);
1155
-}
1156
-
1157
-.feature-card:hover::after {
1158
- opacity: 1;
1159
-}
1160
-
1161
-.feature-top {
1162
- display: flex;
1163
- align-items: center;
1164
- justify-content: space-between;
1165
- margin-bottom: 18px;
138
+/* Navbar scrolled state */
139
+.navbar-scrolled {
140
+ border-bottom-color: #21262d !important;
141
+ background-color: rgba(13, 17, 23, 0.92) !important;
1166
142
}
1167
143
1168
-.feature-icon-box {
1169
- width: 44px;
1170
- height: 44px;
1171
- border-radius: 10px;
1172
- background: var(--bg-surface-active);
1173
- border: 1px solid var(--border-muted);
1174
- display: flex;
1175
- align-items: center;
1176
- justify-content: center;
1177
- transition: all 0.3s var(--ease-out-expo);
144
+/* Mobile menu animation */
145
+#mobile-menu {
146
+ animation: slideDown 0.2s ease-out forwards;
1178
147
}
1179
148
1180
-.feature-card:hover .feature-icon-box {
1181
- border-color: var(--gh-blue-border);
1182
- box-shadow: 0 0 16px rgba(88, 166, 255, 0.15);
149
+@keyframes slideDown {
150
+ from {
151
+ opacity: 0;
152
+ transform: translateY(-10px);
153
+ }
154
+ to {
155
+ opacity: 1;
156
+ transform: translateY(0);
157
+ }
1183
158
}
1184
159
1185
-.feature-icon-box svg {
1186
- width: 22px;
1187
- height: 22px;
1188
- fill: var(--gh-blue);
1189
- transition: transform 0.3s var(--ease-out-expo);
160
+/* Feature card icon animation */
161
+.feature-icon-wrapper {
162
+ transition: transform 0.3s cubic-bezier(0.16, 1, 0.3, 1);
1190
163
}
1191
-
1192
-.feature-card:hover .feature-icon-box svg {
164
+.group:hover .feature-icon-wrapper {
1193
165
transform: scale(1.1);
1194
166
}
1195
167
1196
-.feature-command-badge {
1197
- font-family: var(--font-mono);
1198
- font-size: 0.75rem;
1199
- padding: 4px 10px;
1200
- background: var(--bg-canvas);
1201
- border: 1px solid var(--border-muted);
1202
- border-radius: 6px;
1203
- color: var(--gh-green);
1204
- font-weight: 600;
1205
- transition: all 0.25s ease;
1206
-}
1207
-
1208
-.feature-card:hover .feature-command-badge {
1209
- border-color: var(--gh-green-border);
1210
- background: var(--gh-green-subtle);
1211
-}
1212
-
1213
-.feature-name {
1214
- font-size: 1.15rem;
1215
- font-weight: 700;
1216
- margin-bottom: 10px;
1217
- color: var(--text-primary);
1218
- letter-spacing: -0.3px;
1219
-}
1220
-
1221
-.feature-text {
1222
- font-size: 0.88rem;
1223
- color: var(--text-secondary);
1224
- line-height: 1.6;
1225
- margin-bottom: 16px;
1226
- flex-grow: 1;
1227
-}
1228
-
1229
-.feature-bullets {
1230
- list-style: none;
1231
- font-size: 0.82rem;
1232
- color: var(--text-muted);
1233
- display: flex;
1234
- flex-direction: column;
1235
- gap: 7px;
1236
-}
1237
-
1238
-.feature-bullets li {
1239
- display: flex;
1240
- align-items: flex-start;
1241
- gap: 8px;
1242
- transition: color 0.2s ease;
1243
-}
1244
-
1245
-.feature-card:hover .feature-bullets li {
1246
- color: var(--text-secondary);
1247
-}
1248
-
1249
-.feature-bullets li svg {
1250
- width: 14px;
1251
- height: 14px;
1252
- fill: var(--gh-blue);
1253
- flex-shrink: 0;
1254
- margin-top: 2px;
1255
-}
1256
-
1257
-/* ==============================================================================
1258
- Killer Feature Highlights
1259
- ============================================================================== */
1260
-
1261
-.killer-section {
1262
- padding: 90px 0;
1263
- background: linear-gradient(180deg, var(--bg-canvas) 0%, var(--bg-canvas-subtle) 50%, var(--bg-canvas) 100%);
1264
- border-top: 1px solid var(--border-muted);
1265
- border-bottom: 1px solid var(--border-muted);
1266
- position: relative;
1267
-}
1268
-
1269
-.killer-section::before {
1270
- content: "";
1271
- position: absolute;
1272
- top: 0;
1273
- left: 0;
1274
- right: 0;
1275
- height: 1px;
1276
- background: linear-gradient(90deg, transparent, var(--gh-blue-border), var(--gh-purple-border), transparent);
1277
- opacity: 0.5;
1278
-}
1279
-
1280
-.killer-grid {
1281
- display: grid;
1282
- grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
1283
- gap: 20px;
1284
-}
1285
-
1286
-.killer-card {
1287
- background: var(--bg-surface);
1288
- border: 1px solid var(--border-default);
1289
- border-radius: 12px;
1290
- padding: 24px;
1291
- transition: all 0.35s var(--ease-out-expo);
1292
- position: relative;
1293
- overflow: hidden;
1294
-}
1295
-
1296
-.killer-card:hover {
1297
- border-color: var(--gh-purple-border);
1298
- transform: translateY(-4px);
1299
- box-shadow: var(--shadow-md), var(--shadow-glow-purple);
1300
-}
1301
-
1302
-.killer-card-title {
1303
- font-size: 1.05rem;
1304
- font-weight: 700;
1305
- margin-bottom: 10px;
1306
- display: flex;
1307
- align-items: center;
1308
- gap: 10px;
1309
- color: var(--text-primary);
1310
-}
1311
-
1312
-.killer-card-desc {
1313
- font-size: 0.86rem;
1314
- color: var(--text-secondary);
1315
- line-height: 1.6;
1316
-}
1317
-
1318
-/* ==============================================================================
1319
- Architecture & Security
1320
- ============================================================================== */
1321
-
1322
-.arch-section {
1323
- padding: 90px 0;
1324
-}
1325
-
1326
-.arch-box {
1327
- background: var(--bg-surface);
1328
- border: 1px solid var(--border-default);
1329
- border-radius: 16px;
1330
- padding: 40px;
1331
- margin-bottom: 40px;
1332
- transition: border-color 0.3s ease;
1333
-}
1334
-
1335
-.arch-box:hover {
1336
- border-color: rgba(56, 139, 253, 0.2);
1337
-}
1338
-
1339
-.arch-flow-grid {
1340
- display: grid;
1341
- grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
1342
- gap: 20px;
1343
- margin-top: 32px;
1344
-}
1345
-
1346
-.arch-flow-step {
1347
- background: var(--bg-canvas);
1348
- border: 1px solid var(--border-muted);
1349
- border-radius: 10px;
1350
- padding: 20px;
1351
- position: relative;
1352
- transition: all 0.3s var(--ease-out-expo);
1353
-}
1354
-
1355
-.arch-flow-step:hover {
1356
- border-color: var(--gh-blue-border);
1357
- transform: translateY(-3px);
1358
- box-shadow: var(--shadow-md);
1359
-}
1360
-
1361
-.step-num {
1362
- display: inline-block;
1363
- font-family: var(--font-mono);
1364
- font-size: 0.72rem;
1365
- background: var(--gh-blue-subtle);
1366
- color: var(--gh-blue);
1367
- border: 1px solid var(--gh-blue-border);
1368
- border-radius: 4px;
1369
- padding: 2px 8px;
1370
- margin-bottom: 10px;
1371
- letter-spacing: 0.5px;
1372
-}
1373
-
1374
-.step-title {
1375
- font-size: 0.95rem;
1376
- font-weight: 700;
1377
- margin-bottom: 6px;
1378
-}
1379
-
1380
-.step-desc {
1381
- font-size: 0.82rem;
1382
- color: var(--text-secondary);
1383
- line-height: 1.5;
1384
-}
1385
-
1386
-/* Quick Start Terminal Walkthrough */
1387
-.install-section {
1388
- padding: 70px 0 100px;
1389
-}
1390
-
1391
-.terminal-box {
1392
- background: #0d1117;
1393
- border: 1px solid var(--border-default);
1394
- border-radius: 12px;
1395
- overflow: hidden;
1396
- box-shadow: var(--shadow-md);
1397
- margin-top: 28px;
1398
- transition: border-color 0.3s ease;
1399
-}
1400
-
1401
-.terminal-box:hover {
1402
- border-color: rgba(56, 139, 253, 0.2);
1403
-}
1404
-
1405
-.terminal-topbar {
1406
- display: flex;
1407
- align-items: center;
1408
- justify-content: space-between;
1409
- padding: 12px 18px;
1410
- background: #161b22;
1411
- border-bottom: 1px solid var(--border-default);
1412
-}
1413
-
1414
-.terminal-content {
1415
- padding: 24px;
1416
- font-family: var(--font-mono);
1417
- font-size: 0.88rem;
1418
- line-height: 1.8;
1419
-}
1420
-
168
+/* Terminal line hover */
1421
169
.terminal-line {
1422
- display: flex;
1423
- align-items: center;
1424
- justify-content: space-between;
1425
- margin-bottom: 14px;
1426
- transition: background 0.2s ease;
170
+ transition: background 0.15s ease;
1427
171
padding: 2px 4px;
172
+ margin: -2px -4px;
1428
173
border-radius: 4px;
1429
- margin-left: -4px;
1430
- margin-right: -4px;
1431
174
}
1432
-
1433
175
.terminal-line:hover {
1434
- background: rgba(255, 255, 255, 0.02);
1435
-}
1436
-
1437
-.terminal-cmd {
1438
- color: var(--text-primary);
1439
-}
1440
-
1441
-.terminal-comment {
1442
- color: var(--text-muted);
1443
- font-style: italic;
1444
- font-size: 0.8rem;
1445
-}
1446
-
1447
-.terminal-copy-btn {
1448
- background: transparent;
1449
- border: none;
1450
- color: var(--text-muted);
1451
- cursor: pointer;
1452
- padding: 6px;
1453
- border-radius: 6px;
1454
- transition: all 0.2s ease;
1455
-}
1456
-
1457
-.terminal-copy-btn:hover {
1458
- color: var(--text-primary);
1459
- background: var(--bg-surface-active);
1460
-}
1461
-
1462
-/* ==============================================================================
1463
- Footer
1464
- ============================================================================== */
1465
-
1466
-.footer {
1467
- border-top: 1px solid var(--border-muted);
1468
- background: var(--bg-canvas-subtle);
1469
- padding: 64px 0 32px;
1470
- position: relative;
1471
-}
1472
-
1473
-.footer::before {
1474
- content: "";
1475
- position: absolute;
1476
- top: 0;
1477
- left: 0;
1478
- right: 0;
1479
- height: 1px;
1480
- background: linear-gradient(90deg, transparent, var(--border-glow), transparent);
1481
- opacity: 0.3;
1482
-}
1483
-
1484
-.footer-grid {
1485
- display: grid;
1486
- grid-template-columns: 2fr 1fr 1fr 1fr;
1487
- gap: 40px;
1488
- margin-bottom: 44px;
1489
-}
1490
-
1491
-.footer-col-desc {
1492
- color: var(--text-secondary);
1493
- font-size: 0.86rem;
1494
- margin-top: 14px;
1495
- max-width: 320px;
1496
- line-height: 1.6;
1497
-}
1498
-
1499
-.footer-col-title {
1500
- font-size: 0.82rem;
1501
- font-weight: 700;
1502
- text-transform: uppercase;
1503
- letter-spacing: 0.8px;
1504
- color: var(--text-primary);
1505
- margin-bottom: 18px;
176
+ background: rgba(255, 255, 255, 0.03);
1506
177
}
1507
178
1508
-.footer-col-links {
1509
- list-style: none;
1510
- display: flex;
1511
- flex-direction: column;
1512
- gap: 12px;
179
+/* Copy button feedback */
180
+.copy-success {
181
+ color: #3fb950 !important;
1513
182
}
1514
183
1515
-.footer-col-links a {
1516
- color: var(--text-secondary);
1517
- text-decoration: none;
1518
- font-size: 0.86rem;
1519
- transition: all 0.2s ease;
1520
- position: relative;
1521
- display: inline-block;
1522
-}
1523
-
1524
-.footer-col-links a:hover {
1525
- color: var(--gh-blue);
1526
- transform: translateX(3px);
1527
-}
1528
-
1529
-.footer-bottom {
1530
- padding-top: 28px;
1531
- border-top: 1px solid var(--border-muted);
1532
- display: flex;
1533
- align-items: center;
1534
- justify-content: space-between;
1535
- font-size: 0.8rem;
1536
- color: var(--text-muted);
1537
- flex-wrap: wrap;
1538
- gap: 14px;
1539
-}
1540
-
1541
-/* ==============================================================================
1542
- Responsive Design
1543
- ============================================================================== */
1544
-
1545
-@media (max-width: 900px) {
1546
- .nav-links {
1547
- display: none;
1548
- }
1549
- .mobile-toggle {
1550
- display: block;
1551
- }
1552
- .footer-grid {
1553
- grid-template-columns: 1fr 1fr;
1554
- }
1555
- .arch-box {
1556
- padding: 28px;
1557
- }
1558
-}
1559
-
1560
-@media (max-width: 640px) {
1561
- .hero-section {
1562
- padding: 70px 0 50px;
1563
- }
1564
- .features-grid {
1565
- grid-template-columns: 1fr;
1566
- }
1567
- .footer-grid {
1568
- grid-template-columns: 1fr;
1569
- gap: 28px;
1570
- }
1571
- .embed-grid {
1572
- grid-template-columns: 1fr;
1573
- }
1574
- .hero-badges {
1575
- gap: 16px;
1576
- }
1577
- .simulator-body {
1578
- padding: 18px;
1579
- }
1580
- .arch-box {
1581
- padding: 20px;
1582
- }
1583
- .killer-grid {
1584
- grid-template-columns: 1fr;
1585
- }
1586
-}
1587
-
1588
-@media (max-width: 480px) {
1589
- .hero-title {
1590
- letter-spacing: -1px;
1591
- }
1592
- .hero-actions {
1593
- flex-direction: column;
1594
- width: 100%;
1595
- padding: 0 16px;
1596
- }
1597
- .hero-actions .btn {
1598
- width: 100%;
1599
- }
1600
- .clone-pill {
1601
- font-size: 0.75rem;
1602
- padding: 6px 10px;
1603
- }
1604
- .discord-message {
1605
- gap: 12px;
1606
- }
1607
- .discord-avatar {
1608
- width: 36px;
1609
- height: 36px;
1610
- }
1611
-}
1612
-
1613
-/* ==============================================================================
1614
- Utility & Polish
1615
- ============================================================================== */
1616
-
1617
-::selection {
1618
- background: rgba(88, 166, 255, 0.3);
1619
- color: #ffffff;
184
+/* Smooth scroll */
185
+html {
186
+ scroll-behavior: smooth;
1620
187
}
1621
188
1622
-/* Scrollbar styling */
1623
-::-webkit-scrollbar {
1624
- width: 8px;
1625
- height: 8px;
189
+/* Body overflow */
190
+body {
191
+ overflow-x: hidden;
1626
192
}
1627
193
1628
-::-webkit-scrollbar-track {
1629
- background: var(--bg-canvas);
194
+/* Z-index layering */
195
+.z-background {
196
+ z-index: 0;
1630
197
}
1631
-
1632
-::-webkit-scrollbar-thumb {
1633
- background: var(--border-default);
1634
- border-radius: 4px;
198
+.z-content {
199
+ z-index: 10;
1635
200
}
1636
-
1637
-::-webkit-scrollbar-thumb:hover {
1638
- background: var(--text-muted);
201
+.z-navbar {
202
+ z-index: 50;
1639
203
}
1640
-
1641
-/* Focus visible for accessibility */
1642
-:focus-visible {
1643
- outline: 2px solid var(--gh-blue);
1644
- outline-offset: 2px;
1645
- border-radius: 4px;
1646
-}
1647
-
1648
-/* Reduced motion */
1649
-@media (prefers-reduced-motion: reduce) {
1650
- *, *::before, *::after {
1651
- animation-duration: 0.01ms !important;
1652
- animation-iteration-count: 1 !important;
1653
- transition-duration: 0.01ms !important;
1654
- }
1655
- .reveal {
1656
- opacity: 1;
1657
- transform: none;
1658
- }
204
+.z-modal {
205
+ z-index: 100;
1659
206
}
1660
207