gabriel / musehub public
_blob.scss
1,717 lines 61.6 KB
Raw
sha256:9590cee1e0ccd6c76528f005b95d634d80f5019f0dcb7c371e149adc31d1fb65 refactor: enforce gRPC framing on all MWP wire traffic Sonnet 4.6 minor ⚠ breaking 155 days ago
1 // _blob.scss — Blob / blame / search pages (.blob-*, .blob2-*, .blame-*, .sr-* prefixes)
2
3 /* =========================================================================
4 Blame page (v2 — piano-roll blame visualization)
5 ========================================================================= */
6
7 // ── Header ────────────────────────────────────────────────────────────────
8 .blame2-header {
9 display: flex;
10 align-items: flex-start;
11 justify-content: space-between;
12 gap: 12px;
13 flex-wrap: wrap;
14 padding-bottom: 12px;
15 border-bottom: 1px solid var(--border-default);
16 margin-bottom: 12px;
17 }
18 .blame2-title-group { display: flex; align-items: center; gap: 12px; }
19 .blame2-icon-wrap {
20 width: 36px; height: 36px;
21 display: flex; align-items: center; justify-content: center;
22 background: rgba(88,166,255,0.12);
23 border-radius: var(--radius);
24 color: #58a6ff;
25 flex-shrink: 0;
26 }
27 .blame2-title { margin: 0; font-size: 17px; color: var(--text-secondary); font-weight: 600; }
28 .blame2-path-code { font-size: 15px; background: var(--bg-overlay); padding: 2px 8px; border-radius: 4px; color: var(--text-primary); }
29 .blame2-ref-code { font-size: 12px; background: var(--bg-overlay); padding: 1px 6px; border-radius: 4px; color: var(--text-muted); font-family: var(--font-mono); }
30 .blame2-subtitle { margin: 4px 0 0; font-size: 13px; color: var(--text-muted); }
31 .blame2-file-link { color: var(--color-accent); text-decoration: none; font-size: 13px; }
32 .blame2-file-link:hover { text-decoration: underline; }
33 .blame2-actions { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
34
35 // ── Stats strip ───────────────────────────────────────────────────────────
36 .blame2-stats {
37 display: flex;
38 gap: 0;
39 background: var(--bg-surface);
40 border: 1px solid var(--border-default);
41 border-radius: var(--radius);
42 overflow: hidden;
43 margin-bottom: 10px;
44 }
45 .blame2-stat {
46 display: flex;
47 flex-direction: column;
48 align-items: center;
49 padding: 10px 20px;
50 flex: 1;
51 border-right: 1px solid var(--border-default);
52 &:last-child { border-right: none; }
53 }
54 .blame2-stat-val { font-size: 18px; font-weight: 700; color: var(--text-secondary); font-variant-numeric: tabular-nums; }
55 .blame2-stat-lbl { font-size: 11px; color: var(--text-muted); margin-top: 2px; text-transform: uppercase; letter-spacing: 0.04em; }
56
57 // ── Filter bar ────────────────────────────────────────────────────────────
58 .blame2-filter {
59 display: flex;
60 align-items: center;
61 gap: 12px;
62 flex-wrap: wrap;
63 padding: 8px 12px;
64 background: var(--bg-surface);
65 border: 1px solid var(--border-default);
66 border-radius: var(--radius);
67 margin-bottom: 14px;
68 font-size: 13px;
69 }
70 .blame2-filter-label { display: flex; align-items: center; gap: 6px; color: var(--text-muted); }
71 .blame2-filter-select,
72 .blame2-filter-input {
73 font-size: 12px;
74 background: var(--bg-base);
75 border: 1px solid var(--border-default);
76 color: var(--text-primary);
77 border-radius: 4px;
78 padding: 4px 8px;
79 }
80 .blame2-filter-clear { font-size: 12px; color: var(--text-muted); text-decoration: none; margin-left: 4px; &:hover { color: var(--text-secondary); } }
81
82 // ── Empty state ───────────────────────────────────────────────────────────
83 .blame2-empty {
84 padding: 60px 24px;
85 text-align: center;
86 color: var(--text-muted);
87 font-size: 14px;
88 display: flex;
89 flex-direction: column;
90 align-items: center;
91 gap: 4px;
92 }
93 .blame2-empty-hint { font-size: 12px; color: var(--text-muted); opacity: 0.7; }
94
95 // ── Two-column layout ──────────────────────────────────────────────────────
96 .blame2-layout {
97 display: grid;
98 grid-template-columns: 240px 1fr;
99 gap: var(--space-3);
100 align-items: start;
101 }
102 @media (max-width: 768px) {
103 .blame2-layout { grid-template-columns: 1fr; }
104 }
105
106 // ── Commit legend (left panel) ────────────────────────────────────────────
107 .blame2-legend {
108 background: var(--bg-surface);
109 border: 1px solid var(--border-default);
110 border-radius: var(--radius);
111 overflow: hidden;
112 }
113 .blame2-legend-title {
114 margin: 0;
115 padding: 8px 12px;
116 font-size: 11px;
117 font-weight: 600;
118 text-transform: uppercase;
119 letter-spacing: 0.05em;
120 color: var(--text-muted);
121 border-bottom: 1px solid var(--border-default);
122 background: var(--bg-overlay);
123 }
124 .blame2-commit {
125 display: flex;
126 align-items: flex-start;
127 gap: 10px;
128 padding: 10px 12px;
129 border-bottom: 1px solid var(--border-subtle);
130 text-decoration: none;
131 transition: background 0.1s;
132 &:last-child { border-bottom: none; }
133 &:hover { background: var(--bg-overlay); }
134 }
135 .blame2-commit-dot {
136 width: 10px;
137 height: 10px;
138 border-radius: 50%;
139 flex-shrink: 0;
140 margin-top: 3px;
141 }
142 .blame2-commit-body { min-width: 0; flex: 1; }
143 .blame2-commit-top { display: flex; justify-content: space-between; align-items: baseline; gap: 6px; margin-bottom: 2px; }
144 .blame2-commit-sha { font-family: var(--font-mono); font-size: 11px; color: var(--color-accent); }
145 .blame2-commit-count { font-size: 10px; color: var(--text-muted); white-space: nowrap; }
146 .blame2-commit-msg { font-size: 12px; color: var(--text-primary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin-bottom: 2px; }
147 .blame2-commit-meta { font-size: 11px; color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
148
149 // ── Blame canvas (right panel) ────────────────────────────────────────────
150 .blame2-canvas {
151 background: var(--bg-surface);
152 border: 1px solid var(--border-default);
153 border-radius: var(--radius);
154 overflow: hidden;
155 }
156
157 // Beat ruler
158 .blame2-ruler {
159 position: relative;
160 height: 20px;
161 background: var(--bg-overlay);
162 border-bottom: 1px solid var(--border-default);
163 font-family: var(--font-mono);
164 font-size: 10px;
165 color: var(--text-muted);
166 overflow: hidden;
167 }
168 .blame2-ruler-tick {
169 position: absolute;
170 top: 4px;
171 transform: translateX(-50%);
172 white-space: nowrap;
173 pointer-events: none;
174 line-height: 1;
175 }
176 .blame2-ruler-minor {
177 position: absolute;
178 top: 14px;
179 width: 1px;
180 height: 5px;
181 background: var(--border-subtle);
182 transform: translateX(-50%);
183 pointer-events: none;
184 }
185
186 // Track lanes
187 .blame2-track {
188 display: flex;
189 align-items: stretch;
190 border-bottom: 1px solid var(--border-subtle);
191 &:last-child { border-bottom: none; }
192 &:hover { background: rgba(255,255,255,0.02); }
193 }
194 .blame2-track-label {
195 width: 72px;
196 flex-shrink: 0;
197 display: flex;
198 align-items: center;
199 padding: 0 10px;
200 font-size: 11px;
201 font-weight: 600;
202 text-transform: uppercase;
203 letter-spacing: 0.04em;
204 color: var(--text-muted);
205 border-right: 1px solid var(--border-default);
206 background: var(--bg-overlay);
207 }
208 .blame2-track-lane {
209 position: relative;
210 flex: 1;
211 height: 88px;
212 overflow: hidden;
213 }
214 .blame2-grid-line {
215 position: absolute;
216 top: 0; bottom: 0;
217 width: 1px;
218 background: var(--border-subtle);
219 pointer-events: none;
220 }
221 .blame2-note {
222 position: absolute;
223 height: 8px;
224 min-width: 3px;
225 border-radius: 2px;
226 opacity: 0.85;
227 cursor: pointer;
228 transition: opacity 0.1s, transform 0.1s;
229 &:hover { opacity: 1; transform: scaleY(1.3); z-index: 2; }
230 }
231
232 // ── Hover tooltip ─────────────────────────────────────────────────────────
233 .blame2-tooltip {
234 position: absolute;
235 z-index: 1000;
236 background: var(--bg-overlay);
237 border: 1px solid var(--border-default);
238 border-radius: var(--radius);
239 padding: 10px 12px;
240 font-size: 12px;
241 min-width: 220px;
242 max-width: 320px;
243 pointer-events: none;
244 box-shadow: 0 8px 24px rgba(0,0,0,0.5);
245 }
246 .blame2-tip-sha { font-family: var(--font-mono); font-size: 11px; color: var(--color-accent); margin-bottom: 4px; }
247 .blame2-tip-msg { color: var(--text-primary); margin-bottom: 8px; font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
248 .blame2-tip-row {
249 display: flex;
250 justify-content: space-between;
251 gap: 12px;
252 font-size: 11px;
253 color: var(--text-muted);
254 padding: 1px 0;
255 span:last-child { color: var(--text-secondary); font-family: var(--font-mono); }
256 }
257
258 // ── Type badge ────────────────────────────────────────────────────────────
259 .blame2-type-badge {
260 display: inline-block;
261 font-size: 10px;
262 font-weight: 600;
263 padding: 2px 7px;
264 border-radius: 12px;
265 vertical-align: middle;
266 margin-left: 8px;
267 text-transform: uppercase;
268 letter-spacing: 0.05em;
269 }
270 .blame2-type-symbol { background: rgba(88,166,255,0.15); color: #58a6ff; }
271 .blame2-type-midi { background: rgba(63,185,80,0.15); color: #3fb950; }
272 .blame2-type-file { background: rgba(240,136,62,0.15); color: #f0883e; }
273
274 // ── Symbol blame table ─────────────────────────────────────────────────────
275 .blame2-symbol-table-wrap {
276 background: var(--bg-surface);
277 border: 1px solid var(--border-default);
278 border-radius: var(--radius);
279 overflow: hidden;
280 }
281 .blame2-symbol-table {
282 width: 100%;
283 border-collapse: collapse;
284 font-size: 13px;
285 th {
286 text-align: left;
287 padding: 8px 12px;
288 border-bottom: 1px solid var(--border-default);
289 color: var(--text-muted);
290 font-weight: 500;
291 font-size: 11px;
292 text-transform: uppercase;
293 letter-spacing: 0.04em;
294 background: var(--bg-overlay);
295 white-space: nowrap;
296 }
297 }
298 .blame2-symbol-row {
299 border-bottom: 1px solid var(--border-subtle);
300 &:last-child { border-bottom: none; }
301 &:hover td { background: rgba(255,255,255,0.02); }
302 td { padding: 7px 12px; vertical-align: middle; }
303 }
304 .blame2-symbol-name { font-family: var(--font-mono); font-size: 12px; }
305 .blame2-symbol-link { color: var(--text-secondary); text-decoration: none; &:hover { color: var(--color-accent); text-decoration: underline; } }
306 .blame2-commit-msg-inline { font-size: 12px; color: var(--text-muted); margin-left: 8px; }
307 .blame2-author { font-size: 12px; color: var(--text-muted); white-space: nowrap; }
308 .blame2-date { font-size: 12px; color: var(--text-muted); white-space: nowrap; }
309 .blame2-op {
310 display: inline-block;
311 padding: 1px 7px;
312 border-radius: 10px;
313 font-size: 10px;
314 font-weight: 600;
315 text-transform: uppercase;
316 letter-spacing: 0.04em;
317 }
318 .blame2-op-add { background: rgba(63,185,80,0.15); color: #3fb950; }
319 .blame2-op-modify { background: rgba(88,166,255,0.15); color: #58a6ff; }
320 .blame2-op-delete { background: rgba(248,81,73,0.15); color: #f85149; }
321 .blame2-changes { display: flex; align-items: center; gap: 8px; white-space: nowrap; }
322 .blame2-heat-bar {
323 width: 48px; height: 4px;
324 background: var(--bg-overlay);
325 border-radius: 2px;
326 overflow: hidden;
327 }
328 .blame2-heat-fill {
329 height: 100%;
330 border-radius: 2px;
331 background: linear-gradient(to right, #58a6ff, #ff7b72);
332 min-width: 2px;
333 }
334 .blame2-change-count { font-size: 11px; color: var(--text-muted); font-variant-numeric: tabular-nums; }
335 .blame2-file-fallback {
336 background: var(--bg-surface);
337 border: 1px solid var(--border-default);
338 border-radius: var(--radius);
339 padding: 32px 20px;
340 }
341 .blame2-file-fallback-msg { font-size: 13px; color: var(--text-muted); }
342
343 /* =========================================================================
344 Blame page (v3 — symbol-level redesign)
345 .blame-* prefix. .blame2-* (piano roll) kept for MIDI files.
346 ========================================================================= */
347
348 // ── Header ────────────────────────────────────────────────────────────────
349 .blame-header {
350 display: flex;
351 align-items: flex-start;
352 justify-content: space-between;
353 gap: 12px;
354 flex-wrap: wrap;
355 padding-bottom: 12px;
356 border-bottom: 1px solid var(--border-default);
357 margin-bottom: 12px;
358 }
359 .blame-title-group { display: flex; align-items: center; gap: 12px; }
360 .blame-icon-wrap {
361 width: 36px; height: 36px;
362 display: flex; align-items: center; justify-content: center;
363 background: rgba(88,166,255,0.12);
364 border-radius: var(--radius);
365 color: #58a6ff;
366 flex-shrink: 0;
367 }
368 .blame-title {
369 margin: 0;
370 font-size: 17px;
371 color: var(--text-secondary);
372 font-weight: 600;
373 display: flex;
374 align-items: center;
375 gap: 10px;
376 flex-wrap: wrap;
377 }
378 .blame-path-code {
379 font-size: 15px;
380 background: var(--bg-overlay);
381 padding: 2px 8px;
382 border-radius: 4px;
383 color: var(--text-primary);
384 }
385 .blame-ref-code {
386 font-size: 12px;
387 background: var(--bg-overlay);
388 padding: 1px 6px;
389 border-radius: 4px;
390 color: var(--text-muted);
391 font-family: var(--font-mono);
392 }
393 .blame-subtitle { margin: 4px 0 0; font-size: 13px; color: var(--text-muted); }
394 .blame-file-link { color: var(--color-accent); text-decoration: none; font-size: 13px; &:hover { text-decoration: underline; } }
395 .blame-actions { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
396
397 // ── Type badge ────────────────────────────────────────────────────────────
398 .blame-type-badge {
399 display: inline-flex;
400 align-items: center;
401 padding: 2px 8px;
402 border-radius: 20px;
403 font-size: 11px;
404 font-weight: 600;
405 letter-spacing: 0.03em;
406 text-transform: uppercase;
407 }
408 .blame-type-symbol { background: rgba(88,166,255,0.15); color: #58a6ff; }
409 .blame-type-midi { background: rgba(63,185,80,0.15); color: #3fb950; }
410 .blame-type-file { background: rgba(240,136,62,0.15); color: #f0883e; }
411
412 // ── Stats strip ───────────────────────────────────────────────────────────
413 .blame-stats {
414 display: flex;
415 gap: 0;
416 background: var(--bg-surface);
417 border: 1px solid var(--border-default);
418 border-radius: var(--radius);
419 overflow: hidden;
420 margin-bottom: 14px;
421 }
422 .blame-stat {
423 display: flex;
424 flex-direction: column;
425 align-items: center;
426 padding: 10px 18px;
427 flex: 1;
428 border-right: 1px solid var(--border-default);
429 &:last-child { border-right: none; }
430 }
431 .blame-stat-val { font-size: 18px; font-weight: 700; color: var(--text-secondary); font-variant-numeric: tabular-nums; }
432 .blame-stat-lbl { font-size: 11px; color: var(--text-muted); margin-top: 2px; text-transform: uppercase; letter-spacing: 0.04em; }
433 // Signal stats glow when non-zero
434 .blame-stat-hotspot.blame-stat-active .blame-stat-val { color: #ffa657; }
435 .blame-stat-dead.blame-stat-active .blame-stat-val { color: #79c0ff; }
436 .blame-stat-blast.blame-stat-active .blame-stat-val { color: #ff7b72; }
437
438 // ── Empty state ───────────────────────────────────────────────────────────
439 .blame-empty {
440 text-align: center;
441 padding: 64px 20px;
442 color: var(--text-muted);
443 code { background: var(--bg-overlay); padding: 1px 5px; border-radius: 3px; }
444 }
445 .blame-empty-hint { font-size: 12px; color: var(--text-muted); opacity: 0.7; margin-top: 6px; }
446
447 // ── Two-column layout ─────────────────────────────────────────────────────
448 .blame-layout {
449 display: grid;
450 grid-template-columns: 220px 1fr;
451 gap: 14px;
452 align-items: start;
453 @media (max-width: 768px) { grid-template-columns: 1fr; }
454 }
455 .blame-content { min-width: 0; }
456
457 // ── Commit legend (left panel) ────────────────────────────────────────────
458 .blame-legend {
459 background: var(--bg-surface);
460 border: 1px solid var(--border-default);
461 border-radius: var(--radius);
462 overflow: hidden;
463 position: sticky;
464 top: 12px;
465 }
466 .blame-legend-header {
467 display: flex;
468 align-items: center;
469 justify-content: space-between;
470 padding: 8px 10px;
471 border-bottom: 1px solid var(--border-default);
472 background: var(--bg-overlay);
473 }
474 .blame-legend-title {
475 font-size: 11px;
476 font-weight: 600;
477 text-transform: uppercase;
478 letter-spacing: 0.06em;
479 color: var(--text-muted);
480 }
481 .blame-legend-authorship-key {
482 font-size: 10px;
483 color: var(--text-muted);
484 white-space: nowrap;
485 }
486 .blame-legend-entry {
487 display: flex;
488 align-items: flex-start;
489 gap: 8px;
490 padding: 8px 10px;
491 border-bottom: 1px solid var(--border-subtle, rgba(255,255,255,0.05));
492 text-decoration: none;
493 transition: background 0.1s;
494 &:last-child { border-bottom: none; }
495 &:hover { background: var(--bg-overlay); }
496 }
497 .blame-legend-dot {
498 width: 10px;
499 height: 10px;
500 border-radius: 50%;
501 flex-shrink: 0;
502 margin-top: 3px;
503 }
504 .blame-legend-body { min-width: 0; flex: 1; }
505 .blame-legend-top {
506 display: flex;
507 align-items: center;
508 gap: 5px;
509 margin-bottom: 2px;
510 }
511 .blame-legend-sha {
512 font-family: var(--font-mono);
513 font-size: 11px;
514 color: var(--color-accent);
515 }
516 .blame-legend-count {
517 font-size: 10px;
518 color: var(--text-muted);
519 white-space: nowrap;
520 margin-left: auto;
521 }
522 .blame-legend-msg {
523 font-size: 12px;
524 color: var(--text-primary);
525 white-space: nowrap;
526 overflow: hidden;
527 text-overflow: ellipsis;
528 margin-bottom: 2px;
529 }
530 .blame-legend-meta {
531 font-size: 11px;
532 color: var(--text-muted);
533 white-space: nowrap;
534 overflow: hidden;
535 text-overflow: ellipsis;
536 }
537 .blame-legend-model {
538 display: inline-block;
539 background: rgba(88,166,255,0.12);
540 color: #58a6ff;
541 font-size: 10px;
542 padding: 0 4px;
543 border-radius: 3px;
544 margin-left: 4px;
545 font-family: var(--font-mono);
546 }
547
548 // ── Authorship icons ──────────────────────────────────────────────────────
549 .blame-author-icon {
550 display: inline-flex;
551 align-items: center;
552 justify-content: center;
553 width: 16px;
554 height: 16px;
555 border-radius: 50%;
556 flex-shrink: 0;
557 }
558 .blame-author-agent {
559 background: rgba(88,166,255,0.15);
560 color: #58a6ff;
561 }
562 .blame-author-human {
563 background: rgba(63,185,80,0.12);
564 color: #3fb950;
565 }
566 .blame-legend-author-icon {
567 @extend .blame-author-icon;
568 width: 14px;
569 height: 14px;
570 }
571
572 // ── Symbol blame table ────────────────────────────────────────────────────
573 .blame-table {
574 background: var(--bg-surface);
575 border: 1px solid var(--border-default);
576 border-radius: var(--radius);
577 overflow: hidden;
578 }
579 .blame-table-head {
580 display: grid;
581 grid-template-columns: 1fr 52px 110px 130px 88px 64px;
582 padding: 6px 12px;
583 background: var(--bg-overlay);
584 border-bottom: 1px solid var(--border-default);
585 font-size: 11px;
586 font-weight: 600;
587 text-transform: uppercase;
588 letter-spacing: 0.05em;
589 color: var(--text-muted);
590 gap: 8px;
591 }
592
593 // ── Blame row (<details>) ─────────────────────────────────────────────────
594 .blame-row {
595 border-bottom: 1px solid var(--border-subtle, rgba(255,255,255,0.04));
596 &:last-child { border-bottom: none; }
597 &[open] > summary { background: var(--bg-overlay); }
598 &[open] .blame-expand-chevron { transform: rotate(0deg); }
599 }
600 .blame-row-summary {
601 display: grid;
602 grid-template-columns: 1fr 52px 110px 130px 88px 64px;
603 align-items: center;
604 padding: 7px 12px;
605 gap: 8px;
606 cursor: pointer;
607 list-style: none;
608 transition: background 0.1s;
609 &:hover { background: var(--bg-overlay); }
610 &::-webkit-details-marker { display: none; }
611 }
612
613 // Column spans — must match .blame-table-head grid
614 .blame-col-symbol {
615 display: flex;
616 align-items: center;
617 gap: 6px;
618 min-width: 0;
619 font-family: var(--font-mono);
620 font-size: 12px;
621 }
622 .blame-col-op { display: flex; align-items: center; }
623 .blame-col-heat { display: flex; align-items: center; gap: 6px; }
624 .blame-col-author { display: flex; align-items: center; gap: 5px; min-width: 0; font-size: 12px; color: var(--text-muted); }
625 .blame-col-age { font-size: 12px; color: var(--text-muted); white-space: nowrap; }
626 .blame-col-signals { display: flex; align-items: center; gap: 3px; }
627
628 .blame-expand-chevron {
629 flex-shrink: 0;
630 color: var(--text-muted);
631 transform: rotate(-90deg);
632 transition: transform 0.15s;
633 details[open] & { transform: rotate(0deg); }
634 }
635 .blame-symbol-link {
636 color: var(--text-secondary);
637 text-decoration: none;
638 white-space: nowrap;
639 overflow: hidden;
640 text-overflow: ellipsis;
641 &:hover { color: var(--color-accent); text-decoration: underline; }
642 }
643 .blame-author-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
644
645 // ── Op badges ────────────────────────────────────────────────────────────
646 .blame-op {
647 display: inline-flex;
648 align-items: center;
649 padding: 1px 6px;
650 border-radius: 3px;
651 font-size: 10px;
652 font-weight: 600;
653 font-family: var(--font-mono);
654 text-transform: lowercase;
655 white-space: nowrap;
656 }
657 .blame-op-add { background: rgba(63,185,80,0.15); color: #3fb950; }
658 .blame-op-modify,
659 .blame-op-mod { background: rgba(88,166,255,0.15); color: #58a6ff; }
660 .blame-op-delete,
661 .blame-op-del { background: rgba(248,81,73,0.15); color: #f85149; }
662
663 // ── Heat bar ──────────────────────────────────────────────────────────────
664 .blame-heat-bar {
665 width: 56px;
666 height: 6px;
667 background: var(--bg-overlay);
668 border-radius: 3px;
669 overflow: hidden;
670 flex-shrink: 0;
671 }
672 .blame-heat-fill {
673 height: 100%;
674 border-radius: 3px;
675 background: linear-gradient(90deg, #58a6ff 0%, #f0883e 60%, #ff7b72 100%);
676 min-width: 2px;
677 transition: width 0.2s;
678 }
679 .blame-heat-count {
680 font-size: 11px;
681 color: var(--text-muted);
682 font-variant-numeric: tabular-nums;
683 min-width: 14px;
684 }
685
686 // ── Signal badges ─────────────────────────────────────────────────────────
687 .blame-signal {
688 font-size: 13px;
689 cursor: default;
690 line-height: 1;
691 opacity: 0.85;
692 &:hover { opacity: 1; }
693 }
694
695 // ── Expanded history panel ────────────────────────────────────────────────
696 .blame-history-panel {
697 padding: 0 12px 12px 12px;
698 background: var(--bg-base);
699 border-top: 1px solid var(--border-default);
700 }
701 .blame-history-table {
702 width: 100%;
703 border-collapse: collapse;
704 font-size: 12px;
705 margin-top: 10px;
706 th {
707 text-align: left;
708 font-size: 10px;
709 font-weight: 600;
710 text-transform: uppercase;
711 letter-spacing: 0.05em;
712 color: var(--text-muted);
713 padding: 4px 8px;
714 border-bottom: 1px solid var(--border-default);
715 }
716 }
717 .blame-history-row {
718 &:hover td { background: var(--bg-overlay); }
719 td { padding: 4px 8px; border-bottom: 1px solid var(--border-subtle, rgba(255,255,255,0.04)); }
720 }
721 .blame-hist-num { color: var(--text-muted); font-size: 11px; width: 24px; }
722 .blame-hist-sha { font-family: var(--font-mono); font-size: 11px; white-space: nowrap; a { color: var(--color-accent); text-decoration: none; &:hover { text-decoration: underline; } } }
723 .blame-hist-msg { color: var(--text-secondary); max-width: 320px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
724 .blame-hist-author { color: var(--text-muted); white-space: nowrap; display: flex; align-items: center; gap: 4px; }
725 .blame-hist-age { color: var(--text-muted); white-space: nowrap; font-family: var(--font-mono); font-size: 11px; }
726 .blame-history-empty { font-size: 12px; color: var(--text-muted); padding: 10px 0; }
727 .blame-history-footer {
728 margin-top: 8px;
729 font-size: 12px;
730 a { color: var(--color-accent); text-decoration: none; &:hover { text-decoration: underline; } }
731 }
732
733 // ── MIDI filter bar (inside blame-content) ────────────────────────────────
734 .blame-filter {
735 display: flex;
736 align-items: center;
737 gap: 12px;
738 flex-wrap: wrap;
739 padding: 8px 12px;
740 background: var(--bg-surface);
741 border: 1px solid var(--border-default);
742 border-radius: var(--radius);
743 margin-bottom: 12px;
744 font-size: 12px;
745 }
746 .blame-filter-label { display: flex; align-items: center; gap: 6px; color: var(--text-muted); }
747 .blame-filter-select,
748 .blame-filter-input {
749 background: var(--bg-base);
750 border: 1px solid var(--border-default);
751 border-radius: 4px;
752 color: var(--text-primary);
753 font-size: 12px;
754 padding: 3px 6px;
755 &:focus { outline: none; border-color: var(--color-accent); }
756 }
757 .blame-filter-clear { font-size: 12px; color: var(--text-muted); text-decoration: none; margin-left: 4px; &:hover { color: var(--text-secondary); } }
758
759 /* =========================================================================
760 Blob (file viewer) page
761 ========================================================================= */
762 .blob-header { display: flex; align-items: center; justify-content: space-between; padding: 10px 16px; background: var(--bg-surface); border: 1px solid var(--border-default); border-radius: 8px 8px 0 0; border-bottom: none; margin-top: 8px; gap: 12px; flex-wrap: wrap; }
763 .blob-filename { font-size: 14px; font-weight: 600; color: var(--text-secondary); display: flex; align-items: center; gap: 8px; }
764 .blob-meta { font-size: 12px; color: var(--text-muted); display: flex; gap: 16px; flex-wrap: wrap; }
765 .blob-meta span { display: flex; align-items: center; gap: 4px; }
766 .blob-actions { display: flex; gap: 8px; flex-wrap: wrap; }
767 .btn-blob { display: inline-flex; align-items: center; gap: 6px; padding: 6px 14px; border-radius: 6px; font-size: 13px; text-decoration: none; font-weight: 500; border: 1px solid transparent; cursor: pointer; }
768 .btn-blob-primary { background: var(--color-success, #238636); border-color: #2ea043; color: #fff; }
769 .btn-blob-primary:hover { background: #2ea043; }
770 .btn-blob-secondary { background: var(--bg-overlay); border-color: var(--border-default); color: var(--text-secondary); }
771 .btn-blob-secondary:hover { background: var(--bg-hover, var(--bg-overlay)); }
772 .blob-body { background: var(--bg-base); border: 1px solid var(--border-default); border-radius: 0 0 8px 8px; min-height: 120px; overflow: hidden; }
773 .blob-loading { padding: 40px; text-align: center; color: var(--text-muted); font-size: 14px; }
774 .blob-error { padding: 24px; color: var(--color-danger, #f85149); font-size: 14px; }
775 .blob-midi-banner { padding: 48px 24px; text-align: center; background: var(--bg-base); }
776 .blob-midi-icon { font-size: 64px; margin-bottom: 16px; display: block; }
777 .blob-midi-title { font-size: 20px; font-weight: 600; color: var(--text-secondary); margin-bottom: 8px; }
778 .blob-midi-sub { font-size: 14px; color: var(--text-muted); margin-bottom: 24px; }
779 .blob-code-wrap { overflow: auto; max-height: 680px; border-radius: 0 0 8px 8px; }
780 .blob-code { margin: 0; padding: 16px; font-family: var(--font-mono); font-size: 12px; line-height: 1.6; color: var(--text-secondary); white-space: pre-wrap; word-break: break-word; background: var(--bg-base); tab-size: 2; }
781 .blob-code .json-key { color: #79c0ff; }
782 .blob-code .json-str { color: #a5d6ff; }
783 .blob-code .json-num { color: #f2cc60; }
784 .blob-code .json-bool { color: #ff7b72; }
785 .blob-code .json-null { color: var(--text-muted); }
786 .blob-img-wrap { padding: 24px; display: flex; justify-content: center; align-items: center; background: repeating-conic-gradient(var(--bg-surface) 0% 25%, var(--bg-base) 0% 50%) 0 0 / 20px 20px; min-height: 200px; border-radius: 0 0 8px 8px; }
787 .blob-img { max-width: 100%; max-height: 640px; border-radius: 4px; box-shadow: 0 4px 16px rgba(0,0,0,0.6); }
788 .blob-hex-wrap { overflow: auto; max-height: 400px; }
789 .blob-hex { margin: 0; padding: 16px; font-family: var(--font-mono); font-size: 12px; line-height: 1.7; color: var(--text-muted); background: var(--bg-base); white-space: pre; }
790 .blob-hex .hex-offset { color: var(--text-muted); margin-right: 12px; }
791 .blob-hex .hex-bytes { color: var(--text-secondary); margin-right: 12px; }
792 .blob-hex .hex-ascii { color: var(--text-muted); }
793 .blob-binary-notice { padding: 24px; text-align: center; color: var(--text-muted); font-size: 14px; border-top: 1px solid var(--border-subtle); }
794
795 // ── Blob line-numbered table (replaces old inline styles) ────────────────────
796 .blob-viewer { overflow-x: auto; }
797
798 .blob-line-table {
799 width: 100%; border-collapse: collapse;
800 font-family: var(--font-mono); font-size: 12.5px; line-height: 1.65;
801 // When hljs runs, we fade from plain colour to highlighted
802 &.hljs { background: var(--bg-base); }
803 }
804
805 .blob-line {
806 &:hover .blob-ln,
807 &:hover .blob-code { background: color-mix(in srgb, var(--color-accent) 5%, transparent); }
808 // Line anchor highlight when navigated to via #L{n}
809 &:target .blob-ln,
810 &:target .blob-code { background: color-mix(in srgb, var(--color-accent) 15%, transparent); }
811 }
812
813 .blob-ln {
814 width: 1%; min-width: 44px; padding: 0 12px 0 8px;
815 text-align: right; color: var(--text-muted); user-select: none;
816 vertical-align: top; white-space: nowrap;
817 a { color: inherit; text-decoration: none; &:hover { color: var(--text-secondary); } }
818 }
819
820 .blob-code {
821 padding: 0 16px 0 4px; white-space: pre; vertical-align: top;
822 color: var(--text-secondary);
823 // hljs injects <span> tokens; allow them to colour inline
824 &.hljs { color: var(--text-secondary); }
825 // Smooth colour transition as JS injects highlighted spans
826 transition: color 0.1s;
827 }
828
829 .blob-lang-badge {
830 display: inline-block; font-size: 10px; font-family: var(--font-mono);
831 padding: 2px 7px; border-radius: 4px;
832 background: var(--bg-overlay); color: var(--text-muted);
833 border: 1px solid var(--border-subtle);
834 }
835
836 /* =========================================================================
837 Collaborators settings page
838 ========================================================================= */
839 .badge-perm-read { background: var(--bg-overlay); color: var(--text-muted); }
840 .badge-perm-write { background: #1f4e96; color: #58a6ff; }
841 .badge-perm-admin { background: #7d2a00; color: #f0883e; }
842 .badge-perm-owner { background: #5a3e00; color: #e3b341; }
843 .collab-list { display: flex; flex-direction: column; gap: 0; }
844 .collab-row { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-3) var(--space-4); border-bottom: 1px solid var(--border-subtle); }
845 .collab-row:last-child { border-bottom: none; }
846 .collab-avatar { width: 32px; height: 32px; border-radius: 50%; background: var(--bg-overlay); display: flex; align-items: center; justify-content: center; font-size: 14px; flex-shrink: 0; }
847 .collab-info { flex: 1; min-width: 0; }
848 .collab-user-id { font-weight: 600; font-size: 13px; color: var(--text-primary); }
849 .collab-meta { font-size: 11px; color: var(--text-muted); margin-top: 2px; }
850 .invite-grid { display: grid; grid-template-columns: 1fr auto auto; gap: var(--space-2); align-items: center; }
851 @media (max-width: 600px) { .invite-grid { grid-template-columns: 1fr; } }
852 .settings-tabs { display: flex; gap: 0; border-bottom: 1px solid var(--border-subtle); margin-bottom: var(--space-4); }
853 .settings-tab { padding: 8px 16px; font-size: 13px; color: var(--text-muted); text-decoration: none; border-bottom: 2px solid transparent; margin-bottom: -1px; }
854 .settings-tab.active { color: var(--text-primary); border-bottom-color: var(--color-accent); font-weight: 600; }
855 .perm-badge { display: inline-block; border-radius: 4px; padding: 2px 8px; font-size: 11px; font-weight: 600; }
856
857 /* =========================================================================
858 Search pages (.sr-* prefix)
859 ========================================================================= */
860
861 /* ── Search hero (in-repo search) ──────────────────────────────────────── */
862 .sr-hero {
863 margin-bottom: var(--space-5);
864 }
865 .sr-hero-title {
866 font-size: var(--font-size-lg);
867 font-weight: var(--font-weight-semibold);
868 color: var(--text-primary);
869 margin-bottom: var(--space-4);
870 }
871 .sr-input-wrap {
872 display: flex;
873 align-items: stretch;
874 gap: 0;
875 background: var(--bg-surface);
876 border: 1px solid var(--border-default);
877 border-radius: var(--radius-lg);
878 overflow: hidden;
879 transition: border-color 0.15s, box-shadow 0.15s;
880 &:focus-within {
881 border-color: var(--color-accent);
882 box-shadow: 0 0 0 3px rgba(88, 166, 255, 0.15);
883 }
884 }
885 .sr-input-icon {
886 display: flex;
887 align-items: center;
888 padding: 0 var(--space-3);
889 color: var(--text-muted);
890 font-size: 1rem;
891 flex-shrink: 0;
892 }
893 .sr-input {
894 flex: 1;
895 background: transparent;
896 border: none;
897 outline: none;
898 padding: var(--space-3) var(--space-2);
899 font-size: var(--font-size-base);
900 color: var(--text-primary);
901 min-width: 0;
902 &::placeholder { color: var(--text-muted); }
903 }
904 .sr-submit-btn {
905 padding: var(--space-3) var(--space-5);
906 background: var(--color-accent);
907 color: var(--bg-base);
908 border: none;
909 font-size: var(--font-size-sm);
910 font-weight: var(--font-weight-semibold);
911 cursor: pointer;
912 flex-shrink: 0;
913 transition: opacity 0.15s;
914 &:hover { opacity: 0.88; }
915 }
916
917 /* ── Mode pills ─────────────────────────────────────────────────────────── */
918 .sr-mode-bar {
919 display: flex;
920 align-items: center;
921 gap: var(--space-2);
922 margin-top: var(--space-3);
923 flex-wrap: wrap;
924 }
925 .sr-mode-label {
926 font-size: var(--font-size-xs);
927 color: var(--text-muted);
928 margin-right: var(--space-1);
929 }
930 .sr-mode-pill {
931 display: inline-flex;
932 align-items: center;
933 gap: var(--space-1);
934 padding: 3px 12px;
935 border-radius: var(--radius-full);
936 border: 1px solid var(--border-default);
937 font-size: var(--font-size-xs);
938 font-weight: var(--font-weight-medium);
939 color: var(--text-muted);
940 cursor: pointer;
941 text-decoration: none;
942 transition: border-color 0.12s, color 0.12s, background 0.12s;
943 &:hover {
944 border-color: var(--color-accent);
945 color: var(--color-accent);
946 }
947 &.sr-mode-pill--active {
948 background: var(--color-accent);
949 border-color: var(--color-accent);
950 color: var(--bg-base);
951 font-weight: var(--font-weight-semibold);
952 }
953 }
954
955 /* ── Type tabs ──────────────────────────────────────────────────────────── */
956 .sr-type-tabs {
957 display: flex;
958 gap: 0;
959 border-bottom: 1px solid var(--border-default);
960 margin-bottom: var(--space-4);
961 overflow-x: auto;
962 flex-wrap: nowrap;
963 }
964 .sr-type-tab {
965 display: inline-flex;
966 align-items: center;
967 gap: var(--space-2);
968 padding: var(--space-2) var(--space-4);
969 font-size: var(--font-size-sm);
970 font-weight: var(--font-weight-medium);
971 color: var(--text-muted);
972 cursor: pointer;
973 text-decoration: none;
974 border-bottom: 2px solid transparent;
975 white-space: nowrap;
976 transition: color 0.12s, border-color 0.12s;
977 margin-bottom: -1px;
978 &:hover { color: var(--text-primary); }
979 &.sr-type-tab--active {
980 color: var(--text-primary);
981 border-bottom-color: var(--color-accent);
982 font-weight: var(--font-weight-semibold);
983 }
984 }
985 .sr-type-count {
986 font-size: 0.7rem;
987 padding: 1px 6px;
988 background: var(--bg-overlay);
989 border-radius: var(--radius-full);
990 font-weight: var(--font-weight-semibold);
991 color: var(--text-muted);
992 font-family: var(--font-mono);
993 }
994 .sr-type-tab--active .sr-type-count {
995 background: var(--color-accent);
996 color: var(--bg-base);
997 }
998
999 /* ── Results meta ───────────────────────────────────────────────────────── */
1000 .sr-results-meta {
1001 font-size: var(--font-size-xs);
1002 color: var(--text-muted);
1003 margin-bottom: var(--space-3);
1004 display: flex;
1005 align-items: center;
1006 gap: var(--space-3);
1007 flex-wrap: wrap;
1008 }
1009 .sr-results-meta strong { color: var(--text-primary); }
1010
1011 /* ── Section headers ────────────────────────────────────────────────────── */
1012 .sr-section {
1013 margin-bottom: var(--space-5);
1014 }
1015 .sr-section-header {
1016 display: flex;
1017 align-items: center;
1018 gap: var(--space-2);
1019 margin-bottom: var(--space-3);
1020 padding-bottom: var(--space-2);
1021 border-bottom: 1px solid var(--border-default);
1022 font-size: var(--font-size-sm);
1023 font-weight: var(--font-weight-semibold);
1024 color: var(--text-secondary);
1025 }
1026
1027 /* ── Result cards ───────────────────────────────────────────────────────── */
1028 .sr-card {
1029 display: grid;
1030 grid-template-columns: auto 1fr auto;
1031 gap: var(--space-3);
1032 align-items: start;
1033 padding: var(--space-3) var(--space-4);
1034 background: var(--bg-surface);
1035 border: 1px solid var(--border-default);
1036 border-radius: var(--radius-base);
1037 margin-bottom: var(--space-2);
1038 transition: border-color 0.12s, box-shadow 0.12s;
1039 text-decoration: none;
1040 color: inherit;
1041 &:hover {
1042 border-color: var(--color-accent);
1043 box-shadow: 0 0 0 1px var(--color-accent);
1044 }
1045 &:last-child { margin-bottom: 0; }
1046 }
1047 .sr-card-icon {
1048 width: 32px;
1049 height: 32px;
1050 border-radius: var(--radius-base);
1051 display: flex;
1052 align-items: center;
1053 justify-content: center;
1054 font-size: 1rem;
1055 flex-shrink: 0;
1056 &.sr-icon-commit { background: rgba(88,166,255,0.12); }
1057 &.sr-icon-issue { background: rgba(63,185,80,0.12); }
1058 &.sr-icon-proposal { background: rgba(163,113,247,0.12); }
1059 &.sr-icon-release { background: rgba(248,113,113,0.12); }
1060 &.sr-icon-session { background: rgba(251,191,36,0.12); }
1061 }
1062 .sr-card-body {
1063 min-width: 0;
1064 }
1065 .sr-card-title {
1066 font-size: var(--font-size-sm);
1067 font-weight: var(--font-weight-medium);
1068 color: var(--text-primary);
1069 margin-bottom: 2px;
1070 overflow: hidden;
1071 text-overflow: ellipsis;
1072 white-space: nowrap;
1073 a {
1074 color: inherit;
1075 text-decoration: none;
1076 &:hover { color: var(--color-accent); }
1077 }
1078 }
1079 .sr-card-meta {
1080 font-size: var(--font-size-xs);
1081 color: var(--text-muted);
1082 display: flex;
1083 align-items: center;
1084 gap: var(--space-2);
1085 flex-wrap: wrap;
1086 margin-top: 2px;
1087 }
1088 .sr-card-side {
1089 display: flex;
1090 flex-direction: column;
1091 align-items: flex-end;
1092 gap: var(--space-1);
1093 flex-shrink: 0;
1094 }
1095 .sr-badge {
1096 font-size: 0.68rem;
1097 padding: 2px 8px;
1098 border-radius: var(--radius-full);
1099 font-weight: 600;
1100 white-space: nowrap;
1101 &.sr-badge-open { background: rgba(63,185,80,0.15); color: var(--color-success); border: 1px solid var(--color-success); }
1102 &.sr-badge-closed { background: rgba(248,81,73,0.12); color: var(--color-danger); border: 1px solid var(--color-danger); }
1103 &.sr-badge-merged { background: rgba(163,113,247,0.15); color: var(--dim-harmonic); border: 1px solid var(--dim-harmonic); }
1104 &.sr-badge-stable { background: rgba(63,185,80,0.12); color: var(--color-success); border: 1px solid var(--color-success); }
1105 &.sr-badge-pre { background: rgba(240,136,62,0.15); color: var(--color-warning); border: 1px solid var(--color-warning); }
1106 &.sr-badge-draft { background: var(--bg-overlay); color: var(--text-muted); border: 1px solid var(--border-default); }
1107 &.sr-badge-active { background: rgba(63,185,80,0.12); color: var(--color-success); border: 1px solid var(--color-success); }
1108 &.sr-badge-keyword { background: rgba(88,166,255,0.1); color: var(--color-accent); border: 1px solid var(--color-accent); }
1109 }
1110 .sr-sha {
1111 font-family: var(--font-mono);
1112 font-size: 0.7rem;
1113 padding: 2px 6px;
1114 background: var(--bg-overlay);
1115 border-radius: 4px;
1116 color: var(--text-muted);
1117 }
1118 .sr-score {
1119 font-family: var(--font-mono);
1120 font-size: 0.65rem;
1121 color: var(--text-muted);
1122 }
1123 .sr-branch-pill {
1124 display: inline-flex;
1125 align-items: center;
1126 gap: 3px;
1127 padding: 1px 7px;
1128 background: var(--bg-overlay);
1129 border-radius: var(--radius-full);
1130 font-size: 0.7rem;
1131 color: var(--text-muted);
1132 font-family: var(--font-mono);
1133 }
1134
1135 /* ── Search term highlight ──────────────────────────────────────────────── */
1136 mark.sr-hl {
1137 background: rgba(255, 220, 60, 0.28);
1138 color: inherit;
1139 border-radius: 2px;
1140 padding: 0 1px;
1141 }
1142
1143 /* ── Empty / tips states ────────────────────────────────────────────────── */
1144 .sr-tips {
1145 background: var(--bg-surface);
1146 border: 1px solid var(--border-default);
1147 border-radius: var(--radius-lg);
1148 padding: var(--space-6) var(--space-5);
1149 text-align: center;
1150 }
1151 .sr-tips-icon {
1152 font-size: 2.5rem;
1153 line-height: 1;
1154 margin-bottom: var(--space-3);
1155 }
1156 .sr-tips-title {
1157 font-size: var(--font-size-base);
1158 font-weight: var(--font-weight-semibold);
1159 color: var(--text-primary);
1160 margin-bottom: var(--space-2);
1161 }
1162 .sr-tips-grid {
1163 display: grid;
1164 grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
1165 gap: var(--space-3);
1166 margin-top: var(--space-4);
1167 text-align: left;
1168 }
1169 .sr-tip-card {
1170 background: var(--bg-overlay);
1171 border-radius: var(--radius-base);
1172 padding: var(--space-3);
1173 }
1174 .sr-tip-label {
1175 font-size: var(--font-size-xs);
1176 font-weight: var(--font-weight-semibold);
1177 color: var(--text-secondary);
1178 margin-bottom: var(--space-1);
1179 }
1180 .sr-tip-example {
1181 font-family: var(--font-mono);
1182 font-size: 0.7rem;
1183 color: var(--color-accent);
1184 }
1185 .sr-tip-desc {
1186 font-size: var(--font-size-xs);
1187 color: var(--text-muted);
1188 margin-top: 2px;
1189 }
1190 .sr-no-results {
1191 text-align: center;
1192 padding: var(--space-6);
1193 color: var(--text-muted);
1194 font-size: var(--font-size-sm);
1195 }
1196
1197 /* ── Global search — repo group cards ──────────────────────────────────── */
1198 .sr-repo-group {
1199 background: var(--bg-surface);
1200 border: 1px solid var(--border-default);
1201 border-radius: var(--radius-lg);
1202 margin-bottom: var(--space-4);
1203 overflow: hidden;
1204 }
1205 .sr-repo-group-header {
1206 display: flex;
1207 align-items: center;
1208 justify-content: space-between;
1209 padding: var(--space-3) var(--space-4);
1210 background: var(--bg-overlay);
1211 border-bottom: 1px solid var(--border-default);
1212 gap: var(--space-3);
1213 }
1214 .sr-repo-group-name {
1215 font-weight: var(--font-weight-semibold);
1216 font-size: var(--font-size-sm);
1217 color: var(--text-primary);
1218 a { color: inherit; text-decoration: none; &:hover { color: var(--color-accent); } }
1219 }
1220 .sr-repo-group-meta {
1221 font-size: var(--font-size-xs);
1222 color: var(--text-muted);
1223 display: flex;
1224 align-items: center;
1225 gap: var(--space-2);
1226 }
1227 .sr-repo-group-body {
1228 padding: var(--space-3) var(--space-4);
1229 }
1230 .sr-pagination {
1231 display: flex;
1232 gap: var(--space-2);
1233 margin-top: var(--space-4);
1234 align-items: center;
1235 flex-wrap: wrap;
1236 }
1237
1238 /* ── Legacy aliases (keep commit-row for other templates that use it) ───── */
1239 .commit-row { display: flex; gap: var(--space-2); align-items: baseline; padding: var(--space-1) 0; border-top: 1px solid var(--border-default); font-size: 13px; }
1240 .commit-row:first-child { border-top: none; }
1241 .commit-msg { flex: 1; color: var(--text-primary); }
1242 .commit-meta { font-size: 11px; color: var(--text-muted); flex-shrink: 0; }
1243 .more-note { font-size: 12px; color: var(--text-muted); margin-top: var(--space-1); }
1244 .search-bar { display: flex; gap: var(--space-2); margin-bottom: var(--space-3); flex-wrap: wrap; }
1245 .search-bar input[type="search"] { flex: 1; min-width: 200px; }
1246 .search-result-repo { border: 1px solid var(--border-default); border-radius: 6px; padding: var(--space-3); margin-bottom: var(--space-3); background: var(--bg-surface); }
1247 .search-result-repo h3 { margin: 0 0 var(--space-2) 0; font-size: 16px; }
1248
1249
1250 // ── Blob v2 (content-addressed file viewer) ──────────────────────────────────
1251 // Single-column by default; Phase 2 adds .blob2-panel-open for 1fr 260px split.
1252 .blob2-layout { margin-top: var(--space-4); }
1253 .blob2-main { min-width: 0; }
1254
1255 // Header bar
1256 .blob2-header {
1257 display: flex; align-items: center; gap: var(--space-3);
1258 padding: 10px 14px;
1259 background: var(--bg-surface);
1260 border: 1px solid var(--border-default);
1261 border-bottom: none;
1262 flex-wrap: wrap;
1263 }
1264 .blob2-header-left {
1265 display: flex; align-items: center; gap: 8px; flex: 1 1 0; min-width: 0;
1266 }
1267 .blob2-filename {
1268 font-family: var(--font-mono); font-size: 13px;
1269 color: var(--text-primary); font-weight: 500;
1270 }
1271 .blob2-lang-badge {
1272 font-size: 10px; font-weight: 600; letter-spacing: .5px; text-transform: uppercase;
1273 background: var(--bg-sunken); color: var(--text-muted);
1274 border: 1px solid var(--border-subtle);
1275 border-radius: 4px; padding: 0 6px; line-height: 18px;
1276 }
1277 .blob2-header-meta {
1278 display: flex; align-items: center; gap: 6px;
1279 }
1280 .blob2-meta-pill {
1281 font-size: 11px; color: var(--text-muted);
1282 background: var(--bg-sunken); border-radius: 999px; padding: 1px 8px;
1283 }
1284 .blob2-header-actions {
1285 display: flex; align-items: center; gap: 6px;
1286 }
1287
1288 // Language colour dots
1289 .blob2-lang-dot {
1290 width: 10px; height: 10px; border-radius: 50%; display: inline-block; flex-shrink: 0;
1291 background: var(--text-muted);
1292 }
1293 .blob2-ld-py { background: #3572A5; }
1294 .blob2-ld-ts { background: #2b7489; }
1295 .blob2-ld-js { background: #f1e05a; }
1296 .blob2-ld-rs { background: #dea584; }
1297 .blob2-ld-go { background: #00ADD8; }
1298 .blob2-ld-md { background: #6f42c1; }
1299 .blob2-ld-toml, .blob2-ld-yaml, .blob2-ld-yml { background: #cb171e; }
1300 .blob2-ld-json { background: #292929; }
1301 .blob2-ld-css { background: #563d7c; }
1302 .blob2-ld-scss { background: #c6538c; }
1303 .blob2-ld-html { background: #e34c26; }
1304 .blob2-ld-sh, .blob2-ld-bash { background: #89e051; }
1305 .blob2-ld-mid, .blob2-ld-midi { background: var(--color-accent); }
1306
1307 // Last-modified bar
1308 .blob2-lastmod {
1309 display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
1310 padding: 6px 14px; font-size: 12px;
1311 background: var(--bg-sunken); border: 1px solid var(--border-subtle);
1312 border-bottom: none;
1313 }
1314 .blob2-lastmod-sha {
1315 font-family: var(--font-mono); font-size: 11px; color: var(--color-accent-link);
1316 text-decoration: none; background: var(--bg-surface);
1317 border: 1px solid var(--border-subtle); border-radius: 4px; padding: 1px 5px;
1318 &:hover { border-color: var(--color-accent); }
1319 }
1320 .blob2-lastmod-msg { color: var(--text-secondary); flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
1321 .blob2-lastmod-author { color: var(--text-muted); font-size: 11px; }
1322 .blob2-lastmod-time { color: var(--text-muted); font-size: 11px; margin-left: auto; }
1323
1324 // Content
1325 .blob2-content {
1326 border: 1px solid var(--border-default);
1327 border-radius: 0 0 8px 8px;
1328 overflow: hidden;
1329 background: var(--bg-surface);
1330 }
1331
1332 // Code viewer
1333 .blob2-viewer { overflow-x: auto; }
1334 .blob2-line-table {
1335 width: 100%; border-collapse: collapse; font-size: 13px;
1336 font-family: var(--font-mono); tab-size: 4;
1337 }
1338 .blob2-line {
1339 scroll-margin-top: calc(var(--sticky-offset, 80px) + 16px);
1340 &:target, &:hover { background: var(--bg-sunken); }
1341 }
1342 .blob2-ln {
1343 width: 1%; min-width: 40px; padding: 0 12px 0 16px;
1344 text-align: right; color: var(--text-muted); font-size: 11px; user-select: none;
1345 border-right: 1px solid var(--border-subtle); white-space: nowrap; vertical-align: top;
1346 }
1347 .blob2-ln-link {
1348 color: inherit; text-decoration: none;
1349 &:hover { color: var(--text-primary); }
1350 }
1351 .blob2-code {
1352 padding: 0 16px; white-space: pre; word-break: keep-all;
1353 color: var(--text-primary); line-height: 1.6;
1354 }
1355 .blob2-empty {
1356 color: var(--text-muted); font-size: 13px; padding: 32px; text-align: center;
1357 }
1358
1359 // MIDI banner inside blob2
1360 .blob2-midi-banner {
1361 display: flex; align-items: center; gap: var(--space-4);
1362 padding: var(--space-6) var(--space-5);
1363 background: linear-gradient(135deg, var(--bg-sunken) 0%, var(--bg-surface) 100%);
1364 }
1365 .blob2-midi-info { flex: 1; }
1366 .blob2-midi-filename { font-size: 15px; font-weight: 600; color: var(--text-primary); }
1367 .blob2-midi-sub { font-size: 12px; color: var(--text-muted); margin-top: 2px; }
1368 .blob2-midi-actions { display: flex; gap: 8px; }
1369
1370 // Binary notice
1371 .blob2-binary-notice {
1372 display: flex; flex-direction: column; align-items: center;
1373 gap: var(--space-3); padding: var(--space-8) var(--space-5);
1374 color: var(--text-muted); font-size: 13px; text-align: center;
1375 }
1376
1377 // 404 state
1378 .blob2-not-found {
1379 display: flex; flex-direction: column; align-items: center;
1380 gap: var(--space-3); padding: var(--space-10) var(--space-5);
1381 color: var(--text-muted); text-align: center;
1382 h2 { color: var(--text-secondary); font-size: 18px; }
1383 p { font-size: 13px; }
1384 code { font-family: var(--font-mono); background: var(--bg-sunken); padding: 1px 5px; border-radius: 4px; }
1385 }
1386
1387 // ── Phase 1: Provenance pill ──────────────────────────────────────────────────
1388 .blob2-prov-pill {
1389 display: inline-flex; align-items: center; gap: 4px;
1390 font-size: 10px; font-weight: 700; letter-spacing: 0.04em;
1391 padding: 1px 7px; border-radius: var(--radius-full);
1392 border: 1px solid; white-space: nowrap; flex-shrink: 0;
1393 text-transform: uppercase;
1394 &--human {
1395 color: var(--color-success);
1396 border-color: color-mix(in srgb, var(--color-success) 40%, transparent);
1397 background: color-mix(in srgb, var(--color-success) 8%, transparent);
1398 }
1399 &--agent {
1400 color: var(--color-accent);
1401 border-color: color-mix(in srgb, var(--color-accent) 40%, transparent);
1402 background: color-mix(in srgb, var(--color-accent) 8%, transparent);
1403 }
1404 }
1405
1406 // ── Phase 1: Sem-ver bump badge ───────────────────────────────────────────────
1407 .blob2-bump-badge {
1408 display: inline-block; font-size: 9px; font-weight: 700; letter-spacing: 0.06em;
1409 text-transform: uppercase; padding: 1px 6px; border-radius: 3px;
1410 border: 1px solid; white-space: nowrap; flex-shrink: 0;
1411 &--patch { color: var(--text-muted); border-color: var(--border-subtle); background: var(--bg-overlay); }
1412 &--minor { color: #d4a017; border-color: #5a420a; background: rgba(212,160,23,0.1); }
1413 &--major { color: var(--color-danger); border-color: color-mix(in srgb, var(--color-danger) 40%, transparent); background: color-mix(in srgb, var(--color-danger) 8%, transparent); }
1414 &--breaking { color: var(--color-warning); border-color: color-mix(in srgb, var(--color-warning) 35%, transparent); background: color-mix(in srgb, var(--color-warning) 8%, transparent); }
1415 }
1416
1417 // ── Phase 1: Line selection ───────────────────────────────────────────────────
1418 .blob2-line--selected {
1419 background: color-mix(in srgb, var(--color-accent) 12%, transparent) !important;
1420 .blob2-ln { color: var(--color-accent); }
1421 }
1422
1423 // ── Phase 1: Permalink float ──────────────────────────────────────────────────
1424 .blob2-permalink-float {
1425 position: fixed; bottom: 24px; right: 24px; z-index: 50;
1426 display: none;
1427 &.is-visible { display: block; }
1428 }
1429 .blob2-permalink-btn {
1430 display: inline-flex; align-items: center; gap: 5px;
1431 padding: 6px 12px; border-radius: var(--radius-full);
1432 background: var(--bg-surface); border: 1px solid var(--border-default);
1433 color: var(--text-primary); font-size: 11px; font-weight: 600;
1434 cursor: pointer; box-shadow: 0 2px 8px rgba(0,0,0,0.3);
1435 transition: border-color 0.12s, box-shadow 0.12s;
1436 &:hover { border-color: var(--color-accent); box-shadow: 0 2px 12px rgba(0,0,0,0.4); }
1437 }
1438
1439 // ── Phase 1: Outline toggle button ───────────────────────────────────────────
1440 .blob2-outline-toggle { font-size: 11px; gap: 4px; }
1441
1442 // ── Phase 2: Outline panel ────────────────────────────────────────────────────
1443 // Both columns scroll independently inside a fixed-height grid.
1444 .blob2-layout {
1445 &.blob2-panel-open {
1446 display: grid;
1447 grid-template-columns: 1fr 260px;
1448 gap: var(--space-3);
1449 height: calc(100vh - 180px);
1450 min-height: 400px;
1451
1452 > .blob2-main {
1453 overflow-y: auto;
1454 min-height: 0;
1455 border-radius: var(--radius);
1456 }
1457 }
1458 }
1459
1460 .blob2-panel {
1461 display: none;
1462 min-height: 0;
1463 background: var(--bg-surface);
1464 border: 1px solid var(--border-default);
1465 border-radius: var(--radius);
1466 overflow: clip; // clips children to border-radius without blocking scroll
1467 }
1468 .blob2-layout.blob2-panel-open .blob2-panel { display: flex; flex-direction: column; border-radius: 0; }
1469
1470 @media (max-width: 768px) {
1471 .blob2-layout.blob2-panel-open {
1472 display: block;
1473 height: auto;
1474 > .blob2-main { overflow-y: visible; }
1475 }
1476 .blob2-panel { display: none !important; }
1477 #blob2-outline-toggle { display: none; }
1478 }
1479
1480 // Tabs
1481 .blob2-panel-tabs {
1482 display: flex;
1483 border-bottom: 1px solid var(--border-default);
1484 flex-shrink: 0;
1485 }
1486 .blob2-panel-tab {
1487 flex: 1; padding: 7px 10px;
1488 font-size: 11px; font-weight: 600; color: var(--text-muted);
1489 background: none; border: none; cursor: pointer;
1490 border-bottom: 2px solid transparent; margin-bottom: -1px;
1491 transition: color 0.12s, border-color 0.12s;
1492 &:hover { color: var(--text-primary); }
1493 &--active {
1494 color: var(--text-primary);
1495 border-bottom-color: var(--color-accent);
1496 }
1497 }
1498
1499 // Panes — flex:1 + min-height:0 + overflow-y:auto is the correct pattern
1500 // for a scrollable child inside a flex column with a max-height parent.
1501 .blob2-panel-pane { padding: var(--space-2) 0; }
1502 .blob2-panel-pane--hidden { display: none; }
1503 .blob2-panel-empty {
1504 padding: var(--space-4) var(--space-3);
1505 font-size: 12px; color: var(--text-muted); text-align: center;
1506 }
1507
1508 // Symbols tab — outline rows
1509 .blob2-outline-row {
1510 display: flex; align-items: center; gap: 6px;
1511 padding: 5px var(--space-3);
1512 font-size: 11px;
1513 &:hover { background: var(--bg-sunken); }
1514 }
1515 .blob2-outline-op {
1516 flex-shrink: 0;
1517 font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em;
1518 padding: 1px 5px; border-radius: 3px; border: 1px solid;
1519 &--add { color: var(--color-success); border-color: color-mix(in srgb, var(--color-success) 35%, transparent); background: color-mix(in srgb, var(--color-success) 8%, transparent); }
1520 &--modify { color: var(--color-accent-link); border-color: color-mix(in srgb, var(--color-accent-link) 35%, transparent); background: color-mix(in srgb, var(--color-accent-link) 8%, transparent); }
1521 &--delete { color: var(--color-danger); border-color: color-mix(in srgb, var(--color-danger) 35%, transparent); background: color-mix(in srgb, var(--color-danger) 8%, transparent); }
1522 &--rename { color: #d4a017; border-color: #5a420a; background: rgba(212,160,23,0.1); }
1523 &--patch { color: var(--text-muted); border-color: var(--border-subtle); background: var(--bg-overlay); }
1524 // Live-parsed symbols (no commit history yet) — show kind instead of op
1525 &--fn { color: #d2a8ff; border-color: color-mix(in srgb, #d2a8ff 30%, transparent); background: color-mix(in srgb, #d2a8ff 8%, transparent); }
1526 &--class { color: #ffa657; border-color: color-mix(in srgb, #ffa657 30%, transparent); background: color-mix(in srgb, #ffa657 8%, transparent); }
1527 &--sym { color: var(--text-muted); border-color: var(--border-subtle); background: var(--bg-overlay); }
1528 }
1529 .blob2-outline-addr {
1530 flex: 1; min-width: 0;
1531 font-family: var(--font-mono); font-size: 11px; color: var(--text-secondary);
1532 white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
1533 }
1534 .blob2-outline-meta {
1535 display: flex; align-items: center; gap: 4px; flex-shrink: 0;
1536 }
1537 .blob2-outline-count {
1538 font-size: 9px; color: var(--text-muted);
1539 background: var(--bg-sunken); border-radius: 999px; padding: 0 4px;
1540 }
1541 .blob2-outline-time { font-size: 10px; color: var(--text-muted); }
1542
1543 // Info tab
1544 .blob2-info-section {
1545 padding: var(--space-2) var(--space-3);
1546 &--sep { border-top: 1px solid var(--border-subtle); padding-top: var(--space-3); }
1547 }
1548 .blob2-info-row {
1549 display: flex; justify-content: space-between; align-items: baseline;
1550 gap: 8px; padding: 2px 0; font-size: 11px;
1551 }
1552 .blob2-info-label { color: var(--text-muted); flex-shrink: 0; }
1553 .blob2-info-value { color: var(--text-secondary); text-align: right; min-width: 0; }
1554 .blob2-info-mono { font-family: var(--font-mono); font-size: 10px; }
1555 .blob2-info-label-block {
1556 font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em;
1557 color: var(--text-muted); margin-bottom: var(--space-1);
1558 }
1559 .blob2-info-addr {
1560 display: flex; align-items: center; gap: 6px;
1561 code { color: var(--text-secondary); }
1562 }
1563 .blob2-copy-addr {
1564 background: none; border: none; cursor: pointer; padding: 2px;
1565 color: var(--text-muted); line-height: 0;
1566 &:hover { color: var(--text-primary); }
1567 }
1568 .blob2-info-commit-link {
1569 font-family: var(--font-mono); font-size: 11px; color: var(--color-accent-link);
1570 text-decoration: none; display: inline-block; margin-bottom: 2px;
1571 &:hover { text-decoration: underline; }
1572 }
1573 .blob2-info-commit-msg { font-size: 11px; color: var(--text-secondary); margin-bottom: 2px; }
1574 .blob2-info-commit-time { font-size: 10px; color: var(--text-muted); }
1575 .blob2-info-link {
1576 display: block; font-size: 11px; color: var(--color-accent-link);
1577 text-decoration: none; padding: 2px 0;
1578 &:hover { text-decoration: underline; }
1579 }
1580
1581 // Responsive — panel collapses on narrow screens
1582 @media (max-width: 900px) {
1583 .blob2-layout.blob2-panel-open {
1584 grid-template-columns: 1fr;
1585 }
1586 .blob2-layout.blob2-panel-open .blob2-panel {
1587 position: static;
1588 max-height: 400px;
1589 }
1590 }
1591
1592
1593 // ── Phase 4: Intelligence signal pills ───────────────────────────────────────
1594 .blob2-signal-pill {
1595 display: inline-flex; align-items: center; gap: 4px;
1596 font-size: 10px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase;
1597 padding: 1px 7px; border-radius: var(--radius-full); border: 1px solid;
1598 white-space: nowrap; flex-shrink: 0; cursor: default;
1599 &--hotspot {
1600 color: #e07b39;
1601 border-color: rgba(224, 123, 57, 0.4);
1602 background: rgba(224, 123, 57, 0.1);
1603 }
1604 &--cold {
1605 color: var(--color-accent-link);
1606 border-color: color-mix(in srgb, var(--color-accent-link) 35%, transparent);
1607 background: color-mix(in srgb, var(--color-accent-link) 8%, transparent);
1608 }
1609 &--blast {
1610 color: #d4a017;
1611 border-color: rgba(212, 160, 23, 0.4);
1612 background: rgba(212, 160, 23, 0.1);
1613 }
1614 }
1615
1616 // ── Phase 3: File provenance timeline ────────────────────────────────────────
1617 .blob2-history {
1618 margin-top: var(--space-4);
1619 border: 1px solid var(--border-default);
1620 border-radius: var(--radius);
1621 background: var(--bg-surface);
1622 overflow: hidden;
1623 }
1624 .blob2-history-header {
1625 display: flex; align-items: center; gap: 7px;
1626 padding: 8px 14px;
1627 font-size: 12px; font-weight: 600; color: var(--text-secondary);
1628 background: var(--bg-sunken);
1629 border-bottom: 1px solid var(--border-default);
1630 }
1631 .blob2-history-count {
1632 font-size: 10px; font-weight: 400; color: var(--text-muted);
1633 background: var(--bg-overlay); border-radius: 999px; padding: 1px 7px;
1634 }
1635 .blob2-history-rows { }
1636 .blob2-history-row {
1637 display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
1638 padding: 7px 14px; font-size: 12px;
1639 border-bottom: 1px solid var(--border-subtle);
1640 &:last-child { border-bottom: none; }
1641 &:hover { background: var(--bg-sunken); }
1642 }
1643 .blob2-history-sha {
1644 font-family: var(--font-mono); font-size: 11px; color: var(--color-accent-link);
1645 text-decoration: none; flex-shrink: 0;
1646 background: var(--bg-overlay); border: 1px solid var(--border-subtle);
1647 border-radius: 4px; padding: 1px 5px;
1648 &:hover { border-color: var(--color-accent); }
1649 }
1650 .blob2-history-msg {
1651 flex: 1; min-width: 0;
1652 color: var(--text-secondary);
1653 white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
1654 }
1655 .blob2-history-prov { display: inline-flex; align-items: center; flex-shrink: 0; }
1656 .blob2-history-time { font-size: 11px; color: var(--text-muted); margin-left: auto; flex-shrink: 0; }
1657
1658
1659 // ── Responsive ────────────────────────────────────────────────────────────────
1660
1661 @media (max-width: 768px) {
1662 .blob2-permalink-float { bottom: 12px; right: 12px; }
1663
1664 .blob-toolbar {
1665 flex-wrap: wrap;
1666 gap: var(--space-1);
1667 }
1668
1669 .blob-header {
1670 flex-direction: column;
1671 align-items: flex-start;
1672 }
1673
1674 .sr-layout {
1675 grid-template-columns: 1fr;
1676 }
1677
1678 .sr-filters {
1679 display: none;
1680 }
1681
1682 .sr-result-path {
1683 font-size: 11px;
1684 overflow: hidden;
1685 text-overflow: ellipsis;
1686 white-space: nowrap;
1687 }
1688
1689 .blame-line-meta {
1690 display: none;
1691 }
1692
1693 .blame-gutter {
1694 width: 32px;
1695 font-size: 10px;
1696 }
1697 }
1698
1699 @media (max-width: 480px) {
1700 .blob2-header-bar {
1701 flex-direction: column;
1702 align-items: flex-start;
1703 gap: var(--space-2);
1704 }
1705
1706 .blob-breadcrumb {
1707 font-size: 12px;
1708 }
1709
1710 .sr-result-snippet {
1711 font-size: 12px;
1712 }
1713
1714 .sr-hits-count {
1715 font-size: 11px;
1716 }
1717 }
File History 1 commit
sha256:9590cee1e0ccd6c76528f005b95d634d80f5019f0dcb7c371e149adc31d1fb65 refactor: enforce gRPC framing on all MWP wire traffic Sonnet 4.6 minor ⚠ 155 days ago