rin
Public Open-source lightweight git hosting.
app.css · 1367 lines · 31.4 KB
Raw
1 /* Polar Design System — Minimalist Sidebar Layout, 3 Themes (light, dark, system) */
2
3 @font-face {
4 font-family: 'Inter';
5 font-style: normal;
6 font-weight: 400 600;
7 font-display: swap;
8 src: url('/static/fonts/Inter-Regular.woff2') format('woff2');
9 }
10
11 @font-face {
12 font-family: 'Inter';
13 font-style: normal;
14 font-weight: 400 600;
15 font-display: swap;
16 src: url('/static/fonts/Inter-Cyrillic.woff2') format('woff2');
17 unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
18 }
19
20 @font-face {
21 font-family: 'JetBrains Mono';
22 font-style: normal;
23 font-weight: 400 600;
24 font-display: swap;
25 src: url('/static/fonts/JetBrainsMono-Regular.woff2') format('woff2');
26 }
27
28 :root,
29 html[data-theme="light"] {
30 --background: 0 0% 100%;
31 --foreground: 0 0% 6.7%;
32 --card: 0 0% 98%;
33 --card-foreground: 0 0% 6.7%;
34 --popover: 0 0% 100%;
35 --popover-foreground: 0 0% 6.7%;
36 --primary: 0 0% 6.7%;
37 --primary-foreground: 0 0% 100%;
38 --secondary: 0 0% 95%;
39 --secondary-foreground: 0 0% 6.7%;
40 --muted: 0 0% 95%;
41 --muted-foreground: 0 0% 45%;
42 --accent: 0 0% 93%;
43 --accent-foreground: 0 0% 6.7%;
44 --destructive: 0 72% 46%;
45 --destructive-foreground: 0 0% 100%;
46 --border: 0 0% 90%;
47 --input: 0 0% 89%;
48 --ring: 0 0% 6.7%;
49 --radius: 0.45rem;
50
51 --diff-add-bg: 142 70% 94%;
52 --diff-add-fg: 142 76% 22%;
53 --diff-del-bg: 0 86% 95%;
54 --diff-del-fg: 0 72% 35%;
55
56 --syntax-kw: 262 72% 42%;
57 --syntax-str: 142 68% 28%;
58 --syntax-cmt: 0 0% 46%;
59 --syntax-fn: 215 80% 42%;
60 --syntax-num: 24 85% 38%;
61 --syntax-type: 190 78% 32%;
62 --syntax-op: 0 0% 25%;
63 color-scheme: light;
64 }
65
66 html[data-theme="dark"] {
67 --background: 0 0% 6.7%;
68 --foreground: 0 0% 100%;
69 --card: 0 0% 9%;
70 --card-foreground: 0 0% 100%;
71 --popover: 0 0% 9.5%;
72 --popover-foreground: 0 0% 100%;
73 --primary: 0 0% 100%;
74 --primary-foreground: 0 0% 6.7%;
75 --secondary: 0 0% 13%;
76 --secondary-foreground: 0 0% 100%;
77 --muted: 0 0% 12%;
78 --muted-foreground: 0 0% 65%;
79 --accent: 0 0% 15%;
80 --accent-foreground: 0 0% 100%;
81 --destructive: 0 72% 58%;
82 --destructive-foreground: 0 0% 98%;
83 --border: 0 0% 16%;
84 --input: 0 0% 17%;
85 --ring: 0 0% 85%;
86
87 --diff-add-bg: 142 50% 12%;
88 --diff-add-fg: 142 70% 75%;
89 --diff-del-bg: 0 55% 14%;
90 --diff-del-fg: 0 80% 78%;
91
92 --syntax-kw: 265 85% 78%;
93 --syntax-str: 142 65% 70%;
94 --syntax-cmt: 0 0% 54%;
95 --syntax-fn: 210 90% 74%;
96 --syntax-num: 32 90% 72%;
97 --syntax-type: 188 80% 68%;
98 --syntax-op: 0 0% 78%;
99 color-scheme: dark;
100 }
101
102 @media (prefers-color-scheme: dark) {
103 html[data-theme="system"] {
104 --background: 0 0% 6.7%;
105 --foreground: 0 0% 100%;
106 --card: 0 0% 9%;
107 --card-foreground: 0 0% 100%;
108 --popover: 0 0% 9.5%;
109 --popover-foreground: 0 0% 100%;
110 --primary: 0 0% 100%;
111 --primary-foreground: 0 0% 6.7%;
112 --secondary: 0 0% 13%;
113 --secondary-foreground: 0 0% 100%;
114 --muted: 0 0% 12%;
115 --muted-foreground: 0 0% 65%;
116 --accent: 0 0% 15%;
117 --accent-foreground: 0 0% 100%;
118 --destructive: 0 72% 58%;
119 --destructive-foreground: 0 0% 98%;
120 --border: 0 0% 16%;
121 --input: 0 0% 17%;
122 --ring: 0 0% 85%;
123 --diff-add-bg: 142 50% 12%;
124 --diff-add-fg: 142 70% 75%;
125 --diff-del-bg: 0 55% 14%;
126 --diff-del-fg: 0 80% 78%;
127 --syntax-kw: 265 85% 78%;
128 --syntax-str: 142 65% 70%;
129 --syntax-cmt: 0 0% 54%;
130 --syntax-fn: 210 90% 74%;
131 --syntax-num: 32 90% 72%;
132 --syntax-type: 188 80% 68%;
133 --syntax-op: 0 0% 78%;
134 color-scheme: dark;
135 }
136 }
137
138 *, *::before, *::after {
139 box-sizing: border-box;
140 border-color: hsl(var(--border));
141 }
142
143 html {
144 font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
145 font-size: 13.5px;
146 line-height: 1.5;
147 -webkit-font-smoothing: antialiased;
148 background-color: hsl(var(--background));
149 color: hsl(var(--foreground));
150 overflow-y: scroll;
151 }
152
153 body {
154 margin: 0;
155 min-height: 100vh;
156 background-color: hsl(var(--background));
157 color: hsl(var(--foreground));
158 }
159
160 code, pre, kbd, .font-mono {
161 font-family: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
162 }
163
164 a {
165 color: inherit;
166 text-decoration: none;
167 }
168
169 @media (prefers-reduced-motion: reduce) {
170 *, *::before, *::after {
171 animation-duration: 0.01ms !important;
172 transition-duration: 0.01ms !important;
173 }
174 }
175
176 :focus-visible {
177 outline: 2px solid hsl(var(--ring));
178 outline-offset: 2px;
179 }
180
181 /* App Shell: Left Sidebar + Right Main Content */
182 .app-shell {
183 display: flex;
184 flex-direction: row;
185 align-items: stretch;
186 min-height: 100vh;
187 width: 100%;
188 }
189
190 .app-sidebar {
191 width: 236px;
192 min-width: 236px;
193 max-width: 236px;
194 flex: 0 0 236px;
195 border-right: 1px solid hsl(var(--border));
196 background-color: hsl(var(--card));
197 display: none;
198 flex-direction: column;
199 justify-content: space-between;
200 position: sticky;
201 top: 0;
202 height: 100vh;
203 overflow-y: auto;
204 overflow-x: hidden;
205 padding: 0.85rem 0.75rem;
206 user-select: none;
207 transition:
208 width 200ms cubic-bezier(0.16, 1, 0.3, 1),
209 min-width 200ms cubic-bezier(0.16, 1, 0.3, 1),
210 max-width 200ms cubic-bezier(0.16, 1, 0.3, 1),
211 flex-basis 200ms cubic-bezier(0.16, 1, 0.3, 1),
212 padding 200ms cubic-bezier(0.16, 1, 0.3, 1),
213 border-color 200ms cubic-bezier(0.16, 1, 0.3, 1);
214 }
215
216 .sidebar-inner {
217 width: 218px;
218 min-width: 218px;
219 height: 100%;
220 display: flex;
221 flex-direction: column;
222 justify-content: space-between;
223 transition:
224 opacity 150ms cubic-bezier(0.16, 1, 0.3, 1),
225 transform 200ms cubic-bezier(0.16, 1, 0.3, 1);
226 }
227
228 html[data-sidebar="collapsed"] .app-sidebar {
229 width: 0;
230 min-width: 0;
231 max-width: 0;
232 flex-basis: 0;
233 padding-left: 0;
234 padding-right: 0;
235 border-right-color: transparent;
236 }
237
238 html[data-sidebar="collapsed"] .sidebar-inner {
239 opacity: 0;
240 transform: translateX(-8px);
241 pointer-events: none;
242 }
243
244 .sidebar-expand-btn {
245 position: fixed;
246 top: 0.85rem;
247 left: 0.85rem;
248 z-index: 50;
249 display: none;
250 align-items: center;
251 justify-content: center;
252 width: 2rem;
253 height: 2rem;
254 border-radius: var(--radius);
255 border: 1px solid hsl(var(--border));
256 background-color: hsl(var(--card));
257 color: hsl(var(--muted-foreground));
258 box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
259 cursor: pointer;
260 opacity: 0;
261 transform: translateX(-6px) scale(0.95);
262 pointer-events: none;
263 transition:
264 opacity 160ms cubic-bezier(0.16, 1, 0.3, 1),
265 transform 160ms cubic-bezier(0.16, 1, 0.3, 1),
266 background-color 120ms ease,
267 color 120ms ease;
268 }
269
270 .sidebar-expand-btn:hover {
271 background-color: hsl(var(--accent));
272 color: hsl(var(--foreground));
273 }
274
275 .mobile-topbar {
276 display: flex;
277 align-items: center;
278 justify-content: space-between;
279 height: 2.75rem;
280 padding: 0 0.85rem;
281 border-bottom: 1px solid hsl(var(--border));
282 background-color: hsl(var(--card));
283 }
284
285 .app-col {
286 flex: 1 1 0%;
287 min-width: 0;
288 width: 100%;
289 display: flex;
290 flex-direction: column;
291 min-height: 100vh;
292 }
293
294 .app-main {
295 flex: 1 1 auto;
296 width: 100%;
297 padding: 1.5rem 1.25rem 3rem;
298 }
299
300 @keyframes pageFadeIn {
301 from {
302 opacity: 0;
303 transform: translateY(4px);
304 }
305 to {
306 opacity: 1;
307 transform: translateY(0);
308 }
309 }
310
311 .app-main > .container,
312 .app-main > .container-narrow {
313 animation: pageFadeIn 160ms cubic-bezier(0.16, 1, 0.3, 1);
314 }
315
316 @media (min-width: 640px) {
317 .app-sidebar {
318 display: flex;
319 }
320 .sidebar-expand-btn {
321 display: inline-flex;
322 }
323 html[data-sidebar="collapsed"] .sidebar-expand-btn {
324 opacity: 1;
325 transform: translateX(0) scale(1);
326 pointer-events: auto;
327 }
328 .mobile-topbar {
329 display: none;
330 }
331 .app-main {
332 padding: 2rem 2.5rem 3.5rem;
333 }
334 }
335
336 /* Unified Container Width — identical across Code, Commits, and Settings */
337 .container,
338 .container-narrow {
339 width: 100%;
340 max-width: 960px;
341 margin-left: auto;
342 margin-right: auto;
343 }
344
345 /* Sidebar Navigation */
346 .nav-item {
347 display: flex;
348 align-items: center;
349 justify-content: space-between;
350 gap: 0.5rem;
351 height: 1.95rem;
352 padding: 0 0.55rem;
353 border-radius: var(--radius);
354 font-size: 0.85rem;
355 color: hsl(var(--muted-foreground));
356 transition: background-color 140ms ease, color 140ms ease, transform 120ms cubic-bezier(0.16, 1, 0.3, 1);
357 cursor: pointer;
358 border: 0;
359 background: transparent;
360 width: 100%;
361 text-align: left;
362 overflow: hidden;
363 }
364 .nav-item:hover,
365 .nav-item.active {
366 background-color: hsl(var(--accent));
367 color: hsl(var(--foreground));
368 }
369 .nav-item:active {
370 transform: scale(0.985);
371 }
372 .nav-section-label {
373 display: flex;
374 align-items: center;
375 justify-content: space-between;
376 padding: 0.45rem 0.55rem 0.25rem;
377 font-size: 0.7rem;
378 font-weight: 600;
379 text-transform: uppercase;
380 letter-spacing: 0.04em;
381 color: hsl(var(--muted-foreground));
382 }
383
384 /* Segmented Theme Control in Sidebar */
385 .segmented {
386 display: grid;
387 grid-template-columns: repeat(3, minmax(0, 1fr));
388 gap: 2px;
389 padding: 2px;
390 width: 100%;
391 background-color: hsl(var(--muted));
392 border: 1px solid hsl(var(--border));
393 border-radius: var(--radius);
394 }
395 .segmented-btn {
396 display: inline-flex;
397 align-items: center;
398 justify-content: center;
399 gap: 0.25rem;
400 height: 1.65rem;
401 padding: 0 0.2rem;
402 border: 0;
403 border-radius: calc(var(--radius) - 2px);
404 background: transparent;
405 color: hsl(var(--muted-foreground));
406 font-size: 0.72rem;
407 font-weight: 500;
408 cursor: pointer;
409 overflow: hidden;
410 text-overflow: ellipsis;
411 white-space: nowrap;
412 transition: background-color 150ms cubic-bezier(0.16, 1, 0.3, 1), color 150ms ease, box-shadow 150ms ease, transform 120ms ease;
413 }
414 .segmented-btn:hover {
415 color: hsl(var(--foreground));
416 }
417 .segmented-btn:active {
418 transform: scale(0.96);
419 }
420 .segmented-btn.active {
421 background-color: hsl(var(--background));
422 color: hsl(var(--foreground));
423 box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
424 }
425
426 /* Icons */
427 .icon {
428 display: inline-block;
429 vertical-align: middle;
430 flex-shrink: 0;
431 stroke: currentColor;
432 }
433 .size-3 { width: 0.75rem; height: 0.75rem; }
434 .size-3\.5 { width: 0.875rem; height: 0.875rem; }
435 .size-4 { width: 1rem; height: 1rem; }
436 .size-5 { width: 1.25rem; height: 1.25rem; }
437 .size-6 { width: 1.5rem; height: 1.5rem; }
438
439 /* Buttons */
440 .btn {
441 display: inline-flex;
442 align-items: center;
443 justify-content: center;
444 gap: 0.4rem;
445 white-space: nowrap;
446 border-radius: var(--radius);
447 font-size: 0.85rem;
448 font-weight: 500;
449 line-height: 1;
450 height: 1.95rem;
451 padding: 0 0.7rem;
452 border: 1px solid transparent;
453 cursor: pointer;
454 transition: background-color 140ms ease, border-color 140ms ease, color 140ms ease, opacity 140ms ease, transform 120ms cubic-bezier(0.16, 1, 0.3, 1);
455 user-select: none;
456 }
457 .btn:active:not(:disabled) {
458 transform: scale(0.97);
459 }
460 .btn:disabled {
461 opacity: 0.5;
462 pointer-events: none;
463 }
464 .btn-sm {
465 height: 1.7rem;
466 padding: 0 0.5rem;
467 font-size: 0.78rem;
468 }
469 .btn-lg {
470 height: 2.3rem;
471 padding: 0 1rem;
472 font-size: 0.92rem;
473 }
474 .btn-icon {
475 width: 1.9rem;
476 height: 1.9rem;
477 padding: 0;
478 }
479 .btn-default, .btn-primary {
480 background-color: hsl(var(--primary));
481 color: hsl(var(--primary-foreground));
482 }
483 .btn-default:hover, .btn-primary:hover {
484 opacity: 0.9;
485 }
486 .btn-secondary {
487 background-color: hsl(var(--secondary));
488 color: hsl(var(--secondary-foreground));
489 border-color: hsl(var(--border));
490 }
491 .btn-secondary:hover {
492 background-color: hsl(var(--accent));
493 }
494 .btn-outline {
495 background-color: transparent;
496 color: hsl(var(--foreground));
497 border-color: hsl(var(--border));
498 }
499 .btn-outline:hover {
500 background-color: hsl(var(--accent));
501 color: hsl(var(--accent-foreground));
502 }
503 .btn-ghost {
504 background-color: transparent;
505 color: hsl(var(--muted-foreground));
506 }
507 .btn-ghost:hover {
508 background-color: hsl(var(--accent));
509 color: hsl(var(--foreground));
510 }
511 .btn-destructive {
512 background-color: hsl(var(--destructive));
513 color: hsl(var(--destructive-foreground));
514 }
515 .btn-destructive:hover {
516 opacity: 0.9;
517 }
518
519 /* Inputs, Selects, Textareas */
520 .input, .select, .textarea {
521 display: block;
522 width: 100%;
523 border-radius: var(--radius);
524 border: 1px solid hsl(var(--input));
525 background-color: hsl(var(--background));
526 color: hsl(var(--foreground));
527 font-size: 0.85rem;
528 padding: 0.35rem 0.6rem;
529 transition: border-color 100ms ease;
530 }
531 .input, .select {
532 height: 2.05rem;
533 }
534 .textarea {
535 min-height: 4rem;
536 resize: vertical;
537 }
538 .input:focus, .select:focus, .textarea:focus {
539 outline: none;
540 border-color: hsl(var(--ring));
541 }
542 .input::placeholder, .textarea::placeholder {
543 color: hsl(var(--muted-foreground));
544 }
545 .label {
546 display: block;
547 font-size: 0.8rem;
548 font-weight: 500;
549 margin-bottom: 0.3rem;
550 color: hsl(var(--foreground));
551 }
552 .field-hint {
553 font-size: 0.74rem;
554 color: hsl(var(--muted-foreground));
555 margin-top: 0.25rem;
556 }
557
558 /* Switch */
559 .switch {
560 position: relative;
561 display: inline-flex;
562 width: 2.1rem;
563 height: 1.2rem;
564 flex-shrink: 0;
565 cursor: pointer;
566 align-items: center;
567 border-radius: 9999px;
568 border: 1px solid hsl(var(--border));
569 background-color: hsl(var(--muted));
570 }
571 .switch input {
572 opacity: 0;
573 width: 0;
574 height: 0;
575 position: absolute;
576 }
577 .switch-thumb {
578 pointer-events: none;
579 display: block;
580 width: 0.85rem;
581 height: 0.85rem;
582 border-radius: 9999px;
583 background-color: hsl(var(--foreground));
584 transform: translateX(0.15rem);
585 transition: transform 100ms ease;
586 }
587 .switch input:checked ~ .switch-thumb {
588 transform: translateX(0.95rem);
589 }
590
591 /* Cards */
592 .card {
593 border-radius: var(--radius);
594 border: 1px solid hsl(var(--border));
595 background-color: hsl(var(--card));
596 color: hsl(var(--card-foreground));
597 }
598 .card-header {
599 padding: 0.7rem 0.9rem;
600 border-bottom: 1px solid hsl(var(--border));
601 display: flex;
602 align-items: center;
603 justify-content: space-between;
604 gap: 0.75rem;
605 }
606 .card-body {
607 padding: 0.9rem;
608 }
609 .card-footer {
610 padding: 0.65rem 0.9rem;
611 border-top: 1px solid hsl(var(--border));
612 background-color: hsl(var(--muted) / 0.3);
613 }
614
615 /* Badges */
616 .badge {
617 display: inline-flex;
618 align-items: center;
619 gap: 0.25rem;
620 border-radius: 9999px;
621 border: 1px solid hsl(var(--border));
622 padding: 0.08rem 0.45rem;
623 font-size: 0.72rem;
624 font-weight: 500;
625 line-height: 1.3;
626 color: hsl(var(--foreground));
627 background-color: hsl(var(--secondary));
628 }
629 .badge-outline {
630 background-color: transparent;
631 color: hsl(var(--muted-foreground));
632 }
633 .badge-primary {
634 background-color: hsl(var(--primary));
635 color: hsl(var(--primary-foreground));
636 border-color: transparent;
637 }
638 .badge-destructive {
639 background-color: hsl(var(--destructive) / 0.12);
640 color: hsl(var(--destructive));
641 border-color: hsl(var(--destructive) / 0.3);
642 }
643
644 /* Kbd */
645 kbd, .kbd {
646 display: inline-flex;
647 align-items: center;
648 justify-content: center;
649 min-width: 1.25rem;
650 height: 1.15rem;
651 padding: 0 0.28rem;
652 font-size: 0.68rem;
653 font-weight: 500;
654 line-height: 1;
655 color: hsl(var(--muted-foreground));
656 background-color: hsl(var(--muted));
657 border: 1px solid hsl(var(--border));
658 border-radius: 0.25rem;
659 }
660
661 /* Avatar */
662 .avatar {
663 display: inline-flex;
664 align-items: center;
665 justify-content: center;
666 width: 1.45rem;
667 height: 1.45rem;
668 border-radius: 9999px;
669 background-color: hsl(var(--secondary));
670 border: 1px solid hsl(var(--border));
671 font-size: 0.7rem;
672 font-weight: 600;
673 color: hsl(var(--foreground));
674 text-transform: uppercase;
675 flex-shrink: 0;
676 overflow: hidden;
677 }
678 .avatar-img {
679 width: 100%;
680 height: 100%;
681 object-fit: cover;
682 display: block;
683 }
684 .avatar-lg {
685 width: 2.3rem;
686 height: 2.3rem;
687 font-size: 0.9rem;
688 }
689 .avatar-xl {
690 width: 4.25rem;
691 height: 4.25rem;
692 font-size: 1.5rem;
693 }
694
695
696 /* Separator */
697 .separator {
698 height: 1px;
699 width: 100%;
700 background-color: hsl(var(--border));
701 margin: 0.85rem 0;
702 border: 0;
703 }
704
705 /* Tabs */
706 .tabs-nav {
707 display: flex;
708 align-items: center;
709 gap: 0.15rem;
710 padding: 0.2rem;
711 border: 1px solid hsl(var(--border));
712 border-radius: 999px;
713 background: hsl(var(--muted) / 0.25);
714 margin-bottom: 1rem;
715 overflow-x: auto;
716 }
717 .tab-link {
718 display: inline-flex;
719 align-items: center;
720 gap: 0.35rem;
721 padding: 0.38rem 0.8rem;
722 font-size: 0.82rem;
723 font-weight: 500;
724 color: hsl(var(--muted-foreground));
725 border-radius: 999px;
726 white-space: nowrap;
727 transition: color 100ms ease, background-color 100ms ease;
728 }
729 .tab-link:hover {
730 color: hsl(var(--foreground));
731 }
732 .tab-link.active {
733 color: hsl(var(--foreground));
734 background: hsl(var(--card));
735 box-shadow: 0 1px 2px hsl(0 0% 0% / 0.08);
736 }
737
738 /* Dense File List & Tables */
739 .dense-list {
740 width: 100%;
741 }
742 .dense-row {
743 display: flex;
744 align-items: center;
745 justify-content: space-between;
746 gap: 0.75rem;
747 min-height: 2.05rem;
748 padding: 0.25rem 0.75rem;
749 border-bottom: 1px solid hsl(var(--border));
750 font-size: 0.85rem;
751 transition: background-color 80ms ease;
752 }
753 .dense-row:last-child {
754 border-bottom: none;
755 }
756 .dense-row:hover {
757 background-color: hsl(var(--accent) / 0.5);
758 }
759
760 .table-wrap {
761 width: 100%;
762 overflow-x: auto;
763 border: 1px solid hsl(var(--border));
764 border-radius: var(--radius);
765 background-color: hsl(var(--card));
766 }
767 .table {
768 width: 100%;
769 border-collapse: collapse;
770 font-size: 0.85rem;
771 }
772 .table th {
773 text-align: left;
774 font-weight: 500;
775 color: hsl(var(--muted-foreground));
776 padding: 0.5rem 0.75rem;
777 border-bottom: 1px solid hsl(var(--border));
778 background-color: hsl(var(--muted) / 0.35);
779 font-size: 0.75rem;
780 }
781 .table td {
782 padding: 0.5rem 0.75rem;
783 border-bottom: 1px solid hsl(var(--border));
784 vertical-align: middle;
785 }
786 .table tr:last-child td {
787 border-bottom: none;
788 }
789
790 /* Breadcrumb */
791 .breadcrumb {
792 display: flex;
793 align-items: center;
794 flex-wrap: wrap;
795 gap: 0.25rem;
796 font-size: 0.85rem;
797 }
798 .breadcrumb-sep {
799 color: hsl(var(--muted-foreground));
800 }
801
802 /* Dropdown Menu */
803 @keyframes dropdownIn {
804 from {
805 opacity: 0;
806 transform: translateY(-4px) scale(0.98);
807 }
808 to {
809 opacity: 1;
810 transform: translateY(0) scale(1);
811 }
812 }
813 .dropdown {
814 position: relative;
815 display: inline-block;
816 }
817 .dropdown-menu {
818 position: absolute;
819 left: 0;
820 top: calc(100% + 0.3rem);
821 min-width: 11rem;
822 background-color: hsl(var(--popover));
823 color: hsl(var(--popover-foreground));
824 border: 1px solid hsl(var(--border));
825 border-radius: var(--radius);
826 padding: 0.25rem;
827 box-shadow: 0 8px 24px -4px rgba(0, 0, 0, 0.22);
828 z-index: 60;
829 display: none;
830 transform-origin: top left;
831 }
832 .dropdown-menu.open {
833 display: block;
834 animation: dropdownIn 140ms cubic-bezier(0.16, 1, 0.3, 1);
835 }
836 .dropdown-item {
837 display: flex;
838 width: 100%;
839 align-items: center;
840 justify-content: space-between;
841 gap: 0.5rem;
842 padding: 0.35rem 0.55rem;
843 font-size: 0.8rem;
844 border-radius: calc(var(--radius) - 2px);
845 color: hsl(var(--popover-foreground));
846 background: transparent;
847 border: 0;
848 cursor: pointer;
849 text-align: left;
850 transition: background-color 120ms ease, color 120ms ease;
851 }
852 .dropdown-item:hover, .dropdown-item.active {
853 background-color: hsl(var(--accent));
854 color: hsl(var(--accent-foreground));
855 }
856
857 /* Modal / Dialog & Command Palette */
858 @keyframes backdropIn {
859 from { opacity: 0; }
860 to { opacity: 1; }
861 }
862 @keyframes dialogIn {
863 from {
864 opacity: 0;
865 transform: translateY(-6px) scale(0.97);
866 }
867 to {
868 opacity: 1;
869 transform: translateY(0) scale(1);
870 }
871 }
872 .backdrop {
873 position: fixed;
874 inset: 0;
875 background-color: rgba(0, 0, 0, 0.55);
876 backdrop-filter: blur(2px);
877 z-index: 80;
878 display: none;
879 align-items: flex-start;
880 justify-content: center;
881 padding: 10vh 1rem 2rem;
882 }
883 .backdrop.open {
884 display: flex;
885 animation: backdropIn 140ms ease;
886 }
887 .dialog-box {
888 width: 100%;
889 max-width: 28rem;
890 background-color: hsl(var(--popover));
891 color: hsl(var(--popover-foreground));
892 border: 1px solid hsl(var(--border));
893 border-radius: var(--radius);
894 box-shadow: 0 16px 40px -8px rgba(0, 0, 0, 0.35);
895 overflow: hidden;
896 animation: dialogIn 170ms cubic-bezier(0.16, 1, 0.3, 1);
897 }
898 .palette-box {
899 width: 100%;
900 max-width: 34rem;
901 background-color: hsl(var(--popover));
902 color: hsl(var(--popover-foreground));
903 border: 1px solid hsl(var(--border));
904 border-radius: var(--radius);
905 box-shadow: 0 16px 48px -8px rgba(0, 0, 0, 0.4);
906 overflow: hidden;
907 animation: dialogIn 170ms cubic-bezier(0.16, 1, 0.3, 1);
908 }
909 .palette-input-wrap {
910 display: flex;
911 align-items: center;
912 gap: 0.6rem;
913 padding: 0.6rem 0.8rem;
914 border-bottom: 1px solid hsl(var(--border));
915 }
916 .palette-input {
917 width: 100%;
918 border: 0;
919 background: transparent;
920 color: hsl(var(--foreground));
921 font-size: 0.9rem;
922 outline: none;
923 }
924 .palette-list {
925 max-height: 20rem;
926 overflow-y: auto;
927 padding: 0.3rem;
928 }
929 .palette-group-title {
930 padding: 0.3rem 0.5rem 0.15rem;
931 font-size: 0.68rem;
932 font-weight: 600;
933 text-transform: uppercase;
934 letter-spacing: 0.04em;
935 color: hsl(var(--muted-foreground));
936 }
937 .palette-item {
938 display: flex;
939 width: 100%;
940 align-items: center;
941 justify-content: space-between;
942 gap: 0.5rem;
943 padding: 0.4rem 0.55rem;
944 border-radius: calc(var(--radius) - 2px);
945 font-size: 0.85rem;
946 color: hsl(var(--foreground));
947 cursor: pointer;
948 border: 0;
949 background: transparent;
950 text-align: left;
951 transition: background-color 100ms ease, color 100ms ease;
952 }
953 .palette-item:hover, .palette-item.selected {
954 background-color: hsl(var(--accent));
955 color: hsl(var(--accent-foreground));
956 }
957
958 /* Toast */
959 @keyframes toastIn {
960 from {
961 opacity: 0;
962 transform: translateY(8px) scale(0.97);
963 }
964 to {
965 opacity: 1;
966 transform: translateY(0) scale(1);
967 }
968 }
969 .toast-container {
970 position: fixed;
971 bottom: 1rem;
972 right: 1rem;
973 z-index: 90;
974 display: flex;
975 flex-direction: column;
976 gap: 0.4rem;
977 max-width: 20rem;
978 }
979 .toast {
980 display: flex;
981 align-items: center;
982 justify-content: space-between;
983 gap: 0.65rem;
984 padding: 0.5rem 0.75rem;
985 border-radius: var(--radius);
986 border: 1px solid hsl(var(--border));
987 background-color: hsl(var(--popover));
988 color: hsl(var(--popover-foreground));
989 box-shadow: 0 8px 24px -4px rgba(0, 0, 0, 0.25);
990 font-size: 0.8rem;
991 animation: toastIn 180ms cubic-bezier(0.16, 1, 0.3, 1);
992 }
993
994 /* Skeleton */
995 @keyframes pulse {
996 0%, 100% { opacity: 1; }
997 50% { opacity: 0.45; }
998 }
999 .skeleton {
1000 background-color: hsl(var(--muted));
1001 border-radius: calc(var(--radius) - 2px);
1002 animation: pulse 1.6s ease-in-out infinite;
1003 }
1004
1005 /* Empty State */
1006 .empty-state {
1007 text-align: center;
1008 padding: 2rem 1rem;
1009 border: 1px dashed hsl(var(--border));
1010 border-radius: var(--radius);
1011 color: hsl(var(--muted-foreground));
1012 }
1013
1014 /* Code Viewer & Chroma */
1015 .code-table {
1016 width: 100%;
1017 border-collapse: collapse;
1018 font-family: 'JetBrains Mono', monospace;
1019 font-size: 0.8rem;
1020 line-height: 1.5;
1021 }
1022 .code-ln {
1023 width: 1%;
1024 min-width: 2.75rem;
1025 padding: 0 0.65rem;
1026 text-align: right;
1027 color: hsl(var(--muted-foreground) / 0.6);
1028 user-select: none;
1029 vertical-align: top;
1030 border-right: 1px solid hsl(var(--border));
1031 }
1032 .code-line {
1033 padding: 0 0.75rem;
1034 white-space: pre;
1035 overflow-x: auto;
1036 }
1037 .chroma .k, .chroma .kc, .chroma .kd, .chroma .kn, .chroma .kp, .chroma .kr { color: hsl(var(--syntax-kw)); font-weight: 500; }
1038 .chroma .kt { color: hsl(var(--syntax-type)); }
1039 .chroma .s, .chroma .sa, .chroma .sb, .chroma .sc, .chroma .dl, .chroma .sd, .chroma .s2, .chroma .se, .chroma .sh, .chroma .si, .chroma .sx, .chroma .sr, .chroma .s1, .chroma .ss { color: hsl(var(--syntax-str)); }
1040 .chroma .c, .chroma .ch, .chroma .cm, .chroma .c1, .chroma .cs, .chroma .cp, .chroma .cpf { color: hsl(var(--syntax-cmt)); font-style: italic; }
1041 .chroma .nf, .chroma .fm, .chroma .nx { color: hsl(var(--syntax-fn)); }
1042 .chroma .m, .chroma .mb, .chroma .mf, .chroma .mh, .chroma .mi, .chroma .il, .chroma .mo { color: hsl(var(--syntax-num)); }
1043 .chroma .o, .chroma .ow { color: hsl(var(--syntax-op)); }
1044
1045 /* Diff Viewer */
1046 .diff-table {
1047 width: 100%;
1048 border-collapse: collapse;
1049 font-family: 'JetBrains Mono', monospace;
1050 font-size: 0.78rem;
1051 line-height: 1.5;
1052 }
1053 .diff-row-add {
1054 background-color: hsl(var(--diff-add-bg));
1055 color: hsl(var(--diff-add-fg));
1056 }
1057 .diff-row-del {
1058 background-color: hsl(var(--diff-del-bg));
1059 color: hsl(var(--diff-del-fg));
1060 }
1061 .diff-row-hunk {
1062 background-color: hsl(var(--muted));
1063 color: hsl(var(--muted-foreground));
1064 }
1065 .diff-num {
1066 width: 2.75rem;
1067 padding: 0 0.45rem;
1068 text-align: right;
1069 user-select: none;
1070 opacity: 0.65;
1071 border-right: 1px solid hsl(var(--border));
1072 }
1073 .diff-code {
1074 padding: 0 0.65rem;
1075 white-space: pre-wrap;
1076 word-break: break-all;
1077 }
1078
1079 /* Markdown Body */
1080 .markdown-body {
1081 font-size: 0.9rem;
1082 line-height: 1.6;
1083 color: hsl(var(--foreground));
1084 }
1085 .markdown-body h1, .markdown-body h2, .markdown-body h3, .markdown-body h4 {
1086 margin-top: 1.25em;
1087 margin-bottom: 0.45em;
1088 font-weight: 600;
1089 line-height: 1.25;
1090 }
1091 .markdown-body h1 { font-size: 1.35rem; padding-bottom: 0.25rem; border-bottom: 1px solid hsl(var(--border)); }
1092 .markdown-body h2 { font-size: 1.15rem; padding-bottom: 0.2rem; border-bottom: 1px solid hsl(var(--border)); }
1093 .markdown-body h3 { font-size: 1rem; }
1094 .markdown-body h1:first-child, .markdown-body h2:first-child { margin-top: 0; }
1095 .markdown-body p, .markdown-body ul, .markdown-body ol, .markdown-body pre, .markdown-body blockquote {
1096 margin-top: 0;
1097 margin-bottom: 0.8rem;
1098 }
1099 .markdown-body code {
1100 background-color: hsl(var(--muted));
1101 padding: 0.12rem 0.3rem;
1102 border-radius: 0.25rem;
1103 font-size: 0.84em;
1104 }
1105 .markdown-body pre {
1106 background-color: hsl(var(--muted) / 0.6);
1107 border: 1px solid hsl(var(--border));
1108 border-radius: var(--radius);
1109 padding: 0.75rem 0.9rem;
1110 overflow-x: auto;
1111 }
1112 .markdown-body pre code {
1113 background: transparent;
1114 padding: 0;
1115 }
1116 .markdown-body a {
1117 text-decoration: underline;
1118 text-underline-offset: 3px;
1119 }
1120
1121 /* Utility Helpers */
1122 .flex { display: flex; }
1123 .block { display: block; }
1124 .inline-flex { display: inline-flex; }
1125 .grid { display: grid; }
1126 .hidden { display: none; }
1127 .items-center { align-items: center; }
1128 .items-start { align-items: flex-start; }
1129 .items-baseline { align-items: baseline; }
1130 .justify-between { justify-content: space-between; }
1131 .justify-center { justify-content: center; }
1132 .justify-end { justify-content: flex-end; }
1133 .flex-col { flex-direction: column; }
1134 .flex-wrap { flex-wrap: wrap; }
1135 .flex-1 { flex: 1 1 0%; }
1136 .flex-shrink-0 { flex-shrink: 0; }
1137 .min-w-0 { min-width: 0; }
1138 .gap-0\.5 { gap: 0.125rem; }
1139 .gap-1 { gap: 0.25rem; }
1140 .gap-1\.5 { gap: 0.375rem; }
1141 .gap-2 { gap: 0.5rem; }
1142 .gap-2\.5 { gap: 0.625rem; }
1143 .gap-3 { gap: 0.75rem; }
1144 .gap-4 { gap: 1rem; }
1145 .gap-6 { gap: 1.5rem; }
1146 .w-full { width: 100%; }
1147 .text-xs { font-size: 0.75rem; }
1148 .text-sm { font-size: 0.85rem; }
1149 .text-base { font-size: 0.96rem; }
1150 .text-lg { font-size: 1.1rem; }
1151 .text-xl { font-size: 1.25rem; }
1152 .text-2xl { font-size: 1.5rem; }
1153 .font-medium { font-weight: 500; }
1154 .font-semibold { font-weight: 600; }
1155 .font-bold { font-weight: 700; }
1156 .uppercase { text-transform: uppercase; }
1157 .tracking-tight { letter-spacing: -0.015em; }
1158 .text-muted { color: hsl(var(--muted-foreground)); }
1159 .text-destructive { color: hsl(var(--destructive)); }
1160 .text-foreground { color: hsl(var(--foreground)); }
1161 .text-center { text-align: center; }
1162 .truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1163 .hover\:underline:hover { text-decoration: underline; }
1164 .select-all { user-select: all; }
1165 .cursor-pointer { cursor: pointer; }
1166 .mt-0\.5 { margin-top: 0.125rem; }
1167 .mt-1 { margin-top: 0.25rem; }
1168 .mt-2 { margin-top: 0.5rem; }
1169 .mt-3 { margin-top: 0.75rem; }
1170 .mt-4 { margin-top: 1rem; }
1171 .mt-6 { margin-top: 1.5rem; }
1172 .mr-2 { margin-right: 0.5rem; }
1173 .mb-1 { margin-bottom: 0.25rem; }
1174 .mb-1\.5 { margin-bottom: 0.375rem; }
1175 .mb-2 { margin-bottom: 0.5rem; }
1176 .mb-3 { margin-bottom: 0.75rem; }
1177 .mb-4 { margin-bottom: 1rem; }
1178 .mb-6 { margin-bottom: 1.5rem; }
1179 .p-2 { padding: 0.5rem; }
1180 .p-3 { padding: 0.75rem; }
1181 .p-4 { padding: 1rem; }
1182 .px-3 { padding-left: 0.75rem; padding-right: 0.75rem; }
1183 .py-2 { padding-top: 0.5rem; padding-bottom: 0.5rem; }
1184 .pt-2 { padding-top: 0.5rem; }
1185 .pt-3 { padding-top: 0.75rem; }
1186 .pb-3 { padding-bottom: 0.75rem; }
1187
1188 .grid-2 { display: grid; grid-template-columns: repeat(1, minmax(0, 1fr)); gap: 0.85rem; }
1189 .grid-3 { display: grid; grid-template-columns: repeat(1, minmax(0, 1fr)); gap: 0.85rem; }
1190 .grid-4 { display: grid; grid-template-columns: repeat(1, minmax(0, 1fr)); gap: 0.85rem; }
1191
1192 @media (min-width: 768px) {
1193 .grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
1194 .grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
1195 .grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
1196 .md-flex { display: flex !important; }
1197 .md-hidden { display: none !important; }
1198 }
1199
1200 /* Mobile Drawer */
1201 .mobile-drawer {
1202 position: fixed;
1203 inset: 0;
1204 z-index: 75;
1205 background-color: rgba(0, 0, 0, 0.5);
1206 display: none;
1207 }
1208 .mobile-drawer.open {
1209 display: block;
1210 }
1211 .mobile-drawer-panel {
1212 width: 224px;
1213 max-width: 85vw;
1214 height: 100%;
1215 background-color: hsl(var(--card));
1216 border-right: 1px solid hsl(var(--border));
1217 padding: 0.75rem 0.65rem;
1218 display: flex;
1219 flex-direction: column;
1220 justify-content: space-between;
1221 }
1222
1223 @media (min-width: 1024px) {
1224 .grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
1225 }
1226
1227 /* ── Polar repository shell ─────────────────────────────────────────── */
1228 .repo-banner {
1229 position: relative;
1230 display: flex;
1231 align-items: flex-start;
1232 justify-content: space-between;
1233 gap: 1rem;
1234 flex-wrap: wrap;
1235 padding: 0.9rem 1rem 0.95rem;
1236 background: hsl(var(--card));
1237 border: 1px solid hsl(var(--border));
1238 border-radius: calc(var(--radius) * 1.6);
1239 overflow: hidden;
1240 }
1241 .repo-banner::before {
1242 content: "";
1243 position: absolute;
1244 inset: 0 0 auto 0;
1245 height: 2px;
1246 background: linear-gradient(90deg, hsl(var(--primary)), hsl(var(--primary) / 0) 65%);
1247 }
1248 .repo-banner-main {
1249 display: flex;
1250 align-items: center;
1251 gap: 0.7rem;
1252 min-width: 0;
1253 flex: 1 1 20rem;
1254 }
1255 .repo-banner-actions {
1256 display: flex;
1257 align-items: center;
1258 gap: 0.4rem;
1259 flex-wrap: wrap;
1260 }
1261
1262 .repo-stats {
1263 display: flex;
1264 align-items: center;
1265 gap: 0.4rem;
1266 flex-wrap: wrap;
1267 }
1268 .stat-chip {
1269 display: inline-flex;
1270 align-items: center;
1271 gap: 0.4rem;
1272 height: 1.85rem;
1273 padding: 0 0.7rem;
1274 border: 1px solid hsl(var(--border));
1275 border-radius: 999px;
1276 background: hsl(var(--card));
1277 font-size: 0.78rem;
1278 color: hsl(var(--muted-foreground));
1279 white-space: nowrap;
1280 transition: border-color 120ms ease, color 120ms ease;
1281 }
1282 .stat-chip b {
1283 color: hsl(var(--foreground));
1284 font-weight: 600;
1285 }
1286 .stat-chip:hover {
1287 color: hsl(var(--foreground));
1288 border-color: hsl(var(--primary) / 0.55);
1289 }
1290
1291 .repo-layout {
1292 display: grid;
1293 grid-template-columns: minmax(0, 1fr) 305px;
1294 gap: 1.1rem;
1295 align-items: start;
1296 }
1297 .repo-main {
1298 min-width: 0;
1299 }
1300 .repo-side {
1301 display: flex;
1302 flex-direction: column;
1303 gap: 0.9rem;
1304 position: sticky;
1305 top: 0.75rem;
1306 }
1307 .side-card {
1308 border: 1px solid hsl(var(--border));
1309 border-radius: calc(var(--radius) * 1.3);
1310 background: hsl(var(--card));
1311 overflow: hidden;
1312 }
1313 .side-card-header {
1314 display: flex;
1315 align-items: center;
1316 gap: 0.4rem;
1317 padding: 0.5rem 0.8rem;
1318 font-size: 0.78rem;
1319 font-weight: 600;
1320 border-bottom: 1px solid hsl(var(--border));
1321 background: hsl(var(--muted) / 0.3);
1322 }
1323 .side-card-body {
1324 display: flex;
1325 flex-direction: column;
1326 gap: 0.55rem;
1327 padding: 0.7rem 0.8rem;
1328 font-size: 0.8rem;
1329 }
1330 .meta-row {
1331 display: flex;
1332 align-items: center;
1333 justify-content: space-between;
1334 gap: 0.5rem;
1335 color: hsl(var(--muted-foreground));
1336 }
1337 .meta-row a,
1338 .meta-row b {
1339 color: hsl(var(--foreground));
1340 }
1341 .clone-box {
1342 display: flex;
1343 align-items: center;
1344 gap: 0.35rem;
1345 border: 1px solid hsl(var(--border));
1346 border-radius: var(--radius);
1347 background: hsl(var(--muted) / 0.25);
1348 padding: 0.15rem 0.25rem 0.15rem 0.6rem;
1349 min-width: 0;
1350 }
1351 .clone-box code {
1352 flex: 1;
1353 min-width: 0;
1354 overflow: hidden;
1355 text-overflow: ellipsis;
1356 white-space: nowrap;
1357 font-size: 0.72rem;
1358 }
1359 @media (max-width: 1000px) {
1360 .repo-layout {
1361 grid-template-columns: 1fr;
1362 }
1363 .repo-side {
1364 position: static;
1365 order: -1;
1366 }
1367 }