Pre-launch — Gluecron is in final validation. Public signups and git hosting for non-owner users open after launch review.
CodeIssuesDiscussionsWikiPull RequestsProjectsCommitsActionsReleasesContributorsPulse● GatesSecuritySettingsDeploymentsPipelineInsightsAgents✨ Explain✨ Ask AI✨ Workspace✨ Spec✨ Tests▓ Debt Map✨ NL Search🏛 Archaeology
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.tsxBlame2067 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';
fc1817aClaude513 }
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; }
fc1817aClaude611
958d26aClaude612 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);
06d5ffeClaude720 }
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; }
fc1817aClaude811
2ce1d0bClaude812 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;
fc1817aClaude824 color: var(--text-muted);
958d26aClaude825 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);
06d5ffeClaude937 }
958d26aClaude938 .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);
06d5ffeClaude1034 }
2ce1d0bClaude1035 .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;
debcf27Claude1138 gap: 12px;
1139 margin-bottom: 22px;
1140 }
1141 .repo-header-title {
1142 display: flex;
1143 align-items: center;
1144 gap: 10px;
1145 font-family: var(--font-display);
1146 font-size: 24px;
1147 letter-spacing: -0.025em;
1148 flex-wrap: wrap;
1149 }
1150 .repo-header .owner {
1151 color: var(--text-muted);
1152 font-weight: 500;
1153 transition: color var(--t-fast) var(--ease);
1154 }
1155 .repo-header .owner:hover { color: var(--text-link); text-decoration: none; }
1156 .repo-header .separator { color: var(--text-faint); font-weight: 300; }
1157 .repo-header .name {
1158 color: var(--text-strong);
1159 font-weight: 700;
1160 letter-spacing: -0.028em;
fc1817aClaude1161 }
2ce1d0bClaude1162 .repo-header .name:hover { color: var(--text-link); text-decoration: none; }
debcf27Claude1163 .repo-header-fork {
1164 font-family: var(--font-mono);
1165 font-size: 11px;
1166 color: var(--text-muted);
1167 margin-top: 4px;
1168 letter-spacing: 0.01em;
1169 }
1170 .repo-header-fork a { color: var(--text-muted); }
1171 .repo-header-fork a:hover { color: var(--accent); }
1172 .repo-header-pill {
1173 display: inline-flex;
1174 align-items: center;
1175 padding: 2px 10px;
1176 border-radius: var(--r-full);
1177 font-family: var(--font-mono);
1178 font-size: 10px;
1179 font-weight: 600;
1180 letter-spacing: 0.12em;
1181 text-transform: uppercase;
1182 line-height: 1.6;
1183 vertical-align: 4px;
1184 }
1185 .repo-header-pill-archived {
1186 background: rgba(251,191,36,0.10);
1187 color: var(--yellow);
1188 border: 1px solid rgba(251,191,36,0.30);
1189 }
1190 .repo-header-pill-template {
1191 background: var(--accent-gradient-faint);
1192 color: var(--accent);
1193 border: 1px solid rgba(140,109,255,0.30);
fc1817aClaude1194 }
06d5ffeClaude1195 .repo-header-actions { margin-left: auto; display: flex; gap: 8px; align-items: center; }
fc1817aClaude1196
1197 .repo-nav {
1198 display: flex;
debcf27Claude1199 gap: 1px;
fc1817aClaude1200 border-bottom: 1px solid var(--border);
debcf27Claude1201 margin-bottom: 28px;
2ce1d0bClaude1202 overflow-x: auto;
1203 scrollbar-width: thin;
fc1817aClaude1204 }
2ce1d0bClaude1205 .repo-nav::-webkit-scrollbar { height: 0; }
fc1817aClaude1206 .repo-nav a {
debcf27Claude1207 position: relative;
1208 padding: 11px 14px;
fc1817aClaude1209 color: var(--text-muted);
1210 border-bottom: 2px solid transparent;
2ce1d0bClaude1211 font-size: var(--t-sm);
1212 font-weight: 500;
1213 margin-bottom: -1px;
debcf27Claude1214 transition: color var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
2ce1d0bClaude1215 white-space: nowrap;
1216 }
debcf27Claude1217 .repo-nav a:hover { text-decoration: none; color: var(--text-strong); background: var(--bg-hover); }
2ce1d0bClaude1218 .repo-nav a.active {
debcf27Claude1219 color: var(--text-strong);
1220 font-weight: 600;
1221 }
1222 .repo-nav a.active::after {
1223 content: '';
1224 position: absolute;
1225 left: 14px;
1226 right: 14px;
1227 bottom: -1px;
1228 height: 2px;
1229 background: var(--accent-gradient);
1230 border-radius: 2px;
1231 }
1232 /* AI links in the right-side cluster — sparkle accent */
1233 .repo-nav-ai {
1234 color: var(--accent) !important;
1235 font-weight: 500;
1236 }
1237 .repo-nav-ai:hover {
1238 color: var(--accent-hover) !important;
1239 background: var(--accent-gradient-faint) !important;
1240 }
1241 .repo-nav-ai.active {
1242 color: var(--accent-hover) !important;
2ce1d0bClaude1243 font-weight: 600;
fc1817aClaude1244 }
1245
2ce1d0bClaude1246 .breadcrumb {
1247 display: flex;
debcf27Claude1248 gap: 6px;
2ce1d0bClaude1249 align-items: center;
debcf27Claude1250 margin-bottom: 18px;
2ce1d0bClaude1251 color: var(--text-muted);
1252 font-size: var(--t-sm);
1253 font-family: var(--font-mono);
debcf27Claude1254 font-feature-settings: var(--mono-feat);
2ce1d0bClaude1255 }
1256 .breadcrumb a { color: var(--text-link); font-weight: 500; }
1257 .breadcrumb a:hover { color: var(--accent-hover); }
debcf27Claude1258 .breadcrumb strong {
1259 color: var(--text-strong);
1260 font-weight: 600;
fc1817aClaude1261 }
1262
debcf27Claude1263 /* Page header — eyebrow + title + optional actions row.
1264 Use on dashboard, settings, admin, any "section landing" page. */
1265 .page-header {
1266 display: flex;
1267 align-items: flex-end;
1268 justify-content: space-between;
1269 gap: 16px;
1270 margin-bottom: 28px;
1271 padding-bottom: 20px;
1272 border-bottom: 1px solid var(--border-subtle);
1273 flex-wrap: wrap;
1274 }
1275 .page-header-text { flex: 1; min-width: 280px; }
1276 .page-header .eyebrow { margin-bottom: var(--s-2); }
1277 .page-header h1 {
1278 font-family: var(--font-display);
1279 font-size: clamp(24px, 3vw, 36px);
1280 line-height: 1.1;
1281 letter-spacing: -0.028em;
1282 margin-bottom: 6px;
1283 }
1284 .page-header p {
1285 color: var(--text-muted);
1286 font-size: var(--t-sm);
1287 line-height: 1.55;
1288 max-width: 640px;
1289 }
1290 .page-header-actions { display: flex; gap: 8px; align-items: center; }
fc1817aClaude1291
2ce1d0bClaude1292 /* ============================================================ */
1293 /* File browser table */
1294 /* ============================================================ */
1295 .file-table {
1296 width: 100%;
1297 border: 1px solid var(--border);
1298 border-radius: var(--r-md);
1299 overflow: hidden;
1300 background: var(--bg-elevated);
debcf27Claude1301 border-collapse: collapse;
2ce1d0bClaude1302 }
debcf27Claude1303 .file-table tr { border-bottom: 1px solid var(--border-subtle); transition: background var(--t-fast) var(--ease); }
fc1817aClaude1304 .file-table tr:last-child { border-bottom: none; }
debcf27Claude1305 .file-table td {
1306 padding: 9px 16px;
1307 font-size: var(--t-sm);
1308 font-family: var(--font-mono);
1309 font-feature-settings: var(--mono-feat);
1310 }
2ce1d0bClaude1311 .file-table tr:hover { background: var(--bg-hover); }
debcf27Claude1312 .file-icon {
1313 width: 22px;
1314 color: var(--text-faint);
1315 font-size: 13px;
1316 text-align: center;
1317 }
1318 .file-name a {
1319 color: var(--text);
1320 font-weight: 500;
1321 transition: color var(--t-fast) var(--ease);
1322 }
1323 .file-name a:hover { color: var(--accent); text-decoration: none; }
fc1817aClaude1324
2ce1d0bClaude1325 /* ============================================================ */
1326 /* Blob view */
1327 /* ============================================================ */
fc1817aClaude1328 .blob-view {
1329 border: 1px solid var(--border);
2ce1d0bClaude1330 border-radius: var(--r-md);
fc1817aClaude1331 overflow: hidden;
2ce1d0bClaude1332 background: var(--bg-elevated);
fc1817aClaude1333 }
1334 .blob-header {
1335 background: var(--bg-secondary);
2ce1d0bClaude1336 padding: 10px 16px;
fc1817aClaude1337 border-bottom: 1px solid var(--border);
2ce1d0bClaude1338 font-size: var(--t-sm);
fc1817aClaude1339 color: var(--text-muted);
06d5ffeClaude1340 display: flex;
1341 justify-content: space-between;
1342 align-items: center;
fc1817aClaude1343 }
1344 .blob-code {
1345 overflow-x: auto;
1346 font-family: var(--font-mono);
2ce1d0bClaude1347 font-size: var(--t-sm);
1348 line-height: 1.65;
fc1817aClaude1349 }
1350 .blob-code table { width: 100%; border-collapse: collapse; }
1351 .blob-code .line-num {
1352 width: 1%;
2ce1d0bClaude1353 min-width: 56px;
1354 padding: 0 14px;
fc1817aClaude1355 text-align: right;
2ce1d0bClaude1356 color: var(--text-faint);
fc1817aClaude1357 user-select: none;
1358 white-space: nowrap;
1359 border-right: 1px solid var(--border);
1360 }
2ce1d0bClaude1361 .blob-code .line-content { padding: 0 16px; white-space: pre; }
1362 .blob-code tr:hover { background: var(--bg-hover); }
fc1817aClaude1363
2ce1d0bClaude1364 /* ============================================================ */
1365 /* Commits + diffs */
1366 /* ============================================================ */
1367 .commit-list {
1368 border: 1px solid var(--border);
1369 border-radius: var(--r-md);
1370 overflow: hidden;
1371 background: var(--bg-elevated);
1372 }
fc1817aClaude1373 .commit-item {
1374 display: flex;
1375 justify-content: space-between;
1376 align-items: center;
debcf27Claude1377 padding: 14px 18px;
1378 border-bottom: 1px solid var(--border-subtle);
2ce1d0bClaude1379 transition: background var(--t-fast) var(--ease);
fc1817aClaude1380 }
1381 .commit-item:last-child { border-bottom: none; }
2ce1d0bClaude1382 .commit-item:hover { background: var(--bg-hover); }
debcf27Claude1383 .commit-message {
1384 font-size: var(--t-sm);
1385 font-weight: 500;
1386 line-height: 1.45;
1387 color: var(--text-strong);
1388 letter-spacing: -0.005em;
1389 }
1390 .commit-meta {
1391 font-family: var(--font-mono);
1392 font-size: 11px;
1393 color: var(--text-muted);
1394 margin-top: 5px;
1395 letter-spacing: 0.01em;
1396 }
fc1817aClaude1397 .commit-sha {
1398 font-family: var(--font-mono);
debcf27Claude1399 font-feature-settings: var(--mono-feat);
1400 font-size: 11px;
1401 padding: 4px 9px;
fc1817aClaude1402 background: var(--bg-tertiary);
1403 border: 1px solid var(--border);
2ce1d0bClaude1404 border-radius: var(--r-sm);
debcf27Claude1405 color: var(--accent);
1406 font-weight: 600;
1407 letter-spacing: 0.02em;
2ce1d0bClaude1408 transition: all var(--t-fast) var(--ease);
fc1817aClaude1409 }
debcf27Claude1410 .commit-sha:hover {
1411 border-color: rgba(140,109,255,0.40);
1412 background: var(--accent-gradient-faint);
1413 color: var(--accent-hover);
1414 text-decoration: none;
fc1817aClaude1415 }
1416
1417 .diff-view { margin-top: 16px; }
1418 .diff-file {
1419 border: 1px solid var(--border);
2ce1d0bClaude1420 border-radius: var(--r-md);
fc1817aClaude1421 margin-bottom: 16px;
1422 overflow: hidden;
2ce1d0bClaude1423 background: var(--bg-elevated);
fc1817aClaude1424 }
1425 .diff-file-header {
1426 background: var(--bg-secondary);
2ce1d0bClaude1427 padding: 10px 16px;
fc1817aClaude1428 border-bottom: 1px solid var(--border);
1429 font-family: var(--font-mono);
2ce1d0bClaude1430 font-size: var(--t-sm);
1431 font-weight: 500;
fc1817aClaude1432 }
1433 .diff-content {
1434 overflow-x: auto;
1435 font-family: var(--font-mono);
2ce1d0bClaude1436 font-size: var(--t-sm);
1437 line-height: 1.65;
fc1817aClaude1438 }
958d26aClaude1439 .diff-content .line-add { background: rgba(52,211,153,0.10); color: var(--green); }
1440 .diff-content .line-del { background: rgba(248,113,113,0.08); color: var(--red); }
1441 .diff-content .line-hunk { background: rgba(140,109,255,0.06); color: var(--text-link); }
2ce1d0bClaude1442 .diff-content .line { padding: 0 16px; white-space: pre; display: block; }
fc1817aClaude1443
1444 .stat-add { color: var(--green); font-weight: 600; }
1445 .stat-del { color: var(--red); font-weight: 600; }
1446
2ce1d0bClaude1447 /* ============================================================ */
1448 /* Empty state */
1449 /* ============================================================ */
fc1817aClaude1450 .empty-state {
1451 text-align: center;
958d26aClaude1452 padding: 96px 24px;
fc1817aClaude1453 color: var(--text-muted);
2ce1d0bClaude1454 border: 1px dashed var(--border);
1455 border-radius: var(--r-lg);
958d26aClaude1456 background:
1457 radial-gradient(60% 60% at 50% 0%, rgba(140,109,255,0.05), transparent 70%),
1458 var(--bg-elevated);
1459 position: relative;
1460 overflow: hidden;
1461 }
1462 .empty-state::before {
1463 content: '';
1464 position: absolute;
1465 inset: 0;
1466 background-image: radial-gradient(rgba(255,255,255,0.025) 1px, transparent 1px);
1467 background-size: 24px 24px;
1468 opacity: 0.5;
1469 pointer-events: none;
1470 mask-image: radial-gradient(ellipse at center, #000 30%, transparent 70%);
1471 -webkit-mask-image: radial-gradient(ellipse at center, #000 30%, transparent 70%);
1472 }
1473 :root[data-theme='light'] .empty-state::before {
1474 background-image: radial-gradient(rgba(15,16,28,0.08) 1px, transparent 1px);
fc1817aClaude1475 }
958d26aClaude1476 .empty-state > * { position: relative; z-index: 1; }
2ce1d0bClaude1477 .empty-state h2 {
958d26aClaude1478 font-size: var(--t-xl);
2ce1d0bClaude1479 margin-bottom: 8px;
958d26aClaude1480 color: var(--text-strong);
1481 letter-spacing: -0.022em;
2ce1d0bClaude1482 }
958d26aClaude1483 .empty-state p { font-size: var(--t-md); max-width: 480px; margin: 0 auto; line-height: 1.55; }
fc1817aClaude1484 .empty-state pre {
1485 text-align: left;
1486 display: inline-block;
1487 background: var(--bg-secondary);
958d26aClaude1488 padding: 18px 24px;
1489 border-radius: var(--r-md);
fc1817aClaude1490 border: 1px solid var(--border);
1491 font-family: var(--font-mono);
958d26aClaude1492 font-feature-settings: var(--mono-feat);
2ce1d0bClaude1493 font-size: var(--t-sm);
958d26aClaude1494 margin-top: 24px;
fc1817aClaude1495 line-height: 1.8;
2ce1d0bClaude1496 color: var(--text);
958d26aClaude1497 box-shadow: var(--elev-1);
fc1817aClaude1498 }
1499
2ce1d0bClaude1500 /* ============================================================ */
1501 /* Badges */
1502 /* ============================================================ */
fc1817aClaude1503 .badge {
2ce1d0bClaude1504 display: inline-flex;
1505 align-items: center;
1506 gap: 4px;
1507 padding: 2px 9px;
1508 border-radius: var(--r-full);
1509 font-size: var(--t-xs);
fc1817aClaude1510 font-weight: 500;
1511 background: var(--bg-tertiary);
1512 border: 1px solid var(--border);
1513 color: var(--text-muted);
2ce1d0bClaude1514 line-height: 1.5;
fc1817aClaude1515 }
1516
2ce1d0bClaude1517 /* ============================================================ */
1518 /* Branch dropdown */
1519 /* ============================================================ */
fc1817aClaude1520 .branch-selector {
1521 display: inline-flex;
1522 align-items: center;
2ce1d0bClaude1523 gap: 6px;
1524 padding: 6px 12px;
1525 background: var(--bg-elevated);
fc1817aClaude1526 border: 1px solid var(--border);
2ce1d0bClaude1527 border-radius: var(--r-sm);
1528 font-size: var(--t-sm);
fc1817aClaude1529 color: var(--text);
1530 margin-bottom: 12px;
2ce1d0bClaude1531 transition: border-color var(--t-fast) var(--ease);
fc1817aClaude1532 }
2ce1d0bClaude1533 .branch-selector:hover { border-color: var(--border-strong); }
fc1817aClaude1534
06d5ffeClaude1535 .branch-dropdown {
1536 position: relative;
1537 display: inline-block;
1538 margin-bottom: 12px;
1539 }
1540 .branch-dropdown-content {
1541 display: none;
1542 position: absolute;
2ce1d0bClaude1543 top: calc(100% + 4px);
06d5ffeClaude1544 left: 0;
1545 z-index: 10;
2ce1d0bClaude1546 min-width: 220px;
1547 background: var(--bg-elevated);
1548 border: 1px solid var(--border-strong);
1549 border-radius: var(--r-md);
1550 overflow: hidden;
1551 box-shadow: var(--elev-3);
06d5ffeClaude1552 }
1553 .branch-dropdown:hover .branch-dropdown-content,
1554 .branch-dropdown:focus-within .branch-dropdown-content { display: block; }
1555 .branch-dropdown-content a {
1556 display: block;
2ce1d0bClaude1557 padding: 9px 14px;
1558 font-size: var(--t-sm);
06d5ffeClaude1559 color: var(--text);
1560 border-bottom: 1px solid var(--border);
2ce1d0bClaude1561 transition: background var(--t-fast) var(--ease);
06d5ffeClaude1562 }
1563 .branch-dropdown-content a:last-child { border-bottom: none; }
2ce1d0bClaude1564 .branch-dropdown-content a:hover { background: var(--bg-hover); text-decoration: none; }
1565 .branch-dropdown-content a.active-branch { color: var(--text-link); font-weight: 600; background: var(--accent-gradient-faint); }
06d5ffeClaude1566
2ce1d0bClaude1567 /* ============================================================ */
1568 /* Card grid */
1569 /* ============================================================ */
1570 .card-grid {
1571 display: grid;
1572 grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
1573 gap: 16px;
1574 }
fc1817aClaude1575 .card {
1576 border: 1px solid var(--border);
2ce1d0bClaude1577 border-radius: var(--r-md);
958d26aClaude1578 padding: 20px;
2ce1d0bClaude1579 background: var(--bg-elevated);
1580 transition:
958d26aClaude1581 border-color var(--t-base) var(--ease),
1582 transform var(--t-base) var(--ease-out-quart),
2ce1d0bClaude1583 box-shadow var(--t-base) var(--ease);
1584 position: relative;
1585 overflow: hidden;
958d26aClaude1586 isolation: isolate;
1587 }
1588 .card::before {
1589 content: '';
1590 position: absolute;
1591 inset: 0;
1592 background: linear-gradient(135deg, rgba(140,109,255,0.06), transparent 50%);
1593 opacity: 0;
1594 transition: opacity var(--t-base) var(--ease);
1595 pointer-events: none;
1596 z-index: -1;
2ce1d0bClaude1597 }
1598 .card:hover {
1599 border-color: var(--border-strong);
1600 box-shadow: var(--elev-2);
958d26aClaude1601 transform: translateY(-2px);
2ce1d0bClaude1602 }
958d26aClaude1603 .card:hover::before { opacity: 1; }
1604 .card h3 { font-size: var(--t-md); margin-bottom: 6px; letter-spacing: -0.012em; }
2ce1d0bClaude1605 .card h3 a { color: var(--text); font-weight: 600; }
1606 .card h3 a:hover { color: var(--text-link); }
1607 .card p { font-size: var(--t-sm); color: var(--text-muted); line-height: 1.5; }
1608 .card-meta {
1609 display: flex;
1610 gap: 14px;
1611 margin-top: 14px;
1612 padding-top: 14px;
1613 border-top: 1px solid var(--border);
1614 font-size: var(--t-xs);
1615 color: var(--text-muted);
1616 }
1617 .card-meta span { display: flex; align-items: center; gap: 5px; }
1618
1619 /* ============================================================ */
1620 /* Stat card / box */
1621 /* ============================================================ */
1622 .stat-card {
1623 background: var(--bg-elevated);
1624 border: 1px solid var(--border);
1625 border-radius: var(--r-md);
fc1817aClaude1626 padding: 16px;
2ce1d0bClaude1627 transition: border-color var(--t-fast) var(--ease);
1628 }
1629 .stat-card:hover { border-color: var(--border-strong); }
1630 .stat-label {
1631 font-size: var(--t-xs);
1632 color: var(--text-muted);
1633 text-transform: uppercase;
1634 letter-spacing: 0.06em;
1635 font-weight: 500;
1636 }
1637 .stat-value {
1638 font-size: var(--t-xl);
1639 font-weight: 700;
1640 margin-top: 4px;
1641 letter-spacing: -0.025em;
1642 color: var(--text);
1643 font-feature-settings: 'tnum';
fc1817aClaude1644 }
06d5ffeClaude1645
2ce1d0bClaude1646 /* ============================================================ */
1647 /* Star button */
1648 /* ============================================================ */
06d5ffeClaude1649 .star-btn {
1650 display: inline-flex;
1651 align-items: center;
1652 gap: 6px;
2ce1d0bClaude1653 padding: 5px 12px;
1654 background: var(--bg-elevated);
06d5ffeClaude1655 border: 1px solid var(--border);
2ce1d0bClaude1656 border-radius: var(--r-sm);
06d5ffeClaude1657 color: var(--text);
2ce1d0bClaude1658 font-size: var(--t-sm);
1659 font-weight: 500;
06d5ffeClaude1660 cursor: pointer;
2ce1d0bClaude1661 transition: all var(--t-fast) var(--ease);
1662 }
1663 .star-btn:hover { background: var(--bg-surface); border-color: var(--border-strong); text-decoration: none; }
1664 .star-btn.starred {
1665 color: var(--yellow);
958d26aClaude1666 border-color: rgba(251,191,36,0.4);
1667 background: rgba(251,191,36,0.08);
06d5ffeClaude1668 }
1669
2ce1d0bClaude1670 /* ============================================================ */
1671 /* User profile */
1672 /* ============================================================ */
06d5ffeClaude1673 .user-profile {
1674 display: flex;
1675 gap: 32px;
1676 margin-bottom: 32px;
2ce1d0bClaude1677 padding: 24px;
1678 background: var(--bg-elevated);
1679 border: 1px solid var(--border);
1680 border-radius: var(--r-lg);
06d5ffeClaude1681 }
1682 .user-avatar {
1683 width: 96px;
1684 height: 96px;
2ce1d0bClaude1685 border-radius: var(--r-full);
1686 background: var(--accent-gradient-soft);
1687 border: 1px solid var(--border-strong);
06d5ffeClaude1688 display: flex;
1689 align-items: center;
1690 justify-content: center;
2ce1d0bClaude1691 font-size: 36px;
1692 font-weight: 600;
1693 color: var(--text);
06d5ffeClaude1694 flex-shrink: 0;
2ce1d0bClaude1695 letter-spacing: -0.02em;
06d5ffeClaude1696 }
2ce1d0bClaude1697 .user-info h2 { font-size: var(--t-xl); margin-bottom: 2px; letter-spacing: -0.025em; }
1698 .user-info .username { font-size: var(--t-md); color: var(--text-muted); }
1699 .user-info .bio { font-size: var(--t-sm); color: var(--text-muted); margin-top: 10px; line-height: 1.55; }
06d5ffeClaude1700
2ce1d0bClaude1701 /* ============================================================ */
1702 /* New repo form */
1703 /* ============================================================ */
1704 .new-repo-form { max-width: 640px; }
1705 .new-repo-form h2 { margin-bottom: 24px; font-size: var(--t-xl); letter-spacing: -0.025em; }
1706 .visibility-options { display: flex; gap: 12px; margin-bottom: 20px; }
06d5ffeClaude1707 .visibility-option {
1708 flex: 1;
2ce1d0bClaude1709 padding: 16px;
06d5ffeClaude1710 border: 1px solid var(--border);
2ce1d0bClaude1711 border-radius: var(--r-md);
1712 background: var(--bg-elevated);
06d5ffeClaude1713 cursor: pointer;
2ce1d0bClaude1714 text-align: left;
1715 transition: all var(--t-fast) var(--ease);
1716 }
1717 .visibility-option:hover { border-color: var(--border-strong); background: var(--bg-surface); }
1718 .visibility-option:has(input:checked) {
1719 border-color: var(--accent);
1720 background: var(--accent-gradient-faint);
1721 box-shadow: 0 0 0 1px var(--accent);
06d5ffeClaude1722 }
1723 .visibility-option input { display: none; }
2ce1d0bClaude1724 .visibility-option .vis-label { font-size: var(--t-sm); font-weight: 600; margin-bottom: 4px; }
1725 .visibility-option .vis-desc { font-size: var(--t-xs); color: var(--text-muted); }
79136bbClaude1726
2ce1d0bClaude1727 /* ============================================================ */
1728 /* Issues */
1729 /* ============================================================ */
1730 .issue-tabs { display: flex; gap: 4px; }
1731 .issue-tabs a {
1732 color: var(--text-muted);
1733 font-size: var(--t-sm);
1734 font-weight: 500;
1735 padding: 6px 12px;
1736 border-radius: var(--r-sm);
1737 transition: all var(--t-fast) var(--ease);
1738 }
1739 .issue-tabs a:hover { color: var(--text); background: var(--bg-hover); text-decoration: none; }
1740 .issue-tabs a.active { color: var(--text); background: var(--bg-elevated); }
79136bbClaude1741
2ce1d0bClaude1742 .issue-list {
1743 border: 1px solid var(--border);
1744 border-radius: var(--r-md);
1745 overflow: hidden;
1746 background: var(--bg-elevated);
1747 }
79136bbClaude1748 .issue-item {
1749 display: flex;
2ce1d0bClaude1750 gap: 14px;
79136bbClaude1751 align-items: flex-start;
2ce1d0bClaude1752 padding: 14px 16px;
79136bbClaude1753 border-bottom: 1px solid var(--border);
2ce1d0bClaude1754 transition: background var(--t-fast) var(--ease);
79136bbClaude1755 }
1756 .issue-item:last-child { border-bottom: none; }
2ce1d0bClaude1757 .issue-item:hover { background: var(--bg-hover); }
1758 .issue-state-icon {
1759 font-size: 14px;
1760 padding-top: 2px;
1761 width: 18px;
1762 height: 18px;
1763 display: inline-flex;
1764 align-items: center;
1765 justify-content: center;
1766 border-radius: var(--r-full);
1767 flex-shrink: 0;
1768 }
79136bbClaude1769 .state-open { color: var(--green); }
958d26aClaude1770 .state-closed { color: #b69dff; }
2ce1d0bClaude1771 .issue-title {
debcf27Claude1772 font-family: var(--font-display);
1773 font-size: var(--t-md);
2ce1d0bClaude1774 font-weight: 600;
debcf27Claude1775 line-height: 1.35;
1776 letter-spacing: -0.012em;
1777 }
1778 .issue-title a { color: var(--text-strong); transition: color var(--t-fast) var(--ease); }
1779 .issue-title a:hover { color: var(--accent); text-decoration: none; }
1780 .issue-meta {
1781 font-family: var(--font-mono);
1782 font-size: 11px;
1783 color: var(--text-muted);
1784 margin-top: 5px;
1785 letter-spacing: 0.01em;
2ce1d0bClaude1786 }
79136bbClaude1787
1788 .issue-badge {
1789 display: inline-flex;
1790 align-items: center;
2ce1d0bClaude1791 gap: 6px;
79136bbClaude1792 padding: 4px 12px;
2ce1d0bClaude1793 border-radius: var(--r-full);
1794 font-size: var(--t-sm);
79136bbClaude1795 font-weight: 500;
2ce1d0bClaude1796 line-height: 1.4;
79136bbClaude1797 }
958d26aClaude1798 .badge-open { background: rgba(52,211,153,0.10); color: var(--green); border: 1px solid rgba(52,211,153,0.35); }
1799 .badge-closed { background: rgba(182,157,255,0.10); color: #b69dff; border: 1px solid rgba(182,157,255,0.35); }
1800 .badge-merged { background: rgba(140,109,255,0.10); color: var(--accent); border: 1px solid rgba(140,109,255,0.35); }
2ce1d0bClaude1801 .state-merged { color: var(--accent); }
958d26aClaude1802 .ai-review { border-color: var(--accent); box-shadow: 0 0 0 1px rgba(140,109,255,0.3); }
79136bbClaude1803
2ce1d0bClaude1804 .issue-detail { max-width: 920px; }
79136bbClaude1805 .issue-comment-box {
1806 border: 1px solid var(--border);
2ce1d0bClaude1807 border-radius: var(--r-md);
79136bbClaude1808 margin-bottom: 16px;
1809 overflow: hidden;
2ce1d0bClaude1810 background: var(--bg-elevated);
79136bbClaude1811 }
1812 .comment-header {
1813 background: var(--bg-secondary);
2ce1d0bClaude1814 padding: 10px 16px;
79136bbClaude1815 border-bottom: 1px solid var(--border);
2ce1d0bClaude1816 font-size: var(--t-sm);
79136bbClaude1817 color: var(--text-muted);
1818 }
1819
2ce1d0bClaude1820 /* ============================================================ */
1821 /* Panel — flexible container used across many pages */
1822 /* ============================================================ */
1823 .panel {
1824 background: var(--bg-elevated);
1825 border: 1px solid var(--border);
1826 border-radius: var(--r-md);
1827 overflow: hidden;
1828 }
1829 .panel-item {
1830 display: flex;
1831 align-items: center;
1832 gap: 12px;
1833 padding: 12px 16px;
79136bbClaude1834 border-bottom: 1px solid var(--border);
2ce1d0bClaude1835 transition: background var(--t-fast) var(--ease);
1836 }
1837 .panel-item:last-child { border-bottom: none; }
1838 .panel-item:hover { background: var(--bg-hover); }
1839 .panel-empty {
1840 padding: 24px;
1841 text-align: center;
79136bbClaude1842 color: var(--text-muted);
2ce1d0bClaude1843 font-size: var(--t-sm);
79136bbClaude1844 }
1845
2ce1d0bClaude1846 /* ============================================================ */
1847 /* Search */
1848 /* ============================================================ */
79136bbClaude1849 .search-results .diff-file { margin-bottom: 12px; }
16b325cClaude1850
2ce1d0bClaude1851 /* ============================================================ */
1852 /* Timeline */
1853 /* ============================================================ */
1854 .timeline { position: relative; padding-left: 28px; }
16b325cClaude1855 .timeline::before {
1856 content: '';
1857 position: absolute;
1858 left: 4px;
1859 top: 8px;
1860 bottom: 8px;
1861 width: 2px;
2ce1d0bClaude1862 background: linear-gradient(180deg, var(--border) 0%, transparent 100%);
16b325cClaude1863 }
2ce1d0bClaude1864 .timeline-item { position: relative; padding-bottom: 16px; }
16b325cClaude1865 .timeline-dot {
1866 position: absolute;
2ce1d0bClaude1867 left: -28px;
1868 top: 8px;
1869 width: 12px;
1870 height: 12px;
1871 border-radius: var(--r-full);
1872 background: var(--accent-gradient);
16b325cClaude1873 border: 2px solid var(--bg);
2ce1d0bClaude1874 box-shadow: 0 0 0 1px var(--border-strong);
16b325cClaude1875 }
1876 .timeline-content {
2ce1d0bClaude1877 background: var(--bg-elevated);
16b325cClaude1878 border: 1px solid var(--border);
2ce1d0bClaude1879 border-radius: var(--r-md);
1880 padding: 14px 16px;
16b325cClaude1881 }
f1ab587Claude1882
2ce1d0bClaude1883 /* ============================================================ */
1884 /* Toggle switch */
1885 /* ============================================================ */
f1ab587Claude1886 .toggle-switch {
1887 position: relative;
1888 display: inline-block;
2ce1d0bClaude1889 width: 40px;
1890 height: 22px;
f1ab587Claude1891 flex-shrink: 0;
1892 margin-left: 16px;
1893 }
1894 .toggle-switch input { opacity: 0; width: 0; height: 0; }
1895 .toggle-slider {
1896 position: absolute;
1897 cursor: pointer;
1898 top: 0; left: 0; right: 0; bottom: 0;
1899 background: var(--bg-tertiary);
1900 border: 1px solid var(--border);
2ce1d0bClaude1901 border-radius: var(--r-full);
1902 transition: all var(--t-base) var(--ease);
f1ab587Claude1903 }
1904 .toggle-slider::before {
1905 content: '';
1906 position: absolute;
2ce1d0bClaude1907 height: 16px;
1908 width: 16px;
f1ab587Claude1909 left: 2px;
1910 bottom: 2px;
1911 background: var(--text-muted);
2ce1d0bClaude1912 border-radius: var(--r-full);
1913 transition: all var(--t-base) var(--ease);
f1ab587Claude1914 }
1915 .toggle-switch input:checked + .toggle-slider {
2ce1d0bClaude1916 background: var(--accent-gradient);
1917 border-color: transparent;
958d26aClaude1918 box-shadow: 0 0 0 1px rgba(140,109,255,0.4);
f1ab587Claude1919 }
1920 .toggle-switch input:checked + .toggle-slider::before {
2ce1d0bClaude1921 transform: translateX(18px);
f1ab587Claude1922 background: #fff;
1923 }
ef8d378Claude1924
1925 /* ============================================================
1926 * 2026 polish layer (purely additive — no layout changes).
1927 * Improves typography rendering, focus states, hover affordances,
1928 * and adds the gradient brand cue to primary buttons. Anything
1929 * that could alter dimensions stays in the rules above.
1930 * ============================================================ */
1931 html { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
1932 body { letter-spacing: -0.005em; font-feature-settings: 'cv11', 'ss01', 'ss03'; }
1933 *::selection { background: rgba(168,85,247,0.35); color: var(--text); }
1934
1935 h1, h2, h3, h4 { letter-spacing: -0.018em; }
1936 h1 { letter-spacing: -0.025em; }
1937
1938 /* Smoother colour transitions everywhere links live */
1939 a { transition: color 120ms cubic-bezier(0.16,1,0.3,1); }
1940
1941 /* Buttons: focus rings + smoother transitions; primary gets the gradient */
1942 .btn {
1943 transition:
1944 background 120ms cubic-bezier(0.16,1,0.3,1),
1945 border-color 120ms cubic-bezier(0.16,1,0.3,1),
1946 transform 120ms cubic-bezier(0.16,1,0.3,1),
1947 box-shadow 120ms cubic-bezier(0.16,1,0.3,1);
1948 }
1949 .btn:active { transform: translateY(0.5px); }
1950 .btn:focus-visible {
1951 outline: none;
1952 box-shadow: 0 0 0 3px rgba(168,85,247,0.30);
1953 }
1954 .btn-primary {
1955 background: linear-gradient(135deg, #a855f7 0%, #06b6d4 100%);
1956 border-color: transparent;
1957 box-shadow:
1958 inset 0 1px 0 rgba(255,255,255,0.15),
1959 0 1px 2px rgba(168,85,247,0.25);
1960 }
1961 .btn-primary:hover {
1962 background: linear-gradient(135deg, #b766f8 0%, #22cce0 100%);
1963 filter: none;
1964 box-shadow:
1965 inset 0 1px 0 rgba(255,255,255,0.20),
1966 0 4px 12px rgba(168,85,247,0.30);
1967 }
1968
1969 /* Inputs: cleaner focus ring + hover */
1970 .form-group input:hover,
1971 .form-group textarea:hover,
1972 .form-group select:hover {
1973 border-color: rgba(255,255,255,0.14);
1974 }
1975 .form-group input:focus,
1976 .form-group textarea:focus,
1977 .form-group select:focus {
1978 border-color: rgba(168,85,247,0.55);
1979 box-shadow: 0 0 0 3px rgba(168,85,247,0.22);
1980 }
1981 :root[data-theme='light'] .form-group input:hover,
1982 :root[data-theme='light'] .form-group textarea:hover,
1983 :root[data-theme='light'] .form-group select:hover {
1984 border-color: rgba(0,0,0,0.18);
1985 }
1986
1987 /* Cards: subtle hover lift */
1988 .card {
1989 transition:
1990 border-color 160ms cubic-bezier(0.16,1,0.3,1),
1991 transform 160ms cubic-bezier(0.16,1,0.3,1),
1992 box-shadow 200ms cubic-bezier(0.16,1,0.3,1);
1993 }
1994 .card:hover {
1995 border-color: rgba(255,255,255,0.18);
1996 transform: translateY(-1px);
1997 box-shadow: 0 8px 24px rgba(0,0,0,0.30);
1998 }
1999 :root[data-theme='light'] .card:hover {
2000 border-color: rgba(0,0,0,0.18);
2001 box-shadow: 0 8px 24px rgba(0,0,0,0.08);
2002 }
2003
2004 /* Issue / commit / panel rows: smoother hover */
2005 .issue-item, .commit-item {
2006 transition: background 120ms cubic-bezier(0.16,1,0.3,1);
2007 }
2008 .repo-nav a {
2009 transition: color 120ms cubic-bezier(0.16,1,0.3,1),
2010 border-bottom-color 120ms cubic-bezier(0.16,1,0.3,1);
2011 }
2012 .nav-link {
2013 transition: color 120ms cubic-bezier(0.16,1,0.3,1);
2014 }
2015
2016 /* Auth card: subtle elevation so register/login feel premium */
2017 .auth-container {
2018 background: var(--bg-secondary);
2019 border: 1px solid var(--border);
2020 border-radius: var(--r-lg, 12px);
2021 padding: 32px;
2022 box-shadow: 0 4px 16px rgba(0,0,0,0.30), 0 0 0 1px var(--border);
2023 }
2024 :root[data-theme='light'] .auth-container {
2025 box-shadow: 0 4px 16px rgba(0,0,0,0.06), 0 0 0 1px var(--border);
2026 }
2027 .auth-container h2 { letter-spacing: -0.025em; }
2028
2029 /* Empty state: dashed border, generous padding */
2030 .empty-state {
2031 border: 1px dashed var(--border);
2032 border-radius: var(--r-lg, 12px);
2033 background: var(--bg);
2034 }
2035
2036 /* Badges + commit-sha: smoother transition */
2037 .commit-sha, .badge { transition: all 120ms cubic-bezier(0.16,1,0.3,1); }
2038
2039 /* Gradient text utility — matches landing's accent treatment */
2040 .gradient-text {
2041 background: linear-gradient(135deg, #a855f7 0%, #06b6d4 100%);
2042 -webkit-background-clip: text;
2043 background-clip: text;
2044 -webkit-text-fill-color: transparent;
2045 }
2046
2047 /* Custom scrollbars (subtle, themed) */
2048 ::-webkit-scrollbar { width: 10px; height: 10px; }
2049 ::-webkit-scrollbar-track { background: transparent; }
2050 ::-webkit-scrollbar-thumb {
2051 background: rgba(255,255,255,0.06);
2052 border: 2px solid var(--bg);
2053 border-radius: 9999px;
2054 }
2055 ::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,0.14); }
2056 :root[data-theme='light'] ::-webkit-scrollbar-thumb { background: rgba(0,0,0,0.10); }
2057 :root[data-theme='light'] ::-webkit-scrollbar-thumb:hover { background: rgba(0,0,0,0.18); }
2058
2059 /* Honour reduced-motion preference */
2060 @media (prefers-reduced-motion: reduce) {
2061 *, *::before, *::after {
2062 animation-duration: 0.01ms !important;
2063 animation-iteration-count: 1 !important;
2064 transition-duration: 0.01ms !important;
2065 }
2066 }
fc1817aClaude2067`;