@memberjunction/ng-dashboards 5.46.0 → 5.48.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 (71) hide show
  1. package/dist/DataExplorer/data-explorer-dashboard.component.d.ts +15 -4
  2. package/dist/DataExplorer/data-explorer-dashboard.component.d.ts.map +1 -1
  3. package/dist/DataExplorer/data-explorer-dashboard.component.js +45 -35
  4. package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
  5. package/dist/DataExplorer/models/explorer-state.interface.d.ts +7 -0
  6. package/dist/DataExplorer/models/explorer-state.interface.d.ts.map +1 -1
  7. package/dist/DataExplorer/models/explorer-state.interface.js.map +1 -1
  8. package/dist/Lists/components/lists-browse-resource.component.d.ts +4 -0
  9. package/dist/Lists/components/lists-browse-resource.component.d.ts.map +1 -1
  10. package/dist/Lists/components/lists-browse-resource.component.js +39 -30
  11. package/dist/Lists/components/lists-browse-resource.component.js.map +1 -1
  12. package/dist/Lists/components/lists-my-lists-resource.component.d.ts.map +1 -1
  13. package/dist/Lists/components/lists-my-lists-resource.component.js +14 -12
  14. package/dist/Lists/components/lists-my-lists-resource.component.js.map +1 -1
  15. package/dist/Lists/components/lists-operations-resource.component.d.ts.map +1 -1
  16. package/dist/Lists/components/lists-operations-resource.component.js +6 -1
  17. package/dist/Lists/components/lists-operations-resource.component.js.map +1 -1
  18. package/dist/Lists/services/list-set-operations.service.d.ts +11 -0
  19. package/dist/Lists/services/list-set-operations.service.d.ts.map +1 -1
  20. package/dist/Lists/services/list-set-operations.service.js +27 -2
  21. package/dist/Lists/services/list-set-operations.service.js.map +1 -1
  22. package/dist/PredictiveStudio/at-risk.view-models.d.ts +33 -0
  23. package/dist/PredictiveStudio/at-risk.view-models.d.ts.map +1 -1
  24. package/dist/PredictiveStudio/at-risk.view-models.js +69 -2
  25. package/dist/PredictiveStudio/at-risk.view-models.js.map +1 -1
  26. package/dist/PredictiveStudio/components/ps-catalog.component.js +2 -2
  27. package/dist/PredictiveStudio/components/ps-catalog.component.js.map +1 -1
  28. package/dist/PredictiveStudio/components/ps-compare.component.js +2 -2
  29. package/dist/PredictiveStudio/components/ps-compare.component.js.map +1 -1
  30. package/dist/PredictiveStudio/components/ps-confirm-modal.component.js +2 -2
  31. package/dist/PredictiveStudio/components/ps-confirm-modal.component.js.map +1 -1
  32. package/dist/PredictiveStudio/components/ps-experiments.component.js +2 -2
  33. package/dist/PredictiveStudio/components/ps-experiments.component.js.map +1 -1
  34. package/dist/PredictiveStudio/components/ps-home.component.js +2 -2
  35. package/dist/PredictiveStudio/components/ps-home.component.js.map +1 -1
  36. package/dist/PredictiveStudio/components/ps-operate-dialog.component.js +2 -2
  37. package/dist/PredictiveStudio/components/ps-operate-dialog.component.js.map +1 -1
  38. package/dist/PredictiveStudio/components/ps-pipelines.component.d.ts.map +1 -1
  39. package/dist/PredictiveStudio/components/ps-pipelines.component.js +306 -297
  40. package/dist/PredictiveStudio/components/ps-pipelines.component.js.map +1 -1
  41. package/dist/PredictiveStudio/components/ps-production.component.js +2 -2
  42. package/dist/PredictiveStudio/components/ps-production.component.js.map +1 -1
  43. package/dist/PredictiveStudio/components/ps-registry.component.d.ts +1 -1
  44. package/dist/PredictiveStudio/components/ps-registry.component.d.ts.map +1 -1
  45. package/dist/PredictiveStudio/components/ps-registry.component.js +15 -9
  46. package/dist/PredictiveStudio/components/ps-registry.component.js.map +1 -1
  47. package/dist/PredictiveStudio/predictive-studio-agent-context.d.ts +115 -0
  48. package/dist/PredictiveStudio/predictive-studio-agent-context.d.ts.map +1 -0
  49. package/dist/PredictiveStudio/predictive-studio-agent-context.js +119 -0
  50. package/dist/PredictiveStudio/predictive-studio-agent-context.js.map +1 -0
  51. package/dist/PredictiveStudio/predictive-studio-copilot.view-models.d.ts +36 -0
  52. package/dist/PredictiveStudio/predictive-studio-copilot.view-models.d.ts.map +1 -0
  53. package/dist/PredictiveStudio/predictive-studio-copilot.view-models.js +52 -0
  54. package/dist/PredictiveStudio/predictive-studio-copilot.view-models.js.map +1 -0
  55. package/dist/PredictiveStudio/resources/ps-models-resource.component.d.ts +9 -1
  56. package/dist/PredictiveStudio/resources/ps-models-resource.component.d.ts.map +1 -1
  57. package/dist/PredictiveStudio/resources/ps-models-resource.component.js +133 -56
  58. package/dist/PredictiveStudio/resources/ps-models-resource.component.js.map +1 -1
  59. package/dist/PredictiveStudio/resources/ps-predictions-resource.component.d.ts +50 -1
  60. package/dist/PredictiveStudio/resources/ps-predictions-resource.component.d.ts.map +1 -1
  61. package/dist/PredictiveStudio/resources/ps-predictions-resource.component.js +591 -165
  62. package/dist/PredictiveStudio/resources/ps-predictions-resource.component.js.map +1 -1
  63. package/dist/PredictiveStudio/resources/ps-resource-base.d.ts +17 -0
  64. package/dist/PredictiveStudio/resources/ps-resource-base.d.ts.map +1 -1
  65. package/dist/PredictiveStudio/resources/ps-resource-base.js +27 -1
  66. package/dist/PredictiveStudio/resources/ps-resource-base.js.map +1 -1
  67. package/dist/PredictiveStudio/resources/ps-studio-resource.component.d.ts +11 -1
  68. package/dist/PredictiveStudio/resources/ps-studio-resource.component.d.ts.map +1 -1
  69. package/dist/PredictiveStudio/resources/ps-studio-resource.component.js +199 -99
  70. package/dist/PredictiveStudio/resources/ps-studio-resource.component.js.map +1 -1
  71. package/package.json +59 -59
@@ -77,6 +77,7 @@ export declare class DataExplorerDashboardComponent extends BaseDashboard implem
77
77
  breadcrumbs: BreadcrumbItem[];
78
78
  isLoadingEntities: boolean;
79
79
  recentRecords: RecentRecordAccess[];
80
+ private recentTimeRefreshTimer;
80
81
  favoriteRecords: FavoriteRecord[];
81
82
  isLoadingRecentRecords: boolean;
82
83
  recentRecordsEntityFilter: string | null;
@@ -671,12 +672,22 @@ export declare class DataExplorerDashboardComponent extends BaseDashboard implem
671
672
  * Get the icon for an entity by ID (for recent records)
672
673
  */
673
674
  getEntityIconById(entityId: string): string;
674
- private relativeTimeCache;
675
675
  /**
676
- * Format relative time for display (e.g., "2 hours ago")
677
- * Cached to prevent ExpressionChangedAfterItHasBeenCheckedError
676
+ * Pre-compute the "N ago" relative-time label for each recent record into its `relativeTime`
677
+ * field. The template binds `record.relativeTime` (a stable value) instead of calling
678
+ * {@link formatRelativeTime} — which reads `Date.now()` — during change detection. Recomputing
679
+ * time inside a template binding is what produced the NG0100
680
+ * ExpressionChangedAfterItHasBeenCheckedError (the value could differ between the two dev-mode
681
+ * CD passes when a minute boundary was crossed); binding a stored field cannot. Called when the
682
+ * record set loads and on a timer so the labels stay current.
678
683
  */
679
- formatRelativeTime(date: Date): string;
684
+ private refreshRecentRecordTimes;
685
+ /**
686
+ * Format relative time for display (e.g., "2 hours ago").
687
+ * NOTE: this reads Date.now(), so it must NOT be called directly from a template binding —
688
+ * use the pre-computed {@link RecentRecordAccess.relativeTime} field (see refreshRecentRecordTimes).
689
+ */
690
+ private formatRelativeTime;
680
691
  /**
681
692
  * Check if we're at the home level (no entity selected)
682
693
  */
@@ -1 +1 @@
1
- {"version":3,"file":"data-explorer-dashboard.component.d.ts","sourceRoot":"","sources":["../../src/DataExplorer/data-explorer-dashboard.component.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"data-explorer-dashboard.component.d.ts","sourceRoot":"","sources":["../../src/DataExplorer/data-explorer-dashboard.component.ts"],"names":[],"mappings":"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"}
@@ -397,7 +397,7 @@ function DataExplorerDashboardComponent_Conditional_14_Conditional_2_For_33_Temp
397
397
  i0.ɵɵadvance(2);
398
398
  i0.ɵɵtextInterpolate(record_r21.entityName);
399
399
  i0.ɵɵadvance(2);
400
- i0.ɵɵtextInterpolate(ctx_r1.formatRelativeTime(record_r21.latestAt));
400
+ i0.ɵɵtextInterpolate(record_r21.relativeTime);
401
401
  } }
402
402
  function DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_34_Template(rf, ctx) { if (rf & 1) {
403
403
  i0.ɵɵelementStart(0, "div", 60);
@@ -693,6 +693,8 @@ let DataExplorerDashboardComponent = class DataExplorerDashboardComponent extend
693
693
  isLoadingEntities = true;
694
694
  // Recent records from User Record Logs
695
695
  recentRecords = [];
696
+ // Timer that refreshes the pre-computed relative-time labels on recentRecords (see refreshRecentRecordTimes / NG0100 note)
697
+ recentTimeRefreshTimer = null;
696
698
  // Favorite records from User Favorites (non-entity favorites)
697
699
  favoriteRecords = [];
698
700
  // Loading state for home screen sections
@@ -978,9 +980,20 @@ let DataExplorerDashboardComponent = class DataExplorerDashboardComponent extend
978
980
  .pipe(takeUntil(this.destroy$))
979
981
  .subscribe(records => {
980
982
  this.recentRecords = records;
983
+ this.refreshRecentRecordTimes(); // pre-compute the "N ago" labels off the CD path (see NG0100 note)
981
984
  this.isLoadingRecentRecords = false;
982
985
  this.cdr.detectChanges();
983
986
  });
987
+ // Refresh the pre-computed relative-time labels on a timer so "Just now" ages into "1m ago"
988
+ // etc. without the template ever computing time during change detection. Updating the stored
989
+ // field + running detectChanges here (rather than calling a Date.now()-based method from the
990
+ // template binding) is what prevents the ExpressionChangedAfterItHasBeenCheckedError (NG0100).
991
+ this.recentTimeRefreshTimer = setInterval(() => {
992
+ if (this.recentRecords.length > 0) {
993
+ this.refreshRecentRecordTimes();
994
+ this.cdr.detectChanges();
995
+ }
996
+ }, 30000);
984
997
  // Subscribe to favorite records changes
985
998
  this.stateService.FavoriteRecords
986
999
  .pipe(takeUntil(this.destroy$))
@@ -1771,6 +1784,10 @@ let DataExplorerDashboardComponent = class DataExplorerDashboardComponent extend
1771
1784
  }
1772
1785
  }
1773
1786
  ngOnDestroy() {
1787
+ if (this.recentTimeRefreshTimer !== null) {
1788
+ clearInterval(this.recentTimeRefreshTimer);
1789
+ this.recentTimeRefreshTimer = null;
1790
+ }
1774
1791
  this.destroy$.next();
1775
1792
  this.destroy$.complete();
1776
1793
  super.ngOnDestroy();
@@ -2752,48 +2769,41 @@ let DataExplorerDashboardComponent = class DataExplorerDashboardComponent extend
2752
2769
  }
2753
2770
  return 'fa-solid fa-table';
2754
2771
  }
2755
- // Cache for relative time strings to prevent recalculation during change detection
2756
- relativeTimeCache = new Map();
2757
2772
  /**
2758
- * Format relative time for display (e.g., "2 hours ago")
2759
- * Cached to prevent ExpressionChangedAfterItHasBeenCheckedError
2773
+ * Pre-compute the "N ago" relative-time label for each recent record into its `relativeTime`
2774
+ * field. The template binds `record.relativeTime` (a stable value) instead of calling
2775
+ * {@link formatRelativeTime} — which reads `Date.now()` — during change detection. Recomputing
2776
+ * time inside a template binding is what produced the NG0100
2777
+ * ExpressionChangedAfterItHasBeenCheckedError (the value could differ between the two dev-mode
2778
+ * CD passes when a minute boundary was crossed); binding a stored field cannot. Called when the
2779
+ * record set loads and on a timer so the labels stay current.
2780
+ */
2781
+ refreshRecentRecordTimes() {
2782
+ for (const record of this.recentRecords) {
2783
+ record.relativeTime = this.formatRelativeTime(record.latestAt);
2784
+ }
2785
+ }
2786
+ /**
2787
+ * Format relative time for display (e.g., "2 hours ago").
2788
+ * NOTE: this reads Date.now(), so it must NOT be called directly from a template binding —
2789
+ * use the pre-computed {@link RecentRecordAccess.relativeTime} field (see refreshRecentRecordTimes).
2760
2790
  */
2761
2791
  formatRelativeTime(date) {
2762
2792
  if (!date)
2763
2793
  return '';
2764
- const timestamp = new Date(date).getTime();
2765
- const now = Date.now();
2766
- // Check cache - use cached value if less than 10 seconds old
2767
- const cached = this.relativeTimeCache.get(timestamp);
2768
- if (cached && (now - cached.cachedAt) < 10000) {
2769
- return cached.formatted;
2770
- }
2771
- // Calculate new value
2772
- const diff = now - timestamp;
2794
+ const diff = Date.now() - new Date(date).getTime();
2773
2795
  const minutes = Math.floor(diff / 60000);
2774
2796
  const hours = Math.floor(diff / 3600000);
2775
2797
  const days = Math.floor(diff / 86400000);
2776
- let formatted;
2777
2798
  if (minutes < 1)
2778
- formatted = 'Just now';
2779
- else if (minutes < 60)
2780
- formatted = `${minutes}m ago`;
2781
- else if (hours < 24)
2782
- formatted = `${hours}h ago`;
2783
- else if (days < 7)
2784
- formatted = `${days}d ago`;
2785
- else
2786
- formatted = new Date(date).toLocaleDateString();
2787
- // Cache the result
2788
- this.relativeTimeCache.set(timestamp, { formatted, cachedAt: now });
2789
- // Cleanup old cache entries (keep last 100)
2790
- if (this.relativeTimeCache.size > 100) {
2791
- const firstKey = this.relativeTimeCache.keys().next().value;
2792
- if (firstKey !== undefined) {
2793
- this.relativeTimeCache.delete(firstKey);
2794
- }
2795
- }
2796
- return formatted;
2799
+ return 'Just now';
2800
+ if (minutes < 60)
2801
+ return `${minutes}m ago`;
2802
+ if (hours < 24)
2803
+ return `${hours}h ago`;
2804
+ if (days < 7)
2805
+ return `${days}d ago`;
2806
+ return new Date(date).toLocaleDateString();
2797
2807
  }
2798
2808
  /**
2799
2809
  * Check if we're at the home level (no entity selected)
@@ -2892,7 +2902,7 @@ export { DataExplorerDashboardComponent };
2892
2902
  animate('200ms ease-in', style({ transform: 'translateX(-100%)', opacity: 0 }))
2893
2903
  ])
2894
2904
  ])
2895
- ], template: "<div class=\"data-explorer-container\">\n <!-- Navigation Panel (Left) - Hidden at home level, animated -->\n @if (!isAtHomeLevel) {\n <div\n class=\"navigation-panel\"\n [class.collapsed]=\"state.navigationPanelCollapsed\"\n [style.width.px]=\"state.navigationPanelCollapsed ? 48 : state.navigationPanelWidth\"\n [@slideInLeft]>\n\n <mj-explorer-navigation-panel\n [entities]=\"entities\"\n [appEntityGroups]=\"appEntityGroups\"\n [selectedEntityName]=\"state.selectedEntityName\"\n [favorites]=\"state.favorites\"\n [recentItems]=\"state.recentItems\"\n [collapsed]=\"state.navigationPanelCollapsed\"\n [allowedEntityNames]=\"allowedEntityNames\"\n [favoritesSectionExpanded]=\"state.favoritesSectionExpanded\"\n [recentSectionExpanded]=\"state.recentSectionExpanded\"\n [entitiesSectionExpanded]=\"state.entitiesSectionExpanded\"\n [viewsSectionExpanded]=\"state.viewsSectionExpanded\"\n (entitySelected)=\"onEntitySelected($event)\"\n (toggleCollapse)=\"toggleNavigationPanel()\"\n (sectionToggled)=\"stateService.toggleSection($event)\"\n (openRecord)=\"onOpenRecordFromNav($event)\"\n (selectRecord)=\"onSelectRecordFromNav($event)\"\n (expandAndFocus)=\"onExpandAndFocus($event)\">\n </mj-explorer-navigation-panel>\n </div>\n }\n\n <!-- Main Content Area -->\n <div class=\"content-area\">\n <!-- Breadcrumb Bar - Hidden at home level -->\n @if (!isAtHomeLevel && breadcrumbs.length > 0) {\n <div class=\"breadcrumb-bar\">\n @for (crumb of breadcrumbs; track crumb.label; let i = $index; let last = $last) {\n <span\n class=\"breadcrumb-item\"\n [class.clickable]=\"!last\"\n [class.current]=\"last\"\n (click)=\"onBreadcrumbClick(crumb, i)\"\n [title]=\"crumb.label\">\n @if (crumb.icon) {\n <i [class]=\"crumb.icon\" class=\"breadcrumb-icon\"></i>\n }\n <span class=\"breadcrumb-label\">{{ crumb.label }}</span>\n </span>\n @if (!last) {\n <i class=\"fa-solid fa-chevron-right breadcrumb-separator\"></i>\n }\n }\n </div>\n }\n\n <!-- Header -->\n <div class=\"content-header\" [class.home-header]=\"isAtHomeLevel\">\n <div class=\"header-left\">\n @if (selectedEntity) {\n <i [class]=\"getEntityIcon(selectedEntity)\" class=\"entity-icon\"></i>\n <h2 class=\"entity-title\">{{ selectedEntity.DisplayNameOrName }}</h2>\n @if (debouncedFilterText && filteredRecordCount !== totalRecordCount) {\n <span class=\"record-count\">{{ filteredRecordCount | number }} of {{ totalRecordCount | number }} records</span>\n } @else {\n <span class=\"record-count\">{{ totalRecordCount | number }} records</span>\n }\n\n <!-- View selector + view header now live inside mj-view-workspace (below). -->\n <!-- Add-to-List is now owned inside the grid plug-in renderer (it hosts its own dialog). -->\n } @else {\n @if (displayIcon) {\n <i [class]=\"displayIcon\" class=\"entity-icon\"></i>\n }\n <h2 class=\"entity-title\">{{ displayTitle }}</h2>\n <span class=\"record-count\">{{ entities.length }} entities available</span>\n }\n </div>\n\n <div class=\"header-center\">\n @if (selectedEntity) {\n <div class=\"smart-filter-container\">\n <i class=\"fa-solid fa-search filter-icon\"></i>\n <input\n #filterInput\n type=\"text\"\n class=\"smart-filter-input\"\n placeholder=\"Filter records... (press / to focus)\"\n [value]=\"liveFilterText\"\n (input)=\"onFilterInputChanged(filterInput.value)\"\n />\n @if (liveFilterText) {\n <button class=\"clear-filter-btn\" (click)=\"clearRecordFilter()\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n }\n </div>\n }\n <!-- Home-level search moved to search hero section -->\n </div>\n\n <div class=\"header-right\">\n @if (selectedEntity) {\n <!-- View-type switcher AND all view-specific controls (timeline date/orientation/sort,\n map render mode, etc.) now live inside the plug-in renderers hosted by\n mj-view-workspace. Nothing view-type-specific lives in this header anymore. -->\n }\n @if (!selectedEntity) {\n <!-- Quick Access panel toggle -->\n <button\n class=\"header-action-btn\"\n [class.active]=\"state.quickAccessPanelOpen\"\n (click)=\"toggleQuickAccessPanel()\"\n title=\"Recents & Favorites\">\n <i class=\"fa-solid fa-clock-rotate-left\"></i>\n @if (recentRecords.length + favoriteRecords.length > 0) {\n <span class=\"qa-badge\">{{ recentRecords.length + favoriteRecords.length }}</span>\n }\n </button>\n }\n </div>\n </div>\n\n <!-- Content Body - Using mj-entity-viewer composite -->\n <div class=\"content-body\" [class.home-content]=\"isAtHomeLevel\">\n @if (!selectedEntity) {\n <!-- Concept D: Application Groups + Search-First Home View -->\n <div class=\"home-view-concept-d\">\n @if (isLoadingEntities) {\n <div class=\"loading-state\">\n <mj-loading text=\"Loading entities...\" size=\"medium\"></mj-loading>\n </div>\n } @else {\n <div class=\"home-main-area\" [class.panel-open]=\"state.quickAccessPanelOpen\">\n <!-- Search Hero -->\n <div class=\"search-hero\">\n <div class=\"search-hero-container\">\n <i class=\"fa-solid fa-magnifying-glass search-hero-icon\"></i>\n <input\n #filterInput\n type=\"text\"\n class=\"search-hero-input\"\n placeholder=\"Search entities...\"\n [(ngModel)]=\"entityFilterText\"\n />\n @if (entityFilterText) {\n <button class=\"search-hero-clear\" (click)=\"entityFilterText = ''\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n } @else {\n <span class=\"search-hero-shortcut\">/</span>\n }\n </div>\n\n <!-- Meta row: entity count + All/Favorites pills -->\n <div class=\"search-meta-row\">\n <span class=\"search-entity-count\">\n {{ filteredEntityCount }} entities\n @if (applicationCount > 0) {\n across {{ applicationCount }} applications\n }\n </span>\n <div class=\"pill-toggle\">\n <button\n class=\"pill-btn\"\n [class.active]=\"state.homeViewMode === 'all'\"\n (click)=\"setHomeViewMode('all')\">\n All Entities\n </button>\n <button\n class=\"pill-btn\"\n [class.active]=\"state.homeViewMode === 'favorites'\"\n (click)=\"setHomeViewMode('favorites')\">\n <i class=\"fa-solid fa-star\"></i> My Favorites\n </button>\n </div>\n </div>\n </div>\n\n <!-- Entity Groups Area -->\n <div class=\"entity-groups-area\">\n @if (entityFilter?.applicationId) {\n <!-- Single-app mode: flat entity grid (no grouping) -->\n <div class=\"entity-item-grid\">\n @for (entity of flatFilteredEntities; track entity.ID) {\n <div\n class=\"entity-item\"\n (click)=\"onEntitySelected(entity)\"\n [title]=\"entity.Description || entity.DisplayNameOrName\">\n <div class=\"entity-item-icon\">\n <i [class]=\"getEntityIcon(entity)\"></i>\n </div>\n <div class=\"entity-item-text\">\n <span class=\"entity-item-name\">{{ entity.DisplayNameOrName }}</span>\n @if (entity.Description) {\n <span class=\"entity-item-desc\">{{ entity.Description }}</span>\n }\n </div>\n <button\n class=\"entity-item-fav\"\n [class.favorited]=\"isEntityFavorited(entity)\"\n (click)=\"toggleEntityFavorite(entity, $event)\"\n [title]=\"isEntityFavorited(entity) ? 'Remove from favorites' : 'Add to favorites'\">\n <i [class]=\"isEntityFavorited(entity) ? 'fa-solid fa-star' : 'fa-regular fa-star'\"></i>\n </button>\n </div>\n }\n </div>\n } @else {\n <!-- Multi-app mode: grouped by application -->\n @for (group of filteredAppEntityGroups; track group.applicationId) {\n <div class=\"app-group\">\n <div class=\"app-group-header\" (click)=\"toggleAppGroup(group.applicationId)\">\n <div\n class=\"app-group-icon\"\n [style.background]=\"group.applicationColor ? group.applicationColor + '15' : null\"\n [style.color]=\"group.applicationColor || null\">\n <i [class]=\"group.applicationIcon || 'fa-solid fa-folder'\"></i>\n </div>\n <span class=\"app-group-name\">{{ group.applicationName }}</span>\n <span class=\"app-group-count\">{{ group.entities.length }}</span>\n <i class=\"fa-solid fa-chevron-right app-group-chevron\"\n [class.expanded]=\"group.isExpanded\"></i>\n </div>\n @if (group.isExpanded) {\n <div class=\"app-group-entities\">\n <div class=\"entity-item-grid\">\n @for (entity of group.entities; track entity.ID) {\n <div\n class=\"entity-item\"\n (click)=\"onEntitySelected(entity)\"\n [title]=\"entity.Description || entity.DisplayNameOrName\">\n <div class=\"entity-item-icon\">\n <i [class]=\"getEntityIcon(entity)\"></i>\n </div>\n <div class=\"entity-item-text\">\n <span class=\"entity-item-name\">{{ entity.DisplayNameOrName }}</span>\n @if (entity.Description) {\n <span class=\"entity-item-desc\">{{ entity.Description }}</span>\n }\n </div>\n <button\n class=\"entity-item-fav\"\n [class.favorited]=\"isEntityFavorited(entity)\"\n (click)=\"toggleEntityFavorite(entity, $event)\"\n [title]=\"isEntityFavorited(entity) ? 'Remove from favorites' : 'Add to favorites'\">\n <i [class]=\"isEntityFavorited(entity) ? 'fa-solid fa-star' : 'fa-regular fa-star'\"></i>\n </button>\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\n }\n\n <!-- No results -->\n @if (filteredEntityCount === 0 && entities.length > 0) {\n <mj-empty-state Variant=\"no-results\"\n Title=\"No entities found\"\n [Message]=\"NoEntityResultsMessage\" />\n }\n @if (entities.length === 0) {\n <mj-empty-state Icon=\"fa-solid fa-database\"\n Title=\"No Entities Available\"\n Message=\"There are no entities configured for this application.\" />\n }\n </div>\n </div>\n\n <!-- Quick Access Panel (right slide-in) -->\n <div class=\"quick-access-panel\" [class.open]=\"state.quickAccessPanelOpen\">\n <div class=\"qa-header\">\n <h3>Quick Access</h3>\n <button class=\"qa-close-btn\" (click)=\"toggleQuickAccessPanel()\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n <div class=\"qa-body\">\n <!-- Recent Records (max 3) -->\n <mj-accordion-panel [Expanded]=\"isQuickAccessSectionExpanded('recentRecords')\" (ExpandedChange)=\"toggleQuickAccessSection('recentRecords')\">\n <ng-template mjAccordionTitle>\n <i class=\"fa-solid fa-clock-rotate-left qa-section-icon\"></i>\n <span>Recent Records</span>\n <span class=\"mj-accordion-badge mj-accordion-badge--right\">{{ quickAccessRecentRecords.length }}</span>\n </ng-template>\n @for (record of quickAccessRecentRecords; track record.entityId + '|' + record.recordId) {\n <div class=\"qa-item\" (click)=\"onRecentRecordClick(record)\">\n <div class=\"qa-item-icon\">\n <i [class]=\"getEntityIconById(record.entityId)\"></i>\n </div>\n <div class=\"qa-item-info\">\n <div class=\"qa-item-name\">{{ record.recordName || record.recordId }}</div>\n <div class=\"qa-item-meta\">{{ record.entityName }}</div>\n </div>\n <span class=\"qa-item-time\">{{ formatRelativeTime(record.latestAt) }}</span>\n </div>\n }\n @if (quickAccessRecentRecords.length === 0) {\n <div class=\"qa-empty\">No recent records</div>\n }\n </mj-accordion-panel>\n\n <!-- Recent Entities (max 3) -->\n <mj-accordion-panel [Expanded]=\"isQuickAccessSectionExpanded('recentEntities')\" (ExpandedChange)=\"toggleQuickAccessSection('recentEntities')\">\n <ng-template mjAccordionTitle>\n <i class=\"fa-solid fa-table qa-section-icon\"></i>\n <span>Recent Entities</span>\n <span class=\"mj-accordion-badge mj-accordion-badge--right\">{{ quickAccessRecentEntities.length }}</span>\n </ng-template>\n @for (entity of quickAccessRecentEntities; track entity.ID) {\n <div class=\"qa-item\" (click)=\"onEntitySelected(entity)\">\n <div class=\"qa-item-icon\">\n <i [class]=\"getEntityIcon(entity)\"></i>\n </div>\n <div class=\"qa-item-info\">\n <div class=\"qa-item-name\">{{ entity.DisplayNameOrName }}</div>\n </div>\n </div>\n }\n @if (quickAccessRecentEntities.length === 0) {\n <div class=\"qa-empty\">No recent entities</div>\n }\n </mj-accordion-panel>\n\n <!-- Favorite Records (max 3) -->\n <mj-accordion-panel [Expanded]=\"isQuickAccessSectionExpanded('favoriteRecords')\" (ExpandedChange)=\"toggleQuickAccessSection('favoriteRecords')\">\n <ng-template mjAccordionTitle>\n <i class=\"fa-solid fa-star qa-section-icon\" style=\"color: var(--mj-status-warning);\"></i>\n <span>Favorite Records</span>\n <span class=\"mj-accordion-badge mj-accordion-badge--right\">{{ quickAccessFavoriteRecords.length }}</span>\n </ng-template>\n @for (record of quickAccessFavoriteRecords; track record.userFavoriteId) {\n <div class=\"qa-item\" (click)=\"onFavoriteRecordClick(record)\">\n <div class=\"qa-item-icon\">\n <i [class]=\"getEntityIconById(record.entityId)\"></i>\n </div>\n <div class=\"qa-item-info\">\n <div class=\"qa-item-name\">{{ record.recordName || record.recordId }}</div>\n <div class=\"qa-item-meta\">{{ record.entityName }}</div>\n </div>\n </div>\n }\n @if (quickAccessFavoriteRecords.length === 0) {\n <div class=\"qa-empty\">No favorite records</div>\n }\n </mj-accordion-panel>\n </div>\n </div>\n }\n </div>\n } @else {\n <!--\n mj-view-workspace owns the saved-view lifecycle (select / save / duplicate / rename /\n delete / revert / quick-save) and the inner data renderer. Every view type is now a\n self-contained plug-in: view-type-specific features (export / add-to-list / delete /\n grid-state / timeline + map controls) live INSIDE the plug-in renderers and no longer\n bubble through the workspace. The dashboard only handles navigation (open record / open\n related record / create new record) + the generic filter/data-load/count signals + URL\n and view-CRUD state sync. AutoSaveView=true \u2192 the workspace persists view CRUD itself.\n -->\n <mj-view-workspace\n [Entity]=\"selectedEntity\"\n [AutoSaveView]=\"true\"\n [SelectedView]=\"selectedViewEntity\"\n [FilterText]=\"debouncedFilterText\"\n [SelectedRecordId]=\"state.selectedRecordId\"\n [ViewerConfig]=\"viewerConfig\"\n (SelectedViewChange)=\"onWorkspaceViewSelected($event)\"\n (ViewSelected)=\"onWorkspaceViewSelected($event)\"\n (OpenViewInTabRequested)=\"onOpenInTabRequested($event)\"\n (OpenRecordRequested)=\"onWorkspaceOpenRecord($event)\"\n (OpenRelatedRecordRequested)=\"onOpenRelatedRecordRequested($event)\"\n (CreateNewRecordRequested)=\"onCreateNewRecordRequested($event)\"\n (RecordSelected)=\"onViewerRecordSelected($event)\"\n (AfterViewSave)=\"onWorkspaceViewSaved()\"\n (AfterViewDelete)=\"onWorkspaceViewSaved()\"\n (FilterTextChanged)=\"onFilterTextChanged($event)\"\n (DataLoaded)=\"onDataLoaded($event)\"\n (FilteredCountChanged)=\"onFilteredCountChanged($event)\">\n </mj-view-workspace>\n }\n </div>\n </div>\n\n <!-- Detail Panel (Right - Slide In) -->\n @if (state.detailPanelOpen && selectedRecord) {\n <div class=\"detail-panel\" [style.width.px]=\"state.detailPanelWidth\">\n <mj-entity-record-detail-panel\n [entity]=\"detailPanelEntity\"\n [record]=\"selectedRecord\"\n (close)=\"onDetailPanelClosed()\"\n (openRecord)=\"onOpenRecord($event)\"\n (navigateToRelated)=\"onNavigateToRelated($event)\"\n (openRelatedRecord)=\"onOpenRelatedRecord($event)\"\n (openForeignKeyRecord)=\"onOpenForeignKeyRecord($event)\">\n </mj-entity-record-detail-panel>\n </div>\n }\n\n <!-- View config panel, filter dialog, quick-save/duplicate/shared-view-warning dialogs\n now live inside mj-view-workspace (the saved-view lifecycle moved there).\n Export + Add-to-List dialogs now live inside the grid plug-in renderer (it hosts its own\n Generic dialogs), so they are no longer rendered at the dashboard level. -->\n</div>\n", styles: [".data-explorer-container {\n display: flex;\n height: 100%;\n width: 100%;\n background: var(--mj-bg-surface-card);\n overflow: hidden;\n}\n\n.navigation-panel {\n flex-shrink: 0;\n height: 100%;\n background: var(--mj-bg-surface);\n border-right: 1px solid var(--mj-border-default);\n transition: width 0.2s ease-in-out;\n overflow: hidden;\n box-shadow: 2px 0 8px rgba(0, 0, 0, 0.04);\n}\n.navigation-panel.collapsed {\n width: 48px;\n}\n\n.content-area {\n flex: 1;\n display: flex;\n flex-direction: column;\n height: 100%;\n min-width: 0;\n overflow: hidden;\n background: var(--mj-bg-surface-card);\n}\n\n/* Breadcrumb Bar */\n.breadcrumb-bar {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 24px;\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n font-size: 13px;\n min-height: 40px;\n}\n\n.breadcrumb-item {\n display: flex;\n align-items: center;\n gap: 6px;\n color: var(--mj-text-secondary);\n padding: 4px 8px;\n border-radius: 4px;\n transition: all 0.15s ease;\n max-width: 200px;\n}\n\n.breadcrumb-item.clickable {\n cursor: pointer;\n}\n\n.breadcrumb-item.clickable:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-brand-primary);\n}\n\n.breadcrumb-item.current {\n color: var(--mj-text-primary);\n font-weight: 500;\n cursor: default;\n}\n\n.breadcrumb-icon {\n font-size: 12px;\n flex-shrink: 0;\n}\n\n.breadcrumb-label {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.breadcrumb-separator {\n font-size: 10px;\n color: var(--mj-border-strong);\n flex-shrink: 0;\n}\n\n.content-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 24px;\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n gap: 24px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);\n position: relative;\n z-index: 2; /* Above sibling .content-body so header dropdowns render on top of grid/map content */\n}\n\n.header-left {\n display: flex;\n align-items: center;\n gap: 12px;\n flex-shrink: 0;\n flex-wrap: wrap;\n}\n\n/* View Selector within header */\n.header-left ::ng-deep mj-view-selector {\n margin-left: 8px;\n}\n\n.entity-icon {\n font-size: 20px;\n color: var(--mj-brand-primary);\n}\n\n.entity-title {\n margin: 0;\n font-size: 20px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.record-count {\n font-size: 13px;\n color: var(--mj-text-secondary);\n font-weight: 500;\n}\n\n.header-center {\n flex: 1;\n max-width: 600px;\n}\n\n.smart-filter-container {\n position: relative;\n width: 100%;\n}\n\n.smart-filter-input {\n width: 100%;\n padding: 10px 40px 10px 16px;\n border: 1px solid var(--mj-border-strong);\n border-radius: 8px;\n font-size: 14px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n transition: all 0.15s ease;\n}\n.smart-filter-input:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n background: var(--mj-bg-surface);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n}\n.smart-filter-input::placeholder {\n color: var(--mj-text-muted);\n}\n\n.clear-filter-btn {\n position: absolute;\n right: 8px;\n top: 50%;\n transform: translateY(-50%);\n width: 28px;\n height: 28px;\n border: none;\n background: transparent;\n border-radius: 50%;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n transition: all 0.15s ease;\n}\n.clear-filter-btn:hover {\n background: var(--mj-border-default);\n color: var(--mj-text-primary);\n}\n\n.header-right {\n display: flex;\n align-items: center;\n gap: 16px;\n flex-shrink: 0;\n}\n\n.view-mode-toggle {\n display: flex;\n background: var(--mj-bg-surface-sunken);\n border-radius: 8px;\n padding: 3px;\n}\n\n.toggle-btn {\n width: 36px;\n height: 32px;\n border: none;\n background: transparent;\n border-radius: 6px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-secondary);\n transition: all 0.15s ease;\n}\n.toggle-btn:hover {\n color: var(--mj-text-primary);\n}\n.toggle-btn.active {\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n/* Header Action Button (Add to List, etc.) */\n.header-action-btn {\n position: relative;\n width: 36px;\n height: 36px;\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n border-radius: 8px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-secondary);\n transition: all 0.15s ease;\n margin-left: 8px;\n}\n.header-action-btn:hover:not(.disabled) {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, var(--mj-bg-surface));\n}\n.header-action-btn.disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.header-action-btn i {\n font-size: 14px;\n}\n.selection-badge {\n position: absolute;\n top: -6px;\n right: -6px;\n min-width: 18px;\n height: 18px;\n padding: 0 5px;\n background: var(--mj-brand-primary);\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 box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n}\n\n/* Timeline Date Field Selector - Styled Dropdown */\n.date-field-selector-container {\n display: flex;\n align-items: center;\n position: relative;\n}\n\n.date-field-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n z-index: 999;\n background: transparent;\n}\n\n.date-field-selector-wrapper {\n position: relative;\n}\n\n.date-field-selector-button {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 12px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n cursor: pointer;\n font-size: 13px;\n color: var(--mj-text-primary);\n transition: all 0.15s ease;\n min-width: 120px;\n max-width: 200px;\n}\n\n.date-field-selector-button:hover:not(:disabled) {\n background: var(--mj-bg-surface-hover);\n border-color: var(--mj-border-strong);\n}\n\n.date-field-selector-button:disabled {\n cursor: default;\n opacity: 0.8;\n}\n\n.date-field-selector-button.open {\n background: var(--mj-bg-surface-active);\n border-color: var(--mj-brand-primary);\n}\n\n.date-field-icon {\n color: var(--mj-text-secondary);\n font-size: 12px;\n}\n\n.date-field-name {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n text-align: left;\n}\n\n.date-field-arrow {\n color: var(--mj-text-secondary);\n font-size: 10px;\n transition: transform 0.2s ease;\n}\n\n.date-field-arrow.rotated {\n transform: rotate(180deg);\n}\n\n.date-field-dropdown-panel {\n position: absolute;\n top: calc(100% + 4px);\n left: 0;\n min-width: 180px;\n max-width: 280px;\n max-height: 300px;\n overflow-y: auto;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);\n z-index: 1000;\n}\n\n.date-field-dropdown-item {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 14px;\n cursor: pointer;\n transition: background 0.1s ease;\n font-size: 13px;\n}\n\n.date-field-dropdown-item:hover {\n background: var(--mj-bg-surface-card);\n}\n\n.date-field-dropdown-item.selected {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n}\n\n.date-field-dropdown-item.selected:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n}\n\n.date-field-dropdown-item .item-icon {\n color: var(--mj-text-secondary);\n font-size: 13px;\n width: 16px;\n text-align: center;\n}\n\n.date-field-dropdown-item .item-name {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.date-field-dropdown-item .selected-check {\n color: var(--mj-brand-primary);\n font-size: 12px;\n}\n\n/* View-specific controls \u2014 contextual controls for the active view mode.\n Positioned LEFT of the view mode toggle with a subtle visual separator. */\n.view-specific-controls {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 3px 8px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 8px;\n border: 1px solid var(--mj-border-subtle);\n}\n\n.view-specific-btn {\n width: 30px;\n height: 30px;\n border: none;\n background: transparent;\n border-radius: 6px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n transition: all 0.15s ease;\n}\n\n.view-specific-btn:hover {\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-hover);\n}\n\n/* Legacy \u2014 keep for backward compat but no longer used in template */\n.timeline-orientation-toggle {\n display: flex;\n background: var(--mj-bg-surface-sunken);\n border-radius: 8px;\n padding: 3px;\n}\n\n.content-body {\n display: flex;\n flex: 1 1 0%;\n overflow: hidden;\n /* Contain the body's stacking context. The view components inside (grid\n option menus, the map's Leaflet panes/toolbar, etc.) use z-index values up\n to ~1000; .content-header sits at z-index 2 (kept below the shell header \u2014\n see #2701). Without this, those body z-indices leak into the shared context\n and paint over the header's own dropdowns (view-selector, date-field).\n `isolation: isolate` flattens all body z-indices into one context beneath\n the header. Safe because modals + the detail panel render at the dashboard\n root (outside .content-body), so they still overlay everything. */\n isolation: isolate;\n position: relative; /* added */\n z-index: 3; /* added \u2014 higher than .content-header's z-index: 2 */\n}\n\n.loading-container,\n.loading-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n gap: 16px;\n background: var(--mj-bg-surface);\n border-radius: 8px;\n}\n\n.loading-spinner {\n font-size: 32px;\n color: var(--mj-brand-primary);\n}\n\n.loading-message {\n margin: 0;\n font-size: 14px;\n color: var(--mj-text-secondary);\n}\n\n\n/* ============================================\n CONCEPT D: HOME VIEW LAYOUT\n ============================================ */\n\n.home-view-concept-d {\n flex: 1;\n display: flex;\n overflow: hidden;\n}\n\n.home-main-area {\n flex: 1;\n overflow-y: auto;\n transition: margin-right 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.home-main-area.panel-open {\n margin-right: 320px;\n}\n\n/* ============================================\n SEARCH HERO\n ============================================ */\n\n.search-hero {\n background: var(--mj-bg-surface);\n padding: 36px 40px 24px;\n text-align: center;\n}\n\n.search-hero-container {\n position: relative;\n max-width: 600px;\n margin: 0 auto;\n}\n\n.search-hero-input {\n width: 100%;\n padding: 14px 18px 14px 44px;\n font-size: 15px;\n border: 2px solid var(--mj-border-default);\n border-radius: 12px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n outline: none;\n transition: all 0.2s;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.06);\n font-family: inherit;\n}\n\n.search-hero-input:focus {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 12px 40px rgba(0, 0, 0, 0.1), 0 0 0 4px color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n}\n\n.search-hero-input::placeholder {\n color: var(--mj-text-primary);\n}\n\n.search-hero-icon {\n position: absolute;\n left: 16px;\n top: 50%;\n transform: translateY(-50%);\n color: var(--mj-text-primary);\n font-size: 15px;\n pointer-events: none;\n}\n\n.search-hero-shortcut {\n position: absolute;\n right: 14px;\n top: 50%;\n transform: translateY(-50%);\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n padding: 2px 7px;\n border-radius: 5px;\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.search-hero-clear {\n position: absolute;\n right: 14px;\n top: 50%;\n transform: translateY(-50%);\n width: 28px;\n height: 28px;\n border: none;\n background: transparent;\n border-radius: 50%;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n transition: all 0.15s ease;\n}\n\n.search-hero-clear:hover {\n background: var(--mj-border-default);\n color: var(--mj-text-primary);\n}\n\n/* Meta row: entity count + pills */\n.search-meta-row {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 12px;\n margin-top: 16px;\n}\n\n.search-entity-count {\n font-size: 13px;\n color: var(--mj-text-muted);\n}\n\n.pill-toggle {\n display: flex;\n gap: 6px;\n}\n\n.pill-btn {\n padding: 6px 16px;\n border-radius: 20px;\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n font-size: 13px;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.15s;\n font-family: inherit;\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.pill-btn:hover {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n.pill-btn.active {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-color: var(--mj-brand-primary);\n}\n\n.pill-btn i {\n font-size: 11px;\n}\n\n/* ============================================\n APPLICATION GROUPS\n ============================================ */\n\n.entity-groups-area {\n padding: 12px 40px 60px;\n max-width: 1200px;\n margin: 0 auto;\n}\n\n.app-group {\n margin-bottom: 4px;\n}\n\n.app-group-header {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 14px;\n cursor: pointer;\n border-radius: 8px;\n transition: background 0.12s;\n user-select: none;\n}\n\n.app-group-header:hover {\n background: rgba(0, 0, 0, 0.025);\n}\n\n.app-group-icon {\n width: 38px;\n height: 38px;\n border-radius: 10px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 17px;\n flex-shrink: 0;\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.app-group-name {\n font-size: 21px;\n font-weight: 600;\n flex: 1;\n}\n\n.app-group-count {\n font-size: 12px;\n color: var(--mj-text-muted);\n background: var(--mj-bg-surface-card);\n padding: 2px 9px;\n border-radius: 10px;\n}\n\n.app-group-chevron {\n color: var(--mj-text-muted);\n font-size: 12px;\n transition: transform 0.2s;\n}\n\n.app-group-chevron.expanded {\n transform: rotate(90deg);\n}\n\n.app-group-entities {\n padding: 4px 14px 10px 60px;\n}\n\n/* ============================================\n ENTITY ITEM GRID (pills)\n ============================================ */\n\n.entity-item-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));\n gap: 12px;\n}\n\n.entity-item {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n padding: 10px 14px;\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.12s;\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n}\n\n.entity-item:hover {\n border-color: color-mix(in srgb, var(--mj-brand-primary) 40%, var(--mj-bg-surface));\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, var(--mj-bg-surface));\n}\n\n.entity-item-icon {\n width: 32px;\n height: 32px;\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 14px;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-card);\n flex-shrink: 0;\n}\n\n.entity-item:hover .entity-item-icon {\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.entity-item-text {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.entity-item-name {\n font-size: 14px;\n font-weight: 500;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.entity-item-desc {\n font-size: 12px;\n color: var(--mj-text-muted);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n line-height: 1.3;\n}\n\n.entity-item-fav {\n color: var(--mj-text-muted);\n opacity: 0;\n transition: opacity 0.12s;\n font-size: 11px;\n cursor: pointer;\n flex-shrink: 0;\n background: none;\n border: none;\n padding: 4px;\n align-self: center;\n}\n\n.entity-item:hover .entity-item-fav {\n opacity: 1;\n}\n\n.entity-item-fav.favorited {\n opacity: 1;\n color: var(--mj-status-warning);\n}\n\n/* ============================================\n QUICK ACCESS PANEL (right slide-in)\n ============================================ */\n\n.quick-access-panel {\n position: fixed;\n top: 60px;\n right: 0;\n width: 320px;\n height: calc(100% - 60px);\n background: var(--mj-bg-surface);\n border-left: 1px solid var(--mj-border-default);\n z-index: 50;\n transform: translateX(100%);\n transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n display: flex;\n flex-direction: column;\n}\n\n.quick-access-panel.open {\n transform: translateX(0);\n}\n\n.qa-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 16px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.qa-header h3 {\n font-size: 14px;\n font-weight: 600;\n margin: 0;\n}\n\n.qa-close-btn {\n background: none;\n border: none;\n color: var(--mj-text-muted);\n cursor: pointer;\n font-size: 14px;\n padding: 4px;\n border-radius: 4px;\n}\n\n.qa-close-btn:hover {\n background: var(--mj-bg-surface-card);\n}\n\n.qa-body {\n flex: 1;\n overflow-y: auto;\n}\n\n.qa-item {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 8px;\n border-radius: 8px;\n cursor: pointer;\n transition: background 0.08s;\n}\n\n.qa-item:hover {\n background: var(--mj-bg-surface-card);\n}\n\n.qa-item-icon {\n width: 28px;\n height: 28px;\n border-radius: 6px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 12px;\n background: var(--mj-bg-surface-card);\n color: var(--mj-text-secondary);\n flex-shrink: 0;\n}\n\n.qa-item-info {\n flex: 1;\n min-width: 0;\n}\n\n.qa-item-name {\n font-size: 13px;\n font-weight: 500;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.qa-item-meta {\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n\n.qa-item-time {\n font-size: 11px;\n color: var(--mj-text-muted);\n white-space: nowrap;\n}\n\n.qa-empty {\n padding: 20px 16px;\n text-align: center;\n color: var(--mj-text-muted);\n font-size: 13px;\n}\n\n/* Quick Access toggle button badge */\n.qa-badge {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n font-size: 10px;\n font-weight: 600;\n padding: 0 5px;\n border-radius: 8px;\n min-width: 16px;\n text-align: center;\n}\n\n.detail-panel {\n flex-shrink: 0;\n height: 100%;\n background: var(--mj-bg-surface);\n border-left: 1px solid var(--mj-border-default);\n box-shadow: -4px 0 16px rgba(0, 0, 0, 0.08);\n overflow: hidden;\n animation: slideIn 0.2s ease-out;\n display: flex;\n flex-direction: column;\n}\n\n.detail-panel mj-entity-record-detail-panel {\n flex: 1;\n min-height: 0;\n overflow: hidden;\n}\n\n@keyframes slideIn {\n from {\n transform: translateX(100%);\n opacity: 0;\n }\n to {\n transform: translateX(0);\n opacity: 1;\n }\n}\n\n/* Detail Panel Actions Bar */\n.detail-panel-actions {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n background: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.detail-action-btn {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n border: none;\n border-radius: 6px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.detail-action-btn:hover {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n transform: translateY(-1px);\n box-shadow: 0 2px 4px color-mix(in srgb, var(--mj-brand-primary) 20%, transparent);\n}\n\n.detail-action-btn i {\n font-size: 12px;\n}\n\n:host ::ng-deep mj-explorer-grid-view,\n:host ::ng-deep mj-explorer-cards-view {\n flex: 1;\n display: flex;\n flex-direction: column;\n min-height: 0;\n}\n\n/* ============================================\n HOME SCREEN STYLES\n ============================================ */\n\n/* Home-level header adjustments */\n.content-header.home-header {\n border-bottom: none;\n background: transparent;\n box-shadow: none;\n padding: 16px 24px 8px;\n}\n\n.content-body.home-content {\n padding: 0;\n}\n\n/* Smart filter with search icon (entity-level filter) */\n.filter-icon {\n position: absolute;\n left: 14px;\n top: 50%;\n transform: translateY(-50%);\n color: var(--mj-text-muted);\n font-size: 14px;\n pointer-events: none;\n}\n\n.smart-filter-container .smart-filter-input {\n padding-left: 40px;\n}\n\n/* ============================================\n VIEW MODE TOGGLE OVERRIDES\n ============================================ */\n\n.view-mode-toggle .toggle-btn {\n width: auto;\n padding: 0 12px;\n gap: 6px;\n}\n\n.toggle-label {\n font-size: 12px;\n font-weight: 500;\n}\n\n/* ============================================\n RESPONSIVE STYLES\n ============================================ */\n\n@media (max-width: 1200px) {\n .entity-item-grid {\n grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));\n }\n}\n\n@media (max-width: 900px) {\n .content-header {\n flex-wrap: wrap;\n gap: 12px;\n }\n\n .header-center {\n order: 3;\n flex-basis: 100%;\n max-width: 100%;\n }\n\n .search-hero {\n padding: 24px 16px 16px;\n }\n\n .entity-groups-area {\n padding: 8px 16px 40px;\n }\n\n .app-group-entities {\n padding-left: 36px;\n }\n\n .home-main-area.panel-open {\n margin-right: 0;\n }\n\n .quick-access-panel {\n width: 100%;\n }\n}\n\n@media (max-width: 600px) {\n .data-explorer-container {\n flex-direction: column;\n }\n\n .navigation-panel {\n display: none;\n }\n\n .content-header {\n padding: 12px 16px;\n }\n\n .content-body {\n padding: 12px 16px;\n }\n\n .entity-item-grid {\n grid-template-columns: 1fr;\n }\n\n .view-mode-toggle {\n display: none;\n }\n\n .app-group-name {\n font-size: 17px;\n }\n\n .entity-item-name {\n font-size: 14px;\n }\n}\n"] }]
2905
+ ], template: "<div class=\"data-explorer-container\">\n <!-- Navigation Panel (Left) - Hidden at home level, animated -->\n @if (!isAtHomeLevel) {\n <div\n class=\"navigation-panel\"\n [class.collapsed]=\"state.navigationPanelCollapsed\"\n [style.width.px]=\"state.navigationPanelCollapsed ? 48 : state.navigationPanelWidth\"\n [@slideInLeft]>\n\n <mj-explorer-navigation-panel\n [entities]=\"entities\"\n [appEntityGroups]=\"appEntityGroups\"\n [selectedEntityName]=\"state.selectedEntityName\"\n [favorites]=\"state.favorites\"\n [recentItems]=\"state.recentItems\"\n [collapsed]=\"state.navigationPanelCollapsed\"\n [allowedEntityNames]=\"allowedEntityNames\"\n [favoritesSectionExpanded]=\"state.favoritesSectionExpanded\"\n [recentSectionExpanded]=\"state.recentSectionExpanded\"\n [entitiesSectionExpanded]=\"state.entitiesSectionExpanded\"\n [viewsSectionExpanded]=\"state.viewsSectionExpanded\"\n (entitySelected)=\"onEntitySelected($event)\"\n (toggleCollapse)=\"toggleNavigationPanel()\"\n (sectionToggled)=\"stateService.toggleSection($event)\"\n (openRecord)=\"onOpenRecordFromNav($event)\"\n (selectRecord)=\"onSelectRecordFromNav($event)\"\n (expandAndFocus)=\"onExpandAndFocus($event)\">\n </mj-explorer-navigation-panel>\n </div>\n }\n\n <!-- Main Content Area -->\n <div class=\"content-area\">\n <!-- Breadcrumb Bar - Hidden at home level -->\n @if (!isAtHomeLevel && breadcrumbs.length > 0) {\n <div class=\"breadcrumb-bar\">\n @for (crumb of breadcrumbs; track crumb.label; let i = $index; let last = $last) {\n <span\n class=\"breadcrumb-item\"\n [class.clickable]=\"!last\"\n [class.current]=\"last\"\n (click)=\"onBreadcrumbClick(crumb, i)\"\n [title]=\"crumb.label\">\n @if (crumb.icon) {\n <i [class]=\"crumb.icon\" class=\"breadcrumb-icon\"></i>\n }\n <span class=\"breadcrumb-label\">{{ crumb.label }}</span>\n </span>\n @if (!last) {\n <i class=\"fa-solid fa-chevron-right breadcrumb-separator\"></i>\n }\n }\n </div>\n }\n\n <!-- Header -->\n <div class=\"content-header\" [class.home-header]=\"isAtHomeLevel\">\n <div class=\"header-left\">\n @if (selectedEntity) {\n <i [class]=\"getEntityIcon(selectedEntity)\" class=\"entity-icon\"></i>\n <h2 class=\"entity-title\">{{ selectedEntity.DisplayNameOrName }}</h2>\n @if (debouncedFilterText && filteredRecordCount !== totalRecordCount) {\n <span class=\"record-count\">{{ filteredRecordCount | number }} of {{ totalRecordCount | number }} records</span>\n } @else {\n <span class=\"record-count\">{{ totalRecordCount | number }} records</span>\n }\n\n <!-- View selector + view header now live inside mj-view-workspace (below). -->\n <!-- Add-to-List is now owned inside the grid plug-in renderer (it hosts its own dialog). -->\n } @else {\n @if (displayIcon) {\n <i [class]=\"displayIcon\" class=\"entity-icon\"></i>\n }\n <h2 class=\"entity-title\">{{ displayTitle }}</h2>\n <span class=\"record-count\">{{ entities.length }} entities available</span>\n }\n </div>\n\n <div class=\"header-center\">\n @if (selectedEntity) {\n <div class=\"smart-filter-container\">\n <i class=\"fa-solid fa-search filter-icon\"></i>\n <input\n #filterInput\n type=\"text\"\n class=\"smart-filter-input\"\n placeholder=\"Filter records... (press / to focus)\"\n [value]=\"liveFilterText\"\n (input)=\"onFilterInputChanged(filterInput.value)\"\n />\n @if (liveFilterText) {\n <button class=\"clear-filter-btn\" (click)=\"clearRecordFilter()\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n }\n </div>\n }\n <!-- Home-level search moved to search hero section -->\n </div>\n\n <div class=\"header-right\">\n @if (selectedEntity) {\n <!-- View-type switcher AND all view-specific controls (timeline date/orientation/sort,\n map render mode, etc.) now live inside the plug-in renderers hosted by\n mj-view-workspace. Nothing view-type-specific lives in this header anymore. -->\n }\n @if (!selectedEntity) {\n <!-- Quick Access panel toggle -->\n <button\n class=\"header-action-btn\"\n [class.active]=\"state.quickAccessPanelOpen\"\n (click)=\"toggleQuickAccessPanel()\"\n title=\"Recents & Favorites\">\n <i class=\"fa-solid fa-clock-rotate-left\"></i>\n @if (recentRecords.length + favoriteRecords.length > 0) {\n <span class=\"qa-badge\">{{ recentRecords.length + favoriteRecords.length }}</span>\n }\n </button>\n }\n </div>\n </div>\n\n <!-- Content Body - Using mj-entity-viewer composite -->\n <div class=\"content-body\" [class.home-content]=\"isAtHomeLevel\">\n @if (!selectedEntity) {\n <!-- Concept D: Application Groups + Search-First Home View -->\n <div class=\"home-view-concept-d\">\n @if (isLoadingEntities) {\n <div class=\"loading-state\">\n <mj-loading text=\"Loading entities...\" size=\"medium\"></mj-loading>\n </div>\n } @else {\n <div class=\"home-main-area\" [class.panel-open]=\"state.quickAccessPanelOpen\">\n <!-- Search Hero -->\n <div class=\"search-hero\">\n <div class=\"search-hero-container\">\n <i class=\"fa-solid fa-magnifying-glass search-hero-icon\"></i>\n <input\n #filterInput\n type=\"text\"\n class=\"search-hero-input\"\n placeholder=\"Search entities...\"\n [(ngModel)]=\"entityFilterText\"\n />\n @if (entityFilterText) {\n <button class=\"search-hero-clear\" (click)=\"entityFilterText = ''\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n } @else {\n <span class=\"search-hero-shortcut\">/</span>\n }\n </div>\n\n <!-- Meta row: entity count + All/Favorites pills -->\n <div class=\"search-meta-row\">\n <span class=\"search-entity-count\">\n {{ filteredEntityCount }} entities\n @if (applicationCount > 0) {\n across {{ applicationCount }} applications\n }\n </span>\n <div class=\"pill-toggle\">\n <button\n class=\"pill-btn\"\n [class.active]=\"state.homeViewMode === 'all'\"\n (click)=\"setHomeViewMode('all')\">\n All Entities\n </button>\n <button\n class=\"pill-btn\"\n [class.active]=\"state.homeViewMode === 'favorites'\"\n (click)=\"setHomeViewMode('favorites')\">\n <i class=\"fa-solid fa-star\"></i> My Favorites\n </button>\n </div>\n </div>\n </div>\n\n <!-- Entity Groups Area -->\n <div class=\"entity-groups-area\">\n @if (entityFilter?.applicationId) {\n <!-- Single-app mode: flat entity grid (no grouping) -->\n <div class=\"entity-item-grid\">\n @for (entity of flatFilteredEntities; track entity.ID) {\n <div\n class=\"entity-item\"\n (click)=\"onEntitySelected(entity)\"\n [title]=\"entity.Description || entity.DisplayNameOrName\">\n <div class=\"entity-item-icon\">\n <i [class]=\"getEntityIcon(entity)\"></i>\n </div>\n <div class=\"entity-item-text\">\n <span class=\"entity-item-name\">{{ entity.DisplayNameOrName }}</span>\n @if (entity.Description) {\n <span class=\"entity-item-desc\">{{ entity.Description }}</span>\n }\n </div>\n <button\n class=\"entity-item-fav\"\n [class.favorited]=\"isEntityFavorited(entity)\"\n (click)=\"toggleEntityFavorite(entity, $event)\"\n [title]=\"isEntityFavorited(entity) ? 'Remove from favorites' : 'Add to favorites'\">\n <i [class]=\"isEntityFavorited(entity) ? 'fa-solid fa-star' : 'fa-regular fa-star'\"></i>\n </button>\n </div>\n }\n </div>\n } @else {\n <!-- Multi-app mode: grouped by application -->\n @for (group of filteredAppEntityGroups; track group.applicationId) {\n <div class=\"app-group\">\n <div class=\"app-group-header\" (click)=\"toggleAppGroup(group.applicationId)\">\n <div\n class=\"app-group-icon\"\n [style.background]=\"group.applicationColor ? group.applicationColor + '15' : null\"\n [style.color]=\"group.applicationColor || null\">\n <i [class]=\"group.applicationIcon || 'fa-solid fa-folder'\"></i>\n </div>\n <span class=\"app-group-name\">{{ group.applicationName }}</span>\n <span class=\"app-group-count\">{{ group.entities.length }}</span>\n <i class=\"fa-solid fa-chevron-right app-group-chevron\"\n [class.expanded]=\"group.isExpanded\"></i>\n </div>\n @if (group.isExpanded) {\n <div class=\"app-group-entities\">\n <div class=\"entity-item-grid\">\n @for (entity of group.entities; track entity.ID) {\n <div\n class=\"entity-item\"\n (click)=\"onEntitySelected(entity)\"\n [title]=\"entity.Description || entity.DisplayNameOrName\">\n <div class=\"entity-item-icon\">\n <i [class]=\"getEntityIcon(entity)\"></i>\n </div>\n <div class=\"entity-item-text\">\n <span class=\"entity-item-name\">{{ entity.DisplayNameOrName }}</span>\n @if (entity.Description) {\n <span class=\"entity-item-desc\">{{ entity.Description }}</span>\n }\n </div>\n <button\n class=\"entity-item-fav\"\n [class.favorited]=\"isEntityFavorited(entity)\"\n (click)=\"toggleEntityFavorite(entity, $event)\"\n [title]=\"isEntityFavorited(entity) ? 'Remove from favorites' : 'Add to favorites'\">\n <i [class]=\"isEntityFavorited(entity) ? 'fa-solid fa-star' : 'fa-regular fa-star'\"></i>\n </button>\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\n }\n\n <!-- No results -->\n @if (filteredEntityCount === 0 && entities.length > 0) {\n <mj-empty-state Variant=\"no-results\"\n Title=\"No entities found\"\n [Message]=\"NoEntityResultsMessage\" />\n }\n @if (entities.length === 0) {\n <mj-empty-state Icon=\"fa-solid fa-database\"\n Title=\"No Entities Available\"\n Message=\"There are no entities configured for this application.\" />\n }\n </div>\n </div>\n\n <!-- Quick Access Panel (right slide-in) -->\n <div class=\"quick-access-panel\" [class.open]=\"state.quickAccessPanelOpen\">\n <div class=\"qa-header\">\n <h3>Quick Access</h3>\n <button class=\"qa-close-btn\" (click)=\"toggleQuickAccessPanel()\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n <div class=\"qa-body\">\n <!-- Recent Records (max 3) -->\n <mj-accordion-panel [Expanded]=\"isQuickAccessSectionExpanded('recentRecords')\" (ExpandedChange)=\"toggleQuickAccessSection('recentRecords')\">\n <ng-template mjAccordionTitle>\n <i class=\"fa-solid fa-clock-rotate-left qa-section-icon\"></i>\n <span>Recent Records</span>\n <span class=\"mj-accordion-badge mj-accordion-badge--right\">{{ quickAccessRecentRecords.length }}</span>\n </ng-template>\n @for (record of quickAccessRecentRecords; track record.entityId + '|' + record.recordId) {\n <div class=\"qa-item\" (click)=\"onRecentRecordClick(record)\">\n <div class=\"qa-item-icon\">\n <i [class]=\"getEntityIconById(record.entityId)\"></i>\n </div>\n <div class=\"qa-item-info\">\n <div class=\"qa-item-name\">{{ record.recordName || record.recordId }}</div>\n <div class=\"qa-item-meta\">{{ record.entityName }}</div>\n </div>\n <span class=\"qa-item-time\">{{ record.relativeTime }}</span>\n </div>\n }\n @if (quickAccessRecentRecords.length === 0) {\n <div class=\"qa-empty\">No recent records</div>\n }\n </mj-accordion-panel>\n\n <!-- Recent Entities (max 3) -->\n <mj-accordion-panel [Expanded]=\"isQuickAccessSectionExpanded('recentEntities')\" (ExpandedChange)=\"toggleQuickAccessSection('recentEntities')\">\n <ng-template mjAccordionTitle>\n <i class=\"fa-solid fa-table qa-section-icon\"></i>\n <span>Recent Entities</span>\n <span class=\"mj-accordion-badge mj-accordion-badge--right\">{{ quickAccessRecentEntities.length }}</span>\n </ng-template>\n @for (entity of quickAccessRecentEntities; track entity.ID) {\n <div class=\"qa-item\" (click)=\"onEntitySelected(entity)\">\n <div class=\"qa-item-icon\">\n <i [class]=\"getEntityIcon(entity)\"></i>\n </div>\n <div class=\"qa-item-info\">\n <div class=\"qa-item-name\">{{ entity.DisplayNameOrName }}</div>\n </div>\n </div>\n }\n @if (quickAccessRecentEntities.length === 0) {\n <div class=\"qa-empty\">No recent entities</div>\n }\n </mj-accordion-panel>\n\n <!-- Favorite Records (max 3) -->\n <mj-accordion-panel [Expanded]=\"isQuickAccessSectionExpanded('favoriteRecords')\" (ExpandedChange)=\"toggleQuickAccessSection('favoriteRecords')\">\n <ng-template mjAccordionTitle>\n <i class=\"fa-solid fa-star qa-section-icon\" style=\"color: var(--mj-status-warning);\"></i>\n <span>Favorite Records</span>\n <span class=\"mj-accordion-badge mj-accordion-badge--right\">{{ quickAccessFavoriteRecords.length }}</span>\n </ng-template>\n @for (record of quickAccessFavoriteRecords; track record.userFavoriteId) {\n <div class=\"qa-item\" (click)=\"onFavoriteRecordClick(record)\">\n <div class=\"qa-item-icon\">\n <i [class]=\"getEntityIconById(record.entityId)\"></i>\n </div>\n <div class=\"qa-item-info\">\n <div class=\"qa-item-name\">{{ record.recordName || record.recordId }}</div>\n <div class=\"qa-item-meta\">{{ record.entityName }}</div>\n </div>\n </div>\n }\n @if (quickAccessFavoriteRecords.length === 0) {\n <div class=\"qa-empty\">No favorite records</div>\n }\n </mj-accordion-panel>\n </div>\n </div>\n }\n </div>\n } @else {\n <!--\n mj-view-workspace owns the saved-view lifecycle (select / save / duplicate / rename /\n delete / revert / quick-save) and the inner data renderer. Every view type is now a\n self-contained plug-in: view-type-specific features (export / add-to-list / delete /\n grid-state / timeline + map controls) live INSIDE the plug-in renderers and no longer\n bubble through the workspace. The dashboard only handles navigation (open record / open\n related record / create new record) + the generic filter/data-load/count signals + URL\n and view-CRUD state sync. AutoSaveView=true \u2192 the workspace persists view CRUD itself.\n -->\n <mj-view-workspace\n [Entity]=\"selectedEntity\"\n [AutoSaveView]=\"true\"\n [SelectedView]=\"selectedViewEntity\"\n [FilterText]=\"debouncedFilterText\"\n [SelectedRecordId]=\"state.selectedRecordId\"\n [ViewerConfig]=\"viewerConfig\"\n (SelectedViewChange)=\"onWorkspaceViewSelected($event)\"\n (ViewSelected)=\"onWorkspaceViewSelected($event)\"\n (OpenViewInTabRequested)=\"onOpenInTabRequested($event)\"\n (OpenRecordRequested)=\"onWorkspaceOpenRecord($event)\"\n (OpenRelatedRecordRequested)=\"onOpenRelatedRecordRequested($event)\"\n (CreateNewRecordRequested)=\"onCreateNewRecordRequested($event)\"\n (RecordSelected)=\"onViewerRecordSelected($event)\"\n (AfterViewSave)=\"onWorkspaceViewSaved()\"\n (AfterViewDelete)=\"onWorkspaceViewSaved()\"\n (FilterTextChanged)=\"onFilterTextChanged($event)\"\n (DataLoaded)=\"onDataLoaded($event)\"\n (FilteredCountChanged)=\"onFilteredCountChanged($event)\">\n </mj-view-workspace>\n }\n </div>\n </div>\n\n <!-- Detail Panel (Right - Slide In) -->\n @if (state.detailPanelOpen && selectedRecord) {\n <div class=\"detail-panel\" [style.width.px]=\"state.detailPanelWidth\">\n <mj-entity-record-detail-panel\n [entity]=\"detailPanelEntity\"\n [record]=\"selectedRecord\"\n (close)=\"onDetailPanelClosed()\"\n (openRecord)=\"onOpenRecord($event)\"\n (navigateToRelated)=\"onNavigateToRelated($event)\"\n (openRelatedRecord)=\"onOpenRelatedRecord($event)\"\n (openForeignKeyRecord)=\"onOpenForeignKeyRecord($event)\">\n </mj-entity-record-detail-panel>\n </div>\n }\n\n <!-- View config panel, filter dialog, quick-save/duplicate/shared-view-warning dialogs\n now live inside mj-view-workspace (the saved-view lifecycle moved there).\n Export + Add-to-List dialogs now live inside the grid plug-in renderer (it hosts its own\n Generic dialogs), so they are no longer rendered at the dashboard level. -->\n</div>\n", styles: [".data-explorer-container {\n display: flex;\n height: 100%;\n width: 100%;\n background: var(--mj-bg-surface-card);\n overflow: hidden;\n}\n\n.navigation-panel {\n flex-shrink: 0;\n height: 100%;\n background: var(--mj-bg-surface);\n border-right: 1px solid var(--mj-border-default);\n transition: width 0.2s ease-in-out;\n overflow: hidden;\n box-shadow: 2px 0 8px rgba(0, 0, 0, 0.04);\n}\n.navigation-panel.collapsed {\n width: 48px;\n}\n\n.content-area {\n flex: 1;\n display: flex;\n flex-direction: column;\n height: 100%;\n min-width: 0;\n overflow: hidden;\n background: var(--mj-bg-surface-card);\n}\n\n/* Breadcrumb Bar */\n.breadcrumb-bar {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 24px;\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n font-size: 13px;\n min-height: 40px;\n}\n\n.breadcrumb-item {\n display: flex;\n align-items: center;\n gap: 6px;\n color: var(--mj-text-secondary);\n padding: 4px 8px;\n border-radius: 4px;\n transition: all 0.15s ease;\n max-width: 200px;\n}\n\n.breadcrumb-item.clickable {\n cursor: pointer;\n}\n\n.breadcrumb-item.clickable:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-brand-primary);\n}\n\n.breadcrumb-item.current {\n color: var(--mj-text-primary);\n font-weight: 500;\n cursor: default;\n}\n\n.breadcrumb-icon {\n font-size: 12px;\n flex-shrink: 0;\n}\n\n.breadcrumb-label {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.breadcrumb-separator {\n font-size: 10px;\n color: var(--mj-border-strong);\n flex-shrink: 0;\n}\n\n.content-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 24px;\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n gap: 24px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);\n position: relative;\n z-index: 2; /* Above sibling .content-body so header dropdowns render on top of grid/map content */\n}\n\n.header-left {\n display: flex;\n align-items: center;\n gap: 12px;\n flex-shrink: 0;\n flex-wrap: wrap;\n}\n\n/* View Selector within header */\n.header-left ::ng-deep mj-view-selector {\n margin-left: 8px;\n}\n\n.entity-icon {\n font-size: 20px;\n color: var(--mj-brand-primary);\n}\n\n.entity-title {\n margin: 0;\n font-size: 20px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.record-count {\n font-size: 13px;\n color: var(--mj-text-secondary);\n font-weight: 500;\n}\n\n.header-center {\n flex: 1;\n max-width: 600px;\n}\n\n.smart-filter-container {\n position: relative;\n width: 100%;\n}\n\n.smart-filter-input {\n width: 100%;\n padding: 10px 40px 10px 16px;\n border: 1px solid var(--mj-border-strong);\n border-radius: 8px;\n font-size: 14px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n transition: all 0.15s ease;\n}\n.smart-filter-input:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n background: var(--mj-bg-surface);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n}\n.smart-filter-input::placeholder {\n color: var(--mj-text-muted);\n}\n\n.clear-filter-btn {\n position: absolute;\n right: 8px;\n top: 50%;\n transform: translateY(-50%);\n width: 28px;\n height: 28px;\n border: none;\n background: transparent;\n border-radius: 50%;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n transition: all 0.15s ease;\n}\n.clear-filter-btn:hover {\n background: var(--mj-border-default);\n color: var(--mj-text-primary);\n}\n\n.header-right {\n display: flex;\n align-items: center;\n gap: 16px;\n flex-shrink: 0;\n}\n\n.view-mode-toggle {\n display: flex;\n background: var(--mj-bg-surface-sunken);\n border-radius: 8px;\n padding: 3px;\n}\n\n.toggle-btn {\n width: 36px;\n height: 32px;\n border: none;\n background: transparent;\n border-radius: 6px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-secondary);\n transition: all 0.15s ease;\n}\n.toggle-btn:hover {\n color: var(--mj-text-primary);\n}\n.toggle-btn.active {\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n/* Header Action Button (Add to List, etc.) */\n.header-action-btn {\n position: relative;\n width: 36px;\n height: 36px;\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n border-radius: 8px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-secondary);\n transition: all 0.15s ease;\n margin-left: 8px;\n}\n.header-action-btn:hover:not(.disabled) {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, var(--mj-bg-surface));\n}\n.header-action-btn.disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.header-action-btn i {\n font-size: 14px;\n}\n.selection-badge {\n position: absolute;\n top: -6px;\n right: -6px;\n min-width: 18px;\n height: 18px;\n padding: 0 5px;\n background: var(--mj-brand-primary);\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 box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n}\n\n/* Timeline Date Field Selector - Styled Dropdown */\n.date-field-selector-container {\n display: flex;\n align-items: center;\n position: relative;\n}\n\n.date-field-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n z-index: 999;\n background: transparent;\n}\n\n.date-field-selector-wrapper {\n position: relative;\n}\n\n.date-field-selector-button {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 12px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n cursor: pointer;\n font-size: 13px;\n color: var(--mj-text-primary);\n transition: all 0.15s ease;\n min-width: 120px;\n max-width: 200px;\n}\n\n.date-field-selector-button:hover:not(:disabled) {\n background: var(--mj-bg-surface-hover);\n border-color: var(--mj-border-strong);\n}\n\n.date-field-selector-button:disabled {\n cursor: default;\n opacity: 0.8;\n}\n\n.date-field-selector-button.open {\n background: var(--mj-bg-surface-active);\n border-color: var(--mj-brand-primary);\n}\n\n.date-field-icon {\n color: var(--mj-text-secondary);\n font-size: 12px;\n}\n\n.date-field-name {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n text-align: left;\n}\n\n.date-field-arrow {\n color: var(--mj-text-secondary);\n font-size: 10px;\n transition: transform 0.2s ease;\n}\n\n.date-field-arrow.rotated {\n transform: rotate(180deg);\n}\n\n.date-field-dropdown-panel {\n position: absolute;\n top: calc(100% + 4px);\n left: 0;\n min-width: 180px;\n max-width: 280px;\n max-height: 300px;\n overflow-y: auto;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);\n z-index: 1000;\n}\n\n.date-field-dropdown-item {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 14px;\n cursor: pointer;\n transition: background 0.1s ease;\n font-size: 13px;\n}\n\n.date-field-dropdown-item:hover {\n background: var(--mj-bg-surface-card);\n}\n\n.date-field-dropdown-item.selected {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n}\n\n.date-field-dropdown-item.selected:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n}\n\n.date-field-dropdown-item .item-icon {\n color: var(--mj-text-secondary);\n font-size: 13px;\n width: 16px;\n text-align: center;\n}\n\n.date-field-dropdown-item .item-name {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.date-field-dropdown-item .selected-check {\n color: var(--mj-brand-primary);\n font-size: 12px;\n}\n\n/* View-specific controls \u2014 contextual controls for the active view mode.\n Positioned LEFT of the view mode toggle with a subtle visual separator. */\n.view-specific-controls {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 3px 8px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 8px;\n border: 1px solid var(--mj-border-subtle);\n}\n\n.view-specific-btn {\n width: 30px;\n height: 30px;\n border: none;\n background: transparent;\n border-radius: 6px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n transition: all 0.15s ease;\n}\n\n.view-specific-btn:hover {\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-hover);\n}\n\n/* Legacy \u2014 keep for backward compat but no longer used in template */\n.timeline-orientation-toggle {\n display: flex;\n background: var(--mj-bg-surface-sunken);\n border-radius: 8px;\n padding: 3px;\n}\n\n.content-body {\n display: flex;\n flex: 1 1 0%;\n overflow: hidden;\n /* Contain the body's stacking context. The view components inside (grid\n option menus, the map's Leaflet panes/toolbar, etc.) use z-index values up\n to ~1000; .content-header sits at z-index 2 (kept below the shell header \u2014\n see #2701). Without this, those body z-indices leak into the shared context\n and paint over the header's own dropdowns (view-selector, date-field).\n `isolation: isolate` flattens all body z-indices into one context beneath\n the header. Safe because modals + the detail panel render at the dashboard\n root (outside .content-body), so they still overlay everything. */\n isolation: isolate;\n position: relative; /* added */\n z-index: 3; /* added \u2014 higher than .content-header's z-index: 2 */\n}\n\n.loading-container,\n.loading-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n gap: 16px;\n background: var(--mj-bg-surface);\n border-radius: 8px;\n}\n\n.loading-spinner {\n font-size: 32px;\n color: var(--mj-brand-primary);\n}\n\n.loading-message {\n margin: 0;\n font-size: 14px;\n color: var(--mj-text-secondary);\n}\n\n\n/* ============================================\n CONCEPT D: HOME VIEW LAYOUT\n ============================================ */\n\n.home-view-concept-d {\n flex: 1;\n display: flex;\n overflow: hidden;\n}\n\n.home-main-area {\n flex: 1;\n overflow-y: auto;\n transition: margin-right 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.home-main-area.panel-open {\n margin-right: 320px;\n}\n\n/* ============================================\n SEARCH HERO\n ============================================ */\n\n.search-hero {\n background: var(--mj-bg-surface);\n padding: 36px 40px 24px;\n text-align: center;\n}\n\n.search-hero-container {\n position: relative;\n max-width: 600px;\n margin: 0 auto;\n}\n\n.search-hero-input {\n width: 100%;\n padding: 14px 18px 14px 44px;\n font-size: 15px;\n border: 2px solid var(--mj-border-default);\n border-radius: 12px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n outline: none;\n transition: all 0.2s;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.06);\n font-family: inherit;\n}\n\n.search-hero-input:focus {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 12px 40px rgba(0, 0, 0, 0.1), 0 0 0 4px color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n}\n\n.search-hero-input::placeholder {\n color: var(--mj-text-primary);\n}\n\n.search-hero-icon {\n position: absolute;\n left: 16px;\n top: 50%;\n transform: translateY(-50%);\n color: var(--mj-text-primary);\n font-size: 15px;\n pointer-events: none;\n}\n\n.search-hero-shortcut {\n position: absolute;\n right: 14px;\n top: 50%;\n transform: translateY(-50%);\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n padding: 2px 7px;\n border-radius: 5px;\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.search-hero-clear {\n position: absolute;\n right: 14px;\n top: 50%;\n transform: translateY(-50%);\n width: 28px;\n height: 28px;\n border: none;\n background: transparent;\n border-radius: 50%;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n transition: all 0.15s ease;\n}\n\n.search-hero-clear:hover {\n background: var(--mj-border-default);\n color: var(--mj-text-primary);\n}\n\n/* Meta row: entity count + pills */\n.search-meta-row {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 12px;\n margin-top: 16px;\n}\n\n.search-entity-count {\n font-size: 13px;\n color: var(--mj-text-muted);\n}\n\n.pill-toggle {\n display: flex;\n gap: 6px;\n}\n\n.pill-btn {\n padding: 6px 16px;\n border-radius: 20px;\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n font-size: 13px;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.15s;\n font-family: inherit;\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.pill-btn:hover {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n.pill-btn.active {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-color: var(--mj-brand-primary);\n}\n\n.pill-btn i {\n font-size: 11px;\n}\n\n/* ============================================\n APPLICATION GROUPS\n ============================================ */\n\n.entity-groups-area {\n padding: 12px 40px 60px;\n max-width: 1200px;\n margin: 0 auto;\n}\n\n.app-group {\n margin-bottom: 4px;\n}\n\n.app-group-header {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 14px;\n cursor: pointer;\n border-radius: 8px;\n transition: background 0.12s;\n user-select: none;\n}\n\n.app-group-header:hover {\n background: rgba(0, 0, 0, 0.025);\n}\n\n.app-group-icon {\n width: 38px;\n height: 38px;\n border-radius: 10px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 17px;\n flex-shrink: 0;\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.app-group-name {\n font-size: 21px;\n font-weight: 600;\n flex: 1;\n}\n\n.app-group-count {\n font-size: 12px;\n color: var(--mj-text-muted);\n background: var(--mj-bg-surface-card);\n padding: 2px 9px;\n border-radius: 10px;\n}\n\n.app-group-chevron {\n color: var(--mj-text-muted);\n font-size: 12px;\n transition: transform 0.2s;\n}\n\n.app-group-chevron.expanded {\n transform: rotate(90deg);\n}\n\n.app-group-entities {\n padding: 4px 14px 10px 60px;\n}\n\n/* ============================================\n ENTITY ITEM GRID (pills)\n ============================================ */\n\n.entity-item-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));\n gap: 12px;\n}\n\n.entity-item {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n padding: 10px 14px;\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.12s;\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n}\n\n.entity-item:hover {\n border-color: color-mix(in srgb, var(--mj-brand-primary) 40%, var(--mj-bg-surface));\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, var(--mj-bg-surface));\n}\n\n.entity-item-icon {\n width: 32px;\n height: 32px;\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 14px;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-card);\n flex-shrink: 0;\n}\n\n.entity-item:hover .entity-item-icon {\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.entity-item-text {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.entity-item-name {\n font-size: 14px;\n font-weight: 500;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.entity-item-desc {\n font-size: 12px;\n color: var(--mj-text-muted);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n line-height: 1.3;\n}\n\n.entity-item-fav {\n color: var(--mj-text-muted);\n opacity: 0;\n transition: opacity 0.12s;\n font-size: 11px;\n cursor: pointer;\n flex-shrink: 0;\n background: none;\n border: none;\n padding: 4px;\n align-self: center;\n}\n\n.entity-item:hover .entity-item-fav {\n opacity: 1;\n}\n\n.entity-item-fav.favorited {\n opacity: 1;\n color: var(--mj-status-warning);\n}\n\n/* ============================================\n QUICK ACCESS PANEL (right slide-in)\n ============================================ */\n\n.quick-access-panel {\n position: fixed;\n top: 60px;\n right: 0;\n width: 320px;\n height: calc(100% - 60px);\n background: var(--mj-bg-surface);\n border-left: 1px solid var(--mj-border-default);\n z-index: 50;\n transform: translateX(100%);\n transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n display: flex;\n flex-direction: column;\n}\n\n.quick-access-panel.open {\n transform: translateX(0);\n}\n\n.qa-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 16px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.qa-header h3 {\n font-size: 14px;\n font-weight: 600;\n margin: 0;\n}\n\n.qa-close-btn {\n background: none;\n border: none;\n color: var(--mj-text-muted);\n cursor: pointer;\n font-size: 14px;\n padding: 4px;\n border-radius: 4px;\n}\n\n.qa-close-btn:hover {\n background: var(--mj-bg-surface-card);\n}\n\n.qa-body {\n flex: 1;\n overflow-y: auto;\n}\n\n.qa-item {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 8px;\n border-radius: 8px;\n cursor: pointer;\n transition: background 0.08s;\n}\n\n.qa-item:hover {\n background: var(--mj-bg-surface-card);\n}\n\n.qa-item-icon {\n width: 28px;\n height: 28px;\n border-radius: 6px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 12px;\n background: var(--mj-bg-surface-card);\n color: var(--mj-text-secondary);\n flex-shrink: 0;\n}\n\n.qa-item-info {\n flex: 1;\n min-width: 0;\n}\n\n.qa-item-name {\n font-size: 13px;\n font-weight: 500;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.qa-item-meta {\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n\n.qa-item-time {\n font-size: 11px;\n color: var(--mj-text-muted);\n white-space: nowrap;\n}\n\n.qa-empty {\n padding: 20px 16px;\n text-align: center;\n color: var(--mj-text-muted);\n font-size: 13px;\n}\n\n/* Quick Access toggle button badge */\n.qa-badge {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n font-size: 10px;\n font-weight: 600;\n padding: 0 5px;\n border-radius: 8px;\n min-width: 16px;\n text-align: center;\n}\n\n.detail-panel {\n flex-shrink: 0;\n height: 100%;\n background: var(--mj-bg-surface);\n border-left: 1px solid var(--mj-border-default);\n box-shadow: -4px 0 16px rgba(0, 0, 0, 0.08);\n overflow: hidden;\n animation: slideIn 0.2s ease-out;\n display: flex;\n flex-direction: column;\n}\n\n.detail-panel mj-entity-record-detail-panel {\n flex: 1;\n min-height: 0;\n overflow: hidden;\n}\n\n@keyframes slideIn {\n from {\n transform: translateX(100%);\n opacity: 0;\n }\n to {\n transform: translateX(0);\n opacity: 1;\n }\n}\n\n/* Detail Panel Actions Bar */\n.detail-panel-actions {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n background: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.detail-action-btn {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n border: none;\n border-radius: 6px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.detail-action-btn:hover {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n transform: translateY(-1px);\n box-shadow: 0 2px 4px color-mix(in srgb, var(--mj-brand-primary) 20%, transparent);\n}\n\n.detail-action-btn i {\n font-size: 12px;\n}\n\n:host ::ng-deep mj-explorer-grid-view,\n:host ::ng-deep mj-explorer-cards-view {\n flex: 1;\n display: flex;\n flex-direction: column;\n min-height: 0;\n}\n\n/* ============================================\n HOME SCREEN STYLES\n ============================================ */\n\n/* Home-level header adjustments */\n.content-header.home-header {\n border-bottom: none;\n background: transparent;\n box-shadow: none;\n padding: 16px 24px 8px;\n}\n\n.content-body.home-content {\n padding: 0;\n}\n\n/* Smart filter with search icon (entity-level filter) */\n.filter-icon {\n position: absolute;\n left: 14px;\n top: 50%;\n transform: translateY(-50%);\n color: var(--mj-text-muted);\n font-size: 14px;\n pointer-events: none;\n}\n\n.smart-filter-container .smart-filter-input {\n padding-left: 40px;\n}\n\n/* ============================================\n VIEW MODE TOGGLE OVERRIDES\n ============================================ */\n\n.view-mode-toggle .toggle-btn {\n width: auto;\n padding: 0 12px;\n gap: 6px;\n}\n\n.toggle-label {\n font-size: 12px;\n font-weight: 500;\n}\n\n/* ============================================\n RESPONSIVE STYLES\n ============================================ */\n\n@media (max-width: 1200px) {\n .entity-item-grid {\n grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));\n }\n}\n\n@media (max-width: 900px) {\n .content-header {\n flex-wrap: wrap;\n gap: 12px;\n }\n\n .header-center {\n order: 3;\n flex-basis: 100%;\n max-width: 100%;\n }\n\n .search-hero {\n padding: 24px 16px 16px;\n }\n\n .entity-groups-area {\n padding: 8px 16px 40px;\n }\n\n .app-group-entities {\n padding-left: 36px;\n }\n\n .home-main-area.panel-open {\n margin-right: 0;\n }\n\n .quick-access-panel {\n width: 100%;\n }\n}\n\n@media (max-width: 600px) {\n .data-explorer-container {\n flex-direction: column;\n }\n\n .navigation-panel {\n display: none;\n }\n\n .content-header {\n padding: 12px 16px;\n }\n\n .content-body {\n padding: 12px 16px;\n }\n\n .entity-item-grid {\n grid-template-columns: 1fr;\n }\n\n .view-mode-toggle {\n display: none;\n }\n\n .app-group-name {\n font-size: 17px;\n }\n\n .entity-item-name {\n font-size: 14px;\n }\n}\n"] }]
2896
2906
  }], () => [{ type: i1.ExplorerStateService }, { type: i0.ChangeDetectorRef }, { type: i2.RecentAccessService }, { type: i0.NgZone }], { filterInputRef: [{
2897
2907
  type: ViewChild,
2898
2908
  args: ['filterInput']