commons-shared-web-ui 0.0.27 → 0.0.28
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.
|
@@ -694,6 +694,8 @@ class FormFieldComponent {
|
|
|
694
694
|
*/
|
|
695
695
|
instanceList = [];
|
|
696
696
|
_nextInstanceId = 0;
|
|
697
|
+
/** Tracks open accordion panels for standard (non-multiSave) GROUP repeaters. */
|
|
698
|
+
expandedGroupInstances = new Set();
|
|
697
699
|
/**
|
|
698
700
|
* Key used to register the GROUP control on the parent formGroup.
|
|
699
701
|
* Priority: sectionConfig.name > field.name > camelCase(label) > '__group__'
|
|
@@ -810,6 +812,11 @@ class FormFieldComponent {
|
|
|
810
812
|
if (isSaved) {
|
|
811
813
|
this.groupFormArray.push(fg);
|
|
812
814
|
}
|
|
815
|
+
// Collapse all existing panels; expand only the new one
|
|
816
|
+
if (!isMultiSave) {
|
|
817
|
+
this.expandedGroupInstances.clear();
|
|
818
|
+
this.expandedGroupInstances.add(this.instanceList.length);
|
|
819
|
+
}
|
|
813
820
|
this.instanceList = [...this.instanceList, instance];
|
|
814
821
|
if (initialData) {
|
|
815
822
|
setTimeout(() => {
|
|
@@ -884,8 +891,30 @@ class FormFieldComponent {
|
|
|
884
891
|
this.groupFormArray.removeAt(arrayIndex);
|
|
885
892
|
}
|
|
886
893
|
this.instanceList = this.instanceList.filter((_, i) => i !== index);
|
|
894
|
+
// Rebuild accordion expanded set after index shift
|
|
895
|
+
if (!isMultiSave) {
|
|
896
|
+
const updated = new Set();
|
|
897
|
+
this.expandedGroupInstances.forEach(i => {
|
|
898
|
+
if (i < index)
|
|
899
|
+
updated.add(i);
|
|
900
|
+
else if (i > index)
|
|
901
|
+
updated.add(i - 1);
|
|
902
|
+
});
|
|
903
|
+
this.expandedGroupInstances = updated;
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
toggleGroupAccordion(index) {
|
|
908
|
+
if (this.expandedGroupInstances.has(index)) {
|
|
909
|
+
this.expandedGroupInstances.delete(index);
|
|
910
|
+
}
|
|
911
|
+
else {
|
|
912
|
+
this.expandedGroupInstances.add(index);
|
|
887
913
|
}
|
|
888
914
|
}
|
|
915
|
+
isGroupExpanded(index) {
|
|
916
|
+
return this.expandedGroupInstances.has(index);
|
|
917
|
+
}
|
|
889
918
|
trackByInstanceId(_, item) {
|
|
890
919
|
return item.id;
|
|
891
920
|
}
|
|
@@ -2195,11 +2224,11 @@ class FormFieldComponent {
|
|
|
2195
2224
|
}
|
|
2196
2225
|
}
|
|
2197
2226
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: FormFieldComponent, deps: [{ token: i1$3.FormBuilder }, { token: ExpressionService }, { token: i3.HttpClient }], target: i0.ɵɵFactoryTarget.Component });
|
|
2198
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: FormFieldComponent, isStandalone: false, selector: "lib-form-field", inputs: { config: "config", controller: "controller", formGroup: "formGroup", allowMulti: "allowMulti" }, viewQueries: [{ propertyName: "mediaDeviceInput", first: true, predicate: ["mediaDeviceInput"], descendants: true }], ngImport: i0, template: "<div class=\"form-field mb-16px\" *ngIf=\"isVisible\" [class.has-error]=\"errorMessage\">\r\n\r\n <!-- \u2550\u2550 ROW Layout \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isRow\" class=\"form-row grid-row\">\r\n <ng-container *ngFor=\"let child of config.children\">\r\n <div class=\"row-field\" [style.gridColumn]=\"'span ' + getChildColSpan(child)\" *ngIf=\"child.isEnabled !== false\">\r\n <lib-form-field [config]=\"child\" [controller]=\"controller\" [formGroup]=\"formGroup\" [allowMulti]=\"allowMulti\">\r\n </lib-form-field>\r\n </div>\r\n </ng-container>\r\n </div>\r\n\r\n <!-- \u2550\u2550 GROUP \u2014 allowMulti (repeater) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isGroup && config.sectionConfig?.allowMulti\"\r\n class=\"group-section-wrapper mb-20px b-1px-solid-E5E7EB br-10px p-20px bc-ffffff\"\r\n [class.multi-save-active]=\"config.sectionConfig?.multiSaveConfig?.active\">\r\n\r\n <!-- Multi-Save Header with Add button (top-right style) -->\r\n <div class=\"multi-save-header d-flex justify-content-between align-items-center mb-24\"\r\n *ngIf=\"config.sectionConfig?.multiSaveConfig?.active\">\r\n <h3\r\n class=\"group-label pb-10 mb-0 d-block font-weight-600 border-none fs-0-875rem c-111827 fs-1rem c-1F2937 m-0-0-16px-0 bb-2px-solid-E5E7EB pb-0 mb-0-75rem\"\r\n *ngIf=\"config.sectionConfig?.label\">{{ config.sectionConfig!.label }}</h3>\r\n <lib-button [variant]=\"'outline'\" [icon]=\"{type: 'material', value: 'add'}\" (click)=\"addGroupInstance()\"\r\n class=\"btn-add-multi\">\r\n {{ addMultiLabel }}\r\n </lib-button>\r\n </div>\r\n\r\n <!-- Standard Header for non-multiSave -->\r\n <h3\r\n class=\"group-label pb-10 mb-0 d-block font-weight-600 border-none fs-0-875rem c-111827 fs-1rem c-1F2937 m-0-0-16px-0 bb-2px-solid-E5E7EB pb-0 mb-0-75rem\"\r\n *ngIf=\"config.sectionConfig?.label && !config.sectionConfig?.multiSaveConfig?.active\">{{\r\n config.sectionConfig!.label }}</h3>\r\n\r\n <div *ngFor=\"let instance of instanceList; trackBy: trackByInstanceId; let i = index\"\r\n class=\"group-instance position-relative mb-16 p-0 overflow-hidden p-16px b-F9FAFB b-1px-solid-E5E7EB br-8px b-ffffff br-10px\"\r\n [class.is-editing]=\"instance.isEditing\"\r\n [class.is-card]=\"config.sectionConfig?.multiSaveConfig?.active && !instance.isEditing\">\r\n\r\n <!-- 1. EDIT MODE / UNSAVED / STANDARD STATE -->\r\n <div [hidden]=\"config.sectionConfig?.multiSaveConfig?.active && !instance.isEditing\">\r\n <!-- Instance header \u2014 show remove only when more than 1 instance -->\r\n <div class=\"group-header d-flex justify-content-between align-items-center mb-12 pb-10 bb-1px-dashed-D1D5DB\"\r\n *ngIf=\"!config.sectionConfig?.multiSaveConfig?.active && instanceList.length > 1\">\r\n <span class=\"group-number font-weight-500 c-4B5563 fs-0-8125rem\">{{ config.sectionConfig!.label }} #{{ i + 1\r\n }}</span>\r\n <lib-button [variant]=\"'danger-outline'\" [icon]=\"{type: 'material', value: 'delete_outline'}\"\r\n (click)=\"removeGroupInstance(i)\">\r\n {{ removeLabel }}\r\n </lib-button>\r\n </div>\r\n\r\n <div class=\"group-fields sf-grid\">\r\n <ng-container *ngFor=\"let field of config.sectionConfig!.children\">\r\n <div class=\"sf-col\" [style.gridColumn]=\"'span ' + (field.colSpan || 12)\" *ngIf=\"field.isEnabled !== false\">\r\n <lib-form-field [config]=\"field\" [controller]=\"controller\" [formGroup]=\"instance.fg\" [allowMulti]=\"true\">\r\n </lib-form-field>\r\n </div>\r\n </ng-container>\r\n </div>\r\n\r\n <!-- SAVE / CANCEL BUTTONS for MultiSave in Editing phase -->\r\n <div\r\n class=\"group-footer d-flex justify-content-between align-items-center gap-16 mt-24 pt-20 bt-1px-solid-E5E7EB\"\r\n *ngIf=\"config.sectionConfig?.multiSaveConfig?.active\">\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"multiSaveError\">{{ multiSaveError }}</span>\r\n <div class=\"footer-actions d-flex gap-12\">\r\n <lib-button [variant]=\"'outline'\" (click)=\"cancelGroupInstance(i)\">Cancel</lib-button>\r\n <lib-button [variant]=\"'primary'\" (click)=\"saveGroupInstance(i)\">Save</lib-button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- 2. CARD VIEW (Saved State) -->\r\n <ng-container *ngIf=\"config.sectionConfig?.multiSaveConfig?.active && !instance.isEditing\">\r\n <div class=\"card-view d-flex justify-content-between align-items-center p-18px-24px\"\r\n [class.is-expanded]=\"instance.isExpanded\">\r\n <div class=\"card-content flex-1 d-flex flex-column gap-4 overflow-hidden\">\r\n <span class=\"card-title font-weight-600 overflow-hidden fs-1rem c-111827\">{{\r\n instance.fg.get(config.sectionConfig!.multiSaveConfig!.summaryField || '')?.value\r\n || '\u2014' }}</span>\r\n <!-- <span class=\"card-desc overflow-hidden fs-0-875rem c-6B7280\" *ngIf=\"config.sectionConfig.multiSaveConfig.descriptionField\"\r\n [innerHTML]=\"instance.fg.get(config.sectionConfig.multiSaveConfig.descriptionField)?.value\">\r\n </span> -->\r\n </div>\r\n <div class=\"card-actions d-flex align-items-center gap-16 ml-20\">\r\n <mat-icon class=\"icon-delete\" (click)=\"removeGroupInstance(i, true)\">delete_outline</mat-icon>\r\n <mat-icon class=\"icon-edit\" (click)=\"editGroupInstance(i)\">edit_outline</mat-icon>\r\n <mat-icon class=\"icon-expand\" (click)=\"toggleExpandGroupInstance(i)\">\r\n {{ instance.isExpanded ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}\r\n </mat-icon>\r\n </div>\r\n </div>\r\n </ng-container>\r\n </div>\r\n\r\n <!-- Standard Add Button for non-multiSave -->\r\n <lib-button *ngIf=\"!config.sectionConfig?.multiSaveConfig?.active\" [variant]=\"'outline'\"\r\n [icon]=\"{type: 'material', value: 'add'}\" (click)=\"addGroupInstance()\" class=\"btn-add-group-wrapper\">\r\n {{ addLabel }} {{ config.sectionConfig!.label }}\r\n </lib-button>\r\n </div>\r\n\r\n <!-- \u2550\u2550 GROUP \u2014 single (non-repeater) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isGroup && config.sectionConfig && !config.sectionConfig.allowMulti\"\r\n class=\"group-section-wrapper mb-20px b-1px-solid-E5E7EB br-10px p-20px bc-ffffff\">\r\n <h3\r\n class=\"group-label pb-10 mb-0 d-block font-weight-600 border-none fs-0-875rem c-111827 fs-1rem c-1F2937 m-0-0-16px-0 bb-2px-solid-E5E7EB pb-0 mb-0-75rem\"\r\n *ngIf=\"config.sectionConfig.label\">{{ config.sectionConfig.label }}</h3>\r\n <div class=\"group-fields sf-grid\">\r\n <ng-container *ngFor=\"let field of config.sectionConfig.children\">\r\n <div class=\"sf-col\" [style.gridColumn]=\"'span ' + (field.colSpan || 12)\" *ngIf=\"field.isEnabled !== false\">\r\n <lib-form-field [config]=\"field\" [controller]=\"controller\" [formGroup]=\"groupFormGroup\" [allowMulti]=\"false\">\r\n </lib-form-field>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </div>\r\n\r\n\r\n <!-- \u2550\u2550 Text Input \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isTextField\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <textarea *ngIf=\"config.subType === 'LONG'\" class=\"field-input textarea\" [placeholder]=\"config.placeholder || ''\"\r\n [formControlName]=\"config.name!\" [class.is-invalid]=\"errorMessage\" rows=\"4\">\r\n </textarea>\r\n\r\n <!-- Password input with show/hide toggle -->\r\n <div *ngIf=\"config.subType === 'PASSWORD'\" class=\"password-wrapper position-relative d-flex align-items-center\">\r\n <input [type]=\"showPassword ? 'text' : 'password'\" class=\"field-input password-input\"\r\n [placeholder]=\"config.placeholder || ''\" [formControlName]=\"config.name!\" [class.is-invalid]=\"errorMessage\">\r\n <button type=\"button\"\r\n class=\"password-toggle position-absolute cursor-pointer d-flex align-items-center justify-content-center b-none border-none c-6B7280 p-0-25rem\"\r\n (click)=\"showPassword = !showPassword\" tabindex=\"-1\"\r\n [attr.aria-label]=\"showPassword ? 'Hide password' : 'Show password'\">\r\n <mat-icon class=\"eye-icon\">{{ showPassword ? 'visibility' : 'visibility_off' }}</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <div class=\"input-group position-relative d-flex w-100\" [class.readonly]=\"config.readonly\">\r\n <span class=\"input-prefix br-none\" *ngIf=\"config.prefix\">{{ config.prefix }}</span>\r\n\r\n <input *ngIf=\"config.subType !== 'LONG' && config.subType !== 'PASSWORD'\"\r\n [type]=\"config.subType === 'EMAIL' ? 'email' : config.subType === 'PHONE' ? 'tel' : 'text'\" class=\"field-input\"\r\n [placeholder]=\"config.placeholder || ''\" [formControlName]=\"config.name!\" [class.is-invalid]=\"errorMessage\"\r\n [readonly]=\"config.readonly\">\r\n\r\n <span class=\"input-suffix d-flex align-items-center font-weight-500\" *ngIf=\"config.suffix\">{{ config.suffix\r\n }}</span>\r\n\r\n <div class=\"readonly-icons position-absolute d-flex gap-8 pe-none\" *ngIf=\"config.readonly\">\r\n <mat-icon class=\"lock-icon\">lock</mat-icon>\r\n </div>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n <div class=\"char-count-hint font-poppins font-weight-400 text-14 text-right mt-4 c-6B7280\" *ngIf=\"showCharCount\">\r\n {{ remainingCharacters }} characters remaining\r\n </div>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Number Input \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isNumberField\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"input-group position-relative d-flex w-100\" [class.readonly]=\"config.readonly\">\r\n <span class=\"input-prefix br-none\" *ngIf=\"config.prefix\">{{ config.prefix }}</span>\r\n\r\n <input type=\"number\" class=\"field-input\" [placeholder]=\"config.placeholder || ''\" [formControlName]=\"config.name!\"\r\n [min]=\"config.numberConfig?.min ?? null\" [max]=\"config.numberConfig?.max ?? null\"\r\n [step]=\"config.numberConfig?.step || 1\" [class.is-invalid]=\"errorMessage\" [readonly]=\"config.readonly\">\r\n\r\n <span class=\"input-suffix d-flex align-items-center font-weight-500\" *ngIf=\"config.suffix\">{{ config.suffix\r\n }}</span>\r\n\r\n <div class=\"readonly-icons position-absolute d-flex gap-8 pe-none\" *ngIf=\"config.readonly\">\r\n <mat-icon class=\"lock-icon\">lock</mat-icon>\r\n </div>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Date Input \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isDateField\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"input-group position-relative d-flex w-100\" [class.readonly]=\"config.readonly\">\r\n <input matInput [matDatepicker]=\"datePicker\" class=\"field-input date-input has-icon-right\"\r\n [formControlName]=\"config.name!\" [min]=\"config.dateConfig?.minDate\" [max]=\"config.dateConfig?.maxDate\"\r\n [class.is-invalid]=\"errorMessage\" [placeholder]=\"config.placeholder || ''\" [readonly]=\"config.readonly\"\r\n (click)=\"!config.readonly && datePicker.open()\">\r\n <div class=\"date-icon-wrapper position-absolute d-flex align-items-center justify-content-center\"\r\n *ngIf=\"!config.readonly\">\r\n <mat-datepicker-toggle matSuffix [for]=\"datePicker\"></mat-datepicker-toggle>\r\n </div>\r\n <mat-datepicker #datePicker></mat-datepicker>\r\n\r\n <div class=\"readonly-icons position-absolute d-flex gap-8 pe-none\" *ngIf=\"config.readonly\">\r\n <mat-icon class=\"lock-icon\">lock</mat-icon>\r\n </div>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Time Input \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isTimeField\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"input-group position-relative d-flex w-100\" [class.readonly]=\"config.readonly\">\r\n <input type=\"time\" class=\"field-input time-input\" [formControlName]=\"config.name!\"\r\n [class.is-invalid]=\"errorMessage\" [readonly]=\"!!config.readonly\">\r\n\r\n <div class=\"readonly-icons position-absolute d-flex gap-8 pe-none\" *ngIf=\"config.readonly\">\r\n <mat-icon class=\"lock-icon\">lock</mat-icon>\r\n </div>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Autocomplete \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isAutocomplete\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <!-- Hidden real control (stores the code value) -->\r\n <input type=\"hidden\" [formControlName]=\"config.name!\">\r\n\r\n <div class=\"autocomplete-wrapper position-relative d-flex align-items-center w-100\"\r\n [class.is-invalid]=\"errorMessage\" [class.readonly]=\"config.readonly\">\r\n <!-- Search icon -->\r\n <mat-icon class=\"ac-search-icon position-absolute fs-1-1rem c-9CA3AF pe-none\">search</mat-icon>\r\n\r\n <input class=\"field-input ac-input\" [formControl]=\"autocompleteInputCtrl\" [matAutocomplete]=\"auto\"\r\n [placeholder]=\"config.placeholder || 'Search\u2026'\" [readonly]=\"!!config.readonly\" [class.is-invalid]=\"errorMessage\"\r\n (blur)=\"onAutocompleteClear()\" autocomplete=\"off\">\r\n\r\n <!-- Clear button -->\r\n <button type=\"button\"\r\n class=\"ac-clear-btn position-absolute d-flex align-items-center justify-content-center cursor-pointer rounded-50 b-none border-none c-9CA3AF p-0-2rem\"\r\n *ngIf=\"autocompleteInputCtrl.value && !config.readonly\"\r\n (click)=\"autocompleteInputCtrl.setValue(''); updateValue(null)\" tabindex=\"-1\" aria-label=\"Clear\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n\r\n <mat-autocomplete #auto=\"matAutocomplete\" [panelWidth]=\"'auto'\">\r\n <mat-option *ngFor=\"let option of filteredOptions\" [value]=\"option.label\"\r\n (onSelectionChange)=\"onAutocompleteSelected(option)\">\r\n {{ option.label }}\r\n </mat-option>\r\n <mat-option *ngIf=\"filteredOptions.length === 0\" disabled class=\"ac-no-results fs-0-8125rem c-6B7280\">\r\n No results found\r\n </mat-option>\r\n </mat-autocomplete>\r\n\r\n <div class=\"readonly-icons position-absolute d-flex gap-8 pe-none\" *ngIf=\"config.readonly\">\r\n <mat-icon class=\"lock-icon\">lock</mat-icon>\r\n </div>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Dropdown \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isDropdown\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <select *ngIf=\"config.subType === 'SINGLE'\" class=\"field-input\" [formControlName]=\"config.name!\"\r\n [class.is-invalid]=\"errorMessage\">\r\n <option [ngValue]=\"null\" disabled selected>{{ config.placeholder || 'Select' }}</option>\r\n <option *ngFor=\"let option of config.optionConfig?.optionList\" [value]=\"option.code\">\r\n {{ option.label }}\r\n </option>\r\n </select>\r\n\r\n <select *ngIf=\"config.subType === 'MULTIPLE'\" class=\"field-input\" multiple [formControlName]=\"config.name!\"\r\n [class.is-invalid]=\"errorMessage\">\r\n <option *ngFor=\"let option of config.optionConfig?.optionList\" [value]=\"option.code\">\r\n {{ option.label }}\r\n </option>\r\n </select>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Radio \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isRadio\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"radio-group\" [class.is-invalid]=\"errorMessage\"\r\n [class]=\"config.optionConfig?.layout ? 'layout-' + config.optionConfig!.layout.toLowerCase() : ''\">\r\n <label *ngFor=\"let option of config.optionConfig?.optionList\" class=\"radio-label\"\r\n [class.card-item]=\"config.subType === 'CARD'\"\r\n [class.selected]=\"formGroup.get(config.name!)?.value === option.code\"\r\n [style.gridColumn]=\"config.optionConfig?.layout?.toUpperCase() === 'COLUMN' ? 'span ' + getOptionColSpan(option) : null\">\r\n <input type=\"radio\" [formControlName]=\"config.name!\" [value]=\"option.code\">\r\n <div class=\"option-content d-flex flex-column gap-4 flex-1 text-left\">\r\n <span class=\"label-text text-16 c-1F2937\">{{ option.label }}</span>\r\n <span class=\"option-hint text-13 color-gray\" *ngIf=\"option.hint\">{{ option.hint }}</span>\r\n </div>\r\n </label>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Checkbox \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isCheckbox\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label && config.subType === 'LIST'\"\r\n class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div *ngIf=\"config.subType === 'BOOL'\" class=\"checkbox-single\">\r\n <label class=\"checkbox-label d-flex align-items-center gap-8 cursor-pointer fs-0-875rem c-111827\">\r\n <input type=\"checkbox\" [formControlName]=\"config.name!\" [class.is-invalid]=\"errorMessage\">\r\n <span>{{ config.label }}</span>\r\n </label>\r\n </div>\r\n\r\n <div *ngIf=\"config.subType === 'LIST' || config.subType === 'CARD'\" class=\"checkbox-group d-flex flex-column gap-8\"\r\n [class.is-invalid]=\"errorMessage\"\r\n [class]=\"config.optionConfig?.layout ? 'layout-' + config.optionConfig!.layout.toLowerCase() : ''\">\r\n <label *ngFor=\"let option of config.optionConfig?.optionList\"\r\n class=\"checkbox-label d-flex align-items-center gap-8 cursor-pointer fs-0-875rem c-111827\"\r\n [class.card-item]=\"config.subType === 'CARD'\" [class.selected]=\"isChecked(option.code)\"\r\n [style.gridColumn]=\"config.optionConfig?.layout?.toUpperCase() === 'COLUMN' ? 'span ' + getOptionColSpan(option) : null\">\r\n <input type=\"checkbox\" [checked]=\"isChecked(option.code)\" [disabled]=\"!!config.disabled\"\r\n (change)=\"onCheckboxListChange(option.code, $any($event.target).checked)\">\r\n <div class=\"option-content d-flex flex-column gap-4 flex-1 text-left\">\r\n <span class=\"label-text text-16 c-1F2937\">{{ option.label }}</span>\r\n <span class=\"option-hint text-13 color-gray\" *ngIf=\"option.hint\">{{ option.hint }}</span>\r\n </div>\r\n </label>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Chip \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isChip\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"chip-group d-flex flex-wrap gap-8\" [class.is-invalid]=\"errorMessage\">\r\n <label *ngFor=\"let option of config.optionConfig?.optionList\"\r\n class=\"chip-label cursor-pointer p-6px-14px b-ffffff c-374151 b-1px-solid-D1D5DB br-20px fs-0-875rem\"\r\n [class.selected]=\"isChecked(option.code)\">\r\n <input type=\"checkbox\" [checked]=\"isChecked(option.code)\" [disabled]=\"!!config.disabled\"\r\n (change)=\"onCheckboxListChange(option.code, $any($event.target).checked)\" hidden>\r\n <span>{{ option.label }}</span>\r\n </label>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Switch \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isSwitch\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label class=\"switch-container d-flex justify-content-between align-items-center cursor-pointer\">\r\n <span class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">{{ config.label }}</span>\r\n <div class=\"switch position-relative\">\r\n <input type=\"checkbox\" [formControlName]=\"config.name!\" [class.is-invalid]=\"errorMessage\">\r\n <span class=\"slider position-absolute cursor-pointer\"></span>\r\n </div>\r\n </label>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Rich Text \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isRichText\" class=\"field-wrapper component-rich-text d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"rich-text-container\" [class.is-invalid]=\"errorMessage\">\r\n <quill-editor [formControlName]=\"config.name!\" class=\"rich-text-editor d-block w-100\"\r\n [placeholder]=\"config.richTextConfig?.placeholder || config.placeholder || ''\"\r\n [styles]=\"{height: config.richTextConfig?.height || '200px'}\">\r\n </quill-editor>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n <div class=\"char-count-hint font-poppins font-weight-400 text-14 text-right mt-4 c-6B7280\" *ngIf=\"showCharCount\">\r\n {{ remainingCharacters }} characters remaining\r\n </div>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Rating \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isRating\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"rating-group d-flex gap-4\" [class.is-invalid]=\"errorMessage\">\r\n <span *ngFor=\"let star of getStarArray()\" class=\"star d-inline-flex align-items-center cursor-pointer\"\r\n [class.filled]=\"isStarFilled(star)\" [class.half]=\"isStarHalf(star)\" (click)=\"onRatingChange(star, $event)\">\r\n <mat-icon>{{ isStarFilled(star) || isStarHalf(star) ? 'star' : 'star_border' }}</mat-icon>\r\n </span>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Generated Field (read-only) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isGenerated\" class=\"field-wrapper d-flex flex-column gap-6\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">{{ config.label\r\n }}</label>\r\n <div class=\"generated-value fs-0-875rem p-0-625rem-0-875rem b-F3F4F6 b-1px-solid-E5E7EB br-8px c-6B7280\">{{ value ||\r\n '-' }}</div>\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint\">{{ config.hint }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 File Upload \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isFileUpload\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <!-- Drop Zone -->\r\n <div\r\n class=\"upload-drop-zone d-flex flex-column align-items-center justify-content-center gap-8 cursor-pointer text-center p-32px-24px us-none b-1-5px-dashed-CBD5E1 br-12px bc-FFFAF1\"\r\n [class.drag-over]=\"isDragOver\" [class.has-files]=\"value?.length\" [class.is-invalid]=\"errorMessage\"\r\n (dragover)=\"onDragOver($event)\" (dragleave)=\"onDragLeave($event)\" (drop)=\"onFileDrop($event)\"\r\n (click)=\"fileInput.click()\">\r\n\r\n <div class=\"upload-icon-wrap mb-4 c-94A3B8\">\r\n <mat-icon class=\"upload-cloud-icon\">cloud_upload</mat-icon>\r\n </div>\r\n\r\n <p class=\"upload-main-text font-weight-600 m-0 c-1E293B fs-0-9rem\">Drag and drop files here or <span\r\n class=\"upload-link c-3B82F6\">click to upload</span></p>\r\n <p class=\"upload-hint-text m-0 fs-0-78rem c-64748B\" *ngIf=\"config.attachmentConfig?.acceptLabel\">\r\n Supported formats:\r\n <span class=\"upload-formats font-weight-500 c-3B82F6\">{{ config.attachmentConfig!.acceptLabel }}</span>\r\n </p>\r\n <p class=\"upload-hint-text m-0 fs-0-78rem c-64748B\" *ngIf=\"!config.attachmentConfig?.acceptLabel && config.hint\">\r\n {{ config.hint }}\r\n </p>\r\n\r\n <!-- Hidden native file input -->\r\n <input #fileInput type=\"file\" hidden [attr.multiple]=\"config.attachmentConfig?.multiple ? true : null\"\r\n [attr.accept]=\"config.attachmentConfig?.accept || null\" (change)=\"onFileSelected($event)\">\r\n </div>\r\n\r\n <!-- Uploaded file list -->\r\n <div class=\"uploaded-list d-flex flex-column gap-8 mt-10\" *ngIf=\"value?.length\">\r\n <div *ngFor=\"let f of value; let i = index\"\r\n class=\"uploaded-item d-flex align-items-center gap-10 p-10px-14px b-ffffff b-1px-solid-E2E8F0 br-8px\"\r\n [class.uploading]=\"f.isUploading\">\r\n\r\n <!-- Uploading spinner (shown while API call is in progress) -->\r\n <ng-container *ngIf=\"f.isUploading; else fileReady\">\r\n <div class=\"upload-spinner rounded-50 b-2px-solid-E2E8F0\"></div>\r\n <div class=\"file-info flex-1 d-flex flex-column\">\r\n <span class=\"file-name font-weight-500 overflow-hidden fs-0-85rem c-1E293B\" [title]=\"f.name\">{{ f.name\r\n }}</span>\r\n <span class=\"file-size uploading-label fs-0-72rem c-94A3B8 c-3B82F6\">Uploading...</span>\r\n </div>\r\n </ng-container>\r\n\r\n <!-- Normal state once upload is done -->\r\n <ng-template #fileReady>\r\n <!-- File type icon -->\r\n <mat-icon class=\"file-type-icon\">{{ getFileIcon(f.type) }}</mat-icon>\r\n\r\n <!-- Image thumbnail (only for images) -->\r\n <img *ngIf=\"f.type?.startsWith('image') && f.dataUrl\" [src]=\"f.dataUrl\" class=\"file-thumb rounded-4\"\r\n alt=\"preview\">\r\n\r\n <!-- Name & size -->\r\n <div class=\"file-info flex-1 d-flex flex-column\">\r\n <span class=\"file-name font-weight-500 overflow-hidden fs-0-85rem c-1E293B\" [title]=\"f.name\">{{ f.name\r\n }}</span>\r\n <span class=\"file-size fs-0-72rem c-94A3B8\">{{ formatFileSize(f.size) }}</span>\r\n </div>\r\n </ng-template>\r\n\r\n <!-- Remove button \u2014 disabled while uploading -->\r\n <lib-button [variant]=\"'danger-outline'\" [disabled]=\"f.isUploading\"\r\n (click)=\"!f.isUploading && removeUploadedFile(i)\">\r\n <mat-icon>close</mat-icon>\r\n </lib-button>\r\n </div>\r\n </div>\r\n\r\n <!-- Validation / file errors -->\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"fileUploadError\">{{ fileUploadError }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage && !fileUploadError\">{{ errorMessage }}</span>\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\"\r\n *ngIf=\"config.hint && !errorMessage && !fileUploadError && !config.attachmentConfig?.acceptLabel\">\r\n {{ config.hint }}\r\n </span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Media Upload (Type 2) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isMediaUpload\" class=\"field-wrapper media-upload-wrapper d-flex flex-column gap-6 p-0 border-none b-none\"\r\n [formGroup]=\"formGroup\">\r\n\r\n <!-- Hidden file input lives outside *ngIf \u2014 triggered via ViewChild -->\r\n <input #mediaDeviceInput type=\"file\" hidden multiple accept=\"image/*\" (change)=\"onMediaFileSelected($event)\">\r\n\r\n <!-- Two-column layout -->\r\n <div class=\"mu-layout d-grid align-items-start\">\r\n\r\n <!-- \u2500\u2500 LEFT PANEL \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <div class=\"mu-left d-flex flex-column gap-20\">\r\n\r\n <!-- Header: title + max-items badge -->\r\n <div class=\"mu-header d-flex align-items-start flex-wrap gap-10\">\r\n <h3 class=\"mu-title m-0 c-111827 fs-1-35rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </h3>\r\n <span\r\n class=\"mu-badge d-inline-flex align-items-center rounded-20 color-white font-weight-600 fs-0-72rem p-4px-12px b-111827\"\r\n *ngIf=\"config.attachmentConfig?.maxFiles\">\r\n {{ controller.labels['LBL_MEDIA_MAX_PREFIX'] || 'Maximum' }}\r\n {{ config.attachmentConfig?.maxFiles }}\r\n {{ controller.labels['LBL_MEDIA_MAX_SUFFIX'] || 'Image & Videos' }}\r\n </span>\r\n </div>\r\n\r\n <!-- Description -->\r\n <p class=\"mu-description m-0 fs-0-875rem c-6B7280\" *ngIf=\"config.attachmentConfig?.description\">\r\n {{ config.attachmentConfig?.description }}\r\n </p>\r\n <p class=\"mu-description m-0 fs-0-875rem c-6B7280\"\r\n *ngIf=\"!config.attachmentConfig?.description && controller.labels['LBL_MEDIA_DESC']\">\r\n {{ controller.labels['LBL_MEDIA_DESC'] }}\r\n </p>\r\n\r\n <!-- Feature bullet list -->\r\n <ul class=\"mu-features m-0 p-0 d-flex flex-column gap-8 ls-none\"\r\n *ngIf=\"config.attachmentConfig?.features?.length || controller.labels['LBL_MEDIA_FEATURE_1']\">\r\n <ng-container *ngIf=\"config.attachmentConfig?.features?.length\">\r\n <li *ngFor=\"let f of config.attachmentConfig?.features\"\r\n class=\"mu-feature-item d-flex align-items-center gap-8 fs-0-875rem c-374151\">\r\n <mat-icon class=\"mu-check text-16 c-3B82F6\">check</mat-icon>{{ f }}\r\n </li>\r\n </ng-container>\r\n <ng-container *ngIf=\"!config.attachmentConfig?.features?.length\">\r\n <li *ngIf=\"controller.labels['LBL_MEDIA_FEATURE_1']\"\r\n class=\"mu-feature-item d-flex align-items-center gap-8 fs-0-875rem c-374151\">\r\n <mat-icon class=\"mu-check text-16 c-3B82F6\">check</mat-icon>{{ controller.labels['LBL_MEDIA_FEATURE_1'] }}\r\n </li>\r\n <li *ngIf=\"controller.labels['LBL_MEDIA_FEATURE_2']\"\r\n class=\"mu-feature-item d-flex align-items-center gap-8 fs-0-875rem c-374151\">\r\n <mat-icon class=\"mu-check text-16 c-3B82F6\">check</mat-icon>{{ controller.labels['LBL_MEDIA_FEATURE_2'] }}\r\n </li>\r\n <li *ngIf=\"controller.labels['LBL_MEDIA_FEATURE_3']\"\r\n class=\"mu-feature-item d-flex align-items-center gap-8 fs-0-875rem c-374151\">\r\n <mat-icon class=\"mu-check text-16 c-3B82F6\">check</mat-icon>{{ controller.labels['LBL_MEDIA_FEATURE_3'] }}\r\n </li>\r\n </ng-container>\r\n </ul>\r\n\r\n <!-- Backdrop to close dropdown on outside click -->\r\n <div class=\"media-menu-backdrop\" *ngIf=\"showMediaMenu\"\r\n (click)=\"$event.stopPropagation(); showMediaMenu = false\"></div>\r\n\r\n <!-- Add Media button + dropdown -->\r\n <div class=\"media-add-container position-relative\" (click)=\"showMediaMenu = !showMediaMenu\">\r\n <lib-button id=\"btn-add-media-{{ config.name }}\" [variant]=\"'warning'\"\r\n [icon]=\"{type: 'material', value: 'add_photo_alternate'}\">\r\n {{ controller.labels['LBL_ADD_MEDIA'] || 'Add media' }}\r\n <mat-icon class=\"menu-chevron fs-18px\">add</mat-icon>\r\n </lib-button>\r\n\r\n <div class=\"media-dropdown position-absolute rounded-12 overflow-hidden b-ffffff b-1px-solid-E5E7EB\"\r\n *ngIf=\"showMediaMenu\" role=\"menu\" (click)=\"$event.stopPropagation()\">\r\n <!-- Video -->\r\n <button id=\"btn-media-video-{{ config.name }}\" type=\"button\"\r\n class=\"media-dropdown-item d-flex align-items-center gap-12 w-100 cursor-pointer text-left b-none border-none p-12px-16px bb-1px-solid-F3F4F6\"\r\n (click)=\"onMediaMenuVideo(); showMediaMenu = false\" role=\"menuitem\">\r\n <span\r\n class=\"media-drop-icon media-drop-icon--video d-flex align-items-center justify-content-center rounded-8\"><mat-icon>videocam</mat-icon></span>\r\n <span class=\"media-drop-text d-flex flex-column flex-1\">\r\n <span class=\"media-drop-label font-weight-600 fs-0-875rem c-111827\">{{\r\n controller.labels['LBL_MEDIA_VIDEO'] || 'Video' }}</span>\r\n <span class=\"media-drop-desc c-6B7280 fs-0-75rem\">{{ controller.labels['LBL_MEDIA_VIDEO_DESC'] || 'Add\r\n YouTube URL'\r\n }}</span>\r\n </span>\r\n </button>\r\n <!-- Device -->\r\n <button id=\"btn-media-device-{{ config.name }}\" type=\"button\"\r\n class=\"media-dropdown-item d-flex align-items-center gap-12 w-100 cursor-pointer text-left b-none border-none p-12px-16px bb-1px-solid-F3F4F6\"\r\n (click)=\"onMediaMenuDevice(); showMediaMenu = false\" role=\"menuitem\">\r\n <span\r\n class=\"media-drop-icon media-drop-icon--device d-flex align-items-center justify-content-center rounded-8\"><mat-icon>upload</mat-icon></span>\r\n <span class=\"media-drop-text d-flex flex-column flex-1\">\r\n <span class=\"media-drop-label font-weight-600 fs-0-875rem c-111827\">{{\r\n controller.labels['LBL_MEDIA_DEVICE'] || 'Upload from device'\r\n }}</span>\r\n <span class=\"media-drop-desc c-6B7280 fs-0-75rem\">{{ controller.labels['LBL_MEDIA_DEVICE_DESC'] ||\r\n 'Select images from your\r\n computer' }}</span>\r\n </span>\r\n </button>\r\n <!-- Library -->\r\n <button id=\"btn-media-library-{{ config.name }}\" type=\"button\"\r\n class=\"media-dropdown-item d-flex align-items-center gap-12 w-100 cursor-pointer text-left b-none border-none p-12px-16px bb-1px-solid-F3F4F6\"\r\n (click)=\"onMediaMenuLibrary(); showMediaMenu = false\" role=\"menuitem\">\r\n <span\r\n class=\"media-drop-icon media-drop-icon--library d-flex align-items-center justify-content-center rounded-8\"><mat-icon>photo_library</mat-icon></span>\r\n <span class=\"media-drop-text d-flex flex-column flex-1\">\r\n <span class=\"media-drop-label font-weight-600 fs-0-875rem c-111827\">{{\r\n controller.labels['LBL_MEDIA_LIBRARY'] || 'Upload from library'\r\n }}</span>\r\n <span class=\"media-drop-desc c-6B7280 fs-0-75rem\">{{ controller.labels['LBL_MEDIA_LIBRARY_DESC'] ||\r\n 'Choose from default\r\n images' }}</span>\r\n </span>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- YouTube URL Input (inline below button) -->\r\n <div class=\"youtube-input-panel d-flex flex-column gap-8 p-16 rounded-10 b-FFFAF1 b-1px-solid-E5E7EB\"\r\n *ngIf=\"showYoutubeInput\">\r\n <label class=\"youtube-panel-label d-flex align-items-center gap-6 font-weight-600 fs-0-875rem c-111827\">\r\n {{ controller.labels['LBL_YOUTUBE_URL'] || 'Video URL' }}\r\n </label>\r\n <div class=\"youtube-input-row d-flex gap-8\">\r\n <input id=\"input-youtube-url-{{ config.name }}\" type=\"url\" class=\"field-input youtube-url-input\"\r\n [(ngModel)]=\"youtubeUrlInput\" [ngModelOptions]=\"{standalone: true}\"\r\n [placeholder]=\"controller.labels['PH_YOUTUBE_URL'] || 'Video URL'\" (keyup.enter)=\"addYoutubeMedia()\">\r\n <lib-button id=\"btn-add-youtube-{{ config.name }}\" [variant]=\"'secondary'\" (click)=\"addYoutubeMedia()\">\r\n {{ controller.labels['LBL_ADD'] || 'Add' }}\r\n </lib-button>\r\n </div>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"youtubeUrlError\">{{ youtubeUrlError }}</span>\r\n </div>\r\n\r\n <div\r\n class=\"media-upload-status d-flex align-items-center gap-8 mt-4 color-error rounded-8 font-weight-500 p-10px-14px b-FEF2F2 fs-0-85rem\"\r\n *ngIf=\"mediaUploadError\">\r\n <mat-icon class=\"status-icon fs-18px\">error_outline</mat-icon>\r\n <span>{{ mediaUploadError }}</span>\r\n </div>\r\n\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n </div>\r\n <!-- end left panel -->\r\n\r\n <!-- \u2500\u2500 RIGHT PANEL (carousel) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <div class=\"mu-right d-flex flex-column gap-12\">\r\n\r\n <!-- Carousel (when items exist) -->\r\n <div class=\"media-carousel-section d-flex flex-column gap-12\" *ngIf=\"mediaItems.length\">\r\n <div\r\n class=\"media-carousel-main position-relative w-100 overflow-hidden d-flex align-items-center justify-content-center br-12px b-0F172A\">\r\n <button id=\"btn-carousel-prev-{{ config.name }}\" type=\"button\"\r\n class=\"carousel-nav carousel-nav--prev position-absolute rounded-50 cursor-pointer d-flex align-items-center justify-content-center border-none b-rgba-255-255-255-0-85\"\r\n (click)=\"mediaCarouselPrev()\" [disabled]=\"mediaCarouselIndex === 0\" aria-label=\"Previous\">\r\n <mat-icon>chevron_left</mat-icon>\r\n </button>\r\n\r\n <div class=\"carousel-viewer position-absolute d-flex align-items-center justify-content-center\"\r\n *ngFor=\"let item of mediaItems; let i = index\" [hidden]=\"i !== mediaCarouselIndex\">\r\n <div *ngIf=\"item.isUploading\"\r\n class=\"carousel-uploading d-flex flex-column align-items-center gap-12 c-94A3B8 fs-0-85rem\">\r\n <div class=\"carousel-spinner rounded-50 b-3px-solid-rgba-255-255-255-0-15\"></div>\r\n <span>{{ controller.labels['LBL_UPLOADING'] || 'Uploading\u2026' }}</span>\r\n </div>\r\n <ng-container *ngIf=\"!item.isUploading && item.mediaType === 'youtube'\">\r\n <iframe class=\"carousel-iframe w-100 h-100 br-12px\" [src]=\"item.url | trustedUrl\" frameborder=\"0\"\r\n allowfullscreen\r\n allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\">\r\n </iframe>\r\n </ng-container>\r\n <ng-container *ngIf=\"!item.isUploading && item.mediaType === 'image'\">\r\n <img class=\"carousel-image w-100 h-100 br-12px\" [src]=\"item.url\" alt=\"Media\">\r\n </ng-container>\r\n <button id=\"btn-remove-media-{{ config.name }}-{{ i }}\" type=\"button\"\r\n class=\"carousel-remove-btn position-absolute rounded-50 cursor-pointer d-flex align-items-center justify-content-center border-none b-rgba-0-0-0-0-55\"\r\n [disabled]=\"item.isUploading\" (click)=\"removeMediaItem(i)\" aria-label=\"Remove\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <button id=\"btn-carousel-next-{{ config.name }}\" type=\"button\"\r\n class=\"carousel-nav carousel-nav--next position-absolute rounded-50 cursor-pointer d-flex align-items-center justify-content-center border-none b-rgba-255-255-255-0-85\"\r\n (click)=\"mediaCarouselNext()\" [disabled]=\"mediaCarouselIndex === mediaItems.length - 1\" aria-label=\"Next\">\r\n <mat-icon>chevron_right</mat-icon>\r\n </button>\r\n\r\n <div class=\"carousel-dots position-absolute d-flex gap-6\">\r\n <span *ngFor=\"let item of mediaItems; let i = index\"\r\n class=\"carousel-dot rounded-50 cursor-pointer b-rgba-255-255-255-0-45\"\r\n [class.active]=\"i === mediaCarouselIndex\" (click)=\"mediaGoTo(i)\"></span>\r\n </div>\r\n </div>\r\n\r\n <!-- Thumbnail strip -->\r\n <div class=\"media-thumbnail-strip d-flex flex-wrap gap-8 pb-4px\">\r\n <div *ngFor=\"let item of mediaThumbnails; let i = index\"\r\n class=\"media-thumb rounded-8 overflow-hidden cursor-pointer d-flex align-items-center justify-content-center b-2px-solid-transparent b-E2E8F0\"\r\n [class.active]=\"i === mediaCarouselIndex\" (click)=\"mediaGoTo(i)\">\r\n <div *ngIf=\"item.isUploading\"\r\n class=\"thumb-uploading d-flex align-items-center justify-content-center w-100 h-100\">\r\n <div class=\"thumb-spinner rounded-50 b-2px-solid-E2E8F0\"></div>\r\n </div>\r\n <img *ngIf=\"!item.isUploading && item.mediaType === 'youtube' && item.thumbnailUrl\"\r\n [src]=\"item.thumbnailUrl\" class=\"thumb-img w-100 h-100\" alt=\"Video thumbnail\">\r\n <div *ngIf=\"!item.isUploading && item.mediaType === 'youtube' && !item.thumbnailUrl\"\r\n class=\"thumb-yt-placeholder d-flex align-items-center justify-content-center w-100 h-100 b-1E293B c-EF4444\">\r\n <mat-icon>play_circle</mat-icon>\r\n </div>\r\n <img *ngIf=\"!item.isUploading && item.mediaType === 'image' && item.url\" [src]=\"item.url\"\r\n class=\"thumb-img w-100 h-100\" alt=\"Image thumbnail\">\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Empty right-side placeholder -->\r\n <div\r\n class=\"mu-right-empty d-flex flex-column align-items-center justify-content-center gap-10 h-100 text-center p-24 br-12px b-FFFAF1 c-94A3B8 b-2px-dashed-CBD5E1\"\r\n *ngIf=\"!mediaItems.length\" (click)=\"onMediaMenuDevice()\">\r\n <mat-icon class=\"mu-right-empty-icon fs-52px\">perm_media</mat-icon>\r\n <p>{{ controller.labels['LBL_ADD_MEDIA'] || 'Add media' }}</p>\r\n </div>\r\n\r\n </div>\r\n <!-- end right panel -->\r\n\r\n </div><!-- end mu-layout -->\r\n </div>\r\n\r\n\r\n <!-- \u2550\u2550 Library Image Picker Modal \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div class=\"media-library-overlay b-rgba-0-0-0-0-5\" *ngIf=\"showLibraryModal\" (click)=\"closeLibraryModal()\"></div>\r\n <div class=\"media-library-modal d-flex flex-column overflow-hidden b-ffffff br-16px\" *ngIf=\"showLibraryModal\"\r\n role=\"dialog\" aria-modal=\"true\">\r\n <div class=\"library-modal-header d-flex align-items-start justify-content-between p-24px-28px bb-1px-solid-E5E7EB\">\r\n <div class=\"header-left d-flex flex-column gap-8\">\r\n <h3 class=\"library-modal-title m-0 color-dark fs-1-25rem\">\r\n {{ controller.labels['LBL_ADD_IMAGES'] || 'Add Images' }}\r\n </h3>\r\n <p class=\"library-modal-subtitle m-0 color-gray fs-0-85rem\">\r\n {{ controller.labels['LBL_LIBRARY_MODAL_DESC'] || 'Upload media to make your opportunity stand out. Plus, take\r\n full control of your sequence - drag images to reorder as you desire.' }}\r\n </p>\r\n </div>\r\n <button id=\"btn-close-library-{{ config.name }}\" type=\"button\"\r\n class=\"library-close-btn d-flex align-items-center justify-content-center cursor-pointer rounded-50 border-none b-none c-9CA3AF\"\r\n (click)=\"closeLibraryModal()\" aria-label=\"Close\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <!-- Loading -->\r\n <div class=\"library-loading\" *ngIf=\"libraryLoading\">\r\n <div class=\"lib-spinner rounded-50 b-3px-solid-E2E8F0\"></div>\r\n <span>{{ controller.labels['LBL_LOADING'] || 'Loading\u2026' }}</span>\r\n </div>\r\n\r\n <!-- Error -->\r\n <div class=\"library-error d-flex align-items-center gap-8 color-error b-FEF2F2 fs-0-875rem p-16px-24px\"\r\n *ngIf=\"libraryError && !libraryLoading\">\r\n <mat-icon>error_outline</mat-icon>\r\n {{ libraryError }}\r\n </div>\r\n\r\n <!-- Image grid -->\r\n <div class=\"library-grid d-grid gap-16 flex-1 p-28px b-F9FAFB\" *ngIf=\"!libraryLoading && libraryImages.length\">\r\n <div *ngFor=\"let img of libraryImages; let li = index\" id=\"lib-img-{{ config.name }}-{{ li }}\"\r\n class=\"library-grid-item position-relative rounded-12 overflow-hidden cursor-pointer bg-white b-3px-solid-transparent\"\r\n [class.selected]=\"isLibraryItemSelected(img)\" (click)=\"toggleLibraryItem(img)\">\r\n <img [src]=\"getLibraryItemUrl(img)\" class=\"library-grid-img w-100 h-100 d-block\" alt=\"Library image\">\r\n <div\r\n class=\"library-check position-absolute bg-white rounded-50 d-flex align-items-center justify-content-center c-3B82F6\"\r\n *ngIf=\"isLibraryItemSelected(img)\">\r\n <mat-icon>check_circle</mat-icon>\r\n </div>\r\n <div class=\"library-overlay-hover position-absolute b-rgba-59-130-246-0-12\"></div>\r\n </div>\r\n </div>\r\n\r\n <!-- Empty library -->\r\n <div\r\n class=\"library-empty d-flex flex-column align-items-center justify-content-center gap-12 flex-1 c-9CA3AF fs-0-875rem p-48px-24px\"\r\n *ngIf=\"!libraryLoading && !libraryError && libraryImages.length === 0\">\r\n <mat-icon>image_not_supported</mat-icon>\r\n <span>{{ controller.labels['LBL_LIBRARY_EMPTY'] || 'No images found in library.' }}</span>\r\n </div>\r\n\r\n <!-- Footer -->\r\n <div\r\n class=\"library-modal-footer d-flex align-items-center justify-content-end bg-white p-20px-28px bt-1px-solid-E5E7EB\">\r\n <div class=\"library-footer-actions d-flex gap-12 gap-10\">\r\n <lib-button id=\"btn-library-cancel-{{ config.name }}\" [variant]=\"'outline'\" (click)=\"closeLibraryModal()\">\r\n {{ controller.labels['LBL_CANCEL'] || 'Cancel' }}\r\n </lib-button>\r\n <lib-button id=\"btn-library-confirm-{{ config.name }}\" [variant]=\"'primary'\"\r\n [disabled]=\"librarySelectedIds.size === 0\" (click)=\"confirmLibrarySelection()\">\r\n {{ controller.labels['LBL_CONTINUE'] || 'Continue' }}\r\n </lib-button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Location Field \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isLocation\" class=\"field-wrapper location-field-wrapper d-flex flex-column gap-6 gap-12\"\r\n [formGroup]=\"formGroup\">\r\n\r\n <!-- Field label -->\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n <p class=\"location-subtitle m-0 c-6B7280 fs-0-8125rem\" *ngIf=\"config.hint\">{{ config.hint }}</p>\r\n\r\n <!-- Three-tab bar -->\r\n <div class=\"location-tabs d-flex gap-12 mb-24\">\r\n <lib-button class=\"loc-tab-btn flex-1\" [variant]=\"locationActiveTab === 'VENUE' ? 'warning' : 'outline'\"\r\n (click)=\"onLocationTabChange('VENUE')\">\r\n {{ controller.labels['LBL_LOC_VENUE'] || 'Venue' }}\r\n </lib-button>\r\n <lib-button class=\"loc-tab-btn flex-1\" [variant]=\"locationActiveTab === 'ONLINE' ? 'warning' : 'outline'\"\r\n (click)=\"onLocationTabChange('ONLINE')\">\r\n {{ controller.labels['LBL_LOC_ONLINE'] || 'Online Event' }}\r\n </lib-button>\r\n <lib-button class=\"loc-tab-btn flex-1\" [variant]=\"locationActiveTab === 'TBA' ? 'warning' : 'outline'\"\r\n (click)=\"onLocationTabChange('TBA')\">\r\n {{ controller.labels['LBL_LOC_TBA'] || 'To be Announced' }}\r\n </lib-button>\r\n </div>\r\n\r\n <!-- VENUE TAB -->\r\n <div *ngIf=\"locationActiveTab === 'VENUE'\" class=\"loc-panel loc-venue-panel d-flex flex-column gap-12\">\r\n\r\n <p class=\"loc-section-label m-0 font-weight-600 c-111827 fs-0-9rem\">\r\n {{ controller.labels['LBL_LOC_ADDRESS'] || 'Location address' }}\r\n </p>\r\n\r\n <!-- Added venue rows -->\r\n <div class=\"loc-venue-list d-flex flex-column gap-8\" *ngIf=\"locationVenues.length > 0\">\r\n <div *ngFor=\"let venue of locationVenues; let i = index\"\r\n class=\"loc-venue-item d-flex align-items-center gap-10 p-10px-14px br-7px b-ffffff b-1px-solid-D1D5DB\">\r\n <mat-icon class=\"loc-venue-search-icon fs-18px c-9CA3AF\">search</mat-icon>\r\n <span class=\"loc-venue-text flex-1 overflow-hidden fs-0-875rem c-111827\">{{ venue.address || venue.name ||\r\n venue.description }}</span>\r\n <button type=\"button\"\r\n class=\"loc-action-btn loc-delete-btn d-flex align-items-center justify-content-center cursor-pointer rounded-50 b-none border-none p-4px\"\r\n (click)=\"removeLocationVenue(i)\">\r\n <mat-icon>delete_outline</mat-icon>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- Location count badge -->\r\n <p class=\"loc-count-text m-0 font-weight-600 fs-0-8125rem c-3B82F6\"\r\n *ngIf=\"locationVenues.length > 0 && config.locationConfig?.allowMulti\">\r\n {{ locationVenues.length }} {{ controller.labels['LBL_LOC_COUNT_SUFFIX'] || 'Locations Added!' }}\r\n </p>\r\n\r\n <!-- Search input (hide when max reached) -->\r\n <div class=\"loc-search-container position-relative\" *ngIf=\"!locationMaxReached\">\r\n <div class=\"loc-search-wrapper position-relative d-flex align-items-center mt-4\">\r\n <mat-icon class=\"loc-search-icon position-absolute fs-1-1rem c-9CA3AF pe-none\">search</mat-icon>\r\n <input\r\n class=\"field-input loc-search-input w-100 font-poppins flex-1 fs-0-875rem c-111827 br-7px br-8px bc-F3F4F6 pl-2-4rem bc-DC2626 pt-0-625rem pb-0-625rem pl-16px pr-16px bc-ffffff b-1px-solid-D1D5DB pr-3-5rem\"\r\n [placeholder]=\"config.locationConfig?.venuePlaceholder || (controller.labels['PH_LOC_VENUE'] || 'Type to search venue...')\"\r\n [value]=\"locationSearchText\" (input)=\"handleLocationSearchInput($event)\" (blur)=\"hideLocationSuggestions()\"\r\n autocomplete=\"off\" [class.is-invalid]=\"errorMessage\">\r\n </div>\r\n <!-- Suggestions dropdown -->\r\n <div class=\"loc-suggestions-panel position-absolute overflow-hidden br-8px b-ffffff b-1px-solid-D1D5DB\"\r\n *ngIf=\"locationShowSuggestions && locationSuggestions.length\">\r\n <div *ngFor=\"let sug of locationSuggestions\"\r\n class=\"loc-suggestion-item d-flex align-items-center gap-10 cursor-pointer p-10px-14px\"\r\n (mousedown)=\"onLocationSuggestionSelect(sug)\">\r\n <mat-icon class=\"loc-suggestion-icon fs-18px c-E53E3E\">place</mat-icon>\r\n <span class=\"loc-suggestion-text overflow-hidden fs-0-875rem c-374151\">{{ sug.description }}</span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Add another button -->\r\n <button type=\"button\"\r\n class=\"loc-add-btn d-inline-flex align-items-center gap-6 cursor-pointer font-weight-600 p-0 b-none border-none fs-0-875rem c-1A56DB\"\r\n *ngIf=\"locationVenues.length > 0 && !locationMaxReached && config.locationConfig?.allowMulti\">\r\n <mat-icon>add_circle_outline</mat-icon>\r\n <span>{{ controller.labels['LBL_LOC_ADD_ANOTHER'] || 'Add another Location' }}</span>\r\n </button>\r\n\r\n <!-- Map -->\r\n <div class=\"loc-map-container overflow-hidden br-10px b-1px-solid-E5E7EB\"\r\n *ngIf=\"config.locationConfig?.showMap !== false\">\r\n <ng-container *ngIf=\"config.locationConfig?.googleMapsApiKey; else simpleEmbed\">\r\n <div [id]=\"'loc-map-' + config.name\" class=\"loc-map-frame w-100 d-block border-none\"\r\n [style.height]=\"config.locationConfig?.mapHeight || '300px'\"></div>\r\n </ng-container>\r\n <ng-template #simpleEmbed>\r\n <iframe class=\"loc-map-frame w-100 d-block border-none\"\r\n [style.height]=\"config.locationConfig?.mapHeight || '300px'\" [src]=\"getLocationMapEmbedUrl() | trustedUrl\"\r\n frameborder=\"0\" allowfullscreen loading=\"lazy\">\r\n </iframe>\r\n </ng-template>\r\n </div>\r\n\r\n <!-- Map hint -->\r\n <p class=\"loc-map-hint m-0 text-center fs-0-78rem c-6B7280\">\r\n {{ controller.labels['LBL_LOC_MAP_HINT'] || 'Type the venue address. A map will appear to assist you.' }}\r\n </p>\r\n </div>\r\n\r\n <!-- ONLINE TAB -->\r\n <div *ngIf=\"locationActiveTab === 'ONLINE'\" class=\"loc-panel loc-online-panel d-flex flex-column gap-12\">\r\n <p class=\"loc-section-label m-0 font-weight-600 c-111827 fs-0-9rem\">\r\n {{ controller.labels['LBL_LOC_ONLINE_URL'] || 'Event URL' }}\r\n </p>\r\n <div class=\"loc-search-wrapper position-relative d-flex align-items-center mt-4\">\r\n <mat-icon class=\"loc-search-icon position-absolute fs-1-1rem c-9CA3AF pe-none\">link</mat-icon>\r\n <input\r\n class=\"field-input loc-search-input w-100 font-poppins flex-1 fs-0-875rem c-111827 br-7px br-8px bc-F3F4F6 pl-2-4rem bc-DC2626 pt-0-625rem pb-0-625rem pl-16px pr-16px bc-ffffff b-1px-solid-D1D5DB pr-3-5rem\"\r\n type=\"url\"\r\n [placeholder]=\"config.locationConfig?.onlinePlaceholder || (controller.labels['PH_LOC_ONLINE'] || 'https://zoom.us/j/...')\"\r\n [value]=\"locationOnlineUrl\" (input)=\"onLocationUrlChange($any($event.target).value)\"\r\n [class.is-invalid]=\"errorMessage\">\r\n </div>\r\n </div>\r\n\r\n <!-- TBA TAB -->\r\n <div *ngIf=\"locationActiveTab === 'TBA'\"\r\n class=\"loc-panel loc-tba-panel d-flex flex-column gap-12 justify-content-center\">\r\n <div\r\n class=\"loc-tba-content d-flex flex-column align-items-center justify-content-center text-center gap-12 p-32px-24px b-F9FAFB b-1px-dashed-D1D5DB br-10px\">\r\n <mat-icon class=\"loc-tba-icon fs-40px c-9CA3AF\">schedule</mat-icon>\r\n <p class=\"loc-tba-text m-0 c-6B7280 fs-0-9rem\">\r\n {{ controller.labels['LBL_LOC_TBA_DESC'] || \"This event's location is yet to be announced. Check back later\r\n for updates.\" }}\r\n </p>\r\n </div>\r\n </div>\r\n\r\n <!-- Hidden real form control -->\r\n <input type=\"hidden\" [formControlName]=\"config.name!\">\r\n\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n</div>", styles: [".d-flex{display:flex}.d-inline-flex{display:inline-flex}.d-grid{display:grid}.d-block{display:block}.d-none{display:none}.flex-column{flex-direction:column}.flex-row{flex-direction:row}.flex-row-reverse{flex-direction:row-reverse}.flex-wrap{flex-wrap:wrap}.flex-1{flex:1}.align-items-center{align-items:center}.align-items-start{align-items:flex-start}.align-items-end{align-items:flex-end}.justify-content-center{justify-content:center}.justify-content-between{justify-content:space-between}.justify-content-start{justify-content:flex-start}.justify-content-end{justify-content:flex-end}.grid-cols-12{grid-template-columns:repeat(12,1fr)}.w-100{width:100%}.h-100{height:100%}.position-relative{position:relative}.position-absolute{position:absolute}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.font-poppins{font-family:var(--cc-sf-font-family, \"Poppins\", sans-serif)}.font-weight-400{font-weight:400}.font-weight-500{font-weight:500}.font-weight-600{font-weight:600}.text-13{font-size:13px}.text-14{font-size:14px}.text-16{font-size:16px}.color-white{color:#fff}.color-dark{color:#111827}.color-gray{color:#6b7280}.color-error{color:var(--cc-sf-error-text-color, #DC2626)}.bg-white{background-color:#fff}.bg-transparent{background-color:transparent}.m-0{margin:0}.mt-4{margin-top:4px}.mt-8{margin-top:8px}.mt-10{margin-top:10px}.mt-12{margin-top:12px}.mt-16{margin-top:16px}.mt-20{margin-top:20px}.mt-24{margin-top:24px}.mb-0{margin-bottom:0}.mb-4{margin-bottom:4px}.mb-8{margin-bottom:8px}.mb-10{margin-bottom:10px}.mb-12{margin-bottom:12px}.mb-16{margin-bottom:16px}.mb-20{margin-bottom:20px}.mb-24{margin-bottom:24px}.ml-16{margin-left:16px}.ml-20{margin-left:20px}.p-0{padding:0}.p-16{padding:16px}.p-20{padding:20px}.p-24{padding:24px}.pt-20{padding-top:20px}.pb-10{padding-bottom:10px}.gap-4{gap:4px}.gap-6{gap:6px}.gap-8{gap:8px}.gap-10{gap:10px}.gap-12{gap:12px}.gap-16{gap:16px}.gap-20{gap:20px}.rounded-4{border-radius:4px}.rounded-6{border-radius:6px}.rounded-8{border-radius:8px}.rounded-10{border-radius:10px}.rounded-12{border-radius:12px}.rounded-20{border-radius:20px}.rounded-24{border-radius:24px}.rounded-50{border-radius:50%}.cursor-pointer{cursor:pointer}.overflow-hidden{overflow:hidden}.resize-vertical{resize:vertical}.box-sizing-border{box-sizing:border-box}.border-none{border:none!important}.mb-16px{margin-bottom:var(--cc-sf-grid-gap, 16px)!important}.c-DC2626{color:var(--cc-sf-label-required-color, #DC2626)!important}.ml-0-125rem{margin-left:.125rem!important}.fs-0-875rem{font-size:.875rem!important}.c-111827{color:var(--cc-sf-label-color, #111827)!important}.br-7px{border-radius:var(--cc-sf-input-radius, 7px)!important}.c-6B7280{color:var(--cc-sf-hint-color, #6B7280)!important}.fs-0-75rem{font-size:var(--cc-sf-error-text-size, .75rem)!important}.b-none{background:none!important}.p-32px-24px{padding:32px 24px!important}.us-none{-webkit-user-select:none!important;user-select:none!important}.c-1E293B{color:var(--cc-sf-label-color, #1E293B)!important}.c-3B82F6{color:var(--cc-sf-chip-selected-bg, #3B82F6)!important}.fs-0-78rem{font-size:.78rem!important}.p-10px-14px{padding:10px 14px!important}.fs-0-85rem{font-size:.85rem!important}.fs-0-72rem{font-size:.72rem!important}.c-94A3B8{color:#94a3b8!important}.p-4px{padding:4px!important}.br-8px{border-radius:var(--cc-sf-input-radius, 8px)!important}.bc-F3F4F6{background-color:var(--cc-sf-input-disabled-bg, #F3F4F6)!important}.br-none{border-right:none!important}.bl-none{border-left:none!important}.pe-none{pointer-events:none!important}.fs-1-1rem{font-size:1.1rem!important}.c-9CA3AF{color:var(--cc-sf-hint-color, #9CA3AF)!important}.pl-2-4rem{padding-left:2.4rem!important}.fs-0-8125rem{font-size:.8125rem!important}.ls-none{list-style:none!important}.br-12px{border-radius:var(--mu-carousel-radius, 12px)!important}.b-FFFAF1{background:var(--cc-sf-dropzone-bg, #FFFAF1)!important}.fs-18px{font-size:18px!important}.b-FEF2F2{background:var(--cc-sf-error-bg, #FEF2F2)!important}.bc-DC2626{border-color:var(--cc-sf-error-border, #DC2626)!important}.c-202124{color:var(--cc-sf-label-color, #202124)!important}.fs-18px{font-size:var(--cc-sf-label-size, 18px)!important}.mb-0-5rem{margin-bottom:.5rem!important}.pt-0-625rem{padding-top:var(--cc-sf-input-padding-y, .625rem)!important}.pb-0-625rem{padding-bottom:var(--cc-sf-input-padding-y, .625rem)!important}.pl-16px{padding-left:var(--cc-sf-input-padding-x, 16px)!important}.pr-16px{padding-right:var(--cc-sf-input-padding-x, 16px)!important}.bc-ffffff{background-color:var(--cc-sf-section-bg, #ffffff)!important}.b-1px-solid-D1D5DB{border:1px solid var(--cc-sf-input-border, #D1D5DB)!important}.fs-0-75rem{font-size:.75rem!important}.c-1F2937{color:var(--cc-sf-section-label-color, #1F2937)!important}.p-6px-14px{padding:var(--cc-sf-chip-padding, 6px 14px)!important}.b-ffffff{background:var(--loc-suggestion-bg, #ffffff)!important}.c-374151{color:var(--cc-sf-label-color, #374151)!important}.br-20px{border-radius:var(--cc-sf-chip-radius, 20px)!important}.fs-0-875rem{font-size:var(--cc-sf-btn-font-size, .875rem)!important}.bc-D1D5DB{background-color:var(--cc-sf-switch-track-off, #D1D5DB)!important}.pr-2-75rem{padding-right:2.75rem!important}.p-0-25rem{padding:.25rem!important}.p-0-625rem-0-875rem{padding:var(--cc-sf-generated-padding, .625rem .875rem)!important}.b-F3F4F6{background:var(--cc-sf-generated-bg, #F3F4F6)!important}.b-1px-solid-E5E7EB{border:1px solid var(--cc-sf-input-disabled-border, #E5E7EB)!important}.br-8px{border-radius:var(--cc-sf-uploaded-item-radius, 8px)!important}.c-6B7280{color:var(--ms-desc-color, #6B7280)!important}.mb-20px{margin-bottom:var(--cc-sf-section-gap, 20px)!important}.br-10px{border-radius:var(--cc-sf-input-radius, 10px)!important}.p-20px{padding:var(--cc-sf-section-padding, 20px)!important}.fs-1rem{font-size:1rem!important}.m-0-0-16px-0{margin:0 0 16px!important}.bb-2px-solid-E5E7EB{border-bottom:var(--cc-sf-section-label-border, 2px solid #E5E7EB)!important}.p-16px{padding:var(--cc-sf-instance-padding, 16px)!important}.b-F9FAFB{background:var(--loc-tba-bg, #F9FAFB)!important}.bb-1px-dashed-D1D5DB{border-bottom:var(--cc-sf-instance-divider, 1px dashed #D1D5DB)!important}.c-4B5563{color:var(--cc-sf-instance-num-color, #4B5563)!important}.fs-0-8125rem{font-size:var(--cc-sf-hint-size, .8125rem)!important}.pb-0{padding-bottom:0!important}.p-18px-24px{padding:18px 24px!important}.c-111827{color:var(--ms-title-color, #111827)!important}.bt-1px-solid-E5E7EB{border-top:1px solid #E5E7EB!important}.p-4px-10px{padding:4px 10px!important}.b-FFF5F5{background:var(--cc-sf-btn-remove-bg, #FFF5F5)!important}.c-E53E3E{color:var(--loc-delete-color, #E53E3E)!important}.b-1px-solid-FED7D7{border:var(--cc-sf-btn-remove-border, 1px solid #FED7D7)!important}.br-4px{border-radius:var(--cc-sf-btn-remove-radius, 4px)!important}.p-8px-16px{padding:8px 16px!important}.b-transparent{background:var(--cc-sf-btn-add-bg, transparent)!important}.c-3B82F6{color:var(--cc-sf-input-focus-border, #3B82F6)!important}.b-1px-dashed-CBD5E1{border:var(--cc-sf-btn-add-border, 1px dashed #CBD5E1)!important}.br-6px{border-radius:var(--cc-sf-btn-add-radius, 6px)!important}.b-1-5px-dashed-CBD5E1{border:var(--cc-sf-dropzone-border, 1.5px dashed #CBD5E1)!important}.br-12px{border-radius:var(--cc-sf-dropzone-radius, 12px)!important}.bc-FFFAF1{background-color:var(--cc-sf-dropzone-bg, #FFFAF1)!important}.c-94A3B8{color:var(--cc-sf-uploaded-remove-color, #94A3B8)!important}.fs-0-9rem{font-size:var(--cc-sf-input-font-size, .9rem)!important}.c-64748B{color:var(--cc-sf-dropzone-hint-color, #64748B)!important}.b-1px-solid-E2E8F0{border:var(--cc-sf-uploaded-item-border, 1px solid #E2E8F0)!important}.b-2px-solid-E2E8F0{border:2px solid #E2E8F0!important}.pr-3-5rem{padding-right:3.5rem!important}.p-0-0-875rem{padding:0 .875rem!important}.bc-FFFFFF{background-color:var(--cc-sf-input-bg, #FFFFFF)!important}.b-1-5px-solid-D1D5DB{border:var(--cc-sf-input-border, 1.5px solid #D1D5DB)!important}.mb-0-75rem{margin-bottom:.75rem!important}.mt-6px{margin-top:6px!important}.pr-2-4rem{padding-right:2.4rem!important}.p-0-2rem{padding:.2rem!important}.fs-1-35rem{font-size:1.35rem!important}.p-4px-12px{padding:4px 12px!important}.b-111827{background:var(--cc-sf-label-color, #111827)!important}.b-2px-dashed-CBD5E1{border:2px dashed var(--cc-sf-dropzone-border, #CBD5E1)!important}.fs-52px{font-size:52px!important}.p-12px-16px{padding:12px 16px!important}.bb-1px-solid-F3F4F6{border-bottom:1px solid var(--cc-sf-input-disabled-border, #F3F4F6)!important}.b-0F172A{background:var(--mu-carousel-bg, #0F172A)!important}.b-3px-solid-rgba-255-255-255-0-15{border:3px solid rgba(255,255,255,.15)!important}.b-rgba-255-255-255-0-85{background:#ffffffd9!important}.b-rgba-0-0-0-0-55{background:#0000008c!important}.b-rgba-255-255-255-0-45{background:#ffffff73!important}.pb-4px{padding-bottom:4px!important}.b-2px-solid-transparent{border:2px solid transparent!important}.b-E2E8F0{background:var(--mu-thumb-bg, #E2E8F0)!important}.b-1E293B{background:#1e293b!important}.c-EF4444{color:#ef4444!important}.b-rgba-0-0-0-0-5{background:#00000080!important}.br-16px{border-radius:var(--mu-modal-radius, 16px)!important}.p-24px-28px{padding:24px 28px!important}.bb-1px-solid-E5E7EB{border-bottom:1px solid var(--cc-sf-input-disabled-border, #E5E7EB)!important}.fs-1-25rem{font-size:1.25rem!important}.p-48px-24px{padding:48px 24px!important}.b-3px-solid-E2E8F0{border:3px solid #E2E8F0!important}.p-16px-24px{padding:16px 24px!important}.p-28px{padding:28px!important}.b-3px-solid-transparent{border:3px solid transparent!important}.b-rgba-59-130-246-0-12{background:#3b82f61f!important}.p-20px-28px{padding:20px 28px!important}.c-1A56DB{color:var(--loc-add-color, #1A56DB)!important}.b-1px-dashed-D1D5DB{border:1px dashed var(--cc-sf-input-disabled-border, #D1D5DB)!important}.fs-40px{font-size:40px!important}.c-9CA3AF{color:var(--loc-tba-icon-color, #9CA3AF)!important}.form-field{font-family:var(--cc-sf-font-family, \"Poppins\", sans-serif)!important}:host{--cc-sf-input-border: var(--field-input-border, #D1D5DB);--cc-sf-input-bg: var(--field-input-bg, #ffffff);--cc-sf-input-radius: var(--field-input-radius, 8px);--cc-sf-input-height: var(--field-input-height, 42px);--cc-sf-label-color: var(--field-label-color, #202124);--cc-sf-hint-color: var(--field-hint-color, #6B7280);--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-input-focus-border: #3B82F6;--cc-sf-input-hover-border: #9CA3AF;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-border: #E5E7EB;--cc-sf-switch-track-on: var(--cc-sf-selected-color, #F05A28);--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-thumb: #ffffff;--cc-sf-selected-color: var(--primary-color, #F05A28)}.form-row{gap:var(--cc-sf-grid-gap, 16px)}.form-row.horizontal{display:flex;flex-direction:row}.form-row.horizontal>*{flex:1}.form-row:not(.horizontal){flex-direction:column}.form-row.grid-row{display:grid;grid-template-columns:repeat(12,1fr);gap:var(--cc-sf-grid-gap, 16px);align-items:start}@media(max-width:640px){.form-row.grid-row{grid-template-columns:1fr}.form-row.grid-row .row-field{grid-column:span 12!important}}.field-label{font-weight:var(--cc-sf-label-weight, 500);line-height:var(--cc-sf-label-line-height, 100%);letter-spacing:var(--cc-sf-label-letter-spacing, 0%)}.field-input,input.matInput,.mat-mdc-input-element{display:block;width:100%;height:var(--cc-sf-input-height)!important;padding:0 16px!important;font-family:inherit;font-size:.875rem;color:var(--cc-sf-label-color);background-color:var(--cc-sf-input-bg)!important;border:1px solid var(--cc-sf-input-border)!important;border-radius:var(--cc-sf-input-radius)!important;box-sizing:border-box;box-shadow:none!important;transition:all .2s ease}.field-input::placeholder,input.matInput::placeholder,.mat-mdc-input-element::placeholder{font-weight:400;font-size:14px;color:var(--cc-sf-input-placeholder)}.field-input{opacity:var(--cc-sf-input-opacity, 1);line-height:var(--cc-sf-input-line-height, 1.5);transition:var(--cc-sf-input-transition, all .2s ease)}.field-input::placeholder{font-weight:var(--cc-sf-placeholder-weight, 400);font-size:var(--cc-sf-placeholder-size, 14px);line-height:var(--cc-sf-placeholder-line-height, 100%);color:var(--cc-sf-input-placeholder)}.field-input:hover:not(:disabled):not([readonly]){border-color:var(--cc-sf-input-hover-border)!important}.field-input:focus{outline:none;border-color:var(--cc-sf-input-focus-border)!important;box-shadow:var(--cc-sf-input-focus-shadow, 0 0 0 3px rgba(59, 130, 246, .12))!important}.field-input:disabled,.field-input[readonly]{background-color:var(--cc-sf-input-disabled-bg)!important;color:var(--cc-sf-input-disabled-color, #6B7280)!important;cursor:not-allowed;border-color:var(--cc-sf-input-disabled-border)!important}.field-input.is-invalid{border-color:var(--cc-sf-error-border)!important;background-color:var(--cc-sf-error-bg)!important}.field-input.is-invalid:focus{box-shadow:var(--cc-sf-error-focus-shadow, 0 0 0 3px rgba(220, 38, 38, .1))!important}.field-input.textarea{resize:vertical;min-height:100px;height:auto;padding:12px 16px!important}input[type=time].time-input{cursor:pointer}input[type=time].time-input::-webkit-calendar-picker-indicator{cursor:pointer;opacity:.7;filter:invert(30%)}input[type=time].time-input::-webkit-calendar-picker-indicator:hover{opacity:1}select.field-input{appearance:none;background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3E%3Cpath stroke='%236B7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3E%3C/svg%3E\");background-position:right .5rem center;background-repeat:no-repeat;background-size:1.5em 1.5em;padding-right:2.5rem;cursor:pointer}select.field-input:disabled{cursor:not-allowed}.char-count-hint{font-style:normal;line-height:100%;letter-spacing:.02em}.radio-group.layout-column,.checkbox-group.layout-column{display:grid!important;grid-template-columns:repeat(12,1fr);gap:16px;width:100%}.radio-group.layout-row,.checkbox-group.layout-row{flex-direction:column!important;gap:12px;width:100%}.radio-label input,.checkbox-label input{cursor:pointer;accent-color:var(--cc-sf-chip-selected-bg, #F05A28)}.radio-label.card-item,.checkbox-label.card-item{display:flex!important;flex-direction:row-reverse!important;justify-content:space-between!important;align-items:center!important;border:1px solid #E5E7EB;border-radius:12px;padding:16px 20px;box-sizing:border-box;transition:all .2s ease;background:#fff;margin-bottom:0}.radio-label.card-item input,.checkbox-label.card-item input{margin-left:16px}.radio-label.card-item.selected,.checkbox-label.card-item.selected{border-color:var(--cc-sf-selected-color);background-color:#f05a280d}.radio-label.card-item .option-content .label-text,.checkbox-label.card-item .option-content .label-text,.checkbox-single .checkbox-label{font-weight:var(--cc-sf-label-weight, 500)}.chip-label{transition:var(--cc-sf-input-transition, all .2s ease)}.chip-label:hover{background:var(--cc-sf-chip-hover-bg, #F3F4F6)}.chip-label.selected{background:var(--cc-sf-selected-color);color:var(--cc-sf-chip-selected-color, #ffffff);border-color:var(--cc-sf-selected-color)}.switch{width:50px;height:24px;display:inline-block}.switch input{opacity:0;width:0;height:0;position:absolute}.switch input:checked+.slider{background-color:var(--cc-sf-switch-track-on)!important}.switch input:checked+.slider:before{transform:translate(26px)}.switch .slider{inset:0;transition:.4s;background-color:var(--cc-sf-switch-track-off);border-radius:24px}.switch .slider:before{position:absolute;content:\"\";height:18px;width:18px;left:3px;bottom:3px;background-color:var(--cc-sf-switch-thumb);transition:.4s;border-radius:50%}.rating-group .star{transition:var(--cc-sf-input-transition, all .2s ease)}.rating-group .star mat-icon{font-size:var(--cc-sf-star-size, 28px);width:var(--cc-sf-star-size, 28px);height:var(--cc-sf-star-size, 28px);line-height:var(--cc-sf-star-size, 28px);color:var(--cc-sf-star-empty, #D1D5DB);transition:var(--cc-sf-input-transition, all .2s ease)}.rating-group .star.filled mat-icon,.rating-group .star.half mat-icon{color:var(--cc-sf-star-filled, #F59E0B)}.rating-group .star:hover mat-icon{color:var(--cc-sf-star-filled, #F59E0B)}.password-wrapper .password-toggle{right:.625rem;top:50%;transform:translateY(-50%);line-height:1;transition:color var(--cc-sf-input-transition, .2s ease)}.password-wrapper .password-toggle mat-icon.eye-icon{font-size:1.125rem;width:1.125rem;height:1.125rem;line-height:1.125rem}.password-wrapper .password-toggle:hover{color:var(--cc-sf-label-color, #374151)}.password-wrapper .password-toggle:focus{outline:none}.group-section-wrapper{box-shadow:var(--cc-sf-section-shadow, 0 1px 4px rgba(0, 0, 0, .05))}.group-section-wrapper .group-label{font-weight:var(--cc-sf-section-label-weight, 600)}.group-section-wrapper .group-fields.sf-grid{display:grid;grid-template-columns:repeat(12,1fr);gap:var(--cc-sf-grid-gap, 16px);align-items:start}@media(max-width:640px){.group-section-wrapper .group-fields.sf-grid{grid-template-columns:1fr}.group-section-wrapper .group-fields.sf-grid .sf-col{grid-column:span 12!important}}.group-section-wrapper .group-instance:last-child{margin-bottom:0}.group-section-wrapper.multi-save-active{border:none;box-shadow:none;padding:0;background:transparent}.group-section-wrapper.multi-save-active .multi-save-header .btn-add-multi ::ng-deep button{color:var(--ms-btn-add-color, #3B82F6);font-weight:600;font-size:.875rem;padding:8px 12px}.group-section-wrapper.multi-save-active .multi-save-header .btn-add-multi ::ng-deep button:hover{color:var(--ms-btn-add-hover, #2563EB);background-color:var(--cc-sf-btn-add-hover-bg, #EFF6FF)}.group-section-wrapper.multi-save-active .group-instance{box-shadow:var(--ms-card-shadow, 0 1px 4px rgba(0, 0, 0, .05))}.group-section-wrapper.multi-save-active .group-instance.is-editing{padding:24px}.group-section-wrapper.multi-save-active .group-instance.is-card{cursor:pointer;transition:all .2s ease-in-out}.group-section-wrapper.multi-save-active .group-instance.is-card:hover{box-shadow:var(--ms-card-shadow-hover, 0 8px 24px rgba(0, 0, 0, .08));border-color:var(--cc-sf-input-focus-border, #3B82F6)}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view .card-content .card-title{white-space:nowrap;text-overflow:ellipsis}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view .card-content .card-desc{line-height:1.4;display:-webkit-box;-webkit-line-clamp:1;line-clamp:1;-webkit-box-orient:vertical}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view.is-expanded .card-content .card-desc{-webkit-line-clamp:unset;line-clamp:unset}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view .card-actions mat-icon{font-size:22px;width:22px;height:22px;color:var(--cc-sf-hint-color, #9CA3AF);transition:color .2s}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view .card-actions mat-icon.icon-delete:hover{color:var(--cc-sf-error-border, #DC2626)}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view .card-actions mat-icon.icon-edit:hover{color:var(--cc-sf-input-focus-border, #3B82F6)}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view .card-actions mat-icon.icon-expand{color:var(--cc-sf-input-disabled-border, #E5E7EB)}.btn-remove{transition:var(--cc-sf-btn-transition, all .2s ease)}.btn-remove mat-icon{font-size:1rem;width:1rem;height:1rem;line-height:1rem}.btn-remove:hover{background:var(--cc-sf-btn-remove-hover-bg, #FED7D7)}.btn-add-group{font-weight:var(--cc-sf-btn-font-weight, 600);transition:var(--cc-sf-btn-transition, all .2s ease)}.btn-add-group mat-icon{font-size:1.1rem;width:1.1rem;height:1.1rem;line-height:1.1rem}.btn-add-group:hover{background:var(--cc-sf-btn-add-hover-bg, #EFF6FF);border-color:var(--cc-sf-btn-add-hover-border, #BFDBFE)}.upload-drop-zone{transition:background-color .2s ease,border-color .2s ease}.upload-drop-zone:hover{background-color:var(--cc-sf-dropzone-hover-bg, #EFF6FF);border-color:var(--cc-sf-dropzone-hover-border, #93C5FD)}.upload-drop-zone.drag-over{background-color:var(--cc-sf-dropzone-hover-bg, #EFF6FF);border-color:var(--cc-sf-dropzone-over-border, #3B82F6);box-shadow:var(--cc-sf-dropzone-over-shadow, 0 0 0 4px rgba(59, 130, 246, .12))}.upload-drop-zone.is-invalid{border-color:var(--cc-sf-error-border, #DC2626);background-color:var(--cc-sf-error-bg, #FEF2F2)}.upload-icon-wrap mat-icon.upload-cloud-icon{font-size:56px;width:56px;height:56px;line-height:56px;color:var(--cc-sf-dropzone-icon-color, #94A3B8)}.uploaded-item{transition:box-shadow .15s ease}.uploaded-item:hover{box-shadow:0 2px 6px #0000000f}.uploaded-item mat-icon.file-type-icon{font-size:20px;width:20px;height:20px;line-height:20px;flex-shrink:0;color:var(--cc-sf-hint-color, #64748B)}.uploaded-item .file-thumb{width:36px;height:36px;object-fit:cover;flex-shrink:0}.uploaded-item .file-info{min-width:0;gap:2px}.uploaded-item .file-info .file-name{white-space:nowrap;text-overflow:ellipsis}.uploaded-item .file-remove-btn{flex-shrink:0;transition:color .15s ease,background .15s ease}.uploaded-item .file-remove-btn mat-icon{font-size:1.1rem;width:1.1rem;height:1.1rem;line-height:1.1rem}.uploaded-item .file-remove-btn:hover{color:var(--cc-sf-uploaded-remove-hover-color, #DC2626);background:var(--cc-sf-uploaded-remove-hover-bg, #FEF2F2)}.uploaded-item.uploading{background:var(--cc-sf-uploaded-uploading-bg, #F8FAFC);border-color:var(--cc-sf-uploaded-uploading-border, #CBD5E1);opacity:.85}.upload-spinner{width:20px;height:20px;flex-shrink:0;border-top-color:var(--cc-sf-spinner-color, #3B82F6);animation:cc-spin .7s linear infinite}@keyframes cc-spin{to{transform:rotate(360deg)}}.uploading-label{font-style:italic}.input-group{align-items:stretch}.input-group .field-input{flex:1;width:auto}.input-prefix+.input-group .field-input{border-top-left-radius:0;border-bottom-left-radius:0}.input-group .field-input:has(+.input-suffix){border-top-right-radius:0;border-bottom-right-radius:0}.input-group .field-input.has-icon-right{padding-right:3rem}.input-group.readonly .field-input{cursor:default}.input-prefix,.input-suffix{display:flex!important;align-items:center;white-space:nowrap;padding:0 14px;background-color:var(--cc-sf-input-disabled-bg);border:1px solid var(--cc-sf-input-border);font-size:.875rem;color:var(--cc-sf-hint-color);-webkit-user-select:none;user-select:none}.input-prefix{border-right:none;border-top-left-radius:var(--cc-sf-input-radius, 8px);border-bottom-left-radius:var(--cc-sf-input-radius, 8px)}.input-suffix{border-left:none;border-top-right-radius:var(--cc-sf-input-radius, 8px);border-bottom-right-radius:var(--cc-sf-input-radius, 8px)}.readonly-icons{right:.875rem;top:50%;transform:translateY(-50%)}.readonly-icons mat-icon.lock-icon{font-size:1rem;width:1rem;height:1rem;line-height:1rem;opacity:.5;color:var(--cc-sf-hint-color, #6B7280)}.date-icon-wrapper{right:.5rem;top:50%;transform:translateY(-50%);pointer-events:auto}.date-icon-wrapper .mat-icon-button{width:32px;height:32px;line-height:32px}.subfields-group-wrapper .subfields-row{transition:all .2s ease}.subfields-group-wrapper .subfields-row.is-invalid .subfield-item ::ng-deep .field-input{border-color:var(--cc-sf-error-border, #DC2626);background-color:var(--cc-sf-error-bg, #FEF2F2)}.subfields-group-wrapper .subfields-row .subfield-item{min-width:0}.subfields-group-wrapper .subfields-row .subfield-item ::ng-deep .field-label{font-size:.75rem!important;margin-bottom:4px!important;font-weight:500!important;color:var(--cc-sf-hint-color, #6B7280)!important}.subfields-group-wrapper .subfields-row .subfield-separator{font-weight:700}.autocomplete-wrapper .ac-input{padding-left:40px!important}.autocomplete-wrapper .ac-search-icon{left:.75rem;width:1.1rem;height:1.1rem;line-height:1.1rem;z-index:1;transition:color var(--cc-sf-input-transition, .2s ease)}.autocomplete-wrapper .ac-clear-btn{right:.6rem;transition:color .15s ease,background .15s ease}.autocomplete-wrapper .ac-clear-btn mat-icon{font-size:1rem;width:1rem;height:1rem;line-height:1rem}.autocomplete-wrapper .ac-clear-btn:hover{color:var(--cc-sf-label-color, #374151);background:var(--cc-sf-input-disabled-bg, #F3F4F6)}.autocomplete-wrapper .ac-clear-btn:focus{outline:none}.autocomplete-wrapper:focus-within .ac-search-icon{color:var(--cc-sf-input-focus-border, #3B82F6)}.autocomplete-wrapper.is-invalid .ac-input{border-color:var(--cc-sf-error-border)!important;background-color:var(--cc-sf-error-bg)}.autocomplete-wrapper.readonly .ac-input{background-color:var(--cc-sf-input-disabled-bg);color:var(--cc-sf-input-disabled-color, #6B7280);cursor:not-allowed;border-color:var(--cc-sf-input-disabled-border)!important}.ac-no-results{font-style:italic}.mu-layout{grid-template-columns:1fr 1fr;gap:32px}@media(max-width:768px){.mu-layout{grid-template-columns:1fr}}.mu-title{font-weight:700;line-height:1.3}.mu-badge{white-space:nowrap;flex-shrink:0}.mu-description{line-height:1.6}.mu-feature-item .mu-check{width:16px;height:16px;line-height:16px;flex-shrink:0}.mu-right{min-height:260px}.mu-right-empty{min-height:250px;max-width:400px;box-shadow:0 2px 10px #0000000d;transition:box-shadow .2s ease}.mu-right-empty:hover{cursor:pointer;box-shadow:0 4px 16px #0000001a}.mu-right-empty .mu-right-empty-icon{width:52px;height:52px;line-height:52px;opacity:.3}.mu-right-empty p{margin:0;font-size:.85rem}.media-add-container{display:inline-block}.media-add-container ::ng-deep button{display:flex;align-items:center;gap:6px}.media-add-container ::ng-deep button .menu-chevron{width:18px;height:18px;line-height:18px;transition:transform .2s ease}.media-dropdown{top:calc(100% + 6px);left:0;z-index:200;min-width:240px;box-shadow:var(--mu-dropdown-shadow, 0 8px 32px rgba(0, 0, 0, .12));animation:mu-fade-in .15s ease}@keyframes mu-fade-in{0%{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:translateY(0)}}.media-dropdown-item{transition:background .15s ease}.media-dropdown-item:last-child{border-bottom:none}.media-dropdown-item:hover{background:var(--cc-sf-dropzone-hover-bg, #F0F9FF)}.media-drop-icon{width:36px;height:36px;flex-shrink:0}.media-drop-icon mat-icon{font-size:20px;width:20px;height:20px;line-height:20px}.media-drop-icon--video{background:var(--mu-icon-video-bg, #FFF0F0);color:var(--mu-icon-video-color, #EF4444)}.media-drop-icon--device{background:var(--mu-icon-device-bg, #EFF6FF);color:var(--mu-icon-device-color, #3B82F6)}.media-drop-icon--library{background:var(--mu-icon-library-bg, #F0FDF4);color:var(--mu-icon-library-color, #22C55E)}.media-drop-text{gap:2px}.youtube-input-panel{animation:mu-fade-in .18s ease}.youtube-panel-label mat-icon{font-size:18px;width:18px;height:18px;line-height:18px;color:var(--mu-icon-video-color, #EF4444)}.youtube-input-row{align-items:stretch}.media-menu-backdrop{position:fixed;inset:0;z-index:100}.media-upload-status{animation:mu-fade-in .2s ease}.media-upload-status .status-icon{width:18px;height:18px;line-height:18px}.media-carousel-main{max-width:400px;height:var(--mu-carousel-height, 250px)}.carousel-viewer{inset:0}.carousel-viewer .carousel-image{object-fit:cover}.carousel-viewer .carousel-spinner{width:36px;height:36px;border-top-color:#3b82f6;animation:cc-spin .7s linear infinite}.carousel-nav{top:50%;transform:translateY(-50%);z-index:10;width:40px;height:40px;box-shadow:0 2px 8px #0003;transition:background .2s ease,opacity .2s ease;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.carousel-nav mat-icon{font-size:22px;width:22px;height:22px;line-height:22px;color:#1e293b}.carousel-nav:hover:not(:disabled){background:#fff}.carousel-nav:disabled{opacity:.3;cursor:not-allowed}.carousel-nav--prev{left:12px}.carousel-nav--next{right:12px}.carousel-remove-btn{top:10px;right:10px;z-index:10;width:32px;height:32px;transition:background .2s ease}.carousel-remove-btn mat-icon{font-size:18px;width:18px;height:18px;line-height:18px;color:#fff}.carousel-remove-btn:hover:not(:disabled){background:#dc2626d9}.carousel-remove-btn:disabled{opacity:.4;cursor:not-allowed}.carousel-dots{bottom:10px;left:50%;transform:translate(-50%);z-index:10}.carousel-dot{width:8px;height:8px;transition:background .2s ease,transform .2s ease}.carousel-dot.active{background:#fff;transform:scale(1.3)}.media-thumbnail-strip{max-width:400px;overflow-x:auto}.media-thumbnail-strip::-webkit-scrollbar{height:4px}.media-thumbnail-strip::-webkit-scrollbar-thumb{background:var(--cc-sf-input-disabled-border, #D1D5DB);border-radius:2px}.media-thumb{flex-shrink:0;width:72px;height:52px;transition:border-color .2s ease,transform .15s ease}.media-thumb.active{border-color:var(--mu-thumb-active-border, #3B82F6);transform:scale(1.04)}.media-thumb:hover:not(.active){border-color:var(--cc-sf-input-hover-border, #9CA3AF)}.media-thumb .thumb-img{object-fit:cover}.media-thumb .thumb-yt-placeholder mat-icon{font-size:28px;width:28px;height:28px;line-height:28px}.media-thumb .thumb-uploading .thumb-spinner{width:20px;height:20px;border-top-color:#3b82f6;animation:cc-spin .7s linear infinite}.media-library-overlay{position:fixed;inset:0;z-index:999;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);animation:mu-fade-in .2s ease}.media-library-modal{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);z-index:1000;width:min(90vw,780px);max-height:85vh;box-shadow:var(--mu-modal-shadow, 0 20px 60px rgba(0, 0, 0, .2));animation:mu-modal-in .22s cubic-bezier(.34,1.56,.64,1)}@keyframes mu-modal-in{0%{opacity:0;transform:translate(-50%,-48%) scale(.95)}to{opacity:1;transform:translate(-50%,-50%) scale(1)}}.library-modal-header{flex-shrink:0}.library-modal-title{font-weight:700}.library-modal-subtitle{line-height:1.5;max-width:600px}.library-close-btn{width:32px;height:32px;transition:background .15s ease,color .15s ease}.library-close-btn mat-icon{font-size:20px;width:20px;height:20px;line-height:20px}.library-close-btn:hover{background:var(--cc-sf-input-disabled-bg, #F3F4F6);color:var(--cc-sf-label-color, #374151)}.library-loading mat-icon,.library-empty mat-icon{font-size:40px;width:40px;height:40px;line-height:40px;opacity:.5}.lib-spinner{width:36px;height:36px;border-top-color:#3b82f6;animation:cc-spin .7s linear infinite}.library-error{flex-shrink:0}.library-error mat-icon{font-size:20px;width:20px;height:20px;line-height:20px}.library-grid{grid-template-columns:repeat(5,1fr);overflow-y:auto}.library-grid::-webkit-scrollbar{width:8px}.library-grid::-webkit-scrollbar-track{background:#f1f1f1}.library-grid::-webkit-scrollbar-thumb{background:#c1c1c1;border-radius:10px;border:2px solid #F1F1F1}.library-grid-item{aspect-ratio:1/1;transition:all .3s cubic-bezier(.4,0,.2,1);box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -1px #0000000f}.library-grid-item:hover{transform:translateY(-4px) scale(1.02);box-shadow:0 20px 25px -5px #0000001a,0 10px 10px -5px #0000000a}.library-grid-item.selected{border-color:#3b82f6}.library-grid-item.selected .library-grid-img{opacity:.7}.library-grid-item:hover .library-overlay-hover{opacity:1}.library-grid-img{object-fit:cover}.library-overlay-hover{inset:0;opacity:0;transition:opacity .15s ease}.library-check{top:6px;right:6px;width:22px;height:22px;box-shadow:0 1px 4px #00000026}.library-check mat-icon{font-size:18px;width:18px;height:18px;line-height:18px}.library-modal-footer{flex-shrink:0}.library-modal-footer .library-footer-actions ::ng-deep .cc-btn-primary{background-color:#3b82f6!important;border-color:#3b82f6!important;color:#fff!important;font-weight:600;padding-left:32px;padding-right:32px}.library-modal-footer .library-footer-actions ::ng-deep .cc-btn-primary:hover{background-color:#2563eb!important}.library-modal-footer .library-footer-actions ::ng-deep .cc-btn-primary:disabled{background-color:#93c5fd!important;cursor:not-allowed}.library-modal-footer .library-footer-actions ::ng-deep .cc-btn-outline{font-weight:600;padding-left:24px;padding-right:24px;border-color:#d1d5db;color:#374151}.library-modal-footer .library-footer-actions ::ng-deep .cc-btn-outline:hover{background-color:#f9fafb}.location-subtitle{line-height:1.5}.loc-tab-btn ::ng-deep button{width:100%}.loc-tab-btn ::ng-deep button:not(.cc-btn-warning){background-color:#fff!important;color:#000!important;border:1px solid #E5E7EB}.loc-tab-btn ::ng-deep button:not(.cc-btn-warning):hover{background-color:#f3f4f6!important}.loc-venue-item{transition:box-shadow .15s ease,border-color .15s ease}.loc-venue-item:hover{box-shadow:0 2px 8px #0000000f;border-color:var(--cc-sf-input-hover-border, #9CA3AF)}.loc-venue-search-icon{width:18px;height:18px;line-height:18px;flex-shrink:0}.loc-venue-text{white-space:nowrap;text-overflow:ellipsis}.loc-action-btn{transition:background .15s ease,color .15s ease;flex-shrink:0}.loc-action-btn mat-icon{font-size:18px;width:18px;height:18px;line-height:18px}.loc-action-btn.loc-delete-btn{color:var(--loc-delete-color, #E53E3E)}.loc-action-btn.loc-delete-btn:hover{background:var(--cc-sf-error-bg, #FEF2F2)}.loc-action-btn.loc-edit-btn{color:var(--cc-sf-hint-color, #9CA3AF)}.loc-action-btn.loc-edit-btn:hover{color:var(--cc-sf-input-focus-border, #3B82F6);background:var(--cc-sf-dropzone-hover-bg, #EFF6FF)}.loc-search-icon{left:.75rem;width:1.1rem;height:1.1rem;line-height:1.1rem;z-index:1}.loc-suggestions-panel{top:calc(100% + 4px);left:0;right:0;z-index:300;box-shadow:0 8px 24px #0000001a;animation:mu-fade-in .15s ease;max-height:260px;overflow-y:auto}.loc-suggestion-item{transition:background .12s ease}.loc-suggestion-item:hover,.loc-suggestion-item:focus{background:var(--loc-suggestion-hover-bg, #F0F9FF)}.loc-suggestion-item:not(:last-child){border-bottom:1px solid var(--cc-sf-input-disabled-border, #F3F4F6)}.loc-suggestion-icon{width:18px;height:18px;line-height:18px;flex-shrink:0}.loc-suggestion-text{white-space:nowrap;text-overflow:ellipsis}.loc-add-btn{transition:opacity .15s ease}.loc-add-btn mat-icon{font-size:20px;width:20px;height:20px;line-height:20px}.loc-add-btn:hover{opacity:.8}.loc-map-container{box-shadow:0 2px 10px #0000000f}.loc-tba-panel{min-height:120px}.loc-tba-icon{width:40px;height:40px;line-height:40px;opacity:.6}.loc-tba-text{line-height:1.6;max-width:360px}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$3.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$3.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$3.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$3.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1$3.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1$3.SelectMultipleControlValueAccessor, selector: "select[multiple][formControlName],select[multiple][formControl],select[multiple][ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1$3.RadioControlValueAccessor, selector: "input[type=radio][formControlName],input[type=radio][formControl],input[type=radio][ngModel]", inputs: ["name", "formControlName", "value"] }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$3.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1$3.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { kind: "directive", type: i1$3.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$3.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1$3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i5.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: i5.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: i6.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i6.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i6.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { kind: "directive", type: i7.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i9.MatAutocomplete, selector: "mat-autocomplete", inputs: ["aria-label", "aria-labelledby", "displayWith", "autoActiveFirstOption", "autoSelectActiveOption", "requireSelection", "panelWidth", "disableRipple", "class", "hideSingleSelectionIndicator"], outputs: ["optionSelected", "opened", "closed", "optionActivated"], exportAs: ["matAutocomplete"] }, { kind: "directive", type: i9.MatAutocompleteTrigger, selector: "input[matAutocomplete], textarea[matAutocomplete]", inputs: ["matAutocomplete", "matAutocompletePosition", "matAutocompleteConnectedTo", "autocomplete", "matAutocompleteDisabled"], exportAs: ["matAutocompleteTrigger"] }, { kind: "component", type: ButtonComponent, selector: "lib-button", inputs: ["variant", "type", "disabled", "width", "height", "borderRadius", "fontSize", "fontWeight", "backgroundColor", "color", "border", "icon", "labels"] }, { kind: "component", type: i11.QuillEditorComponent, selector: "quill-editor" }, { kind: "component", type: FormFieldComponent, selector: "lib-form-field", inputs: ["config", "controller", "formGroup", "allowMulti"] }, { kind: "pipe", type: TrustedUrlPipe, name: "trustedUrl" }] });
|
|
2227
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: FormFieldComponent, isStandalone: false, selector: "lib-form-field", inputs: { config: "config", controller: "controller", formGroup: "formGroup", allowMulti: "allowMulti" }, viewQueries: [{ propertyName: "mediaDeviceInput", first: true, predicate: ["mediaDeviceInput"], descendants: true }], ngImport: i0, template: "<div class=\"form-field mb-16px\" *ngIf=\"isVisible\" [class.has-error]=\"errorMessage\">\r\n\r\n <!-- \u2550\u2550 ROW Layout \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isRow\" class=\"form-row grid-row\">\r\n <ng-container *ngFor=\"let child of config.children\">\r\n <div class=\"row-field\" [style.gridColumn]=\"'span ' + getChildColSpan(child)\" *ngIf=\"child.isEnabled !== false\">\r\n <lib-form-field [config]=\"child\" [controller]=\"controller\" [formGroup]=\"formGroup\" [allowMulti]=\"allowMulti\">\r\n </lib-form-field>\r\n </div>\r\n </ng-container>\r\n </div>\r\n\r\n <!-- \u2550\u2550 GROUP \u2014 allowMulti (repeater) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isGroup && config.sectionConfig?.allowMulti\"\r\n class=\"group-section-wrapper mb-20px\"\r\n [class.multi-save-active]=\"config.sectionConfig?.multiSaveConfig?.active\">\r\n\r\n <!-- Multi-Save: header row with label + top-right Add button -->\r\n <div class=\"multi-save-header d-flex justify-content-between align-items-center mb-24\"\r\n *ngIf=\"config.sectionConfig?.multiSaveConfig?.active\">\r\n <h3 class=\"group-label\" *ngIf=\"config.sectionConfig?.label\">{{ config.sectionConfig!.label }}</h3>\r\n <lib-button [variant]=\"'outline'\" [icon]=\"{type: 'material', value: 'add'}\" (click)=\"addGroupInstance()\"\r\n class=\"btn-add-multi\">\r\n {{ addMultiLabel }}\r\n </lib-button>\r\n </div>\r\n\r\n <!-- Standard heading (non-multiSave) -->\r\n <h3 class=\"group-label\"\r\n *ngIf=\"config.sectionConfig?.label && !config.sectionConfig?.multiSaveConfig?.active\">{{\r\n config.sectionConfig!.label }}</h3>\r\n\r\n <!-- \u2500\u2500 Standard (non-multiSave) repeater: accordion instances \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <ng-container *ngIf=\"!config.sectionConfig?.multiSaveConfig?.active\">\r\n <div *ngFor=\"let instance of instanceList; trackBy: trackByInstanceId; let i = index\"\r\n class=\"group-accordion-instance\"\r\n [class.is-expanded]=\"isGroupExpanded(i)\">\r\n\r\n <!-- Accordion header -->\r\n <div class=\"group-accordion-header\" (click)=\"toggleGroupAccordion(i)\"\r\n role=\"button\" [attr.aria-expanded]=\"isGroupExpanded(i)\">\r\n <div class=\"accordion-header-left d-flex align-items-center gap-10\">\r\n <span class=\"instance-badge\">{{ i + 1 }}</span>\r\n <span class=\"instance-title\">{{ config.sectionConfig!.label }} #{{ i + 1 }}</span>\r\n </div>\r\n <div class=\"accordion-header-right d-flex align-items-center gap-6\">\r\n <button type=\"button\" class=\"accordion-remove-btn\"\r\n *ngIf=\"instanceList.length > 1\"\r\n (click)=\"$event.stopPropagation(); removeGroupInstance(i)\"\r\n aria-label=\"Remove\">\r\n <mat-icon>delete_outline</mat-icon>\r\n </button>\r\n <mat-icon class=\"accordion-chevron\">\r\n {{ isGroupExpanded(i) ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}\r\n </mat-icon>\r\n </div>\r\n </div>\r\n\r\n <!-- Accordion body -->\r\n <div class=\"group-accordion-body\" *ngIf=\"isGroupExpanded(i)\">\r\n <div class=\"group-fields sf-grid\">\r\n <ng-container *ngFor=\"let field of config.sectionConfig!.children\">\r\n <div class=\"sf-col\" [style.gridColumn]=\"'span ' + (field.colSpan || 12)\"\r\n *ngIf=\"field.isEnabled !== false\">\r\n <lib-form-field [config]=\"field\" [controller]=\"controller\" [formGroup]=\"instance.fg\"\r\n [allowMulti]=\"true\">\r\n </lib-form-field>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Full-width dashed Add button -->\r\n <button type=\"button\" class=\"btn-add-group\" (click)=\"addGroupInstance()\">\r\n <mat-icon>add</mat-icon> {{ addLabel }} {{ config.sectionConfig!.label }}\r\n </button>\r\n </ng-container>\r\n\r\n <!-- \u2500\u2500 MultiSave: card instances \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <ng-container *ngIf=\"config.sectionConfig?.multiSaveConfig?.active\">\r\n <div *ngFor=\"let instance of instanceList; trackBy: trackByInstanceId; let i = index\"\r\n class=\"group-instance position-relative mb-16 overflow-hidden\"\r\n [class.is-editing]=\"instance.isEditing\"\r\n [class.is-card]=\"!instance.isEditing\">\r\n\r\n <!-- Edit / new form view -->\r\n <div [hidden]=\"!instance.isEditing\">\r\n <div class=\"group-fields sf-grid p-24\">\r\n <ng-container *ngFor=\"let field of config.sectionConfig!.children\">\r\n <div class=\"sf-col\" [style.gridColumn]=\"'span ' + (field.colSpan || 12)\"\r\n *ngIf=\"field.isEnabled !== false\">\r\n <lib-form-field [config]=\"field\" [controller]=\"controller\" [formGroup]=\"instance.fg\"\r\n [allowMulti]=\"true\">\r\n </lib-form-field>\r\n </div>\r\n </ng-container>\r\n </div>\r\n\r\n <!-- Save / Cancel -->\r\n <div\r\n class=\"group-footer d-flex justify-content-between align-items-center gap-16 mt-24 pt-20 bt-1px-solid-E5E7EB p-0-24\"\r\n *ngIf=\"config.sectionConfig?.multiSaveConfig?.active\">\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"multiSaveError\">{{ multiSaveError }}</span>\r\n <div class=\"footer-actions d-flex gap-12\">\r\n <lib-button [variant]=\"'outline'\" (click)=\"cancelGroupInstance(i)\">Cancel</lib-button>\r\n <lib-button [variant]=\"'primary'\" (click)=\"saveGroupInstance(i)\">Save</lib-button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Card view (saved state) -->\r\n <ng-container *ngIf=\"!instance.isEditing\">\r\n <div class=\"card-view d-flex justify-content-between align-items-center p-18px-24px\"\r\n [class.is-expanded]=\"instance.isExpanded\">\r\n <div class=\"card-content flex-1 d-flex flex-column gap-4 overflow-hidden\">\r\n <span class=\"card-title font-weight-600 overflow-hidden fs-1rem c-111827\">{{\r\n instance.fg.get(config.sectionConfig!.multiSaveConfig!.summaryField || '')?.value\r\n || '\u2014' }}</span>\r\n </div>\r\n <div class=\"card-actions d-flex align-items-center gap-16 ml-20\">\r\n <mat-icon class=\"icon-delete\" (click)=\"removeGroupInstance(i, true)\">delete_outline</mat-icon>\r\n <mat-icon class=\"icon-edit\" (click)=\"editGroupInstance(i)\">edit_outline</mat-icon>\r\n <mat-icon class=\"icon-expand\" (click)=\"toggleExpandGroupInstance(i)\">\r\n {{ instance.isExpanded ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}\r\n </mat-icon>\r\n </div>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </ng-container>\r\n </div>\r\n\r\n <!-- \u2550\u2550 GROUP \u2014 single (non-repeater) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isGroup && config.sectionConfig && !config.sectionConfig.allowMulti\"\r\n class=\"group-section-wrapper mb-20px\">\r\n <h3 class=\"group-label\" *ngIf=\"config.sectionConfig.label\">{{ config.sectionConfig.label }}</h3>\r\n <div class=\"group-fields sf-grid\">\r\n <ng-container *ngFor=\"let field of config.sectionConfig.children\">\r\n <div class=\"sf-col\" [style.gridColumn]=\"'span ' + (field.colSpan || 12)\" *ngIf=\"field.isEnabled !== false\">\r\n <lib-form-field [config]=\"field\" [controller]=\"controller\" [formGroup]=\"groupFormGroup\" [allowMulti]=\"false\">\r\n </lib-form-field>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </div>\r\n\r\n\r\n <!-- \u2550\u2550 Text Input \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isTextField\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <textarea *ngIf=\"config.subType === 'LONG'\" class=\"field-input textarea\" [placeholder]=\"config.placeholder || ''\"\r\n [formControlName]=\"config.name!\" [class.is-invalid]=\"errorMessage\" rows=\"4\">\r\n </textarea>\r\n\r\n <!-- Password input with show/hide toggle -->\r\n <div *ngIf=\"config.subType === 'PASSWORD'\" class=\"password-wrapper position-relative d-flex align-items-center\">\r\n <input [type]=\"showPassword ? 'text' : 'password'\" class=\"field-input password-input\"\r\n [placeholder]=\"config.placeholder || ''\" [formControlName]=\"config.name!\" [class.is-invalid]=\"errorMessage\">\r\n <button type=\"button\"\r\n class=\"password-toggle position-absolute cursor-pointer d-flex align-items-center justify-content-center b-none border-none c-6B7280 p-0-25rem\"\r\n (click)=\"showPassword = !showPassword\" tabindex=\"-1\"\r\n [attr.aria-label]=\"showPassword ? 'Hide password' : 'Show password'\">\r\n <mat-icon class=\"eye-icon\">{{ showPassword ? 'visibility' : 'visibility_off' }}</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <div class=\"input-group position-relative d-flex w-100\" [class.readonly]=\"config.readonly\">\r\n <span class=\"input-prefix br-none\" *ngIf=\"config.prefix\">{{ config.prefix }}</span>\r\n\r\n <input *ngIf=\"config.subType !== 'LONG' && config.subType !== 'PASSWORD'\"\r\n [type]=\"config.subType === 'EMAIL' ? 'email' : config.subType === 'PHONE' ? 'tel' : 'text'\" class=\"field-input\"\r\n [placeholder]=\"config.placeholder || ''\" [formControlName]=\"config.name!\" [class.is-invalid]=\"errorMessage\"\r\n [readonly]=\"config.readonly\">\r\n\r\n <span class=\"input-suffix d-flex align-items-center font-weight-500\" *ngIf=\"config.suffix\">{{ config.suffix\r\n }}</span>\r\n\r\n <div class=\"readonly-icons position-absolute d-flex gap-8 pe-none\" *ngIf=\"config.readonly\">\r\n <mat-icon class=\"lock-icon\">lock</mat-icon>\r\n </div>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n <div class=\"char-count-hint font-poppins font-weight-400 text-14 text-right mt-4 c-6B7280\" *ngIf=\"showCharCount\">\r\n {{ remainingCharacters }} characters remaining\r\n </div>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Number Input \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isNumberField\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"input-group position-relative d-flex w-100\" [class.readonly]=\"config.readonly\">\r\n <span class=\"input-prefix br-none\" *ngIf=\"config.prefix\">{{ config.prefix }}</span>\r\n\r\n <input type=\"number\" class=\"field-input\" [placeholder]=\"config.placeholder || ''\" [formControlName]=\"config.name!\"\r\n [min]=\"config.numberConfig?.min ?? null\" [max]=\"config.numberConfig?.max ?? null\"\r\n [step]=\"config.numberConfig?.step || 1\" [class.is-invalid]=\"errorMessage\" [readonly]=\"config.readonly\">\r\n\r\n <span class=\"input-suffix d-flex align-items-center font-weight-500\" *ngIf=\"config.suffix\">{{ config.suffix\r\n }}</span>\r\n\r\n <div class=\"readonly-icons position-absolute d-flex gap-8 pe-none\" *ngIf=\"config.readonly\">\r\n <mat-icon class=\"lock-icon\">lock</mat-icon>\r\n </div>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Date Input \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isDateField\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"input-group position-relative d-flex w-100\" [class.readonly]=\"config.readonly\">\r\n <input matInput [matDatepicker]=\"datePicker\" class=\"field-input date-input has-icon-right\"\r\n [formControlName]=\"config.name!\" [min]=\"config.dateConfig?.minDate\" [max]=\"config.dateConfig?.maxDate\"\r\n [class.is-invalid]=\"errorMessage\" [placeholder]=\"config.placeholder || ''\" [readonly]=\"config.readonly\"\r\n (click)=\"!config.readonly && datePicker.open()\">\r\n <div class=\"date-icon-wrapper position-absolute d-flex align-items-center justify-content-center\"\r\n *ngIf=\"!config.readonly\">\r\n <mat-datepicker-toggle matSuffix [for]=\"datePicker\"></mat-datepicker-toggle>\r\n </div>\r\n <mat-datepicker #datePicker></mat-datepicker>\r\n\r\n <div class=\"readonly-icons position-absolute d-flex gap-8 pe-none\" *ngIf=\"config.readonly\">\r\n <mat-icon class=\"lock-icon\">lock</mat-icon>\r\n </div>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Time Input \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isTimeField\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"input-group position-relative d-flex w-100\" [class.readonly]=\"config.readonly\">\r\n <input type=\"time\" class=\"field-input time-input\" [formControlName]=\"config.name!\"\r\n [class.is-invalid]=\"errorMessage\" [readonly]=\"!!config.readonly\">\r\n\r\n <div class=\"readonly-icons position-absolute d-flex gap-8 pe-none\" *ngIf=\"config.readonly\">\r\n <mat-icon class=\"lock-icon\">lock</mat-icon>\r\n </div>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Autocomplete \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isAutocomplete\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <!-- Hidden real control (stores the code value) -->\r\n <input type=\"hidden\" [formControlName]=\"config.name!\">\r\n\r\n <div class=\"autocomplete-wrapper position-relative d-flex align-items-center w-100\"\r\n [class.is-invalid]=\"errorMessage\" [class.readonly]=\"config.readonly\">\r\n <!-- Search icon -->\r\n <mat-icon class=\"ac-search-icon position-absolute fs-1-1rem c-9CA3AF pe-none\">search</mat-icon>\r\n\r\n <input class=\"field-input ac-input\" [formControl]=\"autocompleteInputCtrl\" [matAutocomplete]=\"auto\"\r\n [placeholder]=\"config.placeholder || 'Search\u2026'\" [readonly]=\"!!config.readonly\" [class.is-invalid]=\"errorMessage\"\r\n (blur)=\"onAutocompleteClear()\" autocomplete=\"off\">\r\n\r\n <!-- Clear button -->\r\n <button type=\"button\"\r\n class=\"ac-clear-btn position-absolute d-flex align-items-center justify-content-center cursor-pointer rounded-50 b-none border-none c-9CA3AF p-0-2rem\"\r\n *ngIf=\"autocompleteInputCtrl.value && !config.readonly\"\r\n (click)=\"autocompleteInputCtrl.setValue(''); updateValue(null)\" tabindex=\"-1\" aria-label=\"Clear\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n\r\n <mat-autocomplete #auto=\"matAutocomplete\" [panelWidth]=\"'auto'\">\r\n <mat-option *ngFor=\"let option of filteredOptions\" [value]=\"option.label\"\r\n (onSelectionChange)=\"onAutocompleteSelected(option)\">\r\n {{ option.label }}\r\n </mat-option>\r\n <mat-option *ngIf=\"filteredOptions.length === 0\" disabled class=\"ac-no-results fs-0-8125rem c-6B7280\">\r\n No results found\r\n </mat-option>\r\n </mat-autocomplete>\r\n\r\n <div class=\"readonly-icons position-absolute d-flex gap-8 pe-none\" *ngIf=\"config.readonly\">\r\n <mat-icon class=\"lock-icon\">lock</mat-icon>\r\n </div>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Dropdown \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isDropdown\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <select *ngIf=\"config.subType === 'SINGLE'\" class=\"field-input\" [formControlName]=\"config.name!\"\r\n [class.is-invalid]=\"errorMessage\">\r\n <option [ngValue]=\"null\" disabled selected>{{ config.placeholder || 'Select' }}</option>\r\n <option *ngFor=\"let option of config.optionConfig?.optionList\" [value]=\"option.code\">\r\n {{ option.label }}\r\n </option>\r\n </select>\r\n\r\n <select *ngIf=\"config.subType === 'MULTIPLE'\" class=\"field-input\" multiple [formControlName]=\"config.name!\"\r\n [class.is-invalid]=\"errorMessage\">\r\n <option *ngFor=\"let option of config.optionConfig?.optionList\" [value]=\"option.code\">\r\n {{ option.label }}\r\n </option>\r\n </select>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Radio \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isRadio\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"radio-group\" [class.is-invalid]=\"errorMessage\"\r\n [class]=\"config.optionConfig?.layout ? 'layout-' + config.optionConfig!.layout.toLowerCase() : ''\">\r\n <label *ngFor=\"let option of config.optionConfig?.optionList\" class=\"radio-label\"\r\n [class.card-item]=\"config.subType === 'CARD'\"\r\n [class.selected]=\"formGroup.get(config.name!)?.value === option.code\"\r\n [style.gridColumn]=\"config.optionConfig?.layout?.toUpperCase() === 'COLUMN' ? 'span ' + getOptionColSpan(option) : null\">\r\n <input type=\"radio\" [formControlName]=\"config.name!\" [value]=\"option.code\">\r\n <div class=\"option-content d-flex flex-column gap-4 flex-1 text-left\">\r\n <span class=\"label-text text-16 c-1F2937\">{{ option.label }}</span>\r\n <span class=\"option-hint text-13 color-gray\" *ngIf=\"option.hint\">{{ option.hint }}</span>\r\n </div>\r\n </label>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Checkbox \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isCheckbox\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label && config.subType === 'LIST'\"\r\n class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div *ngIf=\"config.subType === 'BOOL'\" class=\"checkbox-single\">\r\n <label class=\"checkbox-label d-flex align-items-center gap-8 cursor-pointer fs-0-875rem c-111827\">\r\n <input type=\"checkbox\" [formControlName]=\"config.name!\" [class.is-invalid]=\"errorMessage\">\r\n <span>{{ config.label }}</span>\r\n </label>\r\n </div>\r\n\r\n <div *ngIf=\"config.subType === 'LIST' || config.subType === 'CARD'\" class=\"checkbox-group d-flex flex-column gap-8\"\r\n [class.is-invalid]=\"errorMessage\"\r\n [class]=\"config.optionConfig?.layout ? 'layout-' + config.optionConfig!.layout.toLowerCase() : ''\">\r\n <label *ngFor=\"let option of config.optionConfig?.optionList\"\r\n class=\"checkbox-label d-flex align-items-center gap-8 cursor-pointer fs-0-875rem c-111827\"\r\n [class.card-item]=\"config.subType === 'CARD'\" [class.selected]=\"isChecked(option.code)\"\r\n [style.gridColumn]=\"config.optionConfig?.layout?.toUpperCase() === 'COLUMN' ? 'span ' + getOptionColSpan(option) : null\">\r\n <input type=\"checkbox\" [checked]=\"isChecked(option.code)\" [disabled]=\"!!config.disabled\"\r\n (change)=\"onCheckboxListChange(option.code, $any($event.target).checked)\">\r\n <div class=\"option-content d-flex flex-column gap-4 flex-1 text-left\">\r\n <span class=\"label-text text-16 c-1F2937\">{{ option.label }}</span>\r\n <span class=\"option-hint text-13 color-gray\" *ngIf=\"option.hint\">{{ option.hint }}</span>\r\n </div>\r\n </label>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Chip \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isChip\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"chip-group d-flex flex-wrap gap-8\" [class.is-invalid]=\"errorMessage\">\r\n <label *ngFor=\"let option of config.optionConfig?.optionList\"\r\n class=\"chip-label cursor-pointer p-6px-14px b-ffffff c-374151 b-1px-solid-D1D5DB br-20px fs-0-875rem\"\r\n [class.selected]=\"isChecked(option.code)\">\r\n <input type=\"checkbox\" [checked]=\"isChecked(option.code)\" [disabled]=\"!!config.disabled\"\r\n (change)=\"onCheckboxListChange(option.code, $any($event.target).checked)\" hidden>\r\n <span>{{ option.label }}</span>\r\n </label>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Switch \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isSwitch\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label class=\"switch-container d-flex justify-content-between align-items-center cursor-pointer\">\r\n <span class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">{{ config.label }}</span>\r\n <div class=\"switch position-relative\">\r\n <input type=\"checkbox\" [formControlName]=\"config.name!\" [class.is-invalid]=\"errorMessage\">\r\n <span class=\"slider position-absolute cursor-pointer\"></span>\r\n </div>\r\n </label>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Rich Text \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isRichText\" class=\"field-wrapper component-rich-text d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"rich-text-container\" [class.is-invalid]=\"errorMessage\">\r\n <quill-editor [formControlName]=\"config.name!\" class=\"rich-text-editor d-block w-100\"\r\n [placeholder]=\"config.richTextConfig?.placeholder || config.placeholder || ''\"\r\n [styles]=\"{height: config.richTextConfig?.height || '200px'}\">\r\n </quill-editor>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n <div class=\"char-count-hint font-poppins font-weight-400 text-14 text-right mt-4 c-6B7280\" *ngIf=\"showCharCount\">\r\n {{ remainingCharacters }} characters remaining\r\n </div>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Rating \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isRating\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"rating-group d-flex gap-4\" [class.is-invalid]=\"errorMessage\">\r\n <span *ngFor=\"let star of getStarArray()\" class=\"star d-inline-flex align-items-center cursor-pointer\"\r\n [class.filled]=\"isStarFilled(star)\" [class.half]=\"isStarHalf(star)\" (click)=\"onRatingChange(star, $event)\">\r\n <mat-icon>{{ isStarFilled(star) || isStarHalf(star) ? 'star' : 'star_border' }}</mat-icon>\r\n </span>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Generated Field (read-only) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isGenerated\" class=\"field-wrapper d-flex flex-column gap-6\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">{{ config.label\r\n }}</label>\r\n <div class=\"generated-value fs-0-875rem p-0-625rem-0-875rem b-F3F4F6 b-1px-solid-E5E7EB br-8px c-6B7280\">{{ value ||\r\n '-' }}</div>\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint\">{{ config.hint }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 File Upload \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isFileUpload\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <!-- Drop Zone -->\r\n <div\r\n class=\"upload-drop-zone d-flex flex-column align-items-center justify-content-center gap-8 cursor-pointer text-center p-32px-24px us-none\"\r\n [class.drag-over]=\"isDragOver\" [class.has-files]=\"value?.length\" [class.is-invalid]=\"errorMessage\"\r\n (dragover)=\"onDragOver($event)\" (dragleave)=\"onDragLeave($event)\" (drop)=\"onFileDrop($event)\"\r\n (click)=\"fileInput.click()\">\r\n\r\n <!-- Icon with accent-colour pill background -->\r\n <div class=\"upload-icon-wrap mb-4\">\r\n <div class=\"dropzone-icon-pill d-flex align-items-center justify-content-center\">\r\n <mat-icon class=\"upload-cloud-icon\">cloud_upload</mat-icon>\r\n </div>\r\n </div>\r\n\r\n <p class=\"upload-main-text font-weight-600 m-0 fs-0-9rem\">Drag & drop files here</p>\r\n <p class=\"upload-sub-text m-0 fs-0-8rem c-64748B\">or <span class=\"upload-link\">Browse files</span></p>\r\n <p class=\"upload-hint-text m-0 fs-0-78rem c-64748B\" *ngIf=\"config.attachmentConfig?.acceptLabel\">\r\n Supported: <span class=\"upload-formats font-weight-500\">{{ config.attachmentConfig!.acceptLabel }}</span>\r\n </p>\r\n <p class=\"upload-hint-text m-0 fs-0-78rem c-64748B\" *ngIf=\"!config.attachmentConfig?.acceptLabel && config.hint\">\r\n {{ config.hint }}\r\n </p>\r\n <span class=\"upload-size-badge fs-0-72rem\" *ngIf=\"config.attachmentConfig?.maxSizeMB\">\r\n Max {{ config.attachmentConfig!.maxSizeMB }}MB\r\n </span>\r\n\r\n <!-- Hidden native file input -->\r\n <input #fileInput type=\"file\" hidden [attr.multiple]=\"config.attachmentConfig?.multiple ? true : null\"\r\n [attr.accept]=\"config.attachmentConfig?.accept || null\" (change)=\"onFileSelected($event)\">\r\n </div>\r\n\r\n <!-- Uploaded file list -->\r\n <div class=\"uploaded-list d-flex flex-column gap-8 mt-10\" *ngIf=\"value?.length\">\r\n <div *ngFor=\"let f of value; let i = index\"\r\n class=\"uploaded-item d-flex align-items-center gap-10 p-10px-14px br-8px\"\r\n [class.uploading]=\"f.isUploading\">\r\n\r\n <!-- Uploading spinner -->\r\n <ng-container *ngIf=\"f.isUploading; else fileReady\">\r\n <div class=\"upload-spinner rounded-50 b-2px-solid-E2E8F0\"></div>\r\n <div class=\"file-info flex-1 d-flex flex-column\">\r\n <span class=\"file-name font-weight-500 overflow-hidden fs-0-85rem\" [title]=\"f.name\">{{ f.name }}</span>\r\n <span class=\"file-size uploading-label fs-0-72rem\">Uploading...</span>\r\n </div>\r\n </ng-container>\r\n\r\n <!-- Normal state once upload is done -->\r\n <ng-template #fileReady>\r\n <mat-icon class=\"file-type-icon\">{{ getFileIcon(f.type) }}</mat-icon>\r\n <img *ngIf=\"f.type?.startsWith('image') && f.dataUrl\" [src]=\"f.dataUrl\" class=\"file-thumb rounded-4\"\r\n alt=\"preview\">\r\n <div class=\"file-info flex-1 d-flex flex-column\">\r\n <span class=\"file-name font-weight-500 overflow-hidden fs-0-85rem\" [title]=\"f.name\">{{ f.name }}</span>\r\n <span class=\"file-size fs-0-72rem\">{{ formatFileSize(f.size) }}</span>\r\n </div>\r\n </ng-template>\r\n\r\n <!-- Compact icon-only remove button -->\r\n <button type=\"button\" class=\"file-remove-btn d-flex align-items-center justify-content-center rounded-50\"\r\n [disabled]=\"f.isUploading\" (click)=\"!f.isUploading && removeUploadedFile(i)\"\r\n aria-label=\"Remove file\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- Validation / file errors -->\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"fileUploadError\">{{ fileUploadError }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage && !fileUploadError\">{{ errorMessage }}</span>\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\"\r\n *ngIf=\"config.hint && !errorMessage && !fileUploadError && !config.attachmentConfig?.acceptLabel\">\r\n {{ config.hint }}\r\n </span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Media Upload (Type 2) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isMediaUpload\" class=\"field-wrapper media-upload-wrapper d-flex flex-column gap-6 p-0 border-none b-none\"\r\n [formGroup]=\"formGroup\">\r\n\r\n <!-- Hidden file input lives outside *ngIf \u2014 triggered via ViewChild -->\r\n <input #mediaDeviceInput type=\"file\" hidden multiple accept=\"image/*\" (change)=\"onMediaFileSelected($event)\">\r\n\r\n <!-- Two-column layout -->\r\n <div class=\"mu-layout d-grid align-items-start\">\r\n\r\n <!-- \u2500\u2500 LEFT PANEL \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <div class=\"mu-left d-flex flex-column gap-20\">\r\n\r\n <!-- Header: title + max-items badge -->\r\n <div class=\"mu-header d-flex align-items-start flex-wrap gap-10\">\r\n <h3 class=\"mu-title m-0 c-111827 fs-1-35rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </h3>\r\n <span\r\n class=\"mu-badge d-inline-flex align-items-center rounded-20 color-white font-weight-600 fs-0-72rem p-4px-12px b-111827\"\r\n *ngIf=\"config.attachmentConfig?.maxFiles\">\r\n {{ controller.labels['LBL_MEDIA_MAX_PREFIX'] || 'Maximum' }}\r\n {{ config.attachmentConfig?.maxFiles }}\r\n {{ controller.labels['LBL_MEDIA_MAX_SUFFIX'] || 'Image & Videos' }}\r\n </span>\r\n </div>\r\n\r\n <!-- Description -->\r\n <p class=\"mu-description m-0 fs-0-875rem c-6B7280\" *ngIf=\"config.attachmentConfig?.description\">\r\n {{ config.attachmentConfig?.description }}\r\n </p>\r\n <p class=\"mu-description m-0 fs-0-875rem c-6B7280\"\r\n *ngIf=\"!config.attachmentConfig?.description && controller.labels['LBL_MEDIA_DESC']\">\r\n {{ controller.labels['LBL_MEDIA_DESC'] }}\r\n </p>\r\n\r\n <!-- Feature bullet list -->\r\n <ul class=\"mu-features m-0 p-0 d-flex flex-column gap-8 ls-none\"\r\n *ngIf=\"config.attachmentConfig?.features?.length || controller.labels['LBL_MEDIA_FEATURE_1']\">\r\n <ng-container *ngIf=\"config.attachmentConfig?.features?.length\">\r\n <li *ngFor=\"let f of config.attachmentConfig?.features\"\r\n class=\"mu-feature-item d-flex align-items-center gap-8 fs-0-875rem c-374151\">\r\n <mat-icon class=\"mu-check text-16 c-3B82F6\">check</mat-icon>{{ f }}\r\n </li>\r\n </ng-container>\r\n <ng-container *ngIf=\"!config.attachmentConfig?.features?.length\">\r\n <li *ngIf=\"controller.labels['LBL_MEDIA_FEATURE_1']\"\r\n class=\"mu-feature-item d-flex align-items-center gap-8 fs-0-875rem c-374151\">\r\n <mat-icon class=\"mu-check text-16 c-3B82F6\">check</mat-icon>{{ controller.labels['LBL_MEDIA_FEATURE_1'] }}\r\n </li>\r\n <li *ngIf=\"controller.labels['LBL_MEDIA_FEATURE_2']\"\r\n class=\"mu-feature-item d-flex align-items-center gap-8 fs-0-875rem c-374151\">\r\n <mat-icon class=\"mu-check text-16 c-3B82F6\">check</mat-icon>{{ controller.labels['LBL_MEDIA_FEATURE_2'] }}\r\n </li>\r\n <li *ngIf=\"controller.labels['LBL_MEDIA_FEATURE_3']\"\r\n class=\"mu-feature-item d-flex align-items-center gap-8 fs-0-875rem c-374151\">\r\n <mat-icon class=\"mu-check text-16 c-3B82F6\">check</mat-icon>{{ controller.labels['LBL_MEDIA_FEATURE_3'] }}\r\n </li>\r\n </ng-container>\r\n </ul>\r\n\r\n <!-- Backdrop to close dropdown on outside click -->\r\n <div class=\"media-menu-backdrop\" *ngIf=\"showMediaMenu\"\r\n (click)=\"$event.stopPropagation(); showMediaMenu = false\"></div>\r\n\r\n <!-- Add Media button + dropdown -->\r\n <div class=\"media-add-container position-relative\" (click)=\"showMediaMenu = !showMediaMenu\">\r\n <lib-button id=\"btn-add-media-{{ config.name }}\" [variant]=\"'warning'\"\r\n [icon]=\"{type: 'material', value: 'add_photo_alternate'}\">\r\n {{ controller.labels['LBL_ADD_MEDIA'] || 'Add media' }}\r\n <mat-icon class=\"menu-chevron fs-18px\">add</mat-icon>\r\n </lib-button>\r\n\r\n <div class=\"media-dropdown position-absolute rounded-12 overflow-hidden b-ffffff b-1px-solid-E5E7EB\"\r\n *ngIf=\"showMediaMenu\" role=\"menu\" (click)=\"$event.stopPropagation()\">\r\n <!-- Video -->\r\n <button id=\"btn-media-video-{{ config.name }}\" type=\"button\"\r\n class=\"media-dropdown-item d-flex align-items-center gap-12 w-100 cursor-pointer text-left b-none border-none p-12px-16px bb-1px-solid-F3F4F6\"\r\n (click)=\"onMediaMenuVideo(); showMediaMenu = false\" role=\"menuitem\">\r\n <span\r\n class=\"media-drop-icon media-drop-icon--video d-flex align-items-center justify-content-center rounded-8\"><mat-icon>videocam</mat-icon></span>\r\n <span class=\"media-drop-text d-flex flex-column flex-1\">\r\n <span class=\"media-drop-label font-weight-600 fs-0-875rem c-111827\">{{\r\n controller.labels['LBL_MEDIA_VIDEO'] || 'Video' }}</span>\r\n <span class=\"media-drop-desc c-6B7280 fs-0-75rem\">{{ controller.labels['LBL_MEDIA_VIDEO_DESC'] || 'Add\r\n YouTube URL'\r\n }}</span>\r\n </span>\r\n </button>\r\n <!-- Device -->\r\n <button id=\"btn-media-device-{{ config.name }}\" type=\"button\"\r\n class=\"media-dropdown-item d-flex align-items-center gap-12 w-100 cursor-pointer text-left b-none border-none p-12px-16px bb-1px-solid-F3F4F6\"\r\n (click)=\"onMediaMenuDevice(); showMediaMenu = false\" role=\"menuitem\">\r\n <span\r\n class=\"media-drop-icon media-drop-icon--device d-flex align-items-center justify-content-center rounded-8\"><mat-icon>upload</mat-icon></span>\r\n <span class=\"media-drop-text d-flex flex-column flex-1\">\r\n <span class=\"media-drop-label font-weight-600 fs-0-875rem c-111827\">{{\r\n controller.labels['LBL_MEDIA_DEVICE'] || 'Upload from device'\r\n }}</span>\r\n <span class=\"media-drop-desc c-6B7280 fs-0-75rem\">{{ controller.labels['LBL_MEDIA_DEVICE_DESC'] ||\r\n 'Select images from your\r\n computer' }}</span>\r\n </span>\r\n </button>\r\n <!-- Library -->\r\n <button id=\"btn-media-library-{{ config.name }}\" type=\"button\"\r\n class=\"media-dropdown-item d-flex align-items-center gap-12 w-100 cursor-pointer text-left b-none border-none p-12px-16px bb-1px-solid-F3F4F6\"\r\n (click)=\"onMediaMenuLibrary(); showMediaMenu = false\" role=\"menuitem\">\r\n <span\r\n class=\"media-drop-icon media-drop-icon--library d-flex align-items-center justify-content-center rounded-8\"><mat-icon>photo_library</mat-icon></span>\r\n <span class=\"media-drop-text d-flex flex-column flex-1\">\r\n <span class=\"media-drop-label font-weight-600 fs-0-875rem c-111827\">{{\r\n controller.labels['LBL_MEDIA_LIBRARY'] || 'Upload from library'\r\n }}</span>\r\n <span class=\"media-drop-desc c-6B7280 fs-0-75rem\">{{ controller.labels['LBL_MEDIA_LIBRARY_DESC'] ||\r\n 'Choose from default\r\n images' }}</span>\r\n </span>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- YouTube URL Input (inline below button) -->\r\n <div class=\"youtube-input-panel d-flex flex-column gap-8 p-16 rounded-10 b-FFFAF1 b-1px-solid-E5E7EB\"\r\n *ngIf=\"showYoutubeInput\">\r\n <label class=\"youtube-panel-label d-flex align-items-center gap-6 font-weight-600 fs-0-875rem c-111827\">\r\n {{ controller.labels['LBL_YOUTUBE_URL'] || 'Video URL' }}\r\n </label>\r\n <div class=\"youtube-input-row d-flex gap-8\">\r\n <input id=\"input-youtube-url-{{ config.name }}\" type=\"url\" class=\"field-input youtube-url-input\"\r\n [(ngModel)]=\"youtubeUrlInput\" [ngModelOptions]=\"{standalone: true}\"\r\n [placeholder]=\"controller.labels['PH_YOUTUBE_URL'] || 'Video URL'\" (keyup.enter)=\"addYoutubeMedia()\">\r\n <lib-button id=\"btn-add-youtube-{{ config.name }}\" [variant]=\"'secondary'\" (click)=\"addYoutubeMedia()\">\r\n {{ controller.labels['LBL_ADD'] || 'Add' }}\r\n </lib-button>\r\n </div>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"youtubeUrlError\">{{ youtubeUrlError }}</span>\r\n </div>\r\n\r\n <div\r\n class=\"media-upload-status d-flex align-items-center gap-8 mt-4 color-error rounded-8 font-weight-500 p-10px-14px b-FEF2F2 fs-0-85rem\"\r\n *ngIf=\"mediaUploadError\">\r\n <mat-icon class=\"status-icon fs-18px\">error_outline</mat-icon>\r\n <span>{{ mediaUploadError }}</span>\r\n </div>\r\n\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n </div>\r\n <!-- end left panel -->\r\n\r\n <!-- \u2500\u2500 RIGHT PANEL (carousel) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <div class=\"mu-right d-flex flex-column gap-12\">\r\n\r\n <!-- Carousel (when items exist) -->\r\n <div class=\"media-carousel-section d-flex flex-column gap-12\" *ngIf=\"mediaItems.length\">\r\n <div\r\n class=\"media-carousel-main position-relative w-100 overflow-hidden d-flex align-items-center justify-content-center br-12px b-0F172A\">\r\n <button id=\"btn-carousel-prev-{{ config.name }}\" type=\"button\"\r\n class=\"carousel-nav carousel-nav--prev position-absolute rounded-50 cursor-pointer d-flex align-items-center justify-content-center border-none b-rgba-255-255-255-0-85\"\r\n (click)=\"mediaCarouselPrev()\" [disabled]=\"mediaCarouselIndex === 0\" aria-label=\"Previous\">\r\n <mat-icon>chevron_left</mat-icon>\r\n </button>\r\n\r\n <div class=\"carousel-viewer position-absolute d-flex align-items-center justify-content-center\"\r\n *ngFor=\"let item of mediaItems; let i = index\" [hidden]=\"i !== mediaCarouselIndex\">\r\n <div *ngIf=\"item.isUploading\"\r\n class=\"carousel-uploading d-flex flex-column align-items-center gap-12 c-94A3B8 fs-0-85rem\">\r\n <div class=\"carousel-spinner rounded-50 b-3px-solid-rgba-255-255-255-0-15\"></div>\r\n <span>{{ controller.labels['LBL_UPLOADING'] || 'Uploading\u2026' }}</span>\r\n </div>\r\n <ng-container *ngIf=\"!item.isUploading && item.mediaType === 'youtube'\">\r\n <iframe class=\"carousel-iframe w-100 h-100 br-12px\" [src]=\"item.url | trustedUrl\" frameborder=\"0\"\r\n allowfullscreen\r\n allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\">\r\n </iframe>\r\n </ng-container>\r\n <ng-container *ngIf=\"!item.isUploading && item.mediaType === 'image'\">\r\n <img class=\"carousel-image w-100 h-100 br-12px\" [src]=\"item.url\" alt=\"Media\">\r\n </ng-container>\r\n <button id=\"btn-remove-media-{{ config.name }}-{{ i }}\" type=\"button\"\r\n class=\"carousel-remove-btn position-absolute rounded-50 cursor-pointer d-flex align-items-center justify-content-center border-none b-rgba-0-0-0-0-55\"\r\n [disabled]=\"item.isUploading\" (click)=\"removeMediaItem(i)\" aria-label=\"Remove\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <button id=\"btn-carousel-next-{{ config.name }}\" type=\"button\"\r\n class=\"carousel-nav carousel-nav--next position-absolute rounded-50 cursor-pointer d-flex align-items-center justify-content-center border-none b-rgba-255-255-255-0-85\"\r\n (click)=\"mediaCarouselNext()\" [disabled]=\"mediaCarouselIndex === mediaItems.length - 1\" aria-label=\"Next\">\r\n <mat-icon>chevron_right</mat-icon>\r\n </button>\r\n\r\n <div class=\"carousel-dots position-absolute d-flex gap-6\">\r\n <span *ngFor=\"let item of mediaItems; let i = index\"\r\n class=\"carousel-dot rounded-50 cursor-pointer b-rgba-255-255-255-0-45\"\r\n [class.active]=\"i === mediaCarouselIndex\" (click)=\"mediaGoTo(i)\"></span>\r\n </div>\r\n </div>\r\n\r\n <!-- Thumbnail strip -->\r\n <div class=\"media-thumbnail-strip d-flex flex-wrap gap-8 pb-4px\">\r\n <div *ngFor=\"let item of mediaThumbnails; let i = index\"\r\n class=\"media-thumb rounded-8 overflow-hidden cursor-pointer d-flex align-items-center justify-content-center b-2px-solid-transparent b-E2E8F0\"\r\n [class.active]=\"i === mediaCarouselIndex\" (click)=\"mediaGoTo(i)\">\r\n <div *ngIf=\"item.isUploading\"\r\n class=\"thumb-uploading d-flex align-items-center justify-content-center w-100 h-100\">\r\n <div class=\"thumb-spinner rounded-50 b-2px-solid-E2E8F0\"></div>\r\n </div>\r\n <img *ngIf=\"!item.isUploading && item.mediaType === 'youtube' && item.thumbnailUrl\"\r\n [src]=\"item.thumbnailUrl\" class=\"thumb-img w-100 h-100\" alt=\"Video thumbnail\">\r\n <div *ngIf=\"!item.isUploading && item.mediaType === 'youtube' && !item.thumbnailUrl\"\r\n class=\"thumb-yt-placeholder d-flex align-items-center justify-content-center w-100 h-100 b-1E293B c-EF4444\">\r\n <mat-icon>play_circle</mat-icon>\r\n </div>\r\n <img *ngIf=\"!item.isUploading && item.mediaType === 'image' && item.url\" [src]=\"item.url\"\r\n class=\"thumb-img w-100 h-100\" alt=\"Image thumbnail\">\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Empty right-side placeholder -->\r\n <div\r\n class=\"mu-right-empty d-flex flex-column align-items-center justify-content-center gap-10 h-100 text-center p-24 br-12px b-FFFAF1 c-94A3B8 b-2px-dashed-CBD5E1\"\r\n *ngIf=\"!mediaItems.length\" (click)=\"onMediaMenuDevice()\">\r\n <mat-icon class=\"mu-right-empty-icon fs-52px\">perm_media</mat-icon>\r\n <p>{{ controller.labels['LBL_ADD_MEDIA'] || 'Add media' }}</p>\r\n </div>\r\n\r\n </div>\r\n <!-- end right panel -->\r\n\r\n </div><!-- end mu-layout -->\r\n </div>\r\n\r\n\r\n <!-- \u2550\u2550 Library Image Picker Modal \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div class=\"media-library-overlay b-rgba-0-0-0-0-5\" *ngIf=\"showLibraryModal\" (click)=\"closeLibraryModal()\"></div>\r\n <div class=\"media-library-modal d-flex flex-column overflow-hidden b-ffffff br-16px\" *ngIf=\"showLibraryModal\"\r\n role=\"dialog\" aria-modal=\"true\">\r\n <div class=\"library-modal-header d-flex align-items-start justify-content-between p-24px-28px bb-1px-solid-E5E7EB\">\r\n <div class=\"header-left d-flex flex-column gap-8\">\r\n <h3 class=\"library-modal-title m-0 color-dark fs-1-25rem\">\r\n {{ controller.labels['LBL_ADD_IMAGES'] || 'Add Images' }}\r\n </h3>\r\n <p class=\"library-modal-subtitle m-0 color-gray fs-0-85rem\">\r\n {{ controller.labels['LBL_LIBRARY_MODAL_DESC'] || 'Upload media to make your opportunity stand out. Plus, take\r\n full control of your sequence - drag images to reorder as you desire.' }}\r\n </p>\r\n </div>\r\n <button id=\"btn-close-library-{{ config.name }}\" type=\"button\"\r\n class=\"library-close-btn d-flex align-items-center justify-content-center cursor-pointer rounded-50 border-none b-none c-9CA3AF\"\r\n (click)=\"closeLibraryModal()\" aria-label=\"Close\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <!-- Loading -->\r\n <div class=\"library-loading\" *ngIf=\"libraryLoading\">\r\n <div class=\"lib-spinner rounded-50 b-3px-solid-E2E8F0\"></div>\r\n <span>{{ controller.labels['LBL_LOADING'] || 'Loading\u2026' }}</span>\r\n </div>\r\n\r\n <!-- Error -->\r\n <div class=\"library-error d-flex align-items-center gap-8 color-error b-FEF2F2 fs-0-875rem p-16px-24px\"\r\n *ngIf=\"libraryError && !libraryLoading\">\r\n <mat-icon>error_outline</mat-icon>\r\n {{ libraryError }}\r\n </div>\r\n\r\n <!-- Image grid -->\r\n <div class=\"library-grid d-grid gap-16 flex-1 p-28px b-F9FAFB\" *ngIf=\"!libraryLoading && libraryImages.length\">\r\n <div *ngFor=\"let img of libraryImages; let li = index\" id=\"lib-img-{{ config.name }}-{{ li }}\"\r\n class=\"library-grid-item position-relative rounded-12 overflow-hidden cursor-pointer bg-white b-3px-solid-transparent\"\r\n [class.selected]=\"isLibraryItemSelected(img)\" (click)=\"toggleLibraryItem(img)\">\r\n <img [src]=\"getLibraryItemUrl(img)\" class=\"library-grid-img w-100 h-100 d-block\" alt=\"Library image\">\r\n <div\r\n class=\"library-check position-absolute bg-white rounded-50 d-flex align-items-center justify-content-center c-3B82F6\"\r\n *ngIf=\"isLibraryItemSelected(img)\">\r\n <mat-icon>check_circle</mat-icon>\r\n </div>\r\n <div class=\"library-overlay-hover position-absolute b-rgba-59-130-246-0-12\"></div>\r\n </div>\r\n </div>\r\n\r\n <!-- Empty library -->\r\n <div\r\n class=\"library-empty d-flex flex-column align-items-center justify-content-center gap-12 flex-1 c-9CA3AF fs-0-875rem p-48px-24px\"\r\n *ngIf=\"!libraryLoading && !libraryError && libraryImages.length === 0\">\r\n <mat-icon>image_not_supported</mat-icon>\r\n <span>{{ controller.labels['LBL_LIBRARY_EMPTY'] || 'No images found in library.' }}</span>\r\n </div>\r\n\r\n <!-- Footer -->\r\n <div\r\n class=\"library-modal-footer d-flex align-items-center justify-content-end bg-white p-20px-28px bt-1px-solid-E5E7EB\">\r\n <div class=\"library-footer-actions d-flex gap-12 gap-10\">\r\n <lib-button id=\"btn-library-cancel-{{ config.name }}\" [variant]=\"'outline'\" (click)=\"closeLibraryModal()\">\r\n {{ controller.labels['LBL_CANCEL'] || 'Cancel' }}\r\n </lib-button>\r\n <lib-button id=\"btn-library-confirm-{{ config.name }}\" [variant]=\"'primary'\"\r\n [disabled]=\"librarySelectedIds.size === 0\" (click)=\"confirmLibrarySelection()\">\r\n {{ controller.labels['LBL_CONTINUE'] || 'Continue' }}\r\n </lib-button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Location Field \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isLocation\" class=\"field-wrapper location-field-wrapper d-flex flex-column gap-6 gap-12\"\r\n [formGroup]=\"formGroup\">\r\n\r\n <!-- Field label -->\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n <p class=\"location-subtitle m-0 c-6B7280 fs-0-8125rem\" *ngIf=\"config.hint\">{{ config.hint }}</p>\r\n\r\n <!-- Three-tab bar -->\r\n <div class=\"location-tabs d-flex gap-12 mb-24\">\r\n <lib-button class=\"loc-tab-btn flex-1\" [variant]=\"locationActiveTab === 'VENUE' ? 'warning' : 'outline'\"\r\n (click)=\"onLocationTabChange('VENUE')\">\r\n {{ controller.labels['LBL_LOC_VENUE'] || 'Venue' }}\r\n </lib-button>\r\n <lib-button class=\"loc-tab-btn flex-1\" [variant]=\"locationActiveTab === 'ONLINE' ? 'warning' : 'outline'\"\r\n (click)=\"onLocationTabChange('ONLINE')\">\r\n {{ controller.labels['LBL_LOC_ONLINE'] || 'Online Event' }}\r\n </lib-button>\r\n <lib-button class=\"loc-tab-btn flex-1\" [variant]=\"locationActiveTab === 'TBA' ? 'warning' : 'outline'\"\r\n (click)=\"onLocationTabChange('TBA')\">\r\n {{ controller.labels['LBL_LOC_TBA'] || 'To be Announced' }}\r\n </lib-button>\r\n </div>\r\n\r\n <!-- VENUE TAB -->\r\n <div *ngIf=\"locationActiveTab === 'VENUE'\" class=\"loc-panel loc-venue-panel d-flex flex-column gap-12\">\r\n\r\n <p class=\"loc-section-label m-0 font-weight-600 c-111827 fs-0-9rem\">\r\n {{ controller.labels['LBL_LOC_ADDRESS'] || 'Location address' }}\r\n </p>\r\n\r\n <!-- Added venue rows -->\r\n <div class=\"loc-venue-list d-flex flex-column gap-8\" *ngIf=\"locationVenues.length > 0\">\r\n <div *ngFor=\"let venue of locationVenues; let i = index\"\r\n class=\"loc-venue-item d-flex align-items-center gap-10 p-10px-14px br-7px b-ffffff b-1px-solid-D1D5DB\">\r\n <mat-icon class=\"loc-venue-search-icon fs-18px c-9CA3AF\">search</mat-icon>\r\n <span class=\"loc-venue-text flex-1 overflow-hidden fs-0-875rem c-111827\">{{ venue.address || venue.name ||\r\n venue.description }}</span>\r\n <button type=\"button\"\r\n class=\"loc-action-btn loc-delete-btn d-flex align-items-center justify-content-center cursor-pointer rounded-50 b-none border-none p-4px\"\r\n (click)=\"removeLocationVenue(i)\">\r\n <mat-icon>delete_outline</mat-icon>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- Location count badge -->\r\n <p class=\"loc-count-text m-0 font-weight-600 fs-0-8125rem c-3B82F6\"\r\n *ngIf=\"locationVenues.length > 0 && config.locationConfig?.allowMulti\">\r\n {{ locationVenues.length }} {{ controller.labels['LBL_LOC_COUNT_SUFFIX'] || 'Locations Added!' }}\r\n </p>\r\n\r\n <!-- Search input (hide when max reached) -->\r\n <div class=\"loc-search-container position-relative\" *ngIf=\"!locationMaxReached\">\r\n <div class=\"loc-search-wrapper position-relative d-flex align-items-center mt-4\">\r\n <mat-icon class=\"loc-search-icon position-absolute fs-1-1rem c-9CA3AF pe-none\">search</mat-icon>\r\n <input\r\n class=\"field-input loc-search-input w-100 font-poppins flex-1 fs-0-875rem c-111827 br-7px br-8px bc-F3F4F6 pl-2-4rem bc-DC2626 pt-0-625rem pb-0-625rem pl-16px pr-16px bc-ffffff b-1px-solid-D1D5DB pr-3-5rem\"\r\n [placeholder]=\"config.locationConfig?.venuePlaceholder || (controller.labels['PH_LOC_VENUE'] || 'Type to search venue...')\"\r\n [value]=\"locationSearchText\" (input)=\"handleLocationSearchInput($event)\" (blur)=\"hideLocationSuggestions()\"\r\n autocomplete=\"off\" [class.is-invalid]=\"errorMessage\">\r\n </div>\r\n <!-- Suggestions dropdown -->\r\n <div class=\"loc-suggestions-panel position-absolute overflow-hidden br-8px b-ffffff b-1px-solid-D1D5DB\"\r\n *ngIf=\"locationShowSuggestions && locationSuggestions.length\">\r\n <div *ngFor=\"let sug of locationSuggestions\"\r\n class=\"loc-suggestion-item d-flex align-items-center gap-10 cursor-pointer p-10px-14px\"\r\n (mousedown)=\"onLocationSuggestionSelect(sug)\">\r\n <mat-icon class=\"loc-suggestion-icon fs-18px c-E53E3E\">place</mat-icon>\r\n <span class=\"loc-suggestion-text overflow-hidden fs-0-875rem c-374151\">{{ sug.description }}</span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Add another button -->\r\n <button type=\"button\"\r\n class=\"loc-add-btn d-inline-flex align-items-center gap-6 cursor-pointer font-weight-600 p-0 b-none border-none fs-0-875rem c-1A56DB\"\r\n *ngIf=\"locationVenues.length > 0 && !locationMaxReached && config.locationConfig?.allowMulti\">\r\n <mat-icon>add_circle_outline</mat-icon>\r\n <span>{{ controller.labels['LBL_LOC_ADD_ANOTHER'] || 'Add another Location' }}</span>\r\n </button>\r\n\r\n <!-- Map -->\r\n <div class=\"loc-map-container overflow-hidden br-10px b-1px-solid-E5E7EB\"\r\n *ngIf=\"config.locationConfig?.showMap !== false\">\r\n <ng-container *ngIf=\"config.locationConfig?.googleMapsApiKey; else simpleEmbed\">\r\n <div [id]=\"'loc-map-' + config.name\" class=\"loc-map-frame w-100 d-block border-none\"\r\n [style.height]=\"config.locationConfig?.mapHeight || '300px'\"></div>\r\n </ng-container>\r\n <ng-template #simpleEmbed>\r\n <iframe class=\"loc-map-frame w-100 d-block border-none\"\r\n [style.height]=\"config.locationConfig?.mapHeight || '300px'\" [src]=\"getLocationMapEmbedUrl() | trustedUrl\"\r\n frameborder=\"0\" allowfullscreen loading=\"lazy\">\r\n </iframe>\r\n </ng-template>\r\n </div>\r\n\r\n <!-- Map hint -->\r\n <p class=\"loc-map-hint m-0 text-center fs-0-78rem c-6B7280\">\r\n {{ controller.labels['LBL_LOC_MAP_HINT'] || 'Type the venue address. A map will appear to assist you.' }}\r\n </p>\r\n </div>\r\n\r\n <!-- ONLINE TAB -->\r\n <div *ngIf=\"locationActiveTab === 'ONLINE'\" class=\"loc-panel loc-online-panel d-flex flex-column gap-12\">\r\n <p class=\"loc-section-label m-0 font-weight-600 c-111827 fs-0-9rem\">\r\n {{ controller.labels['LBL_LOC_ONLINE_URL'] || 'Event URL' }}\r\n </p>\r\n <div class=\"loc-search-wrapper position-relative d-flex align-items-center mt-4\">\r\n <mat-icon class=\"loc-search-icon position-absolute fs-1-1rem c-9CA3AF pe-none\">link</mat-icon>\r\n <input\r\n class=\"field-input loc-search-input w-100 font-poppins flex-1 fs-0-875rem c-111827 br-7px br-8px bc-F3F4F6 pl-2-4rem bc-DC2626 pt-0-625rem pb-0-625rem pl-16px pr-16px bc-ffffff b-1px-solid-D1D5DB pr-3-5rem\"\r\n type=\"url\"\r\n [placeholder]=\"config.locationConfig?.onlinePlaceholder || (controller.labels['PH_LOC_ONLINE'] || 'https://zoom.us/j/...')\"\r\n [value]=\"locationOnlineUrl\" (input)=\"onLocationUrlChange($any($event.target).value)\"\r\n [class.is-invalid]=\"errorMessage\">\r\n </div>\r\n </div>\r\n\r\n <!-- TBA TAB -->\r\n <div *ngIf=\"locationActiveTab === 'TBA'\"\r\n class=\"loc-panel loc-tba-panel d-flex flex-column gap-12 justify-content-center\">\r\n <div\r\n class=\"loc-tba-content d-flex flex-column align-items-center justify-content-center text-center gap-12 p-32px-24px b-F9FAFB b-1px-dashed-D1D5DB br-10px\">\r\n <mat-icon class=\"loc-tba-icon fs-40px c-9CA3AF\">schedule</mat-icon>\r\n <p class=\"loc-tba-text m-0 c-6B7280 fs-0-9rem\">\r\n {{ controller.labels['LBL_LOC_TBA_DESC'] || \"This event's location is yet to be announced. Check back later\r\n for updates.\" }}\r\n </p>\r\n </div>\r\n </div>\r\n\r\n <!-- Hidden real form control -->\r\n <input type=\"hidden\" [formControlName]=\"config.name!\">\r\n\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n</div>", styles: [".d-flex{display:flex}.d-inline-flex{display:inline-flex}.d-grid{display:grid}.d-block{display:block}.d-none{display:none}.flex-column{flex-direction:column}.flex-row{flex-direction:row}.flex-row-reverse{flex-direction:row-reverse}.flex-wrap{flex-wrap:wrap}.flex-1{flex:1}.align-items-center{align-items:center}.align-items-start{align-items:flex-start}.align-items-end{align-items:flex-end}.justify-content-center{justify-content:center}.justify-content-between{justify-content:space-between}.justify-content-start{justify-content:flex-start}.justify-content-end{justify-content:flex-end}.grid-cols-12{grid-template-columns:repeat(12,1fr)}.w-100{width:100%}.h-100{height:100%}.position-relative{position:relative}.position-absolute{position:absolute}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.font-poppins{font-family:var(--cc-sf-font-family, \"Poppins\", sans-serif)}.font-weight-400{font-weight:400}.font-weight-500{font-weight:500}.font-weight-600{font-weight:600}.text-13{font-size:13px}.text-14{font-size:14px}.text-16{font-size:16px}.color-white{color:#fff}.color-dark{color:#111827}.color-gray{color:#6b7280}.color-error{color:var(--cc-sf-error-text-color, #DC2626)}.bg-white{background-color:#fff}.bg-transparent{background-color:transparent}.m-0{margin:0}.mt-4{margin-top:4px}.mt-8{margin-top:8px}.mt-10{margin-top:10px}.mt-12{margin-top:12px}.mt-16{margin-top:16px}.mt-20{margin-top:20px}.mt-24{margin-top:24px}.mb-0{margin-bottom:0}.mb-4{margin-bottom:4px}.mb-8{margin-bottom:8px}.mb-10{margin-bottom:10px}.mb-12{margin-bottom:12px}.mb-16{margin-bottom:16px}.mb-20{margin-bottom:20px}.mb-24{margin-bottom:24px}.ml-16{margin-left:16px}.ml-20{margin-left:20px}.p-0{padding:0}.p-16{padding:16px}.p-20{padding:20px}.p-24{padding:24px}.pt-20{padding-top:20px}.pb-10{padding-bottom:10px}.gap-4{gap:4px}.gap-6{gap:6px}.gap-8{gap:8px}.gap-10{gap:10px}.gap-12{gap:12px}.gap-16{gap:16px}.gap-20{gap:20px}.rounded-4{border-radius:4px}.rounded-6{border-radius:6px}.rounded-8{border-radius:8px}.rounded-10{border-radius:10px}.rounded-12{border-radius:12px}.rounded-20{border-radius:20px}.rounded-24{border-radius:24px}.rounded-50{border-radius:50%}.cursor-pointer{cursor:pointer}.overflow-hidden{overflow:hidden}.resize-vertical{resize:vertical}.box-sizing-border{box-sizing:border-box}.border-none{border:none!important}.mb-16px{margin-bottom:var(--cc-sf-grid-gap, 16px)!important}.c-DC2626{color:var(--cc-sf-label-required-color, #DC2626)!important}.ml-0-125rem{margin-left:.125rem!important}.fs-0-875rem{font-size:.875rem!important}.c-111827{color:var(--cc-sf-label-color, #111827)!important}.br-7px{border-radius:var(--cc-sf-input-radius, 7px)!important}.c-6B7280{color:var(--cc-sf-hint-color, #6B7280)!important}.fs-0-75rem{font-size:var(--cc-sf-error-text-size, .75rem)!important}.b-none{background:none!important}.p-32px-24px{padding:32px 24px!important}.us-none{-webkit-user-select:none!important;user-select:none!important}.c-1E293B{color:var(--cc-sf-label-color, #1E293B)!important}.c-3B82F6{color:var(--cc-sf-chip-selected-bg, #3B82F6)!important}.fs-0-78rem{font-size:.78rem!important}.p-10px-14px{padding:10px 14px!important}.fs-0-85rem{font-size:.85rem!important}.fs-0-72rem{font-size:.72rem!important}.c-94A3B8{color:#94a3b8!important}.p-4px{padding:4px!important}.br-8px{border-radius:var(--cc-sf-input-radius, 8px)!important}.bc-F3F4F6{background-color:var(--cc-sf-input-disabled-bg, #F3F4F6)!important}.br-none{border-right:none!important}.bl-none{border-left:none!important}.pe-none{pointer-events:none!important}.fs-1-1rem{font-size:1.1rem!important}.c-9CA3AF{color:var(--cc-sf-hint-color, #9CA3AF)!important}.pl-2-4rem{padding-left:2.4rem!important}.fs-0-8125rem{font-size:.8125rem!important}.ls-none{list-style:none!important}.br-12px{border-radius:var(--mu-carousel-radius, 12px)!important}.b-FFFAF1{background:var(--cc-sf-dropzone-bg, #FFFAF1)!important}.fs-18px{font-size:18px!important}.b-FEF2F2{background:var(--cc-sf-error-bg, #FEF2F2)!important}.bc-DC2626{border-color:var(--cc-sf-error-border, #DC2626)!important}.c-202124{color:var(--cc-sf-label-color, #202124)!important}.fs-18px{font-size:var(--cc-sf-label-size, 18px)!important}.mb-0-5rem{margin-bottom:.5rem!important}.pt-0-625rem{padding-top:var(--cc-sf-input-padding-y, .625rem)!important}.pb-0-625rem{padding-bottom:var(--cc-sf-input-padding-y, .625rem)!important}.pl-16px{padding-left:var(--cc-sf-input-padding-x, 16px)!important}.pr-16px{padding-right:var(--cc-sf-input-padding-x, 16px)!important}.bc-ffffff{background-color:var(--cc-sf-section-bg, #ffffff)!important}.b-1px-solid-D1D5DB{border:1px solid var(--cc-sf-input-border, #D1D5DB)!important}.fs-0-75rem{font-size:.75rem!important}.c-1F2937{color:var(--cc-sf-section-label-color, #1F2937)!important}.p-6px-14px{padding:var(--cc-sf-chip-padding, 6px 14px)!important}.b-ffffff{background:var(--loc-suggestion-bg, #ffffff)!important}.c-374151{color:var(--cc-sf-label-color, #374151)!important}.br-20px{border-radius:var(--cc-sf-chip-radius, 20px)!important}.fs-0-875rem{font-size:var(--cc-sf-btn-font-size, .875rem)!important}.bc-D1D5DB{background-color:var(--cc-sf-switch-track-off, #D1D5DB)!important}.pr-2-75rem{padding-right:2.75rem!important}.p-0-25rem{padding:.25rem!important}.p-0-625rem-0-875rem{padding:var(--cc-sf-generated-padding, .625rem .875rem)!important}.b-F3F4F6{background:var(--cc-sf-generated-bg, #F3F4F6)!important}.b-1px-solid-E5E7EB{border:1px solid var(--cc-sf-input-disabled-border, #E5E7EB)!important}.br-8px{border-radius:var(--cc-sf-uploaded-item-radius, 8px)!important}.c-6B7280{color:var(--ms-desc-color, #6B7280)!important}.mb-20px{margin-bottom:var(--cc-sf-section-gap, 20px)!important}.br-10px{border-radius:var(--cc-sf-input-radius, 10px)!important}.p-20px{padding:var(--cc-sf-section-padding, 20px)!important}.fs-1rem{font-size:1rem!important}.m-0-0-16px-0{margin:0 0 16px!important}.bb-2px-solid-E5E7EB{border-bottom:var(--cc-sf-section-label-border, 2px solid #E5E7EB)!important}.p-16px{padding:var(--cc-sf-instance-padding, 16px)!important}.b-F9FAFB{background:var(--loc-tba-bg, #F9FAFB)!important}.bb-1px-dashed-D1D5DB{border-bottom:var(--cc-sf-instance-divider, 1px dashed #D1D5DB)!important}.c-4B5563{color:var(--cc-sf-instance-num-color, #4B5563)!important}.fs-0-8125rem{font-size:var(--cc-sf-hint-size, .8125rem)!important}.pb-0{padding-bottom:0!important}.p-18px-24px{padding:18px 24px!important}.c-111827{color:var(--ms-title-color, #111827)!important}.bt-1px-solid-E5E7EB{border-top:1px solid #E5E7EB!important}.p-4px-10px{padding:4px 10px!important}.b-FFF5F5{background:var(--cc-sf-btn-remove-bg, #FFF5F5)!important}.c-E53E3E{color:var(--loc-delete-color, #E53E3E)!important}.b-1px-solid-FED7D7{border:var(--cc-sf-btn-remove-border, 1px solid #FED7D7)!important}.br-4px{border-radius:var(--cc-sf-btn-remove-radius, 4px)!important}.p-8px-16px{padding:8px 16px!important}.b-transparent{background:var(--cc-sf-btn-add-bg, transparent)!important}.c-3B82F6{color:var(--cc-sf-input-focus-border, #3B82F6)!important}.b-1px-dashed-CBD5E1{border:var(--cc-sf-btn-add-border, 1px dashed #CBD5E1)!important}.br-6px{border-radius:var(--cc-sf-btn-add-radius, 6px)!important}.b-1-5px-dashed-CBD5E1{border:var(--cc-sf-dropzone-border, 1.5px dashed #CBD5E1)!important}.br-12px{border-radius:var(--cc-sf-dropzone-radius, 12px)!important}.bc-FFFAF1{background-color:var(--cc-sf-dropzone-bg, #FFFAF1)!important}.c-94A3B8{color:var(--cc-sf-uploaded-remove-color, #94A3B8)!important}.fs-0-9rem{font-size:var(--cc-sf-input-font-size, .9rem)!important}.c-64748B{color:var(--cc-sf-dropzone-hint-color, #64748B)!important}.b-1px-solid-E2E8F0{border:var(--cc-sf-uploaded-item-border, 1px solid #E2E8F0)!important}.b-2px-solid-E2E8F0{border:2px solid #E2E8F0!important}.pr-3-5rem{padding-right:3.5rem!important}.p-0-0-875rem{padding:0 .875rem!important}.bc-FFFFFF{background-color:var(--cc-sf-input-bg, #FFFFFF)!important}.b-1-5px-solid-D1D5DB{border:var(--cc-sf-input-border, 1.5px solid #D1D5DB)!important}.mb-0-75rem{margin-bottom:.75rem!important}.mt-6px{margin-top:6px!important}.pr-2-4rem{padding-right:2.4rem!important}.p-0-2rem{padding:.2rem!important}.fs-1-35rem{font-size:1.35rem!important}.p-4px-12px{padding:4px 12px!important}.b-111827{background:var(--cc-sf-label-color, #111827)!important}.b-2px-dashed-CBD5E1{border:2px dashed var(--cc-sf-dropzone-border, #CBD5E1)!important}.fs-52px{font-size:52px!important}.p-12px-16px{padding:12px 16px!important}.bb-1px-solid-F3F4F6{border-bottom:1px solid var(--cc-sf-input-disabled-border, #F3F4F6)!important}.b-0F172A{background:var(--mu-carousel-bg, #0F172A)!important}.b-3px-solid-rgba-255-255-255-0-15{border:3px solid rgba(255,255,255,.15)!important}.b-rgba-255-255-255-0-85{background:#ffffffd9!important}.b-rgba-0-0-0-0-55{background:#0000008c!important}.b-rgba-255-255-255-0-45{background:#ffffff73!important}.pb-4px{padding-bottom:4px!important}.b-2px-solid-transparent{border:2px solid transparent!important}.b-E2E8F0{background:var(--mu-thumb-bg, #E2E8F0)!important}.b-1E293B{background:#1e293b!important}.c-EF4444{color:#ef4444!important}.b-rgba-0-0-0-0-5{background:#00000080!important}.br-16px{border-radius:var(--mu-modal-radius, 16px)!important}.p-24px-28px{padding:24px 28px!important}.bb-1px-solid-E5E7EB{border-bottom:1px solid var(--cc-sf-input-disabled-border, #E5E7EB)!important}.fs-1-25rem{font-size:1.25rem!important}.p-48px-24px{padding:48px 24px!important}.b-3px-solid-E2E8F0{border:3px solid #E2E8F0!important}.p-16px-24px{padding:16px 24px!important}.p-28px{padding:28px!important}.b-3px-solid-transparent{border:3px solid transparent!important}.b-rgba-59-130-246-0-12{background:#3b82f61f!important}.p-20px-28px{padding:20px 28px!important}.c-1A56DB{color:var(--loc-add-color, #1A56DB)!important}.b-1px-dashed-D1D5DB{border:1px dashed var(--cc-sf-input-disabled-border, #D1D5DB)!important}.fs-40px{font-size:40px!important}.c-9CA3AF{color:var(--loc-tba-icon-color, #9CA3AF)!important}.form-field{font-family:var(--cc-sf-font-family, \"Poppins\", sans-serif)!important}:host{--cc-sf-input-border: #D1D5DB;--cc-sf-input-bg: #ffffff;--cc-sf-input-radius: 9px;--cc-sf-input-height: 44px;--cc-sf-label-color: #111827;--cc-sf-hint-color: #9CA3AF;--cc-sf-error-border: #EF4444;--cc-sf-error-bg: #FFF5F5;--cc-sf-accent-color: #6366F1;--cc-sf-input-focus-border: #6366F1;--cc-sf-input-hover-border: #A5B4FC;--cc-sf-input-placeholder: #C4C9D4;--cc-sf-input-disabled-bg: #F8F9FB;--cc-sf-input-disabled-border: #E5E7EB;--cc-sf-switch-track-on: #6366F1;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-thumb: #ffffff;--cc-sf-selected-color: #6366F1}.form-row{gap:var(--cc-sf-grid-gap, 16px)}.form-row.horizontal{display:flex;flex-direction:row}.form-row.horizontal>*{flex:1}.form-row:not(.horizontal){flex-direction:column}.form-row.grid-row{display:grid;grid-template-columns:repeat(12,1fr);gap:var(--cc-sf-grid-gap, 16px);align-items:start}@media(max-width:640px){.form-row.grid-row{grid-template-columns:1fr}.form-row.grid-row .row-field{grid-column:span 12!important}}.field-label{font-size:.75rem;font-weight:600;line-height:1;letter-spacing:.04em;text-transform:uppercase;color:#6b7280}.field-input,input.matInput,.mat-mdc-input-element{display:block;width:100%;height:var(--cc-sf-input-height)!important;padding:0 14px!important;font-family:inherit;font-size:.9rem;color:var(--cc-sf-label-color);background-color:var(--cc-sf-input-bg)!important;border:1.5px solid var(--cc-sf-input-border)!important;border-radius:var(--cc-sf-input-radius)!important;box-sizing:border-box;box-shadow:0 1px 2px #0000000a!important;transition:all .2s cubic-bezier(.4,0,.2,1)}.field-input::placeholder,input.matInput::placeholder,.mat-mdc-input-element::placeholder{font-weight:400;font-size:14px;color:var(--cc-sf-input-placeholder)}.field-input{opacity:var(--cc-sf-input-opacity, 1);line-height:var(--cc-sf-input-line-height, 1.5);transition:var(--cc-sf-input-transition, all .2s ease)}.field-input::placeholder{font-weight:var(--cc-sf-placeholder-weight, 400);font-size:var(--cc-sf-placeholder-size, 14px);line-height:var(--cc-sf-placeholder-line-height, 100%);color:var(--cc-sf-input-placeholder)}.field-input:hover:not(:disabled):not([readonly]){border-color:var(--cc-sf-input-hover-border)!important;box-shadow:0 1px 4px #6366f114!important}.field-input:focus{outline:none;border-color:var(--cc-sf-input-focus-border)!important;box-shadow:0 0 0 3px #6366f124,0 1px 4px #6366f11a!important;background-color:#fefeff!important}.field-input:disabled,.field-input[readonly]{background-color:var(--cc-sf-input-disabled-bg)!important;color:#9ca3af!important;cursor:not-allowed;border-color:var(--cc-sf-input-disabled-border)!important;box-shadow:none!important}.field-input.is-invalid{border-color:var(--cc-sf-error-border)!important;background-color:var(--cc-sf-error-bg)!important}.field-input.is-invalid:focus{box-shadow:0 0 0 3px #ef44441f,0 1px 4px #ef44441a!important}.field-input.textarea{resize:vertical;min-height:100px;height:auto;padding:12px 16px!important}input[type=time].time-input{cursor:pointer}input[type=time].time-input::-webkit-calendar-picker-indicator{cursor:pointer;opacity:.7;filter:invert(30%)}input[type=time].time-input::-webkit-calendar-picker-indicator:hover{opacity:1}select.field-input{appearance:none;background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3E%3Cpath stroke='%236B7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3E%3C/svg%3E\");background-position:right .5rem center;background-repeat:no-repeat;background-size:1.5em 1.5em;padding-right:2.5rem;cursor:pointer}select.field-input:disabled{cursor:not-allowed}.char-count-hint{font-style:normal;line-height:100%;letter-spacing:.02em}.radio-group.layout-column,.checkbox-group.layout-column{display:grid!important;grid-template-columns:repeat(12,1fr);gap:16px;width:100%}.radio-group.layout-row,.checkbox-group.layout-row{flex-direction:column!important;gap:12px;width:100%}.radio-label input,.checkbox-label input{cursor:pointer;accent-color:var(--cc-sf-chip-selected-bg, #F05A28)}.radio-label.card-item,.checkbox-label.card-item{display:flex!important;flex-direction:row-reverse!important;justify-content:space-between!important;align-items:center!important;border:1px solid var(--cc-sf-input-disabled-border, #E5E7EB);border-radius:12px;padding:16px 20px;box-sizing:border-box;transition:all .2s ease;background:var(--cc-sf-input-bg, #ffffff);margin-bottom:0}.radio-label.card-item input,.checkbox-label.card-item input{margin-left:16px}.radio-label.card-item.selected,.checkbox-label.card-item.selected{border-color:var(--cc-sf-selected-color);background-color:#f05a280d}.radio-label.card-item .option-content .label-text,.checkbox-label.card-item .option-content .label-text,.checkbox-single .checkbox-label{font-weight:var(--cc-sf-label-weight, 500)}.chip-label{transition:var(--cc-sf-input-transition, all .2s ease)}.chip-label:hover{background:var(--cc-sf-chip-hover-bg, #F3F4F6)}.chip-label.selected{background:var(--cc-sf-selected-color);color:var(--cc-sf-chip-selected-color, #ffffff);border-color:var(--cc-sf-selected-color)}.switch{width:50px;height:24px;display:inline-block}.switch input{opacity:0;width:0;height:0;position:absolute}.switch input:checked+.slider{background-color:var(--cc-sf-switch-track-on)!important}.switch input:checked+.slider:before{transform:translate(26px)}.switch .slider{inset:0;transition:.4s;background-color:var(--cc-sf-switch-track-off);border-radius:24px}.switch .slider:before{position:absolute;content:\"\";height:18px;width:18px;left:3px;bottom:3px;background-color:var(--cc-sf-switch-thumb);transition:.4s;border-radius:50%}.rating-group .star{transition:var(--cc-sf-input-transition, all .2s ease)}.rating-group .star mat-icon{font-size:var(--cc-sf-star-size, 28px);width:var(--cc-sf-star-size, 28px);height:var(--cc-sf-star-size, 28px);line-height:var(--cc-sf-star-size, 28px);color:var(--cc-sf-star-empty, #D1D5DB);transition:var(--cc-sf-input-transition, all .2s ease)}.rating-group .star.filled mat-icon,.rating-group .star.half mat-icon{color:var(--cc-sf-star-filled, #F59E0B)}.rating-group .star:hover mat-icon{color:var(--cc-sf-star-filled, #F59E0B)}.password-wrapper .password-toggle{right:.625rem;top:50%;transform:translateY(-50%);line-height:1;transition:color var(--cc-sf-input-transition, .2s ease)}.password-wrapper .password-toggle mat-icon.eye-icon{font-size:1.125rem;width:1.125rem;height:1.125rem;line-height:1.125rem}.password-wrapper .password-toggle:hover{color:var(--cc-sf-label-color, #374151)}.password-wrapper .password-toggle:focus{outline:none}.group-section-wrapper .group-label{font-size:var(--cc-sf-section-label-size, 1rem);font-weight:var(--cc-sf-section-label-weight, 600);color:var(--cc-sf-section-label-color, #1F2937);margin:0 0 16px;padding-left:12px;padding-top:2px;padding-bottom:2px;border-left:var(--cc-sf-section-header-accent-width, 4px) solid var(--cc-sf-section-header-accent-color, #3B82F6);line-height:1.4}.group-section-wrapper .group-fields.sf-grid{display:grid;grid-template-columns:repeat(12,1fr);gap:var(--cc-sf-grid-gap, 16px);align-items:start}@media(max-width:640px){.group-section-wrapper .group-fields.sf-grid{grid-template-columns:1fr}.group-section-wrapper .group-fields.sf-grid .sf-col{grid-column:span 12!important}}.group-section-wrapper .group-accordion-instance{border:var(--cc-sf-instance-border, 1px solid #E5E7EB);border-radius:var(--cc-sf-section-border-radius-inner, 8px);margin-bottom:8px;overflow:hidden;transition:border-color .2s ease}.group-section-wrapper .group-accordion-instance:last-of-type{margin-bottom:0}.group-section-wrapper .group-accordion-instance .group-accordion-header{display:flex;justify-content:space-between;align-items:center;padding:10px 14px;background:var(--cc-sf-repeater-accordion-header-bg, #F9FAFB);cursor:pointer;-webkit-user-select:none;user-select:none;transition:background .15s ease}.group-section-wrapper .group-accordion-instance .group-accordion-header:hover{background:var(--cc-sf-repeater-accordion-active-bg, #EFF6FF)}.group-section-wrapper .group-accordion-instance .group-accordion-header .instance-badge{width:22px;height:22px;border-radius:50%;background:var(--cc-sf-repeater-badge-bg, #E5E7EB);color:var(--cc-sf-repeater-badge-color, #374151);font-size:.75rem;font-weight:600;display:flex;align-items:center;justify-content:center;flex-shrink:0}.group-section-wrapper .group-accordion-instance .group-accordion-header .instance-title{font-size:var(--cc-sf-instance-num-size, .8125rem);font-weight:600;color:var(--cc-sf-repeater-accordion-header-color, #1F2937)}.group-section-wrapper .group-accordion-instance .group-accordion-header .accordion-remove-btn{background:none;border:none;cursor:pointer;color:var(--cc-sf-btn-remove-color, #E53E3E);padding:4px;border-radius:4px;line-height:1;display:flex;align-items:center;transition:background .15s ease}.group-section-wrapper .group-accordion-instance .group-accordion-header .accordion-remove-btn mat-icon{font-size:1.1rem;width:1.1rem;height:1.1rem;line-height:1.1rem}.group-section-wrapper .group-accordion-instance .group-accordion-header .accordion-remove-btn:hover{background:var(--cc-sf-btn-remove-hover-bg, #FED7D7)}.group-section-wrapper .group-accordion-instance .group-accordion-header .accordion-chevron{font-size:1.25rem;width:1.25rem;height:1.25rem;line-height:1.25rem;color:var(--cc-sf-instance-num-color, #4B5563)}.group-section-wrapper .group-accordion-instance .group-accordion-body{padding:var(--cc-sf-instance-padding, 16px);background:var(--cc-sf-instance-bg, #F9FAFB);border-top:var(--cc-sf-instance-divider, 1px dashed #D1D5DB)}.group-section-wrapper .btn-add-group{display:flex;align-items:center;justify-content:center;gap:6px;width:100%;padding:10px 20px;margin-top:12px;background:var(--cc-sf-btn-add-bg, transparent);color:var(--cc-sf-btn-add-color, #3B82F6);border:var(--cc-sf-btn-add-border, 1px dashed #CBD5E1);border-radius:var(--cc-sf-btn-add-radius, 6px);cursor:pointer;font-family:inherit;font-size:var(--cc-sf-btn-font-size, .875rem);font-weight:var(--cc-sf-btn-font-weight, 600);transition:var(--cc-sf-btn-transition, all .2s ease)}.group-section-wrapper .btn-add-group mat-icon{font-size:1.1rem;width:1.1rem;height:1.1rem;line-height:1.1rem}.group-section-wrapper .btn-add-group:hover{background:var(--cc-sf-btn-add-hover-bg, #EFF6FF);border-color:var(--cc-sf-btn-add-hover-border, #BFDBFE)}.group-section-wrapper .group-instance:last-child{margin-bottom:0}.group-section-wrapper.multi-save-active{border:none;box-shadow:none;padding:0;background:transparent}.group-section-wrapper.multi-save-active .multi-save-header .btn-add-multi ::ng-deep button{color:var(--ms-btn-add-color, #3B82F6);font-weight:600;font-size:.875rem;padding:8px 12px}.group-section-wrapper.multi-save-active .multi-save-header .btn-add-multi ::ng-deep button:hover{color:var(--ms-btn-add-hover, #2563EB);background-color:var(--cc-sf-btn-add-hover-bg, #EFF6FF)}.group-section-wrapper.multi-save-active .group-instance{box-shadow:var(--ms-card-shadow, 0 1px 4px rgba(0, 0, 0, .05))}.group-section-wrapper.multi-save-active .group-instance.is-editing{padding:24px}.group-section-wrapper.multi-save-active .group-instance.is-card{cursor:pointer;transition:all .2s ease-in-out}.group-section-wrapper.multi-save-active .group-instance.is-card:hover{box-shadow:var(--ms-card-shadow-hover, 0 8px 24px rgba(0, 0, 0, .08));border-color:var(--cc-sf-input-focus-border, #3B82F6)}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view .card-content .card-title{white-space:nowrap;text-overflow:ellipsis}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view .card-content .card-desc{line-height:1.4;display:-webkit-box;-webkit-line-clamp:1;line-clamp:1;-webkit-box-orient:vertical}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view.is-expanded .card-content .card-desc{-webkit-line-clamp:unset;line-clamp:unset}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view .card-actions mat-icon{font-size:22px;width:22px;height:22px;color:var(--cc-sf-hint-color, #9CA3AF);transition:color .2s}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view .card-actions mat-icon.icon-delete:hover{color:var(--cc-sf-error-border, #DC2626)}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view .card-actions mat-icon.icon-edit:hover{color:var(--cc-sf-input-focus-border, #3B82F6)}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view .card-actions mat-icon.icon-expand{color:var(--cc-sf-input-disabled-border, #E5E7EB)}.btn-remove{transition:var(--cc-sf-btn-transition, all .2s ease)}.btn-remove mat-icon{font-size:1rem;width:1rem;height:1rem;line-height:1rem}.btn-remove:hover{background:var(--cc-sf-btn-remove-hover-bg, #FED7D7)}.btn-add-group{font-weight:var(--cc-sf-btn-font-weight, 600);transition:var(--cc-sf-btn-transition, all .2s ease)}.btn-add-group mat-icon{font-size:1.1rem;width:1.1rem;height:1.1rem;line-height:1.1rem}.btn-add-group:hover{background:var(--cc-sf-btn-add-hover-bg, #EFF6FF);border-color:var(--cc-sf-btn-add-hover-border, #BFDBFE)}.upload-drop-zone{background-color:var(--cc-sf-dropzone-bg, #F8FAFC);border:var(--cc-sf-dropzone-border, 1.5px dashed #CBD5E1);border-radius:var(--cc-sf-dropzone-radius, 12px);transition:background-color .2s ease,border-color .2s ease}.upload-drop-zone:hover{background-color:var(--cc-sf-dropzone-hover-bg, #EFF6FF);border-color:var(--cc-sf-dropzone-hover-border, #93C5FD)}.upload-drop-zone.drag-over{background-color:var(--cc-sf-dropzone-hover-bg, #EFF6FF);border-color:var(--cc-sf-dropzone-over-border, #3B82F6);box-shadow:var(--cc-sf-dropzone-over-shadow, 0 0 0 4px rgba(59, 130, 246, .12))}.upload-drop-zone.is-invalid{border-color:var(--cc-sf-error-border, #DC2626);background-color:var(--cc-sf-error-bg, #FEF2F2)}.upload-icon-wrap .dropzone-icon-pill{width:52px;height:52px;border-radius:50%;background:var(--cc-sf-dropzone-icon-bg, rgba(59, 130, 246, .1))}.upload-icon-wrap mat-icon.upload-cloud-icon{font-size:28px;width:28px;height:28px;line-height:28px;color:var(--cc-sf-accent-color, #3B82F6)}.upload-main-text{color:var(--cc-sf-label-color, #1E293B)}.upload-sub-text{color:var(--cc-sf-hint-color, #64748B)}.upload-link{color:var(--cc-sf-dropzone-link-color, #3B82F6);font-weight:500}.upload-formats{color:var(--cc-sf-dropzone-link-color, #3B82F6)}.upload-size-badge{display:inline-block;padding:2px 8px;border-radius:20px;background:var(--cc-sf-input-disabled-bg, #F3F4F6);color:var(--cc-sf-hint-color, #6B7280);font-weight:500}.uploaded-item{background:var(--cc-sf-uploaded-item-bg, #ffffff);border:var(--cc-sf-uploaded-item-border, 1px solid #E2E8F0);border-radius:var(--cc-sf-uploaded-item-radius, 8px);transition:box-shadow .15s ease}.uploaded-item:hover{box-shadow:0 2px 6px #0000000f}.uploaded-item mat-icon.file-type-icon{font-size:20px;width:20px;height:20px;line-height:20px;flex-shrink:0;color:var(--cc-sf-hint-color, #64748B)}.uploaded-item .file-thumb{width:36px;height:36px;object-fit:cover;flex-shrink:0}.uploaded-item .file-info{min-width:0;gap:2px}.uploaded-item .file-info .file-name{white-space:nowrap;text-overflow:ellipsis}.uploaded-item .file-remove-btn{flex-shrink:0;width:32px;height:32px;background:none;border:none;cursor:pointer;color:var(--cc-sf-uploaded-remove-color, #94A3B8);padding:0;display:flex;align-items:center;justify-content:center;transition:color .15s ease,background .15s ease}.uploaded-item .file-remove-btn mat-icon{font-size:1.1rem;width:1.1rem;height:1.1rem;line-height:1.1rem}.uploaded-item .file-remove-btn:hover:not(:disabled){color:var(--cc-sf-uploaded-remove-hover-color, #DC2626);background:var(--cc-sf-uploaded-remove-hover-bg, #FEF2F2)}.uploaded-item .file-remove-btn:disabled{opacity:.4;cursor:not-allowed}.uploaded-item.uploading{background:var(--cc-sf-uploaded-uploading-bg, #F8FAFC);border-color:var(--cc-sf-uploaded-uploading-border, #CBD5E1);opacity:.85}.upload-spinner{width:20px;height:20px;flex-shrink:0;border-top-color:var(--cc-sf-accent-color, #3B82F6);animation:cc-spin .7s linear infinite}@keyframes cc-spin{to{transform:rotate(360deg)}}.uploading-label{font-style:italic}.input-group{align-items:stretch}.input-group .field-input{flex:1;width:auto}.input-prefix+.input-group .field-input{border-top-left-radius:0;border-bottom-left-radius:0}.input-group .field-input:has(+.input-suffix){border-top-right-radius:0;border-bottom-right-radius:0}.input-group .field-input.has-icon-right{padding-right:3rem}.input-group.readonly .field-input{cursor:default}.input-prefix,.input-suffix{display:flex!important;align-items:center;white-space:nowrap;padding:0 14px;background-color:var(--cc-sf-input-disabled-bg);border:1px solid var(--cc-sf-input-border);font-size:.875rem;color:var(--cc-sf-hint-color);-webkit-user-select:none;user-select:none}.input-prefix{border-right:none;border-top-left-radius:var(--cc-sf-input-radius, 8px);border-bottom-left-radius:var(--cc-sf-input-radius, 8px)}.input-suffix{border-left:none;border-top-right-radius:var(--cc-sf-input-radius, 8px);border-bottom-right-radius:var(--cc-sf-input-radius, 8px)}.readonly-icons{right:.875rem;top:50%;transform:translateY(-50%)}.readonly-icons mat-icon.lock-icon{font-size:1rem;width:1rem;height:1rem;line-height:1rem;opacity:.5;color:var(--cc-sf-hint-color, #6B7280)}.date-icon-wrapper{right:.5rem;top:50%;transform:translateY(-50%);pointer-events:auto}.date-icon-wrapper .mat-icon-button{width:32px;height:32px;line-height:32px}.subfields-group-wrapper .subfields-row{transition:all .2s ease}.subfields-group-wrapper .subfields-row.is-invalid .subfield-item ::ng-deep .field-input{border-color:var(--cc-sf-error-border, #DC2626);background-color:var(--cc-sf-error-bg, #FEF2F2)}.subfields-group-wrapper .subfields-row .subfield-item{min-width:0}.subfields-group-wrapper .subfields-row .subfield-item ::ng-deep .field-label{font-size:.75rem!important;margin-bottom:4px!important;font-weight:500!important;color:var(--cc-sf-hint-color, #6B7280)!important}.subfields-group-wrapper .subfields-row .subfield-separator{font-weight:700}.autocomplete-wrapper .ac-input{padding-left:40px!important}.autocomplete-wrapper .ac-search-icon{left:.75rem;width:1.1rem;height:1.1rem;line-height:1.1rem;z-index:1;transition:color var(--cc-sf-input-transition, .2s ease)}.autocomplete-wrapper .ac-clear-btn{right:.6rem;transition:color .15s ease,background .15s ease}.autocomplete-wrapper .ac-clear-btn mat-icon{font-size:1rem;width:1rem;height:1rem;line-height:1rem}.autocomplete-wrapper .ac-clear-btn:hover{color:var(--cc-sf-label-color, #374151);background:var(--cc-sf-input-disabled-bg, #F3F4F6)}.autocomplete-wrapper .ac-clear-btn:focus{outline:none}.autocomplete-wrapper:focus-within .ac-search-icon{color:var(--cc-sf-accent-color, #3B82F6)}.autocomplete-wrapper.is-invalid .ac-input{border-color:var(--cc-sf-error-border)!important;background-color:var(--cc-sf-error-bg)}.autocomplete-wrapper.readonly .ac-input{background-color:var(--cc-sf-input-disabled-bg);color:var(--cc-sf-input-disabled-color, #6B7280);cursor:not-allowed;border-color:var(--cc-sf-input-disabled-border)!important}.ac-no-results{font-style:italic}.mu-layout{grid-template-columns:1fr 1fr;gap:32px}@media(max-width:768px){.mu-layout{grid-template-columns:1fr}}.mu-title{font-weight:700;line-height:1.3}.mu-badge{white-space:nowrap;flex-shrink:0}.mu-description{line-height:1.6}.mu-feature-item .mu-check{width:16px;height:16px;line-height:16px;flex-shrink:0}.mu-right{min-height:260px}.mu-right-empty{min-height:250px;max-width:400px;box-shadow:0 2px 10px #0000000d;transition:box-shadow .2s ease}.mu-right-empty:hover{cursor:pointer;box-shadow:0 4px 16px #0000001a}.mu-right-empty .mu-right-empty-icon{width:52px;height:52px;line-height:52px;opacity:.3}.mu-right-empty p{margin:0;font-size:.85rem}.media-add-container{display:inline-block}.media-add-container ::ng-deep button{display:flex;align-items:center;gap:6px}.media-add-container ::ng-deep button .menu-chevron{width:18px;height:18px;line-height:18px;transition:transform .2s ease}.media-dropdown{top:calc(100% + 6px);left:0;z-index:200;min-width:240px;box-shadow:var(--mu-dropdown-shadow, 0 8px 32px rgba(0, 0, 0, .12));animation:mu-fade-in .15s ease}@keyframes mu-fade-in{0%{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:translateY(0)}}.media-dropdown-item{transition:background .15s ease}.media-dropdown-item:last-child{border-bottom:none}.media-dropdown-item:hover{background:var(--cc-sf-dropzone-hover-bg, #F0F9FF)}.media-drop-icon{width:36px;height:36px;flex-shrink:0}.media-drop-icon mat-icon{font-size:20px;width:20px;height:20px;line-height:20px}.media-drop-icon--video{background:var(--mu-icon-video-bg, #FFF0F0);color:var(--mu-icon-video-color, #EF4444)}.media-drop-icon--device{background:var(--mu-icon-device-bg, #EFF6FF);color:var(--mu-icon-device-color, #3B82F6)}.media-drop-icon--library{background:var(--mu-icon-library-bg, #F0FDF4);color:var(--mu-icon-library-color, #22C55E)}.media-drop-text{gap:2px}.youtube-input-panel{animation:mu-fade-in .18s ease}.youtube-panel-label mat-icon{font-size:18px;width:18px;height:18px;line-height:18px;color:var(--mu-icon-video-color, #EF4444)}.youtube-input-row{align-items:stretch}.media-menu-backdrop{position:fixed;inset:0;z-index:100}.media-upload-status{animation:mu-fade-in .2s ease}.media-upload-status .status-icon{width:18px;height:18px;line-height:18px}.media-carousel-main{max-width:400px;height:var(--mu-carousel-height, 250px)}.carousel-viewer{inset:0}.carousel-viewer .carousel-image{object-fit:cover}.carousel-viewer .carousel-spinner{width:36px;height:36px;border-top-color:var(--cc-sf-accent-color, #3B82F6);animation:cc-spin .7s linear infinite}.carousel-nav{top:50%;transform:translateY(-50%);z-index:10;width:40px;height:40px;box-shadow:0 2px 8px #0003;transition:background .2s ease,opacity .2s ease;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.carousel-nav mat-icon{font-size:22px;width:22px;height:22px;line-height:22px;color:#1e293b}.carousel-nav:hover:not(:disabled){background:#fff}.carousel-nav:disabled{opacity:.3;cursor:not-allowed}.carousel-nav--prev{left:12px}.carousel-nav--next{right:12px}.carousel-remove-btn{top:10px;right:10px;z-index:10;width:32px;height:32px;transition:background .2s ease}.carousel-remove-btn mat-icon{font-size:18px;width:18px;height:18px;line-height:18px;color:#fff}.carousel-remove-btn:hover:not(:disabled){background:#dc2626d9}.carousel-remove-btn:disabled{opacity:.4;cursor:not-allowed}.carousel-dots{bottom:10px;left:50%;transform:translate(-50%);z-index:10}.carousel-dot{width:8px;height:8px;transition:background .2s ease,transform .2s ease}.carousel-dot.active{background:#fff;transform:scale(1.3)}.media-thumbnail-strip{max-width:400px;overflow-x:auto}.media-thumbnail-strip::-webkit-scrollbar{height:4px}.media-thumbnail-strip::-webkit-scrollbar-thumb{background:var(--cc-sf-input-disabled-border, #D1D5DB);border-radius:2px}.media-thumb{flex-shrink:0;width:72px;height:52px;transition:border-color .2s ease,transform .15s ease}.media-thumb.active{border-color:var(--mu-thumb-active-border, var(--cc-sf-accent-color, #3B82F6));transform:scale(1.04)}.media-thumb:hover:not(.active){border-color:var(--cc-sf-input-hover-border, #9CA3AF)}.media-thumb .thumb-img{object-fit:cover}.media-thumb .thumb-yt-placeholder mat-icon{font-size:28px;width:28px;height:28px;line-height:28px}.media-thumb .thumb-uploading .thumb-spinner{width:20px;height:20px;border-top-color:var(--cc-sf-accent-color, #3B82F6);animation:cc-spin .7s linear infinite}.media-library-overlay{position:fixed;inset:0;z-index:999;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);animation:mu-fade-in .2s ease}.media-library-modal{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);z-index:1000;width:min(90vw,780px);max-height:85vh;box-shadow:var(--mu-modal-shadow, 0 20px 60px rgba(0, 0, 0, .2));animation:mu-modal-in .22s cubic-bezier(.34,1.56,.64,1)}@keyframes mu-modal-in{0%{opacity:0;transform:translate(-50%,-48%) scale(.95)}to{opacity:1;transform:translate(-50%,-50%) scale(1)}}.library-modal-header{flex-shrink:0}.library-modal-title{font-weight:700}.library-modal-subtitle{line-height:1.5;max-width:600px}.library-close-btn{width:32px;height:32px;transition:background .15s ease,color .15s ease}.library-close-btn mat-icon{font-size:20px;width:20px;height:20px;line-height:20px}.library-close-btn:hover{background:var(--cc-sf-input-disabled-bg, #F3F4F6);color:var(--cc-sf-label-color, #374151)}.library-loading mat-icon,.library-empty mat-icon{font-size:40px;width:40px;height:40px;line-height:40px;opacity:.5}.lib-spinner{width:36px;height:36px;border-top-color:var(--cc-sf-accent-color, #3B82F6);animation:cc-spin .7s linear infinite}.library-error{flex-shrink:0}.library-error mat-icon{font-size:20px;width:20px;height:20px;line-height:20px}.library-grid{grid-template-columns:repeat(5,1fr);overflow-y:auto}.library-grid::-webkit-scrollbar{width:8px}.library-grid::-webkit-scrollbar-track{background:#f1f1f1}.library-grid::-webkit-scrollbar-thumb{background:#c1c1c1;border-radius:10px;border:2px solid #F1F1F1}.library-grid-item{aspect-ratio:1/1;transition:all .3s cubic-bezier(.4,0,.2,1);box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -1px #0000000f}.library-grid-item:hover{transform:translateY(-4px) scale(1.02);box-shadow:0 20px 25px -5px #0000001a,0 10px 10px -5px #0000000a}.library-grid-item.selected{border-color:var(--cc-sf-accent-color, #3B82F6)}.library-grid-item.selected .library-grid-img{opacity:.7}.library-grid-item:hover .library-overlay-hover{opacity:1}.library-grid-img{object-fit:cover}.library-overlay-hover{inset:0;opacity:0;transition:opacity .15s ease}.library-check{top:6px;right:6px;width:22px;height:22px;box-shadow:0 1px 4px #00000026}.library-check mat-icon{font-size:18px;width:18px;height:18px;line-height:18px}.library-modal-footer{flex-shrink:0}.library-modal-footer .library-footer-actions ::ng-deep .cc-btn-primary{background-color:var(--cc-sf-accent-color, #3B82F6)!important;border-color:var(--cc-sf-accent-color, #3B82F6)!important;color:#fff!important;font-weight:600;padding-left:32px;padding-right:32px}.library-modal-footer .library-footer-actions ::ng-deep .cc-btn-primary:hover{background-color:var(--cc-sf-btn-primary-hover-bg, #2563EB)!important}.library-modal-footer .library-footer-actions ::ng-deep .cc-btn-primary:disabled{background-color:#93c5fd!important;cursor:not-allowed}.library-modal-footer .library-footer-actions ::ng-deep .cc-btn-outline{font-weight:600;padding-left:24px;padding-right:24px;border-color:#d1d5db;color:#374151}.library-modal-footer .library-footer-actions ::ng-deep .cc-btn-outline:hover{background-color:#f9fafb}.location-subtitle{line-height:1.5}.loc-tab-btn ::ng-deep button{width:100%}.loc-tab-btn ::ng-deep button:not(.cc-btn-warning){background-color:var(--cc-sf-input-bg, #ffffff)!important;color:var(--cc-sf-label-color, #000000)!important;border:1px solid var(--cc-sf-input-disabled-border, #E5E7EB)}.loc-tab-btn ::ng-deep button:not(.cc-btn-warning):hover{background-color:var(--cc-sf-input-disabled-bg, #F3F4F6)!important}.loc-venue-item{transition:box-shadow .15s ease,border-color .15s ease}.loc-venue-item:hover{box-shadow:0 2px 8px #0000000f;border-color:var(--cc-sf-input-hover-border, #9CA3AF)}.loc-venue-search-icon{width:18px;height:18px;line-height:18px;flex-shrink:0}.loc-venue-text{white-space:nowrap;text-overflow:ellipsis}.loc-action-btn{transition:background .15s ease,color .15s ease;flex-shrink:0}.loc-action-btn mat-icon{font-size:18px;width:18px;height:18px;line-height:18px}.loc-action-btn.loc-delete-btn{color:var(--loc-delete-color, #E53E3E)}.loc-action-btn.loc-delete-btn:hover{background:var(--cc-sf-error-bg, #FEF2F2)}.loc-action-btn.loc-edit-btn{color:var(--cc-sf-hint-color, #9CA3AF)}.loc-action-btn.loc-edit-btn:hover{color:var(--cc-sf-input-focus-border, #3B82F6);background:var(--cc-sf-dropzone-hover-bg, #EFF6FF)}.loc-search-icon{left:.75rem;width:1.1rem;height:1.1rem;line-height:1.1rem;z-index:1}.loc-suggestions-panel{top:calc(100% + 4px);left:0;right:0;z-index:300;box-shadow:0 8px 24px #0000001a;animation:mu-fade-in .15s ease;max-height:260px;overflow-y:auto}.loc-suggestion-item{transition:background .12s ease}.loc-suggestion-item:hover,.loc-suggestion-item:focus{background:var(--loc-suggestion-hover-bg, #F0F9FF)}.loc-suggestion-item:not(:last-child){border-bottom:1px solid var(--cc-sf-input-disabled-border, #F3F4F6)}.loc-suggestion-icon{width:18px;height:18px;line-height:18px;flex-shrink:0}.loc-suggestion-text{white-space:nowrap;text-overflow:ellipsis}.loc-add-btn{transition:opacity .15s ease}.loc-add-btn mat-icon{font-size:20px;width:20px;height:20px;line-height:20px}.loc-add-btn:hover{opacity:.8}.loc-map-container{box-shadow:0 2px 10px #0000000f}.loc-tba-panel{min-height:120px}.loc-tba-icon{width:40px;height:40px;line-height:40px;opacity:.6}.loc-tba-text{line-height:1.6;max-width:360px}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$3.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$3.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$3.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$3.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1$3.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1$3.SelectMultipleControlValueAccessor, selector: "select[multiple][formControlName],select[multiple][formControl],select[multiple][ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1$3.RadioControlValueAccessor, selector: "input[type=radio][formControlName],input[type=radio][formControl],input[type=radio][ngModel]", inputs: ["name", "formControlName", "value"] }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$3.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1$3.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { kind: "directive", type: i1$3.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$3.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1$3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i5.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: i5.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: i6.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i6.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i6.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { kind: "directive", type: i7.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i9.MatAutocomplete, selector: "mat-autocomplete", inputs: ["aria-label", "aria-labelledby", "displayWith", "autoActiveFirstOption", "autoSelectActiveOption", "requireSelection", "panelWidth", "disableRipple", "class", "hideSingleSelectionIndicator"], outputs: ["optionSelected", "opened", "closed", "optionActivated"], exportAs: ["matAutocomplete"] }, { kind: "directive", type: i9.MatAutocompleteTrigger, selector: "input[matAutocomplete], textarea[matAutocomplete]", inputs: ["matAutocomplete", "matAutocompletePosition", "matAutocompleteConnectedTo", "autocomplete", "matAutocompleteDisabled"], exportAs: ["matAutocompleteTrigger"] }, { kind: "component", type: ButtonComponent, selector: "lib-button", inputs: ["variant", "type", "disabled", "width", "height", "borderRadius", "fontSize", "fontWeight", "backgroundColor", "color", "border", "icon", "labels"] }, { kind: "component", type: i11.QuillEditorComponent, selector: "quill-editor" }, { kind: "component", type: FormFieldComponent, selector: "lib-form-field", inputs: ["config", "controller", "formGroup", "allowMulti"] }, { kind: "pipe", type: TrustedUrlPipe, name: "trustedUrl" }] });
|
|
2199
2228
|
}
|
|
2200
2229
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: FormFieldComponent, decorators: [{
|
|
2201
2230
|
type: Component,
|
|
2202
|
-
args: [{ selector: 'lib-form-field', standalone: false, template: "<div class=\"form-field mb-16px\" *ngIf=\"isVisible\" [class.has-error]=\"errorMessage\">\r\n\r\n <!-- \u2550\u2550 ROW Layout \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isRow\" class=\"form-row grid-row\">\r\n <ng-container *ngFor=\"let child of config.children\">\r\n <div class=\"row-field\" [style.gridColumn]=\"'span ' + getChildColSpan(child)\" *ngIf=\"child.isEnabled !== false\">\r\n <lib-form-field [config]=\"child\" [controller]=\"controller\" [formGroup]=\"formGroup\" [allowMulti]=\"allowMulti\">\r\n </lib-form-field>\r\n </div>\r\n </ng-container>\r\n </div>\r\n\r\n <!-- \u2550\u2550 GROUP \u2014 allowMulti (repeater) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isGroup && config.sectionConfig?.allowMulti\"\r\n class=\"group-section-wrapper mb-20px b-1px-solid-E5E7EB br-10px p-20px bc-ffffff\"\r\n [class.multi-save-active]=\"config.sectionConfig?.multiSaveConfig?.active\">\r\n\r\n <!-- Multi-Save Header with Add button (top-right style) -->\r\n <div class=\"multi-save-header d-flex justify-content-between align-items-center mb-24\"\r\n *ngIf=\"config.sectionConfig?.multiSaveConfig?.active\">\r\n <h3\r\n class=\"group-label pb-10 mb-0 d-block font-weight-600 border-none fs-0-875rem c-111827 fs-1rem c-1F2937 m-0-0-16px-0 bb-2px-solid-E5E7EB pb-0 mb-0-75rem\"\r\n *ngIf=\"config.sectionConfig?.label\">{{ config.sectionConfig!.label }}</h3>\r\n <lib-button [variant]=\"'outline'\" [icon]=\"{type: 'material', value: 'add'}\" (click)=\"addGroupInstance()\"\r\n class=\"btn-add-multi\">\r\n {{ addMultiLabel }}\r\n </lib-button>\r\n </div>\r\n\r\n <!-- Standard Header for non-multiSave -->\r\n <h3\r\n class=\"group-label pb-10 mb-0 d-block font-weight-600 border-none fs-0-875rem c-111827 fs-1rem c-1F2937 m-0-0-16px-0 bb-2px-solid-E5E7EB pb-0 mb-0-75rem\"\r\n *ngIf=\"config.sectionConfig?.label && !config.sectionConfig?.multiSaveConfig?.active\">{{\r\n config.sectionConfig!.label }}</h3>\r\n\r\n <div *ngFor=\"let instance of instanceList; trackBy: trackByInstanceId; let i = index\"\r\n class=\"group-instance position-relative mb-16 p-0 overflow-hidden p-16px b-F9FAFB b-1px-solid-E5E7EB br-8px b-ffffff br-10px\"\r\n [class.is-editing]=\"instance.isEditing\"\r\n [class.is-card]=\"config.sectionConfig?.multiSaveConfig?.active && !instance.isEditing\">\r\n\r\n <!-- 1. EDIT MODE / UNSAVED / STANDARD STATE -->\r\n <div [hidden]=\"config.sectionConfig?.multiSaveConfig?.active && !instance.isEditing\">\r\n <!-- Instance header \u2014 show remove only when more than 1 instance -->\r\n <div class=\"group-header d-flex justify-content-between align-items-center mb-12 pb-10 bb-1px-dashed-D1D5DB\"\r\n *ngIf=\"!config.sectionConfig?.multiSaveConfig?.active && instanceList.length > 1\">\r\n <span class=\"group-number font-weight-500 c-4B5563 fs-0-8125rem\">{{ config.sectionConfig!.label }} #{{ i + 1\r\n }}</span>\r\n <lib-button [variant]=\"'danger-outline'\" [icon]=\"{type: 'material', value: 'delete_outline'}\"\r\n (click)=\"removeGroupInstance(i)\">\r\n {{ removeLabel }}\r\n </lib-button>\r\n </div>\r\n\r\n <div class=\"group-fields sf-grid\">\r\n <ng-container *ngFor=\"let field of config.sectionConfig!.children\">\r\n <div class=\"sf-col\" [style.gridColumn]=\"'span ' + (field.colSpan || 12)\" *ngIf=\"field.isEnabled !== false\">\r\n <lib-form-field [config]=\"field\" [controller]=\"controller\" [formGroup]=\"instance.fg\" [allowMulti]=\"true\">\r\n </lib-form-field>\r\n </div>\r\n </ng-container>\r\n </div>\r\n\r\n <!-- SAVE / CANCEL BUTTONS for MultiSave in Editing phase -->\r\n <div\r\n class=\"group-footer d-flex justify-content-between align-items-center gap-16 mt-24 pt-20 bt-1px-solid-E5E7EB\"\r\n *ngIf=\"config.sectionConfig?.multiSaveConfig?.active\">\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"multiSaveError\">{{ multiSaveError }}</span>\r\n <div class=\"footer-actions d-flex gap-12\">\r\n <lib-button [variant]=\"'outline'\" (click)=\"cancelGroupInstance(i)\">Cancel</lib-button>\r\n <lib-button [variant]=\"'primary'\" (click)=\"saveGroupInstance(i)\">Save</lib-button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- 2. CARD VIEW (Saved State) -->\r\n <ng-container *ngIf=\"config.sectionConfig?.multiSaveConfig?.active && !instance.isEditing\">\r\n <div class=\"card-view d-flex justify-content-between align-items-center p-18px-24px\"\r\n [class.is-expanded]=\"instance.isExpanded\">\r\n <div class=\"card-content flex-1 d-flex flex-column gap-4 overflow-hidden\">\r\n <span class=\"card-title font-weight-600 overflow-hidden fs-1rem c-111827\">{{\r\n instance.fg.get(config.sectionConfig!.multiSaveConfig!.summaryField || '')?.value\r\n || '\u2014' }}</span>\r\n <!-- <span class=\"card-desc overflow-hidden fs-0-875rem c-6B7280\" *ngIf=\"config.sectionConfig.multiSaveConfig.descriptionField\"\r\n [innerHTML]=\"instance.fg.get(config.sectionConfig.multiSaveConfig.descriptionField)?.value\">\r\n </span> -->\r\n </div>\r\n <div class=\"card-actions d-flex align-items-center gap-16 ml-20\">\r\n <mat-icon class=\"icon-delete\" (click)=\"removeGroupInstance(i, true)\">delete_outline</mat-icon>\r\n <mat-icon class=\"icon-edit\" (click)=\"editGroupInstance(i)\">edit_outline</mat-icon>\r\n <mat-icon class=\"icon-expand\" (click)=\"toggleExpandGroupInstance(i)\">\r\n {{ instance.isExpanded ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}\r\n </mat-icon>\r\n </div>\r\n </div>\r\n </ng-container>\r\n </div>\r\n\r\n <!-- Standard Add Button for non-multiSave -->\r\n <lib-button *ngIf=\"!config.sectionConfig?.multiSaveConfig?.active\" [variant]=\"'outline'\"\r\n [icon]=\"{type: 'material', value: 'add'}\" (click)=\"addGroupInstance()\" class=\"btn-add-group-wrapper\">\r\n {{ addLabel }} {{ config.sectionConfig!.label }}\r\n </lib-button>\r\n </div>\r\n\r\n <!-- \u2550\u2550 GROUP \u2014 single (non-repeater) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isGroup && config.sectionConfig && !config.sectionConfig.allowMulti\"\r\n class=\"group-section-wrapper mb-20px b-1px-solid-E5E7EB br-10px p-20px bc-ffffff\">\r\n <h3\r\n class=\"group-label pb-10 mb-0 d-block font-weight-600 border-none fs-0-875rem c-111827 fs-1rem c-1F2937 m-0-0-16px-0 bb-2px-solid-E5E7EB pb-0 mb-0-75rem\"\r\n *ngIf=\"config.sectionConfig.label\">{{ config.sectionConfig.label }}</h3>\r\n <div class=\"group-fields sf-grid\">\r\n <ng-container *ngFor=\"let field of config.sectionConfig.children\">\r\n <div class=\"sf-col\" [style.gridColumn]=\"'span ' + (field.colSpan || 12)\" *ngIf=\"field.isEnabled !== false\">\r\n <lib-form-field [config]=\"field\" [controller]=\"controller\" [formGroup]=\"groupFormGroup\" [allowMulti]=\"false\">\r\n </lib-form-field>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </div>\r\n\r\n\r\n <!-- \u2550\u2550 Text Input \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isTextField\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <textarea *ngIf=\"config.subType === 'LONG'\" class=\"field-input textarea\" [placeholder]=\"config.placeholder || ''\"\r\n [formControlName]=\"config.name!\" [class.is-invalid]=\"errorMessage\" rows=\"4\">\r\n </textarea>\r\n\r\n <!-- Password input with show/hide toggle -->\r\n <div *ngIf=\"config.subType === 'PASSWORD'\" class=\"password-wrapper position-relative d-flex align-items-center\">\r\n <input [type]=\"showPassword ? 'text' : 'password'\" class=\"field-input password-input\"\r\n [placeholder]=\"config.placeholder || ''\" [formControlName]=\"config.name!\" [class.is-invalid]=\"errorMessage\">\r\n <button type=\"button\"\r\n class=\"password-toggle position-absolute cursor-pointer d-flex align-items-center justify-content-center b-none border-none c-6B7280 p-0-25rem\"\r\n (click)=\"showPassword = !showPassword\" tabindex=\"-1\"\r\n [attr.aria-label]=\"showPassword ? 'Hide password' : 'Show password'\">\r\n <mat-icon class=\"eye-icon\">{{ showPassword ? 'visibility' : 'visibility_off' }}</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <div class=\"input-group position-relative d-flex w-100\" [class.readonly]=\"config.readonly\">\r\n <span class=\"input-prefix br-none\" *ngIf=\"config.prefix\">{{ config.prefix }}</span>\r\n\r\n <input *ngIf=\"config.subType !== 'LONG' && config.subType !== 'PASSWORD'\"\r\n [type]=\"config.subType === 'EMAIL' ? 'email' : config.subType === 'PHONE' ? 'tel' : 'text'\" class=\"field-input\"\r\n [placeholder]=\"config.placeholder || ''\" [formControlName]=\"config.name!\" [class.is-invalid]=\"errorMessage\"\r\n [readonly]=\"config.readonly\">\r\n\r\n <span class=\"input-suffix d-flex align-items-center font-weight-500\" *ngIf=\"config.suffix\">{{ config.suffix\r\n }}</span>\r\n\r\n <div class=\"readonly-icons position-absolute d-flex gap-8 pe-none\" *ngIf=\"config.readonly\">\r\n <mat-icon class=\"lock-icon\">lock</mat-icon>\r\n </div>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n <div class=\"char-count-hint font-poppins font-weight-400 text-14 text-right mt-4 c-6B7280\" *ngIf=\"showCharCount\">\r\n {{ remainingCharacters }} characters remaining\r\n </div>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Number Input \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isNumberField\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"input-group position-relative d-flex w-100\" [class.readonly]=\"config.readonly\">\r\n <span class=\"input-prefix br-none\" *ngIf=\"config.prefix\">{{ config.prefix }}</span>\r\n\r\n <input type=\"number\" class=\"field-input\" [placeholder]=\"config.placeholder || ''\" [formControlName]=\"config.name!\"\r\n [min]=\"config.numberConfig?.min ?? null\" [max]=\"config.numberConfig?.max ?? null\"\r\n [step]=\"config.numberConfig?.step || 1\" [class.is-invalid]=\"errorMessage\" [readonly]=\"config.readonly\">\r\n\r\n <span class=\"input-suffix d-flex align-items-center font-weight-500\" *ngIf=\"config.suffix\">{{ config.suffix\r\n }}</span>\r\n\r\n <div class=\"readonly-icons position-absolute d-flex gap-8 pe-none\" *ngIf=\"config.readonly\">\r\n <mat-icon class=\"lock-icon\">lock</mat-icon>\r\n </div>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Date Input \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isDateField\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"input-group position-relative d-flex w-100\" [class.readonly]=\"config.readonly\">\r\n <input matInput [matDatepicker]=\"datePicker\" class=\"field-input date-input has-icon-right\"\r\n [formControlName]=\"config.name!\" [min]=\"config.dateConfig?.minDate\" [max]=\"config.dateConfig?.maxDate\"\r\n [class.is-invalid]=\"errorMessage\" [placeholder]=\"config.placeholder || ''\" [readonly]=\"config.readonly\"\r\n (click)=\"!config.readonly && datePicker.open()\">\r\n <div class=\"date-icon-wrapper position-absolute d-flex align-items-center justify-content-center\"\r\n *ngIf=\"!config.readonly\">\r\n <mat-datepicker-toggle matSuffix [for]=\"datePicker\"></mat-datepicker-toggle>\r\n </div>\r\n <mat-datepicker #datePicker></mat-datepicker>\r\n\r\n <div class=\"readonly-icons position-absolute d-flex gap-8 pe-none\" *ngIf=\"config.readonly\">\r\n <mat-icon class=\"lock-icon\">lock</mat-icon>\r\n </div>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Time Input \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isTimeField\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"input-group position-relative d-flex w-100\" [class.readonly]=\"config.readonly\">\r\n <input type=\"time\" class=\"field-input time-input\" [formControlName]=\"config.name!\"\r\n [class.is-invalid]=\"errorMessage\" [readonly]=\"!!config.readonly\">\r\n\r\n <div class=\"readonly-icons position-absolute d-flex gap-8 pe-none\" *ngIf=\"config.readonly\">\r\n <mat-icon class=\"lock-icon\">lock</mat-icon>\r\n </div>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Autocomplete \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isAutocomplete\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <!-- Hidden real control (stores the code value) -->\r\n <input type=\"hidden\" [formControlName]=\"config.name!\">\r\n\r\n <div class=\"autocomplete-wrapper position-relative d-flex align-items-center w-100\"\r\n [class.is-invalid]=\"errorMessage\" [class.readonly]=\"config.readonly\">\r\n <!-- Search icon -->\r\n <mat-icon class=\"ac-search-icon position-absolute fs-1-1rem c-9CA3AF pe-none\">search</mat-icon>\r\n\r\n <input class=\"field-input ac-input\" [formControl]=\"autocompleteInputCtrl\" [matAutocomplete]=\"auto\"\r\n [placeholder]=\"config.placeholder || 'Search\u2026'\" [readonly]=\"!!config.readonly\" [class.is-invalid]=\"errorMessage\"\r\n (blur)=\"onAutocompleteClear()\" autocomplete=\"off\">\r\n\r\n <!-- Clear button -->\r\n <button type=\"button\"\r\n class=\"ac-clear-btn position-absolute d-flex align-items-center justify-content-center cursor-pointer rounded-50 b-none border-none c-9CA3AF p-0-2rem\"\r\n *ngIf=\"autocompleteInputCtrl.value && !config.readonly\"\r\n (click)=\"autocompleteInputCtrl.setValue(''); updateValue(null)\" tabindex=\"-1\" aria-label=\"Clear\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n\r\n <mat-autocomplete #auto=\"matAutocomplete\" [panelWidth]=\"'auto'\">\r\n <mat-option *ngFor=\"let option of filteredOptions\" [value]=\"option.label\"\r\n (onSelectionChange)=\"onAutocompleteSelected(option)\">\r\n {{ option.label }}\r\n </mat-option>\r\n <mat-option *ngIf=\"filteredOptions.length === 0\" disabled class=\"ac-no-results fs-0-8125rem c-6B7280\">\r\n No results found\r\n </mat-option>\r\n </mat-autocomplete>\r\n\r\n <div class=\"readonly-icons position-absolute d-flex gap-8 pe-none\" *ngIf=\"config.readonly\">\r\n <mat-icon class=\"lock-icon\">lock</mat-icon>\r\n </div>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Dropdown \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isDropdown\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <select *ngIf=\"config.subType === 'SINGLE'\" class=\"field-input\" [formControlName]=\"config.name!\"\r\n [class.is-invalid]=\"errorMessage\">\r\n <option [ngValue]=\"null\" disabled selected>{{ config.placeholder || 'Select' }}</option>\r\n <option *ngFor=\"let option of config.optionConfig?.optionList\" [value]=\"option.code\">\r\n {{ option.label }}\r\n </option>\r\n </select>\r\n\r\n <select *ngIf=\"config.subType === 'MULTIPLE'\" class=\"field-input\" multiple [formControlName]=\"config.name!\"\r\n [class.is-invalid]=\"errorMessage\">\r\n <option *ngFor=\"let option of config.optionConfig?.optionList\" [value]=\"option.code\">\r\n {{ option.label }}\r\n </option>\r\n </select>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Radio \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isRadio\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"radio-group\" [class.is-invalid]=\"errorMessage\"\r\n [class]=\"config.optionConfig?.layout ? 'layout-' + config.optionConfig!.layout.toLowerCase() : ''\">\r\n <label *ngFor=\"let option of config.optionConfig?.optionList\" class=\"radio-label\"\r\n [class.card-item]=\"config.subType === 'CARD'\"\r\n [class.selected]=\"formGroup.get(config.name!)?.value === option.code\"\r\n [style.gridColumn]=\"config.optionConfig?.layout?.toUpperCase() === 'COLUMN' ? 'span ' + getOptionColSpan(option) : null\">\r\n <input type=\"radio\" [formControlName]=\"config.name!\" [value]=\"option.code\">\r\n <div class=\"option-content d-flex flex-column gap-4 flex-1 text-left\">\r\n <span class=\"label-text text-16 c-1F2937\">{{ option.label }}</span>\r\n <span class=\"option-hint text-13 color-gray\" *ngIf=\"option.hint\">{{ option.hint }}</span>\r\n </div>\r\n </label>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Checkbox \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isCheckbox\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label && config.subType === 'LIST'\"\r\n class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div *ngIf=\"config.subType === 'BOOL'\" class=\"checkbox-single\">\r\n <label class=\"checkbox-label d-flex align-items-center gap-8 cursor-pointer fs-0-875rem c-111827\">\r\n <input type=\"checkbox\" [formControlName]=\"config.name!\" [class.is-invalid]=\"errorMessage\">\r\n <span>{{ config.label }}</span>\r\n </label>\r\n </div>\r\n\r\n <div *ngIf=\"config.subType === 'LIST' || config.subType === 'CARD'\" class=\"checkbox-group d-flex flex-column gap-8\"\r\n [class.is-invalid]=\"errorMessage\"\r\n [class]=\"config.optionConfig?.layout ? 'layout-' + config.optionConfig!.layout.toLowerCase() : ''\">\r\n <label *ngFor=\"let option of config.optionConfig?.optionList\"\r\n class=\"checkbox-label d-flex align-items-center gap-8 cursor-pointer fs-0-875rem c-111827\"\r\n [class.card-item]=\"config.subType === 'CARD'\" [class.selected]=\"isChecked(option.code)\"\r\n [style.gridColumn]=\"config.optionConfig?.layout?.toUpperCase() === 'COLUMN' ? 'span ' + getOptionColSpan(option) : null\">\r\n <input type=\"checkbox\" [checked]=\"isChecked(option.code)\" [disabled]=\"!!config.disabled\"\r\n (change)=\"onCheckboxListChange(option.code, $any($event.target).checked)\">\r\n <div class=\"option-content d-flex flex-column gap-4 flex-1 text-left\">\r\n <span class=\"label-text text-16 c-1F2937\">{{ option.label }}</span>\r\n <span class=\"option-hint text-13 color-gray\" *ngIf=\"option.hint\">{{ option.hint }}</span>\r\n </div>\r\n </label>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Chip \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isChip\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"chip-group d-flex flex-wrap gap-8\" [class.is-invalid]=\"errorMessage\">\r\n <label *ngFor=\"let option of config.optionConfig?.optionList\"\r\n class=\"chip-label cursor-pointer p-6px-14px b-ffffff c-374151 b-1px-solid-D1D5DB br-20px fs-0-875rem\"\r\n [class.selected]=\"isChecked(option.code)\">\r\n <input type=\"checkbox\" [checked]=\"isChecked(option.code)\" [disabled]=\"!!config.disabled\"\r\n (change)=\"onCheckboxListChange(option.code, $any($event.target).checked)\" hidden>\r\n <span>{{ option.label }}</span>\r\n </label>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Switch \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isSwitch\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label class=\"switch-container d-flex justify-content-between align-items-center cursor-pointer\">\r\n <span class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">{{ config.label }}</span>\r\n <div class=\"switch position-relative\">\r\n <input type=\"checkbox\" [formControlName]=\"config.name!\" [class.is-invalid]=\"errorMessage\">\r\n <span class=\"slider position-absolute cursor-pointer\"></span>\r\n </div>\r\n </label>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Rich Text \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isRichText\" class=\"field-wrapper component-rich-text d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"rich-text-container\" [class.is-invalid]=\"errorMessage\">\r\n <quill-editor [formControlName]=\"config.name!\" class=\"rich-text-editor d-block w-100\"\r\n [placeholder]=\"config.richTextConfig?.placeholder || config.placeholder || ''\"\r\n [styles]=\"{height: config.richTextConfig?.height || '200px'}\">\r\n </quill-editor>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n <div class=\"char-count-hint font-poppins font-weight-400 text-14 text-right mt-4 c-6B7280\" *ngIf=\"showCharCount\">\r\n {{ remainingCharacters }} characters remaining\r\n </div>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Rating \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isRating\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"rating-group d-flex gap-4\" [class.is-invalid]=\"errorMessage\">\r\n <span *ngFor=\"let star of getStarArray()\" class=\"star d-inline-flex align-items-center cursor-pointer\"\r\n [class.filled]=\"isStarFilled(star)\" [class.half]=\"isStarHalf(star)\" (click)=\"onRatingChange(star, $event)\">\r\n <mat-icon>{{ isStarFilled(star) || isStarHalf(star) ? 'star' : 'star_border' }}</mat-icon>\r\n </span>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Generated Field (read-only) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isGenerated\" class=\"field-wrapper d-flex flex-column gap-6\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">{{ config.label\r\n }}</label>\r\n <div class=\"generated-value fs-0-875rem p-0-625rem-0-875rem b-F3F4F6 b-1px-solid-E5E7EB br-8px c-6B7280\">{{ value ||\r\n '-' }}</div>\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint\">{{ config.hint }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 File Upload \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isFileUpload\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <!-- Drop Zone -->\r\n <div\r\n class=\"upload-drop-zone d-flex flex-column align-items-center justify-content-center gap-8 cursor-pointer text-center p-32px-24px us-none b-1-5px-dashed-CBD5E1 br-12px bc-FFFAF1\"\r\n [class.drag-over]=\"isDragOver\" [class.has-files]=\"value?.length\" [class.is-invalid]=\"errorMessage\"\r\n (dragover)=\"onDragOver($event)\" (dragleave)=\"onDragLeave($event)\" (drop)=\"onFileDrop($event)\"\r\n (click)=\"fileInput.click()\">\r\n\r\n <div class=\"upload-icon-wrap mb-4 c-94A3B8\">\r\n <mat-icon class=\"upload-cloud-icon\">cloud_upload</mat-icon>\r\n </div>\r\n\r\n <p class=\"upload-main-text font-weight-600 m-0 c-1E293B fs-0-9rem\">Drag and drop files here or <span\r\n class=\"upload-link c-3B82F6\">click to upload</span></p>\r\n <p class=\"upload-hint-text m-0 fs-0-78rem c-64748B\" *ngIf=\"config.attachmentConfig?.acceptLabel\">\r\n Supported formats:\r\n <span class=\"upload-formats font-weight-500 c-3B82F6\">{{ config.attachmentConfig!.acceptLabel }}</span>\r\n </p>\r\n <p class=\"upload-hint-text m-0 fs-0-78rem c-64748B\" *ngIf=\"!config.attachmentConfig?.acceptLabel && config.hint\">\r\n {{ config.hint }}\r\n </p>\r\n\r\n <!-- Hidden native file input -->\r\n <input #fileInput type=\"file\" hidden [attr.multiple]=\"config.attachmentConfig?.multiple ? true : null\"\r\n [attr.accept]=\"config.attachmentConfig?.accept || null\" (change)=\"onFileSelected($event)\">\r\n </div>\r\n\r\n <!-- Uploaded file list -->\r\n <div class=\"uploaded-list d-flex flex-column gap-8 mt-10\" *ngIf=\"value?.length\">\r\n <div *ngFor=\"let f of value; let i = index\"\r\n class=\"uploaded-item d-flex align-items-center gap-10 p-10px-14px b-ffffff b-1px-solid-E2E8F0 br-8px\"\r\n [class.uploading]=\"f.isUploading\">\r\n\r\n <!-- Uploading spinner (shown while API call is in progress) -->\r\n <ng-container *ngIf=\"f.isUploading; else fileReady\">\r\n <div class=\"upload-spinner rounded-50 b-2px-solid-E2E8F0\"></div>\r\n <div class=\"file-info flex-1 d-flex flex-column\">\r\n <span class=\"file-name font-weight-500 overflow-hidden fs-0-85rem c-1E293B\" [title]=\"f.name\">{{ f.name\r\n }}</span>\r\n <span class=\"file-size uploading-label fs-0-72rem c-94A3B8 c-3B82F6\">Uploading...</span>\r\n </div>\r\n </ng-container>\r\n\r\n <!-- Normal state once upload is done -->\r\n <ng-template #fileReady>\r\n <!-- File type icon -->\r\n <mat-icon class=\"file-type-icon\">{{ getFileIcon(f.type) }}</mat-icon>\r\n\r\n <!-- Image thumbnail (only for images) -->\r\n <img *ngIf=\"f.type?.startsWith('image') && f.dataUrl\" [src]=\"f.dataUrl\" class=\"file-thumb rounded-4\"\r\n alt=\"preview\">\r\n\r\n <!-- Name & size -->\r\n <div class=\"file-info flex-1 d-flex flex-column\">\r\n <span class=\"file-name font-weight-500 overflow-hidden fs-0-85rem c-1E293B\" [title]=\"f.name\">{{ f.name\r\n }}</span>\r\n <span class=\"file-size fs-0-72rem c-94A3B8\">{{ formatFileSize(f.size) }}</span>\r\n </div>\r\n </ng-template>\r\n\r\n <!-- Remove button \u2014 disabled while uploading -->\r\n <lib-button [variant]=\"'danger-outline'\" [disabled]=\"f.isUploading\"\r\n (click)=\"!f.isUploading && removeUploadedFile(i)\">\r\n <mat-icon>close</mat-icon>\r\n </lib-button>\r\n </div>\r\n </div>\r\n\r\n <!-- Validation / file errors -->\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"fileUploadError\">{{ fileUploadError }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage && !fileUploadError\">{{ errorMessage }}</span>\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\"\r\n *ngIf=\"config.hint && !errorMessage && !fileUploadError && !config.attachmentConfig?.acceptLabel\">\r\n {{ config.hint }}\r\n </span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Media Upload (Type 2) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isMediaUpload\" class=\"field-wrapper media-upload-wrapper d-flex flex-column gap-6 p-0 border-none b-none\"\r\n [formGroup]=\"formGroup\">\r\n\r\n <!-- Hidden file input lives outside *ngIf \u2014 triggered via ViewChild -->\r\n <input #mediaDeviceInput type=\"file\" hidden multiple accept=\"image/*\" (change)=\"onMediaFileSelected($event)\">\r\n\r\n <!-- Two-column layout -->\r\n <div class=\"mu-layout d-grid align-items-start\">\r\n\r\n <!-- \u2500\u2500 LEFT PANEL \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <div class=\"mu-left d-flex flex-column gap-20\">\r\n\r\n <!-- Header: title + max-items badge -->\r\n <div class=\"mu-header d-flex align-items-start flex-wrap gap-10\">\r\n <h3 class=\"mu-title m-0 c-111827 fs-1-35rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </h3>\r\n <span\r\n class=\"mu-badge d-inline-flex align-items-center rounded-20 color-white font-weight-600 fs-0-72rem p-4px-12px b-111827\"\r\n *ngIf=\"config.attachmentConfig?.maxFiles\">\r\n {{ controller.labels['LBL_MEDIA_MAX_PREFIX'] || 'Maximum' }}\r\n {{ config.attachmentConfig?.maxFiles }}\r\n {{ controller.labels['LBL_MEDIA_MAX_SUFFIX'] || 'Image & Videos' }}\r\n </span>\r\n </div>\r\n\r\n <!-- Description -->\r\n <p class=\"mu-description m-0 fs-0-875rem c-6B7280\" *ngIf=\"config.attachmentConfig?.description\">\r\n {{ config.attachmentConfig?.description }}\r\n </p>\r\n <p class=\"mu-description m-0 fs-0-875rem c-6B7280\"\r\n *ngIf=\"!config.attachmentConfig?.description && controller.labels['LBL_MEDIA_DESC']\">\r\n {{ controller.labels['LBL_MEDIA_DESC'] }}\r\n </p>\r\n\r\n <!-- Feature bullet list -->\r\n <ul class=\"mu-features m-0 p-0 d-flex flex-column gap-8 ls-none\"\r\n *ngIf=\"config.attachmentConfig?.features?.length || controller.labels['LBL_MEDIA_FEATURE_1']\">\r\n <ng-container *ngIf=\"config.attachmentConfig?.features?.length\">\r\n <li *ngFor=\"let f of config.attachmentConfig?.features\"\r\n class=\"mu-feature-item d-flex align-items-center gap-8 fs-0-875rem c-374151\">\r\n <mat-icon class=\"mu-check text-16 c-3B82F6\">check</mat-icon>{{ f }}\r\n </li>\r\n </ng-container>\r\n <ng-container *ngIf=\"!config.attachmentConfig?.features?.length\">\r\n <li *ngIf=\"controller.labels['LBL_MEDIA_FEATURE_1']\"\r\n class=\"mu-feature-item d-flex align-items-center gap-8 fs-0-875rem c-374151\">\r\n <mat-icon class=\"mu-check text-16 c-3B82F6\">check</mat-icon>{{ controller.labels['LBL_MEDIA_FEATURE_1'] }}\r\n </li>\r\n <li *ngIf=\"controller.labels['LBL_MEDIA_FEATURE_2']\"\r\n class=\"mu-feature-item d-flex align-items-center gap-8 fs-0-875rem c-374151\">\r\n <mat-icon class=\"mu-check text-16 c-3B82F6\">check</mat-icon>{{ controller.labels['LBL_MEDIA_FEATURE_2'] }}\r\n </li>\r\n <li *ngIf=\"controller.labels['LBL_MEDIA_FEATURE_3']\"\r\n class=\"mu-feature-item d-flex align-items-center gap-8 fs-0-875rem c-374151\">\r\n <mat-icon class=\"mu-check text-16 c-3B82F6\">check</mat-icon>{{ controller.labels['LBL_MEDIA_FEATURE_3'] }}\r\n </li>\r\n </ng-container>\r\n </ul>\r\n\r\n <!-- Backdrop to close dropdown on outside click -->\r\n <div class=\"media-menu-backdrop\" *ngIf=\"showMediaMenu\"\r\n (click)=\"$event.stopPropagation(); showMediaMenu = false\"></div>\r\n\r\n <!-- Add Media button + dropdown -->\r\n <div class=\"media-add-container position-relative\" (click)=\"showMediaMenu = !showMediaMenu\">\r\n <lib-button id=\"btn-add-media-{{ config.name }}\" [variant]=\"'warning'\"\r\n [icon]=\"{type: 'material', value: 'add_photo_alternate'}\">\r\n {{ controller.labels['LBL_ADD_MEDIA'] || 'Add media' }}\r\n <mat-icon class=\"menu-chevron fs-18px\">add</mat-icon>\r\n </lib-button>\r\n\r\n <div class=\"media-dropdown position-absolute rounded-12 overflow-hidden b-ffffff b-1px-solid-E5E7EB\"\r\n *ngIf=\"showMediaMenu\" role=\"menu\" (click)=\"$event.stopPropagation()\">\r\n <!-- Video -->\r\n <button id=\"btn-media-video-{{ config.name }}\" type=\"button\"\r\n class=\"media-dropdown-item d-flex align-items-center gap-12 w-100 cursor-pointer text-left b-none border-none p-12px-16px bb-1px-solid-F3F4F6\"\r\n (click)=\"onMediaMenuVideo(); showMediaMenu = false\" role=\"menuitem\">\r\n <span\r\n class=\"media-drop-icon media-drop-icon--video d-flex align-items-center justify-content-center rounded-8\"><mat-icon>videocam</mat-icon></span>\r\n <span class=\"media-drop-text d-flex flex-column flex-1\">\r\n <span class=\"media-drop-label font-weight-600 fs-0-875rem c-111827\">{{\r\n controller.labels['LBL_MEDIA_VIDEO'] || 'Video' }}</span>\r\n <span class=\"media-drop-desc c-6B7280 fs-0-75rem\">{{ controller.labels['LBL_MEDIA_VIDEO_DESC'] || 'Add\r\n YouTube URL'\r\n }}</span>\r\n </span>\r\n </button>\r\n <!-- Device -->\r\n <button id=\"btn-media-device-{{ config.name }}\" type=\"button\"\r\n class=\"media-dropdown-item d-flex align-items-center gap-12 w-100 cursor-pointer text-left b-none border-none p-12px-16px bb-1px-solid-F3F4F6\"\r\n (click)=\"onMediaMenuDevice(); showMediaMenu = false\" role=\"menuitem\">\r\n <span\r\n class=\"media-drop-icon media-drop-icon--device d-flex align-items-center justify-content-center rounded-8\"><mat-icon>upload</mat-icon></span>\r\n <span class=\"media-drop-text d-flex flex-column flex-1\">\r\n <span class=\"media-drop-label font-weight-600 fs-0-875rem c-111827\">{{\r\n controller.labels['LBL_MEDIA_DEVICE'] || 'Upload from device'\r\n }}</span>\r\n <span class=\"media-drop-desc c-6B7280 fs-0-75rem\">{{ controller.labels['LBL_MEDIA_DEVICE_DESC'] ||\r\n 'Select images from your\r\n computer' }}</span>\r\n </span>\r\n </button>\r\n <!-- Library -->\r\n <button id=\"btn-media-library-{{ config.name }}\" type=\"button\"\r\n class=\"media-dropdown-item d-flex align-items-center gap-12 w-100 cursor-pointer text-left b-none border-none p-12px-16px bb-1px-solid-F3F4F6\"\r\n (click)=\"onMediaMenuLibrary(); showMediaMenu = false\" role=\"menuitem\">\r\n <span\r\n class=\"media-drop-icon media-drop-icon--library d-flex align-items-center justify-content-center rounded-8\"><mat-icon>photo_library</mat-icon></span>\r\n <span class=\"media-drop-text d-flex flex-column flex-1\">\r\n <span class=\"media-drop-label font-weight-600 fs-0-875rem c-111827\">{{\r\n controller.labels['LBL_MEDIA_LIBRARY'] || 'Upload from library'\r\n }}</span>\r\n <span class=\"media-drop-desc c-6B7280 fs-0-75rem\">{{ controller.labels['LBL_MEDIA_LIBRARY_DESC'] ||\r\n 'Choose from default\r\n images' }}</span>\r\n </span>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- YouTube URL Input (inline below button) -->\r\n <div class=\"youtube-input-panel d-flex flex-column gap-8 p-16 rounded-10 b-FFFAF1 b-1px-solid-E5E7EB\"\r\n *ngIf=\"showYoutubeInput\">\r\n <label class=\"youtube-panel-label d-flex align-items-center gap-6 font-weight-600 fs-0-875rem c-111827\">\r\n {{ controller.labels['LBL_YOUTUBE_URL'] || 'Video URL' }}\r\n </label>\r\n <div class=\"youtube-input-row d-flex gap-8\">\r\n <input id=\"input-youtube-url-{{ config.name }}\" type=\"url\" class=\"field-input youtube-url-input\"\r\n [(ngModel)]=\"youtubeUrlInput\" [ngModelOptions]=\"{standalone: true}\"\r\n [placeholder]=\"controller.labels['PH_YOUTUBE_URL'] || 'Video URL'\" (keyup.enter)=\"addYoutubeMedia()\">\r\n <lib-button id=\"btn-add-youtube-{{ config.name }}\" [variant]=\"'secondary'\" (click)=\"addYoutubeMedia()\">\r\n {{ controller.labels['LBL_ADD'] || 'Add' }}\r\n </lib-button>\r\n </div>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"youtubeUrlError\">{{ youtubeUrlError }}</span>\r\n </div>\r\n\r\n <div\r\n class=\"media-upload-status d-flex align-items-center gap-8 mt-4 color-error rounded-8 font-weight-500 p-10px-14px b-FEF2F2 fs-0-85rem\"\r\n *ngIf=\"mediaUploadError\">\r\n <mat-icon class=\"status-icon fs-18px\">error_outline</mat-icon>\r\n <span>{{ mediaUploadError }}</span>\r\n </div>\r\n\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n </div>\r\n <!-- end left panel -->\r\n\r\n <!-- \u2500\u2500 RIGHT PANEL (carousel) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <div class=\"mu-right d-flex flex-column gap-12\">\r\n\r\n <!-- Carousel (when items exist) -->\r\n <div class=\"media-carousel-section d-flex flex-column gap-12\" *ngIf=\"mediaItems.length\">\r\n <div\r\n class=\"media-carousel-main position-relative w-100 overflow-hidden d-flex align-items-center justify-content-center br-12px b-0F172A\">\r\n <button id=\"btn-carousel-prev-{{ config.name }}\" type=\"button\"\r\n class=\"carousel-nav carousel-nav--prev position-absolute rounded-50 cursor-pointer d-flex align-items-center justify-content-center border-none b-rgba-255-255-255-0-85\"\r\n (click)=\"mediaCarouselPrev()\" [disabled]=\"mediaCarouselIndex === 0\" aria-label=\"Previous\">\r\n <mat-icon>chevron_left</mat-icon>\r\n </button>\r\n\r\n <div class=\"carousel-viewer position-absolute d-flex align-items-center justify-content-center\"\r\n *ngFor=\"let item of mediaItems; let i = index\" [hidden]=\"i !== mediaCarouselIndex\">\r\n <div *ngIf=\"item.isUploading\"\r\n class=\"carousel-uploading d-flex flex-column align-items-center gap-12 c-94A3B8 fs-0-85rem\">\r\n <div class=\"carousel-spinner rounded-50 b-3px-solid-rgba-255-255-255-0-15\"></div>\r\n <span>{{ controller.labels['LBL_UPLOADING'] || 'Uploading\u2026' }}</span>\r\n </div>\r\n <ng-container *ngIf=\"!item.isUploading && item.mediaType === 'youtube'\">\r\n <iframe class=\"carousel-iframe w-100 h-100 br-12px\" [src]=\"item.url | trustedUrl\" frameborder=\"0\"\r\n allowfullscreen\r\n allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\">\r\n </iframe>\r\n </ng-container>\r\n <ng-container *ngIf=\"!item.isUploading && item.mediaType === 'image'\">\r\n <img class=\"carousel-image w-100 h-100 br-12px\" [src]=\"item.url\" alt=\"Media\">\r\n </ng-container>\r\n <button id=\"btn-remove-media-{{ config.name }}-{{ i }}\" type=\"button\"\r\n class=\"carousel-remove-btn position-absolute rounded-50 cursor-pointer d-flex align-items-center justify-content-center border-none b-rgba-0-0-0-0-55\"\r\n [disabled]=\"item.isUploading\" (click)=\"removeMediaItem(i)\" aria-label=\"Remove\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <button id=\"btn-carousel-next-{{ config.name }}\" type=\"button\"\r\n class=\"carousel-nav carousel-nav--next position-absolute rounded-50 cursor-pointer d-flex align-items-center justify-content-center border-none b-rgba-255-255-255-0-85\"\r\n (click)=\"mediaCarouselNext()\" [disabled]=\"mediaCarouselIndex === mediaItems.length - 1\" aria-label=\"Next\">\r\n <mat-icon>chevron_right</mat-icon>\r\n </button>\r\n\r\n <div class=\"carousel-dots position-absolute d-flex gap-6\">\r\n <span *ngFor=\"let item of mediaItems; let i = index\"\r\n class=\"carousel-dot rounded-50 cursor-pointer b-rgba-255-255-255-0-45\"\r\n [class.active]=\"i === mediaCarouselIndex\" (click)=\"mediaGoTo(i)\"></span>\r\n </div>\r\n </div>\r\n\r\n <!-- Thumbnail strip -->\r\n <div class=\"media-thumbnail-strip d-flex flex-wrap gap-8 pb-4px\">\r\n <div *ngFor=\"let item of mediaThumbnails; let i = index\"\r\n class=\"media-thumb rounded-8 overflow-hidden cursor-pointer d-flex align-items-center justify-content-center b-2px-solid-transparent b-E2E8F0\"\r\n [class.active]=\"i === mediaCarouselIndex\" (click)=\"mediaGoTo(i)\">\r\n <div *ngIf=\"item.isUploading\"\r\n class=\"thumb-uploading d-flex align-items-center justify-content-center w-100 h-100\">\r\n <div class=\"thumb-spinner rounded-50 b-2px-solid-E2E8F0\"></div>\r\n </div>\r\n <img *ngIf=\"!item.isUploading && item.mediaType === 'youtube' && item.thumbnailUrl\"\r\n [src]=\"item.thumbnailUrl\" class=\"thumb-img w-100 h-100\" alt=\"Video thumbnail\">\r\n <div *ngIf=\"!item.isUploading && item.mediaType === 'youtube' && !item.thumbnailUrl\"\r\n class=\"thumb-yt-placeholder d-flex align-items-center justify-content-center w-100 h-100 b-1E293B c-EF4444\">\r\n <mat-icon>play_circle</mat-icon>\r\n </div>\r\n <img *ngIf=\"!item.isUploading && item.mediaType === 'image' && item.url\" [src]=\"item.url\"\r\n class=\"thumb-img w-100 h-100\" alt=\"Image thumbnail\">\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Empty right-side placeholder -->\r\n <div\r\n class=\"mu-right-empty d-flex flex-column align-items-center justify-content-center gap-10 h-100 text-center p-24 br-12px b-FFFAF1 c-94A3B8 b-2px-dashed-CBD5E1\"\r\n *ngIf=\"!mediaItems.length\" (click)=\"onMediaMenuDevice()\">\r\n <mat-icon class=\"mu-right-empty-icon fs-52px\">perm_media</mat-icon>\r\n <p>{{ controller.labels['LBL_ADD_MEDIA'] || 'Add media' }}</p>\r\n </div>\r\n\r\n </div>\r\n <!-- end right panel -->\r\n\r\n </div><!-- end mu-layout -->\r\n </div>\r\n\r\n\r\n <!-- \u2550\u2550 Library Image Picker Modal \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div class=\"media-library-overlay b-rgba-0-0-0-0-5\" *ngIf=\"showLibraryModal\" (click)=\"closeLibraryModal()\"></div>\r\n <div class=\"media-library-modal d-flex flex-column overflow-hidden b-ffffff br-16px\" *ngIf=\"showLibraryModal\"\r\n role=\"dialog\" aria-modal=\"true\">\r\n <div class=\"library-modal-header d-flex align-items-start justify-content-between p-24px-28px bb-1px-solid-E5E7EB\">\r\n <div class=\"header-left d-flex flex-column gap-8\">\r\n <h3 class=\"library-modal-title m-0 color-dark fs-1-25rem\">\r\n {{ controller.labels['LBL_ADD_IMAGES'] || 'Add Images' }}\r\n </h3>\r\n <p class=\"library-modal-subtitle m-0 color-gray fs-0-85rem\">\r\n {{ controller.labels['LBL_LIBRARY_MODAL_DESC'] || 'Upload media to make your opportunity stand out. Plus, take\r\n full control of your sequence - drag images to reorder as you desire.' }}\r\n </p>\r\n </div>\r\n <button id=\"btn-close-library-{{ config.name }}\" type=\"button\"\r\n class=\"library-close-btn d-flex align-items-center justify-content-center cursor-pointer rounded-50 border-none b-none c-9CA3AF\"\r\n (click)=\"closeLibraryModal()\" aria-label=\"Close\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <!-- Loading -->\r\n <div class=\"library-loading\" *ngIf=\"libraryLoading\">\r\n <div class=\"lib-spinner rounded-50 b-3px-solid-E2E8F0\"></div>\r\n <span>{{ controller.labels['LBL_LOADING'] || 'Loading\u2026' }}</span>\r\n </div>\r\n\r\n <!-- Error -->\r\n <div class=\"library-error d-flex align-items-center gap-8 color-error b-FEF2F2 fs-0-875rem p-16px-24px\"\r\n *ngIf=\"libraryError && !libraryLoading\">\r\n <mat-icon>error_outline</mat-icon>\r\n {{ libraryError }}\r\n </div>\r\n\r\n <!-- Image grid -->\r\n <div class=\"library-grid d-grid gap-16 flex-1 p-28px b-F9FAFB\" *ngIf=\"!libraryLoading && libraryImages.length\">\r\n <div *ngFor=\"let img of libraryImages; let li = index\" id=\"lib-img-{{ config.name }}-{{ li }}\"\r\n class=\"library-grid-item position-relative rounded-12 overflow-hidden cursor-pointer bg-white b-3px-solid-transparent\"\r\n [class.selected]=\"isLibraryItemSelected(img)\" (click)=\"toggleLibraryItem(img)\">\r\n <img [src]=\"getLibraryItemUrl(img)\" class=\"library-grid-img w-100 h-100 d-block\" alt=\"Library image\">\r\n <div\r\n class=\"library-check position-absolute bg-white rounded-50 d-flex align-items-center justify-content-center c-3B82F6\"\r\n *ngIf=\"isLibraryItemSelected(img)\">\r\n <mat-icon>check_circle</mat-icon>\r\n </div>\r\n <div class=\"library-overlay-hover position-absolute b-rgba-59-130-246-0-12\"></div>\r\n </div>\r\n </div>\r\n\r\n <!-- Empty library -->\r\n <div\r\n class=\"library-empty d-flex flex-column align-items-center justify-content-center gap-12 flex-1 c-9CA3AF fs-0-875rem p-48px-24px\"\r\n *ngIf=\"!libraryLoading && !libraryError && libraryImages.length === 0\">\r\n <mat-icon>image_not_supported</mat-icon>\r\n <span>{{ controller.labels['LBL_LIBRARY_EMPTY'] || 'No images found in library.' }}</span>\r\n </div>\r\n\r\n <!-- Footer -->\r\n <div\r\n class=\"library-modal-footer d-flex align-items-center justify-content-end bg-white p-20px-28px bt-1px-solid-E5E7EB\">\r\n <div class=\"library-footer-actions d-flex gap-12 gap-10\">\r\n <lib-button id=\"btn-library-cancel-{{ config.name }}\" [variant]=\"'outline'\" (click)=\"closeLibraryModal()\">\r\n {{ controller.labels['LBL_CANCEL'] || 'Cancel' }}\r\n </lib-button>\r\n <lib-button id=\"btn-library-confirm-{{ config.name }}\" [variant]=\"'primary'\"\r\n [disabled]=\"librarySelectedIds.size === 0\" (click)=\"confirmLibrarySelection()\">\r\n {{ controller.labels['LBL_CONTINUE'] || 'Continue' }}\r\n </lib-button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Location Field \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isLocation\" class=\"field-wrapper location-field-wrapper d-flex flex-column gap-6 gap-12\"\r\n [formGroup]=\"formGroup\">\r\n\r\n <!-- Field label -->\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n <p class=\"location-subtitle m-0 c-6B7280 fs-0-8125rem\" *ngIf=\"config.hint\">{{ config.hint }}</p>\r\n\r\n <!-- Three-tab bar -->\r\n <div class=\"location-tabs d-flex gap-12 mb-24\">\r\n <lib-button class=\"loc-tab-btn flex-1\" [variant]=\"locationActiveTab === 'VENUE' ? 'warning' : 'outline'\"\r\n (click)=\"onLocationTabChange('VENUE')\">\r\n {{ controller.labels['LBL_LOC_VENUE'] || 'Venue' }}\r\n </lib-button>\r\n <lib-button class=\"loc-tab-btn flex-1\" [variant]=\"locationActiveTab === 'ONLINE' ? 'warning' : 'outline'\"\r\n (click)=\"onLocationTabChange('ONLINE')\">\r\n {{ controller.labels['LBL_LOC_ONLINE'] || 'Online Event' }}\r\n </lib-button>\r\n <lib-button class=\"loc-tab-btn flex-1\" [variant]=\"locationActiveTab === 'TBA' ? 'warning' : 'outline'\"\r\n (click)=\"onLocationTabChange('TBA')\">\r\n {{ controller.labels['LBL_LOC_TBA'] || 'To be Announced' }}\r\n </lib-button>\r\n </div>\r\n\r\n <!-- VENUE TAB -->\r\n <div *ngIf=\"locationActiveTab === 'VENUE'\" class=\"loc-panel loc-venue-panel d-flex flex-column gap-12\">\r\n\r\n <p class=\"loc-section-label m-0 font-weight-600 c-111827 fs-0-9rem\">\r\n {{ controller.labels['LBL_LOC_ADDRESS'] || 'Location address' }}\r\n </p>\r\n\r\n <!-- Added venue rows -->\r\n <div class=\"loc-venue-list d-flex flex-column gap-8\" *ngIf=\"locationVenues.length > 0\">\r\n <div *ngFor=\"let venue of locationVenues; let i = index\"\r\n class=\"loc-venue-item d-flex align-items-center gap-10 p-10px-14px br-7px b-ffffff b-1px-solid-D1D5DB\">\r\n <mat-icon class=\"loc-venue-search-icon fs-18px c-9CA3AF\">search</mat-icon>\r\n <span class=\"loc-venue-text flex-1 overflow-hidden fs-0-875rem c-111827\">{{ venue.address || venue.name ||\r\n venue.description }}</span>\r\n <button type=\"button\"\r\n class=\"loc-action-btn loc-delete-btn d-flex align-items-center justify-content-center cursor-pointer rounded-50 b-none border-none p-4px\"\r\n (click)=\"removeLocationVenue(i)\">\r\n <mat-icon>delete_outline</mat-icon>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- Location count badge -->\r\n <p class=\"loc-count-text m-0 font-weight-600 fs-0-8125rem c-3B82F6\"\r\n *ngIf=\"locationVenues.length > 0 && config.locationConfig?.allowMulti\">\r\n {{ locationVenues.length }} {{ controller.labels['LBL_LOC_COUNT_SUFFIX'] || 'Locations Added!' }}\r\n </p>\r\n\r\n <!-- Search input (hide when max reached) -->\r\n <div class=\"loc-search-container position-relative\" *ngIf=\"!locationMaxReached\">\r\n <div class=\"loc-search-wrapper position-relative d-flex align-items-center mt-4\">\r\n <mat-icon class=\"loc-search-icon position-absolute fs-1-1rem c-9CA3AF pe-none\">search</mat-icon>\r\n <input\r\n class=\"field-input loc-search-input w-100 font-poppins flex-1 fs-0-875rem c-111827 br-7px br-8px bc-F3F4F6 pl-2-4rem bc-DC2626 pt-0-625rem pb-0-625rem pl-16px pr-16px bc-ffffff b-1px-solid-D1D5DB pr-3-5rem\"\r\n [placeholder]=\"config.locationConfig?.venuePlaceholder || (controller.labels['PH_LOC_VENUE'] || 'Type to search venue...')\"\r\n [value]=\"locationSearchText\" (input)=\"handleLocationSearchInput($event)\" (blur)=\"hideLocationSuggestions()\"\r\n autocomplete=\"off\" [class.is-invalid]=\"errorMessage\">\r\n </div>\r\n <!-- Suggestions dropdown -->\r\n <div class=\"loc-suggestions-panel position-absolute overflow-hidden br-8px b-ffffff b-1px-solid-D1D5DB\"\r\n *ngIf=\"locationShowSuggestions && locationSuggestions.length\">\r\n <div *ngFor=\"let sug of locationSuggestions\"\r\n class=\"loc-suggestion-item d-flex align-items-center gap-10 cursor-pointer p-10px-14px\"\r\n (mousedown)=\"onLocationSuggestionSelect(sug)\">\r\n <mat-icon class=\"loc-suggestion-icon fs-18px c-E53E3E\">place</mat-icon>\r\n <span class=\"loc-suggestion-text overflow-hidden fs-0-875rem c-374151\">{{ sug.description }}</span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Add another button -->\r\n <button type=\"button\"\r\n class=\"loc-add-btn d-inline-flex align-items-center gap-6 cursor-pointer font-weight-600 p-0 b-none border-none fs-0-875rem c-1A56DB\"\r\n *ngIf=\"locationVenues.length > 0 && !locationMaxReached && config.locationConfig?.allowMulti\">\r\n <mat-icon>add_circle_outline</mat-icon>\r\n <span>{{ controller.labels['LBL_LOC_ADD_ANOTHER'] || 'Add another Location' }}</span>\r\n </button>\r\n\r\n <!-- Map -->\r\n <div class=\"loc-map-container overflow-hidden br-10px b-1px-solid-E5E7EB\"\r\n *ngIf=\"config.locationConfig?.showMap !== false\">\r\n <ng-container *ngIf=\"config.locationConfig?.googleMapsApiKey; else simpleEmbed\">\r\n <div [id]=\"'loc-map-' + config.name\" class=\"loc-map-frame w-100 d-block border-none\"\r\n [style.height]=\"config.locationConfig?.mapHeight || '300px'\"></div>\r\n </ng-container>\r\n <ng-template #simpleEmbed>\r\n <iframe class=\"loc-map-frame w-100 d-block border-none\"\r\n [style.height]=\"config.locationConfig?.mapHeight || '300px'\" [src]=\"getLocationMapEmbedUrl() | trustedUrl\"\r\n frameborder=\"0\" allowfullscreen loading=\"lazy\">\r\n </iframe>\r\n </ng-template>\r\n </div>\r\n\r\n <!-- Map hint -->\r\n <p class=\"loc-map-hint m-0 text-center fs-0-78rem c-6B7280\">\r\n {{ controller.labels['LBL_LOC_MAP_HINT'] || 'Type the venue address. A map will appear to assist you.' }}\r\n </p>\r\n </div>\r\n\r\n <!-- ONLINE TAB -->\r\n <div *ngIf=\"locationActiveTab === 'ONLINE'\" class=\"loc-panel loc-online-panel d-flex flex-column gap-12\">\r\n <p class=\"loc-section-label m-0 font-weight-600 c-111827 fs-0-9rem\">\r\n {{ controller.labels['LBL_LOC_ONLINE_URL'] || 'Event URL' }}\r\n </p>\r\n <div class=\"loc-search-wrapper position-relative d-flex align-items-center mt-4\">\r\n <mat-icon class=\"loc-search-icon position-absolute fs-1-1rem c-9CA3AF pe-none\">link</mat-icon>\r\n <input\r\n class=\"field-input loc-search-input w-100 font-poppins flex-1 fs-0-875rem c-111827 br-7px br-8px bc-F3F4F6 pl-2-4rem bc-DC2626 pt-0-625rem pb-0-625rem pl-16px pr-16px bc-ffffff b-1px-solid-D1D5DB pr-3-5rem\"\r\n type=\"url\"\r\n [placeholder]=\"config.locationConfig?.onlinePlaceholder || (controller.labels['PH_LOC_ONLINE'] || 'https://zoom.us/j/...')\"\r\n [value]=\"locationOnlineUrl\" (input)=\"onLocationUrlChange($any($event.target).value)\"\r\n [class.is-invalid]=\"errorMessage\">\r\n </div>\r\n </div>\r\n\r\n <!-- TBA TAB -->\r\n <div *ngIf=\"locationActiveTab === 'TBA'\"\r\n class=\"loc-panel loc-tba-panel d-flex flex-column gap-12 justify-content-center\">\r\n <div\r\n class=\"loc-tba-content d-flex flex-column align-items-center justify-content-center text-center gap-12 p-32px-24px b-F9FAFB b-1px-dashed-D1D5DB br-10px\">\r\n <mat-icon class=\"loc-tba-icon fs-40px c-9CA3AF\">schedule</mat-icon>\r\n <p class=\"loc-tba-text m-0 c-6B7280 fs-0-9rem\">\r\n {{ controller.labels['LBL_LOC_TBA_DESC'] || \"This event's location is yet to be announced. Check back later\r\n for updates.\" }}\r\n </p>\r\n </div>\r\n </div>\r\n\r\n <!-- Hidden real form control -->\r\n <input type=\"hidden\" [formControlName]=\"config.name!\">\r\n\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n</div>", styles: [".d-flex{display:flex}.d-inline-flex{display:inline-flex}.d-grid{display:grid}.d-block{display:block}.d-none{display:none}.flex-column{flex-direction:column}.flex-row{flex-direction:row}.flex-row-reverse{flex-direction:row-reverse}.flex-wrap{flex-wrap:wrap}.flex-1{flex:1}.align-items-center{align-items:center}.align-items-start{align-items:flex-start}.align-items-end{align-items:flex-end}.justify-content-center{justify-content:center}.justify-content-between{justify-content:space-between}.justify-content-start{justify-content:flex-start}.justify-content-end{justify-content:flex-end}.grid-cols-12{grid-template-columns:repeat(12,1fr)}.w-100{width:100%}.h-100{height:100%}.position-relative{position:relative}.position-absolute{position:absolute}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.font-poppins{font-family:var(--cc-sf-font-family, \"Poppins\", sans-serif)}.font-weight-400{font-weight:400}.font-weight-500{font-weight:500}.font-weight-600{font-weight:600}.text-13{font-size:13px}.text-14{font-size:14px}.text-16{font-size:16px}.color-white{color:#fff}.color-dark{color:#111827}.color-gray{color:#6b7280}.color-error{color:var(--cc-sf-error-text-color, #DC2626)}.bg-white{background-color:#fff}.bg-transparent{background-color:transparent}.m-0{margin:0}.mt-4{margin-top:4px}.mt-8{margin-top:8px}.mt-10{margin-top:10px}.mt-12{margin-top:12px}.mt-16{margin-top:16px}.mt-20{margin-top:20px}.mt-24{margin-top:24px}.mb-0{margin-bottom:0}.mb-4{margin-bottom:4px}.mb-8{margin-bottom:8px}.mb-10{margin-bottom:10px}.mb-12{margin-bottom:12px}.mb-16{margin-bottom:16px}.mb-20{margin-bottom:20px}.mb-24{margin-bottom:24px}.ml-16{margin-left:16px}.ml-20{margin-left:20px}.p-0{padding:0}.p-16{padding:16px}.p-20{padding:20px}.p-24{padding:24px}.pt-20{padding-top:20px}.pb-10{padding-bottom:10px}.gap-4{gap:4px}.gap-6{gap:6px}.gap-8{gap:8px}.gap-10{gap:10px}.gap-12{gap:12px}.gap-16{gap:16px}.gap-20{gap:20px}.rounded-4{border-radius:4px}.rounded-6{border-radius:6px}.rounded-8{border-radius:8px}.rounded-10{border-radius:10px}.rounded-12{border-radius:12px}.rounded-20{border-radius:20px}.rounded-24{border-radius:24px}.rounded-50{border-radius:50%}.cursor-pointer{cursor:pointer}.overflow-hidden{overflow:hidden}.resize-vertical{resize:vertical}.box-sizing-border{box-sizing:border-box}.border-none{border:none!important}.mb-16px{margin-bottom:var(--cc-sf-grid-gap, 16px)!important}.c-DC2626{color:var(--cc-sf-label-required-color, #DC2626)!important}.ml-0-125rem{margin-left:.125rem!important}.fs-0-875rem{font-size:.875rem!important}.c-111827{color:var(--cc-sf-label-color, #111827)!important}.br-7px{border-radius:var(--cc-sf-input-radius, 7px)!important}.c-6B7280{color:var(--cc-sf-hint-color, #6B7280)!important}.fs-0-75rem{font-size:var(--cc-sf-error-text-size, .75rem)!important}.b-none{background:none!important}.p-32px-24px{padding:32px 24px!important}.us-none{-webkit-user-select:none!important;user-select:none!important}.c-1E293B{color:var(--cc-sf-label-color, #1E293B)!important}.c-3B82F6{color:var(--cc-sf-chip-selected-bg, #3B82F6)!important}.fs-0-78rem{font-size:.78rem!important}.p-10px-14px{padding:10px 14px!important}.fs-0-85rem{font-size:.85rem!important}.fs-0-72rem{font-size:.72rem!important}.c-94A3B8{color:#94a3b8!important}.p-4px{padding:4px!important}.br-8px{border-radius:var(--cc-sf-input-radius, 8px)!important}.bc-F3F4F6{background-color:var(--cc-sf-input-disabled-bg, #F3F4F6)!important}.br-none{border-right:none!important}.bl-none{border-left:none!important}.pe-none{pointer-events:none!important}.fs-1-1rem{font-size:1.1rem!important}.c-9CA3AF{color:var(--cc-sf-hint-color, #9CA3AF)!important}.pl-2-4rem{padding-left:2.4rem!important}.fs-0-8125rem{font-size:.8125rem!important}.ls-none{list-style:none!important}.br-12px{border-radius:var(--mu-carousel-radius, 12px)!important}.b-FFFAF1{background:var(--cc-sf-dropzone-bg, #FFFAF1)!important}.fs-18px{font-size:18px!important}.b-FEF2F2{background:var(--cc-sf-error-bg, #FEF2F2)!important}.bc-DC2626{border-color:var(--cc-sf-error-border, #DC2626)!important}.c-202124{color:var(--cc-sf-label-color, #202124)!important}.fs-18px{font-size:var(--cc-sf-label-size, 18px)!important}.mb-0-5rem{margin-bottom:.5rem!important}.pt-0-625rem{padding-top:var(--cc-sf-input-padding-y, .625rem)!important}.pb-0-625rem{padding-bottom:var(--cc-sf-input-padding-y, .625rem)!important}.pl-16px{padding-left:var(--cc-sf-input-padding-x, 16px)!important}.pr-16px{padding-right:var(--cc-sf-input-padding-x, 16px)!important}.bc-ffffff{background-color:var(--cc-sf-section-bg, #ffffff)!important}.b-1px-solid-D1D5DB{border:1px solid var(--cc-sf-input-border, #D1D5DB)!important}.fs-0-75rem{font-size:.75rem!important}.c-1F2937{color:var(--cc-sf-section-label-color, #1F2937)!important}.p-6px-14px{padding:var(--cc-sf-chip-padding, 6px 14px)!important}.b-ffffff{background:var(--loc-suggestion-bg, #ffffff)!important}.c-374151{color:var(--cc-sf-label-color, #374151)!important}.br-20px{border-radius:var(--cc-sf-chip-radius, 20px)!important}.fs-0-875rem{font-size:var(--cc-sf-btn-font-size, .875rem)!important}.bc-D1D5DB{background-color:var(--cc-sf-switch-track-off, #D1D5DB)!important}.pr-2-75rem{padding-right:2.75rem!important}.p-0-25rem{padding:.25rem!important}.p-0-625rem-0-875rem{padding:var(--cc-sf-generated-padding, .625rem .875rem)!important}.b-F3F4F6{background:var(--cc-sf-generated-bg, #F3F4F6)!important}.b-1px-solid-E5E7EB{border:1px solid var(--cc-sf-input-disabled-border, #E5E7EB)!important}.br-8px{border-radius:var(--cc-sf-uploaded-item-radius, 8px)!important}.c-6B7280{color:var(--ms-desc-color, #6B7280)!important}.mb-20px{margin-bottom:var(--cc-sf-section-gap, 20px)!important}.br-10px{border-radius:var(--cc-sf-input-radius, 10px)!important}.p-20px{padding:var(--cc-sf-section-padding, 20px)!important}.fs-1rem{font-size:1rem!important}.m-0-0-16px-0{margin:0 0 16px!important}.bb-2px-solid-E5E7EB{border-bottom:var(--cc-sf-section-label-border, 2px solid #E5E7EB)!important}.p-16px{padding:var(--cc-sf-instance-padding, 16px)!important}.b-F9FAFB{background:var(--loc-tba-bg, #F9FAFB)!important}.bb-1px-dashed-D1D5DB{border-bottom:var(--cc-sf-instance-divider, 1px dashed #D1D5DB)!important}.c-4B5563{color:var(--cc-sf-instance-num-color, #4B5563)!important}.fs-0-8125rem{font-size:var(--cc-sf-hint-size, .8125rem)!important}.pb-0{padding-bottom:0!important}.p-18px-24px{padding:18px 24px!important}.c-111827{color:var(--ms-title-color, #111827)!important}.bt-1px-solid-E5E7EB{border-top:1px solid #E5E7EB!important}.p-4px-10px{padding:4px 10px!important}.b-FFF5F5{background:var(--cc-sf-btn-remove-bg, #FFF5F5)!important}.c-E53E3E{color:var(--loc-delete-color, #E53E3E)!important}.b-1px-solid-FED7D7{border:var(--cc-sf-btn-remove-border, 1px solid #FED7D7)!important}.br-4px{border-radius:var(--cc-sf-btn-remove-radius, 4px)!important}.p-8px-16px{padding:8px 16px!important}.b-transparent{background:var(--cc-sf-btn-add-bg, transparent)!important}.c-3B82F6{color:var(--cc-sf-input-focus-border, #3B82F6)!important}.b-1px-dashed-CBD5E1{border:var(--cc-sf-btn-add-border, 1px dashed #CBD5E1)!important}.br-6px{border-radius:var(--cc-sf-btn-add-radius, 6px)!important}.b-1-5px-dashed-CBD5E1{border:var(--cc-sf-dropzone-border, 1.5px dashed #CBD5E1)!important}.br-12px{border-radius:var(--cc-sf-dropzone-radius, 12px)!important}.bc-FFFAF1{background-color:var(--cc-sf-dropzone-bg, #FFFAF1)!important}.c-94A3B8{color:var(--cc-sf-uploaded-remove-color, #94A3B8)!important}.fs-0-9rem{font-size:var(--cc-sf-input-font-size, .9rem)!important}.c-64748B{color:var(--cc-sf-dropzone-hint-color, #64748B)!important}.b-1px-solid-E2E8F0{border:var(--cc-sf-uploaded-item-border, 1px solid #E2E8F0)!important}.b-2px-solid-E2E8F0{border:2px solid #E2E8F0!important}.pr-3-5rem{padding-right:3.5rem!important}.p-0-0-875rem{padding:0 .875rem!important}.bc-FFFFFF{background-color:var(--cc-sf-input-bg, #FFFFFF)!important}.b-1-5px-solid-D1D5DB{border:var(--cc-sf-input-border, 1.5px solid #D1D5DB)!important}.mb-0-75rem{margin-bottom:.75rem!important}.mt-6px{margin-top:6px!important}.pr-2-4rem{padding-right:2.4rem!important}.p-0-2rem{padding:.2rem!important}.fs-1-35rem{font-size:1.35rem!important}.p-4px-12px{padding:4px 12px!important}.b-111827{background:var(--cc-sf-label-color, #111827)!important}.b-2px-dashed-CBD5E1{border:2px dashed var(--cc-sf-dropzone-border, #CBD5E1)!important}.fs-52px{font-size:52px!important}.p-12px-16px{padding:12px 16px!important}.bb-1px-solid-F3F4F6{border-bottom:1px solid var(--cc-sf-input-disabled-border, #F3F4F6)!important}.b-0F172A{background:var(--mu-carousel-bg, #0F172A)!important}.b-3px-solid-rgba-255-255-255-0-15{border:3px solid rgba(255,255,255,.15)!important}.b-rgba-255-255-255-0-85{background:#ffffffd9!important}.b-rgba-0-0-0-0-55{background:#0000008c!important}.b-rgba-255-255-255-0-45{background:#ffffff73!important}.pb-4px{padding-bottom:4px!important}.b-2px-solid-transparent{border:2px solid transparent!important}.b-E2E8F0{background:var(--mu-thumb-bg, #E2E8F0)!important}.b-1E293B{background:#1e293b!important}.c-EF4444{color:#ef4444!important}.b-rgba-0-0-0-0-5{background:#00000080!important}.br-16px{border-radius:var(--mu-modal-radius, 16px)!important}.p-24px-28px{padding:24px 28px!important}.bb-1px-solid-E5E7EB{border-bottom:1px solid var(--cc-sf-input-disabled-border, #E5E7EB)!important}.fs-1-25rem{font-size:1.25rem!important}.p-48px-24px{padding:48px 24px!important}.b-3px-solid-E2E8F0{border:3px solid #E2E8F0!important}.p-16px-24px{padding:16px 24px!important}.p-28px{padding:28px!important}.b-3px-solid-transparent{border:3px solid transparent!important}.b-rgba-59-130-246-0-12{background:#3b82f61f!important}.p-20px-28px{padding:20px 28px!important}.c-1A56DB{color:var(--loc-add-color, #1A56DB)!important}.b-1px-dashed-D1D5DB{border:1px dashed var(--cc-sf-input-disabled-border, #D1D5DB)!important}.fs-40px{font-size:40px!important}.c-9CA3AF{color:var(--loc-tba-icon-color, #9CA3AF)!important}.form-field{font-family:var(--cc-sf-font-family, \"Poppins\", sans-serif)!important}:host{--cc-sf-input-border: var(--field-input-border, #D1D5DB);--cc-sf-input-bg: var(--field-input-bg, #ffffff);--cc-sf-input-radius: var(--field-input-radius, 8px);--cc-sf-input-height: var(--field-input-height, 42px);--cc-sf-label-color: var(--field-label-color, #202124);--cc-sf-hint-color: var(--field-hint-color, #6B7280);--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-input-focus-border: #3B82F6;--cc-sf-input-hover-border: #9CA3AF;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-border: #E5E7EB;--cc-sf-switch-track-on: var(--cc-sf-selected-color, #F05A28);--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-thumb: #ffffff;--cc-sf-selected-color: var(--primary-color, #F05A28)}.form-row{gap:var(--cc-sf-grid-gap, 16px)}.form-row.horizontal{display:flex;flex-direction:row}.form-row.horizontal>*{flex:1}.form-row:not(.horizontal){flex-direction:column}.form-row.grid-row{display:grid;grid-template-columns:repeat(12,1fr);gap:var(--cc-sf-grid-gap, 16px);align-items:start}@media(max-width:640px){.form-row.grid-row{grid-template-columns:1fr}.form-row.grid-row .row-field{grid-column:span 12!important}}.field-label{font-weight:var(--cc-sf-label-weight, 500);line-height:var(--cc-sf-label-line-height, 100%);letter-spacing:var(--cc-sf-label-letter-spacing, 0%)}.field-input,input.matInput,.mat-mdc-input-element{display:block;width:100%;height:var(--cc-sf-input-height)!important;padding:0 16px!important;font-family:inherit;font-size:.875rem;color:var(--cc-sf-label-color);background-color:var(--cc-sf-input-bg)!important;border:1px solid var(--cc-sf-input-border)!important;border-radius:var(--cc-sf-input-radius)!important;box-sizing:border-box;box-shadow:none!important;transition:all .2s ease}.field-input::placeholder,input.matInput::placeholder,.mat-mdc-input-element::placeholder{font-weight:400;font-size:14px;color:var(--cc-sf-input-placeholder)}.field-input{opacity:var(--cc-sf-input-opacity, 1);line-height:var(--cc-sf-input-line-height, 1.5);transition:var(--cc-sf-input-transition, all .2s ease)}.field-input::placeholder{font-weight:var(--cc-sf-placeholder-weight, 400);font-size:var(--cc-sf-placeholder-size, 14px);line-height:var(--cc-sf-placeholder-line-height, 100%);color:var(--cc-sf-input-placeholder)}.field-input:hover:not(:disabled):not([readonly]){border-color:var(--cc-sf-input-hover-border)!important}.field-input:focus{outline:none;border-color:var(--cc-sf-input-focus-border)!important;box-shadow:var(--cc-sf-input-focus-shadow, 0 0 0 3px rgba(59, 130, 246, .12))!important}.field-input:disabled,.field-input[readonly]{background-color:var(--cc-sf-input-disabled-bg)!important;color:var(--cc-sf-input-disabled-color, #6B7280)!important;cursor:not-allowed;border-color:var(--cc-sf-input-disabled-border)!important}.field-input.is-invalid{border-color:var(--cc-sf-error-border)!important;background-color:var(--cc-sf-error-bg)!important}.field-input.is-invalid:focus{box-shadow:var(--cc-sf-error-focus-shadow, 0 0 0 3px rgba(220, 38, 38, .1))!important}.field-input.textarea{resize:vertical;min-height:100px;height:auto;padding:12px 16px!important}input[type=time].time-input{cursor:pointer}input[type=time].time-input::-webkit-calendar-picker-indicator{cursor:pointer;opacity:.7;filter:invert(30%)}input[type=time].time-input::-webkit-calendar-picker-indicator:hover{opacity:1}select.field-input{appearance:none;background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3E%3Cpath stroke='%236B7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3E%3C/svg%3E\");background-position:right .5rem center;background-repeat:no-repeat;background-size:1.5em 1.5em;padding-right:2.5rem;cursor:pointer}select.field-input:disabled{cursor:not-allowed}.char-count-hint{font-style:normal;line-height:100%;letter-spacing:.02em}.radio-group.layout-column,.checkbox-group.layout-column{display:grid!important;grid-template-columns:repeat(12,1fr);gap:16px;width:100%}.radio-group.layout-row,.checkbox-group.layout-row{flex-direction:column!important;gap:12px;width:100%}.radio-label input,.checkbox-label input{cursor:pointer;accent-color:var(--cc-sf-chip-selected-bg, #F05A28)}.radio-label.card-item,.checkbox-label.card-item{display:flex!important;flex-direction:row-reverse!important;justify-content:space-between!important;align-items:center!important;border:1px solid #E5E7EB;border-radius:12px;padding:16px 20px;box-sizing:border-box;transition:all .2s ease;background:#fff;margin-bottom:0}.radio-label.card-item input,.checkbox-label.card-item input{margin-left:16px}.radio-label.card-item.selected,.checkbox-label.card-item.selected{border-color:var(--cc-sf-selected-color);background-color:#f05a280d}.radio-label.card-item .option-content .label-text,.checkbox-label.card-item .option-content .label-text,.checkbox-single .checkbox-label{font-weight:var(--cc-sf-label-weight, 500)}.chip-label{transition:var(--cc-sf-input-transition, all .2s ease)}.chip-label:hover{background:var(--cc-sf-chip-hover-bg, #F3F4F6)}.chip-label.selected{background:var(--cc-sf-selected-color);color:var(--cc-sf-chip-selected-color, #ffffff);border-color:var(--cc-sf-selected-color)}.switch{width:50px;height:24px;display:inline-block}.switch input{opacity:0;width:0;height:0;position:absolute}.switch input:checked+.slider{background-color:var(--cc-sf-switch-track-on)!important}.switch input:checked+.slider:before{transform:translate(26px)}.switch .slider{inset:0;transition:.4s;background-color:var(--cc-sf-switch-track-off);border-radius:24px}.switch .slider:before{position:absolute;content:\"\";height:18px;width:18px;left:3px;bottom:3px;background-color:var(--cc-sf-switch-thumb);transition:.4s;border-radius:50%}.rating-group .star{transition:var(--cc-sf-input-transition, all .2s ease)}.rating-group .star mat-icon{font-size:var(--cc-sf-star-size, 28px);width:var(--cc-sf-star-size, 28px);height:var(--cc-sf-star-size, 28px);line-height:var(--cc-sf-star-size, 28px);color:var(--cc-sf-star-empty, #D1D5DB);transition:var(--cc-sf-input-transition, all .2s ease)}.rating-group .star.filled mat-icon,.rating-group .star.half mat-icon{color:var(--cc-sf-star-filled, #F59E0B)}.rating-group .star:hover mat-icon{color:var(--cc-sf-star-filled, #F59E0B)}.password-wrapper .password-toggle{right:.625rem;top:50%;transform:translateY(-50%);line-height:1;transition:color var(--cc-sf-input-transition, .2s ease)}.password-wrapper .password-toggle mat-icon.eye-icon{font-size:1.125rem;width:1.125rem;height:1.125rem;line-height:1.125rem}.password-wrapper .password-toggle:hover{color:var(--cc-sf-label-color, #374151)}.password-wrapper .password-toggle:focus{outline:none}.group-section-wrapper{box-shadow:var(--cc-sf-section-shadow, 0 1px 4px rgba(0, 0, 0, .05))}.group-section-wrapper .group-label{font-weight:var(--cc-sf-section-label-weight, 600)}.group-section-wrapper .group-fields.sf-grid{display:grid;grid-template-columns:repeat(12,1fr);gap:var(--cc-sf-grid-gap, 16px);align-items:start}@media(max-width:640px){.group-section-wrapper .group-fields.sf-grid{grid-template-columns:1fr}.group-section-wrapper .group-fields.sf-grid .sf-col{grid-column:span 12!important}}.group-section-wrapper .group-instance:last-child{margin-bottom:0}.group-section-wrapper.multi-save-active{border:none;box-shadow:none;padding:0;background:transparent}.group-section-wrapper.multi-save-active .multi-save-header .btn-add-multi ::ng-deep button{color:var(--ms-btn-add-color, #3B82F6);font-weight:600;font-size:.875rem;padding:8px 12px}.group-section-wrapper.multi-save-active .multi-save-header .btn-add-multi ::ng-deep button:hover{color:var(--ms-btn-add-hover, #2563EB);background-color:var(--cc-sf-btn-add-hover-bg, #EFF6FF)}.group-section-wrapper.multi-save-active .group-instance{box-shadow:var(--ms-card-shadow, 0 1px 4px rgba(0, 0, 0, .05))}.group-section-wrapper.multi-save-active .group-instance.is-editing{padding:24px}.group-section-wrapper.multi-save-active .group-instance.is-card{cursor:pointer;transition:all .2s ease-in-out}.group-section-wrapper.multi-save-active .group-instance.is-card:hover{box-shadow:var(--ms-card-shadow-hover, 0 8px 24px rgba(0, 0, 0, .08));border-color:var(--cc-sf-input-focus-border, #3B82F6)}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view .card-content .card-title{white-space:nowrap;text-overflow:ellipsis}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view .card-content .card-desc{line-height:1.4;display:-webkit-box;-webkit-line-clamp:1;line-clamp:1;-webkit-box-orient:vertical}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view.is-expanded .card-content .card-desc{-webkit-line-clamp:unset;line-clamp:unset}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view .card-actions mat-icon{font-size:22px;width:22px;height:22px;color:var(--cc-sf-hint-color, #9CA3AF);transition:color .2s}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view .card-actions mat-icon.icon-delete:hover{color:var(--cc-sf-error-border, #DC2626)}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view .card-actions mat-icon.icon-edit:hover{color:var(--cc-sf-input-focus-border, #3B82F6)}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view .card-actions mat-icon.icon-expand{color:var(--cc-sf-input-disabled-border, #E5E7EB)}.btn-remove{transition:var(--cc-sf-btn-transition, all .2s ease)}.btn-remove mat-icon{font-size:1rem;width:1rem;height:1rem;line-height:1rem}.btn-remove:hover{background:var(--cc-sf-btn-remove-hover-bg, #FED7D7)}.btn-add-group{font-weight:var(--cc-sf-btn-font-weight, 600);transition:var(--cc-sf-btn-transition, all .2s ease)}.btn-add-group mat-icon{font-size:1.1rem;width:1.1rem;height:1.1rem;line-height:1.1rem}.btn-add-group:hover{background:var(--cc-sf-btn-add-hover-bg, #EFF6FF);border-color:var(--cc-sf-btn-add-hover-border, #BFDBFE)}.upload-drop-zone{transition:background-color .2s ease,border-color .2s ease}.upload-drop-zone:hover{background-color:var(--cc-sf-dropzone-hover-bg, #EFF6FF);border-color:var(--cc-sf-dropzone-hover-border, #93C5FD)}.upload-drop-zone.drag-over{background-color:var(--cc-sf-dropzone-hover-bg, #EFF6FF);border-color:var(--cc-sf-dropzone-over-border, #3B82F6);box-shadow:var(--cc-sf-dropzone-over-shadow, 0 0 0 4px rgba(59, 130, 246, .12))}.upload-drop-zone.is-invalid{border-color:var(--cc-sf-error-border, #DC2626);background-color:var(--cc-sf-error-bg, #FEF2F2)}.upload-icon-wrap mat-icon.upload-cloud-icon{font-size:56px;width:56px;height:56px;line-height:56px;color:var(--cc-sf-dropzone-icon-color, #94A3B8)}.uploaded-item{transition:box-shadow .15s ease}.uploaded-item:hover{box-shadow:0 2px 6px #0000000f}.uploaded-item mat-icon.file-type-icon{font-size:20px;width:20px;height:20px;line-height:20px;flex-shrink:0;color:var(--cc-sf-hint-color, #64748B)}.uploaded-item .file-thumb{width:36px;height:36px;object-fit:cover;flex-shrink:0}.uploaded-item .file-info{min-width:0;gap:2px}.uploaded-item .file-info .file-name{white-space:nowrap;text-overflow:ellipsis}.uploaded-item .file-remove-btn{flex-shrink:0;transition:color .15s ease,background .15s ease}.uploaded-item .file-remove-btn mat-icon{font-size:1.1rem;width:1.1rem;height:1.1rem;line-height:1.1rem}.uploaded-item .file-remove-btn:hover{color:var(--cc-sf-uploaded-remove-hover-color, #DC2626);background:var(--cc-sf-uploaded-remove-hover-bg, #FEF2F2)}.uploaded-item.uploading{background:var(--cc-sf-uploaded-uploading-bg, #F8FAFC);border-color:var(--cc-sf-uploaded-uploading-border, #CBD5E1);opacity:.85}.upload-spinner{width:20px;height:20px;flex-shrink:0;border-top-color:var(--cc-sf-spinner-color, #3B82F6);animation:cc-spin .7s linear infinite}@keyframes cc-spin{to{transform:rotate(360deg)}}.uploading-label{font-style:italic}.input-group{align-items:stretch}.input-group .field-input{flex:1;width:auto}.input-prefix+.input-group .field-input{border-top-left-radius:0;border-bottom-left-radius:0}.input-group .field-input:has(+.input-suffix){border-top-right-radius:0;border-bottom-right-radius:0}.input-group .field-input.has-icon-right{padding-right:3rem}.input-group.readonly .field-input{cursor:default}.input-prefix,.input-suffix{display:flex!important;align-items:center;white-space:nowrap;padding:0 14px;background-color:var(--cc-sf-input-disabled-bg);border:1px solid var(--cc-sf-input-border);font-size:.875rem;color:var(--cc-sf-hint-color);-webkit-user-select:none;user-select:none}.input-prefix{border-right:none;border-top-left-radius:var(--cc-sf-input-radius, 8px);border-bottom-left-radius:var(--cc-sf-input-radius, 8px)}.input-suffix{border-left:none;border-top-right-radius:var(--cc-sf-input-radius, 8px);border-bottom-right-radius:var(--cc-sf-input-radius, 8px)}.readonly-icons{right:.875rem;top:50%;transform:translateY(-50%)}.readonly-icons mat-icon.lock-icon{font-size:1rem;width:1rem;height:1rem;line-height:1rem;opacity:.5;color:var(--cc-sf-hint-color, #6B7280)}.date-icon-wrapper{right:.5rem;top:50%;transform:translateY(-50%);pointer-events:auto}.date-icon-wrapper .mat-icon-button{width:32px;height:32px;line-height:32px}.subfields-group-wrapper .subfields-row{transition:all .2s ease}.subfields-group-wrapper .subfields-row.is-invalid .subfield-item ::ng-deep .field-input{border-color:var(--cc-sf-error-border, #DC2626);background-color:var(--cc-sf-error-bg, #FEF2F2)}.subfields-group-wrapper .subfields-row .subfield-item{min-width:0}.subfields-group-wrapper .subfields-row .subfield-item ::ng-deep .field-label{font-size:.75rem!important;margin-bottom:4px!important;font-weight:500!important;color:var(--cc-sf-hint-color, #6B7280)!important}.subfields-group-wrapper .subfields-row .subfield-separator{font-weight:700}.autocomplete-wrapper .ac-input{padding-left:40px!important}.autocomplete-wrapper .ac-search-icon{left:.75rem;width:1.1rem;height:1.1rem;line-height:1.1rem;z-index:1;transition:color var(--cc-sf-input-transition, .2s ease)}.autocomplete-wrapper .ac-clear-btn{right:.6rem;transition:color .15s ease,background .15s ease}.autocomplete-wrapper .ac-clear-btn mat-icon{font-size:1rem;width:1rem;height:1rem;line-height:1rem}.autocomplete-wrapper .ac-clear-btn:hover{color:var(--cc-sf-label-color, #374151);background:var(--cc-sf-input-disabled-bg, #F3F4F6)}.autocomplete-wrapper .ac-clear-btn:focus{outline:none}.autocomplete-wrapper:focus-within .ac-search-icon{color:var(--cc-sf-input-focus-border, #3B82F6)}.autocomplete-wrapper.is-invalid .ac-input{border-color:var(--cc-sf-error-border)!important;background-color:var(--cc-sf-error-bg)}.autocomplete-wrapper.readonly .ac-input{background-color:var(--cc-sf-input-disabled-bg);color:var(--cc-sf-input-disabled-color, #6B7280);cursor:not-allowed;border-color:var(--cc-sf-input-disabled-border)!important}.ac-no-results{font-style:italic}.mu-layout{grid-template-columns:1fr 1fr;gap:32px}@media(max-width:768px){.mu-layout{grid-template-columns:1fr}}.mu-title{font-weight:700;line-height:1.3}.mu-badge{white-space:nowrap;flex-shrink:0}.mu-description{line-height:1.6}.mu-feature-item .mu-check{width:16px;height:16px;line-height:16px;flex-shrink:0}.mu-right{min-height:260px}.mu-right-empty{min-height:250px;max-width:400px;box-shadow:0 2px 10px #0000000d;transition:box-shadow .2s ease}.mu-right-empty:hover{cursor:pointer;box-shadow:0 4px 16px #0000001a}.mu-right-empty .mu-right-empty-icon{width:52px;height:52px;line-height:52px;opacity:.3}.mu-right-empty p{margin:0;font-size:.85rem}.media-add-container{display:inline-block}.media-add-container ::ng-deep button{display:flex;align-items:center;gap:6px}.media-add-container ::ng-deep button .menu-chevron{width:18px;height:18px;line-height:18px;transition:transform .2s ease}.media-dropdown{top:calc(100% + 6px);left:0;z-index:200;min-width:240px;box-shadow:var(--mu-dropdown-shadow, 0 8px 32px rgba(0, 0, 0, .12));animation:mu-fade-in .15s ease}@keyframes mu-fade-in{0%{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:translateY(0)}}.media-dropdown-item{transition:background .15s ease}.media-dropdown-item:last-child{border-bottom:none}.media-dropdown-item:hover{background:var(--cc-sf-dropzone-hover-bg, #F0F9FF)}.media-drop-icon{width:36px;height:36px;flex-shrink:0}.media-drop-icon mat-icon{font-size:20px;width:20px;height:20px;line-height:20px}.media-drop-icon--video{background:var(--mu-icon-video-bg, #FFF0F0);color:var(--mu-icon-video-color, #EF4444)}.media-drop-icon--device{background:var(--mu-icon-device-bg, #EFF6FF);color:var(--mu-icon-device-color, #3B82F6)}.media-drop-icon--library{background:var(--mu-icon-library-bg, #F0FDF4);color:var(--mu-icon-library-color, #22C55E)}.media-drop-text{gap:2px}.youtube-input-panel{animation:mu-fade-in .18s ease}.youtube-panel-label mat-icon{font-size:18px;width:18px;height:18px;line-height:18px;color:var(--mu-icon-video-color, #EF4444)}.youtube-input-row{align-items:stretch}.media-menu-backdrop{position:fixed;inset:0;z-index:100}.media-upload-status{animation:mu-fade-in .2s ease}.media-upload-status .status-icon{width:18px;height:18px;line-height:18px}.media-carousel-main{max-width:400px;height:var(--mu-carousel-height, 250px)}.carousel-viewer{inset:0}.carousel-viewer .carousel-image{object-fit:cover}.carousel-viewer .carousel-spinner{width:36px;height:36px;border-top-color:#3b82f6;animation:cc-spin .7s linear infinite}.carousel-nav{top:50%;transform:translateY(-50%);z-index:10;width:40px;height:40px;box-shadow:0 2px 8px #0003;transition:background .2s ease,opacity .2s ease;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.carousel-nav mat-icon{font-size:22px;width:22px;height:22px;line-height:22px;color:#1e293b}.carousel-nav:hover:not(:disabled){background:#fff}.carousel-nav:disabled{opacity:.3;cursor:not-allowed}.carousel-nav--prev{left:12px}.carousel-nav--next{right:12px}.carousel-remove-btn{top:10px;right:10px;z-index:10;width:32px;height:32px;transition:background .2s ease}.carousel-remove-btn mat-icon{font-size:18px;width:18px;height:18px;line-height:18px;color:#fff}.carousel-remove-btn:hover:not(:disabled){background:#dc2626d9}.carousel-remove-btn:disabled{opacity:.4;cursor:not-allowed}.carousel-dots{bottom:10px;left:50%;transform:translate(-50%);z-index:10}.carousel-dot{width:8px;height:8px;transition:background .2s ease,transform .2s ease}.carousel-dot.active{background:#fff;transform:scale(1.3)}.media-thumbnail-strip{max-width:400px;overflow-x:auto}.media-thumbnail-strip::-webkit-scrollbar{height:4px}.media-thumbnail-strip::-webkit-scrollbar-thumb{background:var(--cc-sf-input-disabled-border, #D1D5DB);border-radius:2px}.media-thumb{flex-shrink:0;width:72px;height:52px;transition:border-color .2s ease,transform .15s ease}.media-thumb.active{border-color:var(--mu-thumb-active-border, #3B82F6);transform:scale(1.04)}.media-thumb:hover:not(.active){border-color:var(--cc-sf-input-hover-border, #9CA3AF)}.media-thumb .thumb-img{object-fit:cover}.media-thumb .thumb-yt-placeholder mat-icon{font-size:28px;width:28px;height:28px;line-height:28px}.media-thumb .thumb-uploading .thumb-spinner{width:20px;height:20px;border-top-color:#3b82f6;animation:cc-spin .7s linear infinite}.media-library-overlay{position:fixed;inset:0;z-index:999;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);animation:mu-fade-in .2s ease}.media-library-modal{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);z-index:1000;width:min(90vw,780px);max-height:85vh;box-shadow:var(--mu-modal-shadow, 0 20px 60px rgba(0, 0, 0, .2));animation:mu-modal-in .22s cubic-bezier(.34,1.56,.64,1)}@keyframes mu-modal-in{0%{opacity:0;transform:translate(-50%,-48%) scale(.95)}to{opacity:1;transform:translate(-50%,-50%) scale(1)}}.library-modal-header{flex-shrink:0}.library-modal-title{font-weight:700}.library-modal-subtitle{line-height:1.5;max-width:600px}.library-close-btn{width:32px;height:32px;transition:background .15s ease,color .15s ease}.library-close-btn mat-icon{font-size:20px;width:20px;height:20px;line-height:20px}.library-close-btn:hover{background:var(--cc-sf-input-disabled-bg, #F3F4F6);color:var(--cc-sf-label-color, #374151)}.library-loading mat-icon,.library-empty mat-icon{font-size:40px;width:40px;height:40px;line-height:40px;opacity:.5}.lib-spinner{width:36px;height:36px;border-top-color:#3b82f6;animation:cc-spin .7s linear infinite}.library-error{flex-shrink:0}.library-error mat-icon{font-size:20px;width:20px;height:20px;line-height:20px}.library-grid{grid-template-columns:repeat(5,1fr);overflow-y:auto}.library-grid::-webkit-scrollbar{width:8px}.library-grid::-webkit-scrollbar-track{background:#f1f1f1}.library-grid::-webkit-scrollbar-thumb{background:#c1c1c1;border-radius:10px;border:2px solid #F1F1F1}.library-grid-item{aspect-ratio:1/1;transition:all .3s cubic-bezier(.4,0,.2,1);box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -1px #0000000f}.library-grid-item:hover{transform:translateY(-4px) scale(1.02);box-shadow:0 20px 25px -5px #0000001a,0 10px 10px -5px #0000000a}.library-grid-item.selected{border-color:#3b82f6}.library-grid-item.selected .library-grid-img{opacity:.7}.library-grid-item:hover .library-overlay-hover{opacity:1}.library-grid-img{object-fit:cover}.library-overlay-hover{inset:0;opacity:0;transition:opacity .15s ease}.library-check{top:6px;right:6px;width:22px;height:22px;box-shadow:0 1px 4px #00000026}.library-check mat-icon{font-size:18px;width:18px;height:18px;line-height:18px}.library-modal-footer{flex-shrink:0}.library-modal-footer .library-footer-actions ::ng-deep .cc-btn-primary{background-color:#3b82f6!important;border-color:#3b82f6!important;color:#fff!important;font-weight:600;padding-left:32px;padding-right:32px}.library-modal-footer .library-footer-actions ::ng-deep .cc-btn-primary:hover{background-color:#2563eb!important}.library-modal-footer .library-footer-actions ::ng-deep .cc-btn-primary:disabled{background-color:#93c5fd!important;cursor:not-allowed}.library-modal-footer .library-footer-actions ::ng-deep .cc-btn-outline{font-weight:600;padding-left:24px;padding-right:24px;border-color:#d1d5db;color:#374151}.library-modal-footer .library-footer-actions ::ng-deep .cc-btn-outline:hover{background-color:#f9fafb}.location-subtitle{line-height:1.5}.loc-tab-btn ::ng-deep button{width:100%}.loc-tab-btn ::ng-deep button:not(.cc-btn-warning){background-color:#fff!important;color:#000!important;border:1px solid #E5E7EB}.loc-tab-btn ::ng-deep button:not(.cc-btn-warning):hover{background-color:#f3f4f6!important}.loc-venue-item{transition:box-shadow .15s ease,border-color .15s ease}.loc-venue-item:hover{box-shadow:0 2px 8px #0000000f;border-color:var(--cc-sf-input-hover-border, #9CA3AF)}.loc-venue-search-icon{width:18px;height:18px;line-height:18px;flex-shrink:0}.loc-venue-text{white-space:nowrap;text-overflow:ellipsis}.loc-action-btn{transition:background .15s ease,color .15s ease;flex-shrink:0}.loc-action-btn mat-icon{font-size:18px;width:18px;height:18px;line-height:18px}.loc-action-btn.loc-delete-btn{color:var(--loc-delete-color, #E53E3E)}.loc-action-btn.loc-delete-btn:hover{background:var(--cc-sf-error-bg, #FEF2F2)}.loc-action-btn.loc-edit-btn{color:var(--cc-sf-hint-color, #9CA3AF)}.loc-action-btn.loc-edit-btn:hover{color:var(--cc-sf-input-focus-border, #3B82F6);background:var(--cc-sf-dropzone-hover-bg, #EFF6FF)}.loc-search-icon{left:.75rem;width:1.1rem;height:1.1rem;line-height:1.1rem;z-index:1}.loc-suggestions-panel{top:calc(100% + 4px);left:0;right:0;z-index:300;box-shadow:0 8px 24px #0000001a;animation:mu-fade-in .15s ease;max-height:260px;overflow-y:auto}.loc-suggestion-item{transition:background .12s ease}.loc-suggestion-item:hover,.loc-suggestion-item:focus{background:var(--loc-suggestion-hover-bg, #F0F9FF)}.loc-suggestion-item:not(:last-child){border-bottom:1px solid var(--cc-sf-input-disabled-border, #F3F4F6)}.loc-suggestion-icon{width:18px;height:18px;line-height:18px;flex-shrink:0}.loc-suggestion-text{white-space:nowrap;text-overflow:ellipsis}.loc-add-btn{transition:opacity .15s ease}.loc-add-btn mat-icon{font-size:20px;width:20px;height:20px;line-height:20px}.loc-add-btn:hover{opacity:.8}.loc-map-container{box-shadow:0 2px 10px #0000000f}.loc-tba-panel{min-height:120px}.loc-tba-icon{width:40px;height:40px;line-height:40px;opacity:.6}.loc-tba-text{line-height:1.6;max-width:360px}\n"] }]
|
|
2231
|
+
args: [{ selector: 'lib-form-field', standalone: false, template: "<div class=\"form-field mb-16px\" *ngIf=\"isVisible\" [class.has-error]=\"errorMessage\">\r\n\r\n <!-- \u2550\u2550 ROW Layout \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isRow\" class=\"form-row grid-row\">\r\n <ng-container *ngFor=\"let child of config.children\">\r\n <div class=\"row-field\" [style.gridColumn]=\"'span ' + getChildColSpan(child)\" *ngIf=\"child.isEnabled !== false\">\r\n <lib-form-field [config]=\"child\" [controller]=\"controller\" [formGroup]=\"formGroup\" [allowMulti]=\"allowMulti\">\r\n </lib-form-field>\r\n </div>\r\n </ng-container>\r\n </div>\r\n\r\n <!-- \u2550\u2550 GROUP \u2014 allowMulti (repeater) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isGroup && config.sectionConfig?.allowMulti\"\r\n class=\"group-section-wrapper mb-20px\"\r\n [class.multi-save-active]=\"config.sectionConfig?.multiSaveConfig?.active\">\r\n\r\n <!-- Multi-Save: header row with label + top-right Add button -->\r\n <div class=\"multi-save-header d-flex justify-content-between align-items-center mb-24\"\r\n *ngIf=\"config.sectionConfig?.multiSaveConfig?.active\">\r\n <h3 class=\"group-label\" *ngIf=\"config.sectionConfig?.label\">{{ config.sectionConfig!.label }}</h3>\r\n <lib-button [variant]=\"'outline'\" [icon]=\"{type: 'material', value: 'add'}\" (click)=\"addGroupInstance()\"\r\n class=\"btn-add-multi\">\r\n {{ addMultiLabel }}\r\n </lib-button>\r\n </div>\r\n\r\n <!-- Standard heading (non-multiSave) -->\r\n <h3 class=\"group-label\"\r\n *ngIf=\"config.sectionConfig?.label && !config.sectionConfig?.multiSaveConfig?.active\">{{\r\n config.sectionConfig!.label }}</h3>\r\n\r\n <!-- \u2500\u2500 Standard (non-multiSave) repeater: accordion instances \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <ng-container *ngIf=\"!config.sectionConfig?.multiSaveConfig?.active\">\r\n <div *ngFor=\"let instance of instanceList; trackBy: trackByInstanceId; let i = index\"\r\n class=\"group-accordion-instance\"\r\n [class.is-expanded]=\"isGroupExpanded(i)\">\r\n\r\n <!-- Accordion header -->\r\n <div class=\"group-accordion-header\" (click)=\"toggleGroupAccordion(i)\"\r\n role=\"button\" [attr.aria-expanded]=\"isGroupExpanded(i)\">\r\n <div class=\"accordion-header-left d-flex align-items-center gap-10\">\r\n <span class=\"instance-badge\">{{ i + 1 }}</span>\r\n <span class=\"instance-title\">{{ config.sectionConfig!.label }} #{{ i + 1 }}</span>\r\n </div>\r\n <div class=\"accordion-header-right d-flex align-items-center gap-6\">\r\n <button type=\"button\" class=\"accordion-remove-btn\"\r\n *ngIf=\"instanceList.length > 1\"\r\n (click)=\"$event.stopPropagation(); removeGroupInstance(i)\"\r\n aria-label=\"Remove\">\r\n <mat-icon>delete_outline</mat-icon>\r\n </button>\r\n <mat-icon class=\"accordion-chevron\">\r\n {{ isGroupExpanded(i) ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}\r\n </mat-icon>\r\n </div>\r\n </div>\r\n\r\n <!-- Accordion body -->\r\n <div class=\"group-accordion-body\" *ngIf=\"isGroupExpanded(i)\">\r\n <div class=\"group-fields sf-grid\">\r\n <ng-container *ngFor=\"let field of config.sectionConfig!.children\">\r\n <div class=\"sf-col\" [style.gridColumn]=\"'span ' + (field.colSpan || 12)\"\r\n *ngIf=\"field.isEnabled !== false\">\r\n <lib-form-field [config]=\"field\" [controller]=\"controller\" [formGroup]=\"instance.fg\"\r\n [allowMulti]=\"true\">\r\n </lib-form-field>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Full-width dashed Add button -->\r\n <button type=\"button\" class=\"btn-add-group\" (click)=\"addGroupInstance()\">\r\n <mat-icon>add</mat-icon> {{ addLabel }} {{ config.sectionConfig!.label }}\r\n </button>\r\n </ng-container>\r\n\r\n <!-- \u2500\u2500 MultiSave: card instances \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <ng-container *ngIf=\"config.sectionConfig?.multiSaveConfig?.active\">\r\n <div *ngFor=\"let instance of instanceList; trackBy: trackByInstanceId; let i = index\"\r\n class=\"group-instance position-relative mb-16 overflow-hidden\"\r\n [class.is-editing]=\"instance.isEditing\"\r\n [class.is-card]=\"!instance.isEditing\">\r\n\r\n <!-- Edit / new form view -->\r\n <div [hidden]=\"!instance.isEditing\">\r\n <div class=\"group-fields sf-grid p-24\">\r\n <ng-container *ngFor=\"let field of config.sectionConfig!.children\">\r\n <div class=\"sf-col\" [style.gridColumn]=\"'span ' + (field.colSpan || 12)\"\r\n *ngIf=\"field.isEnabled !== false\">\r\n <lib-form-field [config]=\"field\" [controller]=\"controller\" [formGroup]=\"instance.fg\"\r\n [allowMulti]=\"true\">\r\n </lib-form-field>\r\n </div>\r\n </ng-container>\r\n </div>\r\n\r\n <!-- Save / Cancel -->\r\n <div\r\n class=\"group-footer d-flex justify-content-between align-items-center gap-16 mt-24 pt-20 bt-1px-solid-E5E7EB p-0-24\"\r\n *ngIf=\"config.sectionConfig?.multiSaveConfig?.active\">\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"multiSaveError\">{{ multiSaveError }}</span>\r\n <div class=\"footer-actions d-flex gap-12\">\r\n <lib-button [variant]=\"'outline'\" (click)=\"cancelGroupInstance(i)\">Cancel</lib-button>\r\n <lib-button [variant]=\"'primary'\" (click)=\"saveGroupInstance(i)\">Save</lib-button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Card view (saved state) -->\r\n <ng-container *ngIf=\"!instance.isEditing\">\r\n <div class=\"card-view d-flex justify-content-between align-items-center p-18px-24px\"\r\n [class.is-expanded]=\"instance.isExpanded\">\r\n <div class=\"card-content flex-1 d-flex flex-column gap-4 overflow-hidden\">\r\n <span class=\"card-title font-weight-600 overflow-hidden fs-1rem c-111827\">{{\r\n instance.fg.get(config.sectionConfig!.multiSaveConfig!.summaryField || '')?.value\r\n || '\u2014' }}</span>\r\n </div>\r\n <div class=\"card-actions d-flex align-items-center gap-16 ml-20\">\r\n <mat-icon class=\"icon-delete\" (click)=\"removeGroupInstance(i, true)\">delete_outline</mat-icon>\r\n <mat-icon class=\"icon-edit\" (click)=\"editGroupInstance(i)\">edit_outline</mat-icon>\r\n <mat-icon class=\"icon-expand\" (click)=\"toggleExpandGroupInstance(i)\">\r\n {{ instance.isExpanded ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}\r\n </mat-icon>\r\n </div>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </ng-container>\r\n </div>\r\n\r\n <!-- \u2550\u2550 GROUP \u2014 single (non-repeater) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isGroup && config.sectionConfig && !config.sectionConfig.allowMulti\"\r\n class=\"group-section-wrapper mb-20px\">\r\n <h3 class=\"group-label\" *ngIf=\"config.sectionConfig.label\">{{ config.sectionConfig.label }}</h3>\r\n <div class=\"group-fields sf-grid\">\r\n <ng-container *ngFor=\"let field of config.sectionConfig.children\">\r\n <div class=\"sf-col\" [style.gridColumn]=\"'span ' + (field.colSpan || 12)\" *ngIf=\"field.isEnabled !== false\">\r\n <lib-form-field [config]=\"field\" [controller]=\"controller\" [formGroup]=\"groupFormGroup\" [allowMulti]=\"false\">\r\n </lib-form-field>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </div>\r\n\r\n\r\n <!-- \u2550\u2550 Text Input \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isTextField\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <textarea *ngIf=\"config.subType === 'LONG'\" class=\"field-input textarea\" [placeholder]=\"config.placeholder || ''\"\r\n [formControlName]=\"config.name!\" [class.is-invalid]=\"errorMessage\" rows=\"4\">\r\n </textarea>\r\n\r\n <!-- Password input with show/hide toggle -->\r\n <div *ngIf=\"config.subType === 'PASSWORD'\" class=\"password-wrapper position-relative d-flex align-items-center\">\r\n <input [type]=\"showPassword ? 'text' : 'password'\" class=\"field-input password-input\"\r\n [placeholder]=\"config.placeholder || ''\" [formControlName]=\"config.name!\" [class.is-invalid]=\"errorMessage\">\r\n <button type=\"button\"\r\n class=\"password-toggle position-absolute cursor-pointer d-flex align-items-center justify-content-center b-none border-none c-6B7280 p-0-25rem\"\r\n (click)=\"showPassword = !showPassword\" tabindex=\"-1\"\r\n [attr.aria-label]=\"showPassword ? 'Hide password' : 'Show password'\">\r\n <mat-icon class=\"eye-icon\">{{ showPassword ? 'visibility' : 'visibility_off' }}</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <div class=\"input-group position-relative d-flex w-100\" [class.readonly]=\"config.readonly\">\r\n <span class=\"input-prefix br-none\" *ngIf=\"config.prefix\">{{ config.prefix }}</span>\r\n\r\n <input *ngIf=\"config.subType !== 'LONG' && config.subType !== 'PASSWORD'\"\r\n [type]=\"config.subType === 'EMAIL' ? 'email' : config.subType === 'PHONE' ? 'tel' : 'text'\" class=\"field-input\"\r\n [placeholder]=\"config.placeholder || ''\" [formControlName]=\"config.name!\" [class.is-invalid]=\"errorMessage\"\r\n [readonly]=\"config.readonly\">\r\n\r\n <span class=\"input-suffix d-flex align-items-center font-weight-500\" *ngIf=\"config.suffix\">{{ config.suffix\r\n }}</span>\r\n\r\n <div class=\"readonly-icons position-absolute d-flex gap-8 pe-none\" *ngIf=\"config.readonly\">\r\n <mat-icon class=\"lock-icon\">lock</mat-icon>\r\n </div>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n <div class=\"char-count-hint font-poppins font-weight-400 text-14 text-right mt-4 c-6B7280\" *ngIf=\"showCharCount\">\r\n {{ remainingCharacters }} characters remaining\r\n </div>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Number Input \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isNumberField\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"input-group position-relative d-flex w-100\" [class.readonly]=\"config.readonly\">\r\n <span class=\"input-prefix br-none\" *ngIf=\"config.prefix\">{{ config.prefix }}</span>\r\n\r\n <input type=\"number\" class=\"field-input\" [placeholder]=\"config.placeholder || ''\" [formControlName]=\"config.name!\"\r\n [min]=\"config.numberConfig?.min ?? null\" [max]=\"config.numberConfig?.max ?? null\"\r\n [step]=\"config.numberConfig?.step || 1\" [class.is-invalid]=\"errorMessage\" [readonly]=\"config.readonly\">\r\n\r\n <span class=\"input-suffix d-flex align-items-center font-weight-500\" *ngIf=\"config.suffix\">{{ config.suffix\r\n }}</span>\r\n\r\n <div class=\"readonly-icons position-absolute d-flex gap-8 pe-none\" *ngIf=\"config.readonly\">\r\n <mat-icon class=\"lock-icon\">lock</mat-icon>\r\n </div>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Date Input \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isDateField\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"input-group position-relative d-flex w-100\" [class.readonly]=\"config.readonly\">\r\n <input matInput [matDatepicker]=\"datePicker\" class=\"field-input date-input has-icon-right\"\r\n [formControlName]=\"config.name!\" [min]=\"config.dateConfig?.minDate\" [max]=\"config.dateConfig?.maxDate\"\r\n [class.is-invalid]=\"errorMessage\" [placeholder]=\"config.placeholder || ''\" [readonly]=\"config.readonly\"\r\n (click)=\"!config.readonly && datePicker.open()\">\r\n <div class=\"date-icon-wrapper position-absolute d-flex align-items-center justify-content-center\"\r\n *ngIf=\"!config.readonly\">\r\n <mat-datepicker-toggle matSuffix [for]=\"datePicker\"></mat-datepicker-toggle>\r\n </div>\r\n <mat-datepicker #datePicker></mat-datepicker>\r\n\r\n <div class=\"readonly-icons position-absolute d-flex gap-8 pe-none\" *ngIf=\"config.readonly\">\r\n <mat-icon class=\"lock-icon\">lock</mat-icon>\r\n </div>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Time Input \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isTimeField\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"input-group position-relative d-flex w-100\" [class.readonly]=\"config.readonly\">\r\n <input type=\"time\" class=\"field-input time-input\" [formControlName]=\"config.name!\"\r\n [class.is-invalid]=\"errorMessage\" [readonly]=\"!!config.readonly\">\r\n\r\n <div class=\"readonly-icons position-absolute d-flex gap-8 pe-none\" *ngIf=\"config.readonly\">\r\n <mat-icon class=\"lock-icon\">lock</mat-icon>\r\n </div>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Autocomplete \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isAutocomplete\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <!-- Hidden real control (stores the code value) -->\r\n <input type=\"hidden\" [formControlName]=\"config.name!\">\r\n\r\n <div class=\"autocomplete-wrapper position-relative d-flex align-items-center w-100\"\r\n [class.is-invalid]=\"errorMessage\" [class.readonly]=\"config.readonly\">\r\n <!-- Search icon -->\r\n <mat-icon class=\"ac-search-icon position-absolute fs-1-1rem c-9CA3AF pe-none\">search</mat-icon>\r\n\r\n <input class=\"field-input ac-input\" [formControl]=\"autocompleteInputCtrl\" [matAutocomplete]=\"auto\"\r\n [placeholder]=\"config.placeholder || 'Search\u2026'\" [readonly]=\"!!config.readonly\" [class.is-invalid]=\"errorMessage\"\r\n (blur)=\"onAutocompleteClear()\" autocomplete=\"off\">\r\n\r\n <!-- Clear button -->\r\n <button type=\"button\"\r\n class=\"ac-clear-btn position-absolute d-flex align-items-center justify-content-center cursor-pointer rounded-50 b-none border-none c-9CA3AF p-0-2rem\"\r\n *ngIf=\"autocompleteInputCtrl.value && !config.readonly\"\r\n (click)=\"autocompleteInputCtrl.setValue(''); updateValue(null)\" tabindex=\"-1\" aria-label=\"Clear\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n\r\n <mat-autocomplete #auto=\"matAutocomplete\" [panelWidth]=\"'auto'\">\r\n <mat-option *ngFor=\"let option of filteredOptions\" [value]=\"option.label\"\r\n (onSelectionChange)=\"onAutocompleteSelected(option)\">\r\n {{ option.label }}\r\n </mat-option>\r\n <mat-option *ngIf=\"filteredOptions.length === 0\" disabled class=\"ac-no-results fs-0-8125rem c-6B7280\">\r\n No results found\r\n </mat-option>\r\n </mat-autocomplete>\r\n\r\n <div class=\"readonly-icons position-absolute d-flex gap-8 pe-none\" *ngIf=\"config.readonly\">\r\n <mat-icon class=\"lock-icon\">lock</mat-icon>\r\n </div>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Dropdown \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isDropdown\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <select *ngIf=\"config.subType === 'SINGLE'\" class=\"field-input\" [formControlName]=\"config.name!\"\r\n [class.is-invalid]=\"errorMessage\">\r\n <option [ngValue]=\"null\" disabled selected>{{ config.placeholder || 'Select' }}</option>\r\n <option *ngFor=\"let option of config.optionConfig?.optionList\" [value]=\"option.code\">\r\n {{ option.label }}\r\n </option>\r\n </select>\r\n\r\n <select *ngIf=\"config.subType === 'MULTIPLE'\" class=\"field-input\" multiple [formControlName]=\"config.name!\"\r\n [class.is-invalid]=\"errorMessage\">\r\n <option *ngFor=\"let option of config.optionConfig?.optionList\" [value]=\"option.code\">\r\n {{ option.label }}\r\n </option>\r\n </select>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Radio \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isRadio\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"radio-group\" [class.is-invalid]=\"errorMessage\"\r\n [class]=\"config.optionConfig?.layout ? 'layout-' + config.optionConfig!.layout.toLowerCase() : ''\">\r\n <label *ngFor=\"let option of config.optionConfig?.optionList\" class=\"radio-label\"\r\n [class.card-item]=\"config.subType === 'CARD'\"\r\n [class.selected]=\"formGroup.get(config.name!)?.value === option.code\"\r\n [style.gridColumn]=\"config.optionConfig?.layout?.toUpperCase() === 'COLUMN' ? 'span ' + getOptionColSpan(option) : null\">\r\n <input type=\"radio\" [formControlName]=\"config.name!\" [value]=\"option.code\">\r\n <div class=\"option-content d-flex flex-column gap-4 flex-1 text-left\">\r\n <span class=\"label-text text-16 c-1F2937\">{{ option.label }}</span>\r\n <span class=\"option-hint text-13 color-gray\" *ngIf=\"option.hint\">{{ option.hint }}</span>\r\n </div>\r\n </label>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Checkbox \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isCheckbox\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label && config.subType === 'LIST'\"\r\n class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div *ngIf=\"config.subType === 'BOOL'\" class=\"checkbox-single\">\r\n <label class=\"checkbox-label d-flex align-items-center gap-8 cursor-pointer fs-0-875rem c-111827\">\r\n <input type=\"checkbox\" [formControlName]=\"config.name!\" [class.is-invalid]=\"errorMessage\">\r\n <span>{{ config.label }}</span>\r\n </label>\r\n </div>\r\n\r\n <div *ngIf=\"config.subType === 'LIST' || config.subType === 'CARD'\" class=\"checkbox-group d-flex flex-column gap-8\"\r\n [class.is-invalid]=\"errorMessage\"\r\n [class]=\"config.optionConfig?.layout ? 'layout-' + config.optionConfig!.layout.toLowerCase() : ''\">\r\n <label *ngFor=\"let option of config.optionConfig?.optionList\"\r\n class=\"checkbox-label d-flex align-items-center gap-8 cursor-pointer fs-0-875rem c-111827\"\r\n [class.card-item]=\"config.subType === 'CARD'\" [class.selected]=\"isChecked(option.code)\"\r\n [style.gridColumn]=\"config.optionConfig?.layout?.toUpperCase() === 'COLUMN' ? 'span ' + getOptionColSpan(option) : null\">\r\n <input type=\"checkbox\" [checked]=\"isChecked(option.code)\" [disabled]=\"!!config.disabled\"\r\n (change)=\"onCheckboxListChange(option.code, $any($event.target).checked)\">\r\n <div class=\"option-content d-flex flex-column gap-4 flex-1 text-left\">\r\n <span class=\"label-text text-16 c-1F2937\">{{ option.label }}</span>\r\n <span class=\"option-hint text-13 color-gray\" *ngIf=\"option.hint\">{{ option.hint }}</span>\r\n </div>\r\n </label>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Chip \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isChip\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"chip-group d-flex flex-wrap gap-8\" [class.is-invalid]=\"errorMessage\">\r\n <label *ngFor=\"let option of config.optionConfig?.optionList\"\r\n class=\"chip-label cursor-pointer p-6px-14px b-ffffff c-374151 b-1px-solid-D1D5DB br-20px fs-0-875rem\"\r\n [class.selected]=\"isChecked(option.code)\">\r\n <input type=\"checkbox\" [checked]=\"isChecked(option.code)\" [disabled]=\"!!config.disabled\"\r\n (change)=\"onCheckboxListChange(option.code, $any($event.target).checked)\" hidden>\r\n <span>{{ option.label }}</span>\r\n </label>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Switch \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isSwitch\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label class=\"switch-container d-flex justify-content-between align-items-center cursor-pointer\">\r\n <span class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">{{ config.label }}</span>\r\n <div class=\"switch position-relative\">\r\n <input type=\"checkbox\" [formControlName]=\"config.name!\" [class.is-invalid]=\"errorMessage\">\r\n <span class=\"slider position-absolute cursor-pointer\"></span>\r\n </div>\r\n </label>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Rich Text \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isRichText\" class=\"field-wrapper component-rich-text d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"rich-text-container\" [class.is-invalid]=\"errorMessage\">\r\n <quill-editor [formControlName]=\"config.name!\" class=\"rich-text-editor d-block w-100\"\r\n [placeholder]=\"config.richTextConfig?.placeholder || config.placeholder || ''\"\r\n [styles]=\"{height: config.richTextConfig?.height || '200px'}\">\r\n </quill-editor>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n <div class=\"char-count-hint font-poppins font-weight-400 text-14 text-right mt-4 c-6B7280\" *ngIf=\"showCharCount\">\r\n {{ remainingCharacters }} characters remaining\r\n </div>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Rating \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isRating\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"rating-group d-flex gap-4\" [class.is-invalid]=\"errorMessage\">\r\n <span *ngFor=\"let star of getStarArray()\" class=\"star d-inline-flex align-items-center cursor-pointer\"\r\n [class.filled]=\"isStarFilled(star)\" [class.half]=\"isStarHalf(star)\" (click)=\"onRatingChange(star, $event)\">\r\n <mat-icon>{{ isStarFilled(star) || isStarHalf(star) ? 'star' : 'star_border' }}</mat-icon>\r\n </span>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Generated Field (read-only) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isGenerated\" class=\"field-wrapper d-flex flex-column gap-6\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">{{ config.label\r\n }}</label>\r\n <div class=\"generated-value fs-0-875rem p-0-625rem-0-875rem b-F3F4F6 b-1px-solid-E5E7EB br-8px c-6B7280\">{{ value ||\r\n '-' }}</div>\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint\">{{ config.hint }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 File Upload \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isFileUpload\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <!-- Drop Zone -->\r\n <div\r\n class=\"upload-drop-zone d-flex flex-column align-items-center justify-content-center gap-8 cursor-pointer text-center p-32px-24px us-none\"\r\n [class.drag-over]=\"isDragOver\" [class.has-files]=\"value?.length\" [class.is-invalid]=\"errorMessage\"\r\n (dragover)=\"onDragOver($event)\" (dragleave)=\"onDragLeave($event)\" (drop)=\"onFileDrop($event)\"\r\n (click)=\"fileInput.click()\">\r\n\r\n <!-- Icon with accent-colour pill background -->\r\n <div class=\"upload-icon-wrap mb-4\">\r\n <div class=\"dropzone-icon-pill d-flex align-items-center justify-content-center\">\r\n <mat-icon class=\"upload-cloud-icon\">cloud_upload</mat-icon>\r\n </div>\r\n </div>\r\n\r\n <p class=\"upload-main-text font-weight-600 m-0 fs-0-9rem\">Drag & drop files here</p>\r\n <p class=\"upload-sub-text m-0 fs-0-8rem c-64748B\">or <span class=\"upload-link\">Browse files</span></p>\r\n <p class=\"upload-hint-text m-0 fs-0-78rem c-64748B\" *ngIf=\"config.attachmentConfig?.acceptLabel\">\r\n Supported: <span class=\"upload-formats font-weight-500\">{{ config.attachmentConfig!.acceptLabel }}</span>\r\n </p>\r\n <p class=\"upload-hint-text m-0 fs-0-78rem c-64748B\" *ngIf=\"!config.attachmentConfig?.acceptLabel && config.hint\">\r\n {{ config.hint }}\r\n </p>\r\n <span class=\"upload-size-badge fs-0-72rem\" *ngIf=\"config.attachmentConfig?.maxSizeMB\">\r\n Max {{ config.attachmentConfig!.maxSizeMB }}MB\r\n </span>\r\n\r\n <!-- Hidden native file input -->\r\n <input #fileInput type=\"file\" hidden [attr.multiple]=\"config.attachmentConfig?.multiple ? true : null\"\r\n [attr.accept]=\"config.attachmentConfig?.accept || null\" (change)=\"onFileSelected($event)\">\r\n </div>\r\n\r\n <!-- Uploaded file list -->\r\n <div class=\"uploaded-list d-flex flex-column gap-8 mt-10\" *ngIf=\"value?.length\">\r\n <div *ngFor=\"let f of value; let i = index\"\r\n class=\"uploaded-item d-flex align-items-center gap-10 p-10px-14px br-8px\"\r\n [class.uploading]=\"f.isUploading\">\r\n\r\n <!-- Uploading spinner -->\r\n <ng-container *ngIf=\"f.isUploading; else fileReady\">\r\n <div class=\"upload-spinner rounded-50 b-2px-solid-E2E8F0\"></div>\r\n <div class=\"file-info flex-1 d-flex flex-column\">\r\n <span class=\"file-name font-weight-500 overflow-hidden fs-0-85rem\" [title]=\"f.name\">{{ f.name }}</span>\r\n <span class=\"file-size uploading-label fs-0-72rem\">Uploading...</span>\r\n </div>\r\n </ng-container>\r\n\r\n <!-- Normal state once upload is done -->\r\n <ng-template #fileReady>\r\n <mat-icon class=\"file-type-icon\">{{ getFileIcon(f.type) }}</mat-icon>\r\n <img *ngIf=\"f.type?.startsWith('image') && f.dataUrl\" [src]=\"f.dataUrl\" class=\"file-thumb rounded-4\"\r\n alt=\"preview\">\r\n <div class=\"file-info flex-1 d-flex flex-column\">\r\n <span class=\"file-name font-weight-500 overflow-hidden fs-0-85rem\" [title]=\"f.name\">{{ f.name }}</span>\r\n <span class=\"file-size fs-0-72rem\">{{ formatFileSize(f.size) }}</span>\r\n </div>\r\n </ng-template>\r\n\r\n <!-- Compact icon-only remove button -->\r\n <button type=\"button\" class=\"file-remove-btn d-flex align-items-center justify-content-center rounded-50\"\r\n [disabled]=\"f.isUploading\" (click)=\"!f.isUploading && removeUploadedFile(i)\"\r\n aria-label=\"Remove file\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- Validation / file errors -->\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"fileUploadError\">{{ fileUploadError }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage && !fileUploadError\">{{ errorMessage }}</span>\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\"\r\n *ngIf=\"config.hint && !errorMessage && !fileUploadError && !config.attachmentConfig?.acceptLabel\">\r\n {{ config.hint }}\r\n </span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Media Upload (Type 2) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isMediaUpload\" class=\"field-wrapper media-upload-wrapper d-flex flex-column gap-6 p-0 border-none b-none\"\r\n [formGroup]=\"formGroup\">\r\n\r\n <!-- Hidden file input lives outside *ngIf \u2014 triggered via ViewChild -->\r\n <input #mediaDeviceInput type=\"file\" hidden multiple accept=\"image/*\" (change)=\"onMediaFileSelected($event)\">\r\n\r\n <!-- Two-column layout -->\r\n <div class=\"mu-layout d-grid align-items-start\">\r\n\r\n <!-- \u2500\u2500 LEFT PANEL \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <div class=\"mu-left d-flex flex-column gap-20\">\r\n\r\n <!-- Header: title + max-items badge -->\r\n <div class=\"mu-header d-flex align-items-start flex-wrap gap-10\">\r\n <h3 class=\"mu-title m-0 c-111827 fs-1-35rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </h3>\r\n <span\r\n class=\"mu-badge d-inline-flex align-items-center rounded-20 color-white font-weight-600 fs-0-72rem p-4px-12px b-111827\"\r\n *ngIf=\"config.attachmentConfig?.maxFiles\">\r\n {{ controller.labels['LBL_MEDIA_MAX_PREFIX'] || 'Maximum' }}\r\n {{ config.attachmentConfig?.maxFiles }}\r\n {{ controller.labels['LBL_MEDIA_MAX_SUFFIX'] || 'Image & Videos' }}\r\n </span>\r\n </div>\r\n\r\n <!-- Description -->\r\n <p class=\"mu-description m-0 fs-0-875rem c-6B7280\" *ngIf=\"config.attachmentConfig?.description\">\r\n {{ config.attachmentConfig?.description }}\r\n </p>\r\n <p class=\"mu-description m-0 fs-0-875rem c-6B7280\"\r\n *ngIf=\"!config.attachmentConfig?.description && controller.labels['LBL_MEDIA_DESC']\">\r\n {{ controller.labels['LBL_MEDIA_DESC'] }}\r\n </p>\r\n\r\n <!-- Feature bullet list -->\r\n <ul class=\"mu-features m-0 p-0 d-flex flex-column gap-8 ls-none\"\r\n *ngIf=\"config.attachmentConfig?.features?.length || controller.labels['LBL_MEDIA_FEATURE_1']\">\r\n <ng-container *ngIf=\"config.attachmentConfig?.features?.length\">\r\n <li *ngFor=\"let f of config.attachmentConfig?.features\"\r\n class=\"mu-feature-item d-flex align-items-center gap-8 fs-0-875rem c-374151\">\r\n <mat-icon class=\"mu-check text-16 c-3B82F6\">check</mat-icon>{{ f }}\r\n </li>\r\n </ng-container>\r\n <ng-container *ngIf=\"!config.attachmentConfig?.features?.length\">\r\n <li *ngIf=\"controller.labels['LBL_MEDIA_FEATURE_1']\"\r\n class=\"mu-feature-item d-flex align-items-center gap-8 fs-0-875rem c-374151\">\r\n <mat-icon class=\"mu-check text-16 c-3B82F6\">check</mat-icon>{{ controller.labels['LBL_MEDIA_FEATURE_1'] }}\r\n </li>\r\n <li *ngIf=\"controller.labels['LBL_MEDIA_FEATURE_2']\"\r\n class=\"mu-feature-item d-flex align-items-center gap-8 fs-0-875rem c-374151\">\r\n <mat-icon class=\"mu-check text-16 c-3B82F6\">check</mat-icon>{{ controller.labels['LBL_MEDIA_FEATURE_2'] }}\r\n </li>\r\n <li *ngIf=\"controller.labels['LBL_MEDIA_FEATURE_3']\"\r\n class=\"mu-feature-item d-flex align-items-center gap-8 fs-0-875rem c-374151\">\r\n <mat-icon class=\"mu-check text-16 c-3B82F6\">check</mat-icon>{{ controller.labels['LBL_MEDIA_FEATURE_3'] }}\r\n </li>\r\n </ng-container>\r\n </ul>\r\n\r\n <!-- Backdrop to close dropdown on outside click -->\r\n <div class=\"media-menu-backdrop\" *ngIf=\"showMediaMenu\"\r\n (click)=\"$event.stopPropagation(); showMediaMenu = false\"></div>\r\n\r\n <!-- Add Media button + dropdown -->\r\n <div class=\"media-add-container position-relative\" (click)=\"showMediaMenu = !showMediaMenu\">\r\n <lib-button id=\"btn-add-media-{{ config.name }}\" [variant]=\"'warning'\"\r\n [icon]=\"{type: 'material', value: 'add_photo_alternate'}\">\r\n {{ controller.labels['LBL_ADD_MEDIA'] || 'Add media' }}\r\n <mat-icon class=\"menu-chevron fs-18px\">add</mat-icon>\r\n </lib-button>\r\n\r\n <div class=\"media-dropdown position-absolute rounded-12 overflow-hidden b-ffffff b-1px-solid-E5E7EB\"\r\n *ngIf=\"showMediaMenu\" role=\"menu\" (click)=\"$event.stopPropagation()\">\r\n <!-- Video -->\r\n <button id=\"btn-media-video-{{ config.name }}\" type=\"button\"\r\n class=\"media-dropdown-item d-flex align-items-center gap-12 w-100 cursor-pointer text-left b-none border-none p-12px-16px bb-1px-solid-F3F4F6\"\r\n (click)=\"onMediaMenuVideo(); showMediaMenu = false\" role=\"menuitem\">\r\n <span\r\n class=\"media-drop-icon media-drop-icon--video d-flex align-items-center justify-content-center rounded-8\"><mat-icon>videocam</mat-icon></span>\r\n <span class=\"media-drop-text d-flex flex-column flex-1\">\r\n <span class=\"media-drop-label font-weight-600 fs-0-875rem c-111827\">{{\r\n controller.labels['LBL_MEDIA_VIDEO'] || 'Video' }}</span>\r\n <span class=\"media-drop-desc c-6B7280 fs-0-75rem\">{{ controller.labels['LBL_MEDIA_VIDEO_DESC'] || 'Add\r\n YouTube URL'\r\n }}</span>\r\n </span>\r\n </button>\r\n <!-- Device -->\r\n <button id=\"btn-media-device-{{ config.name }}\" type=\"button\"\r\n class=\"media-dropdown-item d-flex align-items-center gap-12 w-100 cursor-pointer text-left b-none border-none p-12px-16px bb-1px-solid-F3F4F6\"\r\n (click)=\"onMediaMenuDevice(); showMediaMenu = false\" role=\"menuitem\">\r\n <span\r\n class=\"media-drop-icon media-drop-icon--device d-flex align-items-center justify-content-center rounded-8\"><mat-icon>upload</mat-icon></span>\r\n <span class=\"media-drop-text d-flex flex-column flex-1\">\r\n <span class=\"media-drop-label font-weight-600 fs-0-875rem c-111827\">{{\r\n controller.labels['LBL_MEDIA_DEVICE'] || 'Upload from device'\r\n }}</span>\r\n <span class=\"media-drop-desc c-6B7280 fs-0-75rem\">{{ controller.labels['LBL_MEDIA_DEVICE_DESC'] ||\r\n 'Select images from your\r\n computer' }}</span>\r\n </span>\r\n </button>\r\n <!-- Library -->\r\n <button id=\"btn-media-library-{{ config.name }}\" type=\"button\"\r\n class=\"media-dropdown-item d-flex align-items-center gap-12 w-100 cursor-pointer text-left b-none border-none p-12px-16px bb-1px-solid-F3F4F6\"\r\n (click)=\"onMediaMenuLibrary(); showMediaMenu = false\" role=\"menuitem\">\r\n <span\r\n class=\"media-drop-icon media-drop-icon--library d-flex align-items-center justify-content-center rounded-8\"><mat-icon>photo_library</mat-icon></span>\r\n <span class=\"media-drop-text d-flex flex-column flex-1\">\r\n <span class=\"media-drop-label font-weight-600 fs-0-875rem c-111827\">{{\r\n controller.labels['LBL_MEDIA_LIBRARY'] || 'Upload from library'\r\n }}</span>\r\n <span class=\"media-drop-desc c-6B7280 fs-0-75rem\">{{ controller.labels['LBL_MEDIA_LIBRARY_DESC'] ||\r\n 'Choose from default\r\n images' }}</span>\r\n </span>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- YouTube URL Input (inline below button) -->\r\n <div class=\"youtube-input-panel d-flex flex-column gap-8 p-16 rounded-10 b-FFFAF1 b-1px-solid-E5E7EB\"\r\n *ngIf=\"showYoutubeInput\">\r\n <label class=\"youtube-panel-label d-flex align-items-center gap-6 font-weight-600 fs-0-875rem c-111827\">\r\n {{ controller.labels['LBL_YOUTUBE_URL'] || 'Video URL' }}\r\n </label>\r\n <div class=\"youtube-input-row d-flex gap-8\">\r\n <input id=\"input-youtube-url-{{ config.name }}\" type=\"url\" class=\"field-input youtube-url-input\"\r\n [(ngModel)]=\"youtubeUrlInput\" [ngModelOptions]=\"{standalone: true}\"\r\n [placeholder]=\"controller.labels['PH_YOUTUBE_URL'] || 'Video URL'\" (keyup.enter)=\"addYoutubeMedia()\">\r\n <lib-button id=\"btn-add-youtube-{{ config.name }}\" [variant]=\"'secondary'\" (click)=\"addYoutubeMedia()\">\r\n {{ controller.labels['LBL_ADD'] || 'Add' }}\r\n </lib-button>\r\n </div>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"youtubeUrlError\">{{ youtubeUrlError }}</span>\r\n </div>\r\n\r\n <div\r\n class=\"media-upload-status d-flex align-items-center gap-8 mt-4 color-error rounded-8 font-weight-500 p-10px-14px b-FEF2F2 fs-0-85rem\"\r\n *ngIf=\"mediaUploadError\">\r\n <mat-icon class=\"status-icon fs-18px\">error_outline</mat-icon>\r\n <span>{{ mediaUploadError }}</span>\r\n </div>\r\n\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n </div>\r\n <!-- end left panel -->\r\n\r\n <!-- \u2500\u2500 RIGHT PANEL (carousel) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <div class=\"mu-right d-flex flex-column gap-12\">\r\n\r\n <!-- Carousel (when items exist) -->\r\n <div class=\"media-carousel-section d-flex flex-column gap-12\" *ngIf=\"mediaItems.length\">\r\n <div\r\n class=\"media-carousel-main position-relative w-100 overflow-hidden d-flex align-items-center justify-content-center br-12px b-0F172A\">\r\n <button id=\"btn-carousel-prev-{{ config.name }}\" type=\"button\"\r\n class=\"carousel-nav carousel-nav--prev position-absolute rounded-50 cursor-pointer d-flex align-items-center justify-content-center border-none b-rgba-255-255-255-0-85\"\r\n (click)=\"mediaCarouselPrev()\" [disabled]=\"mediaCarouselIndex === 0\" aria-label=\"Previous\">\r\n <mat-icon>chevron_left</mat-icon>\r\n </button>\r\n\r\n <div class=\"carousel-viewer position-absolute d-flex align-items-center justify-content-center\"\r\n *ngFor=\"let item of mediaItems; let i = index\" [hidden]=\"i !== mediaCarouselIndex\">\r\n <div *ngIf=\"item.isUploading\"\r\n class=\"carousel-uploading d-flex flex-column align-items-center gap-12 c-94A3B8 fs-0-85rem\">\r\n <div class=\"carousel-spinner rounded-50 b-3px-solid-rgba-255-255-255-0-15\"></div>\r\n <span>{{ controller.labels['LBL_UPLOADING'] || 'Uploading\u2026' }}</span>\r\n </div>\r\n <ng-container *ngIf=\"!item.isUploading && item.mediaType === 'youtube'\">\r\n <iframe class=\"carousel-iframe w-100 h-100 br-12px\" [src]=\"item.url | trustedUrl\" frameborder=\"0\"\r\n allowfullscreen\r\n allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\">\r\n </iframe>\r\n </ng-container>\r\n <ng-container *ngIf=\"!item.isUploading && item.mediaType === 'image'\">\r\n <img class=\"carousel-image w-100 h-100 br-12px\" [src]=\"item.url\" alt=\"Media\">\r\n </ng-container>\r\n <button id=\"btn-remove-media-{{ config.name }}-{{ i }}\" type=\"button\"\r\n class=\"carousel-remove-btn position-absolute rounded-50 cursor-pointer d-flex align-items-center justify-content-center border-none b-rgba-0-0-0-0-55\"\r\n [disabled]=\"item.isUploading\" (click)=\"removeMediaItem(i)\" aria-label=\"Remove\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <button id=\"btn-carousel-next-{{ config.name }}\" type=\"button\"\r\n class=\"carousel-nav carousel-nav--next position-absolute rounded-50 cursor-pointer d-flex align-items-center justify-content-center border-none b-rgba-255-255-255-0-85\"\r\n (click)=\"mediaCarouselNext()\" [disabled]=\"mediaCarouselIndex === mediaItems.length - 1\" aria-label=\"Next\">\r\n <mat-icon>chevron_right</mat-icon>\r\n </button>\r\n\r\n <div class=\"carousel-dots position-absolute d-flex gap-6\">\r\n <span *ngFor=\"let item of mediaItems; let i = index\"\r\n class=\"carousel-dot rounded-50 cursor-pointer b-rgba-255-255-255-0-45\"\r\n [class.active]=\"i === mediaCarouselIndex\" (click)=\"mediaGoTo(i)\"></span>\r\n </div>\r\n </div>\r\n\r\n <!-- Thumbnail strip -->\r\n <div class=\"media-thumbnail-strip d-flex flex-wrap gap-8 pb-4px\">\r\n <div *ngFor=\"let item of mediaThumbnails; let i = index\"\r\n class=\"media-thumb rounded-8 overflow-hidden cursor-pointer d-flex align-items-center justify-content-center b-2px-solid-transparent b-E2E8F0\"\r\n [class.active]=\"i === mediaCarouselIndex\" (click)=\"mediaGoTo(i)\">\r\n <div *ngIf=\"item.isUploading\"\r\n class=\"thumb-uploading d-flex align-items-center justify-content-center w-100 h-100\">\r\n <div class=\"thumb-spinner rounded-50 b-2px-solid-E2E8F0\"></div>\r\n </div>\r\n <img *ngIf=\"!item.isUploading && item.mediaType === 'youtube' && item.thumbnailUrl\"\r\n [src]=\"item.thumbnailUrl\" class=\"thumb-img w-100 h-100\" alt=\"Video thumbnail\">\r\n <div *ngIf=\"!item.isUploading && item.mediaType === 'youtube' && !item.thumbnailUrl\"\r\n class=\"thumb-yt-placeholder d-flex align-items-center justify-content-center w-100 h-100 b-1E293B c-EF4444\">\r\n <mat-icon>play_circle</mat-icon>\r\n </div>\r\n <img *ngIf=\"!item.isUploading && item.mediaType === 'image' && item.url\" [src]=\"item.url\"\r\n class=\"thumb-img w-100 h-100\" alt=\"Image thumbnail\">\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Empty right-side placeholder -->\r\n <div\r\n class=\"mu-right-empty d-flex flex-column align-items-center justify-content-center gap-10 h-100 text-center p-24 br-12px b-FFFAF1 c-94A3B8 b-2px-dashed-CBD5E1\"\r\n *ngIf=\"!mediaItems.length\" (click)=\"onMediaMenuDevice()\">\r\n <mat-icon class=\"mu-right-empty-icon fs-52px\">perm_media</mat-icon>\r\n <p>{{ controller.labels['LBL_ADD_MEDIA'] || 'Add media' }}</p>\r\n </div>\r\n\r\n </div>\r\n <!-- end right panel -->\r\n\r\n </div><!-- end mu-layout -->\r\n </div>\r\n\r\n\r\n <!-- \u2550\u2550 Library Image Picker Modal \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div class=\"media-library-overlay b-rgba-0-0-0-0-5\" *ngIf=\"showLibraryModal\" (click)=\"closeLibraryModal()\"></div>\r\n <div class=\"media-library-modal d-flex flex-column overflow-hidden b-ffffff br-16px\" *ngIf=\"showLibraryModal\"\r\n role=\"dialog\" aria-modal=\"true\">\r\n <div class=\"library-modal-header d-flex align-items-start justify-content-between p-24px-28px bb-1px-solid-E5E7EB\">\r\n <div class=\"header-left d-flex flex-column gap-8\">\r\n <h3 class=\"library-modal-title m-0 color-dark fs-1-25rem\">\r\n {{ controller.labels['LBL_ADD_IMAGES'] || 'Add Images' }}\r\n </h3>\r\n <p class=\"library-modal-subtitle m-0 color-gray fs-0-85rem\">\r\n {{ controller.labels['LBL_LIBRARY_MODAL_DESC'] || 'Upload media to make your opportunity stand out. Plus, take\r\n full control of your sequence - drag images to reorder as you desire.' }}\r\n </p>\r\n </div>\r\n <button id=\"btn-close-library-{{ config.name }}\" type=\"button\"\r\n class=\"library-close-btn d-flex align-items-center justify-content-center cursor-pointer rounded-50 border-none b-none c-9CA3AF\"\r\n (click)=\"closeLibraryModal()\" aria-label=\"Close\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <!-- Loading -->\r\n <div class=\"library-loading\" *ngIf=\"libraryLoading\">\r\n <div class=\"lib-spinner rounded-50 b-3px-solid-E2E8F0\"></div>\r\n <span>{{ controller.labels['LBL_LOADING'] || 'Loading\u2026' }}</span>\r\n </div>\r\n\r\n <!-- Error -->\r\n <div class=\"library-error d-flex align-items-center gap-8 color-error b-FEF2F2 fs-0-875rem p-16px-24px\"\r\n *ngIf=\"libraryError && !libraryLoading\">\r\n <mat-icon>error_outline</mat-icon>\r\n {{ libraryError }}\r\n </div>\r\n\r\n <!-- Image grid -->\r\n <div class=\"library-grid d-grid gap-16 flex-1 p-28px b-F9FAFB\" *ngIf=\"!libraryLoading && libraryImages.length\">\r\n <div *ngFor=\"let img of libraryImages; let li = index\" id=\"lib-img-{{ config.name }}-{{ li }}\"\r\n class=\"library-grid-item position-relative rounded-12 overflow-hidden cursor-pointer bg-white b-3px-solid-transparent\"\r\n [class.selected]=\"isLibraryItemSelected(img)\" (click)=\"toggleLibraryItem(img)\">\r\n <img [src]=\"getLibraryItemUrl(img)\" class=\"library-grid-img w-100 h-100 d-block\" alt=\"Library image\">\r\n <div\r\n class=\"library-check position-absolute bg-white rounded-50 d-flex align-items-center justify-content-center c-3B82F6\"\r\n *ngIf=\"isLibraryItemSelected(img)\">\r\n <mat-icon>check_circle</mat-icon>\r\n </div>\r\n <div class=\"library-overlay-hover position-absolute b-rgba-59-130-246-0-12\"></div>\r\n </div>\r\n </div>\r\n\r\n <!-- Empty library -->\r\n <div\r\n class=\"library-empty d-flex flex-column align-items-center justify-content-center gap-12 flex-1 c-9CA3AF fs-0-875rem p-48px-24px\"\r\n *ngIf=\"!libraryLoading && !libraryError && libraryImages.length === 0\">\r\n <mat-icon>image_not_supported</mat-icon>\r\n <span>{{ controller.labels['LBL_LIBRARY_EMPTY'] || 'No images found in library.' }}</span>\r\n </div>\r\n\r\n <!-- Footer -->\r\n <div\r\n class=\"library-modal-footer d-flex align-items-center justify-content-end bg-white p-20px-28px bt-1px-solid-E5E7EB\">\r\n <div class=\"library-footer-actions d-flex gap-12 gap-10\">\r\n <lib-button id=\"btn-library-cancel-{{ config.name }}\" [variant]=\"'outline'\" (click)=\"closeLibraryModal()\">\r\n {{ controller.labels['LBL_CANCEL'] || 'Cancel' }}\r\n </lib-button>\r\n <lib-button id=\"btn-library-confirm-{{ config.name }}\" [variant]=\"'primary'\"\r\n [disabled]=\"librarySelectedIds.size === 0\" (click)=\"confirmLibrarySelection()\">\r\n {{ controller.labels['LBL_CONTINUE'] || 'Continue' }}\r\n </lib-button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Location Field \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isLocation\" class=\"field-wrapper location-field-wrapper d-flex flex-column gap-6 gap-12\"\r\n [formGroup]=\"formGroup\">\r\n\r\n <!-- Field label -->\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n <p class=\"location-subtitle m-0 c-6B7280 fs-0-8125rem\" *ngIf=\"config.hint\">{{ config.hint }}</p>\r\n\r\n <!-- Three-tab bar -->\r\n <div class=\"location-tabs d-flex gap-12 mb-24\">\r\n <lib-button class=\"loc-tab-btn flex-1\" [variant]=\"locationActiveTab === 'VENUE' ? 'warning' : 'outline'\"\r\n (click)=\"onLocationTabChange('VENUE')\">\r\n {{ controller.labels['LBL_LOC_VENUE'] || 'Venue' }}\r\n </lib-button>\r\n <lib-button class=\"loc-tab-btn flex-1\" [variant]=\"locationActiveTab === 'ONLINE' ? 'warning' : 'outline'\"\r\n (click)=\"onLocationTabChange('ONLINE')\">\r\n {{ controller.labels['LBL_LOC_ONLINE'] || 'Online Event' }}\r\n </lib-button>\r\n <lib-button class=\"loc-tab-btn flex-1\" [variant]=\"locationActiveTab === 'TBA' ? 'warning' : 'outline'\"\r\n (click)=\"onLocationTabChange('TBA')\">\r\n {{ controller.labels['LBL_LOC_TBA'] || 'To be Announced' }}\r\n </lib-button>\r\n </div>\r\n\r\n <!-- VENUE TAB -->\r\n <div *ngIf=\"locationActiveTab === 'VENUE'\" class=\"loc-panel loc-venue-panel d-flex flex-column gap-12\">\r\n\r\n <p class=\"loc-section-label m-0 font-weight-600 c-111827 fs-0-9rem\">\r\n {{ controller.labels['LBL_LOC_ADDRESS'] || 'Location address' }}\r\n </p>\r\n\r\n <!-- Added venue rows -->\r\n <div class=\"loc-venue-list d-flex flex-column gap-8\" *ngIf=\"locationVenues.length > 0\">\r\n <div *ngFor=\"let venue of locationVenues; let i = index\"\r\n class=\"loc-venue-item d-flex align-items-center gap-10 p-10px-14px br-7px b-ffffff b-1px-solid-D1D5DB\">\r\n <mat-icon class=\"loc-venue-search-icon fs-18px c-9CA3AF\">search</mat-icon>\r\n <span class=\"loc-venue-text flex-1 overflow-hidden fs-0-875rem c-111827\">{{ venue.address || venue.name ||\r\n venue.description }}</span>\r\n <button type=\"button\"\r\n class=\"loc-action-btn loc-delete-btn d-flex align-items-center justify-content-center cursor-pointer rounded-50 b-none border-none p-4px\"\r\n (click)=\"removeLocationVenue(i)\">\r\n <mat-icon>delete_outline</mat-icon>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- Location count badge -->\r\n <p class=\"loc-count-text m-0 font-weight-600 fs-0-8125rem c-3B82F6\"\r\n *ngIf=\"locationVenues.length > 0 && config.locationConfig?.allowMulti\">\r\n {{ locationVenues.length }} {{ controller.labels['LBL_LOC_COUNT_SUFFIX'] || 'Locations Added!' }}\r\n </p>\r\n\r\n <!-- Search input (hide when max reached) -->\r\n <div class=\"loc-search-container position-relative\" *ngIf=\"!locationMaxReached\">\r\n <div class=\"loc-search-wrapper position-relative d-flex align-items-center mt-4\">\r\n <mat-icon class=\"loc-search-icon position-absolute fs-1-1rem c-9CA3AF pe-none\">search</mat-icon>\r\n <input\r\n class=\"field-input loc-search-input w-100 font-poppins flex-1 fs-0-875rem c-111827 br-7px br-8px bc-F3F4F6 pl-2-4rem bc-DC2626 pt-0-625rem pb-0-625rem pl-16px pr-16px bc-ffffff b-1px-solid-D1D5DB pr-3-5rem\"\r\n [placeholder]=\"config.locationConfig?.venuePlaceholder || (controller.labels['PH_LOC_VENUE'] || 'Type to search venue...')\"\r\n [value]=\"locationSearchText\" (input)=\"handleLocationSearchInput($event)\" (blur)=\"hideLocationSuggestions()\"\r\n autocomplete=\"off\" [class.is-invalid]=\"errorMessage\">\r\n </div>\r\n <!-- Suggestions dropdown -->\r\n <div class=\"loc-suggestions-panel position-absolute overflow-hidden br-8px b-ffffff b-1px-solid-D1D5DB\"\r\n *ngIf=\"locationShowSuggestions && locationSuggestions.length\">\r\n <div *ngFor=\"let sug of locationSuggestions\"\r\n class=\"loc-suggestion-item d-flex align-items-center gap-10 cursor-pointer p-10px-14px\"\r\n (mousedown)=\"onLocationSuggestionSelect(sug)\">\r\n <mat-icon class=\"loc-suggestion-icon fs-18px c-E53E3E\">place</mat-icon>\r\n <span class=\"loc-suggestion-text overflow-hidden fs-0-875rem c-374151\">{{ sug.description }}</span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Add another button -->\r\n <button type=\"button\"\r\n class=\"loc-add-btn d-inline-flex align-items-center gap-6 cursor-pointer font-weight-600 p-0 b-none border-none fs-0-875rem c-1A56DB\"\r\n *ngIf=\"locationVenues.length > 0 && !locationMaxReached && config.locationConfig?.allowMulti\">\r\n <mat-icon>add_circle_outline</mat-icon>\r\n <span>{{ controller.labels['LBL_LOC_ADD_ANOTHER'] || 'Add another Location' }}</span>\r\n </button>\r\n\r\n <!-- Map -->\r\n <div class=\"loc-map-container overflow-hidden br-10px b-1px-solid-E5E7EB\"\r\n *ngIf=\"config.locationConfig?.showMap !== false\">\r\n <ng-container *ngIf=\"config.locationConfig?.googleMapsApiKey; else simpleEmbed\">\r\n <div [id]=\"'loc-map-' + config.name\" class=\"loc-map-frame w-100 d-block border-none\"\r\n [style.height]=\"config.locationConfig?.mapHeight || '300px'\"></div>\r\n </ng-container>\r\n <ng-template #simpleEmbed>\r\n <iframe class=\"loc-map-frame w-100 d-block border-none\"\r\n [style.height]=\"config.locationConfig?.mapHeight || '300px'\" [src]=\"getLocationMapEmbedUrl() | trustedUrl\"\r\n frameborder=\"0\" allowfullscreen loading=\"lazy\">\r\n </iframe>\r\n </ng-template>\r\n </div>\r\n\r\n <!-- Map hint -->\r\n <p class=\"loc-map-hint m-0 text-center fs-0-78rem c-6B7280\">\r\n {{ controller.labels['LBL_LOC_MAP_HINT'] || 'Type the venue address. A map will appear to assist you.' }}\r\n </p>\r\n </div>\r\n\r\n <!-- ONLINE TAB -->\r\n <div *ngIf=\"locationActiveTab === 'ONLINE'\" class=\"loc-panel loc-online-panel d-flex flex-column gap-12\">\r\n <p class=\"loc-section-label m-0 font-weight-600 c-111827 fs-0-9rem\">\r\n {{ controller.labels['LBL_LOC_ONLINE_URL'] || 'Event URL' }}\r\n </p>\r\n <div class=\"loc-search-wrapper position-relative d-flex align-items-center mt-4\">\r\n <mat-icon class=\"loc-search-icon position-absolute fs-1-1rem c-9CA3AF pe-none\">link</mat-icon>\r\n <input\r\n class=\"field-input loc-search-input w-100 font-poppins flex-1 fs-0-875rem c-111827 br-7px br-8px bc-F3F4F6 pl-2-4rem bc-DC2626 pt-0-625rem pb-0-625rem pl-16px pr-16px bc-ffffff b-1px-solid-D1D5DB pr-3-5rem\"\r\n type=\"url\"\r\n [placeholder]=\"config.locationConfig?.onlinePlaceholder || (controller.labels['PH_LOC_ONLINE'] || 'https://zoom.us/j/...')\"\r\n [value]=\"locationOnlineUrl\" (input)=\"onLocationUrlChange($any($event.target).value)\"\r\n [class.is-invalid]=\"errorMessage\">\r\n </div>\r\n </div>\r\n\r\n <!-- TBA TAB -->\r\n <div *ngIf=\"locationActiveTab === 'TBA'\"\r\n class=\"loc-panel loc-tba-panel d-flex flex-column gap-12 justify-content-center\">\r\n <div\r\n class=\"loc-tba-content d-flex flex-column align-items-center justify-content-center text-center gap-12 p-32px-24px b-F9FAFB b-1px-dashed-D1D5DB br-10px\">\r\n <mat-icon class=\"loc-tba-icon fs-40px c-9CA3AF\">schedule</mat-icon>\r\n <p class=\"loc-tba-text m-0 c-6B7280 fs-0-9rem\">\r\n {{ controller.labels['LBL_LOC_TBA_DESC'] || \"This event's location is yet to be announced. Check back later\r\n for updates.\" }}\r\n </p>\r\n </div>\r\n </div>\r\n\r\n <!-- Hidden real form control -->\r\n <input type=\"hidden\" [formControlName]=\"config.name!\">\r\n\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n</div>", styles: [".d-flex{display:flex}.d-inline-flex{display:inline-flex}.d-grid{display:grid}.d-block{display:block}.d-none{display:none}.flex-column{flex-direction:column}.flex-row{flex-direction:row}.flex-row-reverse{flex-direction:row-reverse}.flex-wrap{flex-wrap:wrap}.flex-1{flex:1}.align-items-center{align-items:center}.align-items-start{align-items:flex-start}.align-items-end{align-items:flex-end}.justify-content-center{justify-content:center}.justify-content-between{justify-content:space-between}.justify-content-start{justify-content:flex-start}.justify-content-end{justify-content:flex-end}.grid-cols-12{grid-template-columns:repeat(12,1fr)}.w-100{width:100%}.h-100{height:100%}.position-relative{position:relative}.position-absolute{position:absolute}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.font-poppins{font-family:var(--cc-sf-font-family, \"Poppins\", sans-serif)}.font-weight-400{font-weight:400}.font-weight-500{font-weight:500}.font-weight-600{font-weight:600}.text-13{font-size:13px}.text-14{font-size:14px}.text-16{font-size:16px}.color-white{color:#fff}.color-dark{color:#111827}.color-gray{color:#6b7280}.color-error{color:var(--cc-sf-error-text-color, #DC2626)}.bg-white{background-color:#fff}.bg-transparent{background-color:transparent}.m-0{margin:0}.mt-4{margin-top:4px}.mt-8{margin-top:8px}.mt-10{margin-top:10px}.mt-12{margin-top:12px}.mt-16{margin-top:16px}.mt-20{margin-top:20px}.mt-24{margin-top:24px}.mb-0{margin-bottom:0}.mb-4{margin-bottom:4px}.mb-8{margin-bottom:8px}.mb-10{margin-bottom:10px}.mb-12{margin-bottom:12px}.mb-16{margin-bottom:16px}.mb-20{margin-bottom:20px}.mb-24{margin-bottom:24px}.ml-16{margin-left:16px}.ml-20{margin-left:20px}.p-0{padding:0}.p-16{padding:16px}.p-20{padding:20px}.p-24{padding:24px}.pt-20{padding-top:20px}.pb-10{padding-bottom:10px}.gap-4{gap:4px}.gap-6{gap:6px}.gap-8{gap:8px}.gap-10{gap:10px}.gap-12{gap:12px}.gap-16{gap:16px}.gap-20{gap:20px}.rounded-4{border-radius:4px}.rounded-6{border-radius:6px}.rounded-8{border-radius:8px}.rounded-10{border-radius:10px}.rounded-12{border-radius:12px}.rounded-20{border-radius:20px}.rounded-24{border-radius:24px}.rounded-50{border-radius:50%}.cursor-pointer{cursor:pointer}.overflow-hidden{overflow:hidden}.resize-vertical{resize:vertical}.box-sizing-border{box-sizing:border-box}.border-none{border:none!important}.mb-16px{margin-bottom:var(--cc-sf-grid-gap, 16px)!important}.c-DC2626{color:var(--cc-sf-label-required-color, #DC2626)!important}.ml-0-125rem{margin-left:.125rem!important}.fs-0-875rem{font-size:.875rem!important}.c-111827{color:var(--cc-sf-label-color, #111827)!important}.br-7px{border-radius:var(--cc-sf-input-radius, 7px)!important}.c-6B7280{color:var(--cc-sf-hint-color, #6B7280)!important}.fs-0-75rem{font-size:var(--cc-sf-error-text-size, .75rem)!important}.b-none{background:none!important}.p-32px-24px{padding:32px 24px!important}.us-none{-webkit-user-select:none!important;user-select:none!important}.c-1E293B{color:var(--cc-sf-label-color, #1E293B)!important}.c-3B82F6{color:var(--cc-sf-chip-selected-bg, #3B82F6)!important}.fs-0-78rem{font-size:.78rem!important}.p-10px-14px{padding:10px 14px!important}.fs-0-85rem{font-size:.85rem!important}.fs-0-72rem{font-size:.72rem!important}.c-94A3B8{color:#94a3b8!important}.p-4px{padding:4px!important}.br-8px{border-radius:var(--cc-sf-input-radius, 8px)!important}.bc-F3F4F6{background-color:var(--cc-sf-input-disabled-bg, #F3F4F6)!important}.br-none{border-right:none!important}.bl-none{border-left:none!important}.pe-none{pointer-events:none!important}.fs-1-1rem{font-size:1.1rem!important}.c-9CA3AF{color:var(--cc-sf-hint-color, #9CA3AF)!important}.pl-2-4rem{padding-left:2.4rem!important}.fs-0-8125rem{font-size:.8125rem!important}.ls-none{list-style:none!important}.br-12px{border-radius:var(--mu-carousel-radius, 12px)!important}.b-FFFAF1{background:var(--cc-sf-dropzone-bg, #FFFAF1)!important}.fs-18px{font-size:18px!important}.b-FEF2F2{background:var(--cc-sf-error-bg, #FEF2F2)!important}.bc-DC2626{border-color:var(--cc-sf-error-border, #DC2626)!important}.c-202124{color:var(--cc-sf-label-color, #202124)!important}.fs-18px{font-size:var(--cc-sf-label-size, 18px)!important}.mb-0-5rem{margin-bottom:.5rem!important}.pt-0-625rem{padding-top:var(--cc-sf-input-padding-y, .625rem)!important}.pb-0-625rem{padding-bottom:var(--cc-sf-input-padding-y, .625rem)!important}.pl-16px{padding-left:var(--cc-sf-input-padding-x, 16px)!important}.pr-16px{padding-right:var(--cc-sf-input-padding-x, 16px)!important}.bc-ffffff{background-color:var(--cc-sf-section-bg, #ffffff)!important}.b-1px-solid-D1D5DB{border:1px solid var(--cc-sf-input-border, #D1D5DB)!important}.fs-0-75rem{font-size:.75rem!important}.c-1F2937{color:var(--cc-sf-section-label-color, #1F2937)!important}.p-6px-14px{padding:var(--cc-sf-chip-padding, 6px 14px)!important}.b-ffffff{background:var(--loc-suggestion-bg, #ffffff)!important}.c-374151{color:var(--cc-sf-label-color, #374151)!important}.br-20px{border-radius:var(--cc-sf-chip-radius, 20px)!important}.fs-0-875rem{font-size:var(--cc-sf-btn-font-size, .875rem)!important}.bc-D1D5DB{background-color:var(--cc-sf-switch-track-off, #D1D5DB)!important}.pr-2-75rem{padding-right:2.75rem!important}.p-0-25rem{padding:.25rem!important}.p-0-625rem-0-875rem{padding:var(--cc-sf-generated-padding, .625rem .875rem)!important}.b-F3F4F6{background:var(--cc-sf-generated-bg, #F3F4F6)!important}.b-1px-solid-E5E7EB{border:1px solid var(--cc-sf-input-disabled-border, #E5E7EB)!important}.br-8px{border-radius:var(--cc-sf-uploaded-item-radius, 8px)!important}.c-6B7280{color:var(--ms-desc-color, #6B7280)!important}.mb-20px{margin-bottom:var(--cc-sf-section-gap, 20px)!important}.br-10px{border-radius:var(--cc-sf-input-radius, 10px)!important}.p-20px{padding:var(--cc-sf-section-padding, 20px)!important}.fs-1rem{font-size:1rem!important}.m-0-0-16px-0{margin:0 0 16px!important}.bb-2px-solid-E5E7EB{border-bottom:var(--cc-sf-section-label-border, 2px solid #E5E7EB)!important}.p-16px{padding:var(--cc-sf-instance-padding, 16px)!important}.b-F9FAFB{background:var(--loc-tba-bg, #F9FAFB)!important}.bb-1px-dashed-D1D5DB{border-bottom:var(--cc-sf-instance-divider, 1px dashed #D1D5DB)!important}.c-4B5563{color:var(--cc-sf-instance-num-color, #4B5563)!important}.fs-0-8125rem{font-size:var(--cc-sf-hint-size, .8125rem)!important}.pb-0{padding-bottom:0!important}.p-18px-24px{padding:18px 24px!important}.c-111827{color:var(--ms-title-color, #111827)!important}.bt-1px-solid-E5E7EB{border-top:1px solid #E5E7EB!important}.p-4px-10px{padding:4px 10px!important}.b-FFF5F5{background:var(--cc-sf-btn-remove-bg, #FFF5F5)!important}.c-E53E3E{color:var(--loc-delete-color, #E53E3E)!important}.b-1px-solid-FED7D7{border:var(--cc-sf-btn-remove-border, 1px solid #FED7D7)!important}.br-4px{border-radius:var(--cc-sf-btn-remove-radius, 4px)!important}.p-8px-16px{padding:8px 16px!important}.b-transparent{background:var(--cc-sf-btn-add-bg, transparent)!important}.c-3B82F6{color:var(--cc-sf-input-focus-border, #3B82F6)!important}.b-1px-dashed-CBD5E1{border:var(--cc-sf-btn-add-border, 1px dashed #CBD5E1)!important}.br-6px{border-radius:var(--cc-sf-btn-add-radius, 6px)!important}.b-1-5px-dashed-CBD5E1{border:var(--cc-sf-dropzone-border, 1.5px dashed #CBD5E1)!important}.br-12px{border-radius:var(--cc-sf-dropzone-radius, 12px)!important}.bc-FFFAF1{background-color:var(--cc-sf-dropzone-bg, #FFFAF1)!important}.c-94A3B8{color:var(--cc-sf-uploaded-remove-color, #94A3B8)!important}.fs-0-9rem{font-size:var(--cc-sf-input-font-size, .9rem)!important}.c-64748B{color:var(--cc-sf-dropzone-hint-color, #64748B)!important}.b-1px-solid-E2E8F0{border:var(--cc-sf-uploaded-item-border, 1px solid #E2E8F0)!important}.b-2px-solid-E2E8F0{border:2px solid #E2E8F0!important}.pr-3-5rem{padding-right:3.5rem!important}.p-0-0-875rem{padding:0 .875rem!important}.bc-FFFFFF{background-color:var(--cc-sf-input-bg, #FFFFFF)!important}.b-1-5px-solid-D1D5DB{border:var(--cc-sf-input-border, 1.5px solid #D1D5DB)!important}.mb-0-75rem{margin-bottom:.75rem!important}.mt-6px{margin-top:6px!important}.pr-2-4rem{padding-right:2.4rem!important}.p-0-2rem{padding:.2rem!important}.fs-1-35rem{font-size:1.35rem!important}.p-4px-12px{padding:4px 12px!important}.b-111827{background:var(--cc-sf-label-color, #111827)!important}.b-2px-dashed-CBD5E1{border:2px dashed var(--cc-sf-dropzone-border, #CBD5E1)!important}.fs-52px{font-size:52px!important}.p-12px-16px{padding:12px 16px!important}.bb-1px-solid-F3F4F6{border-bottom:1px solid var(--cc-sf-input-disabled-border, #F3F4F6)!important}.b-0F172A{background:var(--mu-carousel-bg, #0F172A)!important}.b-3px-solid-rgba-255-255-255-0-15{border:3px solid rgba(255,255,255,.15)!important}.b-rgba-255-255-255-0-85{background:#ffffffd9!important}.b-rgba-0-0-0-0-55{background:#0000008c!important}.b-rgba-255-255-255-0-45{background:#ffffff73!important}.pb-4px{padding-bottom:4px!important}.b-2px-solid-transparent{border:2px solid transparent!important}.b-E2E8F0{background:var(--mu-thumb-bg, #E2E8F0)!important}.b-1E293B{background:#1e293b!important}.c-EF4444{color:#ef4444!important}.b-rgba-0-0-0-0-5{background:#00000080!important}.br-16px{border-radius:var(--mu-modal-radius, 16px)!important}.p-24px-28px{padding:24px 28px!important}.bb-1px-solid-E5E7EB{border-bottom:1px solid var(--cc-sf-input-disabled-border, #E5E7EB)!important}.fs-1-25rem{font-size:1.25rem!important}.p-48px-24px{padding:48px 24px!important}.b-3px-solid-E2E8F0{border:3px solid #E2E8F0!important}.p-16px-24px{padding:16px 24px!important}.p-28px{padding:28px!important}.b-3px-solid-transparent{border:3px solid transparent!important}.b-rgba-59-130-246-0-12{background:#3b82f61f!important}.p-20px-28px{padding:20px 28px!important}.c-1A56DB{color:var(--loc-add-color, #1A56DB)!important}.b-1px-dashed-D1D5DB{border:1px dashed var(--cc-sf-input-disabled-border, #D1D5DB)!important}.fs-40px{font-size:40px!important}.c-9CA3AF{color:var(--loc-tba-icon-color, #9CA3AF)!important}.form-field{font-family:var(--cc-sf-font-family, \"Poppins\", sans-serif)!important}:host{--cc-sf-input-border: #D1D5DB;--cc-sf-input-bg: #ffffff;--cc-sf-input-radius: 9px;--cc-sf-input-height: 44px;--cc-sf-label-color: #111827;--cc-sf-hint-color: #9CA3AF;--cc-sf-error-border: #EF4444;--cc-sf-error-bg: #FFF5F5;--cc-sf-accent-color: #6366F1;--cc-sf-input-focus-border: #6366F1;--cc-sf-input-hover-border: #A5B4FC;--cc-sf-input-placeholder: #C4C9D4;--cc-sf-input-disabled-bg: #F8F9FB;--cc-sf-input-disabled-border: #E5E7EB;--cc-sf-switch-track-on: #6366F1;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-thumb: #ffffff;--cc-sf-selected-color: #6366F1}.form-row{gap:var(--cc-sf-grid-gap, 16px)}.form-row.horizontal{display:flex;flex-direction:row}.form-row.horizontal>*{flex:1}.form-row:not(.horizontal){flex-direction:column}.form-row.grid-row{display:grid;grid-template-columns:repeat(12,1fr);gap:var(--cc-sf-grid-gap, 16px);align-items:start}@media(max-width:640px){.form-row.grid-row{grid-template-columns:1fr}.form-row.grid-row .row-field{grid-column:span 12!important}}.field-label{font-size:.75rem;font-weight:600;line-height:1;letter-spacing:.04em;text-transform:uppercase;color:#6b7280}.field-input,input.matInput,.mat-mdc-input-element{display:block;width:100%;height:var(--cc-sf-input-height)!important;padding:0 14px!important;font-family:inherit;font-size:.9rem;color:var(--cc-sf-label-color);background-color:var(--cc-sf-input-bg)!important;border:1.5px solid var(--cc-sf-input-border)!important;border-radius:var(--cc-sf-input-radius)!important;box-sizing:border-box;box-shadow:0 1px 2px #0000000a!important;transition:all .2s cubic-bezier(.4,0,.2,1)}.field-input::placeholder,input.matInput::placeholder,.mat-mdc-input-element::placeholder{font-weight:400;font-size:14px;color:var(--cc-sf-input-placeholder)}.field-input{opacity:var(--cc-sf-input-opacity, 1);line-height:var(--cc-sf-input-line-height, 1.5);transition:var(--cc-sf-input-transition, all .2s ease)}.field-input::placeholder{font-weight:var(--cc-sf-placeholder-weight, 400);font-size:var(--cc-sf-placeholder-size, 14px);line-height:var(--cc-sf-placeholder-line-height, 100%);color:var(--cc-sf-input-placeholder)}.field-input:hover:not(:disabled):not([readonly]){border-color:var(--cc-sf-input-hover-border)!important;box-shadow:0 1px 4px #6366f114!important}.field-input:focus{outline:none;border-color:var(--cc-sf-input-focus-border)!important;box-shadow:0 0 0 3px #6366f124,0 1px 4px #6366f11a!important;background-color:#fefeff!important}.field-input:disabled,.field-input[readonly]{background-color:var(--cc-sf-input-disabled-bg)!important;color:#9ca3af!important;cursor:not-allowed;border-color:var(--cc-sf-input-disabled-border)!important;box-shadow:none!important}.field-input.is-invalid{border-color:var(--cc-sf-error-border)!important;background-color:var(--cc-sf-error-bg)!important}.field-input.is-invalid:focus{box-shadow:0 0 0 3px #ef44441f,0 1px 4px #ef44441a!important}.field-input.textarea{resize:vertical;min-height:100px;height:auto;padding:12px 16px!important}input[type=time].time-input{cursor:pointer}input[type=time].time-input::-webkit-calendar-picker-indicator{cursor:pointer;opacity:.7;filter:invert(30%)}input[type=time].time-input::-webkit-calendar-picker-indicator:hover{opacity:1}select.field-input{appearance:none;background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3E%3Cpath stroke='%236B7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3E%3C/svg%3E\");background-position:right .5rem center;background-repeat:no-repeat;background-size:1.5em 1.5em;padding-right:2.5rem;cursor:pointer}select.field-input:disabled{cursor:not-allowed}.char-count-hint{font-style:normal;line-height:100%;letter-spacing:.02em}.radio-group.layout-column,.checkbox-group.layout-column{display:grid!important;grid-template-columns:repeat(12,1fr);gap:16px;width:100%}.radio-group.layout-row,.checkbox-group.layout-row{flex-direction:column!important;gap:12px;width:100%}.radio-label input,.checkbox-label input{cursor:pointer;accent-color:var(--cc-sf-chip-selected-bg, #F05A28)}.radio-label.card-item,.checkbox-label.card-item{display:flex!important;flex-direction:row-reverse!important;justify-content:space-between!important;align-items:center!important;border:1px solid var(--cc-sf-input-disabled-border, #E5E7EB);border-radius:12px;padding:16px 20px;box-sizing:border-box;transition:all .2s ease;background:var(--cc-sf-input-bg, #ffffff);margin-bottom:0}.radio-label.card-item input,.checkbox-label.card-item input{margin-left:16px}.radio-label.card-item.selected,.checkbox-label.card-item.selected{border-color:var(--cc-sf-selected-color);background-color:#f05a280d}.radio-label.card-item .option-content .label-text,.checkbox-label.card-item .option-content .label-text,.checkbox-single .checkbox-label{font-weight:var(--cc-sf-label-weight, 500)}.chip-label{transition:var(--cc-sf-input-transition, all .2s ease)}.chip-label:hover{background:var(--cc-sf-chip-hover-bg, #F3F4F6)}.chip-label.selected{background:var(--cc-sf-selected-color);color:var(--cc-sf-chip-selected-color, #ffffff);border-color:var(--cc-sf-selected-color)}.switch{width:50px;height:24px;display:inline-block}.switch input{opacity:0;width:0;height:0;position:absolute}.switch input:checked+.slider{background-color:var(--cc-sf-switch-track-on)!important}.switch input:checked+.slider:before{transform:translate(26px)}.switch .slider{inset:0;transition:.4s;background-color:var(--cc-sf-switch-track-off);border-radius:24px}.switch .slider:before{position:absolute;content:\"\";height:18px;width:18px;left:3px;bottom:3px;background-color:var(--cc-sf-switch-thumb);transition:.4s;border-radius:50%}.rating-group .star{transition:var(--cc-sf-input-transition, all .2s ease)}.rating-group .star mat-icon{font-size:var(--cc-sf-star-size, 28px);width:var(--cc-sf-star-size, 28px);height:var(--cc-sf-star-size, 28px);line-height:var(--cc-sf-star-size, 28px);color:var(--cc-sf-star-empty, #D1D5DB);transition:var(--cc-sf-input-transition, all .2s ease)}.rating-group .star.filled mat-icon,.rating-group .star.half mat-icon{color:var(--cc-sf-star-filled, #F59E0B)}.rating-group .star:hover mat-icon{color:var(--cc-sf-star-filled, #F59E0B)}.password-wrapper .password-toggle{right:.625rem;top:50%;transform:translateY(-50%);line-height:1;transition:color var(--cc-sf-input-transition, .2s ease)}.password-wrapper .password-toggle mat-icon.eye-icon{font-size:1.125rem;width:1.125rem;height:1.125rem;line-height:1.125rem}.password-wrapper .password-toggle:hover{color:var(--cc-sf-label-color, #374151)}.password-wrapper .password-toggle:focus{outline:none}.group-section-wrapper .group-label{font-size:var(--cc-sf-section-label-size, 1rem);font-weight:var(--cc-sf-section-label-weight, 600);color:var(--cc-sf-section-label-color, #1F2937);margin:0 0 16px;padding-left:12px;padding-top:2px;padding-bottom:2px;border-left:var(--cc-sf-section-header-accent-width, 4px) solid var(--cc-sf-section-header-accent-color, #3B82F6);line-height:1.4}.group-section-wrapper .group-fields.sf-grid{display:grid;grid-template-columns:repeat(12,1fr);gap:var(--cc-sf-grid-gap, 16px);align-items:start}@media(max-width:640px){.group-section-wrapper .group-fields.sf-grid{grid-template-columns:1fr}.group-section-wrapper .group-fields.sf-grid .sf-col{grid-column:span 12!important}}.group-section-wrapper .group-accordion-instance{border:var(--cc-sf-instance-border, 1px solid #E5E7EB);border-radius:var(--cc-sf-section-border-radius-inner, 8px);margin-bottom:8px;overflow:hidden;transition:border-color .2s ease}.group-section-wrapper .group-accordion-instance:last-of-type{margin-bottom:0}.group-section-wrapper .group-accordion-instance .group-accordion-header{display:flex;justify-content:space-between;align-items:center;padding:10px 14px;background:var(--cc-sf-repeater-accordion-header-bg, #F9FAFB);cursor:pointer;-webkit-user-select:none;user-select:none;transition:background .15s ease}.group-section-wrapper .group-accordion-instance .group-accordion-header:hover{background:var(--cc-sf-repeater-accordion-active-bg, #EFF6FF)}.group-section-wrapper .group-accordion-instance .group-accordion-header .instance-badge{width:22px;height:22px;border-radius:50%;background:var(--cc-sf-repeater-badge-bg, #E5E7EB);color:var(--cc-sf-repeater-badge-color, #374151);font-size:.75rem;font-weight:600;display:flex;align-items:center;justify-content:center;flex-shrink:0}.group-section-wrapper .group-accordion-instance .group-accordion-header .instance-title{font-size:var(--cc-sf-instance-num-size, .8125rem);font-weight:600;color:var(--cc-sf-repeater-accordion-header-color, #1F2937)}.group-section-wrapper .group-accordion-instance .group-accordion-header .accordion-remove-btn{background:none;border:none;cursor:pointer;color:var(--cc-sf-btn-remove-color, #E53E3E);padding:4px;border-radius:4px;line-height:1;display:flex;align-items:center;transition:background .15s ease}.group-section-wrapper .group-accordion-instance .group-accordion-header .accordion-remove-btn mat-icon{font-size:1.1rem;width:1.1rem;height:1.1rem;line-height:1.1rem}.group-section-wrapper .group-accordion-instance .group-accordion-header .accordion-remove-btn:hover{background:var(--cc-sf-btn-remove-hover-bg, #FED7D7)}.group-section-wrapper .group-accordion-instance .group-accordion-header .accordion-chevron{font-size:1.25rem;width:1.25rem;height:1.25rem;line-height:1.25rem;color:var(--cc-sf-instance-num-color, #4B5563)}.group-section-wrapper .group-accordion-instance .group-accordion-body{padding:var(--cc-sf-instance-padding, 16px);background:var(--cc-sf-instance-bg, #F9FAFB);border-top:var(--cc-sf-instance-divider, 1px dashed #D1D5DB)}.group-section-wrapper .btn-add-group{display:flex;align-items:center;justify-content:center;gap:6px;width:100%;padding:10px 20px;margin-top:12px;background:var(--cc-sf-btn-add-bg, transparent);color:var(--cc-sf-btn-add-color, #3B82F6);border:var(--cc-sf-btn-add-border, 1px dashed #CBD5E1);border-radius:var(--cc-sf-btn-add-radius, 6px);cursor:pointer;font-family:inherit;font-size:var(--cc-sf-btn-font-size, .875rem);font-weight:var(--cc-sf-btn-font-weight, 600);transition:var(--cc-sf-btn-transition, all .2s ease)}.group-section-wrapper .btn-add-group mat-icon{font-size:1.1rem;width:1.1rem;height:1.1rem;line-height:1.1rem}.group-section-wrapper .btn-add-group:hover{background:var(--cc-sf-btn-add-hover-bg, #EFF6FF);border-color:var(--cc-sf-btn-add-hover-border, #BFDBFE)}.group-section-wrapper .group-instance:last-child{margin-bottom:0}.group-section-wrapper.multi-save-active{border:none;box-shadow:none;padding:0;background:transparent}.group-section-wrapper.multi-save-active .multi-save-header .btn-add-multi ::ng-deep button{color:var(--ms-btn-add-color, #3B82F6);font-weight:600;font-size:.875rem;padding:8px 12px}.group-section-wrapper.multi-save-active .multi-save-header .btn-add-multi ::ng-deep button:hover{color:var(--ms-btn-add-hover, #2563EB);background-color:var(--cc-sf-btn-add-hover-bg, #EFF6FF)}.group-section-wrapper.multi-save-active .group-instance{box-shadow:var(--ms-card-shadow, 0 1px 4px rgba(0, 0, 0, .05))}.group-section-wrapper.multi-save-active .group-instance.is-editing{padding:24px}.group-section-wrapper.multi-save-active .group-instance.is-card{cursor:pointer;transition:all .2s ease-in-out}.group-section-wrapper.multi-save-active .group-instance.is-card:hover{box-shadow:var(--ms-card-shadow-hover, 0 8px 24px rgba(0, 0, 0, .08));border-color:var(--cc-sf-input-focus-border, #3B82F6)}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view .card-content .card-title{white-space:nowrap;text-overflow:ellipsis}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view .card-content .card-desc{line-height:1.4;display:-webkit-box;-webkit-line-clamp:1;line-clamp:1;-webkit-box-orient:vertical}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view.is-expanded .card-content .card-desc{-webkit-line-clamp:unset;line-clamp:unset}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view .card-actions mat-icon{font-size:22px;width:22px;height:22px;color:var(--cc-sf-hint-color, #9CA3AF);transition:color .2s}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view .card-actions mat-icon.icon-delete:hover{color:var(--cc-sf-error-border, #DC2626)}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view .card-actions mat-icon.icon-edit:hover{color:var(--cc-sf-input-focus-border, #3B82F6)}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view .card-actions mat-icon.icon-expand{color:var(--cc-sf-input-disabled-border, #E5E7EB)}.btn-remove{transition:var(--cc-sf-btn-transition, all .2s ease)}.btn-remove mat-icon{font-size:1rem;width:1rem;height:1rem;line-height:1rem}.btn-remove:hover{background:var(--cc-sf-btn-remove-hover-bg, #FED7D7)}.btn-add-group{font-weight:var(--cc-sf-btn-font-weight, 600);transition:var(--cc-sf-btn-transition, all .2s ease)}.btn-add-group mat-icon{font-size:1.1rem;width:1.1rem;height:1.1rem;line-height:1.1rem}.btn-add-group:hover{background:var(--cc-sf-btn-add-hover-bg, #EFF6FF);border-color:var(--cc-sf-btn-add-hover-border, #BFDBFE)}.upload-drop-zone{background-color:var(--cc-sf-dropzone-bg, #F8FAFC);border:var(--cc-sf-dropzone-border, 1.5px dashed #CBD5E1);border-radius:var(--cc-sf-dropzone-radius, 12px);transition:background-color .2s ease,border-color .2s ease}.upload-drop-zone:hover{background-color:var(--cc-sf-dropzone-hover-bg, #EFF6FF);border-color:var(--cc-sf-dropzone-hover-border, #93C5FD)}.upload-drop-zone.drag-over{background-color:var(--cc-sf-dropzone-hover-bg, #EFF6FF);border-color:var(--cc-sf-dropzone-over-border, #3B82F6);box-shadow:var(--cc-sf-dropzone-over-shadow, 0 0 0 4px rgba(59, 130, 246, .12))}.upload-drop-zone.is-invalid{border-color:var(--cc-sf-error-border, #DC2626);background-color:var(--cc-sf-error-bg, #FEF2F2)}.upload-icon-wrap .dropzone-icon-pill{width:52px;height:52px;border-radius:50%;background:var(--cc-sf-dropzone-icon-bg, rgba(59, 130, 246, .1))}.upload-icon-wrap mat-icon.upload-cloud-icon{font-size:28px;width:28px;height:28px;line-height:28px;color:var(--cc-sf-accent-color, #3B82F6)}.upload-main-text{color:var(--cc-sf-label-color, #1E293B)}.upload-sub-text{color:var(--cc-sf-hint-color, #64748B)}.upload-link{color:var(--cc-sf-dropzone-link-color, #3B82F6);font-weight:500}.upload-formats{color:var(--cc-sf-dropzone-link-color, #3B82F6)}.upload-size-badge{display:inline-block;padding:2px 8px;border-radius:20px;background:var(--cc-sf-input-disabled-bg, #F3F4F6);color:var(--cc-sf-hint-color, #6B7280);font-weight:500}.uploaded-item{background:var(--cc-sf-uploaded-item-bg, #ffffff);border:var(--cc-sf-uploaded-item-border, 1px solid #E2E8F0);border-radius:var(--cc-sf-uploaded-item-radius, 8px);transition:box-shadow .15s ease}.uploaded-item:hover{box-shadow:0 2px 6px #0000000f}.uploaded-item mat-icon.file-type-icon{font-size:20px;width:20px;height:20px;line-height:20px;flex-shrink:0;color:var(--cc-sf-hint-color, #64748B)}.uploaded-item .file-thumb{width:36px;height:36px;object-fit:cover;flex-shrink:0}.uploaded-item .file-info{min-width:0;gap:2px}.uploaded-item .file-info .file-name{white-space:nowrap;text-overflow:ellipsis}.uploaded-item .file-remove-btn{flex-shrink:0;width:32px;height:32px;background:none;border:none;cursor:pointer;color:var(--cc-sf-uploaded-remove-color, #94A3B8);padding:0;display:flex;align-items:center;justify-content:center;transition:color .15s ease,background .15s ease}.uploaded-item .file-remove-btn mat-icon{font-size:1.1rem;width:1.1rem;height:1.1rem;line-height:1.1rem}.uploaded-item .file-remove-btn:hover:not(:disabled){color:var(--cc-sf-uploaded-remove-hover-color, #DC2626);background:var(--cc-sf-uploaded-remove-hover-bg, #FEF2F2)}.uploaded-item .file-remove-btn:disabled{opacity:.4;cursor:not-allowed}.uploaded-item.uploading{background:var(--cc-sf-uploaded-uploading-bg, #F8FAFC);border-color:var(--cc-sf-uploaded-uploading-border, #CBD5E1);opacity:.85}.upload-spinner{width:20px;height:20px;flex-shrink:0;border-top-color:var(--cc-sf-accent-color, #3B82F6);animation:cc-spin .7s linear infinite}@keyframes cc-spin{to{transform:rotate(360deg)}}.uploading-label{font-style:italic}.input-group{align-items:stretch}.input-group .field-input{flex:1;width:auto}.input-prefix+.input-group .field-input{border-top-left-radius:0;border-bottom-left-radius:0}.input-group .field-input:has(+.input-suffix){border-top-right-radius:0;border-bottom-right-radius:0}.input-group .field-input.has-icon-right{padding-right:3rem}.input-group.readonly .field-input{cursor:default}.input-prefix,.input-suffix{display:flex!important;align-items:center;white-space:nowrap;padding:0 14px;background-color:var(--cc-sf-input-disabled-bg);border:1px solid var(--cc-sf-input-border);font-size:.875rem;color:var(--cc-sf-hint-color);-webkit-user-select:none;user-select:none}.input-prefix{border-right:none;border-top-left-radius:var(--cc-sf-input-radius, 8px);border-bottom-left-radius:var(--cc-sf-input-radius, 8px)}.input-suffix{border-left:none;border-top-right-radius:var(--cc-sf-input-radius, 8px);border-bottom-right-radius:var(--cc-sf-input-radius, 8px)}.readonly-icons{right:.875rem;top:50%;transform:translateY(-50%)}.readonly-icons mat-icon.lock-icon{font-size:1rem;width:1rem;height:1rem;line-height:1rem;opacity:.5;color:var(--cc-sf-hint-color, #6B7280)}.date-icon-wrapper{right:.5rem;top:50%;transform:translateY(-50%);pointer-events:auto}.date-icon-wrapper .mat-icon-button{width:32px;height:32px;line-height:32px}.subfields-group-wrapper .subfields-row{transition:all .2s ease}.subfields-group-wrapper .subfields-row.is-invalid .subfield-item ::ng-deep .field-input{border-color:var(--cc-sf-error-border, #DC2626);background-color:var(--cc-sf-error-bg, #FEF2F2)}.subfields-group-wrapper .subfields-row .subfield-item{min-width:0}.subfields-group-wrapper .subfields-row .subfield-item ::ng-deep .field-label{font-size:.75rem!important;margin-bottom:4px!important;font-weight:500!important;color:var(--cc-sf-hint-color, #6B7280)!important}.subfields-group-wrapper .subfields-row .subfield-separator{font-weight:700}.autocomplete-wrapper .ac-input{padding-left:40px!important}.autocomplete-wrapper .ac-search-icon{left:.75rem;width:1.1rem;height:1.1rem;line-height:1.1rem;z-index:1;transition:color var(--cc-sf-input-transition, .2s ease)}.autocomplete-wrapper .ac-clear-btn{right:.6rem;transition:color .15s ease,background .15s ease}.autocomplete-wrapper .ac-clear-btn mat-icon{font-size:1rem;width:1rem;height:1rem;line-height:1rem}.autocomplete-wrapper .ac-clear-btn:hover{color:var(--cc-sf-label-color, #374151);background:var(--cc-sf-input-disabled-bg, #F3F4F6)}.autocomplete-wrapper .ac-clear-btn:focus{outline:none}.autocomplete-wrapper:focus-within .ac-search-icon{color:var(--cc-sf-accent-color, #3B82F6)}.autocomplete-wrapper.is-invalid .ac-input{border-color:var(--cc-sf-error-border)!important;background-color:var(--cc-sf-error-bg)}.autocomplete-wrapper.readonly .ac-input{background-color:var(--cc-sf-input-disabled-bg);color:var(--cc-sf-input-disabled-color, #6B7280);cursor:not-allowed;border-color:var(--cc-sf-input-disabled-border)!important}.ac-no-results{font-style:italic}.mu-layout{grid-template-columns:1fr 1fr;gap:32px}@media(max-width:768px){.mu-layout{grid-template-columns:1fr}}.mu-title{font-weight:700;line-height:1.3}.mu-badge{white-space:nowrap;flex-shrink:0}.mu-description{line-height:1.6}.mu-feature-item .mu-check{width:16px;height:16px;line-height:16px;flex-shrink:0}.mu-right{min-height:260px}.mu-right-empty{min-height:250px;max-width:400px;box-shadow:0 2px 10px #0000000d;transition:box-shadow .2s ease}.mu-right-empty:hover{cursor:pointer;box-shadow:0 4px 16px #0000001a}.mu-right-empty .mu-right-empty-icon{width:52px;height:52px;line-height:52px;opacity:.3}.mu-right-empty p{margin:0;font-size:.85rem}.media-add-container{display:inline-block}.media-add-container ::ng-deep button{display:flex;align-items:center;gap:6px}.media-add-container ::ng-deep button .menu-chevron{width:18px;height:18px;line-height:18px;transition:transform .2s ease}.media-dropdown{top:calc(100% + 6px);left:0;z-index:200;min-width:240px;box-shadow:var(--mu-dropdown-shadow, 0 8px 32px rgba(0, 0, 0, .12));animation:mu-fade-in .15s ease}@keyframes mu-fade-in{0%{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:translateY(0)}}.media-dropdown-item{transition:background .15s ease}.media-dropdown-item:last-child{border-bottom:none}.media-dropdown-item:hover{background:var(--cc-sf-dropzone-hover-bg, #F0F9FF)}.media-drop-icon{width:36px;height:36px;flex-shrink:0}.media-drop-icon mat-icon{font-size:20px;width:20px;height:20px;line-height:20px}.media-drop-icon--video{background:var(--mu-icon-video-bg, #FFF0F0);color:var(--mu-icon-video-color, #EF4444)}.media-drop-icon--device{background:var(--mu-icon-device-bg, #EFF6FF);color:var(--mu-icon-device-color, #3B82F6)}.media-drop-icon--library{background:var(--mu-icon-library-bg, #F0FDF4);color:var(--mu-icon-library-color, #22C55E)}.media-drop-text{gap:2px}.youtube-input-panel{animation:mu-fade-in .18s ease}.youtube-panel-label mat-icon{font-size:18px;width:18px;height:18px;line-height:18px;color:var(--mu-icon-video-color, #EF4444)}.youtube-input-row{align-items:stretch}.media-menu-backdrop{position:fixed;inset:0;z-index:100}.media-upload-status{animation:mu-fade-in .2s ease}.media-upload-status .status-icon{width:18px;height:18px;line-height:18px}.media-carousel-main{max-width:400px;height:var(--mu-carousel-height, 250px)}.carousel-viewer{inset:0}.carousel-viewer .carousel-image{object-fit:cover}.carousel-viewer .carousel-spinner{width:36px;height:36px;border-top-color:var(--cc-sf-accent-color, #3B82F6);animation:cc-spin .7s linear infinite}.carousel-nav{top:50%;transform:translateY(-50%);z-index:10;width:40px;height:40px;box-shadow:0 2px 8px #0003;transition:background .2s ease,opacity .2s ease;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.carousel-nav mat-icon{font-size:22px;width:22px;height:22px;line-height:22px;color:#1e293b}.carousel-nav:hover:not(:disabled){background:#fff}.carousel-nav:disabled{opacity:.3;cursor:not-allowed}.carousel-nav--prev{left:12px}.carousel-nav--next{right:12px}.carousel-remove-btn{top:10px;right:10px;z-index:10;width:32px;height:32px;transition:background .2s ease}.carousel-remove-btn mat-icon{font-size:18px;width:18px;height:18px;line-height:18px;color:#fff}.carousel-remove-btn:hover:not(:disabled){background:#dc2626d9}.carousel-remove-btn:disabled{opacity:.4;cursor:not-allowed}.carousel-dots{bottom:10px;left:50%;transform:translate(-50%);z-index:10}.carousel-dot{width:8px;height:8px;transition:background .2s ease,transform .2s ease}.carousel-dot.active{background:#fff;transform:scale(1.3)}.media-thumbnail-strip{max-width:400px;overflow-x:auto}.media-thumbnail-strip::-webkit-scrollbar{height:4px}.media-thumbnail-strip::-webkit-scrollbar-thumb{background:var(--cc-sf-input-disabled-border, #D1D5DB);border-radius:2px}.media-thumb{flex-shrink:0;width:72px;height:52px;transition:border-color .2s ease,transform .15s ease}.media-thumb.active{border-color:var(--mu-thumb-active-border, var(--cc-sf-accent-color, #3B82F6));transform:scale(1.04)}.media-thumb:hover:not(.active){border-color:var(--cc-sf-input-hover-border, #9CA3AF)}.media-thumb .thumb-img{object-fit:cover}.media-thumb .thumb-yt-placeholder mat-icon{font-size:28px;width:28px;height:28px;line-height:28px}.media-thumb .thumb-uploading .thumb-spinner{width:20px;height:20px;border-top-color:var(--cc-sf-accent-color, #3B82F6);animation:cc-spin .7s linear infinite}.media-library-overlay{position:fixed;inset:0;z-index:999;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);animation:mu-fade-in .2s ease}.media-library-modal{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);z-index:1000;width:min(90vw,780px);max-height:85vh;box-shadow:var(--mu-modal-shadow, 0 20px 60px rgba(0, 0, 0, .2));animation:mu-modal-in .22s cubic-bezier(.34,1.56,.64,1)}@keyframes mu-modal-in{0%{opacity:0;transform:translate(-50%,-48%) scale(.95)}to{opacity:1;transform:translate(-50%,-50%) scale(1)}}.library-modal-header{flex-shrink:0}.library-modal-title{font-weight:700}.library-modal-subtitle{line-height:1.5;max-width:600px}.library-close-btn{width:32px;height:32px;transition:background .15s ease,color .15s ease}.library-close-btn mat-icon{font-size:20px;width:20px;height:20px;line-height:20px}.library-close-btn:hover{background:var(--cc-sf-input-disabled-bg, #F3F4F6);color:var(--cc-sf-label-color, #374151)}.library-loading mat-icon,.library-empty mat-icon{font-size:40px;width:40px;height:40px;line-height:40px;opacity:.5}.lib-spinner{width:36px;height:36px;border-top-color:var(--cc-sf-accent-color, #3B82F6);animation:cc-spin .7s linear infinite}.library-error{flex-shrink:0}.library-error mat-icon{font-size:20px;width:20px;height:20px;line-height:20px}.library-grid{grid-template-columns:repeat(5,1fr);overflow-y:auto}.library-grid::-webkit-scrollbar{width:8px}.library-grid::-webkit-scrollbar-track{background:#f1f1f1}.library-grid::-webkit-scrollbar-thumb{background:#c1c1c1;border-radius:10px;border:2px solid #F1F1F1}.library-grid-item{aspect-ratio:1/1;transition:all .3s cubic-bezier(.4,0,.2,1);box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -1px #0000000f}.library-grid-item:hover{transform:translateY(-4px) scale(1.02);box-shadow:0 20px 25px -5px #0000001a,0 10px 10px -5px #0000000a}.library-grid-item.selected{border-color:var(--cc-sf-accent-color, #3B82F6)}.library-grid-item.selected .library-grid-img{opacity:.7}.library-grid-item:hover .library-overlay-hover{opacity:1}.library-grid-img{object-fit:cover}.library-overlay-hover{inset:0;opacity:0;transition:opacity .15s ease}.library-check{top:6px;right:6px;width:22px;height:22px;box-shadow:0 1px 4px #00000026}.library-check mat-icon{font-size:18px;width:18px;height:18px;line-height:18px}.library-modal-footer{flex-shrink:0}.library-modal-footer .library-footer-actions ::ng-deep .cc-btn-primary{background-color:var(--cc-sf-accent-color, #3B82F6)!important;border-color:var(--cc-sf-accent-color, #3B82F6)!important;color:#fff!important;font-weight:600;padding-left:32px;padding-right:32px}.library-modal-footer .library-footer-actions ::ng-deep .cc-btn-primary:hover{background-color:var(--cc-sf-btn-primary-hover-bg, #2563EB)!important}.library-modal-footer .library-footer-actions ::ng-deep .cc-btn-primary:disabled{background-color:#93c5fd!important;cursor:not-allowed}.library-modal-footer .library-footer-actions ::ng-deep .cc-btn-outline{font-weight:600;padding-left:24px;padding-right:24px;border-color:#d1d5db;color:#374151}.library-modal-footer .library-footer-actions ::ng-deep .cc-btn-outline:hover{background-color:#f9fafb}.location-subtitle{line-height:1.5}.loc-tab-btn ::ng-deep button{width:100%}.loc-tab-btn ::ng-deep button:not(.cc-btn-warning){background-color:var(--cc-sf-input-bg, #ffffff)!important;color:var(--cc-sf-label-color, #000000)!important;border:1px solid var(--cc-sf-input-disabled-border, #E5E7EB)}.loc-tab-btn ::ng-deep button:not(.cc-btn-warning):hover{background-color:var(--cc-sf-input-disabled-bg, #F3F4F6)!important}.loc-venue-item{transition:box-shadow .15s ease,border-color .15s ease}.loc-venue-item:hover{box-shadow:0 2px 8px #0000000f;border-color:var(--cc-sf-input-hover-border, #9CA3AF)}.loc-venue-search-icon{width:18px;height:18px;line-height:18px;flex-shrink:0}.loc-venue-text{white-space:nowrap;text-overflow:ellipsis}.loc-action-btn{transition:background .15s ease,color .15s ease;flex-shrink:0}.loc-action-btn mat-icon{font-size:18px;width:18px;height:18px;line-height:18px}.loc-action-btn.loc-delete-btn{color:var(--loc-delete-color, #E53E3E)}.loc-action-btn.loc-delete-btn:hover{background:var(--cc-sf-error-bg, #FEF2F2)}.loc-action-btn.loc-edit-btn{color:var(--cc-sf-hint-color, #9CA3AF)}.loc-action-btn.loc-edit-btn:hover{color:var(--cc-sf-input-focus-border, #3B82F6);background:var(--cc-sf-dropzone-hover-bg, #EFF6FF)}.loc-search-icon{left:.75rem;width:1.1rem;height:1.1rem;line-height:1.1rem;z-index:1}.loc-suggestions-panel{top:calc(100% + 4px);left:0;right:0;z-index:300;box-shadow:0 8px 24px #0000001a;animation:mu-fade-in .15s ease;max-height:260px;overflow-y:auto}.loc-suggestion-item{transition:background .12s ease}.loc-suggestion-item:hover,.loc-suggestion-item:focus{background:var(--loc-suggestion-hover-bg, #F0F9FF)}.loc-suggestion-item:not(:last-child){border-bottom:1px solid var(--cc-sf-input-disabled-border, #F3F4F6)}.loc-suggestion-icon{width:18px;height:18px;line-height:18px;flex-shrink:0}.loc-suggestion-text{white-space:nowrap;text-overflow:ellipsis}.loc-add-btn{transition:opacity .15s ease}.loc-add-btn mat-icon{font-size:20px;width:20px;height:20px;line-height:20px}.loc-add-btn:hover{opacity:.8}.loc-map-container{box-shadow:0 2px 10px #0000000f}.loc-tba-panel{min-height:120px}.loc-tba-icon{width:40px;height:40px;line-height:40px;opacity:.6}.loc-tba-text{line-height:1.6;max-width:360px}\n"] }]
|
|
2203
2232
|
}], ctorParameters: () => [{ type: i1$3.FormBuilder }, { type: ExpressionService }, { type: i3.HttpClient }], propDecorators: { config: [{
|
|
2204
2233
|
type: Input
|
|
2205
2234
|
}], controller: [{
|
|
@@ -2223,6 +2252,8 @@ class FormSectionComponent {
|
|
|
2223
2252
|
* Each element is a FormGroup representing one repeater instance.
|
|
2224
2253
|
*/
|
|
2225
2254
|
repeaterFormArray;
|
|
2255
|
+
/** Tracks which accordion panels are open (by index). New instances start expanded. */
|
|
2256
|
+
expandedInstances = new Set();
|
|
2226
2257
|
/**
|
|
2227
2258
|
* The key under which the FormArray is registered in the root formGroup.
|
|
2228
2259
|
* Falls back to config.name or a generated key.
|
|
@@ -2252,13 +2283,37 @@ class FormSectionComponent {
|
|
|
2252
2283
|
return this.fb.group({});
|
|
2253
2284
|
}
|
|
2254
2285
|
addInstance() {
|
|
2286
|
+
const newIndex = this.repeaterFormArray.length;
|
|
2255
2287
|
this.repeaterFormArray.push(this.createInstanceGroup());
|
|
2288
|
+
// Collapse all existing panels; expand only the new one
|
|
2289
|
+
this.expandedInstances.clear();
|
|
2290
|
+
this.expandedInstances.add(newIndex);
|
|
2256
2291
|
}
|
|
2257
2292
|
removeInstance(index) {
|
|
2258
2293
|
if (this.repeaterFormArray.length > 1) {
|
|
2259
2294
|
this.repeaterFormArray.removeAt(index);
|
|
2295
|
+
// Rebuild expanded set to account for shifted indices
|
|
2296
|
+
const updated = new Set();
|
|
2297
|
+
this.expandedInstances.forEach(i => {
|
|
2298
|
+
if (i < index)
|
|
2299
|
+
updated.add(i);
|
|
2300
|
+
else if (i > index)
|
|
2301
|
+
updated.add(i - 1);
|
|
2302
|
+
});
|
|
2303
|
+
this.expandedInstances = updated;
|
|
2260
2304
|
}
|
|
2261
2305
|
}
|
|
2306
|
+
toggleInstance(index) {
|
|
2307
|
+
if (this.expandedInstances.has(index)) {
|
|
2308
|
+
this.expandedInstances.delete(index);
|
|
2309
|
+
}
|
|
2310
|
+
else {
|
|
2311
|
+
this.expandedInstances.add(index);
|
|
2312
|
+
}
|
|
2313
|
+
}
|
|
2314
|
+
isExpanded(index) {
|
|
2315
|
+
return this.expandedInstances.has(index);
|
|
2316
|
+
}
|
|
2262
2317
|
getInstanceGroup(index) {
|
|
2263
2318
|
return this.repeaterFormArray.at(index);
|
|
2264
2319
|
}
|
|
@@ -2285,11 +2340,11 @@ class FormSectionComponent {
|
|
|
2285
2340
|
return result;
|
|
2286
2341
|
}
|
|
2287
2342
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: FormSectionComponent, deps: [{ token: i1$3.FormBuilder }], target: i0.ɵɵFactoryTarget.Component });
|
|
2288
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: FormSectionComponent, isStandalone: false, selector: "lib-form-section", inputs: { config: "config", controller: "controller", formGroup: "formGroup" }, ngImport: i0, template: "<div class=\"form-section-container\">\
|
|
2343
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: FormSectionComponent, isStandalone: false, selector: "lib-form-section", inputs: { config: "config", controller: "controller", formGroup: "formGroup" }, ngImport: i0, template: "<div class=\"form-section-container\">\n <h3 class=\"section-label\" *ngIf=\"config.label && !config.allowMulti\">{{ config.label }}</h3>\n\n <!-- \u2550\u2550 Repeater (allowMulti) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n <ng-container *ngIf=\"config.allowMulti\">\n <h3 class=\"section-label\">{{ config.label }}</h3>\n\n <div *ngFor=\"let instanceGroup of instanceGroups; let i = index\"\n class=\"accordion-instance\"\n [class.is-expanded]=\"isExpanded(i)\">\n\n <!-- Accordion header (always visible) -->\n <div class=\"accordion-header\" (click)=\"toggleInstance(i)\" role=\"button\" [attr.aria-expanded]=\"isExpanded(i)\">\n <div class=\"accordion-header-left\">\n <span class=\"instance-badge\">{{ i + 1 }}</span>\n <span class=\"instance-title\">{{ config.label }} #{{ i + 1 }}</span>\n </div>\n <div class=\"accordion-header-right\">\n <button type=\"button\" class=\"accordion-remove-btn\"\n *ngIf=\"instanceGroups.length > 1\"\n (click)=\"$event.stopPropagation(); removeInstance(i)\"\n aria-label=\"Remove instance\">\n <mat-icon>delete_outline</mat-icon>\n </button>\n <mat-icon class=\"accordion-chevron\">\n {{ isExpanded(i) ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}\n </mat-icon>\n </div>\n </div>\n\n <!-- Accordion body (shown when expanded) -->\n <div class=\"accordion-body\" *ngIf=\"isExpanded(i)\">\n <div class=\"section-fields sf-grid\">\n <ng-container *ngFor=\"let field of config.children\">\n <div class=\"sf-col\" [style.gridColumn]=\"'span ' + (field.colSpan || 12)\"\n *ngIf=\"field.isEnabled !== false\">\n <lib-form-field [config]=\"field\" [controller]=\"controller\" [formGroup]=\"instanceGroup\">\n </lib-form-field>\n </div>\n </ng-container>\n </div>\n </div>\n </div>\n\n <!-- Full-width dashed Add button -->\n <button type=\"button\" class=\"btn-add-section\" (click)=\"addInstance()\">\n <mat-icon>add</mat-icon> Add {{ config.label }}\n </button>\n </ng-container>\n\n <!-- \u2550\u2550 Non-repeater (single instance) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n <ng-container *ngIf=\"!config.allowMulti\">\n <div class=\"section-fields sf-grid\">\n <ng-container *ngFor=\"let field of config.children\">\n <div class=\"sf-col\" [style.gridColumn]=\"'span ' + (field.colSpan || 12)\"\n *ngIf=\"field.isEnabled !== false\">\n <lib-form-field [config]=\"field\" [controller]=\"controller\" [formGroup]=\"flatFormGroup\">\n </lib-form-field>\n </div>\n </ng-container>\n </div>\n </ng-container>\n\n</div>\n", styles: ["@keyframes section-card-in{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}.form-section-container{background:#fff;border:1px solid #EAECF0;border-radius:14px;padding:22px 24px 24px;margin-bottom:14px;box-shadow:0 1px 2px #0000000a,0 4px 12px #6366f10a;animation:section-card-in .3s cubic-bezier(.4,0,.2,1) both;transition:box-shadow .2s ease}.form-section-container:hover{box-shadow:0 1px 2px #0000000a,0 6px 20px #6366f114}.form-section-container:last-child{margin-bottom:0}.form-section-container .section-label{display:flex;align-items:center;gap:10px;font-size:.9375rem;font-weight:700;color:#111827;margin:0 0 20px;padding-bottom:14px;border-bottom:1px solid #F3F4F6;letter-spacing:-.01em}.form-section-container .section-label:before{content:\"\";display:inline-block;width:4px;height:18px;border-radius:4px;background:linear-gradient(180deg,#6366f1,#8b5cf6);flex-shrink:0}.form-section-container .section-fields.sf-grid{display:grid;grid-template-columns:repeat(12,1fr);gap:18px 20px;align-items:start}@media(max-width:640px){.form-section-container .section-fields.sf-grid{grid-template-columns:1fr}.form-section-container .section-fields.sf-grid .sf-col{grid-column:span 12!important}}.form-section-container .accordion-instance{border:1px solid #E8EAF0;border-radius:10px;margin-bottom:10px;overflow:hidden;transition:border-color .2s ease,box-shadow .2s ease;background:#fafbff}.form-section-container .accordion-instance:last-of-type{margin-bottom:0}.form-section-container .accordion-instance.is-expanded{border-color:#c7d2fe;box-shadow:0 0 0 3px #6366f112}.form-section-container .accordion-instance .accordion-header{display:flex;justify-content:space-between;align-items:center;padding:11px 16px;background:#f8f9ff;cursor:pointer;-webkit-user-select:none;user-select:none;transition:background .15s ease}.form-section-container .accordion-instance .accordion-header:hover{background:#eef0ff}.form-section-container .accordion-instance .accordion-header .accordion-header-left{display:flex;align-items:center;gap:10px}.form-section-container .accordion-instance .accordion-header .instance-badge{width:24px;height:24px;border-radius:6px;background:linear-gradient(135deg,#6366f1,#8b5cf6);color:#fff;font-size:.75rem;font-weight:700;display:flex;align-items:center;justify-content:center;flex-shrink:0}.form-section-container .accordion-instance .accordion-header .instance-title{font-size:.8125rem;font-weight:600;color:#1f2937}.form-section-container .accordion-instance .accordion-header .accordion-header-right{display:flex;align-items:center;gap:6px}.form-section-container .accordion-instance .accordion-header .accordion-remove-btn{background:none;border:none;cursor:pointer;color:#ef4444;padding:4px 6px;border-radius:6px;line-height:1;display:flex;align-items:center;transition:background .15s ease,color .15s ease}.form-section-container .accordion-instance .accordion-header .accordion-remove-btn mat-icon{font-size:1.1rem;width:1.1rem;height:1.1rem;line-height:1.1rem}.form-section-container .accordion-instance .accordion-header .accordion-remove-btn:hover{background:#fee2e2;color:#dc2626}.form-section-container .accordion-instance .accordion-header .accordion-chevron{font-size:1.25rem;width:1.25rem;height:1.25rem;line-height:1.25rem;color:#6b7280;transition:transform .2s ease}.form-section-container .accordion-instance .accordion-body{padding:18px 16px;background:#fff;border-top:1px solid #E8EAF0}.form-section-container .btn-add-section{display:flex;align-items:center;justify-content:center;gap:7px;width:100%;padding:11px 20px;margin-top:14px;background:transparent;color:#6366f1;border:1.5px dashed #C7D2FE;border-radius:8px;cursor:pointer;font-family:inherit;font-size:.8125rem;font-weight:600;transition:all .2s ease;letter-spacing:.01em}.form-section-container .btn-add-section mat-icon{font-size:1.1rem;width:1.1rem;height:1.1rem;line-height:1.1rem}.form-section-container .btn-add-section:hover{background:#eef2ff;border-color:#a5b4fc;border-style:solid;transform:translateY(-1px);box-shadow:0 2px 8px #6366f11f}.form-section-container .btn-add-section:active{transform:translateY(0)}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: FormFieldComponent, selector: "lib-form-field", inputs: ["config", "controller", "formGroup", "allowMulti"] }] });
|
|
2289
2344
|
}
|
|
2290
2345
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: FormSectionComponent, decorators: [{
|
|
2291
2346
|
type: Component,
|
|
2292
|
-
args: [{ selector: 'lib-form-section', standalone: false, template: "<div class=\"form-section-container\">\
|
|
2347
|
+
args: [{ selector: 'lib-form-section', standalone: false, template: "<div class=\"form-section-container\">\n <h3 class=\"section-label\" *ngIf=\"config.label && !config.allowMulti\">{{ config.label }}</h3>\n\n <!-- \u2550\u2550 Repeater (allowMulti) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n <ng-container *ngIf=\"config.allowMulti\">\n <h3 class=\"section-label\">{{ config.label }}</h3>\n\n <div *ngFor=\"let instanceGroup of instanceGroups; let i = index\"\n class=\"accordion-instance\"\n [class.is-expanded]=\"isExpanded(i)\">\n\n <!-- Accordion header (always visible) -->\n <div class=\"accordion-header\" (click)=\"toggleInstance(i)\" role=\"button\" [attr.aria-expanded]=\"isExpanded(i)\">\n <div class=\"accordion-header-left\">\n <span class=\"instance-badge\">{{ i + 1 }}</span>\n <span class=\"instance-title\">{{ config.label }} #{{ i + 1 }}</span>\n </div>\n <div class=\"accordion-header-right\">\n <button type=\"button\" class=\"accordion-remove-btn\"\n *ngIf=\"instanceGroups.length > 1\"\n (click)=\"$event.stopPropagation(); removeInstance(i)\"\n aria-label=\"Remove instance\">\n <mat-icon>delete_outline</mat-icon>\n </button>\n <mat-icon class=\"accordion-chevron\">\n {{ isExpanded(i) ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}\n </mat-icon>\n </div>\n </div>\n\n <!-- Accordion body (shown when expanded) -->\n <div class=\"accordion-body\" *ngIf=\"isExpanded(i)\">\n <div class=\"section-fields sf-grid\">\n <ng-container *ngFor=\"let field of config.children\">\n <div class=\"sf-col\" [style.gridColumn]=\"'span ' + (field.colSpan || 12)\"\n *ngIf=\"field.isEnabled !== false\">\n <lib-form-field [config]=\"field\" [controller]=\"controller\" [formGroup]=\"instanceGroup\">\n </lib-form-field>\n </div>\n </ng-container>\n </div>\n </div>\n </div>\n\n <!-- Full-width dashed Add button -->\n <button type=\"button\" class=\"btn-add-section\" (click)=\"addInstance()\">\n <mat-icon>add</mat-icon> Add {{ config.label }}\n </button>\n </ng-container>\n\n <!-- \u2550\u2550 Non-repeater (single instance) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n <ng-container *ngIf=\"!config.allowMulti\">\n <div class=\"section-fields sf-grid\">\n <ng-container *ngFor=\"let field of config.children\">\n <div class=\"sf-col\" [style.gridColumn]=\"'span ' + (field.colSpan || 12)\"\n *ngIf=\"field.isEnabled !== false\">\n <lib-form-field [config]=\"field\" [controller]=\"controller\" [formGroup]=\"flatFormGroup\">\n </lib-form-field>\n </div>\n </ng-container>\n </div>\n </ng-container>\n\n</div>\n", styles: ["@keyframes section-card-in{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}.form-section-container{background:#fff;border:1px solid #EAECF0;border-radius:14px;padding:22px 24px 24px;margin-bottom:14px;box-shadow:0 1px 2px #0000000a,0 4px 12px #6366f10a;animation:section-card-in .3s cubic-bezier(.4,0,.2,1) both;transition:box-shadow .2s ease}.form-section-container:hover{box-shadow:0 1px 2px #0000000a,0 6px 20px #6366f114}.form-section-container:last-child{margin-bottom:0}.form-section-container .section-label{display:flex;align-items:center;gap:10px;font-size:.9375rem;font-weight:700;color:#111827;margin:0 0 20px;padding-bottom:14px;border-bottom:1px solid #F3F4F6;letter-spacing:-.01em}.form-section-container .section-label:before{content:\"\";display:inline-block;width:4px;height:18px;border-radius:4px;background:linear-gradient(180deg,#6366f1,#8b5cf6);flex-shrink:0}.form-section-container .section-fields.sf-grid{display:grid;grid-template-columns:repeat(12,1fr);gap:18px 20px;align-items:start}@media(max-width:640px){.form-section-container .section-fields.sf-grid{grid-template-columns:1fr}.form-section-container .section-fields.sf-grid .sf-col{grid-column:span 12!important}}.form-section-container .accordion-instance{border:1px solid #E8EAF0;border-radius:10px;margin-bottom:10px;overflow:hidden;transition:border-color .2s ease,box-shadow .2s ease;background:#fafbff}.form-section-container .accordion-instance:last-of-type{margin-bottom:0}.form-section-container .accordion-instance.is-expanded{border-color:#c7d2fe;box-shadow:0 0 0 3px #6366f112}.form-section-container .accordion-instance .accordion-header{display:flex;justify-content:space-between;align-items:center;padding:11px 16px;background:#f8f9ff;cursor:pointer;-webkit-user-select:none;user-select:none;transition:background .15s ease}.form-section-container .accordion-instance .accordion-header:hover{background:#eef0ff}.form-section-container .accordion-instance .accordion-header .accordion-header-left{display:flex;align-items:center;gap:10px}.form-section-container .accordion-instance .accordion-header .instance-badge{width:24px;height:24px;border-radius:6px;background:linear-gradient(135deg,#6366f1,#8b5cf6);color:#fff;font-size:.75rem;font-weight:700;display:flex;align-items:center;justify-content:center;flex-shrink:0}.form-section-container .accordion-instance .accordion-header .instance-title{font-size:.8125rem;font-weight:600;color:#1f2937}.form-section-container .accordion-instance .accordion-header .accordion-header-right{display:flex;align-items:center;gap:6px}.form-section-container .accordion-instance .accordion-header .accordion-remove-btn{background:none;border:none;cursor:pointer;color:#ef4444;padding:4px 6px;border-radius:6px;line-height:1;display:flex;align-items:center;transition:background .15s ease,color .15s ease}.form-section-container .accordion-instance .accordion-header .accordion-remove-btn mat-icon{font-size:1.1rem;width:1.1rem;height:1.1rem;line-height:1.1rem}.form-section-container .accordion-instance .accordion-header .accordion-remove-btn:hover{background:#fee2e2;color:#dc2626}.form-section-container .accordion-instance .accordion-header .accordion-chevron{font-size:1.25rem;width:1.25rem;height:1.25rem;line-height:1.25rem;color:#6b7280;transition:transform .2s ease}.form-section-container .accordion-instance .accordion-body{padding:18px 16px;background:#fff;border-top:1px solid #E8EAF0}.form-section-container .btn-add-section{display:flex;align-items:center;justify-content:center;gap:7px;width:100%;padding:11px 20px;margin-top:14px;background:transparent;color:#6366f1;border:1.5px dashed #C7D2FE;border-radius:8px;cursor:pointer;font-family:inherit;font-size:.8125rem;font-weight:600;transition:all .2s ease;letter-spacing:.01em}.form-section-container .btn-add-section mat-icon{font-size:1.1rem;width:1.1rem;height:1.1rem;line-height:1.1rem}.form-section-container .btn-add-section:hover{background:#eef2ff;border-color:#a5b4fc;border-style:solid;transform:translateY(-1px);box-shadow:0 2px 8px #6366f11f}.form-section-container .btn-add-section:active{transform:translateY(0)}\n"] }]
|
|
2293
2348
|
}], ctorParameters: () => [{ type: i1$3.FormBuilder }], propDecorators: { config: [{
|
|
2294
2349
|
type: Input
|
|
2295
2350
|
}], controller: [{
|
|
@@ -2330,6 +2385,9 @@ class SmartFormComponent {
|
|
|
2330
2385
|
fileAdded = new EventEmitter();
|
|
2331
2386
|
fileUploadFinished = new EventEmitter();
|
|
2332
2387
|
fileRemoved = new EventEmitter();
|
|
2388
|
+
/** Emitted whenever the active section step changes. Carries current state so the
|
|
2389
|
+
* host can show/hide Previous/Next/Submit buttons in its own footer. */
|
|
2390
|
+
stepChange = new EventEmitter();
|
|
2333
2391
|
formSchema;
|
|
2334
2392
|
formGroup;
|
|
2335
2393
|
fieldList = [];
|
|
@@ -2337,6 +2395,22 @@ class SmartFormComponent {
|
|
|
2337
2395
|
currentStep = 0;
|
|
2338
2396
|
isLoading = false;
|
|
2339
2397
|
isDraftLoading = false;
|
|
2398
|
+
/** True when sectionStepper mode is active (SECTION form with top-level GROUPs as steps). */
|
|
2399
|
+
isSectionStepper = false;
|
|
2400
|
+
/** Index of the currently visible section step. */
|
|
2401
|
+
currentSectionStep = 0;
|
|
2402
|
+
/** Flat list of top-level GROUP FieldConfigs that become the stepper steps. */
|
|
2403
|
+
sectionSteps = [];
|
|
2404
|
+
/** Validation state per section step — drives badge colour/icon. */
|
|
2405
|
+
stepValidationStates = [];
|
|
2406
|
+
/** Flat field-name lists per step used for targeted validation. */
|
|
2407
|
+
stepFieldNames = [];
|
|
2408
|
+
/** Controls skeleton visibility. Stays false until schema is parsed AND
|
|
2409
|
+
* any EDIT-mode data fetch completes, but always shows for at least
|
|
2410
|
+
* SKELETON_MIN_MS so the animation is visible even on fast loads. */
|
|
2411
|
+
isFormReady = false;
|
|
2412
|
+
SKELETON_MIN_MS = 350;
|
|
2413
|
+
_skeletonStart = 0;
|
|
2340
2414
|
constructor(fb, controller, expressionService, http, snackbarService, router) {
|
|
2341
2415
|
this.fb = fb;
|
|
2342
2416
|
this.controller = controller;
|
|
@@ -2346,13 +2420,18 @@ class SmartFormComponent {
|
|
|
2346
2420
|
this.router = router;
|
|
2347
2421
|
}
|
|
2348
2422
|
ngOnInit() {
|
|
2423
|
+
this._skeletonStart = Date.now();
|
|
2349
2424
|
this.parseFormJson();
|
|
2350
|
-
// Load
|
|
2425
|
+
// Load data in EDIT mode, or use fallback initialValues
|
|
2351
2426
|
if (this.mode === 'EDIT' && this.formSchema?.editConfig?.loadApiUrl) {
|
|
2352
2427
|
this.loadEditData();
|
|
2353
2428
|
}
|
|
2354
2429
|
else if (this.initialValues) {
|
|
2355
2430
|
this.controller.initialize(this.initialValues);
|
|
2431
|
+
this._markReady();
|
|
2432
|
+
}
|
|
2433
|
+
else {
|
|
2434
|
+
this._markReady();
|
|
2356
2435
|
}
|
|
2357
2436
|
this.controller.fileAdded$.pipe(takeUntil$1(this.destroy$)).subscribe(file => this.fileAdded.emit(file));
|
|
2358
2437
|
this.controller.fileUploadFinished$.pipe(takeUntil$1(this.destroy$)).subscribe(file => this.fileUploadFinished.emit(file));
|
|
@@ -2364,18 +2443,25 @@ class SmartFormComponent {
|
|
|
2364
2443
|
const headers = this.getHeaders();
|
|
2365
2444
|
this.http.get(config.loadApiUrl, { headers }).subscribe({
|
|
2366
2445
|
next: (response) => {
|
|
2367
|
-
// Assume API returns flat or easily mappable object matching form controls
|
|
2368
2446
|
this.initialValues = response;
|
|
2369
2447
|
this.controller.initialize(this.initialValues || {});
|
|
2370
2448
|
this.isLoading = false;
|
|
2449
|
+
this._markReady();
|
|
2371
2450
|
},
|
|
2372
2451
|
error: (err) => {
|
|
2373
2452
|
this.showAlert('error', config.errorMessage || 'Failed to load form data', config.snackbarConfig);
|
|
2374
2453
|
console.error('Load data error:', err);
|
|
2375
2454
|
this.isLoading = false;
|
|
2455
|
+
this._markReady();
|
|
2376
2456
|
}
|
|
2377
2457
|
});
|
|
2378
2458
|
}
|
|
2459
|
+
/** Flips isFormReady=true after the skeleton has been visible for at least SKELETON_MIN_MS. */
|
|
2460
|
+
_markReady() {
|
|
2461
|
+
const elapsed = Date.now() - this._skeletonStart;
|
|
2462
|
+
const remaining = Math.max(0, this.SKELETON_MIN_MS - elapsed);
|
|
2463
|
+
setTimeout(() => { this.isFormReady = true; }, remaining);
|
|
2464
|
+
}
|
|
2379
2465
|
ngOnChanges(changes) {
|
|
2380
2466
|
if (changes['formJson'] && !changes['formJson'].isFirstChange()) {
|
|
2381
2467
|
this.parseFormJson();
|
|
@@ -2412,6 +2498,20 @@ class SmartFormComponent {
|
|
|
2412
2498
|
this.fieldList = this.isStepper
|
|
2413
2499
|
? (this.formSchema.stepperConfig?.children || []).filter(step => step.isEnabled !== false && step.sectionConfig?.isEnabled !== false)
|
|
2414
2500
|
: (this.formSchema.sectionConfig?.children || []).filter(field => field.isEnabled !== false);
|
|
2501
|
+
// Section stepper: active when explicitly set OR when all enabled top-level
|
|
2502
|
+
// children are GROUP type (auto-detection for structured section forms).
|
|
2503
|
+
const topLevelGroups = this.fieldList.filter(f => f.type === 'GROUP' && f.sectionConfig);
|
|
2504
|
+
this.isSectionStepper = !this.isStepper &&
|
|
2505
|
+
(this.formSchema.sectionStepper === true ||
|
|
2506
|
+
(this.formSchema.sectionStepper !== false && topLevelGroups.length === this.fieldList.length && topLevelGroups.length > 1));
|
|
2507
|
+
if (this.isSectionStepper) {
|
|
2508
|
+
this.sectionSteps = topLevelGroups;
|
|
2509
|
+
this.currentSectionStep = 0;
|
|
2510
|
+
this.stepValidationStates = this.sectionSteps.map(() => 'untouched');
|
|
2511
|
+
this.stepFieldNames = this.sectionSteps.map(s => this._collectFieldNames(s.sectionConfig?.children || []));
|
|
2512
|
+
// Emit initial state after a tick so host bindings are ready
|
|
2513
|
+
setTimeout(() => this._emitStepChange());
|
|
2514
|
+
}
|
|
2415
2515
|
this.initializeForm();
|
|
2416
2516
|
}
|
|
2417
2517
|
catch (e) {
|
|
@@ -2809,6 +2909,104 @@ class SmartFormComponent {
|
|
|
2809
2909
|
get currentStepConfig() {
|
|
2810
2910
|
return this.isStepper ? this.fieldList[this.currentStep] : undefined;
|
|
2811
2911
|
}
|
|
2912
|
+
// ── Section Stepper (public API called by host via ViewChild) ────────────────
|
|
2913
|
+
/** Advance to the next section step. Called by the host footer "Next" button.
|
|
2914
|
+
* Validates the current step first — marks it valid (green) or warning (orange). */
|
|
2915
|
+
navigateToNext() {
|
|
2916
|
+
if (!this.isSectionStepper)
|
|
2917
|
+
return;
|
|
2918
|
+
if (this.currentSectionStep < this.sectionSteps.length - 1) {
|
|
2919
|
+
this._validateStep(this.currentSectionStep);
|
|
2920
|
+
this.currentSectionStep++;
|
|
2921
|
+
this._emitStepChange();
|
|
2922
|
+
}
|
|
2923
|
+
}
|
|
2924
|
+
/** Go back to the previous section step. Called by the host footer "Previous" button. */
|
|
2925
|
+
navigateToPrevious() {
|
|
2926
|
+
if (!this.isSectionStepper)
|
|
2927
|
+
return;
|
|
2928
|
+
if (this.currentSectionStep > 0) {
|
|
2929
|
+
this.currentSectionStep--;
|
|
2930
|
+
this._emitStepChange();
|
|
2931
|
+
}
|
|
2932
|
+
}
|
|
2933
|
+
/** Jump directly to a specific section step by index.
|
|
2934
|
+
* Validates the step being left so the badge state updates correctly. */
|
|
2935
|
+
goToSectionStep(index) {
|
|
2936
|
+
if (!this.isSectionStepper)
|
|
2937
|
+
return;
|
|
2938
|
+
if (index < 0 || index >= this.sectionSteps.length || index === this.currentSectionStep)
|
|
2939
|
+
return;
|
|
2940
|
+
this._validateStep(this.currentSectionStep);
|
|
2941
|
+
this.currentSectionStep = index;
|
|
2942
|
+
this._emitStepChange();
|
|
2943
|
+
}
|
|
2944
|
+
get isSectionStepFirst() { return this.currentSectionStep === 0; }
|
|
2945
|
+
get isSectionStepLast() { return this.currentSectionStep === this.sectionSteps.length - 1; }
|
|
2946
|
+
/** Returns the SectionConfig for a given step — passed to lib-form-section.
|
|
2947
|
+
* The outer label is intentionally omitted because the stepper nav already
|
|
2948
|
+
* displays it; showing it again inside the content would be redundant. */
|
|
2949
|
+
getSectionStepConfig(step) {
|
|
2950
|
+
const { label, ...rest } = step.sectionConfig;
|
|
2951
|
+
return rest;
|
|
2952
|
+
}
|
|
2953
|
+
_emitStepChange() {
|
|
2954
|
+
const step = this.sectionSteps[this.currentSectionStep];
|
|
2955
|
+
this.stepChange.emit({
|
|
2956
|
+
currentStep: this.currentSectionStep,
|
|
2957
|
+
totalSteps: this.sectionSteps.length,
|
|
2958
|
+
isFirst: this.isSectionStepFirst,
|
|
2959
|
+
isLast: this.isSectionStepLast,
|
|
2960
|
+
stepLabel: step?.sectionConfig?.label || `Step ${this.currentSectionStep + 1}`
|
|
2961
|
+
});
|
|
2962
|
+
}
|
|
2963
|
+
/** Marks all controls in the given step as touched and records valid/warning state. */
|
|
2964
|
+
_validateStep(stepIndex) {
|
|
2965
|
+
const names = this.stepFieldNames[stepIndex] || [];
|
|
2966
|
+
let hasInvalid = false;
|
|
2967
|
+
names.forEach(name => {
|
|
2968
|
+
const ctrl = this.formGroup.get(name);
|
|
2969
|
+
if (!ctrl)
|
|
2970
|
+
return;
|
|
2971
|
+
if (ctrl instanceof FormArray) {
|
|
2972
|
+
ctrl.controls.forEach(c => c.markAllAsTouched());
|
|
2973
|
+
if (ctrl.invalid)
|
|
2974
|
+
hasInvalid = true;
|
|
2975
|
+
}
|
|
2976
|
+
else if (ctrl instanceof FormGroup) {
|
|
2977
|
+
ctrl.markAllAsTouched();
|
|
2978
|
+
if (ctrl.invalid)
|
|
2979
|
+
hasInvalid = true;
|
|
2980
|
+
}
|
|
2981
|
+
else {
|
|
2982
|
+
ctrl.markAsTouched();
|
|
2983
|
+
if (ctrl.invalid)
|
|
2984
|
+
hasInvalid = true;
|
|
2985
|
+
}
|
|
2986
|
+
});
|
|
2987
|
+
this.stepValidationStates[stepIndex] = hasInvalid ? 'warning' : 'valid';
|
|
2988
|
+
}
|
|
2989
|
+
/** Recursively collects all leaf field names from a set of FieldConfigs. */
|
|
2990
|
+
_collectFieldNames(fields) {
|
|
2991
|
+
const names = [];
|
|
2992
|
+
fields.forEach(f => {
|
|
2993
|
+
if (f.isEnabled === false)
|
|
2994
|
+
return;
|
|
2995
|
+
if (f.name && f.type !== 'GROUP' && f.type !== 'ROW') {
|
|
2996
|
+
names.push(f.name);
|
|
2997
|
+
}
|
|
2998
|
+
if (f.type === 'ROW' && f.children?.length) {
|
|
2999
|
+
names.push(...this._collectFieldNames(f.children));
|
|
3000
|
+
}
|
|
3001
|
+
if (f.type === 'GROUP' && f.sectionConfig?.children?.length) {
|
|
3002
|
+
if (f.name || f.sectionConfig.name) {
|
|
3003
|
+
names.push((f.name || f.sectionConfig.name));
|
|
3004
|
+
}
|
|
3005
|
+
names.push(...this._collectFieldNames(f.sectionConfig.children));
|
|
3006
|
+
}
|
|
3007
|
+
});
|
|
3008
|
+
return names;
|
|
3009
|
+
}
|
|
2812
3010
|
// ── Action Labels ──────────────────────────────────────────────────────────
|
|
2813
3011
|
get nextLabel() {
|
|
2814
3012
|
const key = this.formSchema?.labels?.nextLabel || 'Next';
|
|
@@ -2868,11 +3066,11 @@ class SmartFormComponent {
|
|
|
2868
3066
|
}
|
|
2869
3067
|
}
|
|
2870
3068
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SmartFormComponent, deps: [{ token: i1$3.FormBuilder }, { token: SmartFormController }, { token: ExpressionService }, { token: i3.HttpClient }, { token: SnackbarService }, { token: i1$4.Router }], target: i0.ɵɵFactoryTarget.Component });
|
|
2871
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: SmartFormComponent, isStandalone: false, selector: "lib-smart-form", inputs: { formJson: "formJson", initialValues: "initialValues", enableDraftAutoSave: "enableDraftAutoSave", labels: "labels", mode: "mode", readOnly: "readOnly" }, outputs: { submit: "submit", draftSave: "draftSave", actionClick: "actionClick", valueChange: "valueChange", fileAdded: "fileAdded", fileUploadFinished: "fileUploadFinished", fileRemoved: "fileRemoved" }, providers: [SmartFormController], usesOnChanges: true, ngImport: i0, template: "<div class=\"smart-form-container\">\r\n <div class=\"smart-form-wrapper\" *ngIf=\"formSchema\" [class.smart-form-wrapper--readonly]=\"readOnly\">\r\n\r\n <!-- Form Header -->\r\n <div class=\"form-header\" *ngIf=\"formSchema.showTitle !== false\">\r\n <h2 class=\"form-title\">{{ formSchema.label }}</h2>\r\n <p class=\"form-description\" *ngIf=\"formSchema.description\">{{ formSchema.description }}</p>\r\n </div>\r\n\r\n <!-- Stepper Navigation -->\r\n <div class=\"stepper-nav\" *ngIf=\"isStepper && formSchema.stepperConfig?.showStep !== false\">\r\n <div class=\"stepper-steps\" [class.horizontal]=\"formSchema.stepperConfig?.isHorizontal !== false\">\r\n <div *ngFor=\"let step of fieldList; let i = index\" class=\"stepper-step\" [class.active]=\"i === currentStep\"\r\n [class.completed]=\"i < currentStep\">\r\n <div class=\"step-number\">{{ i + 1 }}</div>\r\n <div class=\"step-label\">{{ step.sectionConfig?.label || 'Step ' + (i + 1) }}</div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Form Content -->\r\n <form [formGroup]=\"formGroup\" class=\"smart-form\">\r\n <!-- Section Form -->\r\n <div *ngIf=\"!isStepper && formSchema.sectionConfig && formSchema.sectionConfig.isEnabled !== false\" class=\"form-section\">\r\n <lib-form-section [config]=\"formSchema.sectionConfig\" [controller]=\"controller\" [formGroup]=\"formGroup\">\r\n </lib-form-section>\r\n </div>\r\n\r\n <!-- Stepper Form -->\r\n <div *ngIf=\"isStepper && currentStepConfig && currentStepConfig.sectionConfig?.isEnabled !== false\" class=\"form-stepper\">\r\n <lib-form-section [config]=\"currentStepConfig.sectionConfig!\" [controller]=\"controller\" [formGroup]=\"formGroup\">\r\n </lib-form-section>\r\n </div>\r\n </form>\r\n\r\n <!-- \u2500\u2500 Form Actions \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <div class=\"form-actions\" *ngIf=\"formSchema.showActions !== false && !readOnly\">\r\n\r\n <!-- LEFT GROUP -->\r\n <div class=\"action-group action-group--left\">\r\n <!-- Optional: Navigational buttons like 'Previous' for stepper can be explicitly added to config, \r\n but we'll keep the logic if they are provided in the buttons array via action.kind === 'prev' -->\r\n <lib-button\r\n *ngFor=\"let btn of getButtonsForAlignment('left')\"\r\n [variant]=\"$any(btn.variant) || 'outline'\"\r\n [disabled]=\"isButtonDisabled(btn)\"\r\n (click)=\"handleButtonClick(btn)\">\r\n {{ getButtonLabel(btn) }}\r\n </lib-button>\r\n </div>\r\n\r\n <!-- RIGHT GROUP -->\r\n <div class=\"action-group action-group--right\">\r\n <lib-button\r\n *ngFor=\"let btn of getButtonsForAlignment('right')\"\r\n [variant]=\"$any(btn.variant) || 'primary'\"\r\n [disabled]=\"isButtonDisabled(btn)\"\r\n (click)=\"handleButtonClick(btn)\">\r\n {{ getButtonLabel(btn) }}\r\n </lib-button>\r\n </div>\r\n\r\n </div>\r\n </div>\r\n\r\n</div>", styles: [".smart-form-container{width:100%;font-family:var(--cc-sf-font-family, \"Inter\", sans-serif)}.smart-form-wrapper{background:var(--cc-sf-form-bg, #ffffff);border-radius:var(--cc-sf-form-border-radius, 12px);border:var(--cc-sf-form-border, none);box-shadow:var(--cc-sf-form-shadow, 0 1px 3px rgba(0, 0, 0, .06))}.smart-form-wrapper .form-alert-feedback{margin-bottom:1rem}.form-header .form-title{font-size:var(--cc-sf-form-title-size, 1.5rem);font-weight:var(--cc-sf-form-title-weight, 700);color:var(--cc-sf-form-title-color, #111827);margin:0 0 8px;line-height:1.25}.form-header .form-description{font-size:var(--cc-sf-form-desc-size, .875rem);color:var(--cc-sf-form-desc-color, #6B7280);margin:0}.stepper-nav{margin-bottom:32px}.stepper-nav .stepper-steps{display:flex;gap:16px}.stepper-nav .stepper-steps.horizontal{flex-direction:row;justify-content:space-between}.stepper-nav .stepper-steps:not(.horizontal){flex-direction:column}.stepper-nav .stepper-step{display:flex;align-items:center;gap:12px;flex:1;position:relative}.stepper-nav .stepper-step:not(:last-child):after{content:\"\";position:absolute;top:calc(var(--cc-sf-step-number-size, 40px) / 2);left:calc(100% + 8px);width:calc(100% - 40px);height:2px;background:var(--cc-sf-step-connector-color, #E5E7EB);transition:background var(--cc-sf-btn-transition, .2s ease)}.stepper-nav .stepper-step.completed:after{background:var(--cc-sf-step-connector-done, #22C55E)}.stepper-nav .stepper-step .step-number{width:var(--cc-sf-step-number-size, 40px);height:var(--cc-sf-step-number-size, 40px);min-width:var(--cc-sf-step-number-size, 40px);border-radius:50%;background:var(--cc-sf-step-number-bg, #E5E7EB);color:var(--cc-sf-step-number-color, #6B7280);display:flex;align-items:center;justify-content:center;font-size:var(--cc-sf-step-number-font-size, .875rem);font-weight:var(--cc-sf-step-number-weight, 600);transition:var(--cc-sf-btn-transition, all .2s ease)}.stepper-nav .stepper-step .step-label{font-size:var(--cc-sf-step-label-size, .875rem);color:var(--cc-sf-step-label-color, #6B7280);font-weight:var(--cc-sf-step-label-weight, 500);transition:var(--cc-sf-btn-transition, all .2s ease)}.stepper-nav .stepper-step.active .step-number{background:var(--cc-sf-step-active-bg, #3B82F6);color:var(--cc-sf-step-active-color, #ffffff)}.stepper-nav .stepper-step.active .step-label{color:var(--cc-sf-step-active-label, #1D4ED8);font-weight:var(--cc-sf-step-active-label-weight, 700)}.stepper-nav .stepper-step.completed .step-number{background:var(--cc-sf-step-done-bg, #22C55E);color:var(--cc-sf-step-done-color, #ffffff)}.smart-form{margin-bottom:24px}.form-actions{display:flex;justify-content:space-between;align-items:center;gap:var(--cc-sf-actions-gap, 12px);padding:var(--cc-sf-actions-padding, 20px 0 0);border-top:var(--cc-sf-actions-border, 1px solid #E5E7EB)}.form-actions .action-group{display:flex;align-items:center;gap:var(--cc-sf-actions-gap, 12px)}.form-actions .action-group--left{justify-content:flex-start}.form-actions .action-group--right{justify-content:flex-end;margin-left:auto}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: ButtonComponent, selector: "lib-button", inputs: ["variant", "type", "disabled", "width", "height", "borderRadius", "fontSize", "fontWeight", "backgroundColor", "color", "border", "icon", "labels"] }, { kind: "component", type: FormSectionComponent, selector: "lib-form-section", inputs: ["config", "controller", "formGroup"] }] });
|
|
3069
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: SmartFormComponent, isStandalone: false, selector: "lib-smart-form", inputs: { formJson: "formJson", initialValues: "initialValues", enableDraftAutoSave: "enableDraftAutoSave", labels: "labels", mode: "mode", readOnly: "readOnly" }, outputs: { submit: "submit", draftSave: "draftSave", actionClick: "actionClick", valueChange: "valueChange", fileAdded: "fileAdded", fileUploadFinished: "fileUploadFinished", fileRemoved: "fileRemoved", stepChange: "stepChange" }, providers: [SmartFormController], usesOnChanges: true, ngImport: i0, template: "<div class=\"smart-form-container\">\n\n <!-- \u2550\u2550 Skeleton loader \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n <div class=\"smart-form-skeleton\" *ngIf=\"!isFormReady\" aria-hidden=\"true\">\n\n <!-- Title + description -->\n <div class=\"skel-header\">\n <div class=\"skel-block skel-title\" style=\"--sd: 0s\"></div>\n <div class=\"skel-block skel-desc\" style=\"--sd: 0.07s\"></div>\n </div>\n\n <!-- Section 1 \u2014 two full-width fields -->\n <div class=\"skel-section\">\n <div class=\"skel-block skel-section-label\" style=\"--sd: 0.1s; width: 32%\"></div>\n <div class=\"skel-fields skel-fields--two\">\n <div class=\"skel-field\">\n <div class=\"skel-block skel-label\" style=\"--sd: 0.13s; width: 55%\"></div>\n <div class=\"skel-block skel-input\" style=\"--sd: 0.15s\"></div>\n </div>\n <div class=\"skel-field\">\n <div class=\"skel-block skel-label\" style=\"--sd: 0.16s; width: 45%\"></div>\n <div class=\"skel-block skel-input\" style=\"--sd: 0.18s\"></div>\n </div>\n <div class=\"skel-field skel-field--full\">\n <div class=\"skel-block skel-label\" style=\"--sd: 0.2s; width: 38%\"></div>\n <div class=\"skel-block skel-input skel-input--textarea\" style=\"--sd: 0.22s\"></div>\n </div>\n </div>\n </div>\n\n <!-- Section 2 \u2014 three columns -->\n <div class=\"skel-section\">\n <div class=\"skel-block skel-section-label\" style=\"--sd: 0.25s; width: 24%\"></div>\n <div class=\"skel-fields skel-fields--three\">\n <div class=\"skel-field\">\n <div class=\"skel-block skel-label\" style=\"--sd: 0.28s; width: 60%\"></div>\n <div class=\"skel-block skel-input\" style=\"--sd: 0.30s\"></div>\n </div>\n <div class=\"skel-field\">\n <div class=\"skel-block skel-label\" style=\"--sd: 0.31s; width: 50%\"></div>\n <div class=\"skel-block skel-input\" style=\"--sd: 0.33s\"></div>\n </div>\n <div class=\"skel-field\">\n <div class=\"skel-block skel-label\" style=\"--sd: 0.34s; width: 65%\"></div>\n <div class=\"skel-block skel-input\" style=\"--sd: 0.36s\"></div>\n </div>\n </div>\n </div>\n\n <!-- Section 3 \u2014 two columns + chip row -->\n <div class=\"skel-section\">\n <div class=\"skel-block skel-section-label\" style=\"--sd: 0.38s; width: 28%\"></div>\n <div class=\"skel-fields skel-fields--two\">\n <div class=\"skel-field\">\n <div class=\"skel-block skel-label\" style=\"--sd: 0.40s; width: 48%\"></div>\n <div class=\"skel-block skel-input\" style=\"--sd: 0.42s\"></div>\n </div>\n <div class=\"skel-field\">\n <div class=\"skel-block skel-label\" style=\"--sd: 0.43s; width: 55%\"></div>\n <div class=\"skel-block skel-input\" style=\"--sd: 0.45s\"></div>\n </div>\n </div>\n <div class=\"skel-chips\">\n <div class=\"skel-block skel-chip\" style=\"--sd: 0.47s; width: 72px\"></div>\n <div class=\"skel-block skel-chip\" style=\"--sd: 0.49s; width: 96px\"></div>\n <div class=\"skel-block skel-chip\" style=\"--sd: 0.51s; width: 80px\"></div>\n <div class=\"skel-block skel-chip\" style=\"--sd: 0.53s; width: 64px\"></div>\n </div>\n </div>\n\n <!-- Action bar -->\n <div class=\"skel-actions\">\n <div class=\"skel-block skel-btn\" style=\"--sd: 0.55s; width: 88px\"></div>\n <div class=\"skel-block skel-btn skel-btn--primary\" style=\"--sd: 0.58s; width: 120px\"></div>\n </div>\n </div>\n\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n SECTION STEPPER layout \u2014 stepper nav card + per-step form panels.\n Rendered when formSchema.sectionStepper === true.\n The nav and each step section are separate cards (no outer wrapper card).\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n <ng-container *ngIf=\"formSchema && isFormReady && isSectionStepper\">\n\n <!-- Horizontal stepper nav card -->\n <div class=\"section-stepper-nav\" *ngIf=\"sectionSteps.length > 0\">\n <div class=\"section-stepper-track\">\n <div\n *ngFor=\"let step of sectionSteps; let i = index\"\n class=\"section-stepper-step\"\n [class.ss-active]=\"i === currentSectionStep\"\n [class.ss-completed]=\"i < currentSectionStep && stepValidationStates[i] !== 'warning'\"\n [class.ss-warning]=\"i < currentSectionStep && stepValidationStates[i] === 'warning'\"\n [attr.data-tooltip]=\"step.sectionConfig?.label || 'Step ' + (i + 1)\"\n (click)=\"goToSectionStep(i)\">\n\n <!-- Connector line \u2014 left side (hidden for first step) -->\n <div class=\"ss-connector ss-connector--left\" *ngIf=\"i > 0\"></div>\n\n <!-- Step badge -->\n <div class=\"ss-badge\">\n <!-- Green checkmark: visited and valid -->\n <svg *ngIf=\"i < currentSectionStep && stepValidationStates[i] !== 'warning'\"\n width=\"13\" height=\"13\" viewBox=\"0 0 24 24\"\n fill=\"none\" stroke=\"currentColor\" stroke-width=\"3\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <polyline points=\"20 6 9 17 4 12\"></polyline>\n </svg>\n <!-- Warning: bold ! is the most visible option inside a 38px circle badge -->\n <span *ngIf=\"i < currentSectionStep && stepValidationStates[i] === 'warning'\"\n class=\"ss-warning-mark\">!</span>\n <!-- Number: current or future step -->\n <span *ngIf=\"i >= currentSectionStep\">{{ i + 1 }}</span>\n </div>\n\n <!-- Step label (truncated; full text revealed by CSS tooltip) -->\n <div class=\"ss-label\" [title]=\"step.sectionConfig?.label || 'Step ' + (i + 1)\">\n {{ step.sectionConfig?.label || 'Step ' + (i + 1) }}\n </div>\n\n <!-- Connector line \u2014 right side (hidden for last step) -->\n <div class=\"ss-connector ss-connector--right\" *ngIf=\"i < sectionSteps.length - 1\"></div>\n </div>\n </div>\n </div>\n\n <!-- Step panels \u2014 all mounted, only active one is visible (preserves form data) -->\n <form [formGroup]=\"formGroup\" class=\"smart-form ss-form\">\n <div\n *ngFor=\"let step of sectionSteps; let i = index\"\n class=\"ss-step-panel\"\n [style.display]=\"i === currentSectionStep ? 'block' : 'none'\">\n <lib-form-section\n [config]=\"getSectionStepConfig(step)\"\n [controller]=\"controller\"\n [formGroup]=\"formGroup\">\n </lib-form-section>\n </div>\n </form>\n\n </ng-container>\n\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n Regular card wrapper \u2014 used for SECTION and STEPPER form types.\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n <div class=\"smart-form-wrapper\" *ngIf=\"formSchema && isFormReady && !isSectionStepper\"\n [class.smart-form-wrapper--readonly]=\"readOnly\">\n\n <!-- Form Header -->\n <div class=\"form-header\" *ngIf=\"formSchema.showTitle !== false\">\n <h2 class=\"form-title\">{{ formSchema.label }}</h2>\n <p class=\"form-description\" *ngIf=\"formSchema.description\">{{ formSchema.description }}</p>\n </div>\n\n <!-- STEPPER type nav -->\n <div class=\"stepper-nav\" *ngIf=\"isStepper && formSchema.stepperConfig?.showStep !== false\">\n <div class=\"stepper-steps\" [class.horizontal]=\"formSchema.stepperConfig?.isHorizontal !== false\">\n <div *ngFor=\"let step of fieldList; let i = index\" class=\"stepper-step\" [class.active]=\"i === currentStep\"\n [class.completed]=\"i < currentStep\">\n <div class=\"step-number\">{{ i + 1 }}</div>\n <div class=\"step-label\">{{ step.sectionConfig?.label || 'Step ' + (i + 1) }}</div>\n </div>\n </div>\n </div>\n\n <!-- Form Content -->\n <form [formGroup]=\"formGroup\" class=\"smart-form\">\n <!-- Regular SECTION form -->\n <div *ngIf=\"!isStepper && formSchema.sectionConfig && formSchema.sectionConfig.isEnabled !== false\" class=\"form-section\">\n <lib-form-section [config]=\"formSchema.sectionConfig\" [controller]=\"controller\" [formGroup]=\"formGroup\">\n </lib-form-section>\n </div>\n\n <!-- STEPPER type form -->\n <div *ngIf=\"isStepper && currentStepConfig && currentStepConfig.sectionConfig?.isEnabled !== false\" class=\"form-stepper\">\n <lib-form-section [config]=\"currentStepConfig.sectionConfig!\" [controller]=\"controller\" [formGroup]=\"formGroup\">\n </lib-form-section>\n </div>\n </form>\n\n <!-- \u2500\u2500 Form Actions \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"form-actions\" *ngIf=\"formSchema.showActions !== false && !readOnly && actionBarConfig?.buttons?.length\">\n\n <!-- LEFT GROUP -->\n <div class=\"action-group action-group--left\">\n <lib-button\n *ngFor=\"let btn of getButtonsForAlignment('left')\"\n [variant]=\"$any(btn.variant) || 'outline'\"\n [disabled]=\"isButtonDisabled(btn)\"\n (click)=\"handleButtonClick(btn)\">\n {{ getButtonLabel(btn) }}\n </lib-button>\n </div>\n\n <!-- RIGHT GROUP -->\n <div class=\"action-group action-group--right\">\n <lib-button\n *ngFor=\"let btn of getButtonsForAlignment('right')\"\n [variant]=\"$any(btn.variant) || 'primary'\"\n [disabled]=\"isButtonDisabled(btn)\"\n (click)=\"handleButtonClick(btn)\">\n {{ getButtonLabel(btn) }}\n </lib-button>\n </div>\n\n </div>\n </div>\n\n</div>\n", styles: ["@keyframes skel-wave{0%{transform:translate(-100%)}to{transform:translate(200%)}}@keyframes skel-fade-in{0%{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}@keyframes form-reveal{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}.smart-form-skeleton{background:var(--cc-sf-form-bg, #ffffff);border-radius:var(--cc-sf-form-border-radius, 12px);border:var(--cc-sf-form-border, none);box-shadow:var(--cc-sf-form-shadow, 0 1px 3px rgba(0, 0, 0, .06));padding:1.5rem;display:flex;flex-direction:column;gap:var(--cc-sf-form-section-gap, 24px);animation:skel-fade-in .3s ease both}.skel-block{position:relative;overflow:hidden;border-radius:6px;background:var(--cc-sf-input-disabled-bg, #F0F2F5)}.skel-block:after{content:\"\";position:absolute;inset:0;transform:translate(-100%);background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,.55) 45%,rgba(255,255,255,.75) 50%,rgba(255,255,255,.55) 55%,transparent 100%);animation:skel-wave 1.8s ease-in-out infinite;animation-delay:var(--sd, 0s)}.skel-header{display:flex;flex-direction:column;gap:10px}.skel-header .skel-title{height:26px;border-radius:8px}.skel-header .skel-desc{height:14px;border-radius:5px;opacity:.7}.skel-section{display:flex;flex-direction:column;gap:14px}.skel-section-label{height:16px;border-radius:0 5px 5px 0;border-left:var(--cc-sf-section-header-accent-width, 4px) solid var(--cc-sf-section-header-accent-color, #3B82F6);background:var(--cc-sf-input-disabled-bg, #F0F2F5);opacity:.85}.skel-fields{display:grid;gap:var(--cc-sf-grid-gap, 16px);align-items:start}.skel-fields--two{grid-template-columns:1fr 1fr}.skel-fields--three{grid-template-columns:1fr 1fr 1fr}@media(max-width:640px){.skel-fields--two,.skel-fields--three{grid-template-columns:1fr}}.skel-field{display:flex;flex-direction:column;gap:7px}.skel-field--full{grid-column:1/-1}.skel-label{height:12px;border-radius:4px;opacity:.75}.skel-input{height:42px;border-radius:8px}.skel-input--textarea{height:80px}.skel-chips{display:flex;flex-wrap:wrap;gap:8px}.skel-chip{height:32px;border-radius:20px;opacity:.8}.skel-actions{display:flex;justify-content:flex-end;align-items:center;gap:12px;padding-top:20px;border-top:var(--cc-sf-actions-border, 1px solid #E5E7EB)}.skel-btn{height:40px;border-radius:8px}.skel-btn--primary{background:color-mix(in srgb,var(--cc-sf-accent-color, #3B82F6) 18%,var(--cc-sf-input-disabled-bg, #F0F2F5))}.smart-form-container{width:100%;font-family:var(--cc-sf-font-family, \"Inter\", sans-serif)}.smart-form-wrapper{background:var(--cc-sf-form-bg, #ffffff);border-radius:var(--cc-sf-form-border-radius, 12px);border:var(--cc-sf-form-border, none);box-shadow:var(--cc-sf-form-shadow, 0 1px 3px rgba(0, 0, 0, .06));padding:1.5rem;animation:form-reveal .3s ease both}.smart-form-wrapper .form-alert-feedback{margin-bottom:1rem}.form-header .form-title{font-size:var(--cc-sf-form-title-size, 1.5rem);font-weight:var(--cc-sf-form-title-weight, 700);color:var(--cc-sf-form-title-color, #111827);margin:0 0 8px;line-height:1.25}.form-header .form-description{font-size:var(--cc-sf-form-desc-size, .875rem);color:var(--cc-sf-form-desc-color, #6B7280);margin:0}@keyframes ss-badge-pop{0%{transform:scale(.6);opacity:0}70%{transform:scale(1.12)}to{transform:scale(1);opacity:1}}@keyframes ss-pulse-ring{0%{box-shadow:0 0 #6366f173}70%{box-shadow:0 0 0 10px #6366f100}to{box-shadow:0 0 #6366f100}}@keyframes ss-panel-in{0%{opacity:0;transform:translateY(14px)}to{opacity:1;transform:translateY(0)}}@keyframes ss-connector-fill{0%{transform:scaleX(0)}to{transform:scaleX(1)}}.section-stepper-nav{position:relative;background:#fff;border-radius:16px;border:1px solid #E8EAF0;box-shadow:0 1px 3px #0000000d,0 4px 16px #6366f10f;padding:24px 28px 48px;margin-bottom:14px;overflow-x:clip;overflow-y:hidden}.section-stepper-nav:before{content:\"\";position:absolute;inset:0 0 auto;height:3px;border-radius:16px 16px 0 0;background:linear-gradient(90deg,#6366f1,#8b5cf6,#ec4899)}.section-stepper-track{display:flex;align-items:flex-start;justify-content:space-between;min-width:max-content;width:100%}.section-stepper-step{display:flex;flex-direction:column;align-items:center;position:relative;flex:1;cursor:pointer;padding:0 4px}.section-stepper-step:after{content:attr(data-tooltip);position:absolute;top:calc(100% + 8px);left:50%;transform:translate(-50%) translateY(4px);white-space:nowrap;background:#1e1b4b;color:#fff;font-size:.6875rem;font-weight:500;letter-spacing:.02em;padding:5px 11px;border-radius:6px;pointer-events:none;opacity:0;transition:opacity .2s ease,transform .2s ease;z-index:200;box-shadow:0 4px 14px #0003}.section-stepper-step:hover:after{opacity:1;transform:translate(-50%) translateY(0)}.section-stepper-step .ss-badge{width:38px;height:38px;min-width:38px;border-radius:50%;background:#f1f2f6;color:#9ca3af;border:2px solid #E5E7EB;display:flex;align-items:center;justify-content:center;font-size:.8125rem;font-weight:700;position:relative;z-index:1;transition:all .3s cubic-bezier(.34,1.56,.64,1)}.section-stepper-step .ss-badge span{line-height:1;letter-spacing:-.01em}.section-stepper-step .ss-badge svg{flex-shrink:0}.section-stepper-step .ss-badge .ss-warning-mark{font-size:1.25rem;font-weight:900;line-height:1;letter-spacing:0;color:#fff}.section-stepper-step .ss-label{margin-top:9px;font-size:.6875rem;font-weight:500;color:#b0b7c3;white-space:nowrap;text-align:center;transition:color .25s ease,font-weight .25s ease;max-width:88px;overflow:hidden;text-overflow:ellipsis;letter-spacing:.01em}.section-stepper-step .ss-connector{height:2px;background:#e8eaf0;position:absolute;top:19px;z-index:0;overflow:hidden;border-radius:2px}.section-stepper-step .ss-connector--left{left:0;right:calc(50% + 19px)}.section-stepper-step .ss-connector--right{left:calc(50% + 19px);right:0}.section-stepper-step .ss-connector:after{content:\"\";position:absolute;inset:0;background:linear-gradient(90deg,#6366f1,#8b5cf6);transform:scaleX(0);transform-origin:left;transition:transform .4s cubic-bezier(.4,0,.2,1)}.section-stepper-step.ss-active{cursor:default}.section-stepper-step.ss-active .ss-badge{background:linear-gradient(135deg,#6366f1,#8b5cf6);color:#fff;border-color:transparent;box-shadow:0 0 0 4px #6366f12e,0 4px 12px #6366f159;animation:ss-badge-pop .4s cubic-bezier(.34,1.56,.64,1) both,ss-pulse-ring 2s .4s ease-out infinite}.section-stepper-step.ss-active .ss-label{color:#4f46e5;font-weight:700}.section-stepper-step.ss-completed .ss-badge{background:linear-gradient(135deg,#10b981,#059669);color:#fff;border-color:transparent;box-shadow:0 2px 8px #10b9814d}.section-stepper-step.ss-completed .ss-label{color:#6b7280;font-weight:500}.section-stepper-step.ss-completed .ss-connector--left:after,.section-stepper-step.ss-completed .ss-connector--right:after{transform:scaleX(1)}.section-stepper-step.ss-warning .ss-badge{background:linear-gradient(135deg,#f59e0b,#d97706);color:#fff;border-color:transparent;box-shadow:0 2px 8px #f59e0b59;animation:ss-badge-pop .35s cubic-bezier(.34,1.56,.64,1) both}.section-stepper-step.ss-warning .ss-label{color:#b45309;font-weight:600}.section-stepper-step.ss-warning .ss-connector--left:after{transform:scaleX(0)}.section-stepper-step.ss-warning .ss-connector--right:after{transform:scaleX(0)}.section-stepper-step:not(.ss-active):not(.ss-completed):not(.ss-warning):hover .ss-badge{background:#e8eaf0;color:#6366f1;border-color:#c7d2fe;transform:translateY(-2px)}.section-stepper-step:not(.ss-active):not(.ss-completed):not(.ss-warning):hover .ss-label{color:#6b7280}.ss-step-panel{animation:ss-panel-in .35s cubic-bezier(.4,0,.2,1) both}.ss-form{padding-top:0}@media(max-width:768px){.section-stepper-nav{padding:20px 16px 16px}.section-stepper-step .ss-label{font-size:.625rem;max-width:64px}.section-stepper-step .ss-badge{width:32px;height:32px;min-width:32px;font-size:.75rem}.section-stepper-step .ss-connector{top:16px}.section-stepper-step .ss-connector--left{right:calc(50% + 16px)}.section-stepper-step .ss-connector--right{left:calc(50% + 16px)}}.stepper-nav{margin-bottom:32px}.stepper-nav .stepper-steps{display:flex;gap:16px}.stepper-nav .stepper-steps.horizontal{flex-direction:row;justify-content:space-between}.stepper-nav .stepper-steps:not(.horizontal){flex-direction:column}.stepper-nav .stepper-step{display:flex;align-items:center;gap:12px;flex:1;position:relative}.stepper-nav .stepper-step:not(:last-child):after{content:\"\";position:absolute;top:calc(var(--cc-sf-step-number-size, 40px) / 2);left:calc(100% + 8px);width:calc(100% - 40px);height:2px;background:var(--cc-sf-step-connector-color, #E5E7EB);transition:background var(--cc-sf-btn-transition, .2s ease)}.stepper-nav .stepper-step.completed:after{background:var(--cc-sf-step-connector-done, #22C55E)}.stepper-nav .stepper-step .step-number{width:var(--cc-sf-step-number-size, 40px);height:var(--cc-sf-step-number-size, 40px);min-width:var(--cc-sf-step-number-size, 40px);border-radius:50%;background:var(--cc-sf-step-number-bg, #E5E7EB);color:var(--cc-sf-step-number-color, #6B7280);display:flex;align-items:center;justify-content:center;font-size:var(--cc-sf-step-number-font-size, .875rem);font-weight:var(--cc-sf-step-number-weight, 600);transition:var(--cc-sf-btn-transition, all .2s ease)}.stepper-nav .stepper-step .step-label{font-size:var(--cc-sf-step-label-size, .875rem);color:var(--cc-sf-step-label-color, #6B7280);font-weight:var(--cc-sf-step-label-weight, 500);transition:var(--cc-sf-btn-transition, all .2s ease)}.stepper-nav .stepper-step.active .step-number{background:var(--cc-sf-step-active-bg, #3B82F6);color:var(--cc-sf-step-active-color, #ffffff)}.stepper-nav .stepper-step.active .step-label{color:var(--cc-sf-step-active-label, #1D4ED8);font-weight:var(--cc-sf-step-active-label-weight, 700)}.stepper-nav .stepper-step.completed .step-number{background:var(--cc-sf-step-done-bg, #22C55E);color:var(--cc-sf-step-done-color, #ffffff)}.smart-form{padding-top:var(--cc-sf-form-padding, 24px);display:flex;flex-direction:column;gap:var(--cc-sf-form-section-gap, 24px)}.smart-form>*{margin-bottom:0!important}.form-actions{display:flex;justify-content:space-between;align-items:center;gap:var(--cc-sf-actions-gap, 12px);padding:var(--cc-sf-actions-padding, 20px 0 0);margin-top:8px;border-top:var(--cc-sf-actions-border, 1px solid #E5E7EB)}.form-actions .action-group{display:flex;align-items:center;gap:var(--cc-sf-actions-gap, 12px)}.form-actions .action-group--left{justify-content:flex-start}.form-actions .action-group--right{justify-content:flex-end;margin-left:auto}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: ButtonComponent, selector: "lib-button", inputs: ["variant", "type", "disabled", "width", "height", "borderRadius", "fontSize", "fontWeight", "backgroundColor", "color", "border", "icon", "labels"] }, { kind: "component", type: FormSectionComponent, selector: "lib-form-section", inputs: ["config", "controller", "formGroup"] }] });
|
|
2872
3070
|
}
|
|
2873
3071
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SmartFormComponent, decorators: [{
|
|
2874
3072
|
type: Component,
|
|
2875
|
-
args: [{ selector: 'lib-smart-form', providers: [SmartFormController], standalone: false, template: "<div class=\"smart-form-container\">\r\n <div class=\"smart-form-wrapper\" *ngIf=\"formSchema\" [class.smart-form-wrapper--readonly]=\"readOnly\">\r\n\r\n <!-- Form Header -->\r\n <div class=\"form-header\" *ngIf=\"formSchema.showTitle !== false\">\r\n <h2 class=\"form-title\">{{ formSchema.label }}</h2>\r\n <p class=\"form-description\" *ngIf=\"formSchema.description\">{{ formSchema.description }}</p>\r\n </div>\r\n\r\n <!-- Stepper Navigation -->\r\n <div class=\"stepper-nav\" *ngIf=\"isStepper && formSchema.stepperConfig?.showStep !== false\">\r\n <div class=\"stepper-steps\" [class.horizontal]=\"formSchema.stepperConfig?.isHorizontal !== false\">\r\n <div *ngFor=\"let step of fieldList; let i = index\" class=\"stepper-step\" [class.active]=\"i === currentStep\"\r\n [class.completed]=\"i < currentStep\">\r\n <div class=\"step-number\">{{ i + 1 }}</div>\r\n <div class=\"step-label\">{{ step.sectionConfig?.label || 'Step ' + (i + 1) }}</div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Form Content -->\r\n <form [formGroup]=\"formGroup\" class=\"smart-form\">\r\n <!-- Section Form -->\r\n <div *ngIf=\"!isStepper && formSchema.sectionConfig && formSchema.sectionConfig.isEnabled !== false\" class=\"form-section\">\r\n <lib-form-section [config]=\"formSchema.sectionConfig\" [controller]=\"controller\" [formGroup]=\"formGroup\">\r\n </lib-form-section>\r\n </div>\r\n\r\n <!-- Stepper Form -->\r\n <div *ngIf=\"isStepper && currentStepConfig && currentStepConfig.sectionConfig?.isEnabled !== false\" class=\"form-stepper\">\r\n <lib-form-section [config]=\"currentStepConfig.sectionConfig!\" [controller]=\"controller\" [formGroup]=\"formGroup\">\r\n </lib-form-section>\r\n </div>\r\n </form>\r\n\r\n <!-- \u2500\u2500 Form Actions \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <div class=\"form-actions\" *ngIf=\"formSchema.showActions !== false && !readOnly\">\r\n\r\n <!-- LEFT GROUP -->\r\n <div class=\"action-group action-group--left\">\r\n <!-- Optional: Navigational buttons like 'Previous' for stepper can be explicitly added to config, \r\n but we'll keep the logic if they are provided in the buttons array via action.kind === 'prev' -->\r\n <lib-button\r\n *ngFor=\"let btn of getButtonsForAlignment('left')\"\r\n [variant]=\"$any(btn.variant) || 'outline'\"\r\n [disabled]=\"isButtonDisabled(btn)\"\r\n (click)=\"handleButtonClick(btn)\">\r\n {{ getButtonLabel(btn) }}\r\n </lib-button>\r\n </div>\r\n\r\n <!-- RIGHT GROUP -->\r\n <div class=\"action-group action-group--right\">\r\n <lib-button\r\n *ngFor=\"let btn of getButtonsForAlignment('right')\"\r\n [variant]=\"$any(btn.variant) || 'primary'\"\r\n [disabled]=\"isButtonDisabled(btn)\"\r\n (click)=\"handleButtonClick(btn)\">\r\n {{ getButtonLabel(btn) }}\r\n </lib-button>\r\n </div>\r\n\r\n </div>\r\n </div>\r\n\r\n</div>", styles: [".smart-form-container{width:100%;font-family:var(--cc-sf-font-family, \"Inter\", sans-serif)}.smart-form-wrapper{background:var(--cc-sf-form-bg, #ffffff);border-radius:var(--cc-sf-form-border-radius, 12px);border:var(--cc-sf-form-border, none);box-shadow:var(--cc-sf-form-shadow, 0 1px 3px rgba(0, 0, 0, .06))}.smart-form-wrapper .form-alert-feedback{margin-bottom:1rem}.form-header .form-title{font-size:var(--cc-sf-form-title-size, 1.5rem);font-weight:var(--cc-sf-form-title-weight, 700);color:var(--cc-sf-form-title-color, #111827);margin:0 0 8px;line-height:1.25}.form-header .form-description{font-size:var(--cc-sf-form-desc-size, .875rem);color:var(--cc-sf-form-desc-color, #6B7280);margin:0}.stepper-nav{margin-bottom:32px}.stepper-nav .stepper-steps{display:flex;gap:16px}.stepper-nav .stepper-steps.horizontal{flex-direction:row;justify-content:space-between}.stepper-nav .stepper-steps:not(.horizontal){flex-direction:column}.stepper-nav .stepper-step{display:flex;align-items:center;gap:12px;flex:1;position:relative}.stepper-nav .stepper-step:not(:last-child):after{content:\"\";position:absolute;top:calc(var(--cc-sf-step-number-size, 40px) / 2);left:calc(100% + 8px);width:calc(100% - 40px);height:2px;background:var(--cc-sf-step-connector-color, #E5E7EB);transition:background var(--cc-sf-btn-transition, .2s ease)}.stepper-nav .stepper-step.completed:after{background:var(--cc-sf-step-connector-done, #22C55E)}.stepper-nav .stepper-step .step-number{width:var(--cc-sf-step-number-size, 40px);height:var(--cc-sf-step-number-size, 40px);min-width:var(--cc-sf-step-number-size, 40px);border-radius:50%;background:var(--cc-sf-step-number-bg, #E5E7EB);color:var(--cc-sf-step-number-color, #6B7280);display:flex;align-items:center;justify-content:center;font-size:var(--cc-sf-step-number-font-size, .875rem);font-weight:var(--cc-sf-step-number-weight, 600);transition:var(--cc-sf-btn-transition, all .2s ease)}.stepper-nav .stepper-step .step-label{font-size:var(--cc-sf-step-label-size, .875rem);color:var(--cc-sf-step-label-color, #6B7280);font-weight:var(--cc-sf-step-label-weight, 500);transition:var(--cc-sf-btn-transition, all .2s ease)}.stepper-nav .stepper-step.active .step-number{background:var(--cc-sf-step-active-bg, #3B82F6);color:var(--cc-sf-step-active-color, #ffffff)}.stepper-nav .stepper-step.active .step-label{color:var(--cc-sf-step-active-label, #1D4ED8);font-weight:var(--cc-sf-step-active-label-weight, 700)}.stepper-nav .stepper-step.completed .step-number{background:var(--cc-sf-step-done-bg, #22C55E);color:var(--cc-sf-step-done-color, #ffffff)}.smart-form{margin-bottom:24px}.form-actions{display:flex;justify-content:space-between;align-items:center;gap:var(--cc-sf-actions-gap, 12px);padding:var(--cc-sf-actions-padding, 20px 0 0);border-top:var(--cc-sf-actions-border, 1px solid #E5E7EB)}.form-actions .action-group{display:flex;align-items:center;gap:var(--cc-sf-actions-gap, 12px)}.form-actions .action-group--left{justify-content:flex-start}.form-actions .action-group--right{justify-content:flex-end;margin-left:auto}\n"] }]
|
|
3073
|
+
args: [{ selector: 'lib-smart-form', providers: [SmartFormController], standalone: false, template: "<div class=\"smart-form-container\">\n\n <!-- \u2550\u2550 Skeleton loader \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n <div class=\"smart-form-skeleton\" *ngIf=\"!isFormReady\" aria-hidden=\"true\">\n\n <!-- Title + description -->\n <div class=\"skel-header\">\n <div class=\"skel-block skel-title\" style=\"--sd: 0s\"></div>\n <div class=\"skel-block skel-desc\" style=\"--sd: 0.07s\"></div>\n </div>\n\n <!-- Section 1 \u2014 two full-width fields -->\n <div class=\"skel-section\">\n <div class=\"skel-block skel-section-label\" style=\"--sd: 0.1s; width: 32%\"></div>\n <div class=\"skel-fields skel-fields--two\">\n <div class=\"skel-field\">\n <div class=\"skel-block skel-label\" style=\"--sd: 0.13s; width: 55%\"></div>\n <div class=\"skel-block skel-input\" style=\"--sd: 0.15s\"></div>\n </div>\n <div class=\"skel-field\">\n <div class=\"skel-block skel-label\" style=\"--sd: 0.16s; width: 45%\"></div>\n <div class=\"skel-block skel-input\" style=\"--sd: 0.18s\"></div>\n </div>\n <div class=\"skel-field skel-field--full\">\n <div class=\"skel-block skel-label\" style=\"--sd: 0.2s; width: 38%\"></div>\n <div class=\"skel-block skel-input skel-input--textarea\" style=\"--sd: 0.22s\"></div>\n </div>\n </div>\n </div>\n\n <!-- Section 2 \u2014 three columns -->\n <div class=\"skel-section\">\n <div class=\"skel-block skel-section-label\" style=\"--sd: 0.25s; width: 24%\"></div>\n <div class=\"skel-fields skel-fields--three\">\n <div class=\"skel-field\">\n <div class=\"skel-block skel-label\" style=\"--sd: 0.28s; width: 60%\"></div>\n <div class=\"skel-block skel-input\" style=\"--sd: 0.30s\"></div>\n </div>\n <div class=\"skel-field\">\n <div class=\"skel-block skel-label\" style=\"--sd: 0.31s; width: 50%\"></div>\n <div class=\"skel-block skel-input\" style=\"--sd: 0.33s\"></div>\n </div>\n <div class=\"skel-field\">\n <div class=\"skel-block skel-label\" style=\"--sd: 0.34s; width: 65%\"></div>\n <div class=\"skel-block skel-input\" style=\"--sd: 0.36s\"></div>\n </div>\n </div>\n </div>\n\n <!-- Section 3 \u2014 two columns + chip row -->\n <div class=\"skel-section\">\n <div class=\"skel-block skel-section-label\" style=\"--sd: 0.38s; width: 28%\"></div>\n <div class=\"skel-fields skel-fields--two\">\n <div class=\"skel-field\">\n <div class=\"skel-block skel-label\" style=\"--sd: 0.40s; width: 48%\"></div>\n <div class=\"skel-block skel-input\" style=\"--sd: 0.42s\"></div>\n </div>\n <div class=\"skel-field\">\n <div class=\"skel-block skel-label\" style=\"--sd: 0.43s; width: 55%\"></div>\n <div class=\"skel-block skel-input\" style=\"--sd: 0.45s\"></div>\n </div>\n </div>\n <div class=\"skel-chips\">\n <div class=\"skel-block skel-chip\" style=\"--sd: 0.47s; width: 72px\"></div>\n <div class=\"skel-block skel-chip\" style=\"--sd: 0.49s; width: 96px\"></div>\n <div class=\"skel-block skel-chip\" style=\"--sd: 0.51s; width: 80px\"></div>\n <div class=\"skel-block skel-chip\" style=\"--sd: 0.53s; width: 64px\"></div>\n </div>\n </div>\n\n <!-- Action bar -->\n <div class=\"skel-actions\">\n <div class=\"skel-block skel-btn\" style=\"--sd: 0.55s; width: 88px\"></div>\n <div class=\"skel-block skel-btn skel-btn--primary\" style=\"--sd: 0.58s; width: 120px\"></div>\n </div>\n </div>\n\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n SECTION STEPPER layout \u2014 stepper nav card + per-step form panels.\n Rendered when formSchema.sectionStepper === true.\n The nav and each step section are separate cards (no outer wrapper card).\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n <ng-container *ngIf=\"formSchema && isFormReady && isSectionStepper\">\n\n <!-- Horizontal stepper nav card -->\n <div class=\"section-stepper-nav\" *ngIf=\"sectionSteps.length > 0\">\n <div class=\"section-stepper-track\">\n <div\n *ngFor=\"let step of sectionSteps; let i = index\"\n class=\"section-stepper-step\"\n [class.ss-active]=\"i === currentSectionStep\"\n [class.ss-completed]=\"i < currentSectionStep && stepValidationStates[i] !== 'warning'\"\n [class.ss-warning]=\"i < currentSectionStep && stepValidationStates[i] === 'warning'\"\n [attr.data-tooltip]=\"step.sectionConfig?.label || 'Step ' + (i + 1)\"\n (click)=\"goToSectionStep(i)\">\n\n <!-- Connector line \u2014 left side (hidden for first step) -->\n <div class=\"ss-connector ss-connector--left\" *ngIf=\"i > 0\"></div>\n\n <!-- Step badge -->\n <div class=\"ss-badge\">\n <!-- Green checkmark: visited and valid -->\n <svg *ngIf=\"i < currentSectionStep && stepValidationStates[i] !== 'warning'\"\n width=\"13\" height=\"13\" viewBox=\"0 0 24 24\"\n fill=\"none\" stroke=\"currentColor\" stroke-width=\"3\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <polyline points=\"20 6 9 17 4 12\"></polyline>\n </svg>\n <!-- Warning: bold ! is the most visible option inside a 38px circle badge -->\n <span *ngIf=\"i < currentSectionStep && stepValidationStates[i] === 'warning'\"\n class=\"ss-warning-mark\">!</span>\n <!-- Number: current or future step -->\n <span *ngIf=\"i >= currentSectionStep\">{{ i + 1 }}</span>\n </div>\n\n <!-- Step label (truncated; full text revealed by CSS tooltip) -->\n <div class=\"ss-label\" [title]=\"step.sectionConfig?.label || 'Step ' + (i + 1)\">\n {{ step.sectionConfig?.label || 'Step ' + (i + 1) }}\n </div>\n\n <!-- Connector line \u2014 right side (hidden for last step) -->\n <div class=\"ss-connector ss-connector--right\" *ngIf=\"i < sectionSteps.length - 1\"></div>\n </div>\n </div>\n </div>\n\n <!-- Step panels \u2014 all mounted, only active one is visible (preserves form data) -->\n <form [formGroup]=\"formGroup\" class=\"smart-form ss-form\">\n <div\n *ngFor=\"let step of sectionSteps; let i = index\"\n class=\"ss-step-panel\"\n [style.display]=\"i === currentSectionStep ? 'block' : 'none'\">\n <lib-form-section\n [config]=\"getSectionStepConfig(step)\"\n [controller]=\"controller\"\n [formGroup]=\"formGroup\">\n </lib-form-section>\n </div>\n </form>\n\n </ng-container>\n\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n Regular card wrapper \u2014 used for SECTION and STEPPER form types.\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n <div class=\"smart-form-wrapper\" *ngIf=\"formSchema && isFormReady && !isSectionStepper\"\n [class.smart-form-wrapper--readonly]=\"readOnly\">\n\n <!-- Form Header -->\n <div class=\"form-header\" *ngIf=\"formSchema.showTitle !== false\">\n <h2 class=\"form-title\">{{ formSchema.label }}</h2>\n <p class=\"form-description\" *ngIf=\"formSchema.description\">{{ formSchema.description }}</p>\n </div>\n\n <!-- STEPPER type nav -->\n <div class=\"stepper-nav\" *ngIf=\"isStepper && formSchema.stepperConfig?.showStep !== false\">\n <div class=\"stepper-steps\" [class.horizontal]=\"formSchema.stepperConfig?.isHorizontal !== false\">\n <div *ngFor=\"let step of fieldList; let i = index\" class=\"stepper-step\" [class.active]=\"i === currentStep\"\n [class.completed]=\"i < currentStep\">\n <div class=\"step-number\">{{ i + 1 }}</div>\n <div class=\"step-label\">{{ step.sectionConfig?.label || 'Step ' + (i + 1) }}</div>\n </div>\n </div>\n </div>\n\n <!-- Form Content -->\n <form [formGroup]=\"formGroup\" class=\"smart-form\">\n <!-- Regular SECTION form -->\n <div *ngIf=\"!isStepper && formSchema.sectionConfig && formSchema.sectionConfig.isEnabled !== false\" class=\"form-section\">\n <lib-form-section [config]=\"formSchema.sectionConfig\" [controller]=\"controller\" [formGroup]=\"formGroup\">\n </lib-form-section>\n </div>\n\n <!-- STEPPER type form -->\n <div *ngIf=\"isStepper && currentStepConfig && currentStepConfig.sectionConfig?.isEnabled !== false\" class=\"form-stepper\">\n <lib-form-section [config]=\"currentStepConfig.sectionConfig!\" [controller]=\"controller\" [formGroup]=\"formGroup\">\n </lib-form-section>\n </div>\n </form>\n\n <!-- \u2500\u2500 Form Actions \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"form-actions\" *ngIf=\"formSchema.showActions !== false && !readOnly && actionBarConfig?.buttons?.length\">\n\n <!-- LEFT GROUP -->\n <div class=\"action-group action-group--left\">\n <lib-button\n *ngFor=\"let btn of getButtonsForAlignment('left')\"\n [variant]=\"$any(btn.variant) || 'outline'\"\n [disabled]=\"isButtonDisabled(btn)\"\n (click)=\"handleButtonClick(btn)\">\n {{ getButtonLabel(btn) }}\n </lib-button>\n </div>\n\n <!-- RIGHT GROUP -->\n <div class=\"action-group action-group--right\">\n <lib-button\n *ngFor=\"let btn of getButtonsForAlignment('right')\"\n [variant]=\"$any(btn.variant) || 'primary'\"\n [disabled]=\"isButtonDisabled(btn)\"\n (click)=\"handleButtonClick(btn)\">\n {{ getButtonLabel(btn) }}\n </lib-button>\n </div>\n\n </div>\n </div>\n\n</div>\n", styles: ["@keyframes skel-wave{0%{transform:translate(-100%)}to{transform:translate(200%)}}@keyframes skel-fade-in{0%{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}@keyframes form-reveal{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}.smart-form-skeleton{background:var(--cc-sf-form-bg, #ffffff);border-radius:var(--cc-sf-form-border-radius, 12px);border:var(--cc-sf-form-border, none);box-shadow:var(--cc-sf-form-shadow, 0 1px 3px rgba(0, 0, 0, .06));padding:1.5rem;display:flex;flex-direction:column;gap:var(--cc-sf-form-section-gap, 24px);animation:skel-fade-in .3s ease both}.skel-block{position:relative;overflow:hidden;border-radius:6px;background:var(--cc-sf-input-disabled-bg, #F0F2F5)}.skel-block:after{content:\"\";position:absolute;inset:0;transform:translate(-100%);background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,.55) 45%,rgba(255,255,255,.75) 50%,rgba(255,255,255,.55) 55%,transparent 100%);animation:skel-wave 1.8s ease-in-out infinite;animation-delay:var(--sd, 0s)}.skel-header{display:flex;flex-direction:column;gap:10px}.skel-header .skel-title{height:26px;border-radius:8px}.skel-header .skel-desc{height:14px;border-radius:5px;opacity:.7}.skel-section{display:flex;flex-direction:column;gap:14px}.skel-section-label{height:16px;border-radius:0 5px 5px 0;border-left:var(--cc-sf-section-header-accent-width, 4px) solid var(--cc-sf-section-header-accent-color, #3B82F6);background:var(--cc-sf-input-disabled-bg, #F0F2F5);opacity:.85}.skel-fields{display:grid;gap:var(--cc-sf-grid-gap, 16px);align-items:start}.skel-fields--two{grid-template-columns:1fr 1fr}.skel-fields--three{grid-template-columns:1fr 1fr 1fr}@media(max-width:640px){.skel-fields--two,.skel-fields--three{grid-template-columns:1fr}}.skel-field{display:flex;flex-direction:column;gap:7px}.skel-field--full{grid-column:1/-1}.skel-label{height:12px;border-radius:4px;opacity:.75}.skel-input{height:42px;border-radius:8px}.skel-input--textarea{height:80px}.skel-chips{display:flex;flex-wrap:wrap;gap:8px}.skel-chip{height:32px;border-radius:20px;opacity:.8}.skel-actions{display:flex;justify-content:flex-end;align-items:center;gap:12px;padding-top:20px;border-top:var(--cc-sf-actions-border, 1px solid #E5E7EB)}.skel-btn{height:40px;border-radius:8px}.skel-btn--primary{background:color-mix(in srgb,var(--cc-sf-accent-color, #3B82F6) 18%,var(--cc-sf-input-disabled-bg, #F0F2F5))}.smart-form-container{width:100%;font-family:var(--cc-sf-font-family, \"Inter\", sans-serif)}.smart-form-wrapper{background:var(--cc-sf-form-bg, #ffffff);border-radius:var(--cc-sf-form-border-radius, 12px);border:var(--cc-sf-form-border, none);box-shadow:var(--cc-sf-form-shadow, 0 1px 3px rgba(0, 0, 0, .06));padding:1.5rem;animation:form-reveal .3s ease both}.smart-form-wrapper .form-alert-feedback{margin-bottom:1rem}.form-header .form-title{font-size:var(--cc-sf-form-title-size, 1.5rem);font-weight:var(--cc-sf-form-title-weight, 700);color:var(--cc-sf-form-title-color, #111827);margin:0 0 8px;line-height:1.25}.form-header .form-description{font-size:var(--cc-sf-form-desc-size, .875rem);color:var(--cc-sf-form-desc-color, #6B7280);margin:0}@keyframes ss-badge-pop{0%{transform:scale(.6);opacity:0}70%{transform:scale(1.12)}to{transform:scale(1);opacity:1}}@keyframes ss-pulse-ring{0%{box-shadow:0 0 #6366f173}70%{box-shadow:0 0 0 10px #6366f100}to{box-shadow:0 0 #6366f100}}@keyframes ss-panel-in{0%{opacity:0;transform:translateY(14px)}to{opacity:1;transform:translateY(0)}}@keyframes ss-connector-fill{0%{transform:scaleX(0)}to{transform:scaleX(1)}}.section-stepper-nav{position:relative;background:#fff;border-radius:16px;border:1px solid #E8EAF0;box-shadow:0 1px 3px #0000000d,0 4px 16px #6366f10f;padding:24px 28px 48px;margin-bottom:14px;overflow-x:clip;overflow-y:hidden}.section-stepper-nav:before{content:\"\";position:absolute;inset:0 0 auto;height:3px;border-radius:16px 16px 0 0;background:linear-gradient(90deg,#6366f1,#8b5cf6,#ec4899)}.section-stepper-track{display:flex;align-items:flex-start;justify-content:space-between;min-width:max-content;width:100%}.section-stepper-step{display:flex;flex-direction:column;align-items:center;position:relative;flex:1;cursor:pointer;padding:0 4px}.section-stepper-step:after{content:attr(data-tooltip);position:absolute;top:calc(100% + 8px);left:50%;transform:translate(-50%) translateY(4px);white-space:nowrap;background:#1e1b4b;color:#fff;font-size:.6875rem;font-weight:500;letter-spacing:.02em;padding:5px 11px;border-radius:6px;pointer-events:none;opacity:0;transition:opacity .2s ease,transform .2s ease;z-index:200;box-shadow:0 4px 14px #0003}.section-stepper-step:hover:after{opacity:1;transform:translate(-50%) translateY(0)}.section-stepper-step .ss-badge{width:38px;height:38px;min-width:38px;border-radius:50%;background:#f1f2f6;color:#9ca3af;border:2px solid #E5E7EB;display:flex;align-items:center;justify-content:center;font-size:.8125rem;font-weight:700;position:relative;z-index:1;transition:all .3s cubic-bezier(.34,1.56,.64,1)}.section-stepper-step .ss-badge span{line-height:1;letter-spacing:-.01em}.section-stepper-step .ss-badge svg{flex-shrink:0}.section-stepper-step .ss-badge .ss-warning-mark{font-size:1.25rem;font-weight:900;line-height:1;letter-spacing:0;color:#fff}.section-stepper-step .ss-label{margin-top:9px;font-size:.6875rem;font-weight:500;color:#b0b7c3;white-space:nowrap;text-align:center;transition:color .25s ease,font-weight .25s ease;max-width:88px;overflow:hidden;text-overflow:ellipsis;letter-spacing:.01em}.section-stepper-step .ss-connector{height:2px;background:#e8eaf0;position:absolute;top:19px;z-index:0;overflow:hidden;border-radius:2px}.section-stepper-step .ss-connector--left{left:0;right:calc(50% + 19px)}.section-stepper-step .ss-connector--right{left:calc(50% + 19px);right:0}.section-stepper-step .ss-connector:after{content:\"\";position:absolute;inset:0;background:linear-gradient(90deg,#6366f1,#8b5cf6);transform:scaleX(0);transform-origin:left;transition:transform .4s cubic-bezier(.4,0,.2,1)}.section-stepper-step.ss-active{cursor:default}.section-stepper-step.ss-active .ss-badge{background:linear-gradient(135deg,#6366f1,#8b5cf6);color:#fff;border-color:transparent;box-shadow:0 0 0 4px #6366f12e,0 4px 12px #6366f159;animation:ss-badge-pop .4s cubic-bezier(.34,1.56,.64,1) both,ss-pulse-ring 2s .4s ease-out infinite}.section-stepper-step.ss-active .ss-label{color:#4f46e5;font-weight:700}.section-stepper-step.ss-completed .ss-badge{background:linear-gradient(135deg,#10b981,#059669);color:#fff;border-color:transparent;box-shadow:0 2px 8px #10b9814d}.section-stepper-step.ss-completed .ss-label{color:#6b7280;font-weight:500}.section-stepper-step.ss-completed .ss-connector--left:after,.section-stepper-step.ss-completed .ss-connector--right:after{transform:scaleX(1)}.section-stepper-step.ss-warning .ss-badge{background:linear-gradient(135deg,#f59e0b,#d97706);color:#fff;border-color:transparent;box-shadow:0 2px 8px #f59e0b59;animation:ss-badge-pop .35s cubic-bezier(.34,1.56,.64,1) both}.section-stepper-step.ss-warning .ss-label{color:#b45309;font-weight:600}.section-stepper-step.ss-warning .ss-connector--left:after{transform:scaleX(0)}.section-stepper-step.ss-warning .ss-connector--right:after{transform:scaleX(0)}.section-stepper-step:not(.ss-active):not(.ss-completed):not(.ss-warning):hover .ss-badge{background:#e8eaf0;color:#6366f1;border-color:#c7d2fe;transform:translateY(-2px)}.section-stepper-step:not(.ss-active):not(.ss-completed):not(.ss-warning):hover .ss-label{color:#6b7280}.ss-step-panel{animation:ss-panel-in .35s cubic-bezier(.4,0,.2,1) both}.ss-form{padding-top:0}@media(max-width:768px){.section-stepper-nav{padding:20px 16px 16px}.section-stepper-step .ss-label{font-size:.625rem;max-width:64px}.section-stepper-step .ss-badge{width:32px;height:32px;min-width:32px;font-size:.75rem}.section-stepper-step .ss-connector{top:16px}.section-stepper-step .ss-connector--left{right:calc(50% + 16px)}.section-stepper-step .ss-connector--right{left:calc(50% + 16px)}}.stepper-nav{margin-bottom:32px}.stepper-nav .stepper-steps{display:flex;gap:16px}.stepper-nav .stepper-steps.horizontal{flex-direction:row;justify-content:space-between}.stepper-nav .stepper-steps:not(.horizontal){flex-direction:column}.stepper-nav .stepper-step{display:flex;align-items:center;gap:12px;flex:1;position:relative}.stepper-nav .stepper-step:not(:last-child):after{content:\"\";position:absolute;top:calc(var(--cc-sf-step-number-size, 40px) / 2);left:calc(100% + 8px);width:calc(100% - 40px);height:2px;background:var(--cc-sf-step-connector-color, #E5E7EB);transition:background var(--cc-sf-btn-transition, .2s ease)}.stepper-nav .stepper-step.completed:after{background:var(--cc-sf-step-connector-done, #22C55E)}.stepper-nav .stepper-step .step-number{width:var(--cc-sf-step-number-size, 40px);height:var(--cc-sf-step-number-size, 40px);min-width:var(--cc-sf-step-number-size, 40px);border-radius:50%;background:var(--cc-sf-step-number-bg, #E5E7EB);color:var(--cc-sf-step-number-color, #6B7280);display:flex;align-items:center;justify-content:center;font-size:var(--cc-sf-step-number-font-size, .875rem);font-weight:var(--cc-sf-step-number-weight, 600);transition:var(--cc-sf-btn-transition, all .2s ease)}.stepper-nav .stepper-step .step-label{font-size:var(--cc-sf-step-label-size, .875rem);color:var(--cc-sf-step-label-color, #6B7280);font-weight:var(--cc-sf-step-label-weight, 500);transition:var(--cc-sf-btn-transition, all .2s ease)}.stepper-nav .stepper-step.active .step-number{background:var(--cc-sf-step-active-bg, #3B82F6);color:var(--cc-sf-step-active-color, #ffffff)}.stepper-nav .stepper-step.active .step-label{color:var(--cc-sf-step-active-label, #1D4ED8);font-weight:var(--cc-sf-step-active-label-weight, 700)}.stepper-nav .stepper-step.completed .step-number{background:var(--cc-sf-step-done-bg, #22C55E);color:var(--cc-sf-step-done-color, #ffffff)}.smart-form{padding-top:var(--cc-sf-form-padding, 24px);display:flex;flex-direction:column;gap:var(--cc-sf-form-section-gap, 24px)}.smart-form>*{margin-bottom:0!important}.form-actions{display:flex;justify-content:space-between;align-items:center;gap:var(--cc-sf-actions-gap, 12px);padding:var(--cc-sf-actions-padding, 20px 0 0);margin-top:8px;border-top:var(--cc-sf-actions-border, 1px solid #E5E7EB)}.form-actions .action-group{display:flex;align-items:center;gap:var(--cc-sf-actions-gap, 12px)}.form-actions .action-group--left{justify-content:flex-start}.form-actions .action-group--right{justify-content:flex-end;margin-left:auto}\n"] }]
|
|
2876
3074
|
}], ctorParameters: () => [{ type: i1$3.FormBuilder }, { type: SmartFormController }, { type: ExpressionService }, { type: i3.HttpClient }, { type: SnackbarService }, { type: i1$4.Router }], propDecorators: { formJson: [{
|
|
2877
3075
|
type: Input
|
|
2878
3076
|
}], initialValues: [{
|
|
@@ -2899,6 +3097,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
2899
3097
|
type: Output
|
|
2900
3098
|
}], fileRemoved: [{
|
|
2901
3099
|
type: Output
|
|
3100
|
+
}], stepChange: [{
|
|
3101
|
+
type: Output
|
|
2902
3102
|
}] } });
|
|
2903
3103
|
|
|
2904
3104
|
class ButtonModule {
|
|
@@ -7132,11 +7332,11 @@ class ConfiguratorConfigPanelComponent {
|
|
|
7132
7332
|
return patch;
|
|
7133
7333
|
}
|
|
7134
7334
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ConfiguratorConfigPanelComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: SnackbarService }], target: i0.ɵɵFactoryTarget.Component });
|
|
7135
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: ConfiguratorConfigPanelComponent, isStandalone: false, selector: "lib-configurator-config-panel", inputs: { selectedField: "selectedField", selectedFieldInfo: "selectedFieldInfo", builderFieldType: "builderFieldType", fieldTypeSchemaMap: "fieldTypeSchemaMap", showOptionConfig: "showOptionConfig" }, outputs: { configChange: "configChange", typeChange: "typeChange" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"fb-config-panel\">\r\n @if (!selectedField) {\r\n <div class=\"fb-config-panel__empty\">\r\n <div class=\"fb-config-panel__empty-icon\">\r\n <svg width=\"64\" height=\"64\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" ry=\"2\"/>\r\n <line x1=\"3\" y1=\"9\" x2=\"21\" y2=\"9\"/>\r\n <line x1=\"9\" y1=\"21\" x2=\"9\" y2=\"9\"/>\r\n </svg>\r\n </div>\r\n <p class=\"fb-config-panel__empty-text\">\r\n Select a field from the tree panel to edit its configuration.\r\n </p>\r\n </div>\r\n } @else {\r\n <div class=\"fb-config-panel__header\">\r\n <div class=\"fb-config-panel__header-left\">\r\n <h3 class=\"fb-config-panel__title\">\r\n {{ selectedField.label || selectedField.name || 'Field Settings' }}\r\n </h3>\r\n @if (selectedField.type) {\r\n <span class=\"fb-config-panel__badge\">{{ selectedField.type }}</span>\r\n }\r\n </div>\r\n\r\n <!-- Field Type Switcher: hidden for DROPDOWN / MULTI_SELECT fields -->\r\n @if (!isDropdownType) {\r\n <div class=\"fb-config-panel__type-switcher\">\r\n <label class=\"fb-config-panel__type-label\" for=\"fb-field-type-select\">Field Type</label>\r\n <select\r\n id=\"fb-field-type-select\"\r\n class=\"fb-config-panel__type-select\"\r\n [value]=\"currentBuilderType\"\r\n (change)=\"onTypeSelectChange($event)\"\r\n >\r\n @for (opt of switchableFieldTypes; track opt.value) {\r\n <option [value]=\"opt.value\">{{ opt.label }}</option>\r\n }\r\n </select>\r\n </div>\r\n }\r\n </div>\r\n\r\n <div class=\"fb-config-panel__form-wrapper\">\r\n @if (showConfigForm && configFormJson) {\r\n <div class=\"fb-config-card\">\r\n <lib-smart-form\r\n [formJson]=\"configFormJson\"\r\n [initialValues]=\"configInitialValues\"\r\n (actionClick)=\"onActionClick($event)\"\r\n />\r\n </div>\r\n } @else if (!showConfigForm) {\r\n <!-- intentionally empty \u2014 SmartForm is being recycled -->\r\n } @else {\r\n <div class=\"fb-config-panel__error\">\r\n No configuration schema available for this field type.\r\n </div>\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [".fb-config-panel{display:flex;flex-direction:column;height:100%;background:var(--fb-fc-panel-bg, #f9fafb);overflow:hidden;--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 12px;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 12px;--cc-sf-label-size: .75rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .5rem .75rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #FFFAF1;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 0 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}@media(min-width:600px){.fb-config-panel{--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 14px;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 14px;--cc-sf-label-size: .8rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .5rem .75rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #FFFAF1;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 0 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}}@media(min-width:768px){.fb-config-panel{--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 16px;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 16px;--cc-sf-label-size: .8125rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .625rem .875rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #FFFAF1;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 0 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}}@media(min-width:1024px){.fb-config-panel{--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 16px;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 16px;--cc-sf-label-size: .8125rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .625rem .875rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #FFFAF1;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 0 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}}@media(min-width:1440px){.fb-config-panel{--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 18px;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 18px;--cc-sf-label-size: .8125rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .625rem .875rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #FFFAF1;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 0 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}}@media(min-width:1920px){.fb-config-panel{--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 18px;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 18px;--cc-sf-label-size: .8125rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .625rem .875rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #FFFAF1;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 0 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}}.fb-config-panel__empty{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;color:var(--fb-fc-empty-color, #9ca3af);text-align:center;padding:48px 24px}@media(max-width:640px){.fb-config-panel__empty{padding:24px 16px}}.fb-config-panel__empty-icon{margin-bottom:24px;opacity:.4;color:var(--fb-fc-accent, #3b82f6)}@media(max-width:640px){.fb-config-panel__empty-icon{margin-bottom:16px}}.fb-config-panel__empty-text{font-size:15px;max-width:320px;line-height:1.6;font-weight:500}@media(max-width:640px){.fb-config-panel__empty-text{font-size:14px;max-width:100%}}.fb-config-panel__header{background:var(--fb-fc-header-bg, #ffffff);padding:1.4rem;border-bottom:1px solid var(--fb-fc-border, #e5e7eb);display:flex;align-items:center;justify-content:space-between;flex-shrink:0;gap:16px;flex-wrap:wrap}@media(max-width:768px){.fb-config-panel__header{padding:16px 24px;gap:12px}}@media(max-width:640px){.fb-config-panel__header{padding:12px 16px;gap:8px}}.fb-config-panel__header-left{display:flex;align-items:center;gap:12px;min-width:0;flex-wrap:wrap}@media(max-width:640px){.fb-config-panel__header-left{gap:8px}}.fb-config-panel__type-switcher{display:flex;align-items:center;gap:8px;flex-shrink:0}@media(max-width:640px){.fb-config-panel__type-switcher{gap:4px}}.fb-config-panel__type-label{font-size:var(--fb-fc-type-label-size, .75rem);font-weight:600;color:var(--fb-fc-type-label-color, #6b7280);white-space:nowrap}@media(max-width:640px){.fb-config-panel__type-label{font-size:.7rem}}.fb-config-panel__type-select{height:var(--fb-fc-type-select-height, 36px);padding:0 32px 0 10px;border:1px solid var(--fb-fc-type-select-border, #d1d5db);border-radius:var(--fb-fc-type-select-radius, 8px);background-color:var(--fb-fc-type-select-bg, #ffffff);color:var(--fb-fc-type-select-color, #111827);font-size:.8125rem;font-weight:500;cursor:pointer;appearance:none;background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E\");background-repeat:no-repeat;background-position:right 8px center;min-width:160px;transition:border-color .15s ease,box-shadow .15s ease}@media(max-width:640px){.fb-config-panel__type-select{height:32px;font-size:.75rem;min-width:140px;padding:0 28px 0 8px}}.fb-config-panel__type-select:hover{border-color:var(--fb-fc-type-select-hover-border, #9ca3af)}.fb-config-panel__type-select:focus{outline:none;border-color:var(--fb-fc-accent, #3b82f6);box-shadow:0 0 0 3px #3b82f61f}.fb-config-panel__title{margin:0;font-size:1.25rem;font-weight:700;color:var(--fb-fc-title-color, #111827)}@media(max-width:1024px){.fb-config-panel__title{font-size:1.125rem}}@media(max-width:640px){.fb-config-panel__title{font-size:1rem}}.fb-config-panel__badge{padding:4px 12px;background:var(--fb-fc-badge-bg, #eff6ff);color:var(--fb-fc-badge-color, #3b82f6);border-radius:20px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;border:1px solid var(--fb-fc-badge-border, #dbeafe)}@media(max-width:640px){.fb-config-panel__badge{padding:3px 8px;font-size:9px}}.fb-config-panel__form-wrapper{flex:1;overflow-y:auto;overflow-x:hidden;width:100%;min-width:0;display:flex;flex-direction:column;align-items:stretch;box-sizing:border-box;padding:12px 16px}@media(min-width:600px){.fb-config-panel__form-wrapper{padding:16px 20px}}@media(min-width:768px){.fb-config-panel__form-wrapper{padding:20px 24px}}@media(min-width:1024px){.fb-config-panel__form-wrapper{padding:1rem}}@media(min-width:1440px){.fb-config-panel__form-wrapper{padding:28px 40px}}@media(min-width:1920px){.fb-config-panel__form-wrapper{padding:32px 48px}}.fb-config-panel__form-wrapper .fb-config-card{width:100%;max-width:none;margin:0;background:transparent;border:none;box-shadow:none;display:flex;flex-direction:column;min-width:0;flex:1;box-sizing:border-box}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .sf-col{min-width:0}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{display:grid;grid-auto-flow:dense;gap:12px;width:100%;align-items:start}@media(max-width:599px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{grid-template-columns:1fr;gap:12px}}@media(min-width:600px)and (max-width:767px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{grid-template-columns:1fr;gap:14px}}@media(min-width:768px)and (max-width:1023px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{grid-template-columns:repeat(2,1fr);gap:14px}}@media(min-width:1024px)and (max-width:1439px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{grid-template-columns:repeat(2,1fr);gap:16px}}@media(min-width:1440px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{grid-template-columns:repeat(3,1fr);gap:18px}}@media(min-width:1920px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{grid-template-columns:repeat(3,1fr);gap:20px}}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal>*{display:flex;flex-direction:column;min-width:0;overflow:hidden}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal>* ::ng-deep .form-field-wrapper,.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal>* ::ng-deep .field-wrapper,.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal>* ::ng-deep input,.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal>* ::ng-deep select,.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal>* ::ng-deep textarea{width:100%;min-width:0}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper{display:flex;flex-direction:row;align-items:center;gap:8px;white-space:nowrap;min-width:0}@media(max-width:768px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper{gap:6px}}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper .field-label{font-size:.75rem;font-weight:600;margin:0;flex-shrink:1;min-width:0;word-break:keep-all}@media(max-width:768px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper .field-label{font-size:.7rem}}@media(max-width:640px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper .field-label{font-size:.65rem}}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper .switch{flex-shrink:0}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper{display:flex;flex-direction:row;align-items:center;gap:8px;white-space:nowrap;min-width:0}@media(max-width:768px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper{gap:6px}}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper .field-label{font-size:.75rem;font-weight:600;margin:0;flex-shrink:1;min-width:0;word-break:keep-all}@media(max-width:768px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper .field-label{font-size:.7rem}}@media(max-width:640px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper .field-label{font-size:.65rem}}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper .switch{flex-shrink:0}.fb-config-panel__error{padding:24px;background:var(--fb-fc-error-bg, #fef2f2);color:var(--fb-fc-error-color, #dc2626);border:1px solid var(--fb-fc-error-border, #fee2e2);border-radius:8px;font-size:14px;font-weight:500}@media(max-width:768px){.fb-config-panel__error{padding:16px;font-size:13px}}@media(max-width:640px){.fb-config-panel__error{padding:12px;font-size:12px}}\n"], dependencies: [{ kind: "component", type: SmartFormComponent, selector: "lib-smart-form", inputs: ["formJson", "initialValues", "enableDraftAutoSave", "labels", "mode", "readOnly"], outputs: ["submit", "draftSave", "actionClick", "valueChange", "fileAdded", "fileUploadFinished", "fileRemoved"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
7335
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: ConfiguratorConfigPanelComponent, isStandalone: false, selector: "lib-configurator-config-panel", inputs: { selectedField: "selectedField", selectedFieldInfo: "selectedFieldInfo", builderFieldType: "builderFieldType", fieldTypeSchemaMap: "fieldTypeSchemaMap", showOptionConfig: "showOptionConfig" }, outputs: { configChange: "configChange", typeChange: "typeChange" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"fb-config-panel\">\r\n @if (!selectedField) {\r\n <div class=\"fb-config-panel__empty\">\r\n <div class=\"fb-config-panel__empty-icon\">\r\n <svg width=\"64\" height=\"64\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" ry=\"2\"/>\r\n <line x1=\"3\" y1=\"9\" x2=\"21\" y2=\"9\"/>\r\n <line x1=\"9\" y1=\"21\" x2=\"9\" y2=\"9\"/>\r\n </svg>\r\n </div>\r\n <p class=\"fb-config-panel__empty-text\">\r\n Select a field from the tree panel to edit its configuration.\r\n </p>\r\n </div>\r\n } @else {\r\n <div class=\"fb-config-panel__header\">\r\n <div class=\"fb-config-panel__header-left\">\r\n <h3 class=\"fb-config-panel__title\">\r\n {{ selectedField.label || selectedField.name || 'Field Settings' }}\r\n </h3>\r\n @if (selectedField.type) {\r\n <span class=\"fb-config-panel__badge\">{{ selectedField.type }}</span>\r\n }\r\n </div>\r\n\r\n <!-- Field Type Switcher: hidden for DROPDOWN / MULTI_SELECT fields -->\r\n @if (!isDropdownType) {\r\n <div class=\"fb-config-panel__type-switcher\">\r\n <label class=\"fb-config-panel__type-label\" for=\"fb-field-type-select\">Field Type</label>\r\n <select\r\n id=\"fb-field-type-select\"\r\n class=\"fb-config-panel__type-select\"\r\n [value]=\"currentBuilderType\"\r\n (change)=\"onTypeSelectChange($event)\"\r\n >\r\n @for (opt of switchableFieldTypes; track opt.value) {\r\n <option [value]=\"opt.value\">{{ opt.label }}</option>\r\n }\r\n </select>\r\n </div>\r\n }\r\n </div>\r\n\r\n <div class=\"fb-config-panel__form-wrapper\">\r\n @if (showConfigForm && configFormJson) {\r\n <div class=\"fb-config-card\">\r\n <lib-smart-form\r\n [formJson]=\"configFormJson\"\r\n [initialValues]=\"configInitialValues\"\r\n (actionClick)=\"onActionClick($event)\"\r\n />\r\n </div>\r\n } @else if (!showConfigForm) {\r\n <!-- intentionally empty \u2014 SmartForm is being recycled -->\r\n } @else {\r\n <div class=\"fb-config-panel__error\">\r\n No configuration schema available for this field type.\r\n </div>\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [".fb-config-panel{display:flex;flex-direction:column;height:100%;background:var(--fb-fc-panel-bg, #f9fafb);overflow:hidden;--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-accent-color: #3B82F6;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-section-gap: 24px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 12px;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-section-header-accent-width: 4px;--cc-sf-section-header-accent-color: #3B82F6;--cc-sf-section-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-color: #1F2937;--cc-sf-repeater-accordion-active-bg: #EFF6FF;--cc-sf-repeater-badge-bg: #E5E7EB;--cc-sf-repeater-badge-color: #374151;--cc-sf-section-border-radius-inner: 8px;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 12px;--cc-sf-field-gap: 6px;--cc-sf-focus-ring-width: 3px;--cc-sf-focus-ring-offset: 0;--cc-sf-label-size: .75rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .5rem .75rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #F8FAFC;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-icon-bg: rgba(59, 130, 246, .1);--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-btn-remove-padding: .375rem .75rem;--cc-sf-btn-remove-font-size: .875rem;--cc-sf-btn-remove-font-weight: 500;--cc-sf-btn-add-padding: .625rem 1.5rem;--cc-sf-btn-add-font-size: .875rem;--cc-sf-btn-add-font-weight: 600;--cc-sf-stepper-connector-display: block;--cc-sf-instance-shadow: none;--cc-sf-instance-hover-shadow: none;--cc-sf-instance-transition: none;--cc-sf-instance-header-divider: none;--cc-sf-instance-header-pb: 0px;--cc-sf-instance-header-mb: 0px;--cc-sf-instance-num-weight: 600;--cc-sf-section-stepper-accent: #6366F1;--cc-sf-section-stepper-accent-end: #8B5CF6;--cc-sf-section-stepper-active-label: #4F46E5;--cc-sf-section-stepper-active-glow: rgba(99, 102, 241, .25);--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 0 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}.fb-config-panel ::ng-deep .stepper-nav .stepper-step:not(:last-child):after{display:var(--cc-sf-stepper-connector-display)!important}.fb-config-panel ::ng-deep .section-instance{background:var(--cc-sf-instance-bg)!important;border:var(--cc-sf-instance-border)!important;border-radius:var(--cc-sf-instance-radius)!important;box-shadow:var(--cc-sf-instance-shadow);transition:var(--cc-sf-instance-transition)}.fb-config-panel ::ng-deep .section-instance:hover{box-shadow:var(--cc-sf-instance-hover-shadow)}.fb-config-panel ::ng-deep .section-instance-header{display:flex;align-items:center;justify-content:space-between;padding-bottom:var(--cc-sf-instance-header-pb);margin-bottom:var(--cc-sf-instance-header-mb);border-bottom:var(--cc-sf-instance-header-divider)}.fb-config-panel ::ng-deep .section-instance-num{font-size:var(--cc-sf-instance-num-size);font-weight:var(--cc-sf-instance-num-weight);color:var(--cc-sf-instance-num-color)}.fb-config-panel ::ng-deep .btn-instance-remove{display:inline-flex;align-items:center;gap:6px;padding:var(--cc-sf-btn-remove-padding);border-radius:var(--cc-sf-btn-remove-radius);border:var(--cc-sf-btn-remove-border)!important;background:var(--cc-sf-btn-remove-bg);color:var(--cc-sf-btn-remove-color)!important;font-size:var(--cc-sf-btn-remove-font-size);font-weight:var(--cc-sf-btn-remove-font-weight);cursor:pointer;transition:all .15s ease}.fb-config-panel ::ng-deep .btn-instance-remove:hover{background:var(--cc-sf-btn-remove-hover-bg)}.fb-config-panel ::ng-deep .btn-add-section{display:inline-flex;align-items:center;gap:8px;padding:var(--cc-sf-btn-add-padding);border-radius:var(--cc-sf-btn-add-radius);border:var(--cc-sf-btn-add-border)!important;background:var(--cc-sf-btn-add-bg);color:var(--cc-sf-btn-add-color);font-size:var(--cc-sf-btn-add-font-size);font-weight:var(--cc-sf-btn-add-font-weight);cursor:pointer;transition:all .18s ease}.fb-config-panel ::ng-deep .btn-add-section:hover{background:var(--cc-sf-btn-add-hover-bg);border-color:var(--cc-sf-btn-add-hover-border)!important}.fb-config-panel ::ng-deep .section-stepper-nav:before{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-badge{background:linear-gradient(135deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important;box-shadow:0 0 0 4px var(--cc-sf-section-stepper-active-glow),0 4px 12px var(--cc-sf-section-stepper-active-glow)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-label{color:var(--cc-sf-section-stepper-active-label)!important}.fb-config-panel ::ng-deep .section-stepper-step:not(.ss-active):not(.ss-completed):not(.ss-warning):hover .ss-badge{color:var(--cc-sf-section-stepper-accent)!important;border-color:var(--cc-sf-section-stepper-accent-end)!important}.fb-config-panel ::ng-deep .section-stepper-step .ss-connector:after{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent),var(--cc-sf-section-stepper-accent-end))!important}@media(min-width:600px){.fb-config-panel{--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-accent-color: #3B82F6;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-section-gap: 24px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 14px;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-section-header-accent-width: 4px;--cc-sf-section-header-accent-color: #3B82F6;--cc-sf-section-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-color: #1F2937;--cc-sf-repeater-accordion-active-bg: #EFF6FF;--cc-sf-repeater-badge-bg: #E5E7EB;--cc-sf-repeater-badge-color: #374151;--cc-sf-section-border-radius-inner: 8px;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 14px;--cc-sf-field-gap: 6px;--cc-sf-focus-ring-width: 3px;--cc-sf-focus-ring-offset: 0;--cc-sf-label-size: .8rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .5rem .75rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #F8FAFC;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-icon-bg: rgba(59, 130, 246, .1);--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-btn-remove-padding: .375rem .75rem;--cc-sf-btn-remove-font-size: .875rem;--cc-sf-btn-remove-font-weight: 500;--cc-sf-btn-add-padding: .625rem 1.5rem;--cc-sf-btn-add-font-size: .875rem;--cc-sf-btn-add-font-weight: 600;--cc-sf-stepper-connector-display: block;--cc-sf-instance-shadow: none;--cc-sf-instance-hover-shadow: none;--cc-sf-instance-transition: none;--cc-sf-instance-header-divider: none;--cc-sf-instance-header-pb: 0px;--cc-sf-instance-header-mb: 0px;--cc-sf-instance-num-weight: 600;--cc-sf-section-stepper-accent: #6366F1;--cc-sf-section-stepper-accent-end: #8B5CF6;--cc-sf-section-stepper-active-label: #4F46E5;--cc-sf-section-stepper-active-glow: rgba(99, 102, 241, .25);--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 0 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}.fb-config-panel ::ng-deep .stepper-nav .stepper-step:not(:last-child):after{display:var(--cc-sf-stepper-connector-display)!important}.fb-config-panel ::ng-deep .section-instance{background:var(--cc-sf-instance-bg)!important;border:var(--cc-sf-instance-border)!important;border-radius:var(--cc-sf-instance-radius)!important;box-shadow:var(--cc-sf-instance-shadow);transition:var(--cc-sf-instance-transition)}.fb-config-panel ::ng-deep .section-instance:hover{box-shadow:var(--cc-sf-instance-hover-shadow)}.fb-config-panel ::ng-deep .section-instance-header{display:flex;align-items:center;justify-content:space-between;padding-bottom:var(--cc-sf-instance-header-pb);margin-bottom:var(--cc-sf-instance-header-mb);border-bottom:var(--cc-sf-instance-header-divider)}.fb-config-panel ::ng-deep .section-instance-num{font-size:var(--cc-sf-instance-num-size);font-weight:var(--cc-sf-instance-num-weight);color:var(--cc-sf-instance-num-color)}.fb-config-panel ::ng-deep .btn-instance-remove{display:inline-flex;align-items:center;gap:6px;padding:var(--cc-sf-btn-remove-padding);border-radius:var(--cc-sf-btn-remove-radius);border:var(--cc-sf-btn-remove-border)!important;background:var(--cc-sf-btn-remove-bg);color:var(--cc-sf-btn-remove-color)!important;font-size:var(--cc-sf-btn-remove-font-size);font-weight:var(--cc-sf-btn-remove-font-weight);cursor:pointer;transition:all .15s ease}.fb-config-panel ::ng-deep .btn-instance-remove:hover{background:var(--cc-sf-btn-remove-hover-bg)}.fb-config-panel ::ng-deep .btn-add-section{display:inline-flex;align-items:center;gap:8px;padding:var(--cc-sf-btn-add-padding);border-radius:var(--cc-sf-btn-add-radius);border:var(--cc-sf-btn-add-border)!important;background:var(--cc-sf-btn-add-bg);color:var(--cc-sf-btn-add-color);font-size:var(--cc-sf-btn-add-font-size);font-weight:var(--cc-sf-btn-add-font-weight);cursor:pointer;transition:all .18s ease}.fb-config-panel ::ng-deep .btn-add-section:hover{background:var(--cc-sf-btn-add-hover-bg);border-color:var(--cc-sf-btn-add-hover-border)!important}.fb-config-panel ::ng-deep .section-stepper-nav:before{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-badge{background:linear-gradient(135deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important;box-shadow:0 0 0 4px var(--cc-sf-section-stepper-active-glow),0 4px 12px var(--cc-sf-section-stepper-active-glow)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-label{color:var(--cc-sf-section-stepper-active-label)!important}.fb-config-panel ::ng-deep .section-stepper-step:not(.ss-active):not(.ss-completed):not(.ss-warning):hover .ss-badge{color:var(--cc-sf-section-stepper-accent)!important;border-color:var(--cc-sf-section-stepper-accent-end)!important}.fb-config-panel ::ng-deep .section-stepper-step .ss-connector:after{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent),var(--cc-sf-section-stepper-accent-end))!important}}@media(min-width:768px){.fb-config-panel{--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-accent-color: #3B82F6;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-section-gap: 24px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 16px;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-section-header-accent-width: 4px;--cc-sf-section-header-accent-color: #3B82F6;--cc-sf-section-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-color: #1F2937;--cc-sf-repeater-accordion-active-bg: #EFF6FF;--cc-sf-repeater-badge-bg: #E5E7EB;--cc-sf-repeater-badge-color: #374151;--cc-sf-section-border-radius-inner: 8px;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 16px;--cc-sf-field-gap: 6px;--cc-sf-focus-ring-width: 3px;--cc-sf-focus-ring-offset: 0;--cc-sf-label-size: .8125rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .625rem .875rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #F8FAFC;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-icon-bg: rgba(59, 130, 246, .1);--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-btn-remove-padding: .375rem .75rem;--cc-sf-btn-remove-font-size: .875rem;--cc-sf-btn-remove-font-weight: 500;--cc-sf-btn-add-padding: .625rem 1.5rem;--cc-sf-btn-add-font-size: .875rem;--cc-sf-btn-add-font-weight: 600;--cc-sf-stepper-connector-display: block;--cc-sf-instance-shadow: none;--cc-sf-instance-hover-shadow: none;--cc-sf-instance-transition: none;--cc-sf-instance-header-divider: none;--cc-sf-instance-header-pb: 0px;--cc-sf-instance-header-mb: 0px;--cc-sf-instance-num-weight: 600;--cc-sf-section-stepper-accent: #6366F1;--cc-sf-section-stepper-accent-end: #8B5CF6;--cc-sf-section-stepper-active-label: #4F46E5;--cc-sf-section-stepper-active-glow: rgba(99, 102, 241, .25);--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 0 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}.fb-config-panel ::ng-deep .stepper-nav .stepper-step:not(:last-child):after{display:var(--cc-sf-stepper-connector-display)!important}.fb-config-panel ::ng-deep .section-instance{background:var(--cc-sf-instance-bg)!important;border:var(--cc-sf-instance-border)!important;border-radius:var(--cc-sf-instance-radius)!important;box-shadow:var(--cc-sf-instance-shadow);transition:var(--cc-sf-instance-transition)}.fb-config-panel ::ng-deep .section-instance:hover{box-shadow:var(--cc-sf-instance-hover-shadow)}.fb-config-panel ::ng-deep .section-instance-header{display:flex;align-items:center;justify-content:space-between;padding-bottom:var(--cc-sf-instance-header-pb);margin-bottom:var(--cc-sf-instance-header-mb);border-bottom:var(--cc-sf-instance-header-divider)}.fb-config-panel ::ng-deep .section-instance-num{font-size:var(--cc-sf-instance-num-size);font-weight:var(--cc-sf-instance-num-weight);color:var(--cc-sf-instance-num-color)}.fb-config-panel ::ng-deep .btn-instance-remove{display:inline-flex;align-items:center;gap:6px;padding:var(--cc-sf-btn-remove-padding);border-radius:var(--cc-sf-btn-remove-radius);border:var(--cc-sf-btn-remove-border)!important;background:var(--cc-sf-btn-remove-bg);color:var(--cc-sf-btn-remove-color)!important;font-size:var(--cc-sf-btn-remove-font-size);font-weight:var(--cc-sf-btn-remove-font-weight);cursor:pointer;transition:all .15s ease}.fb-config-panel ::ng-deep .btn-instance-remove:hover{background:var(--cc-sf-btn-remove-hover-bg)}.fb-config-panel ::ng-deep .btn-add-section{display:inline-flex;align-items:center;gap:8px;padding:var(--cc-sf-btn-add-padding);border-radius:var(--cc-sf-btn-add-radius);border:var(--cc-sf-btn-add-border)!important;background:var(--cc-sf-btn-add-bg);color:var(--cc-sf-btn-add-color);font-size:var(--cc-sf-btn-add-font-size);font-weight:var(--cc-sf-btn-add-font-weight);cursor:pointer;transition:all .18s ease}.fb-config-panel ::ng-deep .btn-add-section:hover{background:var(--cc-sf-btn-add-hover-bg);border-color:var(--cc-sf-btn-add-hover-border)!important}.fb-config-panel ::ng-deep .section-stepper-nav:before{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-badge{background:linear-gradient(135deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important;box-shadow:0 0 0 4px var(--cc-sf-section-stepper-active-glow),0 4px 12px var(--cc-sf-section-stepper-active-glow)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-label{color:var(--cc-sf-section-stepper-active-label)!important}.fb-config-panel ::ng-deep .section-stepper-step:not(.ss-active):not(.ss-completed):not(.ss-warning):hover .ss-badge{color:var(--cc-sf-section-stepper-accent)!important;border-color:var(--cc-sf-section-stepper-accent-end)!important}.fb-config-panel ::ng-deep .section-stepper-step .ss-connector:after{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent),var(--cc-sf-section-stepper-accent-end))!important}}@media(min-width:1024px){.fb-config-panel{--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-accent-color: #3B82F6;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-section-gap: 24px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 16px;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-section-header-accent-width: 4px;--cc-sf-section-header-accent-color: #3B82F6;--cc-sf-section-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-color: #1F2937;--cc-sf-repeater-accordion-active-bg: #EFF6FF;--cc-sf-repeater-badge-bg: #E5E7EB;--cc-sf-repeater-badge-color: #374151;--cc-sf-section-border-radius-inner: 8px;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 16px;--cc-sf-field-gap: 6px;--cc-sf-focus-ring-width: 3px;--cc-sf-focus-ring-offset: 0;--cc-sf-label-size: .8125rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .625rem .875rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #F8FAFC;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-icon-bg: rgba(59, 130, 246, .1);--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-btn-remove-padding: .375rem .75rem;--cc-sf-btn-remove-font-size: .875rem;--cc-sf-btn-remove-font-weight: 500;--cc-sf-btn-add-padding: .625rem 1.5rem;--cc-sf-btn-add-font-size: .875rem;--cc-sf-btn-add-font-weight: 600;--cc-sf-stepper-connector-display: block;--cc-sf-instance-shadow: none;--cc-sf-instance-hover-shadow: none;--cc-sf-instance-transition: none;--cc-sf-instance-header-divider: none;--cc-sf-instance-header-pb: 0px;--cc-sf-instance-header-mb: 0px;--cc-sf-instance-num-weight: 600;--cc-sf-section-stepper-accent: #6366F1;--cc-sf-section-stepper-accent-end: #8B5CF6;--cc-sf-section-stepper-active-label: #4F46E5;--cc-sf-section-stepper-active-glow: rgba(99, 102, 241, .25);--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 0 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}.fb-config-panel ::ng-deep .stepper-nav .stepper-step:not(:last-child):after{display:var(--cc-sf-stepper-connector-display)!important}.fb-config-panel ::ng-deep .section-instance{background:var(--cc-sf-instance-bg)!important;border:var(--cc-sf-instance-border)!important;border-radius:var(--cc-sf-instance-radius)!important;box-shadow:var(--cc-sf-instance-shadow);transition:var(--cc-sf-instance-transition)}.fb-config-panel ::ng-deep .section-instance:hover{box-shadow:var(--cc-sf-instance-hover-shadow)}.fb-config-panel ::ng-deep .section-instance-header{display:flex;align-items:center;justify-content:space-between;padding-bottom:var(--cc-sf-instance-header-pb);margin-bottom:var(--cc-sf-instance-header-mb);border-bottom:var(--cc-sf-instance-header-divider)}.fb-config-panel ::ng-deep .section-instance-num{font-size:var(--cc-sf-instance-num-size);font-weight:var(--cc-sf-instance-num-weight);color:var(--cc-sf-instance-num-color)}.fb-config-panel ::ng-deep .btn-instance-remove{display:inline-flex;align-items:center;gap:6px;padding:var(--cc-sf-btn-remove-padding);border-radius:var(--cc-sf-btn-remove-radius);border:var(--cc-sf-btn-remove-border)!important;background:var(--cc-sf-btn-remove-bg);color:var(--cc-sf-btn-remove-color)!important;font-size:var(--cc-sf-btn-remove-font-size);font-weight:var(--cc-sf-btn-remove-font-weight);cursor:pointer;transition:all .15s ease}.fb-config-panel ::ng-deep .btn-instance-remove:hover{background:var(--cc-sf-btn-remove-hover-bg)}.fb-config-panel ::ng-deep .btn-add-section{display:inline-flex;align-items:center;gap:8px;padding:var(--cc-sf-btn-add-padding);border-radius:var(--cc-sf-btn-add-radius);border:var(--cc-sf-btn-add-border)!important;background:var(--cc-sf-btn-add-bg);color:var(--cc-sf-btn-add-color);font-size:var(--cc-sf-btn-add-font-size);font-weight:var(--cc-sf-btn-add-font-weight);cursor:pointer;transition:all .18s ease}.fb-config-panel ::ng-deep .btn-add-section:hover{background:var(--cc-sf-btn-add-hover-bg);border-color:var(--cc-sf-btn-add-hover-border)!important}.fb-config-panel ::ng-deep .section-stepper-nav:before{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-badge{background:linear-gradient(135deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important;box-shadow:0 0 0 4px var(--cc-sf-section-stepper-active-glow),0 4px 12px var(--cc-sf-section-stepper-active-glow)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-label{color:var(--cc-sf-section-stepper-active-label)!important}.fb-config-panel ::ng-deep .section-stepper-step:not(.ss-active):not(.ss-completed):not(.ss-warning):hover .ss-badge{color:var(--cc-sf-section-stepper-accent)!important;border-color:var(--cc-sf-section-stepper-accent-end)!important}.fb-config-panel ::ng-deep .section-stepper-step .ss-connector:after{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent),var(--cc-sf-section-stepper-accent-end))!important}}@media(min-width:1440px){.fb-config-panel{--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-accent-color: #3B82F6;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-section-gap: 24px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 18px;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-section-header-accent-width: 4px;--cc-sf-section-header-accent-color: #3B82F6;--cc-sf-section-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-color: #1F2937;--cc-sf-repeater-accordion-active-bg: #EFF6FF;--cc-sf-repeater-badge-bg: #E5E7EB;--cc-sf-repeater-badge-color: #374151;--cc-sf-section-border-radius-inner: 8px;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 18px;--cc-sf-field-gap: 6px;--cc-sf-focus-ring-width: 3px;--cc-sf-focus-ring-offset: 0;--cc-sf-label-size: .8125rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .625rem .875rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #F8FAFC;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-icon-bg: rgba(59, 130, 246, .1);--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-btn-remove-padding: .375rem .75rem;--cc-sf-btn-remove-font-size: .875rem;--cc-sf-btn-remove-font-weight: 500;--cc-sf-btn-add-padding: .625rem 1.5rem;--cc-sf-btn-add-font-size: .875rem;--cc-sf-btn-add-font-weight: 600;--cc-sf-stepper-connector-display: block;--cc-sf-instance-shadow: none;--cc-sf-instance-hover-shadow: none;--cc-sf-instance-transition: none;--cc-sf-instance-header-divider: none;--cc-sf-instance-header-pb: 0px;--cc-sf-instance-header-mb: 0px;--cc-sf-instance-num-weight: 600;--cc-sf-section-stepper-accent: #6366F1;--cc-sf-section-stepper-accent-end: #8B5CF6;--cc-sf-section-stepper-active-label: #4F46E5;--cc-sf-section-stepper-active-glow: rgba(99, 102, 241, .25);--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 0 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}.fb-config-panel ::ng-deep .stepper-nav .stepper-step:not(:last-child):after{display:var(--cc-sf-stepper-connector-display)!important}.fb-config-panel ::ng-deep .section-instance{background:var(--cc-sf-instance-bg)!important;border:var(--cc-sf-instance-border)!important;border-radius:var(--cc-sf-instance-radius)!important;box-shadow:var(--cc-sf-instance-shadow);transition:var(--cc-sf-instance-transition)}.fb-config-panel ::ng-deep .section-instance:hover{box-shadow:var(--cc-sf-instance-hover-shadow)}.fb-config-panel ::ng-deep .section-instance-header{display:flex;align-items:center;justify-content:space-between;padding-bottom:var(--cc-sf-instance-header-pb);margin-bottom:var(--cc-sf-instance-header-mb);border-bottom:var(--cc-sf-instance-header-divider)}.fb-config-panel ::ng-deep .section-instance-num{font-size:var(--cc-sf-instance-num-size);font-weight:var(--cc-sf-instance-num-weight);color:var(--cc-sf-instance-num-color)}.fb-config-panel ::ng-deep .btn-instance-remove{display:inline-flex;align-items:center;gap:6px;padding:var(--cc-sf-btn-remove-padding);border-radius:var(--cc-sf-btn-remove-radius);border:var(--cc-sf-btn-remove-border)!important;background:var(--cc-sf-btn-remove-bg);color:var(--cc-sf-btn-remove-color)!important;font-size:var(--cc-sf-btn-remove-font-size);font-weight:var(--cc-sf-btn-remove-font-weight);cursor:pointer;transition:all .15s ease}.fb-config-panel ::ng-deep .btn-instance-remove:hover{background:var(--cc-sf-btn-remove-hover-bg)}.fb-config-panel ::ng-deep .btn-add-section{display:inline-flex;align-items:center;gap:8px;padding:var(--cc-sf-btn-add-padding);border-radius:var(--cc-sf-btn-add-radius);border:var(--cc-sf-btn-add-border)!important;background:var(--cc-sf-btn-add-bg);color:var(--cc-sf-btn-add-color);font-size:var(--cc-sf-btn-add-font-size);font-weight:var(--cc-sf-btn-add-font-weight);cursor:pointer;transition:all .18s ease}.fb-config-panel ::ng-deep .btn-add-section:hover{background:var(--cc-sf-btn-add-hover-bg);border-color:var(--cc-sf-btn-add-hover-border)!important}.fb-config-panel ::ng-deep .section-stepper-nav:before{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-badge{background:linear-gradient(135deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important;box-shadow:0 0 0 4px var(--cc-sf-section-stepper-active-glow),0 4px 12px var(--cc-sf-section-stepper-active-glow)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-label{color:var(--cc-sf-section-stepper-active-label)!important}.fb-config-panel ::ng-deep .section-stepper-step:not(.ss-active):not(.ss-completed):not(.ss-warning):hover .ss-badge{color:var(--cc-sf-section-stepper-accent)!important;border-color:var(--cc-sf-section-stepper-accent-end)!important}.fb-config-panel ::ng-deep .section-stepper-step .ss-connector:after{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent),var(--cc-sf-section-stepper-accent-end))!important}}@media(min-width:1920px){.fb-config-panel{--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-accent-color: #3B82F6;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-section-gap: 24px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 18px;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-section-header-accent-width: 4px;--cc-sf-section-header-accent-color: #3B82F6;--cc-sf-section-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-color: #1F2937;--cc-sf-repeater-accordion-active-bg: #EFF6FF;--cc-sf-repeater-badge-bg: #E5E7EB;--cc-sf-repeater-badge-color: #374151;--cc-sf-section-border-radius-inner: 8px;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 18px;--cc-sf-field-gap: 6px;--cc-sf-focus-ring-width: 3px;--cc-sf-focus-ring-offset: 0;--cc-sf-label-size: .8125rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .625rem .875rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #F8FAFC;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-icon-bg: rgba(59, 130, 246, .1);--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-btn-remove-padding: .375rem .75rem;--cc-sf-btn-remove-font-size: .875rem;--cc-sf-btn-remove-font-weight: 500;--cc-sf-btn-add-padding: .625rem 1.5rem;--cc-sf-btn-add-font-size: .875rem;--cc-sf-btn-add-font-weight: 600;--cc-sf-stepper-connector-display: block;--cc-sf-instance-shadow: none;--cc-sf-instance-hover-shadow: none;--cc-sf-instance-transition: none;--cc-sf-instance-header-divider: none;--cc-sf-instance-header-pb: 0px;--cc-sf-instance-header-mb: 0px;--cc-sf-instance-num-weight: 600;--cc-sf-section-stepper-accent: #6366F1;--cc-sf-section-stepper-accent-end: #8B5CF6;--cc-sf-section-stepper-active-label: #4F46E5;--cc-sf-section-stepper-active-glow: rgba(99, 102, 241, .25);--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 0 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}.fb-config-panel ::ng-deep .stepper-nav .stepper-step:not(:last-child):after{display:var(--cc-sf-stepper-connector-display)!important}.fb-config-panel ::ng-deep .section-instance{background:var(--cc-sf-instance-bg)!important;border:var(--cc-sf-instance-border)!important;border-radius:var(--cc-sf-instance-radius)!important;box-shadow:var(--cc-sf-instance-shadow);transition:var(--cc-sf-instance-transition)}.fb-config-panel ::ng-deep .section-instance:hover{box-shadow:var(--cc-sf-instance-hover-shadow)}.fb-config-panel ::ng-deep .section-instance-header{display:flex;align-items:center;justify-content:space-between;padding-bottom:var(--cc-sf-instance-header-pb);margin-bottom:var(--cc-sf-instance-header-mb);border-bottom:var(--cc-sf-instance-header-divider)}.fb-config-panel ::ng-deep .section-instance-num{font-size:var(--cc-sf-instance-num-size);font-weight:var(--cc-sf-instance-num-weight);color:var(--cc-sf-instance-num-color)}.fb-config-panel ::ng-deep .btn-instance-remove{display:inline-flex;align-items:center;gap:6px;padding:var(--cc-sf-btn-remove-padding);border-radius:var(--cc-sf-btn-remove-radius);border:var(--cc-sf-btn-remove-border)!important;background:var(--cc-sf-btn-remove-bg);color:var(--cc-sf-btn-remove-color)!important;font-size:var(--cc-sf-btn-remove-font-size);font-weight:var(--cc-sf-btn-remove-font-weight);cursor:pointer;transition:all .15s ease}.fb-config-panel ::ng-deep .btn-instance-remove:hover{background:var(--cc-sf-btn-remove-hover-bg)}.fb-config-panel ::ng-deep .btn-add-section{display:inline-flex;align-items:center;gap:8px;padding:var(--cc-sf-btn-add-padding);border-radius:var(--cc-sf-btn-add-radius);border:var(--cc-sf-btn-add-border)!important;background:var(--cc-sf-btn-add-bg);color:var(--cc-sf-btn-add-color);font-size:var(--cc-sf-btn-add-font-size);font-weight:var(--cc-sf-btn-add-font-weight);cursor:pointer;transition:all .18s ease}.fb-config-panel ::ng-deep .btn-add-section:hover{background:var(--cc-sf-btn-add-hover-bg);border-color:var(--cc-sf-btn-add-hover-border)!important}.fb-config-panel ::ng-deep .section-stepper-nav:before{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-badge{background:linear-gradient(135deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important;box-shadow:0 0 0 4px var(--cc-sf-section-stepper-active-glow),0 4px 12px var(--cc-sf-section-stepper-active-glow)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-label{color:var(--cc-sf-section-stepper-active-label)!important}.fb-config-panel ::ng-deep .section-stepper-step:not(.ss-active):not(.ss-completed):not(.ss-warning):hover .ss-badge{color:var(--cc-sf-section-stepper-accent)!important;border-color:var(--cc-sf-section-stepper-accent-end)!important}.fb-config-panel ::ng-deep .section-stepper-step .ss-connector:after{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent),var(--cc-sf-section-stepper-accent-end))!important}}.fb-config-panel__empty{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;color:var(--fb-fc-empty-color, #9ca3af);text-align:center;padding:48px 24px}@media(max-width:640px){.fb-config-panel__empty{padding:24px 16px}}.fb-config-panel__empty-icon{margin-bottom:24px;opacity:.4;color:var(--fb-fc-accent, #3b82f6)}@media(max-width:640px){.fb-config-panel__empty-icon{margin-bottom:16px}}.fb-config-panel__empty-text{font-size:15px;max-width:320px;line-height:1.6;font-weight:500}@media(max-width:640px){.fb-config-panel__empty-text{font-size:14px;max-width:100%}}.fb-config-panel__header{background:var(--fb-fc-header-bg, #ffffff);padding:1.4rem;border-bottom:1px solid var(--fb-fc-border, #e5e7eb);display:flex;align-items:center;justify-content:space-between;flex-shrink:0;gap:16px;flex-wrap:wrap}@media(max-width:768px){.fb-config-panel__header{padding:16px 24px;gap:12px}}@media(max-width:640px){.fb-config-panel__header{padding:12px 16px;gap:8px}}.fb-config-panel__header-left{display:flex;align-items:center;gap:12px;min-width:0;flex-wrap:wrap}@media(max-width:640px){.fb-config-panel__header-left{gap:8px}}.fb-config-panel__type-switcher{display:flex;align-items:center;gap:8px;flex-shrink:0}@media(max-width:640px){.fb-config-panel__type-switcher{gap:4px}}.fb-config-panel__type-label{font-size:var(--fb-fc-type-label-size, .75rem);font-weight:600;color:var(--fb-fc-type-label-color, #6b7280);white-space:nowrap}@media(max-width:640px){.fb-config-panel__type-label{font-size:.7rem}}.fb-config-panel__type-select{height:var(--fb-fc-type-select-height, 36px);padding:0 32px 0 10px;border:1px solid var(--fb-fc-type-select-border, #d1d5db);border-radius:var(--fb-fc-type-select-radius, 8px);background-color:var(--fb-fc-type-select-bg, #ffffff);color:var(--fb-fc-type-select-color, #111827);font-size:.8125rem;font-weight:500;cursor:pointer;appearance:none;background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E\");background-repeat:no-repeat;background-position:right 8px center;min-width:160px;transition:border-color .15s ease,box-shadow .15s ease}@media(max-width:640px){.fb-config-panel__type-select{height:32px;font-size:.75rem;min-width:140px;padding:0 28px 0 8px}}.fb-config-panel__type-select:hover{border-color:var(--fb-fc-type-select-hover-border, #9ca3af)}.fb-config-panel__type-select:focus{outline:none;border-color:var(--fb-fc-accent, #3b82f6);box-shadow:0 0 0 3px #3b82f61f}.fb-config-panel__title{margin:0;font-size:1.25rem;font-weight:700;color:var(--fb-fc-title-color, #111827)}@media(max-width:1024px){.fb-config-panel__title{font-size:1.125rem}}@media(max-width:640px){.fb-config-panel__title{font-size:1rem}}.fb-config-panel__badge{padding:4px 12px;background:var(--fb-fc-badge-bg, #eff6ff);color:var(--fb-fc-badge-color, #3b82f6);border-radius:20px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;border:1px solid var(--fb-fc-badge-border, #dbeafe)}@media(max-width:640px){.fb-config-panel__badge{padding:3px 8px;font-size:9px}}.fb-config-panel__form-wrapper{flex:1;overflow-y:auto;overflow-x:hidden;width:100%;min-width:0;display:flex;flex-direction:column;align-items:stretch;box-sizing:border-box;padding:12px 16px}@media(min-width:600px){.fb-config-panel__form-wrapper{padding:16px 20px}}@media(min-width:768px){.fb-config-panel__form-wrapper{padding:20px 24px}}@media(min-width:1024px){.fb-config-panel__form-wrapper{padding:1rem}}@media(min-width:1440px){.fb-config-panel__form-wrapper{padding:28px 40px}}@media(min-width:1920px){.fb-config-panel__form-wrapper{padding:32px 48px}}.fb-config-panel__form-wrapper .fb-config-card{width:100%;max-width:none;margin:0;background:transparent;border:none;box-shadow:none;display:flex;flex-direction:column;min-width:0;flex:1;box-sizing:border-box}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .sf-col{min-width:0}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{display:grid;grid-auto-flow:dense;gap:12px;width:100%;align-items:start}@media(max-width:599px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{grid-template-columns:1fr;gap:12px}}@media(min-width:600px)and (max-width:767px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{grid-template-columns:1fr;gap:14px}}@media(min-width:768px)and (max-width:1023px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{grid-template-columns:repeat(2,1fr);gap:14px}}@media(min-width:1024px)and (max-width:1439px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{grid-template-columns:repeat(2,1fr);gap:16px}}@media(min-width:1440px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{grid-template-columns:repeat(3,1fr);gap:18px}}@media(min-width:1920px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{grid-template-columns:repeat(3,1fr);gap:20px}}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal>*{display:flex;flex-direction:column;min-width:0;overflow:hidden}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal>* ::ng-deep .form-field-wrapper,.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal>* ::ng-deep .field-wrapper,.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal>* ::ng-deep input,.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal>* ::ng-deep select,.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal>* ::ng-deep textarea{width:100%;min-width:0}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper{display:flex;flex-direction:row;align-items:center;gap:8px;white-space:nowrap;min-width:0}@media(max-width:768px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper{gap:6px}}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper .field-label{font-size:.75rem;font-weight:600;margin:0;flex-shrink:1;min-width:0;word-break:keep-all}@media(max-width:768px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper .field-label{font-size:.7rem}}@media(max-width:640px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper .field-label{font-size:.65rem}}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper .switch{flex-shrink:0}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper{display:flex;flex-direction:row;align-items:center;gap:8px;white-space:nowrap;min-width:0}@media(max-width:768px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper{gap:6px}}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper .field-label{font-size:.75rem;font-weight:600;margin:0;flex-shrink:1;min-width:0;word-break:keep-all}@media(max-width:768px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper .field-label{font-size:.7rem}}@media(max-width:640px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper .field-label{font-size:.65rem}}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper .switch{flex-shrink:0}.fb-config-panel__error{padding:24px;background:var(--fb-fc-error-bg, #fef2f2);color:var(--fb-fc-error-color, #dc2626);border:1px solid var(--fb-fc-error-border, #fee2e2);border-radius:8px;font-size:14px;font-weight:500}@media(max-width:768px){.fb-config-panel__error{padding:16px;font-size:13px}}@media(max-width:640px){.fb-config-panel__error{padding:12px;font-size:12px}}\n"], dependencies: [{ kind: "component", type: SmartFormComponent, selector: "lib-smart-form", inputs: ["formJson", "initialValues", "enableDraftAutoSave", "labels", "mode", "readOnly"], outputs: ["submit", "draftSave", "actionClick", "valueChange", "fileAdded", "fileUploadFinished", "fileRemoved", "stepChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
7136
7336
|
}
|
|
7137
7337
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ConfiguratorConfigPanelComponent, decorators: [{
|
|
7138
7338
|
type: Component,
|
|
7139
|
-
args: [{ selector: 'lib-configurator-config-panel', standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"fb-config-panel\">\r\n @if (!selectedField) {\r\n <div class=\"fb-config-panel__empty\">\r\n <div class=\"fb-config-panel__empty-icon\">\r\n <svg width=\"64\" height=\"64\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" ry=\"2\"/>\r\n <line x1=\"3\" y1=\"9\" x2=\"21\" y2=\"9\"/>\r\n <line x1=\"9\" y1=\"21\" x2=\"9\" y2=\"9\"/>\r\n </svg>\r\n </div>\r\n <p class=\"fb-config-panel__empty-text\">\r\n Select a field from the tree panel to edit its configuration.\r\n </p>\r\n </div>\r\n } @else {\r\n <div class=\"fb-config-panel__header\">\r\n <div class=\"fb-config-panel__header-left\">\r\n <h3 class=\"fb-config-panel__title\">\r\n {{ selectedField.label || selectedField.name || 'Field Settings' }}\r\n </h3>\r\n @if (selectedField.type) {\r\n <span class=\"fb-config-panel__badge\">{{ selectedField.type }}</span>\r\n }\r\n </div>\r\n\r\n <!-- Field Type Switcher: hidden for DROPDOWN / MULTI_SELECT fields -->\r\n @if (!isDropdownType) {\r\n <div class=\"fb-config-panel__type-switcher\">\r\n <label class=\"fb-config-panel__type-label\" for=\"fb-field-type-select\">Field Type</label>\r\n <select\r\n id=\"fb-field-type-select\"\r\n class=\"fb-config-panel__type-select\"\r\n [value]=\"currentBuilderType\"\r\n (change)=\"onTypeSelectChange($event)\"\r\n >\r\n @for (opt of switchableFieldTypes; track opt.value) {\r\n <option [value]=\"opt.value\">{{ opt.label }}</option>\r\n }\r\n </select>\r\n </div>\r\n }\r\n </div>\r\n\r\n <div class=\"fb-config-panel__form-wrapper\">\r\n @if (showConfigForm && configFormJson) {\r\n <div class=\"fb-config-card\">\r\n <lib-smart-form\r\n [formJson]=\"configFormJson\"\r\n [initialValues]=\"configInitialValues\"\r\n (actionClick)=\"onActionClick($event)\"\r\n />\r\n </div>\r\n } @else if (!showConfigForm) {\r\n <!-- intentionally empty \u2014 SmartForm is being recycled -->\r\n } @else {\r\n <div class=\"fb-config-panel__error\">\r\n No configuration schema available for this field type.\r\n </div>\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [".fb-config-panel{display:flex;flex-direction:column;height:100%;background:var(--fb-fc-panel-bg, #f9fafb);overflow:hidden;--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 12px;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 12px;--cc-sf-label-size: .75rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .5rem .75rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #FFFAF1;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 0 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}@media(min-width:600px){.fb-config-panel{--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 14px;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 14px;--cc-sf-label-size: .8rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .5rem .75rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #FFFAF1;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 0 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}}@media(min-width:768px){.fb-config-panel{--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 16px;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 16px;--cc-sf-label-size: .8125rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .625rem .875rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #FFFAF1;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 0 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}}@media(min-width:1024px){.fb-config-panel{--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 16px;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 16px;--cc-sf-label-size: .8125rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .625rem .875rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #FFFAF1;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 0 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}}@media(min-width:1440px){.fb-config-panel{--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 18px;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 18px;--cc-sf-label-size: .8125rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .625rem .875rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #FFFAF1;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 0 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}}@media(min-width:1920px){.fb-config-panel{--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 18px;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 18px;--cc-sf-label-size: .8125rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .625rem .875rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #FFFAF1;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 0 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}}.fb-config-panel__empty{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;color:var(--fb-fc-empty-color, #9ca3af);text-align:center;padding:48px 24px}@media(max-width:640px){.fb-config-panel__empty{padding:24px 16px}}.fb-config-panel__empty-icon{margin-bottom:24px;opacity:.4;color:var(--fb-fc-accent, #3b82f6)}@media(max-width:640px){.fb-config-panel__empty-icon{margin-bottom:16px}}.fb-config-panel__empty-text{font-size:15px;max-width:320px;line-height:1.6;font-weight:500}@media(max-width:640px){.fb-config-panel__empty-text{font-size:14px;max-width:100%}}.fb-config-panel__header{background:var(--fb-fc-header-bg, #ffffff);padding:1.4rem;border-bottom:1px solid var(--fb-fc-border, #e5e7eb);display:flex;align-items:center;justify-content:space-between;flex-shrink:0;gap:16px;flex-wrap:wrap}@media(max-width:768px){.fb-config-panel__header{padding:16px 24px;gap:12px}}@media(max-width:640px){.fb-config-panel__header{padding:12px 16px;gap:8px}}.fb-config-panel__header-left{display:flex;align-items:center;gap:12px;min-width:0;flex-wrap:wrap}@media(max-width:640px){.fb-config-panel__header-left{gap:8px}}.fb-config-panel__type-switcher{display:flex;align-items:center;gap:8px;flex-shrink:0}@media(max-width:640px){.fb-config-panel__type-switcher{gap:4px}}.fb-config-panel__type-label{font-size:var(--fb-fc-type-label-size, .75rem);font-weight:600;color:var(--fb-fc-type-label-color, #6b7280);white-space:nowrap}@media(max-width:640px){.fb-config-panel__type-label{font-size:.7rem}}.fb-config-panel__type-select{height:var(--fb-fc-type-select-height, 36px);padding:0 32px 0 10px;border:1px solid var(--fb-fc-type-select-border, #d1d5db);border-radius:var(--fb-fc-type-select-radius, 8px);background-color:var(--fb-fc-type-select-bg, #ffffff);color:var(--fb-fc-type-select-color, #111827);font-size:.8125rem;font-weight:500;cursor:pointer;appearance:none;background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E\");background-repeat:no-repeat;background-position:right 8px center;min-width:160px;transition:border-color .15s ease,box-shadow .15s ease}@media(max-width:640px){.fb-config-panel__type-select{height:32px;font-size:.75rem;min-width:140px;padding:0 28px 0 8px}}.fb-config-panel__type-select:hover{border-color:var(--fb-fc-type-select-hover-border, #9ca3af)}.fb-config-panel__type-select:focus{outline:none;border-color:var(--fb-fc-accent, #3b82f6);box-shadow:0 0 0 3px #3b82f61f}.fb-config-panel__title{margin:0;font-size:1.25rem;font-weight:700;color:var(--fb-fc-title-color, #111827)}@media(max-width:1024px){.fb-config-panel__title{font-size:1.125rem}}@media(max-width:640px){.fb-config-panel__title{font-size:1rem}}.fb-config-panel__badge{padding:4px 12px;background:var(--fb-fc-badge-bg, #eff6ff);color:var(--fb-fc-badge-color, #3b82f6);border-radius:20px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;border:1px solid var(--fb-fc-badge-border, #dbeafe)}@media(max-width:640px){.fb-config-panel__badge{padding:3px 8px;font-size:9px}}.fb-config-panel__form-wrapper{flex:1;overflow-y:auto;overflow-x:hidden;width:100%;min-width:0;display:flex;flex-direction:column;align-items:stretch;box-sizing:border-box;padding:12px 16px}@media(min-width:600px){.fb-config-panel__form-wrapper{padding:16px 20px}}@media(min-width:768px){.fb-config-panel__form-wrapper{padding:20px 24px}}@media(min-width:1024px){.fb-config-panel__form-wrapper{padding:1rem}}@media(min-width:1440px){.fb-config-panel__form-wrapper{padding:28px 40px}}@media(min-width:1920px){.fb-config-panel__form-wrapper{padding:32px 48px}}.fb-config-panel__form-wrapper .fb-config-card{width:100%;max-width:none;margin:0;background:transparent;border:none;box-shadow:none;display:flex;flex-direction:column;min-width:0;flex:1;box-sizing:border-box}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .sf-col{min-width:0}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{display:grid;grid-auto-flow:dense;gap:12px;width:100%;align-items:start}@media(max-width:599px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{grid-template-columns:1fr;gap:12px}}@media(min-width:600px)and (max-width:767px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{grid-template-columns:1fr;gap:14px}}@media(min-width:768px)and (max-width:1023px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{grid-template-columns:repeat(2,1fr);gap:14px}}@media(min-width:1024px)and (max-width:1439px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{grid-template-columns:repeat(2,1fr);gap:16px}}@media(min-width:1440px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{grid-template-columns:repeat(3,1fr);gap:18px}}@media(min-width:1920px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{grid-template-columns:repeat(3,1fr);gap:20px}}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal>*{display:flex;flex-direction:column;min-width:0;overflow:hidden}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal>* ::ng-deep .form-field-wrapper,.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal>* ::ng-deep .field-wrapper,.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal>* ::ng-deep input,.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal>* ::ng-deep select,.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal>* ::ng-deep textarea{width:100%;min-width:0}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper{display:flex;flex-direction:row;align-items:center;gap:8px;white-space:nowrap;min-width:0}@media(max-width:768px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper{gap:6px}}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper .field-label{font-size:.75rem;font-weight:600;margin:0;flex-shrink:1;min-width:0;word-break:keep-all}@media(max-width:768px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper .field-label{font-size:.7rem}}@media(max-width:640px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper .field-label{font-size:.65rem}}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper .switch{flex-shrink:0}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper{display:flex;flex-direction:row;align-items:center;gap:8px;white-space:nowrap;min-width:0}@media(max-width:768px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper{gap:6px}}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper .field-label{font-size:.75rem;font-weight:600;margin:0;flex-shrink:1;min-width:0;word-break:keep-all}@media(max-width:768px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper .field-label{font-size:.7rem}}@media(max-width:640px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper .field-label{font-size:.65rem}}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper .switch{flex-shrink:0}.fb-config-panel__error{padding:24px;background:var(--fb-fc-error-bg, #fef2f2);color:var(--fb-fc-error-color, #dc2626);border:1px solid var(--fb-fc-error-border, #fee2e2);border-radius:8px;font-size:14px;font-weight:500}@media(max-width:768px){.fb-config-panel__error{padding:16px;font-size:13px}}@media(max-width:640px){.fb-config-panel__error{padding:12px;font-size:12px}}\n"] }]
|
|
7339
|
+
args: [{ selector: 'lib-configurator-config-panel', standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"fb-config-panel\">\r\n @if (!selectedField) {\r\n <div class=\"fb-config-panel__empty\">\r\n <div class=\"fb-config-panel__empty-icon\">\r\n <svg width=\"64\" height=\"64\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" ry=\"2\"/>\r\n <line x1=\"3\" y1=\"9\" x2=\"21\" y2=\"9\"/>\r\n <line x1=\"9\" y1=\"21\" x2=\"9\" y2=\"9\"/>\r\n </svg>\r\n </div>\r\n <p class=\"fb-config-panel__empty-text\">\r\n Select a field from the tree panel to edit its configuration.\r\n </p>\r\n </div>\r\n } @else {\r\n <div class=\"fb-config-panel__header\">\r\n <div class=\"fb-config-panel__header-left\">\r\n <h3 class=\"fb-config-panel__title\">\r\n {{ selectedField.label || selectedField.name || 'Field Settings' }}\r\n </h3>\r\n @if (selectedField.type) {\r\n <span class=\"fb-config-panel__badge\">{{ selectedField.type }}</span>\r\n }\r\n </div>\r\n\r\n <!-- Field Type Switcher: hidden for DROPDOWN / MULTI_SELECT fields -->\r\n @if (!isDropdownType) {\r\n <div class=\"fb-config-panel__type-switcher\">\r\n <label class=\"fb-config-panel__type-label\" for=\"fb-field-type-select\">Field Type</label>\r\n <select\r\n id=\"fb-field-type-select\"\r\n class=\"fb-config-panel__type-select\"\r\n [value]=\"currentBuilderType\"\r\n (change)=\"onTypeSelectChange($event)\"\r\n >\r\n @for (opt of switchableFieldTypes; track opt.value) {\r\n <option [value]=\"opt.value\">{{ opt.label }}</option>\r\n }\r\n </select>\r\n </div>\r\n }\r\n </div>\r\n\r\n <div class=\"fb-config-panel__form-wrapper\">\r\n @if (showConfigForm && configFormJson) {\r\n <div class=\"fb-config-card\">\r\n <lib-smart-form\r\n [formJson]=\"configFormJson\"\r\n [initialValues]=\"configInitialValues\"\r\n (actionClick)=\"onActionClick($event)\"\r\n />\r\n </div>\r\n } @else if (!showConfigForm) {\r\n <!-- intentionally empty \u2014 SmartForm is being recycled -->\r\n } @else {\r\n <div class=\"fb-config-panel__error\">\r\n No configuration schema available for this field type.\r\n </div>\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [".fb-config-panel{display:flex;flex-direction:column;height:100%;background:var(--fb-fc-panel-bg, #f9fafb);overflow:hidden;--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-accent-color: #3B82F6;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-section-gap: 24px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 12px;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-section-header-accent-width: 4px;--cc-sf-section-header-accent-color: #3B82F6;--cc-sf-section-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-color: #1F2937;--cc-sf-repeater-accordion-active-bg: #EFF6FF;--cc-sf-repeater-badge-bg: #E5E7EB;--cc-sf-repeater-badge-color: #374151;--cc-sf-section-border-radius-inner: 8px;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 12px;--cc-sf-field-gap: 6px;--cc-sf-focus-ring-width: 3px;--cc-sf-focus-ring-offset: 0;--cc-sf-label-size: .75rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .5rem .75rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #F8FAFC;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-icon-bg: rgba(59, 130, 246, .1);--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-btn-remove-padding: .375rem .75rem;--cc-sf-btn-remove-font-size: .875rem;--cc-sf-btn-remove-font-weight: 500;--cc-sf-btn-add-padding: .625rem 1.5rem;--cc-sf-btn-add-font-size: .875rem;--cc-sf-btn-add-font-weight: 600;--cc-sf-stepper-connector-display: block;--cc-sf-instance-shadow: none;--cc-sf-instance-hover-shadow: none;--cc-sf-instance-transition: none;--cc-sf-instance-header-divider: none;--cc-sf-instance-header-pb: 0px;--cc-sf-instance-header-mb: 0px;--cc-sf-instance-num-weight: 600;--cc-sf-section-stepper-accent: #6366F1;--cc-sf-section-stepper-accent-end: #8B5CF6;--cc-sf-section-stepper-active-label: #4F46E5;--cc-sf-section-stepper-active-glow: rgba(99, 102, 241, .25);--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 0 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}.fb-config-panel ::ng-deep .stepper-nav .stepper-step:not(:last-child):after{display:var(--cc-sf-stepper-connector-display)!important}.fb-config-panel ::ng-deep .section-instance{background:var(--cc-sf-instance-bg)!important;border:var(--cc-sf-instance-border)!important;border-radius:var(--cc-sf-instance-radius)!important;box-shadow:var(--cc-sf-instance-shadow);transition:var(--cc-sf-instance-transition)}.fb-config-panel ::ng-deep .section-instance:hover{box-shadow:var(--cc-sf-instance-hover-shadow)}.fb-config-panel ::ng-deep .section-instance-header{display:flex;align-items:center;justify-content:space-between;padding-bottom:var(--cc-sf-instance-header-pb);margin-bottom:var(--cc-sf-instance-header-mb);border-bottom:var(--cc-sf-instance-header-divider)}.fb-config-panel ::ng-deep .section-instance-num{font-size:var(--cc-sf-instance-num-size);font-weight:var(--cc-sf-instance-num-weight);color:var(--cc-sf-instance-num-color)}.fb-config-panel ::ng-deep .btn-instance-remove{display:inline-flex;align-items:center;gap:6px;padding:var(--cc-sf-btn-remove-padding);border-radius:var(--cc-sf-btn-remove-radius);border:var(--cc-sf-btn-remove-border)!important;background:var(--cc-sf-btn-remove-bg);color:var(--cc-sf-btn-remove-color)!important;font-size:var(--cc-sf-btn-remove-font-size);font-weight:var(--cc-sf-btn-remove-font-weight);cursor:pointer;transition:all .15s ease}.fb-config-panel ::ng-deep .btn-instance-remove:hover{background:var(--cc-sf-btn-remove-hover-bg)}.fb-config-panel ::ng-deep .btn-add-section{display:inline-flex;align-items:center;gap:8px;padding:var(--cc-sf-btn-add-padding);border-radius:var(--cc-sf-btn-add-radius);border:var(--cc-sf-btn-add-border)!important;background:var(--cc-sf-btn-add-bg);color:var(--cc-sf-btn-add-color);font-size:var(--cc-sf-btn-add-font-size);font-weight:var(--cc-sf-btn-add-font-weight);cursor:pointer;transition:all .18s ease}.fb-config-panel ::ng-deep .btn-add-section:hover{background:var(--cc-sf-btn-add-hover-bg);border-color:var(--cc-sf-btn-add-hover-border)!important}.fb-config-panel ::ng-deep .section-stepper-nav:before{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-badge{background:linear-gradient(135deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important;box-shadow:0 0 0 4px var(--cc-sf-section-stepper-active-glow),0 4px 12px var(--cc-sf-section-stepper-active-glow)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-label{color:var(--cc-sf-section-stepper-active-label)!important}.fb-config-panel ::ng-deep .section-stepper-step:not(.ss-active):not(.ss-completed):not(.ss-warning):hover .ss-badge{color:var(--cc-sf-section-stepper-accent)!important;border-color:var(--cc-sf-section-stepper-accent-end)!important}.fb-config-panel ::ng-deep .section-stepper-step .ss-connector:after{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent),var(--cc-sf-section-stepper-accent-end))!important}@media(min-width:600px){.fb-config-panel{--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-accent-color: #3B82F6;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-section-gap: 24px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 14px;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-section-header-accent-width: 4px;--cc-sf-section-header-accent-color: #3B82F6;--cc-sf-section-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-color: #1F2937;--cc-sf-repeater-accordion-active-bg: #EFF6FF;--cc-sf-repeater-badge-bg: #E5E7EB;--cc-sf-repeater-badge-color: #374151;--cc-sf-section-border-radius-inner: 8px;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 14px;--cc-sf-field-gap: 6px;--cc-sf-focus-ring-width: 3px;--cc-sf-focus-ring-offset: 0;--cc-sf-label-size: .8rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .5rem .75rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #F8FAFC;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-icon-bg: rgba(59, 130, 246, .1);--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-btn-remove-padding: .375rem .75rem;--cc-sf-btn-remove-font-size: .875rem;--cc-sf-btn-remove-font-weight: 500;--cc-sf-btn-add-padding: .625rem 1.5rem;--cc-sf-btn-add-font-size: .875rem;--cc-sf-btn-add-font-weight: 600;--cc-sf-stepper-connector-display: block;--cc-sf-instance-shadow: none;--cc-sf-instance-hover-shadow: none;--cc-sf-instance-transition: none;--cc-sf-instance-header-divider: none;--cc-sf-instance-header-pb: 0px;--cc-sf-instance-header-mb: 0px;--cc-sf-instance-num-weight: 600;--cc-sf-section-stepper-accent: #6366F1;--cc-sf-section-stepper-accent-end: #8B5CF6;--cc-sf-section-stepper-active-label: #4F46E5;--cc-sf-section-stepper-active-glow: rgba(99, 102, 241, .25);--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 0 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}.fb-config-panel ::ng-deep .stepper-nav .stepper-step:not(:last-child):after{display:var(--cc-sf-stepper-connector-display)!important}.fb-config-panel ::ng-deep .section-instance{background:var(--cc-sf-instance-bg)!important;border:var(--cc-sf-instance-border)!important;border-radius:var(--cc-sf-instance-radius)!important;box-shadow:var(--cc-sf-instance-shadow);transition:var(--cc-sf-instance-transition)}.fb-config-panel ::ng-deep .section-instance:hover{box-shadow:var(--cc-sf-instance-hover-shadow)}.fb-config-panel ::ng-deep .section-instance-header{display:flex;align-items:center;justify-content:space-between;padding-bottom:var(--cc-sf-instance-header-pb);margin-bottom:var(--cc-sf-instance-header-mb);border-bottom:var(--cc-sf-instance-header-divider)}.fb-config-panel ::ng-deep .section-instance-num{font-size:var(--cc-sf-instance-num-size);font-weight:var(--cc-sf-instance-num-weight);color:var(--cc-sf-instance-num-color)}.fb-config-panel ::ng-deep .btn-instance-remove{display:inline-flex;align-items:center;gap:6px;padding:var(--cc-sf-btn-remove-padding);border-radius:var(--cc-sf-btn-remove-radius);border:var(--cc-sf-btn-remove-border)!important;background:var(--cc-sf-btn-remove-bg);color:var(--cc-sf-btn-remove-color)!important;font-size:var(--cc-sf-btn-remove-font-size);font-weight:var(--cc-sf-btn-remove-font-weight);cursor:pointer;transition:all .15s ease}.fb-config-panel ::ng-deep .btn-instance-remove:hover{background:var(--cc-sf-btn-remove-hover-bg)}.fb-config-panel ::ng-deep .btn-add-section{display:inline-flex;align-items:center;gap:8px;padding:var(--cc-sf-btn-add-padding);border-radius:var(--cc-sf-btn-add-radius);border:var(--cc-sf-btn-add-border)!important;background:var(--cc-sf-btn-add-bg);color:var(--cc-sf-btn-add-color);font-size:var(--cc-sf-btn-add-font-size);font-weight:var(--cc-sf-btn-add-font-weight);cursor:pointer;transition:all .18s ease}.fb-config-panel ::ng-deep .btn-add-section:hover{background:var(--cc-sf-btn-add-hover-bg);border-color:var(--cc-sf-btn-add-hover-border)!important}.fb-config-panel ::ng-deep .section-stepper-nav:before{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-badge{background:linear-gradient(135deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important;box-shadow:0 0 0 4px var(--cc-sf-section-stepper-active-glow),0 4px 12px var(--cc-sf-section-stepper-active-glow)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-label{color:var(--cc-sf-section-stepper-active-label)!important}.fb-config-panel ::ng-deep .section-stepper-step:not(.ss-active):not(.ss-completed):not(.ss-warning):hover .ss-badge{color:var(--cc-sf-section-stepper-accent)!important;border-color:var(--cc-sf-section-stepper-accent-end)!important}.fb-config-panel ::ng-deep .section-stepper-step .ss-connector:after{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent),var(--cc-sf-section-stepper-accent-end))!important}}@media(min-width:768px){.fb-config-panel{--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-accent-color: #3B82F6;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-section-gap: 24px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 16px;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-section-header-accent-width: 4px;--cc-sf-section-header-accent-color: #3B82F6;--cc-sf-section-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-color: #1F2937;--cc-sf-repeater-accordion-active-bg: #EFF6FF;--cc-sf-repeater-badge-bg: #E5E7EB;--cc-sf-repeater-badge-color: #374151;--cc-sf-section-border-radius-inner: 8px;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 16px;--cc-sf-field-gap: 6px;--cc-sf-focus-ring-width: 3px;--cc-sf-focus-ring-offset: 0;--cc-sf-label-size: .8125rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .625rem .875rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #F8FAFC;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-icon-bg: rgba(59, 130, 246, .1);--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-btn-remove-padding: .375rem .75rem;--cc-sf-btn-remove-font-size: .875rem;--cc-sf-btn-remove-font-weight: 500;--cc-sf-btn-add-padding: .625rem 1.5rem;--cc-sf-btn-add-font-size: .875rem;--cc-sf-btn-add-font-weight: 600;--cc-sf-stepper-connector-display: block;--cc-sf-instance-shadow: none;--cc-sf-instance-hover-shadow: none;--cc-sf-instance-transition: none;--cc-sf-instance-header-divider: none;--cc-sf-instance-header-pb: 0px;--cc-sf-instance-header-mb: 0px;--cc-sf-instance-num-weight: 600;--cc-sf-section-stepper-accent: #6366F1;--cc-sf-section-stepper-accent-end: #8B5CF6;--cc-sf-section-stepper-active-label: #4F46E5;--cc-sf-section-stepper-active-glow: rgba(99, 102, 241, .25);--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 0 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}.fb-config-panel ::ng-deep .stepper-nav .stepper-step:not(:last-child):after{display:var(--cc-sf-stepper-connector-display)!important}.fb-config-panel ::ng-deep .section-instance{background:var(--cc-sf-instance-bg)!important;border:var(--cc-sf-instance-border)!important;border-radius:var(--cc-sf-instance-radius)!important;box-shadow:var(--cc-sf-instance-shadow);transition:var(--cc-sf-instance-transition)}.fb-config-panel ::ng-deep .section-instance:hover{box-shadow:var(--cc-sf-instance-hover-shadow)}.fb-config-panel ::ng-deep .section-instance-header{display:flex;align-items:center;justify-content:space-between;padding-bottom:var(--cc-sf-instance-header-pb);margin-bottom:var(--cc-sf-instance-header-mb);border-bottom:var(--cc-sf-instance-header-divider)}.fb-config-panel ::ng-deep .section-instance-num{font-size:var(--cc-sf-instance-num-size);font-weight:var(--cc-sf-instance-num-weight);color:var(--cc-sf-instance-num-color)}.fb-config-panel ::ng-deep .btn-instance-remove{display:inline-flex;align-items:center;gap:6px;padding:var(--cc-sf-btn-remove-padding);border-radius:var(--cc-sf-btn-remove-radius);border:var(--cc-sf-btn-remove-border)!important;background:var(--cc-sf-btn-remove-bg);color:var(--cc-sf-btn-remove-color)!important;font-size:var(--cc-sf-btn-remove-font-size);font-weight:var(--cc-sf-btn-remove-font-weight);cursor:pointer;transition:all .15s ease}.fb-config-panel ::ng-deep .btn-instance-remove:hover{background:var(--cc-sf-btn-remove-hover-bg)}.fb-config-panel ::ng-deep .btn-add-section{display:inline-flex;align-items:center;gap:8px;padding:var(--cc-sf-btn-add-padding);border-radius:var(--cc-sf-btn-add-radius);border:var(--cc-sf-btn-add-border)!important;background:var(--cc-sf-btn-add-bg);color:var(--cc-sf-btn-add-color);font-size:var(--cc-sf-btn-add-font-size);font-weight:var(--cc-sf-btn-add-font-weight);cursor:pointer;transition:all .18s ease}.fb-config-panel ::ng-deep .btn-add-section:hover{background:var(--cc-sf-btn-add-hover-bg);border-color:var(--cc-sf-btn-add-hover-border)!important}.fb-config-panel ::ng-deep .section-stepper-nav:before{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-badge{background:linear-gradient(135deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important;box-shadow:0 0 0 4px var(--cc-sf-section-stepper-active-glow),0 4px 12px var(--cc-sf-section-stepper-active-glow)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-label{color:var(--cc-sf-section-stepper-active-label)!important}.fb-config-panel ::ng-deep .section-stepper-step:not(.ss-active):not(.ss-completed):not(.ss-warning):hover .ss-badge{color:var(--cc-sf-section-stepper-accent)!important;border-color:var(--cc-sf-section-stepper-accent-end)!important}.fb-config-panel ::ng-deep .section-stepper-step .ss-connector:after{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent),var(--cc-sf-section-stepper-accent-end))!important}}@media(min-width:1024px){.fb-config-panel{--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-accent-color: #3B82F6;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-section-gap: 24px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 16px;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-section-header-accent-width: 4px;--cc-sf-section-header-accent-color: #3B82F6;--cc-sf-section-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-color: #1F2937;--cc-sf-repeater-accordion-active-bg: #EFF6FF;--cc-sf-repeater-badge-bg: #E5E7EB;--cc-sf-repeater-badge-color: #374151;--cc-sf-section-border-radius-inner: 8px;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 16px;--cc-sf-field-gap: 6px;--cc-sf-focus-ring-width: 3px;--cc-sf-focus-ring-offset: 0;--cc-sf-label-size: .8125rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .625rem .875rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #F8FAFC;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-icon-bg: rgba(59, 130, 246, .1);--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-btn-remove-padding: .375rem .75rem;--cc-sf-btn-remove-font-size: .875rem;--cc-sf-btn-remove-font-weight: 500;--cc-sf-btn-add-padding: .625rem 1.5rem;--cc-sf-btn-add-font-size: .875rem;--cc-sf-btn-add-font-weight: 600;--cc-sf-stepper-connector-display: block;--cc-sf-instance-shadow: none;--cc-sf-instance-hover-shadow: none;--cc-sf-instance-transition: none;--cc-sf-instance-header-divider: none;--cc-sf-instance-header-pb: 0px;--cc-sf-instance-header-mb: 0px;--cc-sf-instance-num-weight: 600;--cc-sf-section-stepper-accent: #6366F1;--cc-sf-section-stepper-accent-end: #8B5CF6;--cc-sf-section-stepper-active-label: #4F46E5;--cc-sf-section-stepper-active-glow: rgba(99, 102, 241, .25);--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 0 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}.fb-config-panel ::ng-deep .stepper-nav .stepper-step:not(:last-child):after{display:var(--cc-sf-stepper-connector-display)!important}.fb-config-panel ::ng-deep .section-instance{background:var(--cc-sf-instance-bg)!important;border:var(--cc-sf-instance-border)!important;border-radius:var(--cc-sf-instance-radius)!important;box-shadow:var(--cc-sf-instance-shadow);transition:var(--cc-sf-instance-transition)}.fb-config-panel ::ng-deep .section-instance:hover{box-shadow:var(--cc-sf-instance-hover-shadow)}.fb-config-panel ::ng-deep .section-instance-header{display:flex;align-items:center;justify-content:space-between;padding-bottom:var(--cc-sf-instance-header-pb);margin-bottom:var(--cc-sf-instance-header-mb);border-bottom:var(--cc-sf-instance-header-divider)}.fb-config-panel ::ng-deep .section-instance-num{font-size:var(--cc-sf-instance-num-size);font-weight:var(--cc-sf-instance-num-weight);color:var(--cc-sf-instance-num-color)}.fb-config-panel ::ng-deep .btn-instance-remove{display:inline-flex;align-items:center;gap:6px;padding:var(--cc-sf-btn-remove-padding);border-radius:var(--cc-sf-btn-remove-radius);border:var(--cc-sf-btn-remove-border)!important;background:var(--cc-sf-btn-remove-bg);color:var(--cc-sf-btn-remove-color)!important;font-size:var(--cc-sf-btn-remove-font-size);font-weight:var(--cc-sf-btn-remove-font-weight);cursor:pointer;transition:all .15s ease}.fb-config-panel ::ng-deep .btn-instance-remove:hover{background:var(--cc-sf-btn-remove-hover-bg)}.fb-config-panel ::ng-deep .btn-add-section{display:inline-flex;align-items:center;gap:8px;padding:var(--cc-sf-btn-add-padding);border-radius:var(--cc-sf-btn-add-radius);border:var(--cc-sf-btn-add-border)!important;background:var(--cc-sf-btn-add-bg);color:var(--cc-sf-btn-add-color);font-size:var(--cc-sf-btn-add-font-size);font-weight:var(--cc-sf-btn-add-font-weight);cursor:pointer;transition:all .18s ease}.fb-config-panel ::ng-deep .btn-add-section:hover{background:var(--cc-sf-btn-add-hover-bg);border-color:var(--cc-sf-btn-add-hover-border)!important}.fb-config-panel ::ng-deep .section-stepper-nav:before{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-badge{background:linear-gradient(135deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important;box-shadow:0 0 0 4px var(--cc-sf-section-stepper-active-glow),0 4px 12px var(--cc-sf-section-stepper-active-glow)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-label{color:var(--cc-sf-section-stepper-active-label)!important}.fb-config-panel ::ng-deep .section-stepper-step:not(.ss-active):not(.ss-completed):not(.ss-warning):hover .ss-badge{color:var(--cc-sf-section-stepper-accent)!important;border-color:var(--cc-sf-section-stepper-accent-end)!important}.fb-config-panel ::ng-deep .section-stepper-step .ss-connector:after{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent),var(--cc-sf-section-stepper-accent-end))!important}}@media(min-width:1440px){.fb-config-panel{--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-accent-color: #3B82F6;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-section-gap: 24px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 18px;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-section-header-accent-width: 4px;--cc-sf-section-header-accent-color: #3B82F6;--cc-sf-section-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-color: #1F2937;--cc-sf-repeater-accordion-active-bg: #EFF6FF;--cc-sf-repeater-badge-bg: #E5E7EB;--cc-sf-repeater-badge-color: #374151;--cc-sf-section-border-radius-inner: 8px;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 18px;--cc-sf-field-gap: 6px;--cc-sf-focus-ring-width: 3px;--cc-sf-focus-ring-offset: 0;--cc-sf-label-size: .8125rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .625rem .875rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #F8FAFC;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-icon-bg: rgba(59, 130, 246, .1);--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-btn-remove-padding: .375rem .75rem;--cc-sf-btn-remove-font-size: .875rem;--cc-sf-btn-remove-font-weight: 500;--cc-sf-btn-add-padding: .625rem 1.5rem;--cc-sf-btn-add-font-size: .875rem;--cc-sf-btn-add-font-weight: 600;--cc-sf-stepper-connector-display: block;--cc-sf-instance-shadow: none;--cc-sf-instance-hover-shadow: none;--cc-sf-instance-transition: none;--cc-sf-instance-header-divider: none;--cc-sf-instance-header-pb: 0px;--cc-sf-instance-header-mb: 0px;--cc-sf-instance-num-weight: 600;--cc-sf-section-stepper-accent: #6366F1;--cc-sf-section-stepper-accent-end: #8B5CF6;--cc-sf-section-stepper-active-label: #4F46E5;--cc-sf-section-stepper-active-glow: rgba(99, 102, 241, .25);--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 0 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}.fb-config-panel ::ng-deep .stepper-nav .stepper-step:not(:last-child):after{display:var(--cc-sf-stepper-connector-display)!important}.fb-config-panel ::ng-deep .section-instance{background:var(--cc-sf-instance-bg)!important;border:var(--cc-sf-instance-border)!important;border-radius:var(--cc-sf-instance-radius)!important;box-shadow:var(--cc-sf-instance-shadow);transition:var(--cc-sf-instance-transition)}.fb-config-panel ::ng-deep .section-instance:hover{box-shadow:var(--cc-sf-instance-hover-shadow)}.fb-config-panel ::ng-deep .section-instance-header{display:flex;align-items:center;justify-content:space-between;padding-bottom:var(--cc-sf-instance-header-pb);margin-bottom:var(--cc-sf-instance-header-mb);border-bottom:var(--cc-sf-instance-header-divider)}.fb-config-panel ::ng-deep .section-instance-num{font-size:var(--cc-sf-instance-num-size);font-weight:var(--cc-sf-instance-num-weight);color:var(--cc-sf-instance-num-color)}.fb-config-panel ::ng-deep .btn-instance-remove{display:inline-flex;align-items:center;gap:6px;padding:var(--cc-sf-btn-remove-padding);border-radius:var(--cc-sf-btn-remove-radius);border:var(--cc-sf-btn-remove-border)!important;background:var(--cc-sf-btn-remove-bg);color:var(--cc-sf-btn-remove-color)!important;font-size:var(--cc-sf-btn-remove-font-size);font-weight:var(--cc-sf-btn-remove-font-weight);cursor:pointer;transition:all .15s ease}.fb-config-panel ::ng-deep .btn-instance-remove:hover{background:var(--cc-sf-btn-remove-hover-bg)}.fb-config-panel ::ng-deep .btn-add-section{display:inline-flex;align-items:center;gap:8px;padding:var(--cc-sf-btn-add-padding);border-radius:var(--cc-sf-btn-add-radius);border:var(--cc-sf-btn-add-border)!important;background:var(--cc-sf-btn-add-bg);color:var(--cc-sf-btn-add-color);font-size:var(--cc-sf-btn-add-font-size);font-weight:var(--cc-sf-btn-add-font-weight);cursor:pointer;transition:all .18s ease}.fb-config-panel ::ng-deep .btn-add-section:hover{background:var(--cc-sf-btn-add-hover-bg);border-color:var(--cc-sf-btn-add-hover-border)!important}.fb-config-panel ::ng-deep .section-stepper-nav:before{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-badge{background:linear-gradient(135deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important;box-shadow:0 0 0 4px var(--cc-sf-section-stepper-active-glow),0 4px 12px var(--cc-sf-section-stepper-active-glow)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-label{color:var(--cc-sf-section-stepper-active-label)!important}.fb-config-panel ::ng-deep .section-stepper-step:not(.ss-active):not(.ss-completed):not(.ss-warning):hover .ss-badge{color:var(--cc-sf-section-stepper-accent)!important;border-color:var(--cc-sf-section-stepper-accent-end)!important}.fb-config-panel ::ng-deep .section-stepper-step .ss-connector:after{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent),var(--cc-sf-section-stepper-accent-end))!important}}@media(min-width:1920px){.fb-config-panel{--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-accent-color: #3B82F6;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-section-gap: 24px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 18px;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-section-header-accent-width: 4px;--cc-sf-section-header-accent-color: #3B82F6;--cc-sf-section-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-color: #1F2937;--cc-sf-repeater-accordion-active-bg: #EFF6FF;--cc-sf-repeater-badge-bg: #E5E7EB;--cc-sf-repeater-badge-color: #374151;--cc-sf-section-border-radius-inner: 8px;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 18px;--cc-sf-field-gap: 6px;--cc-sf-focus-ring-width: 3px;--cc-sf-focus-ring-offset: 0;--cc-sf-label-size: .8125rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .625rem .875rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #F8FAFC;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-icon-bg: rgba(59, 130, 246, .1);--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-btn-remove-padding: .375rem .75rem;--cc-sf-btn-remove-font-size: .875rem;--cc-sf-btn-remove-font-weight: 500;--cc-sf-btn-add-padding: .625rem 1.5rem;--cc-sf-btn-add-font-size: .875rem;--cc-sf-btn-add-font-weight: 600;--cc-sf-stepper-connector-display: block;--cc-sf-instance-shadow: none;--cc-sf-instance-hover-shadow: none;--cc-sf-instance-transition: none;--cc-sf-instance-header-divider: none;--cc-sf-instance-header-pb: 0px;--cc-sf-instance-header-mb: 0px;--cc-sf-instance-num-weight: 600;--cc-sf-section-stepper-accent: #6366F1;--cc-sf-section-stepper-accent-end: #8B5CF6;--cc-sf-section-stepper-active-label: #4F46E5;--cc-sf-section-stepper-active-glow: rgba(99, 102, 241, .25);--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 0 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}.fb-config-panel ::ng-deep .stepper-nav .stepper-step:not(:last-child):after{display:var(--cc-sf-stepper-connector-display)!important}.fb-config-panel ::ng-deep .section-instance{background:var(--cc-sf-instance-bg)!important;border:var(--cc-sf-instance-border)!important;border-radius:var(--cc-sf-instance-radius)!important;box-shadow:var(--cc-sf-instance-shadow);transition:var(--cc-sf-instance-transition)}.fb-config-panel ::ng-deep .section-instance:hover{box-shadow:var(--cc-sf-instance-hover-shadow)}.fb-config-panel ::ng-deep .section-instance-header{display:flex;align-items:center;justify-content:space-between;padding-bottom:var(--cc-sf-instance-header-pb);margin-bottom:var(--cc-sf-instance-header-mb);border-bottom:var(--cc-sf-instance-header-divider)}.fb-config-panel ::ng-deep .section-instance-num{font-size:var(--cc-sf-instance-num-size);font-weight:var(--cc-sf-instance-num-weight);color:var(--cc-sf-instance-num-color)}.fb-config-panel ::ng-deep .btn-instance-remove{display:inline-flex;align-items:center;gap:6px;padding:var(--cc-sf-btn-remove-padding);border-radius:var(--cc-sf-btn-remove-radius);border:var(--cc-sf-btn-remove-border)!important;background:var(--cc-sf-btn-remove-bg);color:var(--cc-sf-btn-remove-color)!important;font-size:var(--cc-sf-btn-remove-font-size);font-weight:var(--cc-sf-btn-remove-font-weight);cursor:pointer;transition:all .15s ease}.fb-config-panel ::ng-deep .btn-instance-remove:hover{background:var(--cc-sf-btn-remove-hover-bg)}.fb-config-panel ::ng-deep .btn-add-section{display:inline-flex;align-items:center;gap:8px;padding:var(--cc-sf-btn-add-padding);border-radius:var(--cc-sf-btn-add-radius);border:var(--cc-sf-btn-add-border)!important;background:var(--cc-sf-btn-add-bg);color:var(--cc-sf-btn-add-color);font-size:var(--cc-sf-btn-add-font-size);font-weight:var(--cc-sf-btn-add-font-weight);cursor:pointer;transition:all .18s ease}.fb-config-panel ::ng-deep .btn-add-section:hover{background:var(--cc-sf-btn-add-hover-bg);border-color:var(--cc-sf-btn-add-hover-border)!important}.fb-config-panel ::ng-deep .section-stepper-nav:before{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-badge{background:linear-gradient(135deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important;box-shadow:0 0 0 4px var(--cc-sf-section-stepper-active-glow),0 4px 12px var(--cc-sf-section-stepper-active-glow)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-label{color:var(--cc-sf-section-stepper-active-label)!important}.fb-config-panel ::ng-deep .section-stepper-step:not(.ss-active):not(.ss-completed):not(.ss-warning):hover .ss-badge{color:var(--cc-sf-section-stepper-accent)!important;border-color:var(--cc-sf-section-stepper-accent-end)!important}.fb-config-panel ::ng-deep .section-stepper-step .ss-connector:after{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent),var(--cc-sf-section-stepper-accent-end))!important}}.fb-config-panel__empty{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;color:var(--fb-fc-empty-color, #9ca3af);text-align:center;padding:48px 24px}@media(max-width:640px){.fb-config-panel__empty{padding:24px 16px}}.fb-config-panel__empty-icon{margin-bottom:24px;opacity:.4;color:var(--fb-fc-accent, #3b82f6)}@media(max-width:640px){.fb-config-panel__empty-icon{margin-bottom:16px}}.fb-config-panel__empty-text{font-size:15px;max-width:320px;line-height:1.6;font-weight:500}@media(max-width:640px){.fb-config-panel__empty-text{font-size:14px;max-width:100%}}.fb-config-panel__header{background:var(--fb-fc-header-bg, #ffffff);padding:1.4rem;border-bottom:1px solid var(--fb-fc-border, #e5e7eb);display:flex;align-items:center;justify-content:space-between;flex-shrink:0;gap:16px;flex-wrap:wrap}@media(max-width:768px){.fb-config-panel__header{padding:16px 24px;gap:12px}}@media(max-width:640px){.fb-config-panel__header{padding:12px 16px;gap:8px}}.fb-config-panel__header-left{display:flex;align-items:center;gap:12px;min-width:0;flex-wrap:wrap}@media(max-width:640px){.fb-config-panel__header-left{gap:8px}}.fb-config-panel__type-switcher{display:flex;align-items:center;gap:8px;flex-shrink:0}@media(max-width:640px){.fb-config-panel__type-switcher{gap:4px}}.fb-config-panel__type-label{font-size:var(--fb-fc-type-label-size, .75rem);font-weight:600;color:var(--fb-fc-type-label-color, #6b7280);white-space:nowrap}@media(max-width:640px){.fb-config-panel__type-label{font-size:.7rem}}.fb-config-panel__type-select{height:var(--fb-fc-type-select-height, 36px);padding:0 32px 0 10px;border:1px solid var(--fb-fc-type-select-border, #d1d5db);border-radius:var(--fb-fc-type-select-radius, 8px);background-color:var(--fb-fc-type-select-bg, #ffffff);color:var(--fb-fc-type-select-color, #111827);font-size:.8125rem;font-weight:500;cursor:pointer;appearance:none;background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E\");background-repeat:no-repeat;background-position:right 8px center;min-width:160px;transition:border-color .15s ease,box-shadow .15s ease}@media(max-width:640px){.fb-config-panel__type-select{height:32px;font-size:.75rem;min-width:140px;padding:0 28px 0 8px}}.fb-config-panel__type-select:hover{border-color:var(--fb-fc-type-select-hover-border, #9ca3af)}.fb-config-panel__type-select:focus{outline:none;border-color:var(--fb-fc-accent, #3b82f6);box-shadow:0 0 0 3px #3b82f61f}.fb-config-panel__title{margin:0;font-size:1.25rem;font-weight:700;color:var(--fb-fc-title-color, #111827)}@media(max-width:1024px){.fb-config-panel__title{font-size:1.125rem}}@media(max-width:640px){.fb-config-panel__title{font-size:1rem}}.fb-config-panel__badge{padding:4px 12px;background:var(--fb-fc-badge-bg, #eff6ff);color:var(--fb-fc-badge-color, #3b82f6);border-radius:20px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;border:1px solid var(--fb-fc-badge-border, #dbeafe)}@media(max-width:640px){.fb-config-panel__badge{padding:3px 8px;font-size:9px}}.fb-config-panel__form-wrapper{flex:1;overflow-y:auto;overflow-x:hidden;width:100%;min-width:0;display:flex;flex-direction:column;align-items:stretch;box-sizing:border-box;padding:12px 16px}@media(min-width:600px){.fb-config-panel__form-wrapper{padding:16px 20px}}@media(min-width:768px){.fb-config-panel__form-wrapper{padding:20px 24px}}@media(min-width:1024px){.fb-config-panel__form-wrapper{padding:1rem}}@media(min-width:1440px){.fb-config-panel__form-wrapper{padding:28px 40px}}@media(min-width:1920px){.fb-config-panel__form-wrapper{padding:32px 48px}}.fb-config-panel__form-wrapper .fb-config-card{width:100%;max-width:none;margin:0;background:transparent;border:none;box-shadow:none;display:flex;flex-direction:column;min-width:0;flex:1;box-sizing:border-box}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .sf-col{min-width:0}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{display:grid;grid-auto-flow:dense;gap:12px;width:100%;align-items:start}@media(max-width:599px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{grid-template-columns:1fr;gap:12px}}@media(min-width:600px)and (max-width:767px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{grid-template-columns:1fr;gap:14px}}@media(min-width:768px)and (max-width:1023px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{grid-template-columns:repeat(2,1fr);gap:14px}}@media(min-width:1024px)and (max-width:1439px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{grid-template-columns:repeat(2,1fr);gap:16px}}@media(min-width:1440px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{grid-template-columns:repeat(3,1fr);gap:18px}}@media(min-width:1920px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{grid-template-columns:repeat(3,1fr);gap:20px}}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal>*{display:flex;flex-direction:column;min-width:0;overflow:hidden}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal>* ::ng-deep .form-field-wrapper,.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal>* ::ng-deep .field-wrapper,.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal>* ::ng-deep input,.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal>* ::ng-deep select,.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal>* ::ng-deep textarea{width:100%;min-width:0}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper{display:flex;flex-direction:row;align-items:center;gap:8px;white-space:nowrap;min-width:0}@media(max-width:768px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper{gap:6px}}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper .field-label{font-size:.75rem;font-weight:600;margin:0;flex-shrink:1;min-width:0;word-break:keep-all}@media(max-width:768px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper .field-label{font-size:.7rem}}@media(max-width:640px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper .field-label{font-size:.65rem}}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper .switch{flex-shrink:0}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper{display:flex;flex-direction:row;align-items:center;gap:8px;white-space:nowrap;min-width:0}@media(max-width:768px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper{gap:6px}}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper .field-label{font-size:.75rem;font-weight:600;margin:0;flex-shrink:1;min-width:0;word-break:keep-all}@media(max-width:768px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper .field-label{font-size:.7rem}}@media(max-width:640px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper .field-label{font-size:.65rem}}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper .switch{flex-shrink:0}.fb-config-panel__error{padding:24px;background:var(--fb-fc-error-bg, #fef2f2);color:var(--fb-fc-error-color, #dc2626);border:1px solid var(--fb-fc-error-border, #fee2e2);border-radius:8px;font-size:14px;font-weight:500}@media(max-width:768px){.fb-config-panel__error{padding:16px;font-size:13px}}@media(max-width:640px){.fb-config-panel__error{padding:12px;font-size:12px}}\n"] }]
|
|
7140
7340
|
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: SnackbarService }], propDecorators: { selectedField: [{
|
|
7141
7341
|
type: Input
|
|
7142
7342
|
}], selectedFieldInfo: [{
|