@memberjunction/ng-explorer-core 5.24.0 → 5.25.0

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 (74) hide show
  1. package/dist/app-routing.module.d.ts.map +1 -1
  2. package/dist/app-routing.module.js +14 -19
  3. package/dist/app-routing.module.js.map +1 -1
  4. package/dist/generated/lazy-feature-config.js +3 -3
  5. package/dist/generated/lazy-feature-config.js.map +1 -1
  6. package/dist/lib/resource-wrappers/artifact-resource.component.d.ts.map +1 -1
  7. package/dist/lib/resource-wrappers/artifact-resource.component.js +1 -0
  8. package/dist/lib/resource-wrappers/artifact-resource.component.js.map +1 -1
  9. package/dist/lib/resource-wrappers/chat-collections-resource.component.d.ts +16 -17
  10. package/dist/lib/resource-wrappers/chat-collections-resource.component.d.ts.map +1 -1
  11. package/dist/lib/resource-wrappers/chat-collections-resource.component.js +56 -62
  12. package/dist/lib/resource-wrappers/chat-collections-resource.component.js.map +1 -1
  13. package/dist/lib/resource-wrappers/chat-conversations-resource.component.d.ts +2 -4
  14. package/dist/lib/resource-wrappers/chat-conversations-resource.component.d.ts.map +1 -1
  15. package/dist/lib/resource-wrappers/chat-conversations-resource.component.js +9 -13
  16. package/dist/lib/resource-wrappers/chat-conversations-resource.component.js.map +1 -1
  17. package/dist/lib/resource-wrappers/chat-tasks-resource.component.d.ts +2 -15
  18. package/dist/lib/resource-wrappers/chat-tasks-resource.component.d.ts.map +1 -1
  19. package/dist/lib/resource-wrappers/chat-tasks-resource.component.js +18 -52
  20. package/dist/lib/resource-wrappers/chat-tasks-resource.component.js.map +1 -1
  21. package/dist/lib/resource-wrappers/dashboard-resource.component.d.ts +2 -3
  22. package/dist/lib/resource-wrappers/dashboard-resource.component.d.ts.map +1 -1
  23. package/dist/lib/resource-wrappers/dashboard-resource.component.js +7 -9
  24. package/dist/lib/resource-wrappers/dashboard-resource.component.js.map +1 -1
  25. package/dist/lib/resource-wrappers/list-detail-resource.component.d.ts.map +1 -1
  26. package/dist/lib/resource-wrappers/list-detail-resource.component.js +1 -0
  27. package/dist/lib/resource-wrappers/list-detail-resource.component.js.map +1 -1
  28. package/dist/lib/resource-wrappers/notifications-resource.component.d.ts.map +1 -1
  29. package/dist/lib/resource-wrappers/notifications-resource.component.js +1 -0
  30. package/dist/lib/resource-wrappers/notifications-resource.component.js.map +1 -1
  31. package/dist/lib/resource-wrappers/query-resource.component.js +1 -0
  32. package/dist/lib/resource-wrappers/query-resource.component.js.map +1 -1
  33. package/dist/lib/resource-wrappers/search-results-resource.component.d.ts +74 -4
  34. package/dist/lib/resource-wrappers/search-results-resource.component.d.ts.map +1 -1
  35. package/dist/lib/resource-wrappers/search-results-resource.component.js +786 -25
  36. package/dist/lib/resource-wrappers/search-results-resource.component.js.map +1 -1
  37. package/dist/lib/resource-wrappers/view-resource.component.d.ts +7 -4
  38. package/dist/lib/resource-wrappers/view-resource.component.d.ts.map +1 -1
  39. package/dist/lib/resource-wrappers/view-resource.component.js +30 -14
  40. package/dist/lib/resource-wrappers/view-resource.component.js.map +1 -1
  41. package/dist/lib/shell/components/tabs/tab-container.component.d.ts.map +1 -1
  42. package/dist/lib/shell/components/tabs/tab-container.component.js +10 -3
  43. package/dist/lib/shell/components/tabs/tab-container.component.js.map +1 -1
  44. package/dist/lib/shell/shell.component.d.ts +28 -8
  45. package/dist/lib/shell/shell.component.d.ts.map +1 -1
  46. package/dist/lib/shell/shell.component.js +416 -218
  47. package/dist/lib/shell/shell.component.js.map +1 -1
  48. package/dist/lib/shell/shell.module.d.ts +2 -1
  49. package/dist/lib/shell/shell.module.d.ts.map +1 -1
  50. package/dist/lib/shell/shell.module.js +7 -3
  51. package/dist/lib/shell/shell.module.js.map +1 -1
  52. package/dist/lib/single-dashboard/Components/add-item/add-item.component.d.ts +6 -0
  53. package/dist/lib/single-dashboard/Components/add-item/add-item.component.d.ts.map +1 -1
  54. package/dist/lib/single-dashboard/Components/add-item/add-item.component.js +63 -38
  55. package/dist/lib/single-dashboard/Components/add-item/add-item.component.js.map +1 -1
  56. package/dist/lib/single-dashboard/single-dashboard.component.d.ts.map +1 -1
  57. package/dist/lib/single-dashboard/single-dashboard.component.js +1 -0
  58. package/dist/lib/single-dashboard/single-dashboard.component.js.map +1 -1
  59. package/dist/lib/user-menu/base-user-menu.d.ts +7 -7
  60. package/dist/lib/user-menu/base-user-menu.d.ts.map +1 -1
  61. package/dist/lib/user-menu/base-user-menu.js +8 -1
  62. package/dist/lib/user-menu/base-user-menu.js.map +1 -1
  63. package/dist/lib/user-menu/user-menu.types.d.ts +15 -0
  64. package/dist/lib/user-menu/user-menu.types.d.ts.map +1 -1
  65. package/dist/lib/user-menu/user-menu.types.js.map +1 -1
  66. package/dist/lib/user-notifications/user-notifications.component.d.ts +6 -3
  67. package/dist/lib/user-notifications/user-notifications.component.d.ts.map +1 -1
  68. package/dist/lib/user-notifications/user-notifications.component.js +46 -19
  69. package/dist/lib/user-notifications/user-notifications.component.js.map +1 -1
  70. package/dist/module.d.ts +3 -1
  71. package/dist/module.d.ts.map +1 -1
  72. package/dist/module.js +8 -0
  73. package/dist/module.js.map +1 -1
  74. package/package.json +40 -38
@@ -9,6 +9,7 @@ import { MJNotificationService } from '@memberjunction/ng-notifications';
9
9
  import { getActiveTheme } from './loading-themes';
10
10
  import { TabContainerComponent } from './components/tabs/tab-container.component';
11
11
  import { BaseUserMenu, isUserMenuDivider } from '../user-menu';
12
+ import { InstanceConfigEngine } from '@memberjunction/core-entities';
12
13
  import * as i0 from "@angular/core";
13
14
  import * as i1 from "@memberjunction/ng-base-application";
14
15
  import * as i2 from "@memberjunction/ng-shared";
@@ -17,19 +18,22 @@ import * as i4 from "@memberjunction/ng-auth-services";
17
18
  import * as i5 from "@memberjunction/ng-user-avatar";
18
19
  import * as i6 from "./services/settings-dialog.service";
19
20
  import * as i7 from "../command-palette/command-palette.service";
20
- import * as i8 from "@angular/forms";
21
- import * as i9 from "@memberjunction/ng-ui-components";
22
- import * as i10 from "@memberjunction/ng-shared-generic";
23
- import * as i11 from "./components/header/app-switcher.component";
24
- import * as i12 from "./components/header/app-nav.component";
25
- import * as i13 from "./components/tabs/tab-container.component";
26
- import * as i14 from "./components/dialogs/app-access-dialog.component";
27
- import * as i15 from "../command-palette/command-palette.component";
21
+ import * as i8 from "@memberjunction/ng-file-storage";
22
+ import * as i9 from "@angular/forms";
23
+ import * as i10 from "@memberjunction/ng-ui-components";
24
+ import * as i11 from "@memberjunction/ng-shared-generic";
25
+ import * as i12 from "@memberjunction/ng-search";
26
+ import * as i13 from "./components/header/app-switcher.component";
27
+ import * as i14 from "./components/header/app-nav.component";
28
+ import * as i15 from "./components/tabs/tab-container.component";
29
+ import * as i16 from "./components/dialogs/app-access-dialog.component";
30
+ import * as i17 from "../command-palette/command-palette.component";
28
31
  const _c0 = ["searchInput"];
29
- const _c1 = ["appAccessDialog"];
32
+ const _c1 = ["shellSearchComposite"];
33
+ const _c2 = ["appAccessDialog"];
30
34
  function ShellComponent_Conditional_5_For_2_Template(rf, ctx) { if (rf & 1) {
31
35
  const _r2 = i0.ɵɵgetCurrentView();
32
- i0.ɵɵelementStart(0, "button", 45);
36
+ i0.ɵɵelementStart(0, "button", 46);
33
37
  i0.ɵɵlistener("click", function ShellComponent_Conditional_5_For_2_Template_button_click_0_listener($event) { const app_r3 = i0.ɵɵrestoreView(_r2).$implicit; const ctx_r3 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r3.onNavBarAppClick(app_r3, $event)); })("dblclick", function ShellComponent_Conditional_5_For_2_Template_button_dblclick_0_listener($event) { const app_r3 = i0.ɵɵrestoreView(_r2).$implicit; const ctx_r3 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r3.onNavBarAppDblClick(app_r3, $event)); });
34
38
  i0.ɵɵelement(1, "i");
35
39
  i0.ɵɵelementEnd();
@@ -43,8 +47,8 @@ function ShellComponent_Conditional_5_For_2_Template(rf, ctx) { if (rf & 1) {
43
47
  i0.ɵɵclassMap(app_r3.Icon);
44
48
  } }
45
49
  function ShellComponent_Conditional_5_Template(rf, ctx) { if (rf & 1) {
46
- i0.ɵɵelementStart(0, "div", 7);
47
- i0.ɵɵrepeaterCreate(1, ShellComponent_Conditional_5_For_2_Template, 2, 7, "button", 44, i0.ɵɵrepeaterTrackByIdentity);
50
+ i0.ɵɵelementStart(0, "div", 8);
51
+ i0.ɵɵrepeaterCreate(1, ShellComponent_Conditional_5_For_2_Template, 2, 7, "button", 45, i0.ɵɵrepeaterTrackByIdentity);
48
52
  i0.ɵɵelementEnd();
49
53
  } if (rf & 2) {
50
54
  const ctx_r3 = i0.ɵɵnextContext();
@@ -53,14 +57,24 @@ function ShellComponent_Conditional_5_Template(rf, ctx) { if (rf & 1) {
53
57
  } }
54
58
  function ShellComponent_Conditional_7_Template(rf, ctx) { if (rf & 1) {
55
59
  const _r5 = i0.ɵɵgetCurrentView();
56
- i0.ɵɵelementStart(0, "mj-app-nav", 46);
60
+ i0.ɵɵelementStart(0, "mj-app-nav", 47);
57
61
  i0.ɵɵlistener("navItemClick", function ShellComponent_Conditional_7_Template_mj_app_nav_navItemClick_0_listener($event) { i0.ɵɵrestoreView(_r5); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.onNavItemClick($event)); })("navItemDismiss", function ShellComponent_Conditional_7_Template_mj_app_nav_navItemDismiss_0_listener($event) { i0.ɵɵrestoreView(_r5); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.onNavItemDismiss($event)); });
58
62
  i0.ɵɵelementEnd();
59
63
  } if (rf & 2) {
60
64
  const ctx_r3 = i0.ɵɵnextContext();
61
65
  i0.ɵɵproperty("app", ctx_r3.activeApp);
62
66
  } }
63
- function ShellComponent_Conditional_14_Template(rf, ctx) { if (rf & 1) {
67
+ function ShellComponent_Conditional_8_Template(rf, ctx) { if (rf & 1) {
68
+ const _r6 = i0.ɵɵgetCurrentView();
69
+ i0.ɵɵelementStart(0, "div", 11)(1, "mj-search-composite", 48, 2);
70
+ i0.ɵɵlistener("ResultSelected", function ShellComponent_Conditional_8_Template_mj_search_composite_ResultSelected_1_listener($event) { i0.ɵɵrestoreView(_r6); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.OnSearchResultSelected($event)); })("SearchSubmitted", function ShellComponent_Conditional_8_Template_mj_search_composite_SearchSubmitted_1_listener($event) { i0.ɵɵrestoreView(_r6); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.OnSearchSubmitted($event)); })("SeeAllRequested", function ShellComponent_Conditional_8_Template_mj_search_composite_SeeAllRequested_1_listener($event) { i0.ɵɵrestoreView(_r6); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.OnSeeAllSearch($event)); });
71
+ i0.ɵɵelementEnd()();
72
+ } if (rf & 2) {
73
+ const ctx_r3 = i0.ɵɵnextContext();
74
+ i0.ɵɵadvance();
75
+ i0.ɵɵproperty("ShowShortcutHint", true)("EnablePreview", ctx_r3.ShowSearchPreview)("EnableRecent", true)("MaxPreviewResults", 8);
76
+ } }
77
+ function ShellComponent_Conditional_13_Template(rf, ctx) { if (rf & 1) {
64
78
  i0.ɵɵelementStart(0, "span", 16);
65
79
  i0.ɵɵtext(1);
66
80
  i0.ɵɵelementEnd();
@@ -69,37 +83,37 @@ function ShellComponent_Conditional_14_Template(rf, ctx) { if (rf & 1) {
69
83
  i0.ɵɵadvance();
70
84
  i0.ɵɵtextInterpolate1(" ", ctx_r3.unreadNotificationCount > 99 ? "99+" : ctx_r3.unreadNotificationCount, " ");
71
85
  } }
72
- function ShellComponent_Conditional_15_For_2_Template(rf, ctx) { if (rf & 1) {
73
- const _r6 = i0.ɵɵgetCurrentView();
74
- i0.ɵɵelementStart(0, "button", 45);
75
- i0.ɵɵlistener("click", function ShellComponent_Conditional_15_For_2_Template_button_click_0_listener($event) { const app_r7 = i0.ɵɵrestoreView(_r6).$implicit; const ctx_r3 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r3.onNavBarAppClick(app_r7, $event)); })("dblclick", function ShellComponent_Conditional_15_For_2_Template_button_dblclick_0_listener($event) { const app_r7 = i0.ɵɵrestoreView(_r6).$implicit; const ctx_r3 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r3.onNavBarAppDblClick(app_r7, $event)); });
86
+ function ShellComponent_Conditional_14_For_2_Template(rf, ctx) { if (rf & 1) {
87
+ const _r7 = i0.ɵɵgetCurrentView();
88
+ i0.ɵɵelementStart(0, "button", 46);
89
+ i0.ɵɵlistener("click", function ShellComponent_Conditional_14_For_2_Template_button_click_0_listener($event) { const app_r8 = i0.ɵɵrestoreView(_r7).$implicit; const ctx_r3 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r3.onNavBarAppClick(app_r8, $event)); })("dblclick", function ShellComponent_Conditional_14_For_2_Template_button_dblclick_0_listener($event) { const app_r8 = i0.ɵɵrestoreView(_r7).$implicit; const ctx_r3 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r3.onNavBarAppDblClick(app_r8, $event)); });
76
90
  i0.ɵɵelement(1, "i");
77
91
  i0.ɵɵelementEnd();
78
92
  } if (rf & 2) {
79
- const app_r7 = ctx.$implicit;
93
+ const app_r8 = ctx.$implicit;
80
94
  const ctx_r3 = i0.ɵɵnextContext(2);
81
- i0.ɵɵstyleProp("--app-color", app_r7.GetColor());
82
- i0.ɵɵclassProp("active", ctx_r3.IsActiveApp(app_r7));
83
- i0.ɵɵproperty("title", app_r7.Name);
95
+ i0.ɵɵstyleProp("--app-color", app_r8.GetColor());
96
+ i0.ɵɵclassProp("active", ctx_r3.IsActiveApp(app_r8));
97
+ i0.ɵɵproperty("title", app_r8.Name);
84
98
  i0.ɵɵadvance();
85
- i0.ɵɵclassMap(app_r7.Icon);
99
+ i0.ɵɵclassMap(app_r8.Icon);
86
100
  } }
87
- function ShellComponent_Conditional_15_Template(rf, ctx) { if (rf & 1) {
101
+ function ShellComponent_Conditional_14_Template(rf, ctx) { if (rf & 1) {
88
102
  i0.ɵɵelementStart(0, "div", 17);
89
- i0.ɵɵrepeaterCreate(1, ShellComponent_Conditional_15_For_2_Template, 2, 7, "button", 44, i0.ɵɵrepeaterTrackByIdentity);
103
+ i0.ɵɵrepeaterCreate(1, ShellComponent_Conditional_14_For_2_Template, 2, 7, "button", 45, i0.ɵɵrepeaterTrackByIdentity);
90
104
  i0.ɵɵelementEnd();
91
105
  } if (rf & 2) {
92
106
  const ctx_r3 = i0.ɵɵnextContext();
93
107
  i0.ɵɵadvance();
94
108
  i0.ɵɵrepeater(ctx_r3.leftOfUserMenuApps);
95
109
  } }
96
- function ShellComponent_Conditional_18_Template(rf, ctx) { if (rf & 1) {
110
+ function ShellComponent_Conditional_17_Template(rf, ctx) { if (rf & 1) {
97
111
  i0.ɵɵelement(0, "img", 20);
98
112
  } if (rf & 2) {
99
113
  const ctx_r3 = i0.ɵɵnextContext();
100
114
  i0.ɵɵproperty("src", ctx_r3.userImageURL, i0.ɵɵsanitizeUrl);
101
115
  } }
102
- function ShellComponent_Conditional_19_Template(rf, ctx) { if (rf & 1) {
116
+ function ShellComponent_Conditional_18_Template(rf, ctx) { if (rf & 1) {
103
117
  i0.ɵɵelementStart(0, "div", 21);
104
118
  i0.ɵɵelement(1, "i");
105
119
  i0.ɵɵelementEnd();
@@ -108,8 +122,8 @@ function ShellComponent_Conditional_19_Template(rf, ctx) { if (rf & 1) {
108
122
  i0.ɵɵadvance();
109
123
  i0.ɵɵclassMap(ctx_r3.userIconClass || "fa-solid fa-user");
110
124
  } }
111
- function ShellComponent_Conditional_20_Conditional_1_Conditional_4_Template(rf, ctx) { if (rf & 1) {
112
- i0.ɵɵelementStart(0, "span", 51);
125
+ function ShellComponent_Conditional_19_Conditional_1_Conditional_4_Template(rf, ctx) { if (rf & 1) {
126
+ i0.ɵɵelementStart(0, "span", 53);
113
127
  i0.ɵɵtext(1);
114
128
  i0.ɵɵelementEnd();
115
129
  } if (rf & 2) {
@@ -118,107 +132,121 @@ function ShellComponent_Conditional_20_Conditional_1_Conditional_4_Template(rf,
118
132
  i0.ɵɵadvance();
119
133
  i0.ɵɵtextInterpolate1(" ", (tmp_5_0 = ctx_r3.getUserDisplayInfo()) == null ? null : tmp_5_0.email, " ");
120
134
  } }
121
- function ShellComponent_Conditional_20_Conditional_1_Template(rf, ctx) { if (rf & 1) {
122
- i0.ɵɵelementStart(0, "div", 48)(1, "div", 49)(2, "span", 50);
135
+ function ShellComponent_Conditional_19_Conditional_1_Conditional_5_Template(rf, ctx) { if (rf & 1) {
136
+ i0.ɵɵelementStart(0, "span", 54);
137
+ i0.ɵɵtext(1);
138
+ i0.ɵɵelementEnd();
139
+ } if (rf & 2) {
140
+ let tmp_5_0;
141
+ const ctx_r3 = i0.ɵɵnextContext(3);
142
+ i0.ɵɵadvance();
143
+ i0.ɵɵtextInterpolate((tmp_5_0 = ctx_r3.getUserDisplayInfo()) == null ? null : tmp_5_0.subtitle);
144
+ } }
145
+ function ShellComponent_Conditional_19_Conditional_1_Template(rf, ctx) { if (rf & 1) {
146
+ i0.ɵɵelementStart(0, "div", 50)(1, "div", 51)(2, "span", 52);
123
147
  i0.ɵɵtext(3);
124
148
  i0.ɵɵelementEnd();
125
- i0.ɵɵconditionalCreate(4, ShellComponent_Conditional_20_Conditional_1_Conditional_4_Template, 2, 1, "span", 51);
149
+ i0.ɵɵconditionalCreate(4, ShellComponent_Conditional_19_Conditional_1_Conditional_4_Template, 2, 1, "span", 53);
150
+ i0.ɵɵconditionalCreate(5, ShellComponent_Conditional_19_Conditional_1_Conditional_5_Template, 2, 1, "span", 54);
126
151
  i0.ɵɵelementEnd()();
127
- i0.ɵɵelement(5, "div", 52);
152
+ i0.ɵɵelement(6, "div", 55);
128
153
  } if (rf & 2) {
129
154
  let tmp_4_0;
130
155
  let tmp_5_0;
156
+ let tmp_6_0;
131
157
  const ctx_r3 = i0.ɵɵnextContext(2);
132
158
  i0.ɵɵadvance(3);
133
159
  i0.ɵɵtextInterpolate(((tmp_4_0 = ctx_r3.getUserDisplayInfo()) == null ? null : tmp_4_0.name) || ctx_r3.userName);
134
160
  i0.ɵɵadvance();
135
161
  i0.ɵɵconditional(((tmp_5_0 = ctx_r3.getUserMenuOptions()) == null ? null : tmp_5_0.showUserEmail) && ((tmp_5_0 = ctx_r3.getUserDisplayInfo()) == null ? null : tmp_5_0.email) ? 4 : -1);
162
+ i0.ɵɵadvance();
163
+ i0.ɵɵconditional(((tmp_6_0 = ctx_r3.getUserDisplayInfo()) == null ? null : tmp_6_0.subtitle) ? 5 : -1);
136
164
  } }
137
- function ShellComponent_Conditional_20_For_3_Conditional_0_Template(rf, ctx) { if (rf & 1) {
138
- i0.ɵɵelement(0, "div", 52);
165
+ function ShellComponent_Conditional_19_For_3_Conditional_0_Template(rf, ctx) { if (rf & 1) {
166
+ i0.ɵɵelement(0, "div", 55);
139
167
  } }
140
- function ShellComponent_Conditional_20_For_3_Conditional_1_Conditional_0_Conditional_0_Template(rf, ctx) { if (rf & 1) {
141
- const _r8 = i0.ɵɵgetCurrentView();
142
- i0.ɵɵelementStart(0, "div", 55);
143
- i0.ɵɵlistener("click", function ShellComponent_Conditional_20_For_3_Conditional_1_Conditional_0_Conditional_0_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r8); const item_r9 = i0.ɵɵnextContext(); const ctx_r3 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r3.onUserMenuItemClick(item_r9.id)); });
168
+ function ShellComponent_Conditional_19_For_3_Conditional_1_Conditional_0_Conditional_0_Template(rf, ctx) { if (rf & 1) {
169
+ const _r9 = i0.ɵɵgetCurrentView();
170
+ i0.ɵɵelementStart(0, "div", 58);
171
+ i0.ɵɵlistener("click", function ShellComponent_Conditional_19_For_3_Conditional_1_Conditional_0_Conditional_0_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r9); const item_r10 = i0.ɵɵnextContext(); const ctx_r3 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r3.onUserMenuItemClick(item_r10.id)); });
144
172
  i0.ɵɵelement(1, "i");
145
- i0.ɵɵelementStart(2, "span", 56);
173
+ i0.ɵɵelementStart(2, "span", 59);
146
174
  i0.ɵɵtext(3);
147
175
  i0.ɵɵelementEnd();
148
- i0.ɵɵelementStart(4, "div", 57)(5, "div", 58);
149
- i0.ɵɵelement(6, "i", 59);
176
+ i0.ɵɵelementStart(4, "div", 60)(5, "div", 61);
177
+ i0.ɵɵelement(6, "i", 62);
150
178
  i0.ɵɵelementEnd()()();
151
179
  } if (rf & 2) {
152
- const item_r9 = i0.ɵɵnextContext();
180
+ const item_r10 = i0.ɵɵnextContext();
153
181
  const ctx_r3 = i0.ɵɵnextContext(4);
154
- i0.ɵɵproperty("title", item_r9.tooltip || "");
182
+ i0.ɵɵproperty("title", item_r10.tooltip || "");
155
183
  i0.ɵɵadvance();
156
- i0.ɵɵclassMap(item_r9.icon);
184
+ i0.ɵɵclassMap(item_r10.icon);
157
185
  i0.ɵɵadvance(2);
158
- i0.ɵɵtextInterpolate(item_r9.label);
186
+ i0.ɵɵtextInterpolate(item_r10.label);
159
187
  i0.ɵɵadvance();
160
188
  i0.ɵɵclassProp("dark", ctx_r3.IsDarkMode);
161
189
  i0.ɵɵadvance(2);
162
190
  i0.ɵɵclassMap(ctx_r3.IsDarkMode ? "fa-solid fa-moon" : "fa-solid fa-sun");
163
191
  } }
164
- function ShellComponent_Conditional_20_For_3_Conditional_1_Conditional_0_Conditional_1_Conditional_4_Template(rf, ctx) { if (rf & 1) {
165
- i0.ɵɵelementStart(0, "span", 61);
192
+ function ShellComponent_Conditional_19_For_3_Conditional_1_Conditional_0_Conditional_1_Conditional_4_Template(rf, ctx) { if (rf & 1) {
193
+ i0.ɵɵelementStart(0, "span", 64);
166
194
  i0.ɵɵtext(1);
167
195
  i0.ɵɵelementEnd();
168
196
  } if (rf & 2) {
169
- const item_r9 = i0.ɵɵnextContext(2);
197
+ const item_r10 = i0.ɵɵnextContext(2);
170
198
  i0.ɵɵadvance();
171
- i0.ɵɵtextInterpolate(item_r9.shortcut);
199
+ i0.ɵɵtextInterpolate(item_r10.shortcut);
172
200
  } }
173
- function ShellComponent_Conditional_20_For_3_Conditional_1_Conditional_0_Conditional_1_Template(rf, ctx) { if (rf & 1) {
174
- const _r10 = i0.ɵɵgetCurrentView();
175
- i0.ɵɵelementStart(0, "div", 60);
176
- i0.ɵɵlistener("click", function ShellComponent_Conditional_20_For_3_Conditional_1_Conditional_0_Conditional_1_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r10); const item_r9 = i0.ɵɵnextContext(); const ctx_r3 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(item_r9.enabled && ctx_r3.onUserMenuItemClick(item_r9.id)); });
201
+ function ShellComponent_Conditional_19_For_3_Conditional_1_Conditional_0_Conditional_1_Template(rf, ctx) { if (rf & 1) {
202
+ const _r11 = i0.ɵɵgetCurrentView();
203
+ i0.ɵɵelementStart(0, "div", 63);
204
+ i0.ɵɵlistener("click", function ShellComponent_Conditional_19_For_3_Conditional_1_Conditional_0_Conditional_1_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r11); const item_r10 = i0.ɵɵnextContext(); const ctx_r3 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(item_r10.enabled && ctx_r3.onUserMenuItemClick(item_r10.id)); });
177
205
  i0.ɵɵelement(1, "i");
178
- i0.ɵɵelementStart(2, "span", 56);
206
+ i0.ɵɵelementStart(2, "span", 59);
179
207
  i0.ɵɵtext(3);
180
208
  i0.ɵɵelementEnd();
181
- i0.ɵɵconditionalCreate(4, ShellComponent_Conditional_20_For_3_Conditional_1_Conditional_0_Conditional_1_Conditional_4_Template, 2, 1, "span", 61);
209
+ i0.ɵɵconditionalCreate(4, ShellComponent_Conditional_19_For_3_Conditional_1_Conditional_0_Conditional_1_Conditional_4_Template, 2, 1, "span", 64);
182
210
  i0.ɵɵelementEnd();
183
211
  } if (rf & 2) {
184
- const item_r9 = i0.ɵɵnextContext();
185
- i0.ɵɵstyleProp("color", item_r9.color || null);
186
- i0.ɵɵclassProp("disabled", !item_r9.enabled)("danger", item_r9.cssClass === "danger");
187
- i0.ɵɵproperty("title", item_r9.tooltip || "");
212
+ const item_r10 = i0.ɵɵnextContext();
213
+ i0.ɵɵstyleProp("color", item_r10.color || null);
214
+ i0.ɵɵclassProp("disabled", !item_r10.enabled)("danger", item_r10.cssClass === "danger");
215
+ i0.ɵɵproperty("title", item_r10.tooltip || "");
188
216
  i0.ɵɵadvance();
189
- i0.ɵɵclassMap(item_r9.icon);
217
+ i0.ɵɵclassMap(item_r10.icon);
190
218
  i0.ɵɵadvance(2);
191
- i0.ɵɵtextInterpolate(item_r9.label);
219
+ i0.ɵɵtextInterpolate(item_r10.label);
192
220
  i0.ɵɵadvance();
193
- i0.ɵɵconditional(item_r9.shortcut ? 4 : -1);
221
+ i0.ɵɵconditional(item_r10.shortcut ? 4 : -1);
194
222
  } }
195
- function ShellComponent_Conditional_20_For_3_Conditional_1_Conditional_0_Template(rf, ctx) { if (rf & 1) {
196
- i0.ɵɵconditionalCreate(0, ShellComponent_Conditional_20_For_3_Conditional_1_Conditional_0_Conditional_0_Template, 7, 8, "div", 53)(1, ShellComponent_Conditional_20_For_3_Conditional_1_Conditional_0_Conditional_1_Template, 5, 11, "div", 54);
223
+ function ShellComponent_Conditional_19_For_3_Conditional_1_Conditional_0_Template(rf, ctx) { if (rf & 1) {
224
+ i0.ɵɵconditionalCreate(0, ShellComponent_Conditional_19_For_3_Conditional_1_Conditional_0_Conditional_0_Template, 7, 8, "div", 56)(1, ShellComponent_Conditional_19_For_3_Conditional_1_Conditional_0_Conditional_1_Template, 5, 11, "div", 57);
197
225
  } if (rf & 2) {
198
226
  i0.ɵɵconditional(ctx.id === "toggle-theme" ? 0 : 1);
199
227
  } }
200
- function ShellComponent_Conditional_20_For_3_Conditional_1_Template(rf, ctx) { if (rf & 1) {
201
- i0.ɵɵconditionalCreate(0, ShellComponent_Conditional_20_For_3_Conditional_1_Conditional_0_Template, 2, 1);
228
+ function ShellComponent_Conditional_19_For_3_Conditional_1_Template(rf, ctx) { if (rf & 1) {
229
+ i0.ɵɵconditionalCreate(0, ShellComponent_Conditional_19_For_3_Conditional_1_Conditional_0_Template, 2, 1);
202
230
  } if (rf & 2) {
203
231
  let tmp_14_0;
204
- const element_r11 = i0.ɵɵnextContext().$implicit;
232
+ const element_r12 = i0.ɵɵnextContext().$implicit;
205
233
  const ctx_r3 = i0.ɵɵnextContext(2);
206
- i0.ɵɵconditional((tmp_14_0 = ctx_r3.asMenuItem(element_r11)) ? 0 : -1, tmp_14_0);
234
+ i0.ɵɵconditional((tmp_14_0 = ctx_r3.asMenuItem(element_r12)) ? 0 : -1, tmp_14_0);
207
235
  } }
208
- function ShellComponent_Conditional_20_For_3_Template(rf, ctx) { if (rf & 1) {
209
- i0.ɵɵconditionalCreate(0, ShellComponent_Conditional_20_For_3_Conditional_0_Template, 1, 0, "div", 52);
210
- i0.ɵɵconditionalCreate(1, ShellComponent_Conditional_20_For_3_Conditional_1_Template, 1, 1);
236
+ function ShellComponent_Conditional_19_For_3_Template(rf, ctx) { if (rf & 1) {
237
+ i0.ɵɵconditionalCreate(0, ShellComponent_Conditional_19_For_3_Conditional_0_Template, 1, 0, "div", 55);
238
+ i0.ɵɵconditionalCreate(1, ShellComponent_Conditional_19_For_3_Conditional_1_Template, 1, 1);
211
239
  } if (rf & 2) {
212
- const element_r11 = ctx.$implicit;
240
+ const element_r12 = ctx.$implicit;
213
241
  const ctx_r3 = i0.ɵɵnextContext(2);
214
- i0.ɵɵconditional(ctx_r3.isMenuDivider(element_r11) ? 0 : -1);
242
+ i0.ɵɵconditional(ctx_r3.isMenuDivider(element_r12) ? 0 : -1);
215
243
  i0.ɵɵadvance();
216
- i0.ɵɵconditional(!ctx_r3.isMenuDivider(element_r11) ? 1 : -1);
244
+ i0.ɵɵconditional(!ctx_r3.isMenuDivider(element_r12) ? 1 : -1);
217
245
  } }
218
- function ShellComponent_Conditional_20_Template(rf, ctx) { if (rf & 1) {
219
- i0.ɵɵelementStart(0, "div", 47);
220
- i0.ɵɵconditionalCreate(1, ShellComponent_Conditional_20_Conditional_1_Template, 6, 2);
221
- i0.ɵɵrepeaterCreate(2, ShellComponent_Conditional_20_For_3_Template, 2, 2, null, null, i0.ɵɵrepeaterTrackByIdentity);
246
+ function ShellComponent_Conditional_19_Template(rf, ctx) { if (rf & 1) {
247
+ i0.ɵɵelementStart(0, "div", 49);
248
+ i0.ɵɵconditionalCreate(1, ShellComponent_Conditional_19_Conditional_1_Template, 7, 3);
249
+ i0.ɵɵrepeaterCreate(2, ShellComponent_Conditional_19_For_3_Template, 2, 2, null, null, i0.ɵɵrepeaterTrackByIdentity);
222
250
  i0.ɵɵelementEnd();
223
251
  } if (rf & 2) {
224
252
  let tmp_3_0;
@@ -231,25 +259,25 @@ function ShellComponent_Conditional_20_Template(rf, ctx) { if (rf & 1) {
231
259
  i0.ɵɵadvance();
232
260
  i0.ɵɵrepeater(ctx_r3.userMenuElements);
233
261
  } }
234
- function ShellComponent_Conditional_21_Template(rf, ctx) { if (rf & 1) {
235
- const _r12 = i0.ɵɵgetCurrentView();
236
- i0.ɵɵelementStart(0, "div", 62);
237
- i0.ɵɵlistener("click", function ShellComponent_Conditional_21_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r12); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.closeSearch()); });
238
- i0.ɵɵelementEnd();
239
- } }
240
- function ShellComponent_Conditional_29_Template(rf, ctx) { if (rf & 1) {
262
+ function ShellComponent_Conditional_20_Template(rf, ctx) { if (rf & 1) {
241
263
  const _r13 = i0.ɵɵgetCurrentView();
242
- i0.ɵɵelementStart(0, "div", 63);
243
- i0.ɵɵlistener("click", function ShellComponent_Conditional_29_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r13); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.closeMobileNav()); });
264
+ i0.ɵɵelementStart(0, "div", 65);
265
+ i0.ɵɵlistener("click", function ShellComponent_Conditional_20_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r13); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.closeSearch()); });
244
266
  i0.ɵɵelementEnd();
245
267
  } }
246
- function ShellComponent_Conditional_36_Template(rf, ctx) { if (rf & 1) {
268
+ function ShellComponent_Conditional_28_Template(rf, ctx) { if (rf & 1) {
247
269
  const _r14 = i0.ɵɵgetCurrentView();
248
- i0.ɵɵelementStart(0, "div", 34)(1, "div", 64);
270
+ i0.ɵɵelementStart(0, "div", 66);
271
+ i0.ɵɵlistener("click", function ShellComponent_Conditional_28_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r14); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.closeMobileNav()); });
272
+ i0.ɵɵelementEnd();
273
+ } }
274
+ function ShellComponent_Conditional_35_Template(rf, ctx) { if (rf & 1) {
275
+ const _r15 = i0.ɵɵgetCurrentView();
276
+ i0.ɵɵelementStart(0, "div", 35)(1, "div", 67);
249
277
  i0.ɵɵtext(2);
250
278
  i0.ɵɵelementEnd();
251
- i0.ɵɵelementStart(3, "mj-app-nav", 65);
252
- i0.ɵɵlistener("navItemClick", function ShellComponent_Conditional_36_Template_mj_app_nav_navItemClick_3_listener($event) { i0.ɵɵrestoreView(_r14); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.onNavItemClick($event)); })("navItemDismiss", function ShellComponent_Conditional_36_Template_mj_app_nav_navItemDismiss_3_listener($event) { i0.ɵɵrestoreView(_r14); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.onNavItemDismiss($event)); });
279
+ i0.ɵɵelementStart(3, "mj-app-nav", 68);
280
+ i0.ɵɵlistener("navItemClick", function ShellComponent_Conditional_35_Template_mj_app_nav_navItemClick_3_listener($event) { i0.ɵɵrestoreView(_r15); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.onNavItemClick($event)); })("navItemDismiss", function ShellComponent_Conditional_35_Template_mj_app_nav_navItemDismiss_3_listener($event) { i0.ɵɵrestoreView(_r15); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.onNavItemDismiss($event)); });
253
281
  i0.ɵɵelementEnd()();
254
282
  } if (rf & 2) {
255
283
  const ctx_r3 = i0.ɵɵnextContext();
@@ -258,8 +286,8 @@ function ShellComponent_Conditional_36_Template(rf, ctx) { if (rf & 1) {
258
286
  i0.ɵɵadvance();
259
287
  i0.ɵɵproperty("app", ctx_r3.activeApp);
260
288
  } }
261
- function ShellComponent_Conditional_46_Template(rf, ctx) { if (rf & 1) {
262
- i0.ɵɵelementStart(0, "span", 38);
289
+ function ShellComponent_Conditional_45_Template(rf, ctx) { if (rf & 1) {
290
+ i0.ɵɵelementStart(0, "span", 39);
263
291
  i0.ɵɵtext(1);
264
292
  i0.ɵɵelementEnd();
265
293
  } if (rf & 2) {
@@ -267,25 +295,25 @@ function ShellComponent_Conditional_46_Template(rf, ctx) { if (rf & 1) {
267
295
  i0.ɵɵadvance();
268
296
  i0.ɵɵtextInterpolate1(" ", ctx_r3.unreadNotificationCount > 99 ? "99+" : ctx_r3.unreadNotificationCount, " ");
269
297
  } }
270
- function ShellComponent_Conditional_48_Conditional_2_Template(rf, ctx) { if (rf & 1) {
271
- const _r15 = i0.ɵɵgetCurrentView();
272
- i0.ɵɵelementStart(0, "div", 67)(1, "p", 68);
273
- i0.ɵɵelement(2, "i", 69);
298
+ function ShellComponent_Conditional_47_Conditional_2_Template(rf, ctx) { if (rf & 1) {
299
+ const _r16 = i0.ɵɵgetCurrentView();
300
+ i0.ɵɵelementStart(0, "div", 70)(1, "p", 71);
301
+ i0.ɵɵelement(2, "i", 72);
274
302
  i0.ɵɵtext(3, " Taking longer than expected ");
275
303
  i0.ɵɵelementEnd();
276
- i0.ɵɵelementStart(4, "p", 70);
304
+ i0.ɵɵelementStart(4, "p", 73);
277
305
  i0.ɵɵtext(5, " This can happen after updates or due to cached data issues. ");
278
306
  i0.ɵɵelementEnd();
279
- i0.ɵɵelementStart(6, "button", 71);
280
- i0.ɵɵlistener("click", function ShellComponent_Conditional_48_Conditional_2_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r15); const ctx_r3 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r3.ResetApplication()); });
281
- i0.ɵɵelement(7, "i", 72);
307
+ i0.ɵɵelementStart(6, "button", 74);
308
+ i0.ɵɵlistener("click", function ShellComponent_Conditional_47_Conditional_2_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r16); const ctx_r3 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r3.ResetApplication()); });
309
+ i0.ɵɵelement(7, "i", 75);
282
310
  i0.ɵɵtext(8, " Reset ");
283
311
  i0.ɵɵelementEnd()();
284
312
  } }
285
- function ShellComponent_Conditional_48_Template(rf, ctx) { if (rf & 1) {
286
- i0.ɵɵelementStart(0, "div", 40);
287
- i0.ɵɵelement(1, "mj-loading", 66);
288
- i0.ɵɵconditionalCreate(2, ShellComponent_Conditional_48_Conditional_2_Template, 9, 0, "div", 67);
313
+ function ShellComponent_Conditional_47_Template(rf, ctx) { if (rf & 1) {
314
+ i0.ɵɵelementStart(0, "div", 41);
315
+ i0.ɵɵelement(1, "mj-loading", 69);
316
+ i0.ɵɵconditionalCreate(2, ShellComponent_Conditional_47_Conditional_2_Template, 9, 0, "div", 70);
289
317
  i0.ɵɵelementEnd();
290
318
  } if (rf & 2) {
291
319
  const ctx_r3 = i0.ɵɵnextContext();
@@ -294,10 +322,10 @@ function ShellComponent_Conditional_48_Template(rf, ctx) { if (rf & 1) {
294
322
  i0.ɵɵadvance();
295
323
  i0.ɵɵconditional(ctx_r3.ShowResetOption ? 2 : -1);
296
324
  } }
297
- function ShellComponent_Conditional_52_Template(rf, ctx) { if (rf & 1) {
298
- i0.ɵɵelementStart(0, "div", 43)(1, "div", 73);
299
- i0.ɵɵelement(2, "mj-loading", 74);
300
- i0.ɵɵelementStart(3, "span", 75);
325
+ function ShellComponent_Conditional_51_Template(rf, ctx) { if (rf & 1) {
326
+ i0.ɵɵelementStart(0, "div", 44)(1, "div", 76);
327
+ i0.ɵɵelement(2, "mj-loading", 77);
328
+ i0.ɵɵelementStart(3, "span", 78);
301
329
  i0.ɵɵtext(4);
302
330
  i0.ɵɵelementEnd()()();
303
331
  } if (rf & 2) {
@@ -333,10 +361,10 @@ export class ShellComponent {
333
361
  commandPaletteService;
334
362
  themeService;
335
363
  homePinService;
364
+ fileOpenService;
336
365
  subscriptions = [];
337
366
  urlBasedNavigation = false; // Track if we're loading from a URL
338
367
  initialNavigationComplete = false; // Track if initial navigation has completed
339
- firstUrlSync = true; // Track if this is the first URL sync (for replaceUrl behavior)
340
368
  activeApp = null;
341
369
  loading = true;
342
370
  initialized = false;
@@ -389,6 +417,15 @@ export class ShellComponent {
389
417
  searchableEntities = [];
390
418
  selectedEntity = null;
391
419
  searchInput;
420
+ // Universal search bar
421
+ shellSearchComposite;
422
+ // Instance configuration feature flags
423
+ get ShowSearchBar() {
424
+ return InstanceConfigEngine.Instance.GetBoolean('Shell.SearchBar.Enabled', true);
425
+ }
426
+ get ShowSearchPreview() {
427
+ return InstanceConfigEngine.Instance.GetBoolean('Shell.SearchBar.EnablePreview', true);
428
+ }
392
429
  // Tab container reference for thumbnail capture
393
430
  tabContainerRef;
394
431
  // App access dialog
@@ -410,7 +447,7 @@ export class ShellComponent {
410
447
  return this.appManager.GetNavBarApps('Left of User Menu')
411
448
  .filter(app => !(app.HideNavBarIconWhenActive && UUIDsEqual(app.ID, this.activeApp?.ID)));
412
449
  }
413
- constructor(appManager, workspaceManager, layoutManager, tabService, navigationService, route, router, authBase, cdr, userAvatarService, settingsDialogService, viewContainerRef, titleService, developerModeService, commandPaletteService, themeService, homePinService) {
450
+ constructor(appManager, workspaceManager, layoutManager, tabService, navigationService, route, router, authBase, cdr, userAvatarService, settingsDialogService, viewContainerRef, titleService, developerModeService, commandPaletteService, themeService, homePinService, fileOpenService) {
414
451
  this.appManager = appManager;
415
452
  this.workspaceManager = workspaceManager;
416
453
  this.layoutManager = layoutManager;
@@ -428,6 +465,7 @@ export class ShellComponent {
428
465
  this.commandPaletteService = commandPaletteService;
429
466
  this.themeService = themeService;
430
467
  this.homePinService = homePinService;
468
+ this.fileOpenService = fileOpenService;
431
469
  // Initialize theme immediately so loading UI shows correct colors from the start
432
470
  this.activeTheme = getActiveTheme();
433
471
  // Initialize animation based on theme configuration
@@ -481,6 +519,10 @@ export class ShellComponent {
481
519
  // Initialize application manager (subscribes to LoggedIn event)
482
520
  this.appManager.Initialize();
483
521
  await StartupManager.Instance.Startup();
522
+ // Initialize instance configuration for feature flags
523
+ await InstanceConfigEngine.Instance.Config(false).catch(() => {
524
+ LogStatus('InstanceConfigEngine initialization skipped (not critical)');
525
+ });
484
526
  // Get current user
485
527
  const md = new Metadata();
486
528
  const user = md.CurrentUser;
@@ -627,12 +669,21 @@ export class ShellComponent {
627
669
  await this.loadSearchableEntities();
628
670
  this.initialized = true;
629
671
  this.waitingForFirstResource = true;
630
- // Trigger initial URL sync: the Configuration BehaviorSubject already emitted
631
- // its value when the shell subscribed (line above), but this.initialized was false
632
- // at that point so syncUrlWithWorkspace() was skipped. Now that we're initialized,
633
- // manually trigger the first URL sync to set the browser URL from workspace state.
672
+ // Decide whether to restore workspace state or honor the current URL.
673
+ // If the user navigated to a specific path (deep link, bookmark, typed URL),
674
+ // that URL takes priority the ResourceResolver will handle tab creation.
675
+ // Only restore workspace state when the URL is bare root (/) or empty.
676
+ const initialUrl = this.router.url.split('?')[0]; // ignore query params for this check
677
+ const isDeepLink = initialUrl.length > 1 && initialUrl !== '/';
634
678
  const initConfig = this.workspaceManager.GetConfiguration();
635
- if (initConfig && initConfig.activeTabId) {
679
+ if (isDeepLink) {
680
+ // User navigated to a specific URL — sync workspace to match the URL,
681
+ // not the other way around. The ResourceResolver will have created a tab
682
+ // for this URL; we just need to activate it.
683
+ await this.syncWorkspaceWithUrl(this.router.url);
684
+ }
685
+ else if (initConfig && initConfig.activeTabId) {
686
+ // Bare root URL — restore last workspace state
636
687
  await this.syncActiveAppWithTab(initConfig);
637
688
  this.syncUrlWithWorkspace(initConfig);
638
689
  }
@@ -759,10 +810,7 @@ export class ShellComponent {
759
810
  // Suppress ResourceResolver for this navigation - we're just syncing the URL
760
811
  // to reflect the current active tab, not requesting a new tab to be opened
761
812
  this.tabService.SuppressNextResolve();
762
- // Replace URL on first sync (initialization), push new history entries after that
763
- const replaceUrl = this.firstUrlSync;
764
- this.firstUrlSync = false;
765
- this.router.navigateByUrl(resourceUrl, { replaceUrl });
813
+ this.router.navigateByUrl(resourceUrl);
766
814
  }
767
815
  }
768
816
  }
@@ -781,12 +829,54 @@ export class ShellComponent {
781
829
  // Activate the matching tab
782
830
  this.workspaceManager.SetActiveTab(matchingTab.id);
783
831
  }
832
+ else if (matchingTab && matchingTab.id === config.activeTabId) {
833
+ // Same tab is already active, but query params may have changed (back/forward within nav item)
834
+ const urlParams = this.extractQueryParamsFromUrl(url);
835
+ const tabParams = (matchingTab.configuration?.['queryParams'] || {});
836
+ if (!this.queryParamsEqual(urlParams, tabParams)) {
837
+ // URL is source of truth during back/forward — update tab config to match.
838
+ this.urlBasedNavigation = true;
839
+ try {
840
+ this.workspaceManager.UpdateTabConfiguration(matchingTab.id, {
841
+ queryParams: Object.keys(urlParams).length > 0 ? urlParams : undefined
842
+ });
843
+ this.navigationService.NotifyQueryParamsChanged(matchingTab.id, urlParams);
844
+ }
845
+ finally {
846
+ this.urlBasedNavigation = false;
847
+ }
848
+ }
849
+ }
784
850
  else if (!matchingTab) {
785
- // No matching tab found - check if this is an app-only URL for an app with zero nav items
786
- // If so, we need to create a new tab for it (the old one was replaced when navigating away)
787
851
  await this.handleMissingTabForUrl(url);
788
852
  }
789
853
  }
854
+ /**
855
+ * Extract query params from a URL string, stripping any fragment (#hash).
856
+ */
857
+ extractQueryParamsFromUrl(url) {
858
+ const fragmentIndex = url.indexOf('#');
859
+ const cleanUrl = fragmentIndex !== -1 ? url.substring(0, fragmentIndex) : url;
860
+ const queryIndex = cleanUrl.indexOf('?');
861
+ if (queryIndex === -1)
862
+ return {};
863
+ const params = new URLSearchParams(cleanUrl.substring(queryIndex + 1));
864
+ const result = {};
865
+ params.forEach((value, key) => { result[key] = value; });
866
+ return result;
867
+ }
868
+ /**
869
+ * Compare two query param records for equality, normalizing encoding differences
870
+ * (URLSearchParams encodes spaces as +, Angular Router uses %20).
871
+ */
872
+ queryParamsEqual(a, b) {
873
+ const keysA = Object.keys(a);
874
+ const keysB = Object.keys(b);
875
+ if (keysA.length !== keysB.length)
876
+ return false;
877
+ return keysA.every(key => decodeURIComponent(a[key]?.replace(/\+/g, ' ') || '') ===
878
+ decodeURIComponent(b[key]?.replace(/\+/g, ' ') || ''));
879
+ }
790
880
  /**
791
881
  * Handle the case where no tab matches the URL during back/forward navigation.
792
882
  * Creates new tabs for resources when the original tab was replaced.
@@ -851,6 +941,36 @@ export class ShellComponent {
851
941
  this.navigationService.OpenReport(reportId, 'Report');
852
942
  return;
853
943
  }
944
+ // Check for app-scoped search URL: /app/:appName/search/:searchInput
945
+ const appSearchMatch = urlPath.match(/^\/app\/([^\/]+)\/search\/(.+)$/);
946
+ if (appSearchMatch) {
947
+ const searchInput = decodeURIComponent(appSearchMatch[2]);
948
+ this.navigationService.OpenSearch(searchInput);
949
+ return;
950
+ }
951
+ // Check for app nav item URL: /app/:appName/:navItemName
952
+ const appNavItemMatch = urlPath.match(/^\/app\/([^\/]+)\/([^\/]+)$/);
953
+ if (appNavItemMatch) {
954
+ const appPath = decodeURIComponent(appNavItemMatch[1]);
955
+ const navItemName = decodeURIComponent(appNavItemMatch[2]);
956
+ const app = this.appManager.GetAppByPath(appPath) || this.appManager.GetAppByName(appPath);
957
+ if (app) {
958
+ // Activate the app and open the nav item
959
+ await this.appManager.SetActiveApp(app.ID);
960
+ const navItems = await app.GetNavItems();
961
+ const navItem = navItems.find(item => item.Label === navItemName);
962
+ if (navItem) {
963
+ // Parse query params to pass as configuration
964
+ const qpObj = {};
965
+ queryParams.forEach((value, key) => { qpObj[key] = value; });
966
+ this.navigationService.OpenNavItem(app.ID, navItem, app.GetColor(), Object.keys(qpObj).length > 0 ? { queryParams: qpObj } : undefined);
967
+ }
968
+ else {
969
+ console.warn('handleMissingTabForUrl: nav item not found:', navItemName, 'in app:', appPath);
970
+ }
971
+ }
972
+ return;
973
+ }
854
974
  // Check for app-only URL: /app/:appName
855
975
  const appOnlyMatch = urlPath.match(/^\/app\/([^\/]+)$/);
856
976
  if (appOnlyMatch) {
@@ -868,6 +988,14 @@ export class ShellComponent {
868
988
  this.workspaceManager.OpenTab(defaultTab, app.GetColor());
869
989
  }
870
990
  }
991
+ else {
992
+ // App has nav items — activate the app and its default nav item
993
+ await this.appManager.SetActiveApp(app.ID);
994
+ const defaultNavItem = navItems.find(item => item.isDefault) || navItems[0];
995
+ if (defaultNavItem) {
996
+ this.navigationService.OpenNavItem(app.ID, defaultNavItem, app.GetColor());
997
+ }
998
+ }
871
999
  }
872
1000
  return;
873
1001
  }
@@ -1122,6 +1250,14 @@ export class ShellComponent {
1122
1250
  const queryParams = config['queryParams'];
1123
1251
  const isAppDefault = config['isAppDefault'];
1124
1252
  const tabAppId = tab.applicationId;
1253
+ // Helper to append query params to a URL, preserving any existing params
1254
+ const appendQP = (url) => {
1255
+ if (!queryParams || Object.keys(queryParams).length === 0)
1256
+ return url;
1257
+ const separator = url.includes('?') ? '&' : '?';
1258
+ const params = new URLSearchParams(queryParams);
1259
+ return `${url}${separator}${params.toString()}`;
1260
+ };
1125
1261
  // Helper function to get app path for URL
1126
1262
  const getAppPath = (appIdOrName) => {
1127
1263
  // First try by ID
@@ -1223,7 +1359,7 @@ export class ShellComponent {
1223
1359
  case 'records':
1224
1360
  // /app/:appName/record/:entityName/:recordId
1225
1361
  if (entityName && recordId) {
1226
- return `/app/${encodeURIComponent(appPath)}/record/${encodeURIComponent(entityName)}/${recordId}`;
1362
+ return appendQP(`/app/${encodeURIComponent(appPath)}/record/${encodeURIComponent(entityName)}/${recordId}`);
1227
1363
  }
1228
1364
  break;
1229
1365
  case 'user views':
@@ -1235,56 +1371,67 @@ export class ShellComponent {
1235
1371
  if (extraFilter) {
1236
1372
  url += `?ExtraFilter=${encodeURIComponent(extraFilter)}`;
1237
1373
  }
1238
- return url;
1374
+ return appendQP(url);
1239
1375
  }
1240
1376
  }
1241
1377
  else if (recordId) {
1242
1378
  // /app/:appName/view/:viewId (saved view)
1243
- return `/app/${encodeURIComponent(appPath)}/view/${recordId}`;
1379
+ return appendQP(`/app/${encodeURIComponent(appPath)}/view/${recordId}`);
1244
1380
  }
1245
1381
  break;
1246
1382
  case 'dashboards':
1247
1383
  // /app/:appName/dashboard/:dashboardId
1248
1384
  if (recordId) {
1249
- return `/app/${encodeURIComponent(appPath)}/dashboard/${recordId}`;
1385
+ return appendQP(`/app/${encodeURIComponent(appPath)}/dashboard/${recordId}`);
1250
1386
  }
1251
1387
  break;
1252
1388
  case 'artifacts':
1253
1389
  // /app/:appName/artifact/:artifactId
1254
1390
  if (recordId) {
1255
- return `/app/${encodeURIComponent(appPath)}/artifact/${recordId}`;
1391
+ return appendQP(`/app/${encodeURIComponent(appPath)}/artifact/${recordId}`);
1256
1392
  }
1257
1393
  break;
1258
1394
  case 'queries':
1259
1395
  // /app/:appName/query/:queryId
1260
1396
  if (recordId) {
1261
- return `/app/${encodeURIComponent(appPath)}/query/${recordId}`;
1397
+ return appendQP(`/app/${encodeURIComponent(appPath)}/query/${recordId}`);
1262
1398
  }
1263
1399
  break;
1264
1400
  case 'reports':
1265
1401
  // /app/:appName/report/:reportId
1266
1402
  if (recordId) {
1267
- return `/app/${encodeURIComponent(appPath)}/report/${recordId}`;
1403
+ return appendQP(`/app/${encodeURIComponent(appPath)}/report/${recordId}`);
1268
1404
  }
1269
1405
  break;
1270
- case 'search results':
1271
- // /app/:appName/search/:searchInput?Entity=...
1406
+ case 'search results': {
1407
+ // /app/:appName/search/:searchInput?minRelevance=...&Entity=...
1272
1408
  const searchInput = config['SearchInput'];
1273
1409
  if (searchInput) {
1274
1410
  let url = `/app/${encodeURIComponent(appPath)}/search/${encodeURIComponent(searchInput)}`;
1411
+ const searchParams = new URLSearchParams();
1275
1412
  if (entityName) {
1276
- url += `?Entity=${encodeURIComponent(entityName)}`;
1413
+ searchParams.set('Entity', entityName);
1414
+ }
1415
+ if (queryParams) {
1416
+ for (const [key, value] of Object.entries(queryParams)) {
1417
+ if (value != null)
1418
+ searchParams.set(key, value);
1419
+ }
1420
+ }
1421
+ if (searchParams.toString()) {
1422
+ url += `?${searchParams.toString()}`;
1277
1423
  }
1278
1424
  return url;
1279
1425
  }
1280
1426
  break;
1427
+ }
1281
1428
  }
1282
1429
  }
1283
1430
  // Fallback to legacy routes (for backward compatibility during transition)
1284
1431
  switch (resourceType) {
1285
1432
  case 'records':
1286
1433
  if (entityName && recordId) {
1287
- return `/resource/record/${encodeURIComponent(entityName)}/${recordId}`;
1434
+ return appendQP(`/resource/record/${encodeURIComponent(entityName)}/${recordId}`);
1288
1435
  }
1289
1436
  break;
1290
1437
  case 'user views':
@@ -1294,26 +1441,26 @@ export class ShellComponent {
1294
1441
  if (extraFilter) {
1295
1442
  url += `?ExtraFilter=${encodeURIComponent(extraFilter)}`;
1296
1443
  }
1297
- return url;
1444
+ return appendQP(url);
1298
1445
  }
1299
1446
  }
1300
1447
  else if (recordId) {
1301
- return `/resource/view/${recordId}`;
1448
+ return appendQP(`/resource/view/${recordId}`);
1302
1449
  }
1303
1450
  break;
1304
1451
  case 'dashboards':
1305
1452
  if (recordId) {
1306
- return `/resource/dashboard/${recordId}`;
1453
+ return appendQP(`/resource/dashboard/${recordId}`);
1307
1454
  }
1308
1455
  break;
1309
1456
  case 'artifacts':
1310
1457
  if (recordId) {
1311
- return `/resource/artifact/${recordId}`;
1458
+ return appendQP(`/resource/artifact/${recordId}`);
1312
1459
  }
1313
1460
  break;
1314
1461
  case 'queries':
1315
1462
  if (recordId) {
1316
- return `/resource/query/${recordId}`;
1463
+ return appendQP(`/resource/query/${recordId}`);
1317
1464
  }
1318
1465
  break;
1319
1466
  }
@@ -1661,7 +1808,7 @@ export class ShellComponent {
1661
1808
  this.workspaceManager.SetActiveTab(defaultNavItemTab.id);
1662
1809
  const resourceUrl = await this.buildResourceUrl(defaultNavItemTab);
1663
1810
  if (resourceUrl) {
1664
- this.router.navigateByUrl(resourceUrl, { replaceUrl: true });
1811
+ this.router.navigateByUrl(resourceUrl);
1665
1812
  }
1666
1813
  }
1667
1814
  else {
@@ -1677,7 +1824,7 @@ export class ShellComponent {
1677
1824
  // but we can also manually trigger it here to ensure immediate update
1678
1825
  const resourceUrl = await this.buildResourceUrl(firstTab);
1679
1826
  if (resourceUrl) {
1680
- this.router.navigateByUrl(resourceUrl, { replaceUrl: true });
1827
+ this.router.navigateByUrl(resourceUrl);
1681
1828
  }
1682
1829
  }
1683
1830
  }
@@ -2330,6 +2477,45 @@ export class ShellComponent {
2330
2477
  }
2331
2478
  }
2332
2479
  // ========================================
2480
+ // UNIVERSAL SEARCH EVENT HANDLERS
2481
+ // ========================================
2482
+ OnGlobalKeydown(event) {
2483
+ const target = event.target;
2484
+ if (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA' || target.isContentEditable)
2485
+ return;
2486
+ const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0;
2487
+ const isCtrlOrCmd = isMac ? event.metaKey : event.ctrlKey;
2488
+ if (isCtrlOrCmd && event.key === 'k') {
2489
+ event.preventDefault();
2490
+ event.stopPropagation();
2491
+ if (this.shellSearchComposite?.Focus) {
2492
+ this.shellSearchComposite.Focus();
2493
+ }
2494
+ }
2495
+ }
2496
+ OnSearchResultSelected(result) {
2497
+ if (result.ResultType === 'storage-file') {
2498
+ if (!this.fileOpenService.OpenPreviewFromSearchResult(result.RawMetadata)) {
2499
+ this.fileOpenService.OpenFileFromSearchResult(result.RawMetadata);
2500
+ }
2501
+ return;
2502
+ }
2503
+ if (!result.EntityName || !result.RecordID)
2504
+ return;
2505
+ // Entity records — open via NavigationService
2506
+ const pkey = new CompositeKey([{ FieldName: 'ID', Value: result.RecordID }]);
2507
+ this.navigationService.OpenEntityRecord(result.EntityName, pkey);
2508
+ }
2509
+ OnSearchSubmitted(query) {
2510
+ if (query && query.trim().length >= 2) {
2511
+ const minRelevance = this.shellSearchComposite?.MinRelevancePercent;
2512
+ this.navigationService.OpenSearch(query, minRelevance ? { minRelevance } : undefined);
2513
+ }
2514
+ }
2515
+ OnSeeAllSearch(query) {
2516
+ this.OnSearchSubmitted(query);
2517
+ }
2518
+ // ========================================
2333
2519
  // NOTIFICATION FUNCTIONALITY
2334
2520
  // ========================================
2335
2521
  /**
@@ -2419,6 +2605,12 @@ export class ShellComponent {
2419
2605
  appName: accessResult.appName,
2420
2606
  appId: accessResult.appId
2421
2607
  };
2608
+ case 'not_authorized':
2609
+ return {
2610
+ type: 'no_access',
2611
+ appName: accessResult.appName,
2612
+ appId: accessResult.appId
2613
+ };
2422
2614
  default:
2423
2615
  // 'accessible' shouldn't reach here, but handle it as a generic error
2424
2616
  return {
@@ -2574,7 +2766,7 @@ export class ShellComponent {
2574
2766
  }
2575
2767
  // Update URL to reflect the new app
2576
2768
  const appPath = app.Path || app.Name;
2577
- this.router.navigateByUrl(`/app/${encodeURIComponent(appPath)}`, { replaceUrl: true });
2769
+ this.router.navigateByUrl(`/app/${encodeURIComponent(appPath)}`);
2578
2770
  }
2579
2771
  /**
2580
2772
  * Redirect to the first available app (fallback)
@@ -2594,93 +2786,91 @@ export class ShellComponent {
2594
2786
  this.cdr.detectChanges();
2595
2787
  }
2596
2788
  }
2597
- static ɵfac = function ShellComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ShellComponent)(i0.ɵɵdirectiveInject(i1.ApplicationManager), i0.ɵɵdirectiveInject(i1.WorkspaceStateManager), i0.ɵɵdirectiveInject(i1.GoldenLayoutManager), i0.ɵɵdirectiveInject(i1.TabService), i0.ɵɵdirectiveInject(i2.NavigationService), i0.ɵɵdirectiveInject(i3.ActivatedRoute), i0.ɵɵdirectiveInject(i3.Router), i0.ɵɵdirectiveInject(i4.MJAuthBase), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef), i0.ɵɵdirectiveInject(i5.UserAvatarService), i0.ɵɵdirectiveInject(i6.SettingsDialogService), i0.ɵɵdirectiveInject(i0.ViewContainerRef), i0.ɵɵdirectiveInject(i2.TitleService), i0.ɵɵdirectiveInject(i2.DeveloperModeService), i0.ɵɵdirectiveInject(i7.CommandPaletteService), i0.ɵɵdirectiveInject(i2.ThemeService), i0.ɵɵdirectiveInject(i2.HomeAppPinService)); };
2789
+ static ɵfac = function ShellComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ShellComponent)(i0.ɵɵdirectiveInject(i1.ApplicationManager), i0.ɵɵdirectiveInject(i1.WorkspaceStateManager), i0.ɵɵdirectiveInject(i1.GoldenLayoutManager), i0.ɵɵdirectiveInject(i1.TabService), i0.ɵɵdirectiveInject(i2.NavigationService), i0.ɵɵdirectiveInject(i3.ActivatedRoute), i0.ɵɵdirectiveInject(i3.Router), i0.ɵɵdirectiveInject(i4.MJAuthBase), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef), i0.ɵɵdirectiveInject(i5.UserAvatarService), i0.ɵɵdirectiveInject(i6.SettingsDialogService), i0.ɵɵdirectiveInject(i0.ViewContainerRef), i0.ɵɵdirectiveInject(i2.TitleService), i0.ɵɵdirectiveInject(i2.DeveloperModeService), i0.ɵɵdirectiveInject(i7.CommandPaletteService), i0.ɵɵdirectiveInject(i2.ThemeService), i0.ɵɵdirectiveInject(i2.HomeAppPinService), i0.ɵɵdirectiveInject(i8.FileOpenService)); };
2598
2790
  static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ShellComponent, selectors: [["mj-shell"]], viewQuery: function ShellComponent_Query(rf, ctx) { if (rf & 1) {
2599
- i0.ɵɵviewQuery(_c0, 5)(TabContainerComponent, 5)(_c1, 5);
2791
+ i0.ɵɵviewQuery(_c0, 5)(_c1, 5)(TabContainerComponent, 5)(_c2, 5);
2600
2792
  } if (rf & 2) {
2601
2793
  let _t;
2602
2794
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.searchInput = _t.first);
2795
+ i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.shellSearchComposite = _t.first);
2603
2796
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.tabContainerRef = _t.first);
2604
2797
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.appAccessDialog = _t.first);
2605
2798
  } }, hostBindings: function ShellComponent_HostBindings(rf, ctx) { if (rf & 1) {
2606
- i0.ɵɵlistener("keydown", function ShellComponent_keydown_HostBindingHandler($event) { return ctx.handleGlobalKeyboardShortcuts($event); }, i0.ɵɵresolveDocument);
2607
- } }, standalone: false, decls: 53, vars: 27, consts: [["searchInput", ""], ["appAccessDialog", ""], [1, "shell-container"], [1, "shell-header"], ["title", "MemberJunction", 1, "mj-logo"], ["title", "Menu", 1, "hamburger-btn", 3, "click"], [1, "fa-solid", "fa-bars"], [1, "nav-bar-apps", "left-of-switcher"], [3, "appSelected", "activeApp", "isViewingSystemTab", "loadingAppId"], [1, "desktop-nav", 3, "app"], [1, "spacer"], [1, "header-actions"], ["title", "Search", 1, "icon-btn", "desktop-only", "search-toggle-btn", 3, "click"], [1, "fa-solid", "fa-search"], ["title", "Notifications", 1, "icon-btn", "desktop-only", "notification-btn", 3, "click"], [1, "fa-solid", "fa-bell"], [1, "notification-badge"], [1, "nav-bar-apps", "left-of-user-menu"], [1, "user-menu"], [1, "avatar-btn", 3, "click"], ["alt", "User avatar", 1, "avatar-img", 3, "src"], [1, "icon-fallback"], [1, "user-context-menu", 3, "menu-fade", "menu-slide"], [1, "search-popup-overlay"], [1, "search-popup"], [1, "search-popup-content", 3, "click"], ["TextField", "Name", "ValueField", "ID", 1, "search-entity-dropdown", 3, "ngModelChange", "Data", "ngModel"], ["type", "text", "placeholder", "Search...", 1, "mj-input", "search-input", 3, "keydown.enter"], ["title", "Search", 1, "search-submit-btn", 3, "click"], [1, "mobile-nav-overlay"], [1, "mobile-nav-drawer"], [1, "mobile-nav-header"], [1, "close-btn", 3, "click"], [1, "fa-solid", "fa-xmark"], [1, "mobile-nav-content"], [1, "mobile-nav-footer"], ["title", "Search", 1, "mobile-nav-action", 3, "click"], ["title", "Notifications", 1, "mobile-nav-action", 3, "click"], [1, "notification-badge-mobile"], [3, "firstResourceLoadComplete", "layoutInitError"], [1, "shell-loading"], [3, "result"], [3, "AppSelected"], [1, "pin-progress-backdrop"], [1, "nav-bar-app-btn", 3, "active", "title", "--app-color"], [1, "nav-bar-app-btn", 3, "click", "dblclick", "title"], [1, "desktop-nav", 3, "navItemClick", "navItemDismiss", "app"], [1, "user-context-menu"], [1, "user-menu-header"], [1, "user-info"], [1, "user-name"], [1, "user-email"], [1, "user-menu-divider"], [1, "user-menu-item", "theme-toggle-item", 3, "title"], [1, "user-menu-item", 3, "disabled", "danger", "color", "title"], [1, "user-menu-item", "theme-toggle-item", 3, "click", "title"], [1, "menu-label"], [1, "theme-toggle-track"], [1, "theme-toggle-thumb"], [1, "theme-toggle-icon"], [1, "user-menu-item", 3, "click", "title"], [1, "menu-shortcut"], [1, "search-popup-overlay", 3, "click"], [1, "mobile-nav-overlay", 3, "click"], [1, "mobile-nav-section-title"], [3, "navItemClick", "navItemDismiss", "app"], ["size", "large", 3, "text", "textColor", "logoColor", "logoGradient", "animation"], [1, "loading-reset-panel"], [1, "loading-reset-message"], [1, "fa-regular", "fa-clock"], [1, "loading-reset-hint"], [1, "loading-reset-btn", 3, "click"], [1, "fa-solid", "fa-arrows-rotate"], [1, "pin-progress-modal"], ["size", "small", 3, "showText"], [1, "pin-progress-text"]], template: function ShellComponent_Template(rf, ctx) { if (rf & 1) {
2799
+ i0.ɵɵlistener("keydown", function ShellComponent_keydown_HostBindingHandler($event) { return ctx.OnGlobalKeydown($event); }, i0.ɵɵresolveDocument);
2800
+ } }, standalone: false, decls: 52, vars: 28, consts: [["searchInput", ""], ["appAccessDialog", ""], ["shellSearchComposite", ""], [1, "shell-container"], [1, "shell-header"], ["title", "MemberJunction", 1, "mj-logo"], ["title", "Menu", 1, "hamburger-btn", 3, "click"], [1, "fa-solid", "fa-bars"], [1, "nav-bar-apps", "left-of-switcher"], [3, "appSelected", "activeApp", "isViewingSystemTab", "loadingAppId"], [1, "desktop-nav", 3, "app"], [1, "shell-search-bar", "desktop-only"], [1, "spacer"], [1, "header-actions"], ["title", "Notifications", 1, "icon-btn", "desktop-only", "notification-btn", 3, "click"], [1, "fa-solid", "fa-bell"], [1, "notification-badge"], [1, "nav-bar-apps", "left-of-user-menu"], [1, "user-menu"], [1, "avatar-btn", 3, "click"], ["alt", "User avatar", 1, "avatar-img", 3, "src"], [1, "icon-fallback"], [1, "user-context-menu", 3, "menu-fade", "menu-slide"], [1, "search-popup-overlay"], [1, "search-popup"], [1, "search-popup-content", 3, "click"], ["TextField", "Name", "ValueField", "ID", 1, "search-entity-dropdown", 3, "ngModelChange", "Data", "ngModel"], ["type", "text", "placeholder", "Search...", 1, "mj-input", "search-input", 3, "keydown.enter"], ["title", "Search", 1, "search-submit-btn", 3, "click"], [1, "fa-solid", "fa-search"], [1, "mobile-nav-overlay"], [1, "mobile-nav-drawer"], [1, "mobile-nav-header"], [1, "close-btn", 3, "click"], [1, "fa-solid", "fa-xmark"], [1, "mobile-nav-content"], [1, "mobile-nav-footer"], ["title", "Search", 1, "mobile-nav-action", 3, "click"], ["title", "Notifications", 1, "mobile-nav-action", 3, "click"], [1, "notification-badge-mobile"], [3, "firstResourceLoadComplete", "layoutInitError"], [1, "shell-loading"], [3, "result"], [3, "AppSelected"], [1, "pin-progress-backdrop"], [1, "nav-bar-app-btn", 3, "active", "title", "--app-color"], [1, "nav-bar-app-btn", 3, "click", "dblclick", "title"], [1, "desktop-nav", 3, "navItemClick", "navItemDismiss", "app"], ["Placeholder", "Search everything...", 3, "ResultSelected", "SearchSubmitted", "SeeAllRequested", "ShowShortcutHint", "EnablePreview", "EnableRecent", "MaxPreviewResults"], [1, "user-context-menu"], [1, "user-menu-header"], [1, "user-info"], [1, "user-name"], [1, "user-email"], [1, "user-subtitle"], [1, "user-menu-divider"], [1, "user-menu-item", "theme-toggle-item", 3, "title"], [1, "user-menu-item", 3, "disabled", "danger", "color", "title"], [1, "user-menu-item", "theme-toggle-item", 3, "click", "title"], [1, "menu-label"], [1, "theme-toggle-track"], [1, "theme-toggle-thumb"], [1, "theme-toggle-icon"], [1, "user-menu-item", 3, "click", "title"], [1, "menu-shortcut"], [1, "search-popup-overlay", 3, "click"], [1, "mobile-nav-overlay", 3, "click"], [1, "mobile-nav-section-title"], [3, "navItemClick", "navItemDismiss", "app"], ["size", "large", 3, "text", "textColor", "logoColor", "logoGradient", "animation"], [1, "loading-reset-panel"], [1, "loading-reset-message"], [1, "fa-regular", "fa-clock"], [1, "loading-reset-hint"], [1, "loading-reset-btn", 3, "click"], [1, "fa-solid", "fa-arrows-rotate"], [1, "pin-progress-modal"], ["size", "small", 3, "showText"], [1, "pin-progress-text"]], template: function ShellComponent_Template(rf, ctx) { if (rf & 1) {
2608
2801
  const _r1 = i0.ɵɵgetCurrentView();
2609
- i0.ɵɵelementStart(0, "div", 2)(1, "header", 3);
2610
- i0.ɵɵelement(2, "div", 4);
2611
- i0.ɵɵelementStart(3, "button", 5);
2802
+ i0.ɵɵelementStart(0, "div", 3)(1, "header", 4);
2803
+ i0.ɵɵelement(2, "div", 5);
2804
+ i0.ɵɵelementStart(3, "button", 6);
2612
2805
  i0.ɵɵlistener("click", function ShellComponent_Template_button_click_3_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.toggleMobileNav()); });
2613
- i0.ɵɵelement(4, "i", 6);
2806
+ i0.ɵɵelement(4, "i", 7);
2614
2807
  i0.ɵɵelementEnd();
2615
- i0.ɵɵconditionalCreate(5, ShellComponent_Conditional_5_Template, 3, 0, "div", 7);
2616
- i0.ɵɵelementStart(6, "mj-app-switcher", 8);
2808
+ i0.ɵɵconditionalCreate(5, ShellComponent_Conditional_5_Template, 3, 0, "div", 8);
2809
+ i0.ɵɵelementStart(6, "mj-app-switcher", 9);
2617
2810
  i0.ɵɵlistener("appSelected", function ShellComponent_Template_mj_app_switcher_appSelected_6_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onAppSwitch($event)); });
2618
2811
  i0.ɵɵelementEnd();
2619
- i0.ɵɵconditionalCreate(7, ShellComponent_Conditional_7_Template, 1, 1, "mj-app-nav", 9);
2620
- i0.ɵɵelement(8, "div", 10);
2621
- i0.ɵɵelementStart(9, "div", 11)(10, "button", 12);
2622
- i0.ɵɵlistener("click", function ShellComponent_Template_button_click_10_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.toggleSearch()); });
2623
- i0.ɵɵelement(11, "i", 13);
2812
+ i0.ɵɵconditionalCreate(7, ShellComponent_Conditional_7_Template, 1, 1, "mj-app-nav", 10);
2813
+ i0.ɵɵconditionalCreate(8, ShellComponent_Conditional_8_Template, 3, 4, "div", 11);
2814
+ i0.ɵɵelement(9, "div", 12);
2815
+ i0.ɵɵelementStart(10, "div", 13)(11, "button", 14);
2816
+ i0.ɵɵlistener("click", function ShellComponent_Template_button_click_11_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.showNotifications()); });
2817
+ i0.ɵɵelement(12, "i", 15);
2818
+ i0.ɵɵconditionalCreate(13, ShellComponent_Conditional_13_Template, 2, 1, "span", 16);
2624
2819
  i0.ɵɵelementEnd();
2625
- i0.ɵɵelementStart(12, "button", 14);
2626
- i0.ɵɵlistener("click", function ShellComponent_Template_button_click_12_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.showNotifications()); });
2627
- i0.ɵɵelement(13, "i", 15);
2628
- i0.ɵɵconditionalCreate(14, ShellComponent_Conditional_14_Template, 2, 1, "span", 16);
2820
+ i0.ɵɵconditionalCreate(14, ShellComponent_Conditional_14_Template, 3, 0, "div", 17);
2821
+ i0.ɵɵelementStart(15, "div", 18)(16, "button", 19);
2822
+ i0.ɵɵlistener("click", function ShellComponent_Template_button_click_16_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.toggleUserMenu($event)); });
2823
+ i0.ɵɵconditionalCreate(17, ShellComponent_Conditional_17_Template, 1, 1, "img", 20)(18, ShellComponent_Conditional_18_Template, 2, 2, "div", 21);
2629
2824
  i0.ɵɵelementEnd();
2630
- i0.ɵɵconditionalCreate(15, ShellComponent_Conditional_15_Template, 3, 0, "div", 17);
2631
- i0.ɵɵelementStart(16, "div", 18)(17, "button", 19);
2632
- i0.ɵɵlistener("click", function ShellComponent_Template_button_click_17_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.toggleUserMenu($event)); });
2633
- i0.ɵɵconditionalCreate(18, ShellComponent_Conditional_18_Template, 1, 1, "img", 20)(19, ShellComponent_Conditional_19_Template, 2, 2, "div", 21);
2634
- i0.ɵɵelementEnd();
2635
- i0.ɵɵconditionalCreate(20, ShellComponent_Conditional_20_Template, 4, 5, "div", 22);
2825
+ i0.ɵɵconditionalCreate(19, ShellComponent_Conditional_19_Template, 4, 5, "div", 22);
2636
2826
  i0.ɵɵelementEnd()()();
2637
- i0.ɵɵconditionalCreate(21, ShellComponent_Conditional_21_Template, 1, 0, "div", 23);
2638
- i0.ɵɵelementStart(22, "div", 24)(23, "div", 25);
2639
- i0.ɵɵlistener("click", function ShellComponent_Template_div_click_23_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView($event.stopPropagation()); });
2640
- i0.ɵɵelementStart(24, "mj-dropdown", 26);
2641
- i0.ɵɵtwoWayListener("ngModelChange", function ShellComponent_Template_mj_dropdown_ngModelChange_24_listener($event) { i0.ɵɵrestoreView(_r1); i0.ɵɵtwoWayBindingSet(ctx.selectedEntity, $event) || (ctx.selectedEntity = $event); return i0.ɵɵresetView($event); });
2827
+ i0.ɵɵconditionalCreate(20, ShellComponent_Conditional_20_Template, 1, 0, "div", 23);
2828
+ i0.ɵɵelementStart(21, "div", 24)(22, "div", 25);
2829
+ i0.ɵɵlistener("click", function ShellComponent_Template_div_click_22_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView($event.stopPropagation()); });
2830
+ i0.ɵɵelementStart(23, "mj-dropdown", 26);
2831
+ i0.ɵɵtwoWayListener("ngModelChange", function ShellComponent_Template_mj_dropdown_ngModelChange_23_listener($event) { i0.ɵɵrestoreView(_r1); i0.ɵɵtwoWayBindingSet(ctx.selectedEntity, $event) || (ctx.selectedEntity = $event); return i0.ɵɵresetView($event); });
2642
2832
  i0.ɵɵelementEnd();
2643
- i0.ɵɵelementStart(25, "input", 27, 0);
2644
- i0.ɵɵlistener("keydown.enter", function ShellComponent_Template_input_keydown_enter_25_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onSearch($event)); });
2833
+ i0.ɵɵelementStart(24, "input", 27, 0);
2834
+ i0.ɵɵlistener("keydown.enter", function ShellComponent_Template_input_keydown_enter_24_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onSearch($event)); });
2645
2835
  i0.ɵɵelementEnd();
2646
- i0.ɵɵelementStart(27, "button", 28);
2647
- i0.ɵɵlistener("click", function ShellComponent_Template_button_click_27_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onSearch($event)); });
2648
- i0.ɵɵelement(28, "i", 13);
2836
+ i0.ɵɵelementStart(26, "button", 28);
2837
+ i0.ɵɵlistener("click", function ShellComponent_Template_button_click_26_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onSearch($event)); });
2838
+ i0.ɵɵelement(27, "i", 29);
2649
2839
  i0.ɵɵelementEnd()()();
2650
- i0.ɵɵconditionalCreate(29, ShellComponent_Conditional_29_Template, 1, 0, "div", 29);
2651
- i0.ɵɵelementStart(30, "div", 30)(31, "div", 31)(32, "span");
2652
- i0.ɵɵtext(33, "Navigation");
2840
+ i0.ɵɵconditionalCreate(28, ShellComponent_Conditional_28_Template, 1, 0, "div", 30);
2841
+ i0.ɵɵelementStart(29, "div", 31)(30, "div", 32)(31, "span");
2842
+ i0.ɵɵtext(32, "Navigation");
2653
2843
  i0.ɵɵelementEnd();
2654
- i0.ɵɵelementStart(34, "button", 32);
2655
- i0.ɵɵlistener("click", function ShellComponent_Template_button_click_34_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.closeMobileNav()); });
2656
- i0.ɵɵelement(35, "i", 33);
2844
+ i0.ɵɵelementStart(33, "button", 33);
2845
+ i0.ɵɵlistener("click", function ShellComponent_Template_button_click_33_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.closeMobileNav()); });
2846
+ i0.ɵɵelement(34, "i", 34);
2657
2847
  i0.ɵɵelementEnd()();
2658
- i0.ɵɵconditionalCreate(36, ShellComponent_Conditional_36_Template, 4, 2, "div", 34);
2659
- i0.ɵɵelementStart(37, "div", 35)(38, "button", 36);
2660
- i0.ɵɵlistener("click", function ShellComponent_Template_button_click_38_listener() { i0.ɵɵrestoreView(_r1); ctx.toggleSearch(); return i0.ɵɵresetView(ctx.closeMobileNav()); });
2661
- i0.ɵɵelement(39, "i", 13);
2662
- i0.ɵɵelementStart(40, "span");
2663
- i0.ɵɵtext(41, "Search");
2848
+ i0.ɵɵconditionalCreate(35, ShellComponent_Conditional_35_Template, 4, 2, "div", 35);
2849
+ i0.ɵɵelementStart(36, "div", 36)(37, "button", 37);
2850
+ i0.ɵɵlistener("click", function ShellComponent_Template_button_click_37_listener() { i0.ɵɵrestoreView(_r1); ctx.toggleSearch(); return i0.ɵɵresetView(ctx.closeMobileNav()); });
2851
+ i0.ɵɵelement(38, "i", 29);
2852
+ i0.ɵɵelementStart(39, "span");
2853
+ i0.ɵɵtext(40, "Search");
2664
2854
  i0.ɵɵelementEnd()();
2665
- i0.ɵɵelementStart(42, "button", 37);
2666
- i0.ɵɵlistener("click", function ShellComponent_Template_button_click_42_listener() { i0.ɵɵrestoreView(_r1); ctx.showNotifications(); return i0.ɵɵresetView(ctx.closeMobileNav()); });
2667
- i0.ɵɵelement(43, "i", 15);
2668
- i0.ɵɵelementStart(44, "span");
2669
- i0.ɵɵtext(45, "Notifications");
2855
+ i0.ɵɵelementStart(41, "button", 38);
2856
+ i0.ɵɵlistener("click", function ShellComponent_Template_button_click_41_listener() { i0.ɵɵrestoreView(_r1); ctx.showNotifications(); return i0.ɵɵresetView(ctx.closeMobileNav()); });
2857
+ i0.ɵɵelement(42, "i", 15);
2858
+ i0.ɵɵelementStart(43, "span");
2859
+ i0.ɵɵtext(44, "Notifications");
2670
2860
  i0.ɵɵelementEnd();
2671
- i0.ɵɵconditionalCreate(46, ShellComponent_Conditional_46_Template, 2, 1, "span", 38);
2861
+ i0.ɵɵconditionalCreate(45, ShellComponent_Conditional_45_Template, 2, 1, "span", 39);
2672
2862
  i0.ɵɵelementEnd()()();
2673
- i0.ɵɵelementStart(47, "mj-tab-container", 39);
2674
- i0.ɵɵlistener("firstResourceLoadComplete", function ShellComponent_Template_mj_tab_container_firstResourceLoadComplete_47_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onFirstResourceLoadComplete()); })("layoutInitError", function ShellComponent_Template_mj_tab_container_layoutInitError_47_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.handleLayoutError()); });
2863
+ i0.ɵɵelementStart(46, "mj-tab-container", 40);
2864
+ i0.ɵɵlistener("firstResourceLoadComplete", function ShellComponent_Template_mj_tab_container_firstResourceLoadComplete_46_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onFirstResourceLoadComplete()); })("layoutInitError", function ShellComponent_Template_mj_tab_container_layoutInitError_46_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.handleLayoutError()); });
2675
2865
  i0.ɵɵelementEnd()();
2676
- i0.ɵɵconditionalCreate(48, ShellComponent_Conditional_48_Template, 3, 6, "div", 40);
2677
- i0.ɵɵelementStart(49, "mj-app-access-dialog", 41, 1);
2678
- i0.ɵɵlistener("result", function ShellComponent_Template_mj_app_access_dialog_result_49_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onAppAccessDialogResult($event)); });
2866
+ i0.ɵɵconditionalCreate(47, ShellComponent_Conditional_47_Template, 3, 6, "div", 41);
2867
+ i0.ɵɵelementStart(48, "mj-app-access-dialog", 42, 1);
2868
+ i0.ɵɵlistener("result", function ShellComponent_Template_mj_app_access_dialog_result_48_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onAppAccessDialogResult($event)); });
2679
2869
  i0.ɵɵelementEnd();
2680
- i0.ɵɵelementStart(51, "mj-command-palette", 42);
2681
- i0.ɵɵlistener("AppSelected", function ShellComponent_Template_mj_command_palette_AppSelected_51_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onAppSwitch($event)); });
2870
+ i0.ɵɵelementStart(50, "mj-command-palette", 43);
2871
+ i0.ɵɵlistener("AppSelected", function ShellComponent_Template_mj_command_palette_AppSelected_50_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onAppSwitch($event)); });
2682
2872
  i0.ɵɵelementEnd();
2683
- i0.ɵɵconditionalCreate(52, ShellComponent_Conditional_52_Template, 5, 2, "div", 43);
2873
+ i0.ɵɵconditionalCreate(51, ShellComponent_Conditional_51_Template, 5, 2, "div", 44);
2684
2874
  } if (rf & 2) {
2685
2875
  i0.ɵɵclassProp("hidden", ctx.loading)("tabs-visible", ctx.tabBarVisible);
2686
2876
  i0.ɵɵadvance(5);
@@ -2689,43 +2879,48 @@ export class ShellComponent {
2689
2879
  i0.ɵɵproperty("activeApp", ctx.activeApp)("isViewingSystemTab", ctx.isViewingSystemTab)("loadingAppId", ctx.loadingAppId);
2690
2880
  i0.ɵɵadvance();
2691
2881
  i0.ɵɵconditional(ctx.activeApp ? 7 : -1);
2692
- i0.ɵɵadvance(7);
2693
- i0.ɵɵconditional(ctx.unreadNotificationCount > 0 ? 14 : -1);
2694
2882
  i0.ɵɵadvance();
2695
- i0.ɵɵconditional(ctx.leftOfUserMenuApps.length > 0 ? 15 : -1);
2883
+ i0.ɵɵconditional(ctx.ShowSearchBar ? 8 : -1);
2884
+ i0.ɵɵadvance(5);
2885
+ i0.ɵɵconditional(ctx.unreadNotificationCount > 0 ? 13 : -1);
2886
+ i0.ɵɵadvance();
2887
+ i0.ɵɵconditional(ctx.leftOfUserMenuApps.length > 0 ? 14 : -1);
2696
2888
  i0.ɵɵadvance(3);
2697
- i0.ɵɵconditional(ctx.userImageURL ? 18 : 19);
2889
+ i0.ɵɵconditional(ctx.userImageURL ? 17 : 18);
2698
2890
  i0.ɵɵadvance(2);
2699
- i0.ɵɵconditional(ctx.userMenuVisible ? 20 : -1);
2891
+ i0.ɵɵconditional(ctx.userMenuVisible ? 19 : -1);
2700
2892
  i0.ɵɵadvance();
2701
- i0.ɵɵconditional(ctx.isSearchOpen ? 21 : -1);
2893
+ i0.ɵɵconditional(ctx.isSearchOpen ? 20 : -1);
2702
2894
  i0.ɵɵadvance();
2703
2895
  i0.ɵɵclassProp("open", ctx.isSearchOpen);
2704
2896
  i0.ɵɵadvance(2);
2705
2897
  i0.ɵɵproperty("Data", ctx.searchableEntities);
2706
2898
  i0.ɵɵtwoWayProperty("ngModel", ctx.selectedEntity);
2707
2899
  i0.ɵɵadvance(5);
2708
- i0.ɵɵconditional(ctx.mobileNavOpen ? 29 : -1);
2900
+ i0.ɵɵconditional(ctx.mobileNavOpen ? 28 : -1);
2709
2901
  i0.ɵɵadvance();
2710
2902
  i0.ɵɵclassProp("open", ctx.mobileNavOpen);
2711
2903
  i0.ɵɵadvance(6);
2712
- i0.ɵɵconditional(ctx.activeApp ? 36 : -1);
2904
+ i0.ɵɵconditional(ctx.activeApp ? 35 : -1);
2713
2905
  i0.ɵɵadvance(10);
2714
- i0.ɵɵconditional(ctx.unreadNotificationCount > 0 ? 46 : -1);
2906
+ i0.ɵɵconditional(ctx.unreadNotificationCount > 0 ? 45 : -1);
2715
2907
  i0.ɵɵadvance();
2716
2908
  i0.ɵɵclassProp("hide-tab-bar", !ctx.tabBarVisible);
2717
2909
  i0.ɵɵadvance();
2718
- i0.ɵɵconditional(ctx.loading ? 48 : -1);
2910
+ i0.ɵɵconditional(ctx.loading ? 47 : -1);
2719
2911
  i0.ɵɵadvance(4);
2720
- i0.ɵɵconditional(ctx.PinProgressVisible ? 52 : -1);
2721
- } }, dependencies: [i8.NgControlStatus, i8.NgModel, i9.MJDropdownComponent, i10.LoadingComponent, i11.AppSwitcherComponent, i12.AppNavComponent, i13.TabContainerComponent, i14.AppAccessDialogComponent, i15.CommandPaletteComponent], styles: ["[_nghost-%COMP%] {\n display: block;\n height: 100vh;\n width: 100%;\n overflow: hidden;\n}\n\n\n\n.mj-logo[_ngcontent-%COMP%] {\n width: 32px;\n height: 18px;\n background-image: var(--mj-logo-mark);\n background-repeat: no-repeat;\n background-position: center;\n background-size: contain;\n flex-shrink: 0;\n}\n\n.shell-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100vh;\n width: 100%;\n overflow: hidden;\n}\n\n\n\n\n.shell-container.hidden[_ngcontent-%COMP%] {\n visibility: hidden;\n position: absolute;\n pointer-events: none;\n}\n\nmj-tab-container[_ngcontent-%COMP%] {\n flex: 1;\n min-height: 0;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n transition: all 0.2s ease-in-out;\n}\n\n\n\nmj-tab-container.hide-tab-bar[_ngcontent-%COMP%] .lm_header {\n display: none;\n}\n\n\n\nmj-tab-container[_ngcontent-%COMP%]:not(.hide-tab-bar) .lm_header {\n opacity: 1;\n max-height: 40px;\n transition: opacity 0.2s ease-in-out, max-height 0.2s ease-in-out;\n}\n\n\n\nmj-tab-container.hide-tab-bar[_ngcontent-%COMP%] .lm_content {\n height: 100% !important;\n}\n\n\n\nmj-tab-container[_ngcontent-%COMP%] .lm_stack {\n transition: all 0.2s ease-in-out;\n}\n\n.shell-header[_ngcontent-%COMP%] {\n height: 60px;\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n display: flex;\n align-items: center;\n padding: 0 16px;\n gap: 16px;\n box-shadow: var(--mj-shadow-sm);\n flex-shrink: 0;\n}\n\n\n\n.nav-bar-apps[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.nav-bar-apps.left-of-switcher[_ngcontent-%COMP%] {\n \n\n \n\n}\n\n.nav-bar-apps.left-of-user-menu[_ngcontent-%COMP%] {\n margin-right: 8px;\n}\n\n.nav-bar-app-btn[_ngcontent-%COMP%] {\n --app-color: var(--mj-text-muted);\n width: 40px;\n height: 40px;\n border-radius: 10px;\n border: none;\n background: transparent;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-secondary);\n font-size: 18px;\n transition: all 0.15s ease;\n position: relative;\n}\n\n.nav-bar-app-btn[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--app-color) 15%, transparent);\n color: var(--app-color);\n}\n\n.nav-bar-app-btn.active[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--app-color) 20%, transparent);\n color: var(--app-color);\n}\n\n.nav-bar-app-btn.active[_ngcontent-%COMP%]::after {\n content: '';\n position: absolute;\n bottom: 6px;\n left: 50%;\n transform: translateX(-50%);\n width: 16px;\n height: 3px;\n background: var(--app-color);\n border-radius: 2px;\n}\n\n.nav-bar-app-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n transition: transform 0.15s ease;\n margin-top: 2px; \n\n}\n\n.nav-bar-app-btn[_ngcontent-%COMP%]:hover i[_ngcontent-%COMP%] {\n transform: scale(1.1);\n}\n\n.spacer[_ngcontent-%COMP%] {\n flex: 1;\n}\n\n.header-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.icon-btn[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n border: none;\n background: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n font-size: 18px;\n transition: background 0.15s;\n}\n\n.icon-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n\n\n.notification-btn[_ngcontent-%COMP%] {\n position: relative;\n}\n\n.notification-badge[_ngcontent-%COMP%] {\n position: absolute;\n top: 4px;\n right: 4px;\n min-width: 16px;\n height: 16px;\n padding: 0 4px;\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n font-size: 10px;\n font-weight: 600;\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n line-height: 1;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n}\n\n.user-menu[_ngcontent-%COMP%] {\n position: relative;\n}\n\n.user-menu[_ngcontent-%COMP%] .avatar-btn[_ngcontent-%COMP%] {\n width: 36px;\n height: 36px;\n border-radius: 50%;\n border: none;\n background: transparent;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: box-shadow 0.15s, transform 0.15s;\n padding: 0;\n overflow: hidden;\n}\n\n.user-menu[_ngcontent-%COMP%] .avatar-btn[_ngcontent-%COMP%]:hover {\n transform: scale(1.05);\n}\n\n\n\n.user-menu[_ngcontent-%COMP%] .avatar-btn[_ngcontent-%COMP%] .icon-fallback[_ngcontent-%COMP%] {\n width: 100%;\n height: 100%;\n border-radius: 50%;\n border: 2px solid var(--mj-border-default);\n background: var(--mj-bg-surface-hover);\n display: flex;\n align-items: center;\n justify-content: center;\n transition: border-color 0.15s;\n}\n\n.user-menu[_ngcontent-%COMP%] .avatar-btn[_ngcontent-%COMP%]:hover .icon-fallback[_ngcontent-%COMP%] {\n border-color: var(--mj-brand-primary);\n}\n\n.user-menu[_ngcontent-%COMP%] .avatar-btn[_ngcontent-%COMP%] .icon-fallback[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-size: 16px;\n}\n\n\n\n.user-menu[_ngcontent-%COMP%] .avatar-btn[_ngcontent-%COMP%] .avatar-img[_ngcontent-%COMP%] {\n width: 100%;\n height: 100%;\n border-radius: 50%;\n object-fit: cover;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15);\n}\n\n.user-menu[_ngcontent-%COMP%] .avatar-btn[_ngcontent-%COMP%]:hover .avatar-img[_ngcontent-%COMP%] {\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);\n}\n\n\n\n.user-menu-header[_ngcontent-%COMP%] {\n padding: 12px 16px;\n background: var(--mj-bg-surface-sunken);\n}\n\n.user-menu-header[_ngcontent-%COMP%] .user-info[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.user-menu-header[_ngcontent-%COMP%] .user-name[_ngcontent-%COMP%] {\n font-weight: 600;\n font-size: 14px;\n color: var(--mj-text-primary);\n}\n\n.user-menu-header[_ngcontent-%COMP%] .user-email[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n\n\n.user-context-menu[_ngcontent-%COMP%] {\n position: absolute;\n top: 100%;\n right: 0;\n margin-top: 8px;\n background: var(--mj-bg-surface-elevated);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: var(--mj-shadow-lg);\n min-width: 180px;\n z-index: 10000;\n overflow: hidden;\n}\n\n.user-menu-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 16px;\n cursor: pointer;\n font-size: 14px;\n color: var(--mj-text-primary);\n transition: background 0.15s;\n}\n\n.user-menu-item[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n width: 18px;\n text-align: center;\n color: var(--mj-text-muted);\n font-size: 14px;\n}\n\n.user-menu-item[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.user-menu-item.danger[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n.user-menu-item.danger[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n.user-menu-item.danger[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface-elevated));\n}\n\n.user-menu-divider[_ngcontent-%COMP%] {\n height: 1px;\n background: var(--mj-border-default);\n margin: 4px 0;\n}\n\n\n\n.user-menu-item.disabled[_ngcontent-%COMP%] {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.user-menu-item.disabled[_ngcontent-%COMP%]:hover {\n background: transparent;\n}\n\n\n\n.theme-toggle-item[_ngcontent-%COMP%] {\n cursor: pointer;\n}\n\n.theme-toggle-track[_ngcontent-%COMP%] {\n position: relative;\n width: 40px;\n height: 22px;\n border-radius: 11px;\n background: var(--mj-bg-surface-active);\n margin-left: auto;\n transition: background 0.2s ease;\n flex-shrink: 0;\n}\n\n.theme-toggle-track.dark[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n}\n\n.theme-toggle-thumb[_ngcontent-%COMP%] {\n position: absolute;\n top: 2px;\n left: 2px;\n width: 18px;\n height: 18px;\n border-radius: 50%;\n background: var(--mj-bg-surface);\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n display: flex;\n align-items: center;\n justify-content: center;\n transition: transform 0.2s ease;\n}\n\n.theme-toggle-track.dark[_ngcontent-%COMP%] .theme-toggle-thumb[_ngcontent-%COMP%] {\n transform: translateX(18px);\n}\n\n.theme-toggle-icon[_ngcontent-%COMP%] {\n font-size: 10px;\n color: var(--mj-text-muted);\n}\n\n.theme-toggle-track.dark[_ngcontent-%COMP%] .theme-toggle-icon[_ngcontent-%COMP%] {\n color: var(--mj-text-inverse);\n}\n\n\n\n.user-menu-item[_ngcontent-%COMP%] .menu-shortcut[_ngcontent-%COMP%] {\n margin-left: auto;\n font-size: 11px;\n color: var(--mj-text-disabled);\n font-family: monospace;\n}\n\n\n\n.user-context-menu.menu-fade[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_menuFadeIn 0.15s ease-out;\n}\n\n.user-context-menu.menu-slide[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_menuSlideIn 0.2s ease-out;\n}\n\n@keyframes _ngcontent-%COMP%_menuFadeIn {\n from {\n opacity: 0;\n transform: translateY(-8px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes _ngcontent-%COMP%_menuSlideIn {\n from {\n opacity: 0;\n transform: translateY(-16px) scale(0.95);\n }\n to {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n}\n\n.shell-loading[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100vh;\n padding-bottom: 15vh;\n background: var(--mj-bg-page);\n}\n\n\n\n.loading-reset-panel[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: var(--mj-space-3);\n margin-top: var(--mj-space-10);\n padding: var(--mj-space-8);\n background: var(--mj-bg-surface-elevated);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n box-shadow: var(--mj-shadow-md);\n max-width: 420px;\n animation: _ngcontent-%COMP%_resetPanelFadeIn 0.4s ease-out;\n}\n\n.loading-reset-message[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: var(--mj-space-2);\n margin: 0;\n font-size: var(--mj-text-base);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-primary);\n}\n\n.loading-reset-message[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: var(--mj-text-lg);\n color: var(--mj-status-warning);\n}\n\n.loading-reset-hint[_ngcontent-%COMP%] {\n margin: 0;\n font-size: var(--mj-text-sm);\n color: var(--mj-text-secondary);\n text-align: center;\n line-height: var(--mj-leading-relaxed);\n}\n\n.loading-reset-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: var(--mj-space-2);\n margin-top: var(--mj-space-3);\n padding: var(--mj-space-3) var(--mj-space-6);\n font-size: var(--mj-text-base);\n font-weight: var(--mj-font-medium);\n font-family: var(--mj-font-family);\n color: var(--mj-text-inverse);\n background: var(--mj-brand-primary);\n border: 1px solid var(--mj-brand-primary);\n border-radius: var(--mj-radius-md);\n cursor: pointer;\n transition: var(--mj-transition-colors);\n}\n\n.loading-reset-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-brand-primary-hover);\n color: var(--mj-text-inverse);\n border-color: var(--mj-brand-primary-hover);\n box-shadow: var(--mj-shadow-md);\n}\n\n.loading-reset-btn[_ngcontent-%COMP%]:active {\n background: var(--mj-brand-primary-active);\n color: var(--mj-text-inverse);\n transform: scale(0.98);\n}\n\n.loading-reset-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: var(--mj-text-sm);\n}\n\n@keyframes _ngcontent-%COMP%_resetPanelFadeIn {\n from {\n opacity: 0;\n transform: translateY(12px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n\n\n.hamburger-btn[_ngcontent-%COMP%] {\n display: none;\n width: 40px;\n height: 40px;\n border-radius: 8px;\n border: none;\n background: none;\n cursor: pointer;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-secondary);\n font-size: 20px;\n transition: background 0.15s;\n}\n.hamburger-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n\n\n.mobile-nav-overlay[_ngcontent-%COMP%] {\n display: none;\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n z-index: 9998;\n}\n\n\n\n.mobile-nav-drawer[_ngcontent-%COMP%] {\n display: none;\n position: fixed;\n top: 0;\n left: 0;\n bottom: 0;\n width: 280px;\n max-width: 85vw;\n background: var(--mj-bg-surface);\n box-shadow: var(--mj-shadow-xl);\n z-index: 9999;\n flex-direction: column;\n transform: translateX(-100%);\n transition: transform 0.3s ease;\n}\n.mobile-nav-drawer.open[_ngcontent-%COMP%] {\n transform: translateX(0);\n}\n\n.mobile-nav-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-sunken);\n}\n.mobile-nav-header[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n font-weight: 600;\n font-size: 16px;\n color: var(--mj-text-primary);\n}\n.mobile-nav-header[_ngcontent-%COMP%] .close-btn[_ngcontent-%COMP%] {\n width: 36px;\n height: 36px;\n border-radius: 50%;\n border: none;\n background: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n font-size: 18px;\n transition: background 0.15s;\n}\n.mobile-nav-header[_ngcontent-%COMP%] .close-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-active);\n}\n\n.mobile-nav-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n padding: 16px 0;\n}\n\n.mobile-nav-section-title[_ngcontent-%COMP%] {\n padding: 8px 20px;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-disabled);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.mobile-nav-footer[_ngcontent-%COMP%] {\n border-top: 1px solid var(--mj-border-default);\n padding: 12px 16px;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.mobile-nav-action[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 16px;\n border: none;\n background: none;\n cursor: pointer;\n border-radius: 8px;\n color: var(--mj-text-secondary);\n font-size: 14px;\n font-weight: 500;\n transition: background 0.15s;\n width: 100%;\n text-align: left;\n}\n.mobile-nav-action[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n.mobile-nav-action[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 16px;\n width: 20px;\n text-align: center;\n}\n\n\n\n@media (max-width: 768px) {\n .hamburger-btn[_ngcontent-%COMP%] {\n display: flex;\n }\n\n .desktop-nav[_ngcontent-%COMP%] {\n display: none !important;\n }\n\n .desktop-only[_ngcontent-%COMP%] {\n display: none !important;\n }\n\n .mobile-nav-overlay[_ngcontent-%COMP%] {\n display: block;\n }\n\n .mobile-nav-drawer[_ngcontent-%COMP%] {\n display: flex;\n }\n\n .shell-header[_ngcontent-%COMP%] {\n padding: 0 12px;\n gap: 8px;\n }\n}\n\n\n\n .settings-fullscreen-window {\n \n\n box-shadow: none !important;\n border: none !important;\n}\n\n .settings-fullscreen-window .k-window-titlebar {\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n padding: 12px 16px;\n}\n\n .settings-fullscreen-window .k-window-title {\n font-size: 18px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n .settings-fullscreen-window .k-window-titlebar-actions {\n gap: 4px;\n}\n\n .settings-fullscreen-window .k-window-titlebar-action {\n width: 32px;\n height: 32px;\n border-radius: 6px;\n}\n\n .settings-fullscreen-window .k-window-titlebar-action:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n .settings-fullscreen-window .k-window-content {\n padding: 0;\n overflow: auto;\n background: var(--mj-bg-page);\n}\n\n\n\n .settings-fullscreen-window .k-window-titlebar-action[title=\"Minimize\"], \n .settings-fullscreen-window .k-window-titlebar-action[title=\"Maximize\"], \n .settings-fullscreen-window .k-window-titlebar-action .k-i-window-minimize, \n .settings-fullscreen-window .k-window-titlebar-action .k-i-window-maximize, \n .settings-fullscreen-window .k-window-titlebar-action .k-i-window {\n display: none !important;\n}\n\n\n\n\n\n\n.search-popup-overlay[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.3);\n z-index: 9999;\n animation: _ngcontent-%COMP%_fadeIn 0.15s ease;\n}\n\n@keyframes _ngcontent-%COMP%_fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n\n.search-popup[_ngcontent-%COMP%] {\n position: fixed;\n top: 60px; \n\n right: 16px;\n width: 480px;\n max-width: calc(100vw - 32px);\n background: var(--mj-bg-surface-elevated);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-xl);\n z-index: 10000;\n opacity: 0;\n transform: translateY(-10px);\n pointer-events: none;\n transition: opacity 0.2s ease, transform 0.2s ease;\n}\n\n.search-popup.open[_ngcontent-%COMP%] {\n opacity: 1;\n transform: translateY(0);\n pointer-events: all;\n}\n\n.search-popup-content[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px;\n}\n\n.search-entity-dropdown[_ngcontent-%COMP%] {\n min-width: 140px;\n max-width: 180px;\n flex-shrink: 0;\n}\n\n.search-input[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n height: 40px;\n padding: 8px 12px;\n font-size: 14px;\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n outline: none;\n display: block !important;\n box-sizing: border-box;\n}\n\n.search-input[_ngcontent-%COMP%]:focus {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n}\n\n.search-submit-btn[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n border-radius: 8px;\n border: none;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 16px;\n transition: background 0.15s;\n flex-shrink: 0;\n}\n\n.search-submit-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-brand-primary-hover);\n}\n\n.search-submit-btn[_ngcontent-%COMP%]:active {\n background: var(--mj-brand-primary-hover);\n}\n\n\n\n.notification-badge-mobile[_ngcontent-%COMP%] {\n position: absolute;\n top: 8px;\n right: 8px;\n min-width: 18px;\n height: 18px;\n padding: 0 5px;\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n font-size: 11px;\n font-weight: 600;\n border-radius: 9px;\n display: flex;\n align-items: center;\n justify-content: center;\n line-height: 1;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n}\n\n\n\n@media (max-width: 768px) {\n .search-popup[_ngcontent-%COMP%] {\n top: 60px;\n left: 16px;\n right: 16px;\n width: auto;\n max-width: none;\n }\n\n .search-popup-content[_ngcontent-%COMP%] {\n flex-wrap: wrap;\n }\n\n .search-entity-dropdown[_ngcontent-%COMP%] {\n width: 100%;\n }\n\n .search-input[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n }\n}\n\n\n\n\n\n.pin-progress-backdrop[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: color-mix(in srgb, var(--mj-text-primary) 40%, transparent);\n z-index: 100000;\n display: flex;\n align-items: center;\n justify-content: center;\n animation: _ngcontent-%COMP%_pinBackdropIn 0.2s ease;\n}\n\n@keyframes _ngcontent-%COMP%_pinBackdropIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n.pin-progress-modal[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border-radius: var(--mj-radius-xl);\n padding: 28px 40px;\n display: flex;\n align-items: center;\n gap: 16px;\n box-shadow: 0 16px 48px color-mix(in srgb, var(--mj-text-primary) 30%, transparent);\n animation: _ngcontent-%COMP%_pinModalIn 0.25s ease;\n}\n\n@keyframes _ngcontent-%COMP%_pinModalIn {\n from { opacity: 0; transform: scale(0.9) translateY(8px); }\n to { opacity: 1; transform: scale(1) translateY(0); }\n}\n\n.pin-progress-text[_ngcontent-%COMP%] {\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-medium);\n color: var(--mj-text-secondary);\n white-space: nowrap;\n}"] });
2912
+ i0.ɵɵconditional(ctx.PinProgressVisible ? 51 : -1);
2913
+ } }, dependencies: [i9.NgControlStatus, i9.NgModel, i10.MJDropdownComponent, i11.LoadingComponent, i12.SearchCompositeComponent, i13.AppSwitcherComponent, i14.AppNavComponent, i15.TabContainerComponent, i16.AppAccessDialogComponent, i17.CommandPaletteComponent], styles: ["[_nghost-%COMP%] {\n display: block;\n height: 100vh;\n width: 100%;\n overflow: hidden;\n}\n\n\n\n.mj-logo[_ngcontent-%COMP%] {\n width: 32px;\n height: 18px;\n background-image: var(--mj-logo-mark);\n background-repeat: no-repeat;\n background-position: center;\n background-size: contain;\n flex-shrink: 0;\n}\n\n.shell-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100vh;\n width: 100%;\n overflow: hidden;\n}\n\n\n\n\n.shell-container.hidden[_ngcontent-%COMP%] {\n visibility: hidden;\n position: absolute;\n pointer-events: none;\n}\n\nmj-tab-container[_ngcontent-%COMP%] {\n flex: 1;\n min-height: 0;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n transition: all 0.2s ease-in-out;\n}\n\n\n\nmj-tab-container.hide-tab-bar[_ngcontent-%COMP%] .lm_header {\n display: none;\n}\n\n\n\nmj-tab-container[_ngcontent-%COMP%]:not(.hide-tab-bar) .lm_header {\n opacity: 1;\n max-height: 40px;\n transition: opacity 0.2s ease-in-out, max-height 0.2s ease-in-out;\n}\n\n\n\nmj-tab-container.hide-tab-bar[_ngcontent-%COMP%] .lm_content {\n height: 100% !important;\n}\n\n\n\nmj-tab-container[_ngcontent-%COMP%] .lm_stack {\n transition: all 0.2s ease-in-out;\n}\n\n.shell-header[_ngcontent-%COMP%] {\n height: 60px;\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n display: flex;\n align-items: center;\n padding: 0 16px;\n gap: 16px;\n box-shadow: var(--mj-shadow-sm);\n flex-shrink: 0;\n \n\n\n position: relative;\n z-index: 500;\n}\n\n\n\n.nav-bar-apps[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.nav-bar-apps.left-of-switcher[_ngcontent-%COMP%] {\n \n\n \n\n}\n\n.nav-bar-apps.left-of-user-menu[_ngcontent-%COMP%] {\n margin-right: 8px;\n}\n\n.nav-bar-app-btn[_ngcontent-%COMP%] {\n --app-color: var(--mj-text-muted);\n width: 40px;\n height: 40px;\n border-radius: 10px;\n border: none;\n background: transparent;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-secondary);\n font-size: 18px;\n transition: all 0.15s ease;\n position: relative;\n}\n\n.nav-bar-app-btn[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--app-color) 15%, transparent);\n color: var(--app-color);\n}\n\n.nav-bar-app-btn.active[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--app-color) 20%, transparent);\n color: var(--app-color);\n}\n\n.nav-bar-app-btn.active[_ngcontent-%COMP%]::after {\n content: '';\n position: absolute;\n bottom: 6px;\n left: 50%;\n transform: translateX(-50%);\n width: 16px;\n height: 3px;\n background: var(--app-color);\n border-radius: 2px;\n}\n\n.nav-bar-app-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n transition: transform 0.15s ease;\n margin-top: 2px; \n\n}\n\n.nav-bar-app-btn[_ngcontent-%COMP%]:hover i[_ngcontent-%COMP%] {\n transform: scale(1.1);\n}\n\n.spacer[_ngcontent-%COMP%] {\n flex: 1;\n}\n\n.header-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.icon-btn[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n border: none;\n background: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n font-size: 18px;\n transition: background 0.15s;\n}\n\n.icon-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n\n\n.notification-btn[_ngcontent-%COMP%] {\n position: relative;\n}\n\n.notification-badge[_ngcontent-%COMP%] {\n position: absolute;\n top: 4px;\n right: 4px;\n min-width: 16px;\n height: 16px;\n padding: 0 4px;\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n font-size: 10px;\n font-weight: 600;\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n line-height: 1;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n}\n\n.user-menu[_ngcontent-%COMP%] {\n position: relative;\n}\n\n.user-menu[_ngcontent-%COMP%] .avatar-btn[_ngcontent-%COMP%] {\n width: 36px;\n height: 36px;\n border-radius: 50%;\n border: none;\n background: transparent;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: box-shadow 0.15s, transform 0.15s;\n padding: 0;\n overflow: hidden;\n}\n\n.user-menu[_ngcontent-%COMP%] .avatar-btn[_ngcontent-%COMP%]:hover {\n transform: scale(1.05);\n}\n\n\n\n.user-menu[_ngcontent-%COMP%] .avatar-btn[_ngcontent-%COMP%] .icon-fallback[_ngcontent-%COMP%] {\n width: 100%;\n height: 100%;\n border-radius: 50%;\n border: 2px solid var(--mj-border-default);\n background: var(--mj-bg-surface-hover);\n display: flex;\n align-items: center;\n justify-content: center;\n transition: border-color 0.15s;\n}\n\n.user-menu[_ngcontent-%COMP%] .avatar-btn[_ngcontent-%COMP%]:hover .icon-fallback[_ngcontent-%COMP%] {\n border-color: var(--mj-brand-primary);\n}\n\n.user-menu[_ngcontent-%COMP%] .avatar-btn[_ngcontent-%COMP%] .icon-fallback[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-size: 16px;\n}\n\n\n\n.user-menu[_ngcontent-%COMP%] .avatar-btn[_ngcontent-%COMP%] .avatar-img[_ngcontent-%COMP%] {\n width: 100%;\n height: 100%;\n border-radius: 50%;\n object-fit: cover;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15);\n}\n\n.user-menu[_ngcontent-%COMP%] .avatar-btn[_ngcontent-%COMP%]:hover .avatar-img[_ngcontent-%COMP%] {\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);\n}\n\n\n\n.user-menu-header[_ngcontent-%COMP%] {\n padding: 12px 16px;\n background: var(--mj-bg-surface-sunken);\n}\n\n.user-menu-header[_ngcontent-%COMP%] .user-info[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.user-menu-header[_ngcontent-%COMP%] .user-name[_ngcontent-%COMP%] {\n font-weight: 600;\n font-size: 14px;\n color: var(--mj-text-primary);\n}\n\n.user-menu-header[_ngcontent-%COMP%] .user-email[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.user-menu-header[_ngcontent-%COMP%] .user-subtitle[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--mj-text-muted);\n font-style: italic;\n}\n\n\n\n.user-context-menu[_ngcontent-%COMP%] {\n position: absolute;\n top: 100%;\n right: 0;\n margin-top: 8px;\n background: var(--mj-bg-surface-elevated);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: var(--mj-shadow-lg);\n min-width: 180px;\n z-index: 10000;\n overflow: hidden;\n}\n\n.user-menu-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 16px;\n cursor: pointer;\n font-size: 14px;\n color: var(--mj-text-primary);\n transition: background 0.15s;\n}\n\n.user-menu-item[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n width: 18px;\n text-align: center;\n color: var(--mj-text-muted);\n font-size: 14px;\n}\n\n.user-menu-item[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.user-menu-item.danger[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n.user-menu-item.danger[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n.user-menu-item.danger[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface-elevated));\n}\n\n.user-menu-divider[_ngcontent-%COMP%] {\n height: 1px;\n background: var(--mj-border-default);\n margin: 4px 0;\n}\n\n\n\n.user-menu-item.disabled[_ngcontent-%COMP%] {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.user-menu-item.disabled[_ngcontent-%COMP%]:hover {\n background: transparent;\n}\n\n\n\n.theme-toggle-item[_ngcontent-%COMP%] {\n cursor: pointer;\n}\n\n.theme-toggle-track[_ngcontent-%COMP%] {\n position: relative;\n width: 40px;\n height: 22px;\n border-radius: 11px;\n background: var(--mj-bg-surface-active);\n margin-left: auto;\n transition: background 0.2s ease;\n flex-shrink: 0;\n}\n\n.theme-toggle-track.dark[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n}\n\n.theme-toggle-thumb[_ngcontent-%COMP%] {\n position: absolute;\n top: 2px;\n left: 2px;\n width: 18px;\n height: 18px;\n border-radius: 50%;\n background: var(--mj-bg-surface);\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n display: flex;\n align-items: center;\n justify-content: center;\n transition: transform 0.2s ease;\n}\n\n.theme-toggle-track.dark[_ngcontent-%COMP%] .theme-toggle-thumb[_ngcontent-%COMP%] {\n transform: translateX(18px);\n}\n\n.theme-toggle-icon[_ngcontent-%COMP%] {\n font-size: 10px;\n color: var(--mj-text-muted);\n}\n\n.theme-toggle-track.dark[_ngcontent-%COMP%] .theme-toggle-icon[_ngcontent-%COMP%] {\n color: var(--mj-text-inverse);\n}\n\n\n\n.user-menu-item[_ngcontent-%COMP%] .menu-shortcut[_ngcontent-%COMP%] {\n margin-left: auto;\n font-size: 11px;\n color: var(--mj-text-disabled);\n font-family: monospace;\n}\n\n\n\n.user-context-menu.menu-fade[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_menuFadeIn 0.15s ease-out;\n}\n\n.user-context-menu.menu-slide[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_menuSlideIn 0.2s ease-out;\n}\n\n@keyframes _ngcontent-%COMP%_menuFadeIn {\n from {\n opacity: 0;\n transform: translateY(-8px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes _ngcontent-%COMP%_menuSlideIn {\n from {\n opacity: 0;\n transform: translateY(-16px) scale(0.95);\n }\n to {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n}\n\n.shell-loading[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100vh;\n padding-bottom: 15vh;\n background: var(--mj-bg-page);\n}\n\n\n\n.loading-reset-panel[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: var(--mj-space-3);\n margin-top: var(--mj-space-10);\n padding: var(--mj-space-8);\n background: var(--mj-bg-surface-elevated);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n box-shadow: var(--mj-shadow-md);\n max-width: 420px;\n animation: _ngcontent-%COMP%_resetPanelFadeIn 0.4s ease-out;\n}\n\n.loading-reset-message[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: var(--mj-space-2);\n margin: 0;\n font-size: var(--mj-text-base);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-primary);\n}\n\n.loading-reset-message[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: var(--mj-text-lg);\n color: var(--mj-status-warning);\n}\n\n.loading-reset-hint[_ngcontent-%COMP%] {\n margin: 0;\n font-size: var(--mj-text-sm);\n color: var(--mj-text-secondary);\n text-align: center;\n line-height: var(--mj-leading-relaxed);\n}\n\n.loading-reset-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: var(--mj-space-2);\n margin-top: var(--mj-space-3);\n padding: var(--mj-space-3) var(--mj-space-6);\n font-size: var(--mj-text-base);\n font-weight: var(--mj-font-medium);\n font-family: var(--mj-font-family);\n color: var(--mj-text-inverse);\n background: var(--mj-brand-primary);\n border: 1px solid var(--mj-brand-primary);\n border-radius: var(--mj-radius-md);\n cursor: pointer;\n transition: var(--mj-transition-colors);\n}\n\n.loading-reset-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-brand-primary-hover);\n color: var(--mj-text-inverse);\n border-color: var(--mj-brand-primary-hover);\n box-shadow: var(--mj-shadow-md);\n}\n\n.loading-reset-btn[_ngcontent-%COMP%]:active {\n background: var(--mj-brand-primary-active);\n color: var(--mj-text-inverse);\n transform: scale(0.98);\n}\n\n.loading-reset-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: var(--mj-text-sm);\n}\n\n@keyframes _ngcontent-%COMP%_resetPanelFadeIn {\n from {\n opacity: 0;\n transform: translateY(12px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n\n\n.hamburger-btn[_ngcontent-%COMP%] {\n display: none;\n width: 40px;\n height: 40px;\n border-radius: 8px;\n border: none;\n background: none;\n cursor: pointer;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-secondary);\n font-size: 20px;\n transition: background 0.15s;\n}\n.hamburger-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n\n\n.mobile-nav-overlay[_ngcontent-%COMP%] {\n display: none;\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n z-index: 9998;\n}\n\n\n\n.mobile-nav-drawer[_ngcontent-%COMP%] {\n display: none;\n position: fixed;\n top: 0;\n left: 0;\n bottom: 0;\n width: 280px;\n max-width: 85vw;\n background: var(--mj-bg-surface);\n box-shadow: var(--mj-shadow-xl);\n z-index: 9999;\n flex-direction: column;\n transform: translateX(-100%);\n transition: transform 0.3s ease;\n}\n.mobile-nav-drawer.open[_ngcontent-%COMP%] {\n transform: translateX(0);\n}\n\n.mobile-nav-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-sunken);\n}\n.mobile-nav-header[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n font-weight: 600;\n font-size: 16px;\n color: var(--mj-text-primary);\n}\n.mobile-nav-header[_ngcontent-%COMP%] .close-btn[_ngcontent-%COMP%] {\n width: 36px;\n height: 36px;\n border-radius: 50%;\n border: none;\n background: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n font-size: 18px;\n transition: background 0.15s;\n}\n.mobile-nav-header[_ngcontent-%COMP%] .close-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-active);\n}\n\n.mobile-nav-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n padding: 16px 0;\n}\n\n.mobile-nav-section-title[_ngcontent-%COMP%] {\n padding: 8px 20px;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-disabled);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.mobile-nav-footer[_ngcontent-%COMP%] {\n border-top: 1px solid var(--mj-border-default);\n padding: 12px 16px;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.mobile-nav-action[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 16px;\n border: none;\n background: none;\n cursor: pointer;\n border-radius: 8px;\n color: var(--mj-text-secondary);\n font-size: 14px;\n font-weight: 500;\n transition: background 0.15s;\n width: 100%;\n text-align: left;\n}\n.mobile-nav-action[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n.mobile-nav-action[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 16px;\n width: 20px;\n text-align: center;\n}\n\n\n\n@media (max-width: 768px) {\n .hamburger-btn[_ngcontent-%COMP%] {\n display: flex;\n }\n\n .desktop-nav[_ngcontent-%COMP%] {\n display: none !important;\n }\n\n .desktop-only[_ngcontent-%COMP%] {\n display: none !important;\n }\n\n .mobile-nav-overlay[_ngcontent-%COMP%] {\n display: block;\n }\n\n .mobile-nav-drawer[_ngcontent-%COMP%] {\n display: flex;\n }\n\n .shell-header[_ngcontent-%COMP%] {\n padding: 0 12px;\n gap: 8px;\n }\n}\n\n\n\n .settings-fullscreen-window {\n \n\n box-shadow: none !important;\n border: none !important;\n}\n\n .settings-fullscreen-window .k-window-titlebar {\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n padding: 12px 16px;\n}\n\n .settings-fullscreen-window .k-window-title {\n font-size: 18px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n .settings-fullscreen-window .k-window-titlebar-actions {\n gap: 4px;\n}\n\n .settings-fullscreen-window .k-window-titlebar-action {\n width: 32px;\n height: 32px;\n border-radius: 6px;\n}\n\n .settings-fullscreen-window .k-window-titlebar-action:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n .settings-fullscreen-window .k-window-content {\n padding: 0;\n overflow: auto;\n background: var(--mj-bg-page);\n}\n\n\n\n .settings-fullscreen-window .k-window-titlebar-action[title=\"Minimize\"], \n .settings-fullscreen-window .k-window-titlebar-action[title=\"Maximize\"], \n .settings-fullscreen-window .k-window-titlebar-action .k-i-window-minimize, \n .settings-fullscreen-window .k-window-titlebar-action .k-i-window-maximize, \n .settings-fullscreen-window .k-window-titlebar-action .k-i-window {\n display: none !important;\n}\n\n\n\n\n\n.shell-search-bar[_ngcontent-%COMP%] {\n flex: 0 1 420px;\n min-width: 200px;\n max-width: 520px;\n margin: 0 12px;\n position: relative;\n z-index: 99999;\n}\n@media (max-width: 768px) {\n .shell-search-bar[_ngcontent-%COMP%] { display: none; }\n}\n\n\n\n\n\n\n.search-popup-overlay[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.3);\n z-index: 9999;\n animation: _ngcontent-%COMP%_fadeIn 0.15s ease;\n}\n\n@keyframes _ngcontent-%COMP%_fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n\n.search-popup[_ngcontent-%COMP%] {\n position: fixed;\n top: 60px; \n\n right: 16px;\n width: 480px;\n max-width: calc(100vw - 32px);\n background: var(--mj-bg-surface-elevated);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-xl);\n z-index: 10000;\n opacity: 0;\n transform: translateY(-10px);\n pointer-events: none;\n transition: opacity 0.2s ease, transform 0.2s ease;\n}\n\n.search-popup.open[_ngcontent-%COMP%] {\n opacity: 1;\n transform: translateY(0);\n pointer-events: all;\n}\n\n.search-popup-content[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px;\n}\n\n.search-entity-dropdown[_ngcontent-%COMP%] {\n min-width: 140px;\n max-width: 180px;\n flex-shrink: 0;\n}\n\n.search-input[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n height: 40px;\n padding: 8px 12px;\n font-size: 14px;\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n outline: none;\n display: block !important;\n box-sizing: border-box;\n}\n\n.search-input[_ngcontent-%COMP%]:focus {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n}\n\n.search-submit-btn[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n border-radius: 8px;\n border: none;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 16px;\n transition: background 0.15s;\n flex-shrink: 0;\n}\n\n.search-submit-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-brand-primary-hover);\n}\n\n.search-submit-btn[_ngcontent-%COMP%]:active {\n background: var(--mj-brand-primary-hover);\n}\n\n\n\n.notification-badge-mobile[_ngcontent-%COMP%] {\n position: absolute;\n top: 8px;\n right: 8px;\n min-width: 18px;\n height: 18px;\n padding: 0 5px;\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n font-size: 11px;\n font-weight: 600;\n border-radius: 9px;\n display: flex;\n align-items: center;\n justify-content: center;\n line-height: 1;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n}\n\n\n\n@media (max-width: 768px) {\n .search-popup[_ngcontent-%COMP%] {\n top: 60px;\n left: 16px;\n right: 16px;\n width: auto;\n max-width: none;\n }\n\n .search-popup-content[_ngcontent-%COMP%] {\n flex-wrap: wrap;\n }\n\n .search-entity-dropdown[_ngcontent-%COMP%] {\n width: 100%;\n }\n\n .search-input[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n }\n}\n\n\n\n\n\n.pin-progress-backdrop[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: color-mix(in srgb, var(--mj-text-primary) 40%, transparent);\n z-index: 100000;\n display: flex;\n align-items: center;\n justify-content: center;\n animation: _ngcontent-%COMP%_pinBackdropIn 0.2s ease;\n}\n\n@keyframes _ngcontent-%COMP%_pinBackdropIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n.pin-progress-modal[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border-radius: var(--mj-radius-xl);\n padding: 28px 40px;\n display: flex;\n align-items: center;\n gap: 16px;\n box-shadow: 0 16px 48px color-mix(in srgb, var(--mj-text-primary) 30%, transparent);\n animation: _ngcontent-%COMP%_pinModalIn 0.25s ease;\n}\n\n@keyframes _ngcontent-%COMP%_pinModalIn {\n from { opacity: 0; transform: scale(0.9) translateY(8px); }\n to { opacity: 1; transform: scale(1) translateY(0); }\n}\n\n.pin-progress-text[_ngcontent-%COMP%] {\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-medium);\n color: var(--mj-text-secondary);\n white-space: nowrap;\n}"] });
2722
2914
  }
2723
2915
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ShellComponent, [{
2724
2916
  type: Component,
2725
- args: [{ standalone: false, selector: 'mj-shell', template: "<div class=\"shell-container\" [class.hidden]=\"loading\" [class.tabs-visible]=\"tabBarVisible\">\n <!-- Header -->\n <header class=\"shell-header\">\n <!-- MJ Logo -->\n <div class=\"mj-logo\" title=\"MemberJunction\"></div>\n\n <!-- Mobile Hamburger Button -->\n <button class=\"hamburger-btn\" (click)=\"toggleMobileNav()\" title=\"Menu\">\n <i class=\"fa-solid fa-bars\"></i>\n </button>\n\n <!-- Nav Bar Apps: Left of App Switcher -->\n @if (leftOfSwitcherApps.length > 0) {\n <div class=\"nav-bar-apps left-of-switcher\">\n @for (app of leftOfSwitcherApps; track app) {\n <button\n class=\"nav-bar-app-btn\"\n [class.active]=\"IsActiveApp(app)\"\n [title]=\"app.Name\"\n [style.--app-color]=\"app.GetColor()\"\n (click)=\"onNavBarAppClick(app, $event)\"\n (dblclick)=\"onNavBarAppDblClick(app, $event)\">\n <i [class]=\"app.Icon\"></i>\n </button>\n }\n </div>\n }\n\n <!-- App Switcher -->\n <mj-app-switcher\n [activeApp]=\"activeApp\"\n [isViewingSystemTab]=\"isViewingSystemTab\"\n [loadingAppId]=\"loadingAppId\"\n (appSelected)=\"onAppSwitch($event)\">\n </mj-app-switcher>\n\n <!-- App Navigation (desktop only) -->\n @if (activeApp) {\n <mj-app-nav\n class=\"desktop-nav\"\n [app]=\"activeApp\"\n (navItemClick)=\"onNavItemClick($event)\"\n (navItemDismiss)=\"onNavItemDismiss($event)\">\n </mj-app-nav>\n }\n\n <!-- Spacer -->\n <div class=\"spacer\"></div>\n\n <!-- Actions (search, notifications, user menu) -->\n <div class=\"header-actions\">\n <button class=\"icon-btn desktop-only search-toggle-btn\" title=\"Search\" (click)=\"toggleSearch()\">\n <i class=\"fa-solid fa-search\"></i>\n </button>\n <button class=\"icon-btn desktop-only notification-btn\" title=\"Notifications\" (click)=\"showNotifications()\">\n <i class=\"fa-solid fa-bell\"></i>\n @if (unreadNotificationCount > 0) {\n <span class=\"notification-badge\">\n {{ unreadNotificationCount > 99 ? '99+' : unreadNotificationCount }}\n </span>\n }\n </button>\n\n <!-- Nav Bar Apps: Left of User Menu -->\n @if (leftOfUserMenuApps.length > 0) {\n <div class=\"nav-bar-apps left-of-user-menu\">\n @for (app of leftOfUserMenuApps; track app) {\n <button\n class=\"nav-bar-app-btn\"\n [class.active]=\"IsActiveApp(app)\"\n [title]=\"app.Name\"\n [style.--app-color]=\"app.GetColor()\"\n (click)=\"onNavBarAppClick(app, $event)\"\n (dblclick)=\"onNavBarAppDblClick(app, $event)\">\n <i [class]=\"app.Icon\"></i>\n </button>\n }\n </div>\n }\n\n <div class=\"user-menu\">\n <button class=\"avatar-btn\" (click)=\"toggleUserMenu($event)\">\n @if (userImageURL) {\n <img [src]=\"userImageURL\" alt=\"User avatar\" class=\"avatar-img\" />\n } @else {\n <div class=\"icon-fallback\">\n <i [class]=\"userIconClass || 'fa-solid fa-user'\"></i>\n </div>\n }\n </button>\n <!-- User Context Menu (Dynamic) -->\n @if (userMenuVisible) {\n <div class=\"user-context-menu\"\n [class.menu-fade]=\"getUserMenuOptions()?.animationStyle === 'fade'\"\n [class.menu-slide]=\"getUserMenuOptions()?.animationStyle === 'slide'\">\n <!-- User Header -->\n @if (getUserMenuOptions()?.showUserName) {\n <div class=\"user-menu-header\">\n <div class=\"user-info\">\n <span class=\"user-name\">{{ getUserDisplayInfo()?.name || userName }}</span>\n @if (getUserMenuOptions()?.showUserEmail && getUserDisplayInfo()?.email) {\n <span class=\"user-email\">\n {{ getUserDisplayInfo()?.email }}\n </span>\n }\n </div>\n </div>\n <div class=\"user-menu-divider\"></div>\n }\n <!-- Dynamic Menu Items -->\n @for (element of userMenuElements; track element) {\n <!-- Divider -->\n @if (isMenuDivider(element)) {\n <div class=\"user-menu-divider\"></div>\n }\n <!-- Menu Item -->\n @if (!isMenuDivider(element)) {\n @if (asMenuItem(element); as item) {\n @if (item.id === 'toggle-theme') {\n <div class=\"user-menu-item theme-toggle-item\"\n [title]=\"item.tooltip || ''\"\n (click)=\"onUserMenuItemClick(item.id)\">\n <i [class]=\"item.icon\"></i>\n <span class=\"menu-label\">{{ item.label }}</span>\n <div class=\"theme-toggle-track\" [class.dark]=\"IsDarkMode\">\n <div class=\"theme-toggle-thumb\">\n <i [class]=\"IsDarkMode ? 'fa-solid fa-moon' : 'fa-solid fa-sun'\" class=\"theme-toggle-icon\"></i>\n </div>\n </div>\n </div>\n } @else {\n <div class=\"user-menu-item\"\n [class.disabled]=\"!item.enabled\"\n [class.danger]=\"item.cssClass === 'danger'\"\n [style.color]=\"item.color || null\"\n [title]=\"item.tooltip || ''\"\n (click)=\"item.enabled && onUserMenuItemClick(item.id)\">\n <i [class]=\"item.icon\"></i>\n <span class=\"menu-label\">{{ item.label }}</span>\n @if (item.shortcut) {\n <span class=\"menu-shortcut\">{{ item.shortcut }}</span>\n }\n </div>\n }\n }\n }\n }\n </div>\n }\n </div>\n </div>\n </header>\n\n <!-- Search Popup -->\n @if (isSearchOpen) {\n <div class=\"search-popup-overlay\" (click)=\"closeSearch()\"></div>\n }\n <div class=\"search-popup\" [class.open]=\"isSearchOpen\">\n <div class=\"search-popup-content\" (click)=\"$event.stopPropagation()\">\n <mj-dropdown\n [Data]=\"searchableEntities\"\n TextField=\"Name\"\n ValueField=\"ID\"\n class=\"search-entity-dropdown\"\n [(ngModel)]=\"selectedEntity\">\n </mj-dropdown>\n <input\n type=\"text\"\n #searchInput\n placeholder=\"Search...\"\n class=\"mj-input search-input\"\n (keydown.enter)=\"onSearch($event)\"\n />\n <button class=\"search-submit-btn\" (click)=\"onSearch($event)\" title=\"Search\">\n <i class=\"fa-solid fa-search\"></i>\n </button>\n </div>\n </div>\n\n <!-- Mobile Navigation Drawer -->\n @if (mobileNavOpen) {\n <div class=\"mobile-nav-overlay\" (click)=\"closeMobileNav()\"></div>\n }\n <div class=\"mobile-nav-drawer\" [class.open]=\"mobileNavOpen\">\n <div class=\"mobile-nav-header\">\n <span>Navigation</span>\n <button class=\"close-btn\" (click)=\"closeMobileNav()\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n @if (activeApp) {\n <div class=\"mobile-nav-content\">\n <div class=\"mobile-nav-section-title\">{{ activeApp.Name }}</div>\n <mj-app-nav\n [app]=\"activeApp\"\n (navItemClick)=\"onNavItemClick($event)\"\n (navItemDismiss)=\"onNavItemDismiss($event)\">\n </mj-app-nav>\n </div>\n }\n <div class=\"mobile-nav-footer\">\n <button class=\"mobile-nav-action\" title=\"Search\" (click)=\"toggleSearch(); closeMobileNav()\">\n <i class=\"fa-solid fa-search\"></i>\n <span>Search</span>\n </button>\n <button class=\"mobile-nav-action\" title=\"Notifications\" (click)=\"showNotifications(); closeMobileNav()\">\n <i class=\"fa-solid fa-bell\"></i>\n <span>Notifications</span>\n @if (unreadNotificationCount > 0) {\n <span class=\"notification-badge-mobile\">\n {{ unreadNotificationCount > 99 ? '99+' : unreadNotificationCount }}\n </span>\n }\n </button>\n </div>\n </div>\n\n <!-- Tab Container - with dynamic tab bar visibility -->\n <mj-tab-container\n [class.hide-tab-bar]=\"!tabBarVisible\"\n (firstResourceLoadComplete)=\"onFirstResourceLoadComplete()\"\n (layoutInitError)=\"handleLayoutError()\">\n </mj-tab-container>\n</div>\n\n<!-- Loading State -->\n@if (loading) {\n <div class=\"shell-loading\">\n <mj-loading\n [text]=\"currentLoadingText\"\n [textColor]=\"currentLoadingTextColor\"\n [logoColor]=\"currentLoadingColor\"\n [logoGradient]=\"currentLoadingGradient\"\n [animation]=\"currentLoadingAnimation\"\n size=\"large\">\n </mj-loading>\n @if (ShowResetOption) {\n <div class=\"loading-reset-panel\">\n <p class=\"loading-reset-message\">\n <i class=\"fa-regular fa-clock\"></i>\n Taking longer than expected\n </p>\n <p class=\"loading-reset-hint\">\n This can happen after updates or due to cached data issues.\n </p>\n <button class=\"loading-reset-btn\" (click)=\"ResetApplication()\">\n <i class=\"fa-solid fa-arrows-rotate\"></i>\n Reset\n </button>\n </div>\n }\n </div>\n}\n\n<!-- App Access Error Dialog -->\n<mj-app-access-dialog\n #appAccessDialog\n (result)=\"onAppAccessDialogResult($event)\">\n</mj-app-access-dialog>\n\n<!-- Command Palette -->\n<mj-command-palette (AppSelected)=\"onAppSwitch($event)\"></mj-command-palette>\n\n<!-- Pin Progress Overlay -->\n@if (PinProgressVisible) {\n <div class=\"pin-progress-backdrop\">\n <div class=\"pin-progress-modal\">\n <mj-loading [showText]=\"false\" size=\"small\"></mj-loading>\n <span class=\"pin-progress-text\">{{ PinProgressText }}</span>\n </div>\n </div>\n}\n", styles: [":host {\n display: block;\n height: 100vh;\n width: 100%;\n overflow: hidden;\n}\n\n/* MJ Logo - uses design token for theme switching & white-labeling */\n.mj-logo {\n width: 32px;\n height: 18px;\n background-image: var(--mj-logo-mark);\n background-repeat: no-repeat;\n background-position: center;\n background-size: contain;\n flex-shrink: 0;\n}\n\n.shell-container {\n display: flex;\n flex-direction: column;\n height: 100vh;\n width: 100%;\n overflow: hidden;\n}\n\n/* Hide shell container while loading - allows tab container to render and load\n first resource in background while shell loading indicator is visible */\n.shell-container.hidden {\n visibility: hidden;\n position: absolute;\n pointer-events: none;\n}\n\nmj-tab-container {\n flex: 1;\n min-height: 0;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n transition: all 0.2s ease-in-out;\n}\n\n/* Hide Golden Layout tab headers when only one tab */\nmj-tab-container.hide-tab-bar ::ng-deep .lm_header {\n display: none;\n}\n\n/* Show tab headers when multiple tabs */\nmj-tab-container:not(.hide-tab-bar) ::ng-deep .lm_header {\n opacity: 1;\n max-height: 40px;\n transition: opacity 0.2s ease-in-out, max-height 0.2s ease-in-out;\n}\n\n/* Adjust content area height when tabs hidden */\nmj-tab-container.hide-tab-bar ::ng-deep .lm_content {\n height: 100% !important;\n}\n\n/* Ensure smooth transitions */\nmj-tab-container ::ng-deep .lm_stack {\n transition: all 0.2s ease-in-out;\n}\n\n.shell-header {\n height: 60px;\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n display: flex;\n align-items: center;\n padding: 0 16px;\n gap: 16px;\n box-shadow: var(--mj-shadow-sm);\n flex-shrink: 0;\n}\n\n/* Nav Bar Apps - permanent app icons in the header */\n.nav-bar-apps {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.nav-bar-apps.left-of-switcher {\n /* No extra margin - header gap handles spacing */\n /* This prevents the app switcher from shifting when icons are hidden */\n}\n\n.nav-bar-apps.left-of-user-menu {\n margin-right: 8px;\n}\n\n.nav-bar-app-btn {\n --app-color: var(--mj-text-muted);\n width: 40px;\n height: 40px;\n border-radius: 10px;\n border: none;\n background: transparent;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-secondary);\n font-size: 18px;\n transition: all 0.15s ease;\n position: relative;\n}\n\n.nav-bar-app-btn:hover {\n background: color-mix(in srgb, var(--app-color) 15%, transparent);\n color: var(--app-color);\n}\n\n.nav-bar-app-btn.active {\n background: color-mix(in srgb, var(--app-color) 20%, transparent);\n color: var(--app-color);\n}\n\n.nav-bar-app-btn.active::after {\n content: '';\n position: absolute;\n bottom: 6px;\n left: 50%;\n transform: translateX(-50%);\n width: 16px;\n height: 3px;\n background: var(--app-color);\n border-radius: 2px;\n}\n\n.nav-bar-app-btn i {\n transition: transform 0.15s ease;\n margin-top: 2px; /* Align with app switcher icon */\n}\n\n.nav-bar-app-btn:hover i {\n transform: scale(1.1);\n}\n\n.spacer {\n flex: 1;\n}\n\n.header-actions {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.icon-btn {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n border: none;\n background: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n font-size: 18px;\n transition: background 0.15s;\n}\n\n.icon-btn:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n/* Notification button with badge */\n.notification-btn {\n position: relative;\n}\n\n.notification-badge {\n position: absolute;\n top: 4px;\n right: 4px;\n min-width: 16px;\n height: 16px;\n padding: 0 4px;\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n font-size: 10px;\n font-weight: 600;\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n line-height: 1;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n}\n\n.user-menu {\n position: relative;\n}\n\n.user-menu .avatar-btn {\n width: 36px;\n height: 36px;\n border-radius: 50%;\n border: none;\n background: transparent;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: box-shadow 0.15s, transform 0.15s;\n padding: 0;\n overflow: hidden;\n}\n\n.user-menu .avatar-btn:hover {\n transform: scale(1.05);\n}\n\n/* Icon fallback styling - shows gray circle with icon */\n.user-menu .avatar-btn .icon-fallback {\n width: 100%;\n height: 100%;\n border-radius: 50%;\n border: 2px solid var(--mj-border-default);\n background: var(--mj-bg-surface-hover);\n display: flex;\n align-items: center;\n justify-content: center;\n transition: border-color 0.15s;\n}\n\n.user-menu .avatar-btn:hover .icon-fallback {\n border-color: var(--mj-brand-primary);\n}\n\n.user-menu .avatar-btn .icon-fallback i {\n color: var(--mj-text-muted);\n font-size: 16px;\n}\n\n/* Avatar image - replaces the gray circle entirely */\n.user-menu .avatar-btn .avatar-img {\n width: 100%;\n height: 100%;\n border-radius: 50%;\n object-fit: cover;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15);\n}\n\n.user-menu .avatar-btn:hover .avatar-img {\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);\n}\n\n/* User Menu Header */\n.user-menu-header {\n padding: 12px 16px;\n background: var(--mj-bg-surface-sunken);\n}\n\n.user-menu-header .user-info {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.user-menu-header .user-name {\n font-weight: 600;\n font-size: 14px;\n color: var(--mj-text-primary);\n}\n\n.user-menu-header .user-email {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n/* User Context Menu */\n.user-context-menu {\n position: absolute;\n top: 100%;\n right: 0;\n margin-top: 8px;\n background: var(--mj-bg-surface-elevated);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: var(--mj-shadow-lg);\n min-width: 180px;\n z-index: 10000;\n overflow: hidden;\n}\n\n.user-menu-item {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 16px;\n cursor: pointer;\n font-size: 14px;\n color: var(--mj-text-primary);\n transition: background 0.15s;\n}\n\n.user-menu-item i {\n width: 18px;\n text-align: center;\n color: var(--mj-text-muted);\n font-size: 14px;\n}\n\n.user-menu-item:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.user-menu-item.danger {\n color: var(--mj-status-error);\n}\n\n.user-menu-item.danger i {\n color: var(--mj-status-error);\n}\n\n.user-menu-item.danger:hover {\n background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface-elevated));\n}\n\n.user-menu-divider {\n height: 1px;\n background: var(--mj-border-default);\n margin: 4px 0;\n}\n\n/* Menu item disabled state */\n.user-menu-item.disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.user-menu-item.disabled:hover {\n background: transparent;\n}\n\n/* Theme Toggle Switch */\n.theme-toggle-item {\n cursor: pointer;\n}\n\n.theme-toggle-track {\n position: relative;\n width: 40px;\n height: 22px;\n border-radius: 11px;\n background: var(--mj-bg-surface-active);\n margin-left: auto;\n transition: background 0.2s ease;\n flex-shrink: 0;\n}\n\n.theme-toggle-track.dark {\n background: var(--mj-brand-primary);\n}\n\n.theme-toggle-thumb {\n position: absolute;\n top: 2px;\n left: 2px;\n width: 18px;\n height: 18px;\n border-radius: 50%;\n background: var(--mj-bg-surface);\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n display: flex;\n align-items: center;\n justify-content: center;\n transition: transform 0.2s ease;\n}\n\n.theme-toggle-track.dark .theme-toggle-thumb {\n transform: translateX(18px);\n}\n\n.theme-toggle-icon {\n font-size: 10px;\n color: var(--mj-text-muted);\n}\n\n.theme-toggle-track.dark .theme-toggle-icon {\n color: var(--mj-text-inverse);\n}\n\n/* Menu shortcut hint */\n.user-menu-item .menu-shortcut {\n margin-left: auto;\n font-size: 11px;\n color: var(--mj-text-disabled);\n font-family: monospace;\n}\n\n/* Menu animations */\n.user-context-menu.menu-fade {\n animation: menuFadeIn 0.15s ease-out;\n}\n\n.user-context-menu.menu-slide {\n animation: menuSlideIn 0.2s ease-out;\n}\n\n@keyframes menuFadeIn {\n from {\n opacity: 0;\n transform: translateY(-8px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes menuSlideIn {\n from {\n opacity: 0;\n transform: translateY(-16px) scale(0.95);\n }\n to {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n}\n\n.shell-loading {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100vh;\n padding-bottom: 15vh;\n background: var(--mj-bg-page);\n}\n\n/* Loading Recovery Reset Panel */\n.loading-reset-panel {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: var(--mj-space-3);\n margin-top: var(--mj-space-10);\n padding: var(--mj-space-8);\n background: var(--mj-bg-surface-elevated);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n box-shadow: var(--mj-shadow-md);\n max-width: 420px;\n animation: resetPanelFadeIn 0.4s ease-out;\n}\n\n.loading-reset-message {\n display: flex;\n align-items: center;\n gap: var(--mj-space-2);\n margin: 0;\n font-size: var(--mj-text-base);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-primary);\n}\n\n.loading-reset-message i {\n font-size: var(--mj-text-lg);\n color: var(--mj-status-warning);\n}\n\n.loading-reset-hint {\n margin: 0;\n font-size: var(--mj-text-sm);\n color: var(--mj-text-secondary);\n text-align: center;\n line-height: var(--mj-leading-relaxed);\n}\n\n.loading-reset-btn {\n display: inline-flex;\n align-items: center;\n gap: var(--mj-space-2);\n margin-top: var(--mj-space-3);\n padding: var(--mj-space-3) var(--mj-space-6);\n font-size: var(--mj-text-base);\n font-weight: var(--mj-font-medium);\n font-family: var(--mj-font-family);\n color: var(--mj-text-inverse);\n background: var(--mj-brand-primary);\n border: 1px solid var(--mj-brand-primary);\n border-radius: var(--mj-radius-md);\n cursor: pointer;\n transition: var(--mj-transition-colors);\n}\n\n.loading-reset-btn:hover {\n background: var(--mj-brand-primary-hover);\n color: var(--mj-text-inverse);\n border-color: var(--mj-brand-primary-hover);\n box-shadow: var(--mj-shadow-md);\n}\n\n.loading-reset-btn:active {\n background: var(--mj-brand-primary-active);\n color: var(--mj-text-inverse);\n transform: scale(0.98);\n}\n\n.loading-reset-btn i {\n font-size: var(--mj-text-sm);\n}\n\n@keyframes resetPanelFadeIn {\n from {\n opacity: 0;\n transform: translateY(12px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n/* Hamburger button - hidden on desktop */\n.hamburger-btn {\n display: none;\n width: 40px;\n height: 40px;\n border-radius: 8px;\n border: none;\n background: none;\n cursor: pointer;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-secondary);\n font-size: 20px;\n transition: background 0.15s;\n}\n.hamburger-btn:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n/* Mobile Navigation Overlay */\n.mobile-nav-overlay {\n display: none;\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n z-index: 9998;\n}\n\n/* Mobile Navigation Drawer */\n.mobile-nav-drawer {\n display: none;\n position: fixed;\n top: 0;\n left: 0;\n bottom: 0;\n width: 280px;\n max-width: 85vw;\n background: var(--mj-bg-surface);\n box-shadow: var(--mj-shadow-xl);\n z-index: 9999;\n flex-direction: column;\n transform: translateX(-100%);\n transition: transform 0.3s ease;\n}\n.mobile-nav-drawer.open {\n transform: translateX(0);\n}\n\n.mobile-nav-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-sunken);\n}\n.mobile-nav-header span {\n font-weight: 600;\n font-size: 16px;\n color: var(--mj-text-primary);\n}\n.mobile-nav-header .close-btn {\n width: 36px;\n height: 36px;\n border-radius: 50%;\n border: none;\n background: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n font-size: 18px;\n transition: background 0.15s;\n}\n.mobile-nav-header .close-btn:hover {\n background: var(--mj-bg-surface-active);\n}\n\n.mobile-nav-content {\n flex: 1;\n overflow-y: auto;\n padding: 16px 0;\n}\n\n.mobile-nav-section-title {\n padding: 8px 20px;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-disabled);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.mobile-nav-footer {\n border-top: 1px solid var(--mj-border-default);\n padding: 12px 16px;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.mobile-nav-action {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 16px;\n border: none;\n background: none;\n cursor: pointer;\n border-radius: 8px;\n color: var(--mj-text-secondary);\n font-size: 14px;\n font-weight: 500;\n transition: background 0.15s;\n width: 100%;\n text-align: left;\n}\n.mobile-nav-action:hover {\n background: var(--mj-bg-surface-hover);\n}\n.mobile-nav-action i {\n font-size: 16px;\n width: 20px;\n text-align: center;\n}\n\n/* Mobile Responsive Styles */\n@media (max-width: 768px) {\n .hamburger-btn {\n display: flex;\n }\n\n .desktop-nav {\n display: none !important;\n }\n\n .desktop-only {\n display: none !important;\n }\n\n .mobile-nav-overlay {\n display: block;\n }\n\n .mobile-nav-drawer {\n display: flex;\n }\n\n .shell-header {\n padding: 0 12px;\n gap: 8px;\n }\n}\n\n/* Settings Full-Screen Window Styles */\n::ng-deep .settings-fullscreen-window {\n /* Remove window chrome for full-screen feel */\n box-shadow: none !important;\n border: none !important;\n}\n\n::ng-deep .settings-fullscreen-window .k-window-titlebar {\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n padding: 12px 16px;\n}\n\n::ng-deep .settings-fullscreen-window .k-window-title {\n font-size: 18px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n::ng-deep .settings-fullscreen-window .k-window-titlebar-actions {\n gap: 4px;\n}\n\n::ng-deep .settings-fullscreen-window .k-window-titlebar-action {\n width: 32px;\n height: 32px;\n border-radius: 6px;\n}\n\n::ng-deep .settings-fullscreen-window .k-window-titlebar-action:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n::ng-deep .settings-fullscreen-window .k-window-content {\n padding: 0;\n overflow: auto;\n background: var(--mj-bg-page);\n}\n\n/* Hide minimize/maximize buttons - only show close */\n::ng-deep .settings-fullscreen-window .k-window-titlebar-action[title=\"Minimize\"],\n::ng-deep .settings-fullscreen-window .k-window-titlebar-action[title=\"Maximize\"],\n::ng-deep .settings-fullscreen-window .k-window-titlebar-action .k-i-window-minimize,\n::ng-deep .settings-fullscreen-window .k-window-titlebar-action .k-i-window-maximize,\n::ng-deep .settings-fullscreen-window .k-window-titlebar-action .k-i-window {\n display: none !important;\n}\n\n/* ========================================\n SEARCH POPUP\n ======================================== */\n\n.search-popup-overlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.3);\n z-index: 9999;\n animation: fadeIn 0.15s ease;\n}\n\n@keyframes fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n\n.search-popup {\n position: fixed;\n top: 60px; /* Below header */\n right: 16px;\n width: 480px;\n max-width: calc(100vw - 32px);\n background: var(--mj-bg-surface-elevated);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-xl);\n z-index: 10000;\n opacity: 0;\n transform: translateY(-10px);\n pointer-events: none;\n transition: opacity 0.2s ease, transform 0.2s ease;\n}\n\n.search-popup.open {\n opacity: 1;\n transform: translateY(0);\n pointer-events: all;\n}\n\n.search-popup-content {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px;\n}\n\n.search-entity-dropdown {\n min-width: 140px;\n max-width: 180px;\n flex-shrink: 0;\n}\n\n.search-input {\n flex: 1;\n min-width: 0;\n height: 40px;\n padding: 8px 12px;\n font-size: 14px;\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n outline: none;\n display: block !important;\n box-sizing: border-box;\n}\n\n.search-input:focus {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n}\n\n.search-submit-btn {\n width: 40px;\n height: 40px;\n border-radius: 8px;\n border: none;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 16px;\n transition: background 0.15s;\n flex-shrink: 0;\n}\n\n.search-submit-btn:hover {\n background: var(--mj-brand-primary-hover);\n}\n\n.search-submit-btn:active {\n background: var(--mj-brand-primary-hover);\n}\n\n/* Mobile notification badge */\n.notification-badge-mobile {\n position: absolute;\n top: 8px;\n right: 8px;\n min-width: 18px;\n height: 18px;\n padding: 0 5px;\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n font-size: 11px;\n font-weight: 600;\n border-radius: 9px;\n display: flex;\n align-items: center;\n justify-content: center;\n line-height: 1;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n}\n\n/* Mobile-specific search popup adjustments */\n@media (max-width: 768px) {\n .search-popup {\n top: 60px;\n left: 16px;\n right: 16px;\n width: auto;\n max-width: none;\n }\n\n .search-popup-content {\n flex-wrap: wrap;\n }\n\n .search-entity-dropdown {\n width: 100%;\n }\n\n .search-input {\n flex: 1;\n min-width: 0;\n }\n}\n\n/* ========================================\n PIN PROGRESS OVERLAY\n ======================================== */\n.pin-progress-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: color-mix(in srgb, var(--mj-text-primary) 40%, transparent);\n z-index: 100000;\n display: flex;\n align-items: center;\n justify-content: center;\n animation: pinBackdropIn 0.2s ease;\n}\n\n@keyframes pinBackdropIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n.pin-progress-modal {\n background: var(--mj-bg-surface);\n border-radius: var(--mj-radius-xl);\n padding: 28px 40px;\n display: flex;\n align-items: center;\n gap: 16px;\n box-shadow: 0 16px 48px color-mix(in srgb, var(--mj-text-primary) 30%, transparent);\n animation: pinModalIn 0.25s ease;\n}\n\n@keyframes pinModalIn {\n from { opacity: 0; transform: scale(0.9) translateY(8px); }\n to { opacity: 1; transform: scale(1) translateY(0); }\n}\n\n.pin-progress-text {\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-medium);\n color: var(--mj-text-secondary);\n white-space: nowrap;\n}"] }]
2726
- }], () => [{ type: i1.ApplicationManager }, { type: i1.WorkspaceStateManager }, { type: i1.GoldenLayoutManager }, { type: i1.TabService }, { type: i2.NavigationService }, { type: i3.ActivatedRoute }, { type: i3.Router }, { type: i4.MJAuthBase }, { type: i0.ChangeDetectorRef }, { type: i5.UserAvatarService }, { type: i6.SettingsDialogService }, { type: i0.ViewContainerRef }, { type: i2.TitleService }, { type: i2.DeveloperModeService }, { type: i7.CommandPaletteService }, { type: i2.ThemeService }, { type: i2.HomeAppPinService }], { searchInput: [{
2917
+ args: [{ standalone: false, selector: 'mj-shell', template: "<div class=\"shell-container\" [class.hidden]=\"loading\" [class.tabs-visible]=\"tabBarVisible\">\n <!-- Header -->\n <header class=\"shell-header\">\n <!-- MJ Logo -->\n <div class=\"mj-logo\" title=\"MemberJunction\"></div>\n\n <!-- Mobile Hamburger Button -->\n <button class=\"hamburger-btn\" (click)=\"toggleMobileNav()\" title=\"Menu\">\n <i class=\"fa-solid fa-bars\"></i>\n </button>\n\n <!-- Nav Bar Apps: Left of App Switcher -->\n @if (leftOfSwitcherApps.length > 0) {\n <div class=\"nav-bar-apps left-of-switcher\">\n @for (app of leftOfSwitcherApps; track app) {\n <button\n class=\"nav-bar-app-btn\"\n [class.active]=\"IsActiveApp(app)\"\n [title]=\"app.Name\"\n [style.--app-color]=\"app.GetColor()\"\n (click)=\"onNavBarAppClick(app, $event)\"\n (dblclick)=\"onNavBarAppDblClick(app, $event)\">\n <i [class]=\"app.Icon\"></i>\n </button>\n }\n </div>\n }\n\n <!-- App Switcher -->\n <mj-app-switcher\n [activeApp]=\"activeApp\"\n [isViewingSystemTab]=\"isViewingSystemTab\"\n [loadingAppId]=\"loadingAppId\"\n (appSelected)=\"onAppSwitch($event)\">\n </mj-app-switcher>\n\n <!-- App Navigation (desktop only) -->\n @if (activeApp) {\n <mj-app-nav\n class=\"desktop-nav\"\n [app]=\"activeApp\"\n (navItemClick)=\"onNavItemClick($event)\"\n (navItemDismiss)=\"onNavItemDismiss($event)\">\n </mj-app-nav>\n }\n\n <!-- Universal Search Bar -->\n @if (ShowSearchBar) {\n <div class=\"shell-search-bar desktop-only\">\n <mj-search-composite\n #shellSearchComposite\n Placeholder=\"Search everything...\"\n [ShowShortcutHint]=\"true\"\n [EnablePreview]=\"ShowSearchPreview\"\n [EnableRecent]=\"true\"\n [MaxPreviewResults]=\"8\"\n (ResultSelected)=\"OnSearchResultSelected($event)\"\n (SearchSubmitted)=\"OnSearchSubmitted($event)\"\n (SeeAllRequested)=\"OnSeeAllSearch($event)\">\n </mj-search-composite>\n </div>\n }\n <!-- Spacer -->\n <div class=\"spacer\"></div>\n <!-- Actions (notifications, user menu) -->\n <div class=\"header-actions\">\n <button class=\"icon-btn desktop-only notification-btn\" title=\"Notifications\" (click)=\"showNotifications()\">\n <i class=\"fa-solid fa-bell\"></i>\n @if (unreadNotificationCount > 0) {\n <span class=\"notification-badge\">\n {{ unreadNotificationCount > 99 ? '99+' : unreadNotificationCount }}\n </span>\n }\n </button>\n\n <!-- Nav Bar Apps: Left of User Menu -->\n @if (leftOfUserMenuApps.length > 0) {\n <div class=\"nav-bar-apps left-of-user-menu\">\n @for (app of leftOfUserMenuApps; track app) {\n <button\n class=\"nav-bar-app-btn\"\n [class.active]=\"IsActiveApp(app)\"\n [title]=\"app.Name\"\n [style.--app-color]=\"app.GetColor()\"\n (click)=\"onNavBarAppClick(app, $event)\"\n (dblclick)=\"onNavBarAppDblClick(app, $event)\">\n <i [class]=\"app.Icon\"></i>\n </button>\n }\n </div>\n }\n\n <div class=\"user-menu\">\n <button class=\"avatar-btn\" (click)=\"toggleUserMenu($event)\">\n @if (userImageURL) {\n <img [src]=\"userImageURL\" alt=\"User avatar\" class=\"avatar-img\" />\n } @else {\n <div class=\"icon-fallback\">\n <i [class]=\"userIconClass || 'fa-solid fa-user'\"></i>\n </div>\n }\n </button>\n <!-- User Context Menu (Dynamic) -->\n @if (userMenuVisible) {\n <div class=\"user-context-menu\"\n [class.menu-fade]=\"getUserMenuOptions()?.animationStyle === 'fade'\"\n [class.menu-slide]=\"getUserMenuOptions()?.animationStyle === 'slide'\">\n <!-- User Header -->\n @if (getUserMenuOptions()?.showUserName) {\n <div class=\"user-menu-header\">\n <div class=\"user-info\">\n <span class=\"user-name\">{{ getUserDisplayInfo()?.name || userName }}</span>\n @if (getUserMenuOptions()?.showUserEmail && getUserDisplayInfo()?.email) {\n <span class=\"user-email\">\n {{ getUserDisplayInfo()?.email }}\n </span>\n }\n @if (getUserDisplayInfo()?.subtitle) {\n <span class=\"user-subtitle\">{{ getUserDisplayInfo()?.subtitle }}</span>\n }\n </div>\n </div>\n <div class=\"user-menu-divider\"></div>\n }\n <!-- Dynamic Menu Items -->\n @for (element of userMenuElements; track element) {\n <!-- Divider -->\n @if (isMenuDivider(element)) {\n <div class=\"user-menu-divider\"></div>\n }\n <!-- Menu Item -->\n @if (!isMenuDivider(element)) {\n @if (asMenuItem(element); as item) {\n @if (item.id === 'toggle-theme') {\n <div class=\"user-menu-item theme-toggle-item\"\n [title]=\"item.tooltip || ''\"\n (click)=\"onUserMenuItemClick(item.id)\">\n <i [class]=\"item.icon\"></i>\n <span class=\"menu-label\">{{ item.label }}</span>\n <div class=\"theme-toggle-track\" [class.dark]=\"IsDarkMode\">\n <div class=\"theme-toggle-thumb\">\n <i [class]=\"IsDarkMode ? 'fa-solid fa-moon' : 'fa-solid fa-sun'\" class=\"theme-toggle-icon\"></i>\n </div>\n </div>\n </div>\n } @else {\n <div class=\"user-menu-item\"\n [class.disabled]=\"!item.enabled\"\n [class.danger]=\"item.cssClass === 'danger'\"\n [style.color]=\"item.color || null\"\n [title]=\"item.tooltip || ''\"\n (click)=\"item.enabled && onUserMenuItemClick(item.id)\">\n <i [class]=\"item.icon\"></i>\n <span class=\"menu-label\">{{ item.label }}</span>\n @if (item.shortcut) {\n <span class=\"menu-shortcut\">{{ item.shortcut }}</span>\n }\n </div>\n }\n }\n }\n }\n </div>\n }\n </div>\n </div>\n </header>\n\n <!-- Search Popup -->\n @if (isSearchOpen) {\n <div class=\"search-popup-overlay\" (click)=\"closeSearch()\"></div>\n }\n <div class=\"search-popup\" [class.open]=\"isSearchOpen\">\n <div class=\"search-popup-content\" (click)=\"$event.stopPropagation()\">\n <mj-dropdown\n [Data]=\"searchableEntities\"\n TextField=\"Name\"\n ValueField=\"ID\"\n class=\"search-entity-dropdown\"\n [(ngModel)]=\"selectedEntity\">\n </mj-dropdown>\n <input\n type=\"text\"\n #searchInput\n placeholder=\"Search...\"\n class=\"mj-input search-input\"\n (keydown.enter)=\"onSearch($event)\"\n />\n <button class=\"search-submit-btn\" (click)=\"onSearch($event)\" title=\"Search\">\n <i class=\"fa-solid fa-search\"></i>\n </button>\n </div>\n </div>\n\n <!-- Mobile Navigation Drawer -->\n @if (mobileNavOpen) {\n <div class=\"mobile-nav-overlay\" (click)=\"closeMobileNav()\"></div>\n }\n <div class=\"mobile-nav-drawer\" [class.open]=\"mobileNavOpen\">\n <div class=\"mobile-nav-header\">\n <span>Navigation</span>\n <button class=\"close-btn\" (click)=\"closeMobileNav()\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n @if (activeApp) {\n <div class=\"mobile-nav-content\">\n <div class=\"mobile-nav-section-title\">{{ activeApp.Name }}</div>\n <mj-app-nav\n [app]=\"activeApp\"\n (navItemClick)=\"onNavItemClick($event)\"\n (navItemDismiss)=\"onNavItemDismiss($event)\">\n </mj-app-nav>\n </div>\n }\n <div class=\"mobile-nav-footer\">\n <button class=\"mobile-nav-action\" title=\"Search\" (click)=\"toggleSearch(); closeMobileNav()\">\n <i class=\"fa-solid fa-search\"></i>\n <span>Search</span>\n </button>\n <button class=\"mobile-nav-action\" title=\"Notifications\" (click)=\"showNotifications(); closeMobileNav()\">\n <i class=\"fa-solid fa-bell\"></i>\n <span>Notifications</span>\n @if (unreadNotificationCount > 0) {\n <span class=\"notification-badge-mobile\">\n {{ unreadNotificationCount > 99 ? '99+' : unreadNotificationCount }}\n </span>\n }\n </button>\n </div>\n </div>\n\n <!-- Tab Container - with dynamic tab bar visibility -->\n <mj-tab-container\n [class.hide-tab-bar]=\"!tabBarVisible\"\n (firstResourceLoadComplete)=\"onFirstResourceLoadComplete()\"\n (layoutInitError)=\"handleLayoutError()\">\n </mj-tab-container>\n</div>\n\n<!-- Loading State -->\n@if (loading) {\n <div class=\"shell-loading\">\n <mj-loading\n [text]=\"currentLoadingText\"\n [textColor]=\"currentLoadingTextColor\"\n [logoColor]=\"currentLoadingColor\"\n [logoGradient]=\"currentLoadingGradient\"\n [animation]=\"currentLoadingAnimation\"\n size=\"large\">\n </mj-loading>\n @if (ShowResetOption) {\n <div class=\"loading-reset-panel\">\n <p class=\"loading-reset-message\">\n <i class=\"fa-regular fa-clock\"></i>\n Taking longer than expected\n </p>\n <p class=\"loading-reset-hint\">\n This can happen after updates or due to cached data issues.\n </p>\n <button class=\"loading-reset-btn\" (click)=\"ResetApplication()\">\n <i class=\"fa-solid fa-arrows-rotate\"></i>\n Reset\n </button>\n </div>\n }\n </div>\n}\n\n<!-- App Access Error Dialog -->\n<mj-app-access-dialog\n #appAccessDialog\n (result)=\"onAppAccessDialogResult($event)\">\n</mj-app-access-dialog>\n\n<!-- Command Palette -->\n<mj-command-palette (AppSelected)=\"onAppSwitch($event)\"></mj-command-palette>\n\n<!-- Pin Progress Overlay -->\n@if (PinProgressVisible) {\n <div class=\"pin-progress-backdrop\">\n <div class=\"pin-progress-modal\">\n <mj-loading [showText]=\"false\" size=\"small\"></mj-loading>\n <span class=\"pin-progress-text\">{{ PinProgressText }}</span>\n </div>\n </div>\n}\n", styles: [":host {\n display: block;\n height: 100vh;\n width: 100%;\n overflow: hidden;\n}\n\n/* MJ Logo - uses design token for theme switching & white-labeling */\n.mj-logo {\n width: 32px;\n height: 18px;\n background-image: var(--mj-logo-mark);\n background-repeat: no-repeat;\n background-position: center;\n background-size: contain;\n flex-shrink: 0;\n}\n\n.shell-container {\n display: flex;\n flex-direction: column;\n height: 100vh;\n width: 100%;\n overflow: hidden;\n}\n\n/* Hide shell container while loading - allows tab container to render and load\n first resource in background while shell loading indicator is visible */\n.shell-container.hidden {\n visibility: hidden;\n position: absolute;\n pointer-events: none;\n}\n\nmj-tab-container {\n flex: 1;\n min-height: 0;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n transition: all 0.2s ease-in-out;\n}\n\n/* Hide Golden Layout tab headers when only one tab */\nmj-tab-container.hide-tab-bar ::ng-deep .lm_header {\n display: none;\n}\n\n/* Show tab headers when multiple tabs */\nmj-tab-container:not(.hide-tab-bar) ::ng-deep .lm_header {\n opacity: 1;\n max-height: 40px;\n transition: opacity 0.2s ease-in-out, max-height 0.2s ease-in-out;\n}\n\n/* Adjust content area height when tabs hidden */\nmj-tab-container.hide-tab-bar ::ng-deep .lm_content {\n height: 100% !important;\n}\n\n/* Ensure smooth transitions */\nmj-tab-container ::ng-deep .lm_stack {\n transition: all 0.2s ease-in-out;\n}\n\n.shell-header {\n height: 60px;\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n display: flex;\n align-items: center;\n padding: 0 16px;\n gap: 16px;\n box-shadow: var(--mj-shadow-sm);\n flex-shrink: 0;\n /* Creates a stacking context so children (search bar z-index: 99999, dropdown)\n are contained within this level. Modal overlays (z-index: 1000+) sit above. */\n position: relative;\n z-index: 500;\n}\n\n/* Nav Bar Apps - permanent app icons in the header */\n.nav-bar-apps {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.nav-bar-apps.left-of-switcher {\n /* No extra margin - header gap handles spacing */\n /* This prevents the app switcher from shifting when icons are hidden */\n}\n\n.nav-bar-apps.left-of-user-menu {\n margin-right: 8px;\n}\n\n.nav-bar-app-btn {\n --app-color: var(--mj-text-muted);\n width: 40px;\n height: 40px;\n border-radius: 10px;\n border: none;\n background: transparent;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-secondary);\n font-size: 18px;\n transition: all 0.15s ease;\n position: relative;\n}\n\n.nav-bar-app-btn:hover {\n background: color-mix(in srgb, var(--app-color) 15%, transparent);\n color: var(--app-color);\n}\n\n.nav-bar-app-btn.active {\n background: color-mix(in srgb, var(--app-color) 20%, transparent);\n color: var(--app-color);\n}\n\n.nav-bar-app-btn.active::after {\n content: '';\n position: absolute;\n bottom: 6px;\n left: 50%;\n transform: translateX(-50%);\n width: 16px;\n height: 3px;\n background: var(--app-color);\n border-radius: 2px;\n}\n\n.nav-bar-app-btn i {\n transition: transform 0.15s ease;\n margin-top: 2px; /* Align with app switcher icon */\n}\n\n.nav-bar-app-btn:hover i {\n transform: scale(1.1);\n}\n\n.spacer {\n flex: 1;\n}\n\n.header-actions {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.icon-btn {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n border: none;\n background: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n font-size: 18px;\n transition: background 0.15s;\n}\n\n.icon-btn:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n/* Notification button with badge */\n.notification-btn {\n position: relative;\n}\n\n.notification-badge {\n position: absolute;\n top: 4px;\n right: 4px;\n min-width: 16px;\n height: 16px;\n padding: 0 4px;\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n font-size: 10px;\n font-weight: 600;\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n line-height: 1;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n}\n\n.user-menu {\n position: relative;\n}\n\n.user-menu .avatar-btn {\n width: 36px;\n height: 36px;\n border-radius: 50%;\n border: none;\n background: transparent;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: box-shadow 0.15s, transform 0.15s;\n padding: 0;\n overflow: hidden;\n}\n\n.user-menu .avatar-btn:hover {\n transform: scale(1.05);\n}\n\n/* Icon fallback styling - shows gray circle with icon */\n.user-menu .avatar-btn .icon-fallback {\n width: 100%;\n height: 100%;\n border-radius: 50%;\n border: 2px solid var(--mj-border-default);\n background: var(--mj-bg-surface-hover);\n display: flex;\n align-items: center;\n justify-content: center;\n transition: border-color 0.15s;\n}\n\n.user-menu .avatar-btn:hover .icon-fallback {\n border-color: var(--mj-brand-primary);\n}\n\n.user-menu .avatar-btn .icon-fallback i {\n color: var(--mj-text-muted);\n font-size: 16px;\n}\n\n/* Avatar image - replaces the gray circle entirely */\n.user-menu .avatar-btn .avatar-img {\n width: 100%;\n height: 100%;\n border-radius: 50%;\n object-fit: cover;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15);\n}\n\n.user-menu .avatar-btn:hover .avatar-img {\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);\n}\n\n/* User Menu Header */\n.user-menu-header {\n padding: 12px 16px;\n background: var(--mj-bg-surface-sunken);\n}\n\n.user-menu-header .user-info {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.user-menu-header .user-name {\n font-weight: 600;\n font-size: 14px;\n color: var(--mj-text-primary);\n}\n\n.user-menu-header .user-email {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.user-menu-header .user-subtitle {\n font-size: 11px;\n color: var(--mj-text-muted);\n font-style: italic;\n}\n\n/* User Context Menu */\n.user-context-menu {\n position: absolute;\n top: 100%;\n right: 0;\n margin-top: 8px;\n background: var(--mj-bg-surface-elevated);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: var(--mj-shadow-lg);\n min-width: 180px;\n z-index: 10000;\n overflow: hidden;\n}\n\n.user-menu-item {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 16px;\n cursor: pointer;\n font-size: 14px;\n color: var(--mj-text-primary);\n transition: background 0.15s;\n}\n\n.user-menu-item i {\n width: 18px;\n text-align: center;\n color: var(--mj-text-muted);\n font-size: 14px;\n}\n\n.user-menu-item:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.user-menu-item.danger {\n color: var(--mj-status-error);\n}\n\n.user-menu-item.danger i {\n color: var(--mj-status-error);\n}\n\n.user-menu-item.danger:hover {\n background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface-elevated));\n}\n\n.user-menu-divider {\n height: 1px;\n background: var(--mj-border-default);\n margin: 4px 0;\n}\n\n/* Menu item disabled state */\n.user-menu-item.disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.user-menu-item.disabled:hover {\n background: transparent;\n}\n\n/* Theme Toggle Switch */\n.theme-toggle-item {\n cursor: pointer;\n}\n\n.theme-toggle-track {\n position: relative;\n width: 40px;\n height: 22px;\n border-radius: 11px;\n background: var(--mj-bg-surface-active);\n margin-left: auto;\n transition: background 0.2s ease;\n flex-shrink: 0;\n}\n\n.theme-toggle-track.dark {\n background: var(--mj-brand-primary);\n}\n\n.theme-toggle-thumb {\n position: absolute;\n top: 2px;\n left: 2px;\n width: 18px;\n height: 18px;\n border-radius: 50%;\n background: var(--mj-bg-surface);\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n display: flex;\n align-items: center;\n justify-content: center;\n transition: transform 0.2s ease;\n}\n\n.theme-toggle-track.dark .theme-toggle-thumb {\n transform: translateX(18px);\n}\n\n.theme-toggle-icon {\n font-size: 10px;\n color: var(--mj-text-muted);\n}\n\n.theme-toggle-track.dark .theme-toggle-icon {\n color: var(--mj-text-inverse);\n}\n\n/* Menu shortcut hint */\n.user-menu-item .menu-shortcut {\n margin-left: auto;\n font-size: 11px;\n color: var(--mj-text-disabled);\n font-family: monospace;\n}\n\n/* Menu animations */\n.user-context-menu.menu-fade {\n animation: menuFadeIn 0.15s ease-out;\n}\n\n.user-context-menu.menu-slide {\n animation: menuSlideIn 0.2s ease-out;\n}\n\n@keyframes menuFadeIn {\n from {\n opacity: 0;\n transform: translateY(-8px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes menuSlideIn {\n from {\n opacity: 0;\n transform: translateY(-16px) scale(0.95);\n }\n to {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n}\n\n.shell-loading {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100vh;\n padding-bottom: 15vh;\n background: var(--mj-bg-page);\n}\n\n/* Loading Recovery Reset Panel */\n.loading-reset-panel {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: var(--mj-space-3);\n margin-top: var(--mj-space-10);\n padding: var(--mj-space-8);\n background: var(--mj-bg-surface-elevated);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n box-shadow: var(--mj-shadow-md);\n max-width: 420px;\n animation: resetPanelFadeIn 0.4s ease-out;\n}\n\n.loading-reset-message {\n display: flex;\n align-items: center;\n gap: var(--mj-space-2);\n margin: 0;\n font-size: var(--mj-text-base);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-primary);\n}\n\n.loading-reset-message i {\n font-size: var(--mj-text-lg);\n color: var(--mj-status-warning);\n}\n\n.loading-reset-hint {\n margin: 0;\n font-size: var(--mj-text-sm);\n color: var(--mj-text-secondary);\n text-align: center;\n line-height: var(--mj-leading-relaxed);\n}\n\n.loading-reset-btn {\n display: inline-flex;\n align-items: center;\n gap: var(--mj-space-2);\n margin-top: var(--mj-space-3);\n padding: var(--mj-space-3) var(--mj-space-6);\n font-size: var(--mj-text-base);\n font-weight: var(--mj-font-medium);\n font-family: var(--mj-font-family);\n color: var(--mj-text-inverse);\n background: var(--mj-brand-primary);\n border: 1px solid var(--mj-brand-primary);\n border-radius: var(--mj-radius-md);\n cursor: pointer;\n transition: var(--mj-transition-colors);\n}\n\n.loading-reset-btn:hover {\n background: var(--mj-brand-primary-hover);\n color: var(--mj-text-inverse);\n border-color: var(--mj-brand-primary-hover);\n box-shadow: var(--mj-shadow-md);\n}\n\n.loading-reset-btn:active {\n background: var(--mj-brand-primary-active);\n color: var(--mj-text-inverse);\n transform: scale(0.98);\n}\n\n.loading-reset-btn i {\n font-size: var(--mj-text-sm);\n}\n\n@keyframes resetPanelFadeIn {\n from {\n opacity: 0;\n transform: translateY(12px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n/* Hamburger button - hidden on desktop */\n.hamburger-btn {\n display: none;\n width: 40px;\n height: 40px;\n border-radius: 8px;\n border: none;\n background: none;\n cursor: pointer;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-secondary);\n font-size: 20px;\n transition: background 0.15s;\n}\n.hamburger-btn:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n/* Mobile Navigation Overlay */\n.mobile-nav-overlay {\n display: none;\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n z-index: 9998;\n}\n\n/* Mobile Navigation Drawer */\n.mobile-nav-drawer {\n display: none;\n position: fixed;\n top: 0;\n left: 0;\n bottom: 0;\n width: 280px;\n max-width: 85vw;\n background: var(--mj-bg-surface);\n box-shadow: var(--mj-shadow-xl);\n z-index: 9999;\n flex-direction: column;\n transform: translateX(-100%);\n transition: transform 0.3s ease;\n}\n.mobile-nav-drawer.open {\n transform: translateX(0);\n}\n\n.mobile-nav-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-sunken);\n}\n.mobile-nav-header span {\n font-weight: 600;\n font-size: 16px;\n color: var(--mj-text-primary);\n}\n.mobile-nav-header .close-btn {\n width: 36px;\n height: 36px;\n border-radius: 50%;\n border: none;\n background: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n font-size: 18px;\n transition: background 0.15s;\n}\n.mobile-nav-header .close-btn:hover {\n background: var(--mj-bg-surface-active);\n}\n\n.mobile-nav-content {\n flex: 1;\n overflow-y: auto;\n padding: 16px 0;\n}\n\n.mobile-nav-section-title {\n padding: 8px 20px;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-disabled);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.mobile-nav-footer {\n border-top: 1px solid var(--mj-border-default);\n padding: 12px 16px;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.mobile-nav-action {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 16px;\n border: none;\n background: none;\n cursor: pointer;\n border-radius: 8px;\n color: var(--mj-text-secondary);\n font-size: 14px;\n font-weight: 500;\n transition: background 0.15s;\n width: 100%;\n text-align: left;\n}\n.mobile-nav-action:hover {\n background: var(--mj-bg-surface-hover);\n}\n.mobile-nav-action i {\n font-size: 16px;\n width: 20px;\n text-align: center;\n}\n\n/* Mobile Responsive Styles */\n@media (max-width: 768px) {\n .hamburger-btn {\n display: flex;\n }\n\n .desktop-nav {\n display: none !important;\n }\n\n .desktop-only {\n display: none !important;\n }\n\n .mobile-nav-overlay {\n display: block;\n }\n\n .mobile-nav-drawer {\n display: flex;\n }\n\n .shell-header {\n padding: 0 12px;\n gap: 8px;\n }\n}\n\n/* Settings Full-Screen Window Styles */\n::ng-deep .settings-fullscreen-window {\n /* Remove window chrome for full-screen feel */\n box-shadow: none !important;\n border: none !important;\n}\n\n::ng-deep .settings-fullscreen-window .k-window-titlebar {\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n padding: 12px 16px;\n}\n\n::ng-deep .settings-fullscreen-window .k-window-title {\n font-size: 18px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n::ng-deep .settings-fullscreen-window .k-window-titlebar-actions {\n gap: 4px;\n}\n\n::ng-deep .settings-fullscreen-window .k-window-titlebar-action {\n width: 32px;\n height: 32px;\n border-radius: 6px;\n}\n\n::ng-deep .settings-fullscreen-window .k-window-titlebar-action:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n::ng-deep .settings-fullscreen-window .k-window-content {\n padding: 0;\n overflow: auto;\n background: var(--mj-bg-page);\n}\n\n/* Hide minimize/maximize buttons - only show close */\n::ng-deep .settings-fullscreen-window .k-window-titlebar-action[title=\"Minimize\"],\n::ng-deep .settings-fullscreen-window .k-window-titlebar-action[title=\"Maximize\"],\n::ng-deep .settings-fullscreen-window .k-window-titlebar-action .k-i-window-minimize,\n::ng-deep .settings-fullscreen-window .k-window-titlebar-action .k-i-window-maximize,\n::ng-deep .settings-fullscreen-window .k-window-titlebar-action .k-i-window {\n display: none !important;\n}\n\n/* ========================================\n UNIVERSAL SEARCH BAR\n ======================================== */\n.shell-search-bar {\n flex: 0 1 420px;\n min-width: 200px;\n max-width: 520px;\n margin: 0 12px;\n position: relative;\n z-index: 99999;\n}\n@media (max-width: 768px) {\n .shell-search-bar { display: none; }\n}\n\n/* ========================================\n SEARCH POPUP\n ======================================== */\n\n.search-popup-overlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.3);\n z-index: 9999;\n animation: fadeIn 0.15s ease;\n}\n\n@keyframes fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n\n.search-popup {\n position: fixed;\n top: 60px; /* Below header */\n right: 16px;\n width: 480px;\n max-width: calc(100vw - 32px);\n background: var(--mj-bg-surface-elevated);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-xl);\n z-index: 10000;\n opacity: 0;\n transform: translateY(-10px);\n pointer-events: none;\n transition: opacity 0.2s ease, transform 0.2s ease;\n}\n\n.search-popup.open {\n opacity: 1;\n transform: translateY(0);\n pointer-events: all;\n}\n\n.search-popup-content {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px;\n}\n\n.search-entity-dropdown {\n min-width: 140px;\n max-width: 180px;\n flex-shrink: 0;\n}\n\n.search-input {\n flex: 1;\n min-width: 0;\n height: 40px;\n padding: 8px 12px;\n font-size: 14px;\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n outline: none;\n display: block !important;\n box-sizing: border-box;\n}\n\n.search-input:focus {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n}\n\n.search-submit-btn {\n width: 40px;\n height: 40px;\n border-radius: 8px;\n border: none;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 16px;\n transition: background 0.15s;\n flex-shrink: 0;\n}\n\n.search-submit-btn:hover {\n background: var(--mj-brand-primary-hover);\n}\n\n.search-submit-btn:active {\n background: var(--mj-brand-primary-hover);\n}\n\n/* Mobile notification badge */\n.notification-badge-mobile {\n position: absolute;\n top: 8px;\n right: 8px;\n min-width: 18px;\n height: 18px;\n padding: 0 5px;\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n font-size: 11px;\n font-weight: 600;\n border-radius: 9px;\n display: flex;\n align-items: center;\n justify-content: center;\n line-height: 1;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n}\n\n/* Mobile-specific search popup adjustments */\n@media (max-width: 768px) {\n .search-popup {\n top: 60px;\n left: 16px;\n right: 16px;\n width: auto;\n max-width: none;\n }\n\n .search-popup-content {\n flex-wrap: wrap;\n }\n\n .search-entity-dropdown {\n width: 100%;\n }\n\n .search-input {\n flex: 1;\n min-width: 0;\n }\n}\n\n/* ========================================\n PIN PROGRESS OVERLAY\n ======================================== */\n.pin-progress-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: color-mix(in srgb, var(--mj-text-primary) 40%, transparent);\n z-index: 100000;\n display: flex;\n align-items: center;\n justify-content: center;\n animation: pinBackdropIn 0.2s ease;\n}\n\n@keyframes pinBackdropIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n.pin-progress-modal {\n background: var(--mj-bg-surface);\n border-radius: var(--mj-radius-xl);\n padding: 28px 40px;\n display: flex;\n align-items: center;\n gap: 16px;\n box-shadow: 0 16px 48px color-mix(in srgb, var(--mj-text-primary) 30%, transparent);\n animation: pinModalIn 0.25s ease;\n}\n\n@keyframes pinModalIn {\n from { opacity: 0; transform: scale(0.9) translateY(8px); }\n to { opacity: 1; transform: scale(1) translateY(0); }\n}\n\n.pin-progress-text {\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-medium);\n color: var(--mj-text-secondary);\n white-space: nowrap;\n}"] }]
2918
+ }], () => [{ type: i1.ApplicationManager }, { type: i1.WorkspaceStateManager }, { type: i1.GoldenLayoutManager }, { type: i1.TabService }, { type: i2.NavigationService }, { type: i3.ActivatedRoute }, { type: i3.Router }, { type: i4.MJAuthBase }, { type: i0.ChangeDetectorRef }, { type: i5.UserAvatarService }, { type: i6.SettingsDialogService }, { type: i0.ViewContainerRef }, { type: i2.TitleService }, { type: i2.DeveloperModeService }, { type: i7.CommandPaletteService }, { type: i2.ThemeService }, { type: i2.HomeAppPinService }, { type: i8.FileOpenService }], { searchInput: [{
2727
2919
  type: ViewChild,
2728
2920
  args: ['searchInput']
2921
+ }], shellSearchComposite: [{
2922
+ type: ViewChild,
2923
+ args: ['shellSearchComposite']
2729
2924
  }], tabContainerRef: [{
2730
2925
  type: ViewChild,
2731
2926
  args: [TabContainerComponent]
@@ -2735,6 +2930,9 @@ export class ShellComponent {
2735
2930
  }], handleGlobalKeyboardShortcuts: [{
2736
2931
  type: HostListener,
2737
2932
  args: ['document:keydown', ['$event']]
2933
+ }], OnGlobalKeydown: [{
2934
+ type: HostListener,
2935
+ args: ['document:keydown', ['$event']]
2738
2936
  }] }); })();
2739
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ShellComponent, { className: "ShellComponent", filePath: "src/lib/shell/shell.component.ts", lineNumber: 46 }); })();
2937
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ShellComponent, { className: "ShellComponent", filePath: "src/lib/shell/shell.component.ts", lineNumber: 47 }); })();
2740
2938
  //# sourceMappingURL=shell.component.js.map