@memberjunction/ng-dashboards 5.28.0 → 5.30.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 (125) hide show
  1. package/dist/AI/components/agents/agent-configuration.component.d.ts.map +1 -1
  2. package/dist/AI/components/agents/agent-configuration.component.js +11 -9
  3. package/dist/AI/components/agents/agent-configuration.component.js.map +1 -1
  4. package/dist/AI/components/agents/agent-editor.component.d.ts.map +1 -1
  5. package/dist/AI/components/agents/agent-editor.component.js +21 -19
  6. package/dist/AI/components/agents/agent-editor.component.js.map +1 -1
  7. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js +154 -154
  8. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js.map +1 -1
  9. package/dist/AI/components/duplicates/duplicate-detection-resource.component.d.ts.map +1 -1
  10. package/dist/AI/components/duplicates/duplicate-detection-resource.component.js +8 -0
  11. package/dist/AI/components/duplicates/duplicate-detection-resource.component.js.map +1 -1
  12. package/dist/AI/components/vectors/vector-management-resource.component.d.ts +1 -1
  13. package/dist/AI/components/vectors/vector-management-resource.component.d.ts.map +1 -1
  14. package/dist/AI/components/vectors/vector-management-resource.component.js +2 -2
  15. package/dist/AI/components/vectors/vector-management-resource.component.js.map +1 -1
  16. package/dist/APIKeys/api-applications-panel.component.d.ts +1 -1
  17. package/dist/APIKeys/api-applications-panel.component.d.ts.map +1 -1
  18. package/dist/APIKeys/api-applications-panel.component.js +15 -2
  19. package/dist/APIKeys/api-applications-panel.component.js.map +1 -1
  20. package/dist/APIKeys/api-key-edit-panel.component.d.ts.map +1 -1
  21. package/dist/APIKeys/api-key-edit-panel.component.js +17 -5
  22. package/dist/APIKeys/api-key-edit-panel.component.js.map +1 -1
  23. package/dist/Archiving/components/archive-config-resource.component.d.ts +20 -0
  24. package/dist/Archiving/components/archive-config-resource.component.d.ts.map +1 -0
  25. package/dist/Archiving/components/archive-config-resource.component.js +46 -0
  26. package/dist/Archiving/components/archive-config-resource.component.js.map +1 -0
  27. package/dist/Archiving/components/archive-runs-resource.component.d.ts +20 -0
  28. package/dist/Archiving/components/archive-runs-resource.component.d.ts.map +1 -0
  29. package/dist/Archiving/components/archive-runs-resource.component.js +46 -0
  30. package/dist/Archiving/components/archive-runs-resource.component.js.map +1 -0
  31. package/dist/Credentials/components/credentials-list-resource.component.d.ts.map +1 -1
  32. package/dist/Credentials/components/credentials-list-resource.component.js +56 -71
  33. package/dist/Credentials/components/credentials-list-resource.component.js.map +1 -1
  34. package/dist/DashboardBrowser/dashboard-browser-resource.component.d.ts +0 -8
  35. package/dist/DashboardBrowser/dashboard-browser-resource.component.d.ts.map +1 -1
  36. package/dist/DashboardBrowser/dashboard-browser-resource.component.js +73 -74
  37. package/dist/DashboardBrowser/dashboard-browser-resource.component.js.map +1 -1
  38. package/dist/DashboardBrowser/dashboard-share-adapter.d.ts +25 -0
  39. package/dist/DashboardBrowser/dashboard-share-adapter.d.ts.map +1 -0
  40. package/dist/DashboardBrowser/dashboard-share-adapter.js +99 -0
  41. package/dist/DashboardBrowser/dashboard-share-adapter.js.map +1 -0
  42. package/dist/DashboardBrowser/dashboard-share-dialog.component.d.ts +21 -104
  43. package/dist/DashboardBrowser/dashboard-share-dialog.component.d.ts.map +1 -1
  44. package/dist/DashboardBrowser/dashboard-share-dialog.component.js +48 -530
  45. package/dist/DashboardBrowser/dashboard-share-dialog.component.js.map +1 -1
  46. package/dist/DataExplorer/data-explorer-dashboard.component.d.ts +5 -0
  47. package/dist/DataExplorer/data-explorer-dashboard.component.d.ts.map +1 -1
  48. package/dist/DataExplorer/data-explorer-dashboard.component.js +17 -0
  49. package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
  50. package/dist/Integration/components/connections/connections.component.d.ts +18 -1
  51. package/dist/Integration/components/connections/connections.component.d.ts.map +1 -1
  52. package/dist/Integration/components/connections/connections.component.js +251 -199
  53. package/dist/Integration/components/connections/connections.component.js.map +1 -1
  54. package/dist/Integration/services/integration-data.service.d.ts +7 -2
  55. package/dist/Integration/services/integration-data.service.d.ts.map +1 -1
  56. package/dist/Integration/services/integration-data.service.js +10 -2
  57. package/dist/Integration/services/integration-data.service.js.map +1 -1
  58. package/dist/KnowledgeHub/components/analytics/analytics-resource.component.js +144 -144
  59. package/dist/KnowledgeHub/components/analytics/analytics-resource.component.js.map +1 -1
  60. package/dist/Lists/components/lists-operations-resource.component.d.ts.map +1 -1
  61. package/dist/Lists/components/lists-operations-resource.component.js +12 -14
  62. package/dist/Lists/components/lists-operations-resource.component.js.map +1 -1
  63. package/dist/MCP/components/mcp-connection-dialog.component.js +1 -1
  64. package/dist/MCP/components/mcp-connection-dialog.component.js.map +1 -1
  65. package/dist/MCP/mcp-dashboard.component.d.ts +170 -0
  66. package/dist/MCP/mcp-dashboard.component.d.ts.map +1 -1
  67. package/dist/MCP/mcp-dashboard.component.js +2521 -758
  68. package/dist/MCP/mcp-dashboard.component.js.map +1 -1
  69. package/dist/MCP/mcp-filter-panel.component.d.ts +16 -1
  70. package/dist/MCP/mcp-filter-panel.component.d.ts.map +1 -1
  71. package/dist/MCP/mcp-filter-panel.component.js +187 -60
  72. package/dist/MCP/mcp-filter-panel.component.js.map +1 -1
  73. package/dist/MCP/mcp-resource.component.d.ts +0 -9
  74. package/dist/MCP/mcp-resource.component.d.ts.map +1 -1
  75. package/dist/MCP/mcp-resource.component.js +1 -10
  76. package/dist/MCP/mcp-resource.component.js.map +1 -1
  77. package/dist/MCP/mcp.module.d.ts +7 -6
  78. package/dist/MCP/mcp.module.d.ts.map +1 -1
  79. package/dist/MCP/mcp.module.js +4 -8
  80. package/dist/MCP/mcp.module.js.map +1 -1
  81. package/dist/Permissions/audit-log-resource.component.d.ts +38 -0
  82. package/dist/Permissions/audit-log-resource.component.d.ts.map +1 -0
  83. package/dist/Permissions/audit-log-resource.component.js +380 -0
  84. package/dist/Permissions/audit-log-resource.component.js.map +1 -0
  85. package/dist/Permissions/permissions-shared.d.ts +51 -0
  86. package/dist/Permissions/permissions-shared.d.ts.map +1 -0
  87. package/dist/Permissions/permissions-shared.js +91 -0
  88. package/dist/Permissions/permissions-shared.js.map +1 -0
  89. package/dist/Permissions/resource-access-resource.component.d.ts +45 -0
  90. package/dist/Permissions/resource-access-resource.component.d.ts.map +1 -0
  91. package/dist/Permissions/resource-access-resource.component.js +342 -0
  92. package/dist/Permissions/resource-access-resource.component.js.map +1 -0
  93. package/dist/Permissions/user-access-resource.component.d.ts +39 -0
  94. package/dist/Permissions/user-access-resource.component.d.ts.map +1 -0
  95. package/dist/Permissions/user-access-resource.component.js +346 -0
  96. package/dist/Permissions/user-access-resource.component.js.map +1 -0
  97. package/dist/QueryBrowser/query-browser-resource.component.d.ts +13 -3
  98. package/dist/QueryBrowser/query-browser-resource.component.d.ts.map +1 -1
  99. package/dist/QueryBrowser/query-browser-resource.component.js +186 -139
  100. package/dist/QueryBrowser/query-browser-resource.component.js.map +1 -1
  101. package/dist/archiving-dashboards.module.d.ts +19 -0
  102. package/dist/archiving-dashboards.module.d.ts.map +1 -0
  103. package/dist/archiving-dashboards.module.js +52 -0
  104. package/dist/archiving-dashboards.module.js.map +1 -0
  105. package/dist/component-studio-dashboards.module.d.ts +1 -0
  106. package/dist/component-studio-dashboards.module.d.ts.map +1 -1
  107. package/dist/component-studio-dashboards.module.js +7 -0
  108. package/dist/component-studio-dashboards.module.js.map +1 -1
  109. package/dist/core-dashboards.module.d.ts +24 -19
  110. package/dist/core-dashboards.module.d.ts.map +1 -1
  111. package/dist/core-dashboards.module.js +30 -1
  112. package/dist/core-dashboards.module.js.map +1 -1
  113. package/dist/module.d.ts +13 -12
  114. package/dist/module.d.ts.map +1 -1
  115. package/dist/module.js +7 -0
  116. package/dist/module.js.map +1 -1
  117. package/dist/public-api.d.ts +7 -1
  118. package/dist/public-api.d.ts.map +1 -1
  119. package/dist/public-api.js +8 -0
  120. package/dist/public-api.js.map +1 -1
  121. package/dist/shared/pipes/highlight-search.pipe.d.ts +1 -1
  122. package/dist/shared/pipes/highlight-search.pipe.d.ts.map +1 -1
  123. package/dist/shared/pipes/highlight-search.pipe.js +14 -4
  124. package/dist/shared/pipes/highlight-search.pipe.js.map +1 -1
  125. package/package.json +52 -48
@@ -2955,8 +2955,8 @@ function AutotaggingPipelineResourceComponent_Conditional_20_Template(rf, ctx) {
2955
2955
  i0.ɵɵconditional(ctx_r2.FormMode === "add-type" || ctx_r2.FormMode === "edit-type" ? 12 : -1);
2956
2956
  } }
2957
2957
  function AutotaggingPipelineResourceComponent_Conditional_21_Conditional_15_Conditional_2_Template(rf, ctx) { if (rf & 1) {
2958
- i0.ɵɵelementStart(0, "span", 426);
2959
- i0.ɵɵelement(1, "i", 427);
2958
+ i0.ɵɵelementStart(0, "span", 427);
2959
+ i0.ɵɵelement(1, "i", 428);
2960
2960
  i0.ɵɵtext(2);
2961
2961
  i0.ɵɵelementEnd();
2962
2962
  } if (rf & 2) {
@@ -2965,10 +2965,10 @@ function AutotaggingPipelineResourceComponent_Conditional_21_Conditional_15_Cond
2965
2965
  i0.ɵɵtextInterpolate1(" ", ctx_r2.SelectedFeedItem.FileTypeName);
2966
2966
  } }
2967
2967
  function AutotaggingPipelineResourceComponent_Conditional_21_Conditional_15_Template(rf, ctx) { if (rf & 1) {
2968
- i0.ɵɵelementStart(0, "span", 425);
2968
+ i0.ɵɵelementStart(0, "span", 426);
2969
2969
  i0.ɵɵtext(1);
2970
2970
  i0.ɵɵelementEnd();
2971
- i0.ɵɵconditionalCreate(2, AutotaggingPipelineResourceComponent_Conditional_21_Conditional_15_Conditional_2_Template, 3, 1, "span", 426);
2971
+ i0.ɵɵconditionalCreate(2, AutotaggingPipelineResourceComponent_Conditional_21_Conditional_15_Conditional_2_Template, 3, 1, "span", 427);
2972
2972
  } if (rf & 2) {
2973
2973
  const ctx_r2 = i0.ɵɵnextContext(2);
2974
2974
  i0.ɵɵadvance();
@@ -2977,12 +2977,12 @@ function AutotaggingPipelineResourceComponent_Conditional_21_Conditional_15_Temp
2977
2977
  i0.ɵɵconditional(ctx_r2.SelectedFeedItem.FileTypeName ? 2 : -1);
2978
2978
  } }
2979
2979
  function AutotaggingPipelineResourceComponent_Conditional_21_Conditional_16_Template(rf, ctx) { if (rf & 1) {
2980
- i0.ɵɵelementStart(0, "div", 415)(1, "div", 416);
2980
+ i0.ɵɵelementStart(0, "div", 416)(1, "div", 417);
2981
2981
  i0.ɵɵtext(2, "URL");
2982
2982
  i0.ɵɵelementEnd();
2983
- i0.ɵɵelementStart(3, "a", 428);
2983
+ i0.ɵɵelementStart(3, "a", 429);
2984
2984
  i0.ɵɵtext(4);
2985
- i0.ɵɵelement(5, "i", 429);
2985
+ i0.ɵɵelement(5, "i", 430);
2986
2986
  i0.ɵɵelementEnd()();
2987
2987
  } if (rf & 2) {
2988
2988
  const ctx_r2 = i0.ɵɵnextContext(2);
@@ -2992,10 +2992,10 @@ function AutotaggingPipelineResourceComponent_Conditional_21_Conditional_16_Temp
2992
2992
  i0.ɵɵtextInterpolate1(" ", ctx_r2.SelectedFeedItem.URL, " ");
2993
2993
  } }
2994
2994
  function AutotaggingPipelineResourceComponent_Conditional_21_Conditional_17_Template(rf, ctx) { if (rf & 1) {
2995
- i0.ɵɵelementStart(0, "div", 415)(1, "div", 416);
2995
+ i0.ɵɵelementStart(0, "div", 416)(1, "div", 417);
2996
2996
  i0.ɵɵtext(2, "Content Preview");
2997
2997
  i0.ɵɵelementEnd();
2998
- i0.ɵɵelementStart(3, "div", 430);
2998
+ i0.ɵɵelementStart(3, "div", 431);
2999
2999
  i0.ɵɵtext(4);
3000
3000
  i0.ɵɵelementEnd()();
3001
3001
  } if (rf & 2) {
@@ -3004,9 +3004,9 @@ function AutotaggingPipelineResourceComponent_Conditional_21_Conditional_17_Temp
3004
3004
  i0.ɵɵtextInterpolate(ctx_r2.SelectedFeedItem.TextContent);
3005
3005
  } }
3006
3006
  function AutotaggingPipelineResourceComponent_Conditional_21_Conditional_18_For_5_Template(rf, ctx) { if (rf & 1) {
3007
- i0.ɵɵelementStart(0, "span", 433);
3007
+ i0.ɵɵelementStart(0, "span", 434);
3008
3008
  i0.ɵɵtext(1);
3009
- i0.ɵɵelementStart(2, "span", 434);
3009
+ i0.ɵɵelementStart(2, "span", 435);
3010
3010
  i0.ɵɵtext(3);
3011
3011
  i0.ɵɵelementEnd()();
3012
3012
  } if (rf & 2) {
@@ -3019,11 +3019,11 @@ function AutotaggingPipelineResourceComponent_Conditional_21_Conditional_18_For_
3019
3019
  i0.ɵɵtextInterpolate(ctx_r2.FormatWeight(wt_r94.Weight));
3020
3020
  } }
3021
3021
  function AutotaggingPipelineResourceComponent_Conditional_21_Conditional_18_Template(rf, ctx) { if (rf & 1) {
3022
- i0.ɵɵelementStart(0, "div", 415)(1, "div", 416);
3022
+ i0.ɵɵelementStart(0, "div", 416)(1, "div", 417);
3023
3023
  i0.ɵɵtext(2);
3024
3024
  i0.ɵɵelementEnd();
3025
- i0.ɵɵelementStart(3, "div", 431);
3026
- i0.ɵɵrepeaterCreate(4, AutotaggingPipelineResourceComponent_Conditional_21_Conditional_18_For_5_Template, 4, 4, "span", 432, _forTrack4);
3025
+ i0.ɵɵelementStart(3, "div", 432);
3026
+ i0.ɵɵrepeaterCreate(4, AutotaggingPipelineResourceComponent_Conditional_21_Conditional_18_For_5_Template, 4, 4, "span", 433, _forTrack4);
3027
3027
  i0.ɵɵelementEnd()();
3028
3028
  } if (rf & 2) {
3029
3029
  const ctx_r2 = i0.ɵɵnextContext(2);
@@ -3033,10 +3033,10 @@ function AutotaggingPipelineResourceComponent_Conditional_21_Conditional_18_Temp
3033
3033
  i0.ɵɵrepeater(ctx_r2.SelectedFeedItem.Tags);
3034
3034
  } }
3035
3035
  function AutotaggingPipelineResourceComponent_Conditional_21_Conditional_23_Template(rf, ctx) { if (rf & 1) {
3036
- i0.ɵɵelementStart(0, "div", 418)(1, "span", 419);
3036
+ i0.ɵɵelementStart(0, "div", 419)(1, "span", 420);
3037
3037
  i0.ɵɵtext(2, "Checksum");
3038
3038
  i0.ɵɵelementEnd();
3039
- i0.ɵɵelementStart(3, "span", 435);
3039
+ i0.ɵɵelementStart(3, "span", 436);
3040
3040
  i0.ɵɵtext(4);
3041
3041
  i0.ɵɵelementEnd()();
3042
3042
  } if (rf & 2) {
@@ -3053,45 +3053,45 @@ function AutotaggingPipelineResourceComponent_Conditional_21_Template(rf, ctx) {
3053
3053
  i0.ɵɵelement(4, "i", 410);
3054
3054
  i0.ɵɵtext(5, " Content Item");
3055
3055
  i0.ɵɵelementEnd();
3056
- i0.ɵɵelementStart(6, "button", 387);
3056
+ i0.ɵɵelementStart(6, "button", 411);
3057
3057
  i0.ɵɵlistener("click", function AutotaggingPipelineResourceComponent_Conditional_21_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r93); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.CloseItemDetail()); });
3058
3058
  i0.ɵɵelement(7, "i", 99);
3059
3059
  i0.ɵɵelementEnd()();
3060
- i0.ɵɵelementStart(8, "div", 388)(9, "div", 411)(10, "h4", 412);
3060
+ i0.ɵɵelementStart(8, "div", 388)(9, "div", 412)(10, "h4", 413);
3061
3061
  i0.ɵɵtext(11);
3062
3062
  i0.ɵɵelementEnd();
3063
- i0.ɵɵelementStart(12, "div", 413)(13, "span", 414);
3063
+ i0.ɵɵelementStart(12, "div", 414)(13, "span", 415);
3064
3064
  i0.ɵɵtext(14);
3065
3065
  i0.ɵɵelementEnd();
3066
3066
  i0.ɵɵconditionalCreate(15, AutotaggingPipelineResourceComponent_Conditional_21_Conditional_15_Template, 3, 2);
3067
3067
  i0.ɵɵelementEnd()();
3068
- i0.ɵɵconditionalCreate(16, AutotaggingPipelineResourceComponent_Conditional_21_Conditional_16_Template, 6, 2, "div", 415);
3069
- i0.ɵɵconditionalCreate(17, AutotaggingPipelineResourceComponent_Conditional_21_Conditional_17_Template, 5, 1, "div", 415);
3070
- i0.ɵɵconditionalCreate(18, AutotaggingPipelineResourceComponent_Conditional_21_Conditional_18_Template, 6, 1, "div", 415);
3071
- i0.ɵɵelementStart(19, "div", 415)(20, "div", 416);
3068
+ i0.ɵɵconditionalCreate(16, AutotaggingPipelineResourceComponent_Conditional_21_Conditional_16_Template, 6, 2, "div", 416);
3069
+ i0.ɵɵconditionalCreate(17, AutotaggingPipelineResourceComponent_Conditional_21_Conditional_17_Template, 5, 1, "div", 416);
3070
+ i0.ɵɵconditionalCreate(18, AutotaggingPipelineResourceComponent_Conditional_21_Conditional_18_Template, 6, 1, "div", 416);
3071
+ i0.ɵɵelementStart(19, "div", 416)(20, "div", 417);
3072
3072
  i0.ɵɵtext(21, "Metadata");
3073
3073
  i0.ɵɵelementEnd();
3074
- i0.ɵɵelementStart(22, "div", 417);
3075
- i0.ɵɵconditionalCreate(23, AutotaggingPipelineResourceComponent_Conditional_21_Conditional_23_Template, 5, 1, "div", 418);
3076
- i0.ɵɵelementStart(24, "div", 418)(25, "span", 419);
3074
+ i0.ɵɵelementStart(22, "div", 418);
3075
+ i0.ɵɵconditionalCreate(23, AutotaggingPipelineResourceComponent_Conditional_21_Conditional_23_Template, 5, 1, "div", 419);
3076
+ i0.ɵɵelementStart(24, "div", 419)(25, "span", 420);
3077
3077
  i0.ɵɵtext(26, "Created");
3078
3078
  i0.ɵɵelementEnd();
3079
- i0.ɵɵelementStart(27, "span", 420);
3079
+ i0.ɵɵelementStart(27, "span", 421);
3080
3080
  i0.ɵɵtext(28);
3081
3081
  i0.ɵɵelementEnd()();
3082
- i0.ɵɵelementStart(29, "div", 418)(30, "span", 419);
3082
+ i0.ɵɵelementStart(29, "div", 419)(30, "span", 420);
3083
3083
  i0.ɵɵtext(31, "Updated");
3084
3084
  i0.ɵɵelementEnd();
3085
- i0.ɵɵelementStart(32, "span", 420);
3085
+ i0.ɵɵelementStart(32, "span", 421);
3086
3086
  i0.ɵɵtext(33);
3087
3087
  i0.ɵɵelementEnd()()()();
3088
- i0.ɵɵelementStart(34, "div", 421)(35, "button", 90);
3088
+ i0.ɵɵelementStart(34, "div", 422)(35, "button", 90);
3089
3089
  i0.ɵɵlistener("click", function AutotaggingPipelineResourceComponent_Conditional_21_Template_button_click_35_listener() { i0.ɵɵrestoreView(_r93); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.OpenRecordFromItem(ctx_r2.SelectedFeedItem)); });
3090
- i0.ɵɵelement(36, "i", 422);
3090
+ i0.ɵɵelement(36, "i", 423);
3091
3091
  i0.ɵɵtext(37, " Open Record ");
3092
3092
  i0.ɵɵelementEnd();
3093
- i0.ɵɵelementStart(38, "button", 423);
3094
- i0.ɵɵelement(39, "i", 424);
3093
+ i0.ɵɵelementStart(38, "button", 424);
3094
+ i0.ɵɵelement(39, "i", 425);
3095
3095
  i0.ɵɵtext(40, " See Similar Items ");
3096
3096
  i0.ɵɵelementEnd()()()();
3097
3097
  } if (rf & 2) {
@@ -3117,14 +3117,14 @@ function AutotaggingPipelineResourceComponent_Conditional_21_Template(rf, ctx) {
3117
3117
  } }
3118
3118
  function AutotaggingPipelineResourceComponent_Conditional_22_Conditional_9_Template(rf, ctx) { if (rf & 1) {
3119
3119
  i0.ɵɵelementStart(0, "div", 12);
3120
- i0.ɵɵelement(1, "mj-loading", 436);
3120
+ i0.ɵɵelement(1, "mj-loading", 438);
3121
3121
  i0.ɵɵelementEnd();
3122
3122
  } }
3123
3123
  function AutotaggingPipelineResourceComponent_Conditional_22_Conditional_10_Conditional_15_Template(rf, ctx) { if (rf & 1) {
3124
- i0.ɵɵelementStart(0, "div", 418)(1, "span", 419);
3124
+ i0.ɵɵelementStart(0, "div", 419)(1, "span", 420);
3125
3125
  i0.ɵɵtext(2, "URL");
3126
3126
  i0.ɵɵelementEnd();
3127
- i0.ɵɵelementStart(3, "a", 453);
3127
+ i0.ɵɵelementStart(3, "a", 455);
3128
3128
  i0.ɵɵtext(4);
3129
3129
  i0.ɵɵelementEnd()();
3130
3130
  } if (rf & 2) {
@@ -3135,16 +3135,16 @@ function AutotaggingPipelineResourceComponent_Conditional_22_Conditional_10_Cond
3135
3135
  i0.ɵɵtextInterpolate(ctx_r2.SelectedSource.URL);
3136
3136
  } }
3137
3137
  function AutotaggingPipelineResourceComponent_Conditional_22_Conditional_10_Conditional_16_Template(rf, ctx) { if (rf & 1) {
3138
- i0.ɵɵelementStart(0, "div", 418)(1, "span", 419);
3138
+ i0.ɵɵelementStart(0, "div", 419)(1, "span", 420);
3139
3139
  i0.ɵɵtext(2, "Content Type");
3140
3140
  i0.ɵɵelementEnd();
3141
- i0.ɵɵelementStart(3, "span", 420);
3141
+ i0.ɵɵelementStart(3, "span", 421);
3142
3142
  i0.ɵɵtext(4);
3143
3143
  i0.ɵɵelementEnd()();
3144
- i0.ɵɵelementStart(5, "div", 418)(6, "span", 419);
3144
+ i0.ɵɵelementStart(5, "div", 419)(6, "span", 420);
3145
3145
  i0.ɵɵtext(7, "File Type");
3146
3146
  i0.ɵɵelementEnd();
3147
- i0.ɵɵelementStart(8, "span", 420);
3147
+ i0.ɵɵelementStart(8, "span", 421);
3148
3148
  i0.ɵɵtext(9);
3149
3149
  i0.ɵɵelementEnd()();
3150
3150
  } if (rf & 2) {
@@ -3165,7 +3165,7 @@ function AutotaggingPipelineResourceComponent_Conditional_22_Conditional_10_For_
3165
3165
  i0.ɵɵtextInterpolate(opt_r97);
3166
3166
  } }
3167
3167
  function AutotaggingPipelineResourceComponent_Conditional_22_Conditional_10_Conditional_69_Template(rf, ctx) { if (rf & 1) {
3168
- i0.ɵɵelementStart(0, "div", 449)(1, "p");
3168
+ i0.ɵɵelementStart(0, "div", 451)(1, "p");
3169
3169
  i0.ɵɵtext(2);
3170
3170
  i0.ɵɵelementEnd()();
3171
3171
  } if (rf & 2) {
@@ -3175,22 +3175,22 @@ function AutotaggingPipelineResourceComponent_Conditional_22_Conditional_10_Cond
3175
3175
  } }
3176
3176
  function AutotaggingPipelineResourceComponent_Conditional_22_Conditional_10_For_71_Template(rf, ctx) { if (rf & 1) {
3177
3177
  const _r98 = i0.ɵɵgetCurrentView();
3178
- i0.ɵɵelementStart(0, "div", 454);
3178
+ i0.ɵɵelementStart(0, "div", 456);
3179
3179
  i0.ɵɵlistener("click", function AutotaggingPipelineResourceComponent_Conditional_22_Conditional_10_For_71_Template_div_click_0_listener() { const ci_r99 = i0.ɵɵrestoreView(_r98).$implicit; const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.OpenContentItemDetail(ci_r99)); });
3180
3180
  i0.ɵɵelement(1, "div", 102);
3181
- i0.ɵɵelementStart(2, "span", 455);
3181
+ i0.ɵɵelementStart(2, "span", 457);
3182
3182
  i0.ɵɵtext(3);
3183
3183
  i0.ɵɵelementEnd();
3184
- i0.ɵɵelementStart(4, "span", 456);
3184
+ i0.ɵɵelementStart(4, "span", 458);
3185
3185
  i0.ɵɵtext(5);
3186
3186
  i0.ɵɵelementEnd();
3187
- i0.ɵɵelementStart(6, "span", 456);
3187
+ i0.ɵɵelementStart(6, "span", 458);
3188
3188
  i0.ɵɵtext(7);
3189
3189
  i0.ɵɵelementEnd();
3190
- i0.ɵɵelementStart(8, "span", 457);
3190
+ i0.ɵɵelementStart(8, "span", 459);
3191
3191
  i0.ɵɵtext(9);
3192
3192
  i0.ɵɵelementEnd();
3193
- i0.ɵɵelementStart(10, "span", 458);
3193
+ i0.ɵɵelementStart(10, "span", 460);
3194
3194
  i0.ɵɵtext(11);
3195
3195
  i0.ɵɵelementEnd()();
3196
3196
  } if (rf & 2) {
@@ -3215,15 +3215,15 @@ function AutotaggingPipelineResourceComponent_Conditional_22_Conditional_10_For_
3215
3215
  } }
3216
3216
  function AutotaggingPipelineResourceComponent_Conditional_22_Conditional_10_Conditional_72_Template(rf, ctx) { if (rf & 1) {
3217
3217
  const _r100 = i0.ɵɵgetCurrentView();
3218
- i0.ɵɵelementStart(0, "div", 451)(1, "button", 459);
3218
+ i0.ɵɵelementStart(0, "div", 453)(1, "button", 461);
3219
3219
  i0.ɵɵlistener("click", function AutotaggingPipelineResourceComponent_Conditional_22_Conditional_10_Conditional_72_Template_button_click_1_listener() { i0.ɵɵrestoreView(_r100); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.SourceDetailPrevPage()); });
3220
3220
  i0.ɵɵelement(2, "i", 109);
3221
3221
  i0.ɵɵtext(3, " Prev ");
3222
3222
  i0.ɵɵelementEnd();
3223
- i0.ɵɵelementStart(4, "span", 460);
3223
+ i0.ɵɵelementStart(4, "span", 462);
3224
3224
  i0.ɵɵtext(5);
3225
3225
  i0.ɵɵelementEnd();
3226
- i0.ɵɵelementStart(6, "button", 459);
3226
+ i0.ɵɵelementStart(6, "button", 461);
3227
3227
  i0.ɵɵlistener("click", function AutotaggingPipelineResourceComponent_Conditional_22_Conditional_10_Conditional_72_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r100); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.SourceDetailNextPage()); });
3228
3228
  i0.ɵɵtext(7, " Next ");
3229
3229
  i0.ɵɵelement(8, "i", 111);
@@ -3238,16 +3238,16 @@ function AutotaggingPipelineResourceComponent_Conditional_22_Conditional_10_Cond
3238
3238
  i0.ɵɵproperty("disabled", ctx_r2.SourceDetailPage >= ctx_r2.SourceDetailTotalPages - 1);
3239
3239
  } }
3240
3240
  function AutotaggingPipelineResourceComponent_Conditional_22_Conditional_10_Conditional_73_For_5_Template(rf, ctx) { if (rf & 1) {
3241
- i0.ɵɵelementStart(0, "div", 462)(1, "span", 96);
3241
+ i0.ɵɵelementStart(0, "div", 464)(1, "span", 96);
3242
3242
  i0.ɵɵtext(2);
3243
3243
  i0.ɵɵelementEnd();
3244
- i0.ɵɵelementStart(3, "span", 463);
3244
+ i0.ɵɵelementStart(3, "span", 465);
3245
3245
  i0.ɵɵtext(4);
3246
3246
  i0.ɵɵelementEnd();
3247
- i0.ɵɵelementStart(5, "span", 464);
3247
+ i0.ɵɵelementStart(5, "span", 466);
3248
3248
  i0.ɵɵtext(6);
3249
3249
  i0.ɵɵelementEnd();
3250
- i0.ɵɵelementStart(7, "span", 465);
3250
+ i0.ɵɵelementStart(7, "span", 467);
3251
3251
  i0.ɵɵtext(8);
3252
3252
  i0.ɵɵelementEnd()();
3253
3253
  } if (rf & 2) {
@@ -3264,11 +3264,11 @@ function AutotaggingPipelineResourceComponent_Conditional_22_Conditional_10_Cond
3264
3264
  i0.ɵɵtextInterpolate1("", run_r101.Items, " items");
3265
3265
  } }
3266
3266
  function AutotaggingPipelineResourceComponent_Conditional_22_Conditional_10_Conditional_73_Template(rf, ctx) { if (rf & 1) {
3267
- i0.ɵɵelementStart(0, "div", 415)(1, "div", 416);
3267
+ i0.ɵɵelementStart(0, "div", 416)(1, "div", 417);
3268
3268
  i0.ɵɵtext(2, "Recent Runs");
3269
3269
  i0.ɵɵelementEnd();
3270
- i0.ɵɵelementStart(3, "div", 461);
3271
- i0.ɵɵrepeaterCreate(4, AutotaggingPipelineResourceComponent_Conditional_22_Conditional_10_Conditional_73_For_5_Template, 9, 6, "div", 462, _forTrack3);
3270
+ i0.ɵɵelementStart(3, "div", 463);
3271
+ i0.ɵɵrepeaterCreate(4, AutotaggingPipelineResourceComponent_Conditional_22_Conditional_10_Conditional_73_For_5_Template, 9, 6, "div", 464, _forTrack3);
3272
3272
  i0.ɵɵelementEnd()();
3273
3273
  } if (rf & 2) {
3274
3274
  const ctx_r2 = i0.ɵɵnextContext(3);
@@ -3277,91 +3277,91 @@ function AutotaggingPipelineResourceComponent_Conditional_22_Conditional_10_Cond
3277
3277
  } }
3278
3278
  function AutotaggingPipelineResourceComponent_Conditional_22_Conditional_10_Template(rf, ctx) { if (rf & 1) {
3279
3279
  const _r96 = i0.ɵɵgetCurrentView();
3280
- i0.ɵɵelementStart(0, "div", 437)(1, "div", 150);
3280
+ i0.ɵɵelementStart(0, "div", 439)(1, "div", 150);
3281
3281
  i0.ɵɵelement(2, "i");
3282
3282
  i0.ɵɵelementEnd();
3283
- i0.ɵɵelementStart(3, "div")(4, "h4", 412);
3283
+ i0.ɵɵelementStart(3, "div")(4, "h4", 413);
3284
3284
  i0.ɵɵtext(5);
3285
3285
  i0.ɵɵelementEnd();
3286
- i0.ɵɵelementStart(6, "div", 413)(7, "span", 425);
3286
+ i0.ɵɵelementStart(6, "div", 414)(7, "span", 426);
3287
3287
  i0.ɵɵtext(8);
3288
3288
  i0.ɵɵelementEnd();
3289
- i0.ɵɵelementStart(9, "span", 438);
3289
+ i0.ɵɵelementStart(9, "span", 440);
3290
3290
  i0.ɵɵtext(10);
3291
3291
  i0.ɵɵelementEnd()()()();
3292
- i0.ɵɵelementStart(11, "div", 415)(12, "div", 416);
3292
+ i0.ɵɵelementStart(11, "div", 416)(12, "div", 417);
3293
3293
  i0.ɵɵtext(13, "Configuration");
3294
3294
  i0.ɵɵelementEnd();
3295
- i0.ɵɵelementStart(14, "div", 417);
3296
- i0.ɵɵconditionalCreate(15, AutotaggingPipelineResourceComponent_Conditional_22_Conditional_10_Conditional_15_Template, 5, 2, "div", 418);
3295
+ i0.ɵɵelementStart(14, "div", 418);
3296
+ i0.ɵɵconditionalCreate(15, AutotaggingPipelineResourceComponent_Conditional_22_Conditional_10_Conditional_15_Template, 5, 2, "div", 419);
3297
3297
  i0.ɵɵconditionalCreate(16, AutotaggingPipelineResourceComponent_Conditional_22_Conditional_10_Conditional_16_Template, 10, 2);
3298
- i0.ɵɵelementStart(17, "div", 418)(18, "span", 419);
3298
+ i0.ɵɵelementStart(17, "div", 419)(18, "span", 420);
3299
3299
  i0.ɵɵtext(19, "Embedding Model");
3300
3300
  i0.ɵɵelementEnd();
3301
- i0.ɵɵelementStart(20, "span", 420);
3301
+ i0.ɵɵelementStart(20, "span", 421);
3302
3302
  i0.ɵɵtext(21);
3303
3303
  i0.ɵɵelementEnd()();
3304
- i0.ɵɵelementStart(22, "div", 418)(23, "span", 419);
3304
+ i0.ɵɵelementStart(22, "div", 419)(23, "span", 420);
3305
3305
  i0.ɵɵtext(24, "Vector Index");
3306
3306
  i0.ɵɵelementEnd();
3307
- i0.ɵɵelementStart(25, "span", 420);
3307
+ i0.ɵɵelementStart(25, "span", 421);
3308
3308
  i0.ɵɵtext(26);
3309
3309
  i0.ɵɵelementEnd()()()();
3310
- i0.ɵɵelementStart(27, "div", 415)(28, "div", 416);
3310
+ i0.ɵɵelementStart(27, "div", 416)(28, "div", 417);
3311
3311
  i0.ɵɵtext(29, "Statistics");
3312
3312
  i0.ɵɵelementEnd();
3313
- i0.ɵɵelementStart(30, "div", 439)(31, "div", 440)(32, "div", 441);
3313
+ i0.ɵɵelementStart(30, "div", 441)(31, "div", 442)(32, "div", 443);
3314
3314
  i0.ɵɵtext(33);
3315
3315
  i0.ɵɵelementEnd();
3316
- i0.ɵɵelementStart(34, "div", 442);
3316
+ i0.ɵɵelementStart(34, "div", 444);
3317
3317
  i0.ɵɵtext(35, "Items");
3318
3318
  i0.ɵɵelementEnd()();
3319
- i0.ɵɵelementStart(36, "div", 440)(37, "div", 441);
3319
+ i0.ɵɵelementStart(36, "div", 442)(37, "div", 443);
3320
3320
  i0.ɵɵtext(38);
3321
3321
  i0.ɵɵelementEnd();
3322
- i0.ɵɵelementStart(39, "div", 442);
3322
+ i0.ɵɵelementStart(39, "div", 444);
3323
3323
  i0.ɵɵtext(40, "Tags");
3324
3324
  i0.ɵɵelementEnd()();
3325
- i0.ɵɵelementStart(41, "div", 440)(42, "div", 441);
3325
+ i0.ɵɵelementStart(41, "div", 442)(42, "div", 443);
3326
3326
  i0.ɵɵtext(43);
3327
3327
  i0.ɵɵelementEnd();
3328
- i0.ɵɵelementStart(44, "div", 442);
3328
+ i0.ɵɵelementStart(44, "div", 444);
3329
3329
  i0.ɵɵtext(45, "Avg Tags");
3330
3330
  i0.ɵɵelementEnd()();
3331
- i0.ɵɵelementStart(46, "div", 440)(47, "div", 441);
3331
+ i0.ɵɵelementStart(46, "div", 442)(47, "div", 443);
3332
3332
  i0.ɵɵtext(48);
3333
3333
  i0.ɵɵelementEnd();
3334
- i0.ɵɵelementStart(49, "div", 442);
3334
+ i0.ɵɵelementStart(49, "div", 444);
3335
3335
  i0.ɵɵtext(50, "Last Run");
3336
3336
  i0.ɵɵelementEnd()();
3337
- i0.ɵɵelementStart(51, "div", 440)(52, "div", 441);
3337
+ i0.ɵɵelementStart(51, "div", 442)(52, "div", 443);
3338
3338
  i0.ɵɵtext(53);
3339
3339
  i0.ɵɵelementEnd();
3340
- i0.ɵɵelementStart(54, "div", 442);
3340
+ i0.ɵɵelementStart(54, "div", 444);
3341
3341
  i0.ɵɵtext(55, "Errors");
3342
3342
  i0.ɵɵelementEnd()()()();
3343
- i0.ɵɵelementStart(56, "div", 415)(57, "div", 443)(58, "div", 416);
3343
+ i0.ɵɵelementStart(56, "div", 416)(57, "div", 445)(58, "div", 417);
3344
3344
  i0.ɵɵtext(59);
3345
3345
  i0.ɵɵpipe(60, "number");
3346
3346
  i0.ɵɵelementEnd();
3347
- i0.ɵɵelementStart(61, "div", 444)(62, "select", 445);
3347
+ i0.ɵɵelementStart(61, "div", 446)(62, "select", 447);
3348
3348
  i0.ɵɵtwoWayListener("ngModelChange", function AutotaggingPipelineResourceComponent_Conditional_22_Conditional_10_Template_select_ngModelChange_62_listener($event) { i0.ɵɵrestoreView(_r96); const ctx_r2 = i0.ɵɵnextContext(2); i0.ɵɵtwoWayBindingSet(ctx_r2.SourceDetailStatusFilter, $event) || (ctx_r2.SourceDetailStatusFilter = $event); return i0.ɵɵresetView($event); });
3349
3349
  i0.ɵɵlistener("ngModelChange", function AutotaggingPipelineResourceComponent_Conditional_22_Conditional_10_Template_select_ngModelChange_62_listener() { i0.ɵɵrestoreView(_r96); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.OnSourceDetailStatusFilterChange()); });
3350
3350
  i0.ɵɵrepeaterCreate(63, AutotaggingPipelineResourceComponent_Conditional_22_Conditional_10_For_64_Template, 2, 2, "option", 373, i0.ɵɵrepeaterTrackByIdentity);
3351
3351
  i0.ɵɵelementEnd();
3352
- i0.ɵɵelementStart(65, "button", 446);
3352
+ i0.ɵɵelementStart(65, "button", 448);
3353
3353
  i0.ɵɵlistener("click", function AutotaggingPipelineResourceComponent_Conditional_22_Conditional_10_Template_button_click_65_listener() { i0.ɵɵrestoreView(_r96); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.RetryFailedItems()); });
3354
- i0.ɵɵelement(66, "i", 447);
3354
+ i0.ɵɵelement(66, "i", 449);
3355
3355
  i0.ɵɵtext(67, " Retry Failed ");
3356
3356
  i0.ɵɵelementEnd()()();
3357
- i0.ɵɵelementStart(68, "div", 448);
3358
- i0.ɵɵconditionalCreate(69, AutotaggingPipelineResourceComponent_Conditional_22_Conditional_10_Conditional_69_Template, 3, 1, "div", 449);
3359
- i0.ɵɵrepeaterCreate(70, AutotaggingPipelineResourceComponent_Conditional_22_Conditional_10_For_71_Template, 12, 11, "div", 450, _forTrack3);
3357
+ i0.ɵɵelementStart(68, "div", 450);
3358
+ i0.ɵɵconditionalCreate(69, AutotaggingPipelineResourceComponent_Conditional_22_Conditional_10_Conditional_69_Template, 3, 1, "div", 451);
3359
+ i0.ɵɵrepeaterCreate(70, AutotaggingPipelineResourceComponent_Conditional_22_Conditional_10_For_71_Template, 12, 11, "div", 452, _forTrack3);
3360
3360
  i0.ɵɵelementEnd();
3361
- i0.ɵɵconditionalCreate(72, AutotaggingPipelineResourceComponent_Conditional_22_Conditional_10_Conditional_72_Template, 9, 4, "div", 451);
3361
+ i0.ɵɵconditionalCreate(72, AutotaggingPipelineResourceComponent_Conditional_22_Conditional_10_Conditional_72_Template, 9, 4, "div", 453);
3362
3362
  i0.ɵɵelementEnd();
3363
- i0.ɵɵconditionalCreate(73, AutotaggingPipelineResourceComponent_Conditional_22_Conditional_10_Conditional_73_Template, 6, 0, "div", 415);
3364
- i0.ɵɵelementStart(74, "div", 421)(75, "button", 90);
3363
+ i0.ɵɵconditionalCreate(73, AutotaggingPipelineResourceComponent_Conditional_22_Conditional_10_Conditional_73_Template, 6, 0, "div", 416);
3364
+ i0.ɵɵelementStart(74, "div", 422)(75, "button", 90);
3365
3365
  i0.ɵɵlistener("click", function AutotaggingPipelineResourceComponent_Conditional_22_Conditional_10_Template_button_click_75_listener() { i0.ɵɵrestoreView(_r96); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.OpenEditSourceFromDetail()); });
3366
3366
  i0.ɵɵelement(76, "i", 162);
3367
3367
  i0.ɵɵtext(77, " Edit ");
@@ -3371,7 +3371,7 @@ function AutotaggingPipelineResourceComponent_Conditional_22_Conditional_10_Temp
3371
3371
  i0.ɵɵelement(79, "i", 18);
3372
3372
  i0.ɵɵtext(80, " Run Now ");
3373
3373
  i0.ɵɵelementEnd();
3374
- i0.ɵɵelementStart(81, "button", 452);
3374
+ i0.ɵɵelementStart(81, "button", 454);
3375
3375
  i0.ɵɵlistener("click", function AutotaggingPipelineResourceComponent_Conditional_22_Conditional_10_Template_button_click_81_listener() { i0.ɵɵrestoreView(_r96); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.DeleteSourceFromDetail()); });
3376
3376
  i0.ɵɵelement(82, "i", 165);
3377
3377
  i0.ɵɵtext(83, " Delete ");
@@ -3432,7 +3432,7 @@ function AutotaggingPipelineResourceComponent_Conditional_22_Template(rf, ctx) {
3432
3432
  i0.ɵɵelement(4, "i", 52);
3433
3433
  i0.ɵɵtext(5, " Source Detail");
3434
3434
  i0.ɵɵelementEnd();
3435
- i0.ɵɵelementStart(6, "button", 387);
3435
+ i0.ɵɵelementStart(6, "button", 437);
3436
3436
  i0.ɵɵlistener("click", function AutotaggingPipelineResourceComponent_Conditional_22_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r95); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.CloseSourceDetail()); });
3437
3437
  i0.ɵɵelement(7, "i", 99);
3438
3438
  i0.ɵɵelementEnd()();
@@ -3457,11 +3457,11 @@ function AutotaggingPipelineResourceComponent_Conditional_23_Conditional_34_Temp
3457
3457
  } }
3458
3458
  function AutotaggingPipelineResourceComponent_Conditional_23_Template(rf, ctx) { if (rf & 1) {
3459
3459
  const _r102 = i0.ɵɵgetCurrentView();
3460
- i0.ɵɵelementStart(0, "div", 466);
3460
+ i0.ɵɵelementStart(0, "div", 468);
3461
3461
  i0.ɵɵlistener("click", function AutotaggingPipelineResourceComponent_Conditional_23_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r102); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.CloseScheduleDialog()); });
3462
- i0.ɵɵelementStart(1, "div", 467);
3462
+ i0.ɵɵelementStart(1, "div", 469);
3463
3463
  i0.ɵɵlistener("click", function AutotaggingPipelineResourceComponent_Conditional_23_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(_r102); return i0.ɵɵresetView($event.stopPropagation()); });
3464
- i0.ɵɵelementStart(2, "div", 468)(3, "h3");
3464
+ i0.ɵɵelementStart(2, "div", 470)(3, "h3");
3465
3465
  i0.ɵɵelement(4, "i", 167);
3466
3466
  i0.ɵɵtext(5, " Schedule Pipeline");
3467
3467
  i0.ɵɵelementEnd();
@@ -3469,36 +3469,36 @@ function AutotaggingPipelineResourceComponent_Conditional_23_Template(rf, ctx) {
3469
3469
  i0.ɵɵlistener("click", function AutotaggingPipelineResourceComponent_Conditional_23_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r102); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.CloseScheduleDialog()); });
3470
3470
  i0.ɵɵelement(7, "i", 99);
3471
3471
  i0.ɵɵelementEnd()();
3472
- i0.ɵɵelementStart(8, "div", 469)(9, "div", 470)(10, "label");
3472
+ i0.ɵɵelementStart(8, "div", 471)(9, "div", 472)(10, "label");
3473
3473
  i0.ɵɵtext(11, "Source");
3474
3474
  i0.ɵɵelementEnd();
3475
- i0.ɵɵelementStart(12, "div", 471);
3475
+ i0.ɵɵelementStart(12, "div", 473);
3476
3476
  i0.ɵɵelement(13, "i");
3477
3477
  i0.ɵɵtext(14);
3478
3478
  i0.ɵɵelementEnd()();
3479
- i0.ɵɵelementStart(15, "div", 470)(16, "label");
3479
+ i0.ɵɵelementStart(15, "div", 472)(16, "label");
3480
3480
  i0.ɵɵtext(17, "Action");
3481
3481
  i0.ɵɵelementEnd();
3482
- i0.ɵɵelementStart(18, "div", 472);
3482
+ i0.ɵɵelementStart(18, "div", 474);
3483
3483
  i0.ɵɵtext(19, "Autotag and Vectorize Content");
3484
3484
  i0.ɵɵelementEnd()();
3485
- i0.ɵɵelementStart(20, "div", 470)(21, "label", 473);
3485
+ i0.ɵɵelementStart(20, "div", 472)(21, "label", 475);
3486
3486
  i0.ɵɵtext(22, "Cron Expression");
3487
3487
  i0.ɵɵelementEnd();
3488
- i0.ɵɵelementStart(23, "input", 474);
3488
+ i0.ɵɵelementStart(23, "input", 476);
3489
3489
  i0.ɵɵtwoWayListener("ngModelChange", function AutotaggingPipelineResourceComponent_Conditional_23_Template_input_ngModelChange_23_listener($event) { i0.ɵɵrestoreView(_r102); const ctx_r2 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r2.ScheduleCron, $event) || (ctx_r2.ScheduleCron = $event); return i0.ɵɵresetView($event); });
3490
3490
  i0.ɵɵelementEnd();
3491
- i0.ɵɵelementStart(24, "div", 475);
3491
+ i0.ɵɵelementStart(24, "div", 477);
3492
3492
  i0.ɵɵelement(25, "i", 383);
3493
3493
  i0.ɵɵtext(26);
3494
3494
  i0.ɵɵelementEnd()();
3495
- i0.ɵɵelementStart(27, "div", 476)(28, "label", 477);
3495
+ i0.ɵɵelementStart(27, "div", 478)(28, "label", 479);
3496
3496
  i0.ɵɵtext(29, "Enabled");
3497
3497
  i0.ɵɵelementEnd();
3498
- i0.ɵɵelementStart(30, "input", 478);
3498
+ i0.ɵɵelementStart(30, "input", 480);
3499
3499
  i0.ɵɵtwoWayListener("ngModelChange", function AutotaggingPipelineResourceComponent_Conditional_23_Template_input_ngModelChange_30_listener($event) { i0.ɵɵrestoreView(_r102); const ctx_r2 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r2.ScheduleEnabled, $event) || (ctx_r2.ScheduleEnabled = $event); return i0.ɵɵresetView($event); });
3500
3500
  i0.ɵɵelementEnd()()();
3501
- i0.ɵɵelementStart(31, "div", 479)(32, "button", 393);
3501
+ i0.ɵɵelementStart(31, "div", 481)(32, "button", 393);
3502
3502
  i0.ɵɵlistener("click", function AutotaggingPipelineResourceComponent_Conditional_23_Template_button_click_32_listener() { i0.ɵɵrestoreView(_r102); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.SaveSchedule()); });
3503
3503
  i0.ɵɵconditionalCreate(33, AutotaggingPipelineResourceComponent_Conditional_23_Conditional_33_Template, 2, 0)(34, AutotaggingPipelineResourceComponent_Conditional_23_Conditional_34_Template, 2, 0);
3504
3504
  i0.ɵɵelementEnd();
@@ -3525,22 +3525,22 @@ function AutotaggingPipelineResourceComponent_Conditional_23_Template(rf, ctx) {
3525
3525
  } }
3526
3526
  function AutotaggingPipelineResourceComponent_Conditional_24_Template(rf, ctx) { if (rf & 1) {
3527
3527
  const _r103 = i0.ɵɵgetCurrentView();
3528
- i0.ɵɵelementStart(0, "div", 466);
3528
+ i0.ɵɵelementStart(0, "div", 468);
3529
3529
  i0.ɵɵlistener("click", function AutotaggingPipelineResourceComponent_Conditional_24_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r103); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.ConfirmDialogCancel()); });
3530
- i0.ɵɵelementStart(1, "div", 467);
3530
+ i0.ɵɵelementStart(1, "div", 469);
3531
3531
  i0.ɵɵlistener("click", function AutotaggingPipelineResourceComponent_Conditional_24_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(_r103); return i0.ɵɵresetView($event.stopPropagation()); });
3532
- i0.ɵɵelementStart(2, "div", 468)(3, "h3");
3533
- i0.ɵɵelement(4, "i", 480);
3532
+ i0.ɵɵelementStart(2, "div", 470)(3, "h3");
3533
+ i0.ɵɵelement(4, "i", 482);
3534
3534
  i0.ɵɵtext(5);
3535
3535
  i0.ɵɵelementEnd();
3536
3536
  i0.ɵɵelementStart(6, "button", 356);
3537
3537
  i0.ɵɵlistener("click", function AutotaggingPipelineResourceComponent_Conditional_24_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r103); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.ConfirmDialogCancel()); });
3538
3538
  i0.ɵɵelement(7, "i", 99);
3539
3539
  i0.ɵɵelementEnd()();
3540
- i0.ɵɵelementStart(8, "div", 469)(9, "p", 481);
3540
+ i0.ɵɵelementStart(8, "div", 471)(9, "p", 483);
3541
3541
  i0.ɵɵtext(10);
3542
3542
  i0.ɵɵelementEnd()();
3543
- i0.ɵɵelementStart(11, "div", 479)(12, "button", 86);
3543
+ i0.ɵɵelementStart(11, "div", 481)(12, "button", 86);
3544
3544
  i0.ɵɵlistener("click", function AutotaggingPipelineResourceComponent_Conditional_24_Template_button_click_12_listener() { i0.ɵɵrestoreView(_r103); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.ConfirmDialogAccept()); });
3545
3545
  i0.ɵɵelement(13, "i", 72);
3546
3546
  i0.ɵɵtext(14, " Confirm ");
@@ -3558,11 +3558,11 @@ function AutotaggingPipelineResourceComponent_Conditional_24_Template(rf, ctx) {
3558
3558
  } }
3559
3559
  function AutotaggingPipelineResourceComponent_Conditional_25_Template(rf, ctx) { if (rf & 1) {
3560
3560
  const _r104 = i0.ɵɵgetCurrentView();
3561
- i0.ɵɵelementStart(0, "div", 466);
3561
+ i0.ɵɵelementStart(0, "div", 468);
3562
3562
  i0.ɵɵlistener("click", function AutotaggingPipelineResourceComponent_Conditional_25_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r104); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.CloseSplitDialog()); });
3563
- i0.ɵɵelementStart(1, "div", 467);
3563
+ i0.ɵɵelementStart(1, "div", 469);
3564
3564
  i0.ɵɵlistener("click", function AutotaggingPipelineResourceComponent_Conditional_25_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(_r104); return i0.ɵɵresetView($event.stopPropagation()); });
3565
- i0.ɵɵelementStart(2, "div", 468)(3, "h3");
3565
+ i0.ɵɵelementStart(2, "div", 470)(3, "h3");
3566
3566
  i0.ɵɵelement(4, "i", 293);
3567
3567
  i0.ɵɵtext(5, " Split Tag");
3568
3568
  i0.ɵɵelementEnd();
@@ -3570,16 +3570,16 @@ function AutotaggingPipelineResourceComponent_Conditional_25_Template(rf, ctx) {
3570
3570
  i0.ɵɵlistener("click", function AutotaggingPipelineResourceComponent_Conditional_25_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r104); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.CloseSplitDialog()); });
3571
3571
  i0.ɵɵelement(7, "i", 99);
3572
3572
  i0.ɵɵelementEnd()();
3573
- i0.ɵɵelementStart(8, "div", 469)(9, "div", 470)(10, "label");
3573
+ i0.ɵɵelementStart(8, "div", 471)(9, "div", 472)(10, "label");
3574
3574
  i0.ɵɵtext(11, "New tag names (comma-separated)");
3575
3575
  i0.ɵɵelementEnd();
3576
- i0.ɵɵelementStart(12, "input", 482);
3576
+ i0.ɵɵelementStart(12, "input", 484);
3577
3577
  i0.ɵɵtwoWayListener("ngModelChange", function AutotaggingPipelineResourceComponent_Conditional_25_Template_input_ngModelChange_12_listener($event) { i0.ɵɵrestoreView(_r104); const ctx_r2 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r2.SplitChildNames, $event) || (ctx_r2.SplitChildNames = $event); return i0.ɵɵresetView($event); });
3578
3578
  i0.ɵɵelementEnd()();
3579
- i0.ɵɵelementStart(13, "p", 481);
3579
+ i0.ɵɵelementStart(13, "p", 483);
3580
3580
  i0.ɵɵtext(14, "New tags will be created as siblings of the original tag under the same parent.");
3581
3581
  i0.ɵɵelementEnd()();
3582
- i0.ɵɵelementStart(15, "div", 479)(16, "button", 393);
3582
+ i0.ɵɵelementStart(15, "div", 481)(16, "button", 393);
3583
3583
  i0.ɵɵlistener("click", function AutotaggingPipelineResourceComponent_Conditional_25_Template_button_click_16_listener() { i0.ɵɵrestoreView(_r104); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.ExecuteSplit()); });
3584
3584
  i0.ɵɵelement(17, "i", 293);
3585
3585
  i0.ɵɵtext(18, " Create Tags ");
@@ -3597,11 +3597,11 @@ function AutotaggingPipelineResourceComponent_Conditional_25_Template(rf, ctx) {
3597
3597
  } }
3598
3598
  function AutotaggingPipelineResourceComponent_Conditional_26_Template(rf, ctx) { if (rf & 1) {
3599
3599
  const _r105 = i0.ɵɵgetCurrentView();
3600
- i0.ɵɵelementStart(0, "div", 466);
3600
+ i0.ɵɵelementStart(0, "div", 468);
3601
3601
  i0.ɵɵlistener("click", function AutotaggingPipelineResourceComponent_Conditional_26_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r105); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.CloseCreateTagDialog()); });
3602
- i0.ɵɵelementStart(1, "div", 467);
3602
+ i0.ɵɵelementStart(1, "div", 469);
3603
3603
  i0.ɵɵlistener("click", function AutotaggingPipelineResourceComponent_Conditional_26_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(_r105); return i0.ɵɵresetView($event.stopPropagation()); });
3604
- i0.ɵɵelementStart(2, "div", 468)(3, "h3");
3604
+ i0.ɵɵelementStart(2, "div", 470)(3, "h3");
3605
3605
  i0.ɵɵelement(4, "i", 134);
3606
3606
  i0.ɵɵtext(5, " Create Tag");
3607
3607
  i0.ɵɵelementEnd();
@@ -3609,23 +3609,23 @@ function AutotaggingPipelineResourceComponent_Conditional_26_Template(rf, ctx) {
3609
3609
  i0.ɵɵlistener("click", function AutotaggingPipelineResourceComponent_Conditional_26_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r105); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.CloseCreateTagDialog()); });
3610
3610
  i0.ɵɵelement(7, "i", 99);
3611
3611
  i0.ɵɵelementEnd()();
3612
- i0.ɵɵelementStart(8, "div", 469)(9, "div", 483);
3612
+ i0.ɵɵelementStart(8, "div", 471)(9, "div", 485);
3613
3613
  i0.ɵɵtext(10);
3614
3614
  i0.ɵɵelementEnd();
3615
- i0.ɵɵelementStart(11, "div", 470)(12, "label");
3615
+ i0.ɵɵelementStart(11, "div", 472)(12, "label");
3616
3616
  i0.ɵɵtext(13, "Name");
3617
3617
  i0.ɵɵelementEnd();
3618
- i0.ɵɵelementStart(14, "input", 484);
3618
+ i0.ɵɵelementStart(14, "input", 486);
3619
3619
  i0.ɵɵtwoWayListener("ngModelChange", function AutotaggingPipelineResourceComponent_Conditional_26_Template_input_ngModelChange_14_listener($event) { i0.ɵɵrestoreView(_r105); const ctx_r2 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r2.CreateTagName, $event) || (ctx_r2.CreateTagName = $event); return i0.ɵɵresetView($event); });
3620
3620
  i0.ɵɵlistener("keydown.enter", function AutotaggingPipelineResourceComponent_Conditional_26_Template_input_keydown_enter_14_listener() { i0.ɵɵrestoreView(_r105); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.SaveNewTag()); });
3621
3621
  i0.ɵɵelementEnd()();
3622
- i0.ɵɵelementStart(15, "div", 470)(16, "label");
3622
+ i0.ɵɵelementStart(15, "div", 472)(16, "label");
3623
3623
  i0.ɵɵtext(17, "Description (optional)");
3624
3624
  i0.ɵɵelementEnd();
3625
- i0.ɵɵelementStart(18, "textarea", 485);
3625
+ i0.ɵɵelementStart(18, "textarea", 487);
3626
3626
  i0.ɵɵtwoWayListener("ngModelChange", function AutotaggingPipelineResourceComponent_Conditional_26_Template_textarea_ngModelChange_18_listener($event) { i0.ɵɵrestoreView(_r105); const ctx_r2 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r2.CreateTagDescription, $event) || (ctx_r2.CreateTagDescription = $event); return i0.ɵɵresetView($event); });
3627
3627
  i0.ɵɵelementEnd()()();
3628
- i0.ɵɵelementStart(19, "div", 479)(20, "button", 393);
3628
+ i0.ɵɵelementStart(19, "div", 481)(20, "button", 393);
3629
3629
  i0.ɵɵlistener("click", function AutotaggingPipelineResourceComponent_Conditional_26_Template_button_click_20_listener() { i0.ɵɵrestoreView(_r105); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.SaveNewTag()); });
3630
3630
  i0.ɵɵelement(21, "i", 72);
3631
3631
  i0.ɵɵtext(22, " Create ");
@@ -3646,7 +3646,7 @@ function AutotaggingPipelineResourceComponent_Conditional_26_Template(rf, ctx) {
3646
3646
  i0.ɵɵproperty("disabled", !ctx_r2.CreateTagName.trim());
3647
3647
  } }
3648
3648
  function AutotaggingPipelineResourceComponent_Conditional_27_For_16_Template(rf, ctx) { if (rf & 1) {
3649
- i0.ɵɵelementStart(0, "option", 487);
3649
+ i0.ɵɵelementStart(0, "option", 489);
3650
3650
  i0.ɵɵtext(1);
3651
3651
  i0.ɵɵelementEnd();
3652
3652
  } if (rf & 2) {
@@ -3657,11 +3657,11 @@ function AutotaggingPipelineResourceComponent_Conditional_27_For_16_Template(rf,
3657
3657
  } }
3658
3658
  function AutotaggingPipelineResourceComponent_Conditional_27_Template(rf, ctx) { if (rf & 1) {
3659
3659
  const _r106 = i0.ɵɵgetCurrentView();
3660
- i0.ɵɵelementStart(0, "div", 466);
3660
+ i0.ɵɵelementStart(0, "div", 468);
3661
3661
  i0.ɵɵlistener("click", function AutotaggingPipelineResourceComponent_Conditional_27_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r106); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.CloseMoveDialog()); });
3662
- i0.ɵɵelementStart(1, "div", 467);
3662
+ i0.ɵɵelementStart(1, "div", 469);
3663
3663
  i0.ɵɵlistener("click", function AutotaggingPipelineResourceComponent_Conditional_27_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(_r106); return i0.ɵɵresetView($event.stopPropagation()); });
3664
- i0.ɵɵelementStart(2, "div", 468)(3, "h3");
3664
+ i0.ɵɵelementStart(2, "div", 470)(3, "h3");
3665
3665
  i0.ɵɵelement(4, "i", 291);
3666
3666
  i0.ɵɵtext(5, " Move Tag");
3667
3667
  i0.ɵɵelementEnd();
@@ -3669,17 +3669,17 @@ function AutotaggingPipelineResourceComponent_Conditional_27_Template(rf, ctx) {
3669
3669
  i0.ɵɵlistener("click", function AutotaggingPipelineResourceComponent_Conditional_27_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r106); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.CloseMoveDialog()); });
3670
3670
  i0.ɵɵelement(7, "i", 99);
3671
3671
  i0.ɵɵelementEnd()();
3672
- i0.ɵɵelementStart(8, "div", 469)(9, "div", 470)(10, "label");
3672
+ i0.ɵɵelementStart(8, "div", 471)(9, "div", 472)(10, "label");
3673
3673
  i0.ɵɵtext(11, "New parent tag");
3674
3674
  i0.ɵɵelementEnd();
3675
- i0.ɵɵelementStart(12, "select", 486);
3675
+ i0.ɵɵelementStart(12, "select", 488);
3676
3676
  i0.ɵɵtwoWayListener("ngModelChange", function AutotaggingPipelineResourceComponent_Conditional_27_Template_select_ngModelChange_12_listener($event) { i0.ɵɵrestoreView(_r106); const ctx_r2 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r2.MoveNewParentID, $event) || (ctx_r2.MoveNewParentID = $event); return i0.ɵɵresetView($event); });
3677
- i0.ɵɵelementStart(13, "option", 487);
3677
+ i0.ɵɵelementStart(13, "option", 489);
3678
3678
  i0.ɵɵtext(14, "(Root level \u2014 no parent)");
3679
3679
  i0.ɵɵelementEnd();
3680
- i0.ɵɵrepeaterCreate(15, AutotaggingPipelineResourceComponent_Conditional_27_For_16_Template, 2, 3, "option", 487, _forTrack3);
3680
+ i0.ɵɵrepeaterCreate(15, AutotaggingPipelineResourceComponent_Conditional_27_For_16_Template, 2, 3, "option", 489, _forTrack3);
3681
3681
  i0.ɵɵelementEnd()()();
3682
- i0.ɵɵelementStart(17, "div", 479)(18, "button", 90);
3682
+ i0.ɵɵelementStart(17, "div", 481)(18, "button", 90);
3683
3683
  i0.ɵɵlistener("click", function AutotaggingPipelineResourceComponent_Conditional_27_Template_button_click_18_listener() { i0.ɵɵrestoreView(_r106); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.ExecuteMove()); });
3684
3684
  i0.ɵɵelement(19, "i", 72);
3685
3685
  i0.ɵɵtext(20, " Move ");
@@ -3707,11 +3707,11 @@ function AutotaggingPipelineResourceComponent_Conditional_28_Conditional_18_Temp
3707
3707
  } }
3708
3708
  function AutotaggingPipelineResourceComponent_Conditional_28_Template(rf, ctx) { if (rf & 1) {
3709
3709
  const _r108 = i0.ɵɵgetCurrentView();
3710
- i0.ɵɵelementStart(0, "div", 466);
3710
+ i0.ɵɵelementStart(0, "div", 468);
3711
3711
  i0.ɵɵlistener("click", function AutotaggingPipelineResourceComponent_Conditional_28_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r108); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.CloseMergeIntoDialog()); });
3712
- i0.ɵɵelementStart(1, "div", 467);
3712
+ i0.ɵɵelementStart(1, "div", 469);
3713
3713
  i0.ɵɵlistener("click", function AutotaggingPipelineResourceComponent_Conditional_28_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(_r108); return i0.ɵɵresetView($event.stopPropagation()); });
3714
- i0.ɵɵelementStart(2, "div", 468)(3, "h3");
3714
+ i0.ɵɵelementStart(2, "div", 470)(3, "h3");
3715
3715
  i0.ɵɵelement(4, "i", 292);
3716
3716
  i0.ɵɵtext(5);
3717
3717
  i0.ɵɵelementEnd();
@@ -3719,16 +3719,16 @@ function AutotaggingPipelineResourceComponent_Conditional_28_Template(rf, ctx) {
3719
3719
  i0.ɵɵlistener("click", function AutotaggingPipelineResourceComponent_Conditional_28_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r108); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.CloseMergeIntoDialog()); });
3720
3720
  i0.ɵɵelement(7, "i", 99);
3721
3721
  i0.ɵɵelementEnd()();
3722
- i0.ɵɵelementStart(8, "div", 469)(9, "p", 488);
3722
+ i0.ɵɵelementStart(8, "div", 471)(9, "p", 490);
3723
3723
  i0.ɵɵtext(10);
3724
3724
  i0.ɵɵelementEnd();
3725
- i0.ɵɵelementStart(11, "div", 470)(12, "label");
3725
+ i0.ɵɵelementStart(11, "div", 472)(12, "label");
3726
3726
  i0.ɵɵtext(13, "Merge into");
3727
3727
  i0.ɵɵelementEnd();
3728
- i0.ɵɵelementStart(14, "mj-combobox", 489);
3728
+ i0.ɵɵelementStart(14, "mj-combobox", 491);
3729
3729
  i0.ɵɵlistener("ValueChange", function AutotaggingPipelineResourceComponent_Conditional_28_Template_mj_combobox_ValueChange_14_listener($event) { i0.ɵɵrestoreView(_r108); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.OnMergeTargetSelected($event)); });
3730
3730
  i0.ɵɵelementEnd()()();
3731
- i0.ɵɵelementStart(15, "div", 479)(16, "button", 393);
3731
+ i0.ɵɵelementStart(15, "div", 481)(16, "button", 393);
3732
3732
  i0.ɵɵlistener("click", function AutotaggingPipelineResourceComponent_Conditional_28_Template_button_click_16_listener() { i0.ɵɵrestoreView(_r108); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.ExecuteMergeInto()); });
3733
3733
  i0.ɵɵconditionalCreate(17, AutotaggingPipelineResourceComponent_Conditional_28_Conditional_17_Template, 2, 0)(18, AutotaggingPipelineResourceComponent_Conditional_28_Conditional_18_Template, 2, 0);
3734
3734
  i0.ɵɵelementEnd();
@@ -3751,31 +3751,31 @@ function AutotaggingPipelineResourceComponent_Conditional_28_Template(rf, ctx) {
3751
3751
  } }
3752
3752
  function AutotaggingPipelineResourceComponent_Conditional_29_Template(rf, ctx) { if (rf & 1) {
3753
3753
  const _r109 = i0.ɵɵgetCurrentView();
3754
- i0.ɵɵelementStart(0, "div", 490);
3754
+ i0.ɵɵelementStart(0, "div", 492);
3755
3755
  i0.ɵɵlistener("click", function AutotaggingPipelineResourceComponent_Conditional_29_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r109); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.ShowNoContentTypeWarning = false); });
3756
- i0.ɵɵelementStart(1, "div", 491);
3756
+ i0.ɵɵelementStart(1, "div", 493);
3757
3757
  i0.ɵɵlistener("click", function AutotaggingPipelineResourceComponent_Conditional_29_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(_r109); return i0.ɵɵresetView($event.stopPropagation()); });
3758
- i0.ɵɵelementStart(2, "div", 468)(3, "span");
3759
- i0.ɵɵelement(4, "i", 492);
3758
+ i0.ɵɵelementStart(2, "div", 470)(3, "span");
3759
+ i0.ɵɵelement(4, "i", 494);
3760
3760
  i0.ɵɵtext(5, " Content Type Required");
3761
3761
  i0.ɵɵelementEnd();
3762
- i0.ɵɵelementStart(6, "button", 493);
3762
+ i0.ɵɵelementStart(6, "button", 495);
3763
3763
  i0.ɵɵlistener("click", function AutotaggingPipelineResourceComponent_Conditional_29_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r109); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.ShowNoContentTypeWarning = false); });
3764
- i0.ɵɵelement(7, "i", 494);
3764
+ i0.ɵɵelement(7, "i", 496);
3765
3765
  i0.ɵɵelementEnd()();
3766
- i0.ɵɵelementStart(8, "div", 495)(9, "p", 496);
3766
+ i0.ɵɵelementStart(8, "div", 497)(9, "p", 498);
3767
3767
  i0.ɵɵtext(10, " No content types have been configured yet. At least one content type is required before you can create a content source. ");
3768
3768
  i0.ɵɵelementEnd();
3769
- i0.ɵɵelementStart(11, "p", 497);
3769
+ i0.ɵɵelementStart(11, "p", 499);
3770
3770
  i0.ɵɵtext(12, " Go to the ");
3771
3771
  i0.ɵɵelementStart(13, "strong");
3772
3772
  i0.ɵɵtext(14, "Content Types");
3773
3773
  i0.ɵɵelementEnd();
3774
3774
  i0.ɵɵtext(15, " tab to create one. ");
3775
3775
  i0.ɵɵelementEnd()();
3776
- i0.ɵɵelementStart(16, "div", 479)(17, "button", 498);
3776
+ i0.ɵɵelementStart(16, "div", 481)(17, "button", 500);
3777
3777
  i0.ɵɵlistener("mousedown", function AutotaggingPipelineResourceComponent_Conditional_29_Template_button_mousedown_17_listener() { i0.ɵɵrestoreView(_r109); const ctx_r2 = i0.ɵɵnextContext(); ctx_r2.ShowNoContentTypeWarning = false; ctx_r2.CloseForm(); return i0.ɵɵresetView(ctx_r2.SwitchTab("types")); });
3778
- i0.ɵɵelement(18, "i", 499);
3778
+ i0.ɵɵelement(18, "i", 501);
3779
3779
  i0.ɵɵtext(19, " Go to Content Types ");
3780
3780
  i0.ɵɵelementEnd();
3781
3781
  i0.ɵɵelementStart(20, "button", 24);
@@ -7882,7 +7882,7 @@ let AutotaggingPipelineResourceComponent = class AutotaggingPipelineResourceComp
7882
7882
  this.cdr.detectChanges();
7883
7883
  }
7884
7884
  static ɵfac = /*@__PURE__*/ (() => { let ɵAutotaggingPipelineResourceComponent_BaseFactory; return function AutotaggingPipelineResourceComponent_Factory(__ngFactoryType__) { return (ɵAutotaggingPipelineResourceComponent_BaseFactory || (ɵAutotaggingPipelineResourceComponent_BaseFactory = i0.ɵɵgetInheritedFactory(AutotaggingPipelineResourceComponent)))(__ngFactoryType__ || AutotaggingPipelineResourceComponent); }; })();
7885
- static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: AutotaggingPipelineResourceComponent, selectors: [["app-autotagging-pipeline-resource"]], standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 30, vars: 16, consts: [[1, "at-dashboard"], [1, "at-left-nav"], [1, "at-left-nav-header"], [1, "fa-solid", "fa-tags"], [1, "at-left-nav-items"], [1, "at-nav-item", 3, "active"], [1, "at-nav-divider"], [1, "at-nav-item", 3, "click"], [1, "fa-solid", "fa-clock-rotate-left"], [1, "at-left-nav-footer"], [1, "at-run-pipeline-btn", 3, "click", "disabled"], [1, "at-main-area"], [1, "at-loading-overlay"], [1, "at-schedule-overlay"], [1, "at-schedule-dialog-overlay", 2, "z-index", "10001"], [1, "at-nav-badge", 3, "at-nav-badge-live"], [1, "at-nav-badge"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "fa-solid", "fa-play"], ["text", "Loading autotagging data..."], [1, "at-page-header"], [1, "at-page-title"], [1, "at-page-subtitle"], [1, "at-page-actions"], [1, "at-action-btn", "at-secondary-btn", 3, "click"], [1, "fa-solid", "fa-arrows-rotate"], [1, "at-page-body"], [1, "at-kpi-strip"], [1, "at-kpi-card"], [1, "at-pipeline-layout"], [1, "at-pipeline-center"], [1, "at-pipeline-stages"], [1, "at-progress-section"], [1, "at-card", 2, "margin-bottom", "12px"], [1, "at-card", "at-feed-card"], [1, "at-card-header"], [1, "at-card-title"], [1, "fa-solid", "fa-bolt"], [1, "at-feed-header-actions"], [1, "at-feed-sort-btn", 3, "click", "title"], [1, "fa-solid"], [1, "at-feed-count"], [1, "at-feed-search-bar"], [1, "fa-solid", "fa-search", "at-feed-search-icon"], ["type", "text", "placeholder", "Search items, sources, or tags...", 1, "mj-input", "at-feed-search-input", 3, "ngModelChange", "input", "ngModel"], [1, "at-feed-search-clear"], [1, "at-card-body", "at-feed-scroll-body"], [1, "at-empty-state"], [1, "at-feed-item", "at-feed-item-clickable"], [1, "at-feed-pagination"], [1, "at-pipeline-right"], [1, "at-card"], [1, "fa-solid", "fa-database"], [1, "at-card-body"], [1, "at-source-mini"], [1, "at-card", "at-tag-cloud-card"], [1, "at-card-title", 2, "margin-bottom", "10px"], [1, "fa-solid", "fa-chart-bar"], [1, "at-tag-cloud"], [1, "at-tag-pill", 3, "class", "opacity", "title"], [1, "at-card", "at-config-card"], [1, "at-card-header", 2, "cursor", "pointer", 3, "click"], [1, "fa-solid", "fa-sliders"], [1, "fa-solid", 2, "font-size", "0.7rem", "color", "var(--mj-text-muted)"], [1, "at-card-body", "at-config-body"], [1, "at-kpi-value"], [1, "at-kpi-label"], [1, "at-kpi-trend", 3, "up"], [1, "at-kpi-trend"], [1, "fa-solid", "fa-arrow-up"], [1, "at-pipeline-stage"], [1, "at-pipeline-stage-icon"], [1, "fa-solid", "fa-check"], [3, "class"], [1, "at-pipeline-stage-name"], [1, "at-stage-connector", 3, "connector-complete"], [1, "at-stage-connector"], [1, "at-progress-header"], [1, "at-progress-stage-label"], [1, "at-progress-pct"], [1, "at-progress-bar"], [1, "at-progress-fill"], [1, "at-progress-current"], [1, "at-pipeline-controls"], [1, "at-action-btn", "at-secondary-btn", 3, "disabled"], [1, "at-action-btn", "at-primary-btn"], [1, "at-action-btn", "at-danger-btn", 3, "click"], [1, "fa-solid", "fa-stop"], [1, "at-action-btn", "at-secondary-btn", 3, "click", "disabled"], [1, "fa-solid", "fa-pause"], [1, "at-action-btn", "at-primary-btn", 3, "click"], [1, "fa-solid", "fa-list-check"], [1, "at-action-btn", "at-secondary-btn", 2, "font-size", "11px", "padding", "3px 8px", 3, "click"], [1, "at-card-body", 2, "max-height", "200px", "overflow-y", "auto"], [1, "at-run-table"], [1, "at-run-source-name"], [1, "at-run-status-badge"], [1, "fa-solid", "fa-spinner", "fa-spin", 2, "font-size", "0.55rem"], [1, "at-feed-search-clear", 3, "click"], [1, "fa-solid", "fa-times"], [1, "fa-solid", "fa-inbox"], [1, "at-feed-item", "at-feed-item-clickable", 3, "click"], [1, "at-feed-status-dot"], [1, "at-feed-item-content"], [1, "at-feed-item-name"], [1, "at-feed-item-source-label"], [1, "at-feed-item-tags"], [1, "at-feed-tag"], [1, "at-feed-item-time"], [1, "fa-solid", "fa-chevron-left"], [1, "at-feed-pagination-label"], [1, "fa-solid", "fa-chevron-right"], [1, "at-source-mini-icon"], [1, "at-source-mini-info"], [1, "at-source-mini-name"], [1, "at-source-mini-meta"], [1, "at-source-mini-status"], [1, "at-tag-pill", 3, "title"], [1, "at-config-row"], [1, "at-config-label"], [1, "at-config-control"], ["type", "number", "min", "10", "max", "1000", "step", "10", 1, "at-config-input", 3, "ngModelChange", "ngModel"], ["type", "range", "min", "0", "max", "5000", "step", "100", 1, "at-config-slider", 3, "ngModelChange", "ngModel"], [1, "at-config-value"], ["type", "range", "min", "5", "max", "50", "step", "5", 1, "at-config-slider", 3, "ngModelChange", "ngModel"], [1, "at-config-toggle"], ["type", "checkbox", 3, "ngModelChange", "ngModel"], [1, "at-toggle-track"], [1, "at-toggle-thumb"], [1, "at-config-divider"], [1, "at-config-section-label"], ["type", "number", "min", "1", "max", "500", 1, "at-config-input", 3, "ngModelChange", "ngModel"], ["type", "number", "min", "1000", "max", "5000000", "step", "10000", 1, "at-config-input", 3, "ngModelChange", "ngModel"], ["type", "number", "min", "1", "max", "1000", 1, "at-config-input", 3, "ngModelChange", "ngModel"], [1, "fa-solid", "fa-plus"], [1, "at-sources-grid"], [1, "at-source-card-full", "at-source-card-clickable"], [1, "at-add-source-card", 3, "click"], [1, "fa-solid", "fa-plus-circle"], [2, "font-size", "0.85rem", "font-weight", "600"], [2, "font-size", "0.72rem"], [1, "at-dedup-section"], [1, "at-dedup-header"], [1, "at-dedup-title"], [1, "fa-solid", "fa-clone"], [1, "at-dedup-subtitle"], [1, "at-dedup-list"], [1, "at-dedup-empty"], [1, "at-source-card-full", "at-source-card-clickable", 3, "click"], [1, "at-source-card-header"], [1, "at-source-card-icon"], [1, "at-source-card-title"], [1, "at-source-card-type"], [1, "at-source-card-status"], [1, "at-source-card-url"], [1, "at-source-card-stats"], [1, "at-source-stat"], [1, "at-source-stat-value"], [1, "at-source-stat-label"], ["title", "Click to remove schedule", 1, "at-schedule-indicator"], [1, "at-source-card-actions"], [1, "at-source-action-btn", 3, "click"], [1, "fa-solid", "fa-pen"], [1, "at-source-action-btn", "at-source-schedule-btn"], [1, "at-source-action-btn", "at-source-delete-btn", 3, "click"], [1, "fa-solid", "fa-trash"], ["title", "Click to remove schedule", 1, "at-schedule-indicator", 3, "click"], [1, "fa-regular", "fa-clock"], [1, "at-source-action-btn", "at-source-schedule-btn", 3, "click"], [1, "at-dedup-card"], [1, "at-dedup-pair"], [1, "at-dedup-item"], [1, "at-dedup-item-name"], [1, "at-dedup-item-source"], [1, "at-dedup-vs"], [1, "fa-solid", "fa-arrows-left-right"], [1, "at-dedup-meta"], [1, "at-dedup-score"], [1, "at-dedup-method"], [1, "at-dedup-actions"], [1, "at-action-btn", "at-primary-btn", "at-dedup-confirm", 3, "click"], [1, "at-action-btn", "at-secondary-btn", "at-dedup-dismiss", 3, "click"], [1, "fa-solid", "fa-check-circle"], [1, "at-ct-grid"], [1, "at-ct-card"], [1, "at-add-type-card", 3, "click"], [1, "at-ct-card-header"], [1, "at-ct-card-name"], [1, "at-ct-card-model"], [1, "at-ct-field"], [1, "at-ct-field-label"], [1, "at-ct-field-value"], [1, "at-ct-tag-range"], [1, "at-ct-tag-range-bar"], [1, "at-ct-tag-range-fill"], [1, "at-ct-range-suffix"], [1, "at-source-card-actions", 2, "margin-top", "10px"], ["type", "text", "placeholder", "Search tags...", 1, "at-search-input", 3, "ngModelChange", "input", "ngModel"], [1, "at-tag-lib-layout"], [1, "at-tag-lib-main"], [1, "at-card-body", 2, "max-height", "500px", "overflow-y", "auto"], [1, "at-tag-table"], [1, "at-tag-row-clickable", 3, "at-tag-row-selected"], [1, "at-card", 2, "margin-top", "12px"], [1, "at-tag-lib-sidebar"], [1, "at-card-title", 2, "margin-bottom", "12px"], [1, "fa-solid", "fa-cloud"], ["Layout", "spiral", "ColorMode", "weight-gradient", 3, "Items", "MaxFontSize", "MinFontSize", "MaxItems", "Interactive", "Animate"], [1, "at-tag-cloud-empty"], [1, "at-card", 2, "padding", "16px", "margin-top", "12px"], [1, "fa-solid", "fa-chart-pie"], [1, "at-tags-by-source"], [1, "at-tag-source-row"], [1, "at-tag-row-clickable", 3, "click"], [1, "at-tag-name-cell"], [1, "at-weight-indicator"], [1, "at-weight-bar"], [1, "at-weight-bar-fill"], [1, "at-weight-value"], [1, "at-tag-bar"], [1, "at-tag-bar-fill"], [1, "fa-solid", "fa-tag"], [1, "at-slide-close", 2, "background", "none", "border", "none", "cursor", "pointer", "color", "var(--mj-text-muted)", 3, "click"], [1, "at-card-body", 2, "max-height", "300px", "overflow-y", "auto"], [1, "at-tag-row-clickable"], [1, "at-tax-tab-strip"], [1, "at-tax-tab", 3, "click"], [1, "fa-solid", "fa-sitemap"], [1, "fa-solid", "fa-link"], [1, "at-tax-tab-badge", "at-tax-badge-warning"], [1, "fa-solid", "fa-ban"], [1, "at-tax-tab-badge", "at-tax-badge-error"], [1, "fa-solid", "fa-chart-tree-map"], [1, "fa-solid", "fa-scroll"], [1, "at-tax-split-view"], [1, "at-tax-tree-panel", 2, "position", "relative"], [1, "at-tax-tree-toolbar"], ["type", "text", "placeholder", "Search tags...", 1, "at-search-input", 2, "flex", "1", 3, "ngModelChange", "input", "ngModel"], ["title", "Add root tag", 1, "at-tax-toolbar-btn", 3, "click"], ["title", "Toggle multi-select for drag reparenting", 1, "at-tax-toolbar-btn", 3, "click"], [1, "fa-solid", "fa-check-double"], [1, "at-tax-tree-body", 3, "dragover", "drop"], [1, "at-tax-tree-node", 3, "at-tax-node-selected", "at-tax-node-drag-over", "at-tax-node-multi-selected", "padding-left"], [1, "at-tax-tree-saving-overlay"], [1, "at-tax-details-panel"], [1, "at-empty-state", 2, "height", "100%"], [1, "at-tax-health-bar"], [1, "at-tax-health-label"], [1, "at-tax-health-stat"], [1, "at-tax-dot", "at-tax-dot-total"], [1, "at-tax-health-value"], [1, "at-tax-health-text"], [1, "at-tax-dot", "at-tax-dot-healthy"], [1, "at-tax-health-value", "at-tax-val-success"], [1, "at-tax-dot", "at-tax-dot-attention"], [1, "at-tax-health-value", "at-tax-val-warning"], [1, "at-tax-dot", "at-tax-dot-orphaned"], [1, "at-tax-health-value", "at-tax-val-error"], [1, "at-tax-dot", "at-tax-dot-duplicates"], [1, "at-tax-health-value", "at-tax-val-info"], [1, "at-tax-tree-node", 3, "dragstart", "dragover", "dragleave", "drop", "click"], ["type", "checkbox", 1, "at-tax-tree-checkbox", 3, "checked"], [1, "at-tax-tree-arrow", 3, "click"], [1, "at-tax-health-dot"], [1, "at-tax-tree-label"], [1, "at-tax-tree-count"], ["title", "Add child tag", 1, "at-tax-tree-add-child", 3, "click"], ["type", "checkbox", 1, "at-tax-tree-checkbox", 3, "click", "checked"], ["text", "Moving tags...", "size", "small"], [1, "at-tax-details-header"], [1, "at-tax-breadcrumb"], [1, "at-tax-bc-current"], [1, "at-tax-edit-form"], [1, "at-tax-stats-row"], [1, "at-tax-stat-item"], [1, "at-tax-stat-value"], [1, "at-tax-stat-label"], [1, "at-tax-stat-value", "at-tax-stat-date"], [1, "at-tax-action-toolbar"], [1, "at-tax-detail-section"], [1, "at-tax-bc-link", 3, "click"], [1, "at-tax-bc-sep"], [1, "at-tax-details-title"], ["title", "Edit name", 1, "at-tax-edit-icon", 3, "click"], [1, "at-tax-details-desc"], [1, "at-form-group"], [1, "at-form-label"], ["type", "text", 1, "at-form-input", 3, "ngModelChange", "ngModel"], ["rows", "3", 1, "at-form-textarea", 3, "ngModelChange", "ngModel"], [1, "at-form-actions"], [1, "at-tax-action-btn", 3, "click"], [1, "fa-solid", "fa-arrows-up-down"], [1, "fa-solid", "fa-compress"], [1, "fa-solid", "fa-code-branch"], [1, "at-tax-action-btn", "at-tax-action-danger", 3, "click"], [1, "at-tax-section-title"], [1, "at-tax-child-chips"], [1, "at-tax-child-chip"], [1, "at-tax-child-chip", 3, "click"], [1, "at-tax-chip-count"], [1, "at-tax-recent-list"], [1, "at-tax-recent-item"], [1, "at-tax-recent-icon"], [1, "at-tax-recent-name"], [1, "at-tax-recent-weight"], [1, "at-tax-recent-date"], [1, "fa-solid", "fa-hand-pointer"], [1, "at-tax-dup-stats-bar"], [1, "at-tax-dup-stat"], [1, "at-tax-dup-stat", "at-tax-dup-high"], [1, "at-tax-dup-stat", "at-tax-dup-moderate"], [1, "at-tax-dup-list"], [1, "at-tax-dup-card", 3, "at-tax-dup-high", "at-tax-dup-moderate"], [1, "at-tax-dup-card"], [1, "at-tax-dup-tag"], [1, "at-tax-dup-similarity"], [1, "at-tax-sim-percent", "high"], [1, "at-tax-dup-actions"], [1, "at-tax-dup-btn", "at-tax-dup-btn-primary", 3, "click", "disabled"], [1, "at-tax-dup-btn", 3, "click"], [1, "at-tax-dup-arrow"], [1, "at-tax-sim-bar-bg"], [1, "at-tax-sim-bar-fill"], [1, "at-tax-sim-percent"], [1, "at-tax-orphan-toolbar"], [1, "at-tax-orphan-count"], [1, "at-tax-orphan-desc"], [1, "at-tax-orphan-bulk"], [1, "at-tax-bulk-btn", 3, "click"], [1, "fa-solid", "fa-square-check"], [1, "fa-regular", "fa-square"], [1, "at-tax-bulk-btn", "at-tax-bulk-danger", 3, "click"], [1, "fa-solid", "fa-trash-can"], [1, "at-tax-orphan-grid"], [1, "at-tax-orphan-card"], [1, "at-tax-orphan-header"], [1, "at-tax-orphan-name"], ["type", "checkbox", 1, "at-tax-orphan-checkbox", 3, "change", "click", "checked"], [1, "at-tax-orphan-stats"], [1, "at-tax-orphan-dates"], [1, "at-tax-orphan-actions"], [1, "at-tax-orphan-btn", "at-tax-orphan-delete", 3, "click"], [1, "at-tax-orphan-btn"], [1, "at-tax-treemap-kpi-strip"], [1, "at-tax-treemap-kpi"], [1, "at-tax-treemap-container"], [1, "at-tax-drillin-overlay"], [1, "at-tax-treemap-kpi-value"], [1, "at-tax-treemap-kpi-label"], [1, "at-tax-treemap-cell", "at-tax-treemap-cell-clickable", 3, "class", "grid-row"], [1, "at-tax-treemap-cell", "at-tax-treemap-cell-clickable", 3, "click"], [1, "at-tax-cell-name"], [1, "at-tax-cell-count"], [1, "at-tax-drillin-overlay", 3, "click"], [1, "at-tax-drillin-panel", 3, "click"], [1, "at-tax-drillin-header"], [1, "at-schedule-dialog-close", 3, "click"], [1, "at-tax-drillin-body"], [1, "at-tax-drillin-footer"], [1, "at-tax-audit-filters"], [1, "at-tax-audit-filter-label"], [1, "at-tax-audit-checkbox-group"], [1, "at-tax-audit-checkbox"], ["type", "checkbox", 3, "change", "checked"], [1, "at-tax-audit-timeline"], [1, "at-tax-audit-event"], [1, "at-tax-audit-event-icon"], [1, "at-tax-audit-event-body"], [1, "at-tax-audit-event-desc"], [1, "at-tax-tag-ref"], [1, "at-tax-audit-event-meta"], [1, "at-filter-select", 3, "ngModelChange", "change", "ngModel"], ["value", ""], [3, "value"], ["value", "complete"], ["value", "failed"], ["value", "running"], [1, "at-card-body", 2, "max-height", "600px", "overflow-y", "auto"], [1, "at-run-row-clickable", 3, "at-run-row-selected"], [1, "at-run-row-clickable", 3, "click"], [1, "at-run-duration"], [1, "fa-solid", "fa-magnifying-glass-chart"], ["text", "Loading run details...", "size", "small"], [1, "fa-solid", "fa-info-circle"], [1, "at-slide-overlay", 3, "click"], [1, "at-slide-panel"], [1, "at-slide-header"], [1, "at-slide-close", 3, "click"], [1, "at-slide-body"], ["type", "text", "placeholder", "Source name", 1, "at-form-input", 3, "ngModelChange", "ngModel"], [1, "at-form-select", 3, "ngModelChange", "ngModel"], ["SelectionMode", "single", "SelectableTypes", "leaf", "Placeholder", "Use system default", 3, "ValueChange", "BranchConfig", "LeafConfig", "Clearable", "Value"], [1, "at-form-hint"], [1, "at-action-btn", "at-primary-btn", 3, "click", "disabled"], [1, "at-required"], ["type", "url", 1, "at-form-input", 3, "ngModel", "placeholder"], ["type", "text", 1, "at-form-input", 3, "ngModel", "placeholder"], ["type", "text", 1, "at-form-input", 3, "ngModel", "placeholder", "value"], [1, "at-form-select", 3, "ngModel"], ["type", "url", 1, "at-form-input", 3, "ngModelChange", "ngModel", "placeholder"], ["type", "text", 1, "at-form-input", 3, "ngModelChange", "ngModel", "placeholder"], ["type", "text", 1, "at-form-input", 3, "ngModelChange", "ngModel", "placeholder", "value"], ["type", "text", "placeholder", "Content type name", 1, "at-form-input", 3, "ngModelChange", "ngModel"], ["rows", "3", "placeholder", "Description...", 1, "at-form-textarea", 3, "ngModelChange", "ngModel"], ["SelectionMode", "single", "SelectableTypes", "leaf", "Placeholder", "Select AI model...", 3, "ValueChange", "BranchConfig", "LeafConfig", "Clearable", "Value"], [1, "at-form-row"], [1, "at-form-group", 2, "flex", "1"], ["type", "number", "min", "0", 1, "at-form-input", 3, "ngModelChange", "ngModel"], ["type", "number", "min", "1", 1, "at-form-input", 3, "ngModelChange", "ngModel"], [1, "at-slide-panel", "at-detail-panel"], [1, "fa-solid", "fa-file-lines"], [1, "at-detail-item-header"], [1, "at-detail-item-name"], [1, "at-detail-badges"], [1, "at-detail-badge", "at-detail-badge-source"], [1, "at-detail-section"], [1, "at-detail-section-label"], [1, "at-detail-meta-grid"], [1, "at-detail-meta-row"], [1, "at-detail-meta-key"], [1, "at-detail-meta-value"], [1, "at-detail-actions"], [1, "fa-solid", "fa-external-link-alt"], ["disabled", "", 1, "at-action-btn", "at-secondary-btn"], [1, "fa-solid", "fa-magnifying-glass"], [1, "at-detail-badge", "at-detail-badge-type"], [1, "at-detail-badge", "at-detail-badge-file"], [1, "fa-solid", "fa-file"], ["target", "_blank", 1, "at-detail-link", 3, "href"], [1, "fa-solid", "fa-external-link-alt", 2, "font-size", "0.65rem", "margin-left", "4px"], [1, "at-detail-text-preview"], [1, "at-detail-tags"], [1, "at-tag-pill", "at-tag-weighted", 3, "font-size"], [1, "at-tag-pill", "at-tag-weighted"], [1, "at-tag-weight"], [1, "at-detail-meta-value", "at-detail-meta-mono"], ["text", "Loading source details..."], [1, "at-detail-source-header"], [1, "at-detail-badge"], [1, "at-detail-stats-strip"], [1, "at-detail-stat"], [1, "at-detail-stat-value"], [1, "at-detail-stat-label"], [1, "at-detail-section-header-row"], [1, "at-detail-section-controls"], [1, "at-detail-filter-select", 3, "ngModelChange", "ngModel"], ["title", "Re-queue failed items for processing", 1, "at-action-btn", "at-retry-btn", 3, "click"], [1, "fa-solid", "fa-rotate-right"], [1, "at-detail-content-list"], [1, "at-empty-state", 2, "padding", "16px"], [1, "at-detail-content-item"], [1, "at-detail-pagination"], [1, "at-action-btn", "at-secondary-btn", "at-source-delete-btn", 3, "click"], ["target", "_blank", 1, "at-detail-link", "at-detail-meta-value", 3, "href"], [1, "at-detail-content-item", 3, "click"], [1, "at-detail-content-item-name"], [1, "at-status-badge"], [1, "at-detail-content-item-tags"], [1, "at-detail-content-item-time"], [1, "at-page-btn", 3, "click", "disabled"], [1, "at-page-info"], [1, "at-detail-run-history"], [1, "at-detail-run-row"], [1, "at-detail-run-time"], [1, "at-detail-run-duration"], [1, "at-detail-run-items"], [1, "at-schedule-overlay", 3, "click"], [1, "at-schedule-dialog", 3, "click"], [1, "at-schedule-dialog-header"], [1, "at-schedule-dialog-body"], [1, "at-schedule-field"], [1, "at-schedule-source-name"], [1, "at-schedule-action-name"], ["for", "schedule-cron"], ["id", "schedule-cron", "type", "text", "placeholder", "0 2 * * *", 1, "mj-input", "at-schedule-cron-input", 3, "ngModelChange", "ngModel"], [1, "at-schedule-cron-preview"], [1, "at-schedule-field", "at-schedule-toggle-row"], ["for", "schedule-enabled"], ["id", "schedule-enabled", "type", "checkbox", 1, "mj-checkbox", 3, "ngModelChange", "ngModel"], [1, "at-schedule-dialog-footer"], [1, "fa-solid", "fa-triangle-exclamation"], [1, "at-confirm-message"], ["type", "text", "placeholder", "Tag A, Tag B, Tag C", 1, "mj-input", 2, "width", "100%", 3, "ngModelChange", "ngModel"], [1, "at-tax-create-context"], ["type", "text", "placeholder", "Tag name", 1, "mj-input", 2, "width", "100%", 3, "ngModelChange", "keydown.enter", "ngModel"], ["rows", "3", "placeholder", "Brief description of this tag", 1, "mj-textarea", 2, "width", "100%", 3, "ngModelChange", "ngModel"], [1, "mj-input", 2, "width", "100%", 3, "ngModelChange", "ngModel"], [3, "ngValue"], [2, "font-size", "0.85rem", "color", "var(--mj-text-secondary)", "margin", "0 0 12px"], ["TextField", "Label", "ValueField", "ID", "Placeholder", "Search and select a tag...", 3, "ValueChange", "Data", "Filterable", "ValuePrimitive"], [1, "at-schedule-dialog-overlay", 2, "z-index", "10001", 3, "click"], [1, "at-schedule-dialog", 2, "max-width", "440px", "z-index", "10002", 3, "click"], [1, "fa-solid", "fa-triangle-exclamation", 2, "color", "var(--mj-status-warning)", "margin-right", "8px"], [1, "at-close-btn", 3, "click"], [1, "fa-solid", "fa-xmark"], [1, "at-schedule-dialog-body", 2, "text-align", "center", "padding", "24px"], [2, "color", "var(--mj-text-secondary)", "margin-bottom", "16px"], [2, "color", "var(--mj-text-muted)", "font-size", "13px"], [1, "at-action-btn", "at-primary-btn", 3, "mousedown"], [1, "fa-solid", "fa-arrow-right"]], template: function AutotaggingPipelineResourceComponent_Template(rf, ctx) { if (rf & 1) {
7885
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: AutotaggingPipelineResourceComponent, selectors: [["app-autotagging-pipeline-resource"]], standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 30, vars: 16, consts: [[1, "at-dashboard"], [1, "at-left-nav"], [1, "at-left-nav-header"], [1, "fa-solid", "fa-tags"], [1, "at-left-nav-items"], [1, "at-nav-item", 3, "active"], [1, "at-nav-divider"], [1, "at-nav-item", 3, "click"], [1, "fa-solid", "fa-clock-rotate-left"], [1, "at-left-nav-footer"], [1, "at-run-pipeline-btn", 3, "click", "disabled"], [1, "at-main-area"], [1, "at-loading-overlay"], [1, "at-schedule-overlay"], [1, "at-schedule-dialog-overlay", 2, "z-index", "10001"], [1, "at-nav-badge", 3, "at-nav-badge-live"], [1, "at-nav-badge"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "fa-solid", "fa-play"], ["text", "Loading autotagging data..."], [1, "at-page-header"], [1, "at-page-title"], [1, "at-page-subtitle"], [1, "at-page-actions"], [1, "at-action-btn", "at-secondary-btn", 3, "click"], [1, "fa-solid", "fa-arrows-rotate"], [1, "at-page-body"], [1, "at-kpi-strip"], [1, "at-kpi-card"], [1, "at-pipeline-layout"], [1, "at-pipeline-center"], [1, "at-pipeline-stages"], [1, "at-progress-section"], [1, "at-card", 2, "margin-bottom", "12px"], [1, "at-card", "at-feed-card"], [1, "at-card-header"], [1, "at-card-title"], [1, "fa-solid", "fa-bolt"], [1, "at-feed-header-actions"], [1, "at-feed-sort-btn", 3, "click", "title"], [1, "fa-solid"], [1, "at-feed-count"], [1, "at-feed-search-bar"], [1, "fa-solid", "fa-search", "at-feed-search-icon"], ["type", "text", "placeholder", "Search items, sources, or tags...", 1, "mj-input", "at-feed-search-input", 3, "ngModelChange", "input", "ngModel"], [1, "at-feed-search-clear"], [1, "at-card-body", "at-feed-scroll-body"], [1, "at-empty-state"], [1, "at-feed-item", "at-feed-item-clickable"], [1, "at-feed-pagination"], [1, "at-pipeline-right"], [1, "at-card"], [1, "fa-solid", "fa-database"], [1, "at-card-body"], [1, "at-source-mini"], [1, "at-card", "at-tag-cloud-card"], [1, "at-card-title", 2, "margin-bottom", "10px"], [1, "fa-solid", "fa-chart-bar"], [1, "at-tag-cloud"], [1, "at-tag-pill", 3, "class", "opacity", "title"], [1, "at-card", "at-config-card"], [1, "at-card-header", 2, "cursor", "pointer", 3, "click"], [1, "fa-solid", "fa-sliders"], [1, "fa-solid", 2, "font-size", "0.7rem", "color", "var(--mj-text-muted)"], [1, "at-card-body", "at-config-body"], [1, "at-kpi-value"], [1, "at-kpi-label"], [1, "at-kpi-trend", 3, "up"], [1, "at-kpi-trend"], [1, "fa-solid", "fa-arrow-up"], [1, "at-pipeline-stage"], [1, "at-pipeline-stage-icon"], [1, "fa-solid", "fa-check"], [3, "class"], [1, "at-pipeline-stage-name"], [1, "at-stage-connector", 3, "connector-complete"], [1, "at-stage-connector"], [1, "at-progress-header"], [1, "at-progress-stage-label"], [1, "at-progress-pct"], [1, "at-progress-bar"], [1, "at-progress-fill"], [1, "at-progress-current"], [1, "at-pipeline-controls"], [1, "at-action-btn", "at-secondary-btn", 3, "disabled"], [1, "at-action-btn", "at-primary-btn"], [1, "at-action-btn", "at-danger-btn", 3, "click"], [1, "fa-solid", "fa-stop"], [1, "at-action-btn", "at-secondary-btn", 3, "click", "disabled"], [1, "fa-solid", "fa-pause"], [1, "at-action-btn", "at-primary-btn", 3, "click"], [1, "fa-solid", "fa-list-check"], [1, "at-action-btn", "at-secondary-btn", 2, "font-size", "11px", "padding", "3px 8px", 3, "click"], [1, "at-card-body", 2, "max-height", "200px", "overflow-y", "auto"], [1, "at-run-table"], [1, "at-run-source-name"], [1, "at-run-status-badge"], [1, "fa-solid", "fa-spinner", "fa-spin", 2, "font-size", "0.55rem"], [1, "at-feed-search-clear", 3, "click"], [1, "fa-solid", "fa-times"], [1, "fa-solid", "fa-inbox"], [1, "at-feed-item", "at-feed-item-clickable", 3, "click"], [1, "at-feed-status-dot"], [1, "at-feed-item-content"], [1, "at-feed-item-name"], [1, "at-feed-item-source-label"], [1, "at-feed-item-tags"], [1, "at-feed-tag"], [1, "at-feed-item-time"], [1, "fa-solid", "fa-chevron-left"], [1, "at-feed-pagination-label"], [1, "fa-solid", "fa-chevron-right"], [1, "at-source-mini-icon"], [1, "at-source-mini-info"], [1, "at-source-mini-name"], [1, "at-source-mini-meta"], [1, "at-source-mini-status"], [1, "at-tag-pill", 3, "title"], [1, "at-config-row"], [1, "at-config-label"], [1, "at-config-control"], ["type", "number", "min", "10", "max", "1000", "step", "10", 1, "at-config-input", 3, "ngModelChange", "ngModel"], ["type", "range", "min", "0", "max", "5000", "step", "100", 1, "at-config-slider", 3, "ngModelChange", "ngModel"], [1, "at-config-value"], ["type", "range", "min", "5", "max", "50", "step", "5", 1, "at-config-slider", 3, "ngModelChange", "ngModel"], [1, "at-config-toggle"], ["type", "checkbox", 3, "ngModelChange", "ngModel"], [1, "at-toggle-track"], [1, "at-toggle-thumb"], [1, "at-config-divider"], [1, "at-config-section-label"], ["type", "number", "min", "1", "max", "500", 1, "at-config-input", 3, "ngModelChange", "ngModel"], ["type", "number", "min", "1000", "max", "5000000", "step", "10000", 1, "at-config-input", 3, "ngModelChange", "ngModel"], ["type", "number", "min", "1", "max", "1000", 1, "at-config-input", 3, "ngModelChange", "ngModel"], [1, "fa-solid", "fa-plus"], [1, "at-sources-grid"], [1, "at-source-card-full", "at-source-card-clickable"], [1, "at-add-source-card", 3, "click"], [1, "fa-solid", "fa-plus-circle"], [2, "font-size", "0.85rem", "font-weight", "600"], [2, "font-size", "0.72rem"], [1, "at-dedup-section"], [1, "at-dedup-header"], [1, "at-dedup-title"], [1, "fa-solid", "fa-clone"], [1, "at-dedup-subtitle"], [1, "at-dedup-list"], [1, "at-dedup-empty"], [1, "at-source-card-full", "at-source-card-clickable", 3, "click"], [1, "at-source-card-header"], [1, "at-source-card-icon"], [1, "at-source-card-title"], [1, "at-source-card-type"], [1, "at-source-card-status"], [1, "at-source-card-url"], [1, "at-source-card-stats"], [1, "at-source-stat"], [1, "at-source-stat-value"], [1, "at-source-stat-label"], ["title", "Click to remove schedule", 1, "at-schedule-indicator"], [1, "at-source-card-actions"], [1, "at-source-action-btn", 3, "click"], [1, "fa-solid", "fa-pen"], [1, "at-source-action-btn", "at-source-schedule-btn"], [1, "at-source-action-btn", "at-source-delete-btn", 3, "click"], [1, "fa-solid", "fa-trash"], ["title", "Click to remove schedule", 1, "at-schedule-indicator", 3, "click"], [1, "fa-regular", "fa-clock"], [1, "at-source-action-btn", "at-source-schedule-btn", 3, "click"], [1, "at-dedup-card"], [1, "at-dedup-pair"], [1, "at-dedup-item"], [1, "at-dedup-item-name"], [1, "at-dedup-item-source"], [1, "at-dedup-vs"], [1, "fa-solid", "fa-arrows-left-right"], [1, "at-dedup-meta"], [1, "at-dedup-score"], [1, "at-dedup-method"], [1, "at-dedup-actions"], [1, "at-action-btn", "at-primary-btn", "at-dedup-confirm", 3, "click"], [1, "at-action-btn", "at-secondary-btn", "at-dedup-dismiss", 3, "click"], [1, "fa-solid", "fa-check-circle"], [1, "at-ct-grid"], [1, "at-ct-card"], [1, "at-add-type-card", 3, "click"], [1, "at-ct-card-header"], [1, "at-ct-card-name"], [1, "at-ct-card-model"], [1, "at-ct-field"], [1, "at-ct-field-label"], [1, "at-ct-field-value"], [1, "at-ct-tag-range"], [1, "at-ct-tag-range-bar"], [1, "at-ct-tag-range-fill"], [1, "at-ct-range-suffix"], [1, "at-source-card-actions", 2, "margin-top", "10px"], ["type", "text", "placeholder", "Search tags...", 1, "at-search-input", 3, "ngModelChange", "input", "ngModel"], [1, "at-tag-lib-layout"], [1, "at-tag-lib-main"], [1, "at-card-body", 2, "max-height", "500px", "overflow-y", "auto"], [1, "at-tag-table"], [1, "at-tag-row-clickable", 3, "at-tag-row-selected"], [1, "at-card", 2, "margin-top", "12px"], [1, "at-tag-lib-sidebar"], [1, "at-card-title", 2, "margin-bottom", "12px"], [1, "fa-solid", "fa-cloud"], ["Layout", "spiral", "ColorMode", "weight-gradient", 3, "Items", "MaxFontSize", "MinFontSize", "MaxItems", "Interactive", "Animate"], [1, "at-tag-cloud-empty"], [1, "at-card", 2, "padding", "16px", "margin-top", "12px"], [1, "fa-solid", "fa-chart-pie"], [1, "at-tags-by-source"], [1, "at-tag-source-row"], [1, "at-tag-row-clickable", 3, "click"], [1, "at-tag-name-cell"], [1, "at-weight-indicator"], [1, "at-weight-bar"], [1, "at-weight-bar-fill"], [1, "at-weight-value"], [1, "at-tag-bar"], [1, "at-tag-bar-fill"], [1, "fa-solid", "fa-tag"], [1, "at-slide-close", 2, "background", "none", "border", "none", "cursor", "pointer", "color", "var(--mj-text-muted)", 3, "click"], [1, "at-card-body", 2, "max-height", "300px", "overflow-y", "auto"], [1, "at-tag-row-clickable"], [1, "at-tax-tab-strip"], [1, "at-tax-tab", 3, "click"], [1, "fa-solid", "fa-sitemap"], [1, "fa-solid", "fa-link"], [1, "at-tax-tab-badge", "at-tax-badge-warning"], [1, "fa-solid", "fa-ban"], [1, "at-tax-tab-badge", "at-tax-badge-error"], [1, "fa-solid", "fa-chart-tree-map"], [1, "fa-solid", "fa-scroll"], [1, "at-tax-split-view"], [1, "at-tax-tree-panel", 2, "position", "relative"], [1, "at-tax-tree-toolbar"], ["type", "text", "placeholder", "Search tags...", 1, "at-search-input", 2, "flex", "1", 3, "ngModelChange", "input", "ngModel"], ["title", "Add root tag", 1, "at-tax-toolbar-btn", 3, "click"], ["title", "Toggle multi-select for drag reparenting", 1, "at-tax-toolbar-btn", 3, "click"], [1, "fa-solid", "fa-check-double"], [1, "at-tax-tree-body", 3, "dragover", "drop"], [1, "at-tax-tree-node", 3, "at-tax-node-selected", "at-tax-node-drag-over", "at-tax-node-multi-selected", "padding-left"], [1, "at-tax-tree-saving-overlay"], [1, "at-tax-details-panel"], [1, "at-empty-state", 2, "height", "100%"], [1, "at-tax-health-bar"], [1, "at-tax-health-label"], [1, "at-tax-health-stat"], [1, "at-tax-dot", "at-tax-dot-total"], [1, "at-tax-health-value"], [1, "at-tax-health-text"], [1, "at-tax-dot", "at-tax-dot-healthy"], [1, "at-tax-health-value", "at-tax-val-success"], [1, "at-tax-dot", "at-tax-dot-attention"], [1, "at-tax-health-value", "at-tax-val-warning"], [1, "at-tax-dot", "at-tax-dot-orphaned"], [1, "at-tax-health-value", "at-tax-val-error"], [1, "at-tax-dot", "at-tax-dot-duplicates"], [1, "at-tax-health-value", "at-tax-val-info"], [1, "at-tax-tree-node", 3, "dragstart", "dragover", "dragleave", "drop", "click"], ["type", "checkbox", 1, "at-tax-tree-checkbox", 3, "checked"], [1, "at-tax-tree-arrow", 3, "click"], [1, "at-tax-health-dot"], [1, "at-tax-tree-label"], [1, "at-tax-tree-count"], ["title", "Add child tag", 1, "at-tax-tree-add-child", 3, "click"], ["type", "checkbox", 1, "at-tax-tree-checkbox", 3, "click", "checked"], ["text", "Moving tags...", "size", "small"], [1, "at-tax-details-header"], [1, "at-tax-breadcrumb"], [1, "at-tax-bc-current"], [1, "at-tax-edit-form"], [1, "at-tax-stats-row"], [1, "at-tax-stat-item"], [1, "at-tax-stat-value"], [1, "at-tax-stat-label"], [1, "at-tax-stat-value", "at-tax-stat-date"], [1, "at-tax-action-toolbar"], [1, "at-tax-detail-section"], [1, "at-tax-bc-link", 3, "click"], [1, "at-tax-bc-sep"], [1, "at-tax-details-title"], ["title", "Edit name", 1, "at-tax-edit-icon", 3, "click"], [1, "at-tax-details-desc"], [1, "at-form-group"], [1, "at-form-label"], ["type", "text", 1, "at-form-input", 3, "ngModelChange", "ngModel"], ["rows", "3", 1, "at-form-textarea", 3, "ngModelChange", "ngModel"], [1, "at-form-actions"], [1, "at-tax-action-btn", 3, "click"], [1, "fa-solid", "fa-arrows-up-down"], [1, "fa-solid", "fa-compress"], [1, "fa-solid", "fa-code-branch"], [1, "at-tax-action-btn", "at-tax-action-danger", 3, "click"], [1, "at-tax-section-title"], [1, "at-tax-child-chips"], [1, "at-tax-child-chip"], [1, "at-tax-child-chip", 3, "click"], [1, "at-tax-chip-count"], [1, "at-tax-recent-list"], [1, "at-tax-recent-item"], [1, "at-tax-recent-icon"], [1, "at-tax-recent-name"], [1, "at-tax-recent-weight"], [1, "at-tax-recent-date"], [1, "fa-solid", "fa-hand-pointer"], [1, "at-tax-dup-stats-bar"], [1, "at-tax-dup-stat"], [1, "at-tax-dup-stat", "at-tax-dup-high"], [1, "at-tax-dup-stat", "at-tax-dup-moderate"], [1, "at-tax-dup-list"], [1, "at-tax-dup-card", 3, "at-tax-dup-high", "at-tax-dup-moderate"], [1, "at-tax-dup-card"], [1, "at-tax-dup-tag"], [1, "at-tax-dup-similarity"], [1, "at-tax-sim-percent", "high"], [1, "at-tax-dup-actions"], [1, "at-tax-dup-btn", "at-tax-dup-btn-primary", 3, "click", "disabled"], [1, "at-tax-dup-btn", 3, "click"], [1, "at-tax-dup-arrow"], [1, "at-tax-sim-bar-bg"], [1, "at-tax-sim-bar-fill"], [1, "at-tax-sim-percent"], [1, "at-tax-orphan-toolbar"], [1, "at-tax-orphan-count"], [1, "at-tax-orphan-desc"], [1, "at-tax-orphan-bulk"], [1, "at-tax-bulk-btn", 3, "click"], [1, "fa-solid", "fa-square-check"], [1, "fa-regular", "fa-square"], [1, "at-tax-bulk-btn", "at-tax-bulk-danger", 3, "click"], [1, "fa-solid", "fa-trash-can"], [1, "at-tax-orphan-grid"], [1, "at-tax-orphan-card"], [1, "at-tax-orphan-header"], [1, "at-tax-orphan-name"], ["type", "checkbox", 1, "at-tax-orphan-checkbox", 3, "change", "click", "checked"], [1, "at-tax-orphan-stats"], [1, "at-tax-orphan-dates"], [1, "at-tax-orphan-actions"], [1, "at-tax-orphan-btn", "at-tax-orphan-delete", 3, "click"], [1, "at-tax-orphan-btn"], [1, "at-tax-treemap-kpi-strip"], [1, "at-tax-treemap-kpi"], [1, "at-tax-treemap-container"], [1, "at-tax-drillin-overlay"], [1, "at-tax-treemap-kpi-value"], [1, "at-tax-treemap-kpi-label"], [1, "at-tax-treemap-cell", "at-tax-treemap-cell-clickable", 3, "class", "grid-row"], [1, "at-tax-treemap-cell", "at-tax-treemap-cell-clickable", 3, "click"], [1, "at-tax-cell-name"], [1, "at-tax-cell-count"], [1, "at-tax-drillin-overlay", 3, "click"], [1, "at-tax-drillin-panel", 3, "click"], [1, "at-tax-drillin-header"], [1, "at-schedule-dialog-close", 3, "click"], [1, "at-tax-drillin-body"], [1, "at-tax-drillin-footer"], [1, "at-tax-audit-filters"], [1, "at-tax-audit-filter-label"], [1, "at-tax-audit-checkbox-group"], [1, "at-tax-audit-checkbox"], ["type", "checkbox", 3, "change", "checked"], [1, "at-tax-audit-timeline"], [1, "at-tax-audit-event"], [1, "at-tax-audit-event-icon"], [1, "at-tax-audit-event-body"], [1, "at-tax-audit-event-desc"], [1, "at-tax-tag-ref"], [1, "at-tax-audit-event-meta"], [1, "at-filter-select", 3, "ngModelChange", "change", "ngModel"], ["value", ""], [3, "value"], ["value", "complete"], ["value", "failed"], ["value", "running"], [1, "at-card-body", 2, "max-height", "600px", "overflow-y", "auto"], [1, "at-run-row-clickable", 3, "at-run-row-selected"], [1, "at-run-row-clickable", 3, "click"], [1, "at-run-duration"], [1, "fa-solid", "fa-magnifying-glass-chart"], ["text", "Loading run details...", "size", "small"], [1, "fa-solid", "fa-info-circle"], [1, "at-slide-overlay", 3, "click"], [1, "at-slide-panel"], [1, "at-slide-header"], ["aria-label", "Close form", 1, "at-slide-close", 3, "click"], [1, "at-slide-body"], ["type", "text", "placeholder", "Source name", 1, "at-form-input", 3, "ngModelChange", "ngModel"], [1, "at-form-select", 3, "ngModelChange", "ngModel"], ["SelectionMode", "single", "SelectableTypes", "leaf", "Placeholder", "Use system default", 3, "ValueChange", "BranchConfig", "LeafConfig", "Clearable", "Value"], [1, "at-form-hint"], [1, "at-action-btn", "at-primary-btn", 3, "click", "disabled"], [1, "at-required"], ["type", "url", 1, "at-form-input", 3, "ngModel", "placeholder"], ["type", "text", 1, "at-form-input", 3, "ngModel", "placeholder"], ["type", "text", 1, "at-form-input", 3, "ngModel", "placeholder", "value"], [1, "at-form-select", 3, "ngModel"], ["type", "url", 1, "at-form-input", 3, "ngModelChange", "ngModel", "placeholder"], ["type", "text", 1, "at-form-input", 3, "ngModelChange", "ngModel", "placeholder"], ["type", "text", 1, "at-form-input", 3, "ngModelChange", "ngModel", "placeholder", "value"], ["type", "text", "placeholder", "Content type name", 1, "at-form-input", 3, "ngModelChange", "ngModel"], ["rows", "3", "placeholder", "Description...", 1, "at-form-textarea", 3, "ngModelChange", "ngModel"], ["SelectionMode", "single", "SelectableTypes", "leaf", "Placeholder", "Select AI model...", 3, "ValueChange", "BranchConfig", "LeafConfig", "Clearable", "Value"], [1, "at-form-row"], [1, "at-form-group", 2, "flex", "1"], ["type", "number", "min", "0", 1, "at-form-input", 3, "ngModelChange", "ngModel"], ["type", "number", "min", "1", 1, "at-form-input", 3, "ngModelChange", "ngModel"], [1, "at-slide-panel", "at-detail-panel"], [1, "fa-solid", "fa-file-lines"], ["aria-label", "Close item detail", 1, "at-slide-close", 3, "click"], [1, "at-detail-item-header"], [1, "at-detail-item-name"], [1, "at-detail-badges"], [1, "at-detail-badge", "at-detail-badge-source"], [1, "at-detail-section"], [1, "at-detail-section-label"], [1, "at-detail-meta-grid"], [1, "at-detail-meta-row"], [1, "at-detail-meta-key"], [1, "at-detail-meta-value"], [1, "at-detail-actions"], [1, "fa-solid", "fa-external-link-alt"], ["disabled", "", 1, "at-action-btn", "at-secondary-btn"], [1, "fa-solid", "fa-magnifying-glass"], [1, "at-detail-badge", "at-detail-badge-type"], [1, "at-detail-badge", "at-detail-badge-file"], [1, "fa-solid", "fa-file"], ["target", "_blank", 1, "at-detail-link", 3, "href"], [1, "fa-solid", "fa-external-link-alt", 2, "font-size", "0.65rem", "margin-left", "4px"], [1, "at-detail-text-preview"], [1, "at-detail-tags"], [1, "at-tag-pill", "at-tag-weighted", 3, "font-size"], [1, "at-tag-pill", "at-tag-weighted"], [1, "at-tag-weight"], [1, "at-detail-meta-value", "at-detail-meta-mono"], ["aria-label", "Close source detail", 1, "at-slide-close", 3, "click"], ["text", "Loading source details..."], [1, "at-detail-source-header"], [1, "at-detail-badge"], [1, "at-detail-stats-strip"], [1, "at-detail-stat"], [1, "at-detail-stat-value"], [1, "at-detail-stat-label"], [1, "at-detail-section-header-row"], [1, "at-detail-section-controls"], [1, "at-detail-filter-select", 3, "ngModelChange", "ngModel"], ["title", "Re-queue failed items for processing", 1, "at-action-btn", "at-retry-btn", 3, "click"], [1, "fa-solid", "fa-rotate-right"], [1, "at-detail-content-list"], [1, "at-empty-state", 2, "padding", "16px"], [1, "at-detail-content-item"], [1, "at-detail-pagination"], [1, "at-action-btn", "at-secondary-btn", "at-source-delete-btn", 3, "click"], ["target", "_blank", 1, "at-detail-link", "at-detail-meta-value", 3, "href"], [1, "at-detail-content-item", 3, "click"], [1, "at-detail-content-item-name"], [1, "at-status-badge"], [1, "at-detail-content-item-tags"], [1, "at-detail-content-item-time"], [1, "at-page-btn", 3, "click", "disabled"], [1, "at-page-info"], [1, "at-detail-run-history"], [1, "at-detail-run-row"], [1, "at-detail-run-time"], [1, "at-detail-run-duration"], [1, "at-detail-run-items"], [1, "at-schedule-overlay", 3, "click"], [1, "at-schedule-dialog", 3, "click"], [1, "at-schedule-dialog-header"], [1, "at-schedule-dialog-body"], [1, "at-schedule-field"], [1, "at-schedule-source-name"], [1, "at-schedule-action-name"], ["for", "schedule-cron"], ["id", "schedule-cron", "type", "text", "placeholder", "0 2 * * *", 1, "mj-input", "at-schedule-cron-input", 3, "ngModelChange", "ngModel"], [1, "at-schedule-cron-preview"], [1, "at-schedule-field", "at-schedule-toggle-row"], ["for", "schedule-enabled"], ["id", "schedule-enabled", "type", "checkbox", 1, "mj-checkbox", 3, "ngModelChange", "ngModel"], [1, "at-schedule-dialog-footer"], [1, "fa-solid", "fa-triangle-exclamation"], [1, "at-confirm-message"], ["type", "text", "placeholder", "Tag A, Tag B, Tag C", 1, "mj-input", 2, "width", "100%", 3, "ngModelChange", "ngModel"], [1, "at-tax-create-context"], ["type", "text", "placeholder", "Tag name", 1, "mj-input", 2, "width", "100%", 3, "ngModelChange", "keydown.enter", "ngModel"], ["rows", "3", "placeholder", "Brief description of this tag", 1, "mj-textarea", 2, "width", "100%", 3, "ngModelChange", "ngModel"], [1, "mj-input", 2, "width", "100%", 3, "ngModelChange", "ngModel"], [3, "ngValue"], [2, "font-size", "0.85rem", "color", "var(--mj-text-secondary)", "margin", "0 0 12px"], ["TextField", "Label", "ValueField", "ID", "Placeholder", "Search and select a tag...", 3, "ValueChange", "Data", "Filterable", "ValuePrimitive"], [1, "at-schedule-dialog-overlay", 2, "z-index", "10001", 3, "click"], [1, "at-schedule-dialog", 2, "max-width", "440px", "z-index", "10002", 3, "click"], [1, "fa-solid", "fa-triangle-exclamation", 2, "color", "var(--mj-status-warning)", "margin-right", "8px"], ["aria-label", "Close warning", 1, "at-close-btn", 3, "click"], [1, "fa-solid", "fa-xmark"], [1, "at-schedule-dialog-body", 2, "text-align", "center", "padding", "24px"], [2, "color", "var(--mj-text-secondary)", "margin-bottom", "16px"], [2, "color", "var(--mj-text-muted)", "font-size", "13px"], [1, "at-action-btn", "at-primary-btn", 3, "mousedown"], [1, "fa-solid", "fa-arrow-right"]], template: function AutotaggingPipelineResourceComponent_Template(rf, ctx) { if (rf & 1) {
7886
7886
  i0.ɵɵelementStart(0, "div", 0)(1, "div", 1)(2, "div", 2)(3, "h2");
7887
7887
  i0.ɵɵelement(4, "i", 3);
7888
7888
  i0.ɵɵtext(5, " Classify");
@@ -7955,7 +7955,7 @@ AutotaggingPipelineResourceComponent = AutotaggingPipelineResourceComponent_1 =
7955
7955
  export { AutotaggingPipelineResourceComponent };
7956
7956
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(AutotaggingPipelineResourceComponent, [{
7957
7957
  type: Component,
7958
- args: [{ standalone: false, selector: 'app-autotagging-pipeline-resource', encapsulation: ViewEncapsulation.None, template: "<!-- Content Classification Dashboard -->\n<div class=\"at-dashboard\">\n\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550 LEFT NAV \u2550\u2550\u2550\u2550\u2550\u2550 -->\n <div class=\"at-left-nav\">\n <div class=\"at-left-nav-header\">\n <h2><i class=\"fa-solid fa-tags\"></i> Classify</h2>\n </div>\n <div class=\"at-left-nav-items\">\n @for (item of NavItems; track item.Tab) {\n <div class=\"at-nav-item\" [class.active]=\"ActiveTab === item.Tab\" (click)=\"SwitchTab(item.Tab)\">\n <i [class]=\"item.Icon\"></i> {{ item.Label }}\n @if (item.BadgeText) {\n <span class=\"at-nav-badge\" [class.at-nav-badge-live]=\"item.BadgeClass === 'nav-badge-live'\">{{ item.BadgeText }}</span>\n }\n </div>\n }\n <div class=\"at-nav-divider\"></div>\n <div class=\"at-nav-item\" [class.active]=\"ActiveTab === 'history'\" (click)=\"SwitchTab('history')\">\n <i class=\"fa-solid fa-clock-rotate-left\"></i> Run History\n </div>\n </div>\n <div class=\"at-left-nav-footer\">\n <button class=\"at-run-pipeline-btn\" (click)=\"RunPipeline()\" [disabled]=\"IsRunning\">\n @if (IsRunning) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Running...\n } @else {\n <i class=\"fa-solid fa-play\"></i> Run Pipeline\n }\n </button>\n </div>\n </div>\n\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550 MAIN AREA \u2550\u2550\u2550\u2550\u2550\u2550 -->\n <div class=\"at-main-area\">\n\n @if (IsLoading) {\n <div class=\"at-loading-overlay\">\n <mj-loading text=\"Loading autotagging data...\"></mj-loading>\n </div>\n }\n\n @if (!IsLoading) {\n\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n <!-- TAB 1: PIPELINE MONITOR -->\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n @if (ActiveTab === 'pipeline') {\n <div class=\"at-page-header\">\n <div>\n <div class=\"at-page-title\">Pipeline Monitor</div>\n <div class=\"at-page-subtitle\">Real-time processing status and recent activity</div>\n </div>\n <div class=\"at-page-actions\">\n <button class=\"at-action-btn at-secondary-btn\" (click)=\"LoadPipelineData()\">\n <i class=\"fa-solid fa-arrows-rotate\"></i> Refresh\n </button>\n </div>\n </div>\n <div class=\"at-page-body\">\n <!-- KPIs -->\n <div class=\"at-kpi-strip\">\n @for (kpi of KPIMetrics; track kpi.Label) {\n <div class=\"at-kpi-card\">\n <div class=\"at-kpi-value\" [class.at-kpi-error-value]=\"kpi.Label === 'Errors' && kpi.Value > 0\">{{ kpi.Value | number }}</div>\n <div class=\"at-kpi-label\">{{ kpi.Label }}</div>\n @if (kpi.Trend) {\n <div class=\"at-kpi-trend\" [class.up]=\"kpi.TrendUp\">\n @if (kpi.TrendUp) { <i class=\"fa-solid fa-arrow-up\"></i> }\n {{ kpi.Trend }}\n </div>\n }\n </div>\n }\n </div>\n\n <div class=\"at-pipeline-layout\">\n <div class=\"at-pipeline-center\">\n <!-- Pipeline stages visualization (only during active run) -->\n @if (PipelineStages.length > 0 && (IsRunning || IsPaused)) {\n <div class=\"at-pipeline-stages\">\n @for (stage of PipelineStages; track stage.Name; let last = $last) {\n <div class=\"at-pipeline-stage\"\n [class.stage-idle]=\"stage.Status === 'idle'\"\n [class.stage-active]=\"stage.Status === 'active'\"\n [class.stage-complete]=\"stage.Status === 'complete'\">\n <div class=\"at-pipeline-stage-icon\">\n @if (stage.Status === 'active') {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n } @else if (stage.Status === 'complete') {\n <i class=\"fa-solid fa-check\"></i>\n } @else {\n <i [class]=\"stage.Icon\"></i>\n }\n </div>\n <div class=\"at-pipeline-stage-name\">{{ stage.Name }}</div>\n </div>\n @if (!last) {\n <div class=\"at-stage-connector\"\n [class.connector-complete]=\"stage.Status === 'complete'\">\n </div>\n }\n }\n </div>\n }\n\n <!-- Progress bar (visible during run or paused) -->\n @if (IsRunning || IsPaused) {\n <div class=\"at-progress-section\">\n <div class=\"at-progress-header\">\n <span class=\"at-progress-stage-label\">{{ RunStage }}</span>\n <span class=\"at-progress-pct\">{{ RunProgress | number:'1.0-0' }}%</span>\n </div>\n <div class=\"at-progress-bar\"><div class=\"at-progress-fill\" [style.width.%]=\"RunProgress\" [class.at-progress-fill-paused]=\"IsPaused\"></div></div>\n @if (RunCurrentItem) {\n <div class=\"at-progress-current\">{{ RunCurrentItem }}</div>\n }\n <div class=\"at-pipeline-controls\">\n @if (IsRunning && !IsPaused) {\n <button class=\"at-action-btn at-secondary-btn\" (click)=\"PausePipeline()\" [disabled]=\"!CurrentProcessRunID\">\n <i class=\"fa-solid fa-pause\"></i> Pause\n </button>\n }\n @if (IsPaused) {\n <button class=\"at-action-btn at-primary-btn\" (click)=\"ResumePipeline()\">\n <i class=\"fa-solid fa-play\"></i> Resume\n </button>\n }\n <button class=\"at-action-btn at-danger-btn\" (click)=\"CancelPipeline()\">\n <i class=\"fa-solid fa-stop\"></i> Cancel\n </button>\n </div>\n </div>\n }\n\n <!-- D2: Live Per-Source Progress (visible during run) -->\n @if (IsRunning && LiveRunDetailRows.length > 0) {\n <div class=\"at-card\" style=\"margin-bottom: 12px;\">\n <div class=\"at-card-header\">\n <span class=\"at-card-title\"><i class=\"fa-solid fa-list-check\"></i> Per-Source Progress</span>\n <button class=\"at-action-btn at-secondary-btn\" style=\"font-size: 11px; padding: 3px 8px;\" (click)=\"LoadLiveRunDetails()\">\n <i class=\"fa-solid fa-arrows-rotate\"></i>\n </button>\n </div>\n <div class=\"at-card-body\" style=\"max-height: 200px; overflow-y: auto;\">\n <table class=\"at-run-table\">\n <thead>\n <tr>\n <th>Source</th>\n <th>Status</th>\n <th>Items</th>\n <th>Tagged</th>\n <th>Vectorized</th>\n <th>Errors</th>\n </tr>\n </thead>\n <tbody>\n @for (row of LiveRunDetailRows; track row.SourceName) {\n <tr>\n <td class=\"at-run-source-name\">{{ row.SourceName }}</td>\n <td>\n <span class=\"at-run-status-badge\" [class]=\"row.StatusClass\">\n @if (row.StatusClass === 'running') {\n <i class=\"fa-solid fa-spinner fa-spin\" style=\"font-size: 0.55rem\"></i>\n }\n {{ row.Status }}\n </span>\n </td>\n <td>{{ row.ItemsProcessed }}</td>\n <td>{{ row.ItemsTagged }}</td>\n <td>{{ row.ItemsVectorized }}</td>\n <td [class.run-error-text]=\"row.ErrorCount > 0\">{{ row.ErrorCount }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n </div>\n }\n\n <!-- Recent Processing Feed -->\n <div class=\"at-card at-feed-card\">\n <div class=\"at-card-header\">\n <span class=\"at-card-title\"><i class=\"fa-solid fa-bolt\"></i> Recent Processing</span>\n <div class=\"at-feed-header-actions\">\n <button class=\"at-feed-sort-btn\" (click)=\"ToggleFeedSort()\"\n [title]=\"FeedSortOrder === 'newest' ? 'Showing newest first' : 'Showing oldest first'\">\n <i class=\"fa-solid\" [class.fa-arrow-down-short-wide]=\"FeedSortOrder === 'newest'\"\n [class.fa-arrow-up-short-wide]=\"FeedSortOrder === 'oldest'\"></i>\n {{ FeedSortOrder === 'newest' ? 'Newest' : 'Oldest' }}\n </button>\n <span class=\"at-feed-count\">{{ FilteredFeedItems.length }} items</span>\n </div>\n </div>\n <!-- Feed search bar -->\n <div class=\"at-feed-search-bar\">\n <i class=\"fa-solid fa-search at-feed-search-icon\"></i>\n <input type=\"text\"\n class=\"mj-input at-feed-search-input\"\n placeholder=\"Search items, sources, or tags...\"\n [(ngModel)]=\"FeedSearchQuery\"\n (input)=\"OnFeedSearchChange()\">\n @if (FeedSearchQuery) {\n <button class=\"at-feed-search-clear\" (click)=\"FeedSearchQuery = ''; OnFeedSearchChange()\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n }\n </div>\n <div class=\"at-card-body at-feed-scroll-body\">\n @if (FilteredFeedItems.length === 0) {\n <div class=\"at-empty-state\">\n <i class=\"fa-solid fa-inbox\"></i>\n @if (FeedSearchQuery) {\n <p>No items match \"{{ FeedSearchQuery }}\"</p>\n } @else {\n <p>No processed items yet.</p>\n }\n </div>\n }\n @for (item of PaginatedFeedItems; track item.Name + item.SourceName + item.TimeAgo) {\n <div class=\"at-feed-item at-feed-item-clickable\" (click)=\"OpenFeedItemDetail(GetFeedItemOriginalIndex(item))\">\n <div class=\"at-feed-status-dot\" [class]=\"item.Status\"></div>\n <div class=\"at-feed-item-content\">\n <span class=\"at-feed-item-name\">{{ item.Name }}</span>\n <span class=\"at-feed-item-source-label\">{{ item.SourceName }}</span>\n </div>\n <div class=\"at-feed-item-tags\">\n @for (tag of item.Tags; track tag) {\n <span class=\"at-feed-tag\">{{ tag }}</span>\n }\n </div>\n <span class=\"at-feed-item-time\">{{ item.TimeAgo }}</span>\n </div>\n }\n </div>\n <!-- Feed pagination -->\n @if (FeedTotalPages > 1) {\n <div class=\"at-feed-pagination\">\n <button class=\"at-action-btn at-secondary-btn\" [disabled]=\"FeedPage === 0\" (click)=\"FeedPrevPage()\">\n <i class=\"fa-solid fa-chevron-left\"></i>\n </button>\n <span class=\"at-feed-pagination-label\">Page {{ FeedPage + 1 }} of {{ FeedTotalPages }}</span>\n <button class=\"at-action-btn at-secondary-btn\" [disabled]=\"FeedPage >= FeedTotalPages - 1\" (click)=\"FeedNextPage()\">\n <i class=\"fa-solid fa-chevron-right\"></i>\n </button>\n </div>\n }\n </div>\n </div>\n\n <!-- Right sidebar -->\n <div class=\"at-pipeline-right\">\n <!-- Sources Quick List -->\n <div class=\"at-card\">\n <div class=\"at-card-header\">\n <span class=\"at-card-title\"><i class=\"fa-solid fa-database\"></i> Sources</span>\n </div>\n <div class=\"at-card-body\">\n @for (source of SourceMinis; track source.ID) {\n <div class=\"at-source-mini\">\n <div class=\"at-source-mini-icon\"><i [class]=\"source.Icon\"></i></div>\n <div class=\"at-source-mini-info\">\n <div class=\"at-source-mini-name\">{{ source.Name }}</div>\n <div class=\"at-source-mini-meta\">{{ source.Meta }}</div>\n </div>\n <div class=\"at-source-mini-status\" [class]=\"source.StatusClass\"></div>\n </div>\n }\n </div>\n </div>\n <!-- Trending Tags -->\n <div class=\"at-card at-tag-cloud-card\">\n <div class=\"at-card-title\" style=\"margin-bottom: 10px;\"><i class=\"fa-solid fa-chart-bar\"></i> Trending Tags</div>\n <div class=\"at-tag-cloud\">\n @for (tag of TrendingTags; track tag.Tag) {\n <span class=\"at-tag-pill\" [class]=\"tag.SizeClass\"\n [style.opacity]=\"0.4 + tag.AvgWeight * 0.6\"\n [title]=\"'Weight: ' + tag.AvgWeight.toFixed(2)\">{{ tag.Tag }}</span>\n }\n </div>\n </div>\n\n <!-- Pipeline Settings Widget -->\n <div class=\"at-card at-config-card\">\n <div class=\"at-card-header\" (click)=\"TogglePipelineConfig()\" style=\"cursor:pointer\">\n <span class=\"at-card-title\"><i class=\"fa-solid fa-sliders\"></i> Pipeline Settings</span>\n <i class=\"fa-solid\" [class.fa-chevron-down]=\"!ShowPipelineConfig\" [class.fa-chevron-up]=\"ShowPipelineConfig\" style=\"font-size:0.7rem; color:var(--mj-text-muted)\"></i>\n </div>\n @if (ShowPipelineConfig) {\n <div class=\"at-card-body at-config-body\">\n <div class=\"at-config-row\">\n <label class=\"at-config-label\">Batch Size</label>\n <div class=\"at-config-control\">\n <input type=\"number\" class=\"at-config-input\" min=\"10\" max=\"1000\" step=\"10\"\n [(ngModel)]=\"PipelineConfig.Pipeline!.BatchSize\">\n </div>\n </div>\n <div class=\"at-config-row\">\n <label class=\"at-config-label\">Throttle (ms)</label>\n <div class=\"at-config-control\">\n <input type=\"range\" class=\"at-config-slider\" min=\"0\" max=\"5000\" step=\"100\"\n [(ngModel)]=\"PipelineConfig.Pipeline!.DelayBetweenBatchesMs\">\n <span class=\"at-config-value\">{{ PipelineConfig.Pipeline!.DelayBetweenBatchesMs }}ms</span>\n </div>\n </div>\n <div class=\"at-config-row\">\n <label class=\"at-config-label\">Error Tolerance</label>\n <div class=\"at-config-control\">\n <input type=\"range\" class=\"at-config-slider\" min=\"5\" max=\"50\" step=\"5\"\n [(ngModel)]=\"PipelineConfig.Pipeline!.ErrorThresholdPercent\">\n <span class=\"at-config-value\">{{ PipelineConfig.Pipeline!.ErrorThresholdPercent }}%</span>\n </div>\n </div>\n <div class=\"at-config-row\">\n <label class=\"at-config-label\">Auto-resume</label>\n <div class=\"at-config-control\">\n <label class=\"at-config-toggle\">\n <input type=\"checkbox\" [(ngModel)]=\"PipelineConfig.Pipeline!.ResumeFromLastBatch\">\n <span class=\"at-toggle-track\"><span class=\"at-toggle-thumb\"></span></span>\n </label>\n </div>\n </div>\n <div class=\"at-config-divider\"></div>\n <div class=\"at-config-section-label\">LLM Rate Limits</div>\n <div class=\"at-config-row\">\n <label class=\"at-config-label\">Requests/min</label>\n <div class=\"at-config-control\">\n <input type=\"number\" class=\"at-config-input\" min=\"1\" max=\"500\"\n [(ngModel)]=\"PipelineConfig.RateLimits!.LLM!.RequestsPerMinute\">\n </div>\n </div>\n <div class=\"at-config-row\">\n <label class=\"at-config-label\">Tokens/min</label>\n <div class=\"at-config-control\">\n <input type=\"number\" class=\"at-config-input\" min=\"1000\" max=\"5000000\" step=\"10000\"\n [(ngModel)]=\"PipelineConfig.RateLimits!.LLM!.TokensPerMinute\">\n <span class=\"at-config-value\">{{ FormatTokenCount(PipelineConfig.RateLimits!.LLM!.TokensPerMinute ?? 0) }}</span>\n </div>\n </div>\n <div class=\"at-config-section-label\">Embedding Rate Limits</div>\n <div class=\"at-config-row\">\n <label class=\"at-config-label\">Requests/min</label>\n <div class=\"at-config-control\">\n <input type=\"number\" class=\"at-config-input\" min=\"1\" max=\"1000\"\n [(ngModel)]=\"PipelineConfig.RateLimits!.Embedding!.RequestsPerMinute\">\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n }\n\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n <!-- TAB 2: SOURCES -->\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n @if (ActiveTab === 'sources') {\n <div class=\"at-page-header\">\n <div>\n <div class=\"at-page-title\">Content Sources</div>\n <div class=\"at-page-subtitle\">Configure where content is ingested from</div>\n </div>\n <div class=\"at-page-actions\">\n <button class=\"at-action-btn at-primary-btn\" (click)=\"OpenAddSourceForm()\">\n <i class=\"fa-solid fa-plus\"></i> Add Source\n </button>\n </div>\n </div>\n <div class=\"at-page-body\">\n <div class=\"at-sources-grid\">\n @for (card of SourceCards; track card.ID) {\n <div class=\"at-source-card-full at-source-card-clickable\" (click)=\"OpenSourceDetail(card)\">\n <div class=\"at-source-card-header\">\n <div class=\"at-source-card-icon\"><i [class]=\"card.Icon\"></i></div>\n <div>\n <div class=\"at-source-card-title\">{{ card.Name }}</div>\n <div class=\"at-source-card-type\">{{ card.SourceTypeName }}@if (card.RequiresFileType) { \u00B7 {{ card.FileTypeName }}}</div>\n </div>\n <div class=\"at-source-card-status\" [class]=\"card.StatusClass\">\n <div class=\"at-source-mini-status\" [class]=\"card.StatusClass\"></div>\n {{ card.StatusLabel }}\n </div>\n </div>\n @if (card.URL) {\n <div class=\"at-source-card-url\">{{ card.URL }}</div>\n }\n <div class=\"at-source-card-stats\">\n <div class=\"at-source-stat\">\n <div class=\"at-source-stat-value\">{{ formatNumber(card.ItemCount) }}</div>\n <div class=\"at-source-stat-label\">Items</div>\n </div>\n <div class=\"at-source-stat\">\n <div class=\"at-source-stat-value\">{{ formatNumber(card.TagCount) }}</div>\n <div class=\"at-source-stat-label\">Tags</div>\n </div>\n <div class=\"at-source-stat\">\n <div class=\"at-source-stat-value\">{{ card.AvgTags }}</div>\n <div class=\"at-source-stat-label\">Avg Tags</div>\n </div>\n <div class=\"at-source-stat\">\n <div class=\"at-source-stat-value\">{{ card.LastRunAgo }}</div>\n <div class=\"at-source-stat-label\">Last Run</div>\n </div>\n </div>\n <!-- Schedule indicator -->\n @if (card.ScheduledActionID) {\n <div class=\"at-schedule-indicator\" (click)=\"RemoveSchedule(card); $event.stopPropagation()\" title=\"Click to remove schedule\">\n <i class=\"fa-regular fa-clock\"></i>\n <span>{{ GetScheduleLabel(card) }}</span>\n </div>\n }\n <div class=\"at-source-card-actions\">\n <button class=\"at-source-action-btn\" (click)=\"OpenEditSourceForm(card); $event.stopPropagation()\"><i class=\"fa-solid fa-pen\"></i> Edit</button>\n <button class=\"at-source-action-btn\" (click)=\"RunPipelineForSource(card.ID); $event.stopPropagation()\"><i class=\"fa-solid fa-play\"></i> Run</button>\n @if (!card.ScheduledActionID) {\n <button class=\"at-source-action-btn at-source-schedule-btn\" (click)=\"OpenScheduleDialog(card); $event.stopPropagation()\"><i class=\"fa-regular fa-clock\"></i> Schedule</button>\n }\n <button class=\"at-source-action-btn at-source-delete-btn\" (click)=\"DeleteSource(card); $event.stopPropagation()\"><i class=\"fa-solid fa-trash\"></i> Delete</button>\n </div>\n </div>\n }\n\n <!-- Add Source Card -->\n <div class=\"at-add-source-card\" (click)=\"OpenAddSourceForm()\">\n <i class=\"fa-solid fa-plus-circle\"></i>\n <span style=\"font-size: 0.85rem; font-weight: 600;\">Add Content Source</span>\n <span style=\"font-size: 0.72rem;\">Web, RSS, Email, Files, API</span>\n </div>\n </div>\n\n <!-- Content Item Duplicates Section -->\n <div class=\"at-dedup-section\">\n <div class=\"at-dedup-header\">\n <div>\n <h3 class=\"at-dedup-title\">\n <i class=\"fa-solid fa-clone\"></i>\n Content Duplicates\n </h3>\n <span class=\"at-dedup-subtitle\">Review detected duplicate content items across sources</span>\n </div>\n <button class=\"at-action-btn at-secondary-btn\" (click)=\"LoadContentDuplicates()\" [disabled]=\"IsLoadingDuplicates\">\n @if (IsLoadingDuplicates) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Loading...\n } @else {\n <i class=\"fa-solid fa-arrows-rotate\"></i> Load Duplicates\n }\n </button>\n </div>\n\n @if (ContentDuplicates.length > 0) {\n <div class=\"at-dedup-list\">\n @for (dup of ContentDuplicates; track dup.ID) {\n <div class=\"at-dedup-card\">\n <div class=\"at-dedup-pair\">\n <div class=\"at-dedup-item\">\n <span class=\"at-dedup-item-name\">{{ dup.ItemAName }}</span>\n <span class=\"at-dedup-item-source\">{{ dup.ItemASource }}</span>\n </div>\n <div class=\"at-dedup-vs\">\n <i class=\"fa-solid fa-arrows-left-right\"></i>\n </div>\n <div class=\"at-dedup-item\">\n <span class=\"at-dedup-item-name\">{{ dup.ItemBName }}</span>\n <span class=\"at-dedup-item-source\">{{ dup.ItemBSource }}</span>\n </div>\n </div>\n <div class=\"at-dedup-meta\">\n <span class=\"at-dedup-score\">{{ (dup.SimilarityScore * 100).toFixed(0) }}% match</span>\n <span class=\"at-dedup-method\">{{ dup.DetectionMethod }}</span>\n </div>\n <div class=\"at-dedup-actions\">\n <button class=\"at-action-btn at-primary-btn at-dedup-confirm\" (click)=\"ConfirmContentDuplicate(dup)\">\n <i class=\"fa-solid fa-check\"></i> Confirm\n </button>\n <button class=\"at-action-btn at-secondary-btn at-dedup-dismiss\" (click)=\"DismissContentDuplicate(dup)\">\n <i class=\"fa-solid fa-times\"></i> Dismiss\n </button>\n </div>\n </div>\n }\n </div>\n } @else if (!IsLoadingDuplicates) {\n <div class=\"at-dedup-empty\">\n <i class=\"fa-solid fa-check-circle\"></i>\n <p>No pending duplicates. Click \"Load Duplicates\" to check.</p>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n <!-- TAB 3: CONTENT TYPES -->\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n @if (ActiveTab === 'types') {\n <div class=\"at-page-header\">\n <div>\n <div class=\"at-page-title\">Content Types</div>\n <div class=\"at-page-subtitle\">Configure AI tagging rules per content category</div>\n </div>\n <div class=\"at-page-actions\">\n <button class=\"at-action-btn at-primary-btn\" (click)=\"OpenAddTypeForm()\">\n <i class=\"fa-solid fa-plus\"></i> Add Type\n </button>\n </div>\n </div>\n <div class=\"at-page-body\">\n <div class=\"at-ct-grid\">\n @for (card of ContentTypeCards; track card.ID) {\n <div class=\"at-ct-card\">\n <div class=\"at-ct-card-header\">\n <span class=\"at-ct-card-name\">{{ card.Name }}</span>\n <span class=\"at-ct-card-model\">{{ card.AIModelName }}</span>\n </div>\n <div class=\"at-ct-field\">\n <span class=\"at-ct-field-label\">Description</span>\n <span class=\"at-ct-field-value\">{{ card.Description || '\\u2014' }}</span>\n </div>\n <div class=\"at-ct-field\">\n <span class=\"at-ct-field-label\">Sources Using</span>\n <span class=\"at-ct-field-value\">{{ card.SourcesUsing }}</span>\n </div>\n <div class=\"at-ct-field\">\n <span class=\"at-ct-field-label\">Items Tagged</span>\n <span class=\"at-ct-field-value\">{{ formatNumber(card.ItemsTagged) }}</span>\n </div>\n <div class=\"at-ct-tag-range\">\n <i class=\"fa-solid fa-tags\"></i>\n <span>{{ card.MinTags }}</span>\n <div class=\"at-ct-tag-range-bar\">\n <div class=\"at-ct-tag-range-fill\" [style.left.%]=\"card.RangeLeftPct\" [style.right.%]=\"card.RangeRightPct\"></div>\n </div>\n <span>{{ card.MaxTags }}</span>\n <span class=\"at-ct-range-suffix\">tags/item</span>\n </div>\n <div class=\"at-source-card-actions\" style=\"margin-top: 10px;\">\n <button class=\"at-source-action-btn\" (click)=\"OpenEditTypeForm(card)\"><i class=\"fa-solid fa-pen\"></i> Edit</button>\n </div>\n </div>\n }\n <!-- Add Content Type Card -->\n <div class=\"at-add-type-card\" (click)=\"OpenAddTypeForm()\">\n <i class=\"fa-solid fa-plus-circle\"></i>\n <span style=\"font-size: 0.85rem; font-weight: 600;\">Add Content Type</span>\n <span style=\"font-size: 0.72rem;\">Configure tagging rules</span>\n </div>\n </div>\n </div>\n }\n\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n <!-- TAB 4: TAG LIBRARY -->\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n @if (ActiveTab === 'tags') {\n <div class=\"at-page-header\">\n <div>\n <div class=\"at-page-title\">Tag Library</div>\n <div class=\"at-page-subtitle\">{{ TagRows.length }} unique tags across all content sources</div>\n </div>\n <div class=\"at-page-actions\">\n <input type=\"text\" class=\"at-search-input\" placeholder=\"Search tags...\"\n [(ngModel)]=\"TagSearchQuery\" (input)=\"FilterTags()\">\n </div>\n </div>\n <div class=\"at-page-body\">\n <div class=\"at-tag-lib-layout\">\n <div class=\"at-tag-lib-main\">\n <div class=\"at-card\">\n <div class=\"at-card-body\" style=\"max-height: 500px; overflow-y: auto;\">\n <table class=\"at-tag-table\">\n <thead>\n <tr>\n <th>Tag</th>\n <th>Count</th>\n <th>Avg Weight</th>\n <th>Distribution</th>\n <th>Top Source</th>\n <th>First Seen</th>\n </tr>\n </thead>\n <tbody>\n @for (row of FilteredTagRows; track row.Tag) {\n <tr class=\"at-tag-row-clickable\" (click)=\"DrillDownTag(row.Tag)\"\n [class.at-tag-row-selected]=\"SelectedDrillDownTag === row.Tag\">\n <td class=\"at-tag-name-cell\">{{ row.Tag }}</td>\n <td>{{ row.UsageCount }}</td>\n <td>\n <div class=\"at-weight-indicator\">\n <div class=\"at-weight-bar\">\n <div class=\"at-weight-bar-fill\" [style.width.%]=\"row.AvgWeight * 100\"\n [class.at-weight-high]=\"row.AvgWeight >= 0.7\"\n [class.at-weight-medium]=\"row.AvgWeight >= 0.4 && row.AvgWeight < 0.7\"\n [class.at-weight-low]=\"row.AvgWeight < 0.4\"></div>\n </div>\n <span class=\"at-weight-value\">{{ row.AvgWeight.toFixed(2) }}</span>\n </div>\n </td>\n <td>\n <div class=\"at-tag-bar\">\n <div class=\"at-tag-bar-fill\" [style.width.%]=\"row.BarWidthPct\"></div>\n </div>\n </td>\n <td>{{ row.TopSource }}</td>\n <td>{{ row.FirstSeen }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n </div>\n\n <!-- Tag drill-down: content items matching selected tag -->\n @if (SelectedDrillDownTag) {\n <div class=\"at-card\" style=\"margin-top: 12px;\">\n <div class=\"at-card-header\">\n <span class=\"at-card-title\">\n <i class=\"fa-solid fa-tag\"></i>\n Content items tagged \"{{ SelectedDrillDownTag }}\"\n ({{ TagDrillDownItems.length }})\n </span>\n <button class=\"at-slide-close\" (click)=\"CloseDrillDownTag()\" style=\"background:none;border:none;cursor:pointer;color:var(--mj-text-muted)\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n <div class=\"at-card-body\" style=\"max-height: 300px; overflow-y: auto;\">\n @if (TagDrillDownItems.length === 0) {\n <div class=\"at-empty-state\"><p>No content items found for this tag.</p></div>\n } @else {\n <table class=\"at-tag-table\">\n <thead>\n <tr>\n <th>Name</th>\n <th>Source</th>\n <th>Weight</th>\n <th>Updated</th>\n </tr>\n </thead>\n <tbody>\n @for (di of TagDrillDownItems; track di.ID) {\n <tr class=\"at-tag-row-clickable\" (click)=\"OpenItemDetailByID(di.ID)\">\n <td>{{ di.Name }}</td>\n <td>{{ di.SourceName }}</td>\n <td>{{ FormatWeight(di.Weight) }}</td>\n <td>{{ di.UpdatedAt }}</td>\n </tr>\n }\n </tbody>\n </table>\n }\n </div>\n </div>\n }\n </div>\n <div class=\"at-tag-lib-sidebar\">\n <div class=\"at-card at-tag-cloud-card\">\n <div class=\"at-card-title\" style=\"margin-bottom: 12px;\"><i class=\"fa-solid fa-cloud\"></i> Tag Cloud</div>\n @if (TagCloudWordItems.length > 0) {\n <mj-word-cloud\n [Items]=\"TagCloudWordItems\"\n [MaxFontSize]=\"40\"\n [MinFontSize]=\"12\"\n [MaxItems]=\"20\"\n Layout=\"spiral\"\n ColorMode=\"weight-gradient\"\n [Interactive]=\"true\"\n [Animate]=\"true\">\n </mj-word-cloud>\n } @else {\n <div class=\"at-tag-cloud-empty\">No tags yet</div>\n }\n </div>\n <div class=\"at-card\" style=\"padding: 16px; margin-top: 12px;\">\n <div class=\"at-card-title\" style=\"margin-bottom: 10px;\"><i class=\"fa-solid fa-chart-pie\"></i> By Source</div>\n <div class=\"at-tags-by-source\">\n @for (s of TagsBySource; track s.SourceName) {\n <div class=\"at-tag-source-row\">\n <span>{{ s.SourceName }}</span>\n <strong>{{ s.Count }}</strong>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n <!-- TAB 6: TAXONOMY GOVERNANCE -->\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n @if (ActiveTab === 'taxonomy') {\n <div class=\"at-page-header\">\n <div>\n <div class=\"at-page-title\">Taxonomy Governance</div>\n <div class=\"at-page-subtitle\">Manage tag hierarchy, resolve duplicates, and monitor taxonomy health &mdash; <strong>{{ TaxHealth.Total }} total tags</strong></div>\n </div>\n <div class=\"at-page-actions\">\n <button class=\"at-action-btn at-secondary-btn\" (click)=\"RefreshTaxonomyData()\">\n <i class=\"fa-solid fa-arrows-rotate\"></i> Refresh\n </button>\n </div>\n </div>\n\n <!-- Sub-tab strip -->\n <div class=\"at-tax-tab-strip\">\n <div class=\"at-tax-tab\" [class.active]=\"TaxSubTab === 'tree'\" (click)=\"SwitchTaxSubTab('tree')\">\n <i class=\"fa-solid fa-sitemap\"></i> Tree View\n </div>\n <div class=\"at-tax-tab\" [class.active]=\"TaxSubTab === 'duplicates'\" (click)=\"SwitchTaxSubTab('duplicates')\">\n <i class=\"fa-solid fa-link\"></i> Duplicates\n @if (TaxDuplicates.length > 0) {\n <span class=\"at-tax-tab-badge at-tax-badge-warning\">{{ TaxDuplicates.length }}</span>\n }\n </div>\n <div class=\"at-tax-tab\" [class.active]=\"TaxSubTab === 'orphans'\" (click)=\"SwitchTaxSubTab('orphans')\">\n <i class=\"fa-solid fa-ban\"></i> Orphans\n @if (TaxOrphans.length > 0) {\n <span class=\"at-tax-tab-badge at-tax-badge-error\">{{ TaxOrphans.length }}</span>\n }\n </div>\n <div class=\"at-tax-tab\" [class.active]=\"TaxSubTab === 'treemap'\" (click)=\"SwitchTaxSubTab('treemap')\">\n <i class=\"fa-solid fa-chart-tree-map\"></i> Treemap\n </div>\n <div class=\"at-tax-tab\" [class.active]=\"TaxSubTab === 'audit'\" (click)=\"SwitchTaxSubTab('audit')\">\n <i class=\"fa-solid fa-scroll\"></i> Audit Log\n </div>\n </div>\n\n <div class=\"at-page-body\">\n\n <!-- \u2550\u2550 SUB-TAB 1: TREE VIEW \u2550\u2550 -->\n @if (TaxSubTab === 'tree') {\n <div class=\"at-tax-split-view\">\n <!-- Tree panel -->\n <div class=\"at-tax-tree-panel\" style=\"position: relative;\">\n <div class=\"at-tax-tree-toolbar\">\n <input type=\"text\" class=\"at-search-input\" style=\"flex: 1;\" placeholder=\"Search tags...\"\n [(ngModel)]=\"TaxTreeSearch\" (input)=\"FilterTaxTree()\">\n <button class=\"at-tax-toolbar-btn\" title=\"Add root tag\" (click)=\"OpenCreateRootTag()\">\n <i class=\"fa-solid fa-plus\"></i>\n </button>\n <button class=\"at-tax-toolbar-btn\" [class.active]=\"TaxMultiSelectMode\"\n title=\"Toggle multi-select for drag reparenting\" (click)=\"ToggleMultiSelectMode()\">\n <i class=\"fa-solid fa-check-double\"></i>\n </button>\n </div>\n <div class=\"at-tax-tree-body\"\n (dragover)=\"$event.preventDefault()\"\n (drop)=\"OnDropToRoot($event)\">\n @if (TaxFilteredNodes.length === 0) {\n <div class=\"at-empty-state\">\n <i class=\"fa-solid fa-sitemap\"></i>\n <p>No tags found</p>\n </div>\n }\n @for (node of TaxFilteredNodes; track node.ID) {\n <div class=\"at-tax-tree-node\"\n [class.at-tax-node-selected]=\"node.IsSelected\"\n [class.at-tax-node-drag-over]=\"TaxDragOverNodeID === node.ID\"\n [class.at-tax-node-multi-selected]=\"IsNodeMultiSelected(node.ID)\"\n [style.padding-left.px]=\"16 + node.Depth * 20\"\n [attr.draggable]=\"true\"\n (dragstart)=\"OnTreeNodeDragStart($event, node)\"\n (dragover)=\"OnTreeNodeDragOver($event, node)\"\n (dragleave)=\"OnTreeNodeDragLeave()\"\n (drop)=\"OnTreeNodeDrop($event, node); $event.stopPropagation()\"\n (click)=\"SelectTaxNode(node)\">\n @if (TaxMultiSelectMode) {\n <input type=\"checkbox\" class=\"at-tax-tree-checkbox\"\n [checked]=\"IsNodeMultiSelected(node.ID)\"\n (click)=\"ToggleNodeSelection(node, $event)\">\n }\n <span class=\"at-tax-tree-arrow\"\n [class.at-tax-arrow-expanded]=\"node.IsExpanded && node.Children.length > 0\"\n [class.at-tax-arrow-collapsed]=\"!node.IsExpanded && node.Children.length > 0\"\n [class.at-tax-arrow-leaf]=\"node.Children.length === 0\"\n (click)=\"ToggleTaxNode(node); $event.stopPropagation()\"></span>\n <span class=\"at-tax-health-dot\" [class]=\"node.HealthColor\"></span>\n <span class=\"at-tax-tree-label\" [class.at-tax-tree-label-selected]=\"node.IsSelected\">{{ node.Name }}</span>\n <span class=\"at-tax-tree-count\">({{ node.ItemCount }})</span>\n <span class=\"at-tax-tree-add-child\" title=\"Add child tag\"\n (click)=\"OpenCreateChildTagFor(node); $event.stopPropagation()\">\n <i class=\"fa-solid fa-plus\"></i>\n </span>\n </div>\n }\n </div>\n @if (TaxTreeSaving) {\n <div class=\"at-tax-tree-saving-overlay\">\n <mj-loading text=\"Moving tags...\" size=\"small\"></mj-loading>\n </div>\n }\n </div>\n\n <!-- Details panel -->\n <div class=\"at-tax-details-panel\">\n @if (TaxSelectedNode) {\n <div class=\"at-tax-details-header\">\n <!-- Breadcrumb -->\n <div class=\"at-tax-breadcrumb\">\n @for (bc of GetTaxBreadcrumb(TaxSelectedNode); track bc.ID) {\n <span class=\"at-tax-bc-link\" (click)=\"NavigateToBreadcrumb(bc.ID)\">{{ bc.Name }}</span>\n <span class=\"at-tax-bc-sep\">&rsaquo;</span>\n }\n <span class=\"at-tax-bc-current\">{{ TaxSelectedNode.Name }}</span>\n </div>\n\n @if (!TaxIsEditing) {\n <div class=\"at-tax-details-title\">\n {{ TaxSelectedNode.DisplayName }}\n <span class=\"at-tax-edit-icon\" (click)=\"StartEditTag()\" title=\"Edit name\">\n <i class=\"fa-solid fa-pen\"></i>\n </span>\n </div>\n @if (TaxSelectedNode.Description) {\n <div class=\"at-tax-details-desc\">{{ TaxSelectedNode.Description }}</div>\n }\n } @else {\n <div class=\"at-tax-edit-form\">\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">Name</label>\n <input type=\"text\" class=\"at-form-input\" [(ngModel)]=\"TaxEditName\">\n </div>\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">Description</label>\n <textarea class=\"at-form-textarea\" rows=\"3\" [(ngModel)]=\"TaxEditDescription\"></textarea>\n </div>\n <div class=\"at-form-actions\">\n <button class=\"at-action-btn at-primary-btn\" (click)=\"SaveEditTag()\">Save</button>\n <button class=\"at-action-btn at-secondary-btn\" (click)=\"CancelEditTag()\">Cancel</button>\n </div>\n </div>\n }\n </div>\n\n <!-- Stats row -->\n <div class=\"at-tax-stats-row\">\n <div class=\"at-tax-stat-item\">\n <div class=\"at-tax-stat-value\">{{ TaxSelectedNode.ItemCount }}</div>\n <div class=\"at-tax-stat-label\">Items Tagged</div>\n </div>\n <div class=\"at-tax-stat-item\">\n <div class=\"at-tax-stat-value\">{{ TaxSelectedNode.AvgWeight.toFixed(2) }}</div>\n <div class=\"at-tax-stat-label\">Avg Weight</div>\n </div>\n <div class=\"at-tax-stat-item\">\n <div class=\"at-tax-stat-value\">{{ TaxSelectedNode.Children.length }}</div>\n <div class=\"at-tax-stat-label\">Children</div>\n </div>\n <div class=\"at-tax-stat-item\">\n <div class=\"at-tax-stat-value\">{{ TaxSelectedNode.Depth }}</div>\n <div class=\"at-tax-stat-label\">Depth</div>\n </div>\n <div class=\"at-tax-stat-item\">\n <div class=\"at-tax-stat-value at-tax-stat-date\">{{ TaxSelectedNode.FirstSeen }}</div>\n <div class=\"at-tax-stat-label\">First Seen</div>\n </div>\n </div>\n\n <!-- Action toolbar -->\n @if (!TaxIsEditing) {\n <div class=\"at-tax-action-toolbar\">\n <button class=\"at-tax-action-btn\" (click)=\"OpenCreateChildTag()\"><i class=\"fa-solid fa-plus\"></i> Add Child</button>\n <button class=\"at-tax-action-btn\" (click)=\"StartEditTag()\"><i class=\"fa-solid fa-pen\"></i> Rename</button>\n <button class=\"at-tax-action-btn\" (click)=\"OpenMoveDialog(TaxSelectedNode)\"><i class=\"fa-solid fa-arrows-up-down\"></i> Move</button>\n <button class=\"at-tax-action-btn\" (click)=\"OpenMergeIntoDialog(TaxSelectedNode)\"><i class=\"fa-solid fa-compress\"></i> Merge Into...</button>\n <button class=\"at-tax-action-btn\" (click)=\"OpenSplitDialog(TaxSelectedNode)\"><i class=\"fa-solid fa-code-branch\"></i> Split</button>\n <button class=\"at-tax-action-btn at-tax-action-danger\" (click)=\"DeleteTag(TaxSelectedNode)\"><i class=\"fa-solid fa-trash\"></i> Delete</button>\n </div>\n }\n\n <!-- Child tags -->\n @if (TaxSelectedNode.Children.length > 0) {\n <div class=\"at-tax-detail-section\">\n <div class=\"at-tax-section-title\">Child Tags</div>\n <div class=\"at-tax-child-chips\">\n @for (child of TaxSelectedNode.Children; track child.ID) {\n <span class=\"at-tax-child-chip\" (click)=\"SelectTaxNode(child)\">\n {{ child.Name }}\n <span class=\"at-tax-chip-count\">{{ child.ItemCount }}</span>\n </span>\n }\n </div>\n </div>\n }\n\n <!-- Recently tagged items -->\n @if (TaxRecentItems.length > 0) {\n <div class=\"at-tax-detail-section\">\n <div class=\"at-tax-section-title\">Recently Tagged Items</div>\n <div class=\"at-tax-recent-list\">\n @for (item of TaxRecentItems; track $index) {\n <div class=\"at-tax-recent-item\">\n <div class=\"at-tax-recent-icon\"><i [class]=\"item.Icon\"></i></div>\n <div class=\"at-tax-recent-name\">{{ item.Name }}</div>\n <div class=\"at-tax-recent-weight\">{{ item.Weight.toFixed(2) }}</div>\n <div class=\"at-tax-recent-date\">{{ item.Date }}</div>\n </div>\n }\n </div>\n </div>\n }\n } @else {\n <div class=\"at-empty-state\" style=\"height: 100%;\">\n <i class=\"fa-solid fa-hand-pointer\"></i>\n <p>Select a tag from the tree to view details</p>\n </div>\n }\n </div>\n </div>\n\n <!-- Health bar -->\n <div class=\"at-tax-health-bar\">\n <span class=\"at-tax-health-label\">Taxonomy Health</span>\n <div class=\"at-tax-health-stat\">\n <span class=\"at-tax-dot at-tax-dot-total\"></span>\n <span class=\"at-tax-health-value\">{{ TaxHealth.Total }}</span>\n <span class=\"at-tax-health-text\">Total</span>\n </div>\n <div class=\"at-tax-health-stat\">\n <span class=\"at-tax-dot at-tax-dot-healthy\"></span>\n <span class=\"at-tax-health-value at-tax-val-success\">{{ TaxHealth.Healthy }}</span>\n <span class=\"at-tax-health-text\">Healthy</span>\n </div>\n <div class=\"at-tax-health-stat\">\n <span class=\"at-tax-dot at-tax-dot-attention\"></span>\n <span class=\"at-tax-health-value at-tax-val-warning\">{{ TaxHealth.NeedAttention }}</span>\n <span class=\"at-tax-health-text\">Need Attention</span>\n </div>\n <div class=\"at-tax-health-stat\">\n <span class=\"at-tax-dot at-tax-dot-orphaned\"></span>\n <span class=\"at-tax-health-value at-tax-val-error\">{{ TaxHealth.Orphaned }}</span>\n <span class=\"at-tax-health-text\">Orphaned</span>\n </div>\n <div class=\"at-tax-health-stat\">\n <span class=\"at-tax-dot at-tax-dot-duplicates\"></span>\n <span class=\"at-tax-health-value at-tax-val-info\">{{ TaxHealth.Duplicates }}</span>\n <span class=\"at-tax-health-text\">Duplicate Candidates</span>\n </div>\n </div>\n }\n\n <!-- \u2550\u2550 SUB-TAB 2: DUPLICATES \u2550\u2550 -->\n @if (TaxSubTab === 'duplicates') {\n <div class=\"at-tax-dup-stats-bar\">\n <div class=\"at-tax-dup-stat\"><strong>{{ TaxDuplicates.length }}</strong> candidates found</div>\n <div class=\"at-tax-dup-stat at-tax-dup-high\"><strong>{{ TaxHighConfidenceDupeCount }}</strong> high confidence (&gt;85%)</div>\n <div class=\"at-tax-dup-stat at-tax-dup-moderate\"><strong>{{ TaxModerateDupeCount }}</strong> moderate (70-85%)</div>\n </div>\n\n @if (TaxDuplicates.length === 0) {\n <div class=\"at-empty-state\">\n <i class=\"fa-solid fa-check-circle\"></i>\n <p>No duplicate tags detected</p>\n </div>\n }\n\n <div class=\"at-tax-dup-list\">\n @for (pair of TaxDuplicates; track $index) {\n <div class=\"at-tax-dup-card\" [class.at-tax-dup-high]=\"pair.SeverityClass === 'high'\" [class.at-tax-dup-moderate]=\"pair.SeverityClass === 'moderate'\">\n @if (pair.IsExactDuplicate) {\n <!-- Exact-name duplicates: show single tag name with count -->\n <div class=\"at-tax-dup-tag\">{{ pair.TagA }}</div>\n <div class=\"at-tax-dup-similarity\">\n <span class=\"at-tax-sim-percent high\">\n <i class=\"fa-solid fa-clone\"></i>&nbsp;{{ pair.ExactDuplicateCount }} identical records\n </span>\n </div>\n <div class=\"at-tax-dup-actions\">\n <button class=\"at-tax-dup-btn at-tax-dup-btn-primary\" (click)=\"MergeTags(pair.TagAID, pair.TagBID, pair.TagA, pair.TagB)\" [disabled]=\"IsMerging\">@if (IsMerging) { <i class=\"fa-solid fa-spinner fa-spin\"></i> Merging... } @else { Merge }</button>\n <button class=\"at-tax-dup-btn\" (click)=\"DismissDuplicate(pair)\">Dismiss</button>\n </div>\n } @else {\n <!-- Similar (non-exact) pairs: show both tags with similarity -->\n <div class=\"at-tax-dup-tag\">{{ pair.TagA }}</div>\n <div class=\"at-tax-dup-arrow\"><i class=\"fa-solid fa-arrows-left-right\"></i></div>\n <div class=\"at-tax-dup-similarity\">\n <div class=\"at-tax-sim-bar-bg\">\n <div class=\"at-tax-sim-bar-fill\" [class]=\"pair.SeverityClass\" [style.width.%]=\"pair.Similarity\"></div>\n </div>\n <span class=\"at-tax-sim-percent\" [class]=\"pair.SeverityClass\">{{ pair.Similarity }}%</span>\n </div>\n <div class=\"at-tax-dup-arrow\"><i class=\"fa-solid fa-arrows-left-right\"></i></div>\n <div class=\"at-tax-dup-tag\">{{ pair.TagB }}</div>\n <div class=\"at-tax-dup-actions\">\n <button class=\"at-tax-dup-btn at-tax-dup-btn-primary\" (click)=\"MergeTags(pair.TagAID, pair.TagBID, pair.TagA, pair.TagB)\" [disabled]=\"IsMerging\">@if (IsMerging) { <i class=\"fa-solid fa-spinner fa-spin\"></i> Merging... } @else { Merge }</button>\n <button class=\"at-tax-dup-btn\" (click)=\"MakeChildTag(pair.TagAID, pair.TagBID)\">Make Child</button>\n <button class=\"at-tax-dup-btn\" (click)=\"DismissDuplicate(pair)\">Dismiss</button>\n </div>\n }\n </div>\n }\n </div>\n }\n\n <!-- \u2550\u2550 SUB-TAB 3: ORPHANS \u2550\u2550 -->\n @if (TaxSubTab === 'orphans') {\n <div class=\"at-tax-orphan-toolbar\">\n <span class=\"at-tax-orphan-count\">{{ TaxOrphans.length }} orphaned tags</span>\n <span class=\"at-tax-orphan-desc\">&mdash; no parent, no children, low usage</span>\n <div class=\"at-tax-orphan-bulk\">\n <button class=\"at-tax-bulk-btn\" (click)=\"ToggleAllOrphans()\">\n @if (TaxAllOrphansSelected) { <i class=\"fa-solid fa-square-check\"></i> } @else { <i class=\"fa-regular fa-square\"></i> }\n Select All\n </button>\n <button class=\"at-tax-bulk-btn at-tax-bulk-danger\" (click)=\"BulkDeleteOrphans()\">\n <i class=\"fa-solid fa-trash\"></i> Bulk Delete\n </button>\n <button class=\"at-tax-bulk-btn at-tax-bulk-danger\" (click)=\"DeleteAllOrphans()\">\n <i class=\"fa-solid fa-trash-can\"></i> Delete All ({{ TaxOrphans.length }})\n </button>\n </div>\n </div>\n\n @if (TaxOrphans.length === 0) {\n <div class=\"at-empty-state\">\n <i class=\"fa-solid fa-check-circle\"></i>\n <p>No orphaned tags</p>\n </div>\n }\n\n <div class=\"at-tax-orphan-grid\">\n @for (orphan of TaxOrphans; track orphan.ID) {\n <div class=\"at-tax-orphan-card\">\n <div class=\"at-tax-orphan-header\">\n <span class=\"at-tax-orphan-name\">{{ orphan.Name }}</span>\n <input type=\"checkbox\" class=\"at-tax-orphan-checkbox\" [checked]=\"orphan.IsSelected\"\n (change)=\"ToggleOrphanSelection(orphan)\" (click)=\"$event.stopPropagation()\">\n </div>\n <div class=\"at-tax-orphan-stats\">\n <span>Usage: <strong>{{ orphan.UsageCount }}</strong></span>\n <span>Avg Weight: <strong>{{ orphan.AvgWeight.toFixed(2) }}</strong></span>\n </div>\n <div class=\"at-tax-orphan-dates\">\n <span>First: {{ orphan.FirstSeen }}</span>\n <span>Last: {{ orphan.LastSeen }}</span>\n </div>\n <div class=\"at-tax-orphan-actions\">\n <button class=\"at-tax-orphan-btn at-tax-orphan-delete\" (click)=\"DeleteOrphan(orphan)\">Delete</button>\n <button class=\"at-tax-orphan-btn\">Ignore</button>\n </div>\n </div>\n }\n </div>\n }\n\n <!-- \u2550\u2550 SUB-TAB 4: TREEMAP \u2550\u2550 -->\n @if (TaxSubTab === 'treemap') {\n <div class=\"at-tax-treemap-kpi-strip\">\n @for (kpi of TaxTreemapKPIs; track kpi.Label) {\n <div class=\"at-tax-treemap-kpi\">\n <div class=\"at-tax-treemap-kpi-value\">{{ kpi.Value }}</div>\n <div class=\"at-tax-treemap-kpi-label\">{{ kpi.Label }}</div>\n </div>\n }\n </div>\n\n @if (TaxTreemapCells.length === 0) {\n <div class=\"at-empty-state\">\n <i class=\"fa-solid fa-chart-tree-map\"></i>\n <p>No taxonomy data to visualize</p>\n </div>\n } @else {\n <div class=\"at-tax-treemap-container\">\n @for (cell of TaxTreemapCells; track $index) {\n <div class=\"at-tax-treemap-cell at-tax-treemap-cell-clickable\" [class]=\"cell.ColorClass\"\n [style.grid-row]=\"cell.RowSpan > 1 ? 'span ' + cell.RowSpan : ''\"\n (click)=\"OpenTreemapDrillIn(cell)\">\n <span class=\"at-tax-cell-name\">{{ cell.Name }}</span>\n <span class=\"at-tax-cell-count\">{{ cell.ItemCount }} items</span>\n </div>\n }\n </div>\n }\n\n <!-- Treemap Drill-In Panel -->\n @if (ShowTreemapDrillIn && TreemapDrillInNode) {\n <div class=\"at-tax-drillin-overlay\" (click)=\"CloseTreemapDrillIn()\">\n <div class=\"at-tax-drillin-panel\" (click)=\"$event.stopPropagation()\">\n <div class=\"at-tax-drillin-header\">\n <h3><i class=\"fa-solid fa-tag\"></i> {{ TreemapDrillInNode.Name }}</h3>\n <button class=\"at-schedule-dialog-close\" (click)=\"CloseTreemapDrillIn()\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n <div class=\"at-tax-drillin-body\">\n <div class=\"at-tax-stats-row\">\n <div class=\"at-tax-stat-item\">\n <div class=\"at-tax-stat-value\">{{ TreemapDrillInNode.ItemCount }}</div>\n <div class=\"at-tax-stat-label\">Items Tagged</div>\n </div>\n <div class=\"at-tax-stat-item\">\n <div class=\"at-tax-stat-value\">{{ TreemapDrillInNode.AvgWeight.toFixed(2) }}</div>\n <div class=\"at-tax-stat-label\">Avg Weight</div>\n </div>\n <div class=\"at-tax-stat-item\">\n <div class=\"at-tax-stat-value\">{{ TreemapDrillInNode.Children.length }}</div>\n <div class=\"at-tax-stat-label\">Children</div>\n </div>\n </div>\n\n @if (TreemapDrillInNode.Children.length > 0) {\n <div class=\"at-tax-detail-section\">\n <div class=\"at-tax-section-title\">Child Tags</div>\n <div class=\"at-tax-child-chips\">\n @for (child of TreemapDrillInNode.Children; track child.ID) {\n <span class=\"at-tax-child-chip\">{{ child.Name }} <span class=\"at-tax-chip-count\">{{ child.ItemCount }}</span></span>\n }\n </div>\n </div>\n }\n\n @if (TaxRecentItems.length > 0) {\n <div class=\"at-tax-detail-section\">\n <div class=\"at-tax-section-title\">Recently Tagged Items</div>\n <div class=\"at-tax-recent-list\">\n @for (item of TaxRecentItems; track $index) {\n <div class=\"at-tax-recent-item\">\n <div class=\"at-tax-recent-icon\"><i [class]=\"item.Icon\"></i></div>\n <div class=\"at-tax-recent-name\">{{ item.Name }}</div>\n <div class=\"at-tax-recent-weight\">{{ item.Weight.toFixed(2) }}</div>\n <div class=\"at-tax-recent-date\">{{ item.Date }}</div>\n </div>\n }\n </div>\n </div>\n }\n </div>\n <div class=\"at-tax-drillin-footer\">\n <button class=\"at-action-btn at-secondary-btn\" (click)=\"DrillInToTreeView(TreemapDrillInNode)\">\n <i class=\"fa-solid fa-sitemap\"></i> View in Tree\n </button>\n </div>\n </div>\n </div>\n }\n }\n\n <!-- \u2550\u2550 SUB-TAB 5: AUDIT LOG \u2550\u2550 -->\n @if (TaxSubTab === 'audit') {\n <div class=\"at-tax-audit-filters\">\n <span class=\"at-tax-audit-filter-label\">Filter</span>\n <div class=\"at-tax-audit-checkbox-group\">\n <label class=\"at-tax-audit-checkbox\">\n <input type=\"checkbox\" [checked]=\"TaxAuditFilterTypes.has('created')\" (change)=\"ToggleTaxAuditFilter('created')\"> Created\n </label>\n <label class=\"at-tax-audit-checkbox\">\n <input type=\"checkbox\" [checked]=\"TaxAuditFilterTypes.has('merged')\" (change)=\"ToggleTaxAuditFilter('merged')\"> Merged\n </label>\n <label class=\"at-tax-audit-checkbox\">\n <input type=\"checkbox\" [checked]=\"TaxAuditFilterTypes.has('moved')\" (change)=\"ToggleTaxAuditFilter('moved')\"> Moved\n </label>\n <label class=\"at-tax-audit-checkbox\">\n <input type=\"checkbox\" [checked]=\"TaxAuditFilterTypes.has('deleted')\" (change)=\"ToggleTaxAuditFilter('deleted')\"> Deleted\n </label>\n <label class=\"at-tax-audit-checkbox\">\n <input type=\"checkbox\" [checked]=\"TaxAuditFilterTypes.has('renamed')\" (change)=\"ToggleTaxAuditFilter('renamed')\"> Renamed\n </label>\n <label class=\"at-tax-audit-checkbox\">\n <input type=\"checkbox\" [checked]=\"TaxAuditFilterTypes.has('deprecated')\" (change)=\"ToggleTaxAuditFilter('deprecated')\"> Deprecated\n </label>\n <label class=\"at-tax-audit-checkbox\">\n <input type=\"checkbox\" [checked]=\"TaxAuditFilterTypes.has('split')\" (change)=\"ToggleTaxAuditFilter('split')\"> Split\n </label>\n <label class=\"at-tax-audit-checkbox\">\n <input type=\"checkbox\" [checked]=\"TaxAuditFilterTypes.has('reactivated')\" (change)=\"ToggleTaxAuditFilter('reactivated')\"> Reactivated\n </label>\n </div>\n </div>\n\n @if (GetFilteredAuditEvents().length === 0) {\n <div class=\"at-empty-state\">\n <i class=\"fa-solid fa-scroll\"></i>\n <p>No audit events match the current filters</p>\n </div>\n }\n\n <div class=\"at-tax-audit-timeline\">\n @for (event of GetFilteredAuditEvents(); track $index) {\n <div class=\"at-tax-audit-event\">\n <div class=\"at-tax-audit-event-icon\" [class]=\"event.Type\">\n <i [class]=\"GetTaxAuditIcon(event.Type)\"></i>\n </div>\n <div class=\"at-tax-audit-event-body\">\n <div class=\"at-tax-audit-event-desc\">\n {{ event.Description }} <span class=\"at-tax-tag-ref\">{{ event.TagRef }}</span>\n </div>\n <div class=\"at-tax-audit-event-meta\">\n <span>{{ event.User }}</span>\n <span>{{ event.Timestamp }}</span>\n </div>\n </div>\n </div>\n }\n </div>\n }\n </div>\n }\n\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n <!-- TAB 7: RUN HISTORY -->\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n @if (ActiveTab === 'history') {\n <div class=\"at-page-header\">\n <div>\n <div class=\"at-page-title\">Run History</div>\n <div class=\"at-page-subtitle\">Processing run log across all content sources</div>\n </div>\n <div class=\"at-page-actions\">\n <select class=\"at-filter-select\" [(ngModel)]=\"HistorySourceFilter\" (change)=\"FilterRunHistory()\">\n <option value=\"\">All Sources</option>\n @for (s of HistorySourceOptions; track s) {\n <option [value]=\"s\">{{ s }}</option>\n }\n </select>\n <select class=\"at-filter-select\" [(ngModel)]=\"HistoryStatusFilter\" (change)=\"FilterRunHistory()\">\n <option value=\"\">All Status</option>\n <option value=\"complete\">Complete</option>\n <option value=\"failed\">Failed</option>\n <option value=\"running\">Running</option>\n </select>\n </div>\n </div>\n <div class=\"at-page-body\">\n <div class=\"at-card\">\n <div class=\"at-card-body\" style=\"max-height: 600px; overflow-y: auto;\">\n <table class=\"at-run-table\">\n <thead>\n <tr>\n <th>Status</th>\n <th>Source</th>\n <th>Started</th>\n <th>Duration</th>\n <th>Items</th>\n <th>Tags</th>\n <th>Errors</th>\n </tr>\n </thead>\n <tbody>\n @for (row of FilteredRunRows; track row.ID) {\n <tr class=\"at-run-row-clickable\"\n [class.at-run-row-selected]=\"SelectedRunID === row.ID\"\n (click)=\"OpenRunDetail(row.ID)\">\n <td>\n <span class=\"at-run-status-badge\" [class]=\"row.StatusClass\">\n @if (row.StatusClass === 'running') {\n <i class=\"fa-solid fa-spinner fa-spin\" style=\"font-size: 0.55rem\"></i>\n }\n {{ row.Status }}\n </span>\n </td>\n <td class=\"at-run-source-name\">{{ row.SourceName }}</td>\n <td>{{ row.StartedDisplay }}</td>\n <td class=\"at-run-duration\">{{ row.Duration }}</td>\n <td>{{ row.Items }}</td>\n <td>{{ row.Tags }}</td>\n <td [class]=\"row.ErrorClass\">{{ row.Errors }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n </div>\n\n <!-- D3/D8: Run Detail Slide-In Panel -->\n @if (SelectedRunID) {\n <div class=\"at-card\" style=\"margin-top: 12px;\">\n <div class=\"at-card-header\">\n <span class=\"at-card-title\">\n <i class=\"fa-solid fa-magnifying-glass-chart\"></i>\n Run Detail: {{ SelectedRunID.slice(0, 14) }}...\n </span>\n <button class=\"at-action-btn at-secondary-btn\" style=\"font-size: 11px; padding: 3px 8px;\" (click)=\"CloseRunDetail()\">\n <i class=\"fa-solid fa-times\"></i> Close\n </button>\n </div>\n <div class=\"at-card-body\">\n @if (IsLoadingRunDetail) {\n <mj-loading text=\"Loading run details...\" size=\"small\"></mj-loading>\n } @else if (RunDetailRows.length > 0) {\n <table class=\"at-run-table\">\n <thead>\n <tr>\n <th>Source</th>\n <th>Source Type</th>\n <th>Status</th>\n <th>Items</th>\n <th>Tagged</th>\n <th>Vectorized</th>\n <th>Errors</th>\n <th>Tokens</th>\n <th>Cost</th>\n <th>Duration</th>\n </tr>\n </thead>\n <tbody>\n @for (detail of RunDetailRows; track detail.SourceName) {\n <tr>\n <td class=\"at-run-source-name\">{{ detail.SourceName }}</td>\n <td>{{ detail.SourceType }}</td>\n <td>\n <span class=\"at-run-status-badge\" [class]=\"detail.StatusClass\">{{ detail.Status }}</span>\n </td>\n <td>{{ detail.ItemsProcessed }}</td>\n <td>{{ detail.ItemsTagged }}</td>\n <td>{{ detail.ItemsVectorized }}</td>\n <td [class.run-error-text]=\"detail.ErrorCount > 0\">{{ detail.ErrorCount }}</td>\n <td>{{ FormatTokenCount(detail.TotalTokens) }}</td>\n <td>{{ detail.TotalCost > 0 ? '$' + detail.TotalCost.toFixed(4) : '$0.00' }}</td>\n <td class=\"at-run-duration\">{{ detail.Duration }}</td>\n </tr>\n }\n </tbody>\n </table>\n } @else {\n <div class=\"at-empty-state\">\n <i class=\"fa-solid fa-info-circle\"></i>\n <p>No per-source detail records found for this run.</p>\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\n }\n </div>\n\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550 SLIDE-IN FORM OVERLAY \u2550\u2550\u2550\u2550\u2550\u2550 -->\n @if (FormMode !== 'none') {\n <div class=\"at-slide-overlay\" (click)=\"CloseForm()\"></div>\n <div class=\"at-slide-panel\">\n <div class=\"at-slide-header\">\n <h3>\n @if (FormMode === 'add-source') { Add Content Source }\n @else if (FormMode === 'edit-source') { Edit Content Source }\n @else if (FormMode === 'add-type') { Add Content Type }\n @else if (FormMode === 'edit-type') { Edit Content Type }\n </h3>\n <button class=\"at-slide-close\" (click)=\"CloseForm()\"><i class=\"fa-solid fa-times\"></i></button>\n </div>\n <div class=\"at-slide-body\">\n\n <!-- Source form -->\n @if (FormMode === 'add-source' || FormMode === 'edit-source') {\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">Name</label>\n <input type=\"text\" class=\"at-form-input\" [(ngModel)]=\"FormSourceName\" placeholder=\"Source name\">\n </div>\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">Source Type</label>\n <select class=\"at-form-select\" [(ngModel)]=\"FormSourceTypeID\">\n <option value=\"\">Select source type...</option>\n @for (opt of SourceTypeOptions; track opt.ID) {\n <option [value]=\"opt.ID\">{{ opt.Name }}</option>\n }\n </select>\n </div>\n <!-- Content Type + File Type: hidden for Entity source type -->\n @if (SelectedSourceTypeRequiresContentType) {\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">Content Type</label>\n <select class=\"at-form-select\" [(ngModel)]=\"FormContentTypeID\">\n <option value=\"\">Select content type...</option>\n @for (opt of ContentTypeOptions; track opt.ID) {\n <option [value]=\"opt.ID\">{{ opt.Name }}</option>\n }\n </select>\n </div>\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">File Type</label>\n <select class=\"at-form-select\" [(ngModel)]=\"FormFileTypeID\">\n <option value=\"\">Select file type...</option>\n @for (opt of FileTypeOptions; track opt.ID) {\n <option [value]=\"opt.ID\">{{ opt.Name }}</option>\n }\n </select>\n </div>\n }\n\n <!-- Dynamic source-type-specific fields from ConfigurationObject.RequiredFields -->\n @for (field of SelectedSourceTypeFields; track field.Key) {\n @if (!field.DependsOnField || FormSourceSpecificConfig[field.DependsOnField]) {\n @if (!field.ShowOnlyIfMultiple || GetDependentOptions(field).length > 1) {\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">{{ field.Label }} @if (field.Required) { <span class=\"at-required\">*</span> }</label>\n @switch (field.Type) {\n @case ('url') {\n <input type=\"url\" class=\"at-form-input\" [(ngModel)]=\"FormSourceSpecificConfig[field.Key]\"\n [placeholder]=\"field.Description || 'https://...'\">\n }\n @case ('path') {\n <input type=\"text\" class=\"at-form-input\" [(ngModel)]=\"FormSourceSpecificConfig[field.Key]\"\n [placeholder]=\"field.Description || '/path/to/...'\">\n }\n @case ('text') {\n <input type=\"text\" class=\"at-form-input\" [(ngModel)]=\"FormSourceSpecificConfig[field.Key]\"\n [placeholder]=\"field.Description || ''\" [value]=\"field.DefaultValue || ''\">\n }\n @case ('entity-picker') {\n <select class=\"at-form-select\" [(ngModel)]=\"FormSourceSpecificConfig[field.Key]\"\n (ngModelChange)=\"OnSourceFieldChanged(field.Key)\">\n <option value=\"\">Select entity...</option>\n @for (opt of EntitiesWithDocuments; track opt.ID) {\n <option [value]=\"opt.ID\">{{ opt.Name }}</option>\n }\n </select>\n }\n @case ('entity-doc-picker') {\n <select class=\"at-form-select\" [(ngModel)]=\"FormSourceSpecificConfig[field.Key]\">\n @for (opt of GetDependentOptions(field); track opt.ID) {\n <option [value]=\"opt.ID\">{{ opt.Name }}</option>\n }\n </select>\n }\n @case ('storage-provider-picker') {\n <select class=\"at-form-select\" [(ngModel)]=\"FormSourceSpecificConfig[field.Key]\">\n <option value=\"\">Select provider...</option>\n @for (opt of StorageProviderOptions; track opt) {\n <option [value]=\"opt\">{{ opt }}</option>\n }\n </select>\n }\n @case ('dropdown') {\n <select class=\"at-form-select\" [(ngModel)]=\"FormSourceSpecificConfig[field.Key]\">\n <option value=\"\">Select...</option>\n @for (opt of field.Options || []; track opt.Value) {\n <option [value]=\"opt.Value\">{{ opt.Label }}</option>\n }\n </select>\n }\n }\n @if (field.Description) {\n <span class=\"at-form-hint\">{{ field.Description }}</span>\n }\n </div>\n }\n }\n }\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">Embedding Model Override</label>\n <mj-tree-dropdown\n [BranchConfig]=\"EmbeddingVendorBranch\"\n [LeafConfig]=\"EmbeddingModelsLeaf\"\n SelectionMode=\"single\"\n SelectableTypes=\"leaf\"\n Placeholder=\"Use system default\"\n [Clearable]=\"true\"\n [Value]=\"ToCompositeKey(FormSourceEmbeddingModelID)\"\n (ValueChange)=\"FormSourceEmbeddingModelID = FromCompositeKey($event)\">\n </mj-tree-dropdown>\n <span class=\"at-form-hint\">Overrides Content Type default</span>\n </div>\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">Vector Index Override</label>\n <select class=\"at-form-select\" [(ngModel)]=\"FormSourceVectorIndexID\">\n <option value=\"\">Use system default</option>\n @for (opt of VectorIndexOptions; track opt.ID) {\n <option [value]=\"opt.ID\">{{ opt.Name }}</option>\n }\n </select>\n <span class=\"at-form-hint\">Overrides Content Type default</span>\n </div>\n <div class=\"at-form-actions\">\n <button class=\"at-action-btn at-primary-btn\" (click)=\"SaveSource()\" [disabled]=\"FormSaving\">\n @if (FormSaving) { <i class=\"fa-solid fa-spinner fa-spin\"></i> Saving... }\n @else { <i class=\"fa-solid fa-check\"></i> Save }\n </button>\n <button class=\"at-action-btn at-secondary-btn\" (click)=\"CloseForm()\">Cancel</button>\n </div>\n }\n\n <!-- Content Type form -->\n @if (FormMode === 'add-type' || FormMode === 'edit-type') {\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">Name</label>\n <input type=\"text\" class=\"at-form-input\" [(ngModel)]=\"FormTypeName\" placeholder=\"Content type name\">\n </div>\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">Description</label>\n <textarea class=\"at-form-textarea\" [(ngModel)]=\"FormTypeDescription\" rows=\"3\" placeholder=\"Description...\"></textarea>\n </div>\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">AI Model (for tagging)</label>\n <mj-tree-dropdown\n [BranchConfig]=\"AIModelVendorBranch\"\n [LeafConfig]=\"AllModelsLeaf\"\n SelectionMode=\"single\"\n SelectableTypes=\"leaf\"\n Placeholder=\"Select AI model...\"\n [Clearable]=\"true\"\n [Value]=\"ToCompositeKey(FormTypeAIModelID)\"\n (ValueChange)=\"FormTypeAIModelID = FromCompositeKey($event)\">\n </mj-tree-dropdown>\n </div>\n <div class=\"at-form-row\">\n <div class=\"at-form-group\" style=\"flex: 1;\">\n <label class=\"at-form-label\">Min Tags</label>\n <input type=\"number\" class=\"at-form-input\" [(ngModel)]=\"FormTypeMinTags\" min=\"0\">\n </div>\n <div class=\"at-form-group\" style=\"flex: 1;\">\n <label class=\"at-form-label\">Max Tags</label>\n <input type=\"number\" class=\"at-form-input\" [(ngModel)]=\"FormTypeMaxTags\" min=\"1\">\n </div>\n </div>\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">Embedding Model</label>\n <mj-tree-dropdown\n [BranchConfig]=\"EmbeddingVendorBranch\"\n [LeafConfig]=\"EmbeddingModelsLeaf\"\n SelectionMode=\"single\"\n SelectableTypes=\"leaf\"\n Placeholder=\"Use system default\"\n [Clearable]=\"true\"\n [Value]=\"ToCompositeKey(FormTypeEmbeddingModelID)\"\n (ValueChange)=\"FormTypeEmbeddingModelID = FromCompositeKey($event)\">\n </mj-tree-dropdown>\n </div>\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">Vector Index</label>\n <select class=\"at-form-select\" [(ngModel)]=\"FormTypeVectorIndexID\">\n <option value=\"\">Use system default</option>\n @for (opt of VectorIndexOptions; track opt.ID) {\n <option [value]=\"opt.ID\">{{ opt.Name }}</option>\n }\n </select>\n </div>\n <div class=\"at-form-actions\">\n <button class=\"at-action-btn at-primary-btn\" (click)=\"SaveContentType()\" [disabled]=\"FormSaving\">\n @if (FormSaving) { <i class=\"fa-solid fa-spinner fa-spin\"></i> Saving... }\n @else { <i class=\"fa-solid fa-check\"></i> Save }\n </button>\n <button class=\"at-action-btn at-secondary-btn\" (click)=\"CloseForm()\">Cancel</button>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550 ITEM DETAIL SLIDE-IN \u2550\u2550\u2550\u2550\u2550\u2550 -->\n @if (ShowItemDetail && SelectedFeedItem) {\n <div class=\"at-slide-overlay\" (click)=\"CloseItemDetail()\"></div>\n <div class=\"at-slide-panel at-detail-panel\">\n <div class=\"at-slide-header\">\n <h3><i class=\"fa-solid fa-file-lines\"></i> Content Item</h3>\n <button class=\"at-slide-close\" (click)=\"CloseItemDetail()\"><i class=\"fa-solid fa-times\"></i></button>\n </div>\n <div class=\"at-slide-body\">\n <!-- Header -->\n <div class=\"at-detail-item-header\">\n <h4 class=\"at-detail-item-name\">{{ SelectedFeedItem.Name }}</h4>\n <div class=\"at-detail-badges\">\n <span class=\"at-detail-badge at-detail-badge-source\">{{ SelectedFeedItem.SourceName }}</span>\n @if (SelectedFeedItem.RequiresContentType) {\n <span class=\"at-detail-badge at-detail-badge-type\">{{ SelectedFeedItem.ContentTypeName }}</span>\n @if (SelectedFeedItem.FileTypeName) {\n <span class=\"at-detail-badge at-detail-badge-file\"><i class=\"fa-solid fa-file\"></i> {{ SelectedFeedItem.FileTypeName }}</span>\n }\n }\n </div>\n </div>\n\n <!-- URL -->\n @if (SelectedFeedItem.URL) {\n <div class=\"at-detail-section\">\n <div class=\"at-detail-section-label\">URL</div>\n <a [href]=\"SelectedFeedItem.URL\" target=\"_blank\" class=\"at-detail-link\">\n {{ SelectedFeedItem.URL }}\n <i class=\"fa-solid fa-external-link-alt\" style=\"font-size: 0.65rem; margin-left: 4px;\"></i>\n </a>\n </div>\n }\n\n <!-- Text Preview -->\n @if (SelectedFeedItem.TextContent) {\n <div class=\"at-detail-section\">\n <div class=\"at-detail-section-label\">Content Preview</div>\n <div class=\"at-detail-text-preview\">{{ SelectedFeedItem.TextContent }}</div>\n </div>\n }\n\n <!-- Tags (weighted) -->\n @if (SelectedFeedItem.Tags.length > 0) {\n <div class=\"at-detail-section\">\n <div class=\"at-detail-section-label\">Tags ({{ SelectedFeedItem.Tags.length }})</div>\n <div class=\"at-detail-tags\">\n @for (wt of SelectedFeedItem.Tags; track wt.Tag) {\n <span class=\"at-tag-pill at-tag-weighted\" [style.font-size]=\"TagFontSize(wt.Weight)\">\n {{ wt.Tag }}\n <span class=\"at-tag-weight\">{{ FormatWeight(wt.Weight) }}</span>\n </span>\n }\n </div>\n </div>\n }\n\n <!-- Metadata -->\n <div class=\"at-detail-section\">\n <div class=\"at-detail-section-label\">Metadata</div>\n <div class=\"at-detail-meta-grid\">\n @if (SelectedFeedItem.Checksum) {\n <div class=\"at-detail-meta-row\">\n <span class=\"at-detail-meta-key\">Checksum</span>\n <span class=\"at-detail-meta-value at-detail-meta-mono\">{{ SelectedFeedItem.Checksum }}</span>\n </div>\n }\n <div class=\"at-detail-meta-row\">\n <span class=\"at-detail-meta-key\">Created</span>\n <span class=\"at-detail-meta-value\">{{ SelectedFeedItem.CreatedAt }}</span>\n </div>\n <div class=\"at-detail-meta-row\">\n <span class=\"at-detail-meta-key\">Updated</span>\n <span class=\"at-detail-meta-value\">{{ SelectedFeedItem.UpdatedAt }}</span>\n </div>\n </div>\n </div>\n\n <!-- Actions -->\n <div class=\"at-detail-actions\">\n <button class=\"at-action-btn at-primary-btn\" (click)=\"OpenRecordFromItem(SelectedFeedItem)\">\n <i class=\"fa-solid fa-external-link-alt\"></i> Open Record\n </button>\n <button class=\"at-action-btn at-secondary-btn\" disabled>\n <i class=\"fa-solid fa-magnifying-glass\"></i> See Similar Items\n </button>\n </div>\n </div>\n </div>\n }\n\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550 SOURCE DETAIL SLIDE-IN \u2550\u2550\u2550\u2550\u2550\u2550 -->\n @if (ShowSourceDetail) {\n <div class=\"at-slide-overlay\" (click)=\"CloseSourceDetail()\"></div>\n <div class=\"at-slide-panel at-detail-panel\">\n <div class=\"at-slide-header\">\n <h3><i class=\"fa-solid fa-database\"></i> Source Detail</h3>\n <button class=\"at-slide-close\" (click)=\"CloseSourceDetail()\"><i class=\"fa-solid fa-times\"></i></button>\n </div>\n <div class=\"at-slide-body\">\n @if (SourceDetailLoading) {\n <div class=\"at-loading-overlay\">\n <mj-loading text=\"Loading source details...\"></mj-loading>\n </div>\n }\n @if (!SourceDetailLoading && SelectedSource) {\n <!-- Source Header -->\n <div class=\"at-detail-source-header\">\n <div class=\"at-source-card-icon\"><i [class]=\"SelectedSource.Icon\"></i></div>\n <div>\n <h4 class=\"at-detail-item-name\">{{ SelectedSource.Name }}</h4>\n <div class=\"at-detail-badges\">\n <span class=\"at-detail-badge at-detail-badge-type\">{{ SelectedSource.SourceTypeName }}</span>\n <span class=\"at-detail-badge\" [class]=\"'at-detail-badge-status-' + SelectedSource.StatusClass\">\n {{ SelectedSource.StatusLabel }}\n </span>\n </div>\n </div>\n </div>\n\n <!-- Configuration -->\n <div class=\"at-detail-section\">\n <div class=\"at-detail-section-label\">Configuration</div>\n <div class=\"at-detail-meta-grid\">\n @if (SelectedSource.URL) {\n <div class=\"at-detail-meta-row\">\n <span class=\"at-detail-meta-key\">URL</span>\n <a [href]=\"SelectedSource.URL\" target=\"_blank\" class=\"at-detail-link at-detail-meta-value\">{{ SelectedSource.URL }}</a>\n </div>\n }\n @if (SelectedSource.RequiresFileType) {\n <div class=\"at-detail-meta-row\">\n <span class=\"at-detail-meta-key\">Content Type</span>\n <span class=\"at-detail-meta-value\">{{ SelectedSource.ContentTypeName }}</span>\n </div>\n <div class=\"at-detail-meta-row\">\n <span class=\"at-detail-meta-key\">File Type</span>\n <span class=\"at-detail-meta-value\">{{ SelectedSource.FileTypeName }}</span>\n </div>\n }\n <div class=\"at-detail-meta-row\">\n <span class=\"at-detail-meta-key\">Embedding Model</span>\n <span class=\"at-detail-meta-value\">{{ SelectedSource.EmbeddingModelName }}</span>\n </div>\n <div class=\"at-detail-meta-row\">\n <span class=\"at-detail-meta-key\">Vector Index</span>\n <span class=\"at-detail-meta-value\">{{ SelectedSource.VectorIndexName }}</span>\n </div>\n </div>\n </div>\n\n <!-- Stats -->\n <div class=\"at-detail-section\">\n <div class=\"at-detail-section-label\">Statistics</div>\n <div class=\"at-detail-stats-strip\">\n <div class=\"at-detail-stat\">\n <div class=\"at-detail-stat-value\">{{ formatNumber(SelectedSource.ItemCount) }}</div>\n <div class=\"at-detail-stat-label\">Items</div>\n </div>\n <div class=\"at-detail-stat\">\n <div class=\"at-detail-stat-value\">{{ formatNumber(SelectedSource.TagCount) }}</div>\n <div class=\"at-detail-stat-label\">Tags</div>\n </div>\n <div class=\"at-detail-stat\">\n <div class=\"at-detail-stat-value\">{{ SelectedSource.AvgTags }}</div>\n <div class=\"at-detail-stat-label\">Avg Tags</div>\n </div>\n <div class=\"at-detail-stat\">\n <div class=\"at-detail-stat-value\">{{ SelectedSource.LastRunAgo }}</div>\n <div class=\"at-detail-stat-label\">Last Run</div>\n </div>\n <div class=\"at-detail-stat\">\n <div class=\"at-detail-stat-value\" [class.at-kpi-error-value]=\"SelectedSource.ErrorCount > 0\">{{ SelectedSource.ErrorCount }}</div>\n <div class=\"at-detail-stat-label\">Errors</div>\n </div>\n </div>\n </div>\n\n <!-- Content Library (D4 status badges, D7 pagination) -->\n <div class=\"at-detail-section\">\n <div class=\"at-detail-section-header-row\">\n <div class=\"at-detail-section-label\">Content Library ({{ FilteredSourceDetailTotal }} of {{ SelectedSource.ItemCount | number }})</div>\n <div class=\"at-detail-section-controls\">\n <select class=\"at-detail-filter-select\" [(ngModel)]=\"SourceDetailStatusFilter\" (ngModelChange)=\"OnSourceDetailStatusFilterChange()\">\n @for (opt of SourceDetailStatusOptions; track opt) {\n <option [value]=\"opt\">{{ opt }}</option>\n }\n </select>\n <button class=\"at-action-btn at-retry-btn\" (click)=\"RetryFailedItems()\" title=\"Re-queue failed items for processing\">\n <i class=\"fa-solid fa-rotate-right\"></i> Retry Failed\n </button>\n </div>\n </div>\n <div class=\"at-detail-content-list\">\n @if (FilteredSourceDetailItems.length === 0) {\n <div class=\"at-empty-state\" style=\"padding: 16px;\">\n <p>{{ SourceDetailStatusFilter === 'All' ? 'No content items yet.' : 'No items match this filter.' }}</p>\n </div>\n }\n @for (ci of FilteredSourceDetailItems; track ci.ID) {\n <div class=\"at-detail-content-item\" (click)=\"OpenContentItemDetail(ci)\">\n <div class=\"at-feed-status-dot\" [class]=\"ci.StatusDot\"></div>\n <span class=\"at-detail-content-item-name\">{{ ci.Name }}</span>\n <span class=\"at-status-badge\" [class]=\"GetStatusBadgeClass(ci.EmbeddingStatus)\">E:{{ ci.EmbeddingStatus }}</span>\n <span class=\"at-status-badge\" [class]=\"GetStatusBadgeClass(ci.TaggingStatus)\">T:{{ ci.TaggingStatus }}</span>\n <span class=\"at-detail-content-item-tags\">{{ ci.TagCount }} tags</span>\n <span class=\"at-detail-content-item-time\">{{ ci.UpdatedAt }}</span>\n </div>\n }\n </div>\n <!-- Pagination -->\n @if (SourceDetailTotalPages > 1) {\n <div class=\"at-detail-pagination\">\n <button class=\"at-page-btn\" [disabled]=\"SourceDetailPage === 0\" (click)=\"SourceDetailPrevPage()\">\n <i class=\"fa-solid fa-chevron-left\"></i> Prev\n </button>\n <span class=\"at-page-info\">Page {{ SourceDetailPage + 1 }} of {{ SourceDetailTotalPages }}</span>\n <button class=\"at-page-btn\" [disabled]=\"SourceDetailPage >= SourceDetailTotalPages - 1\" (click)=\"SourceDetailNextPage()\">\n Next <i class=\"fa-solid fa-chevron-right\"></i>\n </button>\n </div>\n }\n </div>\n\n <!-- Run History -->\n @if (SelectedSource.RunHistory.length > 0) {\n <div class=\"at-detail-section\">\n <div class=\"at-detail-section-label\">Recent Runs</div>\n <div class=\"at-detail-run-history\">\n @for (run of SelectedSource.RunHistory; track run.ID) {\n <div class=\"at-detail-run-row\">\n <span class=\"at-run-status-badge\" [class]=\"run.StatusClass\">{{ run.Status }}</span>\n <span class=\"at-detail-run-time\">{{ run.StartedDisplay }}</span>\n <span class=\"at-detail-run-duration\">{{ run.Duration }}</span>\n <span class=\"at-detail-run-items\">{{ run.Items }} items</span>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- Actions -->\n <div class=\"at-detail-actions\">\n <button class=\"at-action-btn at-primary-btn\" (click)=\"OpenEditSourceFromDetail()\">\n <i class=\"fa-solid fa-pen\"></i> Edit\n </button>\n <button class=\"at-action-btn at-secondary-btn\" (click)=\"RunSourceFromDetail()\">\n <i class=\"fa-solid fa-play\"></i> Run Now\n </button>\n <button class=\"at-action-btn at-secondary-btn at-source-delete-btn\" (click)=\"DeleteSourceFromDetail()\">\n <i class=\"fa-solid fa-trash\"></i> Delete\n </button>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550 SCHEDULE DIALOG \u2550\u2550\u2550\u2550\u2550\u2550 -->\n @if (ShowScheduleDialog && SchedulingSourceCard) {\n <div class=\"at-schedule-overlay\" (click)=\"CloseScheduleDialog()\">\n <div class=\"at-schedule-dialog\" (click)=\"$event.stopPropagation()\">\n <div class=\"at-schedule-dialog-header\">\n <h3><i class=\"fa-regular fa-clock\"></i> Schedule Pipeline</h3>\n <button class=\"at-schedule-dialog-close\" (click)=\"CloseScheduleDialog()\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n <div class=\"at-schedule-dialog-body\">\n <div class=\"at-schedule-field\">\n <label>Source</label>\n <div class=\"at-schedule-source-name\">\n <i [class]=\"SchedulingSourceCard.Icon\"></i>\n {{ SchedulingSourceCard.Name }}\n </div>\n </div>\n <div class=\"at-schedule-field\">\n <label>Action</label>\n <div class=\"at-schedule-action-name\">Autotag and Vectorize Content</div>\n </div>\n <div class=\"at-schedule-field\">\n <label for=\"schedule-cron\">Cron Expression</label>\n <input id=\"schedule-cron\"\n type=\"text\"\n class=\"mj-input at-schedule-cron-input\"\n [(ngModel)]=\"ScheduleCron\"\n placeholder=\"0 2 * * *\" />\n <div class=\"at-schedule-cron-preview\">\n <i class=\"fa-solid fa-info-circle\"></i>\n {{ GetCronPreview(ScheduleCron) }}\n </div>\n </div>\n <div class=\"at-schedule-field at-schedule-toggle-row\">\n <label for=\"schedule-enabled\">Enabled</label>\n <input id=\"schedule-enabled\"\n type=\"checkbox\"\n class=\"mj-checkbox\"\n [(ngModel)]=\"ScheduleEnabled\" />\n </div>\n </div>\n <div class=\"at-schedule-dialog-footer\">\n <button class=\"at-action-btn at-primary-btn\" (click)=\"SaveSchedule()\" [disabled]=\"ScheduleSaving\">\n @if (ScheduleSaving) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Saving...\n } @else {\n <i class=\"fa-solid fa-check\"></i> Create Schedule\n }\n </button>\n <button class=\"at-action-btn at-secondary-btn\" (click)=\"CloseScheduleDialog()\">Cancel</button>\n </div>\n </div>\n </div>\n }\n\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550 CONFIRMATION DIALOG \u2550\u2550\u2550\u2550\u2550\u2550 -->\n @if (ShowConfirmDialog) {\n <div class=\"at-schedule-overlay\" (click)=\"ConfirmDialogCancel()\">\n <div class=\"at-schedule-dialog\" (click)=\"$event.stopPropagation()\">\n <div class=\"at-schedule-dialog-header\">\n <h3><i class=\"fa-solid fa-triangle-exclamation\"></i> {{ ConfirmDialogTitle }}</h3>\n <button class=\"at-schedule-dialog-close\" (click)=\"ConfirmDialogCancel()\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n <div class=\"at-schedule-dialog-body\">\n <p class=\"at-confirm-message\">{{ ConfirmDialogMessage }}</p>\n </div>\n <div class=\"at-schedule-dialog-footer\">\n <button class=\"at-action-btn at-danger-btn\" (click)=\"ConfirmDialogAccept()\">\n <i class=\"fa-solid fa-check\"></i> Confirm\n </button>\n <button class=\"at-action-btn at-secondary-btn\" (click)=\"ConfirmDialogCancel()\">Cancel</button>\n </div>\n </div>\n </div>\n }\n\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550 SPLIT DIALOG \u2550\u2550\u2550\u2550\u2550\u2550 -->\n @if (ShowSplitDialog) {\n <div class=\"at-schedule-overlay\" (click)=\"CloseSplitDialog()\">\n <div class=\"at-schedule-dialog\" (click)=\"$event.stopPropagation()\">\n <div class=\"at-schedule-dialog-header\">\n <h3><i class=\"fa-solid fa-code-branch\"></i> Split Tag</h3>\n <button class=\"at-schedule-dialog-close\" (click)=\"CloseSplitDialog()\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n <div class=\"at-schedule-dialog-body\">\n <div class=\"at-schedule-field\">\n <label>New tag names (comma-separated)</label>\n <input type=\"text\" class=\"mj-input\" style=\"width: 100%;\"\n [(ngModel)]=\"SplitChildNames\"\n placeholder=\"Tag A, Tag B, Tag C\" />\n </div>\n <p class=\"at-confirm-message\">New tags will be created as siblings of the original tag under the same parent.</p>\n </div>\n <div class=\"at-schedule-dialog-footer\">\n <button class=\"at-action-btn at-primary-btn\" (click)=\"ExecuteSplit()\" [disabled]=\"!SplitChildNames.trim()\">\n <i class=\"fa-solid fa-code-branch\"></i> Create Tags\n </button>\n <button class=\"at-action-btn at-secondary-btn\" (click)=\"CloseSplitDialog()\">Cancel</button>\n </div>\n </div>\n </div>\n }\n\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550 MOVE DIALOG \u2550\u2550\u2550\u2550\u2550\u2550 -->\n @if (ShowCreateTagDialog) {\n <div class=\"at-schedule-overlay\" (click)=\"CloseCreateTagDialog()\">\n <div class=\"at-schedule-dialog\" (click)=\"$event.stopPropagation()\">\n <div class=\"at-schedule-dialog-header\">\n <h3><i class=\"fa-solid fa-plus\"></i> Create Tag</h3>\n <button class=\"at-schedule-dialog-close\" (click)=\"CloseCreateTagDialog()\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n <div class=\"at-schedule-dialog-body\">\n <div class=\"at-tax-create-context\">{{ CreateTagParentLabel }}</div>\n <div class=\"at-schedule-field\">\n <label>Name</label>\n <input type=\"text\" class=\"mj-input\" style=\"width: 100%;\" [(ngModel)]=\"CreateTagName\"\n placeholder=\"Tag name\" (keydown.enter)=\"SaveNewTag()\">\n </div>\n <div class=\"at-schedule-field\">\n <label>Description (optional)</label>\n <textarea class=\"mj-textarea\" rows=\"3\" style=\"width: 100%;\" [(ngModel)]=\"CreateTagDescription\"\n placeholder=\"Brief description of this tag\"></textarea>\n </div>\n </div>\n <div class=\"at-schedule-dialog-footer\">\n <button class=\"at-action-btn at-primary-btn\" (click)=\"SaveNewTag()\" [disabled]=\"!CreateTagName.trim()\">\n <i class=\"fa-solid fa-check\"></i> Create\n </button>\n <button class=\"at-action-btn at-secondary-btn\" (click)=\"CloseCreateTagDialog()\">Cancel</button>\n </div>\n </div>\n </div>\n }\n\n @if (ShowMoveDialog) {\n <div class=\"at-schedule-overlay\" (click)=\"CloseMoveDialog()\">\n <div class=\"at-schedule-dialog\" (click)=\"$event.stopPropagation()\">\n <div class=\"at-schedule-dialog-header\">\n <h3><i class=\"fa-solid fa-arrows-up-down\"></i> Move Tag</h3>\n <button class=\"at-schedule-dialog-close\" (click)=\"CloseMoveDialog()\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n <div class=\"at-schedule-dialog-body\">\n <div class=\"at-schedule-field\">\n <label>New parent tag</label>\n <select class=\"mj-input\" style=\"width: 100%;\" [(ngModel)]=\"MoveNewParentID\">\n <option [ngValue]=\"null\">(Root level &mdash; no parent)</option>\n @for (opt of GetMoveTargetOptions(); track opt.ID) {\n <option [ngValue]=\"opt.ID\">{{ '\\u00A0\\u00A0'.repeat(opt.Depth) }}{{ opt.Name }}</option>\n }\n </select>\n </div>\n </div>\n <div class=\"at-schedule-dialog-footer\">\n <button class=\"at-action-btn at-primary-btn\" (click)=\"ExecuteMove()\">\n <i class=\"fa-solid fa-check\"></i> Move\n </button>\n <button class=\"at-action-btn at-secondary-btn\" (click)=\"CloseMoveDialog()\">Cancel</button>\n </div>\n </div>\n </div>\n }\n\n @if (ShowMergeIntoDialog) {\n <div class=\"at-schedule-overlay\" (click)=\"CloseMergeIntoDialog()\">\n <div class=\"at-schedule-dialog\" (click)=\"$event.stopPropagation()\">\n <div class=\"at-schedule-dialog-header\">\n <h3><i class=\"fa-solid fa-compress\"></i> Merge \"{{ MergeSourceTag?.Name }}\" Into...</h3>\n <button class=\"at-schedule-dialog-close\" (click)=\"CloseMergeIntoDialog()\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n <div class=\"at-schedule-dialog-body\">\n <p style=\"font-size: 0.85rem; color: var(--mj-text-secondary); margin: 0 0 12px;\">\n All tagged items will be moved to the target tag, then \"{{ MergeSourceTag?.Name }}\" will be deleted.\n </p>\n <div class=\"at-schedule-field\">\n <label>Merge into</label>\n <mj-combobox\n [Data]=\"MergeTargetData\"\n TextField=\"Label\"\n ValueField=\"ID\"\n [Filterable]=\"true\"\n [ValuePrimitive]=\"true\"\n Placeholder=\"Search and select a tag...\"\n (ValueChange)=\"OnMergeTargetSelected($event)\">\n </mj-combobox>\n </div>\n </div>\n <div class=\"at-schedule-dialog-footer\">\n <button class=\"at-action-btn at-primary-btn\" (click)=\"ExecuteMergeInto()\" [disabled]=\"!MergeTargetID || IsMerging\">\n @if (IsMerging) { <i class=\"fa-solid fa-spinner fa-spin\"></i> Merging... } @else { <i class=\"fa-solid fa-compress\"></i> Merge }\n </button>\n <button class=\"at-action-btn at-secondary-btn\" (click)=\"CloseMergeIntoDialog()\">Cancel</button>\n </div>\n </div>\n </div>\n }\n\n <!-- No Content Types Warning Dialog (z-index above slide-in panel) -->\n @if (ShowNoContentTypeWarning) {\n <div class=\"at-schedule-dialog-overlay\" style=\"z-index: 10001;\" (click)=\"ShowNoContentTypeWarning = false\">\n <div class=\"at-schedule-dialog\" style=\"max-width: 440px; z-index: 10002;\" (click)=\"$event.stopPropagation()\">\n <div class=\"at-schedule-dialog-header\">\n <span><i class=\"fa-solid fa-triangle-exclamation\" style=\"color: var(--mj-status-warning); margin-right: 8px;\"></i> Content Type Required</span>\n <button class=\"at-close-btn\" (click)=\"ShowNoContentTypeWarning = false\"><i class=\"fa-solid fa-xmark\"></i></button>\n </div>\n <div class=\"at-schedule-dialog-body\" style=\"text-align: center; padding: 24px;\">\n <p style=\"color: var(--mj-text-secondary); margin-bottom: 16px;\">\n No content types have been configured yet. At least one content type is required before you can create a content source.\n </p>\n <p style=\"color: var(--mj-text-muted); font-size: 13px;\">\n Go to the <strong>Content Types</strong> tab to create one.\n </p>\n </div>\n <div class=\"at-schedule-dialog-footer\">\n <button class=\"at-action-btn at-primary-btn\" (mousedown)=\"ShowNoContentTypeWarning = false; CloseForm(); SwitchTab('types')\">\n <i class=\"fa-solid fa-arrow-right\"></i> Go to Content Types\n </button>\n <button class=\"at-action-btn at-secondary-btn\" (click)=\"ShowNoContentTypeWarning = false\">Close</button>\n </div>\n </div>\n </div>\n }\n</div>\n", styles: ["/* ============================================================\n Content Autotagging Dashboard\n All colors use MJ design tokens \u2014 no hardcoded hex values.\n All classes prefixed with at- to prevent leaking (ViewEncapsulation.None).\n ============================================================ */\n\n/* \u2500\u2500 Root layout \u2500\u2500 */\n\n.at-dashboard {\n display: flex;\n height: 100%;\n overflow: hidden;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550 LEFT NAV \u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.at-left-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.at-left-nav-header {\n padding: 16px 16px 12px;\n border-bottom: 1px solid var(--mj-border-subtle);\n}\n\n.at-left-nav-header h2 {\n font-size: 0.95rem;\n font-weight: 700;\n display: flex;\n align-items: center;\n gap: 8px;\n margin: 0;\n color: var(--mj-text-primary);\n}\n\n.at-left-nav-header h2 i {\n color: var(--mj-brand-primary);\n}\n\n.at-left-nav-items {\n flex: 1;\n padding: 8px;\n overflow-y: auto;\n}\n\n.at-nav-item {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 12px;\n border-radius: 8px;\n font-size: 0.82rem;\n font-weight: 500;\n color: var(--mj-text-muted);\n cursor: pointer;\n transition: all 0.12s ease;\n margin-bottom: 2px;\n}\n\n.at-nav-item:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-secondary);\n}\n\n.at-nav-item.active {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n font-weight: 600;\n}\n\n.at-nav-item i {\n width: 18px;\n text-align: center;\n font-size: 0.8rem;\n}\n\n.at-nav-badge {\n margin-left: auto;\n background: var(--mj-bg-surface-sunken);\n padding: 1px 7px;\n border-radius: 10px;\n font-size: 0.65rem;\n font-weight: 600;\n color: var(--mj-text-muted);\n}\n\n.at-nav-item.active .at-nav-badge {\n background: color-mix(in srgb, var(--mj-brand-primary) 18%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.at-nav-badge-live {\n background: var(--mj-status-success-bg) !important;\n color: var(--mj-status-success-text) !important;\n}\n\n.at-nav-divider {\n height: 1px;\n background: var(--mj-border-subtle);\n margin: 8px 12px;\n}\n\n.at-left-nav-footer {\n padding: 12px;\n border-top: 1px solid var(--mj-border-subtle);\n}\n\n.at-run-pipeline-btn {\n width: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 10px;\n border: none;\n border-radius: 8px;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n font-size: 0.82rem;\n font-weight: 600;\n cursor: pointer;\n transition: background 0.15s ease;\n}\n\n.at-run-pipeline-btn:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n}\n\n.at-run-pipeline-btn:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550 MAIN CONTENT AREA \u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.at-main-area {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n.at-loading-overlay {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n}\n\n.at-page-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 14px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n.at-page-title {\n font-size: 1rem;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.at-page-subtitle {\n font-size: 0.72rem;\n color: var(--mj-text-muted);\n margin-top: 2px;\n}\n\n.at-page-actions {\n display: flex;\n gap: 8px;\n align-items: center;\n}\n\n.at-page-body {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n padding: 16px 20px;\n min-height: 0;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550 SHARED COMPONENTS \u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.at-action-btn {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 7px 14px;\n border: 1px solid;\n border-radius: 7px;\n cursor: pointer;\n font-size: 0.78rem;\n font-weight: 500;\n transition: all 0.15s ease;\n}\n\n.at-primary-btn {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-color: var(--mj-brand-primary);\n}\n\n.at-primary-btn:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n}\n\n.at-primary-btn:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.at-secondary-btn {\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n border-color: var(--mj-border-default);\n}\n\n.at-secondary-btn:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.at-card {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 10px;\n overflow: hidden;\n}\n\n.at-card-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 16px;\n border-bottom: 1px solid var(--mj-border-subtle);\n}\n\n.at-card-title {\n font-size: 0.82rem;\n font-weight: 600;\n display: flex;\n align-items: center;\n gap: 6px;\n color: var(--mj-text-primary);\n}\n\n.at-card-title i {\n color: var(--mj-brand-primary);\n font-size: 0.75rem;\n}\n\n.at-card-body {\n padding: 0;\n}\n\n.at-empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 32px 16px;\n color: var(--mj-text-disabled);\n}\n\n.at-empty-state i {\n font-size: 28px;\n}\n\n.at-empty-state p {\n margin: 0;\n font-size: 13px;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550 KPI STRIP \u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.at-kpi-strip {\n display: flex;\n gap: 12px;\n margin-bottom: 16px;\n}\n\n.at-kpi-card {\n flex: 1;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 10px;\n padding: 14px 16px;\n}\n\n.at-kpi-value {\n font-size: 1.4rem;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.at-kpi-error-value {\n color: var(--mj-status-error-text);\n}\n\n.at-kpi-label {\n font-size: 0.72rem;\n color: var(--mj-text-muted);\n margin-top: 2px;\n}\n\n.at-kpi-trend {\n font-size: 0.68rem;\n margin-top: 4px;\n display: flex;\n align-items: center;\n gap: 4px;\n color: var(--mj-text-muted);\n}\n\n.at-kpi-trend.up {\n color: var(--mj-status-success-text);\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550 PIPELINE TAB \u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.at-pipeline-layout {\n display: flex;\n gap: 16px;\n flex: 1;\n min-height: 0;\n}\n\n.at-pipeline-center {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 12px;\n min-width: 0;\n min-height: 0;\n}\n\n.at-pipeline-right {\n width: 320px;\n flex-shrink: 0;\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n/* Pipeline Stages */\n\n.at-pipeline-stages {\n display: flex;\n gap: 0;\n align-items: center;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 10px;\n padding: 12px 16px;\n}\n\n.at-pipeline-stage {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 4px;\n}\n\n.at-pipeline-stage-icon {\n width: 36px;\n height: 36px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 50%;\n font-size: 0.85rem;\n}\n\n.stage-idle .at-pipeline-stage-icon {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n\n.stage-active .at-pipeline-stage-icon {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n animation: at-pulse 1.5s infinite;\n}\n\n.stage-complete .at-pipeline-stage-icon {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n}\n\n@keyframes at-pulse {\n 0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--mj-brand-primary) 30%, transparent); }\n 50% { box-shadow: 0 0 0 6px color-mix(in srgb, var(--mj-brand-primary) 0%, transparent); }\n}\n\n.at-pipeline-stage-name {\n font-size: 0.68rem;\n font-weight: 600;\n color: var(--mj-text-secondary);\n}\n\n.at-pipeline-stage-count {\n font-size: 0.6rem;\n color: var(--mj-text-muted);\n}\n\n.at-pipeline-arrow {\n width: 24px;\n text-align: center;\n color: var(--mj-text-disabled);\n font-size: 0.6rem;\n}\n\n.at-stage-connector {\n width: 32px;\n height: 2px;\n background: var(--mj-border-default);\n transition: background 0.4s ease;\n}\n\n.at-stage-connector.connector-complete {\n background: var(--mj-status-success);\n}\n\n/* Progress section */\n\n.at-progress-section {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 8px;\n padding: 10px 16px;\n}\n\n.at-progress-header {\n display: flex;\n justify-content: space-between;\n font-size: 0.75rem;\n margin-bottom: 4px;\n}\n\n.at-progress-stage-label {\n color: var(--mj-text-secondary);\n font-weight: 500;\n}\n\n.at-progress-pct {\n color: var(--mj-brand-primary);\n font-weight: 600;\n}\n\n.at-progress-bar {\n height: 4px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 2px;\n overflow: hidden;\n}\n\n.at-progress-fill {\n height: 100%;\n background: var(--mj-brand-primary);\n border-radius: 2px;\n transition: width 0.3s ease;\n}\n\n.at-progress-current {\n font-size: 0.68rem;\n color: var(--mj-text-muted);\n margin-top: 4px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.at-progress-fill-paused {\n background: var(--mj-status-warning);\n animation: pulse-paused 1.5s ease-in-out infinite;\n}\n\n@keyframes pulse-paused {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.5; }\n}\n\n.at-pipeline-controls {\n display: flex;\n gap: 8px;\n margin-top: 8px;\n justify-content: flex-end;\n}\n\n.at-danger-btn {\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n border-color: var(--mj-status-error);\n}\n\n.at-danger-btn:hover:not(:disabled) {\n background: var(--mj-status-error-text);\n border-color: var(--mj-status-error-text);\n}\n\n/* Feed items */\n\n.at-feed-item {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 14px;\n border-bottom: 1px solid var(--mj-border-subtle);\n font-size: 0.78rem;\n}\n\n.at-feed-item:last-child {\n border-bottom: none;\n}\n\n.at-feed-status-dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n flex-shrink: 0;\n}\n\n.at-feed-status-dot.complete {\n background: var(--mj-status-success);\n}\n\n.at-feed-status-dot.processing {\n background: var(--mj-brand-primary);\n animation: at-pulse 1.5s infinite;\n}\n\n.at-feed-status-dot.error {\n background: var(--mj-status-error);\n}\n\n.at-feed-item-name {\n flex: 1;\n font-weight: 500;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n color: var(--mj-text-primary);\n}\n\n.at-feed-item-source {\n color: var(--mj-text-muted);\n font-size: 0.7rem;\n min-width: 100px;\n}\n\n.at-feed-item-tags {\n display: flex;\n gap: 4px;\n}\n\n.at-feed-tag {\n padding: 1px 6px;\n border-radius: 3px;\n font-size: 0.62rem;\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.at-feed-item-time {\n color: var(--mj-text-muted);\n font-size: 0.68rem;\n white-space: nowrap;\n min-width: 60px;\n text-align: right;\n}\n\n/* Source mini cards (right panel) */\n\n.at-source-mini {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 14px;\n border-bottom: 1px solid var(--mj-border-subtle);\n cursor: pointer;\n transition: background 0.1s ease;\n}\n\n.at-source-mini:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.at-source-mini:last-child {\n border-bottom: none;\n}\n\n.at-source-mini-icon {\n width: 28px;\n height: 28px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 6px;\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n font-size: 0.72rem;\n flex-shrink: 0;\n}\n\n.at-source-mini-info {\n flex: 1;\n min-width: 0;\n}\n\n.at-source-mini-name {\n font-size: 0.78rem;\n font-weight: 600;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n color: var(--mj-text-primary);\n}\n\n.at-source-mini-meta {\n font-size: 0.65rem;\n color: var(--mj-text-muted);\n}\n\n.at-source-mini-status {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n flex-shrink: 0;\n}\n\n.at-source-mini-status.active {\n background: var(--mj-status-success);\n}\n\n.at-source-mini-status.error {\n background: var(--mj-status-error);\n}\n\n.at-source-mini-status.inactive {\n background: var(--mj-text-disabled);\n}\n\n/* Tag cloud card */\n\n.at-tag-cloud-card {\n padding: 16px;\n}\n\n.at-tag-cloud {\n display: flex;\n flex-wrap: wrap;\n gap: 5px;\n}\n\n.at-tag-pill {\n padding: 4px 12px;\n border-radius: 14px;\n font-size: 0.72rem;\n font-weight: 500;\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n color: var(--mj-text-secondary);\n border: 1px solid var(--mj-border-subtle);\n cursor: pointer;\n transition: all 0.12s ease;\n}\n\n.at-tag-pill:hover {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n.at-tag-weighted {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n}\n\n.at-tag-weight {\n font-size: 0.6rem;\n opacity: 0.6;\n font-weight: 400;\n}\n\n.at-tag-row-clickable {\n cursor: pointer;\n transition: background 0.1s ease;\n}\n\n.at-tag-row-clickable:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.at-tag-row-selected {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface)) !important;\n border-left: 3px solid var(--mj-brand-primary);\n}\n\n.at-tag-pill.large {\n font-size: 0.85rem;\n padding: 5px 14px;\n}\n\n.at-tag-pill.small {\n font-size: 0.65rem;\n padding: 3px 8px;\n color: var(--mj-text-muted);\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550 SOURCES TAB \u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.at-sources-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));\n gap: 12px;\n}\n\n.at-source-card-full {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 10px;\n padding: 16px;\n transition: border-color 0.15s ease;\n}\n\n.at-source-card-full:hover {\n border-color: var(--mj-border-default);\n}\n\n.at-source-card-header {\n display: flex;\n align-items: center;\n gap: 10px;\n margin-bottom: 12px;\n}\n\n.at-source-card-icon {\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 10px;\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n font-size: 1rem;\n flex-shrink: 0;\n}\n\n.at-source-card-title {\n font-size: 0.9rem;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.at-source-card-type {\n font-size: 0.68rem;\n color: var(--mj-text-muted);\n}\n\n.at-source-card-status {\n margin-left: auto;\n display: flex;\n align-items: center;\n gap: 5px;\n font-size: 0.7rem;\n font-weight: 500;\n}\n\n.at-source-card-status.active {\n color: var(--mj-status-success-text);\n}\n\n.at-source-card-status.error {\n color: var(--mj-status-error-text);\n}\n\n.at-source-card-status.inactive {\n color: var(--mj-text-disabled);\n}\n\n.at-source-card-url {\n font-size: 0.7rem;\n color: var(--mj-brand-primary);\n margin-bottom: 10px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.at-source-card-stats {\n display: flex;\n gap: 16px;\n padding-top: 10px;\n border-top: 1px solid var(--mj-border-subtle);\n}\n\n.at-source-stat {\n display: flex;\n flex-direction: column;\n}\n\n.at-source-stat-value {\n font-size: 1rem;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.at-source-stat-label {\n font-size: 0.65rem;\n color: var(--mj-text-muted);\n}\n\n.at-source-card-actions {\n display: flex;\n gap: 6px;\n margin-top: 10px;\n}\n\n.at-source-action-btn {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 4px;\n padding: 6px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n font-size: 0.7rem;\n cursor: pointer;\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n transition: all 0.12s ease;\n}\n\n.at-source-action-btn:hover {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n.at-source-delete-btn:hover {\n border-color: var(--mj-status-error);\n color: var(--mj-status-error-text);\n}\n\n.at-add-source-card {\n background: none;\n border: 2px dashed var(--mj-border-default);\n border-radius: 10px;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 40px;\n cursor: pointer;\n transition: all 0.15s ease;\n color: var(--mj-text-muted);\n min-height: 200px;\n}\n\n.at-add-source-card:hover {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n.at-add-source-card i {\n font-size: 1.5rem;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550 CONTENT TYPES TAB \u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.at-ct-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));\n gap: 12px;\n}\n\n.at-ct-card {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 10px;\n padding: 16px;\n}\n\n.at-ct-card-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 10px;\n}\n\n.at-ct-card-name {\n font-size: 0.9rem;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.at-ct-card-model {\n font-size: 0.68rem;\n color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n padding: 2px 8px;\n border-radius: 10px;\n}\n\n.at-ct-field {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 6px 0;\n border-bottom: 1px solid var(--mj-border-subtle);\n font-size: 0.78rem;\n}\n\n.at-ct-field:last-child {\n border-bottom: none;\n}\n\n.at-ct-field-label {\n color: var(--mj-text-muted);\n}\n\n.at-ct-field-value {\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.at-ct-tag-range {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-top: 8px;\n padding: 8px 10px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 6px;\n font-size: 0.75rem;\n color: var(--mj-text-primary);\n}\n\n.at-ct-tag-range i {\n color: var(--mj-brand-primary);\n}\n\n.at-ct-tag-range-bar {\n flex: 1;\n height: 6px;\n background: var(--mj-bg-surface);\n border-radius: 3px;\n position: relative;\n}\n\n.at-ct-tag-range-fill {\n position: absolute;\n height: 100%;\n background: var(--mj-brand-primary);\n border-radius: 3px;\n}\n\n.at-ct-range-suffix {\n color: var(--mj-text-muted);\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550 TAG LIBRARY TAB \u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.at-tag-lib-layout {\n display: flex;\n gap: 16px;\n}\n\n.at-tag-lib-main {\n flex: 1;\n}\n\n.at-tag-lib-sidebar {\n width: 280px;\n flex-shrink: 0;\n}\n\n.at-tag-table {\n width: 100%;\n border-collapse: collapse;\n}\n\n.at-tag-table th {\n text-align: left;\n padding: 8px 12px;\n font-size: 0.7rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--mj-text-muted);\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-elevated);\n position: sticky;\n top: 0;\n z-index: 1;\n}\n\n.at-tag-table td {\n padding: 10px 12px;\n font-size: 0.8rem;\n border-bottom: 1px solid var(--mj-border-subtle);\n color: var(--mj-text-primary);\n}\n\n.at-tag-table tr:hover td {\n background: var(--mj-bg-surface-hover);\n}\n\n.at-tag-name-cell {\n font-weight: 600;\n}\n\n.at-tag-bar {\n width: 80px;\n height: 6px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 3px;\n display: inline-block;\n vertical-align: middle;\n}\n\n.at-tag-bar-fill {\n height: 100%;\n background: var(--mj-brand-primary);\n border-radius: 3px;\n}\n\n/* Weight indicator in tag table */\n.at-weight-indicator {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.at-weight-bar {\n width: 50px;\n height: 6px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 3px;\n overflow: hidden;\n}\n\n.at-weight-bar-fill {\n height: 100%;\n border-radius: 3px;\n transition: width 0.2s ease;\n}\n\n.at-weight-bar-fill.at-weight-high {\n background: var(--mj-status-success);\n}\n\n.at-weight-bar-fill.at-weight-medium {\n background: var(--mj-status-warning);\n}\n\n.at-weight-bar-fill.at-weight-low {\n background: var(--mj-status-error);\n}\n\n.at-weight-value {\n font-size: 0.7rem;\n font-weight: 600;\n color: var(--mj-text-muted);\n min-width: 28px;\n}\n\n.at-tags-by-source {\n font-size: 0.78rem;\n}\n\n.at-tag-source-row {\n display: flex;\n justify-content: space-between;\n padding: 5px 0;\n border-bottom: 1px solid var(--mj-border-subtle);\n color: var(--mj-text-primary);\n}\n\n.at-tag-source-row:last-child {\n border-bottom: none;\n}\n\n.at-search-input {\n padding: 7px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 7px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n font-size: 0.8rem;\n width: 200px;\n outline: none;\n}\n\n.at-search-input::placeholder {\n color: var(--mj-text-disabled);\n}\n\n.at-search-input:focus {\n border-color: var(--mj-brand-primary);\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550 RUN HISTORY TAB \u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.at-run-table {\n width: 100%;\n border-collapse: collapse;\n}\n\n.at-run-table th {\n text-align: left;\n padding: 10px 14px;\n font-size: 0.7rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--mj-text-muted);\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-elevated);\n position: sticky;\n top: 0;\n z-index: 1;\n}\n\n.at-run-table td {\n padding: 12px 14px;\n font-size: 0.8rem;\n border-bottom: 1px solid var(--mj-border-subtle);\n color: var(--mj-text-primary);\n}\n\n.at-run-table tr:hover td {\n background: var(--mj-bg-surface-hover);\n cursor: pointer;\n}\n\n.at-run-status-badge {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 2px 10px;\n border-radius: 10px;\n font-size: 0.7rem;\n font-weight: 600;\n}\n\n.at-run-status-badge.complete {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n}\n\n.at-run-status-badge.failed {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error-text);\n}\n\n.at-run-status-badge.running {\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.at-run-duration {\n color: var(--mj-text-muted);\n font-size: 0.75rem;\n}\n\n.at-run-source-name {\n font-weight: 500;\n}\n\n.at-run-error-text {\n color: var(--mj-status-error-text);\n}\n\n.at-filter-select {\n padding: 7px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 7px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n font-size: 0.78rem;\n outline: none;\n}\n\n.at-filter-select:focus {\n border-color: var(--mj-brand-primary);\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550 SLIDE-IN FORM PANEL \u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.at-slide-overlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: var(--mj-bg-overlay);\n z-index: 1000;\n}\n\n.at-slide-panel {\n position: fixed;\n right: 0;\n top: 0;\n bottom: 0;\n width: 420px;\n max-width: 100vw;\n background: var(--mj-bg-surface);\n border-left: 1px solid var(--mj-border-default);\n z-index: 1001;\n display: flex;\n flex-direction: column;\n box-shadow: -4px 0 24px color-mix(in srgb, var(--mj-text-primary) 15%, transparent);\n}\n\n.at-slide-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-subtle);\n}\n\n.at-slide-header h3 {\n margin: 0;\n font-size: 1rem;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.at-slide-close {\n background: none;\n border: none;\n font-size: 1.1rem;\n color: var(--mj-text-muted);\n cursor: pointer;\n padding: 4px;\n}\n\n.at-slide-close:hover {\n color: var(--mj-text-primary);\n}\n\n.at-slide-body {\n flex: 1;\n overflow-y: auto;\n padding: 20px;\n}\n\n.at-form-group {\n margin-bottom: 16px;\n}\n\n.at-form-label {\n display: block;\n font-size: 0.78rem;\n font-weight: 600;\n color: var(--mj-text-secondary);\n margin-bottom: 6px;\n}\n\n.at-form-input,\n.at-form-select,\n.at-form-textarea {\n width: 100%;\n padding: 9px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 7px;\n background: var(--mj-bg-surface-card);\n color: var(--mj-text-primary);\n font-size: 0.82rem;\n outline: none;\n font-family: inherit;\n}\n\n.at-form-input:focus,\n.at-form-select:focus,\n.at-form-textarea:focus {\n border-color: var(--mj-brand-primary);\n}\n\n.at-form-input::placeholder,\n.at-form-textarea::placeholder {\n color: var(--mj-text-disabled);\n}\n\n.at-form-textarea {\n resize: vertical;\n}\n\n.at-form-row {\n display: flex;\n gap: 12px;\n}\n\n.at-form-actions {\n display: flex;\n gap: 8px;\n margin-top: 24px;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550 RESPONSIVE \u2550\u2550\u2550\u2550\u2550\u2550 */\n\n@media (max-width: 1100px) {\n .at-pipeline-layout {\n flex-direction: column;\n }\n\n .at-pipeline-right {\n width: 100%;\n flex-direction: row;\n }\n\n .at-tag-lib-layout {\n flex-direction: column;\n }\n\n .at-tag-lib-sidebar {\n width: 100%;\n }\n}\n\n@media (max-width: 768px) {\n .at-left-nav {\n width: 180px;\n }\n\n .at-kpi-strip {\n flex-wrap: wrap;\n }\n\n .at-kpi-card {\n min-width: 140px;\n }\n\n .at-sources-grid {\n grid-template-columns: 1fr;\n }\n\n .at-ct-grid {\n grid-template-columns: 1fr;\n }\n\n .at-slide-panel {\n width: 100vw;\n }\n}\n\n@media (max-width: 480px) {\n .at-left-nav {\n width: 56px;\n }\n\n .at-left-nav-header h2 {\n font-size: 0;\n }\n\n .at-left-nav-header h2 i {\n font-size: 1rem;\n }\n\n .at-nav-item {\n justify-content: center;\n padding: 10px;\n font-size: 0;\n }\n\n .at-nav-item i {\n font-size: 1rem;\n }\n\n .at-nav-badge {\n display: none;\n }\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n Slide-in Form Panel\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.at-slide-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.35);\n z-index: 9999;\n animation: at-fade-in 0.2s ease;\n}\n\n@keyframes at-fade-in { from { opacity: 0; } to { opacity: 1; } }\n\n.at-slide-panel {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n width: 420px;\n background: var(--mj-bg-surface);\n border-left: 1px solid var(--mj-border-default);\n box-shadow: -8px 0 40px rgba(0, 0, 0, 0.4);\n z-index: 10000;\n display: flex;\n flex-direction: column;\n animation: at-slide-in 0.25s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n@keyframes at-slide-in { from { transform: translateX(100%); } to { transform: translateX(0); } }\n\n.at-slide-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n.at-slide-header h3 {\n font-size: 1rem;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.at-slide-close {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n border: none;\n border-radius: 6px;\n cursor: pointer;\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n font-size: 0.85rem;\n transition: all 0.15s ease;\n}\n\n.at-slide-close:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n.at-slide-body {\n flex: 1;\n overflow-y: auto;\n padding: 20px;\n display: flex;\n flex-direction: column;\n gap: 16px;\n}\n\n.at-form-group {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.at-form-label {\n font-size: 0.75rem;\n font-weight: 600;\n color: var(--mj-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.3px;\n}\n\n.at-form-input,\n.at-form-select,\n.at-form-textarea {\n padding: 9px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 7px;\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-primary);\n font-size: 0.85rem;\n outline: none;\n transition: border-color 0.15s ease;\n font-family: inherit;\n}\n\n.at-form-input:focus,\n.at-form-select:focus,\n.at-form-textarea:focus {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.at-form-select {\n appearance: none;\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%2364748b' d='M3 5l3 3 3-3'/%3E%3C/svg%3E\");\n background-repeat: no-repeat;\n background-position: right 10px center;\n padding-right: 30px;\n}\n\n.at-form-textarea {\n resize: vertical;\n min-height: 70px;\n}\n\n.at-form-row {\n display: flex;\n gap: 12px;\n}\n\n.at-form-actions {\n display: flex;\n gap: 8px;\n padding-top: 8px;\n border-top: 1px solid var(--mj-border-subtle);\n margin-top: 8px;\n}\n\n.at-form-actions .at-action-btn {\n flex: 1;\n justify-content: center;\n}\n\n/* Also add empty state for Content Types (matching Sources) */\n.at-add-type-card {\n background: none;\n border: 2px dashed var(--mj-border-default);\n border-radius: 10px;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 40px;\n cursor: pointer;\n transition: all 0.15s ease;\n color: var(--mj-text-muted);\n min-height: 200px;\n}\n\n.at-add-type-card:hover {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n.at-add-type-card i {\n font-size: 1.5rem;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550 FORKED PIPELINE STAGES \u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.at-pipeline-stages-forked {\n display: flex;\n align-items: center;\n gap: 0;\n}\n\n.at-pipeline-fork {\n display: flex;\n align-items: center;\n gap: 0;\n flex: 2;\n}\n\n.at-pipeline-fork-lines {\n width: 28px;\n display: flex;\n flex-direction: column;\n gap: 12px;\n position: relative;\n flex-shrink: 0;\n}\n\n.at-pipeline-fork-line {\n height: 2px;\n background: var(--mj-border-default);\n width: 100%;\n position: relative;\n}\n\n.at-pipeline-fork-line::before {\n content: '';\n position: absolute;\n width: 2px;\n height: 12px;\n background: var(--mj-border-default);\n left: 0;\n}\n\n.at-fork-top::before {\n bottom: 0;\n left: 0;\n}\n\n.at-fork-bottom::before {\n top: 0;\n left: 0;\n}\n\n.at-pipeline-fork-branches {\n display: flex;\n flex-direction: column;\n gap: 8px;\n flex: 1;\n}\n\n.at-pipeline-fork-branches .at-pipeline-stage {\n flex: none;\n padding: 6px 0;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550 CLICKABLE FEED ITEMS \u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.at-feed-item-clickable {\n cursor: pointer;\n}\n\n.at-feed-item-clickable:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550 FEED SEARCH & PAGINATION \u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.at-feed-card {\n flex: 1;\n display: flex;\n flex-direction: column;\n min-height: 0;\n}\n\n.at-feed-header-actions {\n display: flex;\n align-items: center;\n gap: 10px;\n margin-left: auto;\n}\n\n.at-feed-sort-btn {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 3px 8px;\n border: 1px solid var(--mj-border-default);\n border-radius: 5px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n font-size: 0.68rem;\n cursor: pointer;\n transition: background 0.15s, color 0.15s;\n}\n\n.at-feed-sort-btn:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n.at-feed-count {\n font-size: 0.7rem;\n color: var(--mj-text-muted);\n}\n\n.at-feed-search-bar {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 14px;\n border-bottom: 1px solid var(--mj-border-subtle);\n background: var(--mj-bg-surface-card);\n}\n\n.at-feed-search-icon {\n color: var(--mj-text-disabled);\n font-size: 0.72rem;\n flex-shrink: 0;\n}\n\n.at-feed-search-input {\n flex: 1;\n border: none;\n background: transparent;\n font-size: 0.78rem;\n color: var(--mj-text-primary);\n outline: none;\n padding: 4px 0;\n min-width: 0;\n}\n\n.at-feed-search-input::placeholder {\n color: var(--mj-text-disabled);\n}\n\n.at-feed-search-clear {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 18px;\n height: 18px;\n padding: 0;\n border: none;\n border-radius: 50%;\n background: var(--mj-border-default);\n color: var(--mj-text-muted);\n cursor: pointer;\n font-size: 9px;\n flex-shrink: 0;\n}\n\n.at-feed-search-clear:hover {\n background: var(--mj-border-strong);\n color: var(--mj-text-primary);\n}\n\n.at-feed-scroll-body {\n overflow-y: auto;\n min-height: 0;\n flex: 1;\n}\n\n.at-feed-item-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n overflow: hidden;\n}\n\n.at-feed-item-content .at-feed-item-name {\n font-size: 0.82rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.at-feed-item-source-label {\n font-size: 0.7rem;\n font-weight: 500;\n color: var(--mj-brand-primary);\n}\n\n.at-feed-pagination {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 12px;\n padding: 8px 14px;\n border-top: 1px solid var(--mj-border-subtle);\n background: var(--mj-bg-surface-card);\n}\n\n.at-feed-pagination-label {\n font-size: 0.72rem;\n color: var(--mj-text-muted);\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550 CLICKABLE SOURCE CARDS \u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.at-source-card-clickable {\n cursor: pointer;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550 FORM HINT \u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.at-form-hint {\n font-size: 0.68rem;\n color: var(--mj-text-muted);\n font-style: italic;\n margin-top: 2px;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550 DETAIL PANEL (wider) \u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.at-detail-panel {\n width: 500px;\n}\n\n/* \u2500\u2500 Detail: Item header \u2500\u2500 */\n\n.at-detail-item-header {\n margin-bottom: 8px;\n}\n\n.at-detail-item-name {\n font-size: 1.05rem;\n font-weight: 700;\n color: var(--mj-text-primary);\n margin: 0 0 6px 0;\n word-break: break-word;\n}\n\n.at-detail-badges {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n}\n\n.at-detail-badge {\n padding: 2px 10px;\n border-radius: 10px;\n font-size: 0.7rem;\n font-weight: 600;\n}\n\n.at-detail-badge-source {\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.at-detail-badge-type {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-secondary);\n}\n\n.at-detail-badge-file {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n\n.at-detail-badge-status-active {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n}\n\n.at-detail-badge-status-error {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error-text);\n}\n\n.at-detail-badge-status-inactive {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-disabled);\n}\n\n/* \u2500\u2500 Detail: Sections \u2500\u2500 */\n\n.at-detail-section {\n margin-bottom: 4px;\n}\n\n.at-detail-section-label {\n font-size: 0.72rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n color: var(--mj-text-muted);\n margin-bottom: 6px;\n}\n\n.at-detail-link {\n font-size: 0.8rem;\n color: var(--mj-brand-primary);\n text-decoration: none;\n word-break: break-all;\n}\n\n.at-detail-link:hover {\n text-decoration: underline;\n}\n\n/* \u2500\u2500 Detail: Text preview \u2500\u2500 */\n\n.at-detail-text-preview {\n max-height: 200px;\n overflow-y: auto;\n padding: 10px 12px;\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 6px;\n font-size: 0.78rem;\n font-family: 'SF Mono', 'Cascadia Code', 'Menlo', monospace;\n color: var(--mj-text-primary);\n white-space: pre-wrap;\n word-break: break-word;\n line-height: 1.5;\n}\n\n/* \u2500\u2500 Detail: Tags \u2500\u2500 */\n\n.at-detail-tags {\n display: flex;\n flex-wrap: wrap;\n gap: 5px;\n}\n\n/* \u2500\u2500 Detail: Meta grid \u2500\u2500 */\n\n.at-detail-meta-grid {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 8px;\n overflow: hidden;\n}\n\n.at-detail-meta-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 8px 12px;\n border-bottom: 1px solid var(--mj-border-subtle);\n font-size: 0.78rem;\n}\n\n.at-detail-meta-row:last-child {\n border-bottom: none;\n}\n\n.at-detail-meta-key {\n color: var(--mj-text-muted);\n font-weight: 500;\n flex-shrink: 0;\n margin-right: 12px;\n}\n\n.at-detail-meta-value {\n color: var(--mj-text-primary);\n text-align: right;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.at-detail-meta-mono {\n font-family: 'SF Mono', 'Cascadia Code', 'Menlo', monospace;\n font-size: 0.72rem;\n}\n\n/* \u2500\u2500 Detail: Actions \u2500\u2500 */\n\n.at-detail-actions {\n display: flex;\n gap: 8px;\n padding-top: 8px;\n border-top: 1px solid var(--mj-border-subtle);\n margin-top: 8px;\n}\n\n.at-detail-actions .at-action-btn {\n flex: 1;\n justify-content: center;\n}\n\n/* \u2500\u2500 Detail: Source header \u2500\u2500 */\n\n.at-detail-source-header {\n display: flex;\n align-items: center;\n gap: 12px;\n margin-bottom: 8px;\n}\n\n/* \u2500\u2500 Detail: Stats strip \u2500\u2500 */\n\n.at-detail-stats-strip {\n display: flex;\n gap: 12px;\n flex-wrap: wrap;\n}\n\n.at-detail-stat {\n flex: 1;\n min-width: 60px;\n text-align: center;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 8px;\n padding: 8px 6px;\n}\n\n.at-detail-stat-value {\n font-size: 1rem;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.at-detail-stat-label {\n font-size: 0.62rem;\n color: var(--mj-text-muted);\n margin-top: 2px;\n}\n\n/* \u2500\u2500 Detail: Content Library \u2500\u2500 */\n\n.at-detail-content-list {\n max-height: 250px;\n overflow-y: auto;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 8px;\n}\n\n.at-detail-content-item {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n border-bottom: 1px solid var(--mj-border-subtle);\n font-size: 0.78rem;\n cursor: pointer;\n transition: background 0.1s ease;\n}\n\n.at-detail-content-item:last-child {\n border-bottom: none;\n}\n\n.at-detail-content-item:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.at-detail-content-item-name {\n flex: 1;\n font-weight: 500;\n color: var(--mj-text-primary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.at-detail-content-item-tags {\n font-size: 0.68rem;\n color: var(--mj-text-muted);\n white-space: nowrap;\n}\n\n.at-detail-content-item-time {\n font-size: 0.68rem;\n color: var(--mj-text-muted);\n white-space: nowrap;\n}\n\n/* \u2500\u2500 Detail: Run history \u2500\u2500 */\n\n.at-detail-run-history {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 8px;\n max-height: 200px;\n overflow-y: auto;\n}\n\n.at-detail-run-row {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n border-bottom: 1px solid var(--mj-border-subtle);\n font-size: 0.75rem;\n}\n\n.at-detail-run-row:last-child {\n border-bottom: none;\n}\n\n.at-detail-run-time {\n color: var(--mj-text-secondary);\n flex: 1;\n}\n\n.at-detail-run-duration {\n color: var(--mj-text-muted);\n}\n\n.at-detail-run-items {\n color: var(--mj-text-muted);\n}\n\n@media (max-width: 600px) {\n .at-slide-panel {\n width: 100%;\n }\n\n .at-detail-panel {\n width: 100%;\n }\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n TAXONOMY GOVERNANCE TAB\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n/* \u2500\u2500 Sub-tab strip \u2500\u2500 */\n\n.at-tax-tab-strip {\n display: flex;\n border-bottom: 2px solid var(--mj-border-default);\n padding: 0 20px;\n gap: 0;\n flex-shrink: 0;\n}\n\n.at-tax-tab {\n padding: 10px 20px;\n font-size: 0.78rem;\n font-weight: 500;\n color: var(--mj-text-muted);\n cursor: pointer;\n border-bottom: 2px solid transparent;\n margin-bottom: -2px;\n transition: all 0.15s;\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.at-tax-tab:hover {\n color: var(--mj-text-secondary);\n}\n\n.at-tax-tab.active {\n color: var(--mj-brand-primary);\n border-bottom-color: var(--mj-brand-primary);\n font-weight: 600;\n}\n\n.at-tax-tab-badge {\n font-size: 0.62rem;\n font-weight: 600;\n padding: 1px 7px;\n border-radius: 10px;\n}\n\n.at-tax-badge-warning {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.at-tax-badge-error {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n/* \u2500\u2500 Tree View: Split layout \u2500\u2500 */\n\n.at-tax-split-view {\n display: flex;\n gap: 0;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 10px;\n height: calc(100vh - 320px);\n min-height: 400px;\n overflow: hidden;\n}\n\n.at-tax-tree-panel {\n width: 40%;\n border-right: 1px solid var(--mj-border-default);\n display: flex;\n flex-direction: column;\n}\n\n.at-tax-tree-toolbar {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 12px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.at-tax-toolbar-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 30px;\n height: 30px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n cursor: pointer;\n font-size: 0.8rem;\n transition: background 0.15s, color 0.15s;\n}\n\n.at-tax-toolbar-btn:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n.at-tax-toolbar-btn.active {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n}\n\n.at-tax-tree-body {\n flex: 1;\n overflow-y: auto;\n padding: 8px 0;\n}\n\n.at-tax-tree-node {\n padding: 6px 16px;\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 0.78rem;\n cursor: pointer;\n transition: background 0.1s;\n line-height: 1.4;\n}\n\n.at-tax-tree-node:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.at-tax-node-selected {\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n}\n\n.at-tax-node-drag-over {\n background: color-mix(in srgb, var(--mj-brand-primary) 20%, var(--mj-bg-surface));\n outline: 2px dashed var(--mj-brand-primary);\n outline-offset: -2px;\n}\n\n.at-tax-node-multi-selected {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n}\n\n.at-tax-tree-add-child {\n margin-left: auto;\n opacity: 0;\n font-size: 0.7rem;\n color: var(--mj-text-muted);\n cursor: pointer;\n padding: 2px 6px;\n border-radius: 4px;\n transition: opacity 0.15s, color 0.15s, background 0.15s;\n}\n\n.at-tax-tree-node:hover .at-tax-tree-add-child {\n opacity: 1;\n}\n\n.at-tax-tree-add-child:hover {\n color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n}\n\n.at-tax-tree-checkbox {\n width: 14px;\n height: 14px;\n cursor: pointer;\n accent-color: var(--mj-brand-primary);\n flex-shrink: 0;\n}\n\n.at-tax-tree-saving-overlay {\n position: absolute;\n inset: 0;\n background: color-mix(in srgb, var(--mj-bg-surface) 75%, transparent);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10;\n backdrop-filter: blur(1px);\n}\n\n.at-tax-create-context {\n font-size: 0.8rem;\n color: var(--mj-text-muted);\n margin-bottom: 12px;\n padding: 6px 10px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 6px;\n}\n\n.at-tax-tree-arrow {\n width: 16px;\n font-size: 0.55rem;\n color: var(--mj-text-muted);\n flex-shrink: 0;\n text-align: center;\n cursor: pointer;\n}\n\n.at-tax-arrow-collapsed::before {\n content: \"\\25B6\";\n}\n\n.at-tax-arrow-expanded::before {\n content: \"\\25BC\";\n}\n\n.at-tax-arrow-leaf {\n visibility: hidden;\n}\n\n.at-tax-health-dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n flex-shrink: 0;\n}\n\n.at-tax-health-dot.green {\n background: var(--mj-status-success);\n}\n\n.at-tax-health-dot.yellow {\n background: var(--mj-status-warning);\n}\n\n.at-tax-health-dot.red {\n background: var(--mj-status-error);\n}\n\n.at-tax-tree-label {\n flex: 1;\n color: var(--mj-text-primary);\n}\n\n.at-tax-tree-label-selected {\n font-weight: 700;\n}\n\n.at-tax-tree-count {\n font-size: 0.65rem;\n color: var(--mj-text-muted);\n margin-left: 4px;\n}\n\n/* \u2500\u2500 Details panel \u2500\u2500 */\n\n.at-tax-details-panel {\n width: 60%;\n display: flex;\n flex-direction: column;\n overflow-y: auto;\n}\n\n.at-tax-details-header {\n padding: 20px 24px 0;\n}\n\n.at-tax-breadcrumb {\n font-size: 0.7rem;\n color: var(--mj-text-muted);\n margin-bottom: 8px;\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.at-tax-bc-link {\n color: var(--mj-brand-primary);\n cursor: pointer;\n}\n\n.at-tax-bc-link:hover {\n text-decoration: underline;\n}\n\n.at-tax-bc-sep {\n color: var(--mj-border-default);\n}\n\n.at-tax-bc-current {\n color: var(--mj-text-secondary);\n font-weight: 600;\n}\n\n.at-tax-details-title {\n font-size: 1.2rem;\n font-weight: 700;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 4px;\n}\n\n.at-tax-edit-icon {\n font-size: 0.75rem;\n color: var(--mj-text-muted);\n cursor: pointer;\n}\n\n.at-tax-edit-icon:hover {\n color: var(--mj-brand-primary);\n}\n\n.at-tax-details-desc {\n font-size: 0.78rem;\n color: var(--mj-text-secondary);\n line-height: 1.5;\n margin-bottom: 16px;\n padding: 8px 12px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 6px;\n border: 1px solid var(--mj-border-subtle);\n}\n\n.at-tax-edit-form {\n margin-bottom: 16px;\n}\n\n/* \u2500\u2500 Stats row \u2500\u2500 */\n\n.at-tax-stats-row {\n display: flex;\n gap: 12px;\n flex-wrap: wrap;\n margin-bottom: 16px;\n padding: 0 24px;\n}\n\n.at-tax-stat-item {\n display: flex;\n flex-direction: column;\n align-items: center;\n padding: 10px 14px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 8px;\n min-width: 72px;\n}\n\n.at-tax-stat-value {\n font-size: 1.1rem;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.at-tax-stat-date {\n font-size: 0.8rem;\n}\n\n.at-tax-stat-label {\n font-size: 0.62rem;\n color: var(--mj-text-muted);\n margin-top: 2px;\n}\n\n/* \u2500\u2500 Action toolbar \u2500\u2500 */\n\n.at-tax-action-toolbar {\n display: flex;\n gap: 8px;\n padding: 0 24px;\n margin-bottom: 20px;\n flex-wrap: wrap;\n}\n\n.at-tax-action-btn {\n padding: 6px 14px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n background: var(--mj-bg-surface);\n font-size: 0.72rem;\n font-weight: 500;\n color: var(--mj-text-secondary);\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 5px;\n transition: all 0.15s;\n}\n\n.at-tax-action-btn:hover {\n background: var(--mj-bg-surface-hover);\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n.at-tax-action-danger:hover {\n border-color: var(--mj-status-error);\n color: var(--mj-status-error);\n background: color-mix(in srgb, var(--mj-status-error) 8%, var(--mj-bg-surface));\n}\n\n/* \u2500\u2500 Detail sections \u2500\u2500 */\n\n.at-tax-detail-section {\n padding: 0 24px 20px;\n}\n\n.at-tax-section-title {\n font-size: 0.7rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: var(--mj-text-muted);\n margin-bottom: 10px;\n}\n\n.at-tax-child-chips {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n}\n\n.at-tax-child-chip {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 10px;\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-default);\n border-radius: 16px;\n font-size: 0.72rem;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.at-tax-child-chip:hover {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.at-tax-chip-count {\n font-size: 0.6rem;\n background: var(--mj-border-default);\n color: var(--mj-text-muted);\n padding: 0 5px;\n border-radius: 8px;\n}\n\n/* \u2500\u2500 Recent items \u2500\u2500 */\n\n.at-tax-recent-list {\n list-style: none;\n}\n\n.at-tax-recent-item {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 8px 0;\n border-bottom: 1px solid var(--mj-border-subtle);\n font-size: 0.78rem;\n}\n\n.at-tax-recent-item:last-child {\n border-bottom: none;\n}\n\n.at-tax-recent-icon {\n width: 28px;\n height: 28px;\n border-radius: 6px;\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 0.72rem;\n flex-shrink: 0;\n}\n\n.at-tax-recent-name {\n flex: 1;\n color: var(--mj-text-primary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.at-tax-recent-weight {\n font-size: 0.68rem;\n font-weight: 600;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-sunken);\n padding: 2px 8px;\n border-radius: 10px;\n}\n\n.at-tax-recent-date {\n font-size: 0.65rem;\n color: var(--mj-text-muted);\n}\n\n/* \u2500\u2500 Health bar \u2500\u2500 */\n\n.at-tax-health-bar {\n display: flex;\n align-items: center;\n gap: 20px;\n padding: 12px 20px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 8px;\n margin-top: 16px;\n flex-wrap: wrap;\n}\n\n.at-tax-health-label {\n font-size: 0.72rem;\n font-weight: 600;\n color: var(--mj-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.04em;\n}\n\n.at-tax-health-stat {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 0.78rem;\n}\n\n.at-tax-dot {\n width: 10px;\n height: 10px;\n border-radius: 50%;\n}\n\n.at-tax-dot-total {\n background: var(--mj-text-secondary);\n}\n\n.at-tax-dot-healthy {\n background: var(--mj-status-success);\n}\n\n.at-tax-dot-attention {\n background: var(--mj-status-warning);\n}\n\n.at-tax-dot-orphaned {\n background: var(--mj-status-error);\n}\n\n.at-tax-dot-duplicates {\n background: var(--mj-status-info);\n}\n\n.at-tax-health-value {\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.at-tax-val-success {\n color: var(--mj-status-success);\n}\n\n.at-tax-val-warning {\n color: var(--mj-status-warning);\n}\n\n.at-tax-val-error {\n color: var(--mj-status-error);\n}\n\n.at-tax-val-info {\n color: var(--mj-status-info);\n}\n\n.at-tax-health-text {\n color: var(--mj-text-muted);\n}\n\n/* \u2550\u2550\u2550\u2550 Duplicates sub-tab \u2550\u2550\u2550\u2550 */\n\n.at-tax-dup-stats-bar {\n display: flex;\n gap: 24px;\n margin-bottom: 16px;\n align-items: center;\n}\n\n.at-tax-dup-stat {\n font-size: 0.78rem;\n color: var(--mj-text-secondary);\n}\n\n.at-tax-dup-stat strong {\n font-size: 1.1rem;\n color: var(--mj-text-primary);\n margin-right: 4px;\n}\n\n.at-tax-dup-high strong {\n color: var(--mj-status-error);\n}\n\n.at-tax-dup-moderate strong {\n color: var(--mj-status-warning);\n}\n\n.at-tax-dup-list {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.at-tax-dup-card {\n display: flex;\n align-items: center;\n gap: 16px;\n padding: 14px 20px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 8px;\n transition: border-color 0.15s;\n}\n\n.at-tax-dup-card:hover {\n border-color: var(--mj-brand-primary);\n}\n\n.at-tax-dup-card.at-tax-dup-high {\n border-left: 3px solid var(--mj-status-error);\n}\n\n.at-tax-dup-card.at-tax-dup-moderate {\n border-left: 3px solid var(--mj-status-warning);\n}\n\n.at-tax-dup-tag {\n font-size: 0.82rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n min-width: 120px;\n padding: 6px 12px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 6px;\n text-align: center;\n}\n\n.at-tax-dup-arrow {\n font-size: 0.82rem;\n color: var(--mj-text-muted);\n flex-shrink: 0;\n}\n\n.at-tax-dup-similarity {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 4px;\n min-width: 100px;\n}\n\n.at-tax-sim-bar-bg {\n width: 100%;\n height: 6px;\n background: var(--mj-border-default);\n border-radius: 3px;\n overflow: hidden;\n}\n\n.at-tax-sim-bar-fill {\n height: 100%;\n border-radius: 3px;\n transition: width 0.3s;\n}\n\n.at-tax-sim-bar-fill.high {\n background: var(--mj-status-error);\n}\n\n.at-tax-sim-bar-fill.moderate {\n background: var(--mj-status-warning);\n}\n\n.at-tax-sim-percent {\n font-size: 0.78rem;\n font-weight: 700;\n}\n\n.at-tax-sim-percent.high {\n color: var(--mj-status-error);\n}\n\n.at-tax-sim-percent.moderate {\n color: var(--mj-status-warning);\n}\n\n.at-tax-dup-actions {\n display: flex;\n gap: 6px;\n flex-shrink: 0;\n}\n\n.at-tax-dup-btn {\n padding: 5px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n background: var(--mj-bg-surface);\n font-size: 0.68rem;\n font-weight: 500;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.15s;\n white-space: nowrap;\n}\n\n.at-tax-dup-btn:hover {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n.at-tax-dup-btn-primary {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-color: var(--mj-brand-primary);\n}\n\n.at-tax-dup-btn-primary:hover {\n background: var(--mj-brand-primary-hover);\n color: var(--mj-text-inverse);\n}\n\n/* \u2550\u2550\u2550\u2550 Orphans sub-tab \u2550\u2550\u2550\u2550 */\n\n.at-tax-orphan-toolbar {\n display: flex;\n align-items: center;\n gap: 12px;\n margin-bottom: 16px;\n flex-wrap: wrap;\n}\n\n.at-tax-orphan-count {\n font-size: 0.82rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.at-tax-orphan-desc {\n font-size: 0.78rem;\n color: var(--mj-text-muted);\n}\n\n.at-tax-orphan-bulk {\n margin-left: auto;\n display: flex;\n gap: 8px;\n}\n\n.at-tax-bulk-btn {\n padding: 6px 14px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n background: var(--mj-bg-surface);\n font-size: 0.72rem;\n font-weight: 500;\n color: var(--mj-text-secondary);\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 5px;\n transition: all 0.15s;\n}\n\n.at-tax-bulk-btn:hover {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n.at-tax-bulk-danger:hover {\n border-color: var(--mj-status-error);\n color: var(--mj-status-error);\n}\n\n.at-tax-orphan-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));\n gap: 12px;\n}\n\n.at-tax-orphan-card {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 8px;\n padding: 16px;\n transition: all 0.15s;\n display: flex;\n flex-direction: column;\n gap: 10px;\n border-top: 3px solid var(--mj-status-error);\n}\n\n.at-tax-orphan-card:hover {\n border-color: var(--mj-brand-primary);\n}\n\n.at-tax-orphan-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n}\n\n.at-tax-orphan-name {\n font-size: 0.82rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.at-tax-orphan-checkbox {\n width: 16px;\n height: 16px;\n accent-color: var(--mj-brand-primary);\n}\n\n.at-tax-orphan-stats {\n display: flex;\n gap: 12px;\n font-size: 0.72rem;\n color: var(--mj-text-muted);\n}\n\n.at-tax-orphan-stats strong {\n color: var(--mj-text-secondary);\n}\n\n.at-tax-orphan-dates {\n display: flex;\n justify-content: space-between;\n font-size: 0.65rem;\n color: var(--mj-text-muted);\n}\n\n.at-tax-orphan-actions {\n display: flex;\n gap: 6px;\n margin-top: 4px;\n}\n\n.at-tax-orphan-btn {\n flex: 1;\n padding: 5px 8px;\n border: 1px solid var(--mj-border-default);\n border-radius: 5px;\n background: var(--mj-bg-surface);\n font-size: 0.68rem;\n font-weight: 500;\n color: var(--mj-text-secondary);\n cursor: pointer;\n text-align: center;\n transition: all 0.15s;\n}\n\n.at-tax-orphan-btn:hover {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n.at-tax-orphan-delete:hover {\n border-color: var(--mj-status-error);\n color: var(--mj-status-error);\n}\n\n/* \u2550\u2550\u2550\u2550 Treemap sub-tab \u2550\u2550\u2550\u2550 */\n\n.at-tax-treemap-kpi-strip {\n display: flex;\n gap: 20px;\n margin-bottom: 16px;\n flex-wrap: wrap;\n}\n\n.at-tax-treemap-kpi {\n padding: 10px 18px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 8px;\n display: flex;\n flex-direction: column;\n align-items: center;\n min-width: 120px;\n}\n\n.at-tax-treemap-kpi-value {\n font-size: 1.2rem;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.at-tax-treemap-kpi-label {\n font-size: 0.65rem;\n color: var(--mj-text-muted);\n margin-top: 2px;\n}\n\n.at-tax-treemap-container {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 10px;\n padding: 8px;\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));\n grid-auto-rows: 80px;\n gap: 4px;\n min-height: 340px;\n}\n\n.at-tax-treemap-cell {\n border-radius: 6px;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-inverse);\n font-weight: 600;\n font-size: 0.78rem;\n cursor: pointer;\n transition: all 0.15s;\n position: relative;\n overflow: hidden;\n}\n\n.at-tax-treemap-cell:hover {\n transform: scale(1.02);\n z-index: 2;\n}\n\n.at-tax-cell-name {\n font-size: 0.78rem;\n}\n\n.at-tax-cell-count {\n font-size: 0.65rem;\n opacity: 0.85;\n font-weight: 400;\n}\n\n/* Treemap color families */\n.at-tm-blue-1 { background: color-mix(in srgb, var(--mj-brand-primary) 90%, black); }\n.at-tm-blue-2 { background: var(--mj-brand-primary); }\n.at-tm-blue-3 { background: color-mix(in srgb, var(--mj-brand-primary) 75%, white); }\n.at-tm-blue-4 { background: color-mix(in srgb, var(--mj-brand-primary) 55%, white); }\n\n.at-tm-green-1 { background: color-mix(in srgb, var(--mj-status-success) 90%, black); }\n.at-tm-green-2 { background: var(--mj-status-success); }\n.at-tm-green-3 { background: color-mix(in srgb, var(--mj-status-success) 60%, white); color: var(--mj-text-primary); }\n\n.at-tm-purple-1 { background: color-mix(in srgb, var(--mj-status-info) 90%, black); }\n.at-tm-purple-2 { background: var(--mj-status-info); }\n.at-tm-purple-3 { background: color-mix(in srgb, var(--mj-status-info) 65%, white); }\n\n.at-tm-orange-1 { background: color-mix(in srgb, var(--mj-status-warning) 90%, black); }\n.at-tm-orange-2 { background: var(--mj-status-warning); }\n.at-tm-orange-3 { background: color-mix(in srgb, var(--mj-status-warning) 60%, white); color: var(--mj-text-primary); }\n\n/* \u2550\u2550\u2550\u2550 Audit Log sub-tab \u2550\u2550\u2550\u2550 */\n\n.at-tax-audit-filters {\n display: flex;\n align-items: center;\n gap: 16px;\n margin-bottom: 16px;\n padding: 12px 16px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 8px;\n flex-wrap: wrap;\n}\n\n.at-tax-audit-filter-label {\n font-size: 0.72rem;\n font-weight: 600;\n color: var(--mj-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.04em;\n}\n\n.at-tax-audit-checkbox-group {\n display: flex;\n gap: 12px;\n flex-wrap: wrap;\n}\n\n.at-tax-audit-checkbox {\n display: flex;\n align-items: center;\n gap: 4px;\n font-size: 0.72rem;\n color: var(--mj-text-secondary);\n cursor: pointer;\n}\n\n.at-tax-audit-checkbox input {\n accent-color: var(--mj-brand-primary);\n}\n\n.at-tax-audit-timeline {\n position: relative;\n padding-left: 32px;\n}\n\n.at-tax-audit-timeline::before {\n content: '';\n position: absolute;\n left: 14px;\n top: 0;\n bottom: 0;\n width: 2px;\n background: var(--mj-border-default);\n}\n\n.at-tax-audit-event {\n position: relative;\n padding: 10px 16px;\n margin-bottom: 4px;\n display: flex;\n align-items: flex-start;\n gap: 12px;\n border-radius: 8px;\n transition: background 0.1s;\n}\n\n.at-tax-audit-event:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.at-tax-audit-event-icon {\n width: 28px;\n height: 28px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 0.68rem;\n flex-shrink: 0;\n position: absolute;\n left: -32px;\n top: 10px;\n z-index: 1;\n}\n\n.at-tax-audit-event-icon.created {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.at-tax-audit-event-icon.merged {\n background: color-mix(in srgb, var(--mj-status-info) 15%, var(--mj-bg-surface));\n color: var(--mj-status-info);\n}\n\n.at-tax-audit-event-icon.moved {\n background: color-mix(in srgb, var(--mj-status-info) 15%, var(--mj-bg-surface));\n color: var(--mj-status-info);\n}\n\n.at-tax-audit-event-icon.deleted {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.at-tax-audit-event-icon.renamed {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.at-tax-audit-event-body {\n flex: 1;\n}\n\n.at-tax-audit-event-desc {\n font-size: 0.78rem;\n color: var(--mj-text-primary);\n line-height: 1.5;\n}\n\n.at-tax-tag-ref {\n background: var(--mj-bg-surface-sunken);\n padding: 1px 6px;\n border-radius: 4px;\n font-weight: 600;\n font-size: 0.72rem;\n border: 1px solid var(--mj-border-default);\n}\n\n.at-tax-audit-event-meta {\n font-size: 0.65rem;\n color: var(--mj-text-muted);\n margin-top: 2px;\n display: flex;\n gap: 12px;\n}\n\n/* \u2500\u2500 Taxonomy responsive \u2500\u2500 */\n\n@media (max-width: 1100px) {\n .at-tax-split-view {\n flex-direction: column;\n }\n\n .at-tax-tree-panel {\n width: 100%;\n max-height: 300px;\n border-right: none;\n border-bottom: 1px solid var(--mj-border-default);\n }\n\n .at-tax-details-panel {\n width: 100%;\n }\n}\n\n@media (max-width: 768px) {\n .at-tax-dup-card {\n flex-wrap: wrap;\n }\n\n .at-tax-orphan-grid {\n grid-template-columns: 1fr;\n }\n}\n\n/* \u2500\u2500 Pipeline Config Widget \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.at-config-card {\n margin-top: 12px;\n}\n\n.at-config-body {\n display: flex;\n flex-direction: column;\n gap: 10px;\n padding: 12px !important;\n}\n\n.at-config-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n}\n\n.at-config-label {\n font-size: 0.75rem;\n font-weight: 500;\n color: var(--mj-text-secondary);\n min-width: 90px;\n flex-shrink: 0;\n}\n\n.at-config-control {\n display: flex;\n align-items: center;\n gap: 6px;\n flex: 1;\n justify-content: flex-end;\n}\n\n.at-config-input {\n width: 70px;\n padding: 3px 6px;\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n font-size: 0.75rem;\n text-align: right;\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n}\n\n.at-config-input:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n}\n\n.at-config-slider {\n flex: 1;\n max-width: 100px;\n accent-color: var(--mj-brand-primary);\n height: 4px;\n}\n\n.at-config-value {\n font-size: 0.68rem;\n color: var(--mj-text-muted);\n min-width: 40px;\n text-align: right;\n}\n\n.at-config-divider {\n height: 1px;\n background: var(--mj-border-default);\n margin: 4px 0;\n}\n\n.at-config-section-label {\n font-size: 0.68rem;\n font-weight: 600;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.3px;\n}\n\n/* Toggle Switch */\n.at-config-toggle {\n position: relative;\n display: inline-block;\n cursor: pointer;\n}\n\n.at-config-toggle input {\n display: none;\n}\n\n.at-toggle-track {\n display: block;\n width: 32px;\n height: 18px;\n background: var(--mj-border-strong);\n border-radius: 9px;\n transition: background 0.2s ease;\n position: relative;\n}\n\n.at-config-toggle input:checked + .at-toggle-track {\n background: var(--mj-brand-primary);\n}\n\n.at-toggle-thumb {\n position: absolute;\n top: 2px;\n left: 2px;\n width: 14px;\n height: 14px;\n background: var(--mj-bg-surface);\n border-radius: 50%;\n transition: transform 0.2s ease;\n box-shadow: 0 1px 3px rgba(0,0,0,0.15);\n}\n\n.at-config-toggle input:checked + .at-toggle-track .at-toggle-thumb {\n transform: translateX(14px);\n}\n\n/* \u2500\u2500 Schedule Indicator on Source Cards \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.at-schedule-indicator {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 3px 10px;\n margin-top: 6px;\n border-radius: 12px;\n font-size: 0.68rem;\n font-weight: 600;\n color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 20%, var(--mj-border-default));\n cursor: pointer;\n transition: all 0.15s ease;\n width: fit-content;\n}\n\n.at-schedule-indicator i {\n font-size: 0.62rem;\n}\n\n.at-schedule-indicator:hover {\n background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n border-color: color-mix(in srgb, var(--mj-status-error) 30%, var(--mj-border-default));\n}\n\n/* Schedule button in source card actions */\n.at-source-schedule-btn:hover {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n/* \u2500\u2500 Schedule Dialog \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.at-schedule-overlay {\n position: fixed;\n inset: 0;\n z-index: 1000;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--mj-bg-overlay, rgba(0, 0, 0, 0.4));\n}\n\n.at-schedule-dialog {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg, 12px);\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.16);\n width: 420px;\n max-width: 90vw;\n}\n\n.at-schedule-dialog-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.at-schedule-dialog-header h3 {\n display: flex;\n align-items: center;\n gap: 8px;\n margin: 0;\n font-size: 15px;\n font-weight: 650;\n color: var(--mj-text-primary);\n}\n\n.at-schedule-dialog-header h3 i {\n color: var(--mj-brand-primary);\n}\n\n.at-schedule-dialog-close {\n background: none;\n border: none;\n cursor: pointer;\n color: var(--mj-text-muted);\n font-size: 16px;\n padding: 4px;\n line-height: 1;\n transition: color 0.15s;\n}\n\n.at-schedule-dialog-close:hover {\n color: var(--mj-text-primary);\n}\n\n.at-schedule-dialog-body {\n padding: 20px;\n display: flex;\n flex-direction: column;\n gap: 16px;\n}\n\n.at-schedule-field label {\n display: block;\n font-size: 11.5px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.04em;\n margin-bottom: 6px;\n}\n\n.at-schedule-source-name {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 13.5px;\n font-weight: 600;\n color: var(--mj-text-primary);\n padding: 8px 12px;\n background: var(--mj-bg-surface-card);\n border-radius: var(--mj-radius-sm, 6px);\n border: 1px solid var(--mj-border-subtle);\n}\n\n.at-schedule-source-name i {\n color: var(--mj-text-muted);\n}\n\n.at-schedule-action-name {\n font-size: 13px;\n color: var(--mj-text-secondary);\n padding: 8px 12px;\n background: var(--mj-bg-surface-card);\n border-radius: var(--mj-radius-sm, 6px);\n border: 1px solid var(--mj-border-subtle);\n}\n\n.at-schedule-cron-input {\n width: 100%;\n font-family: 'SF Mono', 'Fira Code', 'Consolas', monospace;\n font-size: 13px;\n letter-spacing: 0.02em;\n}\n\n.at-schedule-cron-preview {\n display: flex;\n align-items: center;\n gap: 6px;\n margin-top: 6px;\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.at-schedule-cron-preview i {\n font-size: 11px;\n color: var(--mj-brand-primary);\n}\n\n.at-schedule-toggle-row {\n display: flex;\n flex-direction: row;\n align-items: center;\n gap: 10px;\n}\n\n.at-schedule-toggle-row label {\n margin-bottom: 0;\n}\n\n.at-schedule-dialog-footer {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 14px 20px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550 D4: Status Badges for Content Items \u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.at-status-badge {\n display: inline-block;\n padding: 1px 6px;\n border-radius: 4px;\n font-size: 0.6rem;\n font-weight: 600;\n white-space: nowrap;\n letter-spacing: 0.02em;\n}\n\n.at-status-badge-complete {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success-text);\n}\n\n.at-status-badge-processing {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning-text);\n}\n\n.at-status-badge-failed {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error-text);\n}\n\n.at-status-badge-pending {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550 D4/D7: Source Detail Controls \u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.at-detail-section-header-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 8px;\n gap: 8px;\n flex-wrap: wrap;\n}\n\n.at-detail-section-controls {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.at-detail-filter-select {\n padding: 4px 8px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n font-size: 0.72rem;\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n cursor: pointer;\n}\n\n.at-retry-btn {\n font-size: 0.7rem !important;\n padding: 4px 8px !important;\n background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface)) !important;\n color: var(--mj-status-error-text) !important;\n border: 1px solid color-mix(in srgb, var(--mj-status-error) 20%, var(--mj-border-default)) !important;\n}\n\n.at-retry-btn:hover {\n background: color-mix(in srgb, var(--mj-status-error) 18%, var(--mj-bg-surface)) !important;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550 D7: Pagination \u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.at-detail-pagination {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 12px;\n padding: 10px 0 4px;\n border-top: 1px solid var(--mj-border-subtle);\n margin-top: 4px;\n}\n\n.at-page-btn {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 10px;\n font-size: 0.72rem;\n font-weight: 500;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.12s ease;\n}\n\n.at-page-btn:hover:not(:disabled) {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n.at-page-btn:disabled {\n opacity: 0.4;\n cursor: default;\n}\n\n.at-page-info {\n font-size: 0.72rem;\n color: var(--mj-text-muted);\n font-weight: 500;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550 Confirmation Dialog \u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.at-confirm-message {\n font-size: 13.5px;\n color: var(--mj-text-secondary);\n line-height: 1.5;\n margin: 0;\n}\n\n.at-danger-btn {\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n border: none;\n border-radius: var(--mj-radius-sm, 6px);\n padding: 7px 14px;\n font-size: 12.5px;\n font-weight: 600;\n cursor: pointer;\n transition: background 0.15s;\n}\n\n.at-danger-btn:hover {\n background: var(--mj-status-error-text);\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550 Treemap Drill-In \u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.at-tax-treemap-cell-clickable {\n cursor: pointer;\n transition: transform 0.15s, box-shadow 0.15s;\n}\n\n.at-tax-treemap-cell-clickable:hover {\n transform: scale(1.02);\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);\n z-index: 1;\n}\n\n.at-tax-drillin-overlay {\n position: fixed;\n inset: 0;\n z-index: 1000;\n display: flex;\n align-items: flex-start;\n justify-content: flex-end;\n background: var(--mj-bg-overlay, rgba(0, 0, 0, 0.4));\n}\n\n.at-tax-drillin-panel {\n background: var(--mj-bg-surface);\n border-left: 1px solid var(--mj-border-default);\n width: 420px;\n max-width: 90vw;\n height: 100vh;\n display: flex;\n flex-direction: column;\n box-shadow: -4px 0 24px rgba(0, 0, 0, 0.12);\n}\n\n.at-tax-drillin-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.at-tax-drillin-header h3 {\n display: flex;\n align-items: center;\n gap: 8px;\n margin: 0;\n font-size: 15px;\n font-weight: 650;\n color: var(--mj-text-primary);\n}\n\n.at-tax-drillin-header h3 i {\n color: var(--mj-brand-primary);\n}\n\n.at-tax-drillin-body {\n flex: 1;\n overflow-y: auto;\n padding: 20px;\n}\n\n.at-tax-drillin-footer {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 14px 20px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n/* D3/D8: Clickable run history rows */\n.at-run-row-clickable {\n cursor: pointer;\n transition: background 0.12s ease;\n}\n\n.at-run-row-clickable:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.at-run-row-selected {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface)) !important;\n border-left: 3px solid var(--mj-brand-primary);\n}\n\n/* D2: Error text in detail tables */\n.run-error-text {\n color: var(--mj-status-error);\n font-weight: 600;\n}\n\n/* \u2500\u2500 Content Item Duplicates Section (G3) \u2500\u2500 */\n\n.at-dedup-section {\n margin-top: 24px;\n border-top: 1px solid var(--mj-border-default);\n padding-top: 20px;\n}\n\n.at-dedup-header {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n margin-bottom: 16px;\n}\n\n.at-dedup-title {\n margin: 0;\n font-size: 1rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.at-dedup-subtitle {\n font-size: 0.78rem;\n color: var(--mj-text-muted);\n}\n\n.at-dedup-list {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.at-dedup-card {\n display: flex;\n align-items: center;\n gap: 16px;\n padding: 14px 16px;\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n background: var(--mj-bg-surface);\n transition: border-color 0.15s;\n}\n\n.at-dedup-card:hover {\n border-color: var(--mj-border-strong);\n}\n\n.at-dedup-pair {\n display: flex;\n align-items: center;\n gap: 12px;\n flex: 1;\n min-width: 0;\n}\n\n.at-dedup-item {\n display: flex;\n flex-direction: column;\n min-width: 0;\n flex: 1;\n}\n\n.at-dedup-item-name {\n font-size: 0.85rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.at-dedup-item-source {\n font-size: 0.72rem;\n color: var(--mj-text-muted);\n}\n\n.at-dedup-vs {\n color: var(--mj-text-muted);\n font-size: 0.75rem;\n flex-shrink: 0;\n}\n\n.at-dedup-meta {\n display: flex;\n flex-direction: column;\n align-items: flex-end;\n gap: 3px;\n flex-shrink: 0;\n}\n\n.at-dedup-score {\n font-size: 0.78rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.at-dedup-method {\n font-size: 0.65rem;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.3px;\n}\n\n.at-dedup-actions {\n display: flex;\n gap: 6px;\n flex-shrink: 0;\n}\n\n.at-dedup-confirm {\n font-size: 0.75rem !important;\n padding: 4px 10px !important;\n}\n\n.at-dedup-dismiss {\n font-size: 0.75rem !important;\n padding: 4px 10px !important;\n}\n\n.at-dedup-empty {\n text-align: center;\n padding: 32px 16px;\n color: var(--mj-text-muted);\n}\n\n.at-dedup-empty i {\n font-size: 1.5rem;\n margin-bottom: 8px;\n color: var(--mj-status-success);\n}\n\n.at-dedup-empty p {\n margin: 8px 0 0;\n font-size: 0.82rem;\n}\n"] }]
7958
+ args: [{ standalone: false, selector: 'app-autotagging-pipeline-resource', encapsulation: ViewEncapsulation.None, template: "<!-- Content Classification Dashboard -->\n<div class=\"at-dashboard\">\n\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550 LEFT NAV \u2550\u2550\u2550\u2550\u2550\u2550 -->\n <div class=\"at-left-nav\">\n <div class=\"at-left-nav-header\">\n <h2><i class=\"fa-solid fa-tags\"></i> Classify</h2>\n </div>\n <div class=\"at-left-nav-items\">\n @for (item of NavItems; track item.Tab) {\n <div class=\"at-nav-item\" [class.active]=\"ActiveTab === item.Tab\" (click)=\"SwitchTab(item.Tab)\">\n <i [class]=\"item.Icon\"></i> {{ item.Label }}\n @if (item.BadgeText) {\n <span class=\"at-nav-badge\" [class.at-nav-badge-live]=\"item.BadgeClass === 'nav-badge-live'\">{{ item.BadgeText }}</span>\n }\n </div>\n }\n <div class=\"at-nav-divider\"></div>\n <div class=\"at-nav-item\" [class.active]=\"ActiveTab === 'history'\" (click)=\"SwitchTab('history')\">\n <i class=\"fa-solid fa-clock-rotate-left\"></i> Run History\n </div>\n </div>\n <div class=\"at-left-nav-footer\">\n <button class=\"at-run-pipeline-btn\" (click)=\"RunPipeline()\" [disabled]=\"IsRunning\">\n @if (IsRunning) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Running...\n } @else {\n <i class=\"fa-solid fa-play\"></i> Run Pipeline\n }\n </button>\n </div>\n </div>\n\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550 MAIN AREA \u2550\u2550\u2550\u2550\u2550\u2550 -->\n <div class=\"at-main-area\">\n\n @if (IsLoading) {\n <div class=\"at-loading-overlay\">\n <mj-loading text=\"Loading autotagging data...\"></mj-loading>\n </div>\n }\n\n @if (!IsLoading) {\n\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n <!-- TAB 1: PIPELINE MONITOR -->\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n @if (ActiveTab === 'pipeline') {\n <div class=\"at-page-header\">\n <div>\n <div class=\"at-page-title\">Pipeline Monitor</div>\n <div class=\"at-page-subtitle\">Real-time processing status and recent activity</div>\n </div>\n <div class=\"at-page-actions\">\n <button class=\"at-action-btn at-secondary-btn\" (click)=\"LoadPipelineData()\">\n <i class=\"fa-solid fa-arrows-rotate\"></i> Refresh\n </button>\n </div>\n </div>\n <div class=\"at-page-body\">\n <!-- KPIs -->\n <div class=\"at-kpi-strip\">\n @for (kpi of KPIMetrics; track kpi.Label) {\n <div class=\"at-kpi-card\">\n <div class=\"at-kpi-value\" [class.at-kpi-error-value]=\"kpi.Label === 'Errors' && kpi.Value > 0\">{{ kpi.Value | number }}</div>\n <div class=\"at-kpi-label\">{{ kpi.Label }}</div>\n @if (kpi.Trend) {\n <div class=\"at-kpi-trend\" [class.up]=\"kpi.TrendUp\">\n @if (kpi.TrendUp) { <i class=\"fa-solid fa-arrow-up\"></i> }\n {{ kpi.Trend }}\n </div>\n }\n </div>\n }\n </div>\n\n <div class=\"at-pipeline-layout\">\n <div class=\"at-pipeline-center\">\n <!-- Pipeline stages visualization (only during active run) -->\n @if (PipelineStages.length > 0 && (IsRunning || IsPaused)) {\n <div class=\"at-pipeline-stages\">\n @for (stage of PipelineStages; track stage.Name; let last = $last) {\n <div class=\"at-pipeline-stage\"\n [class.stage-idle]=\"stage.Status === 'idle'\"\n [class.stage-active]=\"stage.Status === 'active'\"\n [class.stage-complete]=\"stage.Status === 'complete'\">\n <div class=\"at-pipeline-stage-icon\">\n @if (stage.Status === 'active') {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n } @else if (stage.Status === 'complete') {\n <i class=\"fa-solid fa-check\"></i>\n } @else {\n <i [class]=\"stage.Icon\"></i>\n }\n </div>\n <div class=\"at-pipeline-stage-name\">{{ stage.Name }}</div>\n </div>\n @if (!last) {\n <div class=\"at-stage-connector\"\n [class.connector-complete]=\"stage.Status === 'complete'\">\n </div>\n }\n }\n </div>\n }\n\n <!-- Progress bar (visible during run or paused) -->\n @if (IsRunning || IsPaused) {\n <div class=\"at-progress-section\">\n <div class=\"at-progress-header\">\n <span class=\"at-progress-stage-label\">{{ RunStage }}</span>\n <span class=\"at-progress-pct\">{{ RunProgress | number:'1.0-0' }}%</span>\n </div>\n <div class=\"at-progress-bar\"><div class=\"at-progress-fill\" [style.width.%]=\"RunProgress\" [class.at-progress-fill-paused]=\"IsPaused\"></div></div>\n @if (RunCurrentItem) {\n <div class=\"at-progress-current\">{{ RunCurrentItem }}</div>\n }\n <div class=\"at-pipeline-controls\">\n @if (IsRunning && !IsPaused) {\n <button class=\"at-action-btn at-secondary-btn\" (click)=\"PausePipeline()\" [disabled]=\"!CurrentProcessRunID\">\n <i class=\"fa-solid fa-pause\"></i> Pause\n </button>\n }\n @if (IsPaused) {\n <button class=\"at-action-btn at-primary-btn\" (click)=\"ResumePipeline()\">\n <i class=\"fa-solid fa-play\"></i> Resume\n </button>\n }\n <button class=\"at-action-btn at-danger-btn\" (click)=\"CancelPipeline()\">\n <i class=\"fa-solid fa-stop\"></i> Cancel\n </button>\n </div>\n </div>\n }\n\n <!-- D2: Live Per-Source Progress (visible during run) -->\n @if (IsRunning && LiveRunDetailRows.length > 0) {\n <div class=\"at-card\" style=\"margin-bottom: 12px;\">\n <div class=\"at-card-header\">\n <span class=\"at-card-title\"><i class=\"fa-solid fa-list-check\"></i> Per-Source Progress</span>\n <button class=\"at-action-btn at-secondary-btn\" style=\"font-size: 11px; padding: 3px 8px;\" (click)=\"LoadLiveRunDetails()\">\n <i class=\"fa-solid fa-arrows-rotate\"></i>\n </button>\n </div>\n <div class=\"at-card-body\" style=\"max-height: 200px; overflow-y: auto;\">\n <table class=\"at-run-table\">\n <thead>\n <tr>\n <th>Source</th>\n <th>Status</th>\n <th>Items</th>\n <th>Tagged</th>\n <th>Vectorized</th>\n <th>Errors</th>\n </tr>\n </thead>\n <tbody>\n @for (row of LiveRunDetailRows; track row.SourceName) {\n <tr>\n <td class=\"at-run-source-name\">{{ row.SourceName }}</td>\n <td>\n <span class=\"at-run-status-badge\" [class]=\"row.StatusClass\">\n @if (row.StatusClass === 'running') {\n <i class=\"fa-solid fa-spinner fa-spin\" style=\"font-size: 0.55rem\"></i>\n }\n {{ row.Status }}\n </span>\n </td>\n <td>{{ row.ItemsProcessed }}</td>\n <td>{{ row.ItemsTagged }}</td>\n <td>{{ row.ItemsVectorized }}</td>\n <td [class.run-error-text]=\"row.ErrorCount > 0\">{{ row.ErrorCount }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n </div>\n }\n\n <!-- Recent Processing Feed -->\n <div class=\"at-card at-feed-card\">\n <div class=\"at-card-header\">\n <span class=\"at-card-title\"><i class=\"fa-solid fa-bolt\"></i> Recent Processing</span>\n <div class=\"at-feed-header-actions\">\n <button class=\"at-feed-sort-btn\" (click)=\"ToggleFeedSort()\"\n [title]=\"FeedSortOrder === 'newest' ? 'Showing newest first' : 'Showing oldest first'\">\n <i class=\"fa-solid\" [class.fa-arrow-down-short-wide]=\"FeedSortOrder === 'newest'\"\n [class.fa-arrow-up-short-wide]=\"FeedSortOrder === 'oldest'\"></i>\n {{ FeedSortOrder === 'newest' ? 'Newest' : 'Oldest' }}\n </button>\n <span class=\"at-feed-count\">{{ FilteredFeedItems.length }} items</span>\n </div>\n </div>\n <!-- Feed search bar -->\n <div class=\"at-feed-search-bar\">\n <i class=\"fa-solid fa-search at-feed-search-icon\"></i>\n <input type=\"text\"\n class=\"mj-input at-feed-search-input\"\n placeholder=\"Search items, sources, or tags...\"\n [(ngModel)]=\"FeedSearchQuery\"\n (input)=\"OnFeedSearchChange()\">\n @if (FeedSearchQuery) {\n <button class=\"at-feed-search-clear\" (click)=\"FeedSearchQuery = ''; OnFeedSearchChange()\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n }\n </div>\n <div class=\"at-card-body at-feed-scroll-body\">\n @if (FilteredFeedItems.length === 0) {\n <div class=\"at-empty-state\">\n <i class=\"fa-solid fa-inbox\"></i>\n @if (FeedSearchQuery) {\n <p>No items match \"{{ FeedSearchQuery }}\"</p>\n } @else {\n <p>No processed items yet.</p>\n }\n </div>\n }\n @for (item of PaginatedFeedItems; track item.Name + item.SourceName + item.TimeAgo) {\n <div class=\"at-feed-item at-feed-item-clickable\" (click)=\"OpenFeedItemDetail(GetFeedItemOriginalIndex(item))\">\n <div class=\"at-feed-status-dot\" [class]=\"item.Status\"></div>\n <div class=\"at-feed-item-content\">\n <span class=\"at-feed-item-name\">{{ item.Name }}</span>\n <span class=\"at-feed-item-source-label\">{{ item.SourceName }}</span>\n </div>\n <div class=\"at-feed-item-tags\">\n @for (tag of item.Tags; track tag) {\n <span class=\"at-feed-tag\">{{ tag }}</span>\n }\n </div>\n <span class=\"at-feed-item-time\">{{ item.TimeAgo }}</span>\n </div>\n }\n </div>\n <!-- Feed pagination -->\n @if (FeedTotalPages > 1) {\n <div class=\"at-feed-pagination\">\n <button class=\"at-action-btn at-secondary-btn\" [disabled]=\"FeedPage === 0\" (click)=\"FeedPrevPage()\">\n <i class=\"fa-solid fa-chevron-left\"></i>\n </button>\n <span class=\"at-feed-pagination-label\">Page {{ FeedPage + 1 }} of {{ FeedTotalPages }}</span>\n <button class=\"at-action-btn at-secondary-btn\" [disabled]=\"FeedPage >= FeedTotalPages - 1\" (click)=\"FeedNextPage()\">\n <i class=\"fa-solid fa-chevron-right\"></i>\n </button>\n </div>\n }\n </div>\n </div>\n\n <!-- Right sidebar -->\n <div class=\"at-pipeline-right\">\n <!-- Sources Quick List -->\n <div class=\"at-card\">\n <div class=\"at-card-header\">\n <span class=\"at-card-title\"><i class=\"fa-solid fa-database\"></i> Sources</span>\n </div>\n <div class=\"at-card-body\">\n @for (source of SourceMinis; track source.ID) {\n <div class=\"at-source-mini\">\n <div class=\"at-source-mini-icon\"><i [class]=\"source.Icon\"></i></div>\n <div class=\"at-source-mini-info\">\n <div class=\"at-source-mini-name\">{{ source.Name }}</div>\n <div class=\"at-source-mini-meta\">{{ source.Meta }}</div>\n </div>\n <div class=\"at-source-mini-status\" [class]=\"source.StatusClass\"></div>\n </div>\n }\n </div>\n </div>\n <!-- Trending Tags -->\n <div class=\"at-card at-tag-cloud-card\">\n <div class=\"at-card-title\" style=\"margin-bottom: 10px;\"><i class=\"fa-solid fa-chart-bar\"></i> Trending Tags</div>\n <div class=\"at-tag-cloud\">\n @for (tag of TrendingTags; track tag.Tag) {\n <span class=\"at-tag-pill\" [class]=\"tag.SizeClass\"\n [style.opacity]=\"0.4 + tag.AvgWeight * 0.6\"\n [title]=\"'Weight: ' + tag.AvgWeight.toFixed(2)\">{{ tag.Tag }}</span>\n }\n </div>\n </div>\n\n <!-- Pipeline Settings Widget -->\n <div class=\"at-card at-config-card\">\n <div class=\"at-card-header\" (click)=\"TogglePipelineConfig()\" style=\"cursor:pointer\">\n <span class=\"at-card-title\"><i class=\"fa-solid fa-sliders\"></i> Pipeline Settings</span>\n <i class=\"fa-solid\" [class.fa-chevron-down]=\"!ShowPipelineConfig\" [class.fa-chevron-up]=\"ShowPipelineConfig\" style=\"font-size:0.7rem; color:var(--mj-text-muted)\"></i>\n </div>\n @if (ShowPipelineConfig) {\n <div class=\"at-card-body at-config-body\">\n <div class=\"at-config-row\">\n <label class=\"at-config-label\">Batch Size</label>\n <div class=\"at-config-control\">\n <input type=\"number\" class=\"at-config-input\" min=\"10\" max=\"1000\" step=\"10\"\n [(ngModel)]=\"PipelineConfig.Pipeline!.BatchSize\">\n </div>\n </div>\n <div class=\"at-config-row\">\n <label class=\"at-config-label\">Throttle (ms)</label>\n <div class=\"at-config-control\">\n <input type=\"range\" class=\"at-config-slider\" min=\"0\" max=\"5000\" step=\"100\"\n [(ngModel)]=\"PipelineConfig.Pipeline!.DelayBetweenBatchesMs\">\n <span class=\"at-config-value\">{{ PipelineConfig.Pipeline!.DelayBetweenBatchesMs }}ms</span>\n </div>\n </div>\n <div class=\"at-config-row\">\n <label class=\"at-config-label\">Error Tolerance</label>\n <div class=\"at-config-control\">\n <input type=\"range\" class=\"at-config-slider\" min=\"5\" max=\"50\" step=\"5\"\n [(ngModel)]=\"PipelineConfig.Pipeline!.ErrorThresholdPercent\">\n <span class=\"at-config-value\">{{ PipelineConfig.Pipeline!.ErrorThresholdPercent }}%</span>\n </div>\n </div>\n <div class=\"at-config-row\">\n <label class=\"at-config-label\">Auto-resume</label>\n <div class=\"at-config-control\">\n <label class=\"at-config-toggle\">\n <input type=\"checkbox\" [(ngModel)]=\"PipelineConfig.Pipeline!.ResumeFromLastBatch\">\n <span class=\"at-toggle-track\"><span class=\"at-toggle-thumb\"></span></span>\n </label>\n </div>\n </div>\n <div class=\"at-config-divider\"></div>\n <div class=\"at-config-section-label\">LLM Rate Limits</div>\n <div class=\"at-config-row\">\n <label class=\"at-config-label\">Requests/min</label>\n <div class=\"at-config-control\">\n <input type=\"number\" class=\"at-config-input\" min=\"1\" max=\"500\"\n [(ngModel)]=\"PipelineConfig.RateLimits!.LLM!.RequestsPerMinute\">\n </div>\n </div>\n <div class=\"at-config-row\">\n <label class=\"at-config-label\">Tokens/min</label>\n <div class=\"at-config-control\">\n <input type=\"number\" class=\"at-config-input\" min=\"1000\" max=\"5000000\" step=\"10000\"\n [(ngModel)]=\"PipelineConfig.RateLimits!.LLM!.TokensPerMinute\">\n <span class=\"at-config-value\">{{ FormatTokenCount(PipelineConfig.RateLimits!.LLM!.TokensPerMinute ?? 0) }}</span>\n </div>\n </div>\n <div class=\"at-config-section-label\">Embedding Rate Limits</div>\n <div class=\"at-config-row\">\n <label class=\"at-config-label\">Requests/min</label>\n <div class=\"at-config-control\">\n <input type=\"number\" class=\"at-config-input\" min=\"1\" max=\"1000\"\n [(ngModel)]=\"PipelineConfig.RateLimits!.Embedding!.RequestsPerMinute\">\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n }\n\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n <!-- TAB 2: SOURCES -->\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n @if (ActiveTab === 'sources') {\n <div class=\"at-page-header\">\n <div>\n <div class=\"at-page-title\">Content Sources</div>\n <div class=\"at-page-subtitle\">Configure where content is ingested from</div>\n </div>\n <div class=\"at-page-actions\">\n <button class=\"at-action-btn at-primary-btn\" (click)=\"OpenAddSourceForm()\">\n <i class=\"fa-solid fa-plus\"></i> Add Source\n </button>\n </div>\n </div>\n <div class=\"at-page-body\">\n <div class=\"at-sources-grid\">\n @for (card of SourceCards; track card.ID) {\n <div class=\"at-source-card-full at-source-card-clickable\" (click)=\"OpenSourceDetail(card)\">\n <div class=\"at-source-card-header\">\n <div class=\"at-source-card-icon\"><i [class]=\"card.Icon\"></i></div>\n <div>\n <div class=\"at-source-card-title\">{{ card.Name }}</div>\n <div class=\"at-source-card-type\">{{ card.SourceTypeName }}@if (card.RequiresFileType) { \u00B7 {{ card.FileTypeName }}}</div>\n </div>\n <div class=\"at-source-card-status\" [class]=\"card.StatusClass\">\n <div class=\"at-source-mini-status\" [class]=\"card.StatusClass\"></div>\n {{ card.StatusLabel }}\n </div>\n </div>\n @if (card.URL) {\n <div class=\"at-source-card-url\">{{ card.URL }}</div>\n }\n <div class=\"at-source-card-stats\">\n <div class=\"at-source-stat\">\n <div class=\"at-source-stat-value\">{{ formatNumber(card.ItemCount) }}</div>\n <div class=\"at-source-stat-label\">Items</div>\n </div>\n <div class=\"at-source-stat\">\n <div class=\"at-source-stat-value\">{{ formatNumber(card.TagCount) }}</div>\n <div class=\"at-source-stat-label\">Tags</div>\n </div>\n <div class=\"at-source-stat\">\n <div class=\"at-source-stat-value\">{{ card.AvgTags }}</div>\n <div class=\"at-source-stat-label\">Avg Tags</div>\n </div>\n <div class=\"at-source-stat\">\n <div class=\"at-source-stat-value\">{{ card.LastRunAgo }}</div>\n <div class=\"at-source-stat-label\">Last Run</div>\n </div>\n </div>\n <!-- Schedule indicator -->\n @if (card.ScheduledActionID) {\n <div class=\"at-schedule-indicator\" (click)=\"RemoveSchedule(card); $event.stopPropagation()\" title=\"Click to remove schedule\">\n <i class=\"fa-regular fa-clock\"></i>\n <span>{{ GetScheduleLabel(card) }}</span>\n </div>\n }\n <div class=\"at-source-card-actions\">\n <button class=\"at-source-action-btn\" (click)=\"OpenEditSourceForm(card); $event.stopPropagation()\"><i class=\"fa-solid fa-pen\"></i> Edit</button>\n <button class=\"at-source-action-btn\" (click)=\"RunPipelineForSource(card.ID); $event.stopPropagation()\"><i class=\"fa-solid fa-play\"></i> Run</button>\n @if (!card.ScheduledActionID) {\n <button class=\"at-source-action-btn at-source-schedule-btn\" (click)=\"OpenScheduleDialog(card); $event.stopPropagation()\"><i class=\"fa-regular fa-clock\"></i> Schedule</button>\n }\n <button class=\"at-source-action-btn at-source-delete-btn\" (click)=\"DeleteSource(card); $event.stopPropagation()\"><i class=\"fa-solid fa-trash\"></i> Delete</button>\n </div>\n </div>\n }\n\n <!-- Add Source Card -->\n <div class=\"at-add-source-card\" (click)=\"OpenAddSourceForm()\">\n <i class=\"fa-solid fa-plus-circle\"></i>\n <span style=\"font-size: 0.85rem; font-weight: 600;\">Add Content Source</span>\n <span style=\"font-size: 0.72rem;\">Web, RSS, Email, Files, API</span>\n </div>\n </div>\n\n <!-- Content Item Duplicates Section -->\n <div class=\"at-dedup-section\">\n <div class=\"at-dedup-header\">\n <div>\n <h3 class=\"at-dedup-title\">\n <i class=\"fa-solid fa-clone\"></i>\n Content Duplicates\n </h3>\n <span class=\"at-dedup-subtitle\">Review detected duplicate content items across sources</span>\n </div>\n <button class=\"at-action-btn at-secondary-btn\" (click)=\"LoadContentDuplicates()\" [disabled]=\"IsLoadingDuplicates\">\n @if (IsLoadingDuplicates) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Loading...\n } @else {\n <i class=\"fa-solid fa-arrows-rotate\"></i> Load Duplicates\n }\n </button>\n </div>\n\n @if (ContentDuplicates.length > 0) {\n <div class=\"at-dedup-list\">\n @for (dup of ContentDuplicates; track dup.ID) {\n <div class=\"at-dedup-card\">\n <div class=\"at-dedup-pair\">\n <div class=\"at-dedup-item\">\n <span class=\"at-dedup-item-name\">{{ dup.ItemAName }}</span>\n <span class=\"at-dedup-item-source\">{{ dup.ItemASource }}</span>\n </div>\n <div class=\"at-dedup-vs\">\n <i class=\"fa-solid fa-arrows-left-right\"></i>\n </div>\n <div class=\"at-dedup-item\">\n <span class=\"at-dedup-item-name\">{{ dup.ItemBName }}</span>\n <span class=\"at-dedup-item-source\">{{ dup.ItemBSource }}</span>\n </div>\n </div>\n <div class=\"at-dedup-meta\">\n <span class=\"at-dedup-score\">{{ (dup.SimilarityScore * 100).toFixed(0) }}% match</span>\n <span class=\"at-dedup-method\">{{ dup.DetectionMethod }}</span>\n </div>\n <div class=\"at-dedup-actions\">\n <button class=\"at-action-btn at-primary-btn at-dedup-confirm\" (click)=\"ConfirmContentDuplicate(dup)\">\n <i class=\"fa-solid fa-check\"></i> Confirm\n </button>\n <button class=\"at-action-btn at-secondary-btn at-dedup-dismiss\" (click)=\"DismissContentDuplicate(dup)\">\n <i class=\"fa-solid fa-times\"></i> Dismiss\n </button>\n </div>\n </div>\n }\n </div>\n } @else if (!IsLoadingDuplicates) {\n <div class=\"at-dedup-empty\">\n <i class=\"fa-solid fa-check-circle\"></i>\n <p>No pending duplicates. Click \"Load Duplicates\" to check.</p>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n <!-- TAB 3: CONTENT TYPES -->\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n @if (ActiveTab === 'types') {\n <div class=\"at-page-header\">\n <div>\n <div class=\"at-page-title\">Content Types</div>\n <div class=\"at-page-subtitle\">Configure AI tagging rules per content category</div>\n </div>\n <div class=\"at-page-actions\">\n <button class=\"at-action-btn at-primary-btn\" (click)=\"OpenAddTypeForm()\">\n <i class=\"fa-solid fa-plus\"></i> Add Type\n </button>\n </div>\n </div>\n <div class=\"at-page-body\">\n <div class=\"at-ct-grid\">\n @for (card of ContentTypeCards; track card.ID) {\n <div class=\"at-ct-card\">\n <div class=\"at-ct-card-header\">\n <span class=\"at-ct-card-name\">{{ card.Name }}</span>\n <span class=\"at-ct-card-model\">{{ card.AIModelName }}</span>\n </div>\n <div class=\"at-ct-field\">\n <span class=\"at-ct-field-label\">Description</span>\n <span class=\"at-ct-field-value\">{{ card.Description || '\\u2014' }}</span>\n </div>\n <div class=\"at-ct-field\">\n <span class=\"at-ct-field-label\">Sources Using</span>\n <span class=\"at-ct-field-value\">{{ card.SourcesUsing }}</span>\n </div>\n <div class=\"at-ct-field\">\n <span class=\"at-ct-field-label\">Items Tagged</span>\n <span class=\"at-ct-field-value\">{{ formatNumber(card.ItemsTagged) }}</span>\n </div>\n <div class=\"at-ct-tag-range\">\n <i class=\"fa-solid fa-tags\"></i>\n <span>{{ card.MinTags }}</span>\n <div class=\"at-ct-tag-range-bar\">\n <div class=\"at-ct-tag-range-fill\" [style.left.%]=\"card.RangeLeftPct\" [style.right.%]=\"card.RangeRightPct\"></div>\n </div>\n <span>{{ card.MaxTags }}</span>\n <span class=\"at-ct-range-suffix\">tags/item</span>\n </div>\n <div class=\"at-source-card-actions\" style=\"margin-top: 10px;\">\n <button class=\"at-source-action-btn\" (click)=\"OpenEditTypeForm(card)\"><i class=\"fa-solid fa-pen\"></i> Edit</button>\n </div>\n </div>\n }\n <!-- Add Content Type Card -->\n <div class=\"at-add-type-card\" (click)=\"OpenAddTypeForm()\">\n <i class=\"fa-solid fa-plus-circle\"></i>\n <span style=\"font-size: 0.85rem; font-weight: 600;\">Add Content Type</span>\n <span style=\"font-size: 0.72rem;\">Configure tagging rules</span>\n </div>\n </div>\n </div>\n }\n\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n <!-- TAB 4: TAG LIBRARY -->\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n @if (ActiveTab === 'tags') {\n <div class=\"at-page-header\">\n <div>\n <div class=\"at-page-title\">Tag Library</div>\n <div class=\"at-page-subtitle\">{{ TagRows.length }} unique tags across all content sources</div>\n </div>\n <div class=\"at-page-actions\">\n <input type=\"text\" class=\"at-search-input\" placeholder=\"Search tags...\"\n [(ngModel)]=\"TagSearchQuery\" (input)=\"FilterTags()\">\n </div>\n </div>\n <div class=\"at-page-body\">\n <div class=\"at-tag-lib-layout\">\n <div class=\"at-tag-lib-main\">\n <div class=\"at-card\">\n <div class=\"at-card-body\" style=\"max-height: 500px; overflow-y: auto;\">\n <table class=\"at-tag-table\">\n <thead>\n <tr>\n <th>Tag</th>\n <th>Count</th>\n <th>Avg Weight</th>\n <th>Distribution</th>\n <th>Top Source</th>\n <th>First Seen</th>\n </tr>\n </thead>\n <tbody>\n @for (row of FilteredTagRows; track row.Tag) {\n <tr class=\"at-tag-row-clickable\" (click)=\"DrillDownTag(row.Tag)\"\n [class.at-tag-row-selected]=\"SelectedDrillDownTag === row.Tag\">\n <td class=\"at-tag-name-cell\">{{ row.Tag }}</td>\n <td>{{ row.UsageCount }}</td>\n <td>\n <div class=\"at-weight-indicator\">\n <div class=\"at-weight-bar\">\n <div class=\"at-weight-bar-fill\" [style.width.%]=\"row.AvgWeight * 100\"\n [class.at-weight-high]=\"row.AvgWeight >= 0.7\"\n [class.at-weight-medium]=\"row.AvgWeight >= 0.4 && row.AvgWeight < 0.7\"\n [class.at-weight-low]=\"row.AvgWeight < 0.4\"></div>\n </div>\n <span class=\"at-weight-value\">{{ row.AvgWeight.toFixed(2) }}</span>\n </div>\n </td>\n <td>\n <div class=\"at-tag-bar\">\n <div class=\"at-tag-bar-fill\" [style.width.%]=\"row.BarWidthPct\"></div>\n </div>\n </td>\n <td>{{ row.TopSource }}</td>\n <td>{{ row.FirstSeen }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n </div>\n\n <!-- Tag drill-down: content items matching selected tag -->\n @if (SelectedDrillDownTag) {\n <div class=\"at-card\" style=\"margin-top: 12px;\">\n <div class=\"at-card-header\">\n <span class=\"at-card-title\">\n <i class=\"fa-solid fa-tag\"></i>\n Content items tagged \"{{ SelectedDrillDownTag }}\"\n ({{ TagDrillDownItems.length }})\n </span>\n <button class=\"at-slide-close\" (click)=\"CloseDrillDownTag()\" style=\"background:none;border:none;cursor:pointer;color:var(--mj-text-muted)\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n <div class=\"at-card-body\" style=\"max-height: 300px; overflow-y: auto;\">\n @if (TagDrillDownItems.length === 0) {\n <div class=\"at-empty-state\"><p>No content items found for this tag.</p></div>\n } @else {\n <table class=\"at-tag-table\">\n <thead>\n <tr>\n <th>Name</th>\n <th>Source</th>\n <th>Weight</th>\n <th>Updated</th>\n </tr>\n </thead>\n <tbody>\n @for (di of TagDrillDownItems; track di.ID) {\n <tr class=\"at-tag-row-clickable\" (click)=\"OpenItemDetailByID(di.ID)\">\n <td>{{ di.Name }}</td>\n <td>{{ di.SourceName }}</td>\n <td>{{ FormatWeight(di.Weight) }}</td>\n <td>{{ di.UpdatedAt }}</td>\n </tr>\n }\n </tbody>\n </table>\n }\n </div>\n </div>\n }\n </div>\n <div class=\"at-tag-lib-sidebar\">\n <div class=\"at-card at-tag-cloud-card\">\n <div class=\"at-card-title\" style=\"margin-bottom: 12px;\"><i class=\"fa-solid fa-cloud\"></i> Tag Cloud</div>\n @if (TagCloudWordItems.length > 0) {\n <mj-word-cloud\n [Items]=\"TagCloudWordItems\"\n [MaxFontSize]=\"40\"\n [MinFontSize]=\"12\"\n [MaxItems]=\"20\"\n Layout=\"spiral\"\n ColorMode=\"weight-gradient\"\n [Interactive]=\"true\"\n [Animate]=\"true\">\n </mj-word-cloud>\n } @else {\n <div class=\"at-tag-cloud-empty\">No tags yet</div>\n }\n </div>\n <div class=\"at-card\" style=\"padding: 16px; margin-top: 12px;\">\n <div class=\"at-card-title\" style=\"margin-bottom: 10px;\"><i class=\"fa-solid fa-chart-pie\"></i> By Source</div>\n <div class=\"at-tags-by-source\">\n @for (s of TagsBySource; track s.SourceName) {\n <div class=\"at-tag-source-row\">\n <span>{{ s.SourceName }}</span>\n <strong>{{ s.Count }}</strong>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n <!-- TAB 6: TAXONOMY GOVERNANCE -->\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n @if (ActiveTab === 'taxonomy') {\n <div class=\"at-page-header\">\n <div>\n <div class=\"at-page-title\">Taxonomy Governance</div>\n <div class=\"at-page-subtitle\">Manage tag hierarchy, resolve duplicates, and monitor taxonomy health &mdash; <strong>{{ TaxHealth.Total }} total tags</strong></div>\n </div>\n <div class=\"at-page-actions\">\n <button class=\"at-action-btn at-secondary-btn\" (click)=\"RefreshTaxonomyData()\">\n <i class=\"fa-solid fa-arrows-rotate\"></i> Refresh\n </button>\n </div>\n </div>\n\n <!-- Sub-tab strip -->\n <div class=\"at-tax-tab-strip\">\n <div class=\"at-tax-tab\" [class.active]=\"TaxSubTab === 'tree'\" (click)=\"SwitchTaxSubTab('tree')\">\n <i class=\"fa-solid fa-sitemap\"></i> Tree View\n </div>\n <div class=\"at-tax-tab\" [class.active]=\"TaxSubTab === 'duplicates'\" (click)=\"SwitchTaxSubTab('duplicates')\">\n <i class=\"fa-solid fa-link\"></i> Duplicates\n @if (TaxDuplicates.length > 0) {\n <span class=\"at-tax-tab-badge at-tax-badge-warning\">{{ TaxDuplicates.length }}</span>\n }\n </div>\n <div class=\"at-tax-tab\" [class.active]=\"TaxSubTab === 'orphans'\" (click)=\"SwitchTaxSubTab('orphans')\">\n <i class=\"fa-solid fa-ban\"></i> Orphans\n @if (TaxOrphans.length > 0) {\n <span class=\"at-tax-tab-badge at-tax-badge-error\">{{ TaxOrphans.length }}</span>\n }\n </div>\n <div class=\"at-tax-tab\" [class.active]=\"TaxSubTab === 'treemap'\" (click)=\"SwitchTaxSubTab('treemap')\">\n <i class=\"fa-solid fa-chart-tree-map\"></i> Treemap\n </div>\n <div class=\"at-tax-tab\" [class.active]=\"TaxSubTab === 'audit'\" (click)=\"SwitchTaxSubTab('audit')\">\n <i class=\"fa-solid fa-scroll\"></i> Audit Log\n </div>\n </div>\n\n <div class=\"at-page-body\">\n\n <!-- \u2550\u2550 SUB-TAB 1: TREE VIEW \u2550\u2550 -->\n @if (TaxSubTab === 'tree') {\n <div class=\"at-tax-split-view\">\n <!-- Tree panel -->\n <div class=\"at-tax-tree-panel\" style=\"position: relative;\">\n <div class=\"at-tax-tree-toolbar\">\n <input type=\"text\" class=\"at-search-input\" style=\"flex: 1;\" placeholder=\"Search tags...\"\n [(ngModel)]=\"TaxTreeSearch\" (input)=\"FilterTaxTree()\">\n <button class=\"at-tax-toolbar-btn\" title=\"Add root tag\" (click)=\"OpenCreateRootTag()\">\n <i class=\"fa-solid fa-plus\"></i>\n </button>\n <button class=\"at-tax-toolbar-btn\" [class.active]=\"TaxMultiSelectMode\"\n title=\"Toggle multi-select for drag reparenting\" (click)=\"ToggleMultiSelectMode()\">\n <i class=\"fa-solid fa-check-double\"></i>\n </button>\n </div>\n <div class=\"at-tax-tree-body\"\n (dragover)=\"$event.preventDefault()\"\n (drop)=\"OnDropToRoot($event)\">\n @if (TaxFilteredNodes.length === 0) {\n <div class=\"at-empty-state\">\n <i class=\"fa-solid fa-sitemap\"></i>\n <p>No tags found</p>\n </div>\n }\n @for (node of TaxFilteredNodes; track node.ID) {\n <div class=\"at-tax-tree-node\"\n [class.at-tax-node-selected]=\"node.IsSelected\"\n [class.at-tax-node-drag-over]=\"TaxDragOverNodeID === node.ID\"\n [class.at-tax-node-multi-selected]=\"IsNodeMultiSelected(node.ID)\"\n [style.padding-left.px]=\"16 + node.Depth * 20\"\n [attr.draggable]=\"true\"\n (dragstart)=\"OnTreeNodeDragStart($event, node)\"\n (dragover)=\"OnTreeNodeDragOver($event, node)\"\n (dragleave)=\"OnTreeNodeDragLeave()\"\n (drop)=\"OnTreeNodeDrop($event, node); $event.stopPropagation()\"\n (click)=\"SelectTaxNode(node)\">\n @if (TaxMultiSelectMode) {\n <input type=\"checkbox\" class=\"at-tax-tree-checkbox\"\n [checked]=\"IsNodeMultiSelected(node.ID)\"\n (click)=\"ToggleNodeSelection(node, $event)\">\n }\n <span class=\"at-tax-tree-arrow\"\n [class.at-tax-arrow-expanded]=\"node.IsExpanded && node.Children.length > 0\"\n [class.at-tax-arrow-collapsed]=\"!node.IsExpanded && node.Children.length > 0\"\n [class.at-tax-arrow-leaf]=\"node.Children.length === 0\"\n (click)=\"ToggleTaxNode(node); $event.stopPropagation()\"></span>\n <span class=\"at-tax-health-dot\" [class]=\"node.HealthColor\"></span>\n <span class=\"at-tax-tree-label\" [class.at-tax-tree-label-selected]=\"node.IsSelected\">{{ node.Name }}</span>\n <span class=\"at-tax-tree-count\">({{ node.ItemCount }})</span>\n <span class=\"at-tax-tree-add-child\" title=\"Add child tag\"\n (click)=\"OpenCreateChildTagFor(node); $event.stopPropagation()\">\n <i class=\"fa-solid fa-plus\"></i>\n </span>\n </div>\n }\n </div>\n @if (TaxTreeSaving) {\n <div class=\"at-tax-tree-saving-overlay\">\n <mj-loading text=\"Moving tags...\" size=\"small\"></mj-loading>\n </div>\n }\n </div>\n\n <!-- Details panel -->\n <div class=\"at-tax-details-panel\">\n @if (TaxSelectedNode) {\n <div class=\"at-tax-details-header\">\n <!-- Breadcrumb -->\n <div class=\"at-tax-breadcrumb\">\n @for (bc of GetTaxBreadcrumb(TaxSelectedNode); track bc.ID) {\n <span class=\"at-tax-bc-link\" (click)=\"NavigateToBreadcrumb(bc.ID)\">{{ bc.Name }}</span>\n <span class=\"at-tax-bc-sep\">&rsaquo;</span>\n }\n <span class=\"at-tax-bc-current\">{{ TaxSelectedNode.Name }}</span>\n </div>\n\n @if (!TaxIsEditing) {\n <div class=\"at-tax-details-title\">\n {{ TaxSelectedNode.DisplayName }}\n <span class=\"at-tax-edit-icon\" (click)=\"StartEditTag()\" title=\"Edit name\">\n <i class=\"fa-solid fa-pen\"></i>\n </span>\n </div>\n @if (TaxSelectedNode.Description) {\n <div class=\"at-tax-details-desc\">{{ TaxSelectedNode.Description }}</div>\n }\n } @else {\n <div class=\"at-tax-edit-form\">\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">Name</label>\n <input type=\"text\" class=\"at-form-input\" [(ngModel)]=\"TaxEditName\">\n </div>\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">Description</label>\n <textarea class=\"at-form-textarea\" rows=\"3\" [(ngModel)]=\"TaxEditDescription\"></textarea>\n </div>\n <div class=\"at-form-actions\">\n <button class=\"at-action-btn at-primary-btn\" (click)=\"SaveEditTag()\">Save</button>\n <button class=\"at-action-btn at-secondary-btn\" (click)=\"CancelEditTag()\">Cancel</button>\n </div>\n </div>\n }\n </div>\n\n <!-- Stats row -->\n <div class=\"at-tax-stats-row\">\n <div class=\"at-tax-stat-item\">\n <div class=\"at-tax-stat-value\">{{ TaxSelectedNode.ItemCount }}</div>\n <div class=\"at-tax-stat-label\">Items Tagged</div>\n </div>\n <div class=\"at-tax-stat-item\">\n <div class=\"at-tax-stat-value\">{{ TaxSelectedNode.AvgWeight.toFixed(2) }}</div>\n <div class=\"at-tax-stat-label\">Avg Weight</div>\n </div>\n <div class=\"at-tax-stat-item\">\n <div class=\"at-tax-stat-value\">{{ TaxSelectedNode.Children.length }}</div>\n <div class=\"at-tax-stat-label\">Children</div>\n </div>\n <div class=\"at-tax-stat-item\">\n <div class=\"at-tax-stat-value\">{{ TaxSelectedNode.Depth }}</div>\n <div class=\"at-tax-stat-label\">Depth</div>\n </div>\n <div class=\"at-tax-stat-item\">\n <div class=\"at-tax-stat-value at-tax-stat-date\">{{ TaxSelectedNode.FirstSeen }}</div>\n <div class=\"at-tax-stat-label\">First Seen</div>\n </div>\n </div>\n\n <!-- Action toolbar -->\n @if (!TaxIsEditing) {\n <div class=\"at-tax-action-toolbar\">\n <button class=\"at-tax-action-btn\" (click)=\"OpenCreateChildTag()\"><i class=\"fa-solid fa-plus\"></i> Add Child</button>\n <button class=\"at-tax-action-btn\" (click)=\"StartEditTag()\"><i class=\"fa-solid fa-pen\"></i> Rename</button>\n <button class=\"at-tax-action-btn\" (click)=\"OpenMoveDialog(TaxSelectedNode)\"><i class=\"fa-solid fa-arrows-up-down\"></i> Move</button>\n <button class=\"at-tax-action-btn\" (click)=\"OpenMergeIntoDialog(TaxSelectedNode)\"><i class=\"fa-solid fa-compress\"></i> Merge Into...</button>\n <button class=\"at-tax-action-btn\" (click)=\"OpenSplitDialog(TaxSelectedNode)\"><i class=\"fa-solid fa-code-branch\"></i> Split</button>\n <button class=\"at-tax-action-btn at-tax-action-danger\" (click)=\"DeleteTag(TaxSelectedNode)\"><i class=\"fa-solid fa-trash\"></i> Delete</button>\n </div>\n }\n\n <!-- Child tags -->\n @if (TaxSelectedNode.Children.length > 0) {\n <div class=\"at-tax-detail-section\">\n <div class=\"at-tax-section-title\">Child Tags</div>\n <div class=\"at-tax-child-chips\">\n @for (child of TaxSelectedNode.Children; track child.ID) {\n <span class=\"at-tax-child-chip\" (click)=\"SelectTaxNode(child)\">\n {{ child.Name }}\n <span class=\"at-tax-chip-count\">{{ child.ItemCount }}</span>\n </span>\n }\n </div>\n </div>\n }\n\n <!-- Recently tagged items -->\n @if (TaxRecentItems.length > 0) {\n <div class=\"at-tax-detail-section\">\n <div class=\"at-tax-section-title\">Recently Tagged Items</div>\n <div class=\"at-tax-recent-list\">\n @for (item of TaxRecentItems; track $index) {\n <div class=\"at-tax-recent-item\">\n <div class=\"at-tax-recent-icon\"><i [class]=\"item.Icon\"></i></div>\n <div class=\"at-tax-recent-name\">{{ item.Name }}</div>\n <div class=\"at-tax-recent-weight\">{{ item.Weight.toFixed(2) }}</div>\n <div class=\"at-tax-recent-date\">{{ item.Date }}</div>\n </div>\n }\n </div>\n </div>\n }\n } @else {\n <div class=\"at-empty-state\" style=\"height: 100%;\">\n <i class=\"fa-solid fa-hand-pointer\"></i>\n <p>Select a tag from the tree to view details</p>\n </div>\n }\n </div>\n </div>\n\n <!-- Health bar -->\n <div class=\"at-tax-health-bar\">\n <span class=\"at-tax-health-label\">Taxonomy Health</span>\n <div class=\"at-tax-health-stat\">\n <span class=\"at-tax-dot at-tax-dot-total\"></span>\n <span class=\"at-tax-health-value\">{{ TaxHealth.Total }}</span>\n <span class=\"at-tax-health-text\">Total</span>\n </div>\n <div class=\"at-tax-health-stat\">\n <span class=\"at-tax-dot at-tax-dot-healthy\"></span>\n <span class=\"at-tax-health-value at-tax-val-success\">{{ TaxHealth.Healthy }}</span>\n <span class=\"at-tax-health-text\">Healthy</span>\n </div>\n <div class=\"at-tax-health-stat\">\n <span class=\"at-tax-dot at-tax-dot-attention\"></span>\n <span class=\"at-tax-health-value at-tax-val-warning\">{{ TaxHealth.NeedAttention }}</span>\n <span class=\"at-tax-health-text\">Need Attention</span>\n </div>\n <div class=\"at-tax-health-stat\">\n <span class=\"at-tax-dot at-tax-dot-orphaned\"></span>\n <span class=\"at-tax-health-value at-tax-val-error\">{{ TaxHealth.Orphaned }}</span>\n <span class=\"at-tax-health-text\">Orphaned</span>\n </div>\n <div class=\"at-tax-health-stat\">\n <span class=\"at-tax-dot at-tax-dot-duplicates\"></span>\n <span class=\"at-tax-health-value at-tax-val-info\">{{ TaxHealth.Duplicates }}</span>\n <span class=\"at-tax-health-text\">Duplicate Candidates</span>\n </div>\n </div>\n }\n\n <!-- \u2550\u2550 SUB-TAB 2: DUPLICATES \u2550\u2550 -->\n @if (TaxSubTab === 'duplicates') {\n <div class=\"at-tax-dup-stats-bar\">\n <div class=\"at-tax-dup-stat\"><strong>{{ TaxDuplicates.length }}</strong> candidates found</div>\n <div class=\"at-tax-dup-stat at-tax-dup-high\"><strong>{{ TaxHighConfidenceDupeCount }}</strong> high confidence (&gt;85%)</div>\n <div class=\"at-tax-dup-stat at-tax-dup-moderate\"><strong>{{ TaxModerateDupeCount }}</strong> moderate (70-85%)</div>\n </div>\n\n @if (TaxDuplicates.length === 0) {\n <div class=\"at-empty-state\">\n <i class=\"fa-solid fa-check-circle\"></i>\n <p>No duplicate tags detected</p>\n </div>\n }\n\n <div class=\"at-tax-dup-list\">\n @for (pair of TaxDuplicates; track $index) {\n <div class=\"at-tax-dup-card\" [class.at-tax-dup-high]=\"pair.SeverityClass === 'high'\" [class.at-tax-dup-moderate]=\"pair.SeverityClass === 'moderate'\">\n @if (pair.IsExactDuplicate) {\n <!-- Exact-name duplicates: show single tag name with count -->\n <div class=\"at-tax-dup-tag\">{{ pair.TagA }}</div>\n <div class=\"at-tax-dup-similarity\">\n <span class=\"at-tax-sim-percent high\">\n <i class=\"fa-solid fa-clone\"></i>&nbsp;{{ pair.ExactDuplicateCount }} identical records\n </span>\n </div>\n <div class=\"at-tax-dup-actions\">\n <button class=\"at-tax-dup-btn at-tax-dup-btn-primary\" (click)=\"MergeTags(pair.TagAID, pair.TagBID, pair.TagA, pair.TagB)\" [disabled]=\"IsMerging\">@if (IsMerging) { <i class=\"fa-solid fa-spinner fa-spin\"></i> Merging... } @else { Merge }</button>\n <button class=\"at-tax-dup-btn\" (click)=\"DismissDuplicate(pair)\">Dismiss</button>\n </div>\n } @else {\n <!-- Similar (non-exact) pairs: show both tags with similarity -->\n <div class=\"at-tax-dup-tag\">{{ pair.TagA }}</div>\n <div class=\"at-tax-dup-arrow\"><i class=\"fa-solid fa-arrows-left-right\"></i></div>\n <div class=\"at-tax-dup-similarity\">\n <div class=\"at-tax-sim-bar-bg\">\n <div class=\"at-tax-sim-bar-fill\" [class]=\"pair.SeverityClass\" [style.width.%]=\"pair.Similarity\"></div>\n </div>\n <span class=\"at-tax-sim-percent\" [class]=\"pair.SeverityClass\">{{ pair.Similarity }}%</span>\n </div>\n <div class=\"at-tax-dup-arrow\"><i class=\"fa-solid fa-arrows-left-right\"></i></div>\n <div class=\"at-tax-dup-tag\">{{ pair.TagB }}</div>\n <div class=\"at-tax-dup-actions\">\n <button class=\"at-tax-dup-btn at-tax-dup-btn-primary\" (click)=\"MergeTags(pair.TagAID, pair.TagBID, pair.TagA, pair.TagB)\" [disabled]=\"IsMerging\">@if (IsMerging) { <i class=\"fa-solid fa-spinner fa-spin\"></i> Merging... } @else { Merge }</button>\n <button class=\"at-tax-dup-btn\" (click)=\"MakeChildTag(pair.TagAID, pair.TagBID)\">Make Child</button>\n <button class=\"at-tax-dup-btn\" (click)=\"DismissDuplicate(pair)\">Dismiss</button>\n </div>\n }\n </div>\n }\n </div>\n }\n\n <!-- \u2550\u2550 SUB-TAB 3: ORPHANS \u2550\u2550 -->\n @if (TaxSubTab === 'orphans') {\n <div class=\"at-tax-orphan-toolbar\">\n <span class=\"at-tax-orphan-count\">{{ TaxOrphans.length }} orphaned tags</span>\n <span class=\"at-tax-orphan-desc\">&mdash; no parent, no children, low usage</span>\n <div class=\"at-tax-orphan-bulk\">\n <button class=\"at-tax-bulk-btn\" (click)=\"ToggleAllOrphans()\">\n @if (TaxAllOrphansSelected) { <i class=\"fa-solid fa-square-check\"></i> } @else { <i class=\"fa-regular fa-square\"></i> }\n Select All\n </button>\n <button class=\"at-tax-bulk-btn at-tax-bulk-danger\" (click)=\"BulkDeleteOrphans()\">\n <i class=\"fa-solid fa-trash\"></i> Bulk Delete\n </button>\n <button class=\"at-tax-bulk-btn at-tax-bulk-danger\" (click)=\"DeleteAllOrphans()\">\n <i class=\"fa-solid fa-trash-can\"></i> Delete All ({{ TaxOrphans.length }})\n </button>\n </div>\n </div>\n\n @if (TaxOrphans.length === 0) {\n <div class=\"at-empty-state\">\n <i class=\"fa-solid fa-check-circle\"></i>\n <p>No orphaned tags</p>\n </div>\n }\n\n <div class=\"at-tax-orphan-grid\">\n @for (orphan of TaxOrphans; track orphan.ID) {\n <div class=\"at-tax-orphan-card\">\n <div class=\"at-tax-orphan-header\">\n <span class=\"at-tax-orphan-name\">{{ orphan.Name }}</span>\n <input type=\"checkbox\" class=\"at-tax-orphan-checkbox\" [checked]=\"orphan.IsSelected\"\n (change)=\"ToggleOrphanSelection(orphan)\" (click)=\"$event.stopPropagation()\">\n </div>\n <div class=\"at-tax-orphan-stats\">\n <span>Usage: <strong>{{ orphan.UsageCount }}</strong></span>\n <span>Avg Weight: <strong>{{ orphan.AvgWeight.toFixed(2) }}</strong></span>\n </div>\n <div class=\"at-tax-orphan-dates\">\n <span>First: {{ orphan.FirstSeen }}</span>\n <span>Last: {{ orphan.LastSeen }}</span>\n </div>\n <div class=\"at-tax-orphan-actions\">\n <button class=\"at-tax-orphan-btn at-tax-orphan-delete\" (click)=\"DeleteOrphan(orphan)\">Delete</button>\n <button class=\"at-tax-orphan-btn\">Ignore</button>\n </div>\n </div>\n }\n </div>\n }\n\n <!-- \u2550\u2550 SUB-TAB 4: TREEMAP \u2550\u2550 -->\n @if (TaxSubTab === 'treemap') {\n <div class=\"at-tax-treemap-kpi-strip\">\n @for (kpi of TaxTreemapKPIs; track kpi.Label) {\n <div class=\"at-tax-treemap-kpi\">\n <div class=\"at-tax-treemap-kpi-value\">{{ kpi.Value }}</div>\n <div class=\"at-tax-treemap-kpi-label\">{{ kpi.Label }}</div>\n </div>\n }\n </div>\n\n @if (TaxTreemapCells.length === 0) {\n <div class=\"at-empty-state\">\n <i class=\"fa-solid fa-chart-tree-map\"></i>\n <p>No taxonomy data to visualize</p>\n </div>\n } @else {\n <div class=\"at-tax-treemap-container\">\n @for (cell of TaxTreemapCells; track $index) {\n <div class=\"at-tax-treemap-cell at-tax-treemap-cell-clickable\" [class]=\"cell.ColorClass\"\n [style.grid-row]=\"cell.RowSpan > 1 ? 'span ' + cell.RowSpan : ''\"\n (click)=\"OpenTreemapDrillIn(cell)\">\n <span class=\"at-tax-cell-name\">{{ cell.Name }}</span>\n <span class=\"at-tax-cell-count\">{{ cell.ItemCount }} items</span>\n </div>\n }\n </div>\n }\n\n <!-- Treemap Drill-In Panel -->\n @if (ShowTreemapDrillIn && TreemapDrillInNode) {\n <div class=\"at-tax-drillin-overlay\" (click)=\"CloseTreemapDrillIn()\">\n <div class=\"at-tax-drillin-panel\" (click)=\"$event.stopPropagation()\">\n <div class=\"at-tax-drillin-header\">\n <h3><i class=\"fa-solid fa-tag\"></i> {{ TreemapDrillInNode.Name }}</h3>\n <button class=\"at-schedule-dialog-close\" (click)=\"CloseTreemapDrillIn()\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n <div class=\"at-tax-drillin-body\">\n <div class=\"at-tax-stats-row\">\n <div class=\"at-tax-stat-item\">\n <div class=\"at-tax-stat-value\">{{ TreemapDrillInNode.ItemCount }}</div>\n <div class=\"at-tax-stat-label\">Items Tagged</div>\n </div>\n <div class=\"at-tax-stat-item\">\n <div class=\"at-tax-stat-value\">{{ TreemapDrillInNode.AvgWeight.toFixed(2) }}</div>\n <div class=\"at-tax-stat-label\">Avg Weight</div>\n </div>\n <div class=\"at-tax-stat-item\">\n <div class=\"at-tax-stat-value\">{{ TreemapDrillInNode.Children.length }}</div>\n <div class=\"at-tax-stat-label\">Children</div>\n </div>\n </div>\n\n @if (TreemapDrillInNode.Children.length > 0) {\n <div class=\"at-tax-detail-section\">\n <div class=\"at-tax-section-title\">Child Tags</div>\n <div class=\"at-tax-child-chips\">\n @for (child of TreemapDrillInNode.Children; track child.ID) {\n <span class=\"at-tax-child-chip\">{{ child.Name }} <span class=\"at-tax-chip-count\">{{ child.ItemCount }}</span></span>\n }\n </div>\n </div>\n }\n\n @if (TaxRecentItems.length > 0) {\n <div class=\"at-tax-detail-section\">\n <div class=\"at-tax-section-title\">Recently Tagged Items</div>\n <div class=\"at-tax-recent-list\">\n @for (item of TaxRecentItems; track $index) {\n <div class=\"at-tax-recent-item\">\n <div class=\"at-tax-recent-icon\"><i [class]=\"item.Icon\"></i></div>\n <div class=\"at-tax-recent-name\">{{ item.Name }}</div>\n <div class=\"at-tax-recent-weight\">{{ item.Weight.toFixed(2) }}</div>\n <div class=\"at-tax-recent-date\">{{ item.Date }}</div>\n </div>\n }\n </div>\n </div>\n }\n </div>\n <div class=\"at-tax-drillin-footer\">\n <button class=\"at-action-btn at-secondary-btn\" (click)=\"DrillInToTreeView(TreemapDrillInNode)\">\n <i class=\"fa-solid fa-sitemap\"></i> View in Tree\n </button>\n </div>\n </div>\n </div>\n }\n }\n\n <!-- \u2550\u2550 SUB-TAB 5: AUDIT LOG \u2550\u2550 -->\n @if (TaxSubTab === 'audit') {\n <div class=\"at-tax-audit-filters\">\n <span class=\"at-tax-audit-filter-label\">Filter</span>\n <div class=\"at-tax-audit-checkbox-group\">\n <label class=\"at-tax-audit-checkbox\">\n <input type=\"checkbox\" [checked]=\"TaxAuditFilterTypes.has('created')\" (change)=\"ToggleTaxAuditFilter('created')\"> Created\n </label>\n <label class=\"at-tax-audit-checkbox\">\n <input type=\"checkbox\" [checked]=\"TaxAuditFilterTypes.has('merged')\" (change)=\"ToggleTaxAuditFilter('merged')\"> Merged\n </label>\n <label class=\"at-tax-audit-checkbox\">\n <input type=\"checkbox\" [checked]=\"TaxAuditFilterTypes.has('moved')\" (change)=\"ToggleTaxAuditFilter('moved')\"> Moved\n </label>\n <label class=\"at-tax-audit-checkbox\">\n <input type=\"checkbox\" [checked]=\"TaxAuditFilterTypes.has('deleted')\" (change)=\"ToggleTaxAuditFilter('deleted')\"> Deleted\n </label>\n <label class=\"at-tax-audit-checkbox\">\n <input type=\"checkbox\" [checked]=\"TaxAuditFilterTypes.has('renamed')\" (change)=\"ToggleTaxAuditFilter('renamed')\"> Renamed\n </label>\n <label class=\"at-tax-audit-checkbox\">\n <input type=\"checkbox\" [checked]=\"TaxAuditFilterTypes.has('deprecated')\" (change)=\"ToggleTaxAuditFilter('deprecated')\"> Deprecated\n </label>\n <label class=\"at-tax-audit-checkbox\">\n <input type=\"checkbox\" [checked]=\"TaxAuditFilterTypes.has('split')\" (change)=\"ToggleTaxAuditFilter('split')\"> Split\n </label>\n <label class=\"at-tax-audit-checkbox\">\n <input type=\"checkbox\" [checked]=\"TaxAuditFilterTypes.has('reactivated')\" (change)=\"ToggleTaxAuditFilter('reactivated')\"> Reactivated\n </label>\n </div>\n </div>\n\n @if (GetFilteredAuditEvents().length === 0) {\n <div class=\"at-empty-state\">\n <i class=\"fa-solid fa-scroll\"></i>\n <p>No audit events match the current filters</p>\n </div>\n }\n\n <div class=\"at-tax-audit-timeline\">\n @for (event of GetFilteredAuditEvents(); track $index) {\n <div class=\"at-tax-audit-event\">\n <div class=\"at-tax-audit-event-icon\" [class]=\"event.Type\">\n <i [class]=\"GetTaxAuditIcon(event.Type)\"></i>\n </div>\n <div class=\"at-tax-audit-event-body\">\n <div class=\"at-tax-audit-event-desc\">\n {{ event.Description }} <span class=\"at-tax-tag-ref\">{{ event.TagRef }}</span>\n </div>\n <div class=\"at-tax-audit-event-meta\">\n <span>{{ event.User }}</span>\n <span>{{ event.Timestamp }}</span>\n </div>\n </div>\n </div>\n }\n </div>\n }\n </div>\n }\n\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n <!-- TAB 7: RUN HISTORY -->\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n @if (ActiveTab === 'history') {\n <div class=\"at-page-header\">\n <div>\n <div class=\"at-page-title\">Run History</div>\n <div class=\"at-page-subtitle\">Processing run log across all content sources</div>\n </div>\n <div class=\"at-page-actions\">\n <select class=\"at-filter-select\" [(ngModel)]=\"HistorySourceFilter\" (change)=\"FilterRunHistory()\">\n <option value=\"\">All Sources</option>\n @for (s of HistorySourceOptions; track s) {\n <option [value]=\"s\">{{ s }}</option>\n }\n </select>\n <select class=\"at-filter-select\" [(ngModel)]=\"HistoryStatusFilter\" (change)=\"FilterRunHistory()\">\n <option value=\"\">All Status</option>\n <option value=\"complete\">Complete</option>\n <option value=\"failed\">Failed</option>\n <option value=\"running\">Running</option>\n </select>\n </div>\n </div>\n <div class=\"at-page-body\">\n <div class=\"at-card\">\n <div class=\"at-card-body\" style=\"max-height: 600px; overflow-y: auto;\">\n <table class=\"at-run-table\">\n <thead>\n <tr>\n <th>Status</th>\n <th>Source</th>\n <th>Started</th>\n <th>Duration</th>\n <th>Items</th>\n <th>Tags</th>\n <th>Errors</th>\n </tr>\n </thead>\n <tbody>\n @for (row of FilteredRunRows; track row.ID) {\n <tr class=\"at-run-row-clickable\"\n [class.at-run-row-selected]=\"SelectedRunID === row.ID\"\n (click)=\"OpenRunDetail(row.ID)\">\n <td>\n <span class=\"at-run-status-badge\" [class]=\"row.StatusClass\">\n @if (row.StatusClass === 'running') {\n <i class=\"fa-solid fa-spinner fa-spin\" style=\"font-size: 0.55rem\"></i>\n }\n {{ row.Status }}\n </span>\n </td>\n <td class=\"at-run-source-name\">{{ row.SourceName }}</td>\n <td>{{ row.StartedDisplay }}</td>\n <td class=\"at-run-duration\">{{ row.Duration }}</td>\n <td>{{ row.Items }}</td>\n <td>{{ row.Tags }}</td>\n <td [class]=\"row.ErrorClass\">{{ row.Errors }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n </div>\n\n <!-- D3/D8: Run Detail Slide-In Panel -->\n @if (SelectedRunID) {\n <div class=\"at-card\" style=\"margin-top: 12px;\">\n <div class=\"at-card-header\">\n <span class=\"at-card-title\">\n <i class=\"fa-solid fa-magnifying-glass-chart\"></i>\n Run Detail: {{ SelectedRunID.slice(0, 14) }}...\n </span>\n <button class=\"at-action-btn at-secondary-btn\" style=\"font-size: 11px; padding: 3px 8px;\" (click)=\"CloseRunDetail()\">\n <i class=\"fa-solid fa-times\"></i> Close\n </button>\n </div>\n <div class=\"at-card-body\">\n @if (IsLoadingRunDetail) {\n <mj-loading text=\"Loading run details...\" size=\"small\"></mj-loading>\n } @else if (RunDetailRows.length > 0) {\n <table class=\"at-run-table\">\n <thead>\n <tr>\n <th>Source</th>\n <th>Source Type</th>\n <th>Status</th>\n <th>Items</th>\n <th>Tagged</th>\n <th>Vectorized</th>\n <th>Errors</th>\n <th>Tokens</th>\n <th>Cost</th>\n <th>Duration</th>\n </tr>\n </thead>\n <tbody>\n @for (detail of RunDetailRows; track detail.SourceName) {\n <tr>\n <td class=\"at-run-source-name\">{{ detail.SourceName }}</td>\n <td>{{ detail.SourceType }}</td>\n <td>\n <span class=\"at-run-status-badge\" [class]=\"detail.StatusClass\">{{ detail.Status }}</span>\n </td>\n <td>{{ detail.ItemsProcessed }}</td>\n <td>{{ detail.ItemsTagged }}</td>\n <td>{{ detail.ItemsVectorized }}</td>\n <td [class.run-error-text]=\"detail.ErrorCount > 0\">{{ detail.ErrorCount }}</td>\n <td>{{ FormatTokenCount(detail.TotalTokens) }}</td>\n <td>{{ detail.TotalCost > 0 ? '$' + detail.TotalCost.toFixed(4) : '$0.00' }}</td>\n <td class=\"at-run-duration\">{{ detail.Duration }}</td>\n </tr>\n }\n </tbody>\n </table>\n } @else {\n <div class=\"at-empty-state\">\n <i class=\"fa-solid fa-info-circle\"></i>\n <p>No per-source detail records found for this run.</p>\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\n }\n </div>\n\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550 SLIDE-IN FORM OVERLAY \u2550\u2550\u2550\u2550\u2550\u2550 -->\n @if (FormMode !== 'none') {\n <div class=\"at-slide-overlay\" (click)=\"CloseForm()\"></div>\n <div class=\"at-slide-panel\">\n <div class=\"at-slide-header\">\n <h3>\n @if (FormMode === 'add-source') { Add Content Source }\n @else if (FormMode === 'edit-source') { Edit Content Source }\n @else if (FormMode === 'add-type') { Add Content Type }\n @else if (FormMode === 'edit-type') { Edit Content Type }\n </h3>\n <button class=\"at-slide-close\" aria-label=\"Close form\" (click)=\"CloseForm()\"><i class=\"fa-solid fa-times\"></i></button>\n </div>\n <div class=\"at-slide-body\">\n\n <!-- Source form -->\n @if (FormMode === 'add-source' || FormMode === 'edit-source') {\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">Name</label>\n <input type=\"text\" class=\"at-form-input\" [(ngModel)]=\"FormSourceName\" placeholder=\"Source name\">\n </div>\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">Source Type</label>\n <select class=\"at-form-select\" [(ngModel)]=\"FormSourceTypeID\">\n <option value=\"\">Select source type...</option>\n @for (opt of SourceTypeOptions; track opt.ID) {\n <option [value]=\"opt.ID\">{{ opt.Name }}</option>\n }\n </select>\n </div>\n <!-- Content Type + File Type: hidden for Entity source type -->\n @if (SelectedSourceTypeRequiresContentType) {\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">Content Type</label>\n <select class=\"at-form-select\" [(ngModel)]=\"FormContentTypeID\">\n <option value=\"\">Select content type...</option>\n @for (opt of ContentTypeOptions; track opt.ID) {\n <option [value]=\"opt.ID\">{{ opt.Name }}</option>\n }\n </select>\n </div>\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">File Type</label>\n <select class=\"at-form-select\" [(ngModel)]=\"FormFileTypeID\">\n <option value=\"\">Select file type...</option>\n @for (opt of FileTypeOptions; track opt.ID) {\n <option [value]=\"opt.ID\">{{ opt.Name }}</option>\n }\n </select>\n </div>\n }\n\n <!-- Dynamic source-type-specific fields from ConfigurationObject.RequiredFields -->\n @for (field of SelectedSourceTypeFields; track field.Key) {\n @if (!field.DependsOnField || FormSourceSpecificConfig[field.DependsOnField]) {\n @if (!field.ShowOnlyIfMultiple || GetDependentOptions(field).length > 1) {\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">{{ field.Label }} @if (field.Required) { <span class=\"at-required\">*</span> }</label>\n @switch (field.Type) {\n @case ('url') {\n <input type=\"url\" class=\"at-form-input\" [(ngModel)]=\"FormSourceSpecificConfig[field.Key]\"\n [placeholder]=\"field.Description || 'https://...'\">\n }\n @case ('path') {\n <input type=\"text\" class=\"at-form-input\" [(ngModel)]=\"FormSourceSpecificConfig[field.Key]\"\n [placeholder]=\"field.Description || '/path/to/...'\">\n }\n @case ('text') {\n <input type=\"text\" class=\"at-form-input\" [(ngModel)]=\"FormSourceSpecificConfig[field.Key]\"\n [placeholder]=\"field.Description || ''\" [value]=\"field.DefaultValue || ''\">\n }\n @case ('entity-picker') {\n <select class=\"at-form-select\" [(ngModel)]=\"FormSourceSpecificConfig[field.Key]\"\n (ngModelChange)=\"OnSourceFieldChanged(field.Key)\">\n <option value=\"\">Select entity...</option>\n @for (opt of EntitiesWithDocuments; track opt.ID) {\n <option [value]=\"opt.ID\">{{ opt.Name }}</option>\n }\n </select>\n }\n @case ('entity-doc-picker') {\n <select class=\"at-form-select\" [(ngModel)]=\"FormSourceSpecificConfig[field.Key]\">\n @for (opt of GetDependentOptions(field); track opt.ID) {\n <option [value]=\"opt.ID\">{{ opt.Name }}</option>\n }\n </select>\n }\n @case ('storage-provider-picker') {\n <select class=\"at-form-select\" [(ngModel)]=\"FormSourceSpecificConfig[field.Key]\">\n <option value=\"\">Select provider...</option>\n @for (opt of StorageProviderOptions; track opt) {\n <option [value]=\"opt\">{{ opt }}</option>\n }\n </select>\n }\n @case ('dropdown') {\n <select class=\"at-form-select\" [(ngModel)]=\"FormSourceSpecificConfig[field.Key]\">\n <option value=\"\">Select...</option>\n @for (opt of field.Options || []; track opt.Value) {\n <option [value]=\"opt.Value\">{{ opt.Label }}</option>\n }\n </select>\n }\n }\n @if (field.Description) {\n <span class=\"at-form-hint\">{{ field.Description }}</span>\n }\n </div>\n }\n }\n }\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">Embedding Model Override</label>\n <mj-tree-dropdown\n [BranchConfig]=\"EmbeddingVendorBranch\"\n [LeafConfig]=\"EmbeddingModelsLeaf\"\n SelectionMode=\"single\"\n SelectableTypes=\"leaf\"\n Placeholder=\"Use system default\"\n [Clearable]=\"true\"\n [Value]=\"ToCompositeKey(FormSourceEmbeddingModelID)\"\n (ValueChange)=\"FormSourceEmbeddingModelID = FromCompositeKey($event)\">\n </mj-tree-dropdown>\n <span class=\"at-form-hint\">Overrides Content Type default</span>\n </div>\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">Vector Index Override</label>\n <select class=\"at-form-select\" [(ngModel)]=\"FormSourceVectorIndexID\">\n <option value=\"\">Use system default</option>\n @for (opt of VectorIndexOptions; track opt.ID) {\n <option [value]=\"opt.ID\">{{ opt.Name }}</option>\n }\n </select>\n <span class=\"at-form-hint\">Overrides Content Type default</span>\n </div>\n <div class=\"at-form-actions\">\n <button class=\"at-action-btn at-primary-btn\" (click)=\"SaveSource()\" [disabled]=\"FormSaving\">\n @if (FormSaving) { <i class=\"fa-solid fa-spinner fa-spin\"></i> Saving... }\n @else { <i class=\"fa-solid fa-check\"></i> Save }\n </button>\n <button class=\"at-action-btn at-secondary-btn\" (click)=\"CloseForm()\">Cancel</button>\n </div>\n }\n\n <!-- Content Type form -->\n @if (FormMode === 'add-type' || FormMode === 'edit-type') {\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">Name</label>\n <input type=\"text\" class=\"at-form-input\" [(ngModel)]=\"FormTypeName\" placeholder=\"Content type name\">\n </div>\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">Description</label>\n <textarea class=\"at-form-textarea\" [(ngModel)]=\"FormTypeDescription\" rows=\"3\" placeholder=\"Description...\"></textarea>\n </div>\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">AI Model (for tagging)</label>\n <mj-tree-dropdown\n [BranchConfig]=\"AIModelVendorBranch\"\n [LeafConfig]=\"AllModelsLeaf\"\n SelectionMode=\"single\"\n SelectableTypes=\"leaf\"\n Placeholder=\"Select AI model...\"\n [Clearable]=\"true\"\n [Value]=\"ToCompositeKey(FormTypeAIModelID)\"\n (ValueChange)=\"FormTypeAIModelID = FromCompositeKey($event)\">\n </mj-tree-dropdown>\n </div>\n <div class=\"at-form-row\">\n <div class=\"at-form-group\" style=\"flex: 1;\">\n <label class=\"at-form-label\">Min Tags</label>\n <input type=\"number\" class=\"at-form-input\" [(ngModel)]=\"FormTypeMinTags\" min=\"0\">\n </div>\n <div class=\"at-form-group\" style=\"flex: 1;\">\n <label class=\"at-form-label\">Max Tags</label>\n <input type=\"number\" class=\"at-form-input\" [(ngModel)]=\"FormTypeMaxTags\" min=\"1\">\n </div>\n </div>\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">Embedding Model</label>\n <mj-tree-dropdown\n [BranchConfig]=\"EmbeddingVendorBranch\"\n [LeafConfig]=\"EmbeddingModelsLeaf\"\n SelectionMode=\"single\"\n SelectableTypes=\"leaf\"\n Placeholder=\"Use system default\"\n [Clearable]=\"true\"\n [Value]=\"ToCompositeKey(FormTypeEmbeddingModelID)\"\n (ValueChange)=\"FormTypeEmbeddingModelID = FromCompositeKey($event)\">\n </mj-tree-dropdown>\n </div>\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">Vector Index</label>\n <select class=\"at-form-select\" [(ngModel)]=\"FormTypeVectorIndexID\">\n <option value=\"\">Use system default</option>\n @for (opt of VectorIndexOptions; track opt.ID) {\n <option [value]=\"opt.ID\">{{ opt.Name }}</option>\n }\n </select>\n </div>\n <div class=\"at-form-actions\">\n <button class=\"at-action-btn at-primary-btn\" (click)=\"SaveContentType()\" [disabled]=\"FormSaving\">\n @if (FormSaving) { <i class=\"fa-solid fa-spinner fa-spin\"></i> Saving... }\n @else { <i class=\"fa-solid fa-check\"></i> Save }\n </button>\n <button class=\"at-action-btn at-secondary-btn\" (click)=\"CloseForm()\">Cancel</button>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550 ITEM DETAIL SLIDE-IN \u2550\u2550\u2550\u2550\u2550\u2550 -->\n @if (ShowItemDetail && SelectedFeedItem) {\n <div class=\"at-slide-overlay\" (click)=\"CloseItemDetail()\"></div>\n <div class=\"at-slide-panel at-detail-panel\">\n <div class=\"at-slide-header\">\n <h3><i class=\"fa-solid fa-file-lines\"></i> Content Item</h3>\n <button class=\"at-slide-close\" aria-label=\"Close item detail\" (click)=\"CloseItemDetail()\"><i class=\"fa-solid fa-times\"></i></button>\n </div>\n <div class=\"at-slide-body\">\n <!-- Header -->\n <div class=\"at-detail-item-header\">\n <h4 class=\"at-detail-item-name\">{{ SelectedFeedItem.Name }}</h4>\n <div class=\"at-detail-badges\">\n <span class=\"at-detail-badge at-detail-badge-source\">{{ SelectedFeedItem.SourceName }}</span>\n @if (SelectedFeedItem.RequiresContentType) {\n <span class=\"at-detail-badge at-detail-badge-type\">{{ SelectedFeedItem.ContentTypeName }}</span>\n @if (SelectedFeedItem.FileTypeName) {\n <span class=\"at-detail-badge at-detail-badge-file\"><i class=\"fa-solid fa-file\"></i> {{ SelectedFeedItem.FileTypeName }}</span>\n }\n }\n </div>\n </div>\n\n <!-- URL -->\n @if (SelectedFeedItem.URL) {\n <div class=\"at-detail-section\">\n <div class=\"at-detail-section-label\">URL</div>\n <a [href]=\"SelectedFeedItem.URL\" target=\"_blank\" class=\"at-detail-link\">\n {{ SelectedFeedItem.URL }}\n <i class=\"fa-solid fa-external-link-alt\" style=\"font-size: 0.65rem; margin-left: 4px;\"></i>\n </a>\n </div>\n }\n\n <!-- Text Preview -->\n @if (SelectedFeedItem.TextContent) {\n <div class=\"at-detail-section\">\n <div class=\"at-detail-section-label\">Content Preview</div>\n <div class=\"at-detail-text-preview\">{{ SelectedFeedItem.TextContent }}</div>\n </div>\n }\n\n <!-- Tags (weighted) -->\n @if (SelectedFeedItem.Tags.length > 0) {\n <div class=\"at-detail-section\">\n <div class=\"at-detail-section-label\">Tags ({{ SelectedFeedItem.Tags.length }})</div>\n <div class=\"at-detail-tags\">\n @for (wt of SelectedFeedItem.Tags; track wt.Tag) {\n <span class=\"at-tag-pill at-tag-weighted\" [style.font-size]=\"TagFontSize(wt.Weight)\">\n {{ wt.Tag }}\n <span class=\"at-tag-weight\">{{ FormatWeight(wt.Weight) }}</span>\n </span>\n }\n </div>\n </div>\n }\n\n <!-- Metadata -->\n <div class=\"at-detail-section\">\n <div class=\"at-detail-section-label\">Metadata</div>\n <div class=\"at-detail-meta-grid\">\n @if (SelectedFeedItem.Checksum) {\n <div class=\"at-detail-meta-row\">\n <span class=\"at-detail-meta-key\">Checksum</span>\n <span class=\"at-detail-meta-value at-detail-meta-mono\">{{ SelectedFeedItem.Checksum }}</span>\n </div>\n }\n <div class=\"at-detail-meta-row\">\n <span class=\"at-detail-meta-key\">Created</span>\n <span class=\"at-detail-meta-value\">{{ SelectedFeedItem.CreatedAt }}</span>\n </div>\n <div class=\"at-detail-meta-row\">\n <span class=\"at-detail-meta-key\">Updated</span>\n <span class=\"at-detail-meta-value\">{{ SelectedFeedItem.UpdatedAt }}</span>\n </div>\n </div>\n </div>\n\n <!-- Actions -->\n <div class=\"at-detail-actions\">\n <button class=\"at-action-btn at-primary-btn\" (click)=\"OpenRecordFromItem(SelectedFeedItem)\">\n <i class=\"fa-solid fa-external-link-alt\"></i> Open Record\n </button>\n <button class=\"at-action-btn at-secondary-btn\" disabled>\n <i class=\"fa-solid fa-magnifying-glass\"></i> See Similar Items\n </button>\n </div>\n </div>\n </div>\n }\n\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550 SOURCE DETAIL SLIDE-IN \u2550\u2550\u2550\u2550\u2550\u2550 -->\n @if (ShowSourceDetail) {\n <div class=\"at-slide-overlay\" (click)=\"CloseSourceDetail()\"></div>\n <div class=\"at-slide-panel at-detail-panel\">\n <div class=\"at-slide-header\">\n <h3><i class=\"fa-solid fa-database\"></i> Source Detail</h3>\n <button class=\"at-slide-close\" aria-label=\"Close source detail\" (click)=\"CloseSourceDetail()\"><i class=\"fa-solid fa-times\"></i></button>\n </div>\n <div class=\"at-slide-body\">\n @if (SourceDetailLoading) {\n <div class=\"at-loading-overlay\">\n <mj-loading text=\"Loading source details...\"></mj-loading>\n </div>\n }\n @if (!SourceDetailLoading && SelectedSource) {\n <!-- Source Header -->\n <div class=\"at-detail-source-header\">\n <div class=\"at-source-card-icon\"><i [class]=\"SelectedSource.Icon\"></i></div>\n <div>\n <h4 class=\"at-detail-item-name\">{{ SelectedSource.Name }}</h4>\n <div class=\"at-detail-badges\">\n <span class=\"at-detail-badge at-detail-badge-type\">{{ SelectedSource.SourceTypeName }}</span>\n <span class=\"at-detail-badge\" [class]=\"'at-detail-badge-status-' + SelectedSource.StatusClass\">\n {{ SelectedSource.StatusLabel }}\n </span>\n </div>\n </div>\n </div>\n\n <!-- Configuration -->\n <div class=\"at-detail-section\">\n <div class=\"at-detail-section-label\">Configuration</div>\n <div class=\"at-detail-meta-grid\">\n @if (SelectedSource.URL) {\n <div class=\"at-detail-meta-row\">\n <span class=\"at-detail-meta-key\">URL</span>\n <a [href]=\"SelectedSource.URL\" target=\"_blank\" class=\"at-detail-link at-detail-meta-value\">{{ SelectedSource.URL }}</a>\n </div>\n }\n @if (SelectedSource.RequiresFileType) {\n <div class=\"at-detail-meta-row\">\n <span class=\"at-detail-meta-key\">Content Type</span>\n <span class=\"at-detail-meta-value\">{{ SelectedSource.ContentTypeName }}</span>\n </div>\n <div class=\"at-detail-meta-row\">\n <span class=\"at-detail-meta-key\">File Type</span>\n <span class=\"at-detail-meta-value\">{{ SelectedSource.FileTypeName }}</span>\n </div>\n }\n <div class=\"at-detail-meta-row\">\n <span class=\"at-detail-meta-key\">Embedding Model</span>\n <span class=\"at-detail-meta-value\">{{ SelectedSource.EmbeddingModelName }}</span>\n </div>\n <div class=\"at-detail-meta-row\">\n <span class=\"at-detail-meta-key\">Vector Index</span>\n <span class=\"at-detail-meta-value\">{{ SelectedSource.VectorIndexName }}</span>\n </div>\n </div>\n </div>\n\n <!-- Stats -->\n <div class=\"at-detail-section\">\n <div class=\"at-detail-section-label\">Statistics</div>\n <div class=\"at-detail-stats-strip\">\n <div class=\"at-detail-stat\">\n <div class=\"at-detail-stat-value\">{{ formatNumber(SelectedSource.ItemCount) }}</div>\n <div class=\"at-detail-stat-label\">Items</div>\n </div>\n <div class=\"at-detail-stat\">\n <div class=\"at-detail-stat-value\">{{ formatNumber(SelectedSource.TagCount) }}</div>\n <div class=\"at-detail-stat-label\">Tags</div>\n </div>\n <div class=\"at-detail-stat\">\n <div class=\"at-detail-stat-value\">{{ SelectedSource.AvgTags }}</div>\n <div class=\"at-detail-stat-label\">Avg Tags</div>\n </div>\n <div class=\"at-detail-stat\">\n <div class=\"at-detail-stat-value\">{{ SelectedSource.LastRunAgo }}</div>\n <div class=\"at-detail-stat-label\">Last Run</div>\n </div>\n <div class=\"at-detail-stat\">\n <div class=\"at-detail-stat-value\" [class.at-kpi-error-value]=\"SelectedSource.ErrorCount > 0\">{{ SelectedSource.ErrorCount }}</div>\n <div class=\"at-detail-stat-label\">Errors</div>\n </div>\n </div>\n </div>\n\n <!-- Content Library (D4 status badges, D7 pagination) -->\n <div class=\"at-detail-section\">\n <div class=\"at-detail-section-header-row\">\n <div class=\"at-detail-section-label\">Content Library ({{ FilteredSourceDetailTotal }} of {{ SelectedSource.ItemCount | number }})</div>\n <div class=\"at-detail-section-controls\">\n <select class=\"at-detail-filter-select\" [(ngModel)]=\"SourceDetailStatusFilter\" (ngModelChange)=\"OnSourceDetailStatusFilterChange()\">\n @for (opt of SourceDetailStatusOptions; track opt) {\n <option [value]=\"opt\">{{ opt }}</option>\n }\n </select>\n <button class=\"at-action-btn at-retry-btn\" (click)=\"RetryFailedItems()\" title=\"Re-queue failed items for processing\">\n <i class=\"fa-solid fa-rotate-right\"></i> Retry Failed\n </button>\n </div>\n </div>\n <div class=\"at-detail-content-list\">\n @if (FilteredSourceDetailItems.length === 0) {\n <div class=\"at-empty-state\" style=\"padding: 16px;\">\n <p>{{ SourceDetailStatusFilter === 'All' ? 'No content items yet.' : 'No items match this filter.' }}</p>\n </div>\n }\n @for (ci of FilteredSourceDetailItems; track ci.ID) {\n <div class=\"at-detail-content-item\" (click)=\"OpenContentItemDetail(ci)\">\n <div class=\"at-feed-status-dot\" [class]=\"ci.StatusDot\"></div>\n <span class=\"at-detail-content-item-name\">{{ ci.Name }}</span>\n <span class=\"at-status-badge\" [class]=\"GetStatusBadgeClass(ci.EmbeddingStatus)\">E:{{ ci.EmbeddingStatus }}</span>\n <span class=\"at-status-badge\" [class]=\"GetStatusBadgeClass(ci.TaggingStatus)\">T:{{ ci.TaggingStatus }}</span>\n <span class=\"at-detail-content-item-tags\">{{ ci.TagCount }} tags</span>\n <span class=\"at-detail-content-item-time\">{{ ci.UpdatedAt }}</span>\n </div>\n }\n </div>\n <!-- Pagination -->\n @if (SourceDetailTotalPages > 1) {\n <div class=\"at-detail-pagination\">\n <button class=\"at-page-btn\" [disabled]=\"SourceDetailPage === 0\" (click)=\"SourceDetailPrevPage()\">\n <i class=\"fa-solid fa-chevron-left\"></i> Prev\n </button>\n <span class=\"at-page-info\">Page {{ SourceDetailPage + 1 }} of {{ SourceDetailTotalPages }}</span>\n <button class=\"at-page-btn\" [disabled]=\"SourceDetailPage >= SourceDetailTotalPages - 1\" (click)=\"SourceDetailNextPage()\">\n Next <i class=\"fa-solid fa-chevron-right\"></i>\n </button>\n </div>\n }\n </div>\n\n <!-- Run History -->\n @if (SelectedSource.RunHistory.length > 0) {\n <div class=\"at-detail-section\">\n <div class=\"at-detail-section-label\">Recent Runs</div>\n <div class=\"at-detail-run-history\">\n @for (run of SelectedSource.RunHistory; track run.ID) {\n <div class=\"at-detail-run-row\">\n <span class=\"at-run-status-badge\" [class]=\"run.StatusClass\">{{ run.Status }}</span>\n <span class=\"at-detail-run-time\">{{ run.StartedDisplay }}</span>\n <span class=\"at-detail-run-duration\">{{ run.Duration }}</span>\n <span class=\"at-detail-run-items\">{{ run.Items }} items</span>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- Actions -->\n <div class=\"at-detail-actions\">\n <button class=\"at-action-btn at-primary-btn\" (click)=\"OpenEditSourceFromDetail()\">\n <i class=\"fa-solid fa-pen\"></i> Edit\n </button>\n <button class=\"at-action-btn at-secondary-btn\" (click)=\"RunSourceFromDetail()\">\n <i class=\"fa-solid fa-play\"></i> Run Now\n </button>\n <button class=\"at-action-btn at-secondary-btn at-source-delete-btn\" (click)=\"DeleteSourceFromDetail()\">\n <i class=\"fa-solid fa-trash\"></i> Delete\n </button>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550 SCHEDULE DIALOG \u2550\u2550\u2550\u2550\u2550\u2550 -->\n @if (ShowScheduleDialog && SchedulingSourceCard) {\n <div class=\"at-schedule-overlay\" (click)=\"CloseScheduleDialog()\">\n <div class=\"at-schedule-dialog\" (click)=\"$event.stopPropagation()\">\n <div class=\"at-schedule-dialog-header\">\n <h3><i class=\"fa-regular fa-clock\"></i> Schedule Pipeline</h3>\n <button class=\"at-schedule-dialog-close\" (click)=\"CloseScheduleDialog()\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n <div class=\"at-schedule-dialog-body\">\n <div class=\"at-schedule-field\">\n <label>Source</label>\n <div class=\"at-schedule-source-name\">\n <i [class]=\"SchedulingSourceCard.Icon\"></i>\n {{ SchedulingSourceCard.Name }}\n </div>\n </div>\n <div class=\"at-schedule-field\">\n <label>Action</label>\n <div class=\"at-schedule-action-name\">Autotag and Vectorize Content</div>\n </div>\n <div class=\"at-schedule-field\">\n <label for=\"schedule-cron\">Cron Expression</label>\n <input id=\"schedule-cron\"\n type=\"text\"\n class=\"mj-input at-schedule-cron-input\"\n [(ngModel)]=\"ScheduleCron\"\n placeholder=\"0 2 * * *\" />\n <div class=\"at-schedule-cron-preview\">\n <i class=\"fa-solid fa-info-circle\"></i>\n {{ GetCronPreview(ScheduleCron) }}\n </div>\n </div>\n <div class=\"at-schedule-field at-schedule-toggle-row\">\n <label for=\"schedule-enabled\">Enabled</label>\n <input id=\"schedule-enabled\"\n type=\"checkbox\"\n class=\"mj-checkbox\"\n [(ngModel)]=\"ScheduleEnabled\" />\n </div>\n </div>\n <div class=\"at-schedule-dialog-footer\">\n <button class=\"at-action-btn at-primary-btn\" (click)=\"SaveSchedule()\" [disabled]=\"ScheduleSaving\">\n @if (ScheduleSaving) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Saving...\n } @else {\n <i class=\"fa-solid fa-check\"></i> Create Schedule\n }\n </button>\n <button class=\"at-action-btn at-secondary-btn\" (click)=\"CloseScheduleDialog()\">Cancel</button>\n </div>\n </div>\n </div>\n }\n\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550 CONFIRMATION DIALOG \u2550\u2550\u2550\u2550\u2550\u2550 -->\n @if (ShowConfirmDialog) {\n <div class=\"at-schedule-overlay\" (click)=\"ConfirmDialogCancel()\">\n <div class=\"at-schedule-dialog\" (click)=\"$event.stopPropagation()\">\n <div class=\"at-schedule-dialog-header\">\n <h3><i class=\"fa-solid fa-triangle-exclamation\"></i> {{ ConfirmDialogTitle }}</h3>\n <button class=\"at-schedule-dialog-close\" (click)=\"ConfirmDialogCancel()\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n <div class=\"at-schedule-dialog-body\">\n <p class=\"at-confirm-message\">{{ ConfirmDialogMessage }}</p>\n </div>\n <div class=\"at-schedule-dialog-footer\">\n <button class=\"at-action-btn at-danger-btn\" (click)=\"ConfirmDialogAccept()\">\n <i class=\"fa-solid fa-check\"></i> Confirm\n </button>\n <button class=\"at-action-btn at-secondary-btn\" (click)=\"ConfirmDialogCancel()\">Cancel</button>\n </div>\n </div>\n </div>\n }\n\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550 SPLIT DIALOG \u2550\u2550\u2550\u2550\u2550\u2550 -->\n @if (ShowSplitDialog) {\n <div class=\"at-schedule-overlay\" (click)=\"CloseSplitDialog()\">\n <div class=\"at-schedule-dialog\" (click)=\"$event.stopPropagation()\">\n <div class=\"at-schedule-dialog-header\">\n <h3><i class=\"fa-solid fa-code-branch\"></i> Split Tag</h3>\n <button class=\"at-schedule-dialog-close\" (click)=\"CloseSplitDialog()\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n <div class=\"at-schedule-dialog-body\">\n <div class=\"at-schedule-field\">\n <label>New tag names (comma-separated)</label>\n <input type=\"text\" class=\"mj-input\" style=\"width: 100%;\"\n [(ngModel)]=\"SplitChildNames\"\n placeholder=\"Tag A, Tag B, Tag C\" />\n </div>\n <p class=\"at-confirm-message\">New tags will be created as siblings of the original tag under the same parent.</p>\n </div>\n <div class=\"at-schedule-dialog-footer\">\n <button class=\"at-action-btn at-primary-btn\" (click)=\"ExecuteSplit()\" [disabled]=\"!SplitChildNames.trim()\">\n <i class=\"fa-solid fa-code-branch\"></i> Create Tags\n </button>\n <button class=\"at-action-btn at-secondary-btn\" (click)=\"CloseSplitDialog()\">Cancel</button>\n </div>\n </div>\n </div>\n }\n\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550 MOVE DIALOG \u2550\u2550\u2550\u2550\u2550\u2550 -->\n @if (ShowCreateTagDialog) {\n <div class=\"at-schedule-overlay\" (click)=\"CloseCreateTagDialog()\">\n <div class=\"at-schedule-dialog\" (click)=\"$event.stopPropagation()\">\n <div class=\"at-schedule-dialog-header\">\n <h3><i class=\"fa-solid fa-plus\"></i> Create Tag</h3>\n <button class=\"at-schedule-dialog-close\" (click)=\"CloseCreateTagDialog()\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n <div class=\"at-schedule-dialog-body\">\n <div class=\"at-tax-create-context\">{{ CreateTagParentLabel }}</div>\n <div class=\"at-schedule-field\">\n <label>Name</label>\n <input type=\"text\" class=\"mj-input\" style=\"width: 100%;\" [(ngModel)]=\"CreateTagName\"\n placeholder=\"Tag name\" (keydown.enter)=\"SaveNewTag()\">\n </div>\n <div class=\"at-schedule-field\">\n <label>Description (optional)</label>\n <textarea class=\"mj-textarea\" rows=\"3\" style=\"width: 100%;\" [(ngModel)]=\"CreateTagDescription\"\n placeholder=\"Brief description of this tag\"></textarea>\n </div>\n </div>\n <div class=\"at-schedule-dialog-footer\">\n <button class=\"at-action-btn at-primary-btn\" (click)=\"SaveNewTag()\" [disabled]=\"!CreateTagName.trim()\">\n <i class=\"fa-solid fa-check\"></i> Create\n </button>\n <button class=\"at-action-btn at-secondary-btn\" (click)=\"CloseCreateTagDialog()\">Cancel</button>\n </div>\n </div>\n </div>\n }\n\n @if (ShowMoveDialog) {\n <div class=\"at-schedule-overlay\" (click)=\"CloseMoveDialog()\">\n <div class=\"at-schedule-dialog\" (click)=\"$event.stopPropagation()\">\n <div class=\"at-schedule-dialog-header\">\n <h3><i class=\"fa-solid fa-arrows-up-down\"></i> Move Tag</h3>\n <button class=\"at-schedule-dialog-close\" (click)=\"CloseMoveDialog()\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n <div class=\"at-schedule-dialog-body\">\n <div class=\"at-schedule-field\">\n <label>New parent tag</label>\n <select class=\"mj-input\" style=\"width: 100%;\" [(ngModel)]=\"MoveNewParentID\">\n <option [ngValue]=\"null\">(Root level &mdash; no parent)</option>\n @for (opt of GetMoveTargetOptions(); track opt.ID) {\n <option [ngValue]=\"opt.ID\">{{ '\\u00A0\\u00A0'.repeat(opt.Depth) }}{{ opt.Name }}</option>\n }\n </select>\n </div>\n </div>\n <div class=\"at-schedule-dialog-footer\">\n <button class=\"at-action-btn at-primary-btn\" (click)=\"ExecuteMove()\">\n <i class=\"fa-solid fa-check\"></i> Move\n </button>\n <button class=\"at-action-btn at-secondary-btn\" (click)=\"CloseMoveDialog()\">Cancel</button>\n </div>\n </div>\n </div>\n }\n\n @if (ShowMergeIntoDialog) {\n <div class=\"at-schedule-overlay\" (click)=\"CloseMergeIntoDialog()\">\n <div class=\"at-schedule-dialog\" (click)=\"$event.stopPropagation()\">\n <div class=\"at-schedule-dialog-header\">\n <h3><i class=\"fa-solid fa-compress\"></i> Merge \"{{ MergeSourceTag?.Name }}\" Into...</h3>\n <button class=\"at-schedule-dialog-close\" (click)=\"CloseMergeIntoDialog()\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n <div class=\"at-schedule-dialog-body\">\n <p style=\"font-size: 0.85rem; color: var(--mj-text-secondary); margin: 0 0 12px;\">\n All tagged items will be moved to the target tag, then \"{{ MergeSourceTag?.Name }}\" will be deleted.\n </p>\n <div class=\"at-schedule-field\">\n <label>Merge into</label>\n <mj-combobox\n [Data]=\"MergeTargetData\"\n TextField=\"Label\"\n ValueField=\"ID\"\n [Filterable]=\"true\"\n [ValuePrimitive]=\"true\"\n Placeholder=\"Search and select a tag...\"\n (ValueChange)=\"OnMergeTargetSelected($event)\">\n </mj-combobox>\n </div>\n </div>\n <div class=\"at-schedule-dialog-footer\">\n <button class=\"at-action-btn at-primary-btn\" (click)=\"ExecuteMergeInto()\" [disabled]=\"!MergeTargetID || IsMerging\">\n @if (IsMerging) { <i class=\"fa-solid fa-spinner fa-spin\"></i> Merging... } @else { <i class=\"fa-solid fa-compress\"></i> Merge }\n </button>\n <button class=\"at-action-btn at-secondary-btn\" (click)=\"CloseMergeIntoDialog()\">Cancel</button>\n </div>\n </div>\n </div>\n }\n\n <!-- No Content Types Warning Dialog (z-index above slide-in panel) -->\n @if (ShowNoContentTypeWarning) {\n <div class=\"at-schedule-dialog-overlay\" style=\"z-index: 10001;\" (click)=\"ShowNoContentTypeWarning = false\">\n <div class=\"at-schedule-dialog\" style=\"max-width: 440px; z-index: 10002;\" (click)=\"$event.stopPropagation()\">\n <div class=\"at-schedule-dialog-header\">\n <span><i class=\"fa-solid fa-triangle-exclamation\" style=\"color: var(--mj-status-warning); margin-right: 8px;\"></i> Content Type Required</span>\n <button class=\"at-close-btn\" aria-label=\"Close warning\" (click)=\"ShowNoContentTypeWarning = false\"><i class=\"fa-solid fa-xmark\"></i></button>\n </div>\n <div class=\"at-schedule-dialog-body\" style=\"text-align: center; padding: 24px;\">\n <p style=\"color: var(--mj-text-secondary); margin-bottom: 16px;\">\n No content types have been configured yet. At least one content type is required before you can create a content source.\n </p>\n <p style=\"color: var(--mj-text-muted); font-size: 13px;\">\n Go to the <strong>Content Types</strong> tab to create one.\n </p>\n </div>\n <div class=\"at-schedule-dialog-footer\">\n <button class=\"at-action-btn at-primary-btn\" (mousedown)=\"ShowNoContentTypeWarning = false; CloseForm(); SwitchTab('types')\">\n <i class=\"fa-solid fa-arrow-right\"></i> Go to Content Types\n </button>\n <button class=\"at-action-btn at-secondary-btn\" (click)=\"ShowNoContentTypeWarning = false\">Close</button>\n </div>\n </div>\n </div>\n }\n</div>\n", styles: ["/* ============================================================\n Content Autotagging Dashboard\n All colors use MJ design tokens \u2014 no hardcoded hex values.\n All classes prefixed with at- to prevent leaking (ViewEncapsulation.None).\n ============================================================ */\n\n/* \u2500\u2500 Root layout \u2500\u2500 */\n\n.at-dashboard {\n display: flex;\n height: 100%;\n overflow: hidden;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550 LEFT NAV \u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.at-left-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.at-left-nav-header {\n padding: 16px 16px 12px;\n border-bottom: 1px solid var(--mj-border-subtle);\n}\n\n.at-left-nav-header h2 {\n font-size: 0.95rem;\n font-weight: 700;\n display: flex;\n align-items: center;\n gap: 8px;\n margin: 0;\n color: var(--mj-text-primary);\n}\n\n.at-left-nav-header h2 i {\n color: var(--mj-brand-primary);\n}\n\n.at-left-nav-items {\n flex: 1;\n padding: 8px;\n overflow-y: auto;\n}\n\n.at-nav-item {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 12px;\n border-radius: 8px;\n font-size: 0.82rem;\n font-weight: 500;\n color: var(--mj-text-muted);\n cursor: pointer;\n transition: all 0.12s ease;\n margin-bottom: 2px;\n}\n\n.at-nav-item:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-secondary);\n}\n\n.at-nav-item.active {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n font-weight: 600;\n}\n\n.at-nav-item i {\n width: 18px;\n text-align: center;\n font-size: 0.8rem;\n}\n\n.at-nav-badge {\n margin-left: auto;\n background: var(--mj-bg-surface-sunken);\n padding: 1px 7px;\n border-radius: 10px;\n font-size: 0.65rem;\n font-weight: 600;\n color: var(--mj-text-muted);\n}\n\n.at-nav-item.active .at-nav-badge {\n background: color-mix(in srgb, var(--mj-brand-primary) 18%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.at-nav-badge-live {\n background: var(--mj-status-success-bg) !important;\n color: var(--mj-status-success-text) !important;\n}\n\n.at-nav-divider {\n height: 1px;\n background: var(--mj-border-subtle);\n margin: 8px 12px;\n}\n\n.at-left-nav-footer {\n padding: 12px;\n border-top: 1px solid var(--mj-border-subtle);\n}\n\n.at-run-pipeline-btn {\n width: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 10px;\n border: none;\n border-radius: 8px;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n font-size: 0.82rem;\n font-weight: 600;\n cursor: pointer;\n transition: background 0.15s ease;\n}\n\n.at-run-pipeline-btn:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n}\n\n.at-run-pipeline-btn:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550 MAIN CONTENT AREA \u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.at-main-area {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n.at-loading-overlay {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n}\n\n.at-page-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 14px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n.at-page-title {\n font-size: 1rem;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.at-page-subtitle {\n font-size: 0.72rem;\n color: var(--mj-text-muted);\n margin-top: 2px;\n}\n\n.at-page-actions {\n display: flex;\n gap: 8px;\n align-items: center;\n}\n\n.at-page-body {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n padding: 16px 20px;\n min-height: 0;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550 SHARED COMPONENTS \u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.at-action-btn {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 7px 14px;\n border: 1px solid;\n border-radius: 7px;\n cursor: pointer;\n font-size: 0.78rem;\n font-weight: 500;\n transition: all 0.15s ease;\n}\n\n.at-primary-btn {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-color: var(--mj-brand-primary);\n}\n\n.at-primary-btn:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n}\n\n.at-primary-btn:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.at-secondary-btn {\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n border-color: var(--mj-border-default);\n}\n\n.at-secondary-btn:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.at-card {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 10px;\n overflow: hidden;\n}\n\n.at-card-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 16px;\n border-bottom: 1px solid var(--mj-border-subtle);\n}\n\n.at-card-title {\n font-size: 0.82rem;\n font-weight: 600;\n display: flex;\n align-items: center;\n gap: 6px;\n color: var(--mj-text-primary);\n}\n\n.at-card-title i {\n color: var(--mj-brand-primary);\n font-size: 0.75rem;\n}\n\n.at-card-body {\n padding: 0;\n}\n\n.at-empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 32px 16px;\n color: var(--mj-text-disabled);\n}\n\n.at-empty-state i {\n font-size: 28px;\n}\n\n.at-empty-state p {\n margin: 0;\n font-size: 13px;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550 KPI STRIP \u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.at-kpi-strip {\n display: flex;\n gap: 12px;\n margin-bottom: 16px;\n}\n\n.at-kpi-card {\n flex: 1;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 10px;\n padding: 14px 16px;\n}\n\n.at-kpi-value {\n font-size: 1.4rem;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.at-kpi-error-value {\n color: var(--mj-status-error-text);\n}\n\n.at-kpi-label {\n font-size: 0.72rem;\n color: var(--mj-text-muted);\n margin-top: 2px;\n}\n\n.at-kpi-trend {\n font-size: 0.68rem;\n margin-top: 4px;\n display: flex;\n align-items: center;\n gap: 4px;\n color: var(--mj-text-muted);\n}\n\n.at-kpi-trend.up {\n color: var(--mj-status-success-text);\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550 PIPELINE TAB \u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.at-pipeline-layout {\n display: flex;\n gap: 16px;\n flex: 1;\n min-height: 0;\n}\n\n.at-pipeline-center {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 12px;\n min-width: 0;\n min-height: 0;\n}\n\n.at-pipeline-right {\n width: 320px;\n flex-shrink: 0;\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n/* Pipeline Stages */\n\n.at-pipeline-stages {\n display: flex;\n gap: 0;\n align-items: center;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 10px;\n padding: 12px 16px;\n}\n\n.at-pipeline-stage {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 4px;\n}\n\n.at-pipeline-stage-icon {\n width: 36px;\n height: 36px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 50%;\n font-size: 0.85rem;\n}\n\n.stage-idle .at-pipeline-stage-icon {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n\n.stage-active .at-pipeline-stage-icon {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n animation: at-pulse 1.5s infinite;\n}\n\n.stage-complete .at-pipeline-stage-icon {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n}\n\n@keyframes at-pulse {\n 0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--mj-brand-primary) 30%, transparent); }\n 50% { box-shadow: 0 0 0 6px color-mix(in srgb, var(--mj-brand-primary) 0%, transparent); }\n}\n\n.at-pipeline-stage-name {\n font-size: 0.68rem;\n font-weight: 600;\n color: var(--mj-text-secondary);\n}\n\n.at-pipeline-stage-count {\n font-size: 0.6rem;\n color: var(--mj-text-muted);\n}\n\n.at-pipeline-arrow {\n width: 24px;\n text-align: center;\n color: var(--mj-text-disabled);\n font-size: 0.6rem;\n}\n\n.at-stage-connector {\n width: 32px;\n height: 2px;\n background: var(--mj-border-default);\n transition: background 0.4s ease;\n}\n\n.at-stage-connector.connector-complete {\n background: var(--mj-status-success);\n}\n\n/* Progress section */\n\n.at-progress-section {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 8px;\n padding: 10px 16px;\n}\n\n.at-progress-header {\n display: flex;\n justify-content: space-between;\n font-size: 0.75rem;\n margin-bottom: 4px;\n}\n\n.at-progress-stage-label {\n color: var(--mj-text-secondary);\n font-weight: 500;\n}\n\n.at-progress-pct {\n color: var(--mj-brand-primary);\n font-weight: 600;\n}\n\n.at-progress-bar {\n height: 4px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 2px;\n overflow: hidden;\n}\n\n.at-progress-fill {\n height: 100%;\n background: var(--mj-brand-primary);\n border-radius: 2px;\n transition: width 0.3s ease;\n}\n\n.at-progress-current {\n font-size: 0.68rem;\n color: var(--mj-text-muted);\n margin-top: 4px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.at-progress-fill-paused {\n background: var(--mj-status-warning);\n animation: pulse-paused 1.5s ease-in-out infinite;\n}\n\n@keyframes pulse-paused {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.5; }\n}\n\n.at-pipeline-controls {\n display: flex;\n gap: 8px;\n margin-top: 8px;\n justify-content: flex-end;\n}\n\n.at-danger-btn {\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n border-color: var(--mj-status-error);\n}\n\n.at-danger-btn:hover:not(:disabled) {\n background: var(--mj-status-error-text);\n border-color: var(--mj-status-error-text);\n}\n\n/* Feed items */\n\n.at-feed-item {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 14px;\n border-bottom: 1px solid var(--mj-border-subtle);\n font-size: 0.78rem;\n}\n\n.at-feed-item:last-child {\n border-bottom: none;\n}\n\n.at-feed-status-dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n flex-shrink: 0;\n}\n\n.at-feed-status-dot.complete {\n background: var(--mj-status-success);\n}\n\n.at-feed-status-dot.processing {\n background: var(--mj-brand-primary);\n animation: at-pulse 1.5s infinite;\n}\n\n.at-feed-status-dot.error {\n background: var(--mj-status-error);\n}\n\n.at-feed-item-name {\n flex: 1;\n font-weight: 500;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n color: var(--mj-text-primary);\n}\n\n.at-feed-item-source {\n color: var(--mj-text-muted);\n font-size: 0.7rem;\n min-width: 100px;\n}\n\n.at-feed-item-tags {\n display: flex;\n gap: 4px;\n}\n\n.at-feed-tag {\n padding: 1px 6px;\n border-radius: 3px;\n font-size: 0.62rem;\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.at-feed-item-time {\n color: var(--mj-text-muted);\n font-size: 0.68rem;\n white-space: nowrap;\n min-width: 60px;\n text-align: right;\n}\n\n/* Source mini cards (right panel) */\n\n.at-source-mini {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 14px;\n border-bottom: 1px solid var(--mj-border-subtle);\n cursor: pointer;\n transition: background 0.1s ease;\n}\n\n.at-source-mini:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.at-source-mini:last-child {\n border-bottom: none;\n}\n\n.at-source-mini-icon {\n width: 28px;\n height: 28px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 6px;\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n font-size: 0.72rem;\n flex-shrink: 0;\n}\n\n.at-source-mini-info {\n flex: 1;\n min-width: 0;\n}\n\n.at-source-mini-name {\n font-size: 0.78rem;\n font-weight: 600;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n color: var(--mj-text-primary);\n}\n\n.at-source-mini-meta {\n font-size: 0.65rem;\n color: var(--mj-text-muted);\n}\n\n.at-source-mini-status {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n flex-shrink: 0;\n}\n\n.at-source-mini-status.active {\n background: var(--mj-status-success);\n}\n\n.at-source-mini-status.error {\n background: var(--mj-status-error);\n}\n\n.at-source-mini-status.inactive {\n background: var(--mj-text-disabled);\n}\n\n/* Tag cloud card */\n\n.at-tag-cloud-card {\n padding: 16px;\n}\n\n.at-tag-cloud {\n display: flex;\n flex-wrap: wrap;\n gap: 5px;\n}\n\n.at-tag-pill {\n padding: 4px 12px;\n border-radius: 14px;\n font-size: 0.72rem;\n font-weight: 500;\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n color: var(--mj-text-secondary);\n border: 1px solid var(--mj-border-subtle);\n cursor: pointer;\n transition: all 0.12s ease;\n}\n\n.at-tag-pill:hover {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n.at-tag-weighted {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n}\n\n.at-tag-weight {\n font-size: 0.6rem;\n opacity: 0.6;\n font-weight: 400;\n}\n\n.at-tag-row-clickable {\n cursor: pointer;\n transition: background 0.1s ease;\n}\n\n.at-tag-row-clickable:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.at-tag-row-selected {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface)) !important;\n border-left: 3px solid var(--mj-brand-primary);\n}\n\n.at-tag-pill.large {\n font-size: 0.85rem;\n padding: 5px 14px;\n}\n\n.at-tag-pill.small {\n font-size: 0.65rem;\n padding: 3px 8px;\n color: var(--mj-text-muted);\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550 SOURCES TAB \u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.at-sources-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));\n gap: 12px;\n}\n\n.at-source-card-full {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 10px;\n padding: 16px;\n transition: border-color 0.15s ease;\n}\n\n.at-source-card-full:hover {\n border-color: var(--mj-border-default);\n}\n\n.at-source-card-header {\n display: flex;\n align-items: center;\n gap: 10px;\n margin-bottom: 12px;\n}\n\n.at-source-card-icon {\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 10px;\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n font-size: 1rem;\n flex-shrink: 0;\n}\n\n.at-source-card-title {\n font-size: 0.9rem;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.at-source-card-type {\n font-size: 0.68rem;\n color: var(--mj-text-muted);\n}\n\n.at-source-card-status {\n margin-left: auto;\n display: flex;\n align-items: center;\n gap: 5px;\n font-size: 0.7rem;\n font-weight: 500;\n}\n\n.at-source-card-status.active {\n color: var(--mj-status-success-text);\n}\n\n.at-source-card-status.error {\n color: var(--mj-status-error-text);\n}\n\n.at-source-card-status.inactive {\n color: var(--mj-text-disabled);\n}\n\n.at-source-card-url {\n font-size: 0.7rem;\n color: var(--mj-brand-primary);\n margin-bottom: 10px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.at-source-card-stats {\n display: flex;\n gap: 16px;\n padding-top: 10px;\n border-top: 1px solid var(--mj-border-subtle);\n}\n\n.at-source-stat {\n display: flex;\n flex-direction: column;\n}\n\n.at-source-stat-value {\n font-size: 1rem;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.at-source-stat-label {\n font-size: 0.65rem;\n color: var(--mj-text-muted);\n}\n\n.at-source-card-actions {\n display: flex;\n gap: 6px;\n margin-top: 10px;\n}\n\n.at-source-action-btn {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 4px;\n padding: 6px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n font-size: 0.7rem;\n cursor: pointer;\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n transition: all 0.12s ease;\n}\n\n.at-source-action-btn:hover {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n.at-source-delete-btn:hover {\n border-color: var(--mj-status-error);\n color: var(--mj-status-error-text);\n}\n\n.at-add-source-card {\n background: none;\n border: 2px dashed var(--mj-border-default);\n border-radius: 10px;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 40px;\n cursor: pointer;\n transition: all 0.15s ease;\n color: var(--mj-text-muted);\n min-height: 200px;\n}\n\n.at-add-source-card:hover {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n.at-add-source-card i {\n font-size: 1.5rem;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550 CONTENT TYPES TAB \u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.at-ct-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));\n gap: 12px;\n}\n\n.at-ct-card {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 10px;\n padding: 16px;\n}\n\n.at-ct-card-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 10px;\n}\n\n.at-ct-card-name {\n font-size: 0.9rem;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.at-ct-card-model {\n font-size: 0.68rem;\n color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n padding: 2px 8px;\n border-radius: 10px;\n}\n\n.at-ct-field {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 6px 0;\n border-bottom: 1px solid var(--mj-border-subtle);\n font-size: 0.78rem;\n}\n\n.at-ct-field:last-child {\n border-bottom: none;\n}\n\n.at-ct-field-label {\n color: var(--mj-text-muted);\n}\n\n.at-ct-field-value {\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.at-ct-tag-range {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-top: 8px;\n padding: 8px 10px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 6px;\n font-size: 0.75rem;\n color: var(--mj-text-primary);\n}\n\n.at-ct-tag-range i {\n color: var(--mj-brand-primary);\n}\n\n.at-ct-tag-range-bar {\n flex: 1;\n height: 6px;\n background: var(--mj-bg-surface);\n border-radius: 3px;\n position: relative;\n}\n\n.at-ct-tag-range-fill {\n position: absolute;\n height: 100%;\n background: var(--mj-brand-primary);\n border-radius: 3px;\n}\n\n.at-ct-range-suffix {\n color: var(--mj-text-muted);\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550 TAG LIBRARY TAB \u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.at-tag-lib-layout {\n display: flex;\n gap: 16px;\n}\n\n.at-tag-lib-main {\n flex: 1;\n}\n\n.at-tag-lib-sidebar {\n width: 280px;\n flex-shrink: 0;\n}\n\n.at-tag-table {\n width: 100%;\n border-collapse: collapse;\n}\n\n.at-tag-table th {\n text-align: left;\n padding: 8px 12px;\n font-size: 0.7rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--mj-text-muted);\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-elevated);\n position: sticky;\n top: 0;\n z-index: 1;\n}\n\n.at-tag-table td {\n padding: 10px 12px;\n font-size: 0.8rem;\n border-bottom: 1px solid var(--mj-border-subtle);\n color: var(--mj-text-primary);\n}\n\n.at-tag-table tr:hover td {\n background: var(--mj-bg-surface-hover);\n}\n\n.at-tag-name-cell {\n font-weight: 600;\n}\n\n.at-tag-bar {\n width: 80px;\n height: 6px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 3px;\n display: inline-block;\n vertical-align: middle;\n}\n\n.at-tag-bar-fill {\n height: 100%;\n background: var(--mj-brand-primary);\n border-radius: 3px;\n}\n\n/* Weight indicator in tag table */\n.at-weight-indicator {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.at-weight-bar {\n width: 50px;\n height: 6px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 3px;\n overflow: hidden;\n}\n\n.at-weight-bar-fill {\n height: 100%;\n border-radius: 3px;\n transition: width 0.2s ease;\n}\n\n.at-weight-bar-fill.at-weight-high {\n background: var(--mj-status-success);\n}\n\n.at-weight-bar-fill.at-weight-medium {\n background: var(--mj-status-warning);\n}\n\n.at-weight-bar-fill.at-weight-low {\n background: var(--mj-status-error);\n}\n\n.at-weight-value {\n font-size: 0.7rem;\n font-weight: 600;\n color: var(--mj-text-muted);\n min-width: 28px;\n}\n\n.at-tags-by-source {\n font-size: 0.78rem;\n}\n\n.at-tag-source-row {\n display: flex;\n justify-content: space-between;\n padding: 5px 0;\n border-bottom: 1px solid var(--mj-border-subtle);\n color: var(--mj-text-primary);\n}\n\n.at-tag-source-row:last-child {\n border-bottom: none;\n}\n\n.at-search-input {\n padding: 7px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 7px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n font-size: 0.8rem;\n width: 200px;\n outline: none;\n}\n\n.at-search-input::placeholder {\n color: var(--mj-text-disabled);\n}\n\n.at-search-input:focus {\n border-color: var(--mj-brand-primary);\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550 RUN HISTORY TAB \u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.at-run-table {\n width: 100%;\n border-collapse: collapse;\n}\n\n.at-run-table th {\n text-align: left;\n padding: 10px 14px;\n font-size: 0.7rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--mj-text-muted);\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-elevated);\n position: sticky;\n top: 0;\n z-index: 1;\n}\n\n.at-run-table td {\n padding: 12px 14px;\n font-size: 0.8rem;\n border-bottom: 1px solid var(--mj-border-subtle);\n color: var(--mj-text-primary);\n}\n\n.at-run-table tr:hover td {\n background: var(--mj-bg-surface-hover);\n cursor: pointer;\n}\n\n.at-run-status-badge {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 2px 10px;\n border-radius: 10px;\n font-size: 0.7rem;\n font-weight: 600;\n}\n\n.at-run-status-badge.complete {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n}\n\n.at-run-status-badge.failed {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error-text);\n}\n\n.at-run-status-badge.running {\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.at-run-duration {\n color: var(--mj-text-muted);\n font-size: 0.75rem;\n}\n\n.at-run-source-name {\n font-weight: 500;\n}\n\n.at-run-error-text {\n color: var(--mj-status-error-text);\n}\n\n.at-filter-select {\n padding: 7px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 7px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n font-size: 0.78rem;\n outline: none;\n}\n\n.at-filter-select:focus {\n border-color: var(--mj-brand-primary);\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550 SLIDE-IN FORM PANEL \u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.at-slide-overlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: var(--mj-bg-overlay);\n z-index: 1000;\n}\n\n.at-slide-panel {\n position: fixed;\n right: 0;\n top: 0;\n bottom: 0;\n width: 420px;\n max-width: 100vw;\n background: var(--mj-bg-surface);\n border-left: 1px solid var(--mj-border-default);\n z-index: 1001;\n display: flex;\n flex-direction: column;\n box-shadow: -4px 0 24px color-mix(in srgb, var(--mj-text-primary) 15%, transparent);\n}\n\n.at-slide-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-subtle);\n}\n\n.at-slide-header h3 {\n margin: 0;\n font-size: 1rem;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.at-slide-close {\n background: none;\n border: none;\n font-size: 1.1rem;\n color: var(--mj-text-muted);\n cursor: pointer;\n padding: 4px;\n}\n\n.at-slide-close:hover {\n color: var(--mj-text-primary);\n}\n\n.at-slide-body {\n flex: 1;\n overflow-y: auto;\n padding: 20px;\n}\n\n.at-form-group {\n margin-bottom: 16px;\n}\n\n.at-form-label {\n display: block;\n font-size: 0.78rem;\n font-weight: 600;\n color: var(--mj-text-secondary);\n margin-bottom: 6px;\n}\n\n.at-form-input,\n.at-form-select,\n.at-form-textarea {\n width: 100%;\n padding: 9px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 7px;\n background: var(--mj-bg-surface-card);\n color: var(--mj-text-primary);\n font-size: 0.82rem;\n outline: none;\n font-family: inherit;\n}\n\n.at-form-input:focus,\n.at-form-select:focus,\n.at-form-textarea:focus {\n border-color: var(--mj-brand-primary);\n}\n\n.at-form-input::placeholder,\n.at-form-textarea::placeholder {\n color: var(--mj-text-disabled);\n}\n\n.at-form-textarea {\n resize: vertical;\n}\n\n.at-form-row {\n display: flex;\n gap: 12px;\n}\n\n.at-form-actions {\n display: flex;\n gap: 8px;\n margin-top: 24px;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550 RESPONSIVE \u2550\u2550\u2550\u2550\u2550\u2550 */\n\n@media (max-width: 1100px) {\n .at-pipeline-layout {\n flex-direction: column;\n }\n\n .at-pipeline-right {\n width: 100%;\n flex-direction: row;\n }\n\n .at-tag-lib-layout {\n flex-direction: column;\n }\n\n .at-tag-lib-sidebar {\n width: 100%;\n }\n}\n\n@media (max-width: 768px) {\n .at-left-nav {\n width: 180px;\n }\n\n .at-kpi-strip {\n flex-wrap: wrap;\n }\n\n .at-kpi-card {\n min-width: 140px;\n }\n\n .at-sources-grid {\n grid-template-columns: 1fr;\n }\n\n .at-ct-grid {\n grid-template-columns: 1fr;\n }\n\n .at-slide-panel {\n width: 100vw;\n }\n}\n\n@media (max-width: 480px) {\n .at-left-nav {\n width: 56px;\n }\n\n .at-left-nav-header h2 {\n font-size: 0;\n }\n\n .at-left-nav-header h2 i {\n font-size: 1rem;\n }\n\n .at-nav-item {\n justify-content: center;\n padding: 10px;\n font-size: 0;\n }\n\n .at-nav-item i {\n font-size: 1rem;\n }\n\n .at-nav-badge {\n display: none;\n }\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n Slide-in Form Panel\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.at-slide-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.35);\n z-index: 9999;\n animation: at-fade-in 0.2s ease;\n}\n\n@keyframes at-fade-in { from { opacity: 0; } to { opacity: 1; } }\n\n.at-slide-panel {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n width: 420px;\n background: var(--mj-bg-surface);\n border-left: 1px solid var(--mj-border-default);\n box-shadow: -8px 0 40px rgba(0, 0, 0, 0.4);\n z-index: 10000;\n display: flex;\n flex-direction: column;\n animation: at-slide-in 0.25s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n@keyframes at-slide-in { from { transform: translateX(100%); } to { transform: translateX(0); } }\n\n.at-slide-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n.at-slide-header h3 {\n font-size: 1rem;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.at-slide-close {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n border: none;\n border-radius: 6px;\n cursor: pointer;\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n font-size: 0.85rem;\n transition: all 0.15s ease;\n}\n\n.at-slide-close:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n.at-slide-body {\n flex: 1;\n overflow-y: auto;\n padding: 20px;\n display: flex;\n flex-direction: column;\n gap: 16px;\n}\n\n.at-form-group {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.at-form-label {\n font-size: 0.75rem;\n font-weight: 600;\n color: var(--mj-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.3px;\n}\n\n.at-form-input,\n.at-form-select,\n.at-form-textarea {\n padding: 9px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 7px;\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-primary);\n font-size: 0.85rem;\n outline: none;\n transition: border-color 0.15s ease;\n font-family: inherit;\n}\n\n.at-form-input:focus,\n.at-form-select:focus,\n.at-form-textarea:focus {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.at-form-select {\n appearance: none;\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%2364748b' d='M3 5l3 3 3-3'/%3E%3C/svg%3E\");\n background-repeat: no-repeat;\n background-position: right 10px center;\n padding-right: 30px;\n}\n\n.at-form-textarea {\n resize: vertical;\n min-height: 70px;\n}\n\n.at-form-row {\n display: flex;\n gap: 12px;\n}\n\n.at-form-actions {\n display: flex;\n gap: 8px;\n padding-top: 8px;\n border-top: 1px solid var(--mj-border-subtle);\n margin-top: 8px;\n}\n\n.at-form-actions .at-action-btn {\n flex: 1;\n justify-content: center;\n}\n\n/* Also add empty state for Content Types (matching Sources) */\n.at-add-type-card {\n background: none;\n border: 2px dashed var(--mj-border-default);\n border-radius: 10px;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 40px;\n cursor: pointer;\n transition: all 0.15s ease;\n color: var(--mj-text-muted);\n min-height: 200px;\n}\n\n.at-add-type-card:hover {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n.at-add-type-card i {\n font-size: 1.5rem;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550 FORKED PIPELINE STAGES \u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.at-pipeline-stages-forked {\n display: flex;\n align-items: center;\n gap: 0;\n}\n\n.at-pipeline-fork {\n display: flex;\n align-items: center;\n gap: 0;\n flex: 2;\n}\n\n.at-pipeline-fork-lines {\n width: 28px;\n display: flex;\n flex-direction: column;\n gap: 12px;\n position: relative;\n flex-shrink: 0;\n}\n\n.at-pipeline-fork-line {\n height: 2px;\n background: var(--mj-border-default);\n width: 100%;\n position: relative;\n}\n\n.at-pipeline-fork-line::before {\n content: '';\n position: absolute;\n width: 2px;\n height: 12px;\n background: var(--mj-border-default);\n left: 0;\n}\n\n.at-fork-top::before {\n bottom: 0;\n left: 0;\n}\n\n.at-fork-bottom::before {\n top: 0;\n left: 0;\n}\n\n.at-pipeline-fork-branches {\n display: flex;\n flex-direction: column;\n gap: 8px;\n flex: 1;\n}\n\n.at-pipeline-fork-branches .at-pipeline-stage {\n flex: none;\n padding: 6px 0;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550 CLICKABLE FEED ITEMS \u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.at-feed-item-clickable {\n cursor: pointer;\n}\n\n.at-feed-item-clickable:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550 FEED SEARCH & PAGINATION \u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.at-feed-card {\n flex: 1;\n display: flex;\n flex-direction: column;\n min-height: 0;\n}\n\n.at-feed-header-actions {\n display: flex;\n align-items: center;\n gap: 10px;\n margin-left: auto;\n}\n\n.at-feed-sort-btn {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 3px 8px;\n border: 1px solid var(--mj-border-default);\n border-radius: 5px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n font-size: 0.68rem;\n cursor: pointer;\n transition: background 0.15s, color 0.15s;\n}\n\n.at-feed-sort-btn:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n.at-feed-count {\n font-size: 0.7rem;\n color: var(--mj-text-muted);\n}\n\n.at-feed-search-bar {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 14px;\n border-bottom: 1px solid var(--mj-border-subtle);\n background: var(--mj-bg-surface-card);\n}\n\n.at-feed-search-icon {\n color: var(--mj-text-disabled);\n font-size: 0.72rem;\n flex-shrink: 0;\n}\n\n.at-feed-search-input {\n flex: 1;\n border: none;\n background: transparent;\n font-size: 0.78rem;\n color: var(--mj-text-primary);\n outline: none;\n padding: 4px 0;\n min-width: 0;\n}\n\n.at-feed-search-input::placeholder {\n color: var(--mj-text-disabled);\n}\n\n.at-feed-search-clear {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 18px;\n height: 18px;\n padding: 0;\n border: none;\n border-radius: 50%;\n background: var(--mj-border-default);\n color: var(--mj-text-muted);\n cursor: pointer;\n font-size: 9px;\n flex-shrink: 0;\n}\n\n.at-feed-search-clear:hover {\n background: var(--mj-border-strong);\n color: var(--mj-text-primary);\n}\n\n.at-feed-scroll-body {\n overflow-y: auto;\n min-height: 0;\n flex: 1;\n}\n\n.at-feed-item-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n overflow: hidden;\n}\n\n.at-feed-item-content .at-feed-item-name {\n font-size: 0.82rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.at-feed-item-source-label {\n font-size: 0.7rem;\n font-weight: 500;\n color: var(--mj-brand-primary);\n}\n\n.at-feed-pagination {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 12px;\n padding: 8px 14px;\n border-top: 1px solid var(--mj-border-subtle);\n background: var(--mj-bg-surface-card);\n}\n\n.at-feed-pagination-label {\n font-size: 0.72rem;\n color: var(--mj-text-muted);\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550 CLICKABLE SOURCE CARDS \u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.at-source-card-clickable {\n cursor: pointer;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550 FORM HINT \u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.at-form-hint {\n font-size: 0.68rem;\n color: var(--mj-text-muted);\n font-style: italic;\n margin-top: 2px;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550 DETAIL PANEL (wider) \u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.at-detail-panel {\n width: 500px;\n}\n\n/* \u2500\u2500 Detail: Item header \u2500\u2500 */\n\n.at-detail-item-header {\n margin-bottom: 8px;\n}\n\n.at-detail-item-name {\n font-size: 1.05rem;\n font-weight: 700;\n color: var(--mj-text-primary);\n margin: 0 0 6px 0;\n word-break: break-word;\n}\n\n.at-detail-badges {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n}\n\n.at-detail-badge {\n padding: 2px 10px;\n border-radius: 10px;\n font-size: 0.7rem;\n font-weight: 600;\n}\n\n.at-detail-badge-source {\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.at-detail-badge-type {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-secondary);\n}\n\n.at-detail-badge-file {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n\n.at-detail-badge-status-active {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n}\n\n.at-detail-badge-status-error {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error-text);\n}\n\n.at-detail-badge-status-inactive {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-disabled);\n}\n\n/* \u2500\u2500 Detail: Sections \u2500\u2500 */\n\n.at-detail-section {\n margin-bottom: 4px;\n}\n\n.at-detail-section-label {\n font-size: 0.72rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n color: var(--mj-text-muted);\n margin-bottom: 6px;\n}\n\n.at-detail-link {\n font-size: 0.8rem;\n color: var(--mj-brand-primary);\n text-decoration: none;\n word-break: break-all;\n}\n\n.at-detail-link:hover {\n text-decoration: underline;\n}\n\n/* \u2500\u2500 Detail: Text preview \u2500\u2500 */\n\n.at-detail-text-preview {\n max-height: 200px;\n overflow-y: auto;\n padding: 10px 12px;\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 6px;\n font-size: 0.78rem;\n font-family: 'SF Mono', 'Cascadia Code', 'Menlo', monospace;\n color: var(--mj-text-primary);\n white-space: pre-wrap;\n word-break: break-word;\n line-height: 1.5;\n}\n\n/* \u2500\u2500 Detail: Tags \u2500\u2500 */\n\n.at-detail-tags {\n display: flex;\n flex-wrap: wrap;\n gap: 5px;\n}\n\n/* \u2500\u2500 Detail: Meta grid \u2500\u2500 */\n\n.at-detail-meta-grid {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 8px;\n overflow: hidden;\n}\n\n.at-detail-meta-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 8px 12px;\n border-bottom: 1px solid var(--mj-border-subtle);\n font-size: 0.78rem;\n}\n\n.at-detail-meta-row:last-child {\n border-bottom: none;\n}\n\n.at-detail-meta-key {\n color: var(--mj-text-muted);\n font-weight: 500;\n flex-shrink: 0;\n margin-right: 12px;\n}\n\n.at-detail-meta-value {\n color: var(--mj-text-primary);\n text-align: right;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.at-detail-meta-mono {\n font-family: 'SF Mono', 'Cascadia Code', 'Menlo', monospace;\n font-size: 0.72rem;\n}\n\n/* \u2500\u2500 Detail: Actions \u2500\u2500 */\n\n.at-detail-actions {\n display: flex;\n gap: 8px;\n padding-top: 8px;\n border-top: 1px solid var(--mj-border-subtle);\n margin-top: 8px;\n}\n\n.at-detail-actions .at-action-btn {\n flex: 1;\n justify-content: center;\n}\n\n/* \u2500\u2500 Detail: Source header \u2500\u2500 */\n\n.at-detail-source-header {\n display: flex;\n align-items: center;\n gap: 12px;\n margin-bottom: 8px;\n}\n\n/* \u2500\u2500 Detail: Stats strip \u2500\u2500 */\n\n.at-detail-stats-strip {\n display: flex;\n gap: 12px;\n flex-wrap: wrap;\n}\n\n.at-detail-stat {\n flex: 1;\n min-width: 60px;\n text-align: center;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 8px;\n padding: 8px 6px;\n}\n\n.at-detail-stat-value {\n font-size: 1rem;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.at-detail-stat-label {\n font-size: 0.62rem;\n color: var(--mj-text-muted);\n margin-top: 2px;\n}\n\n/* \u2500\u2500 Detail: Content Library \u2500\u2500 */\n\n.at-detail-content-list {\n max-height: 250px;\n overflow-y: auto;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 8px;\n}\n\n.at-detail-content-item {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n border-bottom: 1px solid var(--mj-border-subtle);\n font-size: 0.78rem;\n cursor: pointer;\n transition: background 0.1s ease;\n}\n\n.at-detail-content-item:last-child {\n border-bottom: none;\n}\n\n.at-detail-content-item:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.at-detail-content-item-name {\n flex: 1;\n font-weight: 500;\n color: var(--mj-text-primary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.at-detail-content-item-tags {\n font-size: 0.68rem;\n color: var(--mj-text-muted);\n white-space: nowrap;\n}\n\n.at-detail-content-item-time {\n font-size: 0.68rem;\n color: var(--mj-text-muted);\n white-space: nowrap;\n}\n\n/* \u2500\u2500 Detail: Run history \u2500\u2500 */\n\n.at-detail-run-history {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 8px;\n max-height: 200px;\n overflow-y: auto;\n}\n\n.at-detail-run-row {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n border-bottom: 1px solid var(--mj-border-subtle);\n font-size: 0.75rem;\n}\n\n.at-detail-run-row:last-child {\n border-bottom: none;\n}\n\n.at-detail-run-time {\n color: var(--mj-text-secondary);\n flex: 1;\n}\n\n.at-detail-run-duration {\n color: var(--mj-text-muted);\n}\n\n.at-detail-run-items {\n color: var(--mj-text-muted);\n}\n\n@media (max-width: 600px) {\n .at-slide-panel {\n width: 100%;\n }\n\n .at-detail-panel {\n width: 100%;\n }\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n TAXONOMY GOVERNANCE TAB\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n/* \u2500\u2500 Sub-tab strip \u2500\u2500 */\n\n.at-tax-tab-strip {\n display: flex;\n border-bottom: 2px solid var(--mj-border-default);\n padding: 0 20px;\n gap: 0;\n flex-shrink: 0;\n}\n\n.at-tax-tab {\n padding: 10px 20px;\n font-size: 0.78rem;\n font-weight: 500;\n color: var(--mj-text-muted);\n cursor: pointer;\n border-bottom: 2px solid transparent;\n margin-bottom: -2px;\n transition: all 0.15s;\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.at-tax-tab:hover {\n color: var(--mj-text-secondary);\n}\n\n.at-tax-tab.active {\n color: var(--mj-brand-primary);\n border-bottom-color: var(--mj-brand-primary);\n font-weight: 600;\n}\n\n.at-tax-tab-badge {\n font-size: 0.62rem;\n font-weight: 600;\n padding: 1px 7px;\n border-radius: 10px;\n}\n\n.at-tax-badge-warning {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.at-tax-badge-error {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n/* \u2500\u2500 Tree View: Split layout \u2500\u2500 */\n\n.at-tax-split-view {\n display: flex;\n gap: 0;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 10px;\n height: calc(100vh - 320px);\n min-height: 400px;\n overflow: hidden;\n}\n\n.at-tax-tree-panel {\n width: 40%;\n border-right: 1px solid var(--mj-border-default);\n display: flex;\n flex-direction: column;\n}\n\n.at-tax-tree-toolbar {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 12px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.at-tax-toolbar-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 30px;\n height: 30px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n cursor: pointer;\n font-size: 0.8rem;\n transition: background 0.15s, color 0.15s;\n}\n\n.at-tax-toolbar-btn:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n.at-tax-toolbar-btn.active {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n}\n\n.at-tax-tree-body {\n flex: 1;\n overflow-y: auto;\n padding: 8px 0;\n}\n\n.at-tax-tree-node {\n padding: 6px 16px;\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 0.78rem;\n cursor: pointer;\n transition: background 0.1s;\n line-height: 1.4;\n}\n\n.at-tax-tree-node:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.at-tax-node-selected {\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n}\n\n.at-tax-node-drag-over {\n background: color-mix(in srgb, var(--mj-brand-primary) 20%, var(--mj-bg-surface));\n outline: 2px dashed var(--mj-brand-primary);\n outline-offset: -2px;\n}\n\n.at-tax-node-multi-selected {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n}\n\n.at-tax-tree-add-child {\n margin-left: auto;\n opacity: 0;\n font-size: 0.7rem;\n color: var(--mj-text-muted);\n cursor: pointer;\n padding: 2px 6px;\n border-radius: 4px;\n transition: opacity 0.15s, color 0.15s, background 0.15s;\n}\n\n.at-tax-tree-node:hover .at-tax-tree-add-child {\n opacity: 1;\n}\n\n.at-tax-tree-add-child:hover {\n color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n}\n\n.at-tax-tree-checkbox {\n width: 14px;\n height: 14px;\n cursor: pointer;\n accent-color: var(--mj-brand-primary);\n flex-shrink: 0;\n}\n\n.at-tax-tree-saving-overlay {\n position: absolute;\n inset: 0;\n background: color-mix(in srgb, var(--mj-bg-surface) 75%, transparent);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10;\n backdrop-filter: blur(1px);\n}\n\n.at-tax-create-context {\n font-size: 0.8rem;\n color: var(--mj-text-muted);\n margin-bottom: 12px;\n padding: 6px 10px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 6px;\n}\n\n.at-tax-tree-arrow {\n width: 16px;\n font-size: 0.55rem;\n color: var(--mj-text-muted);\n flex-shrink: 0;\n text-align: center;\n cursor: pointer;\n}\n\n.at-tax-arrow-collapsed::before {\n content: \"\\25B6\";\n}\n\n.at-tax-arrow-expanded::before {\n content: \"\\25BC\";\n}\n\n.at-tax-arrow-leaf {\n visibility: hidden;\n}\n\n.at-tax-health-dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n flex-shrink: 0;\n}\n\n.at-tax-health-dot.green {\n background: var(--mj-status-success);\n}\n\n.at-tax-health-dot.yellow {\n background: var(--mj-status-warning);\n}\n\n.at-tax-health-dot.red {\n background: var(--mj-status-error);\n}\n\n.at-tax-tree-label {\n flex: 1;\n color: var(--mj-text-primary);\n}\n\n.at-tax-tree-label-selected {\n font-weight: 700;\n}\n\n.at-tax-tree-count {\n font-size: 0.65rem;\n color: var(--mj-text-muted);\n margin-left: 4px;\n}\n\n/* \u2500\u2500 Details panel \u2500\u2500 */\n\n.at-tax-details-panel {\n width: 60%;\n display: flex;\n flex-direction: column;\n overflow-y: auto;\n}\n\n.at-tax-details-header {\n padding: 20px 24px 0;\n}\n\n.at-tax-breadcrumb {\n font-size: 0.7rem;\n color: var(--mj-text-muted);\n margin-bottom: 8px;\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.at-tax-bc-link {\n color: var(--mj-brand-primary);\n cursor: pointer;\n}\n\n.at-tax-bc-link:hover {\n text-decoration: underline;\n}\n\n.at-tax-bc-sep {\n color: var(--mj-border-default);\n}\n\n.at-tax-bc-current {\n color: var(--mj-text-secondary);\n font-weight: 600;\n}\n\n.at-tax-details-title {\n font-size: 1.2rem;\n font-weight: 700;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 4px;\n}\n\n.at-tax-edit-icon {\n font-size: 0.75rem;\n color: var(--mj-text-muted);\n cursor: pointer;\n}\n\n.at-tax-edit-icon:hover {\n color: var(--mj-brand-primary);\n}\n\n.at-tax-details-desc {\n font-size: 0.78rem;\n color: var(--mj-text-secondary);\n line-height: 1.5;\n margin-bottom: 16px;\n padding: 8px 12px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 6px;\n border: 1px solid var(--mj-border-subtle);\n}\n\n.at-tax-edit-form {\n margin-bottom: 16px;\n}\n\n/* \u2500\u2500 Stats row \u2500\u2500 */\n\n.at-tax-stats-row {\n display: flex;\n gap: 12px;\n flex-wrap: wrap;\n margin-bottom: 16px;\n padding: 0 24px;\n}\n\n.at-tax-stat-item {\n display: flex;\n flex-direction: column;\n align-items: center;\n padding: 10px 14px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 8px;\n min-width: 72px;\n}\n\n.at-tax-stat-value {\n font-size: 1.1rem;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.at-tax-stat-date {\n font-size: 0.8rem;\n}\n\n.at-tax-stat-label {\n font-size: 0.62rem;\n color: var(--mj-text-muted);\n margin-top: 2px;\n}\n\n/* \u2500\u2500 Action toolbar \u2500\u2500 */\n\n.at-tax-action-toolbar {\n display: flex;\n gap: 8px;\n padding: 0 24px;\n margin-bottom: 20px;\n flex-wrap: wrap;\n}\n\n.at-tax-action-btn {\n padding: 6px 14px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n background: var(--mj-bg-surface);\n font-size: 0.72rem;\n font-weight: 500;\n color: var(--mj-text-secondary);\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 5px;\n transition: all 0.15s;\n}\n\n.at-tax-action-btn:hover {\n background: var(--mj-bg-surface-hover);\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n.at-tax-action-danger:hover {\n border-color: var(--mj-status-error);\n color: var(--mj-status-error);\n background: color-mix(in srgb, var(--mj-status-error) 8%, var(--mj-bg-surface));\n}\n\n/* \u2500\u2500 Detail sections \u2500\u2500 */\n\n.at-tax-detail-section {\n padding: 0 24px 20px;\n}\n\n.at-tax-section-title {\n font-size: 0.7rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: var(--mj-text-muted);\n margin-bottom: 10px;\n}\n\n.at-tax-child-chips {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n}\n\n.at-tax-child-chip {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 10px;\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-default);\n border-radius: 16px;\n font-size: 0.72rem;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.at-tax-child-chip:hover {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.at-tax-chip-count {\n font-size: 0.6rem;\n background: var(--mj-border-default);\n color: var(--mj-text-muted);\n padding: 0 5px;\n border-radius: 8px;\n}\n\n/* \u2500\u2500 Recent items \u2500\u2500 */\n\n.at-tax-recent-list {\n list-style: none;\n}\n\n.at-tax-recent-item {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 8px 0;\n border-bottom: 1px solid var(--mj-border-subtle);\n font-size: 0.78rem;\n}\n\n.at-tax-recent-item:last-child {\n border-bottom: none;\n}\n\n.at-tax-recent-icon {\n width: 28px;\n height: 28px;\n border-radius: 6px;\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 0.72rem;\n flex-shrink: 0;\n}\n\n.at-tax-recent-name {\n flex: 1;\n color: var(--mj-text-primary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.at-tax-recent-weight {\n font-size: 0.68rem;\n font-weight: 600;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-sunken);\n padding: 2px 8px;\n border-radius: 10px;\n}\n\n.at-tax-recent-date {\n font-size: 0.65rem;\n color: var(--mj-text-muted);\n}\n\n/* \u2500\u2500 Health bar \u2500\u2500 */\n\n.at-tax-health-bar {\n display: flex;\n align-items: center;\n gap: 20px;\n padding: 12px 20px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 8px;\n margin-top: 16px;\n flex-wrap: wrap;\n}\n\n.at-tax-health-label {\n font-size: 0.72rem;\n font-weight: 600;\n color: var(--mj-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.04em;\n}\n\n.at-tax-health-stat {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 0.78rem;\n}\n\n.at-tax-dot {\n width: 10px;\n height: 10px;\n border-radius: 50%;\n}\n\n.at-tax-dot-total {\n background: var(--mj-text-secondary);\n}\n\n.at-tax-dot-healthy {\n background: var(--mj-status-success);\n}\n\n.at-tax-dot-attention {\n background: var(--mj-status-warning);\n}\n\n.at-tax-dot-orphaned {\n background: var(--mj-status-error);\n}\n\n.at-tax-dot-duplicates {\n background: var(--mj-status-info);\n}\n\n.at-tax-health-value {\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.at-tax-val-success {\n color: var(--mj-status-success);\n}\n\n.at-tax-val-warning {\n color: var(--mj-status-warning);\n}\n\n.at-tax-val-error {\n color: var(--mj-status-error);\n}\n\n.at-tax-val-info {\n color: var(--mj-status-info);\n}\n\n.at-tax-health-text {\n color: var(--mj-text-muted);\n}\n\n/* \u2550\u2550\u2550\u2550 Duplicates sub-tab \u2550\u2550\u2550\u2550 */\n\n.at-tax-dup-stats-bar {\n display: flex;\n gap: 24px;\n margin-bottom: 16px;\n align-items: center;\n}\n\n.at-tax-dup-stat {\n font-size: 0.78rem;\n color: var(--mj-text-secondary);\n}\n\n.at-tax-dup-stat strong {\n font-size: 1.1rem;\n color: var(--mj-text-primary);\n margin-right: 4px;\n}\n\n.at-tax-dup-high strong {\n color: var(--mj-status-error);\n}\n\n.at-tax-dup-moderate strong {\n color: var(--mj-status-warning);\n}\n\n.at-tax-dup-list {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.at-tax-dup-card {\n display: flex;\n align-items: center;\n gap: 16px;\n padding: 14px 20px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 8px;\n transition: border-color 0.15s;\n}\n\n.at-tax-dup-card:hover {\n border-color: var(--mj-brand-primary);\n}\n\n.at-tax-dup-card.at-tax-dup-high {\n border-left: 3px solid var(--mj-status-error);\n}\n\n.at-tax-dup-card.at-tax-dup-moderate {\n border-left: 3px solid var(--mj-status-warning);\n}\n\n.at-tax-dup-tag {\n font-size: 0.82rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n min-width: 120px;\n padding: 6px 12px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 6px;\n text-align: center;\n}\n\n.at-tax-dup-arrow {\n font-size: 0.82rem;\n color: var(--mj-text-muted);\n flex-shrink: 0;\n}\n\n.at-tax-dup-similarity {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 4px;\n min-width: 100px;\n}\n\n.at-tax-sim-bar-bg {\n width: 100%;\n height: 6px;\n background: var(--mj-border-default);\n border-radius: 3px;\n overflow: hidden;\n}\n\n.at-tax-sim-bar-fill {\n height: 100%;\n border-radius: 3px;\n transition: width 0.3s;\n}\n\n.at-tax-sim-bar-fill.high {\n background: var(--mj-status-error);\n}\n\n.at-tax-sim-bar-fill.moderate {\n background: var(--mj-status-warning);\n}\n\n.at-tax-sim-percent {\n font-size: 0.78rem;\n font-weight: 700;\n}\n\n.at-tax-sim-percent.high {\n color: var(--mj-status-error);\n}\n\n.at-tax-sim-percent.moderate {\n color: var(--mj-status-warning);\n}\n\n.at-tax-dup-actions {\n display: flex;\n gap: 6px;\n flex-shrink: 0;\n}\n\n.at-tax-dup-btn {\n padding: 5px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n background: var(--mj-bg-surface);\n font-size: 0.68rem;\n font-weight: 500;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.15s;\n white-space: nowrap;\n}\n\n.at-tax-dup-btn:hover {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n.at-tax-dup-btn-primary {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-color: var(--mj-brand-primary);\n}\n\n.at-tax-dup-btn-primary:hover {\n background: var(--mj-brand-primary-hover);\n color: var(--mj-text-inverse);\n}\n\n/* \u2550\u2550\u2550\u2550 Orphans sub-tab \u2550\u2550\u2550\u2550 */\n\n.at-tax-orphan-toolbar {\n display: flex;\n align-items: center;\n gap: 12px;\n margin-bottom: 16px;\n flex-wrap: wrap;\n}\n\n.at-tax-orphan-count {\n font-size: 0.82rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.at-tax-orphan-desc {\n font-size: 0.78rem;\n color: var(--mj-text-muted);\n}\n\n.at-tax-orphan-bulk {\n margin-left: auto;\n display: flex;\n gap: 8px;\n}\n\n.at-tax-bulk-btn {\n padding: 6px 14px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n background: var(--mj-bg-surface);\n font-size: 0.72rem;\n font-weight: 500;\n color: var(--mj-text-secondary);\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 5px;\n transition: all 0.15s;\n}\n\n.at-tax-bulk-btn:hover {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n.at-tax-bulk-danger:hover {\n border-color: var(--mj-status-error);\n color: var(--mj-status-error);\n}\n\n.at-tax-orphan-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));\n gap: 12px;\n}\n\n.at-tax-orphan-card {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 8px;\n padding: 16px;\n transition: all 0.15s;\n display: flex;\n flex-direction: column;\n gap: 10px;\n border-top: 3px solid var(--mj-status-error);\n}\n\n.at-tax-orphan-card:hover {\n border-color: var(--mj-brand-primary);\n}\n\n.at-tax-orphan-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n}\n\n.at-tax-orphan-name {\n font-size: 0.82rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.at-tax-orphan-checkbox {\n width: 16px;\n height: 16px;\n accent-color: var(--mj-brand-primary);\n}\n\n.at-tax-orphan-stats {\n display: flex;\n gap: 12px;\n font-size: 0.72rem;\n color: var(--mj-text-muted);\n}\n\n.at-tax-orphan-stats strong {\n color: var(--mj-text-secondary);\n}\n\n.at-tax-orphan-dates {\n display: flex;\n justify-content: space-between;\n font-size: 0.65rem;\n color: var(--mj-text-muted);\n}\n\n.at-tax-orphan-actions {\n display: flex;\n gap: 6px;\n margin-top: 4px;\n}\n\n.at-tax-orphan-btn {\n flex: 1;\n padding: 5px 8px;\n border: 1px solid var(--mj-border-default);\n border-radius: 5px;\n background: var(--mj-bg-surface);\n font-size: 0.68rem;\n font-weight: 500;\n color: var(--mj-text-secondary);\n cursor: pointer;\n text-align: center;\n transition: all 0.15s;\n}\n\n.at-tax-orphan-btn:hover {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n.at-tax-orphan-delete:hover {\n border-color: var(--mj-status-error);\n color: var(--mj-status-error);\n}\n\n/* \u2550\u2550\u2550\u2550 Treemap sub-tab \u2550\u2550\u2550\u2550 */\n\n.at-tax-treemap-kpi-strip {\n display: flex;\n gap: 20px;\n margin-bottom: 16px;\n flex-wrap: wrap;\n}\n\n.at-tax-treemap-kpi {\n padding: 10px 18px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 8px;\n display: flex;\n flex-direction: column;\n align-items: center;\n min-width: 120px;\n}\n\n.at-tax-treemap-kpi-value {\n font-size: 1.2rem;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.at-tax-treemap-kpi-label {\n font-size: 0.65rem;\n color: var(--mj-text-muted);\n margin-top: 2px;\n}\n\n.at-tax-treemap-container {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 10px;\n padding: 8px;\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));\n grid-auto-rows: 80px;\n gap: 4px;\n min-height: 340px;\n}\n\n.at-tax-treemap-cell {\n border-radius: 6px;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-inverse);\n font-weight: 600;\n font-size: 0.78rem;\n cursor: pointer;\n transition: all 0.15s;\n position: relative;\n overflow: hidden;\n}\n\n.at-tax-treemap-cell:hover {\n transform: scale(1.02);\n z-index: 2;\n}\n\n.at-tax-cell-name {\n font-size: 0.78rem;\n}\n\n.at-tax-cell-count {\n font-size: 0.65rem;\n opacity: 0.85;\n font-weight: 400;\n}\n\n/* Treemap color families */\n.at-tm-blue-1 { background: color-mix(in srgb, var(--mj-brand-primary) 90%, black); }\n.at-tm-blue-2 { background: var(--mj-brand-primary); }\n.at-tm-blue-3 { background: color-mix(in srgb, var(--mj-brand-primary) 75%, white); }\n.at-tm-blue-4 { background: color-mix(in srgb, var(--mj-brand-primary) 55%, white); }\n\n.at-tm-green-1 { background: color-mix(in srgb, var(--mj-status-success) 90%, black); }\n.at-tm-green-2 { background: var(--mj-status-success); }\n.at-tm-green-3 { background: color-mix(in srgb, var(--mj-status-success) 60%, white); color: var(--mj-text-primary); }\n\n.at-tm-purple-1 { background: color-mix(in srgb, var(--mj-status-info) 90%, black); }\n.at-tm-purple-2 { background: var(--mj-status-info); }\n.at-tm-purple-3 { background: color-mix(in srgb, var(--mj-status-info) 65%, white); }\n\n.at-tm-orange-1 { background: color-mix(in srgb, var(--mj-status-warning) 90%, black); }\n.at-tm-orange-2 { background: var(--mj-status-warning); }\n.at-tm-orange-3 { background: color-mix(in srgb, var(--mj-status-warning) 60%, white); color: var(--mj-text-primary); }\n\n/* \u2550\u2550\u2550\u2550 Audit Log sub-tab \u2550\u2550\u2550\u2550 */\n\n.at-tax-audit-filters {\n display: flex;\n align-items: center;\n gap: 16px;\n margin-bottom: 16px;\n padding: 12px 16px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 8px;\n flex-wrap: wrap;\n}\n\n.at-tax-audit-filter-label {\n font-size: 0.72rem;\n font-weight: 600;\n color: var(--mj-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.04em;\n}\n\n.at-tax-audit-checkbox-group {\n display: flex;\n gap: 12px;\n flex-wrap: wrap;\n}\n\n.at-tax-audit-checkbox {\n display: flex;\n align-items: center;\n gap: 4px;\n font-size: 0.72rem;\n color: var(--mj-text-secondary);\n cursor: pointer;\n}\n\n.at-tax-audit-checkbox input {\n accent-color: var(--mj-brand-primary);\n}\n\n.at-tax-audit-timeline {\n position: relative;\n padding-left: 32px;\n}\n\n.at-tax-audit-timeline::before {\n content: '';\n position: absolute;\n left: 14px;\n top: 0;\n bottom: 0;\n width: 2px;\n background: var(--mj-border-default);\n}\n\n.at-tax-audit-event {\n position: relative;\n padding: 10px 16px;\n margin-bottom: 4px;\n display: flex;\n align-items: flex-start;\n gap: 12px;\n border-radius: 8px;\n transition: background 0.1s;\n}\n\n.at-tax-audit-event:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.at-tax-audit-event-icon {\n width: 28px;\n height: 28px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 0.68rem;\n flex-shrink: 0;\n position: absolute;\n left: -32px;\n top: 10px;\n z-index: 1;\n}\n\n.at-tax-audit-event-icon.created {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.at-tax-audit-event-icon.merged {\n background: color-mix(in srgb, var(--mj-status-info) 15%, var(--mj-bg-surface));\n color: var(--mj-status-info);\n}\n\n.at-tax-audit-event-icon.moved {\n background: color-mix(in srgb, var(--mj-status-info) 15%, var(--mj-bg-surface));\n color: var(--mj-status-info);\n}\n\n.at-tax-audit-event-icon.deleted {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.at-tax-audit-event-icon.renamed {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.at-tax-audit-event-body {\n flex: 1;\n}\n\n.at-tax-audit-event-desc {\n font-size: 0.78rem;\n color: var(--mj-text-primary);\n line-height: 1.5;\n}\n\n.at-tax-tag-ref {\n background: var(--mj-bg-surface-sunken);\n padding: 1px 6px;\n border-radius: 4px;\n font-weight: 600;\n font-size: 0.72rem;\n border: 1px solid var(--mj-border-default);\n}\n\n.at-tax-audit-event-meta {\n font-size: 0.65rem;\n color: var(--mj-text-muted);\n margin-top: 2px;\n display: flex;\n gap: 12px;\n}\n\n/* \u2500\u2500 Taxonomy responsive \u2500\u2500 */\n\n@media (max-width: 1100px) {\n .at-tax-split-view {\n flex-direction: column;\n }\n\n .at-tax-tree-panel {\n width: 100%;\n max-height: 300px;\n border-right: none;\n border-bottom: 1px solid var(--mj-border-default);\n }\n\n .at-tax-details-panel {\n width: 100%;\n }\n}\n\n@media (max-width: 768px) {\n .at-tax-dup-card {\n flex-wrap: wrap;\n }\n\n .at-tax-orphan-grid {\n grid-template-columns: 1fr;\n }\n}\n\n/* \u2500\u2500 Pipeline Config Widget \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.at-config-card {\n margin-top: 12px;\n}\n\n.at-config-body {\n display: flex;\n flex-direction: column;\n gap: 10px;\n padding: 12px !important;\n}\n\n.at-config-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n}\n\n.at-config-label {\n font-size: 0.75rem;\n font-weight: 500;\n color: var(--mj-text-secondary);\n min-width: 90px;\n flex-shrink: 0;\n}\n\n.at-config-control {\n display: flex;\n align-items: center;\n gap: 6px;\n flex: 1;\n justify-content: flex-end;\n}\n\n.at-config-input {\n width: 70px;\n padding: 3px 6px;\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n font-size: 0.75rem;\n text-align: right;\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n}\n\n.at-config-input:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n}\n\n.at-config-slider {\n flex: 1;\n max-width: 100px;\n accent-color: var(--mj-brand-primary);\n height: 4px;\n}\n\n.at-config-value {\n font-size: 0.68rem;\n color: var(--mj-text-muted);\n min-width: 40px;\n text-align: right;\n}\n\n.at-config-divider {\n height: 1px;\n background: var(--mj-border-default);\n margin: 4px 0;\n}\n\n.at-config-section-label {\n font-size: 0.68rem;\n font-weight: 600;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.3px;\n}\n\n/* Toggle Switch */\n.at-config-toggle {\n position: relative;\n display: inline-block;\n cursor: pointer;\n}\n\n.at-config-toggle input {\n display: none;\n}\n\n.at-toggle-track {\n display: block;\n width: 32px;\n height: 18px;\n background: var(--mj-border-strong);\n border-radius: 9px;\n transition: background 0.2s ease;\n position: relative;\n}\n\n.at-config-toggle input:checked + .at-toggle-track {\n background: var(--mj-brand-primary);\n}\n\n.at-toggle-thumb {\n position: absolute;\n top: 2px;\n left: 2px;\n width: 14px;\n height: 14px;\n background: var(--mj-bg-surface);\n border-radius: 50%;\n transition: transform 0.2s ease;\n box-shadow: 0 1px 3px rgba(0,0,0,0.15);\n}\n\n.at-config-toggle input:checked + .at-toggle-track .at-toggle-thumb {\n transform: translateX(14px);\n}\n\n/* \u2500\u2500 Schedule Indicator on Source Cards \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.at-schedule-indicator {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 3px 10px;\n margin-top: 6px;\n border-radius: 12px;\n font-size: 0.68rem;\n font-weight: 600;\n color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 20%, var(--mj-border-default));\n cursor: pointer;\n transition: all 0.15s ease;\n width: fit-content;\n}\n\n.at-schedule-indicator i {\n font-size: 0.62rem;\n}\n\n.at-schedule-indicator:hover {\n background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n border-color: color-mix(in srgb, var(--mj-status-error) 30%, var(--mj-border-default));\n}\n\n/* Schedule button in source card actions */\n.at-source-schedule-btn:hover {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n/* \u2500\u2500 Schedule Dialog \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.at-schedule-overlay {\n position: fixed;\n inset: 0;\n z-index: 1000;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--mj-bg-overlay, rgba(0, 0, 0, 0.4));\n}\n\n.at-schedule-dialog {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg, 12px);\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.16);\n width: 420px;\n max-width: 90vw;\n}\n\n.at-schedule-dialog-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.at-schedule-dialog-header h3 {\n display: flex;\n align-items: center;\n gap: 8px;\n margin: 0;\n font-size: 15px;\n font-weight: 650;\n color: var(--mj-text-primary);\n}\n\n.at-schedule-dialog-header h3 i {\n color: var(--mj-brand-primary);\n}\n\n.at-schedule-dialog-close {\n background: none;\n border: none;\n cursor: pointer;\n color: var(--mj-text-muted);\n font-size: 16px;\n padding: 4px;\n line-height: 1;\n transition: color 0.15s;\n}\n\n.at-schedule-dialog-close:hover {\n color: var(--mj-text-primary);\n}\n\n.at-schedule-dialog-body {\n padding: 20px;\n display: flex;\n flex-direction: column;\n gap: 16px;\n}\n\n.at-schedule-field label {\n display: block;\n font-size: 11.5px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.04em;\n margin-bottom: 6px;\n}\n\n.at-schedule-source-name {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 13.5px;\n font-weight: 600;\n color: var(--mj-text-primary);\n padding: 8px 12px;\n background: var(--mj-bg-surface-card);\n border-radius: var(--mj-radius-sm, 6px);\n border: 1px solid var(--mj-border-subtle);\n}\n\n.at-schedule-source-name i {\n color: var(--mj-text-muted);\n}\n\n.at-schedule-action-name {\n font-size: 13px;\n color: var(--mj-text-secondary);\n padding: 8px 12px;\n background: var(--mj-bg-surface-card);\n border-radius: var(--mj-radius-sm, 6px);\n border: 1px solid var(--mj-border-subtle);\n}\n\n.at-schedule-cron-input {\n width: 100%;\n font-family: 'SF Mono', 'Fira Code', 'Consolas', monospace;\n font-size: 13px;\n letter-spacing: 0.02em;\n}\n\n.at-schedule-cron-preview {\n display: flex;\n align-items: center;\n gap: 6px;\n margin-top: 6px;\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.at-schedule-cron-preview i {\n font-size: 11px;\n color: var(--mj-brand-primary);\n}\n\n.at-schedule-toggle-row {\n display: flex;\n flex-direction: row;\n align-items: center;\n gap: 10px;\n}\n\n.at-schedule-toggle-row label {\n margin-bottom: 0;\n}\n\n.at-schedule-dialog-footer {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 14px 20px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550 D4: Status Badges for Content Items \u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.at-status-badge {\n display: inline-block;\n padding: 1px 6px;\n border-radius: 4px;\n font-size: 0.6rem;\n font-weight: 600;\n white-space: nowrap;\n letter-spacing: 0.02em;\n}\n\n.at-status-badge-complete {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success-text);\n}\n\n.at-status-badge-processing {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning-text);\n}\n\n.at-status-badge-failed {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error-text);\n}\n\n.at-status-badge-pending {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550 D4/D7: Source Detail Controls \u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.at-detail-section-header-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 8px;\n gap: 8px;\n flex-wrap: wrap;\n}\n\n.at-detail-section-controls {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.at-detail-filter-select {\n padding: 4px 8px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n font-size: 0.72rem;\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n cursor: pointer;\n}\n\n.at-retry-btn {\n font-size: 0.7rem !important;\n padding: 4px 8px !important;\n background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface)) !important;\n color: var(--mj-status-error-text) !important;\n border: 1px solid color-mix(in srgb, var(--mj-status-error) 20%, var(--mj-border-default)) !important;\n}\n\n.at-retry-btn:hover {\n background: color-mix(in srgb, var(--mj-status-error) 18%, var(--mj-bg-surface)) !important;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550 D7: Pagination \u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.at-detail-pagination {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 12px;\n padding: 10px 0 4px;\n border-top: 1px solid var(--mj-border-subtle);\n margin-top: 4px;\n}\n\n.at-page-btn {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 10px;\n font-size: 0.72rem;\n font-weight: 500;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.12s ease;\n}\n\n.at-page-btn:hover:not(:disabled) {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n.at-page-btn:disabled {\n opacity: 0.4;\n cursor: default;\n}\n\n.at-page-info {\n font-size: 0.72rem;\n color: var(--mj-text-muted);\n font-weight: 500;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550 Confirmation Dialog \u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.at-confirm-message {\n font-size: 13.5px;\n color: var(--mj-text-secondary);\n line-height: 1.5;\n margin: 0;\n}\n\n.at-danger-btn {\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n border: none;\n border-radius: var(--mj-radius-sm, 6px);\n padding: 7px 14px;\n font-size: 12.5px;\n font-weight: 600;\n cursor: pointer;\n transition: background 0.15s;\n}\n\n.at-danger-btn:hover {\n background: var(--mj-status-error-text);\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550 Treemap Drill-In \u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.at-tax-treemap-cell-clickable {\n cursor: pointer;\n transition: transform 0.15s, box-shadow 0.15s;\n}\n\n.at-tax-treemap-cell-clickable:hover {\n transform: scale(1.02);\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);\n z-index: 1;\n}\n\n.at-tax-drillin-overlay {\n position: fixed;\n inset: 0;\n z-index: 1000;\n display: flex;\n align-items: flex-start;\n justify-content: flex-end;\n background: var(--mj-bg-overlay, rgba(0, 0, 0, 0.4));\n}\n\n.at-tax-drillin-panel {\n background: var(--mj-bg-surface);\n border-left: 1px solid var(--mj-border-default);\n width: 420px;\n max-width: 90vw;\n height: 100vh;\n display: flex;\n flex-direction: column;\n box-shadow: -4px 0 24px rgba(0, 0, 0, 0.12);\n}\n\n.at-tax-drillin-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.at-tax-drillin-header h3 {\n display: flex;\n align-items: center;\n gap: 8px;\n margin: 0;\n font-size: 15px;\n font-weight: 650;\n color: var(--mj-text-primary);\n}\n\n.at-tax-drillin-header h3 i {\n color: var(--mj-brand-primary);\n}\n\n.at-tax-drillin-body {\n flex: 1;\n overflow-y: auto;\n padding: 20px;\n}\n\n.at-tax-drillin-footer {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 14px 20px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n/* D3/D8: Clickable run history rows */\n.at-run-row-clickable {\n cursor: pointer;\n transition: background 0.12s ease;\n}\n\n.at-run-row-clickable:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.at-run-row-selected {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface)) !important;\n border-left: 3px solid var(--mj-brand-primary);\n}\n\n/* D2: Error text in detail tables */\n.run-error-text {\n color: var(--mj-status-error);\n font-weight: 600;\n}\n\n/* \u2500\u2500 Content Item Duplicates Section (G3) \u2500\u2500 */\n\n.at-dedup-section {\n margin-top: 24px;\n border-top: 1px solid var(--mj-border-default);\n padding-top: 20px;\n}\n\n.at-dedup-header {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n margin-bottom: 16px;\n}\n\n.at-dedup-title {\n margin: 0;\n font-size: 1rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.at-dedup-subtitle {\n font-size: 0.78rem;\n color: var(--mj-text-muted);\n}\n\n.at-dedup-list {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.at-dedup-card {\n display: flex;\n align-items: center;\n gap: 16px;\n padding: 14px 16px;\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n background: var(--mj-bg-surface);\n transition: border-color 0.15s;\n}\n\n.at-dedup-card:hover {\n border-color: var(--mj-border-strong);\n}\n\n.at-dedup-pair {\n display: flex;\n align-items: center;\n gap: 12px;\n flex: 1;\n min-width: 0;\n}\n\n.at-dedup-item {\n display: flex;\n flex-direction: column;\n min-width: 0;\n flex: 1;\n}\n\n.at-dedup-item-name {\n font-size: 0.85rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.at-dedup-item-source {\n font-size: 0.72rem;\n color: var(--mj-text-muted);\n}\n\n.at-dedup-vs {\n color: var(--mj-text-muted);\n font-size: 0.75rem;\n flex-shrink: 0;\n}\n\n.at-dedup-meta {\n display: flex;\n flex-direction: column;\n align-items: flex-end;\n gap: 3px;\n flex-shrink: 0;\n}\n\n.at-dedup-score {\n font-size: 0.78rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.at-dedup-method {\n font-size: 0.65rem;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.3px;\n}\n\n.at-dedup-actions {\n display: flex;\n gap: 6px;\n flex-shrink: 0;\n}\n\n.at-dedup-confirm {\n font-size: 0.75rem !important;\n padding: 4px 10px !important;\n}\n\n.at-dedup-dismiss {\n font-size: 0.75rem !important;\n padding: 4px 10px !important;\n}\n\n.at-dedup-empty {\n text-align: center;\n padding: 32px 16px;\n color: var(--mj-text-muted);\n}\n\n.at-dedup-empty i {\n font-size: 1.5rem;\n margin-bottom: 8px;\n color: var(--mj-status-success);\n}\n\n.at-dedup-empty p {\n margin: 8px 0 0;\n font-size: 0.82rem;\n}\n"] }]
7959
7959
  }], null, null); })();
7960
7960
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(AutotaggingPipelineResourceComponent, { className: "AutotaggingPipelineResourceComponent", filePath: "src/AI/components/autotagging/autotagging-pipeline-resource.component.ts", lineNumber: 323 }); })();
7961
7961
  export function LoadAutotaggingPipelineResource() {