web-mojo 2.1.46

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/LICENSE +198 -0
  2. package/README.md +510 -0
  3. package/dist/admin.cjs.js +2 -0
  4. package/dist/admin.cjs.js.map +1 -0
  5. package/dist/admin.css +621 -0
  6. package/dist/admin.es.js +7973 -0
  7. package/dist/admin.es.js.map +1 -0
  8. package/dist/auth.cjs.js +2 -0
  9. package/dist/auth.cjs.js.map +1 -0
  10. package/dist/auth.css +804 -0
  11. package/dist/auth.es.js +2168 -0
  12. package/dist/auth.es.js.map +1 -0
  13. package/dist/charts.cjs.js +2 -0
  14. package/dist/charts.cjs.js.map +1 -0
  15. package/dist/charts.css +1002 -0
  16. package/dist/charts.es.js +16 -0
  17. package/dist/charts.es.js.map +1 -0
  18. package/dist/chunks/ContextMenu-BrHqj0fn.js +80 -0
  19. package/dist/chunks/ContextMenu-BrHqj0fn.js.map +1 -0
  20. package/dist/chunks/ContextMenu-gEcpSz56.js +2 -0
  21. package/dist/chunks/ContextMenu-gEcpSz56.js.map +1 -0
  22. package/dist/chunks/DataView-DPryYpEW.js +2 -0
  23. package/dist/chunks/DataView-DPryYpEW.js.map +1 -0
  24. package/dist/chunks/DataView-DjZQrpba.js +843 -0
  25. package/dist/chunks/DataView-DjZQrpba.js.map +1 -0
  26. package/dist/chunks/Dialog-BsRx4eg3.js +2 -0
  27. package/dist/chunks/Dialog-BsRx4eg3.js.map +1 -0
  28. package/dist/chunks/Dialog-DSlctbon.js +1377 -0
  29. package/dist/chunks/Dialog-DSlctbon.js.map +1 -0
  30. package/dist/chunks/FilePreviewView-BmFHzK5K.js +5868 -0
  31. package/dist/chunks/FilePreviewView-BmFHzK5K.js.map +1 -0
  32. package/dist/chunks/FilePreviewView-DcdRl_ta.js +2 -0
  33. package/dist/chunks/FilePreviewView-DcdRl_ta.js.map +1 -0
  34. package/dist/chunks/FormView-CmBuwKGD.js +2 -0
  35. package/dist/chunks/FormView-CmBuwKGD.js.map +1 -0
  36. package/dist/chunks/FormView-DqUBMPJ9.js +5054 -0
  37. package/dist/chunks/FormView-DqUBMPJ9.js.map +1 -0
  38. package/dist/chunks/MetricsChart-CM4CI6eA.js +2095 -0
  39. package/dist/chunks/MetricsChart-CM4CI6eA.js.map +1 -0
  40. package/dist/chunks/MetricsChart-CPidSMaN.js +2 -0
  41. package/dist/chunks/MetricsChart-CPidSMaN.js.map +1 -0
  42. package/dist/chunks/PDFViewer-BNQlnS83.js +2 -0
  43. package/dist/chunks/PDFViewer-BNQlnS83.js.map +1 -0
  44. package/dist/chunks/PDFViewer-Dyo-Oeyd.js +946 -0
  45. package/dist/chunks/PDFViewer-Dyo-Oeyd.js.map +1 -0
  46. package/dist/chunks/Page-B524zSQs.js +351 -0
  47. package/dist/chunks/Page-B524zSQs.js.map +1 -0
  48. package/dist/chunks/Page-BFgj0pAA.js +2 -0
  49. package/dist/chunks/Page-BFgj0pAA.js.map +1 -0
  50. package/dist/chunks/TokenManager-BXNva8Jk.js +287 -0
  51. package/dist/chunks/TokenManager-BXNva8Jk.js.map +1 -0
  52. package/dist/chunks/TokenManager-Bzn4guFm.js +2 -0
  53. package/dist/chunks/TokenManager-Bzn4guFm.js.map +1 -0
  54. package/dist/chunks/TopNav-D3I3_25f.js +371 -0
  55. package/dist/chunks/TopNav-D3I3_25f.js.map +1 -0
  56. package/dist/chunks/TopNav-MDjL4kV0.js +2 -0
  57. package/dist/chunks/TopNav-MDjL4kV0.js.map +1 -0
  58. package/dist/chunks/User-BalfYTEF.js +3 -0
  59. package/dist/chunks/User-BalfYTEF.js.map +1 -0
  60. package/dist/chunks/User-DwIT-CTQ.js +1937 -0
  61. package/dist/chunks/User-DwIT-CTQ.js.map +1 -0
  62. package/dist/chunks/WebApp-B6mgbNn2.js +4767 -0
  63. package/dist/chunks/WebApp-B6mgbNn2.js.map +1 -0
  64. package/dist/chunks/WebApp-DqDowtkl.js +2 -0
  65. package/dist/chunks/WebApp-DqDowtkl.js.map +1 -0
  66. package/dist/chunks/WebSocketClient-D6i85jl2.js +2 -0
  67. package/dist/chunks/WebSocketClient-D6i85jl2.js.map +1 -0
  68. package/dist/chunks/WebSocketClient-Dvl3AYx1.js +297 -0
  69. package/dist/chunks/WebSocketClient-Dvl3AYx1.js.map +1 -0
  70. package/dist/core.css +1181 -0
  71. package/dist/css/web-mojo.css +17 -0
  72. package/dist/css-manifest.json +6 -0
  73. package/dist/docit.cjs.js +2 -0
  74. package/dist/docit.cjs.js.map +1 -0
  75. package/dist/docit.es.js +959 -0
  76. package/dist/docit.es.js.map +1 -0
  77. package/dist/index.cjs.js +2 -0
  78. package/dist/index.cjs.js.map +1 -0
  79. package/dist/index.es.js +2681 -0
  80. package/dist/index.es.js.map +1 -0
  81. package/dist/lightbox.cjs.js +2 -0
  82. package/dist/lightbox.cjs.js.map +1 -0
  83. package/dist/lightbox.css +606 -0
  84. package/dist/lightbox.es.js +3737 -0
  85. package/dist/lightbox.es.js.map +1 -0
  86. package/dist/loader.es.js +115 -0
  87. package/dist/loader.umd.js +85 -0
  88. package/dist/portal.css +2446 -0
  89. package/dist/table.css +639 -0
  90. package/dist/toast.css +181 -0
  91. package/package.json +179 -0
@@ -0,0 +1,2446 @@
1
+ /**
2
+ * MOJO Framework Portal Styles
3
+ * Portal layout, sidebar, topnav, and group selector components
4
+ * Version: 2.0.0
5
+ *
6
+ * Note: This file contains only custom MOJO styles.
7
+ * Bootstrap 5 is required as a dependency for base styles.
8
+ */
9
+
10
+ /* ========================================================================
11
+ SIDEBAR USAGE GUIDE
12
+ ========================================================================
13
+
14
+ The MOJO Portal Layout uses a single flexbox-based sidebar system.
15
+
16
+ HTML Structure:
17
+
18
+ <div class="portal-container">
19
+ <div class="portal-layout">
20
+ <div id="portal-sidebar">
21
+ <nav class="sidebar sidebar-light"> <!-- or sidebar-dark, sidebar-clean -->
22
+ <div class="sidebar-container">
23
+ <div class="sidebar-header">...</div>
24
+ <div class="sidebar-body">
25
+ <ul class="sidebar-nav">
26
+ <li class="nav-item">
27
+ <a class="nav-link" data-tooltip="Home">
28
+ <i class="bi-house me-2"></i>
29
+ <span class="nav-text">Home</span>
30
+ </a>
31
+ </li>
32
+ </ul>
33
+ </div>
34
+ <div class="sidebar-footer">...</div>
35
+ </div>
36
+ </nav>
37
+ </div>
38
+ <div class="portal-body">
39
+ <div id="portal-topnav">...</div>
40
+ <div class="portal-content">...</div>
41
+ </div>
42
+ </div>
43
+ </div>
44
+
45
+ Sidebar States:
46
+ - Default: Full width sidebar (250px)
47
+ - .collapse-sidebar: Collapsed to icon-only (64px) - nav-text hidden
48
+ - .hide-sidebar: Completely hidden (0px)
49
+ - .sidebar-open: Mobile overlay state
50
+
51
+ Group Selection:
52
+ - .group-selection-sidebar: Full sidebar dedicated to group selection
53
+ - .group-item: Individual group selection items
54
+ - .group-header: Current active group display in menus
55
+
56
+ Themes:
57
+ - .sidebar-light: Light theme
58
+ - .sidebar-dark: Dark theme
59
+ - .sidebar-clean: Clean minimal theme
60
+
61
+ Mobile Behavior:
62
+ - < 768px: Sidebar becomes fixed overlay
63
+ - Backdrop appears when open
64
+ - Always full width when visible
65
+
66
+ ======================================================================== */
67
+
68
+ /* ========================================================================
69
+ Portal Layout System (Custom MOJO Component)
70
+ ======================================================================== */
71
+
72
+ :root {
73
+ --mojo-sidebar-width: 250px;
74
+ --mojo-sidebar-collapsed-width: 40px;
75
+ --mojo-portal-gap: 0;
76
+ --mojo-portal-bg: var(--bs-body-bg);
77
+ --mojo-topnav-bg: var(--bs-primary, #121620);
78
+ --mojo-topnav-color: var(#fff);
79
+ --mojo-portal-muted: var(--bs-secondary-color);
80
+ --mojo-portal-border: var(--bs-border-color);
81
+ --mojo-portal-text: var(--bs-body-color);
82
+ --mojo-sidebar-dark-color: #fff;
83
+ --mojo-sidebar-dark-color-hover: #5388d6;
84
+ --mojo-sidebar-dark-bg: #343a40;
85
+ }
86
+
87
+ .portal-layout {
88
+ display: flex;
89
+ min-height: 100vh;
90
+ height: 100vh;
91
+ background: var(--mojo-portal-bg);
92
+ }
93
+
94
+ #portal-sidebar {
95
+ flex: 0 0 var(--mojo-sidebar-width);
96
+ max-width: var(--mojo-sidebar-width);
97
+ inline-size: var(--mojo-sidebar-width);
98
+ height: 100%;
99
+ overflow-y: hidden;
100
+ z-index: 1;
101
+ transition:
102
+ inline-size 300ms cubic-bezier(0.4, 0, 0.2, 1),
103
+ max-width 300ms cubic-bezier(0.4, 0, 0.2, 1),
104
+ flex-basis 300ms cubic-bezier(0.4, 0, 0.2, 1),
105
+ margin-left 300ms cubic-bezier(0.4, 0, 0.2, 1),
106
+ transform 300ms cubic-bezier(0.4, 0, 0.2, 1);
107
+ will-change: inline-size, max-width, flex-basis, transform;
108
+ }
109
+
110
+ .portal-container.collapse-sidebar #portal-sidebar {
111
+ inline-size: var(--mojo-sidebar-collapsed-width);
112
+ max-width: var(--mojo-sidebar-collapsed-width);
113
+ flex-basis: var(--mojo-sidebar-collapsed-width);
114
+ }
115
+
116
+ .portal-container.hide-sidebar #portal-sidebar {
117
+ margin-left: calc(-1 * var(--mojo-sidebar-width));
118
+ border-inline-end: 0;
119
+ }
120
+
121
+ .portal-body {
122
+ flex: 1 1 auto;
123
+ min-width: 0;
124
+ min-height: 0;
125
+ display: flex;
126
+ flex-direction: column;
127
+ overflow: hidden;
128
+ }
129
+
130
+ #portal-topnav {
131
+ flex: 0 0 auto;
132
+ background: var(--mojo-topnav-bg);
133
+ color: var(--mojo-topnav-color);
134
+ border-block-end: 1px solid var(--mojo-portal-border);
135
+ }
136
+
137
+ .portal-content {
138
+ flex: 1 1 auto;
139
+ min-height: 0;
140
+ overflow-y: auto;
141
+ overflow-x: hidden;
142
+ padding: 16px;
143
+ height: 100%;
144
+ }
145
+
146
+ .portal-content .muted {
147
+ color: var(--mojo-portal-muted);
148
+ }
149
+
150
+ @media (prefers-reduced-motion: reduce) {
151
+ #portal-sidebar {
152
+ transition: none;
153
+ }
154
+ }
155
+
156
+ /* ========================================================================
157
+ MOJO Custom Sidebar Component
158
+ ======================================================================== */
159
+
160
+ /* Standalone sidebar (when not in portal layout) */
161
+ .sidebar {
162
+ display: flex;
163
+ flex-direction: column;
164
+ height: 100%;
165
+ width: 100%;
166
+ min-height: 0;
167
+ transition: all 300ms cubic-bezier(0.4, 0, 0.2, 1);
168
+ }
169
+
170
+ /* Portal-integrated sidebar (inside #portal-sidebar) */
171
+ #portal-sidebar .sidebar {
172
+ position: static;
173
+ top: auto;
174
+ left: auto;
175
+ height: 100%;
176
+ width: 100%;
177
+ z-index: auto;
178
+ transform: none;
179
+ }
180
+
181
+ /* Custom Sidebar Themes */
182
+ .sidebar-dark {
183
+ background-color: var(--mojo-sidebar-dark-bg, --bs-dark);
184
+ color: var(--bs-light);
185
+ border-inline-end: 1px solid var(--bs-border-color-translucent);
186
+ }
187
+
188
+ .sidebar-light {
189
+ background-color: var(--bs-light);
190
+ color: var(--bs-body-color);
191
+ border-right: 1px solid var(--bs-border-color);
192
+ }
193
+
194
+ .sidebar-clean {
195
+ background-color: var(--bs-body-bg);
196
+ color: var(--bs-body-color);
197
+ border-right: 1px solid var(--bs-border-color);
198
+ box-shadow: var(--bs-box-shadow);
199
+ }
200
+
201
+ .sidebar-container {
202
+ display: flex;
203
+ flex-direction: column;
204
+ height: 100%;
205
+ min-height: 0;
206
+ flex: 1;
207
+ }
208
+
209
+ .sidebar-body {
210
+ flex: 1;
211
+ overflow-y: auto;
212
+ min-height: 0;
213
+ }
214
+
215
+ .sidebar-brand {
216
+ height: 56px;
217
+ text-align: center;
218
+ padding-top: 14px;
219
+ }
220
+
221
+ .sidebar-dark .sidebar-brand {
222
+ border-bottom: 1px solid var(--bs-border-color-translucent);
223
+ }
224
+
225
+ .sidebar-light .sidebar-brand {
226
+ border-bottom: 1px solid var(--bs-border-color);
227
+ }
228
+
229
+ .sidebar-clean .sidebar-brand {
230
+ border-bottom: 1px solid var(--bs-border-color);
231
+ background-color: var(--bs-secondary-bg);
232
+ }
233
+
234
+ .sidebar-brand.clickable {
235
+ cursor: pointer;
236
+ transition: background-color 0.2s ease;
237
+ }
238
+
239
+ .sidebar-brand.clickable:hover {
240
+ background-color: rgba(255, 255, 255, 0.1);
241
+ }
242
+
243
+ /* ========================================================================
244
+ Sidebar Toggle Button
245
+ ======================================================================== */
246
+
247
+ .sidebar-toggle {
248
+ position: absolute;
249
+ width: 30px;
250
+ height: 30px;
251
+ font-size: 0.875rem;
252
+ border: none;
253
+ background: none;
254
+ top: 0.75rem;
255
+ right: 5px;
256
+ border: none;
257
+ border-radius: var(--bs-border-radius);
258
+ color: var(--bs-body-color);
259
+ cursor: pointer;
260
+ display: flex;
261
+ align-items: center;
262
+ justify-content: center;
263
+ transition:
264
+ all 300ms cubic-bezier(0.4, 0, 0.2, 1),
265
+ transform 150ms ease-out;
266
+ backdrop-filter: blur(4px);
267
+ z-index: 10;
268
+ }
269
+
270
+ .sidebar-toggle:hover {
271
+ background: var(--bs-secondary-bg);
272
+ transform: scale(1.1);
273
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
274
+ }
275
+
276
+ .sidebar-toggle:active {
277
+ transform: scale(0.95);
278
+ transition-duration: 100ms;
279
+ }
280
+
281
+ /* Toggle button icons */
282
+ .sidebar-toggle .toggle-icon {
283
+ transition: all 300ms cubic-bezier(0.4, 0, 0.2, 1);
284
+ }
285
+
286
+ .sidebar-toggle .bi-chevron-left {
287
+ display: block;
288
+ }
289
+
290
+ .sidebar-toggle .bi-chevron-right {
291
+ display: none;
292
+ }
293
+
294
+ /* Collapsed state - swap icons */
295
+ .portal-container.collapse-sidebar .sidebar-toggle .bi-chevron-left {
296
+ display: none;
297
+ }
298
+
299
+ .portal-container.collapse-sidebar .sidebar-toggle .bi-chevron-right {
300
+ display: block;
301
+ }
302
+
303
+ /* Hidden state - show expand icon */
304
+ .portal-container.hide-sidebar .sidebar-toggle {
305
+ opacity: 0;
306
+ visibility: hidden;
307
+ pointer-events: none;
308
+ }
309
+
310
+ /* Theme-specific toggle button styles */
311
+ .sidebar-dark .sidebar-toggle {
312
+ background: var(--bs-border-color-translucent);
313
+ color: var(--bs-secondary-color);
314
+ border-color: var(--bs-border-color-translucent);
315
+ }
316
+
317
+ .sidebar-dark .sidebar-toggle:hover {
318
+ background: var(--bs-secondary-bg);
319
+ color: var(--bs-light);
320
+ }
321
+
322
+ .sidebar-light .sidebar-toggle {
323
+ background: var(--bs-secondary-bg);
324
+ color: var(--bs-body-color);
325
+ border-color: var(--bs-border-color);
326
+ }
327
+
328
+ .sidebar-light .sidebar-toggle:hover {
329
+ background: var(--bs-tertiary-bg);
330
+ color: var(--bs-emphasis-color);
331
+ }
332
+
333
+ .sidebar-clean .sidebar-toggle {
334
+ background: var(--bs-light);
335
+ color: var(--bs-primary);
336
+ border-color: var(--bs-primary-border-subtle);
337
+ box-shadow: var(--bs-box-shadow-sm);
338
+ }
339
+
340
+ .sidebar-clean .sidebar-toggle:hover {
341
+ background: var(--bs-primary);
342
+ color: white;
343
+ box-shadow: 0 4px 12px rgba(var(--bs-primary-rgb), 0.3);
344
+ }
345
+
346
+ /* Toggle button animation when sidebar state changes */
347
+ .sidebar-toggle .toggle-icon {
348
+ transform: rotate(0deg);
349
+ }
350
+
351
+ /*.portal-container.collapse-sidebar .sidebar-toggle .toggle-icon {
352
+ transform: rotate(180deg);
353
+ }*/
354
+
355
+ /* ========================================================================
356
+ TopNav Sidebar Toggle Button
357
+ ======================================================================== */
358
+
359
+ .topnav-sidebar-toggle {
360
+ background: none !important;
361
+ border: none !important;
362
+ color: rgba(255, 255, 255, 0.9);
363
+ padding: 0.5rem;
364
+ border-radius: 0.375rem;
365
+ cursor: pointer;
366
+ transition: all 0.2s ease;
367
+ display: flex;
368
+ align-items: center;
369
+ justify-content: center;
370
+ }
371
+
372
+ .topnav-sidebar-toggle:hover {
373
+ background: none !important;
374
+ color: var(--bs-light);
375
+ transform: scale(1.1);
376
+ }
377
+
378
+ .topnav-sidebar-toggle:focus {
379
+ outline: none;
380
+ box-shadow: none;
381
+ }
382
+
383
+ .topnav-sidebar-toggle .toggle-chevron {
384
+ font-size: 1.1rem;
385
+ transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
386
+ transform: rotate(180deg); /* Default: points left (expanded state) */
387
+ }
388
+
389
+ /* Collapsed/Hidden state - chevron points right */
390
+ .portal-container.collapse-sidebar .topnav-sidebar-toggle .toggle-chevron,
391
+ .portal-container.hide-sidebar .topnav-sidebar-toggle .toggle-chevron {
392
+ transform: rotate(0deg);
393
+ }
394
+
395
+ /* Theme-specific styles */
396
+ .navbar-dark .topnav-sidebar-toggle {
397
+ color: #ccc;
398
+ }
399
+
400
+ .navbar-dark .topnav-sidebar-toggle:hover {
401
+ color: #fff;
402
+ background: none !important;
403
+ }
404
+
405
+ .navbar-light .topnav-sidebar-toggle {
406
+ color: var(--bs-navbar-light-color);
407
+ }
408
+
409
+ .navbar-light .topnav-sidebar-toggle:hover {
410
+ color: var(--bs-navbar-light-hover-color);
411
+ background: var(--bs-secondary-bg) !important;
412
+ }
413
+
414
+ /* Pulse animation for better discoverability */
415
+ @keyframes sidebar-toggle-pulse {
416
+ 0% {
417
+ box-shadow: 0 0 0 0 rgba(var(--bs-primary-rgb), 0.4);
418
+ }
419
+ 70% {
420
+ box-shadow: 0 0 0 8px rgba(var(--bs-primary-rgb), 0);
421
+ }
422
+ 100% {
423
+ box-shadow: 0 0 0 0 rgba(var(--bs-primary-rgb), 0);
424
+ }
425
+ }
426
+
427
+ /* Show pulse animation on first load or when sidebar is collapsed for a while */
428
+ .sidebar-toggle.pulse {
429
+ animation: sidebar-toggle-pulse 2s infinite;
430
+ }
431
+
432
+ /* Toggle button focus states */
433
+ .sidebar-toggle:focus {
434
+ outline: none;
435
+ box-shadow: 0 0 0 0.25rem rgba(var(--bs-primary-rgb), 0.25);
436
+ }
437
+
438
+ .sidebar-toggle:focus-visible {
439
+ outline: 2px solid var(--bs-primary);
440
+ outline-offset: 2px;
441
+ }
442
+
443
+ /* Collapsed sidebar toggle positioning */
444
+ /*.portal-container.collapse-sidebar .sidebar-toggle {
445
+ right: 0.5rem;
446
+ width: 2rem;
447
+ height: 2rem;
448
+ font-size: 0.875rem;
449
+ }*/
450
+
451
+ /* Dark theme toggle button */
452
+ [data-bs-theme="dark"] .sidebar-toggle {
453
+ background: rgba(255, 255, 255, 0.1);
454
+ color: var(--bs-light);
455
+ border-color: rgba(255, 255, 255, 0.15);
456
+ }
457
+
458
+ [data-bs-theme="dark"] .sidebar-toggle:hover {
459
+ background: rgba(255, 255, 255, 0.2);
460
+ color: var(--bs-white);
461
+ box-shadow: 0 4px 12px rgba(255, 255, 255, 0.1);
462
+ }
463
+
464
+ [data-bs-theme="dark"] .sidebar-clean .sidebar-toggle {
465
+ background: var(--bs-primary);
466
+ color: white;
467
+ border-color: var(--bs-primary);
468
+ }
469
+
470
+ [data-bs-theme="dark"] .sidebar-clean .sidebar-toggle:hover {
471
+ background: var(--bs-primary);
472
+ filter: brightness(1.1);
473
+ }
474
+
475
+ .brand-content {
476
+ display: flex;
477
+ flex-direction: column;
478
+ align-items: center;
479
+ }
480
+
481
+ .brand-logo {
482
+ max-height: 32px;
483
+ width: auto;
484
+ margin-bottom: 0.5rem;
485
+ }
486
+
487
+ .brand-subtext {
488
+ font-size: 0.75rem;
489
+ }
490
+
491
+ .sidebar-group-header {
492
+ cursor: pointer;
493
+ border-bottom: 1px solid rgba(0, 0, 0, 0.1);
494
+ }
495
+
496
+ .sidebar-group-header:hover {
497
+ cursor: pointer;
498
+ color: var(--mojo-primary);
499
+ background-color: rgba(20, 20, 100, 0.1);
500
+ }
501
+
502
+ /* Custom Navigation Styles */
503
+ .sidebar-nav {
504
+ display: flex;
505
+ flex-direction: column;
506
+ padding: 0.5rem 0;
507
+ min-height: 100%;
508
+ }
509
+
510
+ .sidebar-nav .nav-link {
511
+ display: flex;
512
+ align-items: center;
513
+ position: relative;
514
+ padding: 0.75rem 1rem;
515
+ text-decoration: none;
516
+ border-radius: 0;
517
+ transition:
518
+ all 300ms cubic-bezier(0.4, 0, 0.2, 1),
519
+ transform 150ms ease-out;
520
+ cursor: pointer;
521
+ transform: translateX(0);
522
+ }
523
+
524
+ .sidebar-nav .nav-link:hover {
525
+ /*transform: translateX(2px);*/
526
+ margin-left: 0.4rem !important;
527
+ }
528
+
529
+ .sidebar-nav .nav-link i {
530
+ width: 20px;
531
+ text-align: center;
532
+ transition:
533
+ transform 200ms ease-out,
534
+ color 200ms ease-out;
535
+ }
536
+
537
+ .sidebar-nav .nav-link:hover i {
538
+ transform: scale(1.1);
539
+ }
540
+
541
+ .portal-container.collapse-sidebar .sidebar-nav .nav-link:hover i {
542
+ transform: scale(1.2);
543
+ }
544
+
545
+ .sidebar-nav .collapse .nav-link {
546
+ padding: 0.5rem 1rem;
547
+ font-size: 0.9rem;
548
+ }
549
+
550
+ .sidebar-nav .bi-chevron-down {
551
+ transition: transform 0.3s;
552
+ }
553
+
554
+ .sidebar-nav .nav-link[aria-expanded="true"] .bi-chevron-down {
555
+ transform: rotate(180deg);
556
+ }
557
+
558
+ /* Theme-specific navigation styles */
559
+ .sidebar-dark .sidebar-nav .nav-link {
560
+ color: var(--mojo-sidebar-dark-color, #fff);
561
+ }
562
+
563
+ .sidebar-dark .sidebar-nav .nav-link:hover {
564
+ color: var(--mojo-sidebar-dark-color-hover, #5388d6);
565
+ background-color: var(--bs-secondary-bg);
566
+ }
567
+
568
+ .sidebar-dark .sidebar-nav .nav-link.active {
569
+ color: var(--bs-light);
570
+ background-color: var(--bs-primary);
571
+ }
572
+
573
+ .sidebar-light .sidebar-nav .nav-link {
574
+ color: var(--bs-body-color);
575
+ border-top-left-radius: 8px;
576
+ border-bottom-left-radius: 8px;
577
+ margin-left: 0.2rem;
578
+ }
579
+
580
+ .sidebar-light .sidebar-nav .nav-link:hover {
581
+ color: var(--bs-emphasis-color);
582
+ background-color: var(--bs-secondary-bg);
583
+ }
584
+
585
+ .sidebar-light .sidebar-nav .nav-link.active {
586
+ color: var(--bs-light);
587
+ background-color: var(--bs-primary);
588
+ }
589
+
590
+ .sidebar-light .nav-link.has-children {
591
+ border-top-left-radius: 0;
592
+ border-bottom-left-radius: 0;
593
+ }
594
+
595
+ .sidebar-nav .nav-link.has-children:hover {
596
+ transform: none;
597
+ }
598
+
599
+ .sidebar-light .nav-link.has-children.collapsed {
600
+ border-left: none;
601
+ }
602
+
603
+ .sidebar-light .nav-link.active.has-children {
604
+ color: var(--bs-body-color);
605
+ background-color: var(--bs-secondary-bg);
606
+ animation: none;
607
+ }
608
+
609
+ .sidebar-clean .sidebar-nav .nav-link {
610
+ color: var(--bs-secondary-color);
611
+ margin: 0.125rem 0.5rem;
612
+ border-radius: var(--bs-border-radius);
613
+ }
614
+
615
+ .sidebar-clean .sidebar-nav .nav-link:hover {
616
+ color: var(--bs-body-color);
617
+ background-color: var(--bs-secondary-bg);
618
+ }
619
+
620
+ .sidebar-clean .sidebar-nav .nav-link.active {
621
+ color: var(--bs-primary);
622
+ background-color: var(--bs-primary-bg-subtle);
623
+ font-weight: 500;
624
+ }
625
+
626
+ .nav-text {
627
+ flex: 1;
628
+ white-space: nowrap;
629
+ transition:
630
+ opacity 300ms cubic-bezier(0.4, 0, 0.2, 1),
631
+ width 300ms cubic-bezier(0.4, 0, 0.2, 1),
632
+ margin 300ms cubic-bezier(0.4, 0, 0.2, 1);
633
+ }
634
+
635
+ .nav-arrow {
636
+ transition:
637
+ transform 200ms ease,
638
+ opacity 300ms cubic-bezier(0.4, 0, 0.2, 1),
639
+ margin 300ms cubic-bezier(0.4, 0, 0.2, 1);
640
+ margin-left: auto;
641
+ }
642
+
643
+ .nav-link[aria-expanded="true"] .nav-arrow {
644
+ transform: rotate(180deg);
645
+ }
646
+
647
+ /* Collapsed sidebar behavior */
648
+ .portal-container.collapse-sidebar .nav-text,
649
+ .portal-container.collapse-sidebar .sidebar-collapse-hide {
650
+ opacity: 0;
651
+ width: 0;
652
+ margin-right: 0;
653
+ overflow: hidden;
654
+ }
655
+
656
+ .portal-container.collapse-sidebar .nav-arrow {
657
+ opacity: 0;
658
+ margin-left: 0;
659
+ }
660
+
661
+ .portal-container.collapse-sidebar .sidebar-nav .nav-link {
662
+ justify-content: center;
663
+ padding-left: 0.5rem;
664
+ padding-right: 0.5rem;
665
+ transition: all 300ms cubic-bezier(0.4, 0, 0.2, 1);
666
+ }
667
+
668
+ .portal-container.collapse-sidebar .sidebar-nav .nav-link i {
669
+ margin-right: 0 !important;
670
+ }
671
+
672
+ .portal-container.collapse-sidebar .nav-submenu {
673
+ display: none !important;
674
+ }
675
+
676
+ .portal-container.collapse-sidebar .sidebar-header {
677
+ text-align: center;
678
+ overflow: hidden;
679
+ }
680
+
681
+ .portal-container.collapse-sidebar .sidebar-header .fs-5 {
682
+ opacity: 0;
683
+ transition:
684
+ opacity 300ms cubic-bezier(0.4, 0, 0.2, 1),
685
+ transform 300ms cubic-bezier(0.4, 0, 0.2, 1);
686
+ transform: scale(0.8) translateY(-5px);
687
+ }
688
+
689
+ .portal-container.collapse-sidebar .sidebar-footer {
690
+ opacity: 0;
691
+ transition:
692
+ opacity 300ms cubic-bezier(0.4, 0, 0.2, 1),
693
+ transform 300ms cubic-bezier(0.4, 0, 0.2, 1);
694
+ transform: scale(0.8) translateY(5px);
695
+ }
696
+
697
+ /* ========================================================================
698
+ Enhanced Tooltip System for Collapsed Sidebar
699
+ ======================================================================== */
700
+
701
+ .portal-container.collapse-sidebar .sidebar .nav-link {
702
+ position: relative;
703
+ overflow: visible;
704
+ width: var(--mojo-sidebar-collapsed-width, 48px);
705
+ }
706
+
707
+ /* CSS tooltips disabled - using Bootstrap tooltips instead
708
+ .portal-container.collapse-sidebar .sidebar .nav-link[data-tooltip]:hover::after {
709
+ content: attr(data-tooltip);
710
+ position: absolute;
711
+ left: calc(100% + 12px);
712
+ top: 50%;
713
+ transform: translateY(-50%) translateX(-5px);
714
+ background: var(--bs-dark);
715
+ color: var(--bs-white);
716
+ padding: 0.75rem 1rem;
717
+ border-radius: 0.5rem;
718
+ white-space: nowrap;
719
+ font-size: 0.875rem;
720
+ font-weight: 500;
721
+ line-height: 1.2;
722
+ z-index: var(--mojo-zindex-tooltip);
723
+ box-shadow:
724
+ 0 4px 12px rgba(0, 0, 0, 0.15),
725
+ 0 2px 4px rgba(0, 0, 0, 0.1);
726
+ opacity: 0;
727
+ visibility: hidden;
728
+ transition:
729
+ opacity 200ms cubic-bezier(0.4, 0, 0.2, 1),
730
+ visibility 200ms cubic-bezier(0.4, 0, 0.2, 1),
731
+ transform 200ms cubic-bezier(0.4, 0, 0.2, 1);
732
+ animation: tooltip-slide-in 250ms cubic-bezier(0.4, 0, 0.2, 1) forwards;
733
+ animation-delay: 800ms;
734
+ pointer-events: none;
735
+ }
736
+
737
+ .portal-container.collapse-sidebar .sidebar .nav-link[data-tooltip]:hover::before {
738
+ content: "";
739
+ position: absolute;
740
+ left: calc(100% + 6px);
741
+ top: 50%;
742
+ transform: translateY(-50%);
743
+ width: 0;
744
+ height: 0;
745
+ border-style: solid;
746
+ border-width: 6px 6px 6px 0;
747
+ border-color: transparent var(--bs-dark) transparent transparent;
748
+ z-index: calc(var(--mojo-zindex-tooltip) + 1);
749
+ opacity: 0;
750
+ animation: tooltip-arrow-slide-in 250ms cubic-bezier(0.4, 0, 0.2, 1) forwards;
751
+ animation-delay: 300ms;
752
+ }
753
+
754
+ .portal-container.collapse-sidebar .sidebar .nav-link:not([data-tooltip]):hover::after {
755
+ content: attr(data-nav-text);
756
+ position: absolute;
757
+ left: calc(100% + 12px);
758
+ top: 50%;
759
+ transform: translateY(-50%) translateX(-5px);
760
+ background: var(--bs-dark);
761
+ color: var(--bs-white);
762
+ padding: 0.75rem 1rem;
763
+ border-radius: 0.5rem;
764
+ white-space: nowrap;
765
+ font-size: 0.875rem;
766
+ font-weight: 500;
767
+ line-height: 1.2;
768
+ z-index: var(--mojo-zindex-tooltip);
769
+ box-shadow:
770
+ 0 4px 12px rgba(0, 0, 0, 0.15),
771
+ 0 2px 4px rgba(0, 0, 0, 0.1);
772
+ opacity: 0;
773
+ visibility: hidden;
774
+ animation: tooltip-slide-in 250ms cubic-bezier(0.4, 0, 0.2, 1) forwards;
775
+ animation-delay: 300ms;
776
+ pointer-events: none;
777
+ }
778
+
779
+ .portal-container.collapse-sidebar .sidebar .nav-link:not([data-tooltip]):hover::before {
780
+ content: "";
781
+ position: absolute;
782
+ left: calc(100% + 6px);
783
+ top: 50%;
784
+ transform: translateY(-50%);
785
+ width: 0;
786
+ height: 0;
787
+ border-style: solid;
788
+ border-width: 6px 6px 6px 0;
789
+ border-color: transparent var(--bs-dark) transparent transparent;
790
+ z-index: calc(var(--mojo-zindex-tooltip) + 1);
791
+ opacity: 0;
792
+ animation: tooltip-arrow-slide-in 250ms cubic-bezier(0.4, 0, 0.2, 1) forwards;
793
+ animation-delay: 300ms;
794
+ }
795
+
796
+ .portal-container.collapse-sidebar .sidebar-light .nav-link:hover::after {
797
+ background: #2c3e50;
798
+ color: white;
799
+ }
800
+
801
+ .portal-container.collapse-sidebar .sidebar-light .nav-link:hover::before {
802
+ border-right-color: #2c3e50;
803
+ }
804
+
805
+ .portal-container.collapse-sidebar .sidebar-dark .nav-link:hover::after {
806
+ background: #34495e;
807
+ color: #ecf0f1;
808
+ }
809
+
810
+ .portal-container.collapse-sidebar .sidebar-dark .nav-link:hover::before {
811
+ border-right-color: #34495e;
812
+ }
813
+
814
+ .portal-container.collapse-sidebar .sidebar-clean .nav-link:hover::after {
815
+ background: var(--bs-primary);
816
+ color: white;
817
+ box-shadow:
818
+ 0 4px 12px rgba(var(--bs-primary-rgb), 0.3),
819
+ 0 2px 4px rgba(var(--bs-primary-rgb), 0.2);
820
+ }
821
+
822
+ .portal-container.collapse-sidebar .sidebar-clean .nav-link:hover::before {
823
+ border-right-color: var(--bs-primary);
824
+ }
825
+
826
+ /* Tooltip animations */
827
+ @keyframes tooltip-slide-in {
828
+ 0% {
829
+ opacity: 0;
830
+ visibility: hidden;
831
+ transform: translateY(-50%) translateX(-10px) scale(0.9);
832
+ }
833
+ 100% {
834
+ opacity: 1;
835
+ visibility: visible;
836
+ transform: translateY(-50%) translateX(0) scale(1);
837
+ }
838
+ }
839
+
840
+ @keyframes tooltip-arrow-slide-in {
841
+ 0% {
842
+ opacity: 0;
843
+ transform: translateY(-50%) translateX(-3px);
844
+ }
845
+ 100% {
846
+ opacity: 1;
847
+ transform: translateY(-50%) translateX(0);
848
+ }
849
+ }
850
+
851
+ /* Dark theme tooltips */
852
+ [data-bs-theme="dark"] .portal-container.collapse-sidebar .sidebar .nav-link:hover::after {
853
+ background: var(--bs-light);
854
+ color: var(--bs-dark);
855
+ }
856
+
857
+ [data-bs-theme="dark"] .portal-container.collapse-sidebar .sidebar .nav-link:hover::before {
858
+ border-right-color: var(--bs-light);
859
+ }
860
+
861
+ /* Mobile layout: hide tooltips */
862
+ .portal-container.mobile-layout .nav-link:hover::after,
863
+ .portal-container.mobile-layout .nav-link:hover::before {
864
+ display: none !important;
865
+ }
866
+
867
+ /* ========================================================================
868
+ TOOLTIP USAGE GUIDE
869
+ ========================================================================
870
+
871
+ Option 1: Manual Tooltips (Recommended)
872
+ Add data-tooltip attributes to your nav links:
873
+
874
+ <a class="nav-link" data-tooltip="Dashboard">
875
+ <i class="bi-speedometer2 me-2"></i>
876
+ <span class="nav-text">Dashboard</span>
877
+ </a>
878
+
879
+ Option 2: Auto-Tooltips with JavaScript
880
+ Use this script to automatically generate tooltips from nav-text:
881
+
882
+ // Auto-generate tooltips from nav-text content
883
+ document.querySelectorAll('.sidebar-nav .nav-link').forEach(link => {
884
+ const navText = link.querySelector('.nav-text');
885
+ if (navText && !link.hasAttribute('data-tooltip')) {
886
+ link.setAttribute('data-nav-text', navText.textContent.trim());
887
+ }
888
+ });
889
+
890
+ // Or set data-tooltip directly for better control
891
+ document.querySelectorAll('.sidebar-nav .nav-link').forEach(link => {
892
+ const navText = link.querySelector('.nav-text');
893
+ if (navText && !link.hasAttribute('data-tooltip')) {
894
+ link.setAttribute('data-tooltip', navText.textContent.trim());
895
+ }
896
+ });
897
+
898
+ SIDEBAR TOGGLE BUTTON USAGE:
899
+ Add the toggle button to your sidebar header:
900
+
901
+ <div class="sidebar-header">
902
+ <div class="fs-5 fw-bold text-center pt-3">Main Menu</div>
903
+ <button class="sidebar-toggle" data-action="toggle-sidebar"
904
+ aria-label="Toggle Sidebar">
905
+ <i class="bi bi-chevron-left toggle-icon"></i>
906
+ <i class="bi bi-chevron-right toggle-icon"></i>
907
+ </button>
908
+ </div>
909
+
910
+ JavaScript to handle toggle:
911
+ document.querySelector('.sidebar-toggle').addEventListener('click', () => {
912
+ document.querySelector('.portal-container').classList.toggle('collapse-sidebar');
913
+ });
914
+
915
+ ======================================================================== */
916
+
917
+ /* Enhanced visual feedback for collapsed sidebar */
918
+ .portal-container.collapse-sidebar .sidebar .nav-link:hover {
919
+ background-color: rgba(var(--bs-primary-rgb), 0.1);
920
+ border-radius: var(--mojo-border-radius);
921
+ transform: translateX(0) scale(1.05);
922
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
923
+ }
924
+
925
+ .portal-container.collapse-sidebar .sidebar-light .nav-link:hover {
926
+ background-color: rgba(var(--bs-primary-rgb), 0.08);
927
+ box-shadow: 0 2px 8px rgba(var(--bs-primary-rgb), 0.2);
928
+ }
929
+
930
+ .portal-container.collapse-sidebar .sidebar-dark .nav-link:hover {
931
+ background-color: rgba(255, 255, 255, 0.1);
932
+ box-shadow: 0 2px 8px rgba(255, 255, 255, 0.1);
933
+ }
934
+
935
+ .portal-container.collapse-sidebar .sidebar-clean .nav-link:hover {
936
+ background-color: var(--bs-light);
937
+ box-shadow: 0 2px 8px rgba(var(--bs-primary-rgb), 0.15);
938
+ }
939
+
940
+ /* Navigation submenu */
941
+ .nav-submenu .nav-link {
942
+ padding-left: 2.5rem;
943
+ font-size: 0.9rem;
944
+ }
945
+
946
+ .sidebar-dark .nav-submenu {
947
+ background-color: rgba(0, 0, 0, 0.2);
948
+ }
949
+
950
+ .sidebar-light .nav-submenu {
951
+ margin-left: 1.8rem;
952
+ border-left: 4px solid #cdcdcd;
953
+ }
954
+
955
+ .sidebar-clean .nav-submenu {
956
+ background-color: transparent;
957
+ }
958
+
959
+ .sidebar-clean .nav-submenu .nav-link {
960
+ margin-left: 1rem;
961
+ margin-right: 0.5rem;
962
+ }
963
+
964
+ /* Navigation dividers */
965
+ .nav-divider {
966
+ margin: 0.75rem 0;
967
+ padding: 0 1rem;
968
+ }
969
+
970
+ .nav-divider-label {
971
+ font-size: 0.75rem;
972
+ font-weight: 600;
973
+ text-transform: uppercase;
974
+ letter-spacing: 0.05em;
975
+ padding: 0.25rem 0;
976
+ display: block;
977
+ }
978
+
979
+ .sidebar-dark .nav-divider-label {
980
+ color: var(--bs-secondary-color);
981
+ border-bottom: 1px solid var(--bs-border-color-translucent);
982
+ }
983
+
984
+ .sidebar-light .nav-divider-label {
985
+ color: var(--bs-secondary-color);
986
+ border-bottom: 1px solid var(--bs-border-color);
987
+ }
988
+
989
+ .sidebar-clean .nav-divider-label {
990
+ color: var(--bs-secondary-color);
991
+ border-bottom: 1px solid var(--bs-border-color);
992
+ margin: 0 0.5rem;
993
+ }
994
+
995
+ .nav-divider-item {
996
+ margin: 0.25rem 0;
997
+ padding: 0;
998
+ list-style: none;
999
+ }
1000
+
1001
+ .nav-divider-line {
1002
+ margin: 0 1rem;
1003
+ border: 0;
1004
+ border-top: 1px solid;
1005
+ opacity: 0.25;
1006
+ }
1007
+
1008
+ .sidebar-dark .nav-divider-line {
1009
+ border-color: var(--bs-secondary-color);
1010
+ }
1011
+
1012
+ .sidebar-light .nav-divider-line {
1013
+ border-color: var(--bs-secondary-color);
1014
+ }
1015
+
1016
+ .sidebar-clean .nav-divider-line {
1017
+ border-color: var(--bs-border-color);
1018
+ margin: 0 1.5rem;
1019
+ }
1020
+
1021
+ .nav-spacer-item {
1022
+ flex: 1;
1023
+ list-style: none;
1024
+ }
1025
+
1026
+ /* Navigation sections */
1027
+ .nav-section {
1028
+ margin-bottom: 0.5rem;
1029
+ }
1030
+
1031
+ .nav-section-header {
1032
+ padding: 0.5rem 1rem;
1033
+ font-size: 0.8rem;
1034
+ font-weight: 600;
1035
+ text-transform: uppercase;
1036
+ letter-spacing: 0.05em;
1037
+ }
1038
+
1039
+ .nav-section-header.collapsible {
1040
+ cursor: pointer;
1041
+ display: flex;
1042
+ align-items: center;
1043
+ justify-content: space-between;
1044
+ transition: color 0.2s ease;
1045
+ }
1046
+
1047
+ .sidebar-dark .nav-section-header {
1048
+ color: var(--bs-secondary-color);
1049
+ }
1050
+
1051
+ .sidebar-dark .nav-section-header.collapsible:hover {
1052
+ color: var(--bs-light);
1053
+ }
1054
+
1055
+ .sidebar-light .nav-section-header {
1056
+ color: var(--bs-secondary-color);
1057
+ }
1058
+
1059
+ .sidebar-light .nav-section-header.collapsible:hover {
1060
+ color: var(--bs-body-color);
1061
+ }
1062
+
1063
+ .sidebar-clean .nav-section-header {
1064
+ color: var(--bs-secondary-color);
1065
+ margin: 0 0.5rem;
1066
+ }
1067
+
1068
+ .sidebar-clean .nav-section-header.collapsible:hover {
1069
+ color: var(--bs-body-color);
1070
+ }
1071
+
1072
+ .nav-section-items {
1073
+ padding-left: 0;
1074
+ }
1075
+
1076
+ .sidebar-nav .badge {
1077
+ font-size: 0.7rem;
1078
+ padding: 0.25rem 0.5rem;
1079
+ }
1080
+
1081
+ /* Sidebar footer */
1082
+ .sidebar-footer {
1083
+ flex-shrink: 0;
1084
+ margin-top: auto;
1085
+ }
1086
+
1087
+ .footer-content {
1088
+ padding: 1rem;
1089
+ font-size: 0.85rem;
1090
+ }
1091
+
1092
+ .sidebar-dark .sidebar-footer {
1093
+ border-top: 1px solid var(--bs-border-color-translucent);
1094
+ }
1095
+
1096
+ .sidebar-dark .footer-content {
1097
+ color: var(--bs-secondary-color);
1098
+ }
1099
+
1100
+ .sidebar-light .sidebar-footer {
1101
+ border-top: 1px solid var(--bs-border-color);
1102
+ }
1103
+
1104
+ .sidebar-light .footer-content {
1105
+ color: var(--bs-secondary-color);
1106
+ }
1107
+
1108
+ .sidebar-clean .sidebar-footer {
1109
+ border-top: 1px solid var(--bs-border-color);
1110
+ background-color: var(--bs-secondary-bg);
1111
+ }
1112
+
1113
+ .sidebar-clean .footer-content {
1114
+ color: var(--bs-secondary-color);
1115
+ }
1116
+
1117
+ /* ========================================================================
1118
+ MOJO Configuration Switcher (Custom Component)
1119
+ ======================================================================== */
1120
+
1121
+ .config-switcher {
1122
+ position: absolute;
1123
+ top: 8px;
1124
+ right: 8px;
1125
+ }
1126
+
1127
+ .config-menu {
1128
+ position: absolute;
1129
+ top: 0;
1130
+ left: 0;
1131
+ right: 0;
1132
+ bottom: 0;
1133
+ background-color: rgba(var(--bs-dark-rgb), 0.95);
1134
+ backdrop-filter: blur(4px);
1135
+ z-index: 1050;
1136
+ padding: 1rem;
1137
+ }
1138
+
1139
+ .config-menu-header {
1140
+ display: flex;
1141
+ justify-content: space-between;
1142
+ align-items: center;
1143
+ margin-bottom: 1rem;
1144
+ padding-bottom: 0.5rem;
1145
+ border-bottom: 1px solid var(--bs-border-color-translucent);
1146
+ }
1147
+
1148
+ .config-menu-body {
1149
+ display: flex;
1150
+ flex-direction: column;
1151
+ gap: 0.5rem;
1152
+ }
1153
+
1154
+ .config-option {
1155
+ padding: 0.75rem;
1156
+ border: 1px solid var(--bs-border-color-translucent);
1157
+ border-radius: var(--bs-border-radius);
1158
+ background-color: var(--bs-secondary-bg);
1159
+ cursor: pointer;
1160
+ transition: all 0.2s ease;
1161
+ }
1162
+
1163
+ .config-option:hover {
1164
+ background-color: var(--bs-tertiary-bg);
1165
+ border-color: var(--bs-border-color);
1166
+ }
1167
+
1168
+ .config-option.active {
1169
+ background-color: var(--bs-primary-bg-subtle);
1170
+ border-color: var(--bs-primary);
1171
+ }
1172
+
1173
+ .config-name {
1174
+ font-weight: 500;
1175
+ color: var(--bs-body-color);
1176
+ }
1177
+
1178
+ /* ========================================================================
1179
+ MOJO Group Selector (Custom Component)
1180
+ ======================================================================== */
1181
+
1182
+ .group-selector-container {
1183
+ padding: 0.75rem;
1184
+ }
1185
+
1186
+ .group-selector-wrapper {
1187
+ position: relative;
1188
+ width: 100%;
1189
+ }
1190
+
1191
+ .group-selector {
1192
+ position: relative;
1193
+ }
1194
+
1195
+ .group-selector.disabled {
1196
+ opacity: 0.6;
1197
+ pointer-events: none;
1198
+ }
1199
+
1200
+ .group-selector .input-group-text {
1201
+ background-color: var(--bs-secondary-bg);
1202
+ border-color: var(--bs-border-color);
1203
+ color: var(--bs-secondary-color);
1204
+ }
1205
+
1206
+ .group-selector .form-control {
1207
+ background-color: var(--bs-tertiary-bg);
1208
+ border-color: var(--bs-border-color);
1209
+ color: var(--bs-body-color);
1210
+ }
1211
+
1212
+ .group-selector .form-control:focus {
1213
+ background-color: var(--bs-tertiary-bg);
1214
+ border-color: var(--bs-primary);
1215
+ color: var(--bs-body-color);
1216
+ box-shadow: 0 0 0 0.2rem rgba(var(--bs-primary-rgb), 0.25);
1217
+ }
1218
+
1219
+ .group-selector .form-control::placeholder {
1220
+ color: var(--bs-secondary-color);
1221
+ }
1222
+
1223
+ .group-selector .dropdown-toggle {
1224
+ background-color: var(--bs-secondary-bg);
1225
+ border-color: var(--bs-border-color);
1226
+ color: var(--bs-secondary-color);
1227
+ }
1228
+
1229
+ .group-selector .dropdown-toggle:hover,
1230
+ .group-selector .dropdown-toggle:focus {
1231
+ background-color: var(--bs-tertiary-bg);
1232
+ border-color: var(--bs-border-color);
1233
+ color: var(--bs-body-color);
1234
+ }
1235
+
1236
+ .dropdown-arrow {
1237
+ transition: transform 0.2s ease;
1238
+ }
1239
+
1240
+ .group-selector .dropdown-toggle[aria-expanded="true"] .dropdown-arrow {
1241
+ transform: rotate(180deg);
1242
+ }
1243
+
1244
+ /* Custom Group Dropdown */
1245
+ .group-dropdown {
1246
+ position: absolute;
1247
+ top: 100%;
1248
+ left: 0;
1249
+ right: 0;
1250
+ background-color: var(--bs-body-bg);
1251
+ border: 1px solid var(--bs-border-color);
1252
+ border-top: none;
1253
+ border-radius: 0 0 var(--bs-border-radius) var(--bs-border-radius);
1254
+ max-height: 400px;
1255
+ overflow-y: auto;
1256
+ z-index: 1050;
1257
+ box-shadow: var(--bs-box-shadow-lg);
1258
+ opacity: 0;
1259
+ transform: translateY(-10px);
1260
+ transition:
1261
+ opacity 0.2s ease,
1262
+ transform 0.2s ease;
1263
+ display: none;
1264
+ }
1265
+
1266
+ .group-dropdown.show {
1267
+ display: block;
1268
+ opacity: 1;
1269
+ transform: translateY(0);
1270
+ }
1271
+
1272
+ .group-dropdown .dropdown-header {
1273
+ padding: 0.75rem 1rem;
1274
+ background-color: var(--bs-secondary-bg);
1275
+ border-bottom: 1px solid var(--bs-border-color);
1276
+ color: var(--bs-secondary-color);
1277
+ font-size: 0.875rem;
1278
+ }
1279
+
1280
+ .group-results {
1281
+ max-height: 300px;
1282
+ overflow-y: auto;
1283
+ }
1284
+
1285
+ .group-item {
1286
+ padding: 0;
1287
+ border-bottom: 1px solid var(--bs-border-color-translucent);
1288
+ cursor: pointer;
1289
+ transition: background-color 0.2s ease;
1290
+ }
1291
+
1292
+ .group-item:last-child {
1293
+ border-bottom: none;
1294
+ }
1295
+
1296
+ .group-item:hover,
1297
+ .group-item.focused {
1298
+ background-color: var(--bs-secondary-bg);
1299
+ }
1300
+
1301
+ .group-item.selected {
1302
+ background-color: var(--bs-primary-bg-subtle);
1303
+ border-left: 3px solid var(--bs-primary);
1304
+ }
1305
+
1306
+ .group-item.selected:hover {
1307
+ background-color: var(--bs-primary-bg-subtle);
1308
+ }
1309
+
1310
+ .group-content {
1311
+ padding: 0.75rem 1rem;
1312
+ display: flex;
1313
+ justify-content: space-between;
1314
+ align-items: flex-start;
1315
+ gap: 1rem;
1316
+ }
1317
+
1318
+ .group-main {
1319
+ flex: 1;
1320
+ min-width: 0;
1321
+ }
1322
+
1323
+ .group-meta {
1324
+ display: flex;
1325
+ flex-direction: column;
1326
+ align-items: flex-end;
1327
+ gap: 0.25rem;
1328
+ }
1329
+
1330
+ .group-name {
1331
+ display: flex;
1332
+ align-items: center;
1333
+ flex-wrap: wrap;
1334
+ gap: 0.25rem;
1335
+ margin-bottom: 0.25rem;
1336
+ }
1337
+
1338
+ .group-hierarchy {
1339
+ color: var(--bs-secondary-color);
1340
+ font-size: 0.85rem;
1341
+ font-weight: normal;
1342
+ }
1343
+
1344
+ .group-name-text {
1345
+ color: var(--bs-body-color);
1346
+ font-weight: 500;
1347
+ }
1348
+
1349
+ .group-type {
1350
+ font-size: 0.7rem;
1351
+ padding: 0.25rem 0.5rem;
1352
+ }
1353
+
1354
+ .group-description {
1355
+ color: var(--bs-secondary-color);
1356
+ font-size: 0.85rem;
1357
+ line-height: 1.3;
1358
+ margin-top: 0.25rem;
1359
+ }
1360
+
1361
+ .group-item mark {
1362
+ background-color: var(--bs-warning-bg-subtle);
1363
+ color: var(--bs-body-color);
1364
+ padding: 0;
1365
+ border-radius: var(--bs-border-radius-sm);
1366
+ }
1367
+
1368
+ .group-member-count {
1369
+ display: flex;
1370
+ align-items: center;
1371
+ color: var(--bs-secondary-color);
1372
+ font-size: 0.8rem;
1373
+ }
1374
+
1375
+ .group-status {
1376
+ display: flex;
1377
+ align-items: center;
1378
+ }
1379
+
1380
+ .status-indicator {
1381
+ width: 8px;
1382
+ height: 8px;
1383
+ border-radius: 50%;
1384
+ display: inline-block;
1385
+ }
1386
+
1387
+ .status-indicator.status-active {
1388
+ background-color: var(--bs-success);
1389
+ }
1390
+
1391
+ .status-indicator.status-inactive {
1392
+ background-color: var(--bs-secondary);
1393
+ }
1394
+
1395
+ .status-indicator.status-archived {
1396
+ background-color: var(--bs-danger);
1397
+ }
1398
+
1399
+ .status-indicator.status-pending {
1400
+ background-color: var(--bs-warning);
1401
+ }
1402
+
1403
+ .group-dropdown .dropdown-item-text {
1404
+ color: var(--bs-secondary-color);
1405
+ padding: 1rem;
1406
+ }
1407
+
1408
+ .group-dropdown .dropdown-divider {
1409
+ border-top: 1px solid var(--bs-border-color);
1410
+ margin: 0.5rem 0;
1411
+ }
1412
+
1413
+ .selected-group-display {
1414
+ animation: fadeInUp 0.3s ease;
1415
+ }
1416
+
1417
+ .selected-group-card {
1418
+ background-color: var(--bs-primary-bg-subtle);
1419
+ border: 1px solid var(--bs-primary-border-subtle);
1420
+ border-radius: var(--bs-border-radius);
1421
+ padding: 0.75rem;
1422
+ }
1423
+
1424
+ .selected-group-icon {
1425
+ flex-shrink: 0;
1426
+ }
1427
+
1428
+ .selected-group-info {
1429
+ min-width: 0;
1430
+ }
1431
+
1432
+ .selected-group-name {
1433
+ color: var(--bs-body-color);
1434
+ margin-bottom: 0.25rem;
1435
+ }
1436
+
1437
+ .selected-group-desc {
1438
+ color: var(--bs-secondary-color);
1439
+ line-height: 1.3;
1440
+ }
1441
+
1442
+ .selected-group-actions {
1443
+ flex-shrink: 0;
1444
+ }
1445
+
1446
+ .group-dropdown::-webkit-scrollbar,
1447
+ .group-results::-webkit-scrollbar {
1448
+ width: 6px;
1449
+ }
1450
+
1451
+ .group-dropdown::-webkit-scrollbar-track,
1452
+ .group-results::-webkit-scrollbar-track {
1453
+ background: var(--bs-secondary-bg);
1454
+ }
1455
+
1456
+ .group-dropdown::-webkit-scrollbar-thumb,
1457
+ .group-results::-webkit-scrollbar-thumb {
1458
+ background: var(--bs-border-color);
1459
+ border-radius: var(--bs-border-radius-sm);
1460
+ }
1461
+
1462
+ .group-dropdown::-webkit-scrollbar-thumb:hover,
1463
+ .group-results::-webkit-scrollbar-thumb:hover {
1464
+ background: var(--bs-secondary-color);
1465
+ }
1466
+
1467
+ .context-menu-view.header-menu {
1468
+ margin-top: -0.6rem;
1469
+ }
1470
+
1471
+ .context-menu-view.header-menu-absolute {
1472
+ /*position: absolute;*/
1473
+ top: 1rem;
1474
+ right: 1rem;
1475
+ }
1476
+
1477
+ /* ========================================================================
1478
+ Responsive Design
1479
+ ======================================================================== */
1480
+
1481
+ /* ========================================================================
1482
+ Mobile Layout Handling (Class-Based)
1483
+ ======================================================================== */
1484
+
1485
+ /* Mobile layout: Sidebar fullscreen by default */
1486
+ .portal-container.mobile-layout #portal-sidebar {
1487
+ position: fixed !important;
1488
+ top: 0;
1489
+ left: 0;
1490
+ right: 0;
1491
+ bottom: 0;
1492
+ width: 100vw;
1493
+ height: 100vh;
1494
+ z-index: var(--mojo-zindex-modal);
1495
+ transform: translateX(0); /* Show by default */
1496
+ transition: transform 350ms cubic-bezier(0.4, 0, 0.2, 1);
1497
+ box-shadow: 0 0 20px rgba(0, 0, 0, 0.3);
1498
+ }
1499
+
1500
+ .portal-container.mobile-layout #portal-sidebar .sidebar {
1501
+ height: 100vh;
1502
+ width: 100%;
1503
+ }
1504
+
1505
+ .portal-container.mobile-layout #portal-sidebar .sidebar-container {
1506
+ height: 100%;
1507
+ }
1508
+
1509
+ /* Hide sidebar when hide-sidebar class is present */
1510
+ .portal-container.mobile-layout.hide-sidebar #portal-sidebar {
1511
+ transform: translateX(-100%);
1512
+ box-shadow: 0 0 20px rgba(0, 0, 0, 0);
1513
+ }
1514
+
1515
+ /* Force full sidebar width on mobile - override collapse states */
1516
+ .portal-container.mobile-layout #portal-sidebar,
1517
+ .portal-container.mobile-layout.collapse-sidebar #portal-sidebar {
1518
+ inline-size: 100vw !important;
1519
+ max-width: 100vw !important;
1520
+ flex-basis: 100vw !important;
1521
+ }
1522
+
1523
+ /* Show all text and arrows on mobile - override collapsed state */
1524
+ .portal-container.mobile-layout .nav-text,
1525
+ .portal-container.mobile-layout.collapse-sidebar .nav-text {
1526
+ opacity: 1 !important;
1527
+ width: auto !important;
1528
+ overflow: visible !important;
1529
+ }
1530
+
1531
+ .portal-container.mobile-layout .nav-arrow,
1532
+ .portal-container.mobile-layout.collapse-sidebar .nav-arrow {
1533
+ opacity: 1 !important;
1534
+ }
1535
+
1536
+ .portal-container.mobile-layout .sidebar-nav .nav-link,
1537
+ .portal-container.mobile-layout.collapse-sidebar .sidebar-nav .nav-link {
1538
+ justify-content: flex-start !important;
1539
+ padding: 1rem !important;
1540
+ font-size: 1rem;
1541
+ }
1542
+
1543
+ .portal-container.mobile-layout .nav-submenu,
1544
+ .portal-container.mobile-layout.collapse-sidebar .nav-submenu {
1545
+ display: block !important;
1546
+ }
1547
+
1548
+ /* Mobile: Hide sidebar toggle - use topnav toggle instead */
1549
+ .portal-container.mobile-layout .sidebar-toggle {
1550
+ display: none;
1551
+ }
1552
+
1553
+ /* Mobile: Adjust other sidebar elements */
1554
+ .portal-container.mobile-layout .group-selector-container {
1555
+ padding: 0.5rem;
1556
+ }
1557
+
1558
+ .portal-container.mobile-layout .config-menu {
1559
+ padding: 0.5rem;
1560
+ }
1561
+
1562
+ .portal-container.mobile-layout .selected-group-card {
1563
+ padding: 1rem;
1564
+ }
1565
+
1566
+ .portal-container.mobile-layout .group-dropdown {
1567
+ max-height: 300px;
1568
+ left: -5px;
1569
+ right: -5px;
1570
+ border-radius: 0.5rem;
1571
+ border: 1px solid #495057;
1572
+ box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.3);
1573
+ }
1574
+
1575
+ .portal-container.mobile-layout .group-content {
1576
+ padding: 1rem 0.75rem;
1577
+ flex-direction: column;
1578
+ align-items: stretch;
1579
+ gap: 0.5rem;
1580
+ }
1581
+
1582
+ .portal-container.mobile-layout .group-meta {
1583
+ flex-direction: row;
1584
+ justify-content: space-between;
1585
+ align-items: center;
1586
+ }
1587
+
1588
+ /* Mobile sidebar backdrop */
1589
+ .portal-sidebar-backdrop {
1590
+ position: fixed;
1591
+ top: 0;
1592
+ left: 0;
1593
+ width: 100vw;
1594
+ height: 100vh;
1595
+ background: rgba(0, 0, 0, 0.5);
1596
+ z-index: calc(var(--mojo-zindex-modal) - 1);
1597
+ opacity: 0;
1598
+ visibility: hidden;
1599
+ transition:
1600
+ opacity 350ms cubic-bezier(0.4, 0, 0.2, 1),
1601
+ visibility 350ms cubic-bezier(0.4, 0, 0.2, 1),
1602
+ backdrop-filter 350ms cubic-bezier(0.4, 0, 0.2, 1);
1603
+ backdrop-filter: blur(0px);
1604
+ }
1605
+
1606
+ /* Show backdrop when mobile sidebar is visible (not hidden) */
1607
+ .portal-container.mobile-layout:not(.hide-sidebar) .portal-sidebar-backdrop {
1608
+ opacity: 1;
1609
+ visibility: visible;
1610
+ backdrop-filter: blur(4px);
1611
+ }
1612
+
1613
+ /* Enhanced smooth transitions for all sidebar states */
1614
+ .portal-container #portal-sidebar,
1615
+ .sidebar-nav .nav-link,
1616
+ .nav-text,
1617
+ .nav-arrow,
1618
+ .sidebar-header,
1619
+ .sidebar-footer,
1620
+ .sidebar-header .fs-5 {
1621
+ transition-duration: 300ms;
1622
+ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
1623
+ }
1624
+
1625
+ /* Staggered animation for navigation items */
1626
+ .sidebar-nav .nav-item:nth-child(1) .nav-link {
1627
+ transition-delay: 0ms;
1628
+ }
1629
+ .sidebar-nav .nav-item:nth-child(2) .nav-link {
1630
+ transition-delay: 20ms;
1631
+ }
1632
+ .sidebar-nav .nav-item:nth-child(3) .nav-link {
1633
+ transition-delay: 40ms;
1634
+ }
1635
+ .sidebar-nav .nav-item:nth-child(4) .nav-link {
1636
+ transition-delay: 60ms;
1637
+ }
1638
+ .sidebar-nav .nav-item:nth-child(5) .nav-link {
1639
+ transition-delay: 80ms;
1640
+ }
1641
+ .sidebar-nav .nav-item:nth-child(6) .nav-link {
1642
+ transition-delay: 100ms;
1643
+ }
1644
+ .sidebar-nav .nav-item:nth-child(7) .nav-link {
1645
+ transition-delay: 120ms;
1646
+ }
1647
+ .sidebar-nav .nav-item:nth-child(8) .nav-link {
1648
+ transition-delay: 140ms;
1649
+ }
1650
+
1651
+ /* ========================================================================
1652
+ Dark Theme Support
1653
+ ======================================================================== */
1654
+
1655
+ [data-bs-theme="dark"] .group-dropdown {
1656
+ background-color: var(--bs-body-bg);
1657
+ border-color: var(--bs-border-color);
1658
+ }
1659
+
1660
+ [data-bs-theme="dark"] .config-menu {
1661
+ background-color: rgba(var(--bs-dark-rgb), 0.95);
1662
+ }
1663
+
1664
+ [data-bs-theme="dark"] .config-option {
1665
+ background-color: var(--bs-secondary-bg);
1666
+ border-color: var(--bs-border-color);
1667
+ }
1668
+
1669
+ [data-bs-theme="dark"] .group-selector .form-control {
1670
+ background-color: var(--bs-tertiary-bg);
1671
+ border-color: var(--bs-border-color);
1672
+ color: var(--bs-body-color);
1673
+ }
1674
+
1675
+ [data-bs-theme="dark"] .group-selector .input-group-text {
1676
+ background-color: var(--bs-secondary-bg);
1677
+ border-color: var(--bs-border-color);
1678
+ color: var(--bs-secondary-color);
1679
+ }
1680
+
1681
+ [data-bs-theme="dark"] .group-item:hover,
1682
+ [data-bs-theme="dark"] .group-item.focused {
1683
+ background-color: var(--bs-secondary-bg);
1684
+ }
1685
+
1686
+ [data-bs-theme="dark"] .selected-group-card {
1687
+ background-color: var(--bs-primary-bg-subtle);
1688
+ border-color: var(--bs-primary-border-subtle);
1689
+ }
1690
+
1691
+ /* ========================================================================
1692
+ Animations
1693
+ ======================================================================== */
1694
+
1695
+ @keyframes fadeInUp {
1696
+ from {
1697
+ opacity: 0;
1698
+ transform: translateY(10px);
1699
+ }
1700
+ to {
1701
+ opacity: 1;
1702
+ transform: translateY(0);
1703
+ }
1704
+ }
1705
+
1706
+ /* ========================================================================
1707
+ Accessibility
1708
+ ======================================================================== */
1709
+
1710
+ .group-item:focus {
1711
+ outline: 2px solid #0d6efd;
1712
+ outline-offset: -2px;
1713
+ }
1714
+
1715
+ @media (prefers-contrast: high) {
1716
+ .group-dropdown {
1717
+ border-width: 2px;
1718
+ border-color: #fff;
1719
+ }
1720
+
1721
+ .group-item.selected {
1722
+ border-left-width: 4px;
1723
+ }
1724
+
1725
+ .status-indicator {
1726
+ border: 1px solid #fff;
1727
+ }
1728
+ }
1729
+
1730
+ @media (prefers-reduced-motion: reduce) {
1731
+ .group-dropdown {
1732
+ transition: none;
1733
+ }
1734
+
1735
+ .dropdown-arrow {
1736
+ transition: none;
1737
+ }
1738
+
1739
+ .selected-group-display {
1740
+ animation: none;
1741
+ }
1742
+
1743
+ .portal-container #portal-sidebar,
1744
+ .sidebar-nav .nav-link,
1745
+ .nav-text,
1746
+ .nav-arrow,
1747
+ .sidebar-header,
1748
+ .sidebar-footer,
1749
+ .sidebar-header .fs-5 {
1750
+ transition: none !important;
1751
+ animation: none !important;
1752
+ }
1753
+
1754
+ .sidebar-nav .nav-link i {
1755
+ transition: none !important;
1756
+ }
1757
+
1758
+ .sidebar-nav .nav-link:hover,
1759
+ .portal-container.collapse-sidebar .sidebar .nav-link:hover {
1760
+ transform: none !important;
1761
+ box-shadow: none !important;
1762
+ }
1763
+
1764
+ .portal-sidebar-backdrop {
1765
+ transition: none !important;
1766
+ backdrop-filter: none !important;
1767
+ }
1768
+
1769
+ .sidebar-nav .nav-item:nth-child(n) .nav-link {
1770
+ transition-delay: 0ms !important;
1771
+ }
1772
+
1773
+ .portal-container:not(.collapse-sidebar) #portal-sidebar {
1774
+ animation: none !important;
1775
+ }
1776
+
1777
+ .sidebar-nav .nav-link.active {
1778
+ animation: none !important;
1779
+ }
1780
+
1781
+ .nav-link[data-bs-toggle="collapse"] .bi-chevron-down {
1782
+ transition: none !important;
1783
+ }
1784
+
1785
+ .nav-link[aria-expanded="true"] .bi-chevron-down {
1786
+ transform: rotate(180deg) !important;
1787
+ }
1788
+
1789
+ /* Accessibility: Respect reduced motion for tooltips */
1790
+ .portal-container.collapse-sidebar .sidebar .nav-link:hover::after,
1791
+ [data-bs-theme="dark"] .portal-container.collapse-sidebar .sidebar .nav-link:hover::after,
1792
+ .portal-container.collapse-sidebar .sidebar .nav-link:hover::before {
1793
+ animation: none !important;
1794
+ transition: none !important;
1795
+ opacity: 1 !important;
1796
+ visibility: visible !important;
1797
+ transform: translateY(-50%) translateX(0) !important;
1798
+ }
1799
+
1800
+ /* Disable toggle button animations */
1801
+ .sidebar-toggle,
1802
+ .sidebar-toggle .toggle-icon {
1803
+ transition: none !important;
1804
+ animation: none !important;
1805
+ }
1806
+
1807
+ .sidebar-toggle:hover {
1808
+ transform: none !important;
1809
+ }
1810
+ }
1811
+
1812
+ /* ========================================================================
1813
+ MOJO Portal Utility Classes
1814
+ ======================================================================== */
1815
+
1816
+ /* Force sidebar states */
1817
+ .mojo-sidebar-force-open .portal-container {
1818
+ --mojo-sidebar-width: 250px !important;
1819
+ }
1820
+
1821
+ .mojo-sidebar-force-open #portal-sidebar {
1822
+ inline-size: var(--mojo-sidebar-width) !important;
1823
+ max-width: var(--mojo-sidebar-width) !important;
1824
+ flex-basis: var(--mojo-sidebar-width) !important;
1825
+ }
1826
+
1827
+ .mojo-sidebar-force-collapsed .portal-container {
1828
+ --mojo-sidebar-width: var(--mojo-sidebar-collapsed-width) !important;
1829
+ }
1830
+
1831
+ .mojo-sidebar-force-collapsed #portal-sidebar {
1832
+ inline-size: var(--mojo-sidebar-collapsed-width) !important;
1833
+ max-width: var(--mojo-sidebar-collapsed-width) !important;
1834
+ flex-basis: var(--mojo-sidebar-collapsed-width) !important;
1835
+ }
1836
+
1837
+ .mojo-sidebar-force-hidden #portal-sidebar {
1838
+ inline-size: 0 !important;
1839
+ max-width: 0 !important;
1840
+ flex-basis: 0 !important;
1841
+ overflow: hidden !important;
1842
+ }
1843
+
1844
+ /* Sidebar transition control */
1845
+ .mojo-sidebar-no-transition #portal-sidebar,
1846
+ .mojo-sidebar-no-transition .sidebar-nav .nav-link,
1847
+ .mojo-sidebar-no-transition .nav-text,
1848
+ .mojo-sidebar-no-transition .nav-arrow {
1849
+ transition: none !important;
1850
+ }
1851
+
1852
+ /* Additional mobile utilities */
1853
+ .portal-container.sidebar-opening #portal-sidebar {
1854
+ transition-duration: 350ms;
1855
+ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
1856
+ }
1857
+
1858
+ .portal-container.sidebar-closing #portal-sidebar {
1859
+ transition-duration: 250ms;
1860
+ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
1861
+ }
1862
+
1863
+ /* Add spring animation for expand */
1864
+ .portal-container:not(.collapse-sidebar) #portal-sidebar {
1865
+ animation: sidebar-expand 400ms cubic-bezier(0.34, 1.56, 0.64, 1);
1866
+ }
1867
+
1868
+ @keyframes sidebar-expand {
1869
+ 0% {
1870
+ transform: scale(0.98) translateX(-2px);
1871
+ opacity: 0.9;
1872
+ }
1873
+ 60% {
1874
+ transform: scale(1.01) translateX(1px);
1875
+ }
1876
+ 100% {
1877
+ transform: scale(1) translateX(0);
1878
+ opacity: 1;
1879
+ }
1880
+ }
1881
+
1882
+ /* Pulse animation for active nav items */
1883
+ @keyframes nav-pulse {
1884
+ 0% {
1885
+ box-shadow: 0 0 0 0 rgba(var(--bs-primary-rgb), 0.4);
1886
+ }
1887
+ 70% {
1888
+ box-shadow: 0 0 0 6px rgba(var(--bs-primary-rgb), 0);
1889
+ }
1890
+ 100% {
1891
+ box-shadow: 0 0 0 0 rgba(var(--bs-primary-rgb), 0);
1892
+ }
1893
+ }
1894
+
1895
+ .sidebar-nav .nav-link.active {
1896
+ animation: nav-pulse 2s infinite;
1897
+ }
1898
+
1899
+ /* Smooth icon transitions for submenu toggles */
1900
+ .nav-link[data-bs-toggle="collapse"] .bi-chevron-down {
1901
+ transition: transform 250ms cubic-bezier(0.4, 0, 0.2, 1);
1902
+ }
1903
+
1904
+ .nav-link[aria-expanded="true"] .bi-chevron-down {
1905
+ transform: rotate(180deg) scale(1.1);
1906
+ }
1907
+
1908
+ /* Sidebar theme utilities */
1909
+ .mojo-sidebar-theme-auto .sidebar {
1910
+ background-color: var(--bs-body-bg);
1911
+ color: var(--bs-body-color);
1912
+ border-right: 1px solid var(--bs-border-color);
1913
+ }
1914
+
1915
+ .mojo-sidebar-theme-auto .sidebar-nav .nav-link {
1916
+ color: var(--bs-body-color);
1917
+ }
1918
+
1919
+ .mojo-sidebar-theme-auto .sidebar-nav .nav-link:hover {
1920
+ background-color: var(--bs-secondary-bg);
1921
+ }
1922
+
1923
+ .mojo-sidebar-theme-auto .sidebar-nav .nav-link.active {
1924
+ background-color: var(--bs-primary);
1925
+ color: var(--bs-white);
1926
+ }
1927
+
1928
+ /* Sidebar state indicators */
1929
+ .mojo-sidebar-collapsed .nav-text,
1930
+ .mojo-sidebar-collapsed .nav-arrow {
1931
+ opacity: 0;
1932
+ width: 0;
1933
+ overflow: hidden;
1934
+ }
1935
+
1936
+ .mojo-sidebar-collapsed .sidebar-nav .nav-link {
1937
+ justify-content: center;
1938
+ padding-left: 0.5rem;
1939
+ padding-right: 0.5rem;
1940
+ }
1941
+
1942
+ .mojo-sidebar-collapsed .nav-submenu {
1943
+ display: none !important;
1944
+ }
1945
+
1946
+ /* Portal layout variants */
1947
+ .mojo-portal-fixed .portal-layout {
1948
+ position: fixed;
1949
+ top: 0;
1950
+ left: 0;
1951
+ right: 0;
1952
+ bottom: 0;
1953
+ z-index: var(--mojo-zindex-fixed);
1954
+ }
1955
+
1956
+ .mojo-portal-sticky-sidebar #portal-sidebar {
1957
+ position: sticky;
1958
+ top: 0;
1959
+ height: 100vh;
1960
+ }
1961
+
1962
+ /* Portal content utilities */
1963
+ .mojo-portal-content-padded .portal-content {
1964
+ padding: var(--mojo-spacer-lg);
1965
+ }
1966
+
1967
+ .mojo-portal-content-flush .portal-content,
1968
+ .mobile-layout .portal-content {
1969
+ padding: 0;
1970
+ }
1971
+
1972
+ /* Sidebar animation presets */
1973
+ .mojo-sidebar-slide #portal-sidebar {
1974
+ transition: transform var(--mojo-transition-base) ease-in-out;
1975
+ }
1976
+
1977
+ .mojo-sidebar-fade #portal-sidebar {
1978
+ transition: opacity var(--mojo-transition-base) ease-in-out;
1979
+ }
1980
+
1981
+ .mojo-sidebar-scale #portal-sidebar {
1982
+ transition: transform var(--mojo-transition-base) cubic-bezier(0.34, 1.56, 0.64, 1);
1983
+ }
1984
+
1985
+ /* JavaScript state classes */
1986
+ .js-sidebar-transitioning * {
1987
+ pointer-events: none;
1988
+ }
1989
+
1990
+ .js-sidebar-ready {
1991
+ transition: all var(--mojo-transition-base);
1992
+ }
1993
+
1994
+ /* Accessibility enhancements */
1995
+ @media (prefers-color-scheme: dark) {
1996
+ .mojo-sidebar-theme-auto .sidebar {
1997
+ background-color: var(--bs-dark);
1998
+ color: var(--bs-light);
1999
+ border-right: 1px solid var(--bs-gray-800);
2000
+ }
2001
+
2002
+ .mojo-sidebar-theme-auto .sidebar-nav .nav-link {
2003
+ color: var(--bs-gray-300);
2004
+ }
2005
+
2006
+ .mojo-sidebar-theme-auto .sidebar-nav .nav-link:hover {
2007
+ background-color: rgba(255, 255, 255, 0.1);
2008
+ color: var(--bs-white);
2009
+ }
2010
+ }
2011
+
2012
+ /* Focus management for collapsed sidebar */
2013
+ .mojo-sidebar-collapsed .nav-link:focus-visible {
2014
+ outline: 2px solid var(--bs-primary);
2015
+ outline-offset: -2px;
2016
+ z-index: 1;
2017
+ }
2018
+
2019
+ /* Skip to content for accessibility */
2020
+ .mojo-skip-to-content {
2021
+ position: absolute;
2022
+ top: -40px;
2023
+ left: 6px;
2024
+ background: var(--bs-primary);
2025
+ color: white;
2026
+ padding: 8px;
2027
+ text-decoration: none;
2028
+ z-index: var(--mojo-zindex-tooltip);
2029
+ border-radius: var(--mojo-border-radius);
2030
+ font-size: 0.875rem;
2031
+ }
2032
+
2033
+ .mojo-skip-to-content:focus {
2034
+ top: 6px;
2035
+ }
2036
+
2037
+ /* Mobile body behavior when sidebar is showing */
2038
+ .portal-container.mobile-layout:not(.hide-sidebar) {
2039
+ overflow: hidden;
2040
+ }
2041
+
2042
+ .portal-container.mobile-layout:not(.hide-sidebar) .portal-body {
2043
+ pointer-events: none;
2044
+ }
2045
+
2046
+ /* ========================================================================
2047
+ GROUP SELECTION INTERFACE
2048
+ ======================================================================== */
2049
+
2050
+ .group-selection-sidebar {
2051
+ background: white;
2052
+ border-right: 1px solid var(--bs-border-color);
2053
+ }
2054
+
2055
+ .group-selection-sidebar .form-control-sm {
2056
+ font-size: 0.875rem;
2057
+ }
2058
+
2059
+ .group-item {
2060
+ cursor: pointer;
2061
+ transition: all 0.2s ease;
2062
+ border-bottom: 1px solid rgba(0, 0, 0, 0.05);
2063
+ position: relative;
2064
+ }
2065
+
2066
+ .group-item:last-child {
2067
+ border-bottom: none;
2068
+ }
2069
+
2070
+ .group-item:hover {
2071
+ background-color: #f8f9fa !important;
2072
+ border-left: 3px solid var(--bs-primary);
2073
+ }
2074
+
2075
+ .group-item:active {
2076
+ background-color: #e9ecef !important;
2077
+ transform: translateX(1px);
2078
+ }
2079
+
2080
+ .group-item .bi-chevron-right {
2081
+ opacity: 0;
2082
+ transition: opacity 0.2s ease;
2083
+ }
2084
+
2085
+ .group-item:hover .bi-chevron-right {
2086
+ opacity: 1;
2087
+ }
2088
+
2089
+ /* Group header in menus */
2090
+ .group-header {
2091
+ margin-bottom: 1rem;
2092
+ padding-bottom: 0.75rem;
2093
+ border-bottom: 1px solid rgba(0, 0, 0, 0.1);
2094
+ }
2095
+
2096
+ .group-header .cursor-pointer {
2097
+ cursor: pointer;
2098
+ padding: 0.5rem;
2099
+ border-radius: 0.375rem;
2100
+ transition: all 0.2s ease;
2101
+ }
2102
+
2103
+ .group-header .cursor-pointer:hover {
2104
+ background-color: #f8f9fa !important;
2105
+ }
2106
+
2107
+ .group-header .bi-chevron-down {
2108
+ transition: transform 0.2s ease;
2109
+ }
2110
+
2111
+ .group-header .cursor-pointer:hover .bi-chevron-down {
2112
+ transform: rotate(180deg);
2113
+ }
2114
+
2115
+ /* Dark theme adjustments */
2116
+ .sidebar-dark .group-selection-sidebar {
2117
+ background: #2c3e50;
2118
+ border-right-color: #34495e;
2119
+ }
2120
+
2121
+ .sidebar-dark .group-item {
2122
+ border-bottom-color: rgba(255, 255, 255, 0.05);
2123
+ }
2124
+
2125
+ .sidebar-dark .group-item:hover {
2126
+ background-color: #34495e !important;
2127
+ }
2128
+
2129
+ .sidebar-dark .group-item:active {
2130
+ background-color: #3d566e !important;
2131
+ }
2132
+
2133
+ .sidebar-dark .group-header {
2134
+ border-bottom-color: rgba(255, 255, 255, 0.1);
2135
+ }
2136
+
2137
+ .sidebar-dark .group-header .cursor-pointer:hover {
2138
+ background-color: #34495e !important;
2139
+ }
2140
+
2141
+ /* Loading states */
2142
+ .group-selection-sidebar .spinner-border-sm {
2143
+ width: 1rem;
2144
+ height: 1rem;
2145
+ }
2146
+
2147
+ .group-selection-sidebar .text-center {
2148
+ color: var(--bs-secondary);
2149
+ }
2150
+
2151
+ /* Search input focus */
2152
+ .group-selection-sidebar .form-control:focus {
2153
+ border-color: var(--bs-primary);
2154
+ box-shadow: 0 0 0 0.2rem rgba(var(--bs-primary-rgb), 0.25);
2155
+ }
2156
+
2157
+ /* Empty state styling */
2158
+ .group-selection-sidebar .bi-inbox,
2159
+ .group-selection-sidebar .bi-search {
2160
+ color: var(--bs-secondary);
2161
+ }
2162
+
2163
+ /* Help section */
2164
+ .group-selection-sidebar .bg-light {
2165
+ background-color: rgba(0, 0, 0, 0.02) !important;
2166
+ }
2167
+
2168
+ .sidebar-dark .group-selection-sidebar .bg-light {
2169
+ background-color: rgba(255, 255, 255, 0.02) !important;
2170
+ }
2171
+
2172
+ .group-selection-sidebar .text-decoration-none:hover {
2173
+ color: var(--bs-primary) !important;
2174
+ }
2175
+
2176
+ .simple-search-view {
2177
+ background-color: var(--bs-body-bg);
2178
+ color: var(--bs-body-color);
2179
+ border-right: 1px solid var(--bs-border-color);
2180
+ box-shadow: var(--bs-box-shadow);
2181
+ }
2182
+
2183
+ .collapse-sidebar .simple-search-view {
2184
+ background-color: var(--mojo-topnav-bg) !important;
2185
+ }
2186
+
2187
+ .collapse-sidebar .simple-search-view > * {
2188
+ display: none !important;
2189
+ }
2190
+
2191
+ .simple-search-item {
2192
+ cursor: pointer;
2193
+ transition:
2194
+ background-color 0.15s ease-in-out,
2195
+ transform 0.15s ease-in-out;
2196
+ border-radius: 0.25rem;
2197
+ }
2198
+
2199
+ .simple-search-item:hover {
2200
+ background-color: rgba(0, 0, 50, 0.05);
2201
+ transform: translateY(-1px);
2202
+ }
2203
+
2204
+ [data-bs-theme="dark"] .simple-search-item:hover {
2205
+ background-color: rgba(255, 255, 255, 0.1);
2206
+ }
2207
+
2208
+ /* SimpleSearchView Buttons */
2209
+ .simple-search-exit-btn {
2210
+ width: 20px;
2211
+ height: 20px;
2212
+ margin-top: -5px;
2213
+ }
2214
+
2215
+ .simple-search-clear-btn {
2216
+ width: 24px;
2217
+ height: 24px;
2218
+ border-radius: 50%;
2219
+ }
2220
+
2221
+ /* ========================================================================
2222
+ Jobs Admin Styling
2223
+ ======================================================================== */
2224
+
2225
+ /* Timeline Styles */
2226
+ .timeline {
2227
+ position: relative;
2228
+ padding-left: 2rem;
2229
+ }
2230
+
2231
+ .timeline::before {
2232
+ content: "";
2233
+ position: absolute;
2234
+ left: 0.75rem;
2235
+ top: 0;
2236
+ bottom: 0;
2237
+ width: 2px;
2238
+ background-color: #dee2e6;
2239
+ }
2240
+
2241
+ .timeline-item {
2242
+ position: relative;
2243
+ margin-bottom: 1.5rem;
2244
+ }
2245
+
2246
+ .timeline-marker {
2247
+ position: absolute;
2248
+ left: -2rem;
2249
+ top: 0.125rem;
2250
+ width: 1.5rem;
2251
+ height: 1.5rem;
2252
+ border-radius: 50%;
2253
+ display: flex;
2254
+ align-items: center;
2255
+ justify-content: center;
2256
+ font-size: 0.75rem;
2257
+ color: white;
2258
+ border: 2px solid white;
2259
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
2260
+ }
2261
+
2262
+ .timeline-marker-info {
2263
+ background-color: #0dcaf0;
2264
+ }
2265
+
2266
+ .timeline-marker-primary {
2267
+ background-color: #0d6efd;
2268
+ }
2269
+
2270
+ .timeline-marker-success {
2271
+ background-color: #198754;
2272
+ }
2273
+
2274
+ .timeline-marker-danger {
2275
+ background-color: #dc3545;
2276
+ }
2277
+
2278
+ .timeline-marker-warning {
2279
+ background-color: #ffc107;
2280
+ color: #000;
2281
+ }
2282
+
2283
+ .timeline-marker-secondary {
2284
+ background-color: #6c757d;
2285
+ }
2286
+
2287
+ .timeline-content {
2288
+ background-color: #f8f9fa;
2289
+ padding: 1rem;
2290
+ border-radius: 0.375rem;
2291
+ border: 1px solid #dee2e6;
2292
+ }
2293
+
2294
+ /* Job Status Indicators */
2295
+ .job-status-indicator {
2296
+ display: inline-flex;
2297
+ align-items: center;
2298
+ gap: 0.5rem;
2299
+ }
2300
+
2301
+ .job-health-indicator {
2302
+ width: 12px;
2303
+ height: 12px;
2304
+ border-radius: 50%;
2305
+ display: inline-block;
2306
+ }
2307
+
2308
+ .health-healthy {
2309
+ background-color: #198754;
2310
+ }
2311
+
2312
+ .health-warning {
2313
+ background-color: #ffc107;
2314
+ }
2315
+
2316
+ .health-critical {
2317
+ background-color: #dc3545;
2318
+ }
2319
+
2320
+ .health-unknown {
2321
+ background-color: #6c757d;
2322
+ }
2323
+
2324
+ /* Auto-refresh indicator */
2325
+ .spinning {
2326
+ animation: spin 1s linear infinite;
2327
+ }
2328
+
2329
+ @keyframes spin {
2330
+ from {
2331
+ transform: rotate(0deg);
2332
+ }
2333
+ to {
2334
+ transform: rotate(360deg);
2335
+ }
2336
+ }
2337
+
2338
+ /* Job Stats Cards */
2339
+ .job-stats-header .card {
2340
+ transition:
2341
+ transform 0.2s ease,
2342
+ box-shadow 0.2s ease;
2343
+ }
2344
+
2345
+ .job-stats-header .card:hover {
2346
+ transform: translateY(-2px);
2347
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15) !important;
2348
+ }
2349
+
2350
+ /* Job Health Cards */
2351
+ .job-health-header .health-indicator {
2352
+ animation: pulse 2s infinite;
2353
+ }
2354
+
2355
+ @keyframes pulse {
2356
+ 0% {
2357
+ opacity: 1;
2358
+ }
2359
+ 50% {
2360
+ opacity: 0.7;
2361
+ }
2362
+ 100% {
2363
+ opacity: 1;
2364
+ }
2365
+ }
2366
+
2367
+ /* Log container styling */
2368
+ .logs-container {
2369
+ background-color: #1e1e1e !important;
2370
+ color: #d4d4d4 !important;
2371
+ }
2372
+
2373
+ .logs-container .text-info {
2374
+ color: #9cdcfe !important;
2375
+ }
2376
+
2377
+ .logs-container .text-warning {
2378
+ color: #dcdcaa !important;
2379
+ }
2380
+
2381
+ .logs-container .text-danger {
2382
+ color: #f14c4c !important;
2383
+ }
2384
+
2385
+ .logs-container .text-success {
2386
+ color: #4ec9b0 !important;
2387
+ }
2388
+
2389
+ /* Code formatting */
2390
+ .job-details-view pre code {
2391
+ font-size: 0.875rem;
2392
+ line-height: 1.4;
2393
+ }
2394
+
2395
+ /* Responsive timeline */
2396
+ @media (max-width: 768px) {
2397
+ .timeline {
2398
+ padding-left: 1.5rem;
2399
+ }
2400
+
2401
+ .timeline-marker {
2402
+ left: -1.75rem;
2403
+ width: 1.25rem;
2404
+ height: 1.25rem;
2405
+ font-size: 0.625rem;
2406
+ }
2407
+
2408
+ .timeline-content {
2409
+ padding: 0.75rem;
2410
+ }
2411
+ }
2412
+
2413
+ /* Channel status badges */
2414
+ .channel-status-badge {
2415
+ font-size: 0.75rem;
2416
+ padding: 0.25rem 0.5rem;
2417
+ }
2418
+
2419
+ /* Runner utilization bars */
2420
+ .runner-utilization {
2421
+ height: 4px;
2422
+ background-color: #e9ecef;
2423
+ border-radius: 2px;
2424
+ overflow: hidden;
2425
+ }
2426
+
2427
+ .runner-utilization-fill {
2428
+ height: 100%;
2429
+ transition: width 0.3s ease;
2430
+ }
2431
+
2432
+ .runner-utilization-low {
2433
+ background-color: #198754;
2434
+ }
2435
+
2436
+ .runner-utilization-medium {
2437
+ background-color: #ffc107;
2438
+ }
2439
+
2440
+ .runner-utilization-high {
2441
+ background-color: #fd7e14;
2442
+ }
2443
+
2444
+ .runner-utilization-critical {
2445
+ background-color: #dc3545;
2446
+ }