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.tsxBlame1911 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>
b0148e9Claude114 <a href="/features">Features</a>
115 <a href="/pricing">Pricing</a>
958d26aClaude116 <a href="/explore">Explore</a>
117 <a href="/marketplace">Marketplace</a>
118 </div>
119 <div class="footer-col">
120 <div class="footer-col-title">Platform</div>
b0148e9Claude121 <a href="/help">Quickstart</a>
958d26aClaude122 <a href="/status">Status</a>
123 <a href="/api/graphql">GraphQL</a>
124 <a href="/mcp">MCP server</a>
125 </div>
126 <div class="footer-col">
b0148e9Claude127 <div class="footer-col-title">Company</div>
128 <a href="/about">About</a>
958d26aClaude129 <a href="/terms">Terms</a>
130 <a href="/privacy">Privacy</a>
131 <a href="/acceptable-use">Acceptable use</a>
132 </div>
133 </div>
134 </div>
135 <div class="footer-bottom">
136 <span>&copy; {new Date().getFullYear()} gluecron</span>
137 <span>shipped with intent · v1</span>
36b4cbdClaude138 </div>
fc1817aClaude139 </footer>
699e5c7Claude140 {/* Block I4 — Command palette shell (hidden by default) */}
141 <div
142 id="cmdk-backdrop"
143 style="display:none;position:fixed;inset:0;background:rgba(0,0,0,0.5);z-index:9998"
144 />
145 <div
146 id="cmdk-panel"
147 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"
148 >
149 <input
150 id="cmdk-input"
151 type="text"
152 placeholder="Type a command..."
153 aria-label="Command palette"
154 style="width:100%;padding:12px 16px;background:transparent;color:var(--text);border:0;border-bottom:1px solid var(--border);outline:none;font-size:14px"
155 />
156 <div id="cmdk-list" style="max-height:60vh;overflow-y:auto" />
157 </div>
45e31d0Claude158 <script>{clientJs}</script>
699e5c7Claude159 <script>{pwaRegisterScript}</script>
160 <script>{navScript}</script>
fc1817aClaude161 </body>
162 </html>
163 );
164};
165
6fc53bdClaude166// Runs before paint — reads the theme cookie and flips data-theme so there's
167// no dark-to-light flash on load. SSR default is dark.
168const themeInitScript = `
169 (function(){
170 try {
171 var m = document.cookie.match(/(?:^|; )theme=([^;]+)/);
172 var t = m ? decodeURIComponent(m[1]) : 'dark';
173 if (t !== 'light' && t !== 'dark') t = 'dark';
174 document.documentElement.setAttribute('data-theme', t);
175 } catch(_){}
176 })();
177`;
178
eae38d1Claude179// Block G1 — register service worker for offline / install support.
180// Kept inline (and tiny) so we don't block first paint.
181const pwaRegisterScript = `
182 if ('serviceWorker' in navigator) {
183 window.addEventListener('load', function(){
184 navigator.serviceWorker.register('/sw.js').catch(function(){});
185 });
186 }
187`;
188
3ef4c9dClaude189const navScript = `
190 (function(){
191 var chord = null;
192 var chordTimer = null;
193 function isTyping(t){
194 t = t || {};
195 var tag = (t.tagName || '').toLowerCase();
196 return tag === 'input' || tag === 'textarea' || t.isContentEditable;
197 }
71cd5ecClaude198
199 // ---------- Block I4 — Command palette ----------
200 var COMMANDS = [
201 { label: 'Go to Dashboard', href: '/dashboard', kw: 'home' },
202 { label: 'Go to Explore', href: '/explore', kw: 'browse discover' },
203 { label: 'Go to Notifications', href: '/notifications', kw: 'inbox' },
204 { label: 'Go to Ask AI', href: '/ask', kw: 'chat assistant' },
205 { label: 'Create new repository', href: '/new', kw: 'add create' },
206 { label: 'Marketplace', href: '/marketplace', kw: 'apps store' },
207 { label: 'Installed apps', href: '/settings/apps', kw: 'my apps' },
208 { label: 'Register new app', href: '/developer/apps-new', kw: 'developer create' },
209 { label: 'Keyboard shortcuts', href: '/shortcuts', kw: 'help keys' },
210 { label: 'Settings (profile)', href: '/settings', kw: 'account' },
211 { label: '2FA settings', href: '/settings/2fa', kw: 'two factor security' },
212 { label: 'Passkeys settings', href: '/settings/passkeys', kw: 'webauthn' },
213 { label: 'Personal access tokens', href: '/settings/tokens', kw: 'pat api' },
214 { label: 'Billing + quotas', href: '/settings/billing', kw: 'plans money' },
215 { label: 'Audit log (personal)', href: '/settings/audit', kw: 'history' },
216 { label: 'Gists', href: '/gists', kw: 'snippets' },
217 { label: 'GraphQL explorer', href: '/api/graphql', kw: 'api query' },
218 { label: 'Admin dashboard', href: '/admin', kw: 'superuser' },
219 { label: 'Toggle theme', href: '/theme/toggle', kw: 'dark light mode' }
220 ];
221
222 function fuzzyMatch(item, q){
223 if (!q) return true;
224 var hay = (item.label + ' ' + (item.kw||'') + ' ' + item.href).toLowerCase();
225 q = q.toLowerCase();
226 var qi = 0;
227 for (var i = 0; i < hay.length && qi < q.length; i++) {
228 if (hay[i] === q[qi]) qi++;
229 }
230 return qi === q.length;
231 }
232
233 var backdrop, panel, input, list, selected = 0, filtered = COMMANDS.slice();
234
235 function render(){
236 if (!list) return;
237 var html = '';
238 for (var i = 0; i < filtered.length; i++) {
239 var item = filtered[i];
240 var cls = i === selected ? 'cmdk-item cmdk-active' : 'cmdk-item';
241 var bg = i === selected ? 'background:var(--bg);' : '';
ea52715copilot-swe-agent[bot]242 html += '<div class="' + cls + '" data-idx="' + i + '" data-url="' + item.href + '"' +
71cd5ecClaude243 ' style="padding:10px 16px;cursor:pointer;border-bottom:1px solid var(--border);' + bg + '">' +
244 '<div>' + item.label + '</div>' +
245 '<div style="font-size:11px;color:var(--text-muted)">' + item.href + '</div>' +
246 '</div>';
247 }
248 if (filtered.length === 0) {
249 html = '<div style="padding:16px;color:var(--text-muted);text-align:center">No matches.</div>';
250 }
251 list.innerHTML = html;
252 }
253
254 function openPalette(){
255 backdrop = document.getElementById('cmdk-backdrop');
256 panel = document.getElementById('cmdk-panel');
257 input = document.getElementById('cmdk-input');
258 list = document.getElementById('cmdk-list');
259 if (!backdrop || !panel) return;
260 backdrop.style.display = 'block';
261 panel.style.display = 'block';
262 input.value = '';
263 selected = 0;
264 filtered = COMMANDS.slice();
265 render();
266 input.focus();
267 }
268 function closePalette(){
269 if (backdrop) backdrop.style.display = 'none';
270 if (panel) panel.style.display = 'none';
271 }
272 function go(href){ closePalette(); window.location.href = href; }
273
274 document.addEventListener('click', function(e){
275 var t = e.target;
276 if (t && t.id === 'cmdk-backdrop') { closePalette(); return; }
277 var item = t && t.closest && t.closest('.cmdk-item');
ea52715copilot-swe-agent[bot]278 if (item) { go(item.getAttribute('data-url')); }
71cd5ecClaude279 });
280
281 document.addEventListener('input', function(e){
282 if (e.target && e.target.id === 'cmdk-input') {
283 var q = e.target.value;
284 filtered = COMMANDS.filter(function(c){ return fuzzyMatch(c, q); });
285 selected = 0;
286 render();
287 }
288 });
289
3ef4c9dClaude290 document.addEventListener('keydown', function(e){
71cd5ecClaude291 // Palette-scoped keys take priority when open
292 if (panel && panel.style.display === 'block') {
293 if (e.key === 'Escape') { e.preventDefault(); closePalette(); return; }
294 if (e.key === 'ArrowDown') {
295 e.preventDefault();
296 selected = Math.min(filtered.length - 1, selected + 1);
297 render();
298 return;
299 }
300 if (e.key === 'ArrowUp') {
301 e.preventDefault();
302 selected = Math.max(0, selected - 1);
303 render();
304 return;
305 }
306 if (e.key === 'Enter') {
307 e.preventDefault();
308 var item = filtered[selected];
309 if (item) go(item.href);
310 return;
311 }
312 return;
313 }
314
3ef4c9dClaude315 if (isTyping(e.target)) return;
316 // Single key shortcuts
317 if (e.key === '/') {
318 var el = document.querySelector('.nav-search input');
319 if (el) { e.preventDefault(); el.focus(); return; }
320 }
321 if ((e.metaKey||e.ctrlKey) && e.key.toLowerCase() === 'k') {
71cd5ecClaude322 e.preventDefault();
323 openPalette();
324 return;
3ef4c9dClaude325 }
326 if (e.key === '?' && !e.ctrlKey && !e.metaKey) {
327 e.preventDefault(); window.location.href = '/shortcuts'; return;
328 }
329 if (e.key === 'n' && !e.ctrlKey && !e.metaKey) {
330 e.preventDefault(); window.location.href = '/new'; return;
331 }
332 // "g" chord
333 if (e.key === 'g' && !e.ctrlKey && !e.metaKey) {
334 chord = 'g';
335 clearTimeout(chordTimer);
336 chordTimer = setTimeout(function(){ chord = null; }, 1200);
337 return;
338 }
339 if (chord === 'g') {
340 if (e.key === 'd') { e.preventDefault(); window.location.href = '/dashboard'; }
341 else if (e.key === 'n') { e.preventDefault(); window.location.href = '/notifications'; }
342 else if (e.key === 'e') { e.preventDefault(); window.location.href = '/explore'; }
343 else if (e.key === 'a') { e.preventDefault(); window.location.href = '/ask'; }
344 chord = null;
345 }
346 });
347 })();
348`;
349
fc1817aClaude350const css = `
2ce1d0bClaude351 /* ================================================================
958d26aClaude352 * Gluecron design system — 2026.05 "Editorial-Technical"
353 * Slate-noir base · refined violet signature · hairline geometry ·
354 * mono-as-feature · cinematic motion · Inter Tight + JetBrains Mono.
355 * All class names preserved for back-compat across 50+ route views.
2ce1d0bClaude356 * ============================================================== */
6fc53bdClaude357 :root, :root[data-theme='dark'] {
958d26aClaude358 /* Surfaces — slate, not black. More depth, less crush. */
359 --bg: #08090f;
360 --bg-secondary: #0c0d14;
361 --bg-tertiary: #11131c;
362 --bg-elevated: #0f111a;
363 --bg-surface: #161826;
364 --bg-hover: rgba(255,255,255,0.04);
365 --bg-active: rgba(255,255,255,0.08);
366 --bg-inset: rgba(0,0,0,0.30);
367
368 /* Borders — three weights, used deliberately */
369 --border: rgba(255,255,255,0.06);
370 --border-subtle: rgba(255,255,255,0.035);
371 --border-strong: rgba(255,255,255,0.13);
372 --border-focus: rgba(140,109,255,0.55);
373
374 /* Text */
375 --text: #ededf2;
376 --text-strong: #f7f7fb;
377 --text-muted: #8b8c9c;
378 --text-faint: #555665;
379 --text-link: #b69dff;
380
381 /* Accent — refined violet (less candy), warm amber as secondary signal */
382 --accent: #8c6dff;
383 --accent-2: #36c5d6;
384 --accent-warm: #ffb45e;
385 --accent-hover: #a48bff;
386 --accent-pressed:#7559e8;
387 --accent-gradient: linear-gradient(135deg, #8c6dff 0%, #36c5d6 100%);
388 --accent-gradient-soft: linear-gradient(135deg, rgba(140,109,255,0.18) 0%, rgba(54,197,214,0.18) 100%);
389 --accent-gradient-faint: linear-gradient(135deg, rgba(140,109,255,0.07) 0%, rgba(54,197,214,0.07) 100%);
390 --accent-glow: 0 0 24px rgba(140,109,255,0.28);
391
392 /* Semantic */
393 --green: #34d399;
394 --red: #f87171;
395 --yellow: #fbbf24;
396 --amber: #fbbf24;
397 --blue: #60a5fa;
398
399 /* Type — Inter Tight for sans (tighter metrics) */
4c47454Claude400 --font-mono: 'JetBrains Mono', 'SF Mono', 'Cascadia Code', 'Fira Code', ui-monospace, monospace;
958d26aClaude401 --font-sans: 'Inter Tight', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
402 --font-display: 'Inter Tight', 'Inter', -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
403 --mono-feat: 'calt', 'liga', 'ss01';
404
405 /* Radius — sharper than before */
406 --r-sm: 5px;
407 --r: 7px;
408 --r-md: 9px;
409 --r-lg: 12px;
410 --r-xl: 16px;
411 --r-2xl: 22px;
412 --r-full: 9999px;
413 --radius: 7px;
414
415 /* Type scale — bigger display sizes for editorial feel */
416 --t-xs: 11px;
417 --t-sm: 13px;
418 --t-base: 14px;
419 --t-md: 16px;
420 --t-lg: 20px;
421 --t-xl: 28px;
422 --t-2xl: 40px;
423 --t-3xl: 56px;
424 --t-display: 72px;
425 --t-display-lg:96px;
426
427 /* Spacing — 4px base */
2ce1d0bClaude428 --s-0: 0;
958d26aClaude429 --s-1: 4px; --s-2: 8px; --s-3: 12px; --s-4: 16px;
430 --s-5: 20px; --s-6: 24px; --s-7: 28px; --s-8: 32px;
431 --s-10:40px; --s-12:48px; --s-14:56px; --s-16:64px;
432 --s-20:80px; --s-24:96px; --s-32:128px;
433
434 /* Elevation — softer + more layered */
435 --elev-0: 0 0 0 1px var(--border);
436 --elev-1: 0 1px 2px rgba(0,0,0,0.50), 0 0 0 1px var(--border);
437 --elev-2: 0 8px 24px -8px rgba(0,0,0,0.60), 0 0 0 1px var(--border);
438 --elev-3: 0 20px 48px -12px rgba(0,0,0,0.70), 0 0 0 1px var(--border-strong);
439 --elev-glow: 0 0 0 1px rgba(140,109,255,0.40), 0 0 32px -4px rgba(140,109,255,0.30);
440 --ring: 0 0 0 3px rgba(140,109,255,0.28);
441 --ring-warn: 0 0 0 3px rgba(251,191,36,0.28);
442 --ring-err: 0 0 0 3px rgba(248,113,113,0.28);
443
444 /* Motion */
445 --ease: cubic-bezier(0.16, 1, 0.3, 1);
446 --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
447 --ease-out-expo: cubic-bezier(0.19, 1, 0.22, 1);
448 --ease-out-quart: cubic-bezier(0.25, 1, 0.5, 1);
449 --t-fast: 120ms;
450 --t-base: 200ms;
451 --t-slow: 360ms;
452 --t-slower:560ms;
453
454 --header-h: 60px;
fc1817aClaude455 }
456
6fc53bdClaude457 :root[data-theme='light'] {
958d26aClaude458 --bg: #fbfbfc;
4c47454Claude459 --bg-secondary: #ffffff;
958d26aClaude460 --bg-tertiary: #f3f3f6;
461 --bg-elevated: #ffffff;
462 --bg-surface: #f6f6f9;
463 --bg-hover: rgba(0,0,0,0.035);
464 --bg-active: rgba(0,0,0,0.07);
465 --bg-inset: rgba(0,0,0,0.04);
466
467 --border: rgba(15,16,28,0.08);
468 --border-subtle: rgba(15,16,28,0.04);
469 --border-strong: rgba(15,16,28,0.16);
470
471 --text: #0e1020;
472 --text-strong: #050617;
473 --text-muted: #5a5b70;
474 --text-faint: #8a8b9e;
475 --text-link: #6d4dff;
476
477 --accent: #6d4dff;
478 --accent-2: #0891b2;
479 --accent-hover: #5a3df0;
480 --accent-pressed:#4a30d6;
481 --accent-glow: 0 0 24px rgba(109,77,255,0.18);
482
483 --green: #059669;
484 --red: #dc2626;
4c47454Claude485 --yellow: #d97706;
958d26aClaude486
487 --elev-1: 0 1px 2px rgba(15,16,28,0.06), 0 0 0 1px var(--border);
488 --elev-2: 0 8px 24px -10px rgba(15,16,28,0.10), 0 0 0 1px var(--border);
489 --elev-3: 0 20px 48px -16px rgba(15,16,28,0.14), 0 0 0 1px var(--border-strong);
6fc53bdClaude490 }
491
492 /* Theme toggle — show the icon for the *opposite* theme so users see what they'll switch to. */
958d26aClaude493 .nav-theme { display: inline-flex; align-items: center; font-size: 15px; line-height: 1; opacity: 0.85; }
494 .nav-theme:hover { opacity: 1; }
6fc53bdClaude495 :root[data-theme='dark'] .theme-icon-dark { display: none; }
496 :root[data-theme='light'] .theme-icon-light { display: none; }
497
fc1817aClaude498 * { margin: 0; padding: 0; box-sizing: border-box; }
958d26aClaude499 *::selection { background: rgba(140,109,255,0.32); color: var(--text-strong); }
2ce1d0bClaude500
958d26aClaude501 html { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-rendering: optimizeLegibility; }
fc1817aClaude502
503 body {
504 font-family: var(--font-sans);
505 background: var(--bg);
506 color: var(--text);
2ce1d0bClaude507 line-height: 1.55;
958d26aClaude508 letter-spacing: -0.011em;
fc1817aClaude509 min-height: 100vh;
510 display: flex;
511 flex-direction: column;
958d26aClaude512 font-feature-settings: 'cv11', 'ss01', 'ss03', 'calt';
2ce1d0bClaude513 }
514
958d26aClaude515 /* Whole-page atmosphere: very subtle gradient + dot-grid layered behind everything.
516 Keeps every page feeling like part of the same product without competing with hero art. */
2ce1d0bClaude517 body::before {
518 content: '';
519 position: fixed;
520 inset: 0;
521 pointer-events: none;
958d26aClaude522 z-index: -2;
2ce1d0bClaude523 background:
958d26aClaude524 radial-gradient(70% 55% at 85% -20%, rgba(140,109,255,0.07), transparent 65%),
525 radial-gradient(55% 45% at -10% 115%, rgba(54,197,214,0.05), transparent 65%);
526 }
527 body::after {
528 content: '';
529 position: fixed;
530 inset: 0;
531 pointer-events: none;
532 z-index: -1;
533 background-image: radial-gradient(rgba(255,255,255,0.025) 1px, transparent 1px);
534 background-size: 28px 28px;
535 background-position: 0 0;
536 opacity: 0.55;
537 mask-image: radial-gradient(ellipse at 50% 0%, #000 0%, transparent 70%);
538 -webkit-mask-image: radial-gradient(ellipse at 50% 0%, #000 0%, transparent 70%);
539 }
540 :root[data-theme='light'] body::before { opacity: 0.55; }
541 :root[data-theme='light'] body::after {
542 background-image: radial-gradient(rgba(15,16,28,0.06) 1px, transparent 1px);
543 opacity: 0.4;
fc1817aClaude544 }
2ce1d0bClaude545
546 a { color: var(--text-link); text-decoration: none; transition: color var(--t-fast) var(--ease); }
547 a:hover { color: var(--accent-hover); text-decoration: none; }
fc1817aClaude548
958d26aClaude549 /* Heading scale — confident, editorial, tight tracking */
550 h1, h2, h3, h4, h5, h6 {
551 font-family: var(--font-display);
2ce1d0bClaude552 font-weight: 600;
958d26aClaude553 letter-spacing: -0.022em;
554 line-height: 1.18;
555 color: var(--text-strong);
556 }
557 h1 { font-size: var(--t-xl); letter-spacing: -0.028em; }
558 h2 { font-size: var(--t-lg); letter-spacing: -0.022em; }
559 h3 { font-size: var(--t-md); font-weight: 600; letter-spacing: -0.015em; }
560 h4 { font-size: var(--t-base); font-weight: 600; letter-spacing: -0.01em; }
561 h5, h6 { font-size: var(--t-sm); font-weight: 600; letter-spacing: -0.005em; }
562
563 /* Editorial display heading utility — used by landing + marketing pages */
564 .display {
565 font-family: var(--font-display);
566 font-size: clamp(40px, 7.5vw, 96px);
567 line-height: 0.98;
568 letter-spacing: -0.04em;
569 font-weight: 600;
570 color: var(--text-strong);
2ce1d0bClaude571 }
fc1817aClaude572
958d26aClaude573 /* Eyebrow — uppercase mono label that sits above section headings */
574 .eyebrow {
575 display: inline-flex;
576 align-items: center;
577 gap: 8px;
578 font-family: var(--font-mono);
579 font-size: 11px;
580 font-weight: 500;
581 letter-spacing: 0.14em;
582 text-transform: uppercase;
583 color: var(--accent);
584 margin-bottom: var(--s-3);
585 }
586 .eyebrow::before {
587 content: '';
588 width: 18px;
589 height: 1px;
590 background: currentColor;
591 opacity: 0.6;
592 }
593
594 /* Section header — paired eyebrow + title + lede */
595 .section-header { max-width: 720px; margin: 0 auto var(--s-10); text-align: center; }
596 .section-header.left { text-align: left; margin-left: 0; margin-right: auto; }
597 .section-header h2 {
598 font-size: clamp(28px, 4vw, 44px);
599 line-height: 1.05;
600 letter-spacing: -0.028em;
601 margin-bottom: var(--s-3);
602 }
603 .section-header p {
604 color: var(--text-muted);
605 font-size: var(--t-md);
606 line-height: 1.6;
607 max-width: 580px;
608 margin: 0 auto;
609 }
610 .section-header.left p { margin-left: 0; }
611
612 code, kbd, samp {
2ce1d0bClaude613 font-family: var(--font-mono);
958d26aClaude614 font-feature-settings: var(--mono-feat);
615 }
616 code {
617 font-size: 0.9em;
2ce1d0bClaude618 background: var(--bg-tertiary);
958d26aClaude619 border: 1px solid var(--border-subtle);
2ce1d0bClaude620 padding: 1px 6px;
621 border-radius: var(--r-sm);
622 color: var(--text);
623 }
958d26aClaude624 kbd, .kbd {
625 display: inline-flex;
626 align-items: center;
627 padding: 1px 6px;
628 font-family: var(--font-mono);
629 font-size: 11px;
630 background: var(--bg-elevated);
631 border: 1px solid var(--border);
632 border-bottom-width: 2px;
633 border-radius: 4px;
634 color: var(--text);
635 line-height: 1.5;
636 vertical-align: middle;
637 }
2ce1d0bClaude638
958d26aClaude639 /* Mono utility for technical chrome (paths, IDs, dates) */
640 .mono { font-family: var(--font-mono); font-feature-settings: var(--mono-feat); font-size: 0.96em; }
641 .meta-mono { font-family: var(--font-mono); font-size: var(--t-xs); color: var(--text-muted); letter-spacing: 0; }
642
643 /* Pre-launch banner — slim, refined, mono caption */
4a52a98Claude644 .prelaunch-banner {
958d26aClaude645 position: relative;
2ce1d0bClaude646 background:
958d26aClaude647 linear-gradient(180deg, rgba(251,191,36,0.10), rgba(251,191,36,0.03)),
2ce1d0bClaude648 var(--bg);
958d26aClaude649 border-bottom: 1px solid rgba(251,191,36,0.28);
4a52a98Claude650 color: var(--yellow);
958d26aClaude651 padding: 7px 24px;
652 font-family: var(--font-mono);
653 font-size: 11px;
4a52a98Claude654 font-weight: 500;
655 text-align: center;
2ce1d0bClaude656 line-height: 1.5;
958d26aClaude657 letter-spacing: 0.04em;
658 text-transform: uppercase;
659 }
660 .prelaunch-banner::before {
661 content: '◆';
662 margin-right: 8px;
663 font-size: 9px;
664 opacity: 0.7;
665 vertical-align: 1px;
4a52a98Claude666 }
667
958d26aClaude668 /* Header — sticky, blurred, hairline border, taller for breathing room */
fc1817aClaude669 header {
2ce1d0bClaude670 position: sticky;
671 top: 0;
672 z-index: 100;
fc1817aClaude673 border-bottom: 1px solid var(--border);
2ce1d0bClaude674 padding: 0 24px;
675 height: var(--header-h);
958d26aClaude676 background: rgba(8,9,15,0.72);
677 backdrop-filter: saturate(180%) blur(18px);
678 -webkit-backdrop-filter: saturate(180%) blur(18px);
fc1817aClaude679 }
958d26aClaude680 :root[data-theme='light'] header { background: rgba(251,251,252,0.78); }
fc1817aClaude681
06d5ffeClaude682 header nav {
683 display: flex;
684 align-items: center;
958d26aClaude685 gap: 18px;
686 max-width: 1240px;
06d5ffeClaude687 margin: 0 auto;
2ce1d0bClaude688 height: 100%;
689 }
690 .logo {
958d26aClaude691 font-family: var(--font-display);
692 font-size: 16px;
2ce1d0bClaude693 font-weight: 700;
958d26aClaude694 letter-spacing: -0.025em;
695 color: var(--text-strong);
2ce1d0bClaude696 display: inline-flex;
697 align-items: center;
958d26aClaude698 gap: 9px;
699 transition: opacity var(--t-fast) var(--ease);
06d5ffeClaude700 }
2ce1d0bClaude701 .logo::before {
702 content: '';
958d26aClaude703 width: 20px; height: 20px;
704 border-radius: 6px;
2ce1d0bClaude705 background: var(--accent-gradient);
958d26aClaude706 box-shadow:
707 inset 0 1px 0 rgba(255,255,255,0.25),
708 0 0 0 1px rgba(140,109,255,0.45),
709 0 0 20px rgba(140,109,255,0.30);
2ce1d0bClaude710 flex-shrink: 0;
958d26aClaude711 transition: transform var(--t-base) var(--ease-spring), box-shadow var(--t-base) var(--ease);
712 }
713 .logo:hover { text-decoration: none; color: var(--text-strong); }
714 .logo:hover::before {
715 transform: rotate(8deg) scale(1.05);
716 box-shadow:
717 inset 0 1px 0 rgba(255,255,255,0.30),
718 0 0 0 1px rgba(140,109,255,0.55),
719 0 0 28px rgba(140,109,255,0.45);
2ce1d0bClaude720 }
fc1817aClaude721
2ce1d0bClaude722 .nav-search {
723 flex: 1;
958d26aClaude724 max-width: 360px;
725 margin: 0 4px 0 8px;
726 position: relative;
2ce1d0bClaude727 }
728 .nav-search input {
729 width: 100%;
958d26aClaude730 padding: 7px 12px 7px 32px;
2ce1d0bClaude731 background: var(--bg-tertiary);
732 border: 1px solid var(--border);
733 border-radius: var(--r-sm);
734 color: var(--text);
735 font-family: var(--font-sans);
736 font-size: var(--t-sm);
958d26aClaude737 transition: border-color var(--t-fast) var(--ease), background var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease);
738 }
739 .nav-search::before {
740 content: '';
741 position: absolute;
742 left: 11px; top: 50%;
743 transform: translateY(-50%);
744 width: 12px; height: 12px;
745 border: 1.5px solid var(--text-faint);
746 border-radius: 50%;
747 pointer-events: none;
748 }
749 .nav-search::after {
750 content: '';
751 position: absolute;
752 left: 19px; top: calc(50% + 4px);
753 width: 5px; height: 1.5px;
754 background: var(--text-faint);
755 transform: rotate(45deg);
756 pointer-events: none;
2ce1d0bClaude757 }
758 .nav-search input::placeholder { color: var(--text-faint); }
759 .nav-search input:focus {
760 outline: none;
761 background: var(--bg-secondary);
958d26aClaude762 border-color: var(--border-focus);
763 box-shadow: var(--ring);
2ce1d0bClaude764 }
06d5ffeClaude765
958d26aClaude766 .nav-right { display: flex; align-items: center; gap: 2px; margin-left: auto; }
2ce1d0bClaude767 .nav-link {
958d26aClaude768 position: relative;
2ce1d0bClaude769 color: var(--text-muted);
770 font-size: var(--t-sm);
771 font-weight: 500;
958d26aClaude772 padding: 7px 11px;
2ce1d0bClaude773 border-radius: var(--r-sm);
958d26aClaude774 transition: color var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
2ce1d0bClaude775 }
776 .nav-link:hover {
958d26aClaude777 color: var(--text-strong);
2ce1d0bClaude778 background: var(--bg-hover);
779 text-decoration: none;
780 }
958d26aClaude781 .nav-link.active { color: var(--text-strong); }
782 .nav-link.active::after {
783 content: '';
784 position: absolute;
785 left: 11px; right: 11px;
786 bottom: -1px;
787 height: 2px;
788 background: var(--accent-gradient);
789 border-radius: 2px;
790 }
2ce1d0bClaude791 .nav-user {
958d26aClaude792 color: var(--text-strong);
2ce1d0bClaude793 font-weight: 600;
794 font-size: var(--t-sm);
795 padding: 6px 10px;
796 border-radius: var(--r-sm);
958d26aClaude797 margin-left: 6px;
2ce1d0bClaude798 transition: background var(--t-fast) var(--ease);
799 }
958d26aClaude800 .nav-user::before {
801 content: '';
802 display: inline-block;
803 width: 8px; height: 8px;
804 background: var(--green);
805 border-radius: 50%;
806 margin-right: 7px;
807 box-shadow: 0 0 8px rgba(52,211,153,0.5);
808 vertical-align: 1px;
809 }
2ce1d0bClaude810 .nav-user:hover { background: var(--bg-hover); text-decoration: none; }
811
812 main {
958d26aClaude813 max-width: 1240px;
2ce1d0bClaude814 margin: 0 auto;
958d26aClaude815 padding: 36px 24px 80px;
2ce1d0bClaude816 flex: 1;
817 width: 100%;
818 }
fc1817aClaude819
958d26aClaude820 /* Editorial footer: link grid + tagline row */
fc1817aClaude821 footer {
822 border-top: 1px solid var(--border);
958d26aClaude823 padding: 56px 24px 40px;
824 color: var(--text-muted);
825 font-size: var(--t-sm);
826 background:
827 linear-gradient(180deg, transparent 0%, rgba(140,109,255,0.025) 100%),
828 var(--bg);
829 }
830 footer .footer-inner {
831 max-width: 1240px;
832 margin: 0 auto;
833 display: grid;
834 grid-template-columns: 1fr auto;
835 gap: 48px;
836 align-items: start;
837 }
838 footer .footer-brand .logo { margin-bottom: var(--s-3); }
839 footer .footer-tag {
840 color: var(--text-muted);
841 font-size: var(--t-sm);
842 max-width: 320px;
843 line-height: 1.55;
844 }
845 footer .footer-links {
846 display: grid;
847 grid-template-columns: repeat(3, minmax(120px, auto));
848 gap: 0 56px;
849 }
850 footer .footer-col-title {
851 font-family: var(--font-mono);
852 font-size: 11px;
853 text-transform: uppercase;
854 letter-spacing: 0.14em;
855 color: var(--text-faint);
856 margin-bottom: var(--s-3);
857 }
858 footer .footer-col a {
859 display: block;
860 color: var(--text-muted);
861 font-size: var(--t-sm);
862 padding: 5px 0;
863 transition: color var(--t-fast) var(--ease);
864 }
865 footer .footer-col a:hover { color: var(--text-strong); text-decoration: none; }
866 footer .footer-bottom {
867 max-width: 1240px;
868 margin: 40px auto 0;
869 padding-top: 24px;
870 border-top: 1px solid var(--border-subtle);
871 display: flex;
872 justify-content: space-between;
873 align-items: center;
2ce1d0bClaude874 color: var(--text-faint);
875 font-size: var(--t-xs);
958d26aClaude876 font-family: var(--font-mono);
877 letter-spacing: 0.02em;
878 }
879 footer .footer-bottom a { color: var(--text-faint); }
880 footer .footer-bottom a:hover { color: var(--text-muted); text-decoration: none; }
881 @media (max-width: 768px) {
882 footer .footer-inner { grid-template-columns: 1fr; gap: 32px; }
883 footer .footer-links { grid-template-columns: repeat(2, 1fr); gap: 24px 32px; }
884 footer .footer-bottom { flex-direction: column; gap: 8px; text-align: center; }
fc1817aClaude885 }
886
2ce1d0bClaude887 /* ============================================================ */
888 /* Buttons */
889 /* ============================================================ */
06d5ffeClaude890 .btn {
891 display: inline-flex;
892 align-items: center;
2ce1d0bClaude893 justify-content: center;
958d26aClaude894 gap: 7px;
2ce1d0bClaude895 padding: 7px 14px;
896 border-radius: var(--r-sm);
958d26aClaude897 font-family: var(--font-sans);
2ce1d0bClaude898 font-size: var(--t-sm);
06d5ffeClaude899 font-weight: 500;
900 border: 1px solid var(--border);
2ce1d0bClaude901 background: var(--bg-elevated);
06d5ffeClaude902 color: var(--text);
903 cursor: pointer;
904 text-decoration: none;
958d26aClaude905 line-height: 1.25;
906 letter-spacing: -0.008em;
2ce1d0bClaude907 transition:
908 background var(--t-fast) var(--ease),
909 border-color var(--t-fast) var(--ease),
910 transform var(--t-fast) var(--ease),
958d26aClaude911 box-shadow var(--t-fast) var(--ease),
912 color var(--t-fast) var(--ease);
2ce1d0bClaude913 user-select: none;
914 white-space: nowrap;
958d26aClaude915 position: relative;
06d5ffeClaude916 }
2ce1d0bClaude917 .btn:hover {
918 background: var(--bg-surface);
919 border-color: var(--border-strong);
958d26aClaude920 color: var(--text-strong);
2ce1d0bClaude921 text-decoration: none;
922 }
958d26aClaude923 .btn:active { transform: translateY(1px); }
2ce1d0bClaude924 .btn:focus-visible { outline: none; box-shadow: var(--ring); }
925
926 .btn-primary {
927 background: var(--accent-gradient);
928 border-color: transparent;
929 color: #fff;
930 font-weight: 600;
958d26aClaude931 text-shadow: 0 1px 0 rgba(0,0,0,0.15);
2ce1d0bClaude932 box-shadow:
958d26aClaude933 inset 0 1px 0 rgba(255,255,255,0.22),
934 inset 0 -1px 0 rgba(0,0,0,0.10),
935 0 1px 2px rgba(0,0,0,0.40),
936 0 0 0 1px rgba(140,109,255,0.30);
937 }
938 .btn-primary::before {
939 content: '';
940 position: absolute;
941 inset: 0;
942 border-radius: inherit;
943 background: linear-gradient(180deg, rgba(255,255,255,0.18), transparent 60%);
944 opacity: 0;
945 transition: opacity var(--t-fast) var(--ease);
946 pointer-events: none;
2ce1d0bClaude947 }
948 .btn-primary:hover {
958d26aClaude949 color: #fff;
2ce1d0bClaude950 background: var(--accent-gradient);
958d26aClaude951 border-color: transparent;
2ce1d0bClaude952 box-shadow:
958d26aClaude953 inset 0 1px 0 rgba(255,255,255,0.30),
954 inset 0 -1px 0 rgba(0,0,0,0.10),
955 0 6px 18px -4px rgba(140,109,255,0.45),
956 0 0 0 1px rgba(140,109,255,0.45);
2ce1d0bClaude957 }
958d26aClaude958 .btn-primary:hover::before { opacity: 1; }
2ce1d0bClaude959
960 .btn-danger {
961 background: transparent;
958d26aClaude962 border-color: rgba(248,113,113,0.40);
2ce1d0bClaude963 color: var(--red);
964 }
965 .btn-danger:hover {
958d26aClaude966 background: rgba(248,113,113,0.08);
2ce1d0bClaude967 border-color: var(--red);
958d26aClaude968 color: var(--red);
2ce1d0bClaude969 }
958d26aClaude970 .btn-danger:focus-visible { box-shadow: var(--ring-err); }
2ce1d0bClaude971
972 .btn-ghost {
973 background: transparent;
974 border-color: transparent;
975 color: var(--text-muted);
976 }
977 .btn-ghost:hover {
978 background: var(--bg-hover);
958d26aClaude979 color: var(--text-strong);
2ce1d0bClaude980 border-color: var(--border);
981 }
982
958d26aClaude983 .btn-secondary {
984 background: var(--bg-elevated);
985 border-color: var(--border-strong);
986 color: var(--text-strong);
987 }
988 .btn-secondary:hover {
989 background: var(--bg-surface);
990 border-color: var(--border-strong);
991 }
992
993 .btn-sm { padding: 4px 10px; font-size: var(--t-xs); border-radius: var(--r-sm); gap: 5px; }
994 .btn-lg { padding: 11px 22px; font-size: var(--t-base); border-radius: var(--r); }
995 .btn-xl { padding: 14px 28px; font-size: var(--t-md); border-radius: var(--r); font-weight: 600; }
996 .btn-block { width: 100%; }
2ce1d0bClaude997
998 .btn:disabled, .btn[aria-disabled='true'] {
958d26aClaude999 opacity: 0.45;
2ce1d0bClaude1000 cursor: not-allowed;
1001 pointer-events: none;
1002 }
1003
1004 /* ============================================================ */
1005 /* Forms */
1006 /* ============================================================ */
1007 .form-group { margin-bottom: 20px; }
1008 .form-group label {
1009 display: block;
1010 font-size: var(--t-sm);
1011 font-weight: 500;
1012 margin-bottom: 6px;
1013 color: var(--text);
1014 letter-spacing: -0.005em;
1015 }
1016 .form-group input,
1017 .form-group textarea,
1018 .form-group select,
1019 input[type='text'], input[type='email'], input[type='password'],
1020 input[type='url'], input[type='search'], input[type='number'],
1021 textarea, select {
06d5ffeClaude1022 width: 100%;
2ce1d0bClaude1023 padding: 9px 12px;
1024 background: var(--bg-secondary);
06d5ffeClaude1025 border: 1px solid var(--border);
2ce1d0bClaude1026 border-radius: var(--r-sm);
06d5ffeClaude1027 color: var(--text);
2ce1d0bClaude1028 font-size: var(--t-sm);
06d5ffeClaude1029 font-family: var(--font-sans);
2ce1d0bClaude1030 transition:
1031 border-color var(--t-fast) var(--ease),
1032 background var(--t-fast) var(--ease),
1033 box-shadow var(--t-fast) var(--ease);
1034 }
1035 .form-group input::placeholder, textarea::placeholder, input::placeholder {
1036 color: var(--text-faint);
06d5ffeClaude1037 }
2ce1d0bClaude1038 .form-group input:hover, textarea:hover, select:hover,
1039 input[type='text']:hover, input[type='email']:hover, input[type='password']:hover {
1040 border-color: var(--border-strong);
1041 }
1042 .form-group input:focus, .form-group textarea:focus, .form-group select:focus,
1043 input:focus, textarea:focus, select:focus {
06d5ffeClaude1044 outline: none;
2ce1d0bClaude1045 background: var(--bg);
1046 border-color: var(--border-focus);
1047 box-shadow: var(--ring);
06d5ffeClaude1048 }
2ce1d0bClaude1049 textarea { font-family: var(--font-mono); font-size: var(--t-sm); line-height: 1.55; }
06d5ffeClaude1050 .input-disabled { opacity: 0.5; cursor: not-allowed; }
1051
2ce1d0bClaude1052 /* ============================================================ */
1053 /* Auth (register / login / verify) */
1054 /* ============================================================ */
1055 .auth-container {
1056 max-width: 420px;
1057 margin: 64px auto;
1058 padding: 32px;
1059 background: var(--bg-elevated);
1060 border: 1px solid var(--border);
1061 border-radius: var(--r-lg);
1062 box-shadow: var(--elev-2);
1063 }
1064 .auth-container h2 {
1065 margin-bottom: 6px;
1066 font-size: var(--t-lg);
1067 letter-spacing: -0.02em;
1068 }
1069 .auth-container > p {
1070 color: var(--text-muted);
1071 font-size: var(--t-sm);
1072 margin-bottom: 24px;
1073 }
1074 .auth-container .btn-primary { width: 100%; padding: 10px 16px; }
06d5ffeClaude1075 .auth-error {
958d26aClaude1076 background: rgba(248,113,113,0.08);
1077 border: 1px solid rgba(248,113,113,0.35);
06d5ffeClaude1078 color: var(--red);
2ce1d0bClaude1079 padding: 10px 14px;
1080 border-radius: var(--r-sm);
06d5ffeClaude1081 margin-bottom: 16px;
2ce1d0bClaude1082 font-size: var(--t-sm);
06d5ffeClaude1083 }
1084 .auth-success {
958d26aClaude1085 background: rgba(52,211,153,0.08);
1086 border: 1px solid rgba(52,211,153,0.35);
06d5ffeClaude1087 color: var(--green);
2ce1d0bClaude1088 padding: 10px 14px;
1089 border-radius: var(--r-sm);
06d5ffeClaude1090 margin-bottom: 16px;
2ce1d0bClaude1091 font-size: var(--t-sm);
1092 }
1093 .auth-switch {
1094 margin-top: 20px;
1095 font-size: var(--t-sm);
1096 color: var(--text-muted);
1097 text-align: center;
1098 }
1099 .banner {
1100 background: var(--accent-gradient-faint);
958d26aClaude1101 border: 1px solid rgba(140,109,255,0.35);
2ce1d0bClaude1102 color: var(--text);
1103 padding: 10px 14px;
1104 border-radius: var(--r-sm);
1105 font-size: var(--t-sm);
06d5ffeClaude1106 }
1107
2ce1d0bClaude1108 /* ============================================================ */
1109 /* Settings */
1110 /* ============================================================ */
1111 .settings-container { max-width: 720px; }
1112 .settings-container h2 { margin-bottom: 8px; font-size: var(--t-xl); letter-spacing: -0.02em; }
1113 .settings-container > h2 + p { color: var(--text-muted); font-size: var(--t-sm); margin-bottom: 24px; }
1114 .settings-container h3 { font-size: var(--t-md); margin-bottom: 12px; margin-top: 28px; }
1115 .settings-container h3:first-of-type { margin-top: 0; }
06d5ffeClaude1116 .ssh-keys-list { margin-bottom: 24px; }
1117 .ssh-key-item {
1118 display: flex;
1119 justify-content: space-between;
1120 align-items: center;
2ce1d0bClaude1121 padding: 14px 16px;
06d5ffeClaude1122 border: 1px solid var(--border);
2ce1d0bClaude1123 border-radius: var(--r-md);
06d5ffeClaude1124 margin-bottom: 8px;
2ce1d0bClaude1125 background: var(--bg-elevated);
1126 transition: border-color var(--t-fast) var(--ease);
06d5ffeClaude1127 }
2ce1d0bClaude1128 .ssh-key-item:hover { border-color: var(--border-strong); }
1129 .ssh-key-meta { font-size: var(--t-xs); color: var(--text-muted); margin-top: 4px; }
1130 .ssh-key-meta code { font-size: var(--t-xs); background: var(--bg-tertiary); padding: 1px 6px; border-radius: 3px; margin-right: 8px; }
06d5ffeClaude1131
2ce1d0bClaude1132 /* ============================================================ */
1133 /* Repo header + nav */
1134 /* ============================================================ */
fc1817aClaude1135 .repo-header {
1136 display: flex;
1137 align-items: center;
1138 gap: 8px;
2ce1d0bClaude1139 margin-bottom: 18px;
1140 font-size: var(--t-lg);
1141 letter-spacing: -0.015em;
fc1817aClaude1142 }
2ce1d0bClaude1143 .repo-header .owner { color: var(--text-link); font-weight: 500; }
1144 .repo-header .separator { color: var(--text-faint); }
1145 .repo-header .name { color: var(--text); font-weight: 700; }
1146 .repo-header .name:hover { color: var(--text-link); text-decoration: none; }
06d5ffeClaude1147 .repo-header-actions { margin-left: auto; display: flex; gap: 8px; align-items: center; }
fc1817aClaude1148
1149 .repo-nav {
1150 display: flex;
2ce1d0bClaude1151 gap: 2px;
fc1817aClaude1152 border-bottom: 1px solid var(--border);
2ce1d0bClaude1153 margin-bottom: 24px;
1154 overflow-x: auto;
1155 scrollbar-width: thin;
fc1817aClaude1156 }
2ce1d0bClaude1157 .repo-nav::-webkit-scrollbar { height: 0; }
fc1817aClaude1158 .repo-nav a {
2ce1d0bClaude1159 padding: 10px 14px;
fc1817aClaude1160 color: var(--text-muted);
1161 border-bottom: 2px solid transparent;
2ce1d0bClaude1162 font-size: var(--t-sm);
1163 font-weight: 500;
1164 margin-bottom: -1px;
1165 transition: all var(--t-fast) var(--ease);
1166 white-space: nowrap;
1167 }
1168 .repo-nav a:hover { text-decoration: none; color: var(--text); background: var(--bg-hover); }
1169 .repo-nav a.active {
1170 color: var(--text);
1171 border-bottom-color: var(--accent);
1172 font-weight: 600;
fc1817aClaude1173 }
1174
2ce1d0bClaude1175 .breadcrumb {
1176 display: flex;
1177 gap: 4px;
1178 align-items: center;
1179 margin-bottom: 16px;
1180 color: var(--text-muted);
1181 font-size: var(--t-sm);
1182 font-family: var(--font-mono);
1183 }
1184 .breadcrumb a { color: var(--text-link); font-weight: 500; }
1185 .breadcrumb a:hover { color: var(--accent-hover); }
fc1817aClaude1186
2ce1d0bClaude1187 /* ============================================================ */
1188 /* File browser table */
1189 /* ============================================================ */
1190 .file-table {
1191 width: 100%;
1192 border: 1px solid var(--border);
1193 border-radius: var(--r-md);
1194 overflow: hidden;
1195 background: var(--bg-elevated);
1196 }
fc1817aClaude1197 .file-table tr { border-bottom: 1px solid var(--border); }
1198 .file-table tr:last-child { border-bottom: none; }
2ce1d0bClaude1199 .file-table td { padding: 10px 16px; font-size: var(--t-sm); }
1200 .file-table tr:hover { background: var(--bg-hover); }
1201 .file-icon { width: 22px; color: var(--text-faint); font-family: var(--font-mono); font-size: var(--t-sm); }
1202 .file-name a { color: var(--text); font-weight: 500; }
1203 .file-name a:hover { color: var(--text-link); text-decoration: none; }
fc1817aClaude1204
2ce1d0bClaude1205 /* ============================================================ */
1206 /* Blob view */
1207 /* ============================================================ */
fc1817aClaude1208 .blob-view {
1209 border: 1px solid var(--border);
2ce1d0bClaude1210 border-radius: var(--r-md);
fc1817aClaude1211 overflow: hidden;
2ce1d0bClaude1212 background: var(--bg-elevated);
fc1817aClaude1213 }
1214 .blob-header {
1215 background: var(--bg-secondary);
2ce1d0bClaude1216 padding: 10px 16px;
fc1817aClaude1217 border-bottom: 1px solid var(--border);
2ce1d0bClaude1218 font-size: var(--t-sm);
fc1817aClaude1219 color: var(--text-muted);
06d5ffeClaude1220 display: flex;
1221 justify-content: space-between;
1222 align-items: center;
fc1817aClaude1223 }
1224 .blob-code {
1225 overflow-x: auto;
1226 font-family: var(--font-mono);
2ce1d0bClaude1227 font-size: var(--t-sm);
1228 line-height: 1.65;
fc1817aClaude1229 }
1230 .blob-code table { width: 100%; border-collapse: collapse; }
1231 .blob-code .line-num {
1232 width: 1%;
2ce1d0bClaude1233 min-width: 56px;
1234 padding: 0 14px;
fc1817aClaude1235 text-align: right;
2ce1d0bClaude1236 color: var(--text-faint);
fc1817aClaude1237 user-select: none;
1238 white-space: nowrap;
1239 border-right: 1px solid var(--border);
1240 }
2ce1d0bClaude1241 .blob-code .line-content { padding: 0 16px; white-space: pre; }
1242 .blob-code tr:hover { background: var(--bg-hover); }
fc1817aClaude1243
2ce1d0bClaude1244 /* ============================================================ */
1245 /* Commits + diffs */
1246 /* ============================================================ */
1247 .commit-list {
1248 border: 1px solid var(--border);
1249 border-radius: var(--r-md);
1250 overflow: hidden;
1251 background: var(--bg-elevated);
1252 }
fc1817aClaude1253 .commit-item {
1254 display: flex;
1255 justify-content: space-between;
1256 align-items: center;
2ce1d0bClaude1257 padding: 14px 16px;
fc1817aClaude1258 border-bottom: 1px solid var(--border);
2ce1d0bClaude1259 transition: background var(--t-fast) var(--ease);
fc1817aClaude1260 }
1261 .commit-item:last-child { border-bottom: none; }
2ce1d0bClaude1262 .commit-item:hover { background: var(--bg-hover); }
1263 .commit-message { font-size: var(--t-sm); font-weight: 500; line-height: 1.45; }
1264 .commit-meta { font-size: var(--t-xs); color: var(--text-muted); margin-top: 4px; }
fc1817aClaude1265 .commit-sha {
1266 font-family: var(--font-mono);
2ce1d0bClaude1267 font-size: var(--t-xs);
1268 padding: 3px 8px;
fc1817aClaude1269 background: var(--bg-tertiary);
1270 border: 1px solid var(--border);
2ce1d0bClaude1271 border-radius: var(--r-sm);
fc1817aClaude1272 color: var(--text-link);
2ce1d0bClaude1273 font-weight: 500;
1274 transition: all var(--t-fast) var(--ease);
fc1817aClaude1275 }
2ce1d0bClaude1276 .commit-sha:hover { border-color: var(--border-strong); color: var(--accent-hover); }
fc1817aClaude1277
1278 .diff-view { margin-top: 16px; }
1279 .diff-file {
1280 border: 1px solid var(--border);
2ce1d0bClaude1281 border-radius: var(--r-md);
fc1817aClaude1282 margin-bottom: 16px;
1283 overflow: hidden;
2ce1d0bClaude1284 background: var(--bg-elevated);
fc1817aClaude1285 }
1286 .diff-file-header {
1287 background: var(--bg-secondary);
2ce1d0bClaude1288 padding: 10px 16px;
fc1817aClaude1289 border-bottom: 1px solid var(--border);
1290 font-family: var(--font-mono);
2ce1d0bClaude1291 font-size: var(--t-sm);
1292 font-weight: 500;
fc1817aClaude1293 }
1294 .diff-content {
1295 overflow-x: auto;
1296 font-family: var(--font-mono);
2ce1d0bClaude1297 font-size: var(--t-sm);
1298 line-height: 1.65;
fc1817aClaude1299 }
958d26aClaude1300 .diff-content .line-add { background: rgba(52,211,153,0.10); color: var(--green); }
1301 .diff-content .line-del { background: rgba(248,113,113,0.08); color: var(--red); }
1302 .diff-content .line-hunk { background: rgba(140,109,255,0.06); color: var(--text-link); }
2ce1d0bClaude1303 .diff-content .line { padding: 0 16px; white-space: pre; display: block; }
fc1817aClaude1304
1305 .stat-add { color: var(--green); font-weight: 600; }
1306 .stat-del { color: var(--red); font-weight: 600; }
1307
2ce1d0bClaude1308 /* ============================================================ */
1309 /* Empty state */
1310 /* ============================================================ */
fc1817aClaude1311 .empty-state {
1312 text-align: center;
958d26aClaude1313 padding: 96px 24px;
fc1817aClaude1314 color: var(--text-muted);
2ce1d0bClaude1315 border: 1px dashed var(--border);
1316 border-radius: var(--r-lg);
958d26aClaude1317 background:
1318 radial-gradient(60% 60% at 50% 0%, rgba(140,109,255,0.05), transparent 70%),
1319 var(--bg-elevated);
1320 position: relative;
1321 overflow: hidden;
1322 }
1323 .empty-state::before {
1324 content: '';
1325 position: absolute;
1326 inset: 0;
1327 background-image: radial-gradient(rgba(255,255,255,0.025) 1px, transparent 1px);
1328 background-size: 24px 24px;
1329 opacity: 0.5;
1330 pointer-events: none;
1331 mask-image: radial-gradient(ellipse at center, #000 30%, transparent 70%);
1332 -webkit-mask-image: radial-gradient(ellipse at center, #000 30%, transparent 70%);
1333 }
1334 :root[data-theme='light'] .empty-state::before {
1335 background-image: radial-gradient(rgba(15,16,28,0.08) 1px, transparent 1px);
fc1817aClaude1336 }
958d26aClaude1337 .empty-state > * { position: relative; z-index: 1; }
2ce1d0bClaude1338 .empty-state h2 {
958d26aClaude1339 font-size: var(--t-xl);
2ce1d0bClaude1340 margin-bottom: 8px;
958d26aClaude1341 color: var(--text-strong);
1342 letter-spacing: -0.022em;
2ce1d0bClaude1343 }
958d26aClaude1344 .empty-state p { font-size: var(--t-md); max-width: 480px; margin: 0 auto; line-height: 1.55; }
fc1817aClaude1345 .empty-state pre {
1346 text-align: left;
1347 display: inline-block;
1348 background: var(--bg-secondary);
958d26aClaude1349 padding: 18px 24px;
1350 border-radius: var(--r-md);
fc1817aClaude1351 border: 1px solid var(--border);
1352 font-family: var(--font-mono);
958d26aClaude1353 font-feature-settings: var(--mono-feat);
2ce1d0bClaude1354 font-size: var(--t-sm);
958d26aClaude1355 margin-top: 24px;
fc1817aClaude1356 line-height: 1.8;
2ce1d0bClaude1357 color: var(--text);
958d26aClaude1358 box-shadow: var(--elev-1);
fc1817aClaude1359 }
1360
2ce1d0bClaude1361 /* ============================================================ */
1362 /* Badges */
1363 /* ============================================================ */
fc1817aClaude1364 .badge {
2ce1d0bClaude1365 display: inline-flex;
1366 align-items: center;
1367 gap: 4px;
1368 padding: 2px 9px;
1369 border-radius: var(--r-full);
1370 font-size: var(--t-xs);
fc1817aClaude1371 font-weight: 500;
1372 background: var(--bg-tertiary);
1373 border: 1px solid var(--border);
1374 color: var(--text-muted);
2ce1d0bClaude1375 line-height: 1.5;
fc1817aClaude1376 }
1377
2ce1d0bClaude1378 /* ============================================================ */
1379 /* Branch dropdown */
1380 /* ============================================================ */
fc1817aClaude1381 .branch-selector {
1382 display: inline-flex;
1383 align-items: center;
2ce1d0bClaude1384 gap: 6px;
1385 padding: 6px 12px;
1386 background: var(--bg-elevated);
fc1817aClaude1387 border: 1px solid var(--border);
2ce1d0bClaude1388 border-radius: var(--r-sm);
1389 font-size: var(--t-sm);
fc1817aClaude1390 color: var(--text);
1391 margin-bottom: 12px;
2ce1d0bClaude1392 transition: border-color var(--t-fast) var(--ease);
fc1817aClaude1393 }
2ce1d0bClaude1394 .branch-selector:hover { border-color: var(--border-strong); }
fc1817aClaude1395
06d5ffeClaude1396 .branch-dropdown {
1397 position: relative;
1398 display: inline-block;
1399 margin-bottom: 12px;
1400 }
1401 .branch-dropdown-content {
1402 display: none;
1403 position: absolute;
2ce1d0bClaude1404 top: calc(100% + 4px);
06d5ffeClaude1405 left: 0;
1406 z-index: 10;
2ce1d0bClaude1407 min-width: 220px;
1408 background: var(--bg-elevated);
1409 border: 1px solid var(--border-strong);
1410 border-radius: var(--r-md);
1411 overflow: hidden;
1412 box-shadow: var(--elev-3);
06d5ffeClaude1413 }
1414 .branch-dropdown:hover .branch-dropdown-content,
1415 .branch-dropdown:focus-within .branch-dropdown-content { display: block; }
1416 .branch-dropdown-content a {
1417 display: block;
2ce1d0bClaude1418 padding: 9px 14px;
1419 font-size: var(--t-sm);
06d5ffeClaude1420 color: var(--text);
1421 border-bottom: 1px solid var(--border);
2ce1d0bClaude1422 transition: background var(--t-fast) var(--ease);
06d5ffeClaude1423 }
1424 .branch-dropdown-content a:last-child { border-bottom: none; }
2ce1d0bClaude1425 .branch-dropdown-content a:hover { background: var(--bg-hover); text-decoration: none; }
1426 .branch-dropdown-content a.active-branch { color: var(--text-link); font-weight: 600; background: var(--accent-gradient-faint); }
06d5ffeClaude1427
2ce1d0bClaude1428 /* ============================================================ */
1429 /* Card grid */
1430 /* ============================================================ */
1431 .card-grid {
1432 display: grid;
1433 grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
1434 gap: 16px;
1435 }
fc1817aClaude1436 .card {
1437 border: 1px solid var(--border);
2ce1d0bClaude1438 border-radius: var(--r-md);
958d26aClaude1439 padding: 20px;
2ce1d0bClaude1440 background: var(--bg-elevated);
1441 transition:
958d26aClaude1442 border-color var(--t-base) var(--ease),
1443 transform var(--t-base) var(--ease-out-quart),
2ce1d0bClaude1444 box-shadow var(--t-base) var(--ease);
1445 position: relative;
1446 overflow: hidden;
958d26aClaude1447 isolation: isolate;
1448 }
1449 .card::before {
1450 content: '';
1451 position: absolute;
1452 inset: 0;
1453 background: linear-gradient(135deg, rgba(140,109,255,0.06), transparent 50%);
1454 opacity: 0;
1455 transition: opacity var(--t-base) var(--ease);
1456 pointer-events: none;
1457 z-index: -1;
2ce1d0bClaude1458 }
1459 .card:hover {
1460 border-color: var(--border-strong);
1461 box-shadow: var(--elev-2);
958d26aClaude1462 transform: translateY(-2px);
2ce1d0bClaude1463 }
958d26aClaude1464 .card:hover::before { opacity: 1; }
1465 .card h3 { font-size: var(--t-md); margin-bottom: 6px; letter-spacing: -0.012em; }
2ce1d0bClaude1466 .card h3 a { color: var(--text); font-weight: 600; }
1467 .card h3 a:hover { color: var(--text-link); }
1468 .card p { font-size: var(--t-sm); color: var(--text-muted); line-height: 1.5; }
1469 .card-meta {
1470 display: flex;
1471 gap: 14px;
1472 margin-top: 14px;
1473 padding-top: 14px;
1474 border-top: 1px solid var(--border);
1475 font-size: var(--t-xs);
1476 color: var(--text-muted);
1477 }
1478 .card-meta span { display: flex; align-items: center; gap: 5px; }
1479
1480 /* ============================================================ */
1481 /* Stat card / box */
1482 /* ============================================================ */
1483 .stat-card {
1484 background: var(--bg-elevated);
1485 border: 1px solid var(--border);
1486 border-radius: var(--r-md);
fc1817aClaude1487 padding: 16px;
2ce1d0bClaude1488 transition: border-color var(--t-fast) var(--ease);
1489 }
1490 .stat-card:hover { border-color: var(--border-strong); }
1491 .stat-label {
1492 font-size: var(--t-xs);
1493 color: var(--text-muted);
1494 text-transform: uppercase;
1495 letter-spacing: 0.06em;
1496 font-weight: 500;
1497 }
1498 .stat-value {
1499 font-size: var(--t-xl);
1500 font-weight: 700;
1501 margin-top: 4px;
1502 letter-spacing: -0.025em;
1503 color: var(--text);
1504 font-feature-settings: 'tnum';
fc1817aClaude1505 }
06d5ffeClaude1506
2ce1d0bClaude1507 /* ============================================================ */
1508 /* Star button */
1509 /* ============================================================ */
06d5ffeClaude1510 .star-btn {
1511 display: inline-flex;
1512 align-items: center;
1513 gap: 6px;
2ce1d0bClaude1514 padding: 5px 12px;
1515 background: var(--bg-elevated);
06d5ffeClaude1516 border: 1px solid var(--border);
2ce1d0bClaude1517 border-radius: var(--r-sm);
06d5ffeClaude1518 color: var(--text);
2ce1d0bClaude1519 font-size: var(--t-sm);
1520 font-weight: 500;
06d5ffeClaude1521 cursor: pointer;
2ce1d0bClaude1522 transition: all var(--t-fast) var(--ease);
1523 }
1524 .star-btn:hover { background: var(--bg-surface); border-color: var(--border-strong); text-decoration: none; }
1525 .star-btn.starred {
1526 color: var(--yellow);
958d26aClaude1527 border-color: rgba(251,191,36,0.4);
1528 background: rgba(251,191,36,0.08);
06d5ffeClaude1529 }
1530
2ce1d0bClaude1531 /* ============================================================ */
1532 /* User profile */
1533 /* ============================================================ */
06d5ffeClaude1534 .user-profile {
1535 display: flex;
1536 gap: 32px;
1537 margin-bottom: 32px;
2ce1d0bClaude1538 padding: 24px;
1539 background: var(--bg-elevated);
1540 border: 1px solid var(--border);
1541 border-radius: var(--r-lg);
06d5ffeClaude1542 }
1543 .user-avatar {
1544 width: 96px;
1545 height: 96px;
2ce1d0bClaude1546 border-radius: var(--r-full);
1547 background: var(--accent-gradient-soft);
1548 border: 1px solid var(--border-strong);
06d5ffeClaude1549 display: flex;
1550 align-items: center;
1551 justify-content: center;
2ce1d0bClaude1552 font-size: 36px;
1553 font-weight: 600;
1554 color: var(--text);
06d5ffeClaude1555 flex-shrink: 0;
2ce1d0bClaude1556 letter-spacing: -0.02em;
06d5ffeClaude1557 }
2ce1d0bClaude1558 .user-info h2 { font-size: var(--t-xl); margin-bottom: 2px; letter-spacing: -0.025em; }
1559 .user-info .username { font-size: var(--t-md); color: var(--text-muted); }
1560 .user-info .bio { font-size: var(--t-sm); color: var(--text-muted); margin-top: 10px; line-height: 1.55; }
06d5ffeClaude1561
2ce1d0bClaude1562 /* ============================================================ */
1563 /* New repo form */
1564 /* ============================================================ */
1565 .new-repo-form { max-width: 640px; }
1566 .new-repo-form h2 { margin-bottom: 24px; font-size: var(--t-xl); letter-spacing: -0.025em; }
1567 .visibility-options { display: flex; gap: 12px; margin-bottom: 20px; }
06d5ffeClaude1568 .visibility-option {
1569 flex: 1;
2ce1d0bClaude1570 padding: 16px;
06d5ffeClaude1571 border: 1px solid var(--border);
2ce1d0bClaude1572 border-radius: var(--r-md);
1573 background: var(--bg-elevated);
06d5ffeClaude1574 cursor: pointer;
2ce1d0bClaude1575 text-align: left;
1576 transition: all var(--t-fast) var(--ease);
1577 }
1578 .visibility-option:hover { border-color: var(--border-strong); background: var(--bg-surface); }
1579 .visibility-option:has(input:checked) {
1580 border-color: var(--accent);
1581 background: var(--accent-gradient-faint);
1582 box-shadow: 0 0 0 1px var(--accent);
06d5ffeClaude1583 }
1584 .visibility-option input { display: none; }
2ce1d0bClaude1585 .visibility-option .vis-label { font-size: var(--t-sm); font-weight: 600; margin-bottom: 4px; }
1586 .visibility-option .vis-desc { font-size: var(--t-xs); color: var(--text-muted); }
79136bbClaude1587
2ce1d0bClaude1588 /* ============================================================ */
1589 /* Issues */
1590 /* ============================================================ */
1591 .issue-tabs { display: flex; gap: 4px; }
1592 .issue-tabs a {
1593 color: var(--text-muted);
1594 font-size: var(--t-sm);
1595 font-weight: 500;
1596 padding: 6px 12px;
1597 border-radius: var(--r-sm);
1598 transition: all var(--t-fast) var(--ease);
1599 }
1600 .issue-tabs a:hover { color: var(--text); background: var(--bg-hover); text-decoration: none; }
1601 .issue-tabs a.active { color: var(--text); background: var(--bg-elevated); }
79136bbClaude1602
2ce1d0bClaude1603 .issue-list {
1604 border: 1px solid var(--border);
1605 border-radius: var(--r-md);
1606 overflow: hidden;
1607 background: var(--bg-elevated);
1608 }
79136bbClaude1609 .issue-item {
1610 display: flex;
2ce1d0bClaude1611 gap: 14px;
79136bbClaude1612 align-items: flex-start;
2ce1d0bClaude1613 padding: 14px 16px;
79136bbClaude1614 border-bottom: 1px solid var(--border);
2ce1d0bClaude1615 transition: background var(--t-fast) var(--ease);
79136bbClaude1616 }
1617 .issue-item:last-child { border-bottom: none; }
2ce1d0bClaude1618 .issue-item:hover { background: var(--bg-hover); }
1619 .issue-state-icon {
1620 font-size: 14px;
1621 padding-top: 2px;
1622 width: 18px;
1623 height: 18px;
1624 display: inline-flex;
1625 align-items: center;
1626 justify-content: center;
1627 border-radius: var(--r-full);
1628 flex-shrink: 0;
1629 }
79136bbClaude1630 .state-open { color: var(--green); }
958d26aClaude1631 .state-closed { color: #b69dff; }
2ce1d0bClaude1632 .issue-title {
1633 font-size: var(--t-base);
1634 font-weight: 600;
1635 line-height: 1.4;
1636 letter-spacing: -0.005em;
1637 }
79136bbClaude1638 .issue-title a { color: var(--text); }
2ce1d0bClaude1639 .issue-title a:hover { color: var(--text-link); text-decoration: none; }
1640 .issue-meta { font-size: var(--t-xs); color: var(--text-muted); margin-top: 4px; }
79136bbClaude1641
1642 .issue-badge {
1643 display: inline-flex;
1644 align-items: center;
2ce1d0bClaude1645 gap: 6px;
79136bbClaude1646 padding: 4px 12px;
2ce1d0bClaude1647 border-radius: var(--r-full);
1648 font-size: var(--t-sm);
79136bbClaude1649 font-weight: 500;
2ce1d0bClaude1650 line-height: 1.4;
79136bbClaude1651 }
958d26aClaude1652 .badge-open { background: rgba(52,211,153,0.10); color: var(--green); border: 1px solid rgba(52,211,153,0.35); }
1653 .badge-closed { background: rgba(182,157,255,0.10); color: #b69dff; border: 1px solid rgba(182,157,255,0.35); }
1654 .badge-merged { background: rgba(140,109,255,0.10); color: var(--accent); border: 1px solid rgba(140,109,255,0.35); }
2ce1d0bClaude1655 .state-merged { color: var(--accent); }
958d26aClaude1656 .ai-review { border-color: var(--accent); box-shadow: 0 0 0 1px rgba(140,109,255,0.3); }
79136bbClaude1657
2ce1d0bClaude1658 .issue-detail { max-width: 920px; }
79136bbClaude1659 .issue-comment-box {
1660 border: 1px solid var(--border);
2ce1d0bClaude1661 border-radius: var(--r-md);
79136bbClaude1662 margin-bottom: 16px;
1663 overflow: hidden;
2ce1d0bClaude1664 background: var(--bg-elevated);
79136bbClaude1665 }
1666 .comment-header {
1667 background: var(--bg-secondary);
2ce1d0bClaude1668 padding: 10px 16px;
1669 border-bottom: 1px solid var(--border);
1670 font-size: var(--t-sm);
1671 color: var(--text-muted);
1672 }
1673
1674 /* ============================================================ */
1675 /* Panel — flexible container used across many pages */
1676 /* ============================================================ */
1677 .panel {
1678 background: var(--bg-elevated);
1679 border: 1px solid var(--border);
1680 border-radius: var(--r-md);
1681 overflow: hidden;
1682 }
1683 .panel-item {
1684 display: flex;
1685 align-items: center;
1686 gap: 12px;
1687 padding: 12px 16px;
79136bbClaude1688 border-bottom: 1px solid var(--border);
2ce1d0bClaude1689 transition: background var(--t-fast) var(--ease);
1690 }
1691 .panel-item:last-child { border-bottom: none; }
1692 .panel-item:hover { background: var(--bg-hover); }
1693 .panel-empty {
1694 padding: 24px;
1695 text-align: center;
79136bbClaude1696 color: var(--text-muted);
2ce1d0bClaude1697 font-size: var(--t-sm);
79136bbClaude1698 }
1699
2ce1d0bClaude1700 /* ============================================================ */
1701 /* Search */
1702 /* ============================================================ */
79136bbClaude1703 .search-results .diff-file { margin-bottom: 12px; }
16b325cClaude1704
2ce1d0bClaude1705 /* ============================================================ */
1706 /* Timeline */
1707 /* ============================================================ */
1708 .timeline { position: relative; padding-left: 28px; }
16b325cClaude1709 .timeline::before {
1710 content: '';
1711 position: absolute;
1712 left: 4px;
1713 top: 8px;
1714 bottom: 8px;
1715 width: 2px;
2ce1d0bClaude1716 background: linear-gradient(180deg, var(--border) 0%, transparent 100%);
16b325cClaude1717 }
2ce1d0bClaude1718 .timeline-item { position: relative; padding-bottom: 16px; }
16b325cClaude1719 .timeline-dot {
1720 position: absolute;
2ce1d0bClaude1721 left: -28px;
1722 top: 8px;
1723 width: 12px;
1724 height: 12px;
1725 border-radius: var(--r-full);
1726 background: var(--accent-gradient);
16b325cClaude1727 border: 2px solid var(--bg);
2ce1d0bClaude1728 box-shadow: 0 0 0 1px var(--border-strong);
16b325cClaude1729 }
1730 .timeline-content {
2ce1d0bClaude1731 background: var(--bg-elevated);
16b325cClaude1732 border: 1px solid var(--border);
2ce1d0bClaude1733 border-radius: var(--r-md);
1734 padding: 14px 16px;
16b325cClaude1735 }
f1ab587Claude1736
2ce1d0bClaude1737 /* ============================================================ */
1738 /* Toggle switch */
1739 /* ============================================================ */
f1ab587Claude1740 .toggle-switch {
1741 position: relative;
1742 display: inline-block;
2ce1d0bClaude1743 width: 40px;
1744 height: 22px;
f1ab587Claude1745 flex-shrink: 0;
1746 margin-left: 16px;
1747 }
1748 .toggle-switch input { opacity: 0; width: 0; height: 0; }
1749 .toggle-slider {
1750 position: absolute;
1751 cursor: pointer;
1752 top: 0; left: 0; right: 0; bottom: 0;
1753 background: var(--bg-tertiary);
1754 border: 1px solid var(--border);
2ce1d0bClaude1755 border-radius: var(--r-full);
1756 transition: all var(--t-base) var(--ease);
f1ab587Claude1757 }
1758 .toggle-slider::before {
1759 content: '';
1760 position: absolute;
2ce1d0bClaude1761 height: 16px;
1762 width: 16px;
f1ab587Claude1763 left: 2px;
1764 bottom: 2px;
1765 background: var(--text-muted);
2ce1d0bClaude1766 border-radius: var(--r-full);
1767 transition: all var(--t-base) var(--ease);
f1ab587Claude1768 }
1769 .toggle-switch input:checked + .toggle-slider {
2ce1d0bClaude1770 background: var(--accent-gradient);
1771 border-color: transparent;
958d26aClaude1772 box-shadow: 0 0 0 1px rgba(140,109,255,0.4);
f1ab587Claude1773 }
1774 .toggle-switch input:checked + .toggle-slider::before {
2ce1d0bClaude1775 transform: translateX(18px);
f1ab587Claude1776 background: #fff;
1777 }
2ce1d0bClaude1778
1779 /* ============================================================ */
958d26aClaude1780 /* Utilities — gradient text, surfaces, dot-grid, skeleton */
2ce1d0bClaude1781 /* ============================================================ */
1782 .gradient-text {
1783 background: var(--accent-gradient);
1784 -webkit-background-clip: text;
1785 background-clip: text;
1786 -webkit-text-fill-color: transparent;
958d26aClaude1787 color: transparent;
2ce1d0bClaude1788 }
1789 .surface { background: var(--bg-elevated); border: 1px solid var(--border); border-radius: var(--r-md); }
1790 .surface-elevated { background: var(--bg-elevated); border: 1px solid var(--border); border-radius: var(--r-md); box-shadow: var(--elev-1); }
958d26aClaude1791 .surface-glow {
1792 background: var(--bg-elevated);
1793 border: 1px solid var(--border-strong);
1794 border-radius: var(--r-lg);
1795 box-shadow: var(--elev-2), var(--accent-glow);
1796 }
1797
1798 /* Dot-grid background utility — for hero surfaces, empty states, terminal blocks */
1799 .dot-grid {
1800 background-image: radial-gradient(rgba(255,255,255,0.04) 1px, transparent 1px);
1801 background-size: 22px 22px;
1802 }
1803 :root[data-theme='light'] .dot-grid {
1804 background-image: radial-gradient(rgba(15,16,28,0.06) 1px, transparent 1px);
1805 }
1806
1807 /* Hairline-grid background utility */
1808 .grid-lines {
1809 background-image:
1810 linear-gradient(to right, var(--border-subtle) 1px, transparent 1px),
1811 linear-gradient(to bottom, var(--border-subtle) 1px, transparent 1px);
1812 background-size: 56px 56px;
1813 }
1814
1815 /* Skeleton loader */
1816 .skeleton {
1817 background: linear-gradient(90deg, var(--bg-tertiary) 0%, var(--bg-surface) 50%, var(--bg-tertiary) 100%);
1818 background-size: 200% 100%;
1819 animation: skel 1.4s ease-in-out infinite;
1820 border-radius: var(--r-sm);
1821 }
1822 @keyframes skel { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }
1823
1824 /* Inline divider */
1825 .divider {
1826 border: 0;
1827 border-top: 1px solid var(--border);
1828 margin: var(--s-6) 0;
1829 }
1830 .divider-vert {
1831 width: 1px;
1832 align-self: stretch;
1833 background: var(--border);
1834 margin: 0 var(--s-3);
1835 }
1836
1837 /* Stagger fade-in helper — apply to a parent, animate children */
1838 .stagger > * {
1839 opacity: 0;
1840 transform: translateY(10px);
1841 animation: stagger-in 600ms var(--ease-out-expo) forwards;
1842 }
1843 .stagger > *:nth-child(1) { animation-delay: 0ms; }
1844 .stagger > *:nth-child(2) { animation-delay: 60ms; }
1845 .stagger > *:nth-child(3) { animation-delay: 120ms; }
1846 .stagger > *:nth-child(4) { animation-delay: 180ms; }
1847 .stagger > *:nth-child(5) { animation-delay: 240ms; }
1848 .stagger > *:nth-child(6) { animation-delay: 300ms; }
1849 .stagger > *:nth-child(7) { animation-delay: 360ms; }
1850 .stagger > *:nth-child(8) { animation-delay: 420ms; }
1851 @keyframes stagger-in {
1852 to { opacity: 1; transform: translateY(0); }
1853 }
1854
1855 /* Tag pill — used for labels, topics */
1856 .tag {
1857 display: inline-flex;
1858 align-items: center;
1859 gap: 5px;
1860 padding: 2px 9px;
1861 border-radius: var(--r-full);
1862 font-size: 11px;
1863 font-weight: 500;
1864 background: var(--bg-tertiary);
1865 border: 1px solid var(--border);
1866 color: var(--text-muted);
1867 line-height: 1.5;
1868 font-family: var(--font-mono);
1869 letter-spacing: 0.01em;
1870 }
1871 .tag-accent {
1872 background: var(--accent-gradient-faint);
1873 border-color: rgba(140,109,255,0.30);
1874 color: var(--accent);
1875 }
2ce1d0bClaude1876
1877 /* Command palette polish */
1878 .cmdk-item { transition: background var(--t-fast) var(--ease); }
1879 .cmdk-item:hover { background: var(--bg-hover) !important; }
1880 .cmdk-active { background: var(--accent-gradient-faint) !important; border-left: 2px solid var(--accent) !important; }
1881
1882 /* Reduced motion preference */
1883 @media (prefers-reduced-motion: reduce) {
1884 *, *::before, *::after {
1885 animation-duration: 0.01ms !important;
1886 animation-iteration-count: 1 !important;
1887 transition-duration: 0.01ms !important;
1888 }
1889 }
1890
1891 /* Tablet + below */
1892 @media (max-width: 768px) {
1893 main { padding: 20px 16px 40px; }
1894 header { padding: 0 16px; }
1895 .nav-search { display: none; }
1896 .repo-header { font-size: var(--t-md); }
1897 .card-grid { grid-template-columns: 1fr; }
1898 .auth-container { margin: 32px 16px; padding: 24px; }
1899 .visibility-options { flex-direction: column; }
1900 }
1901
1902 /* Scrollbar styling — subtle, themed */
1903 ::-webkit-scrollbar { width: 10px; height: 10px; }
1904 ::-webkit-scrollbar-track { background: transparent; }
1905 ::-webkit-scrollbar-thumb {
1906 background: var(--bg-surface);
1907 border: 2px solid var(--bg);
1908 border-radius: var(--r-full);
1909 }
1910 ::-webkit-scrollbar-thumb:hover { background: var(--border-strong); }
fc1817aClaude1911`;