Pre-launch — Gluecron is in final validation. Public signups and git hosting for non-owner users open after launch review.
CodeIssuesPull RequestsActionsSecurityInsightsSettings
✨ AI
More
Blame · Line-by-line history

layout.tsx

Each line is annotated with the commit that last touched it. Click any SHA to jump to that commit and see the surrounding change.

layout.tsxBlame902 lines · 1 contributor
fc1817aClaude1import type { FC, PropsWithChildren } from "hono/jsx";
06d5ffeClaude2import type { User } from "../db/schema";
3import { hljsThemeCss } from "../lib/highlight";
45e31d0Claude4import { clientJs } from "./client-js";
fc1817aClaude5
06d5ffeClaude6export const Layout: FC<
7 PropsWithChildren<{ title?: string; user?: User | null }>
8> = ({ children, title, user }) => {
fc1817aClaude9 return (
10 <html lang="en">
11 <head>
12 <meta charset="UTF-8" />
13 <meta name="viewport" content="width=device-width, initial-scale=1.0" />
14 <title>{title ? `${title} — gluecron` : "gluecron"}</title>
15 <style>{css}</style>
06d5ffeClaude16 <style>{hljsThemeCss}</style>
fc1817aClaude17 </head>
18 <body>
45e31d0Claude19 <a href="#main-content" class="skip-link">Skip to main content</a>
fc1817aClaude20 <header>
21 <nav>
22 <a href="/" class="logo">
23 gluecron
24 </a>
06d5ffeClaude25 <div class="nav-right">
c81ab7aClaude26 <a href="/explore" class="nav-link">
27 Explore
28 </a>
06d5ffeClaude29 {user ? (
30 <>
31 <a href="/new" class="btn btn-sm btn-primary">
32 + New
33 </a>
34 <a href={`/${user.username}`} class="nav-user">
35 {user.displayName || user.username}
36 </a>
37 <a href="/settings" class="nav-link">
38 Settings
39 </a>
40 <a href="/logout" class="nav-link">
41 Sign out
42 </a>
43 </>
44 ) : (
45 <>
46 <a href="/login" class="nav-link">
47 Sign in
48 </a>
49 <a href="/register" class="btn btn-sm btn-primary">
50 Register
51 </a>
52 </>
53 )}
54 </div>
fc1817aClaude55 </nav>
56 </header>
45e31d0Claude57 <main id="main-content">{children}</main>
fc1817aClaude58 <footer>
59 <span>gluecron — AI-native code intelligence</span>
45e31d0Claude60 <span style="margin-left:16px">
61 <a href="/api/docs" style="color:var(--text-muted);font-size:12px">API Docs</a>
62 </span>
fc1817aClaude63 </footer>
45e31d0Claude64 <script>{clientJs}</script>
fc1817aClaude65 </body>
66 </html>
67 );
68};
69
70const css = `
71 :root {
72 --bg: #0d1117;
73 --bg-secondary: #161b22;
74 --bg-tertiary: #21262d;
75 --border: #30363d;
76 --text: #e6edf3;
77 --text-muted: #8b949e;
78 --text-link: #58a6ff;
79 --accent: #1f6feb;
80 --accent-hover: #388bfd;
81 --green: #3fb950;
82 --red: #f85149;
83 --yellow: #d29922;
84 --font-mono: 'SF Mono', 'Cascadia Code', 'Fira Code', monospace;
85 --font-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;
86 --radius: 6px;
87 }
88
89 * { margin: 0; padding: 0; box-sizing: border-box; }
90
91 body {
92 font-family: var(--font-sans);
93 background: var(--bg);
94 color: var(--text);
95 line-height: 1.5;
96 min-height: 100vh;
97 display: flex;
98 flex-direction: column;
99 }
100
101 a { color: var(--text-link); text-decoration: none; }
102 a:hover { text-decoration: underline; }
103
104 header {
105 border-bottom: 1px solid var(--border);
106 padding: 12px 24px;
107 background: var(--bg-secondary);
108 }
109
06d5ffeClaude110 header nav {
111 display: flex;
112 align-items: center;
113 justify-content: space-between;
114 max-width: 1200px;
115 margin: 0 auto;
116 }
fc1817aClaude117 .logo { font-size: 20px; font-weight: 700; color: var(--text); }
118 .logo:hover { text-decoration: none; color: var(--text-link); }
119
06d5ffeClaude120 .nav-right { display: flex; align-items: center; gap: 16px; }
121 .nav-link { color: var(--text-muted); font-size: 14px; }
122 .nav-link:hover { color: var(--text); text-decoration: none; }
123 .nav-user { color: var(--text); font-weight: 600; font-size: 14px; }
124 .nav-user:hover { color: var(--text-link); text-decoration: none; }
125
fc1817aClaude126 main { max-width: 1200px; margin: 0 auto; padding: 24px; flex: 1; width: 100%; }
127
128 footer {
129 border-top: 1px solid var(--border);
130 padding: 16px 24px;
131 text-align: center;
132 color: var(--text-muted);
133 font-size: 13px;
134 }
135
06d5ffeClaude136 /* Buttons */
137 .btn {
138 display: inline-flex;
139 align-items: center;
140 gap: 6px;
141 padding: 8px 16px;
142 border-radius: var(--radius);
143 font-size: 14px;
144 font-weight: 500;
145 border: 1px solid var(--border);
146 background: var(--bg-tertiary);
147 color: var(--text);
148 cursor: pointer;
149 text-decoration: none;
150 line-height: 1.4;
151 }
152 .btn:hover { background: var(--border); text-decoration: none; }
153 .btn-primary { background: var(--accent); border-color: var(--accent); color: #fff; }
154 .btn-primary:hover { background: var(--accent-hover); }
155 .btn-danger { background: transparent; border-color: var(--red); color: var(--red); }
156 .btn-danger:hover { background: rgba(248, 81, 73, 0.15); }
157 .btn-sm { padding: 4px 12px; font-size: 13px; }
158
159 /* Forms */
160 .form-group { margin-bottom: 16px; }
161 .form-group label { display: block; font-size: 14px; font-weight: 500; margin-bottom: 6px; color: var(--text); }
162 .form-group input, .form-group textarea, .form-group select {
163 width: 100%;
164 padding: 8px 12px;
165 background: var(--bg);
166 border: 1px solid var(--border);
167 border-radius: var(--radius);
168 color: var(--text);
169 font-size: 14px;
170 font-family: var(--font-sans);
171 }
172 .form-group input:focus, .form-group textarea:focus, .form-group select:focus {
173 outline: none;
174 border-color: var(--accent);
175 box-shadow: 0 0 0 2px rgba(31, 111, 235, 0.3);
176 }
177 .input-disabled { opacity: 0.5; cursor: not-allowed; }
178
179 /* Auth */
180 .auth-container { max-width: 400px; margin: 40px auto; }
181 .auth-container h2 { margin-bottom: 20px; font-size: 24px; }
182 .auth-error {
183 background: rgba(248, 81, 73, 0.1);
184 border: 1px solid var(--red);
185 color: var(--red);
186 padding: 8px 12px;
187 border-radius: var(--radius);
188 margin-bottom: 16px;
189 font-size: 14px;
190 }
191 .auth-success {
192 background: rgba(63, 185, 80, 0.1);
193 border: 1px solid var(--green);
194 color: var(--green);
195 padding: 8px 12px;
196 border-radius: var(--radius);
197 margin-bottom: 16px;
198 font-size: 14px;
199 }
200 .auth-switch { margin-top: 16px; font-size: 14px; color: var(--text-muted); }
201
202 /* Settings */
203 .settings-container { max-width: 600px; }
204 .settings-container h2 { margin-bottom: 20px; font-size: 24px; }
205 .settings-container h3 { font-size: 18px; margin-bottom: 12px; }
206 .ssh-keys-list { margin-bottom: 24px; }
207 .ssh-key-item {
208 display: flex;
209 justify-content: space-between;
210 align-items: center;
211 padding: 12px 16px;
212 border: 1px solid var(--border);
213 border-radius: var(--radius);
214 margin-bottom: 8px;
215 background: var(--bg-secondary);
216 }
217 .ssh-key-meta { font-size: 12px; color: var(--text-muted); margin-top: 2px; }
218 .ssh-key-meta code { font-size: 11px; background: var(--bg-tertiary); padding: 1px 6px; border-radius: 3px; margin-right: 8px; }
219
220 /* Repo header */
fc1817aClaude221 .repo-header {
222 display: flex;
223 align-items: center;
224 gap: 8px;
225 margin-bottom: 16px;
226 font-size: 20px;
227 }
228 .repo-header .owner { color: var(--text-link); }
229 .repo-header .separator { color: var(--text-muted); }
230 .repo-header .name { color: var(--text-link); font-weight: 600; }
06d5ffeClaude231 .repo-header-actions { margin-left: auto; display: flex; gap: 8px; align-items: center; }
fc1817aClaude232
233 .repo-nav {
234 display: flex;
235 gap: 0;
236 border-bottom: 1px solid var(--border);
237 margin-bottom: 20px;
238 }
239 .repo-nav a {
240 padding: 8px 16px;
241 color: var(--text-muted);
242 border-bottom: 2px solid transparent;
243 font-size: 14px;
244 }
245 .repo-nav a:hover { text-decoration: none; color: var(--text); }
246 .repo-nav a.active { color: var(--text); border-bottom-color: var(--accent); }
247
248 .breadcrumb { display: flex; gap: 4px; align-items: center; margin-bottom: 16px; color: var(--text-muted); font-size: 14px; }
249 .breadcrumb a { color: var(--text-link); }
250
251 .file-table { width: 100%; border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; }
252 .file-table tr { border-bottom: 1px solid var(--border); }
253 .file-table tr:last-child { border-bottom: none; }
254 .file-table td { padding: 8px 16px; font-size: 14px; }
255 .file-table tr:hover { background: var(--bg-secondary); }
256 .file-icon { width: 20px; color: var(--text-muted); }
257 .file-name a { color: var(--text); }
258 .file-name a:hover { color: var(--text-link); text-decoration: underline; }
259
260 .blob-view {
261 border: 1px solid var(--border);
262 border-radius: var(--radius);
263 overflow: hidden;
264 }
265 .blob-header {
266 background: var(--bg-secondary);
267 padding: 8px 16px;
268 border-bottom: 1px solid var(--border);
269 font-size: 13px;
270 color: var(--text-muted);
06d5ffeClaude271 display: flex;
272 justify-content: space-between;
273 align-items: center;
fc1817aClaude274 }
275 .blob-code {
276 overflow-x: auto;
277 font-family: var(--font-mono);
278 font-size: 13px;
279 line-height: 1.6;
280 }
281 .blob-code table { width: 100%; border-collapse: collapse; }
282 .blob-code .line-num {
283 width: 1%;
284 min-width: 50px;
285 padding: 0 12px;
286 text-align: right;
287 color: var(--text-muted);
288 user-select: none;
289 white-space: nowrap;
290 border-right: 1px solid var(--border);
291 }
292 .blob-code .line-content { padding: 0 12px; white-space: pre; }
293
294 .commit-list { border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; }
295 .commit-item {
296 display: flex;
297 justify-content: space-between;
298 align-items: center;
299 padding: 12px 16px;
300 border-bottom: 1px solid var(--border);
301 }
302 .commit-item:last-child { border-bottom: none; }
303 .commit-item:hover { background: var(--bg-secondary); }
304 .commit-message { font-size: 14px; font-weight: 500; }
305 .commit-meta { font-size: 12px; color: var(--text-muted); }
306 .commit-sha {
307 font-family: var(--font-mono);
308 font-size: 12px;
309 padding: 2px 8px;
310 background: var(--bg-tertiary);
311 border: 1px solid var(--border);
312 border-radius: var(--radius);
313 color: var(--text-link);
314 }
315
316 .diff-view { margin-top: 16px; }
317 .diff-file {
318 border: 1px solid var(--border);
319 border-radius: var(--radius);
320 margin-bottom: 16px;
321 overflow: hidden;
322 }
323 .diff-file-header {
324 background: var(--bg-secondary);
325 padding: 8px 16px;
326 border-bottom: 1px solid var(--border);
327 font-family: var(--font-mono);
328 font-size: 13px;
329 }
330 .diff-content {
331 overflow-x: auto;
332 font-family: var(--font-mono);
333 font-size: 13px;
334 line-height: 1.6;
335 }
336 .diff-content .line-add { background: rgba(63, 185, 80, 0.15); color: var(--green); }
337 .diff-content .line-del { background: rgba(248, 81, 73, 0.1); color: var(--red); }
338 .diff-content .line-hunk { background: rgba(56, 139, 253, 0.1); color: var(--text-link); }
339 .diff-content .line { padding: 0 12px; white-space: pre; display: block; }
340
341 .stat-add { color: var(--green); font-weight: 600; }
342 .stat-del { color: var(--red); font-weight: 600; }
343
344 .empty-state {
345 text-align: center;
346 padding: 60px 20px;
347 color: var(--text-muted);
348 }
349 .empty-state h2 { font-size: 24px; margin-bottom: 8px; color: var(--text); }
350 .empty-state pre {
351 text-align: left;
352 display: inline-block;
353 background: var(--bg-secondary);
354 padding: 16px 24px;
355 border-radius: var(--radius);
356 border: 1px solid var(--border);
357 font-family: var(--font-mono);
358 font-size: 13px;
359 margin-top: 16px;
360 line-height: 1.8;
361 }
362
363 .badge {
364 display: inline-block;
365 padding: 2px 8px;
366 border-radius: 12px;
367 font-size: 12px;
368 font-weight: 500;
369 background: var(--bg-tertiary);
370 border: 1px solid var(--border);
371 color: var(--text-muted);
372 }
373
374 .branch-selector {
375 display: inline-flex;
376 align-items: center;
377 gap: 4px;
378 padding: 4px 12px;
379 background: var(--bg-tertiary);
380 border: 1px solid var(--border);
381 border-radius: var(--radius);
382 font-size: 13px;
383 color: var(--text);
384 margin-bottom: 12px;
06d5ffeClaude385 position: relative;
fc1817aClaude386 }
387
06d5ffeClaude388 .branch-dropdown {
389 position: relative;
390 display: inline-block;
391 margin-bottom: 12px;
392 }
393 .branch-dropdown-content {
394 display: none;
395 position: absolute;
396 top: 100%;
397 left: 0;
398 z-index: 10;
399 min-width: 200px;
400 background: var(--bg-secondary);
401 border: 1px solid var(--border);
402 border-radius: var(--radius);
403 margin-top: 4px;
404 box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
405 }
406 .branch-dropdown:hover .branch-dropdown-content,
407 .branch-dropdown:focus-within .branch-dropdown-content { display: block; }
408 .branch-dropdown-content a {
409 display: block;
410 padding: 8px 12px;
411 font-size: 13px;
412 color: var(--text);
413 border-bottom: 1px solid var(--border);
414 }
415 .branch-dropdown-content a:last-child { border-bottom: none; }
416 .branch-dropdown-content a:hover { background: var(--bg-tertiary); text-decoration: none; }
417 .branch-dropdown-content a.active-branch { color: var(--text-link); font-weight: 600; }
418
fc1817aClaude419 .card-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(340px, 1fr)); gap: 16px; }
420 .card {
421 border: 1px solid var(--border);
422 border-radius: var(--radius);
423 padding: 16px;
424 background: var(--bg-secondary);
06d5ffeClaude425 transition: border-color 0.15s;
fc1817aClaude426 }
06d5ffeClaude427 .card:hover { border-color: var(--text-muted); }
fc1817aClaude428 .card h3 { font-size: 16px; margin-bottom: 4px; }
06d5ffeClaude429 .card h3 a { color: var(--text-link); }
fc1817aClaude430 .card p { font-size: 13px; color: var(--text-muted); }
06d5ffeClaude431 .card-meta { display: flex; gap: 16px; margin-top: 12px; font-size: 12px; color: var(--text-muted); }
432 .card-meta span { display: flex; align-items: center; gap: 4px; }
433
434 .star-btn {
435 display: inline-flex;
436 align-items: center;
437 gap: 6px;
438 padding: 4px 12px;
439 background: var(--bg-tertiary);
440 border: 1px solid var(--border);
441 border-radius: var(--radius);
442 color: var(--text);
443 font-size: 13px;
444 cursor: pointer;
445 }
446 .star-btn:hover { background: var(--border); text-decoration: none; }
447 .star-btn.starred { color: var(--yellow); border-color: var(--yellow); }
448
449 .user-profile {
450 display: flex;
451 gap: 32px;
452 margin-bottom: 32px;
453 }
454 .user-avatar {
455 width: 96px;
456 height: 96px;
457 border-radius: 50%;
458 background: var(--bg-tertiary);
459 border: 1px solid var(--border);
460 display: flex;
461 align-items: center;
462 justify-content: center;
463 font-size: 40px;
464 color: var(--text-muted);
465 flex-shrink: 0;
466 }
467 .user-info h2 { font-size: 24px; margin-bottom: 2px; }
468 .user-info .username { font-size: 16px; color: var(--text-muted); }
469 .user-info .bio { font-size: 14px; color: var(--text-muted); margin-top: 8px; }
470
471 .new-repo-form { max-width: 600px; }
472 .new-repo-form h2 { margin-bottom: 20px; }
473 .visibility-options { display: flex; gap: 12px; margin-bottom: 16px; }
474 .visibility-option {
475 flex: 1;
476 padding: 12px;
477 border: 1px solid var(--border);
478 border-radius: var(--radius);
479 background: var(--bg-secondary);
480 cursor: pointer;
481 text-align: center;
482 }
483 .visibility-option:has(input:checked) { border-color: var(--accent); background: rgba(31, 111, 235, 0.1); }
484 .visibility-option input { display: none; }
485 .visibility-option .vis-label { font-size: 14px; font-weight: 500; }
486 .visibility-option .vis-desc { font-size: 12px; color: var(--text-muted); }
79136bbClaude487
488 /* Issues */
489 .issue-tabs { display: flex; gap: 16px; }
490 .issue-tabs a { color: var(--text-muted); font-size: 14px; font-weight: 500; }
491 .issue-tabs a:hover { color: var(--text); text-decoration: none; }
492 .issue-tabs a.active { color: var(--text); }
493
494 .issue-list { border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; }
495 .issue-item {
496 display: flex;
497 gap: 12px;
498 align-items: flex-start;
499 padding: 12px 16px;
500 border-bottom: 1px solid var(--border);
501 }
502 .issue-item:last-child { border-bottom: none; }
503 .issue-item:hover { background: var(--bg-secondary); }
504 .issue-state-icon { font-size: 16px; padding-top: 2px; }
505 .state-open { color: var(--green); }
506 .state-closed { color: #986ee2; }
507 .issue-title { font-size: 15px; font-weight: 600; }
508 .issue-title a { color: var(--text); }
509 .issue-title a:hover { color: var(--text-link); }
510 .issue-meta { font-size: 12px; color: var(--text-muted); margin-top: 2px; }
511
512 .issue-badge {
513 display: inline-flex;
514 align-items: center;
515 gap: 4px;
516 padding: 4px 12px;
517 border-radius: 20px;
518 font-size: 13px;
519 font-weight: 500;
520 }
521 .badge-open { background: rgba(63, 185, 80, 0.15); color: var(--green); border: 1px solid var(--green); }
522 .badge-closed { background: rgba(152, 110, 226, 0.15); color: #986ee2; border: 1px solid #986ee2; }
0074234Claude523 .badge-merged { background: rgba(152, 110, 226, 0.15); color: #986ee2; border: 1px solid #986ee2; }
524 .state-merged { color: #986ee2; }
525 .ai-review { border-color: var(--accent); }
79136bbClaude526
527 .issue-detail { max-width: 900px; }
528 .issue-comment-box {
529 border: 1px solid var(--border);
530 border-radius: var(--radius);
531 margin-bottom: 16px;
532 overflow: hidden;
533 }
534 .comment-header {
535 background: var(--bg-secondary);
536 padding: 8px 16px;
537 border-bottom: 1px solid var(--border);
538 font-size: 13px;
539 color: var(--text-muted);
540 }
541
542 /* Search */
543 .search-results .diff-file { margin-bottom: 12px; }
45e31d0Claude544 .search-input {
545 flex: 1;
546 padding: 8px 12px;
547 background: var(--bg);
548 border: 1px solid var(--border);
549 border-radius: var(--radius);
550 color: var(--text);
551 font-size: 14px;
552 }
553 .search-input:focus {
554 outline: none;
555 border-color: var(--accent);
556 box-shadow: 0 0 0 2px rgba(31, 111, 235, 0.3);
557 }
558
559 /* Toast Notifications */
560 #toast-container {
561 position: fixed;
562 top: 16px;
563 right: 16px;
564 z-index: 9999;
565 display: flex;
566 flex-direction: column;
567 gap: 8px;
568 }
569 .toast {
570 padding: 10px 16px;
571 border-radius: var(--radius);
572 font-size: 14px;
573 font-weight: 500;
574 opacity: 0;
575 transform: translateX(100%);
576 transition: all 0.3s ease;
577 min-width: 200px;
578 box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
579 }
580 .toast-visible { opacity: 1; transform: translateX(0); }
581 .toast-info { background: var(--accent); color: #fff; }
582 .toast-success { background: var(--green); color: #fff; }
583 .toast-error { background: var(--red); color: #fff; }
584 .toast-warning { background: var(--yellow); color: #000; }
585
586 /* Keyboard Shortcut Hints */
587 .kbd {
588 display: inline-block;
589 padding: 2px 6px;
590 border: 1px solid var(--border);
591 border-radius: 4px;
592 background: var(--bg-secondary);
593 font-family: var(--font-mono);
594 font-size: 12px;
595 line-height: 1.4;
596 color: var(--text-muted);
597 box-shadow: 0 1px 0 var(--border);
598 }
599 .shortcut-overlay {
600 position: fixed;
601 inset: 0;
602 background: rgba(0, 0, 0, 0.6);
603 z-index: 9998;
604 display: flex;
605 align-items: center;
606 justify-content: center;
607 }
608 .shortcut-modal {
609 background: var(--bg-secondary);
610 border: 1px solid var(--border);
611 border-radius: var(--radius);
612 padding: 24px;
613 min-width: 300px;
614 max-width: 480px;
615 }
616 .shortcut-modal h3 { margin-bottom: 16px; }
617 .shortcut-grid {
618 display: flex;
619 flex-direction: column;
620 gap: 8px;
621 margin-bottom: 16px;
622 font-size: 14px;
623 }
624 .shortcut-grid div {
625 display: flex;
626 align-items: center;
627 gap: 8px;
628 }
629
630 /* Comment Editor with Preview */
631 .comment-editor {
632 border: 1px solid var(--border);
633 border-radius: var(--radius);
634 overflow: hidden;
635 }
636 .editor-tabs {
637 display: flex;
638 border-bottom: 1px solid var(--border);
639 background: var(--bg-secondary);
640 }
641 .editor-tab {
642 padding: 6px 16px;
643 font-size: 13px;
644 background: none;
645 border: none;
646 color: var(--text-muted);
647 cursor: pointer;
648 border-bottom: 2px solid transparent;
649 }
650 .editor-tab:hover { color: var(--text); }
651 .editor-tab.active { color: var(--text); border-bottom-color: var(--accent); }
652 .comment-editor textarea {
653 width: 100%;
654 border: none;
655 padding: 12px;
656 background: var(--bg);
657 color: var(--text);
658 font-family: var(--font-mono);
659 font-size: 13px;
660 resize: vertical;
661 min-height: 120px;
662 }
663 .comment-editor textarea:focus { outline: none; }
664 .editor-preview {
665 min-height: 120px;
666 background: var(--bg);
667 }
668
669 /* Success Button */
670 .btn-success { background: var(--green); border-color: var(--green); color: #fff; }
671 .btn-success:hover { background: #2ea043; }
672 .btn-ghost { background: transparent; border-color: transparent; color: var(--text-muted); }
673 .btn-ghost:hover { color: var(--text); background: var(--bg-tertiary); }
674 .btn-lg { padding: 12px 24px; font-size: 16px; }
675
676 /* Tab count badge */
677 .tab-count {
678 display: inline-block;
679 padding: 0 6px;
680 margin-left: 4px;
681 font-size: 12px;
682 background: var(--bg-tertiary);
683 border-radius: 10px;
684 }
685
686 /* Copy block */
687 .copy-block {
688 margin: 8px 0;
689 }
690
691 /* Progress bar */
692 .progress-bar {
693 width: 100%;
694 height: 8px;
695 background: var(--bg-tertiary);
696 border-radius: 4px;
697 overflow: hidden;
698 }
699 .progress-fill {
700 height: 100%;
701 background: var(--accent);
702 border-radius: 4px;
703 transition: width 0.3s ease;
704 }
705
706 /* Spinner */
707 .spinner {
708 border: 2px solid var(--border);
709 border-top: 2px solid var(--accent);
710 border-radius: 50%;
711 animation: spin 0.8s linear infinite;
712 }
713 @keyframes spin { to { transform: rotate(360deg); } }
714
715 /* Step indicator (onboarding) */
716 .step-indicator { margin-bottom: 32px; }
717 .step-circle {
718 width: 32px;
719 height: 32px;
720 border-radius: 50%;
721 display: flex;
722 align-items: center;
723 justify-content: center;
724 font-size: 14px;
725 font-weight: 600;
726 background: var(--bg-tertiary);
727 border: 2px solid var(--border);
728 color: var(--text-muted);
729 }
730 .step-completed { background: var(--green); border-color: var(--green); color: #fff; }
731 .step-active { border-color: var(--accent); color: var(--accent); }
732 .step-line {
733 flex: 1;
734 height: 2px;
735 background: var(--border);
736 min-width: 40px;
737 }
738 .step-line[data-completed="true"] { background: var(--green); }
739
740 /* Welcome hero */
741 .welcome-hero {
742 text-align: center;
743 padding: 60px 20px 40px;
744 max-width: 700px;
745 margin: 0 auto;
746 }
747 .welcome-hero h1 { font-size: 36px; margin-bottom: 12px; }
748 .hero-subtitle { font-size: 18px; color: var(--text-muted); margin-bottom: 32px; }
749
750 /* Feature cards */
751 .feature-card {
752 text-align: center;
753 padding: 24px;
754 transition: border-color 0.2s, transform 0.2s;
755 }
756 .feature-card:hover { border-color: var(--accent); transform: translateY(-2px); }
757 .feature-icon { font-size: 36px; margin-bottom: 12px; }
758 .feature-card h3 { font-size: 16px; margin-bottom: 8px; }
759
760 /* Tooltip */
761 .tooltip-wrapper { position: relative; }
762 .tooltip-wrapper:hover::after {
763 content: attr(data-tooltip);
764 position: absolute;
765 bottom: 100%;
766 left: 50%;
767 transform: translateX(-50%);
768 padding: 4px 8px;
769 background: var(--bg-tertiary);
770 border: 1px solid var(--border);
771 border-radius: 4px;
772 font-size: 12px;
773 white-space: nowrap;
774 z-index: 100;
775 margin-bottom: 4px;
776 }
777
778 /* Notification bell */
779 .notification-bell {
780 position: relative;
781 display: inline-flex;
782 align-items: center;
783 color: var(--text-muted);
784 padding: 4px;
785 }
786 .notification-bell:hover { color: var(--text); text-decoration: none; }
787 .notification-count {
788 position: absolute;
789 top: -4px;
790 right: -6px;
791 background: var(--accent);
792 color: #fff;
793 font-size: 10px;
794 font-weight: 700;
795 padding: 1px 5px;
796 border-radius: 10px;
797 min-width: 16px;
798 text-align: center;
799 }
800
801 /* Alert variants */
802 .alert-warning {
803 background: rgba(210, 153, 34, 0.1);
804 border: 1px solid var(--yellow);
805 color: var(--yellow);
806 padding: 8px 12px;
807 border-radius: var(--radius);
808 margin-bottom: 16px;
809 font-size: 14px;
810 }
811 .alert-info {
812 background: rgba(88, 166, 255, 0.1);
813 border: 1px solid var(--text-link);
814 color: var(--text-link);
815 padding: 8px 12px;
816 border-radius: var(--radius);
817 margin-bottom: 16px;
818 font-size: 14px;
819 }
820
821 /* Badge variants */
822 .badge-success { background: rgba(63, 185, 80, 0.15); color: var(--green); border: 1px solid var(--green); }
823 .badge-danger { background: rgba(248, 81, 73, 0.1); color: var(--red); border: 1px solid var(--red); }
824 .badge-warning { background: rgba(210, 153, 34, 0.1); color: var(--yellow); border: 1px solid var(--yellow); }
825
826 /* Mobile responsiveness */
827 @media (max-width: 768px) {
828 main { padding: 16px; }
829 .card-grid { grid-template-columns: 1fr; }
830 .user-profile { flex-direction: column; gap: 16px; }
831 .repo-header { flex-wrap: wrap; }
832 .repo-header-actions { margin-left: 0; }
833 .repo-nav { overflow-x: auto; }
834 .blob-code { font-size: 12px; }
835 .diff-content { font-size: 12px; }
836 .hamburger-btn {
837 display: inline-flex;
838 align-items: center;
839 justify-content: center;
840 width: 36px;
841 height: 36px;
842 background: none;
843 border: 1px solid var(--border);
844 border-radius: var(--radius);
845 color: var(--text);
846 font-size: 18px;
847 cursor: pointer;
848 }
849 .mobile-hidden { display: none !important; }
850 .mobile-visible {
851 display: flex !important;
852 position: absolute;
853 top: 100%;
854 right: 0;
855 background: var(--bg-secondary);
856 border: 1px solid var(--border);
857 border-radius: var(--radius);
858 padding: 8px;
859 flex-direction: column;
860 gap: 4px;
861 box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
862 min-width: 200px;
863 }
864 .mobile-visible a, .mobile-visible button {
865 padding: 8px 12px;
866 display: block;
867 width: 100%;
868 text-align: left;
869 }
870 .issue-item { flex-wrap: wrap; }
871 .commit-item { flex-direction: column; gap: 8px; }
872 .settings-container { max-width: 100%; }
873 .auth-container { max-width: 100%; }
874 }
875
876 /* Focus visible for keyboard nav */
877 :focus-visible {
878 outline: 2px solid var(--accent);
879 outline-offset: 2px;
880 }
881
882 /* Skip to main content (accessibility) */
883 .skip-link {
884 position: absolute;
885 top: -100px;
886 left: 0;
887 background: var(--accent);
888 color: #fff;
889 padding: 8px 16px;
890 z-index: 9999;
891 font-size: 14px;
892 }
893 .skip-link:focus { top: 0; }
894
895 /* Markdown body spacing */
896 .markdown-body { padding: 16px; }
897 .markdown-body h1, .markdown-body h2, .markdown-body h3 { margin-top: 1.5em; margin-bottom: 0.5em; }
898 .markdown-body p { margin-bottom: 1em; }
899 .markdown-body pre { margin: 1em 0; }
900 .markdown-body code { font-size: 85%; }
901 .markdown-body ul, .markdown-body ol { padding-left: 2em; margin-bottom: 1em; }
fc1817aClaude902`;