@memberjunction/ng-entity-viewer 5.24.0 → 5.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2850,11 +2850,11 @@ export class ViewConfigPanelComponent {
2850
2850
  i0.ɵɵproperty("IsOpen", ctx.showDeleteConfirm)("Message", "Are you sure you want to delete '" + ctx.viewName + "'?");
2851
2851
  i0.ɵɵadvance();
2852
2852
  i0.ɵɵproperty("IsOpen", ctx.showFilterModeSwitchConfirm)("Message", ctx.filterMode === "smart" ? "Switching to Traditional mode will clear your smart filter prompt." : "Switching to Smart mode will clear your traditional filter rules.");
2853
- } }, dependencies: [i1.NgSelectOption, i1.ɵNgSelectMultipleOption, i1.DefaultValueAccessor, i1.NumberValueAccessor, i1.CheckboxControlValueAccessor, i1.SelectControlValueAccessor, i1.NgControlStatus, i1.MinValidator, i1.MaxValidator, i1.NgModel, i2.AggregateSetupDialogComponent, i3.ConfirmDialogComponent], styles: ["\n\n.panel-backdrop[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.3);\n z-index: 1000;\n animation: _ngcontent-%COMP%_fadeIn 0.2s ease;\n}\n\n@keyframes _ngcontent-%COMP%_fadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n\n\n.config-panel[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n right: 0;\n width: 450px;\n min-width: 360px;\n max-width: min(800px, 100vw);\n height: 100%;\n background: var(--mj-bg-surface);\n box-shadow: -4px 0 24px rgba(0, 0, 0, 0.15);\n z-index: 1001;\n display: flex;\n flex-direction: column;\n transform: translateX(100%);\n transition: transform 0.25s ease, width 0s;\n}\n\n.config-panel.open[_ngcontent-%COMP%] {\n transform: translateX(0);\n}\n\n.config-panel.resizing[_ngcontent-%COMP%] {\n transition: none;\n user-select: none;\n}\n\n\n\n.resize-handle[_ngcontent-%COMP%] {\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n width: 6px;\n cursor: ew-resize;\n z-index: 10;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.resize-handle[_ngcontent-%COMP%]:hover, \n.config-panel.resizing[_ngcontent-%COMP%] .resize-handle[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n}\n\n.resize-grip[_ngcontent-%COMP%] {\n width: 3px;\n height: 40px;\n background: var(--mj-border-strong);\n border-radius: 3px;\n opacity: 0;\n transition: opacity 0.2s ease;\n}\n\n.resize-handle[_ngcontent-%COMP%]:hover .resize-grip[_ngcontent-%COMP%], \n.config-panel.resizing[_ngcontent-%COMP%] .resize-grip[_ngcontent-%COMP%] {\n opacity: 1;\n background: var(--mj-brand-primary);\n}\n\n\n\n.panel-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n flex-shrink: 0;\n}\n\n.header-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.header-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n.close-btn[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n border: none;\n background: transparent;\n border-radius: 8px;\n cursor: pointer;\n color: var(--mj-text-muted);\n transition: all 0.15s ease;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.close-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n\n\n.tab-nav[_ngcontent-%COMP%] {\n display: flex;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n flex-shrink: 0;\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n}\n\n.tab-btn[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 12px 16px;\n border: none;\n background: transparent;\n cursor: pointer;\n color: var(--mj-text-muted);\n font-size: 13px;\n font-weight: 500;\n transition: all 0.15s ease;\n position: relative;\n white-space: nowrap;\n}\n\n.tab-btn[_ngcontent-%COMP%]:hover {\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-hover);\n}\n\n.tab-btn.active[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n font-weight: 600;\n}\n\n.tab-btn.active[_ngcontent-%COMP%]::after {\n content: '';\n position: absolute;\n bottom: 0;\n left: 8px;\n right: 8px;\n height: 2px;\n background: var(--mj-brand-primary);\n border-radius: 2px 2px 0 0;\n}\n\n.tab-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n\n.tab-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 18px;\n height: 18px;\n padding: 0 5px;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-radius: 9px;\n font-size: 11px;\n font-weight: 600;\n}\n\n\n\n.tab-nav.icon-only[_ngcontent-%COMP%] .tab-btn[_ngcontent-%COMP%] {\n padding: 12px 8px;\n}\n\n\n\n.panel-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n}\n\n.tab-content[_ngcontent-%COMP%] {\n padding: 16px;\n}\n\n\n\n.config-section[_ngcontent-%COMP%] {\n margin-bottom: 20px;\n}\n\n.section-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 0;\n margin-bottom: 8px;\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.section-header[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-size: 14px;\n}\n\n.column-count[_ngcontent-%COMP%] {\n margin-left: auto;\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n padding: 2px 8px;\n border-radius: 10px;\n font-size: 12px;\n font-weight: 500;\n}\n\n\n\n.column-search[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n margin-bottom: 8px;\n}\n\n.column-search[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-text-disabled);\n font-size: 12px;\n}\n\n.column-search[_ngcontent-%COMP%] input[_ngcontent-%COMP%] {\n flex: 1;\n border: none;\n outline: none;\n font-size: 13px;\n background: transparent;\n color: var(--mj-text-primary);\n}\n\n.column-search[_ngcontent-%COMP%] input[_ngcontent-%COMP%]::placeholder {\n color: var(--mj-text-disabled);\n}\n\n\n\n.column-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n\n\n.column-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 10px;\n border-radius: 8px;\n transition: background 0.15s ease;\n cursor: default;\n}\n\n.column-item[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-card);\n}\n\n.column-item.hidden[_ngcontent-%COMP%] {\n opacity: 0.7;\n}\n\n.column-item.hidden[_ngcontent-%COMP%]:hover {\n opacity: 1;\n}\n\n.column-item.dragging[_ngcontent-%COMP%] {\n opacity: 0.4;\n}\n\n.column-item.drop-target[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n}\n\n\n\n.drop-indicator[_ngcontent-%COMP%] {\n height: 2px;\n background: var(--mj-brand-primary);\n border-radius: 1px;\n margin: 0 10px;\n}\n\n\n\n.drag-handle[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n cursor: grab;\n color: var(--mj-text-disabled);\n font-size: 12px;\n padding: 4px 2px;\n}\n\n.drag-handle[_ngcontent-%COMP%]:active {\n cursor: grabbing;\n}\n\n.column-item[_ngcontent-%COMP%]:hover .drag-handle[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n}\n\n\n\n.column-name[_ngcontent-%COMP%] {\n flex: 1;\n font-size: 13px;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.alias-indicator[_ngcontent-%COMP%] {\n font-size: 10px;\n color: var(--mj-brand-primary);\n margin-left: 4px;\n}\n\n.format-indicator[_ngcontent-%COMP%] {\n font-size: 10px;\n color: var(--mj-status-warning);\n margin-left: 4px;\n}\n\n\n\n.column-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 2px;\n opacity: 0;\n transition: opacity 0.15s ease;\n}\n\n.column-item[_ngcontent-%COMP%]:hover .column-actions[_ngcontent-%COMP%] {\n opacity: 1;\n}\n\n.action-btn[_ngcontent-%COMP%] {\n width: 26px;\n height: 26px;\n border: none;\n background: transparent;\n border-radius: 6px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n transition: all 0.15s ease;\n}\n\n.action-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-secondary);\n}\n\n.action-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.3;\n cursor: not-allowed;\n}\n\n.action-btn.hide-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error);\n}\n\n.action-btn.show-btn[_ngcontent-%COMP%] {\n opacity: 0;\n}\n\n.column-item[_ngcontent-%COMP%]:hover .action-btn.show-btn[_ngcontent-%COMP%] {\n opacity: 1;\n}\n\n.action-btn.show-btn[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.action-btn.format-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-status-warning-bg);\n color: var(--mj-status-warning);\n}\n\n.action-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n}\n\n\n\n.empty-list[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 16px;\n color: var(--mj-text-muted);\n font-size: 13px;\n}\n\n.empty-list[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-text-disabled);\n}\n\n\n\n.format-editor[_ngcontent-%COMP%] {\n padding: 0;\n}\n\n.format-editor-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 16px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n}\n\n.back-btn[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n border: none;\n background: var(--mj-bg-surface-sunken);\n border-radius: 8px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-secondary);\n transition: all 0.15s ease;\n}\n\n.back-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-active);\n color: var(--mj-text-primary);\n}\n\n.format-editor-title[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n\n\n.format-section[_ngcontent-%COMP%] {\n padding: 16px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.format-section-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 12px;\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n}\n\n.format-section-header[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n}\n\n\n\n.format-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 8px 0;\n}\n\n.format-row[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-text-secondary);\n}\n\n.format-row.alias-info[_ngcontent-%COMP%] {\n padding: 4px 0;\n}\n\n.muted-text[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.clear-alias-btn[_ngcontent-%COMP%] {\n width: 24px;\n height: 24px;\n border: none;\n background: transparent;\n border-radius: 4px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-disabled);\n transition: all 0.15s ease;\n}\n\n.clear-alias-btn[_ngcontent-%COMP%]:hover {\n color: var(--mj-status-error);\n}\n\n\n\n.format-input[_ngcontent-%COMP%] {\n padding: 6px 10px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n font-size: 13px;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n transition: border-color 0.15s ease;\n}\n\n.format-input[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n}\n\n.format-input.small[_ngcontent-%COMP%] {\n width: 60px;\n text-align: center;\n}\n\n.format-select[_ngcontent-%COMP%] {\n padding: 6px 10px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n font-size: 13px;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n cursor: pointer;\n}\n\n.format-select[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n}\n\n\n\n.color-input[_ngcontent-%COMP%] {\n width: 36px;\n height: 28px;\n padding: 2px;\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n cursor: pointer;\n background: var(--mj-bg-surface);\n}\n\n\n\n.alignment-toggle[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n background: var(--mj-bg-surface-card);\n border-radius: 8px;\n padding: 3px;\n border: 1px solid var(--mj-border-default);\n}\n\n.align-btn[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 6px;\n border: none;\n background: transparent;\n border-radius: 6px;\n cursor: pointer;\n color: var(--mj-text-muted);\n transition: all 0.15s ease;\n}\n\n.align-btn[_ngcontent-%COMP%]:hover {\n color: var(--mj-text-secondary);\n}\n\n.align-btn.active[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);\n}\n\n\n\n.style-buttons[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n margin-bottom: 12px;\n}\n\n.style-btn[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n border-radius: 6px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n transition: all 0.15s ease;\n}\n\n.style-btn[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-border-strong);\n color: var(--mj-text-secondary);\n}\n\n.style-btn.active[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n\n\n.format-preview-section[_ngcontent-%COMP%] {\n padding: 16px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.preview-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 12px;\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n}\n\n.preview-header[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n}\n\n.preview-table[_ngcontent-%COMP%] {\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n overflow: hidden;\n}\n\n.preview-header-cell[_ngcontent-%COMP%] {\n padding: 8px 12px;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n text-transform: uppercase;\n letter-spacing: 0.3px;\n}\n\n.preview-cell[_ngcontent-%COMP%] {\n padding: 8px 12px;\n font-size: 13px;\n color: var(--mj-text-primary);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.preview-cell[_ngcontent-%COMP%]:last-child {\n border-bottom: none;\n}\n\n\n\n.format-actions[_ngcontent-%COMP%] {\n padding: 16px;\n}\n\n.clear-format-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n background: var(--mj-bg-surface);\n cursor: pointer;\n font-size: 13px;\n color: var(--mj-text-secondary);\n transition: all 0.15s ease;\n}\n\n.clear-format-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-status-error-bg);\n border-color: var(--mj-status-error);\n color: var(--mj-status-error);\n}\n\n\n\n.sorting-section[_ngcontent-%COMP%] {\n padding: 0;\n}\n\n.sorting-header[_ngcontent-%COMP%] {\n margin-bottom: 12px;\n}\n\n.sorting-description[_ngcontent-%COMP%], \n.aggregates-description[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 13px;\n color: var(--mj-text-muted);\n line-height: 1.5;\n}\n\n\n\n.add-sort-btn[_ngcontent-%COMP%], \n.add-aggregate-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 16px;\n width: 100%;\n border: 2px dashed var(--mj-border-default);\n border-radius: 10px;\n background: transparent;\n cursor: pointer;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-muted);\n transition: all 0.15s ease;\n margin-bottom: 12px;\n}\n\n.add-sort-btn[_ngcontent-%COMP%]:hover:not(:disabled), \n.add-aggregate-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, var(--mj-bg-surface));\n}\n\n.add-sort-btn[_ngcontent-%COMP%]:disabled, \n.add-aggregate-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n\n\n.sort-items-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 6px;\n margin-bottom: 12px;\n}\n\n.sort-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 10px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n transition: all 0.15s ease;\n}\n\n.sort-item[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-border-strong);\n}\n\n.sort-item.dragging[_ngcontent-%COMP%] {\n opacity: 0.4;\n}\n\n.sort-item.drop-target[_ngcontent-%COMP%] {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, var(--mj-bg-surface));\n}\n\n\n\n.sort-drop-indicator[_ngcontent-%COMP%] {\n height: 2px;\n background: var(--mj-brand-primary);\n border-radius: 1px;\n margin: 0 10px;\n}\n\n\n\n.sort-priority-badge[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-radius: 6px;\n font-size: 11px;\n font-weight: 700;\n flex-shrink: 0;\n}\n\n\n\n.sort-drag-handle[_ngcontent-%COMP%] {\n cursor: grab;\n color: var(--mj-text-disabled);\n padding: 2px;\n font-size: 12px;\n}\n\n.sort-drag-handle[_ngcontent-%COMP%]:active {\n cursor: grabbing;\n}\n\n.sort-item[_ngcontent-%COMP%]:hover .sort-drag-handle[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n}\n\n\n\n.sort-field-dropdown[_ngcontent-%COMP%] {\n flex: 1;\n padding: 6px 10px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n font-size: 13px;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n cursor: pointer;\n min-width: 0;\n}\n\n.sort-field-dropdown[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n}\n\n\n\n.sort-direction-toggle[_ngcontent-%COMP%] {\n display: flex;\n background: var(--mj-bg-surface-sunken);\n border-radius: 6px;\n padding: 2px;\n gap: 2px;\n}\n\n.direction-btn[_ngcontent-%COMP%] {\n width: 28px;\n height: 28px;\n border: none;\n background: transparent;\n border-radius: 5px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n font-size: 12px;\n transition: all 0.15s ease;\n}\n\n.direction-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n color: var(--mj-text-secondary);\n}\n\n.direction-btn.active[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);\n}\n\n.direction-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.3;\n cursor: not-allowed;\n}\n\n\n\n.sort-remove-btn[_ngcontent-%COMP%] {\n width: 28px;\n height: 28px;\n border: none;\n background: transparent;\n border-radius: 6px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-disabled);\n font-size: 12px;\n transition: all 0.15s ease;\n}\n\n.sort-remove-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error);\n}\n\n.sort-remove-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.3;\n cursor: not-allowed;\n}\n\n\n\n.sort-hint[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n padding: 10px 12px;\n background: var(--mj-bg-surface-card);\n border-radius: 8px;\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.sort-hint[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-text-disabled);\n margin-top: 1px;\n}\n\n\n\n.sort-empty-state[_ngcontent-%COMP%], \n.aggregates-empty-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n padding: 32px 16px;\n color: var(--mj-text-muted);\n text-align: center;\n}\n\n.sort-empty-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%], \n.aggregates-empty-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 32px;\n opacity: 0.4;\n}\n\n.sort-empty-state[_ngcontent-%COMP%] span[_ngcontent-%COMP%], \n.aggregates-empty-state[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 500;\n}\n\n.sort-empty-hint[_ngcontent-%COMP%], \n.empty-hint[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 13px;\n color: var(--mj-text-disabled);\n}\n\n\n\n.filter-mode-selector[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-bottom: 16px;\n}\n\n.filter-mode-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 14px;\n border: 2px solid var(--mj-border-default);\n border-radius: 10px;\n background: var(--mj-bg-surface);\n cursor: pointer;\n transition: all 0.15s ease;\n text-align: left;\n}\n\n.filter-mode-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n border-color: var(--mj-border-strong);\n}\n\n.filter-mode-btn.active[_ngcontent-%COMP%] {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, var(--mj-bg-surface));\n}\n\n.filter-mode-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.mode-icon[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 8px;\n font-size: 16px;\n color: var(--mj-text-muted);\n flex-shrink: 0;\n}\n\n.filter-mode-btn.active[_ngcontent-%COMP%] .mode-icon[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.mode-content[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.mode-title[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.mode-subtitle[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.mode-check[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n font-size: 14px;\n}\n\n\n\n.smart-filter-section[_ngcontent-%COMP%] {\n padding: 0;\n}\n\n.smart-filter-input-container[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n padding: 12px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n margin-bottom: 12px;\n}\n\n.smart-filter-icon[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n padding-top: 4px;\n color: var(--mj-brand-primary);\n font-size: 16px;\n}\n\n.smart-filter-textarea[_ngcontent-%COMP%] {\n flex: 1;\n border: none;\n outline: none;\n resize: vertical;\n font-size: 14px;\n font-family: inherit;\n color: var(--mj-text-primary);\n background: transparent;\n min-height: 60px;\n}\n\n.smart-filter-textarea[_ngcontent-%COMP%]::placeholder {\n color: var(--mj-text-disabled);\n}\n\n.smart-filter-textarea[_ngcontent-%COMP%]:disabled {\n color: var(--mj-text-muted);\n}\n\n\n\n.smart-filter-explanation[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n padding: 10px 12px;\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) 25%, var(--mj-bg-surface));\n border-radius: 8px;\n margin-bottom: 12px;\n font-size: 13px;\n color: var(--mj-brand-primary);\n}\n\n.smart-filter-explanation[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n margin-top: 2px;\n}\n\n\n\n.smart-filter-examples[_ngcontent-%COMP%] {\n margin-bottom: 12px;\n}\n\n.examples-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 8px;\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-muted);\n}\n\n.examples-header[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-status-warning);\n}\n\n.example-chips[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n}\n\n.example-chip[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 20px;\n background: var(--mj-bg-surface);\n cursor: pointer;\n font-size: 12px;\n color: var(--mj-text-secondary);\n transition: all 0.15s ease;\n}\n\n.example-chip[_ngcontent-%COMP%]:hover:not(:disabled) {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, var(--mj-bg-surface));\n}\n\n.example-chip[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.example-chip[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 11px;\n}\n\n\n\n.smart-filter-tip[_ngcontent-%COMP%], \n.traditional-filter-tip[_ngcontent-%COMP%], \n.aggregates-tip[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n padding: 10px 12px;\n background: var(--mj-bg-surface-card);\n border-radius: 8px;\n font-size: 12px;\n color: var(--mj-text-muted);\n margin-top: 12px;\n}\n\n.smart-filter-tip[_ngcontent-%COMP%] i[_ngcontent-%COMP%], \n.traditional-filter-tip[_ngcontent-%COMP%] i[_ngcontent-%COMP%], \n.aggregates-tip[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-text-disabled);\n margin-top: 1px;\n}\n\n\n\n.traditional-filter-section[_ngcontent-%COMP%] {\n padding: 0;\n}\n\n.filter-summary-container[_ngcontent-%COMP%] {\n margin-bottom: 12px;\n}\n\n.filter-summary[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 14px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n}\n\n.summary-info[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.filter-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 22px;\n height: 22px;\n padding: 0 6px;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-radius: 11px;\n font-size: 12px;\n font-weight: 600;\n}\n\n.summary-text[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-text-primary);\n font-weight: 500;\n}\n\n.summary-text.no-filters[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-weight: 400;\n}\n\n.summary-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n}\n\n.summary-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n background: var(--mj-bg-surface);\n cursor: pointer;\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n transition: all 0.15s ease;\n}\n\n.summary-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n border-color: var(--mj-border-strong);\n}\n\n.summary-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.summary-btn.clear-btn[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-status-error);\n color: var(--mj-status-error);\n}\n\n.summary-btn.primary[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.summary-btn.primary[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n border-color: var(--mj-brand-primary-hover);\n}\n\n\n\n.aggregates-section[_ngcontent-%COMP%] {\n padding: 0;\n}\n\n.aggregates-header[_ngcontent-%COMP%] {\n margin-bottom: 12px;\n}\n\n\n\n.aggregates-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 6px;\n margin-bottom: 12px;\n}\n\n.aggregate-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 12px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n transition: all 0.15s ease;\n}\n\n.aggregate-item[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-border-strong);\n}\n\n.aggregate-item.disabled[_ngcontent-%COMP%] {\n opacity: 0.5;\n}\n\n\n\n.agg-icon[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n border-radius: 8px;\n color: var(--mj-brand-primary);\n font-size: 14px;\n flex-shrink: 0;\n}\n\n\n\n.agg-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.agg-label[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.agg-details[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-top: 2px;\n}\n\n.agg-type[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n\n.agg-smart-badge[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n font-size: 11px;\n}\n\n\n\n.agg-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 2px;\n opacity: 0;\n transition: opacity 0.15s ease;\n}\n\n.aggregate-item[_ngcontent-%COMP%]:hover .agg-actions[_ngcontent-%COMP%] {\n opacity: 1;\n}\n\n.agg-action-btn[_ngcontent-%COMP%] {\n width: 26px;\n height: 26px;\n border: none;\n background: transparent;\n border-radius: 6px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n font-size: 12px;\n transition: all 0.15s ease;\n}\n\n.agg-action-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-secondary);\n}\n\n.agg-action-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.3;\n cursor: not-allowed;\n}\n\n.agg-action-btn.toggle-btn.enabled[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n.agg-action-btn.remove-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error);\n}\n\n.agg-action-btn.edit-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n\n\n.aggregates-summary[_ngcontent-%COMP%] {\n display: flex;\n gap: 16px;\n padding: 10px 12px;\n background: var(--mj-bg-surface-card);\n border-radius: 8px;\n margin-bottom: 12px;\n}\n\n.aggregates-summary[_ngcontent-%COMP%] .summary-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.aggregates-summary[_ngcontent-%COMP%] .summary-item[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-text-disabled);\n}\n\n\n\n.form-group[_ngcontent-%COMP%] {\n margin-bottom: 16px;\n}\n\n.form-group[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n display: block;\n margin-bottom: 6px;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n.form-input[_ngcontent-%COMP%] {\n width: 100%;\n padding: 8px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n font-size: 14px;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n transition: border-color 0.15s ease;\n box-sizing: border-box;\n}\n\n.form-input[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n}\n\n.form-input.invalid[_ngcontent-%COMP%] {\n border-color: var(--mj-status-error);\n}\n\n.form-textarea[_ngcontent-%COMP%] {\n resize: vertical;\n min-height: 60px;\n font-family: inherit;\n}\n\n.validation-error[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-status-error);\n margin-top: 4px;\n}\n\n\n\n.checkbox-label[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n cursor: pointer;\n}\n\n.checkbox-label[_ngcontent-%COMP%] input[type=\"checkbox\"][_ngcontent-%COMP%] {\n margin-top: 3px;\n flex-shrink: 0;\n}\n\n.checkbox-text[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.checkbox-text[_ngcontent-%COMP%] strong[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-text-primary);\n}\n\n.checkbox-text[_ngcontent-%COMP%] small[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n\n\n.danger-zone[_ngcontent-%COMP%] .section-header[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n.danger-zone[_ngcontent-%COMP%] .section-header[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n.delete-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 16px;\n border: 1px solid var(--mj-status-error);\n border-radius: 8px;\n background: var(--mj-status-error-bg);\n cursor: pointer;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-status-error);\n transition: all 0.15s ease;\n}\n\n.delete-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n}\n\n\n\n.validation-banner[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 16px;\n background: var(--mj-status-error-bg);\n border-top: 1px solid var(--mj-status-error);\n font-size: 13px;\n color: var(--mj-status-error);\n flex-shrink: 0;\n}\n\n\n\n.panel-footer[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 14px 20px;\n border-top: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n flex-shrink: 0;\n}\n\n.footer-left[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n}\n\n.footer-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 9px 18px;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n background: var(--mj-bg-surface);\n cursor: pointer;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n transition: all 0.15s ease;\n}\n\n.footer-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n border-color: var(--mj-border-strong);\n}\n\n.footer-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.footer-btn.primary[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.footer-btn.primary[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n border-color: var(--mj-brand-primary-hover);\n}\n\n.footer-btn.cancel-btn[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-card);\n}\n\n.footer-btn.cancel-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-active);\n}\n\n\n\n@media (max-width: 480px) {\n .config-panel[_ngcontent-%COMP%] {\n width: 100vw;\n min-width: auto;\n }\n\n .resize-handle[_ngcontent-%COMP%] {\n display: none;\n }\n}"] });
2853
+ } }, dependencies: [i1.NgSelectOption, i1.ɵNgSelectMultipleOption, i1.DefaultValueAccessor, i1.NumberValueAccessor, i1.CheckboxControlValueAccessor, i1.SelectControlValueAccessor, i1.NgControlStatus, i1.MinValidator, i1.MaxValidator, i1.NgModel, i2.AggregateSetupDialogComponent, i3.ConfirmDialogComponent], styles: ["\n\n.panel-backdrop[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.3);\n z-index: 1200; \n\n animation: _ngcontent-%COMP%_fadeIn 0.2s ease;\n}\n\n@keyframes _ngcontent-%COMP%_fadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n\n\n.config-panel[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n right: 0;\n width: 450px;\n min-width: 360px;\n max-width: min(800px, 100vw);\n height: 100%;\n background: var(--mj-bg-surface);\n box-shadow: -4px 0 24px rgba(0, 0, 0, 0.15);\n z-index: 1201; \n\n display: flex;\n flex-direction: column;\n transform: translateX(100%);\n transition: transform 0.25s ease, width 0s;\n}\n\n.config-panel.open[_ngcontent-%COMP%] {\n transform: translateX(0);\n}\n\n.config-panel.resizing[_ngcontent-%COMP%] {\n transition: none;\n user-select: none;\n}\n\n\n\n.resize-handle[_ngcontent-%COMP%] {\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n width: 6px;\n cursor: ew-resize;\n z-index: 10;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.resize-handle[_ngcontent-%COMP%]:hover, \n.config-panel.resizing[_ngcontent-%COMP%] .resize-handle[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n}\n\n.resize-grip[_ngcontent-%COMP%] {\n width: 3px;\n height: 40px;\n background: var(--mj-border-strong);\n border-radius: 3px;\n opacity: 0;\n transition: opacity 0.2s ease;\n}\n\n.resize-handle[_ngcontent-%COMP%]:hover .resize-grip[_ngcontent-%COMP%], \n.config-panel.resizing[_ngcontent-%COMP%] .resize-grip[_ngcontent-%COMP%] {\n opacity: 1;\n background: var(--mj-brand-primary);\n}\n\n\n\n.panel-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n flex-shrink: 0;\n}\n\n.header-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.header-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n.close-btn[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n border: none;\n background: transparent;\n border-radius: 8px;\n cursor: pointer;\n color: var(--mj-text-muted);\n transition: all 0.15s ease;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.close-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n\n\n.tab-nav[_ngcontent-%COMP%] {\n display: flex;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n flex-shrink: 0;\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n}\n\n.tab-btn[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 12px 16px;\n border: none;\n background: transparent;\n cursor: pointer;\n color: var(--mj-text-muted);\n font-size: 13px;\n font-weight: 500;\n transition: all 0.15s ease;\n position: relative;\n white-space: nowrap;\n}\n\n.tab-btn[_ngcontent-%COMP%]:hover {\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-hover);\n}\n\n.tab-btn.active[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n font-weight: 600;\n}\n\n.tab-btn.active[_ngcontent-%COMP%]::after {\n content: '';\n position: absolute;\n bottom: 0;\n left: 8px;\n right: 8px;\n height: 2px;\n background: var(--mj-brand-primary);\n border-radius: 2px 2px 0 0;\n}\n\n.tab-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n\n.tab-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 18px;\n height: 18px;\n padding: 0 5px;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-radius: 9px;\n font-size: 11px;\n font-weight: 600;\n}\n\n\n\n.tab-nav.icon-only[_ngcontent-%COMP%] .tab-btn[_ngcontent-%COMP%] {\n padding: 12px 8px;\n}\n\n\n\n.panel-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n}\n\n.tab-content[_ngcontent-%COMP%] {\n padding: 16px;\n}\n\n\n\n.config-section[_ngcontent-%COMP%] {\n margin-bottom: 20px;\n}\n\n.section-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 0;\n margin-bottom: 8px;\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.section-header[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-size: 14px;\n}\n\n.column-count[_ngcontent-%COMP%] {\n margin-left: auto;\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n padding: 2px 8px;\n border-radius: 10px;\n font-size: 12px;\n font-weight: 500;\n}\n\n\n\n.column-search[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n margin-bottom: 8px;\n}\n\n.column-search[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-text-disabled);\n font-size: 12px;\n}\n\n.column-search[_ngcontent-%COMP%] input[_ngcontent-%COMP%] {\n flex: 1;\n border: none;\n outline: none;\n font-size: 13px;\n background: transparent;\n color: var(--mj-text-primary);\n}\n\n.column-search[_ngcontent-%COMP%] input[_ngcontent-%COMP%]::placeholder {\n color: var(--mj-text-disabled);\n}\n\n\n\n.column-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n\n\n.column-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 10px;\n border-radius: 8px;\n transition: background 0.15s ease;\n cursor: default;\n}\n\n.column-item[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-card);\n}\n\n.column-item.hidden[_ngcontent-%COMP%] {\n opacity: 0.7;\n}\n\n.column-item.hidden[_ngcontent-%COMP%]:hover {\n opacity: 1;\n}\n\n.column-item.dragging[_ngcontent-%COMP%] {\n opacity: 0.4;\n}\n\n.column-item.drop-target[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n}\n\n\n\n.drop-indicator[_ngcontent-%COMP%] {\n height: 2px;\n background: var(--mj-brand-primary);\n border-radius: 1px;\n margin: 0 10px;\n}\n\n\n\n.drag-handle[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n cursor: grab;\n color: var(--mj-text-disabled);\n font-size: 12px;\n padding: 4px 2px;\n}\n\n.drag-handle[_ngcontent-%COMP%]:active {\n cursor: grabbing;\n}\n\n.column-item[_ngcontent-%COMP%]:hover .drag-handle[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n}\n\n\n\n.column-name[_ngcontent-%COMP%] {\n flex: 1;\n font-size: 13px;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.alias-indicator[_ngcontent-%COMP%] {\n font-size: 10px;\n color: var(--mj-brand-primary);\n margin-left: 4px;\n}\n\n.format-indicator[_ngcontent-%COMP%] {\n font-size: 10px;\n color: var(--mj-status-warning);\n margin-left: 4px;\n}\n\n\n\n.column-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 2px;\n opacity: 0;\n transition: opacity 0.15s ease;\n}\n\n.column-item[_ngcontent-%COMP%]:hover .column-actions[_ngcontent-%COMP%] {\n opacity: 1;\n}\n\n.action-btn[_ngcontent-%COMP%] {\n width: 26px;\n height: 26px;\n border: none;\n background: transparent;\n border-radius: 6px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n transition: all 0.15s ease;\n}\n\n.action-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-secondary);\n}\n\n.action-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.3;\n cursor: not-allowed;\n}\n\n.action-btn.hide-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error);\n}\n\n.action-btn.show-btn[_ngcontent-%COMP%] {\n opacity: 0;\n}\n\n.column-item[_ngcontent-%COMP%]:hover .action-btn.show-btn[_ngcontent-%COMP%] {\n opacity: 1;\n}\n\n.action-btn.show-btn[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.action-btn.format-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-status-warning-bg);\n color: var(--mj-status-warning);\n}\n\n.action-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n}\n\n\n\n.empty-list[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 16px;\n color: var(--mj-text-muted);\n font-size: 13px;\n}\n\n.empty-list[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-text-disabled);\n}\n\n\n\n.format-editor[_ngcontent-%COMP%] {\n padding: 0;\n}\n\n.format-editor-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 16px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n}\n\n.back-btn[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n border: none;\n background: var(--mj-bg-surface-sunken);\n border-radius: 8px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-secondary);\n transition: all 0.15s ease;\n}\n\n.back-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-active);\n color: var(--mj-text-primary);\n}\n\n.format-editor-title[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n\n\n.format-section[_ngcontent-%COMP%] {\n padding: 16px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.format-section-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 12px;\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n}\n\n.format-section-header[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n}\n\n\n\n.format-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 8px 0;\n}\n\n.format-row[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-text-secondary);\n}\n\n.format-row.alias-info[_ngcontent-%COMP%] {\n padding: 4px 0;\n}\n\n.muted-text[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.clear-alias-btn[_ngcontent-%COMP%] {\n width: 24px;\n height: 24px;\n border: none;\n background: transparent;\n border-radius: 4px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-disabled);\n transition: all 0.15s ease;\n}\n\n.clear-alias-btn[_ngcontent-%COMP%]:hover {\n color: var(--mj-status-error);\n}\n\n\n\n.format-input[_ngcontent-%COMP%] {\n padding: 6px 10px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n font-size: 13px;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n transition: border-color 0.15s ease;\n}\n\n.format-input[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n}\n\n.format-input.small[_ngcontent-%COMP%] {\n width: 60px;\n text-align: center;\n}\n\n.format-select[_ngcontent-%COMP%] {\n padding: 6px 10px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n font-size: 13px;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n cursor: pointer;\n}\n\n.format-select[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n}\n\n\n\n.color-input[_ngcontent-%COMP%] {\n width: 36px;\n height: 28px;\n padding: 2px;\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n cursor: pointer;\n background: var(--mj-bg-surface);\n}\n\n\n\n.alignment-toggle[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n background: var(--mj-bg-surface-card);\n border-radius: 8px;\n padding: 3px;\n border: 1px solid var(--mj-border-default);\n}\n\n.align-btn[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 6px;\n border: none;\n background: transparent;\n border-radius: 6px;\n cursor: pointer;\n color: var(--mj-text-muted);\n transition: all 0.15s ease;\n}\n\n.align-btn[_ngcontent-%COMP%]:hover {\n color: var(--mj-text-secondary);\n}\n\n.align-btn.active[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);\n}\n\n\n\n.style-buttons[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n margin-bottom: 12px;\n}\n\n.style-btn[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n border-radius: 6px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n transition: all 0.15s ease;\n}\n\n.style-btn[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-border-strong);\n color: var(--mj-text-secondary);\n}\n\n.style-btn.active[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n\n\n.format-preview-section[_ngcontent-%COMP%] {\n padding: 16px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.preview-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 12px;\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n}\n\n.preview-header[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n}\n\n.preview-table[_ngcontent-%COMP%] {\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n overflow: hidden;\n}\n\n.preview-header-cell[_ngcontent-%COMP%] {\n padding: 8px 12px;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n text-transform: uppercase;\n letter-spacing: 0.3px;\n}\n\n.preview-cell[_ngcontent-%COMP%] {\n padding: 8px 12px;\n font-size: 13px;\n color: var(--mj-text-primary);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.preview-cell[_ngcontent-%COMP%]:last-child {\n border-bottom: none;\n}\n\n\n\n.format-actions[_ngcontent-%COMP%] {\n padding: 16px;\n}\n\n.clear-format-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n background: var(--mj-bg-surface);\n cursor: pointer;\n font-size: 13px;\n color: var(--mj-text-secondary);\n transition: all 0.15s ease;\n}\n\n.clear-format-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-status-error-bg);\n border-color: var(--mj-status-error);\n color: var(--mj-status-error);\n}\n\n\n\n.sorting-section[_ngcontent-%COMP%] {\n padding: 0;\n}\n\n.sorting-header[_ngcontent-%COMP%] {\n margin-bottom: 12px;\n}\n\n.sorting-description[_ngcontent-%COMP%], \n.aggregates-description[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 13px;\n color: var(--mj-text-muted);\n line-height: 1.5;\n}\n\n\n\n.add-sort-btn[_ngcontent-%COMP%], \n.add-aggregate-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 16px;\n width: 100%;\n border: 2px dashed var(--mj-border-default);\n border-radius: 10px;\n background: transparent;\n cursor: pointer;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-muted);\n transition: all 0.15s ease;\n margin-bottom: 12px;\n}\n\n.add-sort-btn[_ngcontent-%COMP%]:hover:not(:disabled), \n.add-aggregate-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, var(--mj-bg-surface));\n}\n\n.add-sort-btn[_ngcontent-%COMP%]:disabled, \n.add-aggregate-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n\n\n.sort-items-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 6px;\n margin-bottom: 12px;\n}\n\n.sort-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 10px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n transition: all 0.15s ease;\n}\n\n.sort-item[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-border-strong);\n}\n\n.sort-item.dragging[_ngcontent-%COMP%] {\n opacity: 0.4;\n}\n\n.sort-item.drop-target[_ngcontent-%COMP%] {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, var(--mj-bg-surface));\n}\n\n\n\n.sort-drop-indicator[_ngcontent-%COMP%] {\n height: 2px;\n background: var(--mj-brand-primary);\n border-radius: 1px;\n margin: 0 10px;\n}\n\n\n\n.sort-priority-badge[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-radius: 6px;\n font-size: 11px;\n font-weight: 700;\n flex-shrink: 0;\n}\n\n\n\n.sort-drag-handle[_ngcontent-%COMP%] {\n cursor: grab;\n color: var(--mj-text-disabled);\n padding: 2px;\n font-size: 12px;\n}\n\n.sort-drag-handle[_ngcontent-%COMP%]:active {\n cursor: grabbing;\n}\n\n.sort-item[_ngcontent-%COMP%]:hover .sort-drag-handle[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n}\n\n\n\n.sort-field-dropdown[_ngcontent-%COMP%] {\n flex: 1;\n padding: 6px 10px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n font-size: 13px;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n cursor: pointer;\n min-width: 0;\n}\n\n.sort-field-dropdown[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n}\n\n\n\n.sort-direction-toggle[_ngcontent-%COMP%] {\n display: flex;\n background: var(--mj-bg-surface-sunken);\n border-radius: 6px;\n padding: 2px;\n gap: 2px;\n}\n\n.direction-btn[_ngcontent-%COMP%] {\n width: 28px;\n height: 28px;\n border: none;\n background: transparent;\n border-radius: 5px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n font-size: 12px;\n transition: all 0.15s ease;\n}\n\n.direction-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n color: var(--mj-text-secondary);\n}\n\n.direction-btn.active[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);\n}\n\n.direction-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.3;\n cursor: not-allowed;\n}\n\n\n\n.sort-remove-btn[_ngcontent-%COMP%] {\n width: 28px;\n height: 28px;\n border: none;\n background: transparent;\n border-radius: 6px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-disabled);\n font-size: 12px;\n transition: all 0.15s ease;\n}\n\n.sort-remove-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error);\n}\n\n.sort-remove-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.3;\n cursor: not-allowed;\n}\n\n\n\n.sort-hint[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n padding: 10px 12px;\n background: var(--mj-bg-surface-card);\n border-radius: 8px;\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.sort-hint[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-text-disabled);\n margin-top: 1px;\n}\n\n\n\n.sort-empty-state[_ngcontent-%COMP%], \n.aggregates-empty-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n padding: 32px 16px;\n color: var(--mj-text-muted);\n text-align: center;\n}\n\n.sort-empty-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%], \n.aggregates-empty-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 32px;\n opacity: 0.4;\n}\n\n.sort-empty-state[_ngcontent-%COMP%] span[_ngcontent-%COMP%], \n.aggregates-empty-state[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 500;\n}\n\n.sort-empty-hint[_ngcontent-%COMP%], \n.empty-hint[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 13px;\n color: var(--mj-text-disabled);\n}\n\n\n\n.filter-mode-selector[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-bottom: 16px;\n}\n\n.filter-mode-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 14px;\n border: 2px solid var(--mj-border-default);\n border-radius: 10px;\n background: var(--mj-bg-surface);\n cursor: pointer;\n transition: all 0.15s ease;\n text-align: left;\n}\n\n.filter-mode-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n border-color: var(--mj-border-strong);\n}\n\n.filter-mode-btn.active[_ngcontent-%COMP%] {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, var(--mj-bg-surface));\n}\n\n.filter-mode-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.mode-icon[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 8px;\n font-size: 16px;\n color: var(--mj-text-muted);\n flex-shrink: 0;\n}\n\n.filter-mode-btn.active[_ngcontent-%COMP%] .mode-icon[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.mode-content[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.mode-title[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.mode-subtitle[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.mode-check[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n font-size: 14px;\n}\n\n\n\n.smart-filter-section[_ngcontent-%COMP%] {\n padding: 0;\n}\n\n.smart-filter-input-container[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n padding: 12px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n margin-bottom: 12px;\n}\n\n.smart-filter-icon[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n padding-top: 4px;\n color: var(--mj-brand-primary);\n font-size: 16px;\n}\n\n.smart-filter-textarea[_ngcontent-%COMP%] {\n flex: 1;\n border: none;\n outline: none;\n resize: vertical;\n font-size: 14px;\n font-family: inherit;\n color: var(--mj-text-primary);\n background: transparent;\n min-height: 60px;\n}\n\n.smart-filter-textarea[_ngcontent-%COMP%]::placeholder {\n color: var(--mj-text-disabled);\n}\n\n.smart-filter-textarea[_ngcontent-%COMP%]:disabled {\n color: var(--mj-text-muted);\n}\n\n\n\n.smart-filter-explanation[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n padding: 10px 12px;\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) 25%, var(--mj-bg-surface));\n border-radius: 8px;\n margin-bottom: 12px;\n font-size: 13px;\n color: var(--mj-brand-primary);\n}\n\n.smart-filter-explanation[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n margin-top: 2px;\n}\n\n\n\n.smart-filter-examples[_ngcontent-%COMP%] {\n margin-bottom: 12px;\n}\n\n.examples-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 8px;\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-muted);\n}\n\n.examples-header[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-status-warning);\n}\n\n.example-chips[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n}\n\n.example-chip[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 20px;\n background: var(--mj-bg-surface);\n cursor: pointer;\n font-size: 12px;\n color: var(--mj-text-secondary);\n transition: all 0.15s ease;\n}\n\n.example-chip[_ngcontent-%COMP%]:hover:not(:disabled) {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, var(--mj-bg-surface));\n}\n\n.example-chip[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.example-chip[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 11px;\n}\n\n\n\n.smart-filter-tip[_ngcontent-%COMP%], \n.traditional-filter-tip[_ngcontent-%COMP%], \n.aggregates-tip[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n padding: 10px 12px;\n background: var(--mj-bg-surface-card);\n border-radius: 8px;\n font-size: 12px;\n color: var(--mj-text-muted);\n margin-top: 12px;\n}\n\n.smart-filter-tip[_ngcontent-%COMP%] i[_ngcontent-%COMP%], \n.traditional-filter-tip[_ngcontent-%COMP%] i[_ngcontent-%COMP%], \n.aggregates-tip[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-text-disabled);\n margin-top: 1px;\n}\n\n\n\n.traditional-filter-section[_ngcontent-%COMP%] {\n padding: 0;\n}\n\n.filter-summary-container[_ngcontent-%COMP%] {\n margin-bottom: 12px;\n}\n\n.filter-summary[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 14px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n}\n\n.summary-info[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.filter-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 22px;\n height: 22px;\n padding: 0 6px;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-radius: 11px;\n font-size: 12px;\n font-weight: 600;\n}\n\n.summary-text[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-text-primary);\n font-weight: 500;\n}\n\n.summary-text.no-filters[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-weight: 400;\n}\n\n.summary-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n}\n\n.summary-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n background: var(--mj-bg-surface);\n cursor: pointer;\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n transition: all 0.15s ease;\n}\n\n.summary-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n border-color: var(--mj-border-strong);\n}\n\n.summary-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.summary-btn.clear-btn[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-status-error);\n color: var(--mj-status-error);\n}\n\n.summary-btn.primary[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.summary-btn.primary[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n border-color: var(--mj-brand-primary-hover);\n}\n\n\n\n.aggregates-section[_ngcontent-%COMP%] {\n padding: 0;\n}\n\n.aggregates-header[_ngcontent-%COMP%] {\n margin-bottom: 12px;\n}\n\n\n\n.aggregates-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 6px;\n margin-bottom: 12px;\n}\n\n.aggregate-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 12px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n transition: all 0.15s ease;\n}\n\n.aggregate-item[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-border-strong);\n}\n\n.aggregate-item.disabled[_ngcontent-%COMP%] {\n opacity: 0.5;\n}\n\n\n\n.agg-icon[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n border-radius: 8px;\n color: var(--mj-brand-primary);\n font-size: 14px;\n flex-shrink: 0;\n}\n\n\n\n.agg-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.agg-label[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.agg-details[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-top: 2px;\n}\n\n.agg-type[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n\n.agg-smart-badge[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n font-size: 11px;\n}\n\n\n\n.agg-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 2px;\n opacity: 0;\n transition: opacity 0.15s ease;\n}\n\n.aggregate-item[_ngcontent-%COMP%]:hover .agg-actions[_ngcontent-%COMP%] {\n opacity: 1;\n}\n\n.agg-action-btn[_ngcontent-%COMP%] {\n width: 26px;\n height: 26px;\n border: none;\n background: transparent;\n border-radius: 6px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n font-size: 12px;\n transition: all 0.15s ease;\n}\n\n.agg-action-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-secondary);\n}\n\n.agg-action-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.3;\n cursor: not-allowed;\n}\n\n.agg-action-btn.toggle-btn.enabled[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n.agg-action-btn.remove-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error);\n}\n\n.agg-action-btn.edit-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n\n\n.aggregates-summary[_ngcontent-%COMP%] {\n display: flex;\n gap: 16px;\n padding: 10px 12px;\n background: var(--mj-bg-surface-card);\n border-radius: 8px;\n margin-bottom: 12px;\n}\n\n.aggregates-summary[_ngcontent-%COMP%] .summary-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.aggregates-summary[_ngcontent-%COMP%] .summary-item[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-text-disabled);\n}\n\n\n\n.form-group[_ngcontent-%COMP%] {\n margin-bottom: 16px;\n}\n\n.form-group[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n display: block;\n margin-bottom: 6px;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n.form-input[_ngcontent-%COMP%] {\n width: 100%;\n padding: 8px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n font-size: 14px;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n transition: border-color 0.15s ease;\n box-sizing: border-box;\n}\n\n.form-input[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n}\n\n.form-input.invalid[_ngcontent-%COMP%] {\n border-color: var(--mj-status-error);\n}\n\n.form-textarea[_ngcontent-%COMP%] {\n resize: vertical;\n min-height: 60px;\n font-family: inherit;\n}\n\n.validation-error[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-status-error);\n margin-top: 4px;\n}\n\n\n\n.checkbox-label[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n cursor: pointer;\n}\n\n.checkbox-label[_ngcontent-%COMP%] input[type=\"checkbox\"][_ngcontent-%COMP%] {\n margin-top: 3px;\n flex-shrink: 0;\n}\n\n.checkbox-text[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.checkbox-text[_ngcontent-%COMP%] strong[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-text-primary);\n}\n\n.checkbox-text[_ngcontent-%COMP%] small[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n\n\n.danger-zone[_ngcontent-%COMP%] .section-header[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n.danger-zone[_ngcontent-%COMP%] .section-header[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n.delete-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 16px;\n border: 1px solid var(--mj-status-error);\n border-radius: 8px;\n background: var(--mj-status-error-bg);\n cursor: pointer;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-status-error);\n transition: all 0.15s ease;\n}\n\n.delete-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n}\n\n\n\n.validation-banner[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 16px;\n background: var(--mj-status-error-bg);\n border-top: 1px solid var(--mj-status-error);\n font-size: 13px;\n color: var(--mj-status-error);\n flex-shrink: 0;\n}\n\n\n\n.panel-footer[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 14px 20px;\n border-top: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n flex-shrink: 0;\n}\n\n.footer-left[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n}\n\n.footer-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 9px 18px;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n background: var(--mj-bg-surface);\n cursor: pointer;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n transition: all 0.15s ease;\n}\n\n.footer-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n border-color: var(--mj-border-strong);\n}\n\n.footer-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.footer-btn.primary[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.footer-btn.primary[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n border-color: var(--mj-brand-primary-hover);\n}\n\n.footer-btn.cancel-btn[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-card);\n}\n\n.footer-btn.cancel-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-active);\n}\n\n\n\n@media (max-width: 480px) {\n .config-panel[_ngcontent-%COMP%] {\n width: 100vw;\n min-width: auto;\n }\n\n .resize-handle[_ngcontent-%COMP%] {\n display: none;\n }\n}"] });
2854
2854
  }
2855
2855
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ViewConfigPanelComponent, [{
2856
2856
  type: Component,
2857
- args: [{ standalone: false, selector: 'mj-view-config-panel', template: "<!-- Backdrop -->\n@if (isOpen) {\n <div class=\"panel-backdrop\" (click)=\"onClose()\"></div>\n}\n\n<!-- Sliding Panel -->\n<div class=\"config-panel\"\n [class.open]=\"isOpen\"\n [class.resizing]=\"isResizing\"\n [style.width.px]=\"panelWidth\">\n <!-- Resize Handle -->\n <div class=\"resize-handle\"\n (mousedown)=\"onResizeStart($event)\"\n title=\"Drag to resize\">\n <div class=\"resize-grip\"></div>\n </div>\n\n <!-- Panel Header -->\n <div class=\"panel-header\">\n <div class=\"header-title\">\n <i class=\"fa-solid fa-sliders-h\"></i>\n <span>{{ viewEntity ? 'Edit View' : 'Configure View' }}</span>\n </div>\n <button class=\"close-btn\" (click)=\"onClose()\" title=\"Close\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n\n <!-- Tab Navigation -->\n <div class=\"tab-nav\" [class.icon-only]=\"isIconOnlyMode\">\n <button\n class=\"tab-btn\"\n [class.active]=\"activeTab === 'columns'\"\n (click)=\"setActiveTab('columns')\"\n [title]=\"isIconOnlyMode ? 'Columns' : ''\">\n <i class=\"fa-solid fa-columns\"></i>\n @if (!isIconOnlyMode) {\n <span>Columns</span>\n }\n </button>\n <button\n class=\"tab-btn\"\n [class.active]=\"activeTab === 'sorting'\"\n (click)=\"setActiveTab('sorting')\"\n [title]=\"isIconOnlyMode ? 'Sorting' + (sortItems.length > 0 ? ' (' + sortItems.length + ')' : '') : ''\">\n <i class=\"fa-solid fa-arrow-up-wide-short\"></i>\n @if (!isIconOnlyMode) {\n <span>Sorting</span>\n }\n @if (sortItems.length > 0) {\n <span class=\"tab-badge\">{{ sortItems.length }}</span>\n }\n </button>\n <button\n class=\"tab-btn\"\n [class.active]=\"activeTab === 'filters'\"\n (click)=\"setActiveTab('filters')\"\n [title]=\"isIconOnlyMode ? 'Filters' : ''\">\n <i class=\"fa-solid fa-filter\"></i>\n @if (!isIconOnlyMode) {\n <span>Filters</span>\n }\n </button>\n <button\n class=\"tab-btn\"\n [class.active]=\"activeTab === 'aggregates'\"\n (click)=\"setActiveTab('aggregates')\"\n [title]=\"isIconOnlyMode ? 'Aggregates' + (enabledAggregatesCount > 0 ? ' (' + enabledAggregatesCount + ')' : '') : ''\">\n <i class=\"fa-solid fa-chart-simple\"></i>\n @if (!isIconOnlyMode) {\n <span>Aggregates</span>\n }\n @if (enabledAggregatesCount > 0) {\n <span class=\"tab-badge\">{{ enabledAggregatesCount }}</span>\n }\n </button>\n @if (viewEntity || DefaultSaveAsNew) {\n <button\n class=\"tab-btn\"\n [class.active]=\"activeTab === 'settings'\"\n (click)=\"setActiveTab('settings')\"\n [title]=\"isIconOnlyMode ? 'Settings' : ''\">\n <i class=\"fa-solid fa-cog\"></i>\n @if (!isIconOnlyMode) {\n <span>Settings</span>\n }\n </button>\n }\n </div>\n\n <!-- Panel Content -->\n <div class=\"panel-content\">\n <!-- Columns Tab -->\n @if (activeTab === 'columns' && !formatEditingColumn) {\n <div class=\"tab-content\">\n <!-- Visible Columns -->\n <div class=\"config-section\">\n <div class=\"section-header\">\n <i class=\"fa-solid fa-eye\"></i>\n <span>Visible Columns</span>\n <span class=\"column-count\">{{ visibleColumns.length }}</span>\n </div>\n <div class=\"column-list visible-columns\">\n @for (column of visibleColumns; track column.fieldId; let i = $index) {\n <!-- Drop indicator before -->\n @if (isDropBefore(column)) {\n <div class=\"drop-indicator\"></div>\n }\n <div\n class=\"column-item\"\n [class.dragging]=\"draggedColumn === column\"\n [class.drop-target]=\"dropTargetColumn === column\"\n draggable=\"true\"\n (dragstart)=\"onDragStart($event, column)\"\n (dragover)=\"onDragOver($event, column)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event, column)\"\n (dragend)=\"onDragEnd($event)\">\n <div class=\"drag-handle\">\n <i class=\"fa-solid fa-grip-vertical\"></i>\n </div>\n <span class=\"column-name\">\n {{ column.userDisplayName || column.displayName }}\n @if (column.userDisplayName) {\n <i class=\"fa-solid fa-pen-nib alias-indicator\" title=\"Custom name: {{ column.userDisplayName }}\"></i>\n }\n @if (hasCustomFormat(column)) {\n <i class=\"fa-solid fa-paintbrush format-indicator\" title=\"Custom formatting applied\"></i>\n }\n </span>\n <div class=\"column-actions\">\n <button\n class=\"action-btn format-btn\"\n (click)=\"openFormatEditor(column)\"\n title=\"Format column\">\n <i class=\"fa-solid fa-paintbrush\"></i>\n </button>\n <button\n class=\"action-btn\"\n [disabled]=\"i === 0\"\n (click)=\"moveColumnUp(column)\"\n title=\"Move up\">\n <i class=\"fa-solid fa-chevron-up\"></i>\n </button>\n <button\n class=\"action-btn\"\n [disabled]=\"i === visibleColumns.length - 1\"\n (click)=\"moveColumnDown(column)\"\n title=\"Move down\">\n <i class=\"fa-solid fa-chevron-down\"></i>\n </button>\n <button\n class=\"action-btn hide-btn\"\n (click)=\"toggleColumnVisibility(column)\"\n title=\"Hide column\">\n <i class=\"fa-solid fa-eye-slash\"></i>\n </button>\n </div>\n </div>\n <!-- Drop indicator after (only for last item) -->\n @if (isDropAfter(column) && i === visibleColumns.length - 1) {\n <div class=\"drop-indicator\"></div>\n }\n }\n @if (visibleColumns.length === 0) {\n <div class=\"empty-list\">\n <i class=\"fa-solid fa-info-circle\"></i>\n <span>No columns visible. Add columns from below.</span>\n </div>\n }\n </div>\n </div>\n\n <!-- Hidden Columns -->\n <div class=\"config-section\">\n <div class=\"section-header\">\n <i class=\"fa-solid fa-eye-slash\"></i>\n <span>Hidden Columns</span>\n <span class=\"column-count\">{{ hiddenColumns.length }}</span>\n </div>\n @if (hiddenColumns.length > 5) {\n <div class=\"column-search\">\n <i class=\"fa-solid fa-search\"></i>\n <input\n type=\"text\"\n placeholder=\"Search columns...\"\n [(ngModel)]=\"columnSearchText\"\n />\n </div>\n }\n <div class=\"column-list hidden-columns\">\n @for (column of filteredHiddenColumns; track column.fieldId) {\n <div class=\"column-item hidden\">\n <span class=\"column-name\">{{ column.displayName }}</span>\n <button\n class=\"action-btn show-btn\"\n (click)=\"toggleColumnVisibility(column)\"\n title=\"Show column\">\n <i class=\"fa-solid fa-plus\"></i>\n </button>\n </div>\n }\n @if (hiddenColumns.length === 0) {\n <div class=\"empty-list\">\n <i class=\"fa-solid fa-check-circle\"></i>\n <span>All columns are visible</span>\n </div>\n }\n </div>\n </div>\n </div>\n }\n\n <!-- Column Format Editor Sub-Panel -->\n @if (activeTab === 'columns' && formatEditingColumn) {\n <div class=\"format-editor\">\n <!-- Format Editor Header -->\n <div class=\"format-editor-header\">\n <button class=\"back-btn\" (click)=\"closeFormatEditor()\">\n <i class=\"fa-solid fa-arrow-left\"></i>\n </button>\n <div class=\"format-editor-title\">\n <span>Format: {{ formatEditingColumn.userDisplayName || formatEditingColumn.displayName }}</span>\n </div>\n </div>\n\n <!-- Column Alias Section -->\n <div class=\"format-section\">\n <div class=\"format-section-header\">\n <i class=\"fa-solid fa-pen-nib\"></i>\n <span>Column Name</span>\n </div>\n <div class=\"format-row\">\n <label>Display As</label>\n <input type=\"text\" class=\"format-input\"\n [value]=\"formatEditingColumn.userDisplayName || ''\"\n (input)=\"updateUserDisplayName($any($event.target).value)\"\n [placeholder]=\"formatEditingColumn.displayName\" />\n </div>\n @if (formatEditingColumn.userDisplayName) {\n <div class=\"format-row alias-info\">\n <small class=\"muted-text\">Original: {{ formatEditingColumn.displayName }}</small>\n <button class=\"clear-alias-btn\" (click)=\"formatEditingColumn.userDisplayName = undefined\" title=\"Clear alias\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n }\n </div>\n\n <!-- Preview Section -->\n <div class=\"format-preview-section\">\n <div class=\"preview-header\">\n <i class=\"fa-solid fa-eye\"></i>\n <span>Preview</span>\n </div>\n <div class=\"preview-table\">\n <div class=\"preview-header-cell\"\n [style.font-weight]=\"formatEditingColumn.format?.headerStyle?.bold ? 'bold' : 'normal'\"\n [style.font-style]=\"formatEditingColumn.format?.headerStyle?.italic ? 'italic' : 'normal'\"\n [style.text-decoration]=\"formatEditingColumn.format?.headerStyle?.underline ? 'underline' : 'none'\"\n [style.color]=\"formatEditingColumn.format?.headerStyle?.color\"\n [style.background-color]=\"formatEditingColumn.format?.headerStyle?.backgroundColor\">\n {{ formatEditingColumn.userDisplayName || formatEditingColumn.displayName }}\n </div>\n @for (value of getSampleValues(formatEditingColumn); track $index) {\n <div class=\"preview-cell\"\n [style.text-align]=\"formatEditingColumn.format?.align || 'left'\"\n [style.font-weight]=\"formatEditingColumn.format?.cellStyle?.bold ? 'bold' : 'normal'\"\n [style.font-style]=\"formatEditingColumn.format?.cellStyle?.italic ? 'italic' : 'normal'\"\n [style.text-decoration]=\"formatEditingColumn.format?.cellStyle?.underline ? 'underline' : 'none'\"\n [style.color]=\"formatEditingColumn.format?.cellStyle?.color\"\n [style.background-color]=\"formatEditingColumn.format?.cellStyle?.backgroundColor\">\n {{ formatPreviewValue(value, formatEditingColumn.format) }}\n </div>\n }\n </div>\n </div>\n\n <!-- Format Type -->\n <div class=\"format-section\">\n <div class=\"format-section-header\">\n <i class=\"fa-solid fa-hashtag\"></i>\n <span>Format Type</span>\n </div>\n <select class=\"format-select\" [(ngModel)]=\"formatEditingColumn.format!.type\">\n <option value=\"auto\">Auto (Smart Default)</option>\n <option value=\"text\">Text</option>\n <option value=\"number\">Number</option>\n <option value=\"currency\">Currency</option>\n <option value=\"percent\">Percent</option>\n <option value=\"date\">Date</option>\n <option value=\"datetime\">Date & Time</option>\n <option value=\"boolean\">Boolean</option>\n </select>\n </div>\n\n <!-- Type-Specific Options -->\n @if (formatEditingColumn.format?.type === 'number' || formatEditingColumn.format?.type === 'currency' || formatEditingColumn.format?.type === 'percent') {\n <div class=\"format-section\">\n <div class=\"format-section-header\">\n <i class=\"fa-solid fa-sliders\"></i>\n <span>Number Options</span>\n </div>\n <div class=\"format-row\">\n <label>Decimal Places</label>\n <input type=\"number\" class=\"format-input small\" min=\"0\" max=\"10\"\n [(ngModel)]=\"formatEditingColumn.format!.decimals\" />\n </div>\n @if (formatEditingColumn.format?.type === 'currency') {\n <div class=\"format-row\">\n <label>Currency</label>\n <select class=\"format-select\" [(ngModel)]=\"formatEditingColumn.format!.currencyCode\">\n <option value=\"USD\">USD ($)</option>\n <option value=\"EUR\">EUR (\u20AC)</option>\n <option value=\"GBP\">GBP (\u00A3)</option>\n <option value=\"JPY\">JPY (\u00A5)</option>\n <option value=\"CAD\">CAD ($)</option>\n <option value=\"AUD\">AUD ($)</option>\n </select>\n </div>\n }\n <div class=\"format-row\">\n <label>Thousands Separator</label>\n <input type=\"checkbox\" [(ngModel)]=\"formatEditingColumn.format!.thousandsSeparator\" />\n </div>\n </div>\n }\n\n @if (formatEditingColumn.format?.type === 'date' || formatEditingColumn.format?.type === 'datetime') {\n <div class=\"format-section\">\n <div class=\"format-section-header\">\n <i class=\"fa-solid fa-calendar\"></i>\n <span>Date Options</span>\n </div>\n <div class=\"format-row\">\n <label>Format</label>\n <select class=\"format-select\" [(ngModel)]=\"formatEditingColumn.format!.dateFormat\">\n <option value=\"short\">Short (1/15/25)</option>\n <option value=\"short-weekday\">Short + Day (Wed, 1/15/25)</option>\n <option value=\"medium\">Medium (Jan 15, 2025)</option>\n <option value=\"medium-weekday\">Medium + Day (Wed, Jan 15, 2025)</option>\n <option value=\"long\">Long (January 15, 2025)</option>\n <option value=\"long-weekday\">Long + Day (Wednesday, January 15, 2025)</option>\n </select>\n </div>\n </div>\n }\n\n @if (formatEditingColumn.format?.type === 'boolean') {\n <div class=\"format-section\">\n <div class=\"format-section-header\">\n <i class=\"fa-solid fa-toggle-on\"></i>\n <span>Boolean Options</span>\n </div>\n <div class=\"format-row\">\n <label>True Label</label>\n <input type=\"text\" class=\"format-input\" [(ngModel)]=\"formatEditingColumn.format!.trueLabel\" placeholder=\"Yes\" />\n </div>\n <div class=\"format-row\">\n <label>False Label</label>\n <input type=\"text\" class=\"format-input\" [(ngModel)]=\"formatEditingColumn.format!.falseLabel\" placeholder=\"No\" />\n </div>\n <div class=\"format-row\">\n <label>Display As</label>\n <select class=\"format-select\" [(ngModel)]=\"formatEditingColumn.format!.booleanDisplay\">\n <option value=\"text\">Text</option>\n <option value=\"checkbox\">Checkbox</option>\n <option value=\"icon\">Icon</option>\n </select>\n </div>\n </div>\n }\n\n <!-- Alignment -->\n <div class=\"format-section\">\n <div class=\"format-section-header\">\n <i class=\"fa-solid fa-align-left\"></i>\n <span>Alignment</span>\n </div>\n <div class=\"alignment-toggle\">\n <button class=\"align-btn\" [class.active]=\"formatEditingColumn.format?.align === 'left' || !formatEditingColumn.format?.align\"\n (click)=\"formatEditingColumn.format!.align = 'left'\" title=\"Left\">\n <i class=\"fa-solid fa-align-left\"></i>\n </button>\n <button class=\"align-btn\" [class.active]=\"formatEditingColumn.format?.align === 'center'\"\n (click)=\"formatEditingColumn.format!.align = 'center'\" title=\"Center\">\n <i class=\"fa-solid fa-align-center\"></i>\n </button>\n <button class=\"align-btn\" [class.active]=\"formatEditingColumn.format?.align === 'right'\"\n (click)=\"formatEditingColumn.format!.align = 'right'\" title=\"Right\">\n <i class=\"fa-solid fa-align-right\"></i>\n </button>\n </div>\n </div>\n\n <!-- Header Style -->\n <div class=\"format-section\">\n <div class=\"format-section-header\">\n <i class=\"fa-solid fa-heading\"></i>\n <span>Header Style</span>\n </div>\n <div class=\"style-buttons\">\n <button class=\"style-btn\" [class.active]=\"formatEditingColumn.format?.headerStyle?.bold\"\n (click)=\"toggleHeaderStyle('bold')\"\n title=\"Bold\">\n <i class=\"fa-solid fa-bold\"></i>\n </button>\n <button class=\"style-btn\" [class.active]=\"formatEditingColumn.format?.headerStyle?.italic\"\n (click)=\"toggleHeaderStyle('italic')\"\n title=\"Italic\">\n <i class=\"fa-solid fa-italic\"></i>\n </button>\n <button class=\"style-btn\" [class.active]=\"formatEditingColumn.format?.headerStyle?.underline\"\n (click)=\"toggleHeaderStyle('underline')\"\n title=\"Underline\">\n <i class=\"fa-solid fa-underline\"></i>\n </button>\n </div>\n <div class=\"format-row\">\n <label>Text Color</label>\n <input type=\"color\" class=\"color-input\"\n [value]=\"formatEditingColumn.format?.headerStyle?.color || '#000000'\"\n (input)=\"updateHeaderColor('color', $any($event.target).value)\" />\n </div>\n <div class=\"format-row\">\n <label>Background</label>\n <input type=\"color\" class=\"color-input\"\n [value]=\"formatEditingColumn.format?.headerStyle?.backgroundColor || '#ffffff'\"\n (input)=\"updateHeaderColor('backgroundColor', $any($event.target).value)\" />\n </div>\n </div>\n\n <!-- Cell Style -->\n <div class=\"format-section\">\n <div class=\"format-section-header\">\n <i class=\"fa-solid fa-table-cells\"></i>\n <span>Cell Style</span>\n </div>\n <div class=\"style-buttons\">\n <button class=\"style-btn\" [class.active]=\"formatEditingColumn.format?.cellStyle?.bold\"\n (click)=\"toggleCellStyle('bold')\"\n title=\"Bold\">\n <i class=\"fa-solid fa-bold\"></i>\n </button>\n <button class=\"style-btn\" [class.active]=\"formatEditingColumn.format?.cellStyle?.italic\"\n (click)=\"toggleCellStyle('italic')\"\n title=\"Italic\">\n <i class=\"fa-solid fa-italic\"></i>\n </button>\n <button class=\"style-btn\" [class.active]=\"formatEditingColumn.format?.cellStyle?.underline\"\n (click)=\"toggleCellStyle('underline')\"\n title=\"Underline\">\n <i class=\"fa-solid fa-underline\"></i>\n </button>\n </div>\n <div class=\"format-row\">\n <label>Text Color</label>\n <input type=\"color\" class=\"color-input\"\n [value]=\"formatEditingColumn.format?.cellStyle?.color || '#000000'\"\n (input)=\"updateCellColor('color', $any($event.target).value)\" />\n </div>\n <div class=\"format-row\">\n <label>Background</label>\n <input type=\"color\" class=\"color-input\"\n [value]=\"formatEditingColumn.format?.cellStyle?.backgroundColor || '#ffffff'\"\n (input)=\"updateCellColor('backgroundColor', $any($event.target).value)\" />\n </div>\n </div>\n\n <!-- Clear Format Button -->\n <div class=\"format-actions\">\n <button class=\"clear-format-btn\" (click)=\"clearColumnFormat(formatEditingColumn); closeFormatEditor()\">\n <i class=\"fa-solid fa-eraser\"></i>\n Clear Formatting\n </button>\n </div>\n </div>\n }\n\n <!-- Sorting Tab -->\n @if (activeTab === 'sorting') {\n <div class=\"tab-content\">\n <div class=\"config-section sorting-section\">\n <div class=\"sorting-header\">\n <p class=\"sorting-description\">\n Define how records should be ordered. Add multiple levels to sort by secondary fields when values are equal.\n </p>\n </div>\n\n <!-- Add Sort Button -->\n <button\n class=\"add-sort-btn\"\n (click)=\"addSortLevel()\"\n [disabled]=\"!canEdit || sortItems.length >= sortableFields.length\"\n title=\"Add another sort level\">\n <i class=\"fa-solid fa-plus\"></i>\n <span>Add Sort Level</span>\n </button>\n\n <!-- Sort Items List -->\n @if (sortItems.length > 0) {\n <div class=\"sort-items-list\">\n @for (sortItem of sortItems; track $index; let i = $index) {\n <!-- Drop indicator before -->\n @if (isSortDropBefore(sortItem)) {\n <div class=\"sort-drop-indicator\"></div>\n }\n <div\n class=\"sort-item\"\n [class.dragging]=\"draggedSortItem === sortItem\"\n [class.drop-target]=\"dropTargetSortItem === sortItem\"\n draggable=\"true\"\n (dragstart)=\"onSortDragStart($event, sortItem)\"\n (dragover)=\"onSortDragOver($event, sortItem)\"\n (dragleave)=\"onSortDragLeave($event)\"\n (drop)=\"onSortDrop($event, sortItem)\"\n (dragend)=\"onSortDragEnd($event)\">\n <!-- Priority Badge -->\n <div class=\"sort-priority-badge\">{{ i + 1 }}</div>\n <!-- Drag Handle -->\n <div class=\"sort-drag-handle\" title=\"Drag to reorder\">\n <i class=\"fa-solid fa-grip-vertical\"></i>\n </div>\n <!-- Field Dropdown -->\n <select\n class=\"sort-field-dropdown\"\n [(ngModel)]=\"sortItem.field\"\n (ngModelChange)=\"onSortFieldChange(sortItem, $event)\"\n [disabled]=\"!canEdit\">\n @for (field of sortableFields; track field.ID) {\n <option [value]=\"field.Name\">{{ field.DisplayNameOrName }}</option>\n }\n </select>\n <!-- Direction Toggle -->\n <div class=\"sort-direction-toggle\">\n <button\n class=\"direction-btn\"\n [class.active]=\"sortItem.direction === 'asc'\"\n (click)=\"onSortDirectionChange(sortItem, 'asc')\"\n [disabled]=\"!canEdit\"\n title=\"Ascending (A-Z, 1-9)\">\n <i class=\"fa-solid fa-arrow-up\"></i>\n </button>\n <button\n class=\"direction-btn\"\n [class.active]=\"sortItem.direction === 'desc'\"\n (click)=\"onSortDirectionChange(sortItem, 'desc')\"\n [disabled]=\"!canEdit\"\n title=\"Descending (Z-A, 9-1)\">\n <i class=\"fa-solid fa-arrow-down\"></i>\n </button>\n </div>\n <!-- Remove Button -->\n <button\n class=\"sort-remove-btn\"\n (click)=\"removeSortLevel(sortItem)\"\n [disabled]=\"!canEdit\"\n title=\"Remove sort level\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n <!-- Drop indicator after (only for last item) -->\n @if (isSortDropAfter(sortItem) && i === sortItems.length - 1) {\n <div class=\"sort-drop-indicator\"></div>\n }\n }\n </div>\n <!-- Multi-sort hint -->\n @if (sortItems.length > 1) {\n <div class=\"sort-hint\">\n <i class=\"fa-solid fa-info-circle\"></i>\n <span>Drag items to change priority. Records sort by first level, then second, etc.</span>\n </div>\n }\n } @else {\n <div class=\"sort-empty-state\">\n <i class=\"fa-solid fa-arrow-up-wide-short\"></i>\n <span>No sorting configured</span>\n <p class=\"sort-empty-hint\">Click \"Add Sort Level\" to define how records should be ordered</p>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- Filters Tab -->\n @if (activeTab === 'filters') {\n <div class=\"tab-content\">\n <!-- Filter Mode Selection -->\n <div class=\"filter-mode-selector\">\n <button\n class=\"filter-mode-btn\"\n [class.active]=\"filterMode === 'smart'\"\n (click)=\"setFilterMode('smart')\"\n [disabled]=\"!canEdit\">\n <div class=\"mode-icon\">\n <i class=\"fa-solid fa-wand-magic-sparkles\"></i>\n </div>\n <div class=\"mode-content\">\n <span class=\"mode-title\">Smart Filter</span>\n <span class=\"mode-subtitle\">Use AI to filter with natural language</span>\n </div>\n @if (filterMode === 'smart') {\n <i class=\"fa-solid fa-check mode-check\"></i>\n }\n </button>\n <button\n class=\"filter-mode-btn\"\n [class.active]=\"filterMode === 'traditional'\"\n (click)=\"setFilterMode('traditional')\"\n [disabled]=\"!canEdit\">\n <div class=\"mode-icon\">\n <i class=\"fa-solid fa-sliders\"></i>\n </div>\n <div class=\"mode-content\">\n <span class=\"mode-title\">Traditional Filter</span>\n <span class=\"mode-subtitle\">Build filters with field/operator/value</span>\n </div>\n @if (filterMode === 'traditional') {\n <i class=\"fa-solid fa-check mode-check\"></i>\n }\n </button>\n </div>\n\n <!-- Smart Filter Section -->\n @if (filterMode === 'smart') {\n <div class=\"config-section smart-filter-section\">\n <div class=\"smart-filter-input-container\">\n <div class=\"smart-filter-icon\">\n <i class=\"fa-solid fa-wand-magic-sparkles\"></i>\n </div>\n <textarea\n id=\"smartFilterPrompt\"\n class=\"smart-filter-textarea\"\n placeholder=\"Describe what you're looking for...\"\n [(ngModel)]=\"smartFilterPrompt\"\n [disabled]=\"!canEdit\"\n rows=\"3\"\n ></textarea>\n </div>\n\n @if (smartFilterExplanation) {\n <div class=\"smart-filter-explanation\">\n <i class=\"fa-solid fa-robot\"></i>\n <span>{{ smartFilterExplanation }}</span>\n </div>\n }\n\n <!-- Example Prompts -->\n <div class=\"smart-filter-examples\">\n <div class=\"examples-header\">\n <i class=\"fa-solid fa-lightbulb\"></i>\n <span>Try these examples:</span>\n </div>\n <div class=\"example-chips\">\n <button\n class=\"example-chip\"\n (click)=\"applySmartFilterExample('Show records created in the last 30 days')\"\n [disabled]=\"!canEdit\">\n <i class=\"fa-regular fa-calendar\"></i>\n Last 30 days\n </button>\n <button\n class=\"example-chip\"\n (click)=\"applySmartFilterExample('Active records only')\"\n [disabled]=\"!canEdit\">\n <i class=\"fa-solid fa-circle-check\"></i>\n Active only\n </button>\n <button\n class=\"example-chip\"\n (click)=\"applySmartFilterExample('Records with high priority')\"\n [disabled]=\"!canEdit\">\n <i class=\"fa-solid fa-star\"></i>\n High priority\n </button>\n <button\n class=\"example-chip\"\n (click)=\"applySmartFilterExample('Records modified this week')\"\n [disabled]=\"!canEdit\">\n <i class=\"fa-solid fa-clock-rotate-left\"></i>\n Modified this week\n </button>\n </div>\n </div>\n\n <div class=\"smart-filter-tip\">\n <i class=\"fa-solid fa-info-circle\"></i>\n <span>The AI will interpret your description and create the appropriate filter when you save the view.</span>\n </div>\n </div>\n }\n\n <!-- Traditional Filter Section -->\n @if (filterMode === 'traditional') {\n <div class=\"config-section traditional-filter-section\">\n <div class=\"filter-summary-container\">\n <div class=\"filter-summary\">\n <div class=\"summary-info\">\n @if (getFilterCount() > 0) {\n <span class=\"filter-badge\">{{ getFilterCount() }}</span>\n <span class=\"summary-text\">{{ getFilterSummary() }}</span>\n } @else {\n <span class=\"summary-text no-filters\">No filters configured</span>\n }\n </div>\n <div class=\"summary-actions\">\n @if (getFilterCount() > 0 && canEdit) {\n <button\n class=\"summary-btn clear-btn\"\n (click)=\"clearFilters()\"\n title=\"Clear all filters\">\n <i class=\"fa-solid fa-times\"></i>\n Clear\n </button>\n }\n <button\n class=\"summary-btn edit-btn primary\"\n (click)=\"openFilterDialog()\"\n [disabled]=\"!canEdit && getFilterCount() === 0\"\n title=\"Edit filters\">\n <i class=\"fa-solid fa-pen\"></i>\n {{ getFilterCount() > 0 ? 'Edit Filters' : 'Add Filters' }}\n </button>\n </div>\n </div>\n </div>\n\n <div class=\"traditional-filter-tip\">\n <i class=\"fa-solid fa-info-circle\"></i>\n <span>Build precise filters by selecting fields, operators, and values. Use groups for complex AND/OR logic.</span>\n </div>\n </div>\n }\n </div>\n }\n\n <!-- Aggregates Tab -->\n @if (activeTab === 'aggregates') {\n <div class=\"tab-content\">\n <div class=\"config-section aggregates-section\">\n <div class=\"aggregates-header\">\n <p class=\"aggregates-description\">\n Add summary calculations like totals, averages, and counts. Display them in cards or as column footers.\n </p>\n </div>\n\n <!-- Add Aggregate Button -->\n <button\n class=\"add-aggregate-btn\"\n (click)=\"openAddAggregateDialog()\"\n [disabled]=\"!canEdit\"\n title=\"Add a new aggregate\">\n <i class=\"fa-solid fa-plus\"></i>\n <span>Add Aggregate</span>\n </button>\n\n <!-- Aggregates List -->\n @if (aggregates.length > 0) {\n <div class=\"aggregates-list\">\n @for (agg of aggregates; track agg.id; let i = $index) {\n <div class=\"aggregate-item\" [class.disabled]=\"agg.enabled === false\">\n <!-- Icon -->\n <div class=\"agg-icon\">\n <i [class]=\"agg.icon || 'fa-solid fa-chart-simple'\"></i>\n </div>\n\n <!-- Content -->\n <div class=\"agg-content\">\n <div class=\"agg-label\">{{ agg.label }}</div>\n <div class=\"agg-details\">\n <span class=\"agg-type\">\n <i [class]=\"agg.displayType === 'card' ? 'fa-solid fa-id-card' : 'fa-solid fa-table-columns'\"></i>\n {{ agg.displayType === 'card' ? 'Card' : 'Column Footer' }}\n </span>\n @if (agg.smartPrompt) {\n <span class=\"agg-smart-badge\" title=\"AI-generated\">\n <i class=\"fa-solid fa-wand-magic-sparkles\"></i>\n </span>\n }\n </div>\n </div>\n\n <!-- Actions -->\n <div class=\"agg-actions\">\n <button\n class=\"agg-action-btn\"\n [disabled]=\"i === 0 || !canEdit\"\n (click)=\"moveAggregateUp(agg)\"\n title=\"Move up\">\n <i class=\"fa-solid fa-chevron-up\"></i>\n </button>\n <button\n class=\"agg-action-btn\"\n [disabled]=\"i === aggregates.length - 1 || !canEdit\"\n (click)=\"moveAggregateDown(agg)\"\n title=\"Move down\">\n <i class=\"fa-solid fa-chevron-down\"></i>\n </button>\n <button\n class=\"agg-action-btn toggle-btn\"\n [class.enabled]=\"agg.enabled !== false\"\n (click)=\"toggleAggregateEnabled(agg, $event)\"\n [disabled]=\"!canEdit\"\n [title]=\"agg.enabled !== false ? 'Disable' : 'Enable'\">\n <i [class]=\"agg.enabled !== false ? 'fa-solid fa-eye' : 'fa-solid fa-eye-slash'\"></i>\n </button>\n <button\n class=\"agg-action-btn edit-btn\"\n (click)=\"editAggregate(agg)\"\n [disabled]=\"!canEdit\"\n title=\"Edit\">\n <i class=\"fa-solid fa-pen\"></i>\n </button>\n <button\n class=\"agg-action-btn remove-btn\"\n (click)=\"removeAggregate(agg)\"\n [disabled]=\"!canEdit\"\n title=\"Remove\">\n <i class=\"fa-solid fa-trash\"></i>\n </button>\n </div>\n </div>\n }\n </div>\n\n <!-- Summary -->\n <div class=\"aggregates-summary\">\n <div class=\"summary-item\">\n <i class=\"fa-solid fa-id-card\"></i>\n <span>{{ cardAggregates.length }} card{{ cardAggregates.length !== 1 ? 's' : '' }}</span>\n </div>\n <div class=\"summary-item\">\n <i class=\"fa-solid fa-table-columns\"></i>\n <span>{{ columnAggregates.length }} column footer{{ columnAggregates.length !== 1 ? 's' : '' }}</span>\n </div>\n </div>\n } @else {\n <div class=\"aggregates-empty-state\">\n <i class=\"fa-solid fa-chart-simple\"></i>\n <span>No aggregates configured</span>\n <p class=\"empty-hint\">Click \"Add Aggregate\" to create summary calculations</p>\n </div>\n }\n\n <!-- Info Tip -->\n <div class=\"aggregates-tip\">\n <i class=\"fa-solid fa-info-circle\"></i>\n <span>Aggregates are calculated server-side for accuracy with filtered/paginated data.</span>\n </div>\n </div>\n </div>\n }\n\n <!-- Settings Tab -->\n @if (activeTab === 'settings') {\n <div class=\"tab-content\">\n <!-- View Name & Description -->\n <div class=\"config-section\">\n <div class=\"section-header\">\n <i class=\"fa-solid fa-info-circle\"></i>\n <span>View Details</span>\n </div>\n <div class=\"form-group\">\n <label for=\"viewName\">Name</label>\n <input\n id=\"viewName\"\n type=\"text\"\n class=\"form-input\"\n [class.invalid]=\"!viewName || !viewName.trim()\"\n placeholder=\"Enter view name...\"\n [(ngModel)]=\"viewName\"\n [disabled]=\"!canEdit\"\n />\n @if (!viewName || !viewName.trim()) {\n <span class=\"validation-error\">View name is required</span>\n }\n </div>\n <div class=\"form-group\">\n <label for=\"viewDescription\">Description</label>\n <textarea\n id=\"viewDescription\"\n class=\"form-input form-textarea\"\n placeholder=\"Describe this view...\"\n [(ngModel)]=\"viewDescription\"\n [disabled]=\"!canEdit\"\n rows=\"3\"\n ></textarea>\n </div>\n </div>\n\n <!-- Sharing -->\n <div class=\"config-section\">\n <div class=\"section-header\">\n <i class=\"fa-solid fa-share-alt\"></i>\n <span>Sharing</span>\n </div>\n <label class=\"checkbox-label\">\n <input\n type=\"checkbox\"\n [(ngModel)]=\"isShared\"\n [disabled]=\"!canEdit\"\n />\n <span class=\"checkbox-text\">\n <strong>Share with others</strong>\n <small>Allow other users to use this view</small>\n </span>\n </label>\n </div>\n\n <!-- Danger Zone -->\n @if (viewEntity && canDelete) {\n <div class=\"config-section danger-zone\">\n <div class=\"section-header\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n <span>Danger Zone</span>\n </div>\n <button class=\"delete-btn\" (click)=\"onDelete()\">\n <i class=\"fa-solid fa-trash\"></i>\n <span>Delete View</span>\n </button>\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Validation Errors Banner -->\n @if (ValidationErrors.length > 0 && visibleColumns.length === 0) {\n <div class=\"validation-banner\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n <span>At least one column must be visible</span>\n </div>\n }\n\n <!-- Panel Footer -->\n <div class=\"panel-footer\">\n <!-- Action buttons on LEFT -->\n <div class=\"footer-left\">\n @if (viewEntity && canEdit) {\n <!-- Editing an existing saved view -->\n <button\n class=\"footer-btn save-btn primary\"\n (click)=\"onSave()\"\n [disabled]=\"isSaving || !IsValid\">\n @if (isSaving) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n } @else {\n <i class=\"fa-solid fa-save\"></i>\n }\n {{ isSaving ? 'Saving...' : 'Save' }}\n </button>\n }\n @if (!viewEntity && DefaultSaveAsNew) {\n <!-- Creating a new view (from quick save dialog) -->\n <button\n class=\"footer-btn save-btn primary\"\n (click)=\"onSaveAsNew()\"\n [disabled]=\"isSaving || !IsValidForSaveAsNew\">\n @if (isSaving) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n } @else {\n <i class=\"fa-solid fa-plus\"></i>\n }\n {{ isSaving ? 'Saving...' : 'Create View' }}\n </button>\n }\n @if (!viewEntity && !DefaultSaveAsNew) {\n <!-- Default/Dynamic view - Save to user settings -->\n <button\n class=\"footer-btn save-btn primary\"\n (click)=\"onSaveDefaults()\"\n [disabled]=\"isSaving\">\n @if (isSaving) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n } @else {\n <i class=\"fa-solid fa-save\"></i>\n }\n {{ isSaving ? 'Saving...' : 'Save' }}\n </button>\n }\n </div>\n <!-- Cancel button on RIGHT -->\n <button class=\"footer-btn cancel-btn\" (click)=\"onClose()\">\n Cancel\n </button>\n </div>\n</div>\n\n<!-- Aggregate Setup Dialog -->\n<mj-aggregate-setup-dialog\n [Entity]=\"entity\"\n [Aggregate]=\"editingAggregate\"\n [IsOpen]=\"showAggregateDialog\"\n (Close)=\"closeAggregateDialog()\"\n (Save)=\"onAggregateSave($event)\">\n</mj-aggregate-setup-dialog>\n\n<!-- Delete Confirmation Dialog -->\n<mj-ev-confirm-dialog\n [IsOpen]=\"showDeleteConfirm\"\n Title=\"Delete View\"\n [Message]=\"'Are you sure you want to delete \\'' + viewName + '\\'?'\"\n DetailMessage=\"This action cannot be undone. All users who have access to this view will lose it.\"\n ConfirmText=\"Delete\"\n ConfirmStyle=\"danger\"\n Icon=\"fa-solid fa-trash\"\n (Confirmed)=\"OnDeleteConfirmed()\"\n (Cancelled)=\"OnDeleteCancelled()\">\n</mj-ev-confirm-dialog>\n\n<!-- Filter Mode Switch Confirmation Dialog (BUG-006) -->\n<mj-ev-confirm-dialog\n [IsOpen]=\"showFilterModeSwitchConfirm\"\n Title=\"Switch Filter Mode\"\n [Message]=\"filterMode === 'smart' ? 'Switching to Traditional mode will clear your smart filter prompt.' : 'Switching to Smart mode will clear your traditional filter rules.'\"\n DetailMessage=\"You can switch back later, but the current filter data will be lost.\"\n ConfirmText=\"Switch\"\n ConfirmStyle=\"primary\"\n Icon=\"fa-solid fa-exchange-alt\"\n (Confirmed)=\"OnFilterModeSwitchConfirmed()\"\n (Cancelled)=\"OnFilterModeSwitchCancelled()\">\n</mj-ev-confirm-dialog>\n", styles: ["/* Backdrop */\n.panel-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.3);\n z-index: 1000;\n animation: fadeIn 0.2s ease;\n}\n\n@keyframes fadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n/* Sliding Panel */\n.config-panel {\n position: fixed;\n top: 0;\n right: 0;\n width: 450px;\n min-width: 360px;\n max-width: min(800px, 100vw);\n height: 100%;\n background: var(--mj-bg-surface);\n box-shadow: -4px 0 24px rgba(0, 0, 0, 0.15);\n z-index: 1001;\n display: flex;\n flex-direction: column;\n transform: translateX(100%);\n transition: transform 0.25s ease, width 0s;\n}\n\n.config-panel.open {\n transform: translateX(0);\n}\n\n.config-panel.resizing {\n transition: none;\n user-select: none;\n}\n\n/* Resize Handle */\n.resize-handle {\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n width: 6px;\n cursor: ew-resize;\n z-index: 10;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.resize-handle:hover,\n.config-panel.resizing .resize-handle {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n}\n\n.resize-grip {\n width: 3px;\n height: 40px;\n background: var(--mj-border-strong);\n border-radius: 3px;\n opacity: 0;\n transition: opacity 0.2s ease;\n}\n\n.resize-handle:hover .resize-grip,\n.config-panel.resizing .resize-grip {\n opacity: 1;\n background: var(--mj-brand-primary);\n}\n\n/* Panel Header */\n.panel-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n flex-shrink: 0;\n}\n\n.header-title {\n display: flex;\n align-items: center;\n gap: 10px;\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.header-title i {\n color: var(--mj-brand-primary);\n}\n\n.close-btn {\n width: 32px;\n height: 32px;\n border: none;\n background: transparent;\n border-radius: 8px;\n cursor: pointer;\n color: var(--mj-text-muted);\n transition: all 0.15s ease;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.close-btn:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n/* Tab Navigation */\n.tab-nav {\n display: flex;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n flex-shrink: 0;\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n}\n\n.tab-btn {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 12px 16px;\n border: none;\n background: transparent;\n cursor: pointer;\n color: var(--mj-text-muted);\n font-size: 13px;\n font-weight: 500;\n transition: all 0.15s ease;\n position: relative;\n white-space: nowrap;\n}\n\n.tab-btn:hover {\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-hover);\n}\n\n.tab-btn.active {\n color: var(--mj-brand-primary);\n font-weight: 600;\n}\n\n.tab-btn.active::after {\n content: '';\n position: absolute;\n bottom: 0;\n left: 8px;\n right: 8px;\n height: 2px;\n background: var(--mj-brand-primary);\n border-radius: 2px 2px 0 0;\n}\n\n.tab-btn i {\n font-size: 14px;\n}\n\n.tab-badge {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 18px;\n height: 18px;\n padding: 0 5px;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-radius: 9px;\n font-size: 11px;\n font-weight: 600;\n}\n\n/* Icon-only mode for narrow panel */\n.tab-nav.icon-only .tab-btn {\n padding: 12px 8px;\n}\n\n/* Panel Content */\n.panel-content {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n}\n\n.tab-content {\n padding: 16px;\n}\n\n/* Config Sections */\n.config-section {\n margin-bottom: 20px;\n}\n\n.section-header {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 0;\n margin-bottom: 8px;\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.section-header i {\n color: var(--mj-text-muted);\n font-size: 14px;\n}\n\n.column-count {\n margin-left: auto;\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n padding: 2px 8px;\n border-radius: 10px;\n font-size: 12px;\n font-weight: 500;\n}\n\n/* Column Search */\n.column-search {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n margin-bottom: 8px;\n}\n\n.column-search i {\n color: var(--mj-text-disabled);\n font-size: 12px;\n}\n\n.column-search input {\n flex: 1;\n border: none;\n outline: none;\n font-size: 13px;\n background: transparent;\n color: var(--mj-text-primary);\n}\n\n.column-search input::placeholder {\n color: var(--mj-text-disabled);\n}\n\n/* Column List */\n.column-list {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n/* Column Item */\n.column-item {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 10px;\n border-radius: 8px;\n transition: background 0.15s ease;\n cursor: default;\n}\n\n.column-item:hover {\n background: var(--mj-bg-surface-card);\n}\n\n.column-item.hidden {\n opacity: 0.7;\n}\n\n.column-item.hidden:hover {\n opacity: 1;\n}\n\n.column-item.dragging {\n opacity: 0.4;\n}\n\n.column-item.drop-target {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n}\n\n/* Drop Indicator */\n.drop-indicator {\n height: 2px;\n background: var(--mj-brand-primary);\n border-radius: 1px;\n margin: 0 10px;\n}\n\n/* Drag Handle */\n.drag-handle {\n display: flex;\n align-items: center;\n cursor: grab;\n color: var(--mj-text-disabled);\n font-size: 12px;\n padding: 4px 2px;\n}\n\n.drag-handle:active {\n cursor: grabbing;\n}\n\n.column-item:hover .drag-handle {\n color: var(--mj-text-muted);\n}\n\n/* Column Name */\n.column-name {\n flex: 1;\n font-size: 13px;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.alias-indicator {\n font-size: 10px;\n color: var(--mj-brand-primary);\n margin-left: 4px;\n}\n\n.format-indicator {\n font-size: 10px;\n color: var(--mj-status-warning);\n margin-left: 4px;\n}\n\n/* Column Actions */\n.column-actions {\n display: flex;\n align-items: center;\n gap: 2px;\n opacity: 0;\n transition: opacity 0.15s ease;\n}\n\n.column-item:hover .column-actions {\n opacity: 1;\n}\n\n.action-btn {\n width: 26px;\n height: 26px;\n border: none;\n background: transparent;\n border-radius: 6px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n transition: all 0.15s ease;\n}\n\n.action-btn:hover:not(:disabled) {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-secondary);\n}\n\n.action-btn:disabled {\n opacity: 0.3;\n cursor: not-allowed;\n}\n\n.action-btn.hide-btn:hover {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error);\n}\n\n.action-btn.show-btn {\n opacity: 0;\n}\n\n.column-item:hover .action-btn.show-btn {\n opacity: 1;\n}\n\n.action-btn.show-btn:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.action-btn.format-btn:hover {\n background: var(--mj-status-warning-bg);\n color: var(--mj-status-warning);\n}\n\n.action-btn i {\n font-size: 12px;\n}\n\n/* Empty List */\n.empty-list {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 16px;\n color: var(--mj-text-muted);\n font-size: 13px;\n}\n\n.empty-list i {\n color: var(--mj-text-disabled);\n}\n\n/* Format Editor */\n.format-editor {\n padding: 0;\n}\n\n.format-editor-header {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 16px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n}\n\n.back-btn {\n width: 32px;\n height: 32px;\n border: none;\n background: var(--mj-bg-surface-sunken);\n border-radius: 8px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-secondary);\n transition: all 0.15s ease;\n}\n\n.back-btn:hover {\n background: var(--mj-bg-surface-active);\n color: var(--mj-text-primary);\n}\n\n.format-editor-title {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n/* Format Sections */\n.format-section {\n padding: 16px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.format-section-header {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 12px;\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n}\n\n.format-section-header i {\n color: var(--mj-text-muted);\n}\n\n/* Format Rows */\n.format-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 8px 0;\n}\n\n.format-row label {\n font-size: 13px;\n color: var(--mj-text-secondary);\n}\n\n.format-row.alias-info {\n padding: 4px 0;\n}\n\n.muted-text {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.clear-alias-btn {\n width: 24px;\n height: 24px;\n border: none;\n background: transparent;\n border-radius: 4px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-disabled);\n transition: all 0.15s ease;\n}\n\n.clear-alias-btn:hover {\n color: var(--mj-status-error);\n}\n\n/* Format Input */\n.format-input {\n padding: 6px 10px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n font-size: 13px;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n transition: border-color 0.15s ease;\n}\n\n.format-input:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n}\n\n.format-input.small {\n width: 60px;\n text-align: center;\n}\n\n.format-select {\n padding: 6px 10px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n font-size: 13px;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n cursor: pointer;\n}\n\n.format-select:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n}\n\n/* Color Input */\n.color-input {\n width: 36px;\n height: 28px;\n padding: 2px;\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n cursor: pointer;\n background: var(--mj-bg-surface);\n}\n\n/* Alignment Toggle */\n.alignment-toggle {\n display: flex;\n gap: 4px;\n background: var(--mj-bg-surface-card);\n border-radius: 8px;\n padding: 3px;\n border: 1px solid var(--mj-border-default);\n}\n\n.align-btn {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 6px;\n border: none;\n background: transparent;\n border-radius: 6px;\n cursor: pointer;\n color: var(--mj-text-muted);\n transition: all 0.15s ease;\n}\n\n.align-btn:hover {\n color: var(--mj-text-secondary);\n}\n\n.align-btn.active {\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);\n}\n\n/* Style Buttons */\n.style-buttons {\n display: flex;\n gap: 4px;\n margin-bottom: 12px;\n}\n\n.style-btn {\n width: 32px;\n height: 32px;\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n border-radius: 6px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n transition: all 0.15s ease;\n}\n\n.style-btn:hover {\n border-color: var(--mj-border-strong);\n color: var(--mj-text-secondary);\n}\n\n.style-btn.active {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n/* Format Preview */\n.format-preview-section {\n padding: 16px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.preview-header {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 12px;\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n}\n\n.preview-header i {\n color: var(--mj-text-muted);\n}\n\n.preview-table {\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n overflow: hidden;\n}\n\n.preview-header-cell {\n padding: 8px 12px;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n text-transform: uppercase;\n letter-spacing: 0.3px;\n}\n\n.preview-cell {\n padding: 8px 12px;\n font-size: 13px;\n color: var(--mj-text-primary);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.preview-cell:last-child {\n border-bottom: none;\n}\n\n/* Format Actions */\n.format-actions {\n padding: 16px;\n}\n\n.clear-format-btn {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n background: var(--mj-bg-surface);\n cursor: pointer;\n font-size: 13px;\n color: var(--mj-text-secondary);\n transition: all 0.15s ease;\n}\n\n.clear-format-btn:hover {\n background: var(--mj-status-error-bg);\n border-color: var(--mj-status-error);\n color: var(--mj-status-error);\n}\n\n/* Sorting Section */\n.sorting-section {\n padding: 0;\n}\n\n.sorting-header {\n margin-bottom: 12px;\n}\n\n.sorting-description,\n.aggregates-description {\n margin: 0;\n font-size: 13px;\n color: var(--mj-text-muted);\n line-height: 1.5;\n}\n\n/* Add Sort Button */\n.add-sort-btn,\n.add-aggregate-btn {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 16px;\n width: 100%;\n border: 2px dashed var(--mj-border-default);\n border-radius: 10px;\n background: transparent;\n cursor: pointer;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-muted);\n transition: all 0.15s ease;\n margin-bottom: 12px;\n}\n\n.add-sort-btn:hover:not(:disabled),\n.add-aggregate-btn:hover:not(:disabled) {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, var(--mj-bg-surface));\n}\n\n.add-sort-btn:disabled,\n.add-aggregate-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n/* Sort Items List */\n.sort-items-list {\n display: flex;\n flex-direction: column;\n gap: 6px;\n margin-bottom: 12px;\n}\n\n.sort-item {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 10px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n transition: all 0.15s ease;\n}\n\n.sort-item:hover {\n border-color: var(--mj-border-strong);\n}\n\n.sort-item.dragging {\n opacity: 0.4;\n}\n\n.sort-item.drop-target {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, var(--mj-bg-surface));\n}\n\n/* Sort Drop Indicator */\n.sort-drop-indicator {\n height: 2px;\n background: var(--mj-brand-primary);\n border-radius: 1px;\n margin: 0 10px;\n}\n\n/* Sort Priority Badge */\n.sort-priority-badge {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-radius: 6px;\n font-size: 11px;\n font-weight: 700;\n flex-shrink: 0;\n}\n\n/* Sort Drag Handle */\n.sort-drag-handle {\n cursor: grab;\n color: var(--mj-text-disabled);\n padding: 2px;\n font-size: 12px;\n}\n\n.sort-drag-handle:active {\n cursor: grabbing;\n}\n\n.sort-item:hover .sort-drag-handle {\n color: var(--mj-text-muted);\n}\n\n/* Sort Field Dropdown */\n.sort-field-dropdown {\n flex: 1;\n padding: 6px 10px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n font-size: 13px;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n cursor: pointer;\n min-width: 0;\n}\n\n.sort-field-dropdown:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n}\n\n/* Sort Direction Toggle */\n.sort-direction-toggle {\n display: flex;\n background: var(--mj-bg-surface-sunken);\n border-radius: 6px;\n padding: 2px;\n gap: 2px;\n}\n\n.direction-btn {\n width: 28px;\n height: 28px;\n border: none;\n background: transparent;\n border-radius: 5px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n font-size: 12px;\n transition: all 0.15s ease;\n}\n\n.direction-btn:hover:not(:disabled) {\n color: var(--mj-text-secondary);\n}\n\n.direction-btn.active {\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);\n}\n\n.direction-btn:disabled {\n opacity: 0.3;\n cursor: not-allowed;\n}\n\n/* Sort Remove Button */\n.sort-remove-btn {\n width: 28px;\n height: 28px;\n border: none;\n background: transparent;\n border-radius: 6px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-disabled);\n font-size: 12px;\n transition: all 0.15s ease;\n}\n\n.sort-remove-btn:hover:not(:disabled) {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error);\n}\n\n.sort-remove-btn:disabled {\n opacity: 0.3;\n cursor: not-allowed;\n}\n\n/* Sort Hint */\n.sort-hint {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n padding: 10px 12px;\n background: var(--mj-bg-surface-card);\n border-radius: 8px;\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.sort-hint i {\n color: var(--mj-text-disabled);\n margin-top: 1px;\n}\n\n/* Sort Empty State */\n.sort-empty-state,\n.aggregates-empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n padding: 32px 16px;\n color: var(--mj-text-muted);\n text-align: center;\n}\n\n.sort-empty-state i,\n.aggregates-empty-state i {\n font-size: 32px;\n opacity: 0.4;\n}\n\n.sort-empty-state span,\n.aggregates-empty-state span {\n font-size: 14px;\n font-weight: 500;\n}\n\n.sort-empty-hint,\n.empty-hint {\n margin: 0;\n font-size: 13px;\n color: var(--mj-text-disabled);\n}\n\n/* Filter Mode Selector */\n.filter-mode-selector {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-bottom: 16px;\n}\n\n.filter-mode-btn {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 14px;\n border: 2px solid var(--mj-border-default);\n border-radius: 10px;\n background: var(--mj-bg-surface);\n cursor: pointer;\n transition: all 0.15s ease;\n text-align: left;\n}\n\n.filter-mode-btn:hover:not(:disabled) {\n border-color: var(--mj-border-strong);\n}\n\n.filter-mode-btn.active {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, var(--mj-bg-surface));\n}\n\n.filter-mode-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.mode-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 8px;\n font-size: 16px;\n color: var(--mj-text-muted);\n flex-shrink: 0;\n}\n\n.filter-mode-btn.active .mode-icon {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.mode-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.mode-title {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.mode-subtitle {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.mode-check {\n color: var(--mj-brand-primary);\n font-size: 14px;\n}\n\n/* Smart Filter Section */\n.smart-filter-section {\n padding: 0;\n}\n\n.smart-filter-input-container {\n display: flex;\n gap: 12px;\n padding: 12px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n margin-bottom: 12px;\n}\n\n.smart-filter-icon {\n display: flex;\n align-items: flex-start;\n padding-top: 4px;\n color: var(--mj-brand-primary);\n font-size: 16px;\n}\n\n.smart-filter-textarea {\n flex: 1;\n border: none;\n outline: none;\n resize: vertical;\n font-size: 14px;\n font-family: inherit;\n color: var(--mj-text-primary);\n background: transparent;\n min-height: 60px;\n}\n\n.smart-filter-textarea::placeholder {\n color: var(--mj-text-disabled);\n}\n\n.smart-filter-textarea:disabled {\n color: var(--mj-text-muted);\n}\n\n/* Smart Filter Explanation */\n.smart-filter-explanation {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n padding: 10px 12px;\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) 25%, var(--mj-bg-surface));\n border-radius: 8px;\n margin-bottom: 12px;\n font-size: 13px;\n color: var(--mj-brand-primary);\n}\n\n.smart-filter-explanation i {\n margin-top: 2px;\n}\n\n/* Smart Filter Examples */\n.smart-filter-examples {\n margin-bottom: 12px;\n}\n\n.examples-header {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 8px;\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-muted);\n}\n\n.examples-header i {\n color: var(--mj-status-warning);\n}\n\n.example-chips {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n}\n\n.example-chip {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 20px;\n background: var(--mj-bg-surface);\n cursor: pointer;\n font-size: 12px;\n color: var(--mj-text-secondary);\n transition: all 0.15s ease;\n}\n\n.example-chip:hover:not(:disabled) {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, var(--mj-bg-surface));\n}\n\n.example-chip:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.example-chip i {\n font-size: 11px;\n}\n\n/* Smart Filter Tip */\n.smart-filter-tip,\n.traditional-filter-tip,\n.aggregates-tip {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n padding: 10px 12px;\n background: var(--mj-bg-surface-card);\n border-radius: 8px;\n font-size: 12px;\n color: var(--mj-text-muted);\n margin-top: 12px;\n}\n\n.smart-filter-tip i,\n.traditional-filter-tip i,\n.aggregates-tip i {\n color: var(--mj-text-disabled);\n margin-top: 1px;\n}\n\n/* Traditional Filter Section */\n.traditional-filter-section {\n padding: 0;\n}\n\n.filter-summary-container {\n margin-bottom: 12px;\n}\n\n.filter-summary {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 14px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n}\n\n.summary-info {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.filter-badge {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 22px;\n height: 22px;\n padding: 0 6px;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-radius: 11px;\n font-size: 12px;\n font-weight: 600;\n}\n\n.summary-text {\n font-size: 13px;\n color: var(--mj-text-primary);\n font-weight: 500;\n}\n\n.summary-text.no-filters {\n color: var(--mj-text-muted);\n font-weight: 400;\n}\n\n.summary-actions {\n display: flex;\n gap: 8px;\n}\n\n.summary-btn {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n background: var(--mj-bg-surface);\n cursor: pointer;\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n transition: all 0.15s ease;\n}\n\n.summary-btn:hover:not(:disabled) {\n border-color: var(--mj-border-strong);\n}\n\n.summary-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.summary-btn.clear-btn:hover {\n border-color: var(--mj-status-error);\n color: var(--mj-status-error);\n}\n\n.summary-btn.primary {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.summary-btn.primary:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n border-color: var(--mj-brand-primary-hover);\n}\n\n/* Aggregates Section */\n.aggregates-section {\n padding: 0;\n}\n\n.aggregates-header {\n margin-bottom: 12px;\n}\n\n/* Aggregates List */\n.aggregates-list {\n display: flex;\n flex-direction: column;\n gap: 6px;\n margin-bottom: 12px;\n}\n\n.aggregate-item {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 12px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n transition: all 0.15s ease;\n}\n\n.aggregate-item:hover {\n border-color: var(--mj-border-strong);\n}\n\n.aggregate-item.disabled {\n opacity: 0.5;\n}\n\n/* Aggregate Icon */\n.agg-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n border-radius: 8px;\n color: var(--mj-brand-primary);\n font-size: 14px;\n flex-shrink: 0;\n}\n\n/* Aggregate Content */\n.agg-content {\n flex: 1;\n min-width: 0;\n}\n\n.agg-label {\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.agg-details {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-top: 2px;\n}\n\n.agg-type {\n display: flex;\n align-items: center;\n gap: 4px;\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n\n.agg-smart-badge {\n color: var(--mj-brand-primary);\n font-size: 11px;\n}\n\n/* Aggregate Actions */\n.agg-actions {\n display: flex;\n align-items: center;\n gap: 2px;\n opacity: 0;\n transition: opacity 0.15s ease;\n}\n\n.aggregate-item:hover .agg-actions {\n opacity: 1;\n}\n\n.agg-action-btn {\n width: 26px;\n height: 26px;\n border: none;\n background: transparent;\n border-radius: 6px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n font-size: 12px;\n transition: all 0.15s ease;\n}\n\n.agg-action-btn:hover:not(:disabled) {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-secondary);\n}\n\n.agg-action-btn:disabled {\n opacity: 0.3;\n cursor: not-allowed;\n}\n\n.agg-action-btn.toggle-btn.enabled {\n color: var(--mj-brand-primary);\n}\n\n.agg-action-btn.remove-btn:hover:not(:disabled) {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error);\n}\n\n.agg-action-btn.edit-btn:hover:not(:disabled) {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n/* Aggregates Summary */\n.aggregates-summary {\n display: flex;\n gap: 16px;\n padding: 10px 12px;\n background: var(--mj-bg-surface-card);\n border-radius: 8px;\n margin-bottom: 12px;\n}\n\n.aggregates-summary .summary-item {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.aggregates-summary .summary-item i {\n color: var(--mj-text-disabled);\n}\n\n/* Settings Tab */\n.form-group {\n margin-bottom: 16px;\n}\n\n.form-group label {\n display: block;\n margin-bottom: 6px;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n.form-input {\n width: 100%;\n padding: 8px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n font-size: 14px;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n transition: border-color 0.15s ease;\n box-sizing: border-box;\n}\n\n.form-input:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n}\n\n.form-input.invalid {\n border-color: var(--mj-status-error);\n}\n\n.form-textarea {\n resize: vertical;\n min-height: 60px;\n font-family: inherit;\n}\n\n.validation-error {\n font-size: 12px;\n color: var(--mj-status-error);\n margin-top: 4px;\n}\n\n/* Checkbox */\n.checkbox-label {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n cursor: pointer;\n}\n\n.checkbox-label input[type=\"checkbox\"] {\n margin-top: 3px;\n flex-shrink: 0;\n}\n\n.checkbox-text {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.checkbox-text strong {\n font-size: 13px;\n color: var(--mj-text-primary);\n}\n\n.checkbox-text small {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n/* Danger Zone */\n.danger-zone .section-header {\n color: var(--mj-status-error);\n}\n\n.danger-zone .section-header i {\n color: var(--mj-status-error);\n}\n\n.delete-btn {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 16px;\n border: 1px solid var(--mj-status-error);\n border-radius: 8px;\n background: var(--mj-status-error-bg);\n cursor: pointer;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-status-error);\n transition: all 0.15s ease;\n}\n\n.delete-btn:hover {\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n}\n\n/* Validation Banner */\n.validation-banner {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 16px;\n background: var(--mj-status-error-bg);\n border-top: 1px solid var(--mj-status-error);\n font-size: 13px;\n color: var(--mj-status-error);\n flex-shrink: 0;\n}\n\n/* Panel Footer */\n.panel-footer {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 14px 20px;\n border-top: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n flex-shrink: 0;\n}\n\n.footer-left {\n display: flex;\n gap: 8px;\n}\n\n.footer-btn {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 9px 18px;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n background: var(--mj-bg-surface);\n cursor: pointer;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n transition: all 0.15s ease;\n}\n\n.footer-btn:hover:not(:disabled) {\n border-color: var(--mj-border-strong);\n}\n\n.footer-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.footer-btn.primary {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.footer-btn.primary:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n border-color: var(--mj-brand-primary-hover);\n}\n\n.footer-btn.cancel-btn {\n background: var(--mj-bg-surface-card);\n}\n\n.footer-btn.cancel-btn:hover {\n background: var(--mj-bg-surface-active);\n}\n\n/* Responsive */\n@media (max-width: 480px) {\n .config-panel {\n width: 100vw;\n min-width: auto;\n }\n\n .resize-handle {\n display: none;\n }\n}\n"] }]
2857
+ args: [{ standalone: false, selector: 'mj-view-config-panel', template: "<!-- Backdrop -->\n@if (isOpen) {\n <div class=\"panel-backdrop\" (click)=\"onClose()\"></div>\n}\n\n<!-- Sliding Panel -->\n<div class=\"config-panel\"\n [class.open]=\"isOpen\"\n [class.resizing]=\"isResizing\"\n [style.width.px]=\"panelWidth\">\n <!-- Resize Handle -->\n <div class=\"resize-handle\"\n (mousedown)=\"onResizeStart($event)\"\n title=\"Drag to resize\">\n <div class=\"resize-grip\"></div>\n </div>\n\n <!-- Panel Header -->\n <div class=\"panel-header\">\n <div class=\"header-title\">\n <i class=\"fa-solid fa-sliders-h\"></i>\n <span>{{ viewEntity ? 'Edit View' : 'Configure View' }}</span>\n </div>\n <button class=\"close-btn\" (click)=\"onClose()\" title=\"Close\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n\n <!-- Tab Navigation -->\n <div class=\"tab-nav\" [class.icon-only]=\"isIconOnlyMode\">\n <button\n class=\"tab-btn\"\n [class.active]=\"activeTab === 'columns'\"\n (click)=\"setActiveTab('columns')\"\n [title]=\"isIconOnlyMode ? 'Columns' : ''\">\n <i class=\"fa-solid fa-columns\"></i>\n @if (!isIconOnlyMode) {\n <span>Columns</span>\n }\n </button>\n <button\n class=\"tab-btn\"\n [class.active]=\"activeTab === 'sorting'\"\n (click)=\"setActiveTab('sorting')\"\n [title]=\"isIconOnlyMode ? 'Sorting' + (sortItems.length > 0 ? ' (' + sortItems.length + ')' : '') : ''\">\n <i class=\"fa-solid fa-arrow-up-wide-short\"></i>\n @if (!isIconOnlyMode) {\n <span>Sorting</span>\n }\n @if (sortItems.length > 0) {\n <span class=\"tab-badge\">{{ sortItems.length }}</span>\n }\n </button>\n <button\n class=\"tab-btn\"\n [class.active]=\"activeTab === 'filters'\"\n (click)=\"setActiveTab('filters')\"\n [title]=\"isIconOnlyMode ? 'Filters' : ''\">\n <i class=\"fa-solid fa-filter\"></i>\n @if (!isIconOnlyMode) {\n <span>Filters</span>\n }\n </button>\n <button\n class=\"tab-btn\"\n [class.active]=\"activeTab === 'aggregates'\"\n (click)=\"setActiveTab('aggregates')\"\n [title]=\"isIconOnlyMode ? 'Aggregates' + (enabledAggregatesCount > 0 ? ' (' + enabledAggregatesCount + ')' : '') : ''\">\n <i class=\"fa-solid fa-chart-simple\"></i>\n @if (!isIconOnlyMode) {\n <span>Aggregates</span>\n }\n @if (enabledAggregatesCount > 0) {\n <span class=\"tab-badge\">{{ enabledAggregatesCount }}</span>\n }\n </button>\n @if (viewEntity || DefaultSaveAsNew) {\n <button\n class=\"tab-btn\"\n [class.active]=\"activeTab === 'settings'\"\n (click)=\"setActiveTab('settings')\"\n [title]=\"isIconOnlyMode ? 'Settings' : ''\">\n <i class=\"fa-solid fa-cog\"></i>\n @if (!isIconOnlyMode) {\n <span>Settings</span>\n }\n </button>\n }\n </div>\n\n <!-- Panel Content -->\n <div class=\"panel-content\">\n <!-- Columns Tab -->\n @if (activeTab === 'columns' && !formatEditingColumn) {\n <div class=\"tab-content\">\n <!-- Visible Columns -->\n <div class=\"config-section\">\n <div class=\"section-header\">\n <i class=\"fa-solid fa-eye\"></i>\n <span>Visible Columns</span>\n <span class=\"column-count\">{{ visibleColumns.length }}</span>\n </div>\n <div class=\"column-list visible-columns\">\n @for (column of visibleColumns; track column.fieldId; let i = $index) {\n <!-- Drop indicator before -->\n @if (isDropBefore(column)) {\n <div class=\"drop-indicator\"></div>\n }\n <div\n class=\"column-item\"\n [class.dragging]=\"draggedColumn === column\"\n [class.drop-target]=\"dropTargetColumn === column\"\n draggable=\"true\"\n (dragstart)=\"onDragStart($event, column)\"\n (dragover)=\"onDragOver($event, column)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event, column)\"\n (dragend)=\"onDragEnd($event)\">\n <div class=\"drag-handle\">\n <i class=\"fa-solid fa-grip-vertical\"></i>\n </div>\n <span class=\"column-name\">\n {{ column.userDisplayName || column.displayName }}\n @if (column.userDisplayName) {\n <i class=\"fa-solid fa-pen-nib alias-indicator\" title=\"Custom name: {{ column.userDisplayName }}\"></i>\n }\n @if (hasCustomFormat(column)) {\n <i class=\"fa-solid fa-paintbrush format-indicator\" title=\"Custom formatting applied\"></i>\n }\n </span>\n <div class=\"column-actions\">\n <button\n class=\"action-btn format-btn\"\n (click)=\"openFormatEditor(column)\"\n title=\"Format column\">\n <i class=\"fa-solid fa-paintbrush\"></i>\n </button>\n <button\n class=\"action-btn\"\n [disabled]=\"i === 0\"\n (click)=\"moveColumnUp(column)\"\n title=\"Move up\">\n <i class=\"fa-solid fa-chevron-up\"></i>\n </button>\n <button\n class=\"action-btn\"\n [disabled]=\"i === visibleColumns.length - 1\"\n (click)=\"moveColumnDown(column)\"\n title=\"Move down\">\n <i class=\"fa-solid fa-chevron-down\"></i>\n </button>\n <button\n class=\"action-btn hide-btn\"\n (click)=\"toggleColumnVisibility(column)\"\n title=\"Hide column\">\n <i class=\"fa-solid fa-eye-slash\"></i>\n </button>\n </div>\n </div>\n <!-- Drop indicator after (only for last item) -->\n @if (isDropAfter(column) && i === visibleColumns.length - 1) {\n <div class=\"drop-indicator\"></div>\n }\n }\n @if (visibleColumns.length === 0) {\n <div class=\"empty-list\">\n <i class=\"fa-solid fa-info-circle\"></i>\n <span>No columns visible. Add columns from below.</span>\n </div>\n }\n </div>\n </div>\n\n <!-- Hidden Columns -->\n <div class=\"config-section\">\n <div class=\"section-header\">\n <i class=\"fa-solid fa-eye-slash\"></i>\n <span>Hidden Columns</span>\n <span class=\"column-count\">{{ hiddenColumns.length }}</span>\n </div>\n @if (hiddenColumns.length > 5) {\n <div class=\"column-search\">\n <i class=\"fa-solid fa-search\"></i>\n <input\n type=\"text\"\n placeholder=\"Search columns...\"\n [(ngModel)]=\"columnSearchText\"\n />\n </div>\n }\n <div class=\"column-list hidden-columns\">\n @for (column of filteredHiddenColumns; track column.fieldId) {\n <div class=\"column-item hidden\">\n <span class=\"column-name\">{{ column.displayName }}</span>\n <button\n class=\"action-btn show-btn\"\n (click)=\"toggleColumnVisibility(column)\"\n title=\"Show column\">\n <i class=\"fa-solid fa-plus\"></i>\n </button>\n </div>\n }\n @if (hiddenColumns.length === 0) {\n <div class=\"empty-list\">\n <i class=\"fa-solid fa-check-circle\"></i>\n <span>All columns are visible</span>\n </div>\n }\n </div>\n </div>\n </div>\n }\n\n <!-- Column Format Editor Sub-Panel -->\n @if (activeTab === 'columns' && formatEditingColumn) {\n <div class=\"format-editor\">\n <!-- Format Editor Header -->\n <div class=\"format-editor-header\">\n <button class=\"back-btn\" (click)=\"closeFormatEditor()\">\n <i class=\"fa-solid fa-arrow-left\"></i>\n </button>\n <div class=\"format-editor-title\">\n <span>Format: {{ formatEditingColumn.userDisplayName || formatEditingColumn.displayName }}</span>\n </div>\n </div>\n\n <!-- Column Alias Section -->\n <div class=\"format-section\">\n <div class=\"format-section-header\">\n <i class=\"fa-solid fa-pen-nib\"></i>\n <span>Column Name</span>\n </div>\n <div class=\"format-row\">\n <label>Display As</label>\n <input type=\"text\" class=\"format-input\"\n [value]=\"formatEditingColumn.userDisplayName || ''\"\n (input)=\"updateUserDisplayName($any($event.target).value)\"\n [placeholder]=\"formatEditingColumn.displayName\" />\n </div>\n @if (formatEditingColumn.userDisplayName) {\n <div class=\"format-row alias-info\">\n <small class=\"muted-text\">Original: {{ formatEditingColumn.displayName }}</small>\n <button class=\"clear-alias-btn\" (click)=\"formatEditingColumn.userDisplayName = undefined\" title=\"Clear alias\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n }\n </div>\n\n <!-- Preview Section -->\n <div class=\"format-preview-section\">\n <div class=\"preview-header\">\n <i class=\"fa-solid fa-eye\"></i>\n <span>Preview</span>\n </div>\n <div class=\"preview-table\">\n <div class=\"preview-header-cell\"\n [style.font-weight]=\"formatEditingColumn.format?.headerStyle?.bold ? 'bold' : 'normal'\"\n [style.font-style]=\"formatEditingColumn.format?.headerStyle?.italic ? 'italic' : 'normal'\"\n [style.text-decoration]=\"formatEditingColumn.format?.headerStyle?.underline ? 'underline' : 'none'\"\n [style.color]=\"formatEditingColumn.format?.headerStyle?.color\"\n [style.background-color]=\"formatEditingColumn.format?.headerStyle?.backgroundColor\">\n {{ formatEditingColumn.userDisplayName || formatEditingColumn.displayName }}\n </div>\n @for (value of getSampleValues(formatEditingColumn); track $index) {\n <div class=\"preview-cell\"\n [style.text-align]=\"formatEditingColumn.format?.align || 'left'\"\n [style.font-weight]=\"formatEditingColumn.format?.cellStyle?.bold ? 'bold' : 'normal'\"\n [style.font-style]=\"formatEditingColumn.format?.cellStyle?.italic ? 'italic' : 'normal'\"\n [style.text-decoration]=\"formatEditingColumn.format?.cellStyle?.underline ? 'underline' : 'none'\"\n [style.color]=\"formatEditingColumn.format?.cellStyle?.color\"\n [style.background-color]=\"formatEditingColumn.format?.cellStyle?.backgroundColor\">\n {{ formatPreviewValue(value, formatEditingColumn.format) }}\n </div>\n }\n </div>\n </div>\n\n <!-- Format Type -->\n <div class=\"format-section\">\n <div class=\"format-section-header\">\n <i class=\"fa-solid fa-hashtag\"></i>\n <span>Format Type</span>\n </div>\n <select class=\"format-select\" [(ngModel)]=\"formatEditingColumn.format!.type\">\n <option value=\"auto\">Auto (Smart Default)</option>\n <option value=\"text\">Text</option>\n <option value=\"number\">Number</option>\n <option value=\"currency\">Currency</option>\n <option value=\"percent\">Percent</option>\n <option value=\"date\">Date</option>\n <option value=\"datetime\">Date & Time</option>\n <option value=\"boolean\">Boolean</option>\n </select>\n </div>\n\n <!-- Type-Specific Options -->\n @if (formatEditingColumn.format?.type === 'number' || formatEditingColumn.format?.type === 'currency' || formatEditingColumn.format?.type === 'percent') {\n <div class=\"format-section\">\n <div class=\"format-section-header\">\n <i class=\"fa-solid fa-sliders\"></i>\n <span>Number Options</span>\n </div>\n <div class=\"format-row\">\n <label>Decimal Places</label>\n <input type=\"number\" class=\"format-input small\" min=\"0\" max=\"10\"\n [(ngModel)]=\"formatEditingColumn.format!.decimals\" />\n </div>\n @if (formatEditingColumn.format?.type === 'currency') {\n <div class=\"format-row\">\n <label>Currency</label>\n <select class=\"format-select\" [(ngModel)]=\"formatEditingColumn.format!.currencyCode\">\n <option value=\"USD\">USD ($)</option>\n <option value=\"EUR\">EUR (\u20AC)</option>\n <option value=\"GBP\">GBP (\u00A3)</option>\n <option value=\"JPY\">JPY (\u00A5)</option>\n <option value=\"CAD\">CAD ($)</option>\n <option value=\"AUD\">AUD ($)</option>\n </select>\n </div>\n }\n <div class=\"format-row\">\n <label>Thousands Separator</label>\n <input type=\"checkbox\" [(ngModel)]=\"formatEditingColumn.format!.thousandsSeparator\" />\n </div>\n </div>\n }\n\n @if (formatEditingColumn.format?.type === 'date' || formatEditingColumn.format?.type === 'datetime') {\n <div class=\"format-section\">\n <div class=\"format-section-header\">\n <i class=\"fa-solid fa-calendar\"></i>\n <span>Date Options</span>\n </div>\n <div class=\"format-row\">\n <label>Format</label>\n <select class=\"format-select\" [(ngModel)]=\"formatEditingColumn.format!.dateFormat\">\n <option value=\"short\">Short (1/15/25)</option>\n <option value=\"short-weekday\">Short + Day (Wed, 1/15/25)</option>\n <option value=\"medium\">Medium (Jan 15, 2025)</option>\n <option value=\"medium-weekday\">Medium + Day (Wed, Jan 15, 2025)</option>\n <option value=\"long\">Long (January 15, 2025)</option>\n <option value=\"long-weekday\">Long + Day (Wednesday, January 15, 2025)</option>\n </select>\n </div>\n </div>\n }\n\n @if (formatEditingColumn.format?.type === 'boolean') {\n <div class=\"format-section\">\n <div class=\"format-section-header\">\n <i class=\"fa-solid fa-toggle-on\"></i>\n <span>Boolean Options</span>\n </div>\n <div class=\"format-row\">\n <label>True Label</label>\n <input type=\"text\" class=\"format-input\" [(ngModel)]=\"formatEditingColumn.format!.trueLabel\" placeholder=\"Yes\" />\n </div>\n <div class=\"format-row\">\n <label>False Label</label>\n <input type=\"text\" class=\"format-input\" [(ngModel)]=\"formatEditingColumn.format!.falseLabel\" placeholder=\"No\" />\n </div>\n <div class=\"format-row\">\n <label>Display As</label>\n <select class=\"format-select\" [(ngModel)]=\"formatEditingColumn.format!.booleanDisplay\">\n <option value=\"text\">Text</option>\n <option value=\"checkbox\">Checkbox</option>\n <option value=\"icon\">Icon</option>\n </select>\n </div>\n </div>\n }\n\n <!-- Alignment -->\n <div class=\"format-section\">\n <div class=\"format-section-header\">\n <i class=\"fa-solid fa-align-left\"></i>\n <span>Alignment</span>\n </div>\n <div class=\"alignment-toggle\">\n <button class=\"align-btn\" [class.active]=\"formatEditingColumn.format?.align === 'left' || !formatEditingColumn.format?.align\"\n (click)=\"formatEditingColumn.format!.align = 'left'\" title=\"Left\">\n <i class=\"fa-solid fa-align-left\"></i>\n </button>\n <button class=\"align-btn\" [class.active]=\"formatEditingColumn.format?.align === 'center'\"\n (click)=\"formatEditingColumn.format!.align = 'center'\" title=\"Center\">\n <i class=\"fa-solid fa-align-center\"></i>\n </button>\n <button class=\"align-btn\" [class.active]=\"formatEditingColumn.format?.align === 'right'\"\n (click)=\"formatEditingColumn.format!.align = 'right'\" title=\"Right\">\n <i class=\"fa-solid fa-align-right\"></i>\n </button>\n </div>\n </div>\n\n <!-- Header Style -->\n <div class=\"format-section\">\n <div class=\"format-section-header\">\n <i class=\"fa-solid fa-heading\"></i>\n <span>Header Style</span>\n </div>\n <div class=\"style-buttons\">\n <button class=\"style-btn\" [class.active]=\"formatEditingColumn.format?.headerStyle?.bold\"\n (click)=\"toggleHeaderStyle('bold')\"\n title=\"Bold\">\n <i class=\"fa-solid fa-bold\"></i>\n </button>\n <button class=\"style-btn\" [class.active]=\"formatEditingColumn.format?.headerStyle?.italic\"\n (click)=\"toggleHeaderStyle('italic')\"\n title=\"Italic\">\n <i class=\"fa-solid fa-italic\"></i>\n </button>\n <button class=\"style-btn\" [class.active]=\"formatEditingColumn.format?.headerStyle?.underline\"\n (click)=\"toggleHeaderStyle('underline')\"\n title=\"Underline\">\n <i class=\"fa-solid fa-underline\"></i>\n </button>\n </div>\n <div class=\"format-row\">\n <label>Text Color</label>\n <input type=\"color\" class=\"color-input\"\n [value]=\"formatEditingColumn.format?.headerStyle?.color || '#000000'\"\n (input)=\"updateHeaderColor('color', $any($event.target).value)\" />\n </div>\n <div class=\"format-row\">\n <label>Background</label>\n <input type=\"color\" class=\"color-input\"\n [value]=\"formatEditingColumn.format?.headerStyle?.backgroundColor || '#ffffff'\"\n (input)=\"updateHeaderColor('backgroundColor', $any($event.target).value)\" />\n </div>\n </div>\n\n <!-- Cell Style -->\n <div class=\"format-section\">\n <div class=\"format-section-header\">\n <i class=\"fa-solid fa-table-cells\"></i>\n <span>Cell Style</span>\n </div>\n <div class=\"style-buttons\">\n <button class=\"style-btn\" [class.active]=\"formatEditingColumn.format?.cellStyle?.bold\"\n (click)=\"toggleCellStyle('bold')\"\n title=\"Bold\">\n <i class=\"fa-solid fa-bold\"></i>\n </button>\n <button class=\"style-btn\" [class.active]=\"formatEditingColumn.format?.cellStyle?.italic\"\n (click)=\"toggleCellStyle('italic')\"\n title=\"Italic\">\n <i class=\"fa-solid fa-italic\"></i>\n </button>\n <button class=\"style-btn\" [class.active]=\"formatEditingColumn.format?.cellStyle?.underline\"\n (click)=\"toggleCellStyle('underline')\"\n title=\"Underline\">\n <i class=\"fa-solid fa-underline\"></i>\n </button>\n </div>\n <div class=\"format-row\">\n <label>Text Color</label>\n <input type=\"color\" class=\"color-input\"\n [value]=\"formatEditingColumn.format?.cellStyle?.color || '#000000'\"\n (input)=\"updateCellColor('color', $any($event.target).value)\" />\n </div>\n <div class=\"format-row\">\n <label>Background</label>\n <input type=\"color\" class=\"color-input\"\n [value]=\"formatEditingColumn.format?.cellStyle?.backgroundColor || '#ffffff'\"\n (input)=\"updateCellColor('backgroundColor', $any($event.target).value)\" />\n </div>\n </div>\n\n <!-- Clear Format Button -->\n <div class=\"format-actions\">\n <button class=\"clear-format-btn\" (click)=\"clearColumnFormat(formatEditingColumn); closeFormatEditor()\">\n <i class=\"fa-solid fa-eraser\"></i>\n Clear Formatting\n </button>\n </div>\n </div>\n }\n\n <!-- Sorting Tab -->\n @if (activeTab === 'sorting') {\n <div class=\"tab-content\">\n <div class=\"config-section sorting-section\">\n <div class=\"sorting-header\">\n <p class=\"sorting-description\">\n Define how records should be ordered. Add multiple levels to sort by secondary fields when values are equal.\n </p>\n </div>\n\n <!-- Add Sort Button -->\n <button\n class=\"add-sort-btn\"\n (click)=\"addSortLevel()\"\n [disabled]=\"!canEdit || sortItems.length >= sortableFields.length\"\n title=\"Add another sort level\">\n <i class=\"fa-solid fa-plus\"></i>\n <span>Add Sort Level</span>\n </button>\n\n <!-- Sort Items List -->\n @if (sortItems.length > 0) {\n <div class=\"sort-items-list\">\n @for (sortItem of sortItems; track $index; let i = $index) {\n <!-- Drop indicator before -->\n @if (isSortDropBefore(sortItem)) {\n <div class=\"sort-drop-indicator\"></div>\n }\n <div\n class=\"sort-item\"\n [class.dragging]=\"draggedSortItem === sortItem\"\n [class.drop-target]=\"dropTargetSortItem === sortItem\"\n draggable=\"true\"\n (dragstart)=\"onSortDragStart($event, sortItem)\"\n (dragover)=\"onSortDragOver($event, sortItem)\"\n (dragleave)=\"onSortDragLeave($event)\"\n (drop)=\"onSortDrop($event, sortItem)\"\n (dragend)=\"onSortDragEnd($event)\">\n <!-- Priority Badge -->\n <div class=\"sort-priority-badge\">{{ i + 1 }}</div>\n <!-- Drag Handle -->\n <div class=\"sort-drag-handle\" title=\"Drag to reorder\">\n <i class=\"fa-solid fa-grip-vertical\"></i>\n </div>\n <!-- Field Dropdown -->\n <select\n class=\"sort-field-dropdown\"\n [(ngModel)]=\"sortItem.field\"\n (ngModelChange)=\"onSortFieldChange(sortItem, $event)\"\n [disabled]=\"!canEdit\">\n @for (field of sortableFields; track field.ID) {\n <option [value]=\"field.Name\">{{ field.DisplayNameOrName }}</option>\n }\n </select>\n <!-- Direction Toggle -->\n <div class=\"sort-direction-toggle\">\n <button\n class=\"direction-btn\"\n [class.active]=\"sortItem.direction === 'asc'\"\n (click)=\"onSortDirectionChange(sortItem, 'asc')\"\n [disabled]=\"!canEdit\"\n title=\"Ascending (A-Z, 1-9)\">\n <i class=\"fa-solid fa-arrow-up\"></i>\n </button>\n <button\n class=\"direction-btn\"\n [class.active]=\"sortItem.direction === 'desc'\"\n (click)=\"onSortDirectionChange(sortItem, 'desc')\"\n [disabled]=\"!canEdit\"\n title=\"Descending (Z-A, 9-1)\">\n <i class=\"fa-solid fa-arrow-down\"></i>\n </button>\n </div>\n <!-- Remove Button -->\n <button\n class=\"sort-remove-btn\"\n (click)=\"removeSortLevel(sortItem)\"\n [disabled]=\"!canEdit\"\n title=\"Remove sort level\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n <!-- Drop indicator after (only for last item) -->\n @if (isSortDropAfter(sortItem) && i === sortItems.length - 1) {\n <div class=\"sort-drop-indicator\"></div>\n }\n }\n </div>\n <!-- Multi-sort hint -->\n @if (sortItems.length > 1) {\n <div class=\"sort-hint\">\n <i class=\"fa-solid fa-info-circle\"></i>\n <span>Drag items to change priority. Records sort by first level, then second, etc.</span>\n </div>\n }\n } @else {\n <div class=\"sort-empty-state\">\n <i class=\"fa-solid fa-arrow-up-wide-short\"></i>\n <span>No sorting configured</span>\n <p class=\"sort-empty-hint\">Click \"Add Sort Level\" to define how records should be ordered</p>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- Filters Tab -->\n @if (activeTab === 'filters') {\n <div class=\"tab-content\">\n <!-- Filter Mode Selection -->\n <div class=\"filter-mode-selector\">\n <button\n class=\"filter-mode-btn\"\n [class.active]=\"filterMode === 'smart'\"\n (click)=\"setFilterMode('smart')\"\n [disabled]=\"!canEdit\">\n <div class=\"mode-icon\">\n <i class=\"fa-solid fa-wand-magic-sparkles\"></i>\n </div>\n <div class=\"mode-content\">\n <span class=\"mode-title\">Smart Filter</span>\n <span class=\"mode-subtitle\">Use AI to filter with natural language</span>\n </div>\n @if (filterMode === 'smart') {\n <i class=\"fa-solid fa-check mode-check\"></i>\n }\n </button>\n <button\n class=\"filter-mode-btn\"\n [class.active]=\"filterMode === 'traditional'\"\n (click)=\"setFilterMode('traditional')\"\n [disabled]=\"!canEdit\">\n <div class=\"mode-icon\">\n <i class=\"fa-solid fa-sliders\"></i>\n </div>\n <div class=\"mode-content\">\n <span class=\"mode-title\">Traditional Filter</span>\n <span class=\"mode-subtitle\">Build filters with field/operator/value</span>\n </div>\n @if (filterMode === 'traditional') {\n <i class=\"fa-solid fa-check mode-check\"></i>\n }\n </button>\n </div>\n\n <!-- Smart Filter Section -->\n @if (filterMode === 'smart') {\n <div class=\"config-section smart-filter-section\">\n <div class=\"smart-filter-input-container\">\n <div class=\"smart-filter-icon\">\n <i class=\"fa-solid fa-wand-magic-sparkles\"></i>\n </div>\n <textarea\n id=\"smartFilterPrompt\"\n class=\"smart-filter-textarea\"\n placeholder=\"Describe what you're looking for...\"\n [(ngModel)]=\"smartFilterPrompt\"\n [disabled]=\"!canEdit\"\n rows=\"3\"\n ></textarea>\n </div>\n\n @if (smartFilterExplanation) {\n <div class=\"smart-filter-explanation\">\n <i class=\"fa-solid fa-robot\"></i>\n <span>{{ smartFilterExplanation }}</span>\n </div>\n }\n\n <!-- Example Prompts -->\n <div class=\"smart-filter-examples\">\n <div class=\"examples-header\">\n <i class=\"fa-solid fa-lightbulb\"></i>\n <span>Try these examples:</span>\n </div>\n <div class=\"example-chips\">\n <button\n class=\"example-chip\"\n (click)=\"applySmartFilterExample('Show records created in the last 30 days')\"\n [disabled]=\"!canEdit\">\n <i class=\"fa-regular fa-calendar\"></i>\n Last 30 days\n </button>\n <button\n class=\"example-chip\"\n (click)=\"applySmartFilterExample('Active records only')\"\n [disabled]=\"!canEdit\">\n <i class=\"fa-solid fa-circle-check\"></i>\n Active only\n </button>\n <button\n class=\"example-chip\"\n (click)=\"applySmartFilterExample('Records with high priority')\"\n [disabled]=\"!canEdit\">\n <i class=\"fa-solid fa-star\"></i>\n High priority\n </button>\n <button\n class=\"example-chip\"\n (click)=\"applySmartFilterExample('Records modified this week')\"\n [disabled]=\"!canEdit\">\n <i class=\"fa-solid fa-clock-rotate-left\"></i>\n Modified this week\n </button>\n </div>\n </div>\n\n <div class=\"smart-filter-tip\">\n <i class=\"fa-solid fa-info-circle\"></i>\n <span>The AI will interpret your description and create the appropriate filter when you save the view.</span>\n </div>\n </div>\n }\n\n <!-- Traditional Filter Section -->\n @if (filterMode === 'traditional') {\n <div class=\"config-section traditional-filter-section\">\n <div class=\"filter-summary-container\">\n <div class=\"filter-summary\">\n <div class=\"summary-info\">\n @if (getFilterCount() > 0) {\n <span class=\"filter-badge\">{{ getFilterCount() }}</span>\n <span class=\"summary-text\">{{ getFilterSummary() }}</span>\n } @else {\n <span class=\"summary-text no-filters\">No filters configured</span>\n }\n </div>\n <div class=\"summary-actions\">\n @if (getFilterCount() > 0 && canEdit) {\n <button\n class=\"summary-btn clear-btn\"\n (click)=\"clearFilters()\"\n title=\"Clear all filters\">\n <i class=\"fa-solid fa-times\"></i>\n Clear\n </button>\n }\n <button\n class=\"summary-btn edit-btn primary\"\n (click)=\"openFilterDialog()\"\n [disabled]=\"!canEdit && getFilterCount() === 0\"\n title=\"Edit filters\">\n <i class=\"fa-solid fa-pen\"></i>\n {{ getFilterCount() > 0 ? 'Edit Filters' : 'Add Filters' }}\n </button>\n </div>\n </div>\n </div>\n\n <div class=\"traditional-filter-tip\">\n <i class=\"fa-solid fa-info-circle\"></i>\n <span>Build precise filters by selecting fields, operators, and values. Use groups for complex AND/OR logic.</span>\n </div>\n </div>\n }\n </div>\n }\n\n <!-- Aggregates Tab -->\n @if (activeTab === 'aggregates') {\n <div class=\"tab-content\">\n <div class=\"config-section aggregates-section\">\n <div class=\"aggregates-header\">\n <p class=\"aggregates-description\">\n Add summary calculations like totals, averages, and counts. Display them in cards or as column footers.\n </p>\n </div>\n\n <!-- Add Aggregate Button -->\n <button\n class=\"add-aggregate-btn\"\n (click)=\"openAddAggregateDialog()\"\n [disabled]=\"!canEdit\"\n title=\"Add a new aggregate\">\n <i class=\"fa-solid fa-plus\"></i>\n <span>Add Aggregate</span>\n </button>\n\n <!-- Aggregates List -->\n @if (aggregates.length > 0) {\n <div class=\"aggregates-list\">\n @for (agg of aggregates; track agg.id; let i = $index) {\n <div class=\"aggregate-item\" [class.disabled]=\"agg.enabled === false\">\n <!-- Icon -->\n <div class=\"agg-icon\">\n <i [class]=\"agg.icon || 'fa-solid fa-chart-simple'\"></i>\n </div>\n\n <!-- Content -->\n <div class=\"agg-content\">\n <div class=\"agg-label\">{{ agg.label }}</div>\n <div class=\"agg-details\">\n <span class=\"agg-type\">\n <i [class]=\"agg.displayType === 'card' ? 'fa-solid fa-id-card' : 'fa-solid fa-table-columns'\"></i>\n {{ agg.displayType === 'card' ? 'Card' : 'Column Footer' }}\n </span>\n @if (agg.smartPrompt) {\n <span class=\"agg-smart-badge\" title=\"AI-generated\">\n <i class=\"fa-solid fa-wand-magic-sparkles\"></i>\n </span>\n }\n </div>\n </div>\n\n <!-- Actions -->\n <div class=\"agg-actions\">\n <button\n class=\"agg-action-btn\"\n [disabled]=\"i === 0 || !canEdit\"\n (click)=\"moveAggregateUp(agg)\"\n title=\"Move up\">\n <i class=\"fa-solid fa-chevron-up\"></i>\n </button>\n <button\n class=\"agg-action-btn\"\n [disabled]=\"i === aggregates.length - 1 || !canEdit\"\n (click)=\"moveAggregateDown(agg)\"\n title=\"Move down\">\n <i class=\"fa-solid fa-chevron-down\"></i>\n </button>\n <button\n class=\"agg-action-btn toggle-btn\"\n [class.enabled]=\"agg.enabled !== false\"\n (click)=\"toggleAggregateEnabled(agg, $event)\"\n [disabled]=\"!canEdit\"\n [title]=\"agg.enabled !== false ? 'Disable' : 'Enable'\">\n <i [class]=\"agg.enabled !== false ? 'fa-solid fa-eye' : 'fa-solid fa-eye-slash'\"></i>\n </button>\n <button\n class=\"agg-action-btn edit-btn\"\n (click)=\"editAggregate(agg)\"\n [disabled]=\"!canEdit\"\n title=\"Edit\">\n <i class=\"fa-solid fa-pen\"></i>\n </button>\n <button\n class=\"agg-action-btn remove-btn\"\n (click)=\"removeAggregate(agg)\"\n [disabled]=\"!canEdit\"\n title=\"Remove\">\n <i class=\"fa-solid fa-trash\"></i>\n </button>\n </div>\n </div>\n }\n </div>\n\n <!-- Summary -->\n <div class=\"aggregates-summary\">\n <div class=\"summary-item\">\n <i class=\"fa-solid fa-id-card\"></i>\n <span>{{ cardAggregates.length }} card{{ cardAggregates.length !== 1 ? 's' : '' }}</span>\n </div>\n <div class=\"summary-item\">\n <i class=\"fa-solid fa-table-columns\"></i>\n <span>{{ columnAggregates.length }} column footer{{ columnAggregates.length !== 1 ? 's' : '' }}</span>\n </div>\n </div>\n } @else {\n <div class=\"aggregates-empty-state\">\n <i class=\"fa-solid fa-chart-simple\"></i>\n <span>No aggregates configured</span>\n <p class=\"empty-hint\">Click \"Add Aggregate\" to create summary calculations</p>\n </div>\n }\n\n <!-- Info Tip -->\n <div class=\"aggregates-tip\">\n <i class=\"fa-solid fa-info-circle\"></i>\n <span>Aggregates are calculated server-side for accuracy with filtered/paginated data.</span>\n </div>\n </div>\n </div>\n }\n\n <!-- Settings Tab -->\n @if (activeTab === 'settings') {\n <div class=\"tab-content\">\n <!-- View Name & Description -->\n <div class=\"config-section\">\n <div class=\"section-header\">\n <i class=\"fa-solid fa-info-circle\"></i>\n <span>View Details</span>\n </div>\n <div class=\"form-group\">\n <label for=\"viewName\">Name</label>\n <input\n id=\"viewName\"\n type=\"text\"\n class=\"form-input\"\n [class.invalid]=\"!viewName || !viewName.trim()\"\n placeholder=\"Enter view name...\"\n [(ngModel)]=\"viewName\"\n [disabled]=\"!canEdit\"\n />\n @if (!viewName || !viewName.trim()) {\n <span class=\"validation-error\">View name is required</span>\n }\n </div>\n <div class=\"form-group\">\n <label for=\"viewDescription\">Description</label>\n <textarea\n id=\"viewDescription\"\n class=\"form-input form-textarea\"\n placeholder=\"Describe this view...\"\n [(ngModel)]=\"viewDescription\"\n [disabled]=\"!canEdit\"\n rows=\"3\"\n ></textarea>\n </div>\n </div>\n\n <!-- Sharing -->\n <div class=\"config-section\">\n <div class=\"section-header\">\n <i class=\"fa-solid fa-share-alt\"></i>\n <span>Sharing</span>\n </div>\n <label class=\"checkbox-label\">\n <input\n type=\"checkbox\"\n [(ngModel)]=\"isShared\"\n [disabled]=\"!canEdit\"\n />\n <span class=\"checkbox-text\">\n <strong>Share with others</strong>\n <small>Allow other users to use this view</small>\n </span>\n </label>\n </div>\n\n <!-- Danger Zone -->\n @if (viewEntity && canDelete) {\n <div class=\"config-section danger-zone\">\n <div class=\"section-header\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n <span>Danger Zone</span>\n </div>\n <button class=\"delete-btn\" (click)=\"onDelete()\">\n <i class=\"fa-solid fa-trash\"></i>\n <span>Delete View</span>\n </button>\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Validation Errors Banner -->\n @if (ValidationErrors.length > 0 && visibleColumns.length === 0) {\n <div class=\"validation-banner\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n <span>At least one column must be visible</span>\n </div>\n }\n\n <!-- Panel Footer -->\n <div class=\"panel-footer\">\n <!-- Action buttons on LEFT -->\n <div class=\"footer-left\">\n @if (viewEntity && canEdit) {\n <!-- Editing an existing saved view -->\n <button\n class=\"footer-btn save-btn primary\"\n (click)=\"onSave()\"\n [disabled]=\"isSaving || !IsValid\">\n @if (isSaving) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n } @else {\n <i class=\"fa-solid fa-save\"></i>\n }\n {{ isSaving ? 'Saving...' : 'Save' }}\n </button>\n }\n @if (!viewEntity && DefaultSaveAsNew) {\n <!-- Creating a new view (from quick save dialog) -->\n <button\n class=\"footer-btn save-btn primary\"\n (click)=\"onSaveAsNew()\"\n [disabled]=\"isSaving || !IsValidForSaveAsNew\">\n @if (isSaving) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n } @else {\n <i class=\"fa-solid fa-plus\"></i>\n }\n {{ isSaving ? 'Saving...' : 'Create View' }}\n </button>\n }\n @if (!viewEntity && !DefaultSaveAsNew) {\n <!-- Default/Dynamic view - Save to user settings -->\n <button\n class=\"footer-btn save-btn primary\"\n (click)=\"onSaveDefaults()\"\n [disabled]=\"isSaving\">\n @if (isSaving) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n } @else {\n <i class=\"fa-solid fa-save\"></i>\n }\n {{ isSaving ? 'Saving...' : 'Save' }}\n </button>\n }\n </div>\n <!-- Cancel button on RIGHT -->\n <button class=\"footer-btn cancel-btn\" (click)=\"onClose()\">\n Cancel\n </button>\n </div>\n</div>\n\n<!-- Aggregate Setup Dialog -->\n<mj-aggregate-setup-dialog\n [Entity]=\"entity\"\n [Aggregate]=\"editingAggregate\"\n [IsOpen]=\"showAggregateDialog\"\n (Close)=\"closeAggregateDialog()\"\n (Save)=\"onAggregateSave($event)\">\n</mj-aggregate-setup-dialog>\n\n<!-- Delete Confirmation Dialog -->\n<mj-ev-confirm-dialog\n [IsOpen]=\"showDeleteConfirm\"\n Title=\"Delete View\"\n [Message]=\"'Are you sure you want to delete \\'' + viewName + '\\'?'\"\n DetailMessage=\"This action cannot be undone. All users who have access to this view will lose it.\"\n ConfirmText=\"Delete\"\n ConfirmStyle=\"danger\"\n Icon=\"fa-solid fa-trash\"\n (Confirmed)=\"OnDeleteConfirmed()\"\n (Cancelled)=\"OnDeleteCancelled()\">\n</mj-ev-confirm-dialog>\n\n<!-- Filter Mode Switch Confirmation Dialog (BUG-006) -->\n<mj-ev-confirm-dialog\n [IsOpen]=\"showFilterModeSwitchConfirm\"\n Title=\"Switch Filter Mode\"\n [Message]=\"filterMode === 'smart' ? 'Switching to Traditional mode will clear your smart filter prompt.' : 'Switching to Smart mode will clear your traditional filter rules.'\"\n DetailMessage=\"You can switch back later, but the current filter data will be lost.\"\n ConfirmText=\"Switch\"\n ConfirmStyle=\"primary\"\n Icon=\"fa-solid fa-exchange-alt\"\n (Confirmed)=\"OnFilterModeSwitchConfirmed()\"\n (Cancelled)=\"OnFilterModeSwitchCancelled()\">\n</mj-ev-confirm-dialog>\n", styles: ["/* Backdrop */\n.panel-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.3);\n z-index: 1200; /* Above Leaflet map (1000), content-header (1100) */\n animation: fadeIn 0.2s ease;\n}\n\n@keyframes fadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n/* Sliding Panel */\n.config-panel {\n position: fixed;\n top: 0;\n right: 0;\n width: 450px;\n min-width: 360px;\n max-width: min(800px, 100vw);\n height: 100%;\n background: var(--mj-bg-surface);\n box-shadow: -4px 0 24px rgba(0, 0, 0, 0.15);\n z-index: 1201; /* Above backdrop (1200) */\n display: flex;\n flex-direction: column;\n transform: translateX(100%);\n transition: transform 0.25s ease, width 0s;\n}\n\n.config-panel.open {\n transform: translateX(0);\n}\n\n.config-panel.resizing {\n transition: none;\n user-select: none;\n}\n\n/* Resize Handle */\n.resize-handle {\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n width: 6px;\n cursor: ew-resize;\n z-index: 10;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.resize-handle:hover,\n.config-panel.resizing .resize-handle {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n}\n\n.resize-grip {\n width: 3px;\n height: 40px;\n background: var(--mj-border-strong);\n border-radius: 3px;\n opacity: 0;\n transition: opacity 0.2s ease;\n}\n\n.resize-handle:hover .resize-grip,\n.config-panel.resizing .resize-grip {\n opacity: 1;\n background: var(--mj-brand-primary);\n}\n\n/* Panel Header */\n.panel-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n flex-shrink: 0;\n}\n\n.header-title {\n display: flex;\n align-items: center;\n gap: 10px;\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.header-title i {\n color: var(--mj-brand-primary);\n}\n\n.close-btn {\n width: 32px;\n height: 32px;\n border: none;\n background: transparent;\n border-radius: 8px;\n cursor: pointer;\n color: var(--mj-text-muted);\n transition: all 0.15s ease;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.close-btn:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n/* Tab Navigation */\n.tab-nav {\n display: flex;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n flex-shrink: 0;\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n}\n\n.tab-btn {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 12px 16px;\n border: none;\n background: transparent;\n cursor: pointer;\n color: var(--mj-text-muted);\n font-size: 13px;\n font-weight: 500;\n transition: all 0.15s ease;\n position: relative;\n white-space: nowrap;\n}\n\n.tab-btn:hover {\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-hover);\n}\n\n.tab-btn.active {\n color: var(--mj-brand-primary);\n font-weight: 600;\n}\n\n.tab-btn.active::after {\n content: '';\n position: absolute;\n bottom: 0;\n left: 8px;\n right: 8px;\n height: 2px;\n background: var(--mj-brand-primary);\n border-radius: 2px 2px 0 0;\n}\n\n.tab-btn i {\n font-size: 14px;\n}\n\n.tab-badge {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 18px;\n height: 18px;\n padding: 0 5px;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-radius: 9px;\n font-size: 11px;\n font-weight: 600;\n}\n\n/* Icon-only mode for narrow panel */\n.tab-nav.icon-only .tab-btn {\n padding: 12px 8px;\n}\n\n/* Panel Content */\n.panel-content {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n}\n\n.tab-content {\n padding: 16px;\n}\n\n/* Config Sections */\n.config-section {\n margin-bottom: 20px;\n}\n\n.section-header {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 0;\n margin-bottom: 8px;\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.section-header i {\n color: var(--mj-text-muted);\n font-size: 14px;\n}\n\n.column-count {\n margin-left: auto;\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n padding: 2px 8px;\n border-radius: 10px;\n font-size: 12px;\n font-weight: 500;\n}\n\n/* Column Search */\n.column-search {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n margin-bottom: 8px;\n}\n\n.column-search i {\n color: var(--mj-text-disabled);\n font-size: 12px;\n}\n\n.column-search input {\n flex: 1;\n border: none;\n outline: none;\n font-size: 13px;\n background: transparent;\n color: var(--mj-text-primary);\n}\n\n.column-search input::placeholder {\n color: var(--mj-text-disabled);\n}\n\n/* Column List */\n.column-list {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n/* Column Item */\n.column-item {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 10px;\n border-radius: 8px;\n transition: background 0.15s ease;\n cursor: default;\n}\n\n.column-item:hover {\n background: var(--mj-bg-surface-card);\n}\n\n.column-item.hidden {\n opacity: 0.7;\n}\n\n.column-item.hidden:hover {\n opacity: 1;\n}\n\n.column-item.dragging {\n opacity: 0.4;\n}\n\n.column-item.drop-target {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n}\n\n/* Drop Indicator */\n.drop-indicator {\n height: 2px;\n background: var(--mj-brand-primary);\n border-radius: 1px;\n margin: 0 10px;\n}\n\n/* Drag Handle */\n.drag-handle {\n display: flex;\n align-items: center;\n cursor: grab;\n color: var(--mj-text-disabled);\n font-size: 12px;\n padding: 4px 2px;\n}\n\n.drag-handle:active {\n cursor: grabbing;\n}\n\n.column-item:hover .drag-handle {\n color: var(--mj-text-muted);\n}\n\n/* Column Name */\n.column-name {\n flex: 1;\n font-size: 13px;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.alias-indicator {\n font-size: 10px;\n color: var(--mj-brand-primary);\n margin-left: 4px;\n}\n\n.format-indicator {\n font-size: 10px;\n color: var(--mj-status-warning);\n margin-left: 4px;\n}\n\n/* Column Actions */\n.column-actions {\n display: flex;\n align-items: center;\n gap: 2px;\n opacity: 0;\n transition: opacity 0.15s ease;\n}\n\n.column-item:hover .column-actions {\n opacity: 1;\n}\n\n.action-btn {\n width: 26px;\n height: 26px;\n border: none;\n background: transparent;\n border-radius: 6px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n transition: all 0.15s ease;\n}\n\n.action-btn:hover:not(:disabled) {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-secondary);\n}\n\n.action-btn:disabled {\n opacity: 0.3;\n cursor: not-allowed;\n}\n\n.action-btn.hide-btn:hover {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error);\n}\n\n.action-btn.show-btn {\n opacity: 0;\n}\n\n.column-item:hover .action-btn.show-btn {\n opacity: 1;\n}\n\n.action-btn.show-btn:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.action-btn.format-btn:hover {\n background: var(--mj-status-warning-bg);\n color: var(--mj-status-warning);\n}\n\n.action-btn i {\n font-size: 12px;\n}\n\n/* Empty List */\n.empty-list {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 16px;\n color: var(--mj-text-muted);\n font-size: 13px;\n}\n\n.empty-list i {\n color: var(--mj-text-disabled);\n}\n\n/* Format Editor */\n.format-editor {\n padding: 0;\n}\n\n.format-editor-header {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 16px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n}\n\n.back-btn {\n width: 32px;\n height: 32px;\n border: none;\n background: var(--mj-bg-surface-sunken);\n border-radius: 8px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-secondary);\n transition: all 0.15s ease;\n}\n\n.back-btn:hover {\n background: var(--mj-bg-surface-active);\n color: var(--mj-text-primary);\n}\n\n.format-editor-title {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n/* Format Sections */\n.format-section {\n padding: 16px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.format-section-header {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 12px;\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n}\n\n.format-section-header i {\n color: var(--mj-text-muted);\n}\n\n/* Format Rows */\n.format-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 8px 0;\n}\n\n.format-row label {\n font-size: 13px;\n color: var(--mj-text-secondary);\n}\n\n.format-row.alias-info {\n padding: 4px 0;\n}\n\n.muted-text {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.clear-alias-btn {\n width: 24px;\n height: 24px;\n border: none;\n background: transparent;\n border-radius: 4px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-disabled);\n transition: all 0.15s ease;\n}\n\n.clear-alias-btn:hover {\n color: var(--mj-status-error);\n}\n\n/* Format Input */\n.format-input {\n padding: 6px 10px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n font-size: 13px;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n transition: border-color 0.15s ease;\n}\n\n.format-input:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n}\n\n.format-input.small {\n width: 60px;\n text-align: center;\n}\n\n.format-select {\n padding: 6px 10px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n font-size: 13px;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n cursor: pointer;\n}\n\n.format-select:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n}\n\n/* Color Input */\n.color-input {\n width: 36px;\n height: 28px;\n padding: 2px;\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n cursor: pointer;\n background: var(--mj-bg-surface);\n}\n\n/* Alignment Toggle */\n.alignment-toggle {\n display: flex;\n gap: 4px;\n background: var(--mj-bg-surface-card);\n border-radius: 8px;\n padding: 3px;\n border: 1px solid var(--mj-border-default);\n}\n\n.align-btn {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 6px;\n border: none;\n background: transparent;\n border-radius: 6px;\n cursor: pointer;\n color: var(--mj-text-muted);\n transition: all 0.15s ease;\n}\n\n.align-btn:hover {\n color: var(--mj-text-secondary);\n}\n\n.align-btn.active {\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);\n}\n\n/* Style Buttons */\n.style-buttons {\n display: flex;\n gap: 4px;\n margin-bottom: 12px;\n}\n\n.style-btn {\n width: 32px;\n height: 32px;\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n border-radius: 6px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n transition: all 0.15s ease;\n}\n\n.style-btn:hover {\n border-color: var(--mj-border-strong);\n color: var(--mj-text-secondary);\n}\n\n.style-btn.active {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n/* Format Preview */\n.format-preview-section {\n padding: 16px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.preview-header {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 12px;\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n}\n\n.preview-header i {\n color: var(--mj-text-muted);\n}\n\n.preview-table {\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n overflow: hidden;\n}\n\n.preview-header-cell {\n padding: 8px 12px;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n text-transform: uppercase;\n letter-spacing: 0.3px;\n}\n\n.preview-cell {\n padding: 8px 12px;\n font-size: 13px;\n color: var(--mj-text-primary);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.preview-cell:last-child {\n border-bottom: none;\n}\n\n/* Format Actions */\n.format-actions {\n padding: 16px;\n}\n\n.clear-format-btn {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n background: var(--mj-bg-surface);\n cursor: pointer;\n font-size: 13px;\n color: var(--mj-text-secondary);\n transition: all 0.15s ease;\n}\n\n.clear-format-btn:hover {\n background: var(--mj-status-error-bg);\n border-color: var(--mj-status-error);\n color: var(--mj-status-error);\n}\n\n/* Sorting Section */\n.sorting-section {\n padding: 0;\n}\n\n.sorting-header {\n margin-bottom: 12px;\n}\n\n.sorting-description,\n.aggregates-description {\n margin: 0;\n font-size: 13px;\n color: var(--mj-text-muted);\n line-height: 1.5;\n}\n\n/* Add Sort Button */\n.add-sort-btn,\n.add-aggregate-btn {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 16px;\n width: 100%;\n border: 2px dashed var(--mj-border-default);\n border-radius: 10px;\n background: transparent;\n cursor: pointer;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-muted);\n transition: all 0.15s ease;\n margin-bottom: 12px;\n}\n\n.add-sort-btn:hover:not(:disabled),\n.add-aggregate-btn:hover:not(:disabled) {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, var(--mj-bg-surface));\n}\n\n.add-sort-btn:disabled,\n.add-aggregate-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n/* Sort Items List */\n.sort-items-list {\n display: flex;\n flex-direction: column;\n gap: 6px;\n margin-bottom: 12px;\n}\n\n.sort-item {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 10px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n transition: all 0.15s ease;\n}\n\n.sort-item:hover {\n border-color: var(--mj-border-strong);\n}\n\n.sort-item.dragging {\n opacity: 0.4;\n}\n\n.sort-item.drop-target {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, var(--mj-bg-surface));\n}\n\n/* Sort Drop Indicator */\n.sort-drop-indicator {\n height: 2px;\n background: var(--mj-brand-primary);\n border-radius: 1px;\n margin: 0 10px;\n}\n\n/* Sort Priority Badge */\n.sort-priority-badge {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-radius: 6px;\n font-size: 11px;\n font-weight: 700;\n flex-shrink: 0;\n}\n\n/* Sort Drag Handle */\n.sort-drag-handle {\n cursor: grab;\n color: var(--mj-text-disabled);\n padding: 2px;\n font-size: 12px;\n}\n\n.sort-drag-handle:active {\n cursor: grabbing;\n}\n\n.sort-item:hover .sort-drag-handle {\n color: var(--mj-text-muted);\n}\n\n/* Sort Field Dropdown */\n.sort-field-dropdown {\n flex: 1;\n padding: 6px 10px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n font-size: 13px;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n cursor: pointer;\n min-width: 0;\n}\n\n.sort-field-dropdown:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n}\n\n/* Sort Direction Toggle */\n.sort-direction-toggle {\n display: flex;\n background: var(--mj-bg-surface-sunken);\n border-radius: 6px;\n padding: 2px;\n gap: 2px;\n}\n\n.direction-btn {\n width: 28px;\n height: 28px;\n border: none;\n background: transparent;\n border-radius: 5px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n font-size: 12px;\n transition: all 0.15s ease;\n}\n\n.direction-btn:hover:not(:disabled) {\n color: var(--mj-text-secondary);\n}\n\n.direction-btn.active {\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);\n}\n\n.direction-btn:disabled {\n opacity: 0.3;\n cursor: not-allowed;\n}\n\n/* Sort Remove Button */\n.sort-remove-btn {\n width: 28px;\n height: 28px;\n border: none;\n background: transparent;\n border-radius: 6px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-disabled);\n font-size: 12px;\n transition: all 0.15s ease;\n}\n\n.sort-remove-btn:hover:not(:disabled) {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error);\n}\n\n.sort-remove-btn:disabled {\n opacity: 0.3;\n cursor: not-allowed;\n}\n\n/* Sort Hint */\n.sort-hint {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n padding: 10px 12px;\n background: var(--mj-bg-surface-card);\n border-radius: 8px;\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.sort-hint i {\n color: var(--mj-text-disabled);\n margin-top: 1px;\n}\n\n/* Sort Empty State */\n.sort-empty-state,\n.aggregates-empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n padding: 32px 16px;\n color: var(--mj-text-muted);\n text-align: center;\n}\n\n.sort-empty-state i,\n.aggregates-empty-state i {\n font-size: 32px;\n opacity: 0.4;\n}\n\n.sort-empty-state span,\n.aggregates-empty-state span {\n font-size: 14px;\n font-weight: 500;\n}\n\n.sort-empty-hint,\n.empty-hint {\n margin: 0;\n font-size: 13px;\n color: var(--mj-text-disabled);\n}\n\n/* Filter Mode Selector */\n.filter-mode-selector {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-bottom: 16px;\n}\n\n.filter-mode-btn {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 14px;\n border: 2px solid var(--mj-border-default);\n border-radius: 10px;\n background: var(--mj-bg-surface);\n cursor: pointer;\n transition: all 0.15s ease;\n text-align: left;\n}\n\n.filter-mode-btn:hover:not(:disabled) {\n border-color: var(--mj-border-strong);\n}\n\n.filter-mode-btn.active {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, var(--mj-bg-surface));\n}\n\n.filter-mode-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.mode-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 8px;\n font-size: 16px;\n color: var(--mj-text-muted);\n flex-shrink: 0;\n}\n\n.filter-mode-btn.active .mode-icon {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.mode-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.mode-title {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.mode-subtitle {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.mode-check {\n color: var(--mj-brand-primary);\n font-size: 14px;\n}\n\n/* Smart Filter Section */\n.smart-filter-section {\n padding: 0;\n}\n\n.smart-filter-input-container {\n display: flex;\n gap: 12px;\n padding: 12px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n margin-bottom: 12px;\n}\n\n.smart-filter-icon {\n display: flex;\n align-items: flex-start;\n padding-top: 4px;\n color: var(--mj-brand-primary);\n font-size: 16px;\n}\n\n.smart-filter-textarea {\n flex: 1;\n border: none;\n outline: none;\n resize: vertical;\n font-size: 14px;\n font-family: inherit;\n color: var(--mj-text-primary);\n background: transparent;\n min-height: 60px;\n}\n\n.smart-filter-textarea::placeholder {\n color: var(--mj-text-disabled);\n}\n\n.smart-filter-textarea:disabled {\n color: var(--mj-text-muted);\n}\n\n/* Smart Filter Explanation */\n.smart-filter-explanation {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n padding: 10px 12px;\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) 25%, var(--mj-bg-surface));\n border-radius: 8px;\n margin-bottom: 12px;\n font-size: 13px;\n color: var(--mj-brand-primary);\n}\n\n.smart-filter-explanation i {\n margin-top: 2px;\n}\n\n/* Smart Filter Examples */\n.smart-filter-examples {\n margin-bottom: 12px;\n}\n\n.examples-header {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 8px;\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-muted);\n}\n\n.examples-header i {\n color: var(--mj-status-warning);\n}\n\n.example-chips {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n}\n\n.example-chip {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 20px;\n background: var(--mj-bg-surface);\n cursor: pointer;\n font-size: 12px;\n color: var(--mj-text-secondary);\n transition: all 0.15s ease;\n}\n\n.example-chip:hover:not(:disabled) {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, var(--mj-bg-surface));\n}\n\n.example-chip:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.example-chip i {\n font-size: 11px;\n}\n\n/* Smart Filter Tip */\n.smart-filter-tip,\n.traditional-filter-tip,\n.aggregates-tip {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n padding: 10px 12px;\n background: var(--mj-bg-surface-card);\n border-radius: 8px;\n font-size: 12px;\n color: var(--mj-text-muted);\n margin-top: 12px;\n}\n\n.smart-filter-tip i,\n.traditional-filter-tip i,\n.aggregates-tip i {\n color: var(--mj-text-disabled);\n margin-top: 1px;\n}\n\n/* Traditional Filter Section */\n.traditional-filter-section {\n padding: 0;\n}\n\n.filter-summary-container {\n margin-bottom: 12px;\n}\n\n.filter-summary {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 14px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n}\n\n.summary-info {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.filter-badge {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 22px;\n height: 22px;\n padding: 0 6px;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-radius: 11px;\n font-size: 12px;\n font-weight: 600;\n}\n\n.summary-text {\n font-size: 13px;\n color: var(--mj-text-primary);\n font-weight: 500;\n}\n\n.summary-text.no-filters {\n color: var(--mj-text-muted);\n font-weight: 400;\n}\n\n.summary-actions {\n display: flex;\n gap: 8px;\n}\n\n.summary-btn {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n background: var(--mj-bg-surface);\n cursor: pointer;\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n transition: all 0.15s ease;\n}\n\n.summary-btn:hover:not(:disabled) {\n border-color: var(--mj-border-strong);\n}\n\n.summary-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.summary-btn.clear-btn:hover {\n border-color: var(--mj-status-error);\n color: var(--mj-status-error);\n}\n\n.summary-btn.primary {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.summary-btn.primary:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n border-color: var(--mj-brand-primary-hover);\n}\n\n/* Aggregates Section */\n.aggregates-section {\n padding: 0;\n}\n\n.aggregates-header {\n margin-bottom: 12px;\n}\n\n/* Aggregates List */\n.aggregates-list {\n display: flex;\n flex-direction: column;\n gap: 6px;\n margin-bottom: 12px;\n}\n\n.aggregate-item {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 12px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n transition: all 0.15s ease;\n}\n\n.aggregate-item:hover {\n border-color: var(--mj-border-strong);\n}\n\n.aggregate-item.disabled {\n opacity: 0.5;\n}\n\n/* Aggregate Icon */\n.agg-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n border-radius: 8px;\n color: var(--mj-brand-primary);\n font-size: 14px;\n flex-shrink: 0;\n}\n\n/* Aggregate Content */\n.agg-content {\n flex: 1;\n min-width: 0;\n}\n\n.agg-label {\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.agg-details {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-top: 2px;\n}\n\n.agg-type {\n display: flex;\n align-items: center;\n gap: 4px;\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n\n.agg-smart-badge {\n color: var(--mj-brand-primary);\n font-size: 11px;\n}\n\n/* Aggregate Actions */\n.agg-actions {\n display: flex;\n align-items: center;\n gap: 2px;\n opacity: 0;\n transition: opacity 0.15s ease;\n}\n\n.aggregate-item:hover .agg-actions {\n opacity: 1;\n}\n\n.agg-action-btn {\n width: 26px;\n height: 26px;\n border: none;\n background: transparent;\n border-radius: 6px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n font-size: 12px;\n transition: all 0.15s ease;\n}\n\n.agg-action-btn:hover:not(:disabled) {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-secondary);\n}\n\n.agg-action-btn:disabled {\n opacity: 0.3;\n cursor: not-allowed;\n}\n\n.agg-action-btn.toggle-btn.enabled {\n color: var(--mj-brand-primary);\n}\n\n.agg-action-btn.remove-btn:hover:not(:disabled) {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error);\n}\n\n.agg-action-btn.edit-btn:hover:not(:disabled) {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n/* Aggregates Summary */\n.aggregates-summary {\n display: flex;\n gap: 16px;\n padding: 10px 12px;\n background: var(--mj-bg-surface-card);\n border-radius: 8px;\n margin-bottom: 12px;\n}\n\n.aggregates-summary .summary-item {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.aggregates-summary .summary-item i {\n color: var(--mj-text-disabled);\n}\n\n/* Settings Tab */\n.form-group {\n margin-bottom: 16px;\n}\n\n.form-group label {\n display: block;\n margin-bottom: 6px;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n.form-input {\n width: 100%;\n padding: 8px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n font-size: 14px;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n transition: border-color 0.15s ease;\n box-sizing: border-box;\n}\n\n.form-input:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n}\n\n.form-input.invalid {\n border-color: var(--mj-status-error);\n}\n\n.form-textarea {\n resize: vertical;\n min-height: 60px;\n font-family: inherit;\n}\n\n.validation-error {\n font-size: 12px;\n color: var(--mj-status-error);\n margin-top: 4px;\n}\n\n/* Checkbox */\n.checkbox-label {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n cursor: pointer;\n}\n\n.checkbox-label input[type=\"checkbox\"] {\n margin-top: 3px;\n flex-shrink: 0;\n}\n\n.checkbox-text {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.checkbox-text strong {\n font-size: 13px;\n color: var(--mj-text-primary);\n}\n\n.checkbox-text small {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n/* Danger Zone */\n.danger-zone .section-header {\n color: var(--mj-status-error);\n}\n\n.danger-zone .section-header i {\n color: var(--mj-status-error);\n}\n\n.delete-btn {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 16px;\n border: 1px solid var(--mj-status-error);\n border-radius: 8px;\n background: var(--mj-status-error-bg);\n cursor: pointer;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-status-error);\n transition: all 0.15s ease;\n}\n\n.delete-btn:hover {\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n}\n\n/* Validation Banner */\n.validation-banner {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 16px;\n background: var(--mj-status-error-bg);\n border-top: 1px solid var(--mj-status-error);\n font-size: 13px;\n color: var(--mj-status-error);\n flex-shrink: 0;\n}\n\n/* Panel Footer */\n.panel-footer {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 14px 20px;\n border-top: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n flex-shrink: 0;\n}\n\n.footer-left {\n display: flex;\n gap: 8px;\n}\n\n.footer-btn {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 9px 18px;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n background: var(--mj-bg-surface);\n cursor: pointer;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n transition: all 0.15s ease;\n}\n\n.footer-btn:hover:not(:disabled) {\n border-color: var(--mj-border-strong);\n}\n\n.footer-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.footer-btn.primary {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.footer-btn.primary:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n border-color: var(--mj-brand-primary-hover);\n}\n\n.footer-btn.cancel-btn {\n background: var(--mj-bg-surface-card);\n}\n\n.footer-btn.cancel-btn:hover {\n background: var(--mj-bg-surface-active);\n}\n\n/* Responsive */\n@media (max-width: 480px) {\n .config-panel {\n width: 100vw;\n min-width: auto;\n }\n\n .resize-handle {\n display: none;\n }\n}\n"] }]
2858
2858
  }], () => [{ type: i0.ChangeDetectorRef }], { entity: [{
2859
2859
  type: Input
2860
2860
  }], viewEntity: [{