@memberjunction/ng-dashboards 5.3.0 → 5.4.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 (173) hide show
  1. package/dist/AI/components/agents/agent-configuration.component.js.map +1 -1
  2. package/dist/AI/components/agents/agent-editor.component.js.map +1 -1
  3. package/dist/AI/components/agents/agent-filter-panel.component.js.map +1 -1
  4. package/dist/AI/components/charts/performance-heatmap.component.js.map +1 -1
  5. package/dist/AI/components/charts/time-series-chart.component.js.map +1 -1
  6. package/dist/AI/components/execution-monitoring.component.js.map +1 -1
  7. package/dist/AI/components/models/model-management.component.js.map +1 -1
  8. package/dist/AI/components/prompts/model-prompt-priority-matrix.component.js.map +1 -1
  9. package/dist/AI/components/prompts/prompt-filter-panel.component.js.map +1 -1
  10. package/dist/AI/components/prompts/prompt-management.component.js.map +1 -1
  11. package/dist/AI/components/prompts/prompt-version-control.component.js.map +1 -1
  12. package/dist/AI/components/system/system-config-filter-panel.component.js.map +1 -1
  13. package/dist/AI/components/system/system-configuration.component.js.map +1 -1
  14. package/dist/AI/components/widgets/kpi-card.component.js.map +1 -1
  15. package/dist/AI/components/widgets/live-execution-widget.component.js.map +1 -1
  16. package/dist/AI/index.js.map +1 -1
  17. package/dist/AI/services/ai-instrumentation.service.js.map +1 -1
  18. package/dist/APIKeys/api-applications-panel.component.js +2 -2
  19. package/dist/APIKeys/api-applications-panel.component.js.map +1 -1
  20. package/dist/APIKeys/api-key-create-dialog.component.js +2 -2
  21. package/dist/APIKeys/api-key-create-dialog.component.js.map +1 -1
  22. package/dist/APIKeys/api-key-edit-panel.component.js +2 -2
  23. package/dist/APIKeys/api-key-edit-panel.component.js.map +1 -1
  24. package/dist/APIKeys/api-key-list.component.js +2 -2
  25. package/dist/APIKeys/api-key-list.component.js.map +1 -1
  26. package/dist/APIKeys/api-keys-resource.component.js +2 -2
  27. package/dist/APIKeys/api-keys-resource.component.js.map +1 -1
  28. package/dist/APIKeys/api-scopes-panel.component.js +2 -2
  29. package/dist/APIKeys/api-scopes-panel.component.js.map +1 -1
  30. package/dist/APIKeys/api-usage-panel.component.js +2 -2
  31. package/dist/APIKeys/api-usage-panel.component.js.map +1 -1
  32. package/dist/APIKeys/index.js.map +1 -1
  33. package/dist/Actions/components/actions-list-view.component.js.map +1 -1
  34. package/dist/Actions/components/actions-overview.component.js.map +1 -1
  35. package/dist/Actions/components/categories-list-view.component.js.map +1 -1
  36. package/dist/Actions/components/code-management.component.js.map +1 -1
  37. package/dist/Actions/components/entity-integration.component.js.map +1 -1
  38. package/dist/Actions/components/execution-monitoring.component.js.map +1 -1
  39. package/dist/Actions/components/executions-list-view.component.js.map +1 -1
  40. package/dist/Actions/components/explorer/action-breadcrumb.component.js.map +1 -1
  41. package/dist/Actions/components/explorer/action-card.component.js.map +1 -1
  42. package/dist/Actions/components/explorer/action-explorer.component.js.map +1 -1
  43. package/dist/Actions/components/explorer/action-list-item.component.js.map +1 -1
  44. package/dist/Actions/components/explorer/action-toolbar.component.js.map +1 -1
  45. package/dist/Actions/components/explorer/action-tree-panel.component.js.map +1 -1
  46. package/dist/Actions/components/explorer/index.js.map +1 -1
  47. package/dist/Actions/components/explorer/new-action-panel.component.js.map +1 -1
  48. package/dist/Actions/components/explorer/new-category-panel.component.js.map +1 -1
  49. package/dist/Actions/components/scheduled-actions.component.js.map +1 -1
  50. package/dist/Actions/components/security-permissions.component.js.map +1 -1
  51. package/dist/Actions/index.js.map +1 -1
  52. package/dist/Actions/services/action-explorer-state.service.js.map +1 -1
  53. package/dist/Communication/communication-dashboard.component.js.map +1 -1
  54. package/dist/Communication/communication-logs-resource.component.js.map +1 -1
  55. package/dist/Communication/communication-monitor-resource.component.js.map +1 -1
  56. package/dist/Communication/communication-providers-resource.component.js.map +1 -1
  57. package/dist/Communication/communication-runs-resource.component.js.map +1 -1
  58. package/dist/Communication/communication-templates-resource.component.js.map +1 -1
  59. package/dist/ComponentStudio/component-studio-dashboard.component.js.map +1 -1
  60. package/dist/ComponentStudio/components/ai-assistant/ai-assistant-panel.component.js.map +1 -1
  61. package/dist/ComponentStudio/components/artifact-load-dialog.component.js.map +1 -1
  62. package/dist/ComponentStudio/components/artifact-selection-dialog.component.js.map +1 -1
  63. package/dist/ComponentStudio/components/browser/component-browser.component.js.map +1 -1
  64. package/dist/ComponentStudio/components/editors/code-editor-panel.component.js.map +1 -1
  65. package/dist/ComponentStudio/components/editors/data-requirements-editor.component.js.map +1 -1
  66. package/dist/ComponentStudio/components/editors/requirements-editor.component.js.map +1 -1
  67. package/dist/ComponentStudio/components/editors/spec-editor.component.js.map +1 -1
  68. package/dist/ComponentStudio/components/new-component-dialog/new-component-dialog.component.js.map +1 -1
  69. package/dist/ComponentStudio/components/save-version-dialog/save-version-dialog.component.js.map +1 -1
  70. package/dist/ComponentStudio/components/text-import-dialog.component.js.map +1 -1
  71. package/dist/ComponentStudio/components/workspace/component-preview.component.js.map +1 -1
  72. package/dist/ComponentStudio/components/workspace/editor-tabs.component.js.map +1 -1
  73. package/dist/ComponentStudio/index.js.map +1 -1
  74. package/dist/ComponentStudio/services/component-studio-state.service.js.map +1 -1
  75. package/dist/ComponentStudio/services/component-version.service.js.map +1 -1
  76. package/dist/Credentials/components/credentials-audit-resource.component.js.map +1 -1
  77. package/dist/Credentials/components/credentials-categories-resource.component.js.map +1 -1
  78. package/dist/Credentials/components/credentials-list-resource.component.js.map +1 -1
  79. package/dist/Credentials/components/credentials-overview-resource.component.js.map +1 -1
  80. package/dist/Credentials/components/credentials-types-resource.component.js.map +1 -1
  81. package/dist/Credentials/credentials-dashboard.component.js.map +1 -1
  82. package/dist/Credentials/index.js.map +1 -1
  83. package/dist/Credentials/pipes/group-by.pipe.js.map +1 -1
  84. package/dist/DashboardBrowser/dashboard-browser-resource.component.js.map +1 -1
  85. package/dist/DashboardBrowser/dashboard-share-dialog.component.js.map +1 -1
  86. package/dist/DataExplorer/components/filter-dialog/filter-dialog.component.js.map +1 -1
  87. package/dist/DataExplorer/components/navigation-panel/navigation-panel.component.d.ts +25 -3
  88. package/dist/DataExplorer/components/navigation-panel/navigation-panel.component.d.ts.map +1 -1
  89. package/dist/DataExplorer/components/navigation-panel/navigation-panel.component.js +158 -34
  90. package/dist/DataExplorer/components/navigation-panel/navigation-panel.component.js.map +1 -1
  91. package/dist/DataExplorer/components/view-selector/view-selector.component.js.map +1 -1
  92. package/dist/DataExplorer/data-explorer-dashboard.component.d.ts +57 -23
  93. package/dist/DataExplorer/data-explorer-dashboard.component.d.ts.map +1 -1
  94. package/dist/DataExplorer/data-explorer-dashboard.component.js +600 -445
  95. package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
  96. package/dist/DataExplorer/data-explorer-resource.component.js.map +1 -1
  97. package/dist/DataExplorer/index.js.map +1 -1
  98. package/dist/DataExplorer/models/explorer-state.interface.d.ts +25 -0
  99. package/dist/DataExplorer/models/explorer-state.interface.d.ts.map +1 -1
  100. package/dist/DataExplorer/models/explorer-state.interface.js +6 -1
  101. package/dist/DataExplorer/models/explorer-state.interface.js.map +1 -1
  102. package/dist/DataExplorer/services/explorer-state.service.d.ts +21 -3
  103. package/dist/DataExplorer/services/explorer-state.service.d.ts.map +1 -1
  104. package/dist/DataExplorer/services/explorer-state.service.js +70 -36
  105. package/dist/DataExplorer/services/explorer-state.service.js.map +1 -1
  106. package/dist/EntityAdmin/entity-admin-dashboard.component.js +2 -2
  107. package/dist/EntityAdmin/entity-admin-dashboard.component.js.map +1 -1
  108. package/dist/Home/home-application.js.map +1 -1
  109. package/dist/Home/home-dashboard.component.d.ts +20 -5
  110. package/dist/Home/home-dashboard.component.d.ts.map +1 -1
  111. package/dist/Home/home-dashboard.component.js +128 -79
  112. package/dist/Home/home-dashboard.component.js.map +1 -1
  113. package/dist/Lists/components/lists-browse-resource.component.js.map +1 -1
  114. package/dist/Lists/components/lists-categories-resource.component.js.map +1 -1
  115. package/dist/Lists/components/lists-my-lists-resource.component.js.map +1 -1
  116. package/dist/Lists/components/lists-operations-resource.component.js.map +1 -1
  117. package/dist/Lists/components/venn-diagram/venn-diagram.component.js.map +1 -1
  118. package/dist/Lists/index.js.map +1 -1
  119. package/dist/Lists/services/list-set-operations.service.js.map +1 -1
  120. package/dist/MCP/components/mcp-connection-dialog.component.js.map +1 -1
  121. package/dist/MCP/components/mcp-log-detail-panel.component.js.map +1 -1
  122. package/dist/MCP/components/mcp-server-dialog.component.js.map +1 -1
  123. package/dist/MCP/components/mcp-test-tool-dialog.component.js.map +1 -1
  124. package/dist/MCP/index.js.map +1 -1
  125. package/dist/MCP/mcp-dashboard.component.js.map +1 -1
  126. package/dist/MCP/mcp-filter-panel.component.js.map +1 -1
  127. package/dist/MCP/mcp-resource.component.js.map +1 -1
  128. package/dist/MCP/mcp.module.js.map +1 -1
  129. package/dist/MCP/services/mcp-tools.service.js.map +1 -1
  130. package/dist/QueryBrowser/query-browser-resource.component.js.map +1 -1
  131. package/dist/Scheduling/components/index.js.map +1 -1
  132. package/dist/Scheduling/components/job-slideout.component.js.map +1 -1
  133. package/dist/Scheduling/components/scheduling-activity-resource.component.js.map +1 -1
  134. package/dist/Scheduling/components/scheduling-activity.component.js.map +1 -1
  135. package/dist/Scheduling/components/scheduling-jobs-resource.component.js.map +1 -1
  136. package/dist/Scheduling/components/scheduling-jobs.component.js.map +1 -1
  137. package/dist/Scheduling/components/scheduling-overview-resource.component.js.map +1 -1
  138. package/dist/Scheduling/components/scheduling-overview.component.js.map +1 -1
  139. package/dist/Scheduling/scheduling-dashboard.component.js.map +1 -1
  140. package/dist/Scheduling/services/scheduling-instrumentation.service.js.map +1 -1
  141. package/dist/SystemDiagnostics/index.js.map +1 -1
  142. package/dist/SystemDiagnostics/system-diagnostics.component.d.ts.map +1 -1
  143. package/dist/SystemDiagnostics/system-diagnostics.component.js +3 -3
  144. package/dist/SystemDiagnostics/system-diagnostics.component.js.map +1 -1
  145. package/dist/Testing/components/index.js.map +1 -1
  146. package/dist/Testing/components/testing-analytics-resource.component.js.map +1 -1
  147. package/dist/Testing/components/testing-analytics.component.js.map +1 -1
  148. package/dist/Testing/components/testing-dashboard-tab-resource.component.js.map +1 -1
  149. package/dist/Testing/components/testing-dashboard-tab.component.js.map +1 -1
  150. package/dist/Testing/components/testing-explorer-resource.component.js.map +1 -1
  151. package/dist/Testing/components/testing-explorer.component.js.map +1 -1
  152. package/dist/Testing/components/testing-review-resource.component.js.map +1 -1
  153. package/dist/Testing/components/testing-review.component.js.map +1 -1
  154. package/dist/Testing/components/testing-runs-resource.component.js.map +1 -1
  155. package/dist/Testing/components/testing-runs.component.js.map +1 -1
  156. package/dist/Testing/components/widgets/oracle-breakdown-table.component.js.map +1 -1
  157. package/dist/Testing/components/widgets/suite-tree.component.js.map +1 -1
  158. package/dist/Testing/components/widgets/test-run-detail-panel.component.js.map +1 -1
  159. package/dist/Testing/services/testing-instrumentation.service.js.map +1 -1
  160. package/dist/Testing/testing-dashboard.component.js.map +1 -1
  161. package/dist/VersionHistory/components/diff-resource.component.js.map +1 -1
  162. package/dist/VersionHistory/components/graph-resource.component.js.map +1 -1
  163. package/dist/VersionHistory/components/index.js.map +1 -1
  164. package/dist/VersionHistory/components/labels-resource.component.js.map +1 -1
  165. package/dist/VersionHistory/components/restore-resource.component.js.map +1 -1
  166. package/dist/VersionHistory/index.js.map +1 -1
  167. package/dist/__tests__/dashboards.test.js.map +1 -1
  168. package/dist/module.js.map +1 -1
  169. package/dist/public-api.js.map +1 -1
  170. package/dist/shared/pipes/highlight-search.pipe.js.map +1 -1
  171. package/dist/shared/pipes/index.js.map +1 -1
  172. package/dist/shared/shared-pipes.module.js.map +1 -1
  173. package/package.json +38 -38
@@ -1125,7 +1125,7 @@ let APIKeysResourceComponent = class APIKeysResourceComponent extends BaseResour
1125
1125
  i0.ɵɵproperty("Visible", ctx.ShowCreateDialog);
1126
1126
  i0.ɵɵadvance();
1127
1127
  i0.ɵɵproperty("Visible", ctx.ShowEditPanel)("KeyId", ctx.SelectedKeyId);
1128
- } }, dependencies: [i1.NgClass, i2.LoadingComponent, i3.APIKeyCreateDialogComponent, i4.APIKeyEditPanelComponent, i5.APIKeyListComponent, i6.APIApplicationsPanelComponent, i7.APIScopesPanelComponent, i8.APIUsagePanelComponent], styles: ["\n\n.api-keys-dashboard[_ngcontent-%COMP%] {\n display: flex;\n height: 100%;\n position: relative;\n overflow: hidden;\n}\n\n.api-keys-dashboard.panel-open[_ngcontent-%COMP%] .dashboard-content[_ngcontent-%COMP%] {\n overflow: hidden;\n}\n\n\n\n.dashboard-nav[_ngcontent-%COMP%] {\n width: 220px;\n background: var(--card-background, #ffffff);\n border-right: 1px solid var(--border-color, #e5e7eb);\n display: flex;\n flex-direction: column;\n flex-shrink: 0;\n}\n\n.nav-header[_ngcontent-%COMP%] {\n padding: 20px;\n border-bottom: 1px solid var(--border-color, #e5e7eb);\n}\n\n.nav-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n font-weight: 700;\n font-size: 16px;\n color: var(--text-primary, #1f2937);\n}\n\n.nav-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #f59e0b;\n font-size: 18px;\n}\n\n.nav-items[_ngcontent-%COMP%] {\n flex: 1;\n padding: 12px;\n overflow-y: auto;\n}\n\n.nav-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 16px;\n margin-bottom: 4px;\n background: transparent;\n border: none;\n border-radius: 8px;\n font-size: 14px;\n font-weight: 500;\n color: var(--text-secondary, #6b7280);\n cursor: pointer;\n transition: all 0.2s ease;\n width: 100%;\n text-align: left;\n}\n\n.nav-item[_ngcontent-%COMP%]:hover {\n background: var(--item-hover, #f3f4f6);\n color: var(--text-primary, #1f2937);\n}\n\n.nav-item.active[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);\n color: white;\n box-shadow: 0 2px 8px rgba(245, 158, 11, 0.3);\n}\n\n.nav-item[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 16px;\n width: 20px;\n text-align: center;\n}\n\n.nav-item[_ngcontent-%COMP%] .nav-label[_ngcontent-%COMP%] {\n flex: 1;\n}\n\n.nav-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 22px;\n height: 20px;\n padding: 0 6px;\n background: rgba(0, 0, 0, 0.1);\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n}\n\n.nav-item.active[_ngcontent-%COMP%] .nav-badge[_ngcontent-%COMP%] {\n background: rgba(255, 255, 255, 0.25);\n}\n\n\n\n.dashboard-content[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow-y: auto;\n min-width: 0;\n}\n\n.content-wrapper[_ngcontent-%COMP%] {\n flex: 1;\n padding: 24px;\n overflow-y: auto;\n}\n\n\n\n.list-view-header[_ngcontent-%COMP%] {\n margin-bottom: 16px;\n}\n\n.back-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n background: var(--card-background, #ffffff);\n border: 1px solid var(--border-color, #e5e7eb);\n border-radius: 8px;\n font-size: 14px;\n font-weight: 500;\n color: var(--text-secondary, #6b7280);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.back-btn[_ngcontent-%COMP%]:hover {\n background: var(--item-hover, #f3f4f6);\n color: var(--text-primary, #1f2937);\n}\n\n\n\n.overview-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 24px;\n}\n\n.header-left[_ngcontent-%COMP%] {\n flex: 1;\n}\n\n.overview-title[_ngcontent-%COMP%] {\n font-size: 24px;\n font-weight: 700;\n color: var(--text-primary, #1f2937);\n margin: 0 0 4px 0;\n}\n\n.overview-subtitle[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--text-secondary, #6b7280);\n margin: 0;\n}\n\n.header-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n}\n\n.btn-refresh[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 40px;\n height: 40px;\n background: var(--card-background, #ffffff);\n border: 1px solid var(--border-color, #e5e7eb);\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.btn-refresh[_ngcontent-%COMP%]:hover {\n background: var(--item-hover, #f3f4f6);\n}\n\n.btn-refresh[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--text-secondary, #6b7280);\n}\n\n.btn-primary[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 20px;\n background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);\n color: white;\n border: none;\n border-radius: 8px;\n font-weight: 600;\n font-size: 14px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.btn-primary[_ngcontent-%COMP%]:hover {\n transform: translateY(-1px);\n box-shadow: 0 4px 12px rgba(245, 158, 11, 0.4);\n}\n\n\n\n.health-banner[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 20px 24px;\n background: linear-gradient(135deg, #ecfdf5 0%, #d1fae5 100%);\n border: 1px solid #a7f3d0;\n border-radius: 16px;\n margin-bottom: 24px;\n}\n\n.health-banner.health-warning[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #fffbeb 0%, #fef3c7 100%);\n border-color: #fcd34d;\n}\n\n.health-banner.health-critical[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #fef2f2 0%, #fee2e2 100%);\n border-color: #fca5a5;\n}\n\n.health-score-container[_ngcontent-%COMP%] {\n margin-right: 24px;\n}\n\n.health-score-ring[_ngcontent-%COMP%] {\n position: relative;\n width: 80px;\n height: 80px;\n}\n\n.circular-chart[_ngcontent-%COMP%] {\n display: block;\n margin: 0 auto;\n max-height: 80px;\n transform: rotate(-90deg);\n}\n\n.circle-bg[_ngcontent-%COMP%] {\n fill: none;\n stroke: #e5e7eb;\n stroke-width: 3.8;\n}\n\n.circle[_ngcontent-%COMP%] {\n fill: none;\n stroke-width: 3.8;\n stroke-linecap: round;\n stroke: #10b981;\n animation: _ngcontent-%COMP%_progress 1s ease-out forwards;\n}\n\n.health-banner.health-warning[_ngcontent-%COMP%] .circle[_ngcontent-%COMP%] {\n stroke: #f59e0b;\n}\n\n.health-banner.health-critical[_ngcontent-%COMP%] .circle[_ngcontent-%COMP%] {\n stroke: #ef4444;\n}\n\n@keyframes _ngcontent-%COMP%_progress {\n 0% {\n stroke-dasharray: 0 100;\n }\n}\n\n.health-score-value[_ngcontent-%COMP%] {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n font-size: 20px;\n font-weight: 700;\n color: var(--text-primary, #1f2937);\n}\n\n.health-info[_ngcontent-%COMP%] {\n flex: 1;\n}\n\n.health-label[_ngcontent-%COMP%] {\n font-size: 18px;\n font-weight: 700;\n color: #059669;\n margin-bottom: 4px;\n}\n\n.health-banner.health-warning[_ngcontent-%COMP%] .health-label[_ngcontent-%COMP%] {\n color: #d97706;\n}\n\n.health-banner.health-critical[_ngcontent-%COMP%] .health-label[_ngcontent-%COMP%] {\n color: #dc2626;\n}\n\n.health-details[_ngcontent-%COMP%] {\n display: flex;\n gap: 16px;\n flex-wrap: wrap;\n}\n\n.health-alert[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n color: #dc2626;\n font-weight: 500;\n font-size: 14px;\n cursor: pointer;\n}\n\n.health-alert[_ngcontent-%COMP%]:hover {\n text-decoration: underline;\n}\n\n.health-warning-text[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n color: #d97706;\n font-weight: 500;\n font-size: 14px;\n cursor: pointer;\n}\n\n.health-warning-text[_ngcontent-%COMP%]:hover {\n text-decoration: underline;\n}\n\n.health-info-text[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n color: #6b7280;\n font-weight: 500;\n font-size: 14px;\n cursor: pointer;\n}\n\n.health-info-text[_ngcontent-%COMP%]:hover {\n text-decoration: underline;\n}\n\n.health-ok[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n color: #059669;\n font-weight: 500;\n font-size: 14px;\n}\n\n\n\n.kpi-row[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));\n gap: 16px;\n margin-bottom: 24px;\n}\n\n.kpi-card[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 16px 20px;\n background: var(--card-background, #ffffff);\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.kpi-card.clickable[_ngcontent-%COMP%] {\n cursor: pointer;\n}\n\n.kpi-card.clickable[_ngcontent-%COMP%]:hover {\n transform: translateY(-2px);\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);\n}\n\n.kpi-card.active[_ngcontent-%COMP%] .kpi-icon[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #10b981 0%, #059669 100%);\n}\n\n.kpi-card.warning[_ngcontent-%COMP%] .kpi-icon[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);\n}\n\n.kpi-card.danger[_ngcontent-%COMP%] .kpi-icon[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);\n}\n\n.kpi-icon[_ngcontent-%COMP%] {\n width: 48px;\n height: 48px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);\n border-radius: 10px;\n margin-right: 14px;\n flex-shrink: 0;\n}\n\n.kpi-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 20px;\n color: white;\n}\n\n.kpi-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.kpi-value[_ngcontent-%COMP%] {\n font-size: 24px;\n font-weight: 700;\n color: var(--text-primary, #1f2937);\n line-height: 1.2;\n}\n\n.kpi-label[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--text-secondary, #6b7280);\n margin-top: 2px;\n white-space: nowrap;\n}\n\n.kpi-trend[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n margin-left: 8px;\n color: var(--text-tertiary, #9ca3af);\n}\n\n.kpi-trend.success[_ngcontent-%COMP%] {\n color: #10b981;\n}\n\n.kpi-trend.warning[_ngcontent-%COMP%] {\n color: #f59e0b;\n}\n\n.kpi-trend[_ngcontent-%COMP%] .percentage[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 600;\n}\n\n\n\n.content-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 1fr 1fr;\n grid-template-rows: auto auto;\n gap: 20px;\n margin-bottom: 24px;\n}\n\n.keys-panel[_ngcontent-%COMP%] {\n grid-row: span 1;\n}\n\n.scope-panel[_ngcontent-%COMP%] {\n grid-row: span 1;\n}\n\n.activity-panel[_ngcontent-%COMP%] {\n grid-column: span 2;\n}\n\n.panel[_ngcontent-%COMP%] {\n background: var(--card-background, #ffffff);\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n overflow: hidden;\n display: flex;\n flex-direction: column;\n}\n\n.panel-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n background: var(--header-background, #f9fafb);\n border-bottom: 1px solid var(--border-color, #e5e7eb);\n}\n\n.panel-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n font-weight: 600;\n font-size: 14px;\n color: var(--text-primary, #1f2937);\n}\n\n.panel-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #f59e0b;\n}\n\n.panel-subtitle[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--text-tertiary, #9ca3af);\n}\n\n.panel-action[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n background: transparent;\n border: 1px solid var(--border-color, #e5e7eb);\n border-radius: 6px;\n font-size: 12px;\n font-weight: 500;\n color: var(--text-secondary, #6b7280);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.panel-action[_ngcontent-%COMP%]:hover {\n background: #f59e0b;\n border-color: #f59e0b;\n color: white;\n}\n\n.panel-body[_ngcontent-%COMP%] {\n padding: 20px;\n flex: 1;\n overflow-y: auto;\n}\n\n\n\n.key-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.key-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 14px 16px;\n background: var(--item-background, #f9fafb);\n border-radius: 10px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.key-item[_ngcontent-%COMP%]:hover {\n background: var(--item-hover, #f3f4f6);\n transform: translateX(4px);\n}\n\n.key-icon[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: linear-gradient(135deg, #6b7280 0%, #4b5563 100%);\n border-radius: 8px;\n margin-right: 14px;\n flex-shrink: 0;\n}\n\n.key-icon.active[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);\n}\n\n.key-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 16px;\n color: white;\n}\n\n.key-info[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.key-label[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: var(--text-primary, #1f2937);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.key-meta[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-top: 2px;\n font-size: 12px;\n color: var(--text-secondary, #6b7280);\n}\n\n.key-hash[_ngcontent-%COMP%] {\n font-family: monospace;\n background: var(--tag-background, #e5e7eb);\n padding: 2px 6px;\n border-radius: 4px;\n font-size: 11px;\n}\n\n.key-status[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: flex-end;\n gap: 4px;\n margin-left: 16px;\n}\n\n.last-used[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--text-secondary, #6b7280);\n}\n\n.expiration[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--text-tertiary, #9ca3af);\n}\n\n.expiration.expiring-soon[_ngcontent-%COMP%] {\n color: #f59e0b;\n font-weight: 500;\n}\n\n.expiration.expiring-critical[_ngcontent-%COMP%] {\n color: #ef4444;\n font-weight: 500;\n}\n\n.expiration.expired[_ngcontent-%COMP%] {\n color: #ef4444;\n font-weight: 600;\n}\n\n\n\n.scope-chart[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 24px;\n height: 100%;\n}\n\n.donut-chart-container[_ngcontent-%COMP%] {\n position: relative;\n width: 160px;\n height: 160px;\n margin: 0 auto;\n}\n\n.donut-chart[_ngcontent-%COMP%] {\n width: 100%;\n height: 100%;\n transform: rotate(-90deg);\n}\n\n.donut-segment[_ngcontent-%COMP%] {\n cursor: pointer;\n transition: opacity 0.2s ease;\n}\n\n.donut-segment[_ngcontent-%COMP%]:hover {\n opacity: 0.8;\n}\n\n.donut-center[_ngcontent-%COMP%] {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n text-align: center;\n}\n\n.donut-total[_ngcontent-%COMP%] {\n font-size: 28px;\n font-weight: 700;\n color: var(--text-primary, #1f2937);\n}\n\n.donut-label[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--text-secondary, #6b7280);\n}\n\n\n\n.scope-legend[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.legend-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 10px 12px;\n background: var(--item-background, #f9fafb);\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.legend-item[_ngcontent-%COMP%]:hover {\n background: var(--item-hover, #f3f4f6);\n transform: translateX(4px);\n}\n\n.legend-color[_ngcontent-%COMP%] {\n width: 12px;\n height: 12px;\n border-radius: 4px;\n margin-right: 12px;\n flex-shrink: 0;\n}\n\n.legend-info[_ngcontent-%COMP%] {\n flex: 1;\n}\n\n.legend-name[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 500;\n color: var(--text-primary, #1f2937);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.legend-name[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--text-secondary, #6b7280);\n}\n\n.legend-value[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--text-secondary, #6b7280);\n}\n\n.legend-arrow[_ngcontent-%COMP%] {\n color: var(--text-tertiary, #9ca3af);\n font-size: 10px;\n}\n\n\n\n.activity-list[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));\n gap: 12px;\n}\n\n.activity-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 12px 14px;\n background: var(--item-background, #f9fafb);\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.activity-item[_ngcontent-%COMP%]:hover {\n background: var(--item-hover, #f3f4f6);\n}\n\n.activity-icon[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--icon-background, #fef3c7);\n border-radius: 6px;\n margin-right: 12px;\n flex-shrink: 0;\n}\n\n.activity-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n color: #f59e0b;\n}\n\n.activity-icon.action-created[_ngcontent-%COMP%] {\n background: #d1fae5;\n}\n\n.activity-icon.action-created[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #059669;\n}\n\n.activity-icon.action-updated[_ngcontent-%COMP%] {\n background: #e0e7ff;\n}\n\n.activity-icon.action-updated[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #6366f1;\n}\n\n.activity-icon.action-revoked[_ngcontent-%COMP%] {\n background: #fee2e2;\n}\n\n.activity-icon.action-revoked[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #dc2626;\n}\n\n.activity-icon.action-used[_ngcontent-%COMP%] {\n background: #fef3c7;\n}\n\n.activity-icon.action-used[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #d97706;\n}\n\n.activity-icon.action-extended[_ngcontent-%COMP%] {\n background: #dbeafe;\n}\n\n.activity-icon.action-extended[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #3b82f6;\n}\n\n.activity-info[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.activity-name[_ngcontent-%COMP%] {\n font-weight: 500;\n font-size: 13px;\n color: var(--text-primary, #1f2937);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.activity-meta[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n margin-top: 2px;\n font-size: 11px;\n color: var(--text-secondary, #6b7280);\n}\n\n.activity-action[_ngcontent-%COMP%] {\n font-weight: 500;\n text-transform: capitalize;\n}\n\n.activity-time[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--text-tertiary, #9ca3af);\n white-space: nowrap;\n}\n\n\n\n.quick-actions[_ngcontent-%COMP%] {\n margin-bottom: 24px;\n}\n\n.quick-actions-title[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: var(--text-primary, #1f2937);\n margin-bottom: 12px;\n}\n\n.quick-actions-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));\n gap: 12px;\n}\n\n.quick-action[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n padding: 16px;\n background: var(--card-background, #ffffff);\n border: 1px solid var(--border-color, #e5e7eb);\n border-radius: 10px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.quick-action[_ngcontent-%COMP%]:hover {\n border-color: #f59e0b;\n background: #fffbeb;\n transform: translateY(-2px);\n}\n\n.quick-action[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 20px;\n color: #f59e0b;\n}\n\n.quick-action[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 500;\n color: var(--text-secondary, #6b7280);\n}\n\n\n\n.empty-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 32px;\n color: var(--text-secondary, #6b7280);\n text-align: center;\n}\n\n.empty-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 32px;\n margin-bottom: 12px;\n opacity: 0.5;\n}\n\n\n\n.security-notice[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n padding: 16px 20px;\n background: linear-gradient(135deg, #fffbeb 0%, #fef3c7 100%);\n border-radius: 12px;\n border: 1px solid #fcd34d;\n}\n\n.security-notice[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 20px;\n color: #f59e0b;\n margin-right: 12px;\n margin-top: 2px;\n}\n\n.notice-content[_ngcontent-%COMP%] {\n font-size: 13px;\n color: #92400e;\n line-height: 1.5;\n}\n\n.notice-content[_ngcontent-%COMP%] strong[_ngcontent-%COMP%] {\n font-weight: 600;\n}\n\n\n\n.mobile-nav-toggle[_ngcontent-%COMP%] {\n display: none;\n position: fixed;\n bottom: 20px;\n right: 20px;\n width: 56px;\n height: 56px;\n background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);\n border: none;\n border-radius: 50%;\n color: white;\n font-size: 24px;\n box-shadow: 0 4px 16px rgba(245, 158, 11, 0.4);\n cursor: pointer;\n z-index: 50;\n transition: transform 0.2s ease;\n}\n\n.mobile-nav-toggle[_ngcontent-%COMP%]:hover {\n transform: scale(1.05);\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: 90;\n}\n\n\n\n\n\n\n\n\n@media (max-width: 1024px) {\n .content-grid[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n\n .activity-panel[_ngcontent-%COMP%] {\n grid-column: span 1;\n }\n\n .scope-chart[_ngcontent-%COMP%] {\n flex-direction: row;\n align-items: center;\n }\n\n .donut-chart-container[_ngcontent-%COMP%] {\n width: 140px;\n height: 140px;\n }\n\n .scope-legend[_ngcontent-%COMP%] {\n flex: 1;\n }\n\n .dashboard-nav[_ngcontent-%COMP%] {\n width: 200px;\n }\n}\n\n\n\n@media (max-width: 768px) {\n .api-keys-dashboard[_ngcontent-%COMP%] {\n flex-direction: column;\n }\n\n .dashboard-nav[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n left: -280px;\n width: 280px;\n height: 100%;\n z-index: 100;\n transition: left 0.3s ease;\n box-shadow: 4px 0 20px rgba(0, 0, 0, 0.15);\n }\n\n .api-keys-dashboard.nav-open[_ngcontent-%COMP%] .dashboard-nav[_ngcontent-%COMP%] {\n left: 0;\n }\n\n .mobile-nav-toggle[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .mobile-nav-overlay[_ngcontent-%COMP%] {\n display: block;\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.3s ease;\n }\n\n .api-keys-dashboard.nav-open[_ngcontent-%COMP%] .mobile-nav-overlay[_ngcontent-%COMP%] {\n opacity: 1;\n pointer-events: auto;\n }\n\n .dashboard-content[_ngcontent-%COMP%] {\n width: 100%;\n }\n\n .content-wrapper[_ngcontent-%COMP%] {\n padding: 16px;\n }\n\n .overview-header[_ngcontent-%COMP%] {\n flex-direction: column;\n gap: 16px;\n }\n\n .header-actions[_ngcontent-%COMP%] {\n width: 100%;\n justify-content: flex-end;\n }\n\n .health-banner[_ngcontent-%COMP%] {\n flex-direction: column;\n text-align: center;\n }\n\n .health-score-container[_ngcontent-%COMP%] {\n margin-right: 0;\n margin-bottom: 16px;\n }\n\n .kpi-row[_ngcontent-%COMP%] {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .scope-chart[_ngcontent-%COMP%] {\n flex-direction: column;\n }\n\n .quick-actions-grid[_ngcontent-%COMP%] {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .activity-list[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n\n .key-item[_ngcontent-%COMP%] {\n flex-wrap: wrap;\n }\n\n .key-status[_ngcontent-%COMP%] {\n width: 100%;\n flex-direction: row;\n justify-content: flex-start;\n margin-left: 54px;\n margin-top: 8px;\n gap: 12px;\n }\n}\n\n\n\n@media (max-width: 480px) {\n .kpi-row[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n\n .quick-actions-grid[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n\n .kpi-card[_ngcontent-%COMP%] {\n padding: 12px 16px;\n }\n\n .kpi-icon[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n }\n\n .kpi-value[_ngcontent-%COMP%] {\n font-size: 20px;\n }\n\n .overview-title[_ngcontent-%COMP%] {\n font-size: 20px;\n }\n\n .btn-primary[_ngcontent-%COMP%] {\n padding: 8px 16px;\n font-size: 13px;\n }\n}"] });
1128
+ } }, dependencies: [i1.NgClass, i2.LoadingComponent, i3.APIKeyCreateDialogComponent, i4.APIKeyEditPanelComponent, i5.APIKeyListComponent, i6.APIApplicationsPanelComponent, i7.APIScopesPanelComponent, i8.APIUsagePanelComponent], styles: ["\n\n.api-keys-dashboard[_ngcontent-%COMP%] {\n display: flex;\n height: 100%;\n position: relative;\n overflow: hidden;\n}\n\n.api-keys-dashboard.panel-open[_ngcontent-%COMP%] .dashboard-content[_ngcontent-%COMP%] {\n overflow: hidden;\n}\n\n\n\n.dashboard-nav[_ngcontent-%COMP%] {\n width: 220px;\n background: var(--mj-bg-surface);\n border-right: 1px solid var(--mj-border-default);\n display: flex;\n flex-direction: column;\n flex-shrink: 0;\n}\n\n.nav-header[_ngcontent-%COMP%] {\n padding: 20px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.nav-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n font-weight: 700;\n font-size: 16px;\n color: var(--mj-text-primary);\n}\n\n.nav-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n font-size: 18px;\n}\n\n.nav-items[_ngcontent-%COMP%] {\n flex: 1;\n padding: 12px;\n overflow-y: auto;\n}\n\n.nav-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 16px;\n margin-bottom: 4px;\n background: transparent;\n border: none;\n border-radius: 8px;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n width: 100%;\n text-align: left;\n}\n\n.nav-item[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n.nav-item.active[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n box-shadow: var(--mj-shadow-brand-sm);\n}\n\n.nav-item[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 16px;\n width: 20px;\n text-align: center;\n}\n\n.nav-item[_ngcontent-%COMP%] .nav-label[_ngcontent-%COMP%] {\n flex: 1;\n}\n\n.nav-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 22px;\n height: 20px;\n padding: 0 6px;\n background: var(--mj-bg-surface-active);\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n}\n\n.nav-item.active[_ngcontent-%COMP%] .nav-badge[_ngcontent-%COMP%] {\n background: rgba(255, 255, 255, 0.25);\n}\n\n\n\n.dashboard-content[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow-y: auto;\n min-width: 0;\n}\n\n.content-wrapper[_ngcontent-%COMP%] {\n flex: 1;\n padding: 24px;\n overflow-y: auto;\n}\n\n\n\n.list-view-header[_ngcontent-%COMP%] {\n margin-bottom: 16px;\n}\n\n.back-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.back-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n\n\n.overview-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 24px;\n}\n\n.header-left[_ngcontent-%COMP%] {\n flex: 1;\n}\n\n.overview-title[_ngcontent-%COMP%] {\n font-size: 24px;\n font-weight: 700;\n color: var(--mj-text-primary);\n margin: 0 0 4px 0;\n}\n\n.overview-subtitle[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--mj-text-secondary);\n margin: 0;\n}\n\n.header-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n}\n\n.btn-refresh[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 40px;\n height: 40px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.btn-refresh[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.btn-refresh[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-text-secondary);\n}\n\n.btn-primary[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 20px;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border: none;\n border-radius: 8px;\n font-weight: 600;\n font-size: 14px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.btn-primary[_ngcontent-%COMP%]:hover {\n transform: translateY(-1px);\n box-shadow: var(--mj-shadow-brand-md);\n}\n\n\n\n.health-banner[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 20px 24px;\n background: var(--mj-status-success-bg);\n border: 1px solid var(--mj-status-success-border);\n border-radius: 16px;\n margin-bottom: 24px;\n}\n\n.health-banner.health-warning[_ngcontent-%COMP%] {\n background: var(--mj-status-warning-bg);\n border-color: var(--mj-color-accent-300);\n}\n\n.health-banner.health-critical[_ngcontent-%COMP%] {\n background: var(--mj-status-error-bg);\n border-color: var(--mj-status-error-border);\n}\n\n.health-score-container[_ngcontent-%COMP%] {\n margin-right: 24px;\n}\n\n.health-score-ring[_ngcontent-%COMP%] {\n position: relative;\n width: 80px;\n height: 80px;\n}\n\n.circular-chart[_ngcontent-%COMP%] {\n display: block;\n margin: 0 auto;\n max-height: 80px;\n transform: rotate(-90deg);\n}\n\n.circle-bg[_ngcontent-%COMP%] {\n fill: none;\n stroke: var(--mj-border-default);\n stroke-width: 3.8;\n}\n\n.circle[_ngcontent-%COMP%] {\n fill: none;\n stroke-width: 3.8;\n stroke-linecap: round;\n stroke: var(--mj-status-success);\n animation: _ngcontent-%COMP%_progress 1s ease-out forwards;\n}\n\n.health-banner.health-warning[_ngcontent-%COMP%] .circle[_ngcontent-%COMP%] {\n stroke: var(--mj-color-warning-500);\n}\n\n.health-banner.health-critical[_ngcontent-%COMP%] .circle[_ngcontent-%COMP%] {\n stroke: var(--mj-status-error);\n}\n\n@keyframes _ngcontent-%COMP%_progress {\n 0% {\n stroke-dasharray: 0 100;\n }\n}\n\n.health-score-value[_ngcontent-%COMP%] {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n font-size: 20px;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.health-info[_ngcontent-%COMP%] {\n flex: 1;\n}\n\n.health-label[_ngcontent-%COMP%] {\n font-size: 18px;\n font-weight: 700;\n color: var(--mj-color-success-600);\n margin-bottom: 4px;\n}\n\n.health-banner.health-warning[_ngcontent-%COMP%] .health-label[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary-hover);\n}\n\n.health-banner.health-critical[_ngcontent-%COMP%] .health-label[_ngcontent-%COMP%] {\n color: var(--mj-color-error-600);\n}\n\n.health-details[_ngcontent-%COMP%] {\n display: flex;\n gap: 16px;\n flex-wrap: wrap;\n}\n\n.health-alert[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n color: var(--mj-color-error-600);\n font-weight: 500;\n font-size: 14px;\n cursor: pointer;\n}\n\n.health-alert[_ngcontent-%COMP%]:hover {\n text-decoration: underline;\n}\n\n.health-warning-text[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n color: var(--mj-brand-primary-hover);\n font-weight: 500;\n font-size: 14px;\n cursor: pointer;\n}\n\n.health-warning-text[_ngcontent-%COMP%]:hover {\n text-decoration: underline;\n}\n\n.health-info-text[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n color: var(--mj-text-secondary);\n font-weight: 500;\n font-size: 14px;\n cursor: pointer;\n}\n\n.health-info-text[_ngcontent-%COMP%]:hover {\n text-decoration: underline;\n}\n\n.health-ok[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n color: var(--mj-color-success-600);\n font-weight: 500;\n font-size: 14px;\n}\n\n\n\n.kpi-row[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));\n gap: 16px;\n margin-bottom: 24px;\n}\n\n.kpi-card[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 16px 20px;\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-md);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.kpi-card.clickable[_ngcontent-%COMP%] {\n cursor: pointer;\n}\n\n.kpi-card.clickable[_ngcontent-%COMP%]:hover {\n transform: translateY(-2px);\n box-shadow: var(--mj-shadow-lg);\n}\n\n.kpi-card.active[_ngcontent-%COMP%] .kpi-icon[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, var(--mj-status-success) 0%, var(--mj-color-success-600) 100%);\n}\n\n.kpi-card.warning[_ngcontent-%COMP%] .kpi-icon[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, var(--mj-color-warning-500) 0%, var(--mj-brand-primary-hover) 100%);\n}\n\n.kpi-card.danger[_ngcontent-%COMP%] .kpi-icon[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, var(--mj-status-error) 0%, var(--mj-color-error-600) 100%);\n}\n\n.kpi-icon[_ngcontent-%COMP%] {\n width: 48px;\n height: 48px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--mj-brand-primary);\n border-radius: 10px;\n margin-right: 14px;\n flex-shrink: 0;\n}\n\n.kpi-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 20px;\n color: var(--mj-text-inverse);\n}\n\n.kpi-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.kpi-value[_ngcontent-%COMP%] {\n font-size: 24px;\n font-weight: 700;\n color: var(--mj-text-primary);\n line-height: 1.2;\n}\n\n.kpi-label[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-secondary);\n margin-top: 2px;\n white-space: nowrap;\n}\n\n.kpi-trend[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n margin-left: 8px;\n color: var(--mj-text-muted);\n}\n\n.kpi-trend.success[_ngcontent-%COMP%] {\n color: var(--mj-status-success);\n}\n\n.kpi-trend.warning[_ngcontent-%COMP%] {\n color: var(--mj-color-warning-500);\n}\n\n.kpi-trend[_ngcontent-%COMP%] .percentage[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 600;\n}\n\n\n\n.content-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 1fr 1fr;\n grid-template-rows: auto auto;\n gap: 20px;\n margin-bottom: 24px;\n}\n\n.keys-panel[_ngcontent-%COMP%] {\n grid-row: span 1;\n}\n\n.scope-panel[_ngcontent-%COMP%] {\n grid-row: span 1;\n}\n\n.activity-panel[_ngcontent-%COMP%] {\n grid-column: span 2;\n}\n\n.panel[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-md);\n overflow: hidden;\n display: flex;\n flex-direction: column;\n}\n\n.panel-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n background: var(--mj-bg-page);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.panel-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n font-weight: 600;\n font-size: 14px;\n color: var(--mj-text-primary);\n}\n\n.panel-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n.panel-subtitle[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.panel-action[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n background: transparent;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.panel-action[_ngcontent-%COMP%]:hover {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.panel-body[_ngcontent-%COMP%] {\n padding: 20px;\n flex: 1;\n overflow-y: auto;\n}\n\n\n\n.key-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.key-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 14px 16px;\n background: var(--mj-bg-page);\n border-radius: 10px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.key-item[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n transform: translateX(4px);\n}\n\n.key-icon[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: linear-gradient(135deg, var(--mj-color-neutral-500) 0%, var(--mj-color-neutral-600) 100%);\n border-radius: 8px;\n margin-right: 14px;\n flex-shrink: 0;\n}\n\n.key-icon.active[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n}\n\n.key-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 16px;\n color: var(--mj-text-inverse);\n}\n\n.key-info[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.key-label[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.key-meta[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-top: 2px;\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.key-hash[_ngcontent-%COMP%] {\n font-family: monospace;\n background: var(--mj-bg-surface-active);\n padding: 2px 6px;\n border-radius: 4px;\n font-size: 11px;\n}\n\n.key-status[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: flex-end;\n gap: 4px;\n margin-left: 16px;\n}\n\n.last-used[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.expiration[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n\n.expiration.expiring-soon[_ngcontent-%COMP%] {\n color: var(--mj-color-warning-500);\n font-weight: 500;\n}\n\n.expiration.expiring-critical[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n font-weight: 500;\n}\n\n.expiration.expired[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n font-weight: 600;\n}\n\n\n\n.scope-chart[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 24px;\n height: 100%;\n}\n\n.donut-chart-container[_ngcontent-%COMP%] {\n position: relative;\n width: 160px;\n height: 160px;\n margin: 0 auto;\n}\n\n.donut-chart[_ngcontent-%COMP%] {\n width: 100%;\n height: 100%;\n transform: rotate(-90deg);\n}\n\n.donut-segment[_ngcontent-%COMP%] {\n cursor: pointer;\n transition: opacity 0.2s ease;\n}\n\n.donut-segment[_ngcontent-%COMP%]:hover {\n opacity: 0.8;\n}\n\n.donut-center[_ngcontent-%COMP%] {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n text-align: center;\n}\n\n.donut-total[_ngcontent-%COMP%] {\n font-size: 28px;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.donut-label[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--mj-text-secondary);\n}\n\n\n\n.scope-legend[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.legend-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 10px 12px;\n background: var(--mj-bg-page);\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.legend-item[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n transform: translateX(4px);\n}\n\n.legend-color[_ngcontent-%COMP%] {\n width: 12px;\n height: 12px;\n border-radius: 4px;\n margin-right: 12px;\n flex-shrink: 0;\n}\n\n.legend-info[_ngcontent-%COMP%] {\n flex: 1;\n}\n\n.legend-name[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.legend-name[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.legend-value[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.legend-arrow[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-size: 10px;\n}\n\n\n\n.activity-list[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));\n gap: 12px;\n}\n\n.activity-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 12px 14px;\n background: var(--mj-bg-page);\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.activity-item[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.activity-icon[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--icon-background, var(--mj-color-brand-100));\n border-radius: 6px;\n margin-right: 12px;\n flex-shrink: 0;\n}\n\n.activity-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-brand-primary);\n}\n\n.activity-icon.action-created[_ngcontent-%COMP%] {\n background: var(--mj-color-success-100);\n}\n\n.activity-icon.action-created[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-color-success-600);\n}\n\n.activity-icon.action-updated[_ngcontent-%COMP%] {\n background: var(--mj-color-indigo-100);\n}\n\n.activity-icon.action-updated[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-color-indigo-500);\n}\n\n.activity-icon.action-revoked[_ngcontent-%COMP%] {\n background: var(--mj-color-error-100);\n}\n\n.activity-icon.action-revoked[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-color-error-600);\n}\n\n.activity-icon.action-used[_ngcontent-%COMP%] {\n background: var(--mj-color-brand-100);\n}\n\n.activity-icon.action-used[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary-hover);\n}\n\n.activity-icon.action-extended[_ngcontent-%COMP%] {\n background: var(--mj-color-info-100);\n}\n\n.activity-icon.action-extended[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-status-info);\n}\n\n.activity-info[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.activity-name[_ngcontent-%COMP%] {\n font-weight: 500;\n font-size: 13px;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.activity-meta[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n margin-top: 2px;\n font-size: 11px;\n color: var(--mj-text-secondary);\n}\n\n.activity-action[_ngcontent-%COMP%] {\n font-weight: 500;\n text-transform: capitalize;\n}\n\n.activity-time[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--mj-text-muted);\n white-space: nowrap;\n}\n\n\n\n.quick-actions[_ngcontent-%COMP%] {\n margin-bottom: 24px;\n}\n\n.quick-actions-title[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin-bottom: 12px;\n}\n\n.quick-actions-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));\n gap: 12px;\n}\n\n.quick-action[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n padding: 16px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.quick-action[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-brand-primary);\n background: var(--mj-color-brand-50);\n transform: translateY(-2px);\n}\n\n.quick-action[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 20px;\n color: var(--mj-brand-primary);\n}\n\n.quick-action[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n\n\n.empty-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 32px;\n color: var(--mj-text-secondary);\n text-align: center;\n}\n\n.empty-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 32px;\n margin-bottom: 12px;\n opacity: 0.5;\n}\n\n\n\n.security-notice[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n padding: 16px 20px;\n background: linear-gradient(135deg, var(--mj-color-brand-50) 0%, var(--mj-color-brand-100) 100%);\n border-radius: 12px;\n border: 1px solid var(--mj-color-accent-300);\n}\n\n.security-notice[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 20px;\n color: var(--mj-brand-primary);\n margin-right: 12px;\n margin-top: 2px;\n}\n\n.notice-content[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-color-brand-800);\n line-height: 1.5;\n}\n\n.notice-content[_ngcontent-%COMP%] strong[_ngcontent-%COMP%] {\n font-weight: 600;\n}\n\n\n\n.mobile-nav-toggle[_ngcontent-%COMP%] {\n display: none;\n position: fixed;\n bottom: 20px;\n right: 20px;\n width: 56px;\n height: 56px;\n background: var(--mj-brand-primary);\n border: none;\n border-radius: 50%;\n color: var(--mj-text-inverse);\n font-size: 24px;\n box-shadow: var(--mj-shadow-brand-md);\n cursor: pointer;\n z-index: 50;\n transition: transform 0.2s ease;\n}\n\n.mobile-nav-toggle[_ngcontent-%COMP%]:hover {\n transform: scale(1.05);\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: var(--mj-bg-overlay);\n z-index: 90;\n}\n\n\n\n\n\n\n\n\n@media (max-width: 1024px) {\n .content-grid[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n\n .activity-panel[_ngcontent-%COMP%] {\n grid-column: span 1;\n }\n\n .scope-chart[_ngcontent-%COMP%] {\n flex-direction: row;\n align-items: center;\n }\n\n .donut-chart-container[_ngcontent-%COMP%] {\n width: 140px;\n height: 140px;\n }\n\n .scope-legend[_ngcontent-%COMP%] {\n flex: 1;\n }\n\n .dashboard-nav[_ngcontent-%COMP%] {\n width: 200px;\n }\n}\n\n\n\n@media (max-width: 768px) {\n .api-keys-dashboard[_ngcontent-%COMP%] {\n flex-direction: column;\n }\n\n .dashboard-nav[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n left: -280px;\n width: 280px;\n height: 100%;\n z-index: 100;\n transition: left 0.3s ease;\n box-shadow: var(--mj-shadow-xl);\n }\n\n .api-keys-dashboard.nav-open[_ngcontent-%COMP%] .dashboard-nav[_ngcontent-%COMP%] {\n left: 0;\n }\n\n .mobile-nav-toggle[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .mobile-nav-overlay[_ngcontent-%COMP%] {\n display: block;\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.3s ease;\n }\n\n .api-keys-dashboard.nav-open[_ngcontent-%COMP%] .mobile-nav-overlay[_ngcontent-%COMP%] {\n opacity: 1;\n pointer-events: auto;\n }\n\n .dashboard-content[_ngcontent-%COMP%] {\n width: 100%;\n }\n\n .content-wrapper[_ngcontent-%COMP%] {\n padding: 16px;\n }\n\n .overview-header[_ngcontent-%COMP%] {\n flex-direction: column;\n gap: 16px;\n }\n\n .header-actions[_ngcontent-%COMP%] {\n width: 100%;\n justify-content: flex-end;\n }\n\n .health-banner[_ngcontent-%COMP%] {\n flex-direction: column;\n text-align: center;\n }\n\n .health-score-container[_ngcontent-%COMP%] {\n margin-right: 0;\n margin-bottom: 16px;\n }\n\n .kpi-row[_ngcontent-%COMP%] {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .scope-chart[_ngcontent-%COMP%] {\n flex-direction: column;\n }\n\n .quick-actions-grid[_ngcontent-%COMP%] {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .activity-list[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n\n .key-item[_ngcontent-%COMP%] {\n flex-wrap: wrap;\n }\n\n .key-status[_ngcontent-%COMP%] {\n width: 100%;\n flex-direction: row;\n justify-content: flex-start;\n margin-left: 54px;\n margin-top: 8px;\n gap: 12px;\n }\n}\n\n\n\n@media (max-width: 480px) {\n .kpi-row[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n\n .quick-actions-grid[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n\n .kpi-card[_ngcontent-%COMP%] {\n padding: 12px 16px;\n }\n\n .kpi-icon[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n }\n\n .kpi-value[_ngcontent-%COMP%] {\n font-size: 20px;\n }\n\n .overview-title[_ngcontent-%COMP%] {\n font-size: 20px;\n }\n\n .btn-primary[_ngcontent-%COMP%] {\n padding: 8px 16px;\n font-size: 13px;\n }\n}"] });
1129
1129
  };
1130
1130
  APIKeysResourceComponent = __decorate([
1131
1131
  RegisterClass(BaseResourceComponent, 'APIKeysResource')
@@ -1133,7 +1133,7 @@ APIKeysResourceComponent = __decorate([
1133
1133
  export { APIKeysResourceComponent };
1134
1134
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(APIKeysResourceComponent, [{
1135
1135
  type: Component,
1136
- args: [{ standalone: false, selector: 'mj-api-keys-resource', template: "<div class=\"api-keys-dashboard\" [class.panel-open]=\"ShowCreateDialog || ShowEditPanel\" [class.nav-open]=\"NavOpen\">\n @if (IsLoading) {\n <mj-loading text=\"Loading API Keys...\"></mj-loading>\n }\n\n @if (!IsLoading) {\n <!-- Left Navigation Sidebar -->\n <div class=\"dashboard-nav\">\n <div class=\"nav-header\">\n <div class=\"nav-title\">\n <i class=\"fa-solid fa-key\"></i>\n <span>API Keys</span>\n </div>\n </div>\n <div class=\"nav-items\">\n <button class=\"nav-item\" [class.active]=\"MainTab === 'keys'\" (click)=\"switchTab('keys'); closeNav()\">\n <i class=\"fa-solid fa-key\"></i>\n <span class=\"nav-label\">API Keys</span>\n <span class=\"nav-badge\">{{TotalKeys}}</span>\n </button>\n <button class=\"nav-item\" [class.active]=\"MainTab === 'applications'\" (click)=\"switchTab('applications'); closeNav()\">\n <i class=\"fa-solid fa-cube\"></i>\n <span class=\"nav-label\">Applications</span>\n <span class=\"nav-badge\">{{ApplicationCount}}</span>\n </button>\n <button class=\"nav-item\" [class.active]=\"MainTab === 'scopes'\" (click)=\"switchTab('scopes'); closeNav()\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <span class=\"nav-label\">Scopes</span>\n <span class=\"nav-badge\">{{ScopeCount}}</span>\n </button>\n <button class=\"nav-item\" [class.active]=\"MainTab === 'usage'\" (click)=\"switchTab('usage'); closeNav()\">\n <i class=\"fa-solid fa-chart-line\"></i>\n <span class=\"nav-label\">Usage Analytics</span>\n </button>\n </div>\n </div>\n <!-- Main Content Area -->\n <div class=\"dashboard-content\">\n <div class=\"content-wrapper\">\n <!-- Keys Tab Content -->\n @if (MainTab === 'keys') {\n <!-- Overview View -->\n @if (CurrentView === 'overview') {\n <!-- Header with Actions -->\n <div class=\"overview-header\">\n <div class=\"header-left\">\n <h2 class=\"overview-title\">API Keys Management</h2>\n <p class=\"overview-subtitle\">Manage API keys for external integrations and services</p>\n </div>\n <div class=\"header-actions\">\n <button class=\"btn-refresh\" (click)=\"refresh()\" title=\"Refresh\">\n <i class=\"fa-solid fa-refresh\"></i>\n </button>\n @if (UserCanCreateKeys) {\n <button class=\"btn-primary\" (click)=\"openCreateDialog()\">\n <i class=\"fa-solid fa-plus\"></i>\n <span>Generate New Key</span>\n </button>\n }\n </div>\n </div>\n <!-- Health Score Banner -->\n <div class=\"health-banner\" [ngClass]=\"getHealthClass()\">\n <div class=\"health-score-container\">\n <div class=\"health-score-ring\">\n <svg viewBox=\"0 0 36 36\" class=\"circular-chart\">\n <path class=\"circle-bg\"\n d=\"M18 2.0845\n a 15.9155 15.9155 0 0 1 0 31.831\n a 15.9155 15.9155 0 0 1 0 -31.831\"\n />\n <path class=\"circle\"\n [attr.stroke-dasharray]=\"getHealthScore() + ', 100'\"\n d=\"M18 2.0845\n a 15.9155 15.9155 0 0 1 0 31.831\n a 15.9155 15.9155 0 0 1 0 -31.831\"\n />\n </svg>\n <div class=\"health-score-value\">{{getHealthScore()}}</div>\n </div>\n </div>\n <div class=\"health-info\">\n <div class=\"health-label\">{{getHealthLabel()}}</div>\n <div class=\"health-details\">\n @if (ExpiredKeys > 0) {\n <span class=\"health-alert\" (click)=\"showListView('expired')\">\n <i class=\"fa-solid fa-circle-exclamation\"></i>\n {{ExpiredKeys}} expired\n </span>\n }\n @if (ExpiringSoonCount > 0) {\n <span class=\"health-warning-text\" (click)=\"showListView('expiring')\">\n <i class=\"fa-solid fa-clock\"></i>\n {{ExpiringSoonCount}} expiring soon\n </span>\n }\n @if (NeverUsedKeys > 0) {\n <span class=\"health-info-text\" (click)=\"showListView('never-used')\">\n <i class=\"fa-solid fa-question-circle\"></i>\n {{NeverUsedKeys}} never used\n </span>\n }\n @if (ExpiredKeys === 0 && ExpiringSoonCount === 0 && NeverUsedKeys === 0) {\n <span class=\"health-ok\">\n <i class=\"fa-solid fa-check-circle\"></i>\n All keys healthy\n </span>\n }\n </div>\n </div>\n </div>\n <!-- KPI Cards Row -->\n <div class=\"kpi-row\">\n <div class=\"kpi-card clickable\" (click)=\"showListView('all')\">\n <div class=\"kpi-icon\">\n <i class=\"fa-solid fa-key\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{TotalKeys}}</div>\n <div class=\"kpi-label\">Total Keys</div>\n </div>\n <div class=\"kpi-trend\">\n <i class=\"fa-solid fa-arrow-right\"></i>\n </div>\n </div>\n <div class=\"kpi-card active clickable\" (click)=\"showListView('active')\">\n <div class=\"kpi-icon\">\n <i class=\"fa-solid fa-check-circle\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ActiveKeys}}</div>\n <div class=\"kpi-label\">Active</div>\n </div>\n <div class=\"kpi-trend success\">\n <span class=\"percentage\">{{TotalKeys > 0 ? (ActiveKeys / TotalKeys * 100).toFixed(0) : 100}}%</span>\n </div>\n </div>\n <div class=\"kpi-card clickable\" [class.warning]=\"ExpiringSoonCount > 0\" (click)=\"showListView('expiring')\">\n <div class=\"kpi-icon\">\n <i class=\"fa-solid fa-clock\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ExpiringSoonCount}}</div>\n <div class=\"kpi-label\">Expiring Soon</div>\n </div>\n @if (ExpiringSoonCount > 0) {\n <div class=\"kpi-trend warning\">\n <i class=\"fa-solid fa-arrow-right\"></i>\n </div>\n }\n </div>\n <div class=\"kpi-card clickable\" [class.danger]=\"RevokedKeys > 0\" (click)=\"showListView('revoked')\">\n <div class=\"kpi-icon\">\n <i class=\"fa-solid fa-ban\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{RevokedKeys}}</div>\n <div class=\"kpi-label\">Revoked</div>\n </div>\n </div>\n <div class=\"kpi-card clickable\" (click)=\"switchTab('scopes')\">\n <div class=\"kpi-icon\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ScopeStats.length}}</div>\n <div class=\"kpi-label\">Scope Categories</div>\n </div>\n </div>\n </div>\n <!-- Content Grid -->\n <div class=\"content-grid\">\n <!-- Recently Used Keys -->\n <div class=\"panel keys-panel\">\n <div class=\"panel-header\">\n <div class=\"panel-title\">\n <i class=\"fa-solid fa-key\"></i>\n <span>Recently Used Keys</span>\n </div>\n <button class=\"panel-action\" (click)=\"showListView('all')\">\n View All <i class=\"fa-solid fa-arrow-right\"></i>\n </button>\n </div>\n <div class=\"panel-body\">\n @if (TopUsedKeys.length > 0) {\n <div class=\"key-list\">\n @for (key of TopUsedKeys; track key) {\n <div class=\"key-item\" (click)=\"openEditPanel(key)\">\n <div class=\"key-icon\" [class.active]=\"key.Status === 'Active'\">\n <i class=\"fa-solid fa-key\"></i>\n </div>\n <div class=\"key-info\">\n <div class=\"key-label\">{{key.Label}}</div>\n <div class=\"key-meta\">\n <span class=\"key-user\">{{key.User}}</span>\n <span class=\"key-hash\">...{{key.Hash.slice(-8)}}</span>\n </div>\n </div>\n <div class=\"key-status\">\n <div class=\"last-used\">{{formatDate(key.LastUsedAt)}}</div>\n <div class=\"expiration\" [ngClass]=\"getExpirationClass(key)\">\n {{formatExpiration(key.ExpiresAt)}}\n </div>\n </div>\n </div>\n }\n </div>\n }\n @if (TopUsedKeys.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-key\"></i>\n <span>No active keys with recent usage</span>\n </div>\n }\n </div>\n </div>\n <!-- Scope Categories -->\n <div class=\"panel scope-panel\">\n <div class=\"panel-header\">\n <div class=\"panel-title\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <span>Permission Scopes</span>\n </div>\n <span class=\"panel-subtitle\">Available scope categories</span>\n </div>\n <div class=\"panel-body\">\n @if (ScopeStats.length > 0) {\n <div class=\"scope-chart\">\n <!-- Visual Donut Chart -->\n <div class=\"donut-chart-container\">\n <svg viewBox=\"0 0 100 100\" class=\"donut-chart\">\n <circle cx=\"50\" cy=\"50\" r=\"40\" fill=\"none\" stroke=\"#e5e7eb\" stroke-width=\"12\"/>\n @for (stat of ScopeStats; track stat; let i = $index) {\n <ng-container>\n <circle\n cx=\"50\" cy=\"50\" r=\"40\"\n fill=\"none\"\n [attr.stroke]=\"stat.color\"\n stroke-width=\"12\"\n [attr.stroke-dasharray]=\"stat.percentage * 2.51 + ' ' + (251 - stat.percentage * 2.51)\"\n [attr.stroke-dashoffset]=\"getDonutOffset(i)\"\n class=\"donut-segment\"\n (click)=\"onScopeClick(stat)\"\n />\n </ng-container>\n }\n </svg>\n <div class=\"donut-center\">\n <div class=\"donut-total\">{{ScopeStats.length}}</div>\n <div class=\"donut-label\">Categories</div>\n </div>\n </div>\n <!-- Legend -->\n <div class=\"scope-legend\">\n @for (stat of ScopeStats; track stat) {\n <div class=\"legend-item\" (click)=\"onScopeClick(stat)\">\n <div class=\"legend-color\" [style.backgroundColor]=\"stat.color\"></div>\n <div class=\"legend-info\">\n <div class=\"legend-name\">\n <i [class]=\"stat.iconClass\"></i>\n {{stat.category}}\n </div>\n <div class=\"legend-value\">{{stat.count}} scopes</div>\n </div>\n <i class=\"fa-solid fa-chevron-right legend-arrow\"></i>\n </div>\n }\n </div>\n </div>\n }\n @if (ScopeStats.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <span>No scopes configured</span>\n </div>\n }\n </div>\n </div>\n <!-- Recent Activity -->\n <div class=\"panel activity-panel\">\n <div class=\"panel-header\">\n <div class=\"panel-title\">\n <i class=\"fa-solid fa-clock-rotate-left\"></i>\n <span>Recent Activity</span>\n </div>\n </div>\n <div class=\"panel-body\">\n @if (RecentActivity.length > 0) {\n <div class=\"activity-list\">\n @for (activity of RecentActivity; track activity) {\n <div class=\"activity-item\" (click)=\"onActivityClick(activity)\">\n <div class=\"activity-icon\" [ngClass]=\"getActionClass(activity.action)\">\n <i [class]=\"getActionIcon(activity.action)\"></i>\n </div>\n <div class=\"activity-info\">\n <div class=\"activity-name\">{{activity.keyLabel}}</div>\n <div class=\"activity-meta\">\n <span class=\"activity-action\">{{activity.action}}</span>\n @if (activity.user) {\n <span class=\"activity-user\">by {{activity.user}}</span>\n }\n </div>\n </div>\n <div class=\"activity-time\">\n {{formatDate(activity.date)}}\n </div>\n </div>\n }\n </div>\n }\n @if (RecentActivity.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-inbox\"></i>\n <span>No recent activity</span>\n </div>\n }\n </div>\n </div>\n </div>\n <!-- Quick Actions -->\n @if (UserCanCreateKeys) {\n <div class=\"quick-actions\">\n <div class=\"quick-actions-title\">Quick Actions</div>\n <div class=\"quick-actions-grid\">\n <button class=\"quick-action\" (click)=\"openCreateDialog()\">\n <i class=\"fa-solid fa-plus\"></i>\n <span>Generate Key</span>\n </button>\n <button class=\"quick-action\" (click)=\"showListView('all')\">\n <i class=\"fa-solid fa-list\"></i>\n <span>View All Keys</span>\n </button>\n <button class=\"quick-action\" (click)=\"showListView('expiring')\">\n <i class=\"fa-solid fa-clock\"></i>\n <span>Expiring Keys</span>\n </button>\n <button class=\"quick-action\" (click)=\"showListView('never-used')\">\n <i class=\"fa-solid fa-question-circle\"></i>\n <span>Never Used</span>\n </button>\n </div>\n </div>\n }\n <!-- Security Notice -->\n <div class=\"security-notice\">\n <i class=\"fa-solid fa-shield-check\"></i>\n <div class=\"notice-content\">\n <strong>Security Best Practices:</strong>\n API keys should be rotated regularly and revoked when no longer needed.\n Keys are hashed and stored securely - the raw key is only shown once at creation time.\n All API key usage is logged for audit purposes.\n </div>\n </div>\n }\n <!-- List View -->\n @if (CurrentView === 'list') {\n <div class=\"list-view-header\">\n <button class=\"back-btn\" (click)=\"showOverview()\">\n <i class=\"fa-solid fa-arrow-left\"></i>\n Back to Overview\n </button>\n </div>\n <mj-api-key-list #keyList\n [Filter]=\"ListFilter\"\n (KeySelected)=\"onKeySelected($event)\"\n (CreateRequested)=\"openCreateDialog()\">\n </mj-api-key-list>\n }\n }\n <!-- Applications Tab Content -->\n @if (MainTab === 'applications') {\n <mj-api-applications-panel\n (ApplicationUpdated)=\"onDataUpdated()\">\n </mj-api-applications-panel>\n }\n <!-- Scopes Tab Content -->\n @if (MainTab === 'scopes') {\n <mj-api-scopes-panel\n (ScopeUpdated)=\"onDataUpdated()\">\n </mj-api-scopes-panel>\n }\n <!-- Usage Tab Content -->\n @if (MainTab === 'usage') {\n <mj-api-usage-panel></mj-api-usage-panel>\n }\n </div><!-- /.content-wrapper -->\n </div><!-- /.dashboard-content -->\n <!-- Mobile Navigation Toggle -->\n <button class=\"mobile-nav-toggle\" (click)=\"toggleNav()\">\n <i class=\"fa-solid\" [class.fa-bars]=\"!NavOpen\" [class.fa-times]=\"NavOpen\"></i>\n </button>\n <!-- Mobile Navigation Overlay -->\n <div class=\"mobile-nav-overlay\" (click)=\"closeNav()\"></div>\n }\n\n <!-- Create Dialog -->\n <mj-api-key-create-dialog\n [Visible]=\"ShowCreateDialog\"\n (Created)=\"onKeyCreated($event)\"\n (Closed)=\"onCreateDialogClosed()\">\n </mj-api-key-create-dialog>\n\n <!-- Edit Panel -->\n <mj-api-key-edit-panel\n [Visible]=\"ShowEditPanel\"\n [KeyId]=\"SelectedKeyId\"\n (Updated)=\"onKeyUpdated()\"\n (Revoked)=\"onKeyRevoked()\"\n (Closed)=\"onEditPanelClosed()\">\n </mj-api-key-edit-panel>\n</div>\n", styles: ["/* Main Dashboard Container */\n.api-keys-dashboard {\n display: flex;\n height: 100%;\n position: relative;\n overflow: hidden;\n}\n\n.api-keys-dashboard.panel-open .dashboard-content {\n overflow: hidden;\n}\n\n/* Left Navigation Sidebar */\n.dashboard-nav {\n width: 220px;\n background: var(--card-background, #ffffff);\n border-right: 1px solid var(--border-color, #e5e7eb);\n display: flex;\n flex-direction: column;\n flex-shrink: 0;\n}\n\n.nav-header {\n padding: 20px;\n border-bottom: 1px solid var(--border-color, #e5e7eb);\n}\n\n.nav-title {\n display: flex;\n align-items: center;\n gap: 10px;\n font-weight: 700;\n font-size: 16px;\n color: var(--text-primary, #1f2937);\n}\n\n.nav-title i {\n color: #f59e0b;\n font-size: 18px;\n}\n\n.nav-items {\n flex: 1;\n padding: 12px;\n overflow-y: auto;\n}\n\n.nav-item {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 16px;\n margin-bottom: 4px;\n background: transparent;\n border: none;\n border-radius: 8px;\n font-size: 14px;\n font-weight: 500;\n color: var(--text-secondary, #6b7280);\n cursor: pointer;\n transition: all 0.2s ease;\n width: 100%;\n text-align: left;\n}\n\n.nav-item:hover {\n background: var(--item-hover, #f3f4f6);\n color: var(--text-primary, #1f2937);\n}\n\n.nav-item.active {\n background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);\n color: white;\n box-shadow: 0 2px 8px rgba(245, 158, 11, 0.3);\n}\n\n.nav-item i {\n font-size: 16px;\n width: 20px;\n text-align: center;\n}\n\n.nav-item .nav-label {\n flex: 1;\n}\n\n.nav-badge {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 22px;\n height: 20px;\n padding: 0 6px;\n background: rgba(0, 0, 0, 0.1);\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n}\n\n.nav-item.active .nav-badge {\n background: rgba(255, 255, 255, 0.25);\n}\n\n/* Dashboard Content Area */\n.dashboard-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow-y: auto;\n min-width: 0;\n}\n\n.content-wrapper {\n flex: 1;\n padding: 24px;\n overflow-y: auto;\n}\n\n/* List View Header */\n.list-view-header {\n margin-bottom: 16px;\n}\n\n.back-btn {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n background: var(--card-background, #ffffff);\n border: 1px solid var(--border-color, #e5e7eb);\n border-radius: 8px;\n font-size: 14px;\n font-weight: 500;\n color: var(--text-secondary, #6b7280);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.back-btn:hover {\n background: var(--item-hover, #f3f4f6);\n color: var(--text-primary, #1f2937);\n}\n\n/* Header */\n.overview-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 24px;\n}\n\n.header-left {\n flex: 1;\n}\n\n.overview-title {\n font-size: 24px;\n font-weight: 700;\n color: var(--text-primary, #1f2937);\n margin: 0 0 4px 0;\n}\n\n.overview-subtitle {\n font-size: 14px;\n color: var(--text-secondary, #6b7280);\n margin: 0;\n}\n\n.header-actions {\n display: flex;\n gap: 12px;\n}\n\n.btn-refresh {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 40px;\n height: 40px;\n background: var(--card-background, #ffffff);\n border: 1px solid var(--border-color, #e5e7eb);\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.btn-refresh:hover {\n background: var(--item-hover, #f3f4f6);\n}\n\n.btn-refresh i {\n color: var(--text-secondary, #6b7280);\n}\n\n.btn-primary {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 20px;\n background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);\n color: white;\n border: none;\n border-radius: 8px;\n font-weight: 600;\n font-size: 14px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.btn-primary:hover {\n transform: translateY(-1px);\n box-shadow: 0 4px 12px rgba(245, 158, 11, 0.4);\n}\n\n/* Health Banner */\n.health-banner {\n display: flex;\n align-items: center;\n padding: 20px 24px;\n background: linear-gradient(135deg, #ecfdf5 0%, #d1fae5 100%);\n border: 1px solid #a7f3d0;\n border-radius: 16px;\n margin-bottom: 24px;\n}\n\n.health-banner.health-warning {\n background: linear-gradient(135deg, #fffbeb 0%, #fef3c7 100%);\n border-color: #fcd34d;\n}\n\n.health-banner.health-critical {\n background: linear-gradient(135deg, #fef2f2 0%, #fee2e2 100%);\n border-color: #fca5a5;\n}\n\n.health-score-container {\n margin-right: 24px;\n}\n\n.health-score-ring {\n position: relative;\n width: 80px;\n height: 80px;\n}\n\n.circular-chart {\n display: block;\n margin: 0 auto;\n max-height: 80px;\n transform: rotate(-90deg);\n}\n\n.circle-bg {\n fill: none;\n stroke: #e5e7eb;\n stroke-width: 3.8;\n}\n\n.circle {\n fill: none;\n stroke-width: 3.8;\n stroke-linecap: round;\n stroke: #10b981;\n animation: progress 1s ease-out forwards;\n}\n\n.health-banner.health-warning .circle {\n stroke: #f59e0b;\n}\n\n.health-banner.health-critical .circle {\n stroke: #ef4444;\n}\n\n@keyframes progress {\n 0% {\n stroke-dasharray: 0 100;\n }\n}\n\n.health-score-value {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n font-size: 20px;\n font-weight: 700;\n color: var(--text-primary, #1f2937);\n}\n\n.health-info {\n flex: 1;\n}\n\n.health-label {\n font-size: 18px;\n font-weight: 700;\n color: #059669;\n margin-bottom: 4px;\n}\n\n.health-banner.health-warning .health-label {\n color: #d97706;\n}\n\n.health-banner.health-critical .health-label {\n color: #dc2626;\n}\n\n.health-details {\n display: flex;\n gap: 16px;\n flex-wrap: wrap;\n}\n\n.health-alert {\n display: flex;\n align-items: center;\n gap: 6px;\n color: #dc2626;\n font-weight: 500;\n font-size: 14px;\n cursor: pointer;\n}\n\n.health-alert:hover {\n text-decoration: underline;\n}\n\n.health-warning-text {\n display: flex;\n align-items: center;\n gap: 6px;\n color: #d97706;\n font-weight: 500;\n font-size: 14px;\n cursor: pointer;\n}\n\n.health-warning-text:hover {\n text-decoration: underline;\n}\n\n.health-info-text {\n display: flex;\n align-items: center;\n gap: 6px;\n color: #6b7280;\n font-weight: 500;\n font-size: 14px;\n cursor: pointer;\n}\n\n.health-info-text:hover {\n text-decoration: underline;\n}\n\n.health-ok {\n display: flex;\n align-items: center;\n gap: 6px;\n color: #059669;\n font-weight: 500;\n font-size: 14px;\n}\n\n/* KPI Cards */\n.kpi-row {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));\n gap: 16px;\n margin-bottom: 24px;\n}\n\n.kpi-card {\n display: flex;\n align-items: center;\n padding: 16px 20px;\n background: var(--card-background, #ffffff);\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.kpi-card.clickable {\n cursor: pointer;\n}\n\n.kpi-card.clickable:hover {\n transform: translateY(-2px);\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);\n}\n\n.kpi-card.active .kpi-icon {\n background: linear-gradient(135deg, #10b981 0%, #059669 100%);\n}\n\n.kpi-card.warning .kpi-icon {\n background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);\n}\n\n.kpi-card.danger .kpi-icon {\n background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);\n}\n\n.kpi-icon {\n width: 48px;\n height: 48px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);\n border-radius: 10px;\n margin-right: 14px;\n flex-shrink: 0;\n}\n\n.kpi-icon i {\n font-size: 20px;\n color: white;\n}\n\n.kpi-content {\n flex: 1;\n min-width: 0;\n}\n\n.kpi-value {\n font-size: 24px;\n font-weight: 700;\n color: var(--text-primary, #1f2937);\n line-height: 1.2;\n}\n\n.kpi-label {\n font-size: 12px;\n color: var(--text-secondary, #6b7280);\n margin-top: 2px;\n white-space: nowrap;\n}\n\n.kpi-trend {\n display: flex;\n align-items: center;\n margin-left: 8px;\n color: var(--text-tertiary, #9ca3af);\n}\n\n.kpi-trend.success {\n color: #10b981;\n}\n\n.kpi-trend.warning {\n color: #f59e0b;\n}\n\n.kpi-trend .percentage {\n font-size: 12px;\n font-weight: 600;\n}\n\n/* Content Grid */\n.content-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n grid-template-rows: auto auto;\n gap: 20px;\n margin-bottom: 24px;\n}\n\n.keys-panel {\n grid-row: span 1;\n}\n\n.scope-panel {\n grid-row: span 1;\n}\n\n.activity-panel {\n grid-column: span 2;\n}\n\n.panel {\n background: var(--card-background, #ffffff);\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n overflow: hidden;\n display: flex;\n flex-direction: column;\n}\n\n.panel-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n background: var(--header-background, #f9fafb);\n border-bottom: 1px solid var(--border-color, #e5e7eb);\n}\n\n.panel-title {\n display: flex;\n align-items: center;\n gap: 10px;\n font-weight: 600;\n font-size: 14px;\n color: var(--text-primary, #1f2937);\n}\n\n.panel-title i {\n color: #f59e0b;\n}\n\n.panel-subtitle {\n font-size: 12px;\n color: var(--text-tertiary, #9ca3af);\n}\n\n.panel-action {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n background: transparent;\n border: 1px solid var(--border-color, #e5e7eb);\n border-radius: 6px;\n font-size: 12px;\n font-weight: 500;\n color: var(--text-secondary, #6b7280);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.panel-action:hover {\n background: #f59e0b;\n border-color: #f59e0b;\n color: white;\n}\n\n.panel-body {\n padding: 20px;\n flex: 1;\n overflow-y: auto;\n}\n\n/* Key List */\n.key-list {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.key-item {\n display: flex;\n align-items: center;\n padding: 14px 16px;\n background: var(--item-background, #f9fafb);\n border-radius: 10px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.key-item:hover {\n background: var(--item-hover, #f3f4f6);\n transform: translateX(4px);\n}\n\n.key-icon {\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: linear-gradient(135deg, #6b7280 0%, #4b5563 100%);\n border-radius: 8px;\n margin-right: 14px;\n flex-shrink: 0;\n}\n\n.key-icon.active {\n background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);\n}\n\n.key-icon i {\n font-size: 16px;\n color: white;\n}\n\n.key-info {\n flex: 1;\n min-width: 0;\n}\n\n.key-label {\n font-size: 14px;\n font-weight: 600;\n color: var(--text-primary, #1f2937);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.key-meta {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-top: 2px;\n font-size: 12px;\n color: var(--text-secondary, #6b7280);\n}\n\n.key-hash {\n font-family: monospace;\n background: var(--tag-background, #e5e7eb);\n padding: 2px 6px;\n border-radius: 4px;\n font-size: 11px;\n}\n\n.key-status {\n display: flex;\n flex-direction: column;\n align-items: flex-end;\n gap: 4px;\n margin-left: 16px;\n}\n\n.last-used {\n font-size: 12px;\n color: var(--text-secondary, #6b7280);\n}\n\n.expiration {\n font-size: 11px;\n color: var(--text-tertiary, #9ca3af);\n}\n\n.expiration.expiring-soon {\n color: #f59e0b;\n font-weight: 500;\n}\n\n.expiration.expiring-critical {\n color: #ef4444;\n font-weight: 500;\n}\n\n.expiration.expired {\n color: #ef4444;\n font-weight: 600;\n}\n\n/* Scope Chart */\n.scope-chart {\n display: flex;\n flex-direction: column;\n gap: 24px;\n height: 100%;\n}\n\n.donut-chart-container {\n position: relative;\n width: 160px;\n height: 160px;\n margin: 0 auto;\n}\n\n.donut-chart {\n width: 100%;\n height: 100%;\n transform: rotate(-90deg);\n}\n\n.donut-segment {\n cursor: pointer;\n transition: opacity 0.2s ease;\n}\n\n.donut-segment:hover {\n opacity: 0.8;\n}\n\n.donut-center {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n text-align: center;\n}\n\n.donut-total {\n font-size: 28px;\n font-weight: 700;\n color: var(--text-primary, #1f2937);\n}\n\n.donut-label {\n font-size: 11px;\n color: var(--text-secondary, #6b7280);\n}\n\n/* Scope Legend */\n.scope-legend {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.legend-item {\n display: flex;\n align-items: center;\n padding: 10px 12px;\n background: var(--item-background, #f9fafb);\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.legend-item:hover {\n background: var(--item-hover, #f3f4f6);\n transform: translateX(4px);\n}\n\n.legend-color {\n width: 12px;\n height: 12px;\n border-radius: 4px;\n margin-right: 12px;\n flex-shrink: 0;\n}\n\n.legend-info {\n flex: 1;\n}\n\n.legend-name {\n font-size: 14px;\n font-weight: 500;\n color: var(--text-primary, #1f2937);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.legend-name i {\n font-size: 12px;\n color: var(--text-secondary, #6b7280);\n}\n\n.legend-value {\n font-size: 12px;\n color: var(--text-secondary, #6b7280);\n}\n\n.legend-arrow {\n color: var(--text-tertiary, #9ca3af);\n font-size: 10px;\n}\n\n/* Activity List */\n.activity-list {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));\n gap: 12px;\n}\n\n.activity-item {\n display: flex;\n align-items: center;\n padding: 12px 14px;\n background: var(--item-background, #f9fafb);\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.activity-item:hover {\n background: var(--item-hover, #f3f4f6);\n}\n\n.activity-icon {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--icon-background, #fef3c7);\n border-radius: 6px;\n margin-right: 12px;\n flex-shrink: 0;\n}\n\n.activity-icon i {\n font-size: 12px;\n color: #f59e0b;\n}\n\n.activity-icon.action-created {\n background: #d1fae5;\n}\n\n.activity-icon.action-created i {\n color: #059669;\n}\n\n.activity-icon.action-updated {\n background: #e0e7ff;\n}\n\n.activity-icon.action-updated i {\n color: #6366f1;\n}\n\n.activity-icon.action-revoked {\n background: #fee2e2;\n}\n\n.activity-icon.action-revoked i {\n color: #dc2626;\n}\n\n.activity-icon.action-used {\n background: #fef3c7;\n}\n\n.activity-icon.action-used i {\n color: #d97706;\n}\n\n.activity-icon.action-extended {\n background: #dbeafe;\n}\n\n.activity-icon.action-extended i {\n color: #3b82f6;\n}\n\n.activity-info {\n flex: 1;\n min-width: 0;\n}\n\n.activity-name {\n font-weight: 500;\n font-size: 13px;\n color: var(--text-primary, #1f2937);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.activity-meta {\n display: flex;\n align-items: center;\n gap: 6px;\n margin-top: 2px;\n font-size: 11px;\n color: var(--text-secondary, #6b7280);\n}\n\n.activity-action {\n font-weight: 500;\n text-transform: capitalize;\n}\n\n.activity-time {\n font-size: 11px;\n color: var(--text-tertiary, #9ca3af);\n white-space: nowrap;\n}\n\n/* Quick Actions */\n.quick-actions {\n margin-bottom: 24px;\n}\n\n.quick-actions-title {\n font-size: 14px;\n font-weight: 600;\n color: var(--text-primary, #1f2937);\n margin-bottom: 12px;\n}\n\n.quick-actions-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));\n gap: 12px;\n}\n\n.quick-action {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n padding: 16px;\n background: var(--card-background, #ffffff);\n border: 1px solid var(--border-color, #e5e7eb);\n border-radius: 10px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.quick-action:hover {\n border-color: #f59e0b;\n background: #fffbeb;\n transform: translateY(-2px);\n}\n\n.quick-action i {\n font-size: 20px;\n color: #f59e0b;\n}\n\n.quick-action span {\n font-size: 12px;\n font-weight: 500;\n color: var(--text-secondary, #6b7280);\n}\n\n/* Empty State */\n.empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 32px;\n color: var(--text-secondary, #6b7280);\n text-align: center;\n}\n\n.empty-state i {\n font-size: 32px;\n margin-bottom: 12px;\n opacity: 0.5;\n}\n\n/* Security Notice */\n.security-notice {\n display: flex;\n align-items: flex-start;\n padding: 16px 20px;\n background: linear-gradient(135deg, #fffbeb 0%, #fef3c7 100%);\n border-radius: 12px;\n border: 1px solid #fcd34d;\n}\n\n.security-notice i {\n font-size: 20px;\n color: #f59e0b;\n margin-right: 12px;\n margin-top: 2px;\n}\n\n.notice-content {\n font-size: 13px;\n color: #92400e;\n line-height: 1.5;\n}\n\n.notice-content strong {\n font-weight: 600;\n}\n\n/* Mobile Navigation Toggle */\n.mobile-nav-toggle {\n display: none;\n position: fixed;\n bottom: 20px;\n right: 20px;\n width: 56px;\n height: 56px;\n background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);\n border: none;\n border-radius: 50%;\n color: white;\n font-size: 24px;\n box-shadow: 0 4px 16px rgba(245, 158, 11, 0.4);\n cursor: pointer;\n z-index: 50;\n transition: transform 0.2s ease;\n}\n\n.mobile-nav-toggle:hover {\n transform: scale(1.05);\n}\n\n/* Mobile Nav 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: 90;\n}\n\n/* ========================================\n Responsive Styles\n ======================================== */\n\n/* Tablet */\n@media (max-width: 1024px) {\n .content-grid {\n grid-template-columns: 1fr;\n }\n\n .activity-panel {\n grid-column: span 1;\n }\n\n .scope-chart {\n flex-direction: row;\n align-items: center;\n }\n\n .donut-chart-container {\n width: 140px;\n height: 140px;\n }\n\n .scope-legend {\n flex: 1;\n }\n\n .dashboard-nav {\n width: 200px;\n }\n}\n\n/* Mobile */\n@media (max-width: 768px) {\n .api-keys-dashboard {\n flex-direction: column;\n }\n\n .dashboard-nav {\n position: fixed;\n top: 0;\n left: -280px;\n width: 280px;\n height: 100%;\n z-index: 100;\n transition: left 0.3s ease;\n box-shadow: 4px 0 20px rgba(0, 0, 0, 0.15);\n }\n\n .api-keys-dashboard.nav-open .dashboard-nav {\n left: 0;\n }\n\n .mobile-nav-toggle {\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .mobile-nav-overlay {\n display: block;\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.3s ease;\n }\n\n .api-keys-dashboard.nav-open .mobile-nav-overlay {\n opacity: 1;\n pointer-events: auto;\n }\n\n .dashboard-content {\n width: 100%;\n }\n\n .content-wrapper {\n padding: 16px;\n }\n\n .overview-header {\n flex-direction: column;\n gap: 16px;\n }\n\n .header-actions {\n width: 100%;\n justify-content: flex-end;\n }\n\n .health-banner {\n flex-direction: column;\n text-align: center;\n }\n\n .health-score-container {\n margin-right: 0;\n margin-bottom: 16px;\n }\n\n .kpi-row {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .scope-chart {\n flex-direction: column;\n }\n\n .quick-actions-grid {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .activity-list {\n grid-template-columns: 1fr;\n }\n\n .key-item {\n flex-wrap: wrap;\n }\n\n .key-status {\n width: 100%;\n flex-direction: row;\n justify-content: flex-start;\n margin-left: 54px;\n margin-top: 8px;\n gap: 12px;\n }\n}\n\n/* Small Mobile */\n@media (max-width: 480px) {\n .kpi-row {\n grid-template-columns: 1fr;\n }\n\n .quick-actions-grid {\n grid-template-columns: 1fr;\n }\n\n .kpi-card {\n padding: 12px 16px;\n }\n\n .kpi-icon {\n width: 40px;\n height: 40px;\n }\n\n .kpi-value {\n font-size: 20px;\n }\n\n .overview-title {\n font-size: 20px;\n }\n\n .btn-primary {\n padding: 8px 16px;\n font-size: 13px;\n }\n}\n"] }]
1136
+ args: [{ standalone: false, selector: 'mj-api-keys-resource', template: "<div class=\"api-keys-dashboard\" [class.panel-open]=\"ShowCreateDialog || ShowEditPanel\" [class.nav-open]=\"NavOpen\">\n @if (IsLoading) {\n <mj-loading text=\"Loading API Keys...\"></mj-loading>\n }\n\n @if (!IsLoading) {\n <!-- Left Navigation Sidebar -->\n <div class=\"dashboard-nav\">\n <div class=\"nav-header\">\n <div class=\"nav-title\">\n <i class=\"fa-solid fa-key\"></i>\n <span>API Keys</span>\n </div>\n </div>\n <div class=\"nav-items\">\n <button class=\"nav-item\" [class.active]=\"MainTab === 'keys'\" (click)=\"switchTab('keys'); closeNav()\">\n <i class=\"fa-solid fa-key\"></i>\n <span class=\"nav-label\">API Keys</span>\n <span class=\"nav-badge\">{{TotalKeys}}</span>\n </button>\n <button class=\"nav-item\" [class.active]=\"MainTab === 'applications'\" (click)=\"switchTab('applications'); closeNav()\">\n <i class=\"fa-solid fa-cube\"></i>\n <span class=\"nav-label\">Applications</span>\n <span class=\"nav-badge\">{{ApplicationCount}}</span>\n </button>\n <button class=\"nav-item\" [class.active]=\"MainTab === 'scopes'\" (click)=\"switchTab('scopes'); closeNav()\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <span class=\"nav-label\">Scopes</span>\n <span class=\"nav-badge\">{{ScopeCount}}</span>\n </button>\n <button class=\"nav-item\" [class.active]=\"MainTab === 'usage'\" (click)=\"switchTab('usage'); closeNav()\">\n <i class=\"fa-solid fa-chart-line\"></i>\n <span class=\"nav-label\">Usage Analytics</span>\n </button>\n </div>\n </div>\n <!-- Main Content Area -->\n <div class=\"dashboard-content\">\n <div class=\"content-wrapper\">\n <!-- Keys Tab Content -->\n @if (MainTab === 'keys') {\n <!-- Overview View -->\n @if (CurrentView === 'overview') {\n <!-- Header with Actions -->\n <div class=\"overview-header\">\n <div class=\"header-left\">\n <h2 class=\"overview-title\">API Keys Management</h2>\n <p class=\"overview-subtitle\">Manage API keys for external integrations and services</p>\n </div>\n <div class=\"header-actions\">\n <button class=\"btn-refresh\" (click)=\"refresh()\" title=\"Refresh\">\n <i class=\"fa-solid fa-refresh\"></i>\n </button>\n @if (UserCanCreateKeys) {\n <button class=\"btn-primary\" (click)=\"openCreateDialog()\">\n <i class=\"fa-solid fa-plus\"></i>\n <span>Generate New Key</span>\n </button>\n }\n </div>\n </div>\n <!-- Health Score Banner -->\n <div class=\"health-banner\" [ngClass]=\"getHealthClass()\">\n <div class=\"health-score-container\">\n <div class=\"health-score-ring\">\n <svg viewBox=\"0 0 36 36\" class=\"circular-chart\">\n <path class=\"circle-bg\"\n d=\"M18 2.0845\n a 15.9155 15.9155 0 0 1 0 31.831\n a 15.9155 15.9155 0 0 1 0 -31.831\"\n />\n <path class=\"circle\"\n [attr.stroke-dasharray]=\"getHealthScore() + ', 100'\"\n d=\"M18 2.0845\n a 15.9155 15.9155 0 0 1 0 31.831\n a 15.9155 15.9155 0 0 1 0 -31.831\"\n />\n </svg>\n <div class=\"health-score-value\">{{getHealthScore()}}</div>\n </div>\n </div>\n <div class=\"health-info\">\n <div class=\"health-label\">{{getHealthLabel()}}</div>\n <div class=\"health-details\">\n @if (ExpiredKeys > 0) {\n <span class=\"health-alert\" (click)=\"showListView('expired')\">\n <i class=\"fa-solid fa-circle-exclamation\"></i>\n {{ExpiredKeys}} expired\n </span>\n }\n @if (ExpiringSoonCount > 0) {\n <span class=\"health-warning-text\" (click)=\"showListView('expiring')\">\n <i class=\"fa-solid fa-clock\"></i>\n {{ExpiringSoonCount}} expiring soon\n </span>\n }\n @if (NeverUsedKeys > 0) {\n <span class=\"health-info-text\" (click)=\"showListView('never-used')\">\n <i class=\"fa-solid fa-question-circle\"></i>\n {{NeverUsedKeys}} never used\n </span>\n }\n @if (ExpiredKeys === 0 && ExpiringSoonCount === 0 && NeverUsedKeys === 0) {\n <span class=\"health-ok\">\n <i class=\"fa-solid fa-check-circle\"></i>\n All keys healthy\n </span>\n }\n </div>\n </div>\n </div>\n <!-- KPI Cards Row -->\n <div class=\"kpi-row\">\n <div class=\"kpi-card clickable\" (click)=\"showListView('all')\">\n <div class=\"kpi-icon\">\n <i class=\"fa-solid fa-key\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{TotalKeys}}</div>\n <div class=\"kpi-label\">Total Keys</div>\n </div>\n <div class=\"kpi-trend\">\n <i class=\"fa-solid fa-arrow-right\"></i>\n </div>\n </div>\n <div class=\"kpi-card active clickable\" (click)=\"showListView('active')\">\n <div class=\"kpi-icon\">\n <i class=\"fa-solid fa-check-circle\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ActiveKeys}}</div>\n <div class=\"kpi-label\">Active</div>\n </div>\n <div class=\"kpi-trend success\">\n <span class=\"percentage\">{{TotalKeys > 0 ? (ActiveKeys / TotalKeys * 100).toFixed(0) : 100}}%</span>\n </div>\n </div>\n <div class=\"kpi-card clickable\" [class.warning]=\"ExpiringSoonCount > 0\" (click)=\"showListView('expiring')\">\n <div class=\"kpi-icon\">\n <i class=\"fa-solid fa-clock\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ExpiringSoonCount}}</div>\n <div class=\"kpi-label\">Expiring Soon</div>\n </div>\n @if (ExpiringSoonCount > 0) {\n <div class=\"kpi-trend warning\">\n <i class=\"fa-solid fa-arrow-right\"></i>\n </div>\n }\n </div>\n <div class=\"kpi-card clickable\" [class.danger]=\"RevokedKeys > 0\" (click)=\"showListView('revoked')\">\n <div class=\"kpi-icon\">\n <i class=\"fa-solid fa-ban\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{RevokedKeys}}</div>\n <div class=\"kpi-label\">Revoked</div>\n </div>\n </div>\n <div class=\"kpi-card clickable\" (click)=\"switchTab('scopes')\">\n <div class=\"kpi-icon\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ScopeStats.length}}</div>\n <div class=\"kpi-label\">Scope Categories</div>\n </div>\n </div>\n </div>\n <!-- Content Grid -->\n <div class=\"content-grid\">\n <!-- Recently Used Keys -->\n <div class=\"panel keys-panel\">\n <div class=\"panel-header\">\n <div class=\"panel-title\">\n <i class=\"fa-solid fa-key\"></i>\n <span>Recently Used Keys</span>\n </div>\n <button class=\"panel-action\" (click)=\"showListView('all')\">\n View All <i class=\"fa-solid fa-arrow-right\"></i>\n </button>\n </div>\n <div class=\"panel-body\">\n @if (TopUsedKeys.length > 0) {\n <div class=\"key-list\">\n @for (key of TopUsedKeys; track key) {\n <div class=\"key-item\" (click)=\"openEditPanel(key)\">\n <div class=\"key-icon\" [class.active]=\"key.Status === 'Active'\">\n <i class=\"fa-solid fa-key\"></i>\n </div>\n <div class=\"key-info\">\n <div class=\"key-label\">{{key.Label}}</div>\n <div class=\"key-meta\">\n <span class=\"key-user\">{{key.User}}</span>\n <span class=\"key-hash\">...{{key.Hash.slice(-8)}}</span>\n </div>\n </div>\n <div class=\"key-status\">\n <div class=\"last-used\">{{formatDate(key.LastUsedAt)}}</div>\n <div class=\"expiration\" [ngClass]=\"getExpirationClass(key)\">\n {{formatExpiration(key.ExpiresAt)}}\n </div>\n </div>\n </div>\n }\n </div>\n }\n @if (TopUsedKeys.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-key\"></i>\n <span>No active keys with recent usage</span>\n </div>\n }\n </div>\n </div>\n <!-- Scope Categories -->\n <div class=\"panel scope-panel\">\n <div class=\"panel-header\">\n <div class=\"panel-title\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <span>Permission Scopes</span>\n </div>\n <span class=\"panel-subtitle\">Available scope categories</span>\n </div>\n <div class=\"panel-body\">\n @if (ScopeStats.length > 0) {\n <div class=\"scope-chart\">\n <!-- Visual Donut Chart -->\n <div class=\"donut-chart-container\">\n <svg viewBox=\"0 0 100 100\" class=\"donut-chart\">\n <circle cx=\"50\" cy=\"50\" r=\"40\" fill=\"none\" stroke=\"#e5e7eb\" stroke-width=\"12\"/>\n @for (stat of ScopeStats; track stat; let i = $index) {\n <ng-container>\n <circle\n cx=\"50\" cy=\"50\" r=\"40\"\n fill=\"none\"\n [attr.stroke]=\"stat.color\"\n stroke-width=\"12\"\n [attr.stroke-dasharray]=\"stat.percentage * 2.51 + ' ' + (251 - stat.percentage * 2.51)\"\n [attr.stroke-dashoffset]=\"getDonutOffset(i)\"\n class=\"donut-segment\"\n (click)=\"onScopeClick(stat)\"\n />\n </ng-container>\n }\n </svg>\n <div class=\"donut-center\">\n <div class=\"donut-total\">{{ScopeStats.length}}</div>\n <div class=\"donut-label\">Categories</div>\n </div>\n </div>\n <!-- Legend -->\n <div class=\"scope-legend\">\n @for (stat of ScopeStats; track stat) {\n <div class=\"legend-item\" (click)=\"onScopeClick(stat)\">\n <div class=\"legend-color\" [style.backgroundColor]=\"stat.color\"></div>\n <div class=\"legend-info\">\n <div class=\"legend-name\">\n <i [class]=\"stat.iconClass\"></i>\n {{stat.category}}\n </div>\n <div class=\"legend-value\">{{stat.count}} scopes</div>\n </div>\n <i class=\"fa-solid fa-chevron-right legend-arrow\"></i>\n </div>\n }\n </div>\n </div>\n }\n @if (ScopeStats.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <span>No scopes configured</span>\n </div>\n }\n </div>\n </div>\n <!-- Recent Activity -->\n <div class=\"panel activity-panel\">\n <div class=\"panel-header\">\n <div class=\"panel-title\">\n <i class=\"fa-solid fa-clock-rotate-left\"></i>\n <span>Recent Activity</span>\n </div>\n </div>\n <div class=\"panel-body\">\n @if (RecentActivity.length > 0) {\n <div class=\"activity-list\">\n @for (activity of RecentActivity; track activity) {\n <div class=\"activity-item\" (click)=\"onActivityClick(activity)\">\n <div class=\"activity-icon\" [ngClass]=\"getActionClass(activity.action)\">\n <i [class]=\"getActionIcon(activity.action)\"></i>\n </div>\n <div class=\"activity-info\">\n <div class=\"activity-name\">{{activity.keyLabel}}</div>\n <div class=\"activity-meta\">\n <span class=\"activity-action\">{{activity.action}}</span>\n @if (activity.user) {\n <span class=\"activity-user\">by {{activity.user}}</span>\n }\n </div>\n </div>\n <div class=\"activity-time\">\n {{formatDate(activity.date)}}\n </div>\n </div>\n }\n </div>\n }\n @if (RecentActivity.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-inbox\"></i>\n <span>No recent activity</span>\n </div>\n }\n </div>\n </div>\n </div>\n <!-- Quick Actions -->\n @if (UserCanCreateKeys) {\n <div class=\"quick-actions\">\n <div class=\"quick-actions-title\">Quick Actions</div>\n <div class=\"quick-actions-grid\">\n <button class=\"quick-action\" (click)=\"openCreateDialog()\">\n <i class=\"fa-solid fa-plus\"></i>\n <span>Generate Key</span>\n </button>\n <button class=\"quick-action\" (click)=\"showListView('all')\">\n <i class=\"fa-solid fa-list\"></i>\n <span>View All Keys</span>\n </button>\n <button class=\"quick-action\" (click)=\"showListView('expiring')\">\n <i class=\"fa-solid fa-clock\"></i>\n <span>Expiring Keys</span>\n </button>\n <button class=\"quick-action\" (click)=\"showListView('never-used')\">\n <i class=\"fa-solid fa-question-circle\"></i>\n <span>Never Used</span>\n </button>\n </div>\n </div>\n }\n <!-- Security Notice -->\n <div class=\"security-notice\">\n <i class=\"fa-solid fa-shield-check\"></i>\n <div class=\"notice-content\">\n <strong>Security Best Practices:</strong>\n API keys should be rotated regularly and revoked when no longer needed.\n Keys are hashed and stored securely - the raw key is only shown once at creation time.\n All API key usage is logged for audit purposes.\n </div>\n </div>\n }\n <!-- List View -->\n @if (CurrentView === 'list') {\n <div class=\"list-view-header\">\n <button class=\"back-btn\" (click)=\"showOverview()\">\n <i class=\"fa-solid fa-arrow-left\"></i>\n Back to Overview\n </button>\n </div>\n <mj-api-key-list #keyList\n [Filter]=\"ListFilter\"\n (KeySelected)=\"onKeySelected($event)\"\n (CreateRequested)=\"openCreateDialog()\">\n </mj-api-key-list>\n }\n }\n <!-- Applications Tab Content -->\n @if (MainTab === 'applications') {\n <mj-api-applications-panel\n (ApplicationUpdated)=\"onDataUpdated()\">\n </mj-api-applications-panel>\n }\n <!-- Scopes Tab Content -->\n @if (MainTab === 'scopes') {\n <mj-api-scopes-panel\n (ScopeUpdated)=\"onDataUpdated()\">\n </mj-api-scopes-panel>\n }\n <!-- Usage Tab Content -->\n @if (MainTab === 'usage') {\n <mj-api-usage-panel></mj-api-usage-panel>\n }\n </div><!-- /.content-wrapper -->\n </div><!-- /.dashboard-content -->\n <!-- Mobile Navigation Toggle -->\n <button class=\"mobile-nav-toggle\" (click)=\"toggleNav()\">\n <i class=\"fa-solid\" [class.fa-bars]=\"!NavOpen\" [class.fa-times]=\"NavOpen\"></i>\n </button>\n <!-- Mobile Navigation Overlay -->\n <div class=\"mobile-nav-overlay\" (click)=\"closeNav()\"></div>\n }\n\n <!-- Create Dialog -->\n <mj-api-key-create-dialog\n [Visible]=\"ShowCreateDialog\"\n (Created)=\"onKeyCreated($event)\"\n (Closed)=\"onCreateDialogClosed()\">\n </mj-api-key-create-dialog>\n\n <!-- Edit Panel -->\n <mj-api-key-edit-panel\n [Visible]=\"ShowEditPanel\"\n [KeyId]=\"SelectedKeyId\"\n (Updated)=\"onKeyUpdated()\"\n (Revoked)=\"onKeyRevoked()\"\n (Closed)=\"onEditPanelClosed()\">\n </mj-api-key-edit-panel>\n</div>\n", styles: ["/* Main Dashboard Container */\n.api-keys-dashboard {\n display: flex;\n height: 100%;\n position: relative;\n overflow: hidden;\n}\n\n.api-keys-dashboard.panel-open .dashboard-content {\n overflow: hidden;\n}\n\n/* Left Navigation Sidebar */\n.dashboard-nav {\n width: 220px;\n background: var(--mj-bg-surface);\n border-right: 1px solid var(--mj-border-default);\n display: flex;\n flex-direction: column;\n flex-shrink: 0;\n}\n\n.nav-header {\n padding: 20px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.nav-title {\n display: flex;\n align-items: center;\n gap: 10px;\n font-weight: 700;\n font-size: 16px;\n color: var(--mj-text-primary);\n}\n\n.nav-title i {\n color: var(--mj-brand-primary);\n font-size: 18px;\n}\n\n.nav-items {\n flex: 1;\n padding: 12px;\n overflow-y: auto;\n}\n\n.nav-item {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 16px;\n margin-bottom: 4px;\n background: transparent;\n border: none;\n border-radius: 8px;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n width: 100%;\n text-align: left;\n}\n\n.nav-item:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n.nav-item.active {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n box-shadow: var(--mj-shadow-brand-sm);\n}\n\n.nav-item i {\n font-size: 16px;\n width: 20px;\n text-align: center;\n}\n\n.nav-item .nav-label {\n flex: 1;\n}\n\n.nav-badge {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 22px;\n height: 20px;\n padding: 0 6px;\n background: var(--mj-bg-surface-active);\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n}\n\n.nav-item.active .nav-badge {\n background: rgba(255, 255, 255, 0.25);\n}\n\n/* Dashboard Content Area */\n.dashboard-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow-y: auto;\n min-width: 0;\n}\n\n.content-wrapper {\n flex: 1;\n padding: 24px;\n overflow-y: auto;\n}\n\n/* List View Header */\n.list-view-header {\n margin-bottom: 16px;\n}\n\n.back-btn {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.back-btn:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n/* Header */\n.overview-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 24px;\n}\n\n.header-left {\n flex: 1;\n}\n\n.overview-title {\n font-size: 24px;\n font-weight: 700;\n color: var(--mj-text-primary);\n margin: 0 0 4px 0;\n}\n\n.overview-subtitle {\n font-size: 14px;\n color: var(--mj-text-secondary);\n margin: 0;\n}\n\n.header-actions {\n display: flex;\n gap: 12px;\n}\n\n.btn-refresh {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 40px;\n height: 40px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.btn-refresh:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.btn-refresh i {\n color: var(--mj-text-secondary);\n}\n\n.btn-primary {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 20px;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border: none;\n border-radius: 8px;\n font-weight: 600;\n font-size: 14px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.btn-primary:hover {\n transform: translateY(-1px);\n box-shadow: var(--mj-shadow-brand-md);\n}\n\n/* Health Banner */\n.health-banner {\n display: flex;\n align-items: center;\n padding: 20px 24px;\n background: var(--mj-status-success-bg);\n border: 1px solid var(--mj-status-success-border);\n border-radius: 16px;\n margin-bottom: 24px;\n}\n\n.health-banner.health-warning {\n background: var(--mj-status-warning-bg);\n border-color: var(--mj-color-accent-300);\n}\n\n.health-banner.health-critical {\n background: var(--mj-status-error-bg);\n border-color: var(--mj-status-error-border);\n}\n\n.health-score-container {\n margin-right: 24px;\n}\n\n.health-score-ring {\n position: relative;\n width: 80px;\n height: 80px;\n}\n\n.circular-chart {\n display: block;\n margin: 0 auto;\n max-height: 80px;\n transform: rotate(-90deg);\n}\n\n.circle-bg {\n fill: none;\n stroke: var(--mj-border-default);\n stroke-width: 3.8;\n}\n\n.circle {\n fill: none;\n stroke-width: 3.8;\n stroke-linecap: round;\n stroke: var(--mj-status-success);\n animation: progress 1s ease-out forwards;\n}\n\n.health-banner.health-warning .circle {\n stroke: var(--mj-color-warning-500);\n}\n\n.health-banner.health-critical .circle {\n stroke: var(--mj-status-error);\n}\n\n@keyframes progress {\n 0% {\n stroke-dasharray: 0 100;\n }\n}\n\n.health-score-value {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n font-size: 20px;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.health-info {\n flex: 1;\n}\n\n.health-label {\n font-size: 18px;\n font-weight: 700;\n color: var(--mj-color-success-600);\n margin-bottom: 4px;\n}\n\n.health-banner.health-warning .health-label {\n color: var(--mj-brand-primary-hover);\n}\n\n.health-banner.health-critical .health-label {\n color: var(--mj-color-error-600);\n}\n\n.health-details {\n display: flex;\n gap: 16px;\n flex-wrap: wrap;\n}\n\n.health-alert {\n display: flex;\n align-items: center;\n gap: 6px;\n color: var(--mj-color-error-600);\n font-weight: 500;\n font-size: 14px;\n cursor: pointer;\n}\n\n.health-alert:hover {\n text-decoration: underline;\n}\n\n.health-warning-text {\n display: flex;\n align-items: center;\n gap: 6px;\n color: var(--mj-brand-primary-hover);\n font-weight: 500;\n font-size: 14px;\n cursor: pointer;\n}\n\n.health-warning-text:hover {\n text-decoration: underline;\n}\n\n.health-info-text {\n display: flex;\n align-items: center;\n gap: 6px;\n color: var(--mj-text-secondary);\n font-weight: 500;\n font-size: 14px;\n cursor: pointer;\n}\n\n.health-info-text:hover {\n text-decoration: underline;\n}\n\n.health-ok {\n display: flex;\n align-items: center;\n gap: 6px;\n color: var(--mj-color-success-600);\n font-weight: 500;\n font-size: 14px;\n}\n\n/* KPI Cards */\n.kpi-row {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));\n gap: 16px;\n margin-bottom: 24px;\n}\n\n.kpi-card {\n display: flex;\n align-items: center;\n padding: 16px 20px;\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-md);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.kpi-card.clickable {\n cursor: pointer;\n}\n\n.kpi-card.clickable:hover {\n transform: translateY(-2px);\n box-shadow: var(--mj-shadow-lg);\n}\n\n.kpi-card.active .kpi-icon {\n background: linear-gradient(135deg, var(--mj-status-success) 0%, var(--mj-color-success-600) 100%);\n}\n\n.kpi-card.warning .kpi-icon {\n background: linear-gradient(135deg, var(--mj-color-warning-500) 0%, var(--mj-brand-primary-hover) 100%);\n}\n\n.kpi-card.danger .kpi-icon {\n background: linear-gradient(135deg, var(--mj-status-error) 0%, var(--mj-color-error-600) 100%);\n}\n\n.kpi-icon {\n width: 48px;\n height: 48px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--mj-brand-primary);\n border-radius: 10px;\n margin-right: 14px;\n flex-shrink: 0;\n}\n\n.kpi-icon i {\n font-size: 20px;\n color: var(--mj-text-inverse);\n}\n\n.kpi-content {\n flex: 1;\n min-width: 0;\n}\n\n.kpi-value {\n font-size: 24px;\n font-weight: 700;\n color: var(--mj-text-primary);\n line-height: 1.2;\n}\n\n.kpi-label {\n font-size: 12px;\n color: var(--mj-text-secondary);\n margin-top: 2px;\n white-space: nowrap;\n}\n\n.kpi-trend {\n display: flex;\n align-items: center;\n margin-left: 8px;\n color: var(--mj-text-muted);\n}\n\n.kpi-trend.success {\n color: var(--mj-status-success);\n}\n\n.kpi-trend.warning {\n color: var(--mj-color-warning-500);\n}\n\n.kpi-trend .percentage {\n font-size: 12px;\n font-weight: 600;\n}\n\n/* Content Grid */\n.content-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n grid-template-rows: auto auto;\n gap: 20px;\n margin-bottom: 24px;\n}\n\n.keys-panel {\n grid-row: span 1;\n}\n\n.scope-panel {\n grid-row: span 1;\n}\n\n.activity-panel {\n grid-column: span 2;\n}\n\n.panel {\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-md);\n overflow: hidden;\n display: flex;\n flex-direction: column;\n}\n\n.panel-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n background: var(--mj-bg-page);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.panel-title {\n display: flex;\n align-items: center;\n gap: 10px;\n font-weight: 600;\n font-size: 14px;\n color: var(--mj-text-primary);\n}\n\n.panel-title i {\n color: var(--mj-brand-primary);\n}\n\n.panel-subtitle {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.panel-action {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n background: transparent;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.panel-action:hover {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.panel-body {\n padding: 20px;\n flex: 1;\n overflow-y: auto;\n}\n\n/* Key List */\n.key-list {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.key-item {\n display: flex;\n align-items: center;\n padding: 14px 16px;\n background: var(--mj-bg-page);\n border-radius: 10px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.key-item:hover {\n background: var(--mj-bg-surface-hover);\n transform: translateX(4px);\n}\n\n.key-icon {\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: linear-gradient(135deg, var(--mj-color-neutral-500) 0%, var(--mj-color-neutral-600) 100%);\n border-radius: 8px;\n margin-right: 14px;\n flex-shrink: 0;\n}\n\n.key-icon.active {\n background: var(--mj-brand-primary);\n}\n\n.key-icon i {\n font-size: 16px;\n color: var(--mj-text-inverse);\n}\n\n.key-info {\n flex: 1;\n min-width: 0;\n}\n\n.key-label {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.key-meta {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-top: 2px;\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.key-hash {\n font-family: monospace;\n background: var(--mj-bg-surface-active);\n padding: 2px 6px;\n border-radius: 4px;\n font-size: 11px;\n}\n\n.key-status {\n display: flex;\n flex-direction: column;\n align-items: flex-end;\n gap: 4px;\n margin-left: 16px;\n}\n\n.last-used {\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.expiration {\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n\n.expiration.expiring-soon {\n color: var(--mj-color-warning-500);\n font-weight: 500;\n}\n\n.expiration.expiring-critical {\n color: var(--mj-status-error);\n font-weight: 500;\n}\n\n.expiration.expired {\n color: var(--mj-status-error);\n font-weight: 600;\n}\n\n/* Scope Chart */\n.scope-chart {\n display: flex;\n flex-direction: column;\n gap: 24px;\n height: 100%;\n}\n\n.donut-chart-container {\n position: relative;\n width: 160px;\n height: 160px;\n margin: 0 auto;\n}\n\n.donut-chart {\n width: 100%;\n height: 100%;\n transform: rotate(-90deg);\n}\n\n.donut-segment {\n cursor: pointer;\n transition: opacity 0.2s ease;\n}\n\n.donut-segment:hover {\n opacity: 0.8;\n}\n\n.donut-center {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n text-align: center;\n}\n\n.donut-total {\n font-size: 28px;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.donut-label {\n font-size: 11px;\n color: var(--mj-text-secondary);\n}\n\n/* Scope Legend */\n.scope-legend {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.legend-item {\n display: flex;\n align-items: center;\n padding: 10px 12px;\n background: var(--mj-bg-page);\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.legend-item:hover {\n background: var(--mj-bg-surface-hover);\n transform: translateX(4px);\n}\n\n.legend-color {\n width: 12px;\n height: 12px;\n border-radius: 4px;\n margin-right: 12px;\n flex-shrink: 0;\n}\n\n.legend-info {\n flex: 1;\n}\n\n.legend-name {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.legend-name i {\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.legend-value {\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.legend-arrow {\n color: var(--mj-text-muted);\n font-size: 10px;\n}\n\n/* Activity List */\n.activity-list {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));\n gap: 12px;\n}\n\n.activity-item {\n display: flex;\n align-items: center;\n padding: 12px 14px;\n background: var(--mj-bg-page);\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.activity-item:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.activity-icon {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--icon-background, var(--mj-color-brand-100));\n border-radius: 6px;\n margin-right: 12px;\n flex-shrink: 0;\n}\n\n.activity-icon i {\n font-size: 12px;\n color: var(--mj-brand-primary);\n}\n\n.activity-icon.action-created {\n background: var(--mj-color-success-100);\n}\n\n.activity-icon.action-created i {\n color: var(--mj-color-success-600);\n}\n\n.activity-icon.action-updated {\n background: var(--mj-color-indigo-100);\n}\n\n.activity-icon.action-updated i {\n color: var(--mj-color-indigo-500);\n}\n\n.activity-icon.action-revoked {\n background: var(--mj-color-error-100);\n}\n\n.activity-icon.action-revoked i {\n color: var(--mj-color-error-600);\n}\n\n.activity-icon.action-used {\n background: var(--mj-color-brand-100);\n}\n\n.activity-icon.action-used i {\n color: var(--mj-brand-primary-hover);\n}\n\n.activity-icon.action-extended {\n background: var(--mj-color-info-100);\n}\n\n.activity-icon.action-extended i {\n color: var(--mj-status-info);\n}\n\n.activity-info {\n flex: 1;\n min-width: 0;\n}\n\n.activity-name {\n font-weight: 500;\n font-size: 13px;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.activity-meta {\n display: flex;\n align-items: center;\n gap: 6px;\n margin-top: 2px;\n font-size: 11px;\n color: var(--mj-text-secondary);\n}\n\n.activity-action {\n font-weight: 500;\n text-transform: capitalize;\n}\n\n.activity-time {\n font-size: 11px;\n color: var(--mj-text-muted);\n white-space: nowrap;\n}\n\n/* Quick Actions */\n.quick-actions {\n margin-bottom: 24px;\n}\n\n.quick-actions-title {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin-bottom: 12px;\n}\n\n.quick-actions-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));\n gap: 12px;\n}\n\n.quick-action {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n padding: 16px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.quick-action:hover {\n border-color: var(--mj-brand-primary);\n background: var(--mj-color-brand-50);\n transform: translateY(-2px);\n}\n\n.quick-action i {\n font-size: 20px;\n color: var(--mj-brand-primary);\n}\n\n.quick-action span {\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n/* Empty State */\n.empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 32px;\n color: var(--mj-text-secondary);\n text-align: center;\n}\n\n.empty-state i {\n font-size: 32px;\n margin-bottom: 12px;\n opacity: 0.5;\n}\n\n/* Security Notice */\n.security-notice {\n display: flex;\n align-items: flex-start;\n padding: 16px 20px;\n background: linear-gradient(135deg, var(--mj-color-brand-50) 0%, var(--mj-color-brand-100) 100%);\n border-radius: 12px;\n border: 1px solid var(--mj-color-accent-300);\n}\n\n.security-notice i {\n font-size: 20px;\n color: var(--mj-brand-primary);\n margin-right: 12px;\n margin-top: 2px;\n}\n\n.notice-content {\n font-size: 13px;\n color: var(--mj-color-brand-800);\n line-height: 1.5;\n}\n\n.notice-content strong {\n font-weight: 600;\n}\n\n/* Mobile Navigation Toggle */\n.mobile-nav-toggle {\n display: none;\n position: fixed;\n bottom: 20px;\n right: 20px;\n width: 56px;\n height: 56px;\n background: var(--mj-brand-primary);\n border: none;\n border-radius: 50%;\n color: var(--mj-text-inverse);\n font-size: 24px;\n box-shadow: var(--mj-shadow-brand-md);\n cursor: pointer;\n z-index: 50;\n transition: transform 0.2s ease;\n}\n\n.mobile-nav-toggle:hover {\n transform: scale(1.05);\n}\n\n/* Mobile Nav 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: var(--mj-bg-overlay);\n z-index: 90;\n}\n\n/* ========================================\n Responsive Styles\n ======================================== */\n\n/* Tablet */\n@media (max-width: 1024px) {\n .content-grid {\n grid-template-columns: 1fr;\n }\n\n .activity-panel {\n grid-column: span 1;\n }\n\n .scope-chart {\n flex-direction: row;\n align-items: center;\n }\n\n .donut-chart-container {\n width: 140px;\n height: 140px;\n }\n\n .scope-legend {\n flex: 1;\n }\n\n .dashboard-nav {\n width: 200px;\n }\n}\n\n/* Mobile */\n@media (max-width: 768px) {\n .api-keys-dashboard {\n flex-direction: column;\n }\n\n .dashboard-nav {\n position: fixed;\n top: 0;\n left: -280px;\n width: 280px;\n height: 100%;\n z-index: 100;\n transition: left 0.3s ease;\n box-shadow: var(--mj-shadow-xl);\n }\n\n .api-keys-dashboard.nav-open .dashboard-nav {\n left: 0;\n }\n\n .mobile-nav-toggle {\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .mobile-nav-overlay {\n display: block;\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.3s ease;\n }\n\n .api-keys-dashboard.nav-open .mobile-nav-overlay {\n opacity: 1;\n pointer-events: auto;\n }\n\n .dashboard-content {\n width: 100%;\n }\n\n .content-wrapper {\n padding: 16px;\n }\n\n .overview-header {\n flex-direction: column;\n gap: 16px;\n }\n\n .header-actions {\n width: 100%;\n justify-content: flex-end;\n }\n\n .health-banner {\n flex-direction: column;\n text-align: center;\n }\n\n .health-score-container {\n margin-right: 0;\n margin-bottom: 16px;\n }\n\n .kpi-row {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .scope-chart {\n flex-direction: column;\n }\n\n .quick-actions-grid {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .activity-list {\n grid-template-columns: 1fr;\n }\n\n .key-item {\n flex-wrap: wrap;\n }\n\n .key-status {\n width: 100%;\n flex-direction: row;\n justify-content: flex-start;\n margin-left: 54px;\n margin-top: 8px;\n gap: 12px;\n }\n}\n\n/* Small Mobile */\n@media (max-width: 480px) {\n .kpi-row {\n grid-template-columns: 1fr;\n }\n\n .quick-actions-grid {\n grid-template-columns: 1fr;\n }\n\n .kpi-card {\n padding: 12px 16px;\n }\n\n .kpi-icon {\n width: 40px;\n height: 40px;\n }\n\n .kpi-value {\n font-size: 20px;\n }\n\n .overview-title {\n font-size: 20px;\n }\n\n .btn-primary {\n padding: 8px 16px;\n font-size: 13px;\n }\n}\n"] }]
1137
1137
  }], () => [{ type: i0.ChangeDetectorRef }], { keyListComponent: [{
1138
1138
  type: ViewChild,
1139
1139
  args: ['keyList']
@@ -1 +1 @@
1
- {"version":3,"file":"api-keys-resource.component.js","sourceRoot":"","sources":["../../src/APIKeys/api-keys-resource.component.ts","../../src/APIKeys/api-keys-resource.component.html"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,SAAS,EAAqB,SAAS,EAAqB,MAAM,eAAe,CAAC;AAC3F,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAEzD,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACzF,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;;;;;;;;;;;;ICJ3B,gCAAoD;;;;IAoDtC,kCAAyD;IAA7B,wOAAS,yBAAkB,KAAC;IACtD,wBAAgC;IAChC,4BAAM;IAAA,gCAAgB;IACxB,AADwB,iBAAO,EACtB;;;;IA4BP,gCAA6D;IAAlC,uOAAS,oBAAa,SAAS,CAAC,KAAC;IAC1D,wBAA8C;IAC9C,YACF;IAAA,iBAAO;;;IADL,eACF;IADE,2DACF;;;;IAGA,gCAAqE;IAAnC,uOAAS,oBAAa,UAAU,CAAC,KAAC;IAClE,wBAAiC;IACjC,YACF;IAAA,iBAAO;;;IADL,eACF;IADE,uEACF;;;;IAGA,gCAAoE;IAArC,uOAAS,oBAAa,YAAY,CAAC,KAAC;IACjE,wBAA2C;IAC3C,YACF;IAAA,iBAAO;;;IADL,eACF;IADE,gEACF;;;IAGA,gCAAwB;IACtB,wBAAwC;IACxC,kCACF;IAAA,iBAAO;;;IAwCT,+BAA+B;IAC7B,wBAAuC;IACzC,iBAAM;;;;IAuCA,+BAAmD;IAA7B,qQAAS,4BAAkB,KAAC;IAChD,+BAA+D;IAC7D,uBAA+B;IACjC,iBAAM;IAEJ,AADF,+BAAsB,cACG;IAAA,YAAa;IAAA,iBAAM;IAExC,AADF,+BAAsB,eACG;IAAA,YAAY;IAAA,iBAAO;IAC1C,gCAAuB;IAAA,aAAyB;IAEpD,AADE,AADkD,iBAAO,EACnD,EACF;IAEJ,AADF,gCAAwB,eACC;IAAA,aAA8B;IAAA,iBAAM;IAC3D,gCAA4D;IAC1D,aACF;IAEJ,AADE,AADE,iBAAM,EACF,EACF;;;;IAhBkB,cAAwC;IAAxC,oDAAwC;IAIrC,eAAa;IAAb,kCAAa;IAEX,eAAY;IAAZ,iCAAY;IACZ,eAAyB;IAAzB,mDAAyB;IAI3B,eAA8B;IAA9B,0DAA8B;IAC7B,cAAmC;IAAnC,2DAAmC;IACzD,cACF;IADE,0EACF;;;IAjBR,+BAAsB;IACpB,yKAmBC;IACH,iBAAM;;;IApBJ,cAmBC;IAnBD,iCAmBC;;;IAIH,+BAAyB;IACvB,uBAA+B;IAC/B,4BAAM;IAAA,gDAAgC;IACxC,AADwC,iBAAO,EACzC;;;;;IAqBE,6BAAc;IACZ,mCASI;IADF,2QAAS,6BAAkB,KAAC;IAR9B,iBASI;;;;;;IANF,cAA0B;;;;;IAkBhC,gCAAsD;IAA7B,yQAAS,6BAAkB,KAAC;IACnD,2BAAqE;IAEnE,AADF,gCAAyB,eACE;IACvB,oBAAgC;IAChC,YACF;IAAA,iBAAM;IACN,gCAA0B;IAAA,YAAqB;IACjD,AADiD,iBAAM,EACjD;IACN,yBAAsD;IACxD,iBAAM;;;IATsB,cAAoC;IAApC,kDAAoC;IAGvD,eAAwB;IAAxB,iCAAwB;IAC3B,cACF;IADE,kDACF;IAC0B,eAAqB;IAArB,oDAAqB;;;IAjCvD,AAFF,+BAAyB,cAEY;;IACjC,+BAA+C;IAC7C,6BAA+E;IAC/E,wLAaC;IACH,iBAAM;;IAEJ,AADF,+BAA0B,cACC;IAAA,YAAqB;IAAA,iBAAM;IACpD,+BAAyB;IAAA,2BAAU;IAEvC,AADE,AADqC,iBAAM,EACrC,EACF;IAEN,iCAA0B;IACxB,2KAYC;IAEL,AADE,iBAAM,EACF;;;IApCA,eAaC;IAbD,gCAaC;IAGwB,eAAqB;IAArB,8CAAqB;IAMhD,eAYC;IAZD,gCAYC;;;IAKL,+BAAyB;IACvB,wBAAyC;IACzC,4BAAM;IAAA,oCAAoB;IAC5B,AAD4B,iBAAO,EAC7B;;;IAyBM,iCAA4B;IAAA,YAAoB;IAAA,iBAAO;;;IAA3B,cAAoB;IAApB,+CAAoB;;;;IATxD,gCAA+D;IAApC,6QAAS,oCAAyB,KAAC;IAC5D,gCAAuE;IACrE,oBAAgD;IAClD,iBAAM;IAEJ,AADF,gCAA2B,eACE;IAAA,YAAqB;IAAA,iBAAM;IAEpD,AADF,gCAA2B,gBACK;IAAA,YAAmB;IAAA,iBAAO;IACxD,8JAAqB;IAIzB,AADE,iBAAM,EACF;IACN,iCAA2B;IACzB,aACF;IACF,AADE,iBAAM,EACF;;;;IAfuB,cAA2C;IAA3C,oEAA2C;IACjE,cAAwC;IAAxC,wDAAwC;IAGhB,eAAqB;IAArB,2CAAqB;IAEhB,eAAmB;IAAnB,yCAAmB;IACjD,cAEC;IAFD,4CAEC;IAIH,eACF;IADE,qEACF;;;IAjBN,+BAA2B;IACzB,2KAkBC;IACH,iBAAM;;;IAnBJ,cAkBC;IAlBD,oCAkBC;;;IAIH,+BAAyB;IACvB,yBAAiC;IACjC,4BAAM;IAAA,kCAAkB;IAC1B,AAD0B,iBAAO,EAC3B;;;;IAQV,AADF,+BAA2B,eACQ;IAAA,6BAAa;IAAA,iBAAM;IAElD,AADF,gCAAgC,kBAC4B;IAA7B,2OAAS,yBAAkB,KAAC;IACvD,wBAAgC;IAChC,4BAAM;IAAA,4BAAY;IACpB,AADoB,iBAAO,EAClB;IACT,mCAA2D;IAA9B,2OAAS,oBAAa,KAAK,CAAC,KAAC;IACxD,yBAAgC;IAChC,6BAAM;IAAA,8BAAa;IACrB,AADqB,iBAAO,EACnB;IACT,oCAAgE;IAAnC,4OAAS,oBAAa,UAAU,CAAC,KAAC;IAC7D,yBAAiC;IACjC,6BAAM;IAAA,8BAAa;IACrB,AADqB,iBAAO,EACnB;IACT,oCAAkE;IAArC,4OAAS,oBAAa,YAAY,CAAC,KAAC;IAC/D,yBAA2C;IAC3C,6BAAM;IAAA,2BAAU;IAGtB,AADE,AADE,AADkB,iBAAO,EAChB,EACL,EACF;;;;IAvSJ,AADF,AADF,+BAA6B,cACF,aACI;IAAA,mCAAmB;IAAA,iBAAK;IACnD,6BAA6B;IAAA,sEAAsD;IACrF,AADqF,iBAAI,EACnF;IAEJ,AADF,+BAA4B,iBACsC;IAApC,0NAAS,gBAAS,KAAC;IAC7C,wBAAmC;IACrC,iBAAS;IACT,yIAAyB;IAO7B,AADE,iBAAM,EACF;IAIF,AADF,AADF,gCAAwD,eAClB,eACH;;IAC7B,gCAAgD;IAM9C,AALA,4BAII,gBAMA;IACN,iBAAM;;IACN,gCAAgC;IAAA,aAAoB;IAExD,AADE,AADsD,iBAAM,EACtD,EACF;IAEJ,AADF,gCAAyB,eACG;IAAA,aAAoB;IAAA,iBAAM;IACpD,gCAA4B;IAC1B,yIAAuB;IAMvB,yIAA6B;IAM7B,yIAAyB;IAMzB,yIAA2E;IAQjF,AADE,AADE,iBAAM,EACF,EACF;IAGJ,AADF,gCAAqB,eAC2C;IAA9B,wNAAS,oBAAa,KAAK,CAAC,KAAC;IAC3D,gCAAsB;IACpB,wBAA+B;IACjC,iBAAM;IAEJ,AADF,gCAAyB,eACA;IAAA,aAAa;IAAA,iBAAM;IAC1C,gCAAuB;IAAA,2BAAU;IACnC,AADmC,iBAAM,EACnC;IACN,gCAAuB;IACrB,yBAAuC;IAE3C,AADE,iBAAM,EACF;IACN,gCAAwE;IAAjC,wNAAS,oBAAa,QAAQ,CAAC,KAAC;IACrE,gCAAsB;IACpB,yBAAwC;IAC1C,iBAAM;IAEJ,AADF,gCAAyB,eACA;IAAA,aAAc;IAAA,iBAAM;IAC3C,gCAAuB;IAAA,uBAAM;IAC/B,AAD+B,iBAAM,EAC/B;IAEJ,AADF,gCAA+B,gBACJ;IAAA,aAAoE;IAEjG,AADE,AAD+F,iBAAO,EAChG,EACF;IACN,gCAA2G;IAAnC,wNAAS,oBAAa,UAAU,CAAC,KAAC;IACxG,gCAAsB;IACpB,yBAAiC;IACnC,iBAAM;IAEJ,AADF,gCAAyB,eACA;IAAA,aAAqB;IAAA,iBAAM;IAClD,gCAAuB;IAAA,8BAAa;IACtC,AADsC,iBAAM,EACtC;IACN,wIAA6B;IAK/B,iBAAM;IACN,gCAAmG;IAAlC,wNAAS,oBAAa,SAAS,CAAC,KAAC;IAChG,gCAAsB;IACpB,yBAA+B;IACjC,iBAAM;IAEJ,AADF,gCAAyB,eACA;IAAA,aAAe;IAAA,iBAAM;IAC5C,gCAAuB;IAAA,wBAAO;IAElC,AADE,AADgC,iBAAM,EAChC,EACF;IACN,gCAA8D;IAA9B,wNAAS,iBAAU,QAAQ,CAAC,KAAC;IAC3D,gCAAsB;IACpB,yBAAyC;IAC3C,iBAAM;IAEJ,AADF,gCAAyB,eACA;IAAA,aAAqB;IAAA,iBAAM;IAClD,gCAAuB;IAAA,iCAAgB;IAG7C,AADE,AADE,AADyC,iBAAM,EACzC,EACF,EACF;IAMA,AADF,AADF,AAFF,gCAA0B,eAEM,eACF,eACC;IACvB,wBAA+B;IAC/B,6BAAM;IAAA,mCAAkB;IAC1B,AAD0B,iBAAO,EAC3B;IACN,mCAA2D;IAA9B,2NAAS,oBAAa,KAAK,CAAC,KAAC;IACxD,2BAAS;IAAA,yBAAuC;IAEpD,AADE,iBAAS,EACL;IACN,gCAAwB;IACtB,wIAA8B;IAwB9B,wIAAgC;IAOpC,AADE,iBAAM,EACF;IAIF,AADF,AADF,gCAA+B,eACH,eACC;IACvB,yBAAyC;IACzC,6BAAM;IAAA,kCAAiB;IACzB,AADyB,iBAAO,EAC1B;IACN,iCAA6B;IAAA,2CAA0B;IACzD,AADyD,iBAAO,EAC1D;IACN,gCAAwB;IACtB,yIAA6B;IA4C7B,wIAA+B;IAOnC,AADE,iBAAM,EACF;IAIF,AADF,AADF,gCAAkC,eACN,eACC;IACvB,0BAA6C;IAC7C,8BAAM;IAAA,iCAAe;IAEzB,AADE,AADuB,iBAAO,EACxB,EACF;IACN,iCAAwB;IACtB,0IAAiC;IAuBjC,0IAAmC;IAQzC,AADE,AADE,iBAAM,EACF,EACF;IAEN,2IAAyB;IAwBzB,iCAA6B;IAC3B,0BAAwC;IAEtC,AADF,iCAA4B,eAClB;IAAA,0CAAwB;IAAA,iBAAS;IACzC,kOAGF;IACF,AADE,iBAAM,EACF;;;IA3SF,eAKC;IALD,mDAKC;IAIsB,cAA4B;IAA5B,iDAA4B;IAU7C,eAAoD;;IAMxB,eAAoB;IAApB,6CAAoB;IAI5B,eAAoB;IAApB,6CAAoB;IAE5C,eAKC;IALD,kDAKC;IACD,cAKC;IALD,wDAKC;IACD,cAKC;IALD,oDAKC;IACD,cAKC;IALD,oHAKC;IAWsB,eAAa;IAAb,sCAAa;IAYb,gBAAc;IAAd,uCAAc;IAIZ,eAAoE;IAApE,oHAAoE;IAGjE,cAAuC;IAAvC,uDAAuC;IAK5C,eAAqB;IAArB,8CAAqB;IAG9C,eAIC;IAJD,wDAIC;IAE6B,cAAgC;IAAhC,gDAAgC;IAKrC,eAAe;IAAf,wCAAe;IASf,eAAqB;IAArB,8CAAqB;IAmB5C,gBAuBC;IAvBD,yDAuBC;IACD,cAKC;IALD,2DAKC;IAaD,gBA2CC;IA3CD,wDA2CC;IACD,cAKC;IALD,0DAKC;IAYD,eAsBC;IAtBD,6DAsBC;IACD,cAKC;IALD,+DAKC;IAKP,cAsBC;IAtBD,qDAsBC;;;;IAeC,AADF,gCAA8B,kBACsB;IAAzB,2NAAS,qBAAc,KAAC;IAC/C,yBAAsC;IACtC,kCACF;IACF,AADE,iBAAS,EACL;IACN,+CAGyC;IAAvC,AADA,sPAAe,4BAAqB,KAAC,2OAClB,yBAAkB,KAAC;IACxC,iBAAkB;;;IAHhB,eAAqB;IAArB,0CAAqB;;;IAjUzB,gHAAkC;IAyTlC,6GAA8B;;;IAzT9B,4DAuTC;IAED,cAYC;IAZD,wDAYC;;;;IAID,sDACyC;IAAvC,0PAAsB,sBAAe,KAAC;IACxC,iBAA4B;;;;IAI5B,gDACmC;IAAjC,wOAAgB,sBAAe,KAAC;IAClC,iBAAsB;;;IAItB,qCAAyC;;;;IAtX3C,AADF,AADF,8BAA2B,aACD,aACC;IACrB,uBAA+B;IAC/B,4BAAM;IAAA,wBAAQ;IAElB,AADE,AADgB,iBAAO,EACjB,EACF;IAEJ,AADF,8BAAuB,iBACgF;IAAxC,sKAAS,iBAAU,MAAM,CAAC,wBAAE,iBAAU,KAAC;IAClG,uBAA+B;IAC/B,gCAAwB;IAAA,yBAAQ;IAAA,iBAAO;IACvC,iCAAwB;IAAA,aAAa;IACvC,AADuC,iBAAO,EACrC;IACT,mCAAqH;IAAhD,uKAAS,iBAAU,cAAc,CAAC,wBAAE,iBAAU,KAAC;IAClH,yBAAgC;IAChC,iCAAwB;IAAA,6BAAY;IAAA,iBAAO;IAC3C,iCAAwB;IAAA,aAAoB;IAC9C,AAD8C,iBAAO,EAC5C;IACT,mCAAyG;IAA1C,uKAAS,iBAAU,QAAQ,CAAC,wBAAE,iBAAU,KAAC;IACtG,yBAAyC;IACzC,iCAAwB;IAAA,uBAAM;IAAA,iBAAO;IACrC,iCAAwB;IAAA,aAAc;IACxC,AADwC,iBAAO,EACtC;IACT,mCAAuG;IAAzC,uKAAS,iBAAU,OAAO,CAAC,wBAAE,iBAAU,KAAC;IACpG,yBAAsC;IACtC,iCAAwB;IAAA,gCAAe;IAG7C,AADE,AADE,AADyC,iBAAO,EACvC,EACL,EACF;IAGJ,AADF,gCAA+B,eACA;IAE3B,gGAA0B;IA0U1B,6HAAkC;IAMlC,uHAA4B;IAM5B,sHAA2B;IAI/B,AADE,iBAAM,EACF;IAEN,mCAAwD;IAAtB,6LAAS,kBAAW,KAAC;IACrD,yBAA8E;IAChF,iBAAS;IAET,gCAAqD;IAArB,0LAAS,iBAAU,KAAC;IAAC,iBAAM;;;IAzX9B,eAAmC;IAAnC,mDAAmC;IAGlC,eAAa;IAAb,sCAAa;IAEd,cAA2C;IAA3C,2DAA2C;IAG1C,eAAoB;IAApB,6CAAoB;IAErB,cAAqC;IAArC,qDAAqC;IAGpC,eAAc;IAAd,uCAAc;IAEf,cAAoC;IAApC,oDAAoC;IAU7D,eAwUC;IAxUD,qDAwUC;IAED,cAIC;IAJD,6DAIC;IAED,cAIC;IAJD,uDAIC;IAED,cAEC;IAFD,sDAEC;IAKiB,eAA0B;IAAC,AAA3B,0CAA0B,4BAA2B;;ADjW/E;;;;;;;GAOG;AAQI,IAAM,wBAAwB,GAA9B,MAAM,wBAAyB,SAAQ,qBAAqB;IACzC,gBAAgB,CAAkC;IAEhE,QAAQ,GAAG,IAAI,OAAO,EAAQ,CAAC;IAC/B,EAAE,GAAG,IAAI,QAAQ,EAAE,CAAC;IACpB,GAAG,CAAoB;IAE/B,aAAa;IACN,WAAW,GAAa,UAAU,CAAC;IACnC,UAAU,GAAiB,KAAK,CAAC;IACjC,OAAO,GAAY,MAAM,CAAC;IAC1B,OAAO,GAAG,KAAK,CAAC;IAEvB,8CAA8C;IACvC,gBAAgB,GAAG,CAAC,CAAC;IACrB,UAAU,GAAG,CAAC,CAAC;IAEtB,iBAAiB;IACV,SAAS,GAAG,IAAI,CAAC;IAExB,aAAa;IACN,SAAS,GAAG,CAAC,CAAC;IACd,UAAU,GAAG,CAAC,CAAC;IACf,WAAW,GAAG,CAAC,CAAC;IAChB,iBAAiB,GAAG,CAAC,CAAC;IACtB,WAAW,GAAG,CAAC,CAAC;IAChB,aAAa,GAAG,CAAC,CAAC;IAEzB,mBAAmB;IACZ,OAAO,GAAqB,EAAE,CAAC;IAC/B,cAAc,GAAmB,EAAE,CAAC;IACpC,UAAU,GAAgB,EAAE,CAAC;IAC7B,WAAW,GAAqB,EAAE,CAAC;IAE1C,gBAAgB;IACT,gBAAgB,GAAG,KAAK,CAAC;IACzB,aAAa,GAAG,KAAK,CAAC;IACtB,aAAa,GAAkB,IAAI,CAAC;IAE3C,kEAAkE;IACjD,eAAe,GAAG;QAC/B,IAAI,EAAE,sBAAsB;QAC5B,KAAK,EAAE,SAAS;KACnB,CAAC;IAEF,qDAAqD;IAC7C,iBAAiB,GAAG,IAAI,GAAG,EAA2C,CAAC;IAE/E,mBAAmB;IACZ,iBAAiB,GAAG,KAAK,CAAC;IAC1B,iBAAiB,GAAG,KAAK,CAAC;IAEjC,YAAY,GAAsB;QAC9B,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;IACnB,CAAC;IAED,KAAK,CAAC,QAAQ;QACV,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;IAC1B,CAAC;IAED,WAAW;QACP,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QACrB,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;IAC7B,CAAC;IAED,KAAK,CAAC,sBAAsB,CAAC,KAAmB;QAC5C,OAAO,UAAU,CAAC;IACtB,CAAC;IAED,KAAK,CAAC,oBAAoB,CAAC,KAAmB;QAC1C,OAAO,iBAAiB,CAAC;IAC7B,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,QAAQ;QACjB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;QACxB,IAAI,CAAC;YACD,MAAM,OAAO,CAAC,GAAG,CAAC;gBACd,IAAI,CAAC,WAAW,EAAE;gBAClB,IAAI,CAAC,cAAc,EAAE;gBACrB,IAAI,CAAC,kBAAkB,EAAE;gBACzB,IAAI,CAAC,UAAU,EAAE;gBACjB,IAAI,CAAC,gBAAgB,EAAE;aAC1B,CAAC,CAAC;YACH,IAAI,CAAC,mBAAmB,EAAE,CAAC;QAC/B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,wCAAwC,EAAE,KAAK,CAAC,CAAC;QACnE,CAAC;gBAAS,CAAC;YACP,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;YACvB,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC1B,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;QAC5B,CAAC;IACL,CAAC;IAED;;;OAGG;IACK,UAAU;QACd,MAAM,IAAI,GAAG,iBAAiB,CAAC,QAAQ,CAAC;QACxC,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC;QACjD,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;IACzC,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,WAAW;QACrB,MAAM,EAAE,GAAG,IAAI,OAAO,EAAE,CAAC;QACzB,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,OAAO,CAAiB;YAC5C,UAAU,EAAE,cAAc;YAC1B,OAAO,EAAE,qBAAqB;YAC9B,UAAU,EAAE,eAAe;SAC9B,CAAC,CAAC;QACH,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACjB,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;QAClC,CAAC;IACL,CAAC;IAED;;;OAGG;IACK,cAAc;QAClB,MAAM,IAAI,GAAG,iBAAiB,CAAC,QAAQ,CAAC;QACxC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAE3B,6CAA6C;QAC7C,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAAE,CAAC;QAC/B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YACzB,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;gBAClB,MAAM,QAAQ,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;gBAC9C,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE;oBACvC,IAAI,EAAE,QAAQ,CAAC,IAAI,IAAI,IAAI,CAAC,eAAe,CAAC,IAAI;oBAChD,KAAK,EAAE,QAAQ,CAAC,KAAK,IAAI,IAAI,CAAC,eAAe,CAAC,KAAK;iBACtD,CAAC,CAAC;YACP,CAAC;QACL,CAAC;QAED,MAAM,WAAW,GAAG,IAAI,GAAG,EAAkB,CAAC;QAC9C,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YACzB,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,IAAI,OAAO,CAAC;YAC3C,WAAW,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACpE,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC;QAC5B,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,EAAE;YAC1E,MAAM,MAAM,GAAG,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,eAAe,CAAC;YAC5E,OAAO;gBACH,QAAQ;gBACR,KAAK;gBACL,UAAU,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,GAAG,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC7D,KAAK,EAAE,MAAM,CAAC,KAAK;gBACnB,SAAS,EAAE,MAAM,CAAC,IAAI;aACzB,CAAC;QACN,CAAC,CAAC,CAAC;IACP,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,kBAAkB;QAC5B,MAAM,EAAE,GAAG,IAAI,OAAO,EAAE,CAAC;QAEzB,kBAAkB;QAClB,MAAM,WAAW,GAAG,MAAM,EAAE,CAAC,OAAO,CAAyB;YACzD,UAAU,EAAE,wBAAwB;YACpC,OAAO,EAAE,qBAAqB;YAC9B,OAAO,EAAE,EAAE;YACX,UAAU,EAAE,eAAe;SAC9B,CAAC,CAAC;QAEH,MAAM,UAAU,GAAmB,EAAE,CAAC;QAEtC,IAAI,WAAW,CAAC,OAAO,EAAE,CAAC;YACtB,KAAK,MAAM,GAAG,IAAI,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;gBACjD,UAAU,CAAC,IAAI,CAAC;oBACZ,QAAQ,EAAE,GAAG,CAAC,MAAM,IAAI,aAAa;oBACrC,MAAM,EAAE,MAAM;oBACd,IAAI,EAAE,GAAG,CAAC,MAAM,IAAI,QAAQ;oBAC5B,IAAI,EAAE,GAAG,CAAC,cAAc;oBACxB,KAAK,EAAE,GAAG,CAAC,QAAQ;iBACtB,CAAC,CAAC;YACP,CAAC;QACL,CAAC;QAED,+CAA+C;QAC/C,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;YAC1C,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;gBAC3B,UAAU,CAAC,IAAI,CAAC;oBACZ,QAAQ,EAAE,GAAG,CAAC,KAAK;oBACnB,MAAM,EAAE,SAAS;oBACjB,IAAI,EAAE,GAAG,CAAC,IAAI;oBACd,IAAI,EAAE,GAAG,CAAC,cAAc;oBACxB,KAAK,EAAE,GAAG,CAAC,EAAE;iBAChB,CAAC,CAAC;YACP,CAAC;iBAAM,CAAC;gBACJ,UAAU,CAAC,IAAI,CAAC;oBACZ,QAAQ,EAAE,GAAG,CAAC,KAAK;oBACnB,MAAM,EAAE,SAAS;oBACjB,IAAI,EAAE,GAAG,CAAC,aAAa;oBACvB,IAAI,EAAE,GAAG,CAAC,cAAc;oBACxB,KAAK,EAAE,GAAG,CAAC,EAAE;iBAChB,CAAC,CAAC;YACP,CAAC;QACL,CAAC;QAED,+BAA+B;QAC/B,IAAI,CAAC,cAAc,GAAG,UAAU;aAC3B,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;aACnD,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACtB,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,gBAAgB;QAC1B,2CAA2C;QAC3C,MAAM,UAAU,GAAG,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,cAAc,CAAC,CAAC;QACzE,IAAI,UAAU,EAAE,CAAC;YACb,MAAM,WAAW,GAAG,UAAU,CAAC,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC;YACtE,IAAI,CAAC,iBAAiB,GAAG,WAAW,CAAC,SAAS,CAAC;YAC/C,IAAI,CAAC,iBAAiB,GAAG,WAAW,CAAC,SAAS,CAAC;QACnD,CAAC;IACL,CAAC;IAED;;OAEG;IACK,mBAAmB;QACvB,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,iBAAiB,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;QAE7E,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;QACrC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,MAAM,CAAC;QACzE,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,MAAM,CAAC;QAE3E,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CACvC,CAAC,CAAC,SAAS,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,GAAG,CAC7C,CAAC,MAAM,CAAC;QAET,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAC7C,CAAC,CAAC,MAAM,KAAK,QAAQ;YACrB,CAAC,CAAC,SAAS;YACX,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,GAAG;YAC3B,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,iBAAiB,CAC5C,CAAC,MAAM,CAAC;QAET,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CACzC,CAAC,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,CAAC,CAAC,UAAU,CACzC,CAAC,MAAM,CAAC;QAET,qDAAqD;QACrD,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,OAAO;aAC1B,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,CAAC,UAAU,CAAC;aAClD,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YACX,MAAM,KAAK,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YAClE,MAAM,KAAK,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YAClE,OAAO,KAAK,GAAG,KAAK,CAAC;QACzB,CAAC,CAAC;aACD,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACrB,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,OAAO;QAChB,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;QACtB,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACxB,MAAM,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAE,CAAC;QAC3C,CAAC;IACL,CAAC;IAED;;OAEG;IACI,YAAY,CAAC,SAAuB,KAAK;QAC5C,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC;QACzB,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC;IAC9B,CAAC;IAED;;OAEG;IACI,YAAY;QACf,IAAI,CAAC,WAAW,GAAG,UAAU,CAAC;IAClC,CAAC;IAED;;OAEG;IACI,gBAAgB;QACnB,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;IACjC,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,YAAY,CAAC,MAA0B;QAChD,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACjB,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;QACzB,CAAC;IACL,CAAC;IAED;;OAEG;IACI,oBAAoB;QACvB,IAAI,CAAC,gBAAgB,GAAG,KAAK,CAAC;IAClC,CAAC;IAED;;OAEG;IACI,aAAa,CAAC,GAAmB;QACpC,IAAI,CAAC,aAAa,GAAG,GAAG,CAAC,EAAE,CAAC;QAC5B,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;IAC9B,CAAC;IAED;;OAEG;IACI,aAAa,CAAC,GAAmB;QACpC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;IAC5B,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,YAAY;QACrB,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;IACzB,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,YAAY;QACrB,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;IACzB,CAAC;IAED;;OAEG;IACI,iBAAiB;QACpB,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC;QAC3B,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;IAC9B,CAAC;IAED;;OAEG;IACI,cAAc;QACjB,IAAI,IAAI,CAAC,SAAS,KAAK,CAAC;YAAE,OAAO,GAAG,CAAC;QAErC,IAAI,KAAK,GAAG,GAAG,CAAC;QAEhB,0BAA0B;QAC1B,KAAK,IAAI,CAAC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC;QAElD,2BAA2B;QAC3B,KAAK,IAAI,CAAC,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC;QAExD,sDAAsD;QACtD,KAAK,IAAI,CAAC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC;QAEpD,iCAAiC;QACjC,IAAI,IAAI,CAAC,UAAU,GAAG,EAAE,EAAE,CAAC;YACvB,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC;QACxD,CAAC;QAED,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;IAC1C,CAAC;IAED;;OAEG;IACI,cAAc;QACjB,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;QACpC,IAAI,KAAK,IAAI,EAAE;YAAE,OAAO,oBAAoB,CAAC;QAC7C,IAAI,KAAK,IAAI,EAAE;YAAE,OAAO,eAAe,CAAC;QACxC,IAAI,KAAK,IAAI,EAAE;YAAE,OAAO,iBAAiB,CAAC;QAC1C,OAAO,iBAAiB,CAAC;IAC7B,CAAC;IAED;;OAEG;IACI,cAAc;QACjB,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;QACpC,IAAI,KAAK,IAAI,EAAE;YAAE,OAAO,EAAE,CAAC;QAC3B,IAAI,KAAK,IAAI,EAAE;YAAE,OAAO,gBAAgB,CAAC;QACzC,OAAO,iBAAiB,CAAC;IAC7B,CAAC;IAED;;OAEG;IACI,cAAc,CAAC,KAAa;QAC/B,IAAI,MAAM,GAAG,CAAC,CAAC;QACf,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7B,MAAM,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,GAAG,IAAI,CAAC;QACnD,CAAC;QACD,OAAO,MAAM,CAAC;IAClB,CAAC;IAED;;OAEG;IACI,aAAa,CAAC,MAAsB;QACvC,QAAQ,MAAM,EAAE,CAAC;YACb,KAAK,SAAS,CAAC,CAAC,OAAO,kBAAkB,CAAC;YAC1C,KAAK,SAAS,CAAC,CAAC,OAAO,oBAAoB,CAAC;YAC5C,KAAK,SAAS,CAAC,CAAC,OAAO,iBAAiB,CAAC;YACzC,KAAK,MAAM,CAAC,CAAC,OAAO,oCAAoC,CAAC;YACzD,KAAK,UAAU,CAAC,CAAC,OAAO,+BAA+B,CAAC;YACxD,OAAO,CAAC,CAAC,OAAO,oBAAoB,CAAC;QACzC,CAAC;IACL,CAAC;IAED;;OAEG;IACI,cAAc,CAAC,MAAsB;QACxC,QAAQ,MAAM,EAAE,CAAC;YACb,KAAK,SAAS,CAAC,CAAC,OAAO,gBAAgB,CAAC;YACxC,KAAK,SAAS,CAAC,CAAC,OAAO,gBAAgB,CAAC;YACxC,KAAK,SAAS,CAAC,CAAC,OAAO,gBAAgB,CAAC;YACxC,KAAK,MAAM,CAAC,CAAC,OAAO,aAAa,CAAC;YAClC,KAAK,UAAU,CAAC,CAAC,OAAO,iBAAiB,CAAC;YAC1C,OAAO,CAAC,CAAC,OAAO,EAAE,CAAC;QACvB,CAAC;IACL,CAAC;IAED;;OAEG;IACI,UAAU,CAAC,IAAiB;QAC/B,IAAI,CAAC,IAAI;YAAE,OAAO,OAAO,CAAC;QAE1B,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,EAAE,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;QACtD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC;QACzC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,OAAO,CAAC,CAAC;QACzC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,QAAQ,CAAC,CAAC;QAEzC,IAAI,OAAO,GAAG,CAAC;YAAE,OAAO,UAAU,CAAC;QACnC,IAAI,OAAO,GAAG,EAAE;YAAE,OAAO,GAAG,OAAO,OAAO,CAAC;QAC3C,IAAI,KAAK,GAAG,EAAE;YAAE,OAAO,GAAG,KAAK,OAAO,CAAC;QACvC,IAAI,IAAI,GAAG,CAAC;YAAE,OAAO,GAAG,IAAI,OAAO,CAAC;QAEpC,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,kBAAkB,EAAE,CAAC;IAC/C,CAAC;IAED;;OAEG;IACI,gBAAgB,CAAC,IAAiB;QACrC,IAAI,CAAC,IAAI;YAAE,OAAO,eAAe,CAAC;QAElC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC;QACjC,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,EAAE,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC;QAEjD,IAAI,IAAI,GAAG,CAAC;YAAE,OAAO,SAAS,CAAC;QAE/B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,QAAQ,CAAC,CAAC;QACzC,IAAI,IAAI,KAAK,CAAC;YAAE,OAAO,eAAe,CAAC;QACvC,IAAI,IAAI,KAAK,CAAC;YAAE,OAAO,kBAAkB,CAAC;QAC1C,IAAI,IAAI,GAAG,EAAE;YAAE,OAAO,cAAc,IAAI,OAAO,CAAC;QAEhD,OAAO,WAAW,SAAS,CAAC,kBAAkB,EAAE,EAAE,CAAC;IACvD,CAAC;IAED;;OAEG;IACI,kBAAkB,CAAC,GAAmB;QACzC,IAAI,CAAC,GAAG,CAAC,SAAS;YAAE,OAAO,EAAE,CAAC;QAE9B,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC1C,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,EAAE,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC;QACjD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,QAAQ,CAAC,CAAC;QAEzC,IAAI,IAAI,GAAG,CAAC;YAAE,OAAO,SAAS,CAAC;QAC/B,IAAI,IAAI,GAAG,CAAC;YAAE,OAAO,mBAAmB,CAAC;QACzC,IAAI,IAAI,GAAG,EAAE;YAAE,OAAO,eAAe,CAAC;QACtC,OAAO,EAAE,CAAC;IACd,CAAC;IAED;;OAEG;IACI,eAAe,CAAC,QAAsB;QACzC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC5D,IAAI,GAAG,EAAE,CAAC;YACN,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;QAC5B,CAAC;IACL,CAAC;IAED;;OAEG;IACI,YAAY,CAAC,KAAgB;QAChC,IAAI,CAAC,OAAO,GAAG,QAAQ,CAAC;IAC5B,CAAC;IAED;;OAEG;IACI,SAAS,CAAC,GAAY;QACzB,IAAI,CAAC,OAAO,GAAG,GAAG,CAAC;QACnB,gDAAgD;QAChD,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;YACjB,IAAI,CAAC,WAAW,GAAG,UAAU,CAAC;QAClC,CAAC;IACL,CAAC;IAED;;OAEG;IACI,SAAS;QACZ,IAAI,CAAC,OAAO,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC;IACjC,CAAC;IAED;;OAEG;IACI,QAAQ;QACX,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;IACzB,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,aAAa;QACtB,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;QACxB,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;IAC5B,CAAC;kHA9hBQ,wBAAwB;6DAAxB,wBAAwB;;;;;;YCnDrC,8BAAkH;YAChH,iGAAiB;YAIjB,kFAAkB;YAuYlB,mDAGoC;YAAlC,AADA,iIAAW,wBAAoB,IAAC,4GACtB,0BAAsB,IAAC;YACnC,iBAA2B;YAG3B,gDAKiC;YAA/B,AADA,AADA,wHAAW,kBAAc,IAAC,2GACf,kBAAc,IAAC,yGAChB,uBAAmB,IAAC;YAElC,AADE,iBAAwB,EACpB;;YA1ZiF,AAAvD,uEAAsD,yBAA2B;YAC/G,cAEC;YAFD,wCAEC;YAED,cAoYC;YApYD,yCAoYC;YAIC,cAA4B;YAA5B,8CAA4B;YAO5B,cAAyB;YACzB,AADA,2CAAyB,4BACF;;;ADlWd,wBAAwB;IAPpC,aAAa,CAAC,qBAAqB,EAAE,iBAAiB,CAAC;GAO3C,wBAAwB,CA+hBpC;;iFA/hBY,wBAAwB;cANpC,SAAS;6BACI,KAAK,YACL,sBAAsB;;kBAK/B,SAAS;mBAAC,SAAS;;kFADX,wBAAwB"}
1
+ {"version":3,"file":"api-keys-resource.component.js","sourceRoot":"","sources":["../../src/APIKeys/api-keys-resource.component.ts","../../src/APIKeys/api-keys-resource.component.html"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,SAAS,EAAqB,SAAS,EAAqB,MAAM,eAAe,CAAC;AAC3F,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAEzD,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACzF,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;;;;;;;;;;;;ICJ3B,gCAAoD;;;;IAoDtC,kCAAyD;IAA7B,wOAAS,yBAAkB,KAAC;IACtD,wBAAgC;IAChC,4BAAM;IAAA,gCAAgB;IACxB,AADwB,iBAAO,EACtB;;;;IA4BP,gCAA6D;IAAlC,uOAAS,oBAAa,SAAS,CAAC,KAAC;IAC1D,wBAA8C;IAC9C,YACF;IAAA,iBAAO;;;IADL,eACF;IADE,2DACF;;;;IAGA,gCAAqE;IAAnC,uOAAS,oBAAa,UAAU,CAAC,KAAC;IAClE,wBAAiC;IACjC,YACF;IAAA,iBAAO;;;IADL,eACF;IADE,uEACF;;;;IAGA,gCAAoE;IAArC,uOAAS,oBAAa,YAAY,CAAC,KAAC;IACjE,wBAA2C;IAC3C,YACF;IAAA,iBAAO;;;IADL,eACF;IADE,gEACF;;;IAGA,gCAAwB;IACtB,wBAAwC;IACxC,kCACF;IAAA,iBAAO;;;IAwCT,+BAA+B;IAC7B,wBAAuC;IACzC,iBAAM;;;;IAuCA,+BAAmD;IAA7B,qQAAS,4BAAkB,KAAC;IAChD,+BAA+D;IAC7D,uBAA+B;IACjC,iBAAM;IAEJ,AADF,+BAAsB,cACG;IAAA,YAAa;IAAA,iBAAM;IAExC,AADF,+BAAsB,eACG;IAAA,YAAY;IAAA,iBAAO;IAC1C,gCAAuB;IAAA,aAAyB;IAEpD,AADE,AADkD,iBAAO,EACnD,EACF;IAEJ,AADF,gCAAwB,eACC;IAAA,aAA8B;IAAA,iBAAM;IAC3D,gCAA4D;IAC1D,aACF;IAEJ,AADE,AADE,iBAAM,EACF,EACF;;;;IAhBkB,cAAwC;IAAxC,oDAAwC;IAIrC,eAAa;IAAb,kCAAa;IAEX,eAAY;IAAZ,iCAAY;IACZ,eAAyB;IAAzB,mDAAyB;IAI3B,eAA8B;IAA9B,0DAA8B;IAC7B,cAAmC;IAAnC,2DAAmC;IACzD,cACF;IADE,0EACF;;;IAjBR,+BAAsB;IACpB,yKAmBC;IACH,iBAAM;;;IApBJ,cAmBC;IAnBD,iCAmBC;;;IAIH,+BAAyB;IACvB,uBAA+B;IAC/B,4BAAM;IAAA,gDAAgC;IACxC,AADwC,iBAAO,EACzC;;;;;IAqBE,6BAAc;IACZ,mCASI;IADF,2QAAS,6BAAkB,KAAC;IAR9B,iBASI;;;;;;IANF,cAA0B;;;;;IAkBhC,gCAAsD;IAA7B,yQAAS,6BAAkB,KAAC;IACnD,2BAAqE;IAEnE,AADF,gCAAyB,eACE;IACvB,oBAAgC;IAChC,YACF;IAAA,iBAAM;IACN,gCAA0B;IAAA,YAAqB;IACjD,AADiD,iBAAM,EACjD;IACN,yBAAsD;IACxD,iBAAM;;;IATsB,cAAoC;IAApC,kDAAoC;IAGvD,eAAwB;IAAxB,iCAAwB;IAC3B,cACF;IADE,kDACF;IAC0B,eAAqB;IAArB,oDAAqB;;;IAjCvD,AAFF,+BAAyB,cAEY;;IACjC,+BAA+C;IAC7C,6BAA+E;IAC/E,wLAaC;IACH,iBAAM;;IAEJ,AADF,+BAA0B,cACC;IAAA,YAAqB;IAAA,iBAAM;IACpD,+BAAyB;IAAA,2BAAU;IAEvC,AADE,AADqC,iBAAM,EACrC,EACF;IAEN,iCAA0B;IACxB,2KAYC;IAEL,AADE,iBAAM,EACF;;;IApCA,eAaC;IAbD,gCAaC;IAGwB,eAAqB;IAArB,8CAAqB;IAMhD,eAYC;IAZD,gCAYC;;;IAKL,+BAAyB;IACvB,wBAAyC;IACzC,4BAAM;IAAA,oCAAoB;IAC5B,AAD4B,iBAAO,EAC7B;;;IAyBM,iCAA4B;IAAA,YAAoB;IAAA,iBAAO;;;IAA3B,cAAoB;IAApB,+CAAoB;;;;IATxD,gCAA+D;IAApC,6QAAS,oCAAyB,KAAC;IAC5D,gCAAuE;IACrE,oBAAgD;IAClD,iBAAM;IAEJ,AADF,gCAA2B,eACE;IAAA,YAAqB;IAAA,iBAAM;IAEpD,AADF,gCAA2B,gBACK;IAAA,YAAmB;IAAA,iBAAO;IACxD,8JAAqB;IAIzB,AADE,iBAAM,EACF;IACN,iCAA2B;IACzB,aACF;IACF,AADE,iBAAM,EACF;;;;IAfuB,cAA2C;IAA3C,oEAA2C;IACjE,cAAwC;IAAxC,wDAAwC;IAGhB,eAAqB;IAArB,2CAAqB;IAEhB,eAAmB;IAAnB,yCAAmB;IACjD,cAEC;IAFD,4CAEC;IAIH,eACF;IADE,qEACF;;;IAjBN,+BAA2B;IACzB,2KAkBC;IACH,iBAAM;;;IAnBJ,cAkBC;IAlBD,oCAkBC;;;IAIH,+BAAyB;IACvB,yBAAiC;IACjC,4BAAM;IAAA,kCAAkB;IAC1B,AAD0B,iBAAO,EAC3B;;;;IAQV,AADF,+BAA2B,eACQ;IAAA,6BAAa;IAAA,iBAAM;IAElD,AADF,gCAAgC,kBAC4B;IAA7B,2OAAS,yBAAkB,KAAC;IACvD,wBAAgC;IAChC,4BAAM;IAAA,4BAAY;IACpB,AADoB,iBAAO,EAClB;IACT,mCAA2D;IAA9B,2OAAS,oBAAa,KAAK,CAAC,KAAC;IACxD,yBAAgC;IAChC,6BAAM;IAAA,8BAAa;IACrB,AADqB,iBAAO,EACnB;IACT,oCAAgE;IAAnC,4OAAS,oBAAa,UAAU,CAAC,KAAC;IAC7D,yBAAiC;IACjC,6BAAM;IAAA,8BAAa;IACrB,AADqB,iBAAO,EACnB;IACT,oCAAkE;IAArC,4OAAS,oBAAa,YAAY,CAAC,KAAC;IAC/D,yBAA2C;IAC3C,6BAAM;IAAA,2BAAU;IAGtB,AADE,AADE,AADkB,iBAAO,EAChB,EACL,EACF;;;;IAvSJ,AADF,AADF,+BAA6B,cACF,aACI;IAAA,mCAAmB;IAAA,iBAAK;IACnD,6BAA6B;IAAA,sEAAsD;IACrF,AADqF,iBAAI,EACnF;IAEJ,AADF,+BAA4B,iBACsC;IAApC,0NAAS,gBAAS,KAAC;IAC7C,wBAAmC;IACrC,iBAAS;IACT,yIAAyB;IAO7B,AADE,iBAAM,EACF;IAIF,AADF,AADF,gCAAwD,eAClB,eACH;;IAC7B,gCAAgD;IAM9C,AALA,4BAII,gBAMA;IACN,iBAAM;;IACN,gCAAgC;IAAA,aAAoB;IAExD,AADE,AADsD,iBAAM,EACtD,EACF;IAEJ,AADF,gCAAyB,eACG;IAAA,aAAoB;IAAA,iBAAM;IACpD,gCAA4B;IAC1B,yIAAuB;IAMvB,yIAA6B;IAM7B,yIAAyB;IAMzB,yIAA2E;IAQjF,AADE,AADE,iBAAM,EACF,EACF;IAGJ,AADF,gCAAqB,eAC2C;IAA9B,wNAAS,oBAAa,KAAK,CAAC,KAAC;IAC3D,gCAAsB;IACpB,wBAA+B;IACjC,iBAAM;IAEJ,AADF,gCAAyB,eACA;IAAA,aAAa;IAAA,iBAAM;IAC1C,gCAAuB;IAAA,2BAAU;IACnC,AADmC,iBAAM,EACnC;IACN,gCAAuB;IACrB,yBAAuC;IAE3C,AADE,iBAAM,EACF;IACN,gCAAwE;IAAjC,wNAAS,oBAAa,QAAQ,CAAC,KAAC;IACrE,gCAAsB;IACpB,yBAAwC;IAC1C,iBAAM;IAEJ,AADF,gCAAyB,eACA;IAAA,aAAc;IAAA,iBAAM;IAC3C,gCAAuB;IAAA,uBAAM;IAC/B,AAD+B,iBAAM,EAC/B;IAEJ,AADF,gCAA+B,gBACJ;IAAA,aAAoE;IAEjG,AADE,AAD+F,iBAAO,EAChG,EACF;IACN,gCAA2G;IAAnC,wNAAS,oBAAa,UAAU,CAAC,KAAC;IACxG,gCAAsB;IACpB,yBAAiC;IACnC,iBAAM;IAEJ,AADF,gCAAyB,eACA;IAAA,aAAqB;IAAA,iBAAM;IAClD,gCAAuB;IAAA,8BAAa;IACtC,AADsC,iBAAM,EACtC;IACN,wIAA6B;IAK/B,iBAAM;IACN,gCAAmG;IAAlC,wNAAS,oBAAa,SAAS,CAAC,KAAC;IAChG,gCAAsB;IACpB,yBAA+B;IACjC,iBAAM;IAEJ,AADF,gCAAyB,eACA;IAAA,aAAe;IAAA,iBAAM;IAC5C,gCAAuB;IAAA,wBAAO;IAElC,AADE,AADgC,iBAAM,EAChC,EACF;IACN,gCAA8D;IAA9B,wNAAS,iBAAU,QAAQ,CAAC,KAAC;IAC3D,gCAAsB;IACpB,yBAAyC;IAC3C,iBAAM;IAEJ,AADF,gCAAyB,eACA;IAAA,aAAqB;IAAA,iBAAM;IAClD,gCAAuB;IAAA,iCAAgB;IAG7C,AADE,AADE,AADyC,iBAAM,EACzC,EACF,EACF;IAMA,AADF,AADF,AAFF,gCAA0B,eAEM,eACF,eACC;IACvB,wBAA+B;IAC/B,6BAAM;IAAA,mCAAkB;IAC1B,AAD0B,iBAAO,EAC3B;IACN,mCAA2D;IAA9B,2NAAS,oBAAa,KAAK,CAAC,KAAC;IACxD,2BAAS;IAAA,yBAAuC;IAEpD,AADE,iBAAS,EACL;IACN,gCAAwB;IACtB,wIAA8B;IAwB9B,wIAAgC;IAOpC,AADE,iBAAM,EACF;IAIF,AADF,AADF,gCAA+B,eACH,eACC;IACvB,yBAAyC;IACzC,6BAAM;IAAA,kCAAiB;IACzB,AADyB,iBAAO,EAC1B;IACN,iCAA6B;IAAA,2CAA0B;IACzD,AADyD,iBAAO,EAC1D;IACN,gCAAwB;IACtB,yIAA6B;IA4C7B,wIAA+B;IAOnC,AADE,iBAAM,EACF;IAIF,AADF,AADF,gCAAkC,eACN,eACC;IACvB,0BAA6C;IAC7C,8BAAM;IAAA,iCAAe;IAEzB,AADE,AADuB,iBAAO,EACxB,EACF;IACN,iCAAwB;IACtB,0IAAiC;IAuBjC,0IAAmC;IAQzC,AADE,AADE,iBAAM,EACF,EACF;IAEN,2IAAyB;IAwBzB,iCAA6B;IAC3B,0BAAwC;IAEtC,AADF,iCAA4B,eAClB;IAAA,0CAAwB;IAAA,iBAAS;IACzC,kOAGF;IACF,AADE,iBAAM,EACF;;;IA3SF,eAKC;IALD,mDAKC;IAIsB,cAA4B;IAA5B,iDAA4B;IAU7C,eAAoD;;IAMxB,eAAoB;IAApB,6CAAoB;IAI5B,eAAoB;IAApB,6CAAoB;IAE5C,eAKC;IALD,kDAKC;IACD,cAKC;IALD,wDAKC;IACD,cAKC;IALD,oDAKC;IACD,cAKC;IALD,oHAKC;IAWsB,eAAa;IAAb,sCAAa;IAYb,gBAAc;IAAd,uCAAc;IAIZ,eAAoE;IAApE,oHAAoE;IAGjE,cAAuC;IAAvC,uDAAuC;IAK5C,eAAqB;IAArB,8CAAqB;IAG9C,eAIC;IAJD,wDAIC;IAE6B,cAAgC;IAAhC,gDAAgC;IAKrC,eAAe;IAAf,wCAAe;IASf,eAAqB;IAArB,8CAAqB;IAmB5C,gBAuBC;IAvBD,yDAuBC;IACD,cAKC;IALD,2DAKC;IAaD,gBA2CC;IA3CD,wDA2CC;IACD,cAKC;IALD,0DAKC;IAYD,eAsBC;IAtBD,6DAsBC;IACD,cAKC;IALD,+DAKC;IAKP,cAsBC;IAtBD,qDAsBC;;;;IAeC,AADF,gCAA8B,kBACsB;IAAzB,2NAAS,qBAAc,KAAC;IAC/C,yBAAsC;IACtC,kCACF;IACF,AADE,iBAAS,EACL;IACN,+CAGyC;IAAvC,AADA,sPAAe,4BAAqB,KAAC,2OAClB,yBAAkB,KAAC;IACxC,iBAAkB;;;IAHhB,eAAqB;IAArB,0CAAqB;;;IAjUzB,gHAAkC;IAyTlC,6GAA8B;;;IAzT9B,4DAuTC;IAED,cAYC;IAZD,wDAYC;;;;IAID,sDACyC;IAAvC,0PAAsB,sBAAe,KAAC;IACxC,iBAA4B;;;;IAI5B,gDACmC;IAAjC,wOAAgB,sBAAe,KAAC;IAClC,iBAAsB;;;IAItB,qCAAyC;;;;IAtX3C,AADF,AADF,8BAA2B,aACD,aACC;IACrB,uBAA+B;IAC/B,4BAAM;IAAA,wBAAQ;IAElB,AADE,AADgB,iBAAO,EACjB,EACF;IAEJ,AADF,8BAAuB,iBACgF;IAAxC,sKAAS,iBAAU,MAAM,CAAC,wBAAE,iBAAU,KAAC;IAClG,uBAA+B;IAC/B,gCAAwB;IAAA,yBAAQ;IAAA,iBAAO;IACvC,iCAAwB;IAAA,aAAa;IACvC,AADuC,iBAAO,EACrC;IACT,mCAAqH;IAAhD,uKAAS,iBAAU,cAAc,CAAC,wBAAE,iBAAU,KAAC;IAClH,yBAAgC;IAChC,iCAAwB;IAAA,6BAAY;IAAA,iBAAO;IAC3C,iCAAwB;IAAA,aAAoB;IAC9C,AAD8C,iBAAO,EAC5C;IACT,mCAAyG;IAA1C,uKAAS,iBAAU,QAAQ,CAAC,wBAAE,iBAAU,KAAC;IACtG,yBAAyC;IACzC,iCAAwB;IAAA,uBAAM;IAAA,iBAAO;IACrC,iCAAwB;IAAA,aAAc;IACxC,AADwC,iBAAO,EACtC;IACT,mCAAuG;IAAzC,uKAAS,iBAAU,OAAO,CAAC,wBAAE,iBAAU,KAAC;IACpG,yBAAsC;IACtC,iCAAwB;IAAA,gCAAe;IAG7C,AADE,AADE,AADyC,iBAAO,EACvC,EACL,EACF;IAGJ,AADF,gCAA+B,eACA;IAE3B,gGAA0B;IA0U1B,6HAAkC;IAMlC,uHAA4B;IAM5B,sHAA2B;IAI/B,AADE,iBAAM,EACF;IAEN,mCAAwD;IAAtB,6LAAS,kBAAW,KAAC;IACrD,yBAA8E;IAChF,iBAAS;IAET,gCAAqD;IAArB,0LAAS,iBAAU,KAAC;IAAC,iBAAM;;;IAzX9B,eAAmC;IAAnC,mDAAmC;IAGlC,eAAa;IAAb,sCAAa;IAEd,cAA2C;IAA3C,2DAA2C;IAG1C,eAAoB;IAApB,6CAAoB;IAErB,cAAqC;IAArC,qDAAqC;IAGpC,eAAc;IAAd,uCAAc;IAEf,cAAoC;IAApC,oDAAoC;IAU7D,eAwUC;IAxUD,qDAwUC;IAED,cAIC;IAJD,6DAIC;IAED,cAIC;IAJD,uDAIC;IAED,cAEC;IAFD,sDAEC;IAKiB,eAA0B;IAAC,AAA3B,0CAA0B,4BAA2B;;ADjW/E;;;;;;;GAOG;AAQI,IAAM,wBAAwB,GAA9B,MAAM,wBAAyB,SAAQ,qBAAqB;IACzC,gBAAgB,CAAkC;IAEhE,QAAQ,GAAG,IAAI,OAAO,EAAQ,CAAC;IAC/B,EAAE,GAAG,IAAI,QAAQ,EAAE,CAAC;IACpB,GAAG,CAAoB;IAE/B,aAAa;IACN,WAAW,GAAa,UAAU,CAAC;IACnC,UAAU,GAAiB,KAAK,CAAC;IACjC,OAAO,GAAY,MAAM,CAAC;IAC1B,OAAO,GAAG,KAAK,CAAC;IAEvB,8CAA8C;IACvC,gBAAgB,GAAG,CAAC,CAAC;IACrB,UAAU,GAAG,CAAC,CAAC;IAEtB,iBAAiB;IACV,SAAS,GAAG,IAAI,CAAC;IAExB,aAAa;IACN,SAAS,GAAG,CAAC,CAAC;IACd,UAAU,GAAG,CAAC,CAAC;IACf,WAAW,GAAG,CAAC,CAAC;IAChB,iBAAiB,GAAG,CAAC,CAAC;IACtB,WAAW,GAAG,CAAC,CAAC;IAChB,aAAa,GAAG,CAAC,CAAC;IAEzB,mBAAmB;IACZ,OAAO,GAAqB,EAAE,CAAC;IAC/B,cAAc,GAAmB,EAAE,CAAC;IACpC,UAAU,GAAgB,EAAE,CAAC;IAC7B,WAAW,GAAqB,EAAE,CAAC;IAE1C,gBAAgB;IACT,gBAAgB,GAAG,KAAK,CAAC;IACzB,aAAa,GAAG,KAAK,CAAC;IACtB,aAAa,GAAkB,IAAI,CAAC;IAE3C,kEAAkE;IACjD,eAAe,GAAG;QAC/B,IAAI,EAAE,sBAAsB;QAC5B,KAAK,EAAE,SAAS;KACnB,CAAC;IAEF,qDAAqD;IAC7C,iBAAiB,GAAG,IAAI,GAAG,EAA2C,CAAC;IAE/E,mBAAmB;IACZ,iBAAiB,GAAG,KAAK,CAAC;IAC1B,iBAAiB,GAAG,KAAK,CAAC;IAEjC,YAAY,GAAsB;QAC9B,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;IACnB,CAAC;IAED,KAAK,CAAC,QAAQ;QACV,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;IAC1B,CAAC;IAED,WAAW;QACP,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QACrB,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;IAC7B,CAAC;IAED,KAAK,CAAC,sBAAsB,CAAC,KAAmB;QAC5C,OAAO,UAAU,CAAC;IACtB,CAAC;IAED,KAAK,CAAC,oBAAoB,CAAC,KAAmB;QAC1C,OAAO,iBAAiB,CAAC;IAC7B,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,QAAQ;QACjB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;QACxB,IAAI,CAAC;YACD,MAAM,OAAO,CAAC,GAAG,CAAC;gBACd,IAAI,CAAC,WAAW,EAAE;gBAClB,IAAI,CAAC,cAAc,EAAE;gBACrB,IAAI,CAAC,kBAAkB,EAAE;gBACzB,IAAI,CAAC,UAAU,EAAE;gBACjB,IAAI,CAAC,gBAAgB,EAAE;aAC1B,CAAC,CAAC;YACH,IAAI,CAAC,mBAAmB,EAAE,CAAC;QAC/B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,wCAAwC,EAAE,KAAK,CAAC,CAAC;QACnE,CAAC;gBAAS,CAAC;YACP,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;YACvB,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC1B,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;QAC5B,CAAC;IACL,CAAC;IAED;;;OAGG;IACK,UAAU;QACd,MAAM,IAAI,GAAG,iBAAiB,CAAC,QAAQ,CAAC;QACxC,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC;QACjD,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;IACzC,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,WAAW;QACrB,MAAM,EAAE,GAAG,IAAI,OAAO,EAAE,CAAC;QACzB,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,OAAO,CAAiB;YAC5C,UAAU,EAAE,cAAc;YAC1B,OAAO,EAAE,qBAAqB;YAC9B,UAAU,EAAE,eAAe;SAC9B,CAAC,CAAC;QACH,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACjB,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;QAClC,CAAC;IACL,CAAC;IAED;;;OAGG;IACK,cAAc;QAClB,MAAM,IAAI,GAAG,iBAAiB,CAAC,QAAQ,CAAC;QACxC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAE3B,6CAA6C;QAC7C,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAAE,CAAC;QAC/B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YACzB,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;gBAClB,MAAM,QAAQ,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;gBAC9C,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE;oBACvC,IAAI,EAAE,QAAQ,CAAC,IAAI,IAAI,IAAI,CAAC,eAAe,CAAC,IAAI;oBAChD,KAAK,EAAE,QAAQ,CAAC,KAAK,IAAI,IAAI,CAAC,eAAe,CAAC,KAAK;iBACtD,CAAC,CAAC;YACP,CAAC;QACL,CAAC;QAED,MAAM,WAAW,GAAG,IAAI,GAAG,EAAkB,CAAC;QAC9C,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YACzB,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,IAAI,OAAO,CAAC;YAC3C,WAAW,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACpE,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC;QAC5B,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,EAAE;YAC1E,MAAM,MAAM,GAAG,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,eAAe,CAAC;YAC5E,OAAO;gBACH,QAAQ;gBACR,KAAK;gBACL,UAAU,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,GAAG,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC7D,KAAK,EAAE,MAAM,CAAC,KAAK;gBACnB,SAAS,EAAE,MAAM,CAAC,IAAI;aACzB,CAAC;QACN,CAAC,CAAC,CAAC;IACP,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,kBAAkB;QAC5B,MAAM,EAAE,GAAG,IAAI,OAAO,EAAE,CAAC;QAEzB,kBAAkB;QAClB,MAAM,WAAW,GAAG,MAAM,EAAE,CAAC,OAAO,CAAyB;YACzD,UAAU,EAAE,wBAAwB;YACpC,OAAO,EAAE,qBAAqB;YAC9B,OAAO,EAAE,EAAE;YACX,UAAU,EAAE,eAAe;SAC9B,CAAC,CAAC;QAEH,MAAM,UAAU,GAAmB,EAAE,CAAC;QAEtC,IAAI,WAAW,CAAC,OAAO,EAAE,CAAC;YACtB,KAAK,MAAM,GAAG,IAAI,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;gBACjD,UAAU,CAAC,IAAI,CAAC;oBACZ,QAAQ,EAAE,GAAG,CAAC,MAAM,IAAI,aAAa;oBACrC,MAAM,EAAE,MAAM;oBACd,IAAI,EAAE,GAAG,CAAC,MAAM,IAAI,QAAQ;oBAC5B,IAAI,EAAE,GAAG,CAAC,cAAc;oBACxB,KAAK,EAAE,GAAG,CAAC,QAAQ;iBACtB,CAAC,CAAC;YACP,CAAC;QACL,CAAC;QAED,+CAA+C;QAC/C,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;YAC1C,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;gBAC3B,UAAU,CAAC,IAAI,CAAC;oBACZ,QAAQ,EAAE,GAAG,CAAC,KAAK;oBACnB,MAAM,EAAE,SAAS;oBACjB,IAAI,EAAE,GAAG,CAAC,IAAI;oBACd,IAAI,EAAE,GAAG,CAAC,cAAc;oBACxB,KAAK,EAAE,GAAG,CAAC,EAAE;iBAChB,CAAC,CAAC;YACP,CAAC;iBAAM,CAAC;gBACJ,UAAU,CAAC,IAAI,CAAC;oBACZ,QAAQ,EAAE,GAAG,CAAC,KAAK;oBACnB,MAAM,EAAE,SAAS;oBACjB,IAAI,EAAE,GAAG,CAAC,aAAa;oBACvB,IAAI,EAAE,GAAG,CAAC,cAAc;oBACxB,KAAK,EAAE,GAAG,CAAC,EAAE;iBAChB,CAAC,CAAC;YACP,CAAC;QACL,CAAC;QAED,+BAA+B;QAC/B,IAAI,CAAC,cAAc,GAAG,UAAU;aAC3B,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;aACnD,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACtB,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,gBAAgB;QAC1B,2CAA2C;QAC3C,MAAM,UAAU,GAAG,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,cAAc,CAAC,CAAC;QACzE,IAAI,UAAU,EAAE,CAAC;YACb,MAAM,WAAW,GAAG,UAAU,CAAC,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC;YACtE,IAAI,CAAC,iBAAiB,GAAG,WAAW,CAAC,SAAS,CAAC;YAC/C,IAAI,CAAC,iBAAiB,GAAG,WAAW,CAAC,SAAS,CAAC;QACnD,CAAC;IACL,CAAC;IAED;;OAEG;IACK,mBAAmB;QACvB,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,iBAAiB,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;QAE7E,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;QACrC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,MAAM,CAAC;QACzE,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,MAAM,CAAC;QAE3E,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CACvC,CAAC,CAAC,SAAS,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,GAAG,CAC7C,CAAC,MAAM,CAAC;QAET,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAC7C,CAAC,CAAC,MAAM,KAAK,QAAQ;YACrB,CAAC,CAAC,SAAS;YACX,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,GAAG;YAC3B,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,iBAAiB,CAC5C,CAAC,MAAM,CAAC;QAET,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CACzC,CAAC,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,CAAC,CAAC,UAAU,CACzC,CAAC,MAAM,CAAC;QAET,qDAAqD;QACrD,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,OAAO;aAC1B,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,CAAC,UAAU,CAAC;aAClD,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YACX,MAAM,KAAK,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YAClE,MAAM,KAAK,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YAClE,OAAO,KAAK,GAAG,KAAK,CAAC;QACzB,CAAC,CAAC;aACD,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACrB,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,OAAO;QAChB,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;QACtB,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACxB,MAAM,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAE,CAAC;QAC3C,CAAC;IACL,CAAC;IAED;;OAEG;IACI,YAAY,CAAC,SAAuB,KAAK;QAC5C,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC;QACzB,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC;IAC9B,CAAC;IAED;;OAEG;IACI,YAAY;QACf,IAAI,CAAC,WAAW,GAAG,UAAU,CAAC;IAClC,CAAC;IAED;;OAEG;IACI,gBAAgB;QACnB,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;IACjC,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,YAAY,CAAC,MAA0B;QAChD,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACjB,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;QACzB,CAAC;IACL,CAAC;IAED;;OAEG;IACI,oBAAoB;QACvB,IAAI,CAAC,gBAAgB,GAAG,KAAK,CAAC;IAClC,CAAC;IAED;;OAEG;IACI,aAAa,CAAC,GAAmB;QACpC,IAAI,CAAC,aAAa,GAAG,GAAG,CAAC,EAAE,CAAC;QAC5B,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;IAC9B,CAAC;IAED;;OAEG;IACI,aAAa,CAAC,GAAmB;QACpC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;IAC5B,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,YAAY;QACrB,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;IACzB,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,YAAY;QACrB,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;IACzB,CAAC;IAED;;OAEG;IACI,iBAAiB;QACpB,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC;QAC3B,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;IAC9B,CAAC;IAED;;OAEG;IACI,cAAc;QACjB,IAAI,IAAI,CAAC,SAAS,KAAK,CAAC;YAAE,OAAO,GAAG,CAAC;QAErC,IAAI,KAAK,GAAG,GAAG,CAAC;QAEhB,0BAA0B;QAC1B,KAAK,IAAI,CAAC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC;QAElD,2BAA2B;QAC3B,KAAK,IAAI,CAAC,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC;QAExD,sDAAsD;QACtD,KAAK,IAAI,CAAC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC;QAEpD,iCAAiC;QACjC,IAAI,IAAI,CAAC,UAAU,GAAG,EAAE,EAAE,CAAC;YACvB,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC;QACxD,CAAC;QAED,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;IAC1C,CAAC;IAED;;OAEG;IACI,cAAc;QACjB,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;QACpC,IAAI,KAAK,IAAI,EAAE;YAAE,OAAO,oBAAoB,CAAC;QAC7C,IAAI,KAAK,IAAI,EAAE;YAAE,OAAO,eAAe,CAAC;QACxC,IAAI,KAAK,IAAI,EAAE;YAAE,OAAO,iBAAiB,CAAC;QAC1C,OAAO,iBAAiB,CAAC;IAC7B,CAAC;IAED;;OAEG;IACI,cAAc;QACjB,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;QACpC,IAAI,KAAK,IAAI,EAAE;YAAE,OAAO,EAAE,CAAC;QAC3B,IAAI,KAAK,IAAI,EAAE;YAAE,OAAO,gBAAgB,CAAC;QACzC,OAAO,iBAAiB,CAAC;IAC7B,CAAC;IAED;;OAEG;IACI,cAAc,CAAC,KAAa;QAC/B,IAAI,MAAM,GAAG,CAAC,CAAC;QACf,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7B,MAAM,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,GAAG,IAAI,CAAC;QACnD,CAAC;QACD,OAAO,MAAM,CAAC;IAClB,CAAC;IAED;;OAEG;IACI,aAAa,CAAC,MAAsB;QACvC,QAAQ,MAAM,EAAE,CAAC;YACb,KAAK,SAAS,CAAC,CAAC,OAAO,kBAAkB,CAAC;YAC1C,KAAK,SAAS,CAAC,CAAC,OAAO,oBAAoB,CAAC;YAC5C,KAAK,SAAS,CAAC,CAAC,OAAO,iBAAiB,CAAC;YACzC,KAAK,MAAM,CAAC,CAAC,OAAO,oCAAoC,CAAC;YACzD,KAAK,UAAU,CAAC,CAAC,OAAO,+BAA+B,CAAC;YACxD,OAAO,CAAC,CAAC,OAAO,oBAAoB,CAAC;QACzC,CAAC;IACL,CAAC;IAED;;OAEG;IACI,cAAc,CAAC,MAAsB;QACxC,QAAQ,MAAM,EAAE,CAAC;YACb,KAAK,SAAS,CAAC,CAAC,OAAO,gBAAgB,CAAC;YACxC,KAAK,SAAS,CAAC,CAAC,OAAO,gBAAgB,CAAC;YACxC,KAAK,SAAS,CAAC,CAAC,OAAO,gBAAgB,CAAC;YACxC,KAAK,MAAM,CAAC,CAAC,OAAO,aAAa,CAAC;YAClC,KAAK,UAAU,CAAC,CAAC,OAAO,iBAAiB,CAAC;YAC1C,OAAO,CAAC,CAAC,OAAO,EAAE,CAAC;QACvB,CAAC;IACL,CAAC;IAED;;OAEG;IACI,UAAU,CAAC,IAAiB;QAC/B,IAAI,CAAC,IAAI;YAAE,OAAO,OAAO,CAAC;QAE1B,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,EAAE,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;QACtD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC;QACzC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,OAAO,CAAC,CAAC;QACzC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,QAAQ,CAAC,CAAC;QAEzC,IAAI,OAAO,GAAG,CAAC;YAAE,OAAO,UAAU,CAAC;QACnC,IAAI,OAAO,GAAG,EAAE;YAAE,OAAO,GAAG,OAAO,OAAO,CAAC;QAC3C,IAAI,KAAK,GAAG,EAAE;YAAE,OAAO,GAAG,KAAK,OAAO,CAAC;QACvC,IAAI,IAAI,GAAG,CAAC;YAAE,OAAO,GAAG,IAAI,OAAO,CAAC;QAEpC,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,kBAAkB,EAAE,CAAC;IAC/C,CAAC;IAED;;OAEG;IACI,gBAAgB,CAAC,IAAiB;QACrC,IAAI,CAAC,IAAI;YAAE,OAAO,eAAe,CAAC;QAElC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC;QACjC,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,EAAE,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC;QAEjD,IAAI,IAAI,GAAG,CAAC;YAAE,OAAO,SAAS,CAAC;QAE/B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,QAAQ,CAAC,CAAC;QACzC,IAAI,IAAI,KAAK,CAAC;YAAE,OAAO,eAAe,CAAC;QACvC,IAAI,IAAI,KAAK,CAAC;YAAE,OAAO,kBAAkB,CAAC;QAC1C,IAAI,IAAI,GAAG,EAAE;YAAE,OAAO,cAAc,IAAI,OAAO,CAAC;QAEhD,OAAO,WAAW,SAAS,CAAC,kBAAkB,EAAE,EAAE,CAAC;IACvD,CAAC;IAED;;OAEG;IACI,kBAAkB,CAAC,GAAmB;QACzC,IAAI,CAAC,GAAG,CAAC,SAAS;YAAE,OAAO,EAAE,CAAC;QAE9B,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC1C,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,EAAE,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC;QACjD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,QAAQ,CAAC,CAAC;QAEzC,IAAI,IAAI,GAAG,CAAC;YAAE,OAAO,SAAS,CAAC;QAC/B,IAAI,IAAI,GAAG,CAAC;YAAE,OAAO,mBAAmB,CAAC;QACzC,IAAI,IAAI,GAAG,EAAE;YAAE,OAAO,eAAe,CAAC;QACtC,OAAO,EAAE,CAAC;IACd,CAAC;IAED;;OAEG;IACI,eAAe,CAAC,QAAsB;QACzC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC5D,IAAI,GAAG,EAAE,CAAC;YACN,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;QAC5B,CAAC;IACL,CAAC;IAED;;OAEG;IACI,YAAY,CAAC,KAAgB;QAChC,IAAI,CAAC,OAAO,GAAG,QAAQ,CAAC;IAC5B,CAAC;IAED;;OAEG;IACI,SAAS,CAAC,GAAY;QACzB,IAAI,CAAC,OAAO,GAAG,GAAG,CAAC;QACnB,gDAAgD;QAChD,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;YACjB,IAAI,CAAC,WAAW,GAAG,UAAU,CAAC;QAClC,CAAC;IACL,CAAC;IAED;;OAEG;IACI,SAAS;QACZ,IAAI,CAAC,OAAO,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC;IACjC,CAAC;IAED;;OAEG;IACI,QAAQ;QACX,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;IACzB,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,aAAa;QACtB,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;QACxB,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;IAC5B,CAAC;kHA9hBQ,wBAAwB;6DAAxB,wBAAwB;;;;;;YCnDrC,8BAAkH;YAChH,iGAAiB;YAIjB,kFAAkB;YAuYlB,mDAGoC;YAAlC,AADA,iIAAW,wBAAoB,IAAC,4GACtB,0BAAsB,IAAC;YACnC,iBAA2B;YAG3B,gDAKiC;YAA/B,AADA,AADA,wHAAW,kBAAc,IAAC,2GACf,kBAAc,IAAC,yGAChB,uBAAmB,IAAC;YAElC,AADE,iBAAwB,EACpB;;YA1ZiF,AAAvD,uEAAsD,yBAA2B;YAC/G,cAEC;YAFD,wCAEC;YAED,cAoYC;YApYD,yCAoYC;YAIC,cAA4B;YAA5B,8CAA4B;YAO5B,cAAyB;YACzB,AADA,2CAAyB,4BACF;;;ADlWd,wBAAwB;IAPpC,aAAa,CAAC,qBAAqB,EAAE,iBAAiB,CAAC;GAO3C,wBAAwB,CA+hBpC;;iFA/hBY,wBAAwB;cANpC,SAAS;6BACI,KAAK,YACL,sBAAsB;;kBAK/B,SAAS;mBAAC,SAAS;;kFADX,wBAAwB","sourcesContent":["import { Component, OnInit, OnDestroy, ViewChild, ChangeDetectorRef } from '@angular/core';\nimport { BaseResourceComponent } from '@memberjunction/ng-shared';\nimport { RegisterClass } from '@memberjunction/global';\nimport { Metadata, RunView } from '@memberjunction/core';\nimport { MJAPIKeyEntity, MJAPIScopeEntity, MJAPIKeyUsageLogEntity, MJAPIApplicationEntity, ResourceData } from '@memberjunction/core-entities';\nimport { APIKeysEngineBase, parseAPIScopeUIConfig } from '@memberjunction/api-keys-base';\nimport { Subject } from 'rxjs';\nimport { APIKeyFilter, APIKeyListComponent } from './api-key-list.component';\nimport { APIKeyCreateResult } from './api-key-create-dialog.component';\n\n/** Activity types for recent activity display */\ntype ActivityAction = 'Created' | 'Updated' | 'Revoked' | 'Used' | 'Extended';\n\n/** Interface for recent activity items */\ninterface ActivityItem {\n keyLabel: string;\n action: ActivityAction;\n user: string;\n date: Date;\n keyId: string;\n}\n\n/** Interface for scope statistics */\ninterface ScopeStat {\n category: string;\n count: number;\n percentage: number;\n color: string;\n iconClass: string;\n}\n\n/** Current view type */\ntype ViewType = 'overview' | 'list';\n\n/** Main tab type */\ntype MainTab = 'keys' | 'applications' | 'scopes' | 'usage';\n/**\n * API Keys Resource Component\n * Provides management interface for MJ API Keys including:\n * - Overview statistics and health monitoring\n * - Key listing with status filters\n * - Key creation and revocation\n * - Usage tracking and analytics\n */\n@RegisterClass(BaseResourceComponent, 'APIKeysResource')\n@Component({\n standalone: false,\n selector: 'mj-api-keys-resource',\n templateUrl: './api-keys-resource.component.html',\n styleUrls: ['./api-keys-resource.component.css']\n})\nexport class APIKeysResourceComponent extends BaseResourceComponent implements OnInit, OnDestroy {\n @ViewChild('keyList') keyListComponent: APIKeyListComponent | undefined;\n\n private destroy$ = new Subject<void>();\n private md = new Metadata();\n private cdr: ChangeDetectorRef;\n\n // View state\n public CurrentView: ViewType = 'overview';\n public ListFilter: APIKeyFilter = 'all';\n public MainTab: MainTab = 'keys';\n public NavOpen = false;\n\n // Application and scope counts for tab badges\n public ApplicationCount = 0;\n public ScopeCount = 0;\n\n // Loading states\n public IsLoading = true;\n\n // Statistics\n public TotalKeys = 0;\n public ActiveKeys = 0;\n public RevokedKeys = 0;\n public ExpiringSoonCount = 0;\n public ExpiredKeys = 0;\n public NeverUsedKeys = 0;\n\n // Data collections\n public APIKeys: MJAPIKeyEntity[] = [];\n public RecentActivity: ActivityItem[] = [];\n public ScopeStats: ScopeStat[] = [];\n public TopUsedKeys: MJAPIKeyEntity[] = [];\n\n // Dialog states\n public ShowCreateDialog = false;\n public ShowEditPanel = false;\n public SelectedKeyId: string | null = null;\n\n // Default UI config for categories without explicit configuration\n private readonly defaultUIConfig = {\n icon: 'fa-solid fa-ellipsis',\n color: '#6b7280'\n };\n\n // Dynamic category UI configs built from root scopes\n private categoryUIConfigs = new Map<string, { icon: string; color: string }>();\n\n // User permissions\n public UserCanCreateKeys = false;\n public UserCanRevokeKeys = false;\n\n constructor(cdr: ChangeDetectorRef) {\n super();\n this.cdr = cdr;\n }\n\n async ngOnInit(): Promise<void> {\n await this.loadData();\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n async GetResourceDisplayName(_data: ResourceData): Promise<string> {\n return 'API Keys';\n }\n\n async GetResourceIconClass(_data: ResourceData): Promise<string> {\n return 'fa-solid fa-key';\n }\n\n /**\n * Load all dashboard data\n */\n public async loadData(): Promise<void> {\n this.IsLoading = true;\n this.cdr.markForCheck();\n try {\n await Promise.all([\n this.loadAPIKeys(),\n this.loadScopeStats(),\n this.loadRecentActivity(),\n this.loadCounts(),\n this.checkPermissions()\n ]);\n this.calculateStatistics();\n } catch (error) {\n console.error('Error loading API Keys dashboard data:', error);\n } finally {\n this.IsLoading = false;\n this.NotifyLoadComplete();\n this.cdr.markForCheck();\n }\n }\n\n /**\n * Load application and scope counts for tab badges.\n * Uses cached data from APIKeysEngineBase.\n */\n private loadCounts(): void {\n const base = APIKeysEngineBase.Instance;\n this.ApplicationCount = base.Applications.length;\n this.ScopeCount = base.Scopes.length;\n }\n\n /**\n * Load all API keys\n */\n private async loadAPIKeys(): Promise<void> {\n const rv = new RunView();\n const result = await rv.RunView<MJAPIKeyEntity>({\n EntityName: 'MJ: API Keys',\n OrderBy: '__mj_CreatedAt DESC',\n ResultType: 'entity_object'\n });\n if (result.Success) {\n this.APIKeys = result.Results;\n }\n }\n\n /**\n * Load scope statistics by category.\n * Uses cached data from APIKeysEngineBase.\n */\n private loadScopeStats(): void {\n const base = APIKeysEngineBase.Instance;\n const scopes = base.Scopes;\n\n // Build category UI configs from root scopes\n this.categoryUIConfigs.clear();\n for (const scope of scopes) {\n if (!scope.ParentID) {\n const uiConfig = parseAPIScopeUIConfig(scope);\n this.categoryUIConfigs.set(scope.Category, {\n icon: uiConfig.icon || this.defaultUIConfig.icon,\n color: uiConfig.color || this.defaultUIConfig.color\n });\n }\n }\n\n const categoryMap = new Map<string, number>();\n for (const scope of scopes) {\n const category = scope.Category || 'Other';\n categoryMap.set(category, (categoryMap.get(category) || 0) + 1);\n }\n\n const total = scopes.length;\n this.ScopeStats = Array.from(categoryMap.entries()).map(([category, count]) => {\n const config = this.categoryUIConfigs.get(category) || this.defaultUIConfig;\n return {\n category,\n count,\n percentage: total > 0 ? Math.round((count / total) * 100) : 0,\n color: config.color,\n iconClass: config.icon\n };\n });\n }\n\n /**\n * Load recent activity from usage logs and key changes\n */\n private async loadRecentActivity(): Promise<void> {\n const rv = new RunView();\n\n // Load usage logs\n const usageResult = await rv.RunView<MJAPIKeyUsageLogEntity>({\n EntityName: 'MJ: API Key Usage Logs',\n OrderBy: '__mj_CreatedAt DESC',\n MaxRows: 20,\n ResultType: 'entity_object'\n });\n\n const activities: ActivityItem[] = [];\n\n if (usageResult.Success) {\n for (const log of usageResult.Results.slice(0, 10)) {\n activities.push({\n keyLabel: log.APIKey || 'Unknown Key',\n action: 'Used',\n user: log.APIKey || 'System',\n date: log.__mj_CreatedAt,\n keyId: log.APIKeyID\n });\n }\n }\n\n // Add key creation/update activities from keys\n for (const key of this.APIKeys.slice(0, 10)) {\n if (key.Status === 'Revoked') {\n activities.push({\n keyLabel: key.Label,\n action: 'Revoked',\n user: key.User,\n date: key.__mj_UpdatedAt,\n keyId: key.ID\n });\n } else {\n activities.push({\n keyLabel: key.Label,\n action: 'Created',\n user: key.CreatedByUser,\n date: key.__mj_CreatedAt,\n keyId: key.ID\n });\n }\n }\n\n // Sort by date and take top 10\n this.RecentActivity = activities\n .sort((a, b) => b.date.getTime() - a.date.getTime())\n .slice(0, 10);\n }\n\n /**\n * Check user permissions\n */\n private async checkPermissions(): Promise<void> {\n // Check if user can create/manage API keys\n const entityInfo = this.md.Entities.find(e => e.Name === 'MJ: API Keys');\n if (entityInfo) {\n const permissions = entityInfo.GetUserPermisions(this.md.CurrentUser);\n this.UserCanCreateKeys = permissions.CanCreate;\n this.UserCanRevokeKeys = permissions.CanUpdate;\n }\n }\n\n /**\n * Calculate dashboard statistics from loaded data\n */\n private calculateStatistics(): void {\n const now = new Date();\n const thirtyDaysFromNow = new Date(now.getTime() + 30 * 24 * 60 * 60 * 1000);\n\n this.TotalKeys = this.APIKeys.length;\n this.ActiveKeys = this.APIKeys.filter(k => k.Status === 'Active').length;\n this.RevokedKeys = this.APIKeys.filter(k => k.Status === 'Revoked').length;\n\n this.ExpiredKeys = this.APIKeys.filter(k =>\n k.ExpiresAt && new Date(k.ExpiresAt) < now\n ).length;\n\n this.ExpiringSoonCount = this.APIKeys.filter(k =>\n k.Status === 'Active' &&\n k.ExpiresAt &&\n new Date(k.ExpiresAt) > now &&\n new Date(k.ExpiresAt) < thirtyDaysFromNow\n ).length;\n\n this.NeverUsedKeys = this.APIKeys.filter(k =>\n k.Status === 'Active' && !k.LastUsedAt\n ).length;\n\n // Get top used keys (most recently used active keys)\n this.TopUsedKeys = this.APIKeys\n .filter(k => k.Status === 'Active' && k.LastUsedAt)\n .sort((a, b) => {\n const aDate = a.LastUsedAt ? new Date(a.LastUsedAt).getTime() : 0;\n const bDate = b.LastUsedAt ? new Date(b.LastUsedAt).getTime() : 0;\n return bDate - aDate;\n })\n .slice(0, 5);\n }\n\n /**\n * Refresh all data\n */\n public async refresh(): Promise<void> {\n await this.loadData();\n if (this.keyListComponent) {\n await this.keyListComponent.loadKeys();\n }\n }\n\n /**\n * Switch to list view\n */\n public showListView(filter: APIKeyFilter = 'all'): void {\n this.ListFilter = filter;\n this.CurrentView = 'list';\n }\n\n /**\n * Switch to overview\n */\n public showOverview(): void {\n this.CurrentView = 'overview';\n }\n\n /**\n * Open create dialog\n */\n public openCreateDialog(): void {\n this.ShowCreateDialog = true;\n }\n\n /**\n * Handle key created\n */\n public async onKeyCreated(result: APIKeyCreateResult): Promise<void> {\n if (result.success) {\n await this.refresh();\n }\n }\n\n /**\n * Handle create dialog closed\n */\n public onCreateDialogClosed(): void {\n this.ShowCreateDialog = false;\n }\n\n /**\n * Open edit panel for a key\n */\n public openEditPanel(key: MJAPIKeyEntity): void {\n this.SelectedKeyId = key.ID;\n this.ShowEditPanel = true;\n }\n\n /**\n * Handle key from list selected\n */\n public onKeySelected(key: MJAPIKeyEntity): void {\n this.openEditPanel(key);\n }\n\n /**\n * Handle key updated\n */\n public async onKeyUpdated(): Promise<void> {\n await this.refresh();\n }\n\n /**\n * Handle key revoked\n */\n public async onKeyRevoked(): Promise<void> {\n await this.refresh();\n }\n\n /**\n * Handle edit panel closed\n */\n public onEditPanelClosed(): void {\n this.ShowEditPanel = false;\n this.SelectedKeyId = null;\n }\n\n /**\n * Get health score (0-100) based on key status\n */\n public getHealthScore(): number {\n if (this.TotalKeys === 0) return 100;\n\n let score = 100;\n\n // Deduct for expired keys\n score -= (this.ExpiredKeys / this.TotalKeys) * 40;\n\n // Deduct for expiring soon\n score -= (this.ExpiringSoonCount / this.TotalKeys) * 20;\n\n // Deduct for never used active keys (might be leaked)\n score -= (this.NeverUsedKeys / this.TotalKeys) * 10;\n\n // Deduct if too many active keys\n if (this.ActiveKeys > 20) {\n score -= Math.min(15, (this.ActiveKeys - 20) * 0.5);\n }\n\n return Math.max(0, Math.round(score));\n }\n\n /**\n * Get health label based on score\n */\n public getHealthLabel(): string {\n const score = this.getHealthScore();\n if (score >= 90) return 'Excellent Security';\n if (score >= 75) return 'Good Security';\n if (score >= 50) return 'Needs Attention';\n return 'Critical Issues';\n }\n\n /**\n * Get CSS class for health banner\n */\n public getHealthClass(): string {\n const score = this.getHealthScore();\n if (score >= 75) return '';\n if (score >= 50) return 'health-warning';\n return 'health-critical';\n }\n\n /**\n * Get donut chart offset for segment\n */\n public getDonutOffset(index: number): number {\n let offset = 0;\n for (let i = 0; i < index; i++) {\n offset -= this.ScopeStats[i].percentage * 2.51;\n }\n return offset;\n }\n\n /**\n * Get activity icon based on action\n */\n public getActionIcon(action: ActivityAction): string {\n switch (action) {\n case 'Created': return 'fa-solid fa-plus';\n case 'Updated': return 'fa-solid fa-pencil';\n case 'Revoked': return 'fa-solid fa-ban';\n case 'Used': return 'fa-solid fa-arrow-right-to-bracket';\n case 'Extended': return 'fa-solid fa-clock-rotate-left';\n default: return 'fa-solid fa-circle';\n }\n }\n\n /**\n * Get CSS class for activity action\n */\n public getActionClass(action: ActivityAction): string {\n switch (action) {\n case 'Created': return 'action-created';\n case 'Updated': return 'action-updated';\n case 'Revoked': return 'action-revoked';\n case 'Used': return 'action-used';\n case 'Extended': return 'action-extended';\n default: return '';\n }\n }\n\n /**\n * Format date for display\n */\n public formatDate(date: Date | null): string {\n if (!date) return 'Never';\n\n const now = new Date();\n const diff = now.getTime() - new Date(date).getTime();\n const minutes = Math.floor(diff / 60000);\n const hours = Math.floor(diff / 3600000);\n const days = Math.floor(diff / 86400000);\n\n if (minutes < 1) return 'Just now';\n if (minutes < 60) return `${minutes}m ago`;\n if (hours < 24) return `${hours}h ago`;\n if (days < 7) return `${days}d ago`;\n\n return new Date(date).toLocaleDateString();\n }\n\n /**\n * Format expiration for display\n */\n public formatExpiration(date: Date | null): string {\n if (!date) return 'Never expires';\n\n const now = new Date();\n const expiresAt = new Date(date);\n const diff = expiresAt.getTime() - now.getTime();\n\n if (diff < 0) return 'Expired';\n\n const days = Math.floor(diff / 86400000);\n if (days === 0) return 'Expires today';\n if (days === 1) return 'Expires tomorrow';\n if (days < 30) return `Expires in ${days} days`;\n\n return `Expires ${expiresAt.toLocaleDateString()}`;\n }\n\n /**\n * Get expiration status class\n */\n public getExpirationClass(key: MJAPIKeyEntity): string {\n if (!key.ExpiresAt) return '';\n\n const now = new Date();\n const expiresAt = new Date(key.ExpiresAt);\n const diff = expiresAt.getTime() - now.getTime();\n const days = Math.floor(diff / 86400000);\n\n if (diff < 0) return 'expired';\n if (days < 7) return 'expiring-critical';\n if (days < 30) return 'expiring-soon';\n return '';\n }\n\n /**\n * View activity for a key\n */\n public onActivityClick(activity: ActivityItem): void {\n const key = this.APIKeys.find(k => k.ID === activity.keyId);\n if (key) {\n this.openEditPanel(key);\n }\n }\n\n /**\n * View scope details - now navigates to scopes tab\n */\n public onScopeClick(_stat: ScopeStat): void {\n this.MainTab = 'scopes';\n }\n\n /**\n * Switch to a main tab\n */\n public switchTab(tab: MainTab): void {\n this.MainTab = tab;\n // Reset to overview when switching back to keys\n if (tab === 'keys') {\n this.CurrentView = 'overview';\n }\n }\n\n /**\n * Toggle mobile navigation\n */\n public toggleNav(): void {\n this.NavOpen = !this.NavOpen;\n }\n\n /**\n * Close mobile navigation\n */\n public closeNav(): void {\n this.NavOpen = false;\n }\n\n /**\n * Handle updates from child panels\n */\n public async onDataUpdated(): Promise<void> {\n await this.loadCounts();\n this.cdr.markForCheck();\n }\n}\n","<div class=\"api-keys-dashboard\" [class.panel-open]=\"ShowCreateDialog || ShowEditPanel\" [class.nav-open]=\"NavOpen\">\n @if (IsLoading) {\n <mj-loading text=\"Loading API Keys...\"></mj-loading>\n }\n\n @if (!IsLoading) {\n <!-- Left Navigation Sidebar -->\n <div class=\"dashboard-nav\">\n <div class=\"nav-header\">\n <div class=\"nav-title\">\n <i class=\"fa-solid fa-key\"></i>\n <span>API Keys</span>\n </div>\n </div>\n <div class=\"nav-items\">\n <button class=\"nav-item\" [class.active]=\"MainTab === 'keys'\" (click)=\"switchTab('keys'); closeNav()\">\n <i class=\"fa-solid fa-key\"></i>\n <span class=\"nav-label\">API Keys</span>\n <span class=\"nav-badge\">{{TotalKeys}}</span>\n </button>\n <button class=\"nav-item\" [class.active]=\"MainTab === 'applications'\" (click)=\"switchTab('applications'); closeNav()\">\n <i class=\"fa-solid fa-cube\"></i>\n <span class=\"nav-label\">Applications</span>\n <span class=\"nav-badge\">{{ApplicationCount}}</span>\n </button>\n <button class=\"nav-item\" [class.active]=\"MainTab === 'scopes'\" (click)=\"switchTab('scopes'); closeNav()\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <span class=\"nav-label\">Scopes</span>\n <span class=\"nav-badge\">{{ScopeCount}}</span>\n </button>\n <button class=\"nav-item\" [class.active]=\"MainTab === 'usage'\" (click)=\"switchTab('usage'); closeNav()\">\n <i class=\"fa-solid fa-chart-line\"></i>\n <span class=\"nav-label\">Usage Analytics</span>\n </button>\n </div>\n </div>\n <!-- Main Content Area -->\n <div class=\"dashboard-content\">\n <div class=\"content-wrapper\">\n <!-- Keys Tab Content -->\n @if (MainTab === 'keys') {\n <!-- Overview View -->\n @if (CurrentView === 'overview') {\n <!-- Header with Actions -->\n <div class=\"overview-header\">\n <div class=\"header-left\">\n <h2 class=\"overview-title\">API Keys Management</h2>\n <p class=\"overview-subtitle\">Manage API keys for external integrations and services</p>\n </div>\n <div class=\"header-actions\">\n <button class=\"btn-refresh\" (click)=\"refresh()\" title=\"Refresh\">\n <i class=\"fa-solid fa-refresh\"></i>\n </button>\n @if (UserCanCreateKeys) {\n <button class=\"btn-primary\" (click)=\"openCreateDialog()\">\n <i class=\"fa-solid fa-plus\"></i>\n <span>Generate New Key</span>\n </button>\n }\n </div>\n </div>\n <!-- Health Score Banner -->\n <div class=\"health-banner\" [ngClass]=\"getHealthClass()\">\n <div class=\"health-score-container\">\n <div class=\"health-score-ring\">\n <svg viewBox=\"0 0 36 36\" class=\"circular-chart\">\n <path class=\"circle-bg\"\n d=\"M18 2.0845\n a 15.9155 15.9155 0 0 1 0 31.831\n a 15.9155 15.9155 0 0 1 0 -31.831\"\n />\n <path class=\"circle\"\n [attr.stroke-dasharray]=\"getHealthScore() + ', 100'\"\n d=\"M18 2.0845\n a 15.9155 15.9155 0 0 1 0 31.831\n a 15.9155 15.9155 0 0 1 0 -31.831\"\n />\n </svg>\n <div class=\"health-score-value\">{{getHealthScore()}}</div>\n </div>\n </div>\n <div class=\"health-info\">\n <div class=\"health-label\">{{getHealthLabel()}}</div>\n <div class=\"health-details\">\n @if (ExpiredKeys > 0) {\n <span class=\"health-alert\" (click)=\"showListView('expired')\">\n <i class=\"fa-solid fa-circle-exclamation\"></i>\n {{ExpiredKeys}} expired\n </span>\n }\n @if (ExpiringSoonCount > 0) {\n <span class=\"health-warning-text\" (click)=\"showListView('expiring')\">\n <i class=\"fa-solid fa-clock\"></i>\n {{ExpiringSoonCount}} expiring soon\n </span>\n }\n @if (NeverUsedKeys > 0) {\n <span class=\"health-info-text\" (click)=\"showListView('never-used')\">\n <i class=\"fa-solid fa-question-circle\"></i>\n {{NeverUsedKeys}} never used\n </span>\n }\n @if (ExpiredKeys === 0 && ExpiringSoonCount === 0 && NeverUsedKeys === 0) {\n <span class=\"health-ok\">\n <i class=\"fa-solid fa-check-circle\"></i>\n All keys healthy\n </span>\n }\n </div>\n </div>\n </div>\n <!-- KPI Cards Row -->\n <div class=\"kpi-row\">\n <div class=\"kpi-card clickable\" (click)=\"showListView('all')\">\n <div class=\"kpi-icon\">\n <i class=\"fa-solid fa-key\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{TotalKeys}}</div>\n <div class=\"kpi-label\">Total Keys</div>\n </div>\n <div class=\"kpi-trend\">\n <i class=\"fa-solid fa-arrow-right\"></i>\n </div>\n </div>\n <div class=\"kpi-card active clickable\" (click)=\"showListView('active')\">\n <div class=\"kpi-icon\">\n <i class=\"fa-solid fa-check-circle\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ActiveKeys}}</div>\n <div class=\"kpi-label\">Active</div>\n </div>\n <div class=\"kpi-trend success\">\n <span class=\"percentage\">{{TotalKeys > 0 ? (ActiveKeys / TotalKeys * 100).toFixed(0) : 100}}%</span>\n </div>\n </div>\n <div class=\"kpi-card clickable\" [class.warning]=\"ExpiringSoonCount > 0\" (click)=\"showListView('expiring')\">\n <div class=\"kpi-icon\">\n <i class=\"fa-solid fa-clock\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ExpiringSoonCount}}</div>\n <div class=\"kpi-label\">Expiring Soon</div>\n </div>\n @if (ExpiringSoonCount > 0) {\n <div class=\"kpi-trend warning\">\n <i class=\"fa-solid fa-arrow-right\"></i>\n </div>\n }\n </div>\n <div class=\"kpi-card clickable\" [class.danger]=\"RevokedKeys > 0\" (click)=\"showListView('revoked')\">\n <div class=\"kpi-icon\">\n <i class=\"fa-solid fa-ban\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{RevokedKeys}}</div>\n <div class=\"kpi-label\">Revoked</div>\n </div>\n </div>\n <div class=\"kpi-card clickable\" (click)=\"switchTab('scopes')\">\n <div class=\"kpi-icon\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ScopeStats.length}}</div>\n <div class=\"kpi-label\">Scope Categories</div>\n </div>\n </div>\n </div>\n <!-- Content Grid -->\n <div class=\"content-grid\">\n <!-- Recently Used Keys -->\n <div class=\"panel keys-panel\">\n <div class=\"panel-header\">\n <div class=\"panel-title\">\n <i class=\"fa-solid fa-key\"></i>\n <span>Recently Used Keys</span>\n </div>\n <button class=\"panel-action\" (click)=\"showListView('all')\">\n View All <i class=\"fa-solid fa-arrow-right\"></i>\n </button>\n </div>\n <div class=\"panel-body\">\n @if (TopUsedKeys.length > 0) {\n <div class=\"key-list\">\n @for (key of TopUsedKeys; track key) {\n <div class=\"key-item\" (click)=\"openEditPanel(key)\">\n <div class=\"key-icon\" [class.active]=\"key.Status === 'Active'\">\n <i class=\"fa-solid fa-key\"></i>\n </div>\n <div class=\"key-info\">\n <div class=\"key-label\">{{key.Label}}</div>\n <div class=\"key-meta\">\n <span class=\"key-user\">{{key.User}}</span>\n <span class=\"key-hash\">...{{key.Hash.slice(-8)}}</span>\n </div>\n </div>\n <div class=\"key-status\">\n <div class=\"last-used\">{{formatDate(key.LastUsedAt)}}</div>\n <div class=\"expiration\" [ngClass]=\"getExpirationClass(key)\">\n {{formatExpiration(key.ExpiresAt)}}\n </div>\n </div>\n </div>\n }\n </div>\n }\n @if (TopUsedKeys.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-key\"></i>\n <span>No active keys with recent usage</span>\n </div>\n }\n </div>\n </div>\n <!-- Scope Categories -->\n <div class=\"panel scope-panel\">\n <div class=\"panel-header\">\n <div class=\"panel-title\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <span>Permission Scopes</span>\n </div>\n <span class=\"panel-subtitle\">Available scope categories</span>\n </div>\n <div class=\"panel-body\">\n @if (ScopeStats.length > 0) {\n <div class=\"scope-chart\">\n <!-- Visual Donut Chart -->\n <div class=\"donut-chart-container\">\n <svg viewBox=\"0 0 100 100\" class=\"donut-chart\">\n <circle cx=\"50\" cy=\"50\" r=\"40\" fill=\"none\" stroke=\"#e5e7eb\" stroke-width=\"12\"/>\n @for (stat of ScopeStats; track stat; let i = $index) {\n <ng-container>\n <circle\n cx=\"50\" cy=\"50\" r=\"40\"\n fill=\"none\"\n [attr.stroke]=\"stat.color\"\n stroke-width=\"12\"\n [attr.stroke-dasharray]=\"stat.percentage * 2.51 + ' ' + (251 - stat.percentage * 2.51)\"\n [attr.stroke-dashoffset]=\"getDonutOffset(i)\"\n class=\"donut-segment\"\n (click)=\"onScopeClick(stat)\"\n />\n </ng-container>\n }\n </svg>\n <div class=\"donut-center\">\n <div class=\"donut-total\">{{ScopeStats.length}}</div>\n <div class=\"donut-label\">Categories</div>\n </div>\n </div>\n <!-- Legend -->\n <div class=\"scope-legend\">\n @for (stat of ScopeStats; track stat) {\n <div class=\"legend-item\" (click)=\"onScopeClick(stat)\">\n <div class=\"legend-color\" [style.backgroundColor]=\"stat.color\"></div>\n <div class=\"legend-info\">\n <div class=\"legend-name\">\n <i [class]=\"stat.iconClass\"></i>\n {{stat.category}}\n </div>\n <div class=\"legend-value\">{{stat.count}} scopes</div>\n </div>\n <i class=\"fa-solid fa-chevron-right legend-arrow\"></i>\n </div>\n }\n </div>\n </div>\n }\n @if (ScopeStats.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <span>No scopes configured</span>\n </div>\n }\n </div>\n </div>\n <!-- Recent Activity -->\n <div class=\"panel activity-panel\">\n <div class=\"panel-header\">\n <div class=\"panel-title\">\n <i class=\"fa-solid fa-clock-rotate-left\"></i>\n <span>Recent Activity</span>\n </div>\n </div>\n <div class=\"panel-body\">\n @if (RecentActivity.length > 0) {\n <div class=\"activity-list\">\n @for (activity of RecentActivity; track activity) {\n <div class=\"activity-item\" (click)=\"onActivityClick(activity)\">\n <div class=\"activity-icon\" [ngClass]=\"getActionClass(activity.action)\">\n <i [class]=\"getActionIcon(activity.action)\"></i>\n </div>\n <div class=\"activity-info\">\n <div class=\"activity-name\">{{activity.keyLabel}}</div>\n <div class=\"activity-meta\">\n <span class=\"activity-action\">{{activity.action}}</span>\n @if (activity.user) {\n <span class=\"activity-user\">by {{activity.user}}</span>\n }\n </div>\n </div>\n <div class=\"activity-time\">\n {{formatDate(activity.date)}}\n </div>\n </div>\n }\n </div>\n }\n @if (RecentActivity.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-inbox\"></i>\n <span>No recent activity</span>\n </div>\n }\n </div>\n </div>\n </div>\n <!-- Quick Actions -->\n @if (UserCanCreateKeys) {\n <div class=\"quick-actions\">\n <div class=\"quick-actions-title\">Quick Actions</div>\n <div class=\"quick-actions-grid\">\n <button class=\"quick-action\" (click)=\"openCreateDialog()\">\n <i class=\"fa-solid fa-plus\"></i>\n <span>Generate Key</span>\n </button>\n <button class=\"quick-action\" (click)=\"showListView('all')\">\n <i class=\"fa-solid fa-list\"></i>\n <span>View All Keys</span>\n </button>\n <button class=\"quick-action\" (click)=\"showListView('expiring')\">\n <i class=\"fa-solid fa-clock\"></i>\n <span>Expiring Keys</span>\n </button>\n <button class=\"quick-action\" (click)=\"showListView('never-used')\">\n <i class=\"fa-solid fa-question-circle\"></i>\n <span>Never Used</span>\n </button>\n </div>\n </div>\n }\n <!-- Security Notice -->\n <div class=\"security-notice\">\n <i class=\"fa-solid fa-shield-check\"></i>\n <div class=\"notice-content\">\n <strong>Security Best Practices:</strong>\n API keys should be rotated regularly and revoked when no longer needed.\n Keys are hashed and stored securely - the raw key is only shown once at creation time.\n All API key usage is logged for audit purposes.\n </div>\n </div>\n }\n <!-- List View -->\n @if (CurrentView === 'list') {\n <div class=\"list-view-header\">\n <button class=\"back-btn\" (click)=\"showOverview()\">\n <i class=\"fa-solid fa-arrow-left\"></i>\n Back to Overview\n </button>\n </div>\n <mj-api-key-list #keyList\n [Filter]=\"ListFilter\"\n (KeySelected)=\"onKeySelected($event)\"\n (CreateRequested)=\"openCreateDialog()\">\n </mj-api-key-list>\n }\n }\n <!-- Applications Tab Content -->\n @if (MainTab === 'applications') {\n <mj-api-applications-panel\n (ApplicationUpdated)=\"onDataUpdated()\">\n </mj-api-applications-panel>\n }\n <!-- Scopes Tab Content -->\n @if (MainTab === 'scopes') {\n <mj-api-scopes-panel\n (ScopeUpdated)=\"onDataUpdated()\">\n </mj-api-scopes-panel>\n }\n <!-- Usage Tab Content -->\n @if (MainTab === 'usage') {\n <mj-api-usage-panel></mj-api-usage-panel>\n }\n </div><!-- /.content-wrapper -->\n </div><!-- /.dashboard-content -->\n <!-- Mobile Navigation Toggle -->\n <button class=\"mobile-nav-toggle\" (click)=\"toggleNav()\">\n <i class=\"fa-solid\" [class.fa-bars]=\"!NavOpen\" [class.fa-times]=\"NavOpen\"></i>\n </button>\n <!-- Mobile Navigation Overlay -->\n <div class=\"mobile-nav-overlay\" (click)=\"closeNav()\"></div>\n }\n\n <!-- Create Dialog -->\n <mj-api-key-create-dialog\n [Visible]=\"ShowCreateDialog\"\n (Created)=\"onKeyCreated($event)\"\n (Closed)=\"onCreateDialogClosed()\">\n </mj-api-key-create-dialog>\n\n <!-- Edit Panel -->\n <mj-api-key-edit-panel\n [Visible]=\"ShowEditPanel\"\n [KeyId]=\"SelectedKeyId\"\n (Updated)=\"onKeyUpdated()\"\n (Revoked)=\"onKeyRevoked()\"\n (Closed)=\"onEditPanelClosed()\">\n </mj-api-key-edit-panel>\n</div>\n"]}