PluginProbe
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin / 1.1.2
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin v1.1.2
1.1.10 1.1.9 1.1.8 1.1.7 1.1.6 1.1.5 1.1.4 1.1.3 1.1.2 1.1.1 1.1.0 1.0.1 1.0.0 0.9.8 0.9.7 0.9.6 0.9.4 0.9.5 0.9.3 0.9.2 0.9.1 0.9.0 0.8.9 0.8.8 0.8.7 All 34 releases
desktop-mode / assets / css / content-graph.css

content-graph.css in OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin 1.1.2, at assets/css/content-graph.css

1,057 lines 22.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * OpenStation — Content Graph window styles.
3 *
4 * Scoped to `.desktop-mode-content-graph`. Reads `os-variables`
5 * tokens so the chrome adapts to the active theme.
6 *
7 * @since 0.8.2
8 */
9
10 .desktop-mode-content-graph {
11 display: flex;
12 flex-direction: column;
13 width: 100%;
14 height: 100%;
15 background: var( --os-ui-surface, #f7f8fb );
16 color: var( --os-ui-fg, #1a1f2b );
17 font-family: var(
18 --os-ui-font,
19 -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
20 'Helvetica Neue', Arial, sans-serif
21 );
22 }
23
24 /* ---------- Toolbar ------------------------------------------------- */
25
26 .os-content-graph__toolbar {
27 display: flex;
28 align-items: center;
29 gap: 12px;
30 padding: 10px 14px;
31 border-bottom: 1px solid var( --os-ui-border, #e2e6ec );
32 background: var( --os-ui-surface-elevated, #fff );
33 flex-wrap: wrap;
34 }
35
36 .os-content-graph__filters {
37 display: flex;
38 align-items: center;
39 gap: 6px;
40 flex-wrap: wrap;
41 }
42
43 .os-content-graph__chip {
44 display: inline-flex;
45 align-items: center;
46 gap: 6px;
47 padding: 5px 10px;
48 border: 1px solid var( --os-ui-border, #d8dde4 );
49 border-radius: 999px;
50 background: transparent;
51 color: var( --os-ui-fg-muted, #5a6473 );
52 font-size: 12px;
53 cursor: pointer;
54 transition: background 0.12s ease, border-color 0.12s ease,
55 color 0.12s ease;
56 }
57
58 .os-content-graph__chip:hover {
59 background: var( --os-ui-hover, rgba( 79, 139, 243, 0.08 ) );
60 color: var( --os-ui-fg, #1a1f2b );
61 }
62
63 .os-content-graph__chip.is-active {
64 border-color: var( --os-ui-accent, #2c6be5 );
65 background: var( --os-ui-accent-soft, rgba( 44, 107, 229, 0.12 ) );
66 color: var( --os-ui-accent-strong, #1f4ea8 );
67 }
68
69 .os-content-graph__chip .dashicons {
70 font-size: 14px;
71 width: 14px;
72 height: 14px;
73 line-height: 14px;
74 }
75
76 .os-content-graph__chip-count {
77 font-variant-numeric: tabular-nums;
78 font-size: 11px;
79 background: var( --os-ui-surface, #f1f3f7 );
80 padding: 1px 6px;
81 border-radius: 999px;
82 }
83
84 /*
85 * The count pill on an ACTIVE chip is a bright fill, and the chip's
86 * own text colour is `--os-ui-accent-strong` — a light tint, by design,
87 * because the chip body around it is a dark accent wash. The two meet
88 * on this pill and cancel out (Nebula on 70% white is ~1.7:1).
89 *
90 * So the pill names its own text, exactly the way `--os-ui-ribbon-fg`
91 * and `--os-ui-step-chip-fg` do for the other bright fills in the kit.
92 * Unset it inherits the chip's colour, which is what a light theme
93 * wants — there the chip text is already dark.
94 */
95 .os-content-graph__chip.is-active .os-content-graph__chip-count {
96 background: rgba( 255, 255, 255, 0.7 );
97 color: var( --os-ui-cg-chip-count-fg-active, inherit );
98 }
99
100 .os-content-graph__search {
101 position: relative;
102 flex: 1;
103 min-width: 220px;
104 max-width: 320px;
105 }
106
107 .os-content-graph__search-input {
108 width: 100%;
109 padding: 6px 10px;
110 border: 1px solid var( --os-ui-border, #d8dde4 );
111 border-radius: 6px;
112 background: var( --os-ui-surface, #fff );
113 color: inherit;
114 font-size: 13px;
115 }
116
117 .os-content-graph__search-input:focus {
118 outline: none;
119 border-color: var( --os-ui-accent, #2c6be5 );
120 box-shadow: 0 0 0 3px var( --os-ui-accent-soft, rgba( 44, 107, 229, 0.18 ) );
121 }
122
123 .os-content-graph__search-results {
124 position: absolute;
125 top: calc( 100% + 4px );
126 left: 0;
127 right: 0;
128 margin: 0;
129 padding: 4px;
130 list-style: none;
131 background: var( --os-ui-surface-elevated, #fff );
132 border: 1px solid var( --os-ui-border, #d8dde4 );
133 border-radius: 8px;
134 box-shadow: 0 6px 18px rgba( 17, 24, 39, 0.08 );
135 z-index: 10;
136 max-height: 300px;
137 overflow-y: auto;
138 }
139
140 .os-content-graph__search-result {
141 display: flex;
142 align-items: center;
143 justify-content: space-between;
144 gap: 8px;
145 width: 100%;
146 padding: 6px 10px;
147 background: transparent;
148 border: 0;
149 border-radius: 6px;
150 color: inherit;
151 cursor: pointer;
152 text-align: left;
153 font-size: 13px;
154 }
155
156 .os-content-graph__search-result:hover {
157 background: var( --os-ui-hover, rgba( 79, 139, 243, 0.08 ) );
158 }
159
160 .os-content-graph__search-title {
161 flex: 1;
162 overflow: hidden;
163 text-overflow: ellipsis;
164 white-space: nowrap;
165 }
166
167 .os-content-graph__search-type {
168 font-size: 11px;
169 color: var( --os-ui-fg-muted, #6b7280 );
170 text-transform: uppercase;
171 letter-spacing: 0.05em;
172 }
173
174 .os-content-graph__actions {
175 display: flex;
176 align-items: center;
177 gap: 8px;
178 margin-left: auto;
179 }
180
181 .os-content-graph__group-by {
182 /* The os-select grows to its own intrinsic size; cap it so the
183 action row stays compact on narrow windows. */
184 max-width: 180px;
185 }
186
187 .os-content-graph__btn {
188 display: inline-flex;
189 align-items: center;
190 gap: 6px;
191 padding: 5px 10px;
192 border: 1px solid var( --os-ui-border, #d8dde4 );
193 border-radius: 6px;
194 background: var( --os-ui-surface-elevated, #fff );
195 color: inherit;
196 font-size: 12px;
197 cursor: pointer;
198 }
199
200 .os-content-graph__btn:hover {
201 background: var( --os-ui-hover, rgba( 79, 139, 243, 0.08 ) );
202 border-color: var( --os-ui-accent, #2c6be5 );
203 }
204
205 .os-content-graph__btn .dashicons {
206 font-size: 14px;
207 width: 14px;
208 height: 14px;
209 line-height: 14px;
210 }
211
212 .os-content-graph__toolbar-status {
213 margin-left: 8px;
214 font-size: 11px;
215 color: var( --os-ui-fg-muted, #6b7280 );
216 font-variant-numeric: tabular-nums;
217 }
218
219 /* ---------- Cluster labels (DOM overlay) -------------------------- */
220
221 .os-content-graph__group-labels {
222 position: absolute;
223 inset: 0;
224 pointer-events: none;
225 /* Sit above the canvas but below any toolbar / side panel. */
226 z-index: 2;
227 overflow: hidden;
228 }
229
230 .os-content-graph__group-label {
231 position: absolute;
232 top: 0;
233 left: 0;
234 padding: 5px 12px;
235 border-radius: 999px;
236 background: var( --os-ui-cg-cluster-color, #2c6be5 );
237 color: var( --os-ui-fg-on-accent, #fff );
238 font-size: 14px;
239 font-weight: 700;
240 font-family: var(
241 --os-ui-font,
242 -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
243 'Helvetica Neue', Arial, sans-serif
244 );
245 white-space: nowrap;
246 box-shadow: 0 0 0 1.5px rgba( 255, 255, 255, 0.85 ),
247 0 1px 3px rgba( 0, 0, 0, 0.18 );
248 /* Translucent so nodes/edges behind the label remain visible. */
249 opacity: 0.85;
250 /* Smooth the per-frame `style.opacity` and transform updates so
251 the cluster labels glide instead of stutter during the
252 grouping tween. */
253 transition: opacity 120ms ease-out;
254 will-change: transform, opacity;
255 }
256
257 /* ---------- Body layout (stage + side panel) ----------------------- */
258
259 .os-content-graph__body {
260 display: flex;
261 flex: 1;
262 min-height: 0;
263 }
264
265 /* ---------- Stage --------------------------------------------------- */
266
267 .os-content-graph__stage {
268 position: relative;
269 flex: 1;
270 min-width: 0;
271 min-height: 0;
272 overflow: hidden;
273 /*
274 * Three layers, painted bottom-up:
275 * 1. The theme surface fills the canvas (so PixiJS, which uses
276 * `backgroundAlpha: 0`, lets it bleed through).
277 * 2. Two soft theme-tinted radial vignettes give the canvas a
278 * sense of depth without competing with the graph itself.
279 * 3. A 24x24 dot grid at low alpha gives a subtle "graph paper"
280 * texture, mirroring the categories-mindmap reference.
281 */
282 background:
283 radial-gradient(
284 circle,
285 rgba( 0, 0, 0, 0.06 ) 1px,
286 transparent 1.5px
287 ) 0 0 / 24px 24px,
288 radial-gradient(
289 ellipse at 28% 22%,
290 rgba( 79, 139, 243, 0.08 ),
291 transparent 60%
292 ),
293 radial-gradient(
294 ellipse at 78% 80%,
295 rgba( 176, 102, 215, 0.06 ),
296 transparent 58%
297 ),
298 var( --os-ui-surface, #f7f8fb );
299 }
300
301 .os-content-graph__canvas {
302 display: block;
303 width: 100%;
304 height: 100%;
305 }
306
307 .os-content-graph__loading {
308 position: absolute;
309 inset: 0;
310 display: flex;
311 align-items: center;
312 justify-content: center;
313 background: rgba( 247, 248, 251, 0.7 );
314 pointer-events: none;
315 z-index: 2;
316 }
317
318 .os-content-graph__loading[ hidden ] {
319 display: none;
320 }
321
322 /* ---------- Right side panel: breadcrumb --------------------------- */
323
324 .os-content-graph__panel-breadcrumb {
325 display: flex;
326 align-items: center;
327 padding: 8px 14px 0;
328 min-height: 32px;
329 }
330
331 .os-content-graph__panel-breadcrumb[ hidden ] {
332 display: none;
333 }
334
335 .os-content-graph__panel-breadcrumb-back {
336 display: inline-flex;
337 align-items: center;
338 gap: 4px;
339 background: transparent;
340 border: 0;
341 padding: 4px 8px 4px 4px;
342 border-radius: 6px;
343 cursor: pointer;
344 color: var( --os-ui-fg-muted, #6b7280 );
345 font-size: 12px;
346 font-weight: 500;
347 max-width: 100%;
348 min-width: 0;
349 text-align: left;
350 }
351
352 .os-content-graph__panel-breadcrumb-back:hover {
353 background: var( --os-ui-hover, rgba( 0, 0, 0, 0.05 ) );
354 color: var( --os-ui-fg, #1a1f2b );
355 }
356
357 .os-content-graph__panel-breadcrumb-arrow {
358 font-size: 16px;
359 width: 16px;
360 height: 16px;
361 line-height: 16px;
362 flex-shrink: 0;
363 }
364
365 .os-content-graph__panel-breadcrumb-label {
366 overflow: hidden;
367 text-overflow: ellipsis;
368 white-space: nowrap;
369 min-width: 0;
370 }
371
372 /* ---------- Right side panel --------------------------------------- */
373
374 .os-content-graph__panel {
375 width: 320px;
376 flex-shrink: 0;
377 border-left: 1px solid var( --os-ui-border, #e2e6ec );
378 background: var( --os-ui-surface-elevated, #fff );
379 display: flex;
380 flex-direction: column;
381 overflow: hidden;
382 /*
383 * Subtle slide-in / slide-out when the panel opens or closes —
384 * the outer container collapses its width while the inner frame
385 * eases off to the right + fades, so the canvas reclaims the
386 * space smoothly instead of the panel popping out of layout.
387 */
388 transition:
389 width 220ms cubic-bezier( 0.32, 0.72, 0, 1 ),
390 border-left-width 220ms cubic-bezier( 0.32, 0.72, 0, 1 ),
391 opacity 180ms ease-out;
392 will-change: width, opacity;
393 }
394
395 .os-content-graph__panel[ hidden ],
396 .os-content-graph__panel--closed {
397 width: 0;
398 opacity: 0;
399 pointer-events: none;
400 border-left-width: 0;
401 }
402
403 .os-content-graph__panel[ hidden ] {
404 /* Initial PHP-rendered state — no transition on the very first
405 * paint, otherwise the panel briefly slides in on page load. */
406 transition: none;
407 }
408
409 .os-content-graph__panel-frame {
410 /*
411 * Without these rules the body's `flex: 1; overflow-y: auto`
412 * has nothing to constrain it — the body just grows to fit its
413 * dossier content and the action buttons get clipped at the
414 * bottom of the panel. Make the frame a flex column itself so
415 * the body is forced to share the panel's height with the
416 * breadcrumb and head, then scrolls the overflow.
417 */
418 display: flex;
419 flex-direction: column;
420 flex: 1 1 0;
421 min-height: 0;
422 width: 320px;
423 overflow: hidden;
424 /* Slides + fades alongside the parent's width collapse so the
425 * panel content visibly leaves to the right when closing. */
426 transition:
427 transform 220ms cubic-bezier( 0.32, 0.72, 0, 1 ),
428 opacity 180ms ease-out;
429 }
430
431 .os-content-graph__panel[ hidden ] .os-content-graph__panel-frame,
432 .os-content-graph__panel--closed .os-content-graph__panel-frame {
433 transform: translateX( 16% );
434 opacity: 0;
435 }
436
437 @media ( prefers-reduced-motion: reduce ) {
438 .os-content-graph__panel,
439 .os-content-graph__panel-frame {
440 transition: none;
441 }
442 }
443
444 .os-content-graph__panel-head {
445 display: flex;
446 align-items: flex-start;
447 gap: 8px;
448 padding: 14px 16px 10px;
449 border-bottom: 1px solid var( --os-ui-border, #eef0f4 );
450 }
451
452 .os-content-graph__panel-title-wrap {
453 flex: 1;
454 min-width: 0;
455 }
456
457 .os-content-graph__panel-title {
458 margin: 0;
459 font-size: 14px;
460 font-weight: 600;
461 line-height: 1.35;
462 overflow-wrap: anywhere;
463 }
464
465 .os-content-graph__panel-meta {
466 margin: 4px 0 0;
467 font-size: 11px;
468 color: var( --os-ui-fg-muted, #6b7280 );
469 text-transform: uppercase;
470 letter-spacing: 0.06em;
471 }
472
473 .os-content-graph__panel-close {
474 background: transparent;
475 border: 0;
476 color: var( --os-ui-fg-muted, #6b7280 );
477 cursor: pointer;
478 padding: 2px;
479 border-radius: 4px;
480 flex-shrink: 0;
481 }
482
483 .os-content-graph__panel-close:hover {
484 background: var( --os-ui-hover, rgba( 0, 0, 0, 0.05 ) );
485 color: inherit;
486 }
487
488 .os-content-graph__panel-body {
489 flex: 1;
490 min-height: 0;
491 /*
492 * The body is now a clipped stage that holds one or two
493 * absolutely-positioned `__panel-page` children. During an iOS-
494 * style navigation, the new page slides in over the old; both
495 * are clipped here so the off-stage portion isn't visible.
496 */
497 position: relative;
498 overflow: hidden;
499 padding: 0;
500 }
501
502 .os-content-graph__panel-page {
503 position: absolute;
504 inset: 0;
505 overflow-y: auto;
506 padding: 14px 16px 18px;
507 display: flex;
508 flex-direction: column;
509 gap: 14px;
510 background: var( --os-ui-surface-elevated, #fff );
511 /*
512 * iOS navigation curve — quick out, slow in. 240ms matches
513 * UIKit's default push/pop duration closely enough for the
514 * reviewer-flagged "abrupt" feeling to ease.
515 */
516 transition:
517 transform 240ms cubic-bezier( 0.32, 0.72, 0, 1 ),
518 opacity 200ms ease-out;
519 will-change: transform, opacity;
520 }
521
522 /*
523 * Forward push: new page enters from the right at full distance, the
524 * outgoing page parallax-slides a fraction of the way to the left.
525 * Back pop: mirrored — new page enters from the left at parallax
526 * distance, current page slides off the right at full distance.
527 */
528 .os-content-graph__page-from-right {
529 transform: translateX( 100% );
530 }
531 .os-content-graph__page-from-left {
532 transform: translateX( -28% );
533 opacity: 0.55;
534 }
535 .os-content-graph__page-to-right {
536 transform: translateX( 100% );
537 /* Keep the outgoing page above the incoming parallax shadow on
538 * back so the slide reads as the user "removing" it. */
539 z-index: 2;
540 }
541 .os-content-graph__page-to-left {
542 transform: translateX( -28% );
543 opacity: 0.55;
544 }
545
546 @media ( prefers-reduced-motion: reduce ) {
547 .os-content-graph__panel-page {
548 transition: none;
549 }
550 }
551
552 .os-content-graph__panel-section-label {
553 display: block;
554 font-size: 10px;
555 font-weight: 600;
556 color: var( --os-ui-fg-muted, #6b7280 );
557 text-transform: uppercase;
558 letter-spacing: 0.06em;
559 margin-bottom: 4px;
560 }
561
562 .os-content-graph__panel-author {
563 display: flex;
564 flex-direction: column;
565 gap: 4px;
566 }
567
568 .os-content-graph__panel-author[ hidden ] {
569 display: none;
570 }
571
572 .os-content-graph__panel-author-row {
573 display: flex;
574 align-items: center;
575 gap: 8px;
576 }
577
578 .os-content-graph__panel-avatar {
579 width: 32px;
580 height: 32px;
581 border-radius: 50%;
582 flex-shrink: 0;
583 }
584
585 .os-content-graph__panel-author-name {
586 font-size: 13px;
587 font-weight: 500;
588 }
589
590 .os-content-graph__panel-dates {
591 display: flex;
592 flex-direction: column;
593 gap: 8px;
594 }
595
596 .os-content-graph__panel-dates[ hidden ] {
597 display: none;
598 }
599
600 .os-content-graph__panel-date-row {
601 display: flex;
602 flex-direction: column;
603 gap: 2px;
604 }
605
606 .os-content-graph__panel-date-value {
607 font-size: 12px;
608 color: var( --os-ui-fg, #1a1f2b );
609 font-variant-numeric: tabular-nums;
610 }
611
612 .os-content-graph__panel-stats {
613 margin: 0;
614 padding: 0;
615 list-style: none;
616 display: grid;
617 grid-template-columns: repeat( auto-fill, minmax( 80px, 1fr ) );
618 gap: 4px;
619 background: var( --os-ui-surface, #f7f8fb );
620 border: 1px solid var( --os-ui-border, #eef0f4 );
621 border-radius: 8px;
622 padding: 8px;
623 }
624
625 .os-content-graph__panel-stats[ hidden ] {
626 display: none;
627 }
628
629 .os-content-graph__panel-stat {
630 display: flex;
631 flex-direction: column;
632 align-items: center;
633 gap: 1px;
634 }
635
636 .os-content-graph__panel-stat-num {
637 font-size: 16px;
638 font-weight: 600;
639 font-variant-numeric: tabular-nums;
640 color: var( --os-ui-fg, #1a1f2b );
641 }
642
643 .os-content-graph__panel-stat-label {
644 font-size: 10px;
645 color: var( --os-ui-fg-muted, #6b7280 );
646 text-transform: uppercase;
647 letter-spacing: 0.04em;
648 }
649
650 .os-content-graph__panel-actions {
651 display: flex;
652 flex-direction: column;
653 gap: 6px;
654 }
655
656 .os-content-graph__panel-actions[ hidden ] {
657 display: none;
658 }
659
660 .os-content-graph__panel-actions .os-content-graph__btn {
661 width: 100%;
662 justify-content: center;
663 }
664
665 .os-content-graph__btn--primary {
666 border-color: var( --os-ui-accent, #2c6be5 );
667 background: var( --os-ui-accent, #2c6be5 );
668 color: var( --os-ui-fg-on-accent, #fff );
669 }
670
671 .os-content-graph__btn--primary:hover {
672 background: var( --os-ui-accent-strong, #1f4ea8 );
673 border-color: var( --os-ui-accent-strong, #1f4ea8 );
674 }
675
676 .os-content-graph__panel-loading {
677 display: flex;
678 justify-content: center;
679 padding: 24px 0;
680 }
681
682 .os-content-graph__panel-loading[ hidden ] {
683 display: none;
684 }
685
686 .os-content-graph__panel-empty {
687 margin: 0;
688 font-size: 12px;
689 color: var( --os-ui-fg-muted, #6b7280 );
690 font-style: italic;
691 }
692
693 .os-content-graph__panel-empty[ hidden ] {
694 display: none;
695 }
696
697 /* ---------- Contextual detail views (user / term / comment) -------- */
698
699 .os-content-graph__panel-detail-section {
700 display: flex;
701 flex-direction: column;
702 gap: 4px;
703 }
704
705 .os-content-graph__panel-detail-head {
706 display: flex;
707 align-items: center;
708 gap: 12px;
709 }
710
711 .os-content-graph__panel-detail-avatar--lg {
712 width: 56px;
713 height: 56px;
714 border-radius: 50%;
715 flex-shrink: 0;
716 }
717
718 .os-content-graph__panel-detail-handle {
719 display: flex;
720 flex-direction: column;
721 gap: 2px;
722 min-width: 0;
723 }
724
725 .os-content-graph__panel-detail-handle strong {
726 font-size: 14px;
727 font-weight: 600;
728 overflow-wrap: anywhere;
729 }
730
731 .os-content-graph__panel-detail-handle span {
732 font-size: 11px;
733 color: var( --os-ui-fg-muted, #6b7280 );
734 overflow: hidden;
735 text-overflow: ellipsis;
736 white-space: nowrap;
737 }
738
739 .os-content-graph__panel-detail-prose {
740 margin: 0;
741 font-size: 13px;
742 line-height: 1.5;
743 color: var( --os-ui-fg, #1a1f2b );
744 }
745
746 .os-content-graph__panel-detail-link {
747 font-size: 12px;
748 color: var( --os-ui-accent, #2c6be5 );
749 text-decoration: none;
750 overflow: hidden;
751 text-overflow: ellipsis;
752 white-space: nowrap;
753 display: inline-block;
754 max-width: 100%;
755 }
756
757 .os-content-graph__panel-detail-link:hover {
758 text-decoration: underline;
759 }
760
761 .os-content-graph__panel-detail-html {
762 font-size: 13px;
763 line-height: 1.5;
764 color: var( --os-ui-fg, #1a1f2b );
765 background: var( --os-ui-surface, #f7f8fb );
766 border: 1px solid var( --os-ui-border, #eef0f4 );
767 border-radius: 6px;
768 padding: 10px 12px;
769 overflow-wrap: anywhere;
770 }
771
772 .os-content-graph__panel-detail-html p:first-child {
773 margin-top: 0;
774 }
775
776 .os-content-graph__panel-detail-html p:last-child {
777 margin-bottom: 0;
778 }
779
780 .os-content-graph__panel-detail-quote {
781 margin: 0;
782 padding: 10px 12px;
783 border-left: 3px solid var( --os-ui-border, #d8dde4 );
784 background: var( --os-ui-surface, #f7f8fb );
785 border-radius: 0 6px 6px 0;
786 display: flex;
787 flex-direction: column;
788 gap: 4px;
789 }
790
791 .os-content-graph__panel-detail-quote strong {
792 font-size: 12px;
793 font-weight: 600;
794 }
795
796 .os-content-graph__panel-detail-quote span {
797 font-size: 12px;
798 color: var( --os-ui-fg-muted, #4b5563 );
799 }
800
801 .os-content-graph__panel-detail-thumb {
802 display: flex;
803 justify-content: center;
804 background: var( --os-ui-surface, #f7f8fb );
805 border: 1px solid var( --os-ui-border, #eef0f4 );
806 border-radius: 8px;
807 padding: 8px;
808 max-height: 240px;
809 overflow: hidden;
810 }
811
812 .os-content-graph__panel-detail-thumb img {
813 max-width: 100%;
814 max-height: 220px;
815 object-fit: contain;
816 border-radius: 4px;
817 }
818
819 .os-content-graph__panel-badges {
820 display: flex;
821 flex-wrap: wrap;
822 gap: 4px;
823 }
824
825 .os-content-graph__panel-badge {
826 display: inline-flex;
827 align-items: center;
828 padding: 2px 8px;
829 font-size: 11px;
830 font-weight: 500;
831 border-radius: 999px;
832 background: var( --os-ui-surface, #f1f3f7 );
833 color: var( --os-ui-fg-muted, #4b5563 );
834 border: 1px solid var( --os-ui-border, #e2e6ec );
835 }
836
837 .os-content-graph__panel-badge--blue {
838 background: rgba( 44, 107, 229, 0.12 );
839 color: var( --os-ui-accent-strong, #1f4ea8 );
840 border-color: rgba( 44, 107, 229, 0.35 );
841 }
842
843 .os-content-graph__panel-badge--green {
844 background: rgba( 44, 169, 122, 0.14 );
845 color: #1f7754;
846 border-color: rgba( 44, 169, 122, 0.35 );
847 }
848
849 .os-content-graph__panel-badge--amber {
850 background: rgba( 232, 137, 58, 0.16 );
851 color: #8a5012;
852 border-color: rgba( 232, 137, 58, 0.35 );
853 }
854
855 .os-content-graph__panel-inline-meta {
856 display: flex;
857 flex-direction: column;
858 gap: 6px;
859 }
860
861 .os-content-graph__panel-inline-meta-row {
862 display: flex;
863 align-items: baseline;
864 gap: 8px;
865 }
866
867 .os-content-graph__panel-inline-meta-row .os-content-graph__panel-section-label {
868 flex: 0 0 auto;
869 margin-bottom: 0;
870 }
871
872 .os-content-graph__panel-chips {
873 display: flex;
874 flex-wrap: wrap;
875 gap: 4px;
876 margin: 0;
877 padding: 0;
878 list-style: none;
879 }
880
881 .os-content-graph__panel-chip {
882 display: inline-flex;
883 align-items: center;
884 gap: 6px;
885 padding: 3px 9px;
886 font-size: 12px;
887 border-radius: 999px;
888 background: var( --os-ui-surface, #f1f3f7 );
889 border: 1px solid var( --os-ui-border, #e2e6ec );
890 }
891
892 .os-content-graph__panel-chip-count {
893 font-variant-numeric: tabular-nums;
894 font-size: 11px;
895 color: var( --os-ui-fg-muted, #6b7280 );
896 }
897
898 .os-content-graph__panel-author-list {
899 display: flex;
900 flex-direction: column;
901 gap: 6px;
902 margin: 0;
903 padding: 0;
904 list-style: none;
905 }
906
907 .os-content-graph__panel-author-list-row {
908 display: flex;
909 align-items: center;
910 gap: 8px;
911 padding: 4px 0;
912 }
913
914 .os-content-graph__panel-author-list-row .os-content-graph__panel-avatar {
915 width: 24px;
916 height: 24px;
917 border-radius: 50%;
918 flex-shrink: 0;
919 }
920
921 .os-content-graph__panel-author-list-row .os-content-graph__panel-author-name {
922 flex: 1 1 auto;
923 font-size: 13px;
924 min-width: 0;
925 overflow: hidden;
926 text-overflow: ellipsis;
927 white-space: nowrap;
928 }
929
930 .os-content-graph__panel-milestones {
931 display: flex;
932 flex-direction: column;
933 gap: 6px;
934 }
935
936 .os-content-graph__panel-milestone-row {
937 display: flex;
938 justify-content: space-between;
939 gap: 8px;
940 }
941
942 .os-content-graph__panel-milestone-key {
943 font-size: 12px;
944 color: var( --os-ui-fg-muted, #6b7280 );
945 }
946
947 .os-content-graph__panel-replies {
948 display: flex;
949 flex-direction: column;
950 gap: 6px;
951 margin: 0;
952 padding: 0;
953 list-style: none;
954 }
955
956 .os-content-graph__panel-reply {
957 background: var( --os-ui-surface, #f7f8fb );
958 border: 1px solid var( --os-ui-border, #eef0f4 );
959 border-radius: 6px;
960 padding: 8px 10px;
961 }
962
963 .os-content-graph__panel-reply header {
964 display: flex;
965 align-items: baseline;
966 justify-content: space-between;
967 gap: 8px;
968 margin-bottom: 4px;
969 }
970
971 .os-content-graph__panel-reply header strong {
972 font-size: 12px;
973 }
974
975 .os-content-graph__panel-reply header span {
976 font-size: 11px;
977 color: var( --os-ui-fg-muted, #6b7280 );
978 }
979
980 .os-content-graph__panel-reply p {
981 margin: 0;
982 font-size: 12px;
983 line-height: 1.45;
984 color: var( --os-ui-fg-muted, #4b5563 );
985 }
986
987 .os-content-graph__panel-detail-loading {
988 display: flex;
989 align-items: center;
990 gap: 8px;
991 padding: 8px 0;
992 font-size: 12px;
993 color: var( --os-ui-fg-muted, #6b7280 );
994 }
995
996 .os-content-graph__panel-stat-row {
997 display: flex;
998 flex-direction: column;
999 gap: 2px;
1000 }
1001
1002 @media ( max-width: 760px ) {
1003 .os-content-graph__panel {
1004 position: absolute;
1005 inset: auto 0 0 0;
1006 width: 100%;
1007 max-height: 60%;
1008 border-left: 0;
1009 border-top: 1px solid var( --os-ui-border, #e2e6ec );
1010 box-shadow: 0 -8px 24px rgba( 17, 24, 39, 0.08 );
1011 z-index: 4;
1012 }
1013 }
1014
1015 /* ---------- Satellite tooltip -------------------------------------- */
1016
1017 .os-content-graph__tooltip {
1018 position: absolute;
1019 z-index: 5;
1020 display: flex;
1021 flex-direction: column;
1022 gap: 2px;
1023 max-width: 240px;
1024 padding: 6px 10px;
1025 background: var(
1026 --os-tooltip-bg,
1027 var( --os-ui-surface-elevated, #1a1f2b )
1028 );
1029 color: var(
1030 --os-tooltip-fg,
1031 var( --os-ui-fg-on-accent, #fff )
1032 );
1033 border-radius: 6px;
1034 box-shadow: 0 4px 14px rgba( 17, 24, 39, 0.18 );
1035 font-size: 12px;
1036 pointer-events: none;
1037 }
1038
1039 .os-content-graph__tooltip[ hidden ] {
1040 display: none;
1041 }
1042
1043 .os-content-graph__tooltip strong {
1044 font-weight: 600;
1045 overflow: hidden;
1046 text-overflow: ellipsis;
1047 white-space: nowrap;
1048 }
1049
1050 .os-content-graph__tooltip span {
1051 font-size: 11px;
1052 opacity: 0.85;
1053 overflow: hidden;
1054 text-overflow: ellipsis;
1055 white-space: nowrap;
1056 }
1057