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.tsxBlame1910 lines · 2 contributors
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<
3ef4c9dClaude7 PropsWithChildren<{
8 title?: string;
9 user?: User | null;
10 notificationCount?: number;
6fc53bdClaude11 theme?: "dark" | "light";
3ef4c9dClaude12 }>
6fc53bdClaude13> = ({ children, title, user, notificationCount, theme }) => {
14 const initialTheme = theme === "light" ? "light" : "dark";
fc1817aClaude15 return (
6fc53bdClaude16 <html lang="en" data-theme={initialTheme}>
fc1817aClaude17 <head>
18 <meta charset="UTF-8" />
19 <meta name="viewport" content="width=device-width, initial-scale=1.0" />
eae38d1Claude20 <meta name="theme-color" content="#0d1117" />
21 <link rel="manifest" href="/manifest.webmanifest" />
22 <link rel="icon" type="image/svg+xml" href="/icon.svg" />
4c47454Claude23 <link rel="preconnect" href="https://fonts.googleapis.com" />
24 <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="" />
25 <link
26 rel="stylesheet"
27 href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap"
28 />
fc1817aClaude29 <title>{title ? `${title} — gluecron` : "gluecron"}</title>
6fc53bdClaude30 <script>{themeInitScript}</script>
fc1817aClaude31 <style>{css}</style>
06d5ffeClaude32 <style>{hljsThemeCss}</style>
fc1817aClaude33 </head>
34 <body>
4a52a98Claude35 <div class="prelaunch-banner" role="status" aria-live="polite">
36 Pre-launch &mdash; Gluecron is in final validation. Public signups
37 and git hosting for non-owner users open after launch review.
38 </div>
fc1817aClaude39 <header>
40 <nav>
41 <a href="/" class="logo">
42 gluecron
43 </a>
3ef4c9dClaude44 <div class="nav-search">
001af43Claude45 <form method="get" action="/search">
3ef4c9dClaude46 <input
47 type="search"
48 name="q"
49 placeholder="Search (press /)"
50 aria-label="Search"
51 />
52 </form>
53 </div>
06d5ffeClaude54 <div class="nav-right">
6fc53bdClaude55 <a
56 href="/theme/toggle"
57 class="nav-link nav-theme"
58 title="Toggle theme"
59 aria-label="Toggle theme"
60 >
61 <span class="theme-icon-dark">{"\u263E"}</span>
62 <span class="theme-icon-light">{"\u2600"}</span>
63 </a>
c81ab7aClaude64 <a href="/explore" class="nav-link">
65 Explore
66 </a>
06d5ffeClaude67 {user ? (
68 <>
f1ab587Claude69 <a href="/dashboard" class="nav-link" style="font-weight: 600">
70 Dashboard
71 </a>
bdbd0deClaude72 <a href="/import" class="nav-link">
73 Import
74 </a>
06d5ffeClaude75 <a href="/new" class="btn btn-sm btn-primary">
76 + New
77 </a>
78 <a href={`/${user.username}`} class="nav-user">
79 {user.displayName || user.username}
80 </a>
81 <a href="/settings" class="nav-link">
82 Settings
83 </a>
84 <a href="/logout" class="nav-link">
85 Sign out
86 </a>
87 </>
88 ) : (
89 <>
90 <a href="/login" class="nav-link">
91 Sign in
92 </a>
93 <a href="/register" class="btn btn-sm btn-primary">
94 Register
95 </a>
96 </>
97 )}
98 </div>
fc1817aClaude99 </nav>
100 </header>
45e31d0Claude101 <main id="main-content">{children}</main>
fc1817aClaude102 <footer>
958d26aClaude103 <div class="footer-inner">
104 <div class="footer-brand">
105 <a href="/" class="logo">gluecron</a>
106 <p class="footer-tag">
107 AI-native code intelligence. Self-hosted git, automated CI,
108 push-time gates. Software that ships itself.
109 </p>
110 </div>
111 <div class="footer-links">
112 <div class="footer-col">
113 <div class="footer-col-title">Product</div>
114 <a href="/explore">Explore</a>
115 <a href="/marketplace">Marketplace</a>
116 <a href="/help">Quickstart</a>
117 <a href="/shortcuts">Shortcuts</a>
118 </div>
119 <div class="footer-col">
120 <div class="footer-col-title">Platform</div>
121 <a href="/status">Status</a>
122 <a href="/api/graphql">GraphQL</a>
123 <a href="/mcp">MCP server</a>
124 <a href="/sitemap.xml">Sitemap</a>
125 </div>
126 <div class="footer-col">
127 <div class="footer-col-title">Legal</div>
128 <a href="/terms">Terms</a>
129 <a href="/privacy">Privacy</a>
130 <a href="/acceptable-use">Acceptable use</a>
131 </div>
132 </div>
133 </div>
134 <div class="footer-bottom">
135 <span>&copy; {new Date().getFullYear()} gluecron</span>
136 <span>shipped with intent · v1</span>
36b4cbdClaude137 </div>
fc1817aClaude138 </footer>
699e5c7Claude139 {/* Block I4 — Command palette shell (hidden by default) */}
140 <div
141 id="cmdk-backdrop"
142 style="display:none;position:fixed;inset:0;background:rgba(0,0,0,0.5);z-index:9998"
143 />
144 <div
145 id="cmdk-panel"
146 style="display:none;position:fixed;top:10%;left:50%;transform:translateX(-50%);width:min(560px,92vw);background:var(--bg-secondary);border:1px solid var(--border);border-radius:var(--radius);box-shadow:0 12px 32px rgba(0,0,0,0.4);z-index:9999;overflow:hidden"
147 >
148 <input
149 id="cmdk-input"
150 type="text"
151 placeholder="Type a command..."
152 aria-label="Command palette"
153 style="width:100%;padding:12px 16px;background:transparent;color:var(--text);border:0;border-bottom:1px solid var(--border);outline:none;font-size:14px"
154 />
155 <div id="cmdk-list" style="max-height:60vh;overflow-y:auto" />
156 </div>
45e31d0Claude157 <script>{clientJs}</script>
699e5c7Claude158 <script>{pwaRegisterScript}</script>
159 <script>{navScript}</script>
fc1817aClaude160 </body>
161 </html>
162 );
163};
164
6fc53bdClaude165// Runs before paint — reads the theme cookie and flips data-theme so there's
166// no dark-to-light flash on load. SSR default is dark.
167const themeInitScript = `
168 (function(){
169 try {
170 var m = document.cookie.match(/(?:^|; )theme=([^;]+)/);
171 var t = m ? decodeURIComponent(m[1]) : 'dark';
172 if (t !== 'light' && t !== 'dark') t = 'dark';
173 document.documentElement.setAttribute('data-theme', t);
174 } catch(_){}
175 })();
176`;
177
eae38d1Claude178// Block G1 — register service worker for offline / install support.
179// Kept inline (and tiny) so we don't block first paint.
180const pwaRegisterScript = `
181 if ('serviceWorker' in navigator) {
182 window.addEventListener('load', function(){
183 navigator.serviceWorker.register('/sw.js').catch(function(){});
184 });
185 }
186`;
187
3ef4c9dClaude188const navScript = `
189 (function(){
190 var chord = null;
191 var chordTimer = null;
192 function isTyping(t){
193 t = t || {};
194 var tag = (t.tagName || '').toLowerCase();
195 return tag === 'input' || tag === 'textarea' || t.isContentEditable;
196 }
71cd5ecClaude197
198 // ---------- Block I4 — Command palette ----------
199 var COMMANDS = [
200 { label: 'Go to Dashboard', href: '/dashboard', kw: 'home' },
201 { label: 'Go to Explore', href: '/explore', kw: 'browse discover' },
202 { label: 'Go to Notifications', href: '/notifications', kw: 'inbox' },
203 { label: 'Go to Ask AI', href: '/ask', kw: 'chat assistant' },
204 { label: 'Create new repository', href: '/new', kw: 'add create' },
205 { label: 'Marketplace', href: '/marketplace', kw: 'apps store' },
206 { label: 'Installed apps', href: '/settings/apps', kw: 'my apps' },
207 { label: 'Register new app', href: '/developer/apps-new', kw: 'developer create' },
208 { label: 'Keyboard shortcuts', href: '/shortcuts', kw: 'help keys' },
209 { label: 'Settings (profile)', href: '/settings', kw: 'account' },
210 { label: '2FA settings', href: '/settings/2fa', kw: 'two factor security' },
211 { label: 'Passkeys settings', href: '/settings/passkeys', kw: 'webauthn' },
212 { label: 'Personal access tokens', href: '/settings/tokens', kw: 'pat api' },
213 { label: 'Billing + quotas', href: '/settings/billing', kw: 'plans money' },
214 { label: 'Audit log (personal)', href: '/settings/audit', kw: 'history' },
215 { label: 'Gists', href: '/gists', kw: 'snippets' },
216 { label: 'GraphQL explorer', href: '/api/graphql', kw: 'api query' },
217 { label: 'Admin dashboard', href: '/admin', kw: 'superuser' },
218 { label: 'Toggle theme', href: '/theme/toggle', kw: 'dark light mode' }
219 ];
220
221 function fuzzyMatch(item, q){
222 if (!q) return true;
223 var hay = (item.label + ' ' + (item.kw||'') + ' ' + item.href).toLowerCase();
224 q = q.toLowerCase();
225 var qi = 0;
226 for (var i = 0; i < hay.length && qi < q.length; i++) {
227 if (hay[i] === q[qi]) qi++;
228 }
229 return qi === q.length;
230 }
231
232 var backdrop, panel, input, list, selected = 0, filtered = COMMANDS.slice();
233
234 function render(){
235 if (!list) return;
236 var html = '';
237 for (var i = 0; i < filtered.length; i++) {
238 var item = filtered[i];
239 var cls = i === selected ? 'cmdk-item cmdk-active' : 'cmdk-item';
240 var bg = i === selected ? 'background:var(--bg);' : '';
ea52715copilot-swe-agent[bot]241 html += '<div class="' + cls + '" data-idx="' + i + '" data-url="' + item.href + '"' +
71cd5ecClaude242 ' style="padding:10px 16px;cursor:pointer;border-bottom:1px solid var(--border);' + bg + '">' +
243 '<div>' + item.label + '</div>' +
244 '<div style="font-size:11px;color:var(--text-muted)">' + item.href + '</div>' +
245 '</div>';
246 }
247 if (filtered.length === 0) {
248 html = '<div style="padding:16px;color:var(--text-muted);text-align:center">No matches.</div>';
249 }
250 list.innerHTML = html;
251 }
252
253 function openPalette(){
254 backdrop = document.getElementById('cmdk-backdrop');
255 panel = document.getElementById('cmdk-panel');
256 input = document.getElementById('cmdk-input');
257 list = document.getElementById('cmdk-list');
258 if (!backdrop || !panel) return;
259 backdrop.style.display = 'block';
260 panel.style.display = 'block';
261 input.value = '';
262 selected = 0;
263 filtered = COMMANDS.slice();
264 render();
265 input.focus();
266 }
267 function closePalette(){
268 if (backdrop) backdrop.style.display = 'none';
269 if (panel) panel.style.display = 'none';
270 }
271 function go(href){ closePalette(); window.location.href = href; }
272
273 document.addEventListener('click', function(e){
274 var t = e.target;
275 if (t && t.id === 'cmdk-backdrop') { closePalette(); return; }
276 var item = t && t.closest && t.closest('.cmdk-item');
ea52715copilot-swe-agent[bot]277 if (item) { go(item.getAttribute('data-url')); }
71cd5ecClaude278 });
279
280 document.addEventListener('input', function(e){
281 if (e.target && e.target.id === 'cmdk-input') {
282 var q = e.target.value;
283 filtered = COMMANDS.filter(function(c){ return fuzzyMatch(c, q); });
284 selected = 0;
285 render();
286 }
287 });
288
3ef4c9dClaude289 document.addEventListener('keydown', function(e){
71cd5ecClaude290 // Palette-scoped keys take priority when open
291 if (panel && panel.style.display === 'block') {
292 if (e.key === 'Escape') { e.preventDefault(); closePalette(); return; }
293 if (e.key === 'ArrowDown') {
294 e.preventDefault();
295 selected = Math.min(filtered.length - 1, selected + 1);
296 render();
297 return;
298 }
299 if (e.key === 'ArrowUp') {
300 e.preventDefault();
301 selected = Math.max(0, selected - 1);
302 render();
303 return;
304 }
305 if (e.key === 'Enter') {
306 e.preventDefault();
307 var item = filtered[selected];
308 if (item) go(item.href);
309 return;
310 }
311 return;
312 }
313
3ef4c9dClaude314 if (isTyping(e.target)) return;
315 // Single key shortcuts
316 if (e.key === '/') {
317 var el = document.querySelector('.nav-search input');
318 if (el) { e.preventDefault(); el.focus(); return; }
319 }
320 if ((e.metaKey||e.ctrlKey) && e.key.toLowerCase() === 'k') {
71cd5ecClaude321 e.preventDefault();
322 openPalette();
323 return;
3ef4c9dClaude324 }
325 if (e.key === '?' && !e.ctrlKey && !e.metaKey) {
326 e.preventDefault(); window.location.href = '/shortcuts'; return;
327 }
328 if (e.key === 'n' && !e.ctrlKey && !e.metaKey) {
329 e.preventDefault(); window.location.href = '/new'; return;
330 }
331 // "g" chord
332 if (e.key === 'g' && !e.ctrlKey && !e.metaKey) {
333 chord = 'g';
334 clearTimeout(chordTimer);
335 chordTimer = setTimeout(function(){ chord = null; }, 1200);
336 return;
337 }
338 if (chord === 'g') {
339 if (e.key === 'd') { e.preventDefault(); window.location.href = '/dashboard'; }
340 else if (e.key === 'n') { e.preventDefault(); window.location.href = '/notifications'; }
341 else if (e.key === 'e') { e.preventDefault(); window.location.href = '/explore'; }
342 else if (e.key === 'a') { e.preventDefault(); window.location.href = '/ask'; }
343 chord = null;
344 }
345 });
346 })();
347`;
348
fc1817aClaude349const css = `
2ce1d0bClaude350 /* ================================================================
958d26aClaude351 * Gluecron design system — 2026.05 "Editorial-Technical"
352 * Slate-noir base · refined violet signature · hairline geometry ·
353 * mono-as-feature · cinematic motion · Inter Tight + JetBrains Mono.
354 * All class names preserved for back-compat across 50+ route views.
2ce1d0bClaude355 * ============================================================== */
6fc53bdClaude356 :root, :root[data-theme='dark'] {
958d26aClaude357 /* Surfaces — slate, not black. More depth, less crush. */
358 --bg: #08090f;
359 --bg-secondary: #0c0d14;
360 --bg-tertiary: #11131c;
361 --bg-elevated: #0f111a;
362 --bg-surface: #161826;
363 --bg-hover: rgba(255,255,255,0.04);
364 --bg-active: rgba(255,255,255,0.08);
365 --bg-inset: rgba(0,0,0,0.30);
366
367 /* Borders — three weights, used deliberately */
368 --border: rgba(255,255,255,0.06);
369 --border-subtle: rgba(255,255,255,0.035);
370 --border-strong: rgba(255,255,255,0.13);
371 --border-focus: rgba(140,109,255,0.55);
372
373 /* Text */
374 --text: #ededf2;
375 --text-strong: #f7f7fb;
376 --text-muted: #8b8c9c;
377 --text-faint: #555665;
378 --text-link: #b69dff;
379
380 /* Accent — refined violet (less candy), warm amber as secondary signal */
381 --accent: #8c6dff;
382 --accent-2: #36c5d6;
383 --accent-warm: #ffb45e;
384 --accent-hover: #a48bff;
385 --accent-pressed:#7559e8;
386 --accent-gradient: linear-gradient(135deg, #8c6dff 0%, #36c5d6 100%);
387 --accent-gradient-soft: linear-gradient(135deg, rgba(140,109,255,0.18) 0%, rgba(54,197,214,0.18) 100%);
388 --accent-gradient-faint: linear-gradient(135deg, rgba(140,109,255,0.07) 0%, rgba(54,197,214,0.07) 100%);
389 --accent-glow: 0 0 24px rgba(140,109,255,0.28);
390
391 /* Semantic */
392 --green: #34d399;
393 --red: #f87171;
394 --yellow: #fbbf24;
395 --amber: #fbbf24;
396 --blue: #60a5fa;
397
398 /* Type — Inter Tight for sans (tighter metrics) */
4c47454Claude399 --font-mono: 'JetBrains Mono', 'SF Mono', 'Cascadia Code', 'Fira Code', ui-monospace, monospace;
958d26aClaude400 --font-sans: 'Inter Tight', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
401 --font-display: 'Inter Tight', 'Inter', -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
402 --mono-feat: 'calt', 'liga', 'ss01';
403
404 /* Radius — sharper than before */
405 --r-sm: 5px;
406 --r: 7px;
407 --r-md: 9px;
408 --r-lg: 12px;
409 --r-xl: 16px;
410 --r-2xl: 22px;
411 --r-full: 9999px;
412 --radius: 7px;
413
414 /* Type scale — bigger display sizes for editorial feel */
415 --t-xs: 11px;
416 --t-sm: 13px;
417 --t-base: 14px;
418 --t-md: 16px;
419 --t-lg: 20px;
420 --t-xl: 28px;
421 --t-2xl: 40px;
422 --t-3xl: 56px;
423 --t-display: 72px;
424 --t-display-lg:96px;
425
426 /* Spacing — 4px base */
2ce1d0bClaude427 --s-0: 0;
958d26aClaude428 --s-1: 4px; --s-2: 8px; --s-3: 12px; --s-4: 16px;
429 --s-5: 20px; --s-6: 24px; --s-7: 28px; --s-8: 32px;
430 --s-10:40px; --s-12:48px; --s-14:56px; --s-16:64px;
431 --s-20:80px; --s-24:96px; --s-32:128px;
432
433 /* Elevation — softer + more layered */
434 --elev-0: 0 0 0 1px var(--border);
435 --elev-1: 0 1px 2px rgba(0,0,0,0.50), 0 0 0 1px var(--border);
436 --elev-2: 0 8px 24px -8px rgba(0,0,0,0.60), 0 0 0 1px var(--border);
437 --elev-3: 0 20px 48px -12px rgba(0,0,0,0.70), 0 0 0 1px var(--border-strong);
438 --elev-glow: 0 0 0 1px rgba(140,109,255,0.40), 0 0 32px -4px rgba(140,109,255,0.30);
439 --ring: 0 0 0 3px rgba(140,109,255,0.28);
440 --ring-warn: 0 0 0 3px rgba(251,191,36,0.28);
441 --ring-err: 0 0 0 3px rgba(248,113,113,0.28);
442
443 /* Motion */
444 --ease: cubic-bezier(0.16, 1, 0.3, 1);
445 --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
446 --ease-out-expo: cubic-bezier(0.19, 1, 0.22, 1);
447 --ease-out-quart: cubic-bezier(0.25, 1, 0.5, 1);
448 --t-fast: 120ms;
449 --t-base: 200ms;
450 --t-slow: 360ms;
451 --t-slower:560ms;
452
453 --header-h: 60px;
fc1817aClaude454 }
455
6fc53bdClaude456 :root[data-theme='light'] {
958d26aClaude457 --bg: #fbfbfc;
4c47454Claude458 --bg-secondary: #ffffff;
958d26aClaude459 --bg-tertiary: #f3f3f6;
460 --bg-elevated: #ffffff;
461 --bg-surface: #f6f6f9;
462 --bg-hover: rgba(0,0,0,0.035);
463 --bg-active: rgba(0,0,0,0.07);
464 --bg-inset: rgba(0,0,0,0.04);
465
466 --border: rgba(15,16,28,0.08);
467 --border-subtle: rgba(15,16,28,0.04);
468 --border-strong: rgba(15,16,28,0.16);
469
470 --text: #0e1020;
471 --text-strong: #050617;
472 --text-muted: #5a5b70;
473 --text-faint: #8a8b9e;
474 --text-link: #6d4dff;
475
476 --accent: #6d4dff;
477 --accent-2: #0891b2;
478 --accent-hover: #5a3df0;
479 --accent-pressed:#4a30d6;
480 --accent-glow: 0 0 24px rgba(109,77,255,0.18);
481
482 --green: #059669;
483 --red: #dc2626;
4c47454Claude484 --yellow: #d97706;
958d26aClaude485
486 --elev-1: 0 1px 2px rgba(15,16,28,0.06), 0 0 0 1px var(--border);
487 --elev-2: 0 8px 24px -10px rgba(15,16,28,0.10), 0 0 0 1px var(--border);
488 --elev-3: 0 20px 48px -16px rgba(15,16,28,0.14), 0 0 0 1px var(--border-strong);
6fc53bdClaude489 }
490
491 /* Theme toggle — show the icon for the *opposite* theme so users see what they'll switch to. */
958d26aClaude492 .nav-theme { display: inline-flex; align-items: center; font-size: 15px; line-height: 1; opacity: 0.85; }
493 .nav-theme:hover { opacity: 1; }
6fc53bdClaude494 :root[data-theme='dark'] .theme-icon-dark { display: none; }
495 :root[data-theme='light'] .theme-icon-light { display: none; }
496
fc1817aClaude497 * { margin: 0; padding: 0; box-sizing: border-box; }
958d26aClaude498 *::selection { background: rgba(140,109,255,0.32); color: var(--text-strong); }
2ce1d0bClaude499
958d26aClaude500 html { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-rendering: optimizeLegibility; }
fc1817aClaude501
502 body {
503 font-family: var(--font-sans);
504 background: var(--bg);
505 color: var(--text);
2ce1d0bClaude506 line-height: 1.55;
958d26aClaude507 letter-spacing: -0.011em;
fc1817aClaude508 min-height: 100vh;
509 display: flex;
510 flex-direction: column;
958d26aClaude511 font-feature-settings: 'cv11', 'ss01', 'ss03', 'calt';
2ce1d0bClaude512 }
513
958d26aClaude514 /* Whole-page atmosphere: very subtle gradient + dot-grid layered behind everything.
515 Keeps every page feeling like part of the same product without competing with hero art. */
2ce1d0bClaude516 body::before {
517 content: '';
518 position: fixed;
519 inset: 0;
520 pointer-events: none;
958d26aClaude521 z-index: -2;
2ce1d0bClaude522 background:
958d26aClaude523 radial-gradient(70% 55% at 85% -20%, rgba(140,109,255,0.07), transparent 65%),
524 radial-gradient(55% 45% at -10% 115%, rgba(54,197,214,0.05), transparent 65%);
525 }
526 body::after {
527 content: '';
528 position: fixed;
529 inset: 0;
530 pointer-events: none;
531 z-index: -1;
532 background-image: radial-gradient(rgba(255,255,255,0.025) 1px, transparent 1px);
533 background-size: 28px 28px;
534 background-position: 0 0;
535 opacity: 0.55;
536 mask-image: radial-gradient(ellipse at 50% 0%, #000 0%, transparent 70%);
537 -webkit-mask-image: radial-gradient(ellipse at 50% 0%, #000 0%, transparent 70%);
538 }
539 :root[data-theme='light'] body::before { opacity: 0.55; }
540 :root[data-theme='light'] body::after {
541 background-image: radial-gradient(rgba(15,16,28,0.06) 1px, transparent 1px);
542 opacity: 0.4;
fc1817aClaude543 }
2ce1d0bClaude544
545 a { color: var(--text-link); text-decoration: none; transition: color var(--t-fast) var(--ease); }
546 a:hover { color: var(--accent-hover); text-decoration: none; }
fc1817aClaude547
958d26aClaude548 /* Heading scale — confident, editorial, tight tracking */
549 h1, h2, h3, h4, h5, h6 {
550 font-family: var(--font-display);
2ce1d0bClaude551 font-weight: 600;
958d26aClaude552 letter-spacing: -0.022em;
553 line-height: 1.18;
554 color: var(--text-strong);
555 }
556 h1 { font-size: var(--t-xl); letter-spacing: -0.028em; }
557 h2 { font-size: var(--t-lg); letter-spacing: -0.022em; }
558 h3 { font-size: var(--t-md); font-weight: 600; letter-spacing: -0.015em; }
559 h4 { font-size: var(--t-base); font-weight: 600; letter-spacing: -0.01em; }
560 h5, h6 { font-size: var(--t-sm); font-weight: 600; letter-spacing: -0.005em; }
561
562 /* Editorial display heading utility — used by landing + marketing pages */
563 .display {
564 font-family: var(--font-display);
565 font-size: clamp(40px, 7.5vw, 96px);
566 line-height: 0.98;
567 letter-spacing: -0.04em;
568 font-weight: 600;
569 color: var(--text-strong);
2ce1d0bClaude570 }
fc1817aClaude571
958d26aClaude572 /* Eyebrow — uppercase mono label that sits above section headings */
573 .eyebrow {
574 display: inline-flex;
575 align-items: center;
576 gap: 8px;
577 font-family: var(--font-mono);
578 font-size: 11px;
579 font-weight: 500;
580 letter-spacing: 0.14em;
581 text-transform: uppercase;
582 color: var(--accent);
583 margin-bottom: var(--s-3);
584 }
585 .eyebrow::before {
586 content: '';
587 width: 18px;
588 height: 1px;
589 background: currentColor;
590 opacity: 0.6;
591 }
592
593 /* Section header — paired eyebrow + title + lede */
594 .section-header { max-width: 720px; margin: 0 auto var(--s-10); text-align: center; }
595 .section-header.left { text-align: left; margin-left: 0; margin-right: auto; }
596 .section-header h2 {
597 font-size: clamp(28px, 4vw, 44px);
598 line-height: 1.05;
599 letter-spacing: -0.028em;
600 margin-bottom: var(--s-3);
601 }
602 .section-header p {
603 color: var(--text-muted);
604 font-size: var(--t-md);
605 line-height: 1.6;
606 max-width: 580px;
607 margin: 0 auto;
608 }
609 .section-header.left p { margin-left: 0; }
610
611 code, kbd, samp {
2ce1d0bClaude612 font-family: var(--font-mono);
958d26aClaude613 font-feature-settings: var(--mono-feat);
614 }
615 code {
616 font-size: 0.9em;
2ce1d0bClaude617 background: var(--bg-tertiary);
958d26aClaude618 border: 1px solid var(--border-subtle);
2ce1d0bClaude619 padding: 1px 6px;
620 border-radius: var(--r-sm);
621 color: var(--text);
622 }
958d26aClaude623 kbd, .kbd {
624 display: inline-flex;
625 align-items: center;
626 padding: 1px 6px;
627 font-family: var(--font-mono);
628 font-size: 11px;
629 background: var(--bg-elevated);
630 border: 1px solid var(--border);
631 border-bottom-width: 2px;
632 border-radius: 4px;
633 color: var(--text);
634 line-height: 1.5;
635 vertical-align: middle;
636 }
2ce1d0bClaude637
958d26aClaude638 /* Mono utility for technical chrome (paths, IDs, dates) */
639 .mono { font-family: var(--font-mono); font-feature-settings: var(--mono-feat); font-size: 0.96em; }
640 .meta-mono { font-family: var(--font-mono); font-size: var(--t-xs); color: var(--text-muted); letter-spacing: 0; }
641
642 /* Pre-launch banner — slim, refined, mono caption */
4a52a98Claude643 .prelaunch-banner {
958d26aClaude644 position: relative;
2ce1d0bClaude645 background:
958d26aClaude646 linear-gradient(180deg, rgba(251,191,36,0.10), rgba(251,191,36,0.03)),
2ce1d0bClaude647 var(--bg);
958d26aClaude648 border-bottom: 1px solid rgba(251,191,36,0.28);
4a52a98Claude649 color: var(--yellow);
958d26aClaude650 padding: 7px 24px;
651 font-family: var(--font-mono);
652 font-size: 11px;
4a52a98Claude653 font-weight: 500;
654 text-align: center;
2ce1d0bClaude655 line-height: 1.5;
958d26aClaude656 letter-spacing: 0.04em;
657 text-transform: uppercase;
658 }
659 .prelaunch-banner::before {
660 content: '◆';
661 margin-right: 8px;
662 font-size: 9px;
663 opacity: 0.7;
664 vertical-align: 1px;
4a52a98Claude665 }
666
958d26aClaude667 /* Header — sticky, blurred, hairline border, taller for breathing room */
fc1817aClaude668 header {
2ce1d0bClaude669 position: sticky;
670 top: 0;
671 z-index: 100;
fc1817aClaude672 border-bottom: 1px solid var(--border);
2ce1d0bClaude673 padding: 0 24px;
674 height: var(--header-h);
958d26aClaude675 background: rgba(8,9,15,0.72);
676 backdrop-filter: saturate(180%) blur(18px);
677 -webkit-backdrop-filter: saturate(180%) blur(18px);
fc1817aClaude678 }
958d26aClaude679 :root[data-theme='light'] header { background: rgba(251,251,252,0.78); }
fc1817aClaude680
06d5ffeClaude681 header nav {
682 display: flex;
683 align-items: center;
958d26aClaude684 gap: 18px;
685 max-width: 1240px;
06d5ffeClaude686 margin: 0 auto;
2ce1d0bClaude687 height: 100%;
688 }
689 .logo {
958d26aClaude690 font-family: var(--font-display);
691 font-size: 16px;
2ce1d0bClaude692 font-weight: 700;
958d26aClaude693 letter-spacing: -0.025em;
694 color: var(--text-strong);
2ce1d0bClaude695 display: inline-flex;
696 align-items: center;
958d26aClaude697 gap: 9px;
698 transition: opacity var(--t-fast) var(--ease);
06d5ffeClaude699 }
2ce1d0bClaude700 .logo::before {
701 content: '';
958d26aClaude702 width: 20px; height: 20px;
703 border-radius: 6px;
2ce1d0bClaude704 background: var(--accent-gradient);
958d26aClaude705 box-shadow:
706 inset 0 1px 0 rgba(255,255,255,0.25),
707 0 0 0 1px rgba(140,109,255,0.45),
708 0 0 20px rgba(140,109,255,0.30);
2ce1d0bClaude709 flex-shrink: 0;
958d26aClaude710 transition: transform var(--t-base) var(--ease-spring), box-shadow var(--t-base) var(--ease);
711 }
712 .logo:hover { text-decoration: none; color: var(--text-strong); }
713 .logo:hover::before {
714 transform: rotate(8deg) scale(1.05);
715 box-shadow:
716 inset 0 1px 0 rgba(255,255,255,0.30),
717 0 0 0 1px rgba(140,109,255,0.55),
718 0 0 28px rgba(140,109,255,0.45);
2ce1d0bClaude719 }
fc1817aClaude720
2ce1d0bClaude721 .nav-search {
722 flex: 1;
958d26aClaude723 max-width: 360px;
724 margin: 0 4px 0 8px;
725 position: relative;
2ce1d0bClaude726 }
727 .nav-search input {
728 width: 100%;
958d26aClaude729 padding: 7px 12px 7px 32px;
2ce1d0bClaude730 background: var(--bg-tertiary);
731 border: 1px solid var(--border);
732 border-radius: var(--r-sm);
733 color: var(--text);
734 font-family: var(--font-sans);
735 font-size: var(--t-sm);
958d26aClaude736 transition: border-color var(--t-fast) var(--ease), background var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease);
737 }
738 .nav-search::before {
739 content: '';
740 position: absolute;
741 left: 11px; top: 50%;
742 transform: translateY(-50%);
743 width: 12px; height: 12px;
744 border: 1.5px solid var(--text-faint);
745 border-radius: 50%;
746 pointer-events: none;
747 }
748 .nav-search::after {
749 content: '';
750 position: absolute;
751 left: 19px; top: calc(50% + 4px);
752 width: 5px; height: 1.5px;
753 background: var(--text-faint);
754 transform: rotate(45deg);
755 pointer-events: none;
2ce1d0bClaude756 }
757 .nav-search input::placeholder { color: var(--text-faint); }
758 .nav-search input:focus {
759 outline: none;
760 background: var(--bg-secondary);
958d26aClaude761 border-color: var(--border-focus);
762 box-shadow: var(--ring);
2ce1d0bClaude763 }
06d5ffeClaude764
958d26aClaude765 .nav-right { display: flex; align-items: center; gap: 2px; margin-left: auto; }
2ce1d0bClaude766 .nav-link {
958d26aClaude767 position: relative;
2ce1d0bClaude768 color: var(--text-muted);
769 font-size: var(--t-sm);
770 font-weight: 500;
958d26aClaude771 padding: 7px 11px;
2ce1d0bClaude772 border-radius: var(--r-sm);
958d26aClaude773 transition: color var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
2ce1d0bClaude774 }
775 .nav-link:hover {
958d26aClaude776 color: var(--text-strong);
2ce1d0bClaude777 background: var(--bg-hover);
778 text-decoration: none;
779 }
958d26aClaude780 .nav-link.active { color: var(--text-strong); }
781 .nav-link.active::after {
782 content: '';
783 position: absolute;
784 left: 11px; right: 11px;
785 bottom: -1px;
786 height: 2px;
787 background: var(--accent-gradient);
788 border-radius: 2px;
789 }
2ce1d0bClaude790 .nav-user {
958d26aClaude791 color: var(--text-strong);
2ce1d0bClaude792 font-weight: 600;
793 font-size: var(--t-sm);
794 padding: 6px 10px;
795 border-radius: var(--r-sm);
958d26aClaude796 margin-left: 6px;
2ce1d0bClaude797 transition: background var(--t-fast) var(--ease);
798 }
958d26aClaude799 .nav-user::before {
800 content: '';
801 display: inline-block;
802 width: 8px; height: 8px;
803 background: var(--green);
804 border-radius: 50%;
805 margin-right: 7px;
806 box-shadow: 0 0 8px rgba(52,211,153,0.5);
807 vertical-align: 1px;
808 }
2ce1d0bClaude809 .nav-user:hover { background: var(--bg-hover); text-decoration: none; }
810
811 main {
958d26aClaude812 max-width: 1240px;
2ce1d0bClaude813 margin: 0 auto;
958d26aClaude814 padding: 36px 24px 80px;
2ce1d0bClaude815 flex: 1;
816 width: 100%;
817 }
fc1817aClaude818
958d26aClaude819 /* Editorial footer: link grid + tagline row */
fc1817aClaude820 footer {
821 border-top: 1px solid var(--border);
958d26aClaude822 padding: 56px 24px 40px;
823 color: var(--text-muted);
824 font-size: var(--t-sm);
825 background:
826 linear-gradient(180deg, transparent 0%, rgba(140,109,255,0.025) 100%),
827 var(--bg);
828 }
829 footer .footer-inner {
830 max-width: 1240px;
831 margin: 0 auto;
832 display: grid;
833 grid-template-columns: 1fr auto;
834 gap: 48px;
835 align-items: start;
836 }
837 footer .footer-brand .logo { margin-bottom: var(--s-3); }
838 footer .footer-tag {
839 color: var(--text-muted);
840 font-size: var(--t-sm);
841 max-width: 320px;
842 line-height: 1.55;
843 }
844 footer .footer-links {
845 display: grid;
846 grid-template-columns: repeat(3, minmax(120px, auto));
847 gap: 0 56px;
848 }
849 footer .footer-col-title {
850 font-family: var(--font-mono);
851 font-size: 11px;
852 text-transform: uppercase;
853 letter-spacing: 0.14em;
854 color: var(--text-faint);
855 margin-bottom: var(--s-3);
856 }
857 footer .footer-col a {
858 display: block;
859 color: var(--text-muted);
860 font-size: var(--t-sm);
861 padding: 5px 0;
862 transition: color var(--t-fast) var(--ease);
863 }
864 footer .footer-col a:hover { color: var(--text-strong); text-decoration: none; }
865 footer .footer-bottom {
866 max-width: 1240px;
867 margin: 40px auto 0;
868 padding-top: 24px;
869 border-top: 1px solid var(--border-subtle);
870 display: flex;
871 justify-content: space-between;
872 align-items: center;
2ce1d0bClaude873 color: var(--text-faint);
874 font-size: var(--t-xs);
958d26aClaude875 font-family: var(--font-mono);
876 letter-spacing: 0.02em;
877 }
878 footer .footer-bottom a { color: var(--text-faint); }
879 footer .footer-bottom a:hover { color: var(--text-muted); text-decoration: none; }
880 @media (max-width: 768px) {
881 footer .footer-inner { grid-template-columns: 1fr; gap: 32px; }
882 footer .footer-links { grid-template-columns: repeat(2, 1fr); gap: 24px 32px; }
883 footer .footer-bottom { flex-direction: column; gap: 8px; text-align: center; }
fc1817aClaude884 }
885
2ce1d0bClaude886 /* ============================================================ */
887 /* Buttons */
888 /* ============================================================ */
06d5ffeClaude889 .btn {
890 display: inline-flex;
891 align-items: center;
2ce1d0bClaude892 justify-content: center;
958d26aClaude893 gap: 7px;
2ce1d0bClaude894 padding: 7px 14px;
895 border-radius: var(--r-sm);
958d26aClaude896 font-family: var(--font-sans);
2ce1d0bClaude897 font-size: var(--t-sm);
06d5ffeClaude898 font-weight: 500;
899 border: 1px solid var(--border);
2ce1d0bClaude900 background: var(--bg-elevated);
06d5ffeClaude901 color: var(--text);
902 cursor: pointer;
903 text-decoration: none;
958d26aClaude904 line-height: 1.25;
905 letter-spacing: -0.008em;
2ce1d0bClaude906 transition:
907 background var(--t-fast) var(--ease),
908 border-color var(--t-fast) var(--ease),
909 transform var(--t-fast) var(--ease),
958d26aClaude910 box-shadow var(--t-fast) var(--ease),
911 color var(--t-fast) var(--ease);
2ce1d0bClaude912 user-select: none;
913 white-space: nowrap;
958d26aClaude914 position: relative;
06d5ffeClaude915 }
2ce1d0bClaude916 .btn:hover {
917 background: var(--bg-surface);
918 border-color: var(--border-strong);
958d26aClaude919 color: var(--text-strong);
2ce1d0bClaude920 text-decoration: none;
921 }
958d26aClaude922 .btn:active { transform: translateY(1px); }
2ce1d0bClaude923 .btn:focus-visible { outline: none; box-shadow: var(--ring); }
924
925 .btn-primary {
926 background: var(--accent-gradient);
927 border-color: transparent;
928 color: #fff;
929 font-weight: 600;
958d26aClaude930 text-shadow: 0 1px 0 rgba(0,0,0,0.15);
2ce1d0bClaude931 box-shadow:
958d26aClaude932 inset 0 1px 0 rgba(255,255,255,0.22),
933 inset 0 -1px 0 rgba(0,0,0,0.10),
934 0 1px 2px rgba(0,0,0,0.40),
935 0 0 0 1px rgba(140,109,255,0.30);
936 }
937 .btn-primary::before {
938 content: '';
939 position: absolute;
940 inset: 0;
941 border-radius: inherit;
942 background: linear-gradient(180deg, rgba(255,255,255,0.18), transparent 60%);
943 opacity: 0;
944 transition: opacity var(--t-fast) var(--ease);
945 pointer-events: none;
2ce1d0bClaude946 }
947 .btn-primary:hover {
958d26aClaude948 color: #fff;
2ce1d0bClaude949 background: var(--accent-gradient);
958d26aClaude950 border-color: transparent;
2ce1d0bClaude951 box-shadow:
958d26aClaude952 inset 0 1px 0 rgba(255,255,255,0.30),
953 inset 0 -1px 0 rgba(0,0,0,0.10),
954 0 6px 18px -4px rgba(140,109,255,0.45),
955 0 0 0 1px rgba(140,109,255,0.45);
2ce1d0bClaude956 }
958d26aClaude957 .btn-primary:hover::before { opacity: 1; }
2ce1d0bClaude958
959 .btn-danger {
960 background: transparent;
958d26aClaude961 border-color: rgba(248,113,113,0.40);
2ce1d0bClaude962 color: var(--red);
963 }
964 .btn-danger:hover {
958d26aClaude965 background: rgba(248,113,113,0.08);
2ce1d0bClaude966 border-color: var(--red);
958d26aClaude967 color: var(--red);
2ce1d0bClaude968 }
958d26aClaude969 .btn-danger:focus-visible { box-shadow: var(--ring-err); }
2ce1d0bClaude970
971 .btn-ghost {
972 background: transparent;
973 border-color: transparent;
974 color: var(--text-muted);
975 }
976 .btn-ghost:hover {
977 background: var(--bg-hover);
958d26aClaude978 color: var(--text-strong);
2ce1d0bClaude979 border-color: var(--border);
980 }
981
958d26aClaude982 .btn-secondary {
983 background: var(--bg-elevated);
984 border-color: var(--border-strong);
985 color: var(--text-strong);
986 }
987 .btn-secondary:hover {
988 background: var(--bg-surface);
989 border-color: var(--border-strong);
990 }
991
992 .btn-sm { padding: 4px 10px; font-size: var(--t-xs); border-radius: var(--r-sm); gap: 5px; }
993 .btn-lg { padding: 11px 22px; font-size: var(--t-base); border-radius: var(--r); }
994 .btn-xl { padding: 14px 28px; font-size: var(--t-md); border-radius: var(--r); font-weight: 600; }
995 .btn-block { width: 100%; }
2ce1d0bClaude996
997 .btn:disabled, .btn[aria-disabled='true'] {
958d26aClaude998 opacity: 0.45;
2ce1d0bClaude999 cursor: not-allowed;
1000 pointer-events: none;
1001 }
1002
1003 /* ============================================================ */
1004 /* Forms */
1005 /* ============================================================ */
1006 .form-group { margin-bottom: 20px; }
1007 .form-group label {
1008 display: block;
1009 font-size: var(--t-sm);
1010 font-weight: 500;
1011 margin-bottom: 6px;
1012 color: var(--text);
1013 letter-spacing: -0.005em;
1014 }
1015 .form-group input,
1016 .form-group textarea,
1017 .form-group select,
1018 input[type='text'], input[type='email'], input[type='password'],
1019 input[type='url'], input[type='search'], input[type='number'],
1020 textarea, select {
06d5ffeClaude1021 width: 100%;
2ce1d0bClaude1022 padding: 9px 12px;
1023 background: var(--bg-secondary);
06d5ffeClaude1024 border: 1px solid var(--border);
2ce1d0bClaude1025 border-radius: var(--r-sm);
06d5ffeClaude1026 color: var(--text);
2ce1d0bClaude1027 font-size: var(--t-sm);
06d5ffeClaude1028 font-family: var(--font-sans);
2ce1d0bClaude1029 transition:
1030 border-color var(--t-fast) var(--ease),
1031 background var(--t-fast) var(--ease),
1032 box-shadow var(--t-fast) var(--ease);
1033 }
1034 .form-group input::placeholder, textarea::placeholder, input::placeholder {
1035 color: var(--text-faint);
06d5ffeClaude1036 }
2ce1d0bClaude1037 .form-group input:hover, textarea:hover, select:hover,
1038 input[type='text']:hover, input[type='email']:hover, input[type='password']:hover {
1039 border-color: var(--border-strong);
1040 }
1041 .form-group input:focus, .form-group textarea:focus, .form-group select:focus,
1042 input:focus, textarea:focus, select:focus {
06d5ffeClaude1043 outline: none;
2ce1d0bClaude1044 background: var(--bg);
1045 border-color: var(--border-focus);
1046 box-shadow: var(--ring);
06d5ffeClaude1047 }
2ce1d0bClaude1048 textarea { font-family: var(--font-mono); font-size: var(--t-sm); line-height: 1.55; }
06d5ffeClaude1049 .input-disabled { opacity: 0.5; cursor: not-allowed; }
1050
2ce1d0bClaude1051 /* ============================================================ */
1052 /* Auth (register / login / verify) */
1053 /* ============================================================ */
1054 .auth-container {
1055 max-width: 420px;
1056 margin: 64px auto;
1057 padding: 32px;
1058 background: var(--bg-elevated);
1059 border: 1px solid var(--border);
1060 border-radius: var(--r-lg);
1061 box-shadow: var(--elev-2);
1062 }
1063 .auth-container h2 {
1064 margin-bottom: 6px;
1065 font-size: var(--t-lg);
1066 letter-spacing: -0.02em;
1067 }
1068 .auth-container > p {
1069 color: var(--text-muted);
1070 font-size: var(--t-sm);
1071 margin-bottom: 24px;
1072 }
1073 .auth-container .btn-primary { width: 100%; padding: 10px 16px; }
06d5ffeClaude1074 .auth-error {
958d26aClaude1075 background: rgba(248,113,113,0.08);
1076 border: 1px solid rgba(248,113,113,0.35);
06d5ffeClaude1077 color: var(--red);
2ce1d0bClaude1078 padding: 10px 14px;
1079 border-radius: var(--r-sm);
06d5ffeClaude1080 margin-bottom: 16px;
2ce1d0bClaude1081 font-size: var(--t-sm);
06d5ffeClaude1082 }
1083 .auth-success {
958d26aClaude1084 background: rgba(52,211,153,0.08);
1085 border: 1px solid rgba(52,211,153,0.35);
06d5ffeClaude1086 color: var(--green);
2ce1d0bClaude1087 padding: 10px 14px;
1088 border-radius: var(--r-sm);
06d5ffeClaude1089 margin-bottom: 16px;
2ce1d0bClaude1090 font-size: var(--t-sm);
1091 }
1092 .auth-switch {
1093 margin-top: 20px;
1094 font-size: var(--t-sm);
1095 color: var(--text-muted);
1096 text-align: center;
1097 }
1098 .banner {
1099 background: var(--accent-gradient-faint);
958d26aClaude1100 border: 1px solid rgba(140,109,255,0.35);
2ce1d0bClaude1101 color: var(--text);
1102 padding: 10px 14px;
1103 border-radius: var(--r-sm);
1104 font-size: var(--t-sm);
06d5ffeClaude1105 }
1106
2ce1d0bClaude1107 /* ============================================================ */
1108 /* Settings */
1109 /* ============================================================ */
1110 .settings-container { max-width: 720px; }
1111 .settings-container h2 { margin-bottom: 8px; font-size: var(--t-xl); letter-spacing: -0.02em; }
1112 .settings-container > h2 + p { color: var(--text-muted); font-size: var(--t-sm); margin-bottom: 24px; }
1113 .settings-container h3 { font-size: var(--t-md); margin-bottom: 12px; margin-top: 28px; }
1114 .settings-container h3:first-of-type { margin-top: 0; }
06d5ffeClaude1115 .ssh-keys-list { margin-bottom: 24px; }
1116 .ssh-key-item {
1117 display: flex;
1118 justify-content: space-between;
1119 align-items: center;
2ce1d0bClaude1120 padding: 14px 16px;
06d5ffeClaude1121 border: 1px solid var(--border);
2ce1d0bClaude1122 border-radius: var(--r-md);
06d5ffeClaude1123 margin-bottom: 8px;
2ce1d0bClaude1124 background: var(--bg-elevated);
1125 transition: border-color var(--t-fast) var(--ease);
06d5ffeClaude1126 }
2ce1d0bClaude1127 .ssh-key-item:hover { border-color: var(--border-strong); }
1128 .ssh-key-meta { font-size: var(--t-xs); color: var(--text-muted); margin-top: 4px; }
1129 .ssh-key-meta code { font-size: var(--t-xs); background: var(--bg-tertiary); padding: 1px 6px; border-radius: 3px; margin-right: 8px; }
06d5ffeClaude1130
2ce1d0bClaude1131 /* ============================================================ */
1132 /* Repo header + nav */
1133 /* ============================================================ */
fc1817aClaude1134 .repo-header {
1135 display: flex;
1136 align-items: center;
1137 gap: 8px;
2ce1d0bClaude1138 margin-bottom: 18px;
1139 font-size: var(--t-lg);
1140 letter-spacing: -0.015em;
fc1817aClaude1141 }
2ce1d0bClaude1142 .repo-header .owner { color: var(--text-link); font-weight: 500; }
1143 .repo-header .separator { color: var(--text-faint); }
1144 .repo-header .name { color: var(--text); font-weight: 700; }
1145 .repo-header .name:hover { color: var(--text-link); text-decoration: none; }
06d5ffeClaude1146 .repo-header-actions { margin-left: auto; display: flex; gap: 8px; align-items: center; }
fc1817aClaude1147
1148 .repo-nav {
1149 display: flex;
2ce1d0bClaude1150 gap: 2px;
fc1817aClaude1151 border-bottom: 1px solid var(--border);
2ce1d0bClaude1152 margin-bottom: 24px;
1153 overflow-x: auto;
1154 scrollbar-width: thin;
fc1817aClaude1155 }
2ce1d0bClaude1156 .repo-nav::-webkit-scrollbar { height: 0; }
fc1817aClaude1157 .repo-nav a {
2ce1d0bClaude1158 padding: 10px 14px;
fc1817aClaude1159 color: var(--text-muted);
1160 border-bottom: 2px solid transparent;
2ce1d0bClaude1161 font-size: var(--t-sm);
1162 font-weight: 500;
1163 margin-bottom: -1px;
1164 transition: all var(--t-fast) var(--ease);
1165 white-space: nowrap;
1166 }
1167 .repo-nav a:hover { text-decoration: none; color: var(--text); background: var(--bg-hover); }
1168 .repo-nav a.active {
1169 color: var(--text);
1170 border-bottom-color: var(--accent);
1171 font-weight: 600;
fc1817aClaude1172 }
1173
2ce1d0bClaude1174 .breadcrumb {
1175 display: flex;
1176 gap: 4px;
1177 align-items: center;
1178 margin-bottom: 16px;
1179 color: var(--text-muted);
1180 font-size: var(--t-sm);
1181 font-family: var(--font-mono);
1182 }
1183 .breadcrumb a { color: var(--text-link); font-weight: 500; }
1184 .breadcrumb a:hover { color: var(--accent-hover); }
fc1817aClaude1185
2ce1d0bClaude1186 /* ============================================================ */
1187 /* File browser table */
1188 /* ============================================================ */
1189 .file-table {
1190 width: 100%;
1191 border: 1px solid var(--border);
1192 border-radius: var(--r-md);
1193 overflow: hidden;
1194 background: var(--bg-elevated);
1195 }
fc1817aClaude1196 .file-table tr { border-bottom: 1px solid var(--border); }
1197 .file-table tr:last-child { border-bottom: none; }
2ce1d0bClaude1198 .file-table td { padding: 10px 16px; font-size: var(--t-sm); }
1199 .file-table tr:hover { background: var(--bg-hover); }
1200 .file-icon { width: 22px; color: var(--text-faint); font-family: var(--font-mono); font-size: var(--t-sm); }
1201 .file-name a { color: var(--text); font-weight: 500; }
1202 .file-name a:hover { color: var(--text-link); text-decoration: none; }
fc1817aClaude1203
2ce1d0bClaude1204 /* ============================================================ */
1205 /* Blob view */
1206 /* ============================================================ */
fc1817aClaude1207 .blob-view {
1208 border: 1px solid var(--border);
2ce1d0bClaude1209 border-radius: var(--r-md);
fc1817aClaude1210 overflow: hidden;
2ce1d0bClaude1211 background: var(--bg-elevated);
fc1817aClaude1212 }
1213 .blob-header {
1214 background: var(--bg-secondary);
2ce1d0bClaude1215 padding: 10px 16px;
fc1817aClaude1216 border-bottom: 1px solid var(--border);
2ce1d0bClaude1217 font-size: var(--t-sm);
fc1817aClaude1218 color: var(--text-muted);
06d5ffeClaude1219 display: flex;
1220 justify-content: space-between;
1221 align-items: center;
fc1817aClaude1222 }
1223 .blob-code {
1224 overflow-x: auto;
1225 font-family: var(--font-mono);
2ce1d0bClaude1226 font-size: var(--t-sm);
1227 line-height: 1.65;
fc1817aClaude1228 }
1229 .blob-code table { width: 100%; border-collapse: collapse; }
1230 .blob-code .line-num {
1231 width: 1%;
2ce1d0bClaude1232 min-width: 56px;
1233 padding: 0 14px;
fc1817aClaude1234 text-align: right;
2ce1d0bClaude1235 color: var(--text-faint);
fc1817aClaude1236 user-select: none;
1237 white-space: nowrap;
1238 border-right: 1px solid var(--border);
1239 }
2ce1d0bClaude1240 .blob-code .line-content { padding: 0 16px; white-space: pre; }
1241 .blob-code tr:hover { background: var(--bg-hover); }
fc1817aClaude1242
2ce1d0bClaude1243 /* ============================================================ */
1244 /* Commits + diffs */
1245 /* ============================================================ */
1246 .commit-list {
1247 border: 1px solid var(--border);
1248 border-radius: var(--r-md);
1249 overflow: hidden;
1250 background: var(--bg-elevated);
1251 }
fc1817aClaude1252 .commit-item {
1253 display: flex;
1254 justify-content: space-between;
1255 align-items: center;
2ce1d0bClaude1256 padding: 14px 16px;
fc1817aClaude1257 border-bottom: 1px solid var(--border);
2ce1d0bClaude1258 transition: background var(--t-fast) var(--ease);
fc1817aClaude1259 }
1260 .commit-item:last-child { border-bottom: none; }
2ce1d0bClaude1261 .commit-item:hover { background: var(--bg-hover); }
1262 .commit-message { font-size: var(--t-sm); font-weight: 500; line-height: 1.45; }
1263 .commit-meta { font-size: var(--t-xs); color: var(--text-muted); margin-top: 4px; }
fc1817aClaude1264 .commit-sha {
1265 font-family: var(--font-mono);
2ce1d0bClaude1266 font-size: var(--t-xs);
1267 padding: 3px 8px;
fc1817aClaude1268 background: var(--bg-tertiary);
1269 border: 1px solid var(--border);
2ce1d0bClaude1270 border-radius: var(--r-sm);
fc1817aClaude1271 color: var(--text-link);
2ce1d0bClaude1272 font-weight: 500;
1273 transition: all var(--t-fast) var(--ease);
fc1817aClaude1274 }
2ce1d0bClaude1275 .commit-sha:hover { border-color: var(--border-strong); color: var(--accent-hover); }
fc1817aClaude1276
1277 .diff-view { margin-top: 16px; }
1278 .diff-file {
1279 border: 1px solid var(--border);
2ce1d0bClaude1280 border-radius: var(--r-md);
fc1817aClaude1281 margin-bottom: 16px;
1282 overflow: hidden;
2ce1d0bClaude1283 background: var(--bg-elevated);
fc1817aClaude1284 }
1285 .diff-file-header {
1286 background: var(--bg-secondary);
2ce1d0bClaude1287 padding: 10px 16px;
fc1817aClaude1288 border-bottom: 1px solid var(--border);
1289 font-family: var(--font-mono);
2ce1d0bClaude1290 font-size: var(--t-sm);
1291 font-weight: 500;
fc1817aClaude1292 }
1293 .diff-content {
1294 overflow-x: auto;
1295 font-family: var(--font-mono);
2ce1d0bClaude1296 font-size: var(--t-sm);
1297 line-height: 1.65;
fc1817aClaude1298 }
958d26aClaude1299 .diff-content .line-add { background: rgba(52,211,153,0.10); color: var(--green); }
1300 .diff-content .line-del { background: rgba(248,113,113,0.08); color: var(--red); }
1301 .diff-content .line-hunk { background: rgba(140,109,255,0.06); color: var(--text-link); }
2ce1d0bClaude1302 .diff-content .line { padding: 0 16px; white-space: pre; display: block; }
fc1817aClaude1303
1304 .stat-add { color: var(--green); font-weight: 600; }
1305 .stat-del { color: var(--red); font-weight: 600; }
1306
2ce1d0bClaude1307 /* ============================================================ */
1308 /* Empty state */
1309 /* ============================================================ */
fc1817aClaude1310 .empty-state {
1311 text-align: center;
958d26aClaude1312 padding: 96px 24px;
fc1817aClaude1313 color: var(--text-muted);
2ce1d0bClaude1314 border: 1px dashed var(--border);
1315 border-radius: var(--r-lg);
958d26aClaude1316 background:
1317 radial-gradient(60% 60% at 50% 0%, rgba(140,109,255,0.05), transparent 70%),
1318 var(--bg-elevated);
1319 position: relative;
1320 overflow: hidden;
1321 }
1322 .empty-state::before {
1323 content: '';
1324 position: absolute;
1325 inset: 0;
1326 background-image: radial-gradient(rgba(255,255,255,0.025) 1px, transparent 1px);
1327 background-size: 24px 24px;
1328 opacity: 0.5;
1329 pointer-events: none;
1330 mask-image: radial-gradient(ellipse at center, #000 30%, transparent 70%);
1331 -webkit-mask-image: radial-gradient(ellipse at center, #000 30%, transparent 70%);
1332 }
1333 :root[data-theme='light'] .empty-state::before {
1334 background-image: radial-gradient(rgba(15,16,28,0.08) 1px, transparent 1px);
fc1817aClaude1335 }
958d26aClaude1336 .empty-state > * { position: relative; z-index: 1; }
2ce1d0bClaude1337 .empty-state h2 {
958d26aClaude1338 font-size: var(--t-xl);
2ce1d0bClaude1339 margin-bottom: 8px;
958d26aClaude1340 color: var(--text-strong);
1341 letter-spacing: -0.022em;
2ce1d0bClaude1342 }
958d26aClaude1343 .empty-state p { font-size: var(--t-md); max-width: 480px; margin: 0 auto; line-height: 1.55; }
fc1817aClaude1344 .empty-state pre {
1345 text-align: left;
1346 display: inline-block;
1347 background: var(--bg-secondary);
958d26aClaude1348 padding: 18px 24px;
1349 border-radius: var(--r-md);
fc1817aClaude1350 border: 1px solid var(--border);
1351 font-family: var(--font-mono);
958d26aClaude1352 font-feature-settings: var(--mono-feat);
2ce1d0bClaude1353 font-size: var(--t-sm);
958d26aClaude1354 margin-top: 24px;
fc1817aClaude1355 line-height: 1.8;
2ce1d0bClaude1356 color: var(--text);
958d26aClaude1357 box-shadow: var(--elev-1);
fc1817aClaude1358 }
1359
2ce1d0bClaude1360 /* ============================================================ */
1361 /* Badges */
1362 /* ============================================================ */
fc1817aClaude1363 .badge {
2ce1d0bClaude1364 display: inline-flex;
1365 align-items: center;
1366 gap: 4px;
1367 padding: 2px 9px;
1368 border-radius: var(--r-full);
1369 font-size: var(--t-xs);
fc1817aClaude1370 font-weight: 500;
1371 background: var(--bg-tertiary);
1372 border: 1px solid var(--border);
1373 color: var(--text-muted);
2ce1d0bClaude1374 line-height: 1.5;
fc1817aClaude1375 }
1376
2ce1d0bClaude1377 /* ============================================================ */
1378 /* Branch dropdown */
1379 /* ============================================================ */
fc1817aClaude1380 .branch-selector {
1381 display: inline-flex;
1382 align-items: center;
2ce1d0bClaude1383 gap: 6px;
1384 padding: 6px 12px;
1385 background: var(--bg-elevated);
fc1817aClaude1386 border: 1px solid var(--border);
2ce1d0bClaude1387 border-radius: var(--r-sm);
1388 font-size: var(--t-sm);
fc1817aClaude1389 color: var(--text);
1390 margin-bottom: 12px;
2ce1d0bClaude1391 transition: border-color var(--t-fast) var(--ease);
fc1817aClaude1392 }
2ce1d0bClaude1393 .branch-selector:hover { border-color: var(--border-strong); }
fc1817aClaude1394
06d5ffeClaude1395 .branch-dropdown {
1396 position: relative;
1397 display: inline-block;
1398 margin-bottom: 12px;
1399 }
1400 .branch-dropdown-content {
1401 display: none;
1402 position: absolute;
2ce1d0bClaude1403 top: calc(100% + 4px);
06d5ffeClaude1404 left: 0;
1405 z-index: 10;
2ce1d0bClaude1406 min-width: 220px;
1407 background: var(--bg-elevated);
1408 border: 1px solid var(--border-strong);
1409 border-radius: var(--r-md);
1410 overflow: hidden;
1411 box-shadow: var(--elev-3);
06d5ffeClaude1412 }
1413 .branch-dropdown:hover .branch-dropdown-content,
1414 .branch-dropdown:focus-within .branch-dropdown-content { display: block; }
1415 .branch-dropdown-content a {
1416 display: block;
2ce1d0bClaude1417 padding: 9px 14px;
1418 font-size: var(--t-sm);
06d5ffeClaude1419 color: var(--text);
1420 border-bottom: 1px solid var(--border);
2ce1d0bClaude1421 transition: background var(--t-fast) var(--ease);
06d5ffeClaude1422 }
1423 .branch-dropdown-content a:last-child { border-bottom: none; }
2ce1d0bClaude1424 .branch-dropdown-content a:hover { background: var(--bg-hover); text-decoration: none; }
1425 .branch-dropdown-content a.active-branch { color: var(--text-link); font-weight: 600; background: var(--accent-gradient-faint); }
06d5ffeClaude1426
2ce1d0bClaude1427 /* ============================================================ */
1428 /* Card grid */
1429 /* ============================================================ */
1430 .card-grid {
1431 display: grid;
1432 grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
1433 gap: 16px;
1434 }
fc1817aClaude1435 .card {
1436 border: 1px solid var(--border);
2ce1d0bClaude1437 border-radius: var(--r-md);
958d26aClaude1438 padding: 20px;
2ce1d0bClaude1439 background: var(--bg-elevated);
1440 transition:
958d26aClaude1441 border-color var(--t-base) var(--ease),
1442 transform var(--t-base) var(--ease-out-quart),
2ce1d0bClaude1443 box-shadow var(--t-base) var(--ease);
1444 position: relative;
1445 overflow: hidden;
958d26aClaude1446 isolation: isolate;
1447 }
1448 .card::before {
1449 content: '';
1450 position: absolute;
1451 inset: 0;
1452 background: linear-gradient(135deg, rgba(140,109,255,0.06), transparent 50%);
1453 opacity: 0;
1454 transition: opacity var(--t-base) var(--ease);
1455 pointer-events: none;
1456 z-index: -1;
2ce1d0bClaude1457 }
1458 .card:hover {
1459 border-color: var(--border-strong);
1460 box-shadow: var(--elev-2);
958d26aClaude1461 transform: translateY(-2px);
2ce1d0bClaude1462 }
958d26aClaude1463 .card:hover::before { opacity: 1; }
1464 .card h3 { font-size: var(--t-md); margin-bottom: 6px; letter-spacing: -0.012em; }
2ce1d0bClaude1465 .card h3 a { color: var(--text); font-weight: 600; }
1466 .card h3 a:hover { color: var(--text-link); }
1467 .card p { font-size: var(--t-sm); color: var(--text-muted); line-height: 1.5; }
1468 .card-meta {
1469 display: flex;
1470 gap: 14px;
1471 margin-top: 14px;
1472 padding-top: 14px;
1473 border-top: 1px solid var(--border);
1474 font-size: var(--t-xs);
1475 color: var(--text-muted);
1476 }
1477 .card-meta span { display: flex; align-items: center; gap: 5px; }
1478
1479 /* ============================================================ */
1480 /* Stat card / box */
1481 /* ============================================================ */
1482 .stat-card {
1483 background: var(--bg-elevated);
1484 border: 1px solid var(--border);
1485 border-radius: var(--r-md);
fc1817aClaude1486 padding: 16px;
2ce1d0bClaude1487 transition: border-color var(--t-fast) var(--ease);
1488 }
1489 .stat-card:hover { border-color: var(--border-strong); }
1490 .stat-label {
1491 font-size: var(--t-xs);
1492 color: var(--text-muted);
1493 text-transform: uppercase;
1494 letter-spacing: 0.06em;
1495 font-weight: 500;
1496 }
1497 .stat-value {
1498 font-size: var(--t-xl);
1499 font-weight: 700;
1500 margin-top: 4px;
1501 letter-spacing: -0.025em;
1502 color: var(--text);
1503 font-feature-settings: 'tnum';
fc1817aClaude1504 }
06d5ffeClaude1505
2ce1d0bClaude1506 /* ============================================================ */
1507 /* Star button */
1508 /* ============================================================ */
06d5ffeClaude1509 .star-btn {
1510 display: inline-flex;
1511 align-items: center;
1512 gap: 6px;
2ce1d0bClaude1513 padding: 5px 12px;
1514 background: var(--bg-elevated);
06d5ffeClaude1515 border: 1px solid var(--border);
2ce1d0bClaude1516 border-radius: var(--r-sm);
06d5ffeClaude1517 color: var(--text);
2ce1d0bClaude1518 font-size: var(--t-sm);
1519 font-weight: 500;
06d5ffeClaude1520 cursor: pointer;
2ce1d0bClaude1521 transition: all var(--t-fast) var(--ease);
1522 }
1523 .star-btn:hover { background: var(--bg-surface); border-color: var(--border-strong); text-decoration: none; }
1524 .star-btn.starred {
1525 color: var(--yellow);
958d26aClaude1526 border-color: rgba(251,191,36,0.4);
1527 background: rgba(251,191,36,0.08);
06d5ffeClaude1528 }
1529
2ce1d0bClaude1530 /* ============================================================ */
1531 /* User profile */
1532 /* ============================================================ */
06d5ffeClaude1533 .user-profile {
1534 display: flex;
1535 gap: 32px;
1536 margin-bottom: 32px;
2ce1d0bClaude1537 padding: 24px;
1538 background: var(--bg-elevated);
1539 border: 1px solid var(--border);
1540 border-radius: var(--r-lg);
06d5ffeClaude1541 }
1542 .user-avatar {
1543 width: 96px;
1544 height: 96px;
2ce1d0bClaude1545 border-radius: var(--r-full);
1546 background: var(--accent-gradient-soft);
1547 border: 1px solid var(--border-strong);
06d5ffeClaude1548 display: flex;
1549 align-items: center;
1550 justify-content: center;
2ce1d0bClaude1551 font-size: 36px;
1552 font-weight: 600;
1553 color: var(--text);
06d5ffeClaude1554 flex-shrink: 0;
2ce1d0bClaude1555 letter-spacing: -0.02em;
06d5ffeClaude1556 }
2ce1d0bClaude1557 .user-info h2 { font-size: var(--t-xl); margin-bottom: 2px; letter-spacing: -0.025em; }
1558 .user-info .username { font-size: var(--t-md); color: var(--text-muted); }
1559 .user-info .bio { font-size: var(--t-sm); color: var(--text-muted); margin-top: 10px; line-height: 1.55; }
06d5ffeClaude1560
2ce1d0bClaude1561 /* ============================================================ */
1562 /* New repo form */
1563 /* ============================================================ */
1564 .new-repo-form { max-width: 640px; }
1565 .new-repo-form h2 { margin-bottom: 24px; font-size: var(--t-xl); letter-spacing: -0.025em; }
1566 .visibility-options { display: flex; gap: 12px; margin-bottom: 20px; }
06d5ffeClaude1567 .visibility-option {
1568 flex: 1;
2ce1d0bClaude1569 padding: 16px;
06d5ffeClaude1570 border: 1px solid var(--border);
2ce1d0bClaude1571 border-radius: var(--r-md);
1572 background: var(--bg-elevated);
06d5ffeClaude1573 cursor: pointer;
2ce1d0bClaude1574 text-align: left;
1575 transition: all var(--t-fast) var(--ease);
1576 }
1577 .visibility-option:hover { border-color: var(--border-strong); background: var(--bg-surface); }
1578 .visibility-option:has(input:checked) {
1579 border-color: var(--accent);
1580 background: var(--accent-gradient-faint);
1581 box-shadow: 0 0 0 1px var(--accent);
06d5ffeClaude1582 }
1583 .visibility-option input { display: none; }
2ce1d0bClaude1584 .visibility-option .vis-label { font-size: var(--t-sm); font-weight: 600; margin-bottom: 4px; }
1585 .visibility-option .vis-desc { font-size: var(--t-xs); color: var(--text-muted); }
79136bbClaude1586
2ce1d0bClaude1587 /* ============================================================ */
1588 /* Issues */
1589 /* ============================================================ */
1590 .issue-tabs { display: flex; gap: 4px; }
1591 .issue-tabs a {
1592 color: var(--text-muted);
1593 font-size: var(--t-sm);
1594 font-weight: 500;
1595 padding: 6px 12px;
1596 border-radius: var(--r-sm);
1597 transition: all var(--t-fast) var(--ease);
1598 }
1599 .issue-tabs a:hover { color: var(--text); background: var(--bg-hover); text-decoration: none; }
1600 .issue-tabs a.active { color: var(--text); background: var(--bg-elevated); }
79136bbClaude1601
2ce1d0bClaude1602 .issue-list {
1603 border: 1px solid var(--border);
1604 border-radius: var(--r-md);
1605 overflow: hidden;
1606 background: var(--bg-elevated);
1607 }
79136bbClaude1608 .issue-item {
1609 display: flex;
2ce1d0bClaude1610 gap: 14px;
79136bbClaude1611 align-items: flex-start;
2ce1d0bClaude1612 padding: 14px 16px;
79136bbClaude1613 border-bottom: 1px solid var(--border);
2ce1d0bClaude1614 transition: background var(--t-fast) var(--ease);
79136bbClaude1615 }
1616 .issue-item:last-child { border-bottom: none; }
2ce1d0bClaude1617 .issue-item:hover { background: var(--bg-hover); }
1618 .issue-state-icon {
1619 font-size: 14px;
1620 padding-top: 2px;
1621 width: 18px;
1622 height: 18px;
1623 display: inline-flex;
1624 align-items: center;
1625 justify-content: center;
1626 border-radius: var(--r-full);
1627 flex-shrink: 0;
1628 }
79136bbClaude1629 .state-open { color: var(--green); }
958d26aClaude1630 .state-closed { color: #b69dff; }
2ce1d0bClaude1631 .issue-title {
1632 font-size: var(--t-base);
1633 font-weight: 600;
1634 line-height: 1.4;
1635 letter-spacing: -0.005em;
1636 }
79136bbClaude1637 .issue-title a { color: var(--text); }
2ce1d0bClaude1638 .issue-title a:hover { color: var(--text-link); text-decoration: none; }
1639 .issue-meta { font-size: var(--t-xs); color: var(--text-muted); margin-top: 4px; }
79136bbClaude1640
1641 .issue-badge {
1642 display: inline-flex;
1643 align-items: center;
2ce1d0bClaude1644 gap: 6px;
79136bbClaude1645 padding: 4px 12px;
2ce1d0bClaude1646 border-radius: var(--r-full);
1647 font-size: var(--t-sm);
79136bbClaude1648 font-weight: 500;
2ce1d0bClaude1649 line-height: 1.4;
79136bbClaude1650 }
958d26aClaude1651 .badge-open { background: rgba(52,211,153,0.10); color: var(--green); border: 1px solid rgba(52,211,153,0.35); }
1652 .badge-closed { background: rgba(182,157,255,0.10); color: #b69dff; border: 1px solid rgba(182,157,255,0.35); }
1653 .badge-merged { background: rgba(140,109,255,0.10); color: var(--accent); border: 1px solid rgba(140,109,255,0.35); }
2ce1d0bClaude1654 .state-merged { color: var(--accent); }
958d26aClaude1655 .ai-review { border-color: var(--accent); box-shadow: 0 0 0 1px rgba(140,109,255,0.3); }
79136bbClaude1656
2ce1d0bClaude1657 .issue-detail { max-width: 920px; }
79136bbClaude1658 .issue-comment-box {
1659 border: 1px solid var(--border);
2ce1d0bClaude1660 border-radius: var(--r-md);
79136bbClaude1661 margin-bottom: 16px;
1662 overflow: hidden;
2ce1d0bClaude1663 background: var(--bg-elevated);
79136bbClaude1664 }
1665 .comment-header {
1666 background: var(--bg-secondary);
2ce1d0bClaude1667 padding: 10px 16px;
1668 border-bottom: 1px solid var(--border);
1669 font-size: var(--t-sm);
1670 color: var(--text-muted);
1671 }
1672
1673 /* ============================================================ */
1674 /* Panel — flexible container used across many pages */
1675 /* ============================================================ */
1676 .panel {
1677 background: var(--bg-elevated);
1678 border: 1px solid var(--border);
1679 border-radius: var(--r-md);
1680 overflow: hidden;
1681 }
1682 .panel-item {
1683 display: flex;
1684 align-items: center;
1685 gap: 12px;
1686 padding: 12px 16px;
79136bbClaude1687 border-bottom: 1px solid var(--border);
2ce1d0bClaude1688 transition: background var(--t-fast) var(--ease);
1689 }
1690 .panel-item:last-child { border-bottom: none; }
1691 .panel-item:hover { background: var(--bg-hover); }
1692 .panel-empty {
1693 padding: 24px;
1694 text-align: center;
79136bbClaude1695 color: var(--text-muted);
2ce1d0bClaude1696 font-size: var(--t-sm);
79136bbClaude1697 }
1698
2ce1d0bClaude1699 /* ============================================================ */
1700 /* Search */
1701 /* ============================================================ */
79136bbClaude1702 .search-results .diff-file { margin-bottom: 12px; }
16b325cClaude1703
2ce1d0bClaude1704 /* ============================================================ */
1705 /* Timeline */
1706 /* ============================================================ */
1707 .timeline { position: relative; padding-left: 28px; }
16b325cClaude1708 .timeline::before {
1709 content: '';
1710 position: absolute;
1711 left: 4px;
1712 top: 8px;
1713 bottom: 8px;
1714 width: 2px;
2ce1d0bClaude1715 background: linear-gradient(180deg, var(--border) 0%, transparent 100%);
16b325cClaude1716 }
2ce1d0bClaude1717 .timeline-item { position: relative; padding-bottom: 16px; }
16b325cClaude1718 .timeline-dot {
1719 position: absolute;
2ce1d0bClaude1720 left: -28px;
1721 top: 8px;
1722 width: 12px;
1723 height: 12px;
1724 border-radius: var(--r-full);
1725 background: var(--accent-gradient);
16b325cClaude1726 border: 2px solid var(--bg);
2ce1d0bClaude1727 box-shadow: 0 0 0 1px var(--border-strong);
16b325cClaude1728 }
1729 .timeline-content {
2ce1d0bClaude1730 background: var(--bg-elevated);
16b325cClaude1731 border: 1px solid var(--border);
2ce1d0bClaude1732 border-radius: var(--r-md);
1733 padding: 14px 16px;
16b325cClaude1734 }
f1ab587Claude1735
2ce1d0bClaude1736 /* ============================================================ */
1737 /* Toggle switch */
1738 /* ============================================================ */
f1ab587Claude1739 .toggle-switch {
1740 position: relative;
1741 display: inline-block;
2ce1d0bClaude1742 width: 40px;
1743 height: 22px;
f1ab587Claude1744 flex-shrink: 0;
1745 margin-left: 16px;
1746 }
1747 .toggle-switch input { opacity: 0; width: 0; height: 0; }
1748 .toggle-slider {
1749 position: absolute;
1750 cursor: pointer;
1751 top: 0; left: 0; right: 0; bottom: 0;
1752 background: var(--bg-tertiary);
1753 border: 1px solid var(--border);
2ce1d0bClaude1754 border-radius: var(--r-full);
1755 transition: all var(--t-base) var(--ease);
f1ab587Claude1756 }
1757 .toggle-slider::before {
1758 content: '';
1759 position: absolute;
2ce1d0bClaude1760 height: 16px;
1761 width: 16px;
f1ab587Claude1762 left: 2px;
1763 bottom: 2px;
1764 background: var(--text-muted);
2ce1d0bClaude1765 border-radius: var(--r-full);
1766 transition: all var(--t-base) var(--ease);
f1ab587Claude1767 }
1768 .toggle-switch input:checked + .toggle-slider {
2ce1d0bClaude1769 background: var(--accent-gradient);
1770 border-color: transparent;
958d26aClaude1771 box-shadow: 0 0 0 1px rgba(140,109,255,0.4);
f1ab587Claude1772 }
1773 .toggle-switch input:checked + .toggle-slider::before {
2ce1d0bClaude1774 transform: translateX(18px);
f1ab587Claude1775 background: #fff;
1776 }
2ce1d0bClaude1777
1778 /* ============================================================ */
958d26aClaude1779 /* Utilities — gradient text, surfaces, dot-grid, skeleton */
2ce1d0bClaude1780 /* ============================================================ */
1781 .gradient-text {
1782 background: var(--accent-gradient);
1783 -webkit-background-clip: text;
1784 background-clip: text;
1785 -webkit-text-fill-color: transparent;
958d26aClaude1786 color: transparent;
2ce1d0bClaude1787 }
1788 .surface { background: var(--bg-elevated); border: 1px solid var(--border); border-radius: var(--r-md); }
1789 .surface-elevated { background: var(--bg-elevated); border: 1px solid var(--border); border-radius: var(--r-md); box-shadow: var(--elev-1); }
958d26aClaude1790 .surface-glow {
1791 background: var(--bg-elevated);
1792 border: 1px solid var(--border-strong);
1793 border-radius: var(--r-lg);
1794 box-shadow: var(--elev-2), var(--accent-glow);
1795 }
1796
1797 /* Dot-grid background utility — for hero surfaces, empty states, terminal blocks */
1798 .dot-grid {
1799 background-image: radial-gradient(rgba(255,255,255,0.04) 1px, transparent 1px);
1800 background-size: 22px 22px;
1801 }
1802 :root[data-theme='light'] .dot-grid {
1803 background-image: radial-gradient(rgba(15,16,28,0.06) 1px, transparent 1px);
1804 }
1805
1806 /* Hairline-grid background utility */
1807 .grid-lines {
1808 background-image:
1809 linear-gradient(to right, var(--border-subtle) 1px, transparent 1px),
1810 linear-gradient(to bottom, var(--border-subtle) 1px, transparent 1px);
1811 background-size: 56px 56px;
1812 }
1813
1814 /* Skeleton loader */
1815 .skeleton {
1816 background: linear-gradient(90deg, var(--bg-tertiary) 0%, var(--bg-surface) 50%, var(--bg-tertiary) 100%);
1817 background-size: 200% 100%;
1818 animation: skel 1.4s ease-in-out infinite;
1819 border-radius: var(--r-sm);
1820 }
1821 @keyframes skel { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }
1822
1823 /* Inline divider */
1824 .divider {
1825 border: 0;
1826 border-top: 1px solid var(--border);
1827 margin: var(--s-6) 0;
1828 }
1829 .divider-vert {
1830 width: 1px;
1831 align-self: stretch;
1832 background: var(--border);
1833 margin: 0 var(--s-3);
1834 }
1835
1836 /* Stagger fade-in helper — apply to a parent, animate children */
1837 .stagger > * {
1838 opacity: 0;
1839 transform: translateY(10px);
1840 animation: stagger-in 600ms var(--ease-out-expo) forwards;
1841 }
1842 .stagger > *:nth-child(1) { animation-delay: 0ms; }
1843 .stagger > *:nth-child(2) { animation-delay: 60ms; }
1844 .stagger > *:nth-child(3) { animation-delay: 120ms; }
1845 .stagger > *:nth-child(4) { animation-delay: 180ms; }
1846 .stagger > *:nth-child(5) { animation-delay: 240ms; }
1847 .stagger > *:nth-child(6) { animation-delay: 300ms; }
1848 .stagger > *:nth-child(7) { animation-delay: 360ms; }
1849 .stagger > *:nth-child(8) { animation-delay: 420ms; }
1850 @keyframes stagger-in {
1851 to { opacity: 1; transform: translateY(0); }
1852 }
1853
1854 /* Tag pill — used for labels, topics */
1855 .tag {
1856 display: inline-flex;
1857 align-items: center;
1858 gap: 5px;
1859 padding: 2px 9px;
1860 border-radius: var(--r-full);
1861 font-size: 11px;
1862 font-weight: 500;
1863 background: var(--bg-tertiary);
1864 border: 1px solid var(--border);
1865 color: var(--text-muted);
1866 line-height: 1.5;
1867 font-family: var(--font-mono);
1868 letter-spacing: 0.01em;
1869 }
1870 .tag-accent {
1871 background: var(--accent-gradient-faint);
1872 border-color: rgba(140,109,255,0.30);
1873 color: var(--accent);
1874 }
2ce1d0bClaude1875
1876 /* Command palette polish */
1877 .cmdk-item { transition: background var(--t-fast) var(--ease); }
1878 .cmdk-item:hover { background: var(--bg-hover) !important; }
1879 .cmdk-active { background: var(--accent-gradient-faint) !important; border-left: 2px solid var(--accent) !important; }
1880
1881 /* Reduced motion preference */
1882 @media (prefers-reduced-motion: reduce) {
1883 *, *::before, *::after {
1884 animation-duration: 0.01ms !important;
1885 animation-iteration-count: 1 !important;
1886 transition-duration: 0.01ms !important;
1887 }
1888 }
1889
1890 /* Tablet + below */
1891 @media (max-width: 768px) {
1892 main { padding: 20px 16px 40px; }
1893 header { padding: 0 16px; }
1894 .nav-search { display: none; }
1895 .repo-header { font-size: var(--t-md); }
1896 .card-grid { grid-template-columns: 1fr; }
1897 .auth-container { margin: 32px 16px; padding: 24px; }
1898 .visibility-options { flex-direction: column; }
1899 }
1900
1901 /* Scrollbar styling — subtle, themed */
1902 ::-webkit-scrollbar { width: 10px; height: 10px; }
1903 ::-webkit-scrollbar-track { background: transparent; }
1904 ::-webkit-scrollbar-thumb {
1905 background: var(--bg-surface);
1906 border: 2px solid var(--bg);
1907 border-radius: var(--r-full);
1908 }
1909 ::-webkit-scrollbar-thumb:hover { background: var(--border-strong); }
fc1817aClaude1910`;